Source file src/cmd/internal/obj/mips/asm0.go

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

View as plain text