...

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  	{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  type ocmp []Optab
   879  
   880  func (x ocmp) Len() int {
   881  	return len(x)
   882  }
   883  
   884  func (x ocmp) Swap(i, j int) {
   885  	x[i], x[j] = x[j], x[i]
   886  }
   887  
   888  func (x ocmp) Less(i, j int) bool {
   889  	p1 := &x[i]
   890  	p2 := &x[j]
   891  	n := int(p1.as) - int(p2.as)
   892  	if n != 0 {
   893  		return n < 0
   894  	}
   895  	n = int(p1.a1) - int(p2.a1)
   896  	if n != 0 {
   897  		return n < 0
   898  	}
   899  	n = int(p1.a2) - int(p2.a2)
   900  	if n != 0 {
   901  		return n < 0
   902  	}
   903  	n = int(p1.a3) - int(p2.a3)
   904  	if n != 0 {
   905  		return n < 0
   906  	}
   907  	return false
   908  }
   909  
   910  func opset(a, b0 obj.As) {
   911  	oprange[a&obj.AMask] = oprange[b0]
   912  }
   913  
   914  func buildop(ctxt *obj.Link) {
   915  	if oprange[AOR&obj.AMask] != nil {
   916  		// Already initialized; stop now.
   917  		// This happens in the cmd/asm tests,
   918  		// each of which re-initializes the arch.
   919  		return
   920  	}
   921  
   922  	var n int
   923  
   924  	for i := 0; i < C_NCLASS; i++ {
   925  		for n = 0; n < C_NCLASS; n++ {
   926  			if cmp(n, i) {
   927  				xcmp[i][n] = true
   928  			}
   929  		}
   930  	}
   931  	for n = 0; optab[n].as != obj.AXXX; n++ {
   932  	}
   933  	sort.Sort(ocmp(optab[:n]))
   934  	for i := 0; i < n; i++ {
   935  		r := optab[i].as
   936  		r0 := r & obj.AMask
   937  		start := i
   938  		for optab[i].as == r {
   939  			i++
   940  		}
   941  		oprange[r0] = optab[start:i]
   942  		i--
   943  
   944  		switch r {
   945  		default:
   946  			ctxt.Diag("unknown op in build: %v", r)
   947  			ctxt.DiagFlush()
   948  			log.Fatalf("bad code")
   949  
   950  		case AABSF:
   951  			opset(AMOVFD, r0)
   952  			opset(AMOVDF, r0)
   953  			opset(AMOVWF, r0)
   954  			opset(AMOVFW, r0)
   955  			opset(AMOVWD, r0)
   956  			opset(AMOVDW, r0)
   957  			opset(ANEGF, r0)
   958  			opset(ANEGD, r0)
   959  			opset(AABSD, r0)
   960  			opset(ATRUNCDW, r0)
   961  			opset(ATRUNCFW, r0)
   962  			opset(ASQRTF, r0)
   963  			opset(ASQRTD, r0)
   964  
   965  		case AMOVVF:
   966  			opset(AMOVVD, r0)
   967  			opset(AMOVFV, r0)
   968  			opset(AMOVDV, r0)
   969  			opset(ATRUNCDV, r0)
   970  			opset(ATRUNCFV, r0)
   971  
   972  		case AADD:
   973  			opset(ASGT, r0)
   974  			opset(ASGTU, r0)
   975  			opset(AADDU, r0)
   976  
   977  		case AADDV:
   978  			opset(AADDVU, r0)
   979  
   980  		case AADDF:
   981  			opset(ADIVF, r0)
   982  			opset(ADIVD, r0)
   983  			opset(AMULF, r0)
   984  			opset(AMULD, r0)
   985  			opset(ASUBF, r0)
   986  			opset(ASUBD, r0)
   987  			opset(AADDD, r0)
   988  
   989  		case AAND:
   990  			opset(AOR, r0)
   991  			opset(AXOR, r0)
   992  
   993  		case ABEQ:
   994  			opset(ABNE, r0)
   995  
   996  		case ABLEZ:
   997  			opset(ABGEZ, r0)
   998  			opset(ABGEZAL, r0)
   999  			opset(ABLTZ, r0)
  1000  			opset(ABLTZAL, r0)
  1001  			opset(ABGTZ, r0)
  1002  
  1003  		case AMOVB:
  1004  			opset(AMOVH, r0)
  1005  
  1006  		case AMOVBU:
  1007  			opset(AMOVHU, r0)
  1008  
  1009  		case AMUL:
  1010  			opset(AREM, r0)
  1011  			opset(AREMU, r0)
  1012  			opset(ADIVU, r0)
  1013  			opset(AMULU, r0)
  1014  			opset(ADIV, r0)
  1015  			opset(AMADD, r0)
  1016  			opset(AMSUB, r0)
  1017  
  1018  		case AMULV:
  1019  			opset(ADIVV, r0)
  1020  			opset(ADIVVU, r0)
  1021  			opset(AMULVU, r0)
  1022  			opset(AREMV, r0)
  1023  			opset(AREMVU, r0)
  1024  
  1025  		case ASLL:
  1026  			opset(ASRL, r0)
  1027  			opset(ASRA, r0)
  1028  			opset(AROTR, r0)
  1029  
  1030  		case ASLLV:
  1031  			opset(ASRAV, r0)
  1032  			opset(ASRLV, r0)
  1033  			opset(AROTRV, r0)
  1034  
  1035  		case ASUB:
  1036  			opset(ASUBU, r0)
  1037  			opset(ANOR, r0)
  1038  
  1039  		case ASUBV:
  1040  			opset(ASUBVU, r0)
  1041  
  1042  		case ASYSCALL:
  1043  			opset(ASYNC, r0)
  1044  			opset(ANOOP, r0)
  1045  			opset(ATLBP, r0)
  1046  			opset(ATLBR, r0)
  1047  			opset(ATLBWI, r0)
  1048  			opset(ATLBWR, r0)
  1049  
  1050  		case ACMPEQF:
  1051  			opset(ACMPGTF, r0)
  1052  			opset(ACMPGTD, r0)
  1053  			opset(ACMPGEF, r0)
  1054  			opset(ACMPGED, r0)
  1055  			opset(ACMPEQD, r0)
  1056  
  1057  		case ABFPT:
  1058  			opset(ABFPF, r0)
  1059  
  1060  		case AMOVWL:
  1061  			opset(AMOVWR, r0)
  1062  
  1063  		case AMOVVL:
  1064  			opset(AMOVVR, r0)
  1065  
  1066  		case AVMOVB:
  1067  			opset(AVMOVH, r0)
  1068  			opset(AVMOVW, r0)
  1069  			opset(AVMOVD, r0)
  1070  
  1071  		case AMOVW,
  1072  			AMOVD,
  1073  			AMOVF,
  1074  			AMOVV,
  1075  			ABREAK,
  1076  			ARFE,
  1077  			AJAL,
  1078  			AJMP,
  1079  			AMOVWU,
  1080  			ALL,
  1081  			ALLV,
  1082  			ASC,
  1083  			ASCV,
  1084  			ANEGW,
  1085  			ANEGV,
  1086  			AWORD,
  1087  			obj.ANOP,
  1088  			obj.ATEXT,
  1089  			obj.AUNDEF,
  1090  			obj.AFUNCDATA,
  1091  			obj.APCDATA,
  1092  			obj.ADUFFZERO,
  1093  			obj.ADUFFCOPY:
  1094  			break
  1095  
  1096  		case ACMOVN:
  1097  			opset(ACMOVZ, r0)
  1098  
  1099  		case ACMOVT:
  1100  			opset(ACMOVF, r0)
  1101  
  1102  		case ACLO:
  1103  			opset(ACLZ, r0)
  1104  
  1105  		case ATEQ:
  1106  			opset(ATNE, r0)
  1107  
  1108  		case AWSBH:
  1109  			opset(ASEB, r0)
  1110  			opset(ASEH, r0)
  1111  
  1112  		case ADSBH:
  1113  			opset(ADSHD, r0)
  1114  		}
  1115  	}
  1116  }
  1117  
  1118  func OP(x uint32, y uint32) uint32 {
  1119  	return x<<3 | y<<0
  1120  }
  1121  
  1122  func SP(x uint32, y uint32) uint32 {
  1123  	return x<<29 | y<<26
  1124  }
  1125  
  1126  func BCOND(x uint32, y uint32) uint32 {
  1127  	return x<<19 | y<<16
  1128  }
  1129  
  1130  func MMU(x uint32, y uint32) uint32 {
  1131  	return SP(2, 0) | 16<<21 | x<<3 | y<<0
  1132  }
  1133  
  1134  func FPF(x uint32, y uint32) uint32 {
  1135  	return SP(2, 1) | 16<<21 | x<<3 | y<<0
  1136  }
  1137  
  1138  func FPD(x uint32, y uint32) uint32 {
  1139  	return SP(2, 1) | 17<<21 | x<<3 | y<<0
  1140  }
  1141  
  1142  func FPW(x uint32, y uint32) uint32 {
  1143  	return SP(2, 1) | 20<<21 | x<<3 | y<<0
  1144  }
  1145  
  1146  func FPV(x uint32, y uint32) uint32 {
  1147  	return SP(2, 1) | 21<<21 | x<<3 | y<<0
  1148  }
  1149  
  1150  func OP_RRR(op uint32, r1 int16, r2 int16, r3 int16) uint32 {
  1151  	return op | uint32(r1&31)<<16 | uint32(r2&31)<<21 | uint32(r3&31)<<11
  1152  }
  1153  
  1154  func OP_IRR(op uint32, i uint32, r2 int16, r3 int16) uint32 {
  1155  	return op | i&0xFFFF | uint32(r2&31)<<21 | uint32(r3&31)<<16
  1156  }
  1157  
  1158  func OP_SRR(op uint32, s uint32, r2 int16, r3 int16) uint32 {
  1159  	return op | (s&31)<<6 | uint32(r2&31)<<16 | uint32(r3&31)<<11
  1160  }
  1161  
  1162  func OP_FRRR(op uint32, r1 int16, r2 int16, r3 int16) uint32 {
  1163  	return op | uint32(r1&31)<<16 | uint32(r2&31)<<11 | uint32(r3&31)<<6
  1164  }
  1165  
  1166  func OP_JMP(op uint32, i uint32) uint32 {
  1167  	return op | i&0x3FFFFFF
  1168  }
  1169  
  1170  func OP_VI10(op uint32, df uint32, s10 int32, wd uint32, minor uint32) uint32 {
  1171  	return 0x1e<<26 | (op&7)<<23 | (df&3)<<21 | uint32(s10&0x3FF)<<11 | (wd&31)<<6 | minor&0x3F
  1172  }
  1173  
  1174  func OP_VMI10(s10 int32, rs uint32, wd uint32, minor uint32, df uint32) uint32 {
  1175  	return 0x1e<<26 | uint32(s10&0x3FF)<<16 | (rs&31)<<11 | (wd&31)<<6 | (minor&15)<<2 | df&3
  1176  }
  1177  
  1178  func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
  1179  	o1 := uint32(0)
  1180  	o2 := uint32(0)
  1181  	o3 := uint32(0)
  1182  	o4 := uint32(0)
  1183  
  1184  	add := AADDU
  1185  
  1186  	if c.ctxt.Arch.Family == sys.MIPS64 {
  1187  		add = AADDVU
  1188  	}
  1189  	switch o.type_ {
  1190  	default:
  1191  		c.ctxt.Diag("unknown type %d %v", o.type_)
  1192  		prasm(p)
  1193  
  1194  	case 0: /* pseudo ops */
  1195  		break
  1196  
  1197  	case 1: /* mov r1,r2 ==> OR r1,r0,r2 */
  1198  		a := AOR
  1199  		if p.As == AMOVW && c.ctxt.Arch.Family == sys.MIPS64 {
  1200  			// on MIPS64, most of the 32-bit instructions have unpredictable behavior,
  1201  			// but SLL is special that the result is always sign-extended to 64-bit.
  1202  			a = ASLL
  1203  		}
  1204  		o1 = OP_RRR(c.oprrr(a), p.From.Reg, REGZERO, p.To.Reg)
  1205  
  1206  	case 2: /* add/sub r1,[r2],r3 */
  1207  		r := p.Reg
  1208  		if p.As == ANEGW || p.As == ANEGV {
  1209  			r = REGZERO
  1210  		}
  1211  		if r == obj.REG_NONE {
  1212  			r = p.To.Reg
  1213  		}
  1214  		o1 = OP_RRR(c.oprrr(p.As), p.From.Reg, r, p.To.Reg)
  1215  
  1216  	case 3: /* mov $soreg, r ==> or/add $i,o,r */
  1217  		a := add
  1218  		if o.a1 == C_ANDCON {
  1219  			a = AOR
  1220  		}
  1221  		r := p.From.Reg
  1222  		if r == obj.REG_NONE {
  1223  			r = o.param
  1224  		}
  1225  		v := c.regoff(&p.From)
  1226  		o1 = OP_IRR(c.opirr(a), uint32(v), r, p.To.Reg)
  1227  
  1228  	case 4: /* add $scon,[r1],r2 */
  1229  		r := p.Reg
  1230  		if r == obj.REG_NONE {
  1231  			r = p.To.Reg
  1232  		}
  1233  		v := c.regoff(&p.From)
  1234  		o1 = OP_IRR(c.opirr(p.As), uint32(v), r, p.To.Reg)
  1235  
  1236  	case 5: /* syscall */
  1237  		o1 = c.oprrr(p.As)
  1238  
  1239  	case 6: /* beq r1,[r2],sbra */
  1240  		v := int32(0)
  1241  		if p.To.Target() == nil {
  1242  			v = int32(-4) >> 2
  1243  		} else {
  1244  			v = int32(p.To.Target().Pc-p.Pc-4) >> 2
  1245  		}
  1246  		if (v<<16)>>16 != v {
  1247  			c.ctxt.Diag("short branch too far\n%v", p)
  1248  		}
  1249  		o1 = OP_IRR(c.opirr(p.As), uint32(v), p.From.Reg, p.Reg)
  1250  		// for ABFPT and ABFPF only: always fill delay slot with 0
  1251  		// see comments in func preprocess for details.
  1252  		o2 = 0
  1253  
  1254  	case 7: /* mov r, soreg ==> sw o(r) */
  1255  		r := p.To.Reg
  1256  		if r == obj.REG_NONE {
  1257  			r = o.param
  1258  		}
  1259  		v := c.regoff(&p.To)
  1260  		o1 = OP_IRR(c.opirr(p.As), uint32(v), r, p.From.Reg)
  1261  
  1262  	case 8: /* mov soreg, r ==> lw o(r) */
  1263  		r := p.From.Reg
  1264  		if r == obj.REG_NONE {
  1265  			r = o.param
  1266  		}
  1267  		v := c.regoff(&p.From)
  1268  		o1 = OP_IRR(c.opirr(-p.As), uint32(v), r, p.To.Reg)
  1269  
  1270  	case 9: /* sll r1,[r2],r3 */
  1271  		r := p.Reg
  1272  		if r == obj.REG_NONE {
  1273  			r = p.To.Reg
  1274  		}
  1275  		o1 = OP_RRR(c.oprrr(p.As), r, p.From.Reg, p.To.Reg)
  1276  
  1277  	case 10: /* add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2 */
  1278  		v := c.regoff(&p.From)
  1279  		a := AOR
  1280  		if v < 0 {
  1281  			a = AADDU
  1282  		}
  1283  		o1 = OP_IRR(c.opirr(a), uint32(v), obj.REG_NONE, REGTMP)
  1284  		r := p.Reg
  1285  		if r == obj.REG_NONE {
  1286  			r = p.To.Reg
  1287  		}
  1288  		o2 = OP_RRR(c.oprrr(p.As), REGTMP, r, p.To.Reg)
  1289  
  1290  	case 11: /* jmp lbra */
  1291  		v := int32(0)
  1292  		if c.aclass(&p.To) == C_SBRA && p.To.Sym == nil && p.As == AJMP {
  1293  			// use PC-relative branch for short branches
  1294  			// BEQ	R0, R0, sbra
  1295  			if p.To.Target() == nil {
  1296  				v = int32(-4) >> 2
  1297  			} else {
  1298  				v = int32(p.To.Target().Pc-p.Pc-4) >> 2
  1299  			}
  1300  			if (v<<16)>>16 == v {
  1301  				o1 = OP_IRR(c.opirr(ABEQ), uint32(v), REGZERO, REGZERO)
  1302  				break
  1303  			}
  1304  		}
  1305  		if p.To.Target() == nil {
  1306  			v = int32(p.Pc) >> 2
  1307  		} else {
  1308  			v = int32(p.To.Target().Pc) >> 2
  1309  		}
  1310  		o1 = OP_JMP(c.opirr(p.As), uint32(v))
  1311  		if p.To.Sym == nil {
  1312  			p.To.Sym = c.cursym.Func().Text.From.Sym
  1313  			p.To.Offset = p.To.Target().Pc
  1314  		}
  1315  		rel := obj.Addrel(c.cursym)
  1316  		rel.Off = int32(c.pc)
  1317  		rel.Siz = 4
  1318  		rel.Sym = p.To.Sym
  1319  		rel.Add = p.To.Offset
  1320  		if p.As == AJAL {
  1321  			rel.Type = objabi.R_CALLMIPS
  1322  		} else {
  1323  			rel.Type = objabi.R_JMPMIPS
  1324  		}
  1325  
  1326  	case 12: /* movbs r,r */
  1327  		// NOTE: this case does not use REGTMP. If it ever does,
  1328  		// remove the NOTUSETMP flag in optab.
  1329  		v := 16
  1330  		if p.As == AMOVB {
  1331  			v = 24
  1332  		}
  1333  		o1 = OP_SRR(c.opirr(ASLL), uint32(v), p.From.Reg, p.To.Reg)
  1334  		o2 = OP_SRR(c.opirr(ASRA), uint32(v), p.To.Reg, p.To.Reg)
  1335  
  1336  	case 13: /* movbu r,r */
  1337  		if p.As == AMOVBU {
  1338  			o1 = OP_IRR(c.opirr(AAND), uint32(0xff), p.From.Reg, p.To.Reg)
  1339  		} else {
  1340  			o1 = OP_IRR(c.opirr(AAND), uint32(0xffff), p.From.Reg, p.To.Reg)
  1341  		}
  1342  
  1343  	case 14: /* movwu r,r */
  1344  		// NOTE: this case does not use REGTMP. If it ever does,
  1345  		// remove the NOTUSETMP flag in optab.
  1346  		o1 = OP_SRR(c.opirr(-ASLLV), 0, p.From.Reg, p.To.Reg)
  1347  		o2 = OP_SRR(c.opirr(-ASRLV), 0, p.To.Reg, p.To.Reg)
  1348  
  1349  	case 15: /* teq $c r,r */
  1350  		r := p.Reg
  1351  		if r == obj.REG_NONE {
  1352  			r = REGZERO
  1353  		}
  1354  		v := c.regoff(&p.From)
  1355  		/* only use 10 bits of trap code */
  1356  		o1 = OP_IRR(c.opirr(p.As), (uint32(v)&0x3FF)<<6, r, p.To.Reg)
  1357  
  1358  	case 16: /* sll $c,[r1],r2 */
  1359  		r := p.Reg
  1360  		if r == obj.REG_NONE {
  1361  			r = p.To.Reg
  1362  		}
  1363  		v := c.regoff(&p.From)
  1364  
  1365  		/* OP_SRR will use only the low 5 bits of the shift value */
  1366  		if v >= 32 && vshift(p.As) {
  1367  			o1 = OP_SRR(c.opirr(-p.As), uint32(v-32), r, p.To.Reg)
  1368  		} else {
  1369  			o1 = OP_SRR(c.opirr(p.As), uint32(v), r, p.To.Reg)
  1370  		}
  1371  
  1372  	case 17:
  1373  		o1 = OP_RRR(c.oprrr(p.As), REGZERO, p.From.Reg, p.To.Reg)
  1374  
  1375  	case 18: /* jmp [r1],0(r2) */
  1376  		r := p.Reg
  1377  		if r == obj.REG_NONE {
  1378  			r = o.param
  1379  		}
  1380  		o1 = OP_RRR(c.oprrr(p.As), obj.REG_NONE, p.To.Reg, r)
  1381  		if p.As == obj.ACALL {
  1382  			rel := obj.Addrel(c.cursym)
  1383  			rel.Off = int32(c.pc)
  1384  			rel.Siz = 0
  1385  			rel.Type = objabi.R_CALLIND
  1386  		}
  1387  
  1388  	case 19: /* mov $lcon,r ==> lu+or */
  1389  		// NOTE: this case does not use REGTMP. If it ever does,
  1390  		// remove the NOTUSETMP flag in optab.
  1391  		v := c.regoff(&p.From)
  1392  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), REGZERO, p.To.Reg)
  1393  		o2 = OP_IRR(c.opirr(AOR), uint32(v), p.To.Reg, p.To.Reg)
  1394  
  1395  	case 20: /* mov lo/hi,r */
  1396  		a := OP(2, 0) /* mfhi */
  1397  		if p.From.Reg == REG_LO {
  1398  			a = OP(2, 2) /* mflo */
  1399  		}
  1400  		o1 = OP_RRR(a, REGZERO, REGZERO, p.To.Reg)
  1401  
  1402  	case 21: /* mov r,lo/hi */
  1403  		a := OP(2, 1) /* mthi */
  1404  		if p.To.Reg == REG_LO {
  1405  			a = OP(2, 3) /* mtlo */
  1406  		}
  1407  		o1 = OP_RRR(a, REGZERO, p.From.Reg, REGZERO)
  1408  
  1409  	case 22: /* mul r1,r2 [r3]*/
  1410  		if p.To.Reg != obj.REG_NONE {
  1411  			r := p.Reg
  1412  			if r == obj.REG_NONE {
  1413  				r = p.To.Reg
  1414  			}
  1415  			a := SP(3, 4) | 2 /* mul */
  1416  			o1 = OP_RRR(a, p.From.Reg, r, p.To.Reg)
  1417  		} else {
  1418  			o1 = OP_RRR(c.oprrr(p.As), p.From.Reg, p.Reg, REGZERO)
  1419  		}
  1420  
  1421  	case 23: /* add $lcon,r1,r2 ==> lu+or+add */
  1422  		v := c.regoff(&p.From)
  1423  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), REGZERO, REGTMP)
  1424  		o2 = OP_IRR(c.opirr(AOR), uint32(v), REGTMP, REGTMP)
  1425  		r := p.Reg
  1426  		if r == obj.REG_NONE {
  1427  			r = p.To.Reg
  1428  		}
  1429  		o3 = OP_RRR(c.oprrr(p.As), REGTMP, r, p.To.Reg)
  1430  
  1431  	case 24: /* mov $ucon,r ==> lu r */
  1432  		v := c.regoff(&p.From)
  1433  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), REGZERO, p.To.Reg)
  1434  
  1435  	case 25: /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */
  1436  		v := c.regoff(&p.From)
  1437  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), REGZERO, REGTMP)
  1438  		r := p.Reg
  1439  		if r == obj.REG_NONE {
  1440  			r = p.To.Reg
  1441  		}
  1442  		o2 = OP_RRR(c.oprrr(p.As), REGTMP, r, p.To.Reg)
  1443  
  1444  	case 26: /* mov $lsext/auto/oreg,r ==> lu+or+add */
  1445  		v := c.regoff(&p.From)
  1446  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), REGZERO, REGTMP)
  1447  		o2 = OP_IRR(c.opirr(AOR), uint32(v), REGTMP, REGTMP)
  1448  		r := p.From.Reg
  1449  		if r == obj.REG_NONE {
  1450  			r = o.param
  1451  		}
  1452  		o3 = OP_RRR(c.oprrr(add), REGTMP, r, p.To.Reg)
  1453  
  1454  	case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
  1455  		a := -AMOVF
  1456  		if p.As == AMOVD {
  1457  			a = -AMOVD
  1458  		}
  1459  		r := p.From.Reg
  1460  		if r == obj.REG_NONE {
  1461  			r = o.param
  1462  		}
  1463  		v := c.regoff(&p.From)
  1464  		switch o.size {
  1465  		case 12:
  1466  			o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), REGZERO, REGTMP)
  1467  			o2 = OP_RRR(c.oprrr(add), r, REGTMP, REGTMP)
  1468  			o3 = OP_IRR(c.opirr(a), uint32(v), REGTMP, p.To.Reg)
  1469  
  1470  		case 4:
  1471  			o1 = OP_IRR(c.opirr(a), uint32(v), r, p.To.Reg)
  1472  		}
  1473  
  1474  	case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */
  1475  		a := AMOVF
  1476  		if p.As == AMOVD {
  1477  			a = AMOVD
  1478  		}
  1479  		r := p.To.Reg
  1480  		if r == obj.REG_NONE {
  1481  			r = o.param
  1482  		}
  1483  		v := c.regoff(&p.To)
  1484  		switch o.size {
  1485  		case 12:
  1486  			o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), REGZERO, REGTMP)
  1487  			o2 = OP_RRR(c.oprrr(add), r, REGTMP, REGTMP)
  1488  			o3 = OP_IRR(c.opirr(a), uint32(v), REGTMP, p.From.Reg)
  1489  
  1490  		case 4:
  1491  			o1 = OP_IRR(c.opirr(a), uint32(v), r, p.From.Reg)
  1492  		}
  1493  
  1494  	case 30: /* movw r,fr */
  1495  		a := SP(2, 1) | (4 << 21) /* mtc1 */
  1496  		o1 = OP_RRR(a, p.From.Reg, obj.REG_NONE, p.To.Reg)
  1497  
  1498  	case 31: /* movw fr,r */
  1499  		a := SP(2, 1) | (0 << 21) /* mtc1 */
  1500  		o1 = OP_RRR(a, p.To.Reg, obj.REG_NONE, p.From.Reg)
  1501  
  1502  	case 32: /* fadd fr1,[fr2],fr3 */
  1503  		r := p.Reg
  1504  		if r == obj.REG_NONE {
  1505  			r = p.To.Reg
  1506  		}
  1507  		o1 = OP_FRRR(c.oprrr(p.As), p.From.Reg, r, p.To.Reg)
  1508  
  1509  	case 33: /* fabs fr1, fr3 */
  1510  		o1 = OP_FRRR(c.oprrr(p.As), obj.REG_NONE, p.From.Reg, p.To.Reg)
  1511  
  1512  	case 34: /* mov $con,fr ==> or/add $i,t; mov t,fr */
  1513  		a := AADDU
  1514  		if o.a1 == C_ANDCON {
  1515  			a = AOR
  1516  		}
  1517  		v := c.regoff(&p.From)
  1518  		o1 = OP_IRR(c.opirr(a), uint32(v), obj.REG_NONE, REGTMP)
  1519  		o2 = OP_RRR(SP(2, 1)|(4<<21), REGTMP, obj.REG_NONE, p.To.Reg) /* mtc1 */
  1520  
  1521  	case 35: /* mov r,lext/auto/oreg ==> sw o(REGTMP) */
  1522  		r := p.To.Reg
  1523  		if r == obj.REG_NONE {
  1524  			r = o.param
  1525  		}
  1526  		v := c.regoff(&p.To)
  1527  		o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), REGZERO, REGTMP)
  1528  		o2 = OP_RRR(c.oprrr(add), r, REGTMP, REGTMP)
  1529  		o3 = OP_IRR(c.opirr(p.As), uint32(v), REGTMP, p.From.Reg)
  1530  
  1531  	case 36: /* mov lext/auto/oreg,r ==> lw o(REGTMP) */
  1532  		r := p.From.Reg
  1533  		if r == obj.REG_NONE {
  1534  			r = o.param
  1535  		}
  1536  		v := c.regoff(&p.From)
  1537  		o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), REGZERO, REGTMP)
  1538  		o2 = OP_RRR(c.oprrr(add), r, REGTMP, REGTMP)
  1539  		o3 = OP_IRR(c.opirr(-p.As), uint32(v), REGTMP, p.To.Reg)
  1540  
  1541  	case 37: /* movw r,mr */
  1542  		a := SP(2, 0) | (4 << 21) /* mtc0 */
  1543  		if p.As == AMOVV {
  1544  			a = SP(2, 0) | (5 << 21) /* dmtc0 */
  1545  		}
  1546  		o1 = OP_RRR(a, p.From.Reg, obj.REG_NONE, p.To.Reg)
  1547  
  1548  	case 38: /* movw mr,r */
  1549  		a := SP(2, 0) | (0 << 21) /* mfc0 */
  1550  		if p.As == AMOVV {
  1551  			a = SP(2, 0) | (1 << 21) /* dmfc0 */
  1552  		}
  1553  		o1 = OP_RRR(a, p.To.Reg, obj.REG_NONE, p.From.Reg)
  1554  
  1555  	case 40: /* word */
  1556  		o1 = uint32(c.regoff(&p.From))
  1557  
  1558  	case 41: /* movw f,fcr */
  1559  		o1 = OP_RRR(SP(2, 1)|(6<<21), p.From.Reg, obj.REG_NONE, p.To.Reg) /* mtcc1 */
  1560  
  1561  	case 42: /* movw fcr,r */
  1562  		o1 = OP_RRR(SP(2, 1)|(2<<21), p.To.Reg, obj.REG_NONE, p.From.Reg) /* mfcc1 */
  1563  
  1564  	case 47: /* movv r,fr */
  1565  		a := SP(2, 1) | (5 << 21) /* dmtc1 */
  1566  		o1 = OP_RRR(a, p.From.Reg, obj.REG_NONE, p.To.Reg)
  1567  
  1568  	case 48: /* movv fr,r */
  1569  		a := SP(2, 1) | (1 << 21) /* dmtc1 */
  1570  		o1 = OP_RRR(a, p.To.Reg, obj.REG_NONE, p.From.Reg)
  1571  
  1572  	case 49: /* undef */
  1573  		o1 = 52 /* trap -- teq r0, r0 */
  1574  
  1575  	/* relocation operations */
  1576  	case 50: /* mov r,addr ==> lu + add REGSB, REGTMP + sw o(REGTMP) */
  1577  		o1 = OP_IRR(c.opirr(ALUI), 0, REGZERO, REGTMP)
  1578  		rel := obj.Addrel(c.cursym)
  1579  		rel.Off = int32(c.pc)
  1580  		rel.Siz = 4
  1581  		rel.Sym = p.To.Sym
  1582  		rel.Add = p.To.Offset
  1583  		rel.Type = objabi.R_ADDRMIPSU
  1584  		o2 = OP_IRR(c.opirr(p.As), 0, REGTMP, p.From.Reg)
  1585  		rel2 := obj.Addrel(c.cursym)
  1586  		rel2.Off = int32(c.pc + 4)
  1587  		rel2.Siz = 4
  1588  		rel2.Sym = p.To.Sym
  1589  		rel2.Add = p.To.Offset
  1590  		rel2.Type = objabi.R_ADDRMIPS
  1591  
  1592  		if o.size == 12 {
  1593  			o3 = o2
  1594  			o2 = OP_RRR(c.oprrr(AADDVU), REGSB, REGTMP, REGTMP)
  1595  			rel2.Off += 4
  1596  		}
  1597  
  1598  	case 51: /* mov addr,r ==> lu + add REGSB, REGTMP + lw o(REGTMP) */
  1599  		o1 = OP_IRR(c.opirr(ALUI), 0, REGZERO, REGTMP)
  1600  		rel := obj.Addrel(c.cursym)
  1601  		rel.Off = int32(c.pc)
  1602  		rel.Siz = 4
  1603  		rel.Sym = p.From.Sym
  1604  		rel.Add = p.From.Offset
  1605  		rel.Type = objabi.R_ADDRMIPSU
  1606  		o2 = OP_IRR(c.opirr(-p.As), 0, REGTMP, p.To.Reg)
  1607  		rel2 := obj.Addrel(c.cursym)
  1608  		rel2.Off = int32(c.pc + 4)
  1609  		rel2.Siz = 4
  1610  		rel2.Sym = p.From.Sym
  1611  		rel2.Add = p.From.Offset
  1612  		rel2.Type = objabi.R_ADDRMIPS
  1613  
  1614  		if o.size == 12 {
  1615  			o3 = o2
  1616  			o2 = OP_RRR(c.oprrr(AADDVU), REGSB, REGTMP, REGTMP)
  1617  			rel2.Off += 4
  1618  		}
  1619  
  1620  	case 52: /* mov $lext, r ==> lu + add REGSB, r + add */
  1621  		// NOTE: this case does not use REGTMP. If it ever does,
  1622  		// remove the NOTUSETMP flag in optab.
  1623  		o1 = OP_IRR(c.opirr(ALUI), 0, REGZERO, p.To.Reg)
  1624  		rel := obj.Addrel(c.cursym)
  1625  		rel.Off = int32(c.pc)
  1626  		rel.Siz = 4
  1627  		rel.Sym = p.From.Sym
  1628  		rel.Add = p.From.Offset
  1629  		rel.Type = objabi.R_ADDRMIPSU
  1630  		o2 = OP_IRR(c.opirr(add), 0, p.To.Reg, p.To.Reg)
  1631  		rel2 := obj.Addrel(c.cursym)
  1632  		rel2.Off = int32(c.pc + 4)
  1633  		rel2.Siz = 4
  1634  		rel2.Sym = p.From.Sym
  1635  		rel2.Add = p.From.Offset
  1636  		rel2.Type = objabi.R_ADDRMIPS
  1637  
  1638  		if o.size == 12 {
  1639  			o3 = o2
  1640  			o2 = OP_RRR(c.oprrr(AADDVU), REGSB, p.To.Reg, p.To.Reg)
  1641  			rel2.Off += 4
  1642  		}
  1643  
  1644  	case 53: /* mov r, tlsvar ==> rdhwr + sw o(r3) */
  1645  		// clobbers R3 !
  1646  		// load thread pointer with RDHWR, R3 is used for fast kernel emulation on Linux
  1647  		// NOTE: this case does not use REGTMP. If it ever does,
  1648  		// remove the NOTUSETMP flag in optab.
  1649  		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
  1650  		o2 = OP_IRR(c.opirr(p.As), 0, REG_R3, p.From.Reg)
  1651  		rel := obj.Addrel(c.cursym)
  1652  		rel.Off = int32(c.pc + 4)
  1653  		rel.Siz = 4
  1654  		rel.Sym = p.To.Sym
  1655  		rel.Add = p.To.Offset
  1656  		rel.Type = objabi.R_ADDRMIPSTLS
  1657  
  1658  	case 54: /* mov tlsvar, r ==> rdhwr + lw o(r3) */
  1659  		// clobbers R3 !
  1660  		// NOTE: this case does not use REGTMP. If it ever does,
  1661  		// remove the NOTUSETMP flag in optab.
  1662  		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
  1663  		o2 = OP_IRR(c.opirr(-p.As), 0, REG_R3, p.To.Reg)
  1664  		rel := obj.Addrel(c.cursym)
  1665  		rel.Off = int32(c.pc + 4)
  1666  		rel.Siz = 4
  1667  		rel.Sym = p.From.Sym
  1668  		rel.Add = p.From.Offset
  1669  		rel.Type = objabi.R_ADDRMIPSTLS
  1670  
  1671  	case 55: /* mov $tlsvar, r ==> rdhwr + add */
  1672  		// clobbers R3 !
  1673  		// NOTE: this case does not use REGTMP. If it ever does,
  1674  		// remove the NOTUSETMP flag in optab.
  1675  		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
  1676  		o2 = OP_IRR(c.opirr(add), 0, REG_R3, p.To.Reg)
  1677  		rel := obj.Addrel(c.cursym)
  1678  		rel.Off = int32(c.pc + 4)
  1679  		rel.Siz = 4
  1680  		rel.Sym = p.From.Sym
  1681  		rel.Add = p.From.Offset
  1682  		rel.Type = objabi.R_ADDRMIPSTLS
  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