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