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", 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  		if p.From.Reg == REGTMP {
  1512  			c.ctxt.Diag("cannot store REGTMP to large offset (REGTMP needed for address materialization): %v", p)
  1513  		}
  1514  		v := c.regoff(&p.To)
  1515  		o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), REGZERO, REGTMP)
  1516  		o2 = OP_RRR(c.oprrr(add), r, REGTMP, REGTMP)
  1517  		o3 = OP_IRR(c.opirr(p.As), uint32(v), REGTMP, p.From.Reg)
  1518  
  1519  	case 36: /* mov lext/auto/oreg,r ==> lw o(REGTMP) */
  1520  		r := p.From.Reg
  1521  		if r == obj.REG_NONE {
  1522  			r = o.param
  1523  		}
  1524  		v := c.regoff(&p.From)
  1525  		o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), REGZERO, REGTMP)
  1526  		o2 = OP_RRR(c.oprrr(add), r, REGTMP, REGTMP)
  1527  		o3 = OP_IRR(c.opirr(-p.As), uint32(v), REGTMP, p.To.Reg)
  1528  
  1529  	case 37: /* movw r,mr */
  1530  		a := SP(2, 0) | (4 << 21) /* mtc0 */
  1531  		if p.As == AMOVV {
  1532  			a = SP(2, 0) | (5 << 21) /* dmtc0 */
  1533  		}
  1534  		o1 = OP_RRR(a, p.From.Reg, obj.REG_NONE, p.To.Reg)
  1535  
  1536  	case 38: /* movw mr,r */
  1537  		a := SP(2, 0) | (0 << 21) /* mfc0 */
  1538  		if p.As == AMOVV {
  1539  			a = SP(2, 0) | (1 << 21) /* dmfc0 */
  1540  		}
  1541  		o1 = OP_RRR(a, p.To.Reg, obj.REG_NONE, p.From.Reg)
  1542  
  1543  	case 40: /* word */
  1544  		o1 = uint32(c.regoff(&p.From))
  1545  
  1546  	case 41: /* movw f,fcr */
  1547  		o1 = OP_RRR(SP(2, 1)|(6<<21), p.From.Reg, obj.REG_NONE, p.To.Reg) /* mtcc1 */
  1548  
  1549  	case 42: /* movw fcr,r */
  1550  		o1 = OP_RRR(SP(2, 1)|(2<<21), p.To.Reg, obj.REG_NONE, p.From.Reg) /* mfcc1 */
  1551  
  1552  	case 47: /* movv r,fr */
  1553  		a := SP(2, 1) | (5 << 21) /* dmtc1 */
  1554  		o1 = OP_RRR(a, p.From.Reg, obj.REG_NONE, p.To.Reg)
  1555  
  1556  	case 48: /* movv fr,r */
  1557  		a := SP(2, 1) | (1 << 21) /* dmtc1 */
  1558  		o1 = OP_RRR(a, p.To.Reg, obj.REG_NONE, p.From.Reg)
  1559  
  1560  	case 49: /* undef */
  1561  		o1 = 52 /* trap -- teq r0, r0 */
  1562  
  1563  	/* relocation operations */
  1564  	case 50: /* mov r,addr ==> lu + add REGSB, REGTMP + sw o(REGTMP) */
  1565  		o1 = OP_IRR(c.opirr(ALUI), 0, REGZERO, REGTMP)
  1566  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  1567  			Type: objabi.R_ADDRMIPSU,
  1568  			Off:  int32(c.pc),
  1569  			Siz:  4,
  1570  			Sym:  p.To.Sym,
  1571  			Add:  p.To.Offset,
  1572  		})
  1573  
  1574  		o2 = OP_IRR(c.opirr(p.As), 0, REGTMP, p.From.Reg)
  1575  		off := int32(c.pc + 4)
  1576  		if o.size == 12 {
  1577  			o3 = o2
  1578  			o2 = OP_RRR(c.oprrr(AADDVU), REGSB, REGTMP, REGTMP)
  1579  			off += 4
  1580  		}
  1581  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  1582  			Type: objabi.R_ADDRMIPS,
  1583  			Off:  off,
  1584  			Siz:  4,
  1585  			Sym:  p.To.Sym,
  1586  			Add:  p.To.Offset,
  1587  		})
  1588  
  1589  	case 51: /* mov addr,r ==> lu + add REGSB, REGTMP + lw o(REGTMP) */
  1590  		o1 = OP_IRR(c.opirr(ALUI), 0, REGZERO, REGTMP)
  1591  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  1592  			Type: objabi.R_ADDRMIPSU,
  1593  			Off:  int32(c.pc),
  1594  			Siz:  4,
  1595  			Sym:  p.From.Sym,
  1596  			Add:  p.From.Offset,
  1597  		})
  1598  
  1599  		o2 = OP_IRR(c.opirr(-p.As), 0, REGTMP, p.To.Reg)
  1600  		off := int32(c.pc + 4)
  1601  		if o.size == 12 {
  1602  			o3 = o2
  1603  			o2 = OP_RRR(c.oprrr(AADDVU), REGSB, REGTMP, REGTMP)
  1604  			off += 4
  1605  		}
  1606  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  1607  			Type: objabi.R_ADDRMIPS,
  1608  			Off:  off,
  1609  			Siz:  4,
  1610  			Sym:  p.From.Sym,
  1611  			Add:  p.From.Offset,
  1612  		})
  1613  
  1614  	case 52: /* mov $lext, r ==> lu + add REGSB, r + add */
  1615  		// NOTE: this case does not use REGTMP. If it ever does,
  1616  		// remove the NOTUSETMP flag in optab.
  1617  		o1 = OP_IRR(c.opirr(ALUI), 0, REGZERO, p.To.Reg)
  1618  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  1619  			Type: objabi.R_ADDRMIPSU,
  1620  			Off:  int32(c.pc),
  1621  			Siz:  4,
  1622  			Sym:  p.From.Sym,
  1623  			Add:  p.From.Offset,
  1624  		})
  1625  
  1626  		o2 = OP_IRR(c.opirr(add), 0, p.To.Reg, p.To.Reg)
  1627  		off := int32(c.pc + 4)
  1628  		if o.size == 12 {
  1629  			o3 = o2
  1630  			o2 = OP_RRR(c.oprrr(AADDVU), REGSB, p.To.Reg, p.To.Reg)
  1631  			off += 4
  1632  		}
  1633  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  1634  			Type: objabi.R_ADDRMIPS,
  1635  			Off:  off,
  1636  			Siz:  4,
  1637  			Sym:  p.From.Sym,
  1638  			Add:  p.From.Offset,
  1639  		})
  1640  
  1641  	case 53: /* mov r, tlsvar ==> rdhwr + sw o(r3) */
  1642  		// clobbers R3 !
  1643  		// load thread pointer with RDHWR, R3 is used for fast kernel emulation on Linux
  1644  		// NOTE: this case does not use REGTMP. If it ever does,
  1645  		// remove the NOTUSETMP flag in optab.
  1646  		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
  1647  		o2 = OP_IRR(c.opirr(p.As), 0, REG_R3, p.From.Reg)
  1648  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  1649  			Type: objabi.R_ADDRMIPSTLS,
  1650  			Off:  int32(c.pc + 4),
  1651  			Siz:  4,
  1652  			Sym:  p.To.Sym,
  1653  			Add:  p.To.Offset,
  1654  		})
  1655  
  1656  	case 54: /* mov tlsvar, r ==> rdhwr + lw o(r3) */
  1657  		// clobbers R3 !
  1658  		// NOTE: this case does not use REGTMP. If it ever does,
  1659  		// remove the NOTUSETMP flag in optab.
  1660  		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
  1661  		o2 = OP_IRR(c.opirr(-p.As), 0, REG_R3, p.To.Reg)
  1662  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  1663  			Type: objabi.R_ADDRMIPSTLS,
  1664  			Off:  int32(c.pc + 4),
  1665  			Siz:  4,
  1666  			Sym:  p.From.Sym,
  1667  			Add:  p.From.Offset,
  1668  		})
  1669  
  1670  	case 55: /* mov $tlsvar, r ==> rdhwr + add */
  1671  		// clobbers R3 !
  1672  		// NOTE: this case does not use REGTMP. If it ever does,
  1673  		// remove the NOTUSETMP flag in optab.
  1674  		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
  1675  		o2 = OP_IRR(c.opirr(add), 0, REG_R3, p.To.Reg)
  1676  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  1677  			Type: objabi.R_ADDRMIPSTLS,
  1678  			Off:  int32(c.pc + 4),
  1679  			Siz:  4,
  1680  			Sym:  p.From.Sym,
  1681  			Add:  p.From.Offset,
  1682  		})
  1683  
  1684  	case 56: /* vmov{b,h,w,d} $scon, wr */
  1685  
  1686  		v := c.regoff(&p.From)
  1687  		o1 = OP_VI10(110, c.twobitdf(p.As), v, uint32(p.To.Reg), 7)
  1688  
  1689  	case 57: /* vld $soreg, wr */
  1690  		v := c.lsoffset(p.As, c.regoff(&p.From))
  1691  		o1 = OP_VMI10(v, uint32(p.From.Reg), uint32(p.To.Reg), 8, c.twobitdf(p.As))
  1692  
  1693  	case 58: /* vst wr, $soreg */
  1694  		v := c.lsoffset(p.As, c.regoff(&p.To))
  1695  		o1 = OP_VMI10(v, uint32(p.To.Reg), uint32(p.From.Reg), 9, c.twobitdf(p.As))
  1696  
  1697  	case 59:
  1698  		o1 = OP_RRR(c.oprrr(p.As), p.From.Reg, REGZERO, p.To.Reg)
  1699  	}
  1700  
  1701  	out[0] = o1
  1702  	out[1] = o2
  1703  	out[2] = o3
  1704  	out[3] = o4
  1705  }
  1706  
  1707  func (c *ctxt0) vregoff(a *obj.Addr) int64 {
  1708  	c.instoffset = 0
  1709  	c.aclass(a)
  1710  	return c.instoffset
  1711  }
  1712  
  1713  func (c *ctxt0) regoff(a *obj.Addr) int32 {
  1714  	return int32(c.vregoff(a))
  1715  }
  1716  
  1717  func (c *ctxt0) oprrr(a obj.As) uint32 {
  1718  	switch a {
  1719  	case AADD:
  1720  		return OP(4, 0)
  1721  	case AADDU:
  1722  		return OP(4, 1)
  1723  	case ASGT:
  1724  		return OP(5, 2)
  1725  	case ASGTU:
  1726  		return OP(5, 3)
  1727  	case AAND:
  1728  		return OP(4, 4)
  1729  	case AOR:
  1730  		return OP(4, 5)
  1731  	case AXOR:
  1732  		return OP(4, 6)
  1733  	case ASUB:
  1734  		return OP(4, 2)
  1735  	case ASUBU, ANEGW:
  1736  		return OP(4, 3)
  1737  	case ANOR:
  1738  		return OP(4, 7)
  1739  	case ASLL:
  1740  		return OP(0, 4)
  1741  	case ASRL:
  1742  		return OP(0, 6)
  1743  	case ASRA:
  1744  		return OP(0, 7)
  1745  	case AROTR:
  1746  		return OP(8, 6)
  1747  	case ASLLV:
  1748  		return OP(2, 4)
  1749  	case ASRLV:
  1750  		return OP(2, 6)
  1751  	case ASRAV:
  1752  		return OP(2, 7)
  1753  	case AROTRV:
  1754  		return OP(10, 6)
  1755  	case AADDV:
  1756  		return OP(5, 4)
  1757  	case AADDVU:
  1758  		return OP(5, 5)
  1759  	case ASUBV:
  1760  		return OP(5, 6)
  1761  	case ASUBVU, ANEGV:
  1762  		return OP(5, 7)
  1763  	case AREM,
  1764  		ADIV:
  1765  		return OP(3, 2)
  1766  	case AREMU,
  1767  		ADIVU:
  1768  		return OP(3, 3)
  1769  	case AMUL:
  1770  		return OP(3, 0)
  1771  	case AMULU:
  1772  		return OP(3, 1)
  1773  	case AREMV,
  1774  		ADIVV:
  1775  		return OP(3, 6)
  1776  	case AREMVU,
  1777  		ADIVVU:
  1778  		return OP(3, 7)
  1779  	case AMULV:
  1780  		return OP(3, 4)
  1781  	case AMULVU:
  1782  		return OP(3, 5)
  1783  
  1784  	case AJMP:
  1785  		return OP(1, 0)
  1786  	case AJAL:
  1787  		return OP(1, 1)
  1788  
  1789  	case ABREAK:
  1790  		return OP(1, 5)
  1791  	case ASYSCALL:
  1792  		return OP(1, 4)
  1793  	case ATLBP:
  1794  		return MMU(1, 0)
  1795  	case ATLBR:
  1796  		return MMU(0, 1)
  1797  	case ATLBWI:
  1798  		return MMU(0, 2)
  1799  	case ATLBWR:
  1800  		return MMU(0, 6)
  1801  	case ARFE:
  1802  		return MMU(2, 0)
  1803  
  1804  	case ADIVF:
  1805  		return FPF(0, 3)
  1806  	case ADIVD:
  1807  		return FPD(0, 3)
  1808  	case AMULF:
  1809  		return FPF(0, 2)
  1810  	case AMULD:
  1811  		return FPD(0, 2)
  1812  	case ASUBF:
  1813  		return FPF(0, 1)
  1814  	case ASUBD:
  1815  		return FPD(0, 1)
  1816  	case AADDF:
  1817  		return FPF(0, 0)
  1818  	case AADDD:
  1819  		return FPD(0, 0)
  1820  	case ATRUNCFV:
  1821  		return FPF(1, 1)
  1822  	case ATRUNCDV:
  1823  		return FPD(1, 1)
  1824  	case ATRUNCFW:
  1825  		return FPF(1, 5)
  1826  	case ATRUNCDW:
  1827  		return FPD(1, 5)
  1828  	case AMOVFV:
  1829  		return FPF(4, 5)
  1830  	case AMOVDV:
  1831  		return FPD(4, 5)
  1832  	case AMOVVF:
  1833  		return FPV(4, 0)
  1834  	case AMOVVD:
  1835  		return FPV(4, 1)
  1836  	case AMOVFW:
  1837  		return FPF(4, 4)
  1838  	case AMOVDW:
  1839  		return FPD(4, 4)
  1840  	case AMOVWF:
  1841  		return FPW(4, 0)
  1842  	case AMOVDF:
  1843  		return FPD(4, 0)
  1844  	case AMOVWD:
  1845  		return FPW(4, 1)
  1846  	case AMOVFD:
  1847  		return FPF(4, 1)
  1848  	case AABSF:
  1849  		return FPF(0, 5)
  1850  	case AABSD:
  1851  		return FPD(0, 5)
  1852  	case AMOVF:
  1853  		return FPF(0, 6)
  1854  	case AMOVD:
  1855  		return FPD(0, 6)
  1856  	case ANEGF:
  1857  		return FPF(0, 7)
  1858  	case ANEGD:
  1859  		return FPD(0, 7)
  1860  	case ACMPEQF:
  1861  		return FPF(6, 2)
  1862  	case ACMPEQD:
  1863  		return FPD(6, 2)
  1864  	case ACMPGTF:
  1865  		return FPF(7, 4)
  1866  	case ACMPGTD:
  1867  		return FPD(7, 4)
  1868  	case ACMPGEF:
  1869  		return FPF(7, 6)
  1870  	case ACMPGED:
  1871  		return FPD(7, 6)
  1872  
  1873  	case ASQRTF:
  1874  		return FPF(0, 4)
  1875  	case ASQRTD:
  1876  		return FPD(0, 4)
  1877  
  1878  	case ASYNC:
  1879  		return OP(1, 7)
  1880  	case ANOOP:
  1881  		return 0
  1882  
  1883  	case ACMOVN:
  1884  		return OP(1, 3)
  1885  	case ACMOVZ:
  1886  		return OP(1, 2)
  1887  	case ACMOVT:
  1888  		return OP(0, 1) | (1 << 16)
  1889  	case ACMOVF:
  1890  		return OP(0, 1) | (0 << 16)
  1891  	case ACLO:
  1892  		return SP(3, 4) | OP(4, 1)
  1893  	case ACLZ:
  1894  		return SP(3, 4) | OP(4, 0)
  1895  	case AMADD:
  1896  		return SP(3, 4) | OP(0, 0)
  1897  	case AMSUB:
  1898  		return SP(3, 4) | OP(0, 4)
  1899  	case AWSBH:
  1900  		return SP(3, 7) | OP(20, 0)
  1901  	case ADSBH:
  1902  		return SP(3, 7) | OP(20, 4)
  1903  	case ADSHD:
  1904  		return SP(3, 7) | OP(44, 4)
  1905  	case ASEB:
  1906  		return SP(3, 7) | OP(132, 0)
  1907  	case ASEH:
  1908  		return SP(3, 7) | OP(196, 0)
  1909  	}
  1910  
  1911  	if a < 0 {
  1912  		c.ctxt.Diag("bad rrr opcode -%v", -a)
  1913  	} else {
  1914  		c.ctxt.Diag("bad rrr opcode %v", a)
  1915  	}
  1916  	return 0
  1917  }
  1918  
  1919  func (c *ctxt0) opirr(a obj.As) uint32 {
  1920  	switch a {
  1921  	case AADD:
  1922  		return SP(1, 0)
  1923  	case AADDU:
  1924  		return SP(1, 1)
  1925  	case ASGT:
  1926  		return SP(1, 2)
  1927  	case ASGTU:
  1928  		return SP(1, 3)
  1929  	case AAND:
  1930  		return SP(1, 4)
  1931  	case AOR:
  1932  		return SP(1, 5)
  1933  	case AXOR:
  1934  		return SP(1, 6)
  1935  	case ALUI:
  1936  		return SP(1, 7)
  1937  	case ASLL:
  1938  		return OP(0, 0)
  1939  	case ASRL:
  1940  		return OP(0, 2)
  1941  	case ASRA:
  1942  		return OP(0, 3)
  1943  	case AROTR:
  1944  		return OP(0, 2) | 1<<21
  1945  	case AADDV:
  1946  		return SP(3, 0)
  1947  	case AADDVU:
  1948  		return SP(3, 1)
  1949  
  1950  	case AJMP:
  1951  		return SP(0, 2)
  1952  	case AJAL,
  1953  		obj.ADUFFZERO,
  1954  		obj.ADUFFCOPY:
  1955  		return SP(0, 3)
  1956  	case ABEQ:
  1957  		return SP(0, 4)
  1958  	case -ABEQ:
  1959  		return SP(2, 4) /* likely */
  1960  	case ABNE:
  1961  		return SP(0, 5)
  1962  	case -ABNE:
  1963  		return SP(2, 5) /* likely */
  1964  	case ABGEZ:
  1965  		return SP(0, 1) | BCOND(0, 1)
  1966  	case -ABGEZ:
  1967  		return SP(0, 1) | BCOND(0, 3) /* likely */
  1968  	case ABGEZAL:
  1969  		return SP(0, 1) | BCOND(2, 1)
  1970  	case -ABGEZAL:
  1971  		return SP(0, 1) | BCOND(2, 3) /* likely */
  1972  	case ABGTZ:
  1973  		return SP(0, 7)
  1974  	case -ABGTZ:
  1975  		return SP(2, 7) /* likely */
  1976  	case ABLEZ:
  1977  		return SP(0, 6)
  1978  	case -ABLEZ:
  1979  		return SP(2, 6) /* likely */
  1980  	case ABLTZ:
  1981  		return SP(0, 1) | BCOND(0, 0)
  1982  	case -ABLTZ:
  1983  		return SP(0, 1) | BCOND(0, 2) /* likely */
  1984  	case ABLTZAL:
  1985  		return SP(0, 1) | BCOND(2, 0)
  1986  	case -ABLTZAL:
  1987  		return SP(0, 1) | BCOND(2, 2) /* likely */
  1988  	case ABFPT:
  1989  		return SP(2, 1) | (257 << 16)
  1990  	case -ABFPT:
  1991  		return SP(2, 1) | (259 << 16) /* likely */
  1992  	case ABFPF:
  1993  		return SP(2, 1) | (256 << 16)
  1994  	case -ABFPF:
  1995  		return SP(2, 1) | (258 << 16) /* likely */
  1996  
  1997  	case AMOVB,
  1998  		AMOVBU:
  1999  		return SP(5, 0)
  2000  	case AMOVH,
  2001  		AMOVHU:
  2002  		return SP(5, 1)
  2003  	case AMOVW,
  2004  		AMOVWU:
  2005  		return SP(5, 3)
  2006  	case AMOVV:
  2007  		return SP(7, 7)
  2008  	case AMOVF:
  2009  		return SP(7, 1)
  2010  	case AMOVD:
  2011  		return SP(7, 5)
  2012  	case AMOVWL:
  2013  		return SP(5, 2)
  2014  	case AMOVWR:
  2015  		return SP(5, 6)
  2016  	case AMOVVL:
  2017  		return SP(5, 4)
  2018  	case AMOVVR:
  2019  		return SP(5, 5)
  2020  
  2021  	case ABREAK:
  2022  		return SP(5, 7)
  2023  
  2024  	case -AMOVWL:
  2025  		return SP(4, 2)
  2026  	case -AMOVWR:
  2027  		return SP(4, 6)
  2028  	case -AMOVVL:
  2029  		return SP(3, 2)
  2030  	case -AMOVVR:
  2031  		return SP(3, 3)
  2032  	case -AMOVB:
  2033  		return SP(4, 0)
  2034  	case -AMOVBU:
  2035  		return SP(4, 4)
  2036  	case -AMOVH:
  2037  		return SP(4, 1)
  2038  	case -AMOVHU:
  2039  		return SP(4, 5)
  2040  	case -AMOVW:
  2041  		return SP(4, 3)
  2042  	case -AMOVWU:
  2043  		return SP(4, 7)
  2044  	case -AMOVV:
  2045  		return SP(6, 7)
  2046  	case -AMOVF:
  2047  		return SP(6, 1)
  2048  	case -AMOVD:
  2049  		return SP(6, 5)
  2050  
  2051  	case ASLLV:
  2052  		return OP(7, 0)
  2053  	case ASRLV:
  2054  		return OP(7, 2)
  2055  	case ASRAV:
  2056  		return OP(7, 3)
  2057  	case AROTRV:
  2058  		return OP(7, 2) | 1<<21
  2059  	case -ASLLV:
  2060  		return OP(7, 4)
  2061  	case -ASRLV:
  2062  		return OP(7, 6)
  2063  	case -ASRAV:
  2064  		return OP(7, 7)
  2065  	case -AROTRV:
  2066  		return OP(7, 6) | 1<<21
  2067  
  2068  	case ATEQ:
  2069  		return OP(6, 4)
  2070  	case ATNE:
  2071  		return OP(6, 6)
  2072  	case -ALL:
  2073  		return SP(6, 0)
  2074  	case -ALLV:
  2075  		return SP(6, 4)
  2076  	case ASC:
  2077  		return SP(7, 0)
  2078  	case ASCV:
  2079  		return SP(7, 4)
  2080  	}
  2081  
  2082  	if a < 0 {
  2083  		c.ctxt.Diag("bad irr opcode -%v", -a)
  2084  	} else {
  2085  		c.ctxt.Diag("bad irr opcode %v", a)
  2086  	}
  2087  	return 0
  2088  }
  2089  
  2090  func vshift(a obj.As) bool {
  2091  	switch a {
  2092  	case ASLLV,
  2093  		ASRLV,
  2094  		ASRAV,
  2095  		AROTRV:
  2096  		return true
  2097  	}
  2098  	return false
  2099  }
  2100  
  2101  // MSA Two-bit Data Format Field Encoding
  2102  func (c *ctxt0) twobitdf(a obj.As) uint32 {
  2103  	switch a {
  2104  	case AVMOVB:
  2105  		return 0
  2106  	case AVMOVH:
  2107  		return 1
  2108  	case AVMOVW:
  2109  		return 2
  2110  	case AVMOVD:
  2111  		return 3
  2112  	default:
  2113  		c.ctxt.Diag("unsupported data format %v", a)
  2114  	}
  2115  	return 0
  2116  }
  2117  
  2118  // MSA Load/Store offset have to be multiple of size of data format
  2119  func (c *ctxt0) lsoffset(a obj.As, o int32) int32 {
  2120  	var mod int32
  2121  	switch a {
  2122  	case AVMOVB:
  2123  		mod = 1
  2124  	case AVMOVH:
  2125  		mod = 2
  2126  	case AVMOVW:
  2127  		mod = 4
  2128  	case AVMOVD:
  2129  		mod = 8
  2130  	default:
  2131  		c.ctxt.Diag("unsupported instruction:%v", a)
  2132  	}
  2133  
  2134  	if o%mod != 0 {
  2135  		c.ctxt.Diag("invalid offset for %v: %d is not a multiple of %d", a, o, mod)
  2136  	}
  2137  
  2138  	return o / mod
  2139  }
  2140  

View as plain text