asm0.go raw

   1  // cmd/9l/optab.c, cmd/9l/asmout.c from Vita Nuova.
   2  //
   3  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
   4  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
   5  //	Portions Copyright © 1997-1999 Vita Nuova Limited
   6  //	Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
   7  //	Portions Copyright © 2004,2006 Bruce Ellis
   8  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
   9  //	Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
  10  //	Portions Copyright © 2009 The Go Authors. All rights reserved.
  11  //
  12  // Permission is hereby granted, free of charge, to any person obtaining a copy
  13  // of this software and associated documentation files (the "Software"), to deal
  14  // in the Software without restriction, including without limitation the rights
  15  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  16  // copies of the Software, and to permit persons to whom the Software is
  17  // furnished to do so, subject to the following conditions:
  18  //
  19  // The above copyright notice and this permission notice shall be included in
  20  // all copies or substantial portions of the Software.
  21  //
  22  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  23  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  24  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
  25  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  26  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  27  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  28  // THE SOFTWARE.
  29  
  30  package mips
  31  
  32  import (
  33  	"github.com/twitchyliquid64/golang-asm/obj"
  34  	"github.com/twitchyliquid64/golang-asm/objabi"
  35  	"github.com/twitchyliquid64/golang-asm/sys"
  36  	"fmt"
  37  	"log"
  38  	"sort"
  39  )
  40  
  41  // ctxt0 holds state while assembling a single function.
  42  // Each function gets a fresh ctxt0.
  43  // This allows for multiple functions to be safely concurrently assembled.
  44  type ctxt0 struct {
  45  	ctxt       *obj.Link
  46  	newprog    obj.ProgAlloc
  47  	cursym     *obj.LSym
  48  	autosize   int32
  49  	instoffset int64
  50  	pc         int64
  51  }
  52  
  53  // Instruction layout.
  54  
  55  const (
  56  	mips64FuncAlign = 8
  57  )
  58  
  59  const (
  60  	r0iszero = 1
  61  )
  62  
  63  type Optab struct {
  64  	as     obj.As
  65  	a1     uint8
  66  	a2     uint8
  67  	a3     uint8
  68  	type_  int8
  69  	size   int8
  70  	param  int16
  71  	family sys.ArchFamily // 0 means both sys.MIPS and sys.MIPS64
  72  	flag   uint8
  73  }
  74  
  75  const (
  76  	// Optab.flag
  77  	NOTUSETMP = 1 << iota // p expands to multiple instructions, but does NOT use REGTMP
  78  )
  79  
  80  var optab = []Optab{
  81  	{obj.ATEXT, C_LEXT, C_NONE, C_TEXTSIZE, 0, 0, 0, sys.MIPS64, 0},
  82  	{obj.ATEXT, C_ADDR, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0},
  83  
  84  	{AMOVW, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
  85  	{AMOVV, C_REG, C_NONE, C_REG, 1, 4, 0, sys.MIPS64, 0},
  86  	{AMOVB, C_REG, C_NONE, C_REG, 12, 8, 0, 0, NOTUSETMP},
  87  	{AMOVBU, C_REG, C_NONE, C_REG, 13, 4, 0, 0, 0},
  88  	{AMOVWU, C_REG, C_NONE, C_REG, 14, 8, 0, sys.MIPS64, NOTUSETMP},
  89  
  90  	{ASUB, C_REG, C_REG, C_REG, 2, 4, 0, 0, 0},
  91  	{ASUBV, C_REG, C_REG, C_REG, 2, 4, 0, sys.MIPS64, 0},
  92  	{AADD, C_REG, C_REG, C_REG, 2, 4, 0, 0, 0},
  93  	{AADDV, C_REG, C_REG, C_REG, 2, 4, 0, sys.MIPS64, 0},
  94  	{AAND, C_REG, C_REG, C_REG, 2, 4, 0, 0, 0},
  95  	{ASUB, C_REG, C_NONE, C_REG, 2, 4, 0, 0, 0},
  96  	{ASUBV, C_REG, C_NONE, C_REG, 2, 4, 0, sys.MIPS64, 0},
  97  	{AADD, C_REG, C_NONE, C_REG, 2, 4, 0, 0, 0},
  98  	{AADDV, C_REG, C_NONE, C_REG, 2, 4, 0, sys.MIPS64, 0},
  99  	{AAND, C_REG, C_NONE, C_REG, 2, 4, 0, 0, 0},
 100  	{ACMOVN, C_REG, C_REG, C_REG, 2, 4, 0, 0, 0},
 101  	{ANEGW, C_REG, C_NONE, C_REG, 2, 4, 0, 0, 0},
 102  	{ANEGV, C_REG, C_NONE, C_REG, 2, 4, 0, sys.MIPS64, 0},
 103  
 104  	{ASLL, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
 105  	{ASLL, C_REG, C_REG, C_REG, 9, 4, 0, 0, 0},
 106  	{ASLLV, C_REG, C_NONE, C_REG, 9, 4, 0, sys.MIPS64, 0},
 107  	{ASLLV, C_REG, C_REG, C_REG, 9, 4, 0, sys.MIPS64, 0},
 108  	{ACLO, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
 109  
 110  	{AADDF, C_FREG, C_NONE, C_FREG, 32, 4, 0, 0, 0},
 111  	{AADDF, C_FREG, C_REG, C_FREG, 32, 4, 0, 0, 0},
 112  	{ACMPEQF, C_FREG, C_REG, C_NONE, 32, 4, 0, 0, 0},
 113  	{AABSF, C_FREG, C_NONE, C_FREG, 33, 4, 0, 0, 0},
 114  	{AMOVVF, C_FREG, C_NONE, C_FREG, 33, 4, 0, sys.MIPS64, 0},
 115  	{AMOVF, C_FREG, C_NONE, C_FREG, 33, 4, 0, 0, 0},
 116  	{AMOVD, C_FREG, C_NONE, C_FREG, 33, 4, 0, 0, 0},
 117  
 118  	{AMOVW, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
 119  	{AMOVWU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
 120  	{AMOVV, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
 121  	{AMOVB, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
 122  	{AMOVBU, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
 123  	{AMOVWL, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
 124  	{AMOVVL, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0},
 125  	{AMOVW, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0, 0},
 126  	{AMOVWU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, sys.MIPS64, 0},
 127  	{AMOVV, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, sys.MIPS64, 0},
 128  	{AMOVB, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0, 0},
 129  	{AMOVBU, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0, 0},
 130  	{AMOVWL, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, 0, 0},
 131  	{AMOVVL, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, sys.MIPS64, 0},
 132  	{AMOVW, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
 133  	{AMOVWU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
 134  	{AMOVV, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
 135  	{AMOVB, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
 136  	{AMOVBU, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
 137  	{AMOVWL, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
 138  	{AMOVVL, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
 139  	{ASC, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, 0, 0},
 140  	{ASCV, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
 141  
 142  	{AMOVW, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
 143  	{AMOVWU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
 144  	{AMOVV, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
 145  	{AMOVB, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
 146  	{AMOVBU, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
 147  	{AMOVWL, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
 148  	{AMOVVL, C_SEXT, C_NONE, C_REG, 8, 4, REGSB, sys.MIPS64, 0},
 149  	{AMOVW, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0, 0},
 150  	{AMOVWU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, sys.MIPS64, 0},
 151  	{AMOVV, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, sys.MIPS64, 0},
 152  	{AMOVB, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0, 0},
 153  	{AMOVBU, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0, 0},
 154  	{AMOVWL, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, 0, 0},
 155  	{AMOVVL, C_SAUTO, C_NONE, C_REG, 8, 4, REGSP, sys.MIPS64, 0},
 156  	{AMOVW, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
 157  	{AMOVWU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, sys.MIPS64, 0},
 158  	{AMOVV, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, sys.MIPS64, 0},
 159  	{AMOVB, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
 160  	{AMOVBU, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
 161  	{AMOVWL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
 162  	{AMOVVL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, sys.MIPS64, 0},
 163  	{ALL, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, 0, 0},
 164  	{ALLV, C_SOREG, C_NONE, C_REG, 8, 4, REGZERO, sys.MIPS64, 0},
 165  
 166  	{AMOVW, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
 167  	{AMOVWU, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
 168  	{AMOVV, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
 169  	{AMOVB, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
 170  	{AMOVBU, C_REG, C_NONE, C_LEXT, 35, 12, REGSB, sys.MIPS64, 0},
 171  	{AMOVW, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, 0, 0},
 172  	{AMOVWU, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, sys.MIPS64, 0},
 173  	{AMOVV, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, sys.MIPS64, 0},
 174  	{AMOVB, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, 0, 0},
 175  	{AMOVBU, C_REG, C_NONE, C_LAUTO, 35, 12, REGSP, 0, 0},
 176  	{AMOVW, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0, 0},
 177  	{AMOVWU, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, sys.MIPS64, 0},
 178  	{AMOVV, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, sys.MIPS64, 0},
 179  	{AMOVB, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0, 0},
 180  	{AMOVBU, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0, 0},
 181  	{ASC, C_REG, C_NONE, C_LOREG, 35, 12, REGZERO, 0, 0},
 182  	{AMOVW, C_REG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
 183  	{AMOVW, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
 184  	{AMOVWU, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
 185  	{AMOVV, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
 186  	{AMOVB, C_REG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
 187  	{AMOVB, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
 188  	{AMOVBU, C_REG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
 189  	{AMOVBU, C_REG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
 190  	{AMOVW, C_REG, C_NONE, C_TLS, 53, 8, 0, 0, NOTUSETMP},
 191  	{AMOVWU, C_REG, C_NONE, C_TLS, 53, 8, 0, sys.MIPS64, NOTUSETMP},
 192  	{AMOVV, C_REG, C_NONE, C_TLS, 53, 8, 0, sys.MIPS64, NOTUSETMP},
 193  	{AMOVB, C_REG, C_NONE, C_TLS, 53, 8, 0, 0, NOTUSETMP},
 194  	{AMOVBU, C_REG, C_NONE, C_TLS, 53, 8, 0, 0, NOTUSETMP},
 195  
 196  	{AMOVW, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
 197  	{AMOVWU, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
 198  	{AMOVV, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
 199  	{AMOVB, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
 200  	{AMOVBU, C_LEXT, C_NONE, C_REG, 36, 12, REGSB, sys.MIPS64, 0},
 201  	{AMOVW, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, 0, 0},
 202  	{AMOVWU, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, sys.MIPS64, 0},
 203  	{AMOVV, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, sys.MIPS64, 0},
 204  	{AMOVB, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, 0, 0},
 205  	{AMOVBU, C_LAUTO, C_NONE, C_REG, 36, 12, REGSP, 0, 0},
 206  	{AMOVW, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, 0, 0},
 207  	{AMOVWU, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, sys.MIPS64, 0},
 208  	{AMOVV, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, sys.MIPS64, 0},
 209  	{AMOVB, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, 0, 0},
 210  	{AMOVBU, C_LOREG, C_NONE, C_REG, 36, 12, REGZERO, 0, 0},
 211  	{AMOVW, C_ADDR, C_NONE, C_REG, 51, 8, 0, sys.MIPS, 0},
 212  	{AMOVW, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
 213  	{AMOVWU, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
 214  	{AMOVV, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
 215  	{AMOVB, C_ADDR, C_NONE, C_REG, 51, 8, 0, sys.MIPS, 0},
 216  	{AMOVB, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
 217  	{AMOVBU, C_ADDR, C_NONE, C_REG, 51, 8, 0, sys.MIPS, 0},
 218  	{AMOVBU, C_ADDR, C_NONE, C_REG, 51, 12, 0, sys.MIPS64, 0},
 219  	{AMOVW, C_TLS, C_NONE, C_REG, 54, 8, 0, 0, NOTUSETMP},
 220  	{AMOVWU, C_TLS, C_NONE, C_REG, 54, 8, 0, sys.MIPS64, NOTUSETMP},
 221  	{AMOVV, C_TLS, C_NONE, C_REG, 54, 8, 0, sys.MIPS64, NOTUSETMP},
 222  	{AMOVB, C_TLS, C_NONE, C_REG, 54, 8, 0, 0, NOTUSETMP},
 223  	{AMOVBU, C_TLS, C_NONE, C_REG, 54, 8, 0, 0, NOTUSETMP},
 224  
 225  	{AMOVW, C_SECON, C_NONE, C_REG, 3, 4, REGSB, sys.MIPS64, 0},
 226  	{AMOVV, C_SECON, C_NONE, C_REG, 3, 4, REGSB, sys.MIPS64, 0},
 227  	{AMOVW, C_SACON, C_NONE, C_REG, 3, 4, REGSP, 0, 0},
 228  	{AMOVV, C_SACON, C_NONE, C_REG, 3, 4, REGSP, sys.MIPS64, 0},
 229  	{AMOVW, C_LECON, C_NONE, C_REG, 52, 8, REGSB, sys.MIPS, NOTUSETMP},
 230  	{AMOVW, C_LECON, C_NONE, C_REG, 52, 12, REGSB, sys.MIPS64, NOTUSETMP},
 231  	{AMOVV, C_LECON, C_NONE, C_REG, 52, 12, REGSB, sys.MIPS64, NOTUSETMP},
 232  
 233  	{AMOVW, C_LACON, C_NONE, C_REG, 26, 12, REGSP, 0, 0},
 234  	{AMOVV, C_LACON, C_NONE, C_REG, 26, 12, REGSP, sys.MIPS64, 0},
 235  	{AMOVW, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO, 0, 0},
 236  	{AMOVV, C_ADDCON, C_NONE, C_REG, 3, 4, REGZERO, sys.MIPS64, 0},
 237  	{AMOVW, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO, 0, 0},
 238  	{AMOVV, C_ANDCON, C_NONE, C_REG, 3, 4, REGZERO, sys.MIPS64, 0},
 239  	{AMOVW, C_STCON, C_NONE, C_REG, 55, 8, 0, 0, NOTUSETMP},
 240  	{AMOVV, C_STCON, C_NONE, C_REG, 55, 8, 0, sys.MIPS64, NOTUSETMP},
 241  
 242  	{AMOVW, C_UCON, C_NONE, C_REG, 24, 4, 0, 0, 0},
 243  	{AMOVV, C_UCON, C_NONE, C_REG, 24, 4, 0, sys.MIPS64, 0},
 244  	{AMOVW, C_LCON, C_NONE, C_REG, 19, 8, 0, 0, NOTUSETMP},
 245  	{AMOVV, C_LCON, C_NONE, C_REG, 19, 8, 0, sys.MIPS64, NOTUSETMP},
 246  
 247  	{AMOVW, C_HI, C_NONE, C_REG, 20, 4, 0, 0, 0},
 248  	{AMOVV, C_HI, C_NONE, C_REG, 20, 4, 0, sys.MIPS64, 0},
 249  	{AMOVW, C_LO, C_NONE, C_REG, 20, 4, 0, 0, 0},
 250  	{AMOVV, C_LO, C_NONE, C_REG, 20, 4, 0, sys.MIPS64, 0},
 251  	{AMOVW, C_REG, C_NONE, C_HI, 21, 4, 0, 0, 0},
 252  	{AMOVV, C_REG, C_NONE, C_HI, 21, 4, 0, sys.MIPS64, 0},
 253  	{AMOVW, C_REG, C_NONE, C_LO, 21, 4, 0, 0, 0},
 254  	{AMOVV, C_REG, C_NONE, C_LO, 21, 4, 0, sys.MIPS64, 0},
 255  
 256  	{AMUL, C_REG, C_REG, C_NONE, 22, 4, 0, 0, 0},
 257  	{AMUL, C_REG, C_REG, C_REG, 22, 4, 0, 0, 0},
 258  	{AMULV, C_REG, C_REG, C_NONE, 22, 4, 0, sys.MIPS64, 0},
 259  
 260  	{AADD, C_ADD0CON, C_REG, C_REG, 4, 4, 0, 0, 0},
 261  	{AADD, C_ADD0CON, C_NONE, C_REG, 4, 4, 0, 0, 0},
 262  	{AADD, C_ANDCON, C_REG, C_REG, 10, 8, 0, 0, 0},
 263  	{AADD, C_ANDCON, C_NONE, C_REG, 10, 8, 0, 0, 0},
 264  
 265  	{AADDV, C_ADD0CON, C_REG, C_REG, 4, 4, 0, sys.MIPS64, 0},
 266  	{AADDV, C_ADD0CON, C_NONE, C_REG, 4, 4, 0, sys.MIPS64, 0},
 267  	{AADDV, C_ANDCON, C_REG, C_REG, 10, 8, 0, sys.MIPS64, 0},
 268  	{AADDV, C_ANDCON, C_NONE, C_REG, 10, 8, 0, sys.MIPS64, 0},
 269  
 270  	{AAND, C_AND0CON, C_REG, C_REG, 4, 4, 0, 0, 0},
 271  	{AAND, C_AND0CON, C_NONE, C_REG, 4, 4, 0, 0, 0},
 272  	{AAND, C_ADDCON, C_REG, C_REG, 10, 8, 0, 0, 0},
 273  	{AAND, C_ADDCON, C_NONE, C_REG, 10, 8, 0, 0, 0},
 274  
 275  	{AADD, C_UCON, C_REG, C_REG, 25, 8, 0, 0, 0},
 276  	{AADD, C_UCON, C_NONE, C_REG, 25, 8, 0, 0, 0},
 277  	{AADDV, C_UCON, C_REG, C_REG, 25, 8, 0, sys.MIPS64, 0},
 278  	{AADDV, C_UCON, C_NONE, C_REG, 25, 8, 0, sys.MIPS64, 0},
 279  	{AAND, C_UCON, C_REG, C_REG, 25, 8, 0, 0, 0},
 280  	{AAND, C_UCON, C_NONE, C_REG, 25, 8, 0, 0, 0},
 281  
 282  	{AADD, C_LCON, C_NONE, C_REG, 23, 12, 0, 0, 0},
 283  	{AADDV, C_LCON, C_NONE, C_REG, 23, 12, 0, sys.MIPS64, 0},
 284  	{AAND, C_LCON, C_NONE, C_REG, 23, 12, 0, 0, 0},
 285  	{AADD, C_LCON, C_REG, C_REG, 23, 12, 0, 0, 0},
 286  	{AADDV, C_LCON, C_REG, C_REG, 23, 12, 0, sys.MIPS64, 0},
 287  	{AAND, C_LCON, C_REG, C_REG, 23, 12, 0, 0, 0},
 288  
 289  	{ASLL, C_SCON, C_REG, C_REG, 16, 4, 0, 0, 0},
 290  	{ASLL, C_SCON, C_NONE, C_REG, 16, 4, 0, 0, 0},
 291  
 292  	{ASLLV, C_SCON, C_REG, C_REG, 16, 4, 0, sys.MIPS64, 0},
 293  	{ASLLV, C_SCON, C_NONE, C_REG, 16, 4, 0, sys.MIPS64, 0},
 294  
 295  	{ASYSCALL, C_NONE, C_NONE, C_NONE, 5, 4, 0, 0, 0},
 296  
 297  	{ABEQ, C_REG, C_REG, C_SBRA, 6, 4, 0, 0, 0},
 298  	{ABEQ, C_REG, C_NONE, C_SBRA, 6, 4, 0, 0, 0},
 299  	{ABLEZ, C_REG, C_NONE, C_SBRA, 6, 4, 0, 0, 0},
 300  	{ABFPT, C_NONE, C_NONE, C_SBRA, 6, 8, 0, 0, NOTUSETMP},
 301  
 302  	{AJMP, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0, 0},
 303  	{AJAL, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0, 0},
 304  
 305  	{AJMP, C_NONE, C_NONE, C_ZOREG, 18, 4, REGZERO, 0, 0},
 306  	{AJAL, C_NONE, C_NONE, C_ZOREG, 18, 4, REGLINK, 0, 0},
 307  
 308  	{AMOVW, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB, sys.MIPS64, 0},
 309  	{AMOVF, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB, sys.MIPS64, 0},
 310  	{AMOVD, C_SEXT, C_NONE, C_FREG, 27, 4, REGSB, sys.MIPS64, 0},
 311  	{AMOVW, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP, sys.MIPS64, 0},
 312  	{AMOVF, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP, 0, 0},
 313  	{AMOVD, C_SAUTO, C_NONE, C_FREG, 27, 4, REGSP, 0, 0},
 314  	{AMOVW, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO, sys.MIPS64, 0},
 315  	{AMOVF, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO, 0, 0},
 316  	{AMOVD, C_SOREG, C_NONE, C_FREG, 27, 4, REGZERO, 0, 0},
 317  
 318  	{AMOVW, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB, sys.MIPS64, 0},
 319  	{AMOVF, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB, sys.MIPS64, 0},
 320  	{AMOVD, C_LEXT, C_NONE, C_FREG, 27, 12, REGSB, sys.MIPS64, 0},
 321  	{AMOVW, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP, sys.MIPS64, 0},
 322  	{AMOVF, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP, 0, 0},
 323  	{AMOVD, C_LAUTO, C_NONE, C_FREG, 27, 12, REGSP, 0, 0},
 324  	{AMOVW, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO, sys.MIPS64, 0},
 325  	{AMOVF, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO, 0, 0},
 326  	{AMOVD, C_LOREG, C_NONE, C_FREG, 27, 12, REGZERO, 0, 0},
 327  	{AMOVF, C_ADDR, C_NONE, C_FREG, 51, 8, 0, sys.MIPS, 0},
 328  	{AMOVF, C_ADDR, C_NONE, C_FREG, 51, 12, 0, sys.MIPS64, 0},
 329  	{AMOVD, C_ADDR, C_NONE, C_FREG, 51, 8, 0, sys.MIPS, 0},
 330  	{AMOVD, C_ADDR, C_NONE, C_FREG, 51, 12, 0, sys.MIPS64, 0},
 331  
 332  	{AMOVW, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB, sys.MIPS64, 0},
 333  	{AMOVF, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB, sys.MIPS64, 0},
 334  	{AMOVD, C_FREG, C_NONE, C_SEXT, 28, 4, REGSB, sys.MIPS64, 0},
 335  	{AMOVW, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP, sys.MIPS64, 0},
 336  	{AMOVF, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP, 0, 0},
 337  	{AMOVD, C_FREG, C_NONE, C_SAUTO, 28, 4, REGSP, 0, 0},
 338  	{AMOVW, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO, sys.MIPS64, 0},
 339  	{AMOVF, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO, 0, 0},
 340  	{AMOVD, C_FREG, C_NONE, C_SOREG, 28, 4, REGZERO, 0, 0},
 341  
 342  	{AMOVW, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB, sys.MIPS64, 0},
 343  	{AMOVF, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB, sys.MIPS64, 0},
 344  	{AMOVD, C_FREG, C_NONE, C_LEXT, 28, 12, REGSB, sys.MIPS64, 0},
 345  	{AMOVW, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP, sys.MIPS64, 0},
 346  	{AMOVF, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP, 0, 0},
 347  	{AMOVD, C_FREG, C_NONE, C_LAUTO, 28, 12, REGSP, 0, 0},
 348  	{AMOVW, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO, sys.MIPS64, 0},
 349  	{AMOVF, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO, 0, 0},
 350  	{AMOVD, C_FREG, C_NONE, C_LOREG, 28, 12, REGZERO, 0, 0},
 351  	{AMOVF, C_FREG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
 352  	{AMOVF, C_FREG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
 353  	{AMOVD, C_FREG, C_NONE, C_ADDR, 50, 8, 0, sys.MIPS, 0},
 354  	{AMOVD, C_FREG, C_NONE, C_ADDR, 50, 12, 0, sys.MIPS64, 0},
 355  
 356  	{AMOVW, C_REG, C_NONE, C_FREG, 30, 4, 0, 0, 0},
 357  	{AMOVW, C_FREG, C_NONE, C_REG, 31, 4, 0, 0, 0},
 358  	{AMOVV, C_REG, C_NONE, C_FREG, 47, 4, 0, sys.MIPS64, 0},
 359  	{AMOVV, C_FREG, C_NONE, C_REG, 48, 4, 0, sys.MIPS64, 0},
 360  
 361  	{AMOVW, C_ADDCON, C_NONE, C_FREG, 34, 8, 0, sys.MIPS64, 0},
 362  	{AMOVW, C_ANDCON, C_NONE, C_FREG, 34, 8, 0, sys.MIPS64, 0},
 363  
 364  	{AMOVW, C_REG, C_NONE, C_MREG, 37, 4, 0, 0, 0},
 365  	{AMOVV, C_REG, C_NONE, C_MREG, 37, 4, 0, sys.MIPS64, 0},
 366  	{AMOVW, C_MREG, C_NONE, C_REG, 38, 4, 0, 0, 0},
 367  	{AMOVV, C_MREG, C_NONE, C_REG, 38, 4, 0, sys.MIPS64, 0},
 368  
 369  	{AWORD, C_LCON, C_NONE, C_NONE, 40, 4, 0, 0, 0},
 370  
 371  	{AMOVW, C_REG, C_NONE, C_FCREG, 41, 4, 0, 0, 0},
 372  	{AMOVV, C_REG, C_NONE, C_FCREG, 41, 4, 0, sys.MIPS64, 0},
 373  	{AMOVW, C_FCREG, C_NONE, C_REG, 42, 4, 0, 0, 0},
 374  	{AMOVV, C_FCREG, C_NONE, C_REG, 42, 4, 0, sys.MIPS64, 0},
 375  
 376  	{ATEQ, C_SCON, C_REG, C_REG, 15, 4, 0, 0, 0},
 377  	{ATEQ, C_SCON, C_NONE, C_REG, 15, 4, 0, 0, 0},
 378  	{ACMOVT, C_REG, C_NONE, C_REG, 17, 4, 0, 0, 0},
 379  
 380  	{AVMOVB, C_SCON, C_NONE, C_WREG, 56, 4, 0, sys.MIPS64, 0},
 381  	{AVMOVB, C_ADDCON, C_NONE, C_WREG, 56, 4, 0, sys.MIPS64, 0},
 382  	{AVMOVB, C_SOREG, C_NONE, C_WREG, 57, 4, 0, sys.MIPS64, 0},
 383  	{AVMOVB, C_WREG, C_NONE, C_SOREG, 58, 4, 0, sys.MIPS64, 0},
 384  
 385  	{ABREAK, C_REG, C_NONE, C_SEXT, 7, 4, REGSB, sys.MIPS64, 0}, /* really CACHE instruction */
 386  	{ABREAK, C_REG, C_NONE, C_SAUTO, 7, 4, REGSP, sys.MIPS64, 0},
 387  	{ABREAK, C_REG, C_NONE, C_SOREG, 7, 4, REGZERO, sys.MIPS64, 0},
 388  	{ABREAK, C_NONE, C_NONE, C_NONE, 5, 4, 0, 0, 0},
 389  
 390  	{obj.AUNDEF, C_NONE, C_NONE, C_NONE, 49, 4, 0, 0, 0},
 391  	{obj.APCDATA, C_LCON, C_NONE, C_LCON, 0, 0, 0, 0, 0},
 392  	{obj.AFUNCDATA, C_SCON, C_NONE, C_ADDR, 0, 0, 0, 0, 0},
 393  	{obj.ANOP, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
 394  	{obj.ANOP, C_LCON, C_NONE, C_NONE, 0, 0, 0, 0, 0}, // nop variants, see #40689
 395  	{obj.ANOP, C_REG, C_NONE, C_NONE, 0, 0, 0, 0, 0},
 396  	{obj.ANOP, C_FREG, C_NONE, C_NONE, 0, 0, 0, 0, 0},
 397  	{obj.ADUFFZERO, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0, 0}, // same as AJMP
 398  	{obj.ADUFFCOPY, C_NONE, C_NONE, C_LBRA, 11, 4, 0, 0, 0}, // same as AJMP
 399  
 400  	{obj.AXXX, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0},
 401  }
 402  
 403  var oprange [ALAST & obj.AMask][]Optab
 404  
 405  var xcmp [C_NCLASS][C_NCLASS]bool
 406  
 407  func span0(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
 408  	if ctxt.Retpoline {
 409  		ctxt.Diag("-spectre=ret not supported on mips")
 410  		ctxt.Retpoline = false // don't keep printing
 411  	}
 412  
 413  	p := cursym.Func.Text
 414  	if p == nil || p.Link == nil { // handle external functions and ELF section symbols
 415  		return
 416  	}
 417  
 418  	c := ctxt0{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset + ctxt.FixedFrameSize())}
 419  
 420  	if oprange[AOR&obj.AMask] == nil {
 421  		c.ctxt.Diag("mips ops not initialized, call mips.buildop first")
 422  	}
 423  
 424  	pc := int64(0)
 425  	p.Pc = pc
 426  
 427  	var m int
 428  	var o *Optab
 429  	for p = p.Link; p != nil; p = p.Link {
 430  		p.Pc = pc
 431  		o = c.oplook(p)
 432  		m = int(o.size)
 433  		if m == 0 {
 434  			if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
 435  				c.ctxt.Diag("zero-width instruction\n%v", p)
 436  			}
 437  			continue
 438  		}
 439  
 440  		pc += int64(m)
 441  	}
 442  
 443  	c.cursym.Size = pc
 444  
 445  	/*
 446  	 * if any procedure is large enough to
 447  	 * generate a large SBRA branch, then
 448  	 * generate extra passes putting branches
 449  	 * around jmps to fix. this is rare.
 450  	 */
 451  	bflag := 1
 452  
 453  	var otxt int64
 454  	var q *obj.Prog
 455  	for bflag != 0 {
 456  		bflag = 0
 457  		pc = 0
 458  		for p = c.cursym.Func.Text.Link; p != nil; p = p.Link {
 459  			p.Pc = pc
 460  			o = c.oplook(p)
 461  
 462  			// very large conditional branches
 463  			if o.type_ == 6 && p.To.Target() != nil {
 464  				otxt = p.To.Target().Pc - pc
 465  				if otxt < -(1<<17)+10 || otxt >= (1<<17)-10 {
 466  					q = c.newprog()
 467  					q.Link = p.Link
 468  					p.Link = q
 469  					q.As = AJMP
 470  					q.Pos = p.Pos
 471  					q.To.Type = obj.TYPE_BRANCH
 472  					q.To.SetTarget(p.To.Target())
 473  					p.To.SetTarget(q)
 474  					q = c.newprog()
 475  					q.Link = p.Link
 476  					p.Link = q
 477  					q.As = AJMP
 478  					q.Pos = p.Pos
 479  					q.To.Type = obj.TYPE_BRANCH
 480  					q.To.SetTarget(q.Link.Link)
 481  
 482  					c.addnop(p.Link)
 483  					c.addnop(p)
 484  					bflag = 1
 485  				}
 486  			}
 487  
 488  			m = int(o.size)
 489  			if m == 0 {
 490  				if p.As != obj.ANOP && p.As != obj.AFUNCDATA && p.As != obj.APCDATA {
 491  					c.ctxt.Diag("zero-width instruction\n%v", p)
 492  				}
 493  				continue
 494  			}
 495  
 496  			pc += int64(m)
 497  		}
 498  
 499  		c.cursym.Size = pc
 500  	}
 501  	if c.ctxt.Arch.Family == sys.MIPS64 {
 502  		pc += -pc & (mips64FuncAlign - 1)
 503  	}
 504  	c.cursym.Size = pc
 505  
 506  	/*
 507  	 * lay out the code, emitting code and data relocations.
 508  	 */
 509  
 510  	c.cursym.Grow(c.cursym.Size)
 511  
 512  	bp := c.cursym.P
 513  	var i int32
 514  	var out [4]uint32
 515  	for p := c.cursym.Func.Text.Link; p != nil; p = p.Link {
 516  		c.pc = p.Pc
 517  		o = c.oplook(p)
 518  		if int(o.size) > 4*len(out) {
 519  			log.Fatalf("out array in span0 is too small, need at least %d for %v", o.size/4, p)
 520  		}
 521  		c.asmout(p, o, out[:])
 522  		for i = 0; i < int32(o.size/4); i++ {
 523  			c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
 524  			bp = bp[4:]
 525  		}
 526  	}
 527  
 528  	// Mark nonpreemptible instruction sequences.
 529  	// We use REGTMP as a scratch register during call injection,
 530  	// so instruction sequences that use REGTMP are unsafe to
 531  	// preempt asynchronously.
 532  	obj.MarkUnsafePoints(c.ctxt, c.cursym.Func.Text, c.newprog, c.isUnsafePoint, c.isRestartable)
 533  }
 534  
 535  // isUnsafePoint returns whether p is an unsafe point.
 536  func (c *ctxt0) isUnsafePoint(p *obj.Prog) bool {
 537  	// If p explicitly uses REGTMP, it's unsafe to preempt, because the
 538  	// preemption sequence clobbers REGTMP.
 539  	return p.From.Reg == REGTMP || p.To.Reg == REGTMP || p.Reg == REGTMP
 540  }
 541  
 542  // isRestartable returns whether p is a multi-instruction sequence that,
 543  // if preempted, can be restarted.
 544  func (c *ctxt0) isRestartable(p *obj.Prog) bool {
 545  	if c.isUnsafePoint(p) {
 546  		return false
 547  	}
 548  	// If p is a multi-instruction sequence with uses REGTMP inserted by
 549  	// the assembler in order to materialize a large constant/offset, we
 550  	// can restart p (at the start of the instruction sequence), recompute
 551  	// the content of REGTMP, upon async preemption. Currently, all cases
 552  	// of assembler-inserted REGTMP fall into this category.
 553  	// If p doesn't use REGTMP, it can be simply preempted, so we don't
 554  	// mark it.
 555  	o := c.oplook(p)
 556  	return o.size > 4 && o.flag&NOTUSETMP == 0
 557  }
 558  
 559  func isint32(v int64) bool {
 560  	return int64(int32(v)) == v
 561  }
 562  
 563  func isuint32(v uint64) bool {
 564  	return uint64(uint32(v)) == v
 565  }
 566  
 567  func (c *ctxt0) aclass(a *obj.Addr) int {
 568  	switch a.Type {
 569  	case obj.TYPE_NONE:
 570  		return C_NONE
 571  
 572  	case obj.TYPE_REG:
 573  		if REG_R0 <= a.Reg && a.Reg <= REG_R31 {
 574  			return C_REG
 575  		}
 576  		if REG_F0 <= a.Reg && a.Reg <= REG_F31 {
 577  			return C_FREG
 578  		}
 579  		if REG_M0 <= a.Reg && a.Reg <= REG_M31 {
 580  			return C_MREG
 581  		}
 582  		if REG_FCR0 <= a.Reg && a.Reg <= REG_FCR31 {
 583  			return C_FCREG
 584  		}
 585  		if REG_W0 <= a.Reg && a.Reg <= REG_W31 {
 586  			return C_WREG
 587  		}
 588  		if a.Reg == REG_LO {
 589  			return C_LO
 590  		}
 591  		if a.Reg == REG_HI {
 592  			return C_HI
 593  		}
 594  		return C_GOK
 595  
 596  	case obj.TYPE_MEM:
 597  		switch a.Name {
 598  		case obj.NAME_EXTERN,
 599  			obj.NAME_STATIC:
 600  			if a.Sym == nil {
 601  				break
 602  			}
 603  			c.instoffset = a.Offset
 604  			if a.Sym != nil { // use relocation
 605  				if a.Sym.Type == objabi.STLSBSS {
 606  					return C_TLS
 607  				}
 608  				return C_ADDR
 609  			}
 610  			return C_LEXT
 611  
 612  		case obj.NAME_AUTO:
 613  			if a.Reg == REGSP {
 614  				// unset base register for better printing, since
 615  				// a.Offset is still relative to pseudo-SP.
 616  				a.Reg = obj.REG_NONE
 617  			}
 618  			c.instoffset = int64(c.autosize) + a.Offset
 619  			if c.instoffset >= -BIG && c.instoffset < BIG {
 620  				return C_SAUTO
 621  			}
 622  			return C_LAUTO
 623  
 624  		case obj.NAME_PARAM:
 625  			if a.Reg == REGSP {
 626  				// unset base register for better printing, since
 627  				// a.Offset is still relative to pseudo-FP.
 628  				a.Reg = obj.REG_NONE
 629  			}
 630  			c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
 631  			if c.instoffset >= -BIG && c.instoffset < BIG {
 632  				return C_SAUTO
 633  			}
 634  			return C_LAUTO
 635  
 636  		case obj.NAME_NONE:
 637  			c.instoffset = a.Offset
 638  			if c.instoffset == 0 {
 639  				return C_ZOREG
 640  			}
 641  			if c.instoffset >= -BIG && c.instoffset < BIG {
 642  				return C_SOREG
 643  			}
 644  			return C_LOREG
 645  		}
 646  
 647  		return C_GOK
 648  
 649  	case obj.TYPE_TEXTSIZE:
 650  		return C_TEXTSIZE
 651  
 652  	case obj.TYPE_CONST,
 653  		obj.TYPE_ADDR:
 654  		switch a.Name {
 655  		case obj.NAME_NONE:
 656  			c.instoffset = a.Offset
 657  			if a.Reg != 0 {
 658  				if -BIG <= c.instoffset && c.instoffset <= BIG {
 659  					return C_SACON
 660  				}
 661  				if isint32(c.instoffset) {
 662  					return C_LACON
 663  				}
 664  				return C_DACON
 665  			}
 666  
 667  		case obj.NAME_EXTERN,
 668  			obj.NAME_STATIC:
 669  			s := a.Sym
 670  			if s == nil {
 671  				return C_GOK
 672  			}
 673  
 674  			c.instoffset = a.Offset
 675  			if s.Type == objabi.STLSBSS {
 676  				return C_STCON // address of TLS variable
 677  			}
 678  			return C_LECON
 679  
 680  		case obj.NAME_AUTO:
 681  			if a.Reg == REGSP {
 682  				// unset base register for better printing, since
 683  				// a.Offset is still relative to pseudo-SP.
 684  				a.Reg = obj.REG_NONE
 685  			}
 686  			c.instoffset = int64(c.autosize) + a.Offset
 687  			if c.instoffset >= -BIG && c.instoffset < BIG {
 688  				return C_SACON
 689  			}
 690  			return C_LACON
 691  
 692  		case obj.NAME_PARAM:
 693  			if a.Reg == REGSP {
 694  				// unset base register for better printing, since
 695  				// a.Offset is still relative to pseudo-FP.
 696  				a.Reg = obj.REG_NONE
 697  			}
 698  			c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
 699  			if c.instoffset >= -BIG && c.instoffset < BIG {
 700  				return C_SACON
 701  			}
 702  			return C_LACON
 703  
 704  		default:
 705  			return C_GOK
 706  		}
 707  
 708  		if c.instoffset >= 0 {
 709  			if c.instoffset == 0 {
 710  				return C_ZCON
 711  			}
 712  			if c.instoffset <= 0x7fff {
 713  				return C_SCON
 714  			}
 715  			if c.instoffset <= 0xffff {
 716  				return C_ANDCON
 717  			}
 718  			if c.instoffset&0xffff == 0 && isuint32(uint64(c.instoffset)) { /* && (instoffset & (1<<31)) == 0) */
 719  				return C_UCON
 720  			}
 721  			if isint32(c.instoffset) || isuint32(uint64(c.instoffset)) {
 722  				return C_LCON
 723  			}
 724  			return C_LCON // C_DCON
 725  		}
 726  
 727  		if c.instoffset >= -0x8000 {
 728  			return C_ADDCON
 729  		}
 730  		if c.instoffset&0xffff == 0 && isint32(c.instoffset) {
 731  			return C_UCON
 732  		}
 733  		if isint32(c.instoffset) {
 734  			return C_LCON
 735  		}
 736  		return C_LCON // C_DCON
 737  
 738  	case obj.TYPE_BRANCH:
 739  		return C_SBRA
 740  	}
 741  
 742  	return C_GOK
 743  }
 744  
 745  func prasm(p *obj.Prog) {
 746  	fmt.Printf("%v\n", p)
 747  }
 748  
 749  func (c *ctxt0) oplook(p *obj.Prog) *Optab {
 750  	if oprange[AOR&obj.AMask] == nil {
 751  		c.ctxt.Diag("mips ops not initialized, call mips.buildop first")
 752  	}
 753  
 754  	a1 := int(p.Optab)
 755  	if a1 != 0 {
 756  		return &optab[a1-1]
 757  	}
 758  	a1 = int(p.From.Class)
 759  	if a1 == 0 {
 760  		a1 = c.aclass(&p.From) + 1
 761  		p.From.Class = int8(a1)
 762  	}
 763  
 764  	a1--
 765  	a3 := int(p.To.Class)
 766  	if a3 == 0 {
 767  		a3 = c.aclass(&p.To) + 1
 768  		p.To.Class = int8(a3)
 769  	}
 770  
 771  	a3--
 772  	a2 := C_NONE
 773  	if p.Reg != 0 {
 774  		a2 = C_REG
 775  	}
 776  
 777  	ops := oprange[p.As&obj.AMask]
 778  	c1 := &xcmp[a1]
 779  	c3 := &xcmp[a3]
 780  	for i := range ops {
 781  		op := &ops[i]
 782  		if int(op.a2) == a2 && c1[op.a1] && c3[op.a3] && (op.family == 0 || c.ctxt.Arch.Family == op.family) {
 783  			p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
 784  			return op
 785  		}
 786  	}
 787  
 788  	c.ctxt.Diag("illegal combination %v %v %v %v", p.As, DRconv(a1), DRconv(a2), DRconv(a3))
 789  	prasm(p)
 790  	// Turn illegal instruction into an UNDEF, avoid crashing in asmout.
 791  	return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, 49, 4, 0, 0, 0}
 792  }
 793  
 794  func cmp(a int, b int) bool {
 795  	if a == b {
 796  		return true
 797  	}
 798  	switch a {
 799  	case C_LCON:
 800  		if b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON {
 801  			return true
 802  		}
 803  
 804  	case C_ADD0CON:
 805  		if b == C_ADDCON {
 806  			return true
 807  		}
 808  		fallthrough
 809  
 810  	case C_ADDCON:
 811  		if b == C_ZCON || b == C_SCON {
 812  			return true
 813  		}
 814  
 815  	case C_AND0CON:
 816  		if b == C_ANDCON {
 817  			return true
 818  		}
 819  		fallthrough
 820  
 821  	case C_ANDCON:
 822  		if b == C_ZCON || b == C_SCON {
 823  			return true
 824  		}
 825  
 826  	case C_UCON:
 827  		if b == C_ZCON {
 828  			return true
 829  		}
 830  
 831  	case C_SCON:
 832  		if b == C_ZCON {
 833  			return true
 834  		}
 835  
 836  	case C_LACON:
 837  		if b == C_SACON {
 838  			return true
 839  		}
 840  
 841  	case C_LBRA:
 842  		if b == C_SBRA {
 843  			return true
 844  		}
 845  
 846  	case C_LEXT:
 847  		if b == C_SEXT {
 848  			return true
 849  		}
 850  
 851  	case C_LAUTO:
 852  		if b == C_SAUTO {
 853  			return true
 854  		}
 855  
 856  	case C_REG:
 857  		if b == C_ZCON {
 858  			return r0iszero != 0 /*TypeKind(100016)*/
 859  		}
 860  
 861  	case C_LOREG:
 862  		if b == C_ZOREG || b == C_SOREG {
 863  			return true
 864  		}
 865  
 866  	case C_SOREG:
 867  		if b == C_ZOREG {
 868  			return true
 869  		}
 870  	}
 871  
 872  	return false
 873  }
 874  
 875  type ocmp []Optab
 876  
 877  func (x ocmp) Len() int {
 878  	return len(x)
 879  }
 880  
 881  func (x ocmp) Swap(i, j int) {
 882  	x[i], x[j] = x[j], x[i]
 883  }
 884  
 885  func (x ocmp) Less(i, j int) bool {
 886  	p1 := &x[i]
 887  	p2 := &x[j]
 888  	n := int(p1.as) - int(p2.as)
 889  	if n != 0 {
 890  		return n < 0
 891  	}
 892  	n = int(p1.a1) - int(p2.a1)
 893  	if n != 0 {
 894  		return n < 0
 895  	}
 896  	n = int(p1.a2) - int(p2.a2)
 897  	if n != 0 {
 898  		return n < 0
 899  	}
 900  	n = int(p1.a3) - int(p2.a3)
 901  	if n != 0 {
 902  		return n < 0
 903  	}
 904  	return false
 905  }
 906  
 907  func opset(a, b0 obj.As) {
 908  	oprange[a&obj.AMask] = oprange[b0]
 909  }
 910  
 911  func buildop(ctxt *obj.Link) {
 912  	if oprange[AOR&obj.AMask] != nil {
 913  		// Already initialized; stop now.
 914  		// This happens in the cmd/asm tests,
 915  		// each of which re-initializes the arch.
 916  		return
 917  	}
 918  
 919  	var n int
 920  
 921  	for i := 0; i < C_NCLASS; i++ {
 922  		for n = 0; n < C_NCLASS; n++ {
 923  			if cmp(n, i) {
 924  				xcmp[i][n] = true
 925  			}
 926  		}
 927  	}
 928  	for n = 0; optab[n].as != obj.AXXX; n++ {
 929  	}
 930  	sort.Sort(ocmp(optab[:n]))
 931  	for i := 0; i < n; i++ {
 932  		r := optab[i].as
 933  		r0 := r & obj.AMask
 934  		start := i
 935  		for optab[i].as == r {
 936  			i++
 937  		}
 938  		oprange[r0] = optab[start:i]
 939  		i--
 940  
 941  		switch r {
 942  		default:
 943  			ctxt.Diag("unknown op in build: %v", r)
 944  			ctxt.DiagFlush()
 945  			log.Fatalf("bad code")
 946  
 947  		case AABSF:
 948  			opset(AMOVFD, r0)
 949  			opset(AMOVDF, r0)
 950  			opset(AMOVWF, r0)
 951  			opset(AMOVFW, r0)
 952  			opset(AMOVWD, r0)
 953  			opset(AMOVDW, r0)
 954  			opset(ANEGF, r0)
 955  			opset(ANEGD, r0)
 956  			opset(AABSD, r0)
 957  			opset(ATRUNCDW, r0)
 958  			opset(ATRUNCFW, r0)
 959  			opset(ASQRTF, r0)
 960  			opset(ASQRTD, r0)
 961  
 962  		case AMOVVF:
 963  			opset(AMOVVD, r0)
 964  			opset(AMOVFV, r0)
 965  			opset(AMOVDV, r0)
 966  			opset(ATRUNCDV, r0)
 967  			opset(ATRUNCFV, r0)
 968  
 969  		case AADD:
 970  			opset(ASGT, r0)
 971  			opset(ASGTU, r0)
 972  			opset(AADDU, r0)
 973  
 974  		case AADDV:
 975  			opset(AADDVU, r0)
 976  
 977  		case AADDF:
 978  			opset(ADIVF, r0)
 979  			opset(ADIVD, r0)
 980  			opset(AMULF, r0)
 981  			opset(AMULD, r0)
 982  			opset(ASUBF, r0)
 983  			opset(ASUBD, r0)
 984  			opset(AADDD, r0)
 985  
 986  		case AAND:
 987  			opset(AOR, r0)
 988  			opset(AXOR, r0)
 989  
 990  		case ABEQ:
 991  			opset(ABNE, r0)
 992  
 993  		case ABLEZ:
 994  			opset(ABGEZ, r0)
 995  			opset(ABGEZAL, r0)
 996  			opset(ABLTZ, r0)
 997  			opset(ABLTZAL, r0)
 998  			opset(ABGTZ, r0)
 999  
1000  		case AMOVB:
1001  			opset(AMOVH, r0)
1002  
1003  		case AMOVBU:
1004  			opset(AMOVHU, r0)
1005  
1006  		case AMUL:
1007  			opset(AREM, r0)
1008  			opset(AREMU, r0)
1009  			opset(ADIVU, r0)
1010  			opset(AMULU, r0)
1011  			opset(ADIV, r0)
1012  			opset(AMADD, r0)
1013  			opset(AMSUB, r0)
1014  
1015  		case AMULV:
1016  			opset(ADIVV, r0)
1017  			opset(ADIVVU, r0)
1018  			opset(AMULVU, r0)
1019  			opset(AREMV, r0)
1020  			opset(AREMVU, r0)
1021  
1022  		case ASLL:
1023  			opset(ASRL, r0)
1024  			opset(ASRA, r0)
1025  
1026  		case ASLLV:
1027  			opset(ASRAV, r0)
1028  			opset(ASRLV, r0)
1029  
1030  		case ASUB:
1031  			opset(ASUBU, r0)
1032  			opset(ANOR, r0)
1033  
1034  		case ASUBV:
1035  			opset(ASUBVU, r0)
1036  
1037  		case ASYSCALL:
1038  			opset(ASYNC, r0)
1039  			opset(ANOOP, r0)
1040  			opset(ATLBP, r0)
1041  			opset(ATLBR, r0)
1042  			opset(ATLBWI, r0)
1043  			opset(ATLBWR, r0)
1044  
1045  		case ACMPEQF:
1046  			opset(ACMPGTF, r0)
1047  			opset(ACMPGTD, r0)
1048  			opset(ACMPGEF, r0)
1049  			opset(ACMPGED, r0)
1050  			opset(ACMPEQD, r0)
1051  
1052  		case ABFPT:
1053  			opset(ABFPF, r0)
1054  
1055  		case AMOVWL:
1056  			opset(AMOVWR, r0)
1057  
1058  		case AMOVVL:
1059  			opset(AMOVVR, r0)
1060  
1061  		case AVMOVB:
1062  			opset(AVMOVH, r0)
1063  			opset(AVMOVW, r0)
1064  			opset(AVMOVD, r0)
1065  
1066  		case AMOVW,
1067  			AMOVD,
1068  			AMOVF,
1069  			AMOVV,
1070  			ABREAK,
1071  			ARFE,
1072  			AJAL,
1073  			AJMP,
1074  			AMOVWU,
1075  			ALL,
1076  			ALLV,
1077  			ASC,
1078  			ASCV,
1079  			ANEGW,
1080  			ANEGV,
1081  			AWORD,
1082  			obj.ANOP,
1083  			obj.ATEXT,
1084  			obj.AUNDEF,
1085  			obj.AFUNCDATA,
1086  			obj.APCDATA,
1087  			obj.ADUFFZERO,
1088  			obj.ADUFFCOPY:
1089  			break
1090  
1091  		case ACMOVN:
1092  			opset(ACMOVZ, r0)
1093  
1094  		case ACMOVT:
1095  			opset(ACMOVF, r0)
1096  
1097  		case ACLO:
1098  			opset(ACLZ, r0)
1099  
1100  		case ATEQ:
1101  			opset(ATNE, r0)
1102  		}
1103  	}
1104  }
1105  
1106  func OP(x uint32, y uint32) uint32 {
1107  	return x<<3 | y<<0
1108  }
1109  
1110  func SP(x uint32, y uint32) uint32 {
1111  	return x<<29 | y<<26
1112  }
1113  
1114  func BCOND(x uint32, y uint32) uint32 {
1115  	return x<<19 | y<<16
1116  }
1117  
1118  func MMU(x uint32, y uint32) uint32 {
1119  	return SP(2, 0) | 16<<21 | x<<3 | y<<0
1120  }
1121  
1122  func FPF(x uint32, y uint32) uint32 {
1123  	return SP(2, 1) | 16<<21 | x<<3 | y<<0
1124  }
1125  
1126  func FPD(x uint32, y uint32) uint32 {
1127  	return SP(2, 1) | 17<<21 | x<<3 | y<<0
1128  }
1129  
1130  func FPW(x uint32, y uint32) uint32 {
1131  	return SP(2, 1) | 20<<21 | x<<3 | y<<0
1132  }
1133  
1134  func FPV(x uint32, y uint32) uint32 {
1135  	return SP(2, 1) | 21<<21 | x<<3 | y<<0
1136  }
1137  
1138  func OP_RRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
1139  	return op | (r1&31)<<16 | (r2&31)<<21 | (r3&31)<<11
1140  }
1141  
1142  func OP_IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
1143  	return op | i&0xFFFF | (r2&31)<<21 | (r3&31)<<16
1144  }
1145  
1146  func OP_SRR(op uint32, s uint32, r2 uint32, r3 uint32) uint32 {
1147  	return op | (s&31)<<6 | (r2&31)<<16 | (r3&31)<<11
1148  }
1149  
1150  func OP_FRRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
1151  	return op | (r1&31)<<16 | (r2&31)<<11 | (r3&31)<<6
1152  }
1153  
1154  func OP_JMP(op uint32, i uint32) uint32 {
1155  	return op | i&0x3FFFFFF
1156  }
1157  
1158  func OP_VI10(op uint32, df uint32, s10 int32, wd uint32, minor uint32) uint32 {
1159  	return 0x1e<<26 | (op&7)<<23 | (df&3)<<21 | uint32(s10&0x3FF)<<11 | (wd&31)<<6 | minor&0x3F
1160  }
1161  
1162  func OP_VMI10(s10 int32, rs uint32, wd uint32, minor uint32, df uint32) uint32 {
1163  	return 0x1e<<26 | uint32(s10&0x3FF)<<16 | (rs&31)<<11 | (wd&31)<<6 | (minor&15)<<2 | df&3
1164  }
1165  
1166  func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
1167  	o1 := uint32(0)
1168  	o2 := uint32(0)
1169  	o3 := uint32(0)
1170  	o4 := uint32(0)
1171  
1172  	add := AADDU
1173  
1174  	if c.ctxt.Arch.Family == sys.MIPS64 {
1175  		add = AADDVU
1176  	}
1177  	switch o.type_ {
1178  	default:
1179  		c.ctxt.Diag("unknown type %d %v", o.type_)
1180  		prasm(p)
1181  
1182  	case 0: /* pseudo ops */
1183  		break
1184  
1185  	case 1: /* mov r1,r2 ==> OR r1,r0,r2 */
1186  		a := AOR
1187  		if p.As == AMOVW && c.ctxt.Arch.Family == sys.MIPS64 {
1188  			// on MIPS64, most of the 32-bit instructions have unpredictable behavior,
1189  			// but SLL is special that the result is always sign-extended to 64-bit.
1190  			a = ASLL
1191  		}
1192  		o1 = OP_RRR(c.oprrr(a), uint32(p.From.Reg), uint32(REGZERO), uint32(p.To.Reg))
1193  
1194  	case 2: /* add/sub r1,[r2],r3 */
1195  		r := int(p.Reg)
1196  		if p.As == ANEGW || p.As == ANEGV {
1197  			r = REGZERO
1198  		}
1199  		if r == 0 {
1200  			r = int(p.To.Reg)
1201  		}
1202  		o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
1203  
1204  	case 3: /* mov $soreg, r ==> or/add $i,o,r */
1205  		v := c.regoff(&p.From)
1206  
1207  		r := int(p.From.Reg)
1208  		if r == 0 {
1209  			r = int(o.param)
1210  		}
1211  		a := add
1212  		if o.a1 == C_ANDCON {
1213  			a = AOR
1214  		}
1215  
1216  		o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
1217  
1218  	case 4: /* add $scon,[r1],r2 */
1219  		v := c.regoff(&p.From)
1220  
1221  		r := int(p.Reg)
1222  		if r == 0 {
1223  			r = int(p.To.Reg)
1224  		}
1225  
1226  		o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
1227  
1228  	case 5: /* syscall */
1229  		o1 = c.oprrr(p.As)
1230  
1231  	case 6: /* beq r1,[r2],sbra */
1232  		v := int32(0)
1233  		if p.To.Target() == nil {
1234  			v = int32(-4) >> 2
1235  		} else {
1236  			v = int32(p.To.Target().Pc-p.Pc-4) >> 2
1237  		}
1238  		if (v<<16)>>16 != v {
1239  			c.ctxt.Diag("short branch too far\n%v", p)
1240  		}
1241  		o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(p.From.Reg), uint32(p.Reg))
1242  		// for ABFPT and ABFPF only: always fill delay slot with 0
1243  		// see comments in func preprocess for details.
1244  		o2 = 0
1245  
1246  	case 7: /* mov r, soreg ==> sw o(r) */
1247  		r := int(p.To.Reg)
1248  		if r == 0 {
1249  			r = int(o.param)
1250  		}
1251  		v := c.regoff(&p.To)
1252  		o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.From.Reg))
1253  
1254  	case 8: /* mov soreg, r ==> lw o(r) */
1255  		r := int(p.From.Reg)
1256  		if r == 0 {
1257  			r = int(o.param)
1258  		}
1259  		v := c.regoff(&p.From)
1260  		o1 = OP_IRR(c.opirr(-p.As), uint32(v), uint32(r), uint32(p.To.Reg))
1261  
1262  	case 9: /* sll r1,[r2],r3 */
1263  		r := int(p.Reg)
1264  
1265  		if r == 0 {
1266  			r = int(p.To.Reg)
1267  		}
1268  		o1 = OP_RRR(c.oprrr(p.As), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg))
1269  
1270  	case 10: /* add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2 */
1271  		v := c.regoff(&p.From)
1272  		a := AOR
1273  		if v < 0 {
1274  			a = AADDU
1275  		}
1276  		o1 = OP_IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
1277  		r := int(p.Reg)
1278  		if r == 0 {
1279  			r = int(p.To.Reg)
1280  		}
1281  		o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1282  
1283  	case 11: /* jmp lbra */
1284  		v := int32(0)
1285  		if c.aclass(&p.To) == C_SBRA && p.To.Sym == nil && p.As == AJMP {
1286  			// use PC-relative branch for short branches
1287  			// BEQ	R0, R0, sbra
1288  			if p.To.Target() == nil {
1289  				v = int32(-4) >> 2
1290  			} else {
1291  				v = int32(p.To.Target().Pc-p.Pc-4) >> 2
1292  			}
1293  			if (v<<16)>>16 == v {
1294  				o1 = OP_IRR(c.opirr(ABEQ), uint32(v), uint32(REGZERO), uint32(REGZERO))
1295  				break
1296  			}
1297  		}
1298  		if p.To.Target() == nil {
1299  			v = int32(p.Pc) >> 2
1300  		} else {
1301  			v = int32(p.To.Target().Pc) >> 2
1302  		}
1303  		o1 = OP_JMP(c.opirr(p.As), uint32(v))
1304  		if p.To.Sym == nil {
1305  			p.To.Sym = c.cursym.Func.Text.From.Sym
1306  			p.To.Offset = p.To.Target().Pc
1307  		}
1308  		rel := obj.Addrel(c.cursym)
1309  		rel.Off = int32(c.pc)
1310  		rel.Siz = 4
1311  		rel.Sym = p.To.Sym
1312  		rel.Add = p.To.Offset
1313  		if p.As == AJAL {
1314  			rel.Type = objabi.R_CALLMIPS
1315  		} else {
1316  			rel.Type = objabi.R_JMPMIPS
1317  		}
1318  
1319  	case 12: /* movbs r,r */
1320  		// NOTE: this case does not use REGTMP. If it ever does,
1321  		// remove the NOTUSETMP flag in optab.
1322  		v := 16
1323  		if p.As == AMOVB {
1324  			v = 24
1325  		}
1326  		o1 = OP_SRR(c.opirr(ASLL), uint32(v), uint32(p.From.Reg), uint32(p.To.Reg))
1327  		o2 = OP_SRR(c.opirr(ASRA), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
1328  
1329  	case 13: /* movbu r,r */
1330  		if p.As == AMOVBU {
1331  			o1 = OP_IRR(c.opirr(AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg))
1332  		} else {
1333  			o1 = OP_IRR(c.opirr(AAND), uint32(0xffff), uint32(p.From.Reg), uint32(p.To.Reg))
1334  		}
1335  
1336  	case 14: /* movwu r,r */
1337  		// NOTE: this case does not use REGTMP. If it ever does,
1338  		// remove the NOTUSETMP flag in optab.
1339  		o1 = OP_SRR(c.opirr(-ASLLV), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
1340  		o2 = OP_SRR(c.opirr(-ASRLV), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
1341  
1342  	case 15: /* teq $c r,r */
1343  		v := c.regoff(&p.From)
1344  		r := int(p.Reg)
1345  		if r == 0 {
1346  			r = REGZERO
1347  		}
1348  		/* only use 10 bits of trap code */
1349  		o1 = OP_IRR(c.opirr(p.As), (uint32(v)&0x3FF)<<6, uint32(r), uint32(p.To.Reg))
1350  
1351  	case 16: /* sll $c,[r1],r2 */
1352  		v := c.regoff(&p.From)
1353  		r := int(p.Reg)
1354  		if r == 0 {
1355  			r = int(p.To.Reg)
1356  		}
1357  
1358  		/* OP_SRR will use only the low 5 bits of the shift value */
1359  		if v >= 32 && vshift(p.As) {
1360  			o1 = OP_SRR(c.opirr(-p.As), uint32(v-32), uint32(r), uint32(p.To.Reg))
1361  		} else {
1362  			o1 = OP_SRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
1363  		}
1364  
1365  	case 17:
1366  		o1 = OP_RRR(c.oprrr(p.As), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg))
1367  
1368  	case 18: /* jmp [r1],0(r2) */
1369  		r := int(p.Reg)
1370  		if r == 0 {
1371  			r = int(o.param)
1372  		}
1373  		o1 = OP_RRR(c.oprrr(p.As), uint32(0), uint32(p.To.Reg), uint32(r))
1374  		if p.As == obj.ACALL {
1375  			rel := obj.Addrel(c.cursym)
1376  			rel.Off = int32(c.pc)
1377  			rel.Siz = 0
1378  			rel.Type = objabi.R_CALLIND
1379  		}
1380  
1381  	case 19: /* mov $lcon,r ==> lu+or */
1382  		// NOTE: this case does not use REGTMP. If it ever does,
1383  		// remove the NOTUSETMP flag in optab.
1384  		v := c.regoff(&p.From)
1385  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
1386  		o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
1387  
1388  	case 20: /* mov lo/hi,r */
1389  		a := OP(2, 0) /* mfhi */
1390  		if p.From.Reg == REG_LO {
1391  			a = OP(2, 2) /* mflo */
1392  		}
1393  		o1 = OP_RRR(a, uint32(REGZERO), uint32(REGZERO), uint32(p.To.Reg))
1394  
1395  	case 21: /* mov r,lo/hi */
1396  		a := OP(2, 1) /* mthi */
1397  		if p.To.Reg == REG_LO {
1398  			a = OP(2, 3) /* mtlo */
1399  		}
1400  		o1 = OP_RRR(a, uint32(REGZERO), uint32(p.From.Reg), uint32(REGZERO))
1401  
1402  	case 22: /* mul r1,r2 [r3]*/
1403  		if p.To.Reg != 0 {
1404  			r := int(p.Reg)
1405  			if r == 0 {
1406  				r = int(p.To.Reg)
1407  			}
1408  			a := SP(3, 4) | 2 /* mul */
1409  			o1 = OP_RRR(a, uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
1410  		} else {
1411  			o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(p.Reg), uint32(REGZERO))
1412  		}
1413  
1414  	case 23: /* add $lcon,r1,r2 ==> lu+or+add */
1415  		v := c.regoff(&p.From)
1416  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
1417  		o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
1418  		r := int(p.Reg)
1419  		if r == 0 {
1420  			r = int(p.To.Reg)
1421  		}
1422  		o3 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1423  
1424  	case 24: /* mov $ucon,r ==> lu r */
1425  		v := c.regoff(&p.From)
1426  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
1427  
1428  	case 25: /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */
1429  		v := c.regoff(&p.From)
1430  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
1431  		r := int(p.Reg)
1432  		if r == 0 {
1433  			r = int(p.To.Reg)
1434  		}
1435  		o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1436  
1437  	case 26: /* mov $lsext/auto/oreg,r ==> lu+or+add */
1438  		v := c.regoff(&p.From)
1439  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
1440  		o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
1441  		r := int(p.From.Reg)
1442  		if r == 0 {
1443  			r = int(o.param)
1444  		}
1445  		o3 = OP_RRR(c.oprrr(add), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
1446  
1447  	case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
1448  		v := c.regoff(&p.From)
1449  		r := int(p.From.Reg)
1450  		if r == 0 {
1451  			r = int(o.param)
1452  		}
1453  		a := -AMOVF
1454  		if p.As == AMOVD {
1455  			a = -AMOVD
1456  		}
1457  		switch o.size {
1458  		case 12:
1459  			o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
1460  			o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
1461  			o3 = OP_IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
1462  
1463  		case 4:
1464  			o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
1465  		}
1466  
1467  	case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */
1468  		v := c.regoff(&p.To)
1469  		r := int(p.To.Reg)
1470  		if r == 0 {
1471  			r = int(o.param)
1472  		}
1473  		a := AMOVF
1474  		if p.As == AMOVD {
1475  			a = AMOVD
1476  		}
1477  		switch o.size {
1478  		case 12:
1479  			o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
1480  			o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
1481  			o3 = OP_IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
1482  
1483  		case 4:
1484  			o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.From.Reg))
1485  		}
1486  
1487  	case 30: /* movw r,fr */
1488  		a := SP(2, 1) | (4 << 21) /* mtc1 */
1489  		o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
1490  
1491  	case 31: /* movw fr,r */
1492  		a := SP(2, 1) | (0 << 21) /* mtc1 */
1493  		o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
1494  
1495  	case 32: /* fadd fr1,[fr2],fr3 */
1496  		r := int(p.Reg)
1497  		if r == 0 {
1498  			r = int(p.To.Reg)
1499  		}
1500  		o1 = OP_FRRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
1501  
1502  	case 33: /* fabs fr1, fr3 */
1503  		o1 = OP_FRRR(c.oprrr(p.As), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
1504  
1505  	case 34: /* mov $con,fr ==> or/add $i,t; mov t,fr */
1506  		v := c.regoff(&p.From)
1507  		a := AADDU
1508  		if o.a1 == C_ANDCON {
1509  			a = AOR
1510  		}
1511  		o1 = OP_IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
1512  		o2 = OP_RRR(SP(2, 1)|(4<<21), uint32(REGTMP), uint32(0), uint32(p.To.Reg)) /* mtc1 */
1513  
1514  	case 35: /* mov r,lext/auto/oreg ==> sw o(REGTMP) */
1515  		v := c.regoff(&p.To)
1516  		r := int(p.To.Reg)
1517  		if r == 0 {
1518  			r = int(o.param)
1519  		}
1520  		o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
1521  		o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
1522  		o3 = OP_IRR(c.opirr(p.As), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
1523  
1524  	case 36: /* mov lext/auto/oreg,r ==> lw o(REGTMP) */
1525  		v := c.regoff(&p.From)
1526  		r := int(p.From.Reg)
1527  		if r == 0 {
1528  			r = int(o.param)
1529  		}
1530  		o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
1531  		o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
1532  		o3 = OP_IRR(c.opirr(-p.As), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
1533  
1534  	case 37: /* movw r,mr */
1535  		a := SP(2, 0) | (4 << 21) /* mtc0 */
1536  		if p.As == AMOVV {
1537  			a = SP(2, 0) | (5 << 21) /* dmtc0 */
1538  		}
1539  		o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
1540  
1541  	case 38: /* movw mr,r */
1542  		a := SP(2, 0) | (0 << 21) /* mfc0 */
1543  		if p.As == AMOVV {
1544  			a = SP(2, 0) | (1 << 21) /* dmfc0 */
1545  		}
1546  		o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
1547  
1548  	case 40: /* word */
1549  		o1 = uint32(c.regoff(&p.From))
1550  
1551  	case 41: /* movw f,fcr */
1552  		o1 = OP_RRR(SP(2, 1)|(6<<21), uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) /* mtcc1 */
1553  
1554  	case 42: /* movw fcr,r */
1555  		o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) /* mfcc1 */
1556  
1557  	case 47: /* movv r,fr */
1558  		a := SP(2, 1) | (5 << 21) /* dmtc1 */
1559  		o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
1560  
1561  	case 48: /* movv fr,r */
1562  		a := SP(2, 1) | (1 << 21) /* dmtc1 */
1563  		o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
1564  
1565  	case 49: /* undef */
1566  		o1 = 52 /* trap -- teq r0, r0 */
1567  
1568  	/* relocation operations */
1569  	case 50: /* mov r,addr ==> lu + add REGSB, REGTMP + sw o(REGTMP) */
1570  		o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP))
1571  		rel := obj.Addrel(c.cursym)
1572  		rel.Off = int32(c.pc)
1573  		rel.Siz = 4
1574  		rel.Sym = p.To.Sym
1575  		rel.Add = p.To.Offset
1576  		rel.Type = objabi.R_ADDRMIPSU
1577  		o2 = OP_IRR(c.opirr(p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
1578  		rel2 := obj.Addrel(c.cursym)
1579  		rel2.Off = int32(c.pc + 4)
1580  		rel2.Siz = 4
1581  		rel2.Sym = p.To.Sym
1582  		rel2.Add = p.To.Offset
1583  		rel2.Type = objabi.R_ADDRMIPS
1584  
1585  		if o.size == 12 {
1586  			o3 = o2
1587  			o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
1588  			rel2.Off += 4
1589  		}
1590  
1591  	case 51: /* mov addr,r ==> lu + add REGSB, REGTMP + lw o(REGTMP) */
1592  		o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP))
1593  		rel := obj.Addrel(c.cursym)
1594  		rel.Off = int32(c.pc)
1595  		rel.Siz = 4
1596  		rel.Sym = p.From.Sym
1597  		rel.Add = p.From.Offset
1598  		rel.Type = objabi.R_ADDRMIPSU
1599  		o2 = OP_IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
1600  		rel2 := obj.Addrel(c.cursym)
1601  		rel2.Off = int32(c.pc + 4)
1602  		rel2.Siz = 4
1603  		rel2.Sym = p.From.Sym
1604  		rel2.Add = p.From.Offset
1605  		rel2.Type = objabi.R_ADDRMIPS
1606  
1607  		if o.size == 12 {
1608  			o3 = o2
1609  			o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
1610  			rel2.Off += 4
1611  		}
1612  
1613  	case 52: /* mov $lext, r ==> lu + add REGSB, r + add */
1614  		// NOTE: this case does not use REGTMP. If it ever does,
1615  		// remove the NOTUSETMP flag in optab.
1616  		o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(p.To.Reg))
1617  		rel := obj.Addrel(c.cursym)
1618  		rel.Off = int32(c.pc)
1619  		rel.Siz = 4
1620  		rel.Sym = p.From.Sym
1621  		rel.Add = p.From.Offset
1622  		rel.Type = objabi.R_ADDRMIPSU
1623  		o2 = OP_IRR(c.opirr(add), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
1624  		rel2 := obj.Addrel(c.cursym)
1625  		rel2.Off = int32(c.pc + 4)
1626  		rel2.Siz = 4
1627  		rel2.Sym = p.From.Sym
1628  		rel2.Add = p.From.Offset
1629  		rel2.Type = objabi.R_ADDRMIPS
1630  
1631  		if o.size == 12 {
1632  			o3 = o2
1633  			o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(p.To.Reg), uint32(p.To.Reg))
1634  			rel2.Off += 4
1635  		}
1636  
1637  	case 53: /* mov r, tlsvar ==> rdhwr + sw o(r3) */
1638  		// clobbers R3 !
1639  		// load thread pointer with RDHWR, R3 is used for fast kernel emulation on Linux
1640  		// NOTE: this case does not use REGTMP. If it ever does,
1641  		// remove the NOTUSETMP flag in optab.
1642  		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
1643  		o2 = OP_IRR(c.opirr(p.As), uint32(0), uint32(REG_R3), uint32(p.From.Reg))
1644  		rel := obj.Addrel(c.cursym)
1645  		rel.Off = int32(c.pc + 4)
1646  		rel.Siz = 4
1647  		rel.Sym = p.To.Sym
1648  		rel.Add = p.To.Offset
1649  		rel.Type = objabi.R_ADDRMIPSTLS
1650  
1651  	case 54: /* mov tlsvar, r ==> rdhwr + lw o(r3) */
1652  		// clobbers R3 !
1653  		// NOTE: this case does not use REGTMP. If it ever does,
1654  		// remove the NOTUSETMP flag in optab.
1655  		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
1656  		o2 = OP_IRR(c.opirr(-p.As), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
1657  		rel := obj.Addrel(c.cursym)
1658  		rel.Off = int32(c.pc + 4)
1659  		rel.Siz = 4
1660  		rel.Sym = p.From.Sym
1661  		rel.Add = p.From.Offset
1662  		rel.Type = objabi.R_ADDRMIPSTLS
1663  
1664  	case 55: /* mov $tlsvar, r ==> rdhwr + add */
1665  		// clobbers R3 !
1666  		// NOTE: this case does not use REGTMP. If it ever does,
1667  		// remove the NOTUSETMP flag in optab.
1668  		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
1669  		o2 = OP_IRR(c.opirr(add), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
1670  		rel := obj.Addrel(c.cursym)
1671  		rel.Off = int32(c.pc + 4)
1672  		rel.Siz = 4
1673  		rel.Sym = p.From.Sym
1674  		rel.Add = p.From.Offset
1675  		rel.Type = objabi.R_ADDRMIPSTLS
1676  
1677  	case 56: /* vmov{b,h,w,d} $scon, wr */
1678  
1679  		v := c.regoff(&p.From)
1680  		o1 = OP_VI10(110, c.twobitdf(p.As), v, uint32(p.To.Reg), 7)
1681  
1682  	case 57: /* vld $soreg, wr */
1683  		v := c.lsoffset(p.As, c.regoff(&p.From))
1684  		o1 = OP_VMI10(v, uint32(p.From.Reg), uint32(p.To.Reg), 8, c.twobitdf(p.As))
1685  
1686  	case 58: /* vst wr, $soreg */
1687  		v := c.lsoffset(p.As, c.regoff(&p.To))
1688  		o1 = OP_VMI10(v, uint32(p.To.Reg), uint32(p.From.Reg), 9, c.twobitdf(p.As))
1689  	}
1690  
1691  	out[0] = o1
1692  	out[1] = o2
1693  	out[2] = o3
1694  	out[3] = o4
1695  }
1696  
1697  func (c *ctxt0) vregoff(a *obj.Addr) int64 {
1698  	c.instoffset = 0
1699  	c.aclass(a)
1700  	return c.instoffset
1701  }
1702  
1703  func (c *ctxt0) regoff(a *obj.Addr) int32 {
1704  	return int32(c.vregoff(a))
1705  }
1706  
1707  func (c *ctxt0) oprrr(a obj.As) uint32 {
1708  	switch a {
1709  	case AADD:
1710  		return OP(4, 0)
1711  	case AADDU:
1712  		return OP(4, 1)
1713  	case ASGT:
1714  		return OP(5, 2)
1715  	case ASGTU:
1716  		return OP(5, 3)
1717  	case AAND:
1718  		return OP(4, 4)
1719  	case AOR:
1720  		return OP(4, 5)
1721  	case AXOR:
1722  		return OP(4, 6)
1723  	case ASUB:
1724  		return OP(4, 2)
1725  	case ASUBU, ANEGW:
1726  		return OP(4, 3)
1727  	case ANOR:
1728  		return OP(4, 7)
1729  	case ASLL:
1730  		return OP(0, 4)
1731  	case ASRL:
1732  		return OP(0, 6)
1733  	case ASRA:
1734  		return OP(0, 7)
1735  	case ASLLV:
1736  		return OP(2, 4)
1737  	case ASRLV:
1738  		return OP(2, 6)
1739  	case ASRAV:
1740  		return OP(2, 7)
1741  	case AADDV:
1742  		return OP(5, 4)
1743  	case AADDVU:
1744  		return OP(5, 5)
1745  	case ASUBV:
1746  		return OP(5, 6)
1747  	case ASUBVU, ANEGV:
1748  		return OP(5, 7)
1749  	case AREM,
1750  		ADIV:
1751  		return OP(3, 2)
1752  	case AREMU,
1753  		ADIVU:
1754  		return OP(3, 3)
1755  	case AMUL:
1756  		return OP(3, 0)
1757  	case AMULU:
1758  		return OP(3, 1)
1759  	case AREMV,
1760  		ADIVV:
1761  		return OP(3, 6)
1762  	case AREMVU,
1763  		ADIVVU:
1764  		return OP(3, 7)
1765  	case AMULV:
1766  		return OP(3, 4)
1767  	case AMULVU:
1768  		return OP(3, 5)
1769  
1770  	case AJMP:
1771  		return OP(1, 0)
1772  	case AJAL:
1773  		return OP(1, 1)
1774  
1775  	case ABREAK:
1776  		return OP(1, 5)
1777  	case ASYSCALL:
1778  		return OP(1, 4)
1779  	case ATLBP:
1780  		return MMU(1, 0)
1781  	case ATLBR:
1782  		return MMU(0, 1)
1783  	case ATLBWI:
1784  		return MMU(0, 2)
1785  	case ATLBWR:
1786  		return MMU(0, 6)
1787  	case ARFE:
1788  		return MMU(2, 0)
1789  
1790  	case ADIVF:
1791  		return FPF(0, 3)
1792  	case ADIVD:
1793  		return FPD(0, 3)
1794  	case AMULF:
1795  		return FPF(0, 2)
1796  	case AMULD:
1797  		return FPD(0, 2)
1798  	case ASUBF:
1799  		return FPF(0, 1)
1800  	case ASUBD:
1801  		return FPD(0, 1)
1802  	case AADDF:
1803  		return FPF(0, 0)
1804  	case AADDD:
1805  		return FPD(0, 0)
1806  	case ATRUNCFV:
1807  		return FPF(1, 1)
1808  	case ATRUNCDV:
1809  		return FPD(1, 1)
1810  	case ATRUNCFW:
1811  		return FPF(1, 5)
1812  	case ATRUNCDW:
1813  		return FPD(1, 5)
1814  	case AMOVFV:
1815  		return FPF(4, 5)
1816  	case AMOVDV:
1817  		return FPD(4, 5)
1818  	case AMOVVF:
1819  		return FPV(4, 0)
1820  	case AMOVVD:
1821  		return FPV(4, 1)
1822  	case AMOVFW:
1823  		return FPF(4, 4)
1824  	case AMOVDW:
1825  		return FPD(4, 4)
1826  	case AMOVWF:
1827  		return FPW(4, 0)
1828  	case AMOVDF:
1829  		return FPD(4, 0)
1830  	case AMOVWD:
1831  		return FPW(4, 1)
1832  	case AMOVFD:
1833  		return FPF(4, 1)
1834  	case AABSF:
1835  		return FPF(0, 5)
1836  	case AABSD:
1837  		return FPD(0, 5)
1838  	case AMOVF:
1839  		return FPF(0, 6)
1840  	case AMOVD:
1841  		return FPD(0, 6)
1842  	case ANEGF:
1843  		return FPF(0, 7)
1844  	case ANEGD:
1845  		return FPD(0, 7)
1846  	case ACMPEQF:
1847  		return FPF(6, 2)
1848  	case ACMPEQD:
1849  		return FPD(6, 2)
1850  	case ACMPGTF:
1851  		return FPF(7, 4)
1852  	case ACMPGTD:
1853  		return FPD(7, 4)
1854  	case ACMPGEF:
1855  		return FPF(7, 6)
1856  	case ACMPGED:
1857  		return FPD(7, 6)
1858  
1859  	case ASQRTF:
1860  		return FPF(0, 4)
1861  	case ASQRTD:
1862  		return FPD(0, 4)
1863  
1864  	case ASYNC:
1865  		return OP(1, 7)
1866  	case ANOOP:
1867  		return 0
1868  
1869  	case ACMOVN:
1870  		return OP(1, 3)
1871  	case ACMOVZ:
1872  		return OP(1, 2)
1873  	case ACMOVT:
1874  		return OP(0, 1) | (1 << 16)
1875  	case ACMOVF:
1876  		return OP(0, 1) | (0 << 16)
1877  	case ACLO:
1878  		return SP(3, 4) | OP(4, 1)
1879  	case ACLZ:
1880  		return SP(3, 4) | OP(4, 0)
1881  	case AMADD:
1882  		return SP(3, 4) | OP(0, 0)
1883  	case AMSUB:
1884  		return SP(3, 4) | OP(0, 4)
1885  	}
1886  
1887  	if a < 0 {
1888  		c.ctxt.Diag("bad rrr opcode -%v", -a)
1889  	} else {
1890  		c.ctxt.Diag("bad rrr opcode %v", a)
1891  	}
1892  	return 0
1893  }
1894  
1895  func (c *ctxt0) opirr(a obj.As) uint32 {
1896  	switch a {
1897  	case AADD:
1898  		return SP(1, 0)
1899  	case AADDU:
1900  		return SP(1, 1)
1901  	case ASGT:
1902  		return SP(1, 2)
1903  	case ASGTU:
1904  		return SP(1, 3)
1905  	case AAND:
1906  		return SP(1, 4)
1907  	case AOR:
1908  		return SP(1, 5)
1909  	case AXOR:
1910  		return SP(1, 6)
1911  	case ALUI:
1912  		return SP(1, 7)
1913  	case ASLL:
1914  		return OP(0, 0)
1915  	case ASRL:
1916  		return OP(0, 2)
1917  	case ASRA:
1918  		return OP(0, 3)
1919  	case AADDV:
1920  		return SP(3, 0)
1921  	case AADDVU:
1922  		return SP(3, 1)
1923  
1924  	case AJMP:
1925  		return SP(0, 2)
1926  	case AJAL,
1927  		obj.ADUFFZERO,
1928  		obj.ADUFFCOPY:
1929  		return SP(0, 3)
1930  	case ABEQ:
1931  		return SP(0, 4)
1932  	case -ABEQ:
1933  		return SP(2, 4) /* likely */
1934  	case ABNE:
1935  		return SP(0, 5)
1936  	case -ABNE:
1937  		return SP(2, 5) /* likely */
1938  	case ABGEZ:
1939  		return SP(0, 1) | BCOND(0, 1)
1940  	case -ABGEZ:
1941  		return SP(0, 1) | BCOND(0, 3) /* likely */
1942  	case ABGEZAL:
1943  		return SP(0, 1) | BCOND(2, 1)
1944  	case -ABGEZAL:
1945  		return SP(0, 1) | BCOND(2, 3) /* likely */
1946  	case ABGTZ:
1947  		return SP(0, 7)
1948  	case -ABGTZ:
1949  		return SP(2, 7) /* likely */
1950  	case ABLEZ:
1951  		return SP(0, 6)
1952  	case -ABLEZ:
1953  		return SP(2, 6) /* likely */
1954  	case ABLTZ:
1955  		return SP(0, 1) | BCOND(0, 0)
1956  	case -ABLTZ:
1957  		return SP(0, 1) | BCOND(0, 2) /* likely */
1958  	case ABLTZAL:
1959  		return SP(0, 1) | BCOND(2, 0)
1960  	case -ABLTZAL:
1961  		return SP(0, 1) | BCOND(2, 2) /* likely */
1962  	case ABFPT:
1963  		return SP(2, 1) | (257 << 16)
1964  	case -ABFPT:
1965  		return SP(2, 1) | (259 << 16) /* likely */
1966  	case ABFPF:
1967  		return SP(2, 1) | (256 << 16)
1968  	case -ABFPF:
1969  		return SP(2, 1) | (258 << 16) /* likely */
1970  
1971  	case AMOVB,
1972  		AMOVBU:
1973  		return SP(5, 0)
1974  	case AMOVH,
1975  		AMOVHU:
1976  		return SP(5, 1)
1977  	case AMOVW,
1978  		AMOVWU:
1979  		return SP(5, 3)
1980  	case AMOVV:
1981  		return SP(7, 7)
1982  	case AMOVF:
1983  		return SP(7, 1)
1984  	case AMOVD:
1985  		return SP(7, 5)
1986  	case AMOVWL:
1987  		return SP(5, 2)
1988  	case AMOVWR:
1989  		return SP(5, 6)
1990  	case AMOVVL:
1991  		return SP(5, 4)
1992  	case AMOVVR:
1993  		return SP(5, 5)
1994  
1995  	case ABREAK:
1996  		return SP(5, 7)
1997  
1998  	case -AMOVWL:
1999  		return SP(4, 2)
2000  	case -AMOVWR:
2001  		return SP(4, 6)
2002  	case -AMOVVL:
2003  		return SP(3, 2)
2004  	case -AMOVVR:
2005  		return SP(3, 3)
2006  	case -AMOVB:
2007  		return SP(4, 0)
2008  	case -AMOVBU:
2009  		return SP(4, 4)
2010  	case -AMOVH:
2011  		return SP(4, 1)
2012  	case -AMOVHU:
2013  		return SP(4, 5)
2014  	case -AMOVW:
2015  		return SP(4, 3)
2016  	case -AMOVWU:
2017  		return SP(4, 7)
2018  	case -AMOVV:
2019  		return SP(6, 7)
2020  	case -AMOVF:
2021  		return SP(6, 1)
2022  	case -AMOVD:
2023  		return SP(6, 5)
2024  
2025  	case ASLLV:
2026  		return OP(7, 0)
2027  	case ASRLV:
2028  		return OP(7, 2)
2029  	case ASRAV:
2030  		return OP(7, 3)
2031  	case -ASLLV:
2032  		return OP(7, 4)
2033  	case -ASRLV:
2034  		return OP(7, 6)
2035  	case -ASRAV:
2036  		return OP(7, 7)
2037  
2038  	case ATEQ:
2039  		return OP(6, 4)
2040  	case ATNE:
2041  		return OP(6, 6)
2042  	case -ALL:
2043  		return SP(6, 0)
2044  	case -ALLV:
2045  		return SP(6, 4)
2046  	case ASC:
2047  		return SP(7, 0)
2048  	case ASCV:
2049  		return SP(7, 4)
2050  	}
2051  
2052  	if a < 0 {
2053  		c.ctxt.Diag("bad irr opcode -%v", -a)
2054  	} else {
2055  		c.ctxt.Diag("bad irr opcode %v", a)
2056  	}
2057  	return 0
2058  }
2059  
2060  func vshift(a obj.As) bool {
2061  	switch a {
2062  	case ASLLV,
2063  		ASRLV,
2064  		ASRAV:
2065  		return true
2066  	}
2067  	return false
2068  }
2069  
2070  // MSA Two-bit Data Format Field Encoding
2071  func (c *ctxt0) twobitdf(a obj.As) uint32 {
2072  	switch a {
2073  	case AVMOVB:
2074  		return 0
2075  	case AVMOVH:
2076  		return 1
2077  	case AVMOVW:
2078  		return 2
2079  	case AVMOVD:
2080  		return 3
2081  	default:
2082  		c.ctxt.Diag("unsupported data format %v", a)
2083  	}
2084  	return 0
2085  }
2086  
2087  // MSA Load/Store offset have to be multiple of size of data format
2088  func (c *ctxt0) lsoffset(a obj.As, o int32) int32 {
2089  	var mod int32
2090  	switch a {
2091  	case AVMOVB:
2092  		mod = 1
2093  	case AVMOVH:
2094  		mod = 2
2095  	case AVMOVW:
2096  		mod = 4
2097  	case AVMOVD:
2098  		mod = 8
2099  	default:
2100  		c.ctxt.Diag("unsupported instruction:%v", a)
2101  	}
2102  
2103  	if o%mod != 0 {
2104  		c.ctxt.Diag("invalid offset for %v: %d is not a multiple of %d", a, o, mod)
2105  	}
2106  
2107  	return o / mod
2108  }
2109