gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

asm5.go (80187B)


      1 // Inferno utils/5l/span.c
      2 // https://bitbucket.org/inferno-os/inferno-os/src/master/utils/5l/span.c
      3 //
      4 //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
      5 //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
      6 //	Portions Copyright © 1997-1999 Vita Nuova Limited
      7 //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
      8 //	Portions Copyright © 2004,2006 Bruce Ellis
      9 //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
     10 //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
     11 //	Portions Copyright © 2009 The Go Authors. All rights reserved.
     12 //
     13 // Permission is hereby granted, free of charge, to any person obtaining a copy
     14 // of this software and associated documentation files (the "Software"), to deal
     15 // in the Software without restriction, including without limitation the rights
     16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     17 // copies of the Software, and to permit persons to whom the Software is
     18 // furnished to do so, subject to the following conditions:
     19 //
     20 // The above copyright notice and this permission notice shall be included in
     21 // all copies or substantial portions of the Software.
     22 //
     23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     29 // THE SOFTWARE.
     30 
     31 package arm
     32 
     33 import (
     34 	"github.com/twitchyliquid64/golang-asm/obj"
     35 	"github.com/twitchyliquid64/golang-asm/objabi"
     36 	"fmt"
     37 	"log"
     38 	"math"
     39 	"sort"
     40 )
     41 
     42 // ctxt5 holds state while assembling a single function.
     43 // Each function gets a fresh ctxt5.
     44 // This allows for multiple functions to be safely concurrently assembled.
     45 type ctxt5 struct {
     46 	ctxt       *obj.Link
     47 	newprog    obj.ProgAlloc
     48 	cursym     *obj.LSym
     49 	printp     *obj.Prog
     50 	blitrl     *obj.Prog
     51 	elitrl     *obj.Prog
     52 	autosize   int64
     53 	instoffset int64
     54 	pc         int64
     55 	pool       struct {
     56 		start uint32
     57 		size  uint32
     58 		extra uint32
     59 	}
     60 }
     61 
     62 type Optab struct {
     63 	as       obj.As
     64 	a1       uint8
     65 	a2       int8
     66 	a3       uint8
     67 	type_    uint8
     68 	size     int8
     69 	param    int16
     70 	flag     int8
     71 	pcrelsiz uint8
     72 	scond    uint8 // optional flags accepted by the instruction
     73 }
     74 
     75 type Opcross [32][2][32]uint8
     76 
     77 const (
     78 	LFROM  = 1 << 0
     79 	LTO    = 1 << 1
     80 	LPOOL  = 1 << 2
     81 	LPCREL = 1 << 3
     82 )
     83 
     84 var optab = []Optab{
     85 	/* struct Optab:
     86 	OPCODE, from, prog->reg, to, type, size, param, flag, extra data size, optional suffix */
     87 	{obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0, 0},
     88 	{AADD, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT},
     89 	{AADD, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
     90 	{AAND, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT},
     91 	{AAND, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
     92 	{AORR, C_REG, C_REG, C_REG, 1, 4, 0, 0, 0, C_SBIT},
     93 	{AORR, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
     94 	{AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
     95 	{AMVN, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, C_SBIT},
     96 	{ACMP, C_REG, C_REG, C_NONE, 1, 4, 0, 0, 0, 0},
     97 	{AADD, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT},
     98 	{AADD, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT},
     99 	{AAND, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT},
    100 	{AAND, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT},
    101 	{AORR, C_RCON, C_REG, C_REG, 2, 4, 0, 0, 0, C_SBIT},
    102 	{AORR, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, C_SBIT},
    103 	{AMOVW, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, 0},
    104 	{AMVN, C_RCON, C_NONE, C_REG, 2, 4, 0, 0, 0, 0},
    105 	{ACMP, C_RCON, C_REG, C_NONE, 2, 4, 0, 0, 0, 0},
    106 	{AADD, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT},
    107 	{AADD, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
    108 	{AAND, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT},
    109 	{AAND, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
    110 	{AORR, C_SHIFT, C_REG, C_REG, 3, 4, 0, 0, 0, C_SBIT},
    111 	{AORR, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
    112 	{AMVN, C_SHIFT, C_NONE, C_REG, 3, 4, 0, 0, 0, C_SBIT},
    113 	{ACMP, C_SHIFT, C_REG, C_NONE, 3, 4, 0, 0, 0, 0},
    114 	{AMOVW, C_RACON, C_NONE, C_REG, 4, 4, REGSP, 0, 0, C_SBIT},
    115 	{AB, C_NONE, C_NONE, C_SBRA, 5, 4, 0, LPOOL, 0, 0},
    116 	{ABL, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0},
    117 	{ABX, C_NONE, C_NONE, C_SBRA, 74, 20, 0, 0, 0, 0},
    118 	{ABEQ, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0},
    119 	{ABEQ, C_RCON, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, // prediction hinted form, hint ignored
    120 	{AB, C_NONE, C_NONE, C_ROREG, 6, 4, 0, LPOOL, 0, 0},
    121 	{ABL, C_NONE, C_NONE, C_ROREG, 7, 4, 0, 0, 0, 0},
    122 	{ABL, C_REG, C_NONE, C_ROREG, 7, 4, 0, 0, 0, 0},
    123 	{ABX, C_NONE, C_NONE, C_ROREG, 75, 12, 0, 0, 0, 0},
    124 	{ABXRET, C_NONE, C_NONE, C_ROREG, 76, 4, 0, 0, 0, 0},
    125 	{ASLL, C_RCON, C_REG, C_REG, 8, 4, 0, 0, 0, C_SBIT},
    126 	{ASLL, C_RCON, C_NONE, C_REG, 8, 4, 0, 0, 0, C_SBIT},
    127 	{ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0, C_SBIT},
    128 	{ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0, C_SBIT},
    129 	{ASWI, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0, 0},
    130 	{ASWI, C_NONE, C_NONE, C_LCON, 10, 4, 0, 0, 0, 0},
    131 	{AWORD, C_NONE, C_NONE, C_LCON, 11, 4, 0, 0, 0, 0},
    132 	{AWORD, C_NONE, C_NONE, C_LCONADDR, 11, 4, 0, 0, 0, 0},
    133 	{AWORD, C_NONE, C_NONE, C_ADDR, 11, 4, 0, 0, 0, 0},
    134 	{AWORD, C_NONE, C_NONE, C_TLS_LE, 103, 4, 0, 0, 0, 0},
    135 	{AWORD, C_NONE, C_NONE, C_TLS_IE, 104, 4, 0, 0, 0, 0},
    136 	{AMOVW, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0},
    137 	{AMOVW, C_SCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0},
    138 	{AMOVW, C_LCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0, 0},
    139 	{AMOVW, C_LCONADDR, C_NONE, C_REG, 12, 4, 0, LFROM | LPCREL, 4, 0},
    140 	{AMVN, C_NCON, C_NONE, C_REG, 12, 4, 0, 0, 0, 0},
    141 	{AADD, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
    142 	{AADD, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
    143 	{AAND, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
    144 	{AAND, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
    145 	{AORR, C_NCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
    146 	{AORR, C_NCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
    147 	{ACMP, C_NCON, C_REG, C_NONE, 13, 8, 0, 0, 0, 0},
    148 	{AADD, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
    149 	{AADD, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
    150 	{AAND, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
    151 	{AAND, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
    152 	{AORR, C_SCON, C_REG, C_REG, 13, 8, 0, 0, 0, C_SBIT},
    153 	{AORR, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, C_SBIT},
    154 	{AMVN, C_SCON, C_NONE, C_REG, 13, 8, 0, 0, 0, 0},
    155 	{ACMP, C_SCON, C_REG, C_NONE, 13, 8, 0, 0, 0, 0},
    156 	{AADD, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0, 0},
    157 	{AADD, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0, 0},
    158 	{AORR, C_RCON2A, C_REG, C_REG, 106, 8, 0, 0, 0, 0},
    159 	{AORR, C_RCON2A, C_NONE, C_REG, 106, 8, 0, 0, 0, 0},
    160 	{AADD, C_RCON2S, C_REG, C_REG, 107, 8, 0, 0, 0, 0},
    161 	{AADD, C_RCON2S, C_NONE, C_REG, 107, 8, 0, 0, 0, 0},
    162 	{AADD, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
    163 	{AADD, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
    164 	{AAND, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
    165 	{AAND, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
    166 	{AORR, C_LCON, C_REG, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
    167 	{AORR, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, C_SBIT},
    168 	{AMVN, C_LCON, C_NONE, C_REG, 13, 8, 0, LFROM, 0, 0},
    169 	{ACMP, C_LCON, C_REG, C_NONE, 13, 8, 0, LFROM, 0, 0},
    170 	{AMOVB, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, 0},
    171 	{AMOVBS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0},
    172 	{AMOVBU, C_REG, C_NONE, C_REG, 58, 4, 0, 0, 0, 0},
    173 	{AMOVH, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0, 0},
    174 	{AMOVHS, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0},
    175 	{AMOVHU, C_REG, C_NONE, C_REG, 14, 8, 0, 0, 0, 0},
    176 	{AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0, C_SBIT},
    177 	{AMUL, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0, C_SBIT},
    178 	{ADIV, C_REG, C_REG, C_REG, 16, 4, 0, 0, 0, 0},
    179 	{ADIV, C_REG, C_NONE, C_REG, 16, 4, 0, 0, 0, 0},
    180 	{ADIVHW, C_REG, C_REG, C_REG, 105, 4, 0, 0, 0, 0},
    181 	{ADIVHW, C_REG, C_NONE, C_REG, 105, 4, 0, 0, 0, 0},
    182 	{AMULL, C_REG, C_REG, C_REGREG, 17, 4, 0, 0, 0, C_SBIT},
    183 	{ABFX, C_LCON, C_REG, C_REG, 18, 4, 0, 0, 0, 0},  // width in From, LSB in From3
    184 	{ABFX, C_LCON, C_NONE, C_REG, 18, 4, 0, 0, 0, 0}, // width in From, LSB in From3
    185 	{AMOVW, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    186 	{AMOVW, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    187 	{AMOVB, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    188 	{AMOVB, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    189 	{AMOVBS, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    190 	{AMOVBS, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    191 	{AMOVBU, C_REG, C_NONE, C_SAUTO, 20, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    192 	{AMOVBU, C_REG, C_NONE, C_SOREG, 20, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    193 	{AMOVW, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    194 	{AMOVW, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    195 	{AMOVBU, C_SAUTO, C_NONE, C_REG, 21, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    196 	{AMOVBU, C_SOREG, C_NONE, C_REG, 21, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    197 	{AXTAB, C_SHIFT, C_REG, C_REG, 22, 4, 0, 0, 0, 0},
    198 	{AXTAB, C_SHIFT, C_NONE, C_REG, 22, 4, 0, 0, 0, 0},
    199 	{AMOVW, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, C_SBIT},
    200 	{AMOVB, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
    201 	{AMOVBS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
    202 	{AMOVBU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
    203 	{AMOVH, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
    204 	{AMOVHS, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
    205 	{AMOVHU, C_SHIFT, C_NONE, C_REG, 23, 4, 0, 0, 0, 0},
    206 	{AMOVW, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
    207 	{AMOVW, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
    208 	{AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
    209 	{AMOVB, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
    210 	{AMOVB, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
    211 	{AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
    212 	{AMOVBS, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
    213 	{AMOVBS, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
    214 	{AMOVBS, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
    215 	{AMOVBU, C_REG, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
    216 	{AMOVBU, C_REG, C_NONE, C_LOREG, 30, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
    217 	{AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
    218 	{AMOVW, C_TLS_LE, C_NONE, C_REG, 101, 4, 0, LFROM, 0, 0},
    219 	{AMOVW, C_TLS_IE, C_NONE, C_REG, 102, 8, 0, LFROM, 0, 0},
    220 	{AMOVW, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
    221 	{AMOVW, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
    222 	{AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
    223 	{AMOVBU, C_LAUTO, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
    224 	{AMOVBU, C_LOREG, C_NONE, C_REG, 31, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
    225 	{AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
    226 	{AMOVW, C_LACON, C_NONE, C_REG, 34, 8, REGSP, LFROM, 0, C_SBIT},
    227 	{AMOVW, C_PSR, C_NONE, C_REG, 35, 4, 0, 0, 0, 0},
    228 	{AMOVW, C_REG, C_NONE, C_PSR, 36, 4, 0, 0, 0, 0},
    229 	{AMOVW, C_RCON, C_NONE, C_PSR, 37, 4, 0, 0, 0, 0},
    230 	{AMOVM, C_REGLIST, C_NONE, C_SOREG, 38, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    231 	{AMOVM, C_SOREG, C_NONE, C_REGLIST, 39, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    232 	{ASWPW, C_SOREG, C_REG, C_REG, 40, 4, 0, 0, 0, 0},
    233 	{ARFE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0, 0},
    234 	{AMOVF, C_FREG, C_NONE, C_FAUTO, 50, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    235 	{AMOVF, C_FREG, C_NONE, C_FOREG, 50, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    236 	{AMOVF, C_FAUTO, C_NONE, C_FREG, 51, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    237 	{AMOVF, C_FOREG, C_NONE, C_FREG, 51, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    238 	{AMOVF, C_FREG, C_NONE, C_LAUTO, 52, 12, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
    239 	{AMOVF, C_FREG, C_NONE, C_LOREG, 52, 12, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
    240 	{AMOVF, C_LAUTO, C_NONE, C_FREG, 53, 12, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
    241 	{AMOVF, C_LOREG, C_NONE, C_FREG, 53, 12, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
    242 	{AMOVF, C_FREG, C_NONE, C_ADDR, 68, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
    243 	{AMOVF, C_ADDR, C_NONE, C_FREG, 69, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
    244 	{AADDF, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0, 0},
    245 	{AADDF, C_FREG, C_FREG, C_FREG, 54, 4, 0, 0, 0, 0},
    246 	{AMOVF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0, 0},
    247 	{ANEGF, C_FREG, C_NONE, C_FREG, 55, 4, 0, 0, 0, 0},
    248 	{AMOVW, C_REG, C_NONE, C_FCR, 56, 4, 0, 0, 0, 0},
    249 	{AMOVW, C_FCR, C_NONE, C_REG, 57, 4, 0, 0, 0, 0},
    250 	{AMOVW, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    251 	{AMOVBU, C_SHIFTADDR, C_NONE, C_REG, 59, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    252 	{AMOVB, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    253 	{AMOVBS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    254 	{AMOVH, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    255 	{AMOVHS, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    256 	{AMOVHU, C_SHIFTADDR, C_NONE, C_REG, 60, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    257 	{AMOVW, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    258 	{AMOVB, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    259 	{AMOVBS, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    260 	{AMOVBU, C_REG, C_NONE, C_SHIFTADDR, 61, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    261 	{AMOVH, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    262 	{AMOVHS, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    263 	{AMOVHU, C_REG, C_NONE, C_SHIFTADDR, 62, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    264 	{AMOVH, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    265 	{AMOVH, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    266 	{AMOVHS, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    267 	{AMOVHS, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    268 	{AMOVHU, C_REG, C_NONE, C_HAUTO, 70, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    269 	{AMOVHU, C_REG, C_NONE, C_HOREG, 70, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    270 	{AMOVB, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    271 	{AMOVB, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    272 	{AMOVBS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    273 	{AMOVBS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    274 	{AMOVH, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    275 	{AMOVH, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    276 	{AMOVHS, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    277 	{AMOVHS, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    278 	{AMOVHU, C_HAUTO, C_NONE, C_REG, 71, 4, REGSP, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    279 	{AMOVHU, C_HOREG, C_NONE, C_REG, 71, 4, 0, 0, 0, C_PBIT | C_WBIT | C_UBIT},
    280 	{AMOVH, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
    281 	{AMOVH, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
    282 	{AMOVH, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
    283 	{AMOVHS, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
    284 	{AMOVHS, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
    285 	{AMOVHS, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
    286 	{AMOVHU, C_REG, C_NONE, C_LAUTO, 72, 8, REGSP, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
    287 	{AMOVHU, C_REG, C_NONE, C_LOREG, 72, 8, 0, LTO, 0, C_PBIT | C_WBIT | C_UBIT},
    288 	{AMOVHU, C_REG, C_NONE, C_ADDR, 94, 8, 0, LTO | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
    289 	{AMOVB, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
    290 	{AMOVB, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
    291 	{AMOVB, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
    292 	{AMOVBS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
    293 	{AMOVBS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
    294 	{AMOVBS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
    295 	{AMOVH, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
    296 	{AMOVH, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
    297 	{AMOVH, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
    298 	{AMOVHS, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
    299 	{AMOVHS, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
    300 	{AMOVHS, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
    301 	{AMOVHU, C_LAUTO, C_NONE, C_REG, 73, 8, REGSP, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
    302 	{AMOVHU, C_LOREG, C_NONE, C_REG, 73, 8, 0, LFROM, 0, C_PBIT | C_WBIT | C_UBIT},
    303 	{AMOVHU, C_ADDR, C_NONE, C_REG, 93, 8, 0, LFROM | LPCREL, 4, C_PBIT | C_WBIT | C_UBIT},
    304 	{ALDREX, C_SOREG, C_NONE, C_REG, 77, 4, 0, 0, 0, 0},
    305 	{ASTREX, C_SOREG, C_REG, C_REG, 78, 4, 0, 0, 0, 0},
    306 	{ADMB, C_NONE, C_NONE, C_NONE, 110, 4, 0, 0, 0, 0},
    307 	{ADMB, C_LCON, C_NONE, C_NONE, 110, 4, 0, 0, 0, 0},
    308 	{ADMB, C_SPR, C_NONE, C_NONE, 110, 4, 0, 0, 0, 0},
    309 	{AMOVF, C_ZFCON, C_NONE, C_FREG, 80, 8, 0, 0, 0, 0},
    310 	{AMOVF, C_SFCON, C_NONE, C_FREG, 81, 4, 0, 0, 0, 0},
    311 	{ACMPF, C_FREG, C_FREG, C_NONE, 82, 8, 0, 0, 0, 0},
    312 	{ACMPF, C_FREG, C_NONE, C_NONE, 83, 8, 0, 0, 0, 0},
    313 	{AMOVFW, C_FREG, C_NONE, C_FREG, 84, 4, 0, 0, 0, C_UBIT},
    314 	{AMOVWF, C_FREG, C_NONE, C_FREG, 85, 4, 0, 0, 0, C_UBIT},
    315 	{AMOVFW, C_FREG, C_NONE, C_REG, 86, 8, 0, 0, 0, C_UBIT},
    316 	{AMOVWF, C_REG, C_NONE, C_FREG, 87, 8, 0, 0, 0, C_UBIT},
    317 	{AMOVW, C_REG, C_NONE, C_FREG, 88, 4, 0, 0, 0, 0},
    318 	{AMOVW, C_FREG, C_NONE, C_REG, 89, 4, 0, 0, 0, 0},
    319 	{ALDREXD, C_SOREG, C_NONE, C_REG, 91, 4, 0, 0, 0, 0},
    320 	{ASTREXD, C_SOREG, C_REG, C_REG, 92, 4, 0, 0, 0, 0},
    321 	{APLD, C_SOREG, C_NONE, C_NONE, 95, 4, 0, 0, 0, 0},
    322 	{obj.AUNDEF, C_NONE, C_NONE, C_NONE, 96, 4, 0, 0, 0, 0},
    323 	{ACLZ, C_REG, C_NONE, C_REG, 97, 4, 0, 0, 0, 0},
    324 	{AMULWT, C_REG, C_REG, C_REG, 98, 4, 0, 0, 0, 0},
    325 	{AMULA, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0, C_SBIT},
    326 	{AMULAWT, C_REG, C_REG, C_REGREG2, 99, 4, 0, 0, 0, 0},
    327 	{obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0, 0, 0},
    328 	{obj.AFUNCDATA, C_LCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0, 0},
    329 	{obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0},
    330 	{obj.ANOP, C_LCON, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0}, // nop variants, see #40689
    331 	{obj.ANOP, C_REG, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0},
    332 	{obj.ANOP, C_FREG, C_NONE, C_NONE, 0, 0, 0, 0, 0, 0},
    333 	{obj.ADUFFZERO, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, // same as ABL
    334 	{obj.ADUFFCOPY, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0, 0}, // same as ABL
    335 	{obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0, 0},
    336 }
    337 
    338 var mbOp = []struct {
    339 	reg int16
    340 	enc uint32
    341 }{
    342 	{REG_MB_SY, 15},
    343 	{REG_MB_ST, 14},
    344 	{REG_MB_ISH, 11},
    345 	{REG_MB_ISHST, 10},
    346 	{REG_MB_NSH, 7},
    347 	{REG_MB_NSHST, 6},
    348 	{REG_MB_OSH, 3},
    349 	{REG_MB_OSHST, 2},
    350 }
    351 
    352 var oprange [ALAST & obj.AMask][]Optab
    353 
    354 var xcmp [C_GOK + 1][C_GOK + 1]bool
    355 
    356 var (
    357 	deferreturn *obj.LSym
    358 	symdiv      *obj.LSym
    359 	symdivu     *obj.LSym
    360 	symmod      *obj.LSym
    361 	symmodu     *obj.LSym
    362 )
    363 
    364 // Note about encoding: Prog.scond holds the condition encoding,
    365 // but XOR'ed with C_SCOND_XOR, so that C_SCOND_NONE == 0.
    366 // The code that shifts the value << 28 has the responsibility
    367 // for XORing with C_SCOND_XOR too.
    368 
    369 func checkSuffix(c *ctxt5, p *obj.Prog, o *Optab) {
    370 	if p.Scond&C_SBIT != 0 && o.scond&C_SBIT == 0 {
    371 		c.ctxt.Diag("invalid .S suffix: %v", p)
    372 	}
    373 	if p.Scond&C_PBIT != 0 && o.scond&C_PBIT == 0 {
    374 		c.ctxt.Diag("invalid .P suffix: %v", p)
    375 	}
    376 	if p.Scond&C_WBIT != 0 && o.scond&C_WBIT == 0 {
    377 		c.ctxt.Diag("invalid .W suffix: %v", p)
    378 	}
    379 	if p.Scond&C_UBIT != 0 && o.scond&C_UBIT == 0 {
    380 		c.ctxt.Diag("invalid .U suffix: %v", p)
    381 	}
    382 }
    383 
    384 func span5(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
    385 	if ctxt.Retpoline {
    386 		ctxt.Diag("-spectre=ret not supported on arm")
    387 		ctxt.Retpoline = false // don't keep printing
    388 	}
    389 
    390 	var p *obj.Prog
    391 	var op *obj.Prog
    392 
    393 	p = cursym.Func.Text
    394 	if p == nil || p.Link == nil { // handle external functions and ELF section symbols
    395 		return
    396 	}
    397 
    398 	if oprange[AAND&obj.AMask] == nil {
    399 		ctxt.Diag("arm ops not initialized, call arm.buildop first")
    400 	}
    401 
    402 	c := ctxt5{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: p.To.Offset + 4}
    403 	pc := int32(0)
    404 
    405 	op = p
    406 	p = p.Link
    407 	var m int
    408 	var o *Optab
    409 	for ; p != nil || c.blitrl != nil; op, p = p, p.Link {
    410 		if p == nil {
    411 			if c.checkpool(op, pc) {
    412 				p = op
    413 				continue
    414 			}
    415 
    416 			// can't happen: blitrl is not nil, but checkpool didn't flushpool
    417 			ctxt.Diag("internal inconsistency")
    418 
    419 			break
    420 		}
    421 
    422 		p.Pc = int64(pc)
    423 		o = c.oplook(p)
    424 		m = int(o.size)
    425 
    426 		if m%4 != 0 || p.Pc%4 != 0 {
    427 			ctxt.Diag("!pc invalid: %v size=%d", p, m)
    428 		}
    429 
    430 		// must check literal pool here in case p generates many instructions
    431 		if c.blitrl != nil {
    432 			// Emit the constant pool just before p if p
    433 			// would push us over the immediate size limit.
    434 			if c.checkpool(op, pc+int32(m)) {
    435 				// Back up to the instruction just
    436 				// before the pool and continue with
    437 				// the first instruction of the pool.
    438 				p = op
    439 				continue
    440 			}
    441 		}
    442 
    443 		if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.ANOP) {
    444 			ctxt.Diag("zero-width instruction\n%v", p)
    445 			continue
    446 		}
    447 
    448 		switch o.flag & (LFROM | LTO | LPOOL) {
    449 		case LFROM:
    450 			c.addpool(p, &p.From)
    451 
    452 		case LTO:
    453 			c.addpool(p, &p.To)
    454 
    455 		case LPOOL:
    456 			if p.Scond&C_SCOND == C_SCOND_NONE {
    457 				c.flushpool(p, 0, 0)
    458 			}
    459 		}
    460 
    461 		if p.As == AMOVW && p.To.Type == obj.TYPE_REG && p.To.Reg == REGPC && p.Scond&C_SCOND == C_SCOND_NONE {
    462 			c.flushpool(p, 0, 0)
    463 		}
    464 
    465 		pc += int32(m)
    466 	}
    467 
    468 	c.cursym.Size = int64(pc)
    469 
    470 	/*
    471 	 * if any procedure is large enough to
    472 	 * generate a large SBRA branch, then
    473 	 * generate extra passes putting branches
    474 	 * around jmps to fix. this is rare.
    475 	 */
    476 	times := 0
    477 
    478 	var bflag int
    479 	var opc int32
    480 	var out [6 + 3]uint32
    481 	for {
    482 		bflag = 0
    483 		pc = 0
    484 		times++
    485 		c.cursym.Func.Text.Pc = 0 // force re-layout the code.
    486 		for p = c.cursym.Func.Text; p != nil; p = p.Link {
    487 			o = c.oplook(p)
    488 			if int64(pc) > p.Pc {
    489 				p.Pc = int64(pc)
    490 			}
    491 
    492 			/* very large branches
    493 			if(o->type == 6 && p->pcond) {
    494 				otxt = p->pcond->pc - c;
    495 				if(otxt < 0)
    496 					otxt = -otxt;
    497 				if(otxt >= (1L<<17) - 10) {
    498 					q = emallocz(sizeof(Prog));
    499 					q->link = p->link;
    500 					p->link = q;
    501 					q->as = AB;
    502 					q->to.type = TYPE_BRANCH;
    503 					q->pcond = p->pcond;
    504 					p->pcond = q;
    505 					q = emallocz(sizeof(Prog));
    506 					q->link = p->link;
    507 					p->link = q;
    508 					q->as = AB;
    509 					q->to.type = TYPE_BRANCH;
    510 					q->pcond = q->link->link;
    511 					bflag = 1;
    512 				}
    513 			}
    514 			*/
    515 			opc = int32(p.Pc)
    516 			m = int(o.size)
    517 			if p.Pc != int64(opc) {
    518 				bflag = 1
    519 			}
    520 
    521 			//print("%v pc changed %d to %d in iter. %d\n", p, opc, (int32)p->pc, times);
    522 			pc = int32(p.Pc + int64(m))
    523 
    524 			if m%4 != 0 || p.Pc%4 != 0 {
    525 				ctxt.Diag("pc invalid: %v size=%d", p, m)
    526 			}
    527 
    528 			if m/4 > len(out) {
    529 				ctxt.Diag("instruction size too large: %d > %d", m/4, len(out))
    530 			}
    531 			if m == 0 && (p.As != obj.AFUNCDATA && p.As != obj.APCDATA && p.As != obj.ANOP) {
    532 				if p.As == obj.ATEXT {
    533 					c.autosize = p.To.Offset + 4
    534 					continue
    535 				}
    536 
    537 				ctxt.Diag("zero-width instruction\n%v", p)
    538 				continue
    539 			}
    540 		}
    541 
    542 		c.cursym.Size = int64(pc)
    543 		if bflag == 0 {
    544 			break
    545 		}
    546 	}
    547 
    548 	if pc%4 != 0 {
    549 		ctxt.Diag("sym->size=%d, invalid", pc)
    550 	}
    551 
    552 	/*
    553 	 * lay out the code.  all the pc-relative code references,
    554 	 * even cross-function, are resolved now;
    555 	 * only data references need to be relocated.
    556 	 * with more work we could leave cross-function
    557 	 * code references to be relocated too, and then
    558 	 * perhaps we'd be able to parallelize the span loop above.
    559 	 */
    560 
    561 	p = c.cursym.Func.Text
    562 	c.autosize = p.To.Offset + 4
    563 	c.cursym.Grow(c.cursym.Size)
    564 
    565 	bp := c.cursym.P
    566 	pc = int32(p.Pc) // even p->link might need extra padding
    567 	var v int
    568 	for p = p.Link; p != nil; p = p.Link {
    569 		c.pc = p.Pc
    570 		o = c.oplook(p)
    571 		opc = int32(p.Pc)
    572 		c.asmout(p, o, out[:])
    573 		m = int(o.size)
    574 
    575 		if m%4 != 0 || p.Pc%4 != 0 {
    576 			ctxt.Diag("final stage: pc invalid: %v size=%d", p, m)
    577 		}
    578 
    579 		if int64(pc) > p.Pc {
    580 			ctxt.Diag("PC padding invalid: want %#d, has %#d: %v", p.Pc, pc, p)
    581 		}
    582 		for int64(pc) != p.Pc {
    583 			// emit 0xe1a00000 (MOVW R0, R0)
    584 			bp[0] = 0x00
    585 			bp = bp[1:]
    586 
    587 			bp[0] = 0x00
    588 			bp = bp[1:]
    589 			bp[0] = 0xa0
    590 			bp = bp[1:]
    591 			bp[0] = 0xe1
    592 			bp = bp[1:]
    593 			pc += 4
    594 		}
    595 
    596 		for i := 0; i < m/4; i++ {
    597 			v = int(out[i])
    598 			bp[0] = byte(v)
    599 			bp = bp[1:]
    600 			bp[0] = byte(v >> 8)
    601 			bp = bp[1:]
    602 			bp[0] = byte(v >> 16)
    603 			bp = bp[1:]
    604 			bp[0] = byte(v >> 24)
    605 			bp = bp[1:]
    606 		}
    607 
    608 		pc += int32(m)
    609 	}
    610 }
    611 
    612 // checkpool flushes the literal pool when the first reference to
    613 // it threatens to go out of range of a 12-bit PC-relative offset.
    614 //
    615 // nextpc is the tentative next PC at which the pool could be emitted.
    616 // checkpool should be called *before* emitting the instruction that
    617 // would cause the PC to reach nextpc.
    618 // If nextpc is too far from the first pool reference, checkpool will
    619 // flush the pool immediately after p.
    620 // The caller should resume processing a p.Link.
    621 func (c *ctxt5) checkpool(p *obj.Prog, nextpc int32) bool {
    622 	poolLast := nextpc
    623 	poolLast += 4                      // the AB instruction to jump around the pool
    624 	poolLast += int32(c.pool.size) - 4 // the offset of the last pool entry
    625 
    626 	refPC := int32(c.pool.start) // PC of the first pool reference
    627 
    628 	v := poolLast - refPC - 8 // 12-bit PC-relative offset (see omvl)
    629 
    630 	if c.pool.size >= 0xff0 || immaddr(v) == 0 {
    631 		return c.flushpool(p, 1, 0)
    632 	} else if p.Link == nil {
    633 		return c.flushpool(p, 2, 0)
    634 	}
    635 	return false
    636 }
    637 
    638 func (c *ctxt5) flushpool(p *obj.Prog, skip int, force int) bool {
    639 	if c.blitrl != nil {
    640 		if skip != 0 {
    641 			if false && skip == 1 {
    642 				fmt.Printf("note: flush literal pool at %x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start)
    643 			}
    644 			q := c.newprog()
    645 			q.As = AB
    646 			q.To.Type = obj.TYPE_BRANCH
    647 			q.To.SetTarget(p.Link)
    648 			q.Link = c.blitrl
    649 			q.Pos = p.Pos
    650 			c.blitrl = q
    651 		} else if force == 0 && (p.Pc+int64(c.pool.size)-int64(c.pool.start) < 2048) {
    652 			return false
    653 		}
    654 
    655 		// The line number for constant pool entries doesn't really matter.
    656 		// We set it to the line number of the preceding instruction so that
    657 		// there are no deltas to encode in the pc-line tables.
    658 		for q := c.blitrl; q != nil; q = q.Link {
    659 			q.Pos = p.Pos
    660 		}
    661 
    662 		c.elitrl.Link = p.Link
    663 		p.Link = c.blitrl
    664 
    665 		c.blitrl = nil /* BUG: should refer back to values until out-of-range */
    666 		c.elitrl = nil
    667 		c.pool.size = 0
    668 		c.pool.start = 0
    669 		c.pool.extra = 0
    670 		return true
    671 	}
    672 
    673 	return false
    674 }
    675 
    676 func (c *ctxt5) addpool(p *obj.Prog, a *obj.Addr) {
    677 	t := c.newprog()
    678 	t.As = AWORD
    679 
    680 	switch c.aclass(a) {
    681 	default:
    682 		t.To.Offset = a.Offset
    683 		t.To.Sym = a.Sym
    684 		t.To.Type = a.Type
    685 		t.To.Name = a.Name
    686 
    687 		if c.ctxt.Flag_shared && t.To.Sym != nil {
    688 			t.Rel = p
    689 		}
    690 
    691 	case C_SROREG,
    692 		C_LOREG,
    693 		C_ROREG,
    694 		C_FOREG,
    695 		C_SOREG,
    696 		C_HOREG,
    697 		C_FAUTO,
    698 		C_SAUTO,
    699 		C_LAUTO,
    700 		C_LACON:
    701 		t.To.Type = obj.TYPE_CONST
    702 		t.To.Offset = c.instoffset
    703 	}
    704 
    705 	if t.Rel == nil {
    706 		for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */
    707 			if q.Rel == nil && q.To == t.To {
    708 				p.Pool = q
    709 				return
    710 			}
    711 		}
    712 	}
    713 
    714 	q := c.newprog()
    715 	*q = *t
    716 	q.Pc = int64(c.pool.size)
    717 
    718 	if c.blitrl == nil {
    719 		c.blitrl = q
    720 		c.pool.start = uint32(p.Pc)
    721 	} else {
    722 		c.elitrl.Link = q
    723 	}
    724 	c.elitrl = q
    725 	c.pool.size += 4
    726 
    727 	// Store the link to the pool entry in Pool.
    728 	p.Pool = q
    729 }
    730 
    731 func (c *ctxt5) regoff(a *obj.Addr) int32 {
    732 	c.instoffset = 0
    733 	c.aclass(a)
    734 	return int32(c.instoffset)
    735 }
    736 
    737 func immrot(v uint32) int32 {
    738 	for i := 0; i < 16; i++ {
    739 		if v&^0xff == 0 {
    740 			return int32(uint32(int32(i)<<8) | v | 1<<25)
    741 		}
    742 		v = v<<2 | v>>30
    743 	}
    744 
    745 	return 0
    746 }
    747 
    748 // immrot2a returns bits encoding the immediate constant fields of two instructions,
    749 // such that the encoded constants x, y satisfy x|y==v, x&y==0.
    750 // Returns 0,0 if no such decomposition of v exists.
    751 func immrot2a(v uint32) (uint32, uint32) {
    752 	for i := uint(1); i < 32; i++ {
    753 		m := uint32(1<<i - 1)
    754 		if x, y := immrot(v&m), immrot(v&^m); x != 0 && y != 0 {
    755 			return uint32(x), uint32(y)
    756 		}
    757 	}
    758 	// TODO: handle some more cases, like where
    759 	// the wraparound from the rotate could help.
    760 	return 0, 0
    761 }
    762 
    763 // immrot2s returns bits encoding the immediate constant fields of two instructions,
    764 // such that the encoded constants y, x satisfy y-x==v, y&x==0.
    765 // Returns 0,0 if no such decomposition of v exists.
    766 func immrot2s(v uint32) (uint32, uint32) {
    767 	if immrot(v) != 0 {
    768 		return v, 0
    769 	}
    770 	// suppose v in the form of {leading 00, upper effective bits, lower 8 effective bits, trailing 00}
    771 	// omit trailing 00
    772 	var i uint32
    773 	for i = 2; i < 32; i += 2 {
    774 		if v&(1<<i-1) != 0 {
    775 			break
    776 		}
    777 	}
    778 	// i must be <= 24, then adjust i just above lower 8 effective bits of v
    779 	i += 6
    780 	// let x = {the complement of lower 8 effective bits, trailing 00}, y = x + v
    781 	x := 1<<i - v&(1<<i-1)
    782 	y := v + x
    783 	if y, x = uint32(immrot(y)), uint32(immrot(x)); y != 0 && x != 0 {
    784 		return y, x
    785 	}
    786 	return 0, 0
    787 }
    788 
    789 func immaddr(v int32) int32 {
    790 	if v >= 0 && v <= 0xfff {
    791 		return v&0xfff | 1<<24 | 1<<23 /* pre indexing */ /* pre indexing, up */
    792 	}
    793 	if v >= -0xfff && v < 0 {
    794 		return -v&0xfff | 1<<24 /* pre indexing */
    795 	}
    796 	return 0
    797 }
    798 
    799 func immfloat(v int32) bool {
    800 	return v&0xC03 == 0 /* offset will fit in floating-point load/store */
    801 }
    802 
    803 func immhalf(v int32) bool {
    804 	if v >= 0 && v <= 0xff {
    805 		return v|1<<24|1<<23 != 0 /* pre indexing */ /* pre indexing, up */
    806 	}
    807 	if v >= -0xff && v < 0 {
    808 		return -v&0xff|1<<24 != 0 /* pre indexing */
    809 	}
    810 	return false
    811 }
    812 
    813 func (c *ctxt5) aclass(a *obj.Addr) int {
    814 	switch a.Type {
    815 	case obj.TYPE_NONE:
    816 		return C_NONE
    817 
    818 	case obj.TYPE_REG:
    819 		c.instoffset = 0
    820 		if REG_R0 <= a.Reg && a.Reg <= REG_R15 {
    821 			return C_REG
    822 		}
    823 		if REG_F0 <= a.Reg && a.Reg <= REG_F15 {
    824 			return C_FREG
    825 		}
    826 		if a.Reg == REG_FPSR || a.Reg == REG_FPCR {
    827 			return C_FCR
    828 		}
    829 		if a.Reg == REG_CPSR || a.Reg == REG_SPSR {
    830 			return C_PSR
    831 		}
    832 		if a.Reg >= REG_SPECIAL {
    833 			return C_SPR
    834 		}
    835 		return C_GOK
    836 
    837 	case obj.TYPE_REGREG:
    838 		return C_REGREG
    839 
    840 	case obj.TYPE_REGREG2:
    841 		return C_REGREG2
    842 
    843 	case obj.TYPE_REGLIST:
    844 		return C_REGLIST
    845 
    846 	case obj.TYPE_SHIFT:
    847 		if a.Reg == 0 {
    848 			// register shift R>>i
    849 			return C_SHIFT
    850 		} else {
    851 			// memory address with shifted offset R>>i(R)
    852 			return C_SHIFTADDR
    853 		}
    854 
    855 	case obj.TYPE_MEM:
    856 		switch a.Name {
    857 		case obj.NAME_EXTERN,
    858 			obj.NAME_GOTREF,
    859 			obj.NAME_STATIC:
    860 			if a.Sym == nil || a.Sym.Name == "" {
    861 				fmt.Printf("null sym external\n")
    862 				return C_GOK
    863 			}
    864 
    865 			c.instoffset = 0 // s.b. unused but just in case
    866 			if a.Sym.Type == objabi.STLSBSS {
    867 				if c.ctxt.Flag_shared {
    868 					return C_TLS_IE
    869 				} else {
    870 					return C_TLS_LE
    871 				}
    872 			}
    873 
    874 			return C_ADDR
    875 
    876 		case obj.NAME_AUTO:
    877 			if a.Reg == REGSP {
    878 				// unset base register for better printing, since
    879 				// a.Offset is still relative to pseudo-SP.
    880 				a.Reg = obj.REG_NONE
    881 			}
    882 			c.instoffset = c.autosize + a.Offset
    883 			if t := immaddr(int32(c.instoffset)); t != 0 {
    884 				if immhalf(int32(c.instoffset)) {
    885 					if immfloat(t) {
    886 						return C_HFAUTO
    887 					}
    888 					return C_HAUTO
    889 				}
    890 
    891 				if immfloat(t) {
    892 					return C_FAUTO
    893 				}
    894 				return C_SAUTO
    895 			}
    896 
    897 			return C_LAUTO
    898 
    899 		case obj.NAME_PARAM:
    900 			if a.Reg == REGSP {
    901 				// unset base register for better printing, since
    902 				// a.Offset is still relative to pseudo-FP.
    903 				a.Reg = obj.REG_NONE
    904 			}
    905 			c.instoffset = c.autosize + a.Offset + 4
    906 			if t := immaddr(int32(c.instoffset)); t != 0 {
    907 				if immhalf(int32(c.instoffset)) {
    908 					if immfloat(t) {
    909 						return C_HFAUTO
    910 					}
    911 					return C_HAUTO
    912 				}
    913 
    914 				if immfloat(t) {
    915 					return C_FAUTO
    916 				}
    917 				return C_SAUTO
    918 			}
    919 
    920 			return C_LAUTO
    921 
    922 		case obj.NAME_NONE:
    923 			c.instoffset = a.Offset
    924 			if t := immaddr(int32(c.instoffset)); t != 0 {
    925 				if immhalf(int32(c.instoffset)) { /* n.b. that it will also satisfy immrot */
    926 					if immfloat(t) {
    927 						return C_HFOREG
    928 					}
    929 					return C_HOREG
    930 				}
    931 
    932 				if immfloat(t) {
    933 					return C_FOREG /* n.b. that it will also satisfy immrot */
    934 				}
    935 				if immrot(uint32(c.instoffset)) != 0 {
    936 					return C_SROREG
    937 				}
    938 				if immhalf(int32(c.instoffset)) {
    939 					return C_HOREG
    940 				}
    941 				return C_SOREG
    942 			}
    943 
    944 			if immrot(uint32(c.instoffset)) != 0 {
    945 				return C_ROREG
    946 			}
    947 			return C_LOREG
    948 		}
    949 
    950 		return C_GOK
    951 
    952 	case obj.TYPE_FCONST:
    953 		if c.chipzero5(a.Val.(float64)) >= 0 {
    954 			return C_ZFCON
    955 		}
    956 		if c.chipfloat5(a.Val.(float64)) >= 0 {
    957 			return C_SFCON
    958 		}
    959 		return C_LFCON
    960 
    961 	case obj.TYPE_TEXTSIZE:
    962 		return C_TEXTSIZE
    963 
    964 	case obj.TYPE_CONST,
    965 		obj.TYPE_ADDR:
    966 		switch a.Name {
    967 		case obj.NAME_NONE:
    968 			c.instoffset = a.Offset
    969 			if a.Reg != 0 {
    970 				return c.aconsize()
    971 			}
    972 
    973 			if immrot(uint32(c.instoffset)) != 0 {
    974 				return C_RCON
    975 			}
    976 			if immrot(^uint32(c.instoffset)) != 0 {
    977 				return C_NCON
    978 			}
    979 			if uint32(c.instoffset) <= 0xffff && objabi.GOARM == 7 {
    980 				return C_SCON
    981 			}
    982 			if x, y := immrot2a(uint32(c.instoffset)); x != 0 && y != 0 {
    983 				return C_RCON2A
    984 			}
    985 			if y, x := immrot2s(uint32(c.instoffset)); x != 0 && y != 0 {
    986 				return C_RCON2S
    987 			}
    988 			return C_LCON
    989 
    990 		case obj.NAME_EXTERN,
    991 			obj.NAME_GOTREF,
    992 			obj.NAME_STATIC:
    993 			s := a.Sym
    994 			if s == nil {
    995 				break
    996 			}
    997 			c.instoffset = 0 // s.b. unused but just in case
    998 			return C_LCONADDR
    999 
   1000 		case obj.NAME_AUTO:
   1001 			if a.Reg == REGSP {
   1002 				// unset base register for better printing, since
   1003 				// a.Offset is still relative to pseudo-SP.
   1004 				a.Reg = obj.REG_NONE
   1005 			}
   1006 			c.instoffset = c.autosize + a.Offset
   1007 			return c.aconsize()
   1008 
   1009 		case obj.NAME_PARAM:
   1010 			if a.Reg == REGSP {
   1011 				// unset base register for better printing, since
   1012 				// a.Offset is still relative to pseudo-FP.
   1013 				a.Reg = obj.REG_NONE
   1014 			}
   1015 			c.instoffset = c.autosize + a.Offset + 4
   1016 			return c.aconsize()
   1017 		}
   1018 
   1019 		return C_GOK
   1020 
   1021 	case obj.TYPE_BRANCH:
   1022 		return C_SBRA
   1023 	}
   1024 
   1025 	return C_GOK
   1026 }
   1027 
   1028 func (c *ctxt5) aconsize() int {
   1029 	if immrot(uint32(c.instoffset)) != 0 {
   1030 		return C_RACON
   1031 	}
   1032 	if immrot(uint32(-c.instoffset)) != 0 {
   1033 		return C_RACON
   1034 	}
   1035 	return C_LACON
   1036 }
   1037 
   1038 func (c *ctxt5) oplook(p *obj.Prog) *Optab {
   1039 	a1 := int(p.Optab)
   1040 	if a1 != 0 {
   1041 		return &optab[a1-1]
   1042 	}
   1043 	a1 = int(p.From.Class)
   1044 	if a1 == 0 {
   1045 		a1 = c.aclass(&p.From) + 1
   1046 		p.From.Class = int8(a1)
   1047 	}
   1048 
   1049 	a1--
   1050 	a3 := int(p.To.Class)
   1051 	if a3 == 0 {
   1052 		a3 = c.aclass(&p.To) + 1
   1053 		p.To.Class = int8(a3)
   1054 	}
   1055 
   1056 	a3--
   1057 	a2 := C_NONE
   1058 	if p.Reg != 0 {
   1059 		switch {
   1060 		case REG_F0 <= p.Reg && p.Reg <= REG_F15:
   1061 			a2 = C_FREG
   1062 		case REG_R0 <= p.Reg && p.Reg <= REG_R15:
   1063 			a2 = C_REG
   1064 		default:
   1065 			c.ctxt.Diag("invalid register in %v", p)
   1066 		}
   1067 	}
   1068 
   1069 	// check illegal base register
   1070 	switch a1 {
   1071 	case C_SOREG, C_LOREG, C_HOREG, C_FOREG, C_ROREG, C_HFOREG, C_SROREG, C_SHIFTADDR:
   1072 		if p.From.Reg < REG_R0 || REG_R15 < p.From.Reg {
   1073 			c.ctxt.Diag("illegal base register: %v", p)
   1074 		}
   1075 	default:
   1076 	}
   1077 	switch a3 {
   1078 	case C_SOREG, C_LOREG, C_HOREG, C_FOREG, C_ROREG, C_HFOREG, C_SROREG, C_SHIFTADDR:
   1079 		if p.To.Reg < REG_R0 || REG_R15 < p.To.Reg {
   1080 			c.ctxt.Diag("illegal base register: %v", p)
   1081 		}
   1082 	default:
   1083 	}
   1084 
   1085 	// If current instruction has a .S suffix (flags update),
   1086 	// we must use the constant pool instead of splitting it.
   1087 	if (a1 == C_RCON2A || a1 == C_RCON2S) && p.Scond&C_SBIT != 0 {
   1088 		a1 = C_LCON
   1089 	}
   1090 	if (a3 == C_RCON2A || a3 == C_RCON2S) && p.Scond&C_SBIT != 0 {
   1091 		a3 = C_LCON
   1092 	}
   1093 
   1094 	if false { /*debug['O']*/
   1095 		fmt.Printf("oplook %v %v %v %v\n", p.As, DRconv(a1), DRconv(a2), DRconv(a3))
   1096 		fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type)
   1097 	}
   1098 
   1099 	ops := oprange[p.As&obj.AMask]
   1100 	c1 := &xcmp[a1]
   1101 	c3 := &xcmp[a3]
   1102 	for i := range ops {
   1103 		op := &ops[i]
   1104 		if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] {
   1105 			p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
   1106 			checkSuffix(c, p, op)
   1107 			return op
   1108 		}
   1109 	}
   1110 
   1111 	c.ctxt.Diag("illegal combination %v; %v %v %v; from %d %d; to %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), p.From.Type, p.From.Name, p.To.Type, p.To.Name)
   1112 	if ops == nil {
   1113 		ops = optab
   1114 	}
   1115 	return &ops[0]
   1116 }
   1117 
   1118 func cmp(a int, b int) bool {
   1119 	if a == b {
   1120 		return true
   1121 	}
   1122 	switch a {
   1123 	case C_LCON:
   1124 		if b == C_RCON || b == C_NCON || b == C_SCON || b == C_RCON2A || b == C_RCON2S {
   1125 			return true
   1126 		}
   1127 
   1128 	case C_LACON:
   1129 		if b == C_RACON {
   1130 			return true
   1131 		}
   1132 
   1133 	case C_LFCON:
   1134 		if b == C_ZFCON || b == C_SFCON {
   1135 			return true
   1136 		}
   1137 
   1138 	case C_HFAUTO:
   1139 		return b == C_HAUTO || b == C_FAUTO
   1140 
   1141 	case C_FAUTO, C_HAUTO:
   1142 		return b == C_HFAUTO
   1143 
   1144 	case C_SAUTO:
   1145 		return cmp(C_HFAUTO, b)
   1146 
   1147 	case C_LAUTO:
   1148 		return cmp(C_SAUTO, b)
   1149 
   1150 	case C_HFOREG:
   1151 		return b == C_HOREG || b == C_FOREG
   1152 
   1153 	case C_FOREG, C_HOREG:
   1154 		return b == C_HFOREG
   1155 
   1156 	case C_SROREG:
   1157 		return cmp(C_SOREG, b) || cmp(C_ROREG, b)
   1158 
   1159 	case C_SOREG, C_ROREG:
   1160 		return b == C_SROREG || cmp(C_HFOREG, b)
   1161 
   1162 	case C_LOREG:
   1163 		return cmp(C_SROREG, b)
   1164 
   1165 	case C_LBRA:
   1166 		if b == C_SBRA {
   1167 			return true
   1168 		}
   1169 
   1170 	case C_HREG:
   1171 		return cmp(C_SP, b) || cmp(C_PC, b)
   1172 	}
   1173 
   1174 	return false
   1175 }
   1176 
   1177 type ocmp []Optab
   1178 
   1179 func (x ocmp) Len() int {
   1180 	return len(x)
   1181 }
   1182 
   1183 func (x ocmp) Swap(i, j int) {
   1184 	x[i], x[j] = x[j], x[i]
   1185 }
   1186 
   1187 func (x ocmp) Less(i, j int) bool {
   1188 	p1 := &x[i]
   1189 	p2 := &x[j]
   1190 	n := int(p1.as) - int(p2.as)
   1191 	if n != 0 {
   1192 		return n < 0
   1193 	}
   1194 	n = int(p1.a1) - int(p2.a1)
   1195 	if n != 0 {
   1196 		return n < 0
   1197 	}
   1198 	n = int(p1.a2) - int(p2.a2)
   1199 	if n != 0 {
   1200 		return n < 0
   1201 	}
   1202 	n = int(p1.a3) - int(p2.a3)
   1203 	if n != 0 {
   1204 		return n < 0
   1205 	}
   1206 	return false
   1207 }
   1208 
   1209 func opset(a, b0 obj.As) {
   1210 	oprange[a&obj.AMask] = oprange[b0]
   1211 }
   1212 
   1213 func buildop(ctxt *obj.Link) {
   1214 	if oprange[AAND&obj.AMask] != nil {
   1215 		// Already initialized; stop now.
   1216 		// This happens in the cmd/asm tests,
   1217 		// each of which re-initializes the arch.
   1218 		return
   1219 	}
   1220 
   1221 	deferreturn = ctxt.LookupABI("runtime.deferreturn", obj.ABIInternal)
   1222 
   1223 	symdiv = ctxt.Lookup("runtime._div")
   1224 	symdivu = ctxt.Lookup("runtime._divu")
   1225 	symmod = ctxt.Lookup("runtime._mod")
   1226 	symmodu = ctxt.Lookup("runtime._modu")
   1227 
   1228 	var n int
   1229 
   1230 	for i := 0; i < C_GOK; i++ {
   1231 		for n = 0; n < C_GOK; n++ {
   1232 			if cmp(n, i) {
   1233 				xcmp[i][n] = true
   1234 			}
   1235 		}
   1236 	}
   1237 	for n = 0; optab[n].as != obj.AXXX; n++ {
   1238 		if optab[n].flag&LPCREL != 0 {
   1239 			if ctxt.Flag_shared {
   1240 				optab[n].size += int8(optab[n].pcrelsiz)
   1241 			} else {
   1242 				optab[n].flag &^= LPCREL
   1243 			}
   1244 		}
   1245 	}
   1246 
   1247 	sort.Sort(ocmp(optab[:n]))
   1248 	for i := 0; i < n; i++ {
   1249 		r := optab[i].as
   1250 		r0 := r & obj.AMask
   1251 		start := i
   1252 		for optab[i].as == r {
   1253 			i++
   1254 		}
   1255 		oprange[r0] = optab[start:i]
   1256 		i--
   1257 
   1258 		switch r {
   1259 		default:
   1260 			ctxt.Diag("unknown op in build: %v", r)
   1261 			ctxt.DiagFlush()
   1262 			log.Fatalf("bad code")
   1263 
   1264 		case AADD:
   1265 			opset(ASUB, r0)
   1266 			opset(ARSB, r0)
   1267 			opset(AADC, r0)
   1268 			opset(ASBC, r0)
   1269 			opset(ARSC, r0)
   1270 
   1271 		case AORR:
   1272 			opset(AEOR, r0)
   1273 			opset(ABIC, r0)
   1274 
   1275 		case ACMP:
   1276 			opset(ATEQ, r0)
   1277 			opset(ACMN, r0)
   1278 			opset(ATST, r0)
   1279 
   1280 		case AMVN:
   1281 			break
   1282 
   1283 		case ABEQ:
   1284 			opset(ABNE, r0)
   1285 			opset(ABCS, r0)
   1286 			opset(ABHS, r0)
   1287 			opset(ABCC, r0)
   1288 			opset(ABLO, r0)
   1289 			opset(ABMI, r0)
   1290 			opset(ABPL, r0)
   1291 			opset(ABVS, r0)
   1292 			opset(ABVC, r0)
   1293 			opset(ABHI, r0)
   1294 			opset(ABLS, r0)
   1295 			opset(ABGE, r0)
   1296 			opset(ABLT, r0)
   1297 			opset(ABGT, r0)
   1298 			opset(ABLE, r0)
   1299 
   1300 		case ASLL:
   1301 			opset(ASRL, r0)
   1302 			opset(ASRA, r0)
   1303 
   1304 		case AMUL:
   1305 			opset(AMULU, r0)
   1306 
   1307 		case ADIV:
   1308 			opset(AMOD, r0)
   1309 			opset(AMODU, r0)
   1310 			opset(ADIVU, r0)
   1311 
   1312 		case ADIVHW:
   1313 			opset(ADIVUHW, r0)
   1314 
   1315 		case AMOVW,
   1316 			AMOVB,
   1317 			AMOVBS,
   1318 			AMOVBU,
   1319 			AMOVH,
   1320 			AMOVHS,
   1321 			AMOVHU:
   1322 			break
   1323 
   1324 		case ASWPW:
   1325 			opset(ASWPBU, r0)
   1326 
   1327 		case AB,
   1328 			ABL,
   1329 			ABX,
   1330 			ABXRET,
   1331 			obj.ADUFFZERO,
   1332 			obj.ADUFFCOPY,
   1333 			ASWI,
   1334 			AWORD,
   1335 			AMOVM,
   1336 			ARFE,
   1337 			obj.ATEXT:
   1338 			break
   1339 
   1340 		case AADDF:
   1341 			opset(AADDD, r0)
   1342 			opset(ASUBF, r0)
   1343 			opset(ASUBD, r0)
   1344 			opset(AMULF, r0)
   1345 			opset(AMULD, r0)
   1346 			opset(ANMULF, r0)
   1347 			opset(ANMULD, r0)
   1348 			opset(AMULAF, r0)
   1349 			opset(AMULAD, r0)
   1350 			opset(AMULSF, r0)
   1351 			opset(AMULSD, r0)
   1352 			opset(ANMULAF, r0)
   1353 			opset(ANMULAD, r0)
   1354 			opset(ANMULSF, r0)
   1355 			opset(ANMULSD, r0)
   1356 			opset(AFMULAF, r0)
   1357 			opset(AFMULAD, r0)
   1358 			opset(AFMULSF, r0)
   1359 			opset(AFMULSD, r0)
   1360 			opset(AFNMULAF, r0)
   1361 			opset(AFNMULAD, r0)
   1362 			opset(AFNMULSF, r0)
   1363 			opset(AFNMULSD, r0)
   1364 			opset(ADIVF, r0)
   1365 			opset(ADIVD, r0)
   1366 
   1367 		case ANEGF:
   1368 			opset(ANEGD, r0)
   1369 			opset(ASQRTF, r0)
   1370 			opset(ASQRTD, r0)
   1371 			opset(AMOVFD, r0)
   1372 			opset(AMOVDF, r0)
   1373 			opset(AABSF, r0)
   1374 			opset(AABSD, r0)
   1375 
   1376 		case ACMPF:
   1377 			opset(ACMPD, r0)
   1378 
   1379 		case AMOVF:
   1380 			opset(AMOVD, r0)
   1381 
   1382 		case AMOVFW:
   1383 			opset(AMOVDW, r0)
   1384 
   1385 		case AMOVWF:
   1386 			opset(AMOVWD, r0)
   1387 
   1388 		case AMULL:
   1389 			opset(AMULAL, r0)
   1390 			opset(AMULLU, r0)
   1391 			opset(AMULALU, r0)
   1392 
   1393 		case AMULWT:
   1394 			opset(AMULWB, r0)
   1395 			opset(AMULBB, r0)
   1396 			opset(AMMUL, r0)
   1397 
   1398 		case AMULAWT:
   1399 			opset(AMULAWB, r0)
   1400 			opset(AMULABB, r0)
   1401 			opset(AMULS, r0)
   1402 			opset(AMMULA, r0)
   1403 			opset(AMMULS, r0)
   1404 
   1405 		case ABFX:
   1406 			opset(ABFXU, r0)
   1407 			opset(ABFC, r0)
   1408 			opset(ABFI, r0)
   1409 
   1410 		case ACLZ:
   1411 			opset(AREV, r0)
   1412 			opset(AREV16, r0)
   1413 			opset(AREVSH, r0)
   1414 			opset(ARBIT, r0)
   1415 
   1416 		case AXTAB:
   1417 			opset(AXTAH, r0)
   1418 			opset(AXTABU, r0)
   1419 			opset(AXTAHU, r0)
   1420 
   1421 		case ALDREX,
   1422 			ASTREX,
   1423 			ALDREXD,
   1424 			ASTREXD,
   1425 			ADMB,
   1426 			APLD,
   1427 			AAND,
   1428 			AMULA,
   1429 			obj.AUNDEF,
   1430 			obj.AFUNCDATA,
   1431 			obj.APCDATA,
   1432 			obj.ANOP:
   1433 			break
   1434 		}
   1435 	}
   1436 }
   1437 
   1438 func (c *ctxt5) asmout(p *obj.Prog, o *Optab, out []uint32) {
   1439 	c.printp = p
   1440 	o1 := uint32(0)
   1441 	o2 := uint32(0)
   1442 	o3 := uint32(0)
   1443 	o4 := uint32(0)
   1444 	o5 := uint32(0)
   1445 	o6 := uint32(0)
   1446 	if false { /*debug['P']*/
   1447 		fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
   1448 	}
   1449 	switch o.type_ {
   1450 	default:
   1451 		c.ctxt.Diag("%v: unknown asm %d", p, o.type_)
   1452 
   1453 	case 0: /* pseudo ops */
   1454 		if false { /*debug['G']*/
   1455 			fmt.Printf("%x: %s: arm\n", uint32(p.Pc), p.From.Sym.Name)
   1456 		}
   1457 
   1458 	case 1: /* op R,[R],R */
   1459 		o1 = c.oprrr(p, p.As, int(p.Scond))
   1460 
   1461 		rf := int(p.From.Reg)
   1462 		rt := int(p.To.Reg)
   1463 		r := int(p.Reg)
   1464 		if p.To.Type == obj.TYPE_NONE {
   1465 			rt = 0
   1466 		}
   1467 		if p.As == AMOVB || p.As == AMOVH || p.As == AMOVW || p.As == AMVN {
   1468 			r = 0
   1469 		} else if r == 0 {
   1470 			r = rt
   1471 		}
   1472 		o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
   1473 
   1474 	case 2: /* movbu $I,[R],R */
   1475 		c.aclass(&p.From)
   1476 
   1477 		o1 = c.oprrr(p, p.As, int(p.Scond))
   1478 		o1 |= uint32(immrot(uint32(c.instoffset)))
   1479 		rt := int(p.To.Reg)
   1480 		r := int(p.Reg)
   1481 		if p.To.Type == obj.TYPE_NONE {
   1482 			rt = 0
   1483 		}
   1484 		if p.As == AMOVW || p.As == AMVN {
   1485 			r = 0
   1486 		} else if r == 0 {
   1487 			r = rt
   1488 		}
   1489 		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
   1490 
   1491 	case 106: /* op $I,R,R where I can be decomposed into 2 immediates */
   1492 		c.aclass(&p.From)
   1493 		r := int(p.Reg)
   1494 		rt := int(p.To.Reg)
   1495 		if r == 0 {
   1496 			r = rt
   1497 		}
   1498 		x, y := immrot2a(uint32(c.instoffset))
   1499 		var as2 obj.As
   1500 		switch p.As {
   1501 		case AADD, ASUB, AORR, AEOR, ABIC:
   1502 			as2 = p.As // ADD, SUB, ORR, EOR, BIC
   1503 		case ARSB:
   1504 			as2 = AADD // RSB -> RSB/ADD pair
   1505 		case AADC:
   1506 			as2 = AADD // ADC -> ADC/ADD pair
   1507 		case ASBC:
   1508 			as2 = ASUB // SBC -> SBC/SUB pair
   1509 		case ARSC:
   1510 			as2 = AADD // RSC -> RSC/ADD pair
   1511 		default:
   1512 			c.ctxt.Diag("unknown second op for %v", p)
   1513 		}
   1514 		o1 = c.oprrr(p, p.As, int(p.Scond))
   1515 		o2 = c.oprrr(p, as2, int(p.Scond))
   1516 		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
   1517 		o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12
   1518 		o1 |= x
   1519 		o2 |= y
   1520 
   1521 	case 107: /* op $I,R,R where I can be decomposed into 2 immediates */
   1522 		c.aclass(&p.From)
   1523 		r := int(p.Reg)
   1524 		rt := int(p.To.Reg)
   1525 		if r == 0 {
   1526 			r = rt
   1527 		}
   1528 		y, x := immrot2s(uint32(c.instoffset))
   1529 		var as2 obj.As
   1530 		switch p.As {
   1531 		case AADD:
   1532 			as2 = ASUB // ADD -> ADD/SUB pair
   1533 		case ASUB:
   1534 			as2 = AADD // SUB -> SUB/ADD pair
   1535 		case ARSB:
   1536 			as2 = ASUB // RSB -> RSB/SUB pair
   1537 		case AADC:
   1538 			as2 = ASUB // ADC -> ADC/SUB pair
   1539 		case ASBC:
   1540 			as2 = AADD // SBC -> SBC/ADD pair
   1541 		case ARSC:
   1542 			as2 = ASUB // RSC -> RSC/SUB pair
   1543 		default:
   1544 			c.ctxt.Diag("unknown second op for %v", p)
   1545 		}
   1546 		o1 = c.oprrr(p, p.As, int(p.Scond))
   1547 		o2 = c.oprrr(p, as2, int(p.Scond))
   1548 		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
   1549 		o2 |= (uint32(rt)&15)<<16 | (uint32(rt)&15)<<12
   1550 		o1 |= y
   1551 		o2 |= x
   1552 
   1553 	case 3: /* add R<<[IR],[R],R */
   1554 		o1 = c.mov(p)
   1555 
   1556 	case 4: /* MOVW $off(R), R -> add $off,[R],R */
   1557 		c.aclass(&p.From)
   1558 		if c.instoffset < 0 {
   1559 			o1 = c.oprrr(p, ASUB, int(p.Scond))
   1560 			o1 |= uint32(immrot(uint32(-c.instoffset)))
   1561 		} else {
   1562 			o1 = c.oprrr(p, AADD, int(p.Scond))
   1563 			o1 |= uint32(immrot(uint32(c.instoffset)))
   1564 		}
   1565 		r := int(p.From.Reg)
   1566 		if r == 0 {
   1567 			r = int(o.param)
   1568 		}
   1569 		o1 |= (uint32(r) & 15) << 16
   1570 		o1 |= (uint32(p.To.Reg) & 15) << 12
   1571 
   1572 	case 5: /* bra s */
   1573 		o1 = c.opbra(p, p.As, int(p.Scond))
   1574 
   1575 		v := int32(-8)
   1576 		if p.To.Sym != nil {
   1577 			rel := obj.Addrel(c.cursym)
   1578 			rel.Off = int32(c.pc)
   1579 			rel.Siz = 4
   1580 			rel.Sym = p.To.Sym
   1581 			v += int32(p.To.Offset)
   1582 			rel.Add = int64(o1) | (int64(v)>>2)&0xffffff
   1583 			rel.Type = objabi.R_CALLARM
   1584 			break
   1585 		}
   1586 
   1587 		if p.To.Target() != nil {
   1588 			v = int32((p.To.Target().Pc - c.pc) - 8)
   1589 		}
   1590 		o1 |= (uint32(v) >> 2) & 0xffffff
   1591 
   1592 	case 6: /* b ,O(R) -> add $O,R,PC */
   1593 		c.aclass(&p.To)
   1594 
   1595 		o1 = c.oprrr(p, AADD, int(p.Scond))
   1596 		o1 |= uint32(immrot(uint32(c.instoffset)))
   1597 		o1 |= (uint32(p.To.Reg) & 15) << 16
   1598 		o1 |= (REGPC & 15) << 12
   1599 
   1600 	case 7: /* bl (R) -> blx R */
   1601 		c.aclass(&p.To)
   1602 
   1603 		if c.instoffset != 0 {
   1604 			c.ctxt.Diag("%v: doesn't support BL offset(REG) with non-zero offset %d", p, c.instoffset)
   1605 		}
   1606 		o1 = c.oprrr(p, ABL, int(p.Scond))
   1607 		o1 |= (uint32(p.To.Reg) & 15) << 0
   1608 		rel := obj.Addrel(c.cursym)
   1609 		rel.Off = int32(c.pc)
   1610 		rel.Siz = 0
   1611 		rel.Type = objabi.R_CALLIND
   1612 
   1613 	case 8: /* sll $c,[R],R -> mov (R<<$c),R */
   1614 		c.aclass(&p.From)
   1615 
   1616 		o1 = c.oprrr(p, p.As, int(p.Scond))
   1617 		r := int(p.Reg)
   1618 		if r == 0 {
   1619 			r = int(p.To.Reg)
   1620 		}
   1621 		o1 |= (uint32(r) & 15) << 0
   1622 		o1 |= uint32((c.instoffset & 31) << 7)
   1623 		o1 |= (uint32(p.To.Reg) & 15) << 12
   1624 
   1625 	case 9: /* sll R,[R],R -> mov (R<<R),R */
   1626 		o1 = c.oprrr(p, p.As, int(p.Scond))
   1627 
   1628 		r := int(p.Reg)
   1629 		if r == 0 {
   1630 			r = int(p.To.Reg)
   1631 		}
   1632 		o1 |= (uint32(r) & 15) << 0
   1633 		o1 |= (uint32(p.From.Reg)&15)<<8 | 1<<4
   1634 		o1 |= (uint32(p.To.Reg) & 15) << 12
   1635 
   1636 	case 10: /* swi [$con] */
   1637 		o1 = c.oprrr(p, p.As, int(p.Scond))
   1638 
   1639 		if p.To.Type != obj.TYPE_NONE {
   1640 			c.aclass(&p.To)
   1641 			o1 |= uint32(c.instoffset & 0xffffff)
   1642 		}
   1643 
   1644 	case 11: /* word */
   1645 		c.aclass(&p.To)
   1646 
   1647 		o1 = uint32(c.instoffset)
   1648 		if p.To.Sym != nil {
   1649 			// This case happens with words generated
   1650 			// in the PC stream as part of the literal pool (c.pool).
   1651 			rel := obj.Addrel(c.cursym)
   1652 
   1653 			rel.Off = int32(c.pc)
   1654 			rel.Siz = 4
   1655 			rel.Sym = p.To.Sym
   1656 			rel.Add = p.To.Offset
   1657 
   1658 			if c.ctxt.Flag_shared {
   1659 				if p.To.Name == obj.NAME_GOTREF {
   1660 					rel.Type = objabi.R_GOTPCREL
   1661 				} else {
   1662 					rel.Type = objabi.R_PCREL
   1663 				}
   1664 				rel.Add += c.pc - p.Rel.Pc - 8
   1665 			} else {
   1666 				rel.Type = objabi.R_ADDR
   1667 			}
   1668 			o1 = 0
   1669 		}
   1670 
   1671 	case 12: /* movw $lcon, reg */
   1672 		if o.a1 == C_SCON {
   1673 			o1 = c.omvs(p, &p.From, int(p.To.Reg))
   1674 		} else if p.As == AMVN {
   1675 			o1 = c.omvr(p, &p.From, int(p.To.Reg))
   1676 		} else {
   1677 			o1 = c.omvl(p, &p.From, int(p.To.Reg))
   1678 		}
   1679 
   1680 		if o.flag&LPCREL != 0 {
   1681 			o2 = c.oprrr(p, AADD, int(p.Scond)) | (uint32(p.To.Reg)&15)<<0 | (REGPC&15)<<16 | (uint32(p.To.Reg)&15)<<12
   1682 		}
   1683 
   1684 	case 13: /* op $lcon, [R], R */
   1685 		if o.a1 == C_SCON {
   1686 			o1 = c.omvs(p, &p.From, REGTMP)
   1687 		} else {
   1688 			o1 = c.omvl(p, &p.From, REGTMP)
   1689 		}
   1690 
   1691 		if o1 == 0 {
   1692 			break
   1693 		}
   1694 		o2 = c.oprrr(p, p.As, int(p.Scond))
   1695 		o2 |= REGTMP & 15
   1696 		r := int(p.Reg)
   1697 		if p.As == AMVN {
   1698 			r = 0
   1699 		} else if r == 0 {
   1700 			r = int(p.To.Reg)
   1701 		}
   1702 		o2 |= (uint32(r) & 15) << 16
   1703 		if p.To.Type != obj.TYPE_NONE {
   1704 			o2 |= (uint32(p.To.Reg) & 15) << 12
   1705 		}
   1706 
   1707 	case 14: /* movb/movbu/movh/movhu R,R */
   1708 		o1 = c.oprrr(p, ASLL, int(p.Scond))
   1709 
   1710 		if p.As == AMOVBU || p.As == AMOVHU {
   1711 			o2 = c.oprrr(p, ASRL, int(p.Scond))
   1712 		} else {
   1713 			o2 = c.oprrr(p, ASRA, int(p.Scond))
   1714 		}
   1715 
   1716 		r := int(p.To.Reg)
   1717 		o1 |= (uint32(p.From.Reg)&15)<<0 | (uint32(r)&15)<<12
   1718 		o2 |= uint32(r)&15 | (uint32(r)&15)<<12
   1719 		if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU {
   1720 			o1 |= 24 << 7
   1721 			o2 |= 24 << 7
   1722 		} else {
   1723 			o1 |= 16 << 7
   1724 			o2 |= 16 << 7
   1725 		}
   1726 
   1727 	case 15: /* mul r,[r,]r */
   1728 		o1 = c.oprrr(p, p.As, int(p.Scond))
   1729 
   1730 		rf := int(p.From.Reg)
   1731 		rt := int(p.To.Reg)
   1732 		r := int(p.Reg)
   1733 		if r == 0 {
   1734 			r = rt
   1735 		}
   1736 
   1737 		o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16
   1738 
   1739 	case 16: /* div r,[r,]r */
   1740 		o1 = 0xf << 28
   1741 
   1742 		o2 = 0
   1743 
   1744 	case 17:
   1745 		o1 = c.oprrr(p, p.As, int(p.Scond))
   1746 		rf := int(p.From.Reg)
   1747 		rt := int(p.To.Reg)
   1748 		rt2 := int(p.To.Offset)
   1749 		r := int(p.Reg)
   1750 		o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16 | (uint32(rt2)&15)<<12
   1751 
   1752 	case 18: /* BFX/BFXU/BFC/BFI */
   1753 		o1 = c.oprrr(p, p.As, int(p.Scond))
   1754 		rt := int(p.To.Reg)
   1755 		r := int(p.Reg)
   1756 		if r == 0 {
   1757 			r = rt
   1758 		} else if p.As == ABFC { // only "BFC $width, $lsb, Reg" is accepted, p.Reg must be 0
   1759 			c.ctxt.Diag("illegal combination: %v", p)
   1760 		}
   1761 		if p.GetFrom3() == nil || p.GetFrom3().Type != obj.TYPE_CONST {
   1762 			c.ctxt.Diag("%v: missing or wrong LSB", p)
   1763 			break
   1764 		}
   1765 		lsb := p.GetFrom3().Offset
   1766 		width := p.From.Offset
   1767 		if lsb < 0 || lsb > 31 || width <= 0 || (lsb+width) > 32 {
   1768 			c.ctxt.Diag("%v: wrong width or LSB", p)
   1769 		}
   1770 		switch p.As {
   1771 		case ABFX, ABFXU: // (width-1) is encoded
   1772 			o1 |= (uint32(r)&15)<<0 | (uint32(rt)&15)<<12 | uint32(lsb)<<7 | uint32(width-1)<<16
   1773 		case ABFC, ABFI: // MSB is encoded
   1774 			o1 |= (uint32(r)&15)<<0 | (uint32(rt)&15)<<12 | uint32(lsb)<<7 | uint32(lsb+width-1)<<16
   1775 		default:
   1776 			c.ctxt.Diag("illegal combination: %v", p)
   1777 		}
   1778 
   1779 	case 20: /* mov/movb/movbu R,O(R) */
   1780 		c.aclass(&p.To)
   1781 
   1782 		r := int(p.To.Reg)
   1783 		if r == 0 {
   1784 			r = int(o.param)
   1785 		}
   1786 		o1 = c.osr(p.As, int(p.From.Reg), int32(c.instoffset), r, int(p.Scond))
   1787 
   1788 	case 21: /* mov/movbu O(R),R -> lr */
   1789 		c.aclass(&p.From)
   1790 
   1791 		r := int(p.From.Reg)
   1792 		if r == 0 {
   1793 			r = int(o.param)
   1794 		}
   1795 		o1 = c.olr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond))
   1796 		if p.As != AMOVW {
   1797 			o1 |= 1 << 22
   1798 		}
   1799 
   1800 	case 22: /* XTAB R@>i, [R], R */
   1801 		o1 = c.oprrr(p, p.As, int(p.Scond))
   1802 		switch p.From.Offset &^ 0xf {
   1803 		// only 0/8/16/24 bits rotation is accepted
   1804 		case SHIFT_RR, SHIFT_RR | 8<<7, SHIFT_RR | 16<<7, SHIFT_RR | 24<<7:
   1805 			o1 |= uint32(p.From.Offset) & 0xc0f
   1806 		default:
   1807 			c.ctxt.Diag("illegal shift: %v", p)
   1808 		}
   1809 		rt := p.To.Reg
   1810 		r := p.Reg
   1811 		if r == 0 {
   1812 			r = rt
   1813 		}
   1814 		o1 |= (uint32(rt)&15)<<12 | (uint32(r)&15)<<16
   1815 
   1816 	case 23: /* MOVW/MOVB/MOVH R@>i, R */
   1817 		switch p.As {
   1818 		case AMOVW:
   1819 			o1 = c.mov(p)
   1820 		case AMOVBU, AMOVBS, AMOVB, AMOVHU, AMOVHS, AMOVH:
   1821 			o1 = c.movxt(p)
   1822 		default:
   1823 			c.ctxt.Diag("illegal combination: %v", p)
   1824 		}
   1825 
   1826 	case 30: /* mov/movb/movbu R,L(R) */
   1827 		o1 = c.omvl(p, &p.To, REGTMP)
   1828 
   1829 		if o1 == 0 {
   1830 			break
   1831 		}
   1832 		r := int(p.To.Reg)
   1833 		if r == 0 {
   1834 			r = int(o.param)
   1835 		}
   1836 		o2 = c.osrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond))
   1837 		if p.As != AMOVW {
   1838 			o2 |= 1 << 22
   1839 		}
   1840 
   1841 	case 31: /* mov/movbu L(R),R -> lr[b] */
   1842 		o1 = c.omvl(p, &p.From, REGTMP)
   1843 
   1844 		if o1 == 0 {
   1845 			break
   1846 		}
   1847 		r := int(p.From.Reg)
   1848 		if r == 0 {
   1849 			r = int(o.param)
   1850 		}
   1851 		o2 = c.olrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond))
   1852 		if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB {
   1853 			o2 |= 1 << 22
   1854 		}
   1855 
   1856 	case 34: /* mov $lacon,R */
   1857 		o1 = c.omvl(p, &p.From, REGTMP)
   1858 
   1859 		if o1 == 0 {
   1860 			break
   1861 		}
   1862 
   1863 		o2 = c.oprrr(p, AADD, int(p.Scond))
   1864 		o2 |= REGTMP & 15
   1865 		r := int(p.From.Reg)
   1866 		if r == 0 {
   1867 			r = int(o.param)
   1868 		}
   1869 		o2 |= (uint32(r) & 15) << 16
   1870 		if p.To.Type != obj.TYPE_NONE {
   1871 			o2 |= (uint32(p.To.Reg) & 15) << 12
   1872 		}
   1873 
   1874 	case 35: /* mov PSR,R */
   1875 		o1 = 2<<23 | 0xf<<16 | 0<<0
   1876 
   1877 		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
   1878 		o1 |= (uint32(p.From.Reg) & 1) << 22
   1879 		o1 |= (uint32(p.To.Reg) & 15) << 12
   1880 
   1881 	case 36: /* mov R,PSR */
   1882 		o1 = 2<<23 | 0x2cf<<12 | 0<<4
   1883 
   1884 		if p.Scond&C_FBIT != 0 {
   1885 			o1 ^= 0x010 << 12
   1886 		}
   1887 		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
   1888 		o1 |= (uint32(p.To.Reg) & 1) << 22
   1889 		o1 |= (uint32(p.From.Reg) & 15) << 0
   1890 
   1891 	case 37: /* mov $con,PSR */
   1892 		c.aclass(&p.From)
   1893 
   1894 		o1 = 2<<23 | 0x2cf<<12 | 0<<4
   1895 		if p.Scond&C_FBIT != 0 {
   1896 			o1 ^= 0x010 << 12
   1897 		}
   1898 		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
   1899 		o1 |= uint32(immrot(uint32(c.instoffset)))
   1900 		o1 |= (uint32(p.To.Reg) & 1) << 22
   1901 		o1 |= (uint32(p.From.Reg) & 15) << 0
   1902 
   1903 	case 38, 39:
   1904 		switch o.type_ {
   1905 		case 38: /* movm $con,oreg -> stm */
   1906 			o1 = 0x4 << 25
   1907 
   1908 			o1 |= uint32(p.From.Offset & 0xffff)
   1909 			o1 |= (uint32(p.To.Reg) & 15) << 16
   1910 			c.aclass(&p.To)
   1911 
   1912 		case 39: /* movm oreg,$con -> ldm */
   1913 			o1 = 0x4<<25 | 1<<20
   1914 
   1915 			o1 |= uint32(p.To.Offset & 0xffff)
   1916 			o1 |= (uint32(p.From.Reg) & 15) << 16
   1917 			c.aclass(&p.From)
   1918 		}
   1919 
   1920 		if c.instoffset != 0 {
   1921 			c.ctxt.Diag("offset must be zero in MOVM; %v", p)
   1922 		}
   1923 		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
   1924 		if p.Scond&C_PBIT != 0 {
   1925 			o1 |= 1 << 24
   1926 		}
   1927 		if p.Scond&C_UBIT != 0 {
   1928 			o1 |= 1 << 23
   1929 		}
   1930 		if p.Scond&C_WBIT != 0 {
   1931 			o1 |= 1 << 21
   1932 		}
   1933 
   1934 	case 40: /* swp oreg,reg,reg */
   1935 		c.aclass(&p.From)
   1936 
   1937 		if c.instoffset != 0 {
   1938 			c.ctxt.Diag("offset must be zero in SWP")
   1939 		}
   1940 		o1 = 0x2<<23 | 0x9<<4
   1941 		if p.As != ASWPW {
   1942 			o1 |= 1 << 22
   1943 		}
   1944 		o1 |= (uint32(p.From.Reg) & 15) << 16
   1945 		o1 |= (uint32(p.Reg) & 15) << 0
   1946 		o1 |= (uint32(p.To.Reg) & 15) << 12
   1947 		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
   1948 
   1949 	case 41: /* rfe -> movm.s.w.u 0(r13),[r15] */
   1950 		o1 = 0xe8fd8000
   1951 
   1952 	case 50: /* floating point store */
   1953 		v := c.regoff(&p.To)
   1954 
   1955 		r := int(p.To.Reg)
   1956 		if r == 0 {
   1957 			r = int(o.param)
   1958 		}
   1959 		o1 = c.ofsr(p.As, int(p.From.Reg), v, r, int(p.Scond), p)
   1960 
   1961 	case 51: /* floating point load */
   1962 		v := c.regoff(&p.From)
   1963 
   1964 		r := int(p.From.Reg)
   1965 		if r == 0 {
   1966 			r = int(o.param)
   1967 		}
   1968 		o1 = c.ofsr(p.As, int(p.To.Reg), v, r, int(p.Scond), p) | 1<<20
   1969 
   1970 	case 52: /* floating point store, int32 offset UGLY */
   1971 		o1 = c.omvl(p, &p.To, REGTMP)
   1972 
   1973 		if o1 == 0 {
   1974 			break
   1975 		}
   1976 		r := int(p.To.Reg)
   1977 		if r == 0 {
   1978 			r = int(o.param)
   1979 		}
   1980 		o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0
   1981 		o3 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p)
   1982 
   1983 	case 53: /* floating point load, int32 offset UGLY */
   1984 		o1 = c.omvl(p, &p.From, REGTMP)
   1985 
   1986 		if o1 == 0 {
   1987 			break
   1988 		}
   1989 		r := int(p.From.Reg)
   1990 		if r == 0 {
   1991 			r = int(o.param)
   1992 		}
   1993 		o2 = c.oprrr(p, AADD, int(p.Scond)) | (REGTMP&15)<<12 | (REGTMP&15)<<16 | (uint32(r)&15)<<0
   1994 		o3 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20
   1995 
   1996 	case 54: /* floating point arith */
   1997 		o1 = c.oprrr(p, p.As, int(p.Scond))
   1998 
   1999 		rf := int(p.From.Reg)
   2000 		rt := int(p.To.Reg)
   2001 		r := int(p.Reg)
   2002 		if r == 0 {
   2003 			switch p.As {
   2004 			case AMULAD, AMULAF, AMULSF, AMULSD, ANMULAF, ANMULAD, ANMULSF, ANMULSD,
   2005 				AFMULAD, AFMULAF, AFMULSF, AFMULSD, AFNMULAF, AFNMULAD, AFNMULSF, AFNMULSD:
   2006 				c.ctxt.Diag("illegal combination: %v", p)
   2007 			default:
   2008 				r = rt
   2009 			}
   2010 		}
   2011 
   2012 		o1 |= (uint32(rf)&15)<<0 | (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
   2013 
   2014 	case 55: /* negf freg, freg */
   2015 		o1 = c.oprrr(p, p.As, int(p.Scond))
   2016 
   2017 		rf := int(p.From.Reg)
   2018 		rt := int(p.To.Reg)
   2019 
   2020 		o1 |= (uint32(rf)&15)<<0 | (uint32(rt)&15)<<12
   2021 
   2022 	case 56: /* move to FP[CS]R */
   2023 		o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xee1<<16 | 0xa1<<4
   2024 
   2025 		o1 |= (uint32(p.From.Reg) & 15) << 12
   2026 
   2027 	case 57: /* move from FP[CS]R */
   2028 		o1 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0xef1<<16 | 0xa1<<4
   2029 
   2030 		o1 |= (uint32(p.To.Reg) & 15) << 12
   2031 
   2032 	case 58: /* movbu R,R */
   2033 		o1 = c.oprrr(p, AAND, int(p.Scond))
   2034 
   2035 		o1 |= uint32(immrot(0xff))
   2036 		rt := int(p.To.Reg)
   2037 		r := int(p.From.Reg)
   2038 		if p.To.Type == obj.TYPE_NONE {
   2039 			rt = 0
   2040 		}
   2041 		if r == 0 {
   2042 			r = rt
   2043 		}
   2044 		o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
   2045 
   2046 	case 59: /* movw/bu R<<I(R),R -> ldr indexed */
   2047 		if p.From.Reg == 0 {
   2048 			c.ctxt.Diag("source operand is not a memory address: %v", p)
   2049 			break
   2050 		}
   2051 		if p.From.Offset&(1<<4) != 0 {
   2052 			c.ctxt.Diag("bad shift in LDR")
   2053 			break
   2054 		}
   2055 		o1 = c.olrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
   2056 		if p.As == AMOVBU {
   2057 			o1 |= 1 << 22
   2058 		}
   2059 
   2060 	case 60: /* movb R(R),R -> ldrsb indexed */
   2061 		if p.From.Reg == 0 {
   2062 			c.ctxt.Diag("source operand is not a memory address: %v", p)
   2063 			break
   2064 		}
   2065 		if p.From.Offset&(^0xf) != 0 {
   2066 			c.ctxt.Diag("bad shift: %v", p)
   2067 			break
   2068 		}
   2069 		o1 = c.olhrr(int(p.From.Offset), int(p.From.Reg), int(p.To.Reg), int(p.Scond))
   2070 		switch p.As {
   2071 		case AMOVB, AMOVBS:
   2072 			o1 ^= 1<<5 | 1<<6
   2073 		case AMOVH, AMOVHS:
   2074 			o1 ^= 1 << 6
   2075 		default:
   2076 		}
   2077 		if p.Scond&C_UBIT != 0 {
   2078 			o1 &^= 1 << 23
   2079 		}
   2080 
   2081 	case 61: /* movw/b/bu R,R<<[IR](R) -> str indexed */
   2082 		if p.To.Reg == 0 {
   2083 			c.ctxt.Diag("MOV to shifter operand")
   2084 		}
   2085 		o1 = c.osrr(int(p.From.Reg), int(p.To.Offset), int(p.To.Reg), int(p.Scond))
   2086 		if p.As == AMOVB || p.As == AMOVBS || p.As == AMOVBU {
   2087 			o1 |= 1 << 22
   2088 		}
   2089 
   2090 	case 62: /* MOVH/MOVHS/MOVHU Reg, Reg<<0(Reg) -> strh */
   2091 		if p.To.Reg == 0 {
   2092 			c.ctxt.Diag("MOV to shifter operand")
   2093 		}
   2094 		if p.To.Offset&(^0xf) != 0 {
   2095 			c.ctxt.Diag("bad shift: %v", p)
   2096 		}
   2097 		o1 = c.olhrr(int(p.To.Offset), int(p.To.Reg), int(p.From.Reg), int(p.Scond))
   2098 		o1 ^= 1 << 20
   2099 		if p.Scond&C_UBIT != 0 {
   2100 			o1 &^= 1 << 23
   2101 		}
   2102 
   2103 		/* reloc ops */
   2104 	case 64: /* mov/movb/movbu R,addr */
   2105 		o1 = c.omvl(p, &p.To, REGTMP)
   2106 
   2107 		if o1 == 0 {
   2108 			break
   2109 		}
   2110 		o2 = c.osr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond))
   2111 		if o.flag&LPCREL != 0 {
   2112 			o3 = o2
   2113 			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
   2114 		}
   2115 
   2116 	case 65: /* mov/movbu addr,R */
   2117 		o1 = c.omvl(p, &p.From, REGTMP)
   2118 
   2119 		if o1 == 0 {
   2120 			break
   2121 		}
   2122 		o2 = c.olr(0, REGTMP, int(p.To.Reg), int(p.Scond))
   2123 		if p.As == AMOVBU || p.As == AMOVBS || p.As == AMOVB {
   2124 			o2 |= 1 << 22
   2125 		}
   2126 		if o.flag&LPCREL != 0 {
   2127 			o3 = o2
   2128 			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
   2129 		}
   2130 
   2131 	case 101: /* movw tlsvar,R, local exec*/
   2132 		o1 = c.omvl(p, &p.From, int(p.To.Reg))
   2133 
   2134 	case 102: /* movw tlsvar,R, initial exec*/
   2135 		o1 = c.omvl(p, &p.From, int(p.To.Reg))
   2136 		o2 = c.olrr(int(p.To.Reg)&15, (REGPC & 15), int(p.To.Reg), int(p.Scond))
   2137 
   2138 	case 103: /* word tlsvar, local exec */
   2139 		if p.To.Sym == nil {
   2140 			c.ctxt.Diag("nil sym in tls %v", p)
   2141 		}
   2142 		if p.To.Offset != 0 {
   2143 			c.ctxt.Diag("offset against tls var in %v", p)
   2144 		}
   2145 		// This case happens with words generated in the PC stream as part of
   2146 		// the literal c.pool.
   2147 		rel := obj.Addrel(c.cursym)
   2148 
   2149 		rel.Off = int32(c.pc)
   2150 		rel.Siz = 4
   2151 		rel.Sym = p.To.Sym
   2152 		rel.Type = objabi.R_TLS_LE
   2153 		o1 = 0
   2154 
   2155 	case 104: /* word tlsvar, initial exec */
   2156 		if p.To.Sym == nil {
   2157 			c.ctxt.Diag("nil sym in tls %v", p)
   2158 		}
   2159 		if p.To.Offset != 0 {
   2160 			c.ctxt.Diag("offset against tls var in %v", p)
   2161 		}
   2162 		rel := obj.Addrel(c.cursym)
   2163 		rel.Off = int32(c.pc)
   2164 		rel.Siz = 4
   2165 		rel.Sym = p.To.Sym
   2166 		rel.Type = objabi.R_TLS_IE
   2167 		rel.Add = c.pc - p.Rel.Pc - 8 - int64(rel.Siz)
   2168 
   2169 	case 68: /* floating point store -> ADDR */
   2170 		o1 = c.omvl(p, &p.To, REGTMP)
   2171 
   2172 		if o1 == 0 {
   2173 			break
   2174 		}
   2175 		o2 = c.ofsr(p.As, int(p.From.Reg), 0, REGTMP, int(p.Scond), p)
   2176 		if o.flag&LPCREL != 0 {
   2177 			o3 = o2
   2178 			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
   2179 		}
   2180 
   2181 	case 69: /* floating point load <- ADDR */
   2182 		o1 = c.omvl(p, &p.From, REGTMP)
   2183 
   2184 		if o1 == 0 {
   2185 			break
   2186 		}
   2187 		o2 = c.ofsr(p.As, int(p.To.Reg), 0, (REGTMP&15), int(p.Scond), p) | 1<<20
   2188 		if o.flag&LPCREL != 0 {
   2189 			o3 = o2
   2190 			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
   2191 		}
   2192 
   2193 		/* ArmV4 ops: */
   2194 	case 70: /* movh/movhu R,O(R) -> strh */
   2195 		c.aclass(&p.To)
   2196 
   2197 		r := int(p.To.Reg)
   2198 		if r == 0 {
   2199 			r = int(o.param)
   2200 		}
   2201 		o1 = c.oshr(int(p.From.Reg), int32(c.instoffset), r, int(p.Scond))
   2202 
   2203 	case 71: /* movb/movh/movhu O(R),R -> ldrsb/ldrsh/ldrh */
   2204 		c.aclass(&p.From)
   2205 
   2206 		r := int(p.From.Reg)
   2207 		if r == 0 {
   2208 			r = int(o.param)
   2209 		}
   2210 		o1 = c.olhr(int32(c.instoffset), r, int(p.To.Reg), int(p.Scond))
   2211 		if p.As == AMOVB || p.As == AMOVBS {
   2212 			o1 ^= 1<<5 | 1<<6
   2213 		} else if p.As == AMOVH || p.As == AMOVHS {
   2214 			o1 ^= (1 << 6)
   2215 		}
   2216 
   2217 	case 72: /* movh/movhu R,L(R) -> strh */
   2218 		o1 = c.omvl(p, &p.To, REGTMP)
   2219 
   2220 		if o1 == 0 {
   2221 			break
   2222 		}
   2223 		r := int(p.To.Reg)
   2224 		if r == 0 {
   2225 			r = int(o.param)
   2226 		}
   2227 		o2 = c.oshrr(int(p.From.Reg), REGTMP&15, r, int(p.Scond))
   2228 
   2229 	case 73: /* movb/movh/movhu L(R),R -> ldrsb/ldrsh/ldrh */
   2230 		o1 = c.omvl(p, &p.From, REGTMP)
   2231 
   2232 		if o1 == 0 {
   2233 			break
   2234 		}
   2235 		r := int(p.From.Reg)
   2236 		if r == 0 {
   2237 			r = int(o.param)
   2238 		}
   2239 		o2 = c.olhrr(REGTMP&15, r, int(p.To.Reg), int(p.Scond))
   2240 		if p.As == AMOVB || p.As == AMOVBS {
   2241 			o2 ^= 1<<5 | 1<<6
   2242 		} else if p.As == AMOVH || p.As == AMOVHS {
   2243 			o2 ^= (1 << 6)
   2244 		}
   2245 
   2246 	case 74: /* bx $I */
   2247 		c.ctxt.Diag("ABX $I")
   2248 
   2249 	case 75: /* bx O(R) */
   2250 		c.aclass(&p.To)
   2251 
   2252 		if c.instoffset != 0 {
   2253 			c.ctxt.Diag("non-zero offset in ABX")
   2254 		}
   2255 
   2256 		/*
   2257 			o1 = 	c.oprrr(p, AADD, p->scond) | immrot(0) | ((REGPC&15)<<16) | ((REGLINK&15)<<12);	// mov PC, LR
   2258 			o2 = (((p->scond&C_SCOND) ^ C_SCOND_XOR)<<28) | (0x12fff<<8) | (1<<4) | ((p->to.reg&15) << 0);		// BX R
   2259 		*/
   2260 		// p->to.reg may be REGLINK
   2261 		o1 = c.oprrr(p, AADD, int(p.Scond))
   2262 
   2263 		o1 |= uint32(immrot(uint32(c.instoffset)))
   2264 		o1 |= (uint32(p.To.Reg) & 15) << 16
   2265 		o1 |= (REGTMP & 15) << 12
   2266 		o2 = c.oprrr(p, AADD, int(p.Scond)) | uint32(immrot(0)) | (REGPC&15)<<16 | (REGLINK&15)<<12 // mov PC, LR
   2267 		o3 = ((uint32(p.Scond)&C_SCOND)^C_SCOND_XOR)<<28 | 0x12fff<<8 | 1<<4 | REGTMP&15            // BX Rtmp
   2268 
   2269 	case 76: /* bx O(R) when returning from fn*/
   2270 		c.ctxt.Diag("ABXRET")
   2271 
   2272 	case 77: /* ldrex oreg,reg */
   2273 		c.aclass(&p.From)
   2274 
   2275 		if c.instoffset != 0 {
   2276 			c.ctxt.Diag("offset must be zero in LDREX")
   2277 		}
   2278 		o1 = 0x19<<20 | 0xf9f
   2279 		o1 |= (uint32(p.From.Reg) & 15) << 16
   2280 		o1 |= (uint32(p.To.Reg) & 15) << 12
   2281 		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
   2282 
   2283 	case 78: /* strex reg,oreg,reg */
   2284 		c.aclass(&p.From)
   2285 
   2286 		if c.instoffset != 0 {
   2287 			c.ctxt.Diag("offset must be zero in STREX")
   2288 		}
   2289 		if p.To.Reg == p.From.Reg || p.To.Reg == p.Reg {
   2290 			c.ctxt.Diag("cannot use same register as both source and destination: %v", p)
   2291 		}
   2292 		o1 = 0x18<<20 | 0xf90
   2293 		o1 |= (uint32(p.From.Reg) & 15) << 16
   2294 		o1 |= (uint32(p.Reg) & 15) << 0
   2295 		o1 |= (uint32(p.To.Reg) & 15) << 12
   2296 		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
   2297 
   2298 	case 80: /* fmov zfcon,freg */
   2299 		if p.As == AMOVD {
   2300 			o1 = 0xeeb00b00 // VMOV imm 64
   2301 			o2 = c.oprrr(p, ASUBD, int(p.Scond))
   2302 		} else {
   2303 			o1 = 0x0eb00a00 // VMOV imm 32
   2304 			o2 = c.oprrr(p, ASUBF, int(p.Scond))
   2305 		}
   2306 
   2307 		v := int32(0x70) // 1.0
   2308 		r := (int(p.To.Reg) & 15) << 0
   2309 
   2310 		// movf $1.0, r
   2311 		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
   2312 
   2313 		o1 |= (uint32(r) & 15) << 12
   2314 		o1 |= (uint32(v) & 0xf) << 0
   2315 		o1 |= (uint32(v) & 0xf0) << 12
   2316 
   2317 		// subf r,r,r
   2318 		o2 |= (uint32(r)&15)<<0 | (uint32(r)&15)<<16 | (uint32(r)&15)<<12
   2319 
   2320 	case 81: /* fmov sfcon,freg */
   2321 		o1 = 0x0eb00a00 // VMOV imm 32
   2322 		if p.As == AMOVD {
   2323 			o1 = 0xeeb00b00 // VMOV imm 64
   2324 		}
   2325 		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
   2326 		o1 |= (uint32(p.To.Reg) & 15) << 12
   2327 		v := int32(c.chipfloat5(p.From.Val.(float64)))
   2328 		o1 |= (uint32(v) & 0xf) << 0
   2329 		o1 |= (uint32(v) & 0xf0) << 12
   2330 
   2331 	case 82: /* fcmp freg,freg, */
   2332 		o1 = c.oprrr(p, p.As, int(p.Scond))
   2333 
   2334 		o1 |= (uint32(p.Reg)&15)<<12 | (uint32(p.From.Reg)&15)<<0
   2335 		o2 = 0x0ef1fa10 // VMRS R15
   2336 		o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
   2337 
   2338 	case 83: /* fcmp freg,, */
   2339 		o1 = c.oprrr(p, p.As, int(p.Scond))
   2340 
   2341 		o1 |= (uint32(p.From.Reg)&15)<<12 | 1<<16
   2342 		o2 = 0x0ef1fa10 // VMRS R15
   2343 		o2 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
   2344 
   2345 	case 84: /* movfw freg,freg - truncate float-to-fix */
   2346 		o1 = c.oprrr(p, p.As, int(p.Scond))
   2347 
   2348 		o1 |= (uint32(p.From.Reg) & 15) << 0
   2349 		o1 |= (uint32(p.To.Reg) & 15) << 12
   2350 
   2351 	case 85: /* movwf freg,freg - fix-to-float */
   2352 		o1 = c.oprrr(p, p.As, int(p.Scond))
   2353 
   2354 		o1 |= (uint32(p.From.Reg) & 15) << 0
   2355 		o1 |= (uint32(p.To.Reg) & 15) << 12
   2356 
   2357 		// macro for movfw freg,FTMP; movw FTMP,reg
   2358 	case 86: /* movfw freg,reg - truncate float-to-fix */
   2359 		o1 = c.oprrr(p, p.As, int(p.Scond))
   2360 
   2361 		o1 |= (uint32(p.From.Reg) & 15) << 0
   2362 		o1 |= (FREGTMP & 15) << 12
   2363 		o2 = c.oprrr(p, -AMOVFW, int(p.Scond))
   2364 		o2 |= (FREGTMP & 15) << 16
   2365 		o2 |= (uint32(p.To.Reg) & 15) << 12
   2366 
   2367 		// macro for movw reg,FTMP; movwf FTMP,freg
   2368 	case 87: /* movwf reg,freg - fix-to-float */
   2369 		o1 = c.oprrr(p, -AMOVWF, int(p.Scond))
   2370 
   2371 		o1 |= (uint32(p.From.Reg) & 15) << 12
   2372 		o1 |= (FREGTMP & 15) << 16
   2373 		o2 = c.oprrr(p, p.As, int(p.Scond))
   2374 		o2 |= (FREGTMP & 15) << 0
   2375 		o2 |= (uint32(p.To.Reg) & 15) << 12
   2376 
   2377 	case 88: /* movw reg,freg  */
   2378 		o1 = c.oprrr(p, -AMOVWF, int(p.Scond))
   2379 
   2380 		o1 |= (uint32(p.From.Reg) & 15) << 12
   2381 		o1 |= (uint32(p.To.Reg) & 15) << 16
   2382 
   2383 	case 89: /* movw freg,reg  */
   2384 		o1 = c.oprrr(p, -AMOVFW, int(p.Scond))
   2385 
   2386 		o1 |= (uint32(p.From.Reg) & 15) << 16
   2387 		o1 |= (uint32(p.To.Reg) & 15) << 12
   2388 
   2389 	case 91: /* ldrexd oreg,reg */
   2390 		c.aclass(&p.From)
   2391 
   2392 		if c.instoffset != 0 {
   2393 			c.ctxt.Diag("offset must be zero in LDREX")
   2394 		}
   2395 		o1 = 0x1b<<20 | 0xf9f
   2396 		o1 |= (uint32(p.From.Reg) & 15) << 16
   2397 		o1 |= (uint32(p.To.Reg) & 15) << 12
   2398 		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
   2399 
   2400 	case 92: /* strexd reg,oreg,reg */
   2401 		c.aclass(&p.From)
   2402 
   2403 		if c.instoffset != 0 {
   2404 			c.ctxt.Diag("offset must be zero in STREX")
   2405 		}
   2406 		if p.Reg&1 != 0 {
   2407 			c.ctxt.Diag("source register must be even in STREXD: %v", p)
   2408 		}
   2409 		if p.To.Reg == p.From.Reg || p.To.Reg == p.Reg || p.To.Reg == p.Reg+1 {
   2410 			c.ctxt.Diag("cannot use same register as both source and destination: %v", p)
   2411 		}
   2412 		o1 = 0x1a<<20 | 0xf90
   2413 		o1 |= (uint32(p.From.Reg) & 15) << 16
   2414 		o1 |= (uint32(p.Reg) & 15) << 0
   2415 		o1 |= (uint32(p.To.Reg) & 15) << 12
   2416 		o1 |= ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
   2417 
   2418 	case 93: /* movb/movh/movhu addr,R -> ldrsb/ldrsh/ldrh */
   2419 		o1 = c.omvl(p, &p.From, REGTMP)
   2420 
   2421 		if o1 == 0 {
   2422 			break
   2423 		}
   2424 		o2 = c.olhr(0, REGTMP, int(p.To.Reg), int(p.Scond))
   2425 		if p.As == AMOVB || p.As == AMOVBS {
   2426 			o2 ^= 1<<5 | 1<<6
   2427 		} else if p.As == AMOVH || p.As == AMOVHS {
   2428 			o2 ^= (1 << 6)
   2429 		}
   2430 		if o.flag&LPCREL != 0 {
   2431 			o3 = o2
   2432 			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
   2433 		}
   2434 
   2435 	case 94: /* movh/movhu R,addr -> strh */
   2436 		o1 = c.omvl(p, &p.To, REGTMP)
   2437 
   2438 		if o1 == 0 {
   2439 			break
   2440 		}
   2441 		o2 = c.oshr(int(p.From.Reg), 0, REGTMP, int(p.Scond))
   2442 		if o.flag&LPCREL != 0 {
   2443 			o3 = o2
   2444 			o2 = c.oprrr(p, AADD, int(p.Scond)) | REGTMP&15 | (REGPC&15)<<16 | (REGTMP&15)<<12
   2445 		}
   2446 
   2447 	case 95: /* PLD off(reg) */
   2448 		o1 = 0xf5d0f000
   2449 
   2450 		o1 |= (uint32(p.From.Reg) & 15) << 16
   2451 		if p.From.Offset < 0 {
   2452 			o1 &^= (1 << 23)
   2453 			o1 |= uint32((-p.From.Offset) & 0xfff)
   2454 		} else {
   2455 			o1 |= uint32(p.From.Offset & 0xfff)
   2456 		}
   2457 
   2458 	// This is supposed to be something that stops execution.
   2459 	// It's not supposed to be reached, ever, but if it is, we'd
   2460 	// like to be able to tell how we got there. Assemble as
   2461 	// 0xf7fabcfd which is guaranteed to raise undefined instruction
   2462 	// exception.
   2463 	case 96: /* UNDEF */
   2464 		o1 = 0xf7fabcfd
   2465 
   2466 	case 97: /* CLZ Rm, Rd */
   2467 		o1 = c.oprrr(p, p.As, int(p.Scond))
   2468 
   2469 		o1 |= (uint32(p.To.Reg) & 15) << 12
   2470 		o1 |= (uint32(p.From.Reg) & 15) << 0
   2471 
   2472 	case 98: /* MULW{T,B} Rs, Rm, Rd */
   2473 		o1 = c.oprrr(p, p.As, int(p.Scond))
   2474 
   2475 		o1 |= (uint32(p.To.Reg) & 15) << 16
   2476 		o1 |= (uint32(p.From.Reg) & 15) << 8
   2477 		o1 |= (uint32(p.Reg) & 15) << 0
   2478 
   2479 	case 99: /* MULAW{T,B} Rs, Rm, Rn, Rd */
   2480 		o1 = c.oprrr(p, p.As, int(p.Scond))
   2481 
   2482 		o1 |= (uint32(p.To.Reg) & 15) << 16
   2483 		o1 |= (uint32(p.From.Reg) & 15) << 8
   2484 		o1 |= (uint32(p.Reg) & 15) << 0
   2485 		o1 |= uint32((p.To.Offset & 15) << 12)
   2486 
   2487 	case 105: /* divhw r,[r,]r */
   2488 		o1 = c.oprrr(p, p.As, int(p.Scond))
   2489 		rf := int(p.From.Reg)
   2490 		rt := int(p.To.Reg)
   2491 		r := int(p.Reg)
   2492 		if r == 0 {
   2493 			r = rt
   2494 		}
   2495 		o1 |= (uint32(rf)&15)<<8 | (uint32(r)&15)<<0 | (uint32(rt)&15)<<16
   2496 
   2497 	case 110: /* dmb [mbop | $con] */
   2498 		o1 = 0xf57ff050
   2499 		mbop := uint32(0)
   2500 
   2501 		switch c.aclass(&p.From) {
   2502 		case C_SPR:
   2503 			for _, f := range mbOp {
   2504 				if f.reg == p.From.Reg {
   2505 					mbop = f.enc
   2506 					break
   2507 				}
   2508 			}
   2509 		case C_RCON:
   2510 			for _, f := range mbOp {
   2511 				enc := uint32(c.instoffset)
   2512 				if f.enc == enc {
   2513 					mbop = enc
   2514 					break
   2515 				}
   2516 			}
   2517 		case C_NONE:
   2518 			mbop = 0xf
   2519 		}
   2520 
   2521 		if mbop == 0 {
   2522 			c.ctxt.Diag("illegal mb option:\n%v", p)
   2523 		}
   2524 		o1 |= mbop
   2525 	}
   2526 
   2527 	out[0] = o1
   2528 	out[1] = o2
   2529 	out[2] = o3
   2530 	out[3] = o4
   2531 	out[4] = o5
   2532 	out[5] = o6
   2533 }
   2534 
   2535 func (c *ctxt5) movxt(p *obj.Prog) uint32 {
   2536 	o1 := ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
   2537 	switch p.As {
   2538 	case AMOVB, AMOVBS:
   2539 		o1 |= 0x6af<<16 | 0x7<<4
   2540 	case AMOVH, AMOVHS:
   2541 		o1 |= 0x6bf<<16 | 0x7<<4
   2542 	case AMOVBU:
   2543 		o1 |= 0x6ef<<16 | 0x7<<4
   2544 	case AMOVHU:
   2545 		o1 |= 0x6ff<<16 | 0x7<<4
   2546 	default:
   2547 		c.ctxt.Diag("illegal combination: %v", p)
   2548 	}
   2549 	switch p.From.Offset &^ 0xf {
   2550 	// only 0/8/16/24 bits rotation is accepted
   2551 	case SHIFT_RR, SHIFT_RR | 8<<7, SHIFT_RR | 16<<7, SHIFT_RR | 24<<7:
   2552 		o1 |= uint32(p.From.Offset) & 0xc0f
   2553 	default:
   2554 		c.ctxt.Diag("illegal shift: %v", p)
   2555 	}
   2556 	o1 |= (uint32(p.To.Reg) & 15) << 12
   2557 	return o1
   2558 }
   2559 
   2560 func (c *ctxt5) mov(p *obj.Prog) uint32 {
   2561 	c.aclass(&p.From)
   2562 	o1 := c.oprrr(p, p.As, int(p.Scond))
   2563 	o1 |= uint32(p.From.Offset)
   2564 	rt := int(p.To.Reg)
   2565 	if p.To.Type == obj.TYPE_NONE {
   2566 		rt = 0
   2567 	}
   2568 	r := int(p.Reg)
   2569 	if p.As == AMOVW || p.As == AMVN {
   2570 		r = 0
   2571 	} else if r == 0 {
   2572 		r = rt
   2573 	}
   2574 	o1 |= (uint32(r)&15)<<16 | (uint32(rt)&15)<<12
   2575 	return o1
   2576 }
   2577 
   2578 func (c *ctxt5) oprrr(p *obj.Prog, a obj.As, sc int) uint32 {
   2579 	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
   2580 	if sc&C_SBIT != 0 {
   2581 		o |= 1 << 20
   2582 	}
   2583 	switch a {
   2584 	case ADIVHW:
   2585 		return o | 0x71<<20 | 0xf<<12 | 0x1<<4
   2586 	case ADIVUHW:
   2587 		return o | 0x73<<20 | 0xf<<12 | 0x1<<4
   2588 	case AMMUL:
   2589 		return o | 0x75<<20 | 0xf<<12 | 0x1<<4
   2590 	case AMULS:
   2591 		return o | 0x6<<20 | 0x9<<4
   2592 	case AMMULA:
   2593 		return o | 0x75<<20 | 0x1<<4
   2594 	case AMMULS:
   2595 		return o | 0x75<<20 | 0xd<<4
   2596 	case AMULU, AMUL:
   2597 		return o | 0x0<<21 | 0x9<<4
   2598 	case AMULA:
   2599 		return o | 0x1<<21 | 0x9<<4
   2600 	case AMULLU:
   2601 		return o | 0x4<<21 | 0x9<<4
   2602 	case AMULL:
   2603 		return o | 0x6<<21 | 0x9<<4
   2604 	case AMULALU:
   2605 		return o | 0x5<<21 | 0x9<<4
   2606 	case AMULAL:
   2607 		return o | 0x7<<21 | 0x9<<4
   2608 	case AAND:
   2609 		return o | 0x0<<21
   2610 	case AEOR:
   2611 		return o | 0x1<<21
   2612 	case ASUB:
   2613 		return o | 0x2<<21
   2614 	case ARSB:
   2615 		return o | 0x3<<21
   2616 	case AADD:
   2617 		return o | 0x4<<21
   2618 	case AADC:
   2619 		return o | 0x5<<21
   2620 	case ASBC:
   2621 		return o | 0x6<<21
   2622 	case ARSC:
   2623 		return o | 0x7<<21
   2624 	case ATST:
   2625 		return o | 0x8<<21 | 1<<20
   2626 	case ATEQ:
   2627 		return o | 0x9<<21 | 1<<20
   2628 	case ACMP:
   2629 		return o | 0xa<<21 | 1<<20
   2630 	case ACMN:
   2631 		return o | 0xb<<21 | 1<<20
   2632 	case AORR:
   2633 		return o | 0xc<<21
   2634 
   2635 	case AMOVB, AMOVH, AMOVW:
   2636 		if sc&(C_PBIT|C_WBIT) != 0 {
   2637 			c.ctxt.Diag("invalid .P/.W suffix: %v", p)
   2638 		}
   2639 		return o | 0xd<<21
   2640 	case ABIC:
   2641 		return o | 0xe<<21
   2642 	case AMVN:
   2643 		return o | 0xf<<21
   2644 	case ASLL:
   2645 		return o | 0xd<<21 | 0<<5
   2646 	case ASRL:
   2647 		return o | 0xd<<21 | 1<<5
   2648 	case ASRA:
   2649 		return o | 0xd<<21 | 2<<5
   2650 	case ASWI:
   2651 		return o | 0xf<<24
   2652 
   2653 	case AADDD:
   2654 		return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 0<<4
   2655 	case AADDF:
   2656 		return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 0<<4
   2657 	case ASUBD:
   2658 		return o | 0xe<<24 | 0x3<<20 | 0xb<<8 | 4<<4
   2659 	case ASUBF:
   2660 		return o | 0xe<<24 | 0x3<<20 | 0xa<<8 | 4<<4
   2661 	case AMULD:
   2662 		return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0<<4
   2663 	case AMULF:
   2664 		return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0<<4
   2665 	case ANMULD:
   2666 		return o | 0xe<<24 | 0x2<<20 | 0xb<<8 | 0x4<<4
   2667 	case ANMULF:
   2668 		return o | 0xe<<24 | 0x2<<20 | 0xa<<8 | 0x4<<4
   2669 	case AMULAD:
   2670 		return o | 0xe<<24 | 0xb<<8
   2671 	case AMULAF:
   2672 		return o | 0xe<<24 | 0xa<<8
   2673 	case AMULSD:
   2674 		return o | 0xe<<24 | 0xb<<8 | 0x4<<4
   2675 	case AMULSF:
   2676 		return o | 0xe<<24 | 0xa<<8 | 0x4<<4
   2677 	case ANMULAD:
   2678 		return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 0x4<<4
   2679 	case ANMULAF:
   2680 		return o | 0xe<<24 | 0x1<<20 | 0xa<<8 | 0x4<<4
   2681 	case ANMULSD:
   2682 		return o | 0xe<<24 | 0x1<<20 | 0xb<<8
   2683 	case ANMULSF:
   2684 		return o | 0xe<<24 | 0x1<<20 | 0xa<<8
   2685 	case AFMULAD:
   2686 		return o | 0xe<<24 | 0xa<<20 | 0xb<<8
   2687 	case AFMULAF:
   2688 		return o | 0xe<<24 | 0xa<<20 | 0xa<<8
   2689 	case AFMULSD:
   2690 		return o | 0xe<<24 | 0xa<<20 | 0xb<<8 | 0x4<<4
   2691 	case AFMULSF:
   2692 		return o | 0xe<<24 | 0xa<<20 | 0xa<<8 | 0x4<<4
   2693 	case AFNMULAD:
   2694 		return o | 0xe<<24 | 0x9<<20 | 0xb<<8 | 0x4<<4
   2695 	case AFNMULAF:
   2696 		return o | 0xe<<24 | 0x9<<20 | 0xa<<8 | 0x4<<4
   2697 	case AFNMULSD:
   2698 		return o | 0xe<<24 | 0x9<<20 | 0xb<<8
   2699 	case AFNMULSF:
   2700 		return o | 0xe<<24 | 0x9<<20 | 0xa<<8
   2701 	case ADIVD:
   2702 		return o | 0xe<<24 | 0x8<<20 | 0xb<<8 | 0<<4
   2703 	case ADIVF:
   2704 		return o | 0xe<<24 | 0x8<<20 | 0xa<<8 | 0<<4
   2705 	case ASQRTD:
   2706 		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0xc<<4
   2707 	case ASQRTF:
   2708 		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0xc<<4
   2709 	case AABSD:
   2710 		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 0xc<<4
   2711 	case AABSF:
   2712 		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 0xc<<4
   2713 	case ANEGD:
   2714 		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xb<<8 | 0x4<<4
   2715 	case ANEGF:
   2716 		return o | 0xe<<24 | 0xb<<20 | 1<<16 | 0xa<<8 | 0x4<<4
   2717 	case ACMPD:
   2718 		return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xb<<8 | 0xc<<4
   2719 	case ACMPF:
   2720 		return o | 0xe<<24 | 0xb<<20 | 4<<16 | 0xa<<8 | 0xc<<4
   2721 
   2722 	case AMOVF:
   2723 		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xa<<8 | 4<<4
   2724 	case AMOVD:
   2725 		return o | 0xe<<24 | 0xb<<20 | 0<<16 | 0xb<<8 | 4<<4
   2726 
   2727 	case AMOVDF:
   2728 		return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 1<<8 // dtof
   2729 	case AMOVFD:
   2730 		return o | 0xe<<24 | 0xb<<20 | 7<<16 | 0xa<<8 | 0xc<<4 | 0<<8 // dtof
   2731 
   2732 	case AMOVWF:
   2733 		if sc&C_UBIT == 0 {
   2734 			o |= 1 << 7 /* signed */
   2735 		}
   2736 		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 0<<8 // toint, double
   2737 
   2738 	case AMOVWD:
   2739 		if sc&C_UBIT == 0 {
   2740 			o |= 1 << 7 /* signed */
   2741 		}
   2742 		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 0<<18 | 1<<8 // toint, double
   2743 
   2744 	case AMOVFW:
   2745 		if sc&C_UBIT == 0 {
   2746 			o |= 1 << 16 /* signed */
   2747 		}
   2748 		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 0<<8 | 1<<7 // toint, double, trunc
   2749 
   2750 	case AMOVDW:
   2751 		if sc&C_UBIT == 0 {
   2752 			o |= 1 << 16 /* signed */
   2753 		}
   2754 		return o | 0xe<<24 | 0xb<<20 | 8<<16 | 0xa<<8 | 4<<4 | 1<<18 | 1<<8 | 1<<7 // toint, double, trunc
   2755 
   2756 	case -AMOVWF: // copy WtoF
   2757 		return o | 0xe<<24 | 0x0<<20 | 0xb<<8 | 1<<4
   2758 
   2759 	case -AMOVFW: // copy FtoW
   2760 		return o | 0xe<<24 | 0x1<<20 | 0xb<<8 | 1<<4
   2761 
   2762 	case -ACMP: // cmp imm
   2763 		return o | 0x3<<24 | 0x5<<20
   2764 
   2765 	case ABFX:
   2766 		return o | 0x3d<<21 | 0x5<<4
   2767 
   2768 	case ABFXU:
   2769 		return o | 0x3f<<21 | 0x5<<4
   2770 
   2771 	case ABFC:
   2772 		return o | 0x3e<<21 | 0x1f
   2773 
   2774 	case ABFI:
   2775 		return o | 0x3e<<21 | 0x1<<4
   2776 
   2777 	case AXTAB:
   2778 		return o | 0x6a<<20 | 0x7<<4
   2779 
   2780 	case AXTAH:
   2781 		return o | 0x6b<<20 | 0x7<<4
   2782 
   2783 	case AXTABU:
   2784 		return o | 0x6e<<20 | 0x7<<4
   2785 
   2786 	case AXTAHU:
   2787 		return o | 0x6f<<20 | 0x7<<4
   2788 
   2789 		// CLZ doesn't support .nil
   2790 	case ACLZ:
   2791 		return o&(0xf<<28) | 0x16f<<16 | 0xf1<<4
   2792 
   2793 	case AREV:
   2794 		return o&(0xf<<28) | 0x6bf<<16 | 0xf3<<4
   2795 
   2796 	case AREV16:
   2797 		return o&(0xf<<28) | 0x6bf<<16 | 0xfb<<4
   2798 
   2799 	case AREVSH:
   2800 		return o&(0xf<<28) | 0x6ff<<16 | 0xfb<<4
   2801 
   2802 	case ARBIT:
   2803 		return o&(0xf<<28) | 0x6ff<<16 | 0xf3<<4
   2804 
   2805 	case AMULWT:
   2806 		return o&(0xf<<28) | 0x12<<20 | 0xe<<4
   2807 
   2808 	case AMULWB:
   2809 		return o&(0xf<<28) | 0x12<<20 | 0xa<<4
   2810 
   2811 	case AMULBB:
   2812 		return o&(0xf<<28) | 0x16<<20 | 0x8<<4
   2813 
   2814 	case AMULAWT:
   2815 		return o&(0xf<<28) | 0x12<<20 | 0xc<<4
   2816 
   2817 	case AMULAWB:
   2818 		return o&(0xf<<28) | 0x12<<20 | 0x8<<4
   2819 
   2820 	case AMULABB:
   2821 		return o&(0xf<<28) | 0x10<<20 | 0x8<<4
   2822 
   2823 	case ABL: // BLX REG
   2824 		return o&(0xf<<28) | 0x12fff3<<4
   2825 	}
   2826 
   2827 	c.ctxt.Diag("%v: bad rrr %d", p, a)
   2828 	return 0
   2829 }
   2830 
   2831 func (c *ctxt5) opbra(p *obj.Prog, a obj.As, sc int) uint32 {
   2832 	sc &= C_SCOND
   2833 	sc ^= C_SCOND_XOR
   2834 	if a == ABL || a == obj.ADUFFZERO || a == obj.ADUFFCOPY {
   2835 		return uint32(sc)<<28 | 0x5<<25 | 0x1<<24
   2836 	}
   2837 	if sc != 0xe {
   2838 		c.ctxt.Diag("%v: .COND on bcond instruction", p)
   2839 	}
   2840 	switch a {
   2841 	case ABEQ:
   2842 		return 0x0<<28 | 0x5<<25
   2843 	case ABNE:
   2844 		return 0x1<<28 | 0x5<<25
   2845 	case ABCS:
   2846 		return 0x2<<28 | 0x5<<25
   2847 	case ABHS:
   2848 		return 0x2<<28 | 0x5<<25
   2849 	case ABCC:
   2850 		return 0x3<<28 | 0x5<<25
   2851 	case ABLO:
   2852 		return 0x3<<28 | 0x5<<25
   2853 	case ABMI:
   2854 		return 0x4<<28 | 0x5<<25
   2855 	case ABPL:
   2856 		return 0x5<<28 | 0x5<<25
   2857 	case ABVS:
   2858 		return 0x6<<28 | 0x5<<25
   2859 	case ABVC:
   2860 		return 0x7<<28 | 0x5<<25
   2861 	case ABHI:
   2862 		return 0x8<<28 | 0x5<<25
   2863 	case ABLS:
   2864 		return 0x9<<28 | 0x5<<25
   2865 	case ABGE:
   2866 		return 0xa<<28 | 0x5<<25
   2867 	case ABLT:
   2868 		return 0xb<<28 | 0x5<<25
   2869 	case ABGT:
   2870 		return 0xc<<28 | 0x5<<25
   2871 	case ABLE:
   2872 		return 0xd<<28 | 0x5<<25
   2873 	case AB:
   2874 		return 0xe<<28 | 0x5<<25
   2875 	}
   2876 
   2877 	c.ctxt.Diag("%v: bad bra %v", p, a)
   2878 	return 0
   2879 }
   2880 
   2881 func (c *ctxt5) olr(v int32, b int, r int, sc int) uint32 {
   2882 	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
   2883 	if sc&C_PBIT == 0 {
   2884 		o |= 1 << 24
   2885 	}
   2886 	if sc&C_UBIT == 0 {
   2887 		o |= 1 << 23
   2888 	}
   2889 	if sc&C_WBIT != 0 {
   2890 		o |= 1 << 21
   2891 	}
   2892 	o |= 1<<26 | 1<<20
   2893 	if v < 0 {
   2894 		if sc&C_UBIT != 0 {
   2895 			c.ctxt.Diag(".U on neg offset")
   2896 		}
   2897 		v = -v
   2898 		o ^= 1 << 23
   2899 	}
   2900 
   2901 	if v >= 1<<12 || v < 0 {
   2902 		c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp)
   2903 	}
   2904 	o |= uint32(v)
   2905 	o |= (uint32(b) & 15) << 16
   2906 	o |= (uint32(r) & 15) << 12
   2907 	return o
   2908 }
   2909 
   2910 func (c *ctxt5) olhr(v int32, b int, r int, sc int) uint32 {
   2911 	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
   2912 	if sc&C_PBIT == 0 {
   2913 		o |= 1 << 24
   2914 	}
   2915 	if sc&C_WBIT != 0 {
   2916 		o |= 1 << 21
   2917 	}
   2918 	o |= 1<<23 | 1<<20 | 0xb<<4
   2919 	if v < 0 {
   2920 		v = -v
   2921 		o ^= 1 << 23
   2922 	}
   2923 
   2924 	if v >= 1<<8 || v < 0 {
   2925 		c.ctxt.Diag("literal span too large: %d (R%d)\n%v", v, b, c.printp)
   2926 	}
   2927 	o |= uint32(v)&0xf | (uint32(v)>>4)<<8 | 1<<22
   2928 	o |= (uint32(b) & 15) << 16
   2929 	o |= (uint32(r) & 15) << 12
   2930 	return o
   2931 }
   2932 
   2933 func (c *ctxt5) osr(a obj.As, r int, v int32, b int, sc int) uint32 {
   2934 	o := c.olr(v, b, r, sc) ^ (1 << 20)
   2935 	if a != AMOVW {
   2936 		o |= 1 << 22
   2937 	}
   2938 	return o
   2939 }
   2940 
   2941 func (c *ctxt5) oshr(r int, v int32, b int, sc int) uint32 {
   2942 	o := c.olhr(v, b, r, sc) ^ (1 << 20)
   2943 	return o
   2944 }
   2945 
   2946 func (c *ctxt5) osrr(r int, i int, b int, sc int) uint32 {
   2947 	return c.olr(int32(i), b, r, sc) ^ (1<<25 | 1<<20)
   2948 }
   2949 
   2950 func (c *ctxt5) oshrr(r int, i int, b int, sc int) uint32 {
   2951 	return c.olhr(int32(i), b, r, sc) ^ (1<<22 | 1<<20)
   2952 }
   2953 
   2954 func (c *ctxt5) olrr(i int, b int, r int, sc int) uint32 {
   2955 	return c.olr(int32(i), b, r, sc) ^ (1 << 25)
   2956 }
   2957 
   2958 func (c *ctxt5) olhrr(i int, b int, r int, sc int) uint32 {
   2959 	return c.olhr(int32(i), b, r, sc) ^ (1 << 22)
   2960 }
   2961 
   2962 func (c *ctxt5) ofsr(a obj.As, r int, v int32, b int, sc int, p *obj.Prog) uint32 {
   2963 	o := ((uint32(sc) & C_SCOND) ^ C_SCOND_XOR) << 28
   2964 	if sc&C_PBIT == 0 {
   2965 		o |= 1 << 24
   2966 	}
   2967 	if sc&C_WBIT != 0 {
   2968 		o |= 1 << 21
   2969 	}
   2970 	o |= 6<<25 | 1<<24 | 1<<23 | 10<<8
   2971 	if v < 0 {
   2972 		v = -v
   2973 		o ^= 1 << 23
   2974 	}
   2975 
   2976 	if v&3 != 0 {
   2977 		c.ctxt.Diag("odd offset for floating point op: %d\n%v", v, p)
   2978 	} else if v >= 1<<10 || v < 0 {
   2979 		c.ctxt.Diag("literal span too large: %d\n%v", v, p)
   2980 	}
   2981 	o |= (uint32(v) >> 2) & 0xFF
   2982 	o |= (uint32(b) & 15) << 16
   2983 	o |= (uint32(r) & 15) << 12
   2984 
   2985 	switch a {
   2986 	default:
   2987 		c.ctxt.Diag("bad fst %v", a)
   2988 		fallthrough
   2989 
   2990 	case AMOVD:
   2991 		o |= 1 << 8
   2992 		fallthrough
   2993 
   2994 	case AMOVF:
   2995 		break
   2996 	}
   2997 
   2998 	return o
   2999 }
   3000 
   3001 // MOVW $"lower 16-bit", Reg
   3002 func (c *ctxt5) omvs(p *obj.Prog, a *obj.Addr, dr int) uint32 {
   3003 	o1 := ((uint32(p.Scond) & C_SCOND) ^ C_SCOND_XOR) << 28
   3004 	o1 |= 0x30 << 20
   3005 	o1 |= (uint32(dr) & 15) << 12
   3006 	o1 |= uint32(a.Offset) & 0x0fff
   3007 	o1 |= (uint32(a.Offset) & 0xf000) << 4
   3008 	return o1
   3009 }
   3010 
   3011 // MVN $C_NCON, Reg -> MOVW $C_RCON, Reg
   3012 func (c *ctxt5) omvr(p *obj.Prog, a *obj.Addr, dr int) uint32 {
   3013 	o1 := c.oprrr(p, AMOVW, int(p.Scond))
   3014 	o1 |= (uint32(dr) & 15) << 12
   3015 	v := immrot(^uint32(a.Offset))
   3016 	if v == 0 {
   3017 		c.ctxt.Diag("%v: missing literal", p)
   3018 		return 0
   3019 	}
   3020 	o1 |= uint32(v)
   3021 	return o1
   3022 }
   3023 
   3024 func (c *ctxt5) omvl(p *obj.Prog, a *obj.Addr, dr int) uint32 {
   3025 	var o1 uint32
   3026 	if p.Pool == nil {
   3027 		c.aclass(a)
   3028 		v := immrot(^uint32(c.instoffset))
   3029 		if v == 0 {
   3030 			c.ctxt.Diag("%v: missing literal", p)
   3031 			return 0
   3032 		}
   3033 
   3034 		o1 = c.oprrr(p, AMVN, int(p.Scond)&C_SCOND)
   3035 		o1 |= uint32(v)
   3036 		o1 |= (uint32(dr) & 15) << 12
   3037 	} else {
   3038 		v := int32(p.Pool.Pc - p.Pc - 8)
   3039 		o1 = c.olr(v, REGPC, dr, int(p.Scond)&C_SCOND)
   3040 	}
   3041 
   3042 	return o1
   3043 }
   3044 
   3045 func (c *ctxt5) chipzero5(e float64) int {
   3046 	// We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
   3047 	if objabi.GOARM < 7 || math.Float64bits(e) != 0 {
   3048 		return -1
   3049 	}
   3050 	return 0
   3051 }
   3052 
   3053 func (c *ctxt5) chipfloat5(e float64) int {
   3054 	// We use GOARM=7 to gate the use of VFPv3 vmov (imm) instructions.
   3055 	if objabi.GOARM < 7 {
   3056 		return -1
   3057 	}
   3058 
   3059 	ei := math.Float64bits(e)
   3060 	l := uint32(ei)
   3061 	h := uint32(ei >> 32)
   3062 
   3063 	if l != 0 || h&0xffff != 0 {
   3064 		return -1
   3065 	}
   3066 	h1 := h & 0x7fc00000
   3067 	if h1 != 0x40000000 && h1 != 0x3fc00000 {
   3068 		return -1
   3069 	}
   3070 	n := 0
   3071 
   3072 	// sign bit (a)
   3073 	if h&0x80000000 != 0 {
   3074 		n |= 1 << 7
   3075 	}
   3076 
   3077 	// exp sign bit (b)
   3078 	if h1 == 0x3fc00000 {
   3079 		n |= 1 << 6
   3080 	}
   3081 
   3082 	// rest of exp and mantissa (cd-efgh)
   3083 	n |= int((h >> 16) & 0x3f)
   3084 
   3085 	//print("match %.8lux %.8lux %d\n", l, h, n);
   3086 	return n
   3087 }
   3088 
   3089 func nocache(p *obj.Prog) {
   3090 	p.Optab = 0
   3091 	p.From.Class = 0
   3092 	if p.GetFrom3() != nil {
   3093 		p.GetFrom3().Class = 0
   3094 	}
   3095 	p.To.Class = 0
   3096 }