Black Lives Matter. Support the Equal Justice Initiative.

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

Documentation: cmd/internal/obj/mips

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

View as plain text