github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/obj/mips/asm0.go (about)

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