gtsocial-umbx

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

asm0.go (55517B)


      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 }