asm5.go raw

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