...

Source file src/github.com/twitchyliquid64/golang-asm/obj/mips/asm0.go

Documentation: github.com/twitchyliquid64/golang-asm/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  	"github.com/twitchyliquid64/golang-asm/obj"
    34  	"github.com/twitchyliquid64/golang-asm/objabi"
    35  	"github.com/twitchyliquid64/golang-asm/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  
  1026  		case ASLLV:
  1027  			opset(ASRAV, r0)
  1028  			opset(ASRLV, r0)
  1029  
  1030  		case ASUB:
  1031  			opset(ASUBU, r0)
  1032  			opset(ANOR, r0)
  1033  
  1034  		case ASUBV:
  1035  			opset(ASUBVU, r0)
  1036  
  1037  		case ASYSCALL:
  1038  			opset(ASYNC, r0)
  1039  			opset(ANOOP, r0)
  1040  			opset(ATLBP, r0)
  1041  			opset(ATLBR, r0)
  1042  			opset(ATLBWI, r0)
  1043  			opset(ATLBWR, r0)
  1044  
  1045  		case ACMPEQF:
  1046  			opset(ACMPGTF, r0)
  1047  			opset(ACMPGTD, r0)
  1048  			opset(ACMPGEF, r0)
  1049  			opset(ACMPGED, r0)
  1050  			opset(ACMPEQD, r0)
  1051  
  1052  		case ABFPT:
  1053  			opset(ABFPF, r0)
  1054  
  1055  		case AMOVWL:
  1056  			opset(AMOVWR, r0)
  1057  
  1058  		case AMOVVL:
  1059  			opset(AMOVVR, r0)
  1060  
  1061  		case AVMOVB:
  1062  			opset(AVMOVH, r0)
  1063  			opset(AVMOVW, r0)
  1064  			opset(AVMOVD, r0)
  1065  
  1066  		case AMOVW,
  1067  			AMOVD,
  1068  			AMOVF,
  1069  			AMOVV,
  1070  			ABREAK,
  1071  			ARFE,
  1072  			AJAL,
  1073  			AJMP,
  1074  			AMOVWU,
  1075  			ALL,
  1076  			ALLV,
  1077  			ASC,
  1078  			ASCV,
  1079  			ANEGW,
  1080  			ANEGV,
  1081  			AWORD,
  1082  			obj.ANOP,
  1083  			obj.ATEXT,
  1084  			obj.AUNDEF,
  1085  			obj.AFUNCDATA,
  1086  			obj.APCDATA,
  1087  			obj.ADUFFZERO,
  1088  			obj.ADUFFCOPY:
  1089  			break
  1090  
  1091  		case ACMOVN:
  1092  			opset(ACMOVZ, r0)
  1093  
  1094  		case ACMOVT:
  1095  			opset(ACMOVF, r0)
  1096  
  1097  		case ACLO:
  1098  			opset(ACLZ, r0)
  1099  
  1100  		case ATEQ:
  1101  			opset(ATNE, r0)
  1102  		}
  1103  	}
  1104  }
  1105  
  1106  func OP(x uint32, y uint32) uint32 {
  1107  	return x<<3 | y<<0
  1108  }
  1109  
  1110  func SP(x uint32, y uint32) uint32 {
  1111  	return x<<29 | y<<26
  1112  }
  1113  
  1114  func BCOND(x uint32, y uint32) uint32 {
  1115  	return x<<19 | y<<16
  1116  }
  1117  
  1118  func MMU(x uint32, y uint32) uint32 {
  1119  	return SP(2, 0) | 16<<21 | x<<3 | y<<0
  1120  }
  1121  
  1122  func FPF(x uint32, y uint32) uint32 {
  1123  	return SP(2, 1) | 16<<21 | x<<3 | y<<0
  1124  }
  1125  
  1126  func FPD(x uint32, y uint32) uint32 {
  1127  	return SP(2, 1) | 17<<21 | x<<3 | y<<0
  1128  }
  1129  
  1130  func FPW(x uint32, y uint32) uint32 {
  1131  	return SP(2, 1) | 20<<21 | x<<3 | y<<0
  1132  }
  1133  
  1134  func FPV(x uint32, y uint32) uint32 {
  1135  	return SP(2, 1) | 21<<21 | x<<3 | y<<0
  1136  }
  1137  
  1138  func OP_RRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
  1139  	return op | (r1&31)<<16 | (r2&31)<<21 | (r3&31)<<11
  1140  }
  1141  
  1142  func OP_IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
  1143  	return op | i&0xFFFF | (r2&31)<<21 | (r3&31)<<16
  1144  }
  1145  
  1146  func OP_SRR(op uint32, s uint32, r2 uint32, r3 uint32) uint32 {
  1147  	return op | (s&31)<<6 | (r2&31)<<16 | (r3&31)<<11
  1148  }
  1149  
  1150  func OP_FRRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
  1151  	return op | (r1&31)<<16 | (r2&31)<<11 | (r3&31)<<6
  1152  }
  1153  
  1154  func OP_JMP(op uint32, i uint32) uint32 {
  1155  	return op | i&0x3FFFFFF
  1156  }
  1157  
  1158  func OP_VI10(op uint32, df uint32, s10 int32, wd uint32, minor uint32) uint32 {
  1159  	return 0x1e<<26 | (op&7)<<23 | (df&3)<<21 | uint32(s10&0x3FF)<<11 | (wd&31)<<6 | minor&0x3F
  1160  }
  1161  
  1162  func OP_VMI10(s10 int32, rs uint32, wd uint32, minor uint32, df uint32) uint32 {
  1163  	return 0x1e<<26 | uint32(s10&0x3FF)<<16 | (rs&31)<<11 | (wd&31)<<6 | (minor&15)<<2 | df&3
  1164  }
  1165  
  1166  func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
  1167  	o1 := uint32(0)
  1168  	o2 := uint32(0)
  1169  	o3 := uint32(0)
  1170  	o4 := uint32(0)
  1171  
  1172  	add := AADDU
  1173  
  1174  	if c.ctxt.Arch.Family == sys.MIPS64 {
  1175  		add = AADDVU
  1176  	}
  1177  	switch o.type_ {
  1178  	default:
  1179  		c.ctxt.Diag("unknown type %d %v", o.type_)
  1180  		prasm(p)
  1181  
  1182  	case 0: /* pseudo ops */
  1183  		break
  1184  
  1185  	case 1: /* mov r1,r2 ==> OR r1,r0,r2 */
  1186  		a := AOR
  1187  		if p.As == AMOVW && c.ctxt.Arch.Family == sys.MIPS64 {
  1188  			// on MIPS64, most of the 32-bit instructions have unpredictable behavior,
  1189  			// but SLL is special that the result is always sign-extended to 64-bit.
  1190  			a = ASLL
  1191  		}
  1192  		o1 = OP_RRR(c.oprrr(a), uint32(p.From.Reg), uint32(REGZERO), uint32(p.To.Reg))
  1193  
  1194  	case 2: /* add/sub r1,[r2],r3 */
  1195  		r := int(p.Reg)
  1196  		if p.As == ANEGW || p.As == ANEGV {
  1197  			r = REGZERO
  1198  		}
  1199  		if r == 0 {
  1200  			r = int(p.To.Reg)
  1201  		}
  1202  		o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
  1203  
  1204  	case 3: /* mov $soreg, r ==> or/add $i,o,r */
  1205  		v := c.regoff(&p.From)
  1206  
  1207  		r := int(p.From.Reg)
  1208  		if r == 0 {
  1209  			r = int(o.param)
  1210  		}
  1211  		a := add
  1212  		if o.a1 == C_ANDCON {
  1213  			a = AOR
  1214  		}
  1215  
  1216  		o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
  1217  
  1218  	case 4: /* add $scon,[r1],r2 */
  1219  		v := c.regoff(&p.From)
  1220  
  1221  		r := int(p.Reg)
  1222  		if r == 0 {
  1223  			r = int(p.To.Reg)
  1224  		}
  1225  
  1226  		o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  1227  
  1228  	case 5: /* syscall */
  1229  		o1 = c.oprrr(p.As)
  1230  
  1231  	case 6: /* beq r1,[r2],sbra */
  1232  		v := int32(0)
  1233  		if p.To.Target() == nil {
  1234  			v = int32(-4) >> 2
  1235  		} else {
  1236  			v = int32(p.To.Target().Pc-p.Pc-4) >> 2
  1237  		}
  1238  		if (v<<16)>>16 != v {
  1239  			c.ctxt.Diag("short branch too far\n%v", p)
  1240  		}
  1241  		o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(p.From.Reg), uint32(p.Reg))
  1242  		// for ABFPT and ABFPF only: always fill delay slot with 0
  1243  		// see comments in func preprocess for details.
  1244  		o2 = 0
  1245  
  1246  	case 7: /* mov r, soreg ==> sw o(r) */
  1247  		r := int(p.To.Reg)
  1248  		if r == 0 {
  1249  			r = int(o.param)
  1250  		}
  1251  		v := c.regoff(&p.To)
  1252  		o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.From.Reg))
  1253  
  1254  	case 8: /* mov soreg, r ==> lw o(r) */
  1255  		r := int(p.From.Reg)
  1256  		if r == 0 {
  1257  			r = int(o.param)
  1258  		}
  1259  		v := c.regoff(&p.From)
  1260  		o1 = OP_IRR(c.opirr(-p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  1261  
  1262  	case 9: /* sll r1,[r2],r3 */
  1263  		r := int(p.Reg)
  1264  
  1265  		if r == 0 {
  1266  			r = int(p.To.Reg)
  1267  		}
  1268  		o1 = OP_RRR(c.oprrr(p.As), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg))
  1269  
  1270  	case 10: /* add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2 */
  1271  		v := c.regoff(&p.From)
  1272  		a := AOR
  1273  		if v < 0 {
  1274  			a = AADDU
  1275  		}
  1276  		o1 = OP_IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
  1277  		r := int(p.Reg)
  1278  		if r == 0 {
  1279  			r = int(p.To.Reg)
  1280  		}
  1281  		o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  1282  
  1283  	case 11: /* jmp lbra */
  1284  		v := int32(0)
  1285  		if c.aclass(&p.To) == C_SBRA && p.To.Sym == nil && p.As == AJMP {
  1286  			// use PC-relative branch for short branches
  1287  			// BEQ	R0, R0, sbra
  1288  			if p.To.Target() == nil {
  1289  				v = int32(-4) >> 2
  1290  			} else {
  1291  				v = int32(p.To.Target().Pc-p.Pc-4) >> 2
  1292  			}
  1293  			if (v<<16)>>16 == v {
  1294  				o1 = OP_IRR(c.opirr(ABEQ), uint32(v), uint32(REGZERO), uint32(REGZERO))
  1295  				break
  1296  			}
  1297  		}
  1298  		if p.To.Target() == nil {
  1299  			v = int32(p.Pc) >> 2
  1300  		} else {
  1301  			v = int32(p.To.Target().Pc) >> 2
  1302  		}
  1303  		o1 = OP_JMP(c.opirr(p.As), uint32(v))
  1304  		if p.To.Sym == nil {
  1305  			p.To.Sym = c.cursym.Func.Text.From.Sym
  1306  			p.To.Offset = p.To.Target().Pc
  1307  		}
  1308  		rel := obj.Addrel(c.cursym)
  1309  		rel.Off = int32(c.pc)
  1310  		rel.Siz = 4
  1311  		rel.Sym = p.To.Sym
  1312  		rel.Add = p.To.Offset
  1313  		if p.As == AJAL {
  1314  			rel.Type = objabi.R_CALLMIPS
  1315  		} else {
  1316  			rel.Type = objabi.R_JMPMIPS
  1317  		}
  1318  
  1319  	case 12: /* movbs r,r */
  1320  		// NOTE: this case does not use REGTMP. If it ever does,
  1321  		// remove the NOTUSETMP flag in optab.
  1322  		v := 16
  1323  		if p.As == AMOVB {
  1324  			v = 24
  1325  		}
  1326  		o1 = OP_SRR(c.opirr(ASLL), uint32(v), uint32(p.From.Reg), uint32(p.To.Reg))
  1327  		o2 = OP_SRR(c.opirr(ASRA), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
  1328  
  1329  	case 13: /* movbu r,r */
  1330  		if p.As == AMOVBU {
  1331  			o1 = OP_IRR(c.opirr(AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg))
  1332  		} else {
  1333  			o1 = OP_IRR(c.opirr(AAND), uint32(0xffff), uint32(p.From.Reg), uint32(p.To.Reg))
  1334  		}
  1335  
  1336  	case 14: /* movwu r,r */
  1337  		// NOTE: this case does not use REGTMP. If it ever does,
  1338  		// remove the NOTUSETMP flag in optab.
  1339  		o1 = OP_SRR(c.opirr(-ASLLV), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
  1340  		o2 = OP_SRR(c.opirr(-ASRLV), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
  1341  
  1342  	case 15: /* teq $c r,r */
  1343  		v := c.regoff(&p.From)
  1344  		r := int(p.Reg)
  1345  		if r == 0 {
  1346  			r = REGZERO
  1347  		}
  1348  		/* only use 10 bits of trap code */
  1349  		o1 = OP_IRR(c.opirr(p.As), (uint32(v)&0x3FF)<<6, uint32(r), uint32(p.To.Reg))
  1350  
  1351  	case 16: /* sll $c,[r1],r2 */
  1352  		v := c.regoff(&p.From)
  1353  		r := int(p.Reg)
  1354  		if r == 0 {
  1355  			r = int(p.To.Reg)
  1356  		}
  1357  
  1358  		/* OP_SRR will use only the low 5 bits of the shift value */
  1359  		if v >= 32 && vshift(p.As) {
  1360  			o1 = OP_SRR(c.opirr(-p.As), uint32(v-32), uint32(r), uint32(p.To.Reg))
  1361  		} else {
  1362  			o1 = OP_SRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  1363  		}
  1364  
  1365  	case 17:
  1366  		o1 = OP_RRR(c.oprrr(p.As), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg))
  1367  
  1368  	case 18: /* jmp [r1],0(r2) */
  1369  		r := int(p.Reg)
  1370  		if r == 0 {
  1371  			r = int(o.param)
  1372  		}
  1373  		o1 = OP_RRR(c.oprrr(p.As), uint32(0), uint32(p.To.Reg), uint32(r))
  1374  		if p.As == obj.ACALL {
  1375  			rel := obj.Addrel(c.cursym)
  1376  			rel.Off = int32(c.pc)
  1377  			rel.Siz = 0
  1378  			rel.Type = objabi.R_CALLIND
  1379  		}
  1380  
  1381  	case 19: /* mov $lcon,r ==> lu+or */
  1382  		// NOTE: this case does not use REGTMP. If it ever does,
  1383  		// remove the NOTUSETMP flag in optab.
  1384  		v := c.regoff(&p.From)
  1385  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
  1386  		o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
  1387  
  1388  	case 20: /* mov lo/hi,r */
  1389  		a := OP(2, 0) /* mfhi */
  1390  		if p.From.Reg == REG_LO {
  1391  			a = OP(2, 2) /* mflo */
  1392  		}
  1393  		o1 = OP_RRR(a, uint32(REGZERO), uint32(REGZERO), uint32(p.To.Reg))
  1394  
  1395  	case 21: /* mov r,lo/hi */
  1396  		a := OP(2, 1) /* mthi */
  1397  		if p.To.Reg == REG_LO {
  1398  			a = OP(2, 3) /* mtlo */
  1399  		}
  1400  		o1 = OP_RRR(a, uint32(REGZERO), uint32(p.From.Reg), uint32(REGZERO))
  1401  
  1402  	case 22: /* mul r1,r2 [r3]*/
  1403  		if p.To.Reg != 0 {
  1404  			r := int(p.Reg)
  1405  			if r == 0 {
  1406  				r = int(p.To.Reg)
  1407  			}
  1408  			a := SP(3, 4) | 2 /* mul */
  1409  			o1 = OP_RRR(a, uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
  1410  		} else {
  1411  			o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(p.Reg), uint32(REGZERO))
  1412  		}
  1413  
  1414  	case 23: /* add $lcon,r1,r2 ==> lu+or+add */
  1415  		v := c.regoff(&p.From)
  1416  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
  1417  		o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
  1418  		r := int(p.Reg)
  1419  		if r == 0 {
  1420  			r = int(p.To.Reg)
  1421  		}
  1422  		o3 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  1423  
  1424  	case 24: /* mov $ucon,r ==> lu r */
  1425  		v := c.regoff(&p.From)
  1426  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
  1427  
  1428  	case 25: /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */
  1429  		v := c.regoff(&p.From)
  1430  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
  1431  		r := int(p.Reg)
  1432  		if r == 0 {
  1433  			r = int(p.To.Reg)
  1434  		}
  1435  		o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  1436  
  1437  	case 26: /* mov $lsext/auto/oreg,r ==> lu+or+add */
  1438  		v := c.regoff(&p.From)
  1439  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
  1440  		o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
  1441  		r := int(p.From.Reg)
  1442  		if r == 0 {
  1443  			r = int(o.param)
  1444  		}
  1445  		o3 = OP_RRR(c.oprrr(add), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  1446  
  1447  	case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
  1448  		v := c.regoff(&p.From)
  1449  		r := int(p.From.Reg)
  1450  		if r == 0 {
  1451  			r = int(o.param)
  1452  		}
  1453  		a := -AMOVF
  1454  		if p.As == AMOVD {
  1455  			a = -AMOVD
  1456  		}
  1457  		switch o.size {
  1458  		case 12:
  1459  			o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
  1460  			o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  1461  			o3 = OP_IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
  1462  
  1463  		case 4:
  1464  			o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
  1465  		}
  1466  
  1467  	case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */
  1468  		v := c.regoff(&p.To)
  1469  		r := int(p.To.Reg)
  1470  		if r == 0 {
  1471  			r = int(o.param)
  1472  		}
  1473  		a := AMOVF
  1474  		if p.As == AMOVD {
  1475  			a = AMOVD
  1476  		}
  1477  		switch o.size {
  1478  		case 12:
  1479  			o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
  1480  			o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  1481  			o3 = OP_IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
  1482  
  1483  		case 4:
  1484  			o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.From.Reg))
  1485  		}
  1486  
  1487  	case 30: /* movw r,fr */
  1488  		a := SP(2, 1) | (4 << 21) /* mtc1 */
  1489  		o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
  1490  
  1491  	case 31: /* movw fr,r */
  1492  		a := SP(2, 1) | (0 << 21) /* mtc1 */
  1493  		o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
  1494  
  1495  	case 32: /* fadd fr1,[fr2],fr3 */
  1496  		r := int(p.Reg)
  1497  		if r == 0 {
  1498  			r = int(p.To.Reg)
  1499  		}
  1500  		o1 = OP_FRRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
  1501  
  1502  	case 33: /* fabs fr1, fr3 */
  1503  		o1 = OP_FRRR(c.oprrr(p.As), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
  1504  
  1505  	case 34: /* mov $con,fr ==> or/add $i,t; mov t,fr */
  1506  		v := c.regoff(&p.From)
  1507  		a := AADDU
  1508  		if o.a1 == C_ANDCON {
  1509  			a = AOR
  1510  		}
  1511  		o1 = OP_IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
  1512  		o2 = OP_RRR(SP(2, 1)|(4<<21), uint32(REGTMP), uint32(0), uint32(p.To.Reg)) /* mtc1 */
  1513  
  1514  	case 35: /* mov r,lext/auto/oreg ==> sw o(REGTMP) */
  1515  		v := c.regoff(&p.To)
  1516  		r := int(p.To.Reg)
  1517  		if r == 0 {
  1518  			r = int(o.param)
  1519  		}
  1520  		o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
  1521  		o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  1522  		o3 = OP_IRR(c.opirr(p.As), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
  1523  
  1524  	case 36: /* mov lext/auto/oreg,r ==> lw o(REGTMP) */
  1525  		v := c.regoff(&p.From)
  1526  		r := int(p.From.Reg)
  1527  		if r == 0 {
  1528  			r = int(o.param)
  1529  		}
  1530  		o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
  1531  		o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  1532  		o3 = OP_IRR(c.opirr(-p.As), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
  1533  
  1534  	case 37: /* movw r,mr */
  1535  		a := SP(2, 0) | (4 << 21) /* mtc0 */
  1536  		if p.As == AMOVV {
  1537  			a = SP(2, 0) | (5 << 21) /* dmtc0 */
  1538  		}
  1539  		o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
  1540  
  1541  	case 38: /* movw mr,r */
  1542  		a := SP(2, 0) | (0 << 21) /* mfc0 */
  1543  		if p.As == AMOVV {
  1544  			a = SP(2, 0) | (1 << 21) /* dmfc0 */
  1545  		}
  1546  		o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
  1547  
  1548  	case 40: /* word */
  1549  		o1 = uint32(c.regoff(&p.From))
  1550  
  1551  	case 41: /* movw f,fcr */
  1552  		o1 = OP_RRR(SP(2, 1)|(6<<21), uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) /* mtcc1 */
  1553  
  1554  	case 42: /* movw fcr,r */
  1555  		o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) /* mfcc1 */
  1556  
  1557  	case 47: /* movv r,fr */
  1558  		a := SP(2, 1) | (5 << 21) /* dmtc1 */
  1559  		o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
  1560  
  1561  	case 48: /* movv fr,r */
  1562  		a := SP(2, 1) | (1 << 21) /* dmtc1 */
  1563  		o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
  1564  
  1565  	case 49: /* undef */
  1566  		o1 = 52 /* trap -- teq r0, r0 */
  1567  
  1568  	/* relocation operations */
  1569  	case 50: /* mov r,addr ==> lu + add REGSB, REGTMP + sw o(REGTMP) */
  1570  		o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP))
  1571  		rel := obj.Addrel(c.cursym)
  1572  		rel.Off = int32(c.pc)
  1573  		rel.Siz = 4
  1574  		rel.Sym = p.To.Sym
  1575  		rel.Add = p.To.Offset
  1576  		rel.Type = objabi.R_ADDRMIPSU
  1577  		o2 = OP_IRR(c.opirr(p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
  1578  		rel2 := obj.Addrel(c.cursym)
  1579  		rel2.Off = int32(c.pc + 4)
  1580  		rel2.Siz = 4
  1581  		rel2.Sym = p.To.Sym
  1582  		rel2.Add = p.To.Offset
  1583  		rel2.Type = objabi.R_ADDRMIPS
  1584  
  1585  		if o.size == 12 {
  1586  			o3 = o2
  1587  			o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
  1588  			rel2.Off += 4
  1589  		}
  1590  
  1591  	case 51: /* mov addr,r ==> lu + add REGSB, REGTMP + lw o(REGTMP) */
  1592  		o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP))
  1593  		rel := obj.Addrel(c.cursym)
  1594  		rel.Off = int32(c.pc)
  1595  		rel.Siz = 4
  1596  		rel.Sym = p.From.Sym
  1597  		rel.Add = p.From.Offset
  1598  		rel.Type = objabi.R_ADDRMIPSU
  1599  		o2 = OP_IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
  1600  		rel2 := obj.Addrel(c.cursym)
  1601  		rel2.Off = int32(c.pc + 4)
  1602  		rel2.Siz = 4
  1603  		rel2.Sym = p.From.Sym
  1604  		rel2.Add = p.From.Offset
  1605  		rel2.Type = objabi.R_ADDRMIPS
  1606  
  1607  		if o.size == 12 {
  1608  			o3 = o2
  1609  			o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
  1610  			rel2.Off += 4
  1611  		}
  1612  
  1613  	case 52: /* mov $lext, r ==> lu + add REGSB, r + add */
  1614  		// NOTE: this case does not use REGTMP. If it ever does,
  1615  		// remove the NOTUSETMP flag in optab.
  1616  		o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(p.To.Reg))
  1617  		rel := obj.Addrel(c.cursym)
  1618  		rel.Off = int32(c.pc)
  1619  		rel.Siz = 4
  1620  		rel.Sym = p.From.Sym
  1621  		rel.Add = p.From.Offset
  1622  		rel.Type = objabi.R_ADDRMIPSU
  1623  		o2 = OP_IRR(c.opirr(add), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
  1624  		rel2 := obj.Addrel(c.cursym)
  1625  		rel2.Off = int32(c.pc + 4)
  1626  		rel2.Siz = 4
  1627  		rel2.Sym = p.From.Sym
  1628  		rel2.Add = p.From.Offset
  1629  		rel2.Type = objabi.R_ADDRMIPS
  1630  
  1631  		if o.size == 12 {
  1632  			o3 = o2
  1633  			o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(p.To.Reg), uint32(p.To.Reg))
  1634  			rel2.Off += 4
  1635  		}
  1636  
  1637  	case 53: /* mov r, tlsvar ==> rdhwr + sw o(r3) */
  1638  		// clobbers R3 !
  1639  		// load thread pointer with RDHWR, R3 is used for fast kernel emulation on Linux
  1640  		// NOTE: this case does not use REGTMP. If it ever does,
  1641  		// remove the NOTUSETMP flag in optab.
  1642  		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
  1643  		o2 = OP_IRR(c.opirr(p.As), uint32(0), uint32(REG_R3), uint32(p.From.Reg))
  1644  		rel := obj.Addrel(c.cursym)
  1645  		rel.Off = int32(c.pc + 4)
  1646  		rel.Siz = 4
  1647  		rel.Sym = p.To.Sym
  1648  		rel.Add = p.To.Offset
  1649  		rel.Type = objabi.R_ADDRMIPSTLS
  1650  
  1651  	case 54: /* mov tlsvar, r ==> rdhwr + lw o(r3) */
  1652  		// clobbers R3 !
  1653  		// NOTE: this case does not use REGTMP. If it ever does,
  1654  		// remove the NOTUSETMP flag in optab.
  1655  		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
  1656  		o2 = OP_IRR(c.opirr(-p.As), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
  1657  		rel := obj.Addrel(c.cursym)
  1658  		rel.Off = int32(c.pc + 4)
  1659  		rel.Siz = 4
  1660  		rel.Sym = p.From.Sym
  1661  		rel.Add = p.From.Offset
  1662  		rel.Type = objabi.R_ADDRMIPSTLS
  1663  
  1664  	case 55: /* mov $tlsvar, r ==> rdhwr + add */
  1665  		// clobbers R3 !
  1666  		// NOTE: this case does not use REGTMP. If it ever does,
  1667  		// remove the NOTUSETMP flag in optab.
  1668  		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
  1669  		o2 = OP_IRR(c.opirr(add), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
  1670  		rel := obj.Addrel(c.cursym)
  1671  		rel.Off = int32(c.pc + 4)
  1672  		rel.Siz = 4
  1673  		rel.Sym = p.From.Sym
  1674  		rel.Add = p.From.Offset
  1675  		rel.Type = objabi.R_ADDRMIPSTLS
  1676  
  1677  	case 56: /* vmov{b,h,w,d} $scon, wr */
  1678  
  1679  		v := c.regoff(&p.From)
  1680  		o1 = OP_VI10(110, c.twobitdf(p.As), v, uint32(p.To.Reg), 7)
  1681  
  1682  	case 57: /* vld $soreg, wr */
  1683  		v := c.lsoffset(p.As, c.regoff(&p.From))
  1684  		o1 = OP_VMI10(v, uint32(p.From.Reg), uint32(p.To.Reg), 8, c.twobitdf(p.As))
  1685  
  1686  	case 58: /* vst wr, $soreg */
  1687  		v := c.lsoffset(p.As, c.regoff(&p.To))
  1688  		o1 = OP_VMI10(v, uint32(p.To.Reg), uint32(p.From.Reg), 9, c.twobitdf(p.As))
  1689  	}
  1690  
  1691  	out[0] = o1
  1692  	out[1] = o2
  1693  	out[2] = o3
  1694  	out[3] = o4
  1695  }
  1696  
  1697  func (c *ctxt0) vregoff(a *obj.Addr) int64 {
  1698  	c.instoffset = 0
  1699  	c.aclass(a)
  1700  	return c.instoffset
  1701  }
  1702  
  1703  func (c *ctxt0) regoff(a *obj.Addr) int32 {
  1704  	return int32(c.vregoff(a))
  1705  }
  1706  
  1707  func (c *ctxt0) oprrr(a obj.As) uint32 {
  1708  	switch a {
  1709  	case AADD:
  1710  		return OP(4, 0)
  1711  	case AADDU:
  1712  		return OP(4, 1)
  1713  	case ASGT:
  1714  		return OP(5, 2)
  1715  	case ASGTU:
  1716  		return OP(5, 3)
  1717  	case AAND:
  1718  		return OP(4, 4)
  1719  	case AOR:
  1720  		return OP(4, 5)
  1721  	case AXOR:
  1722  		return OP(4, 6)
  1723  	case ASUB:
  1724  		return OP(4, 2)
  1725  	case ASUBU, ANEGW:
  1726  		return OP(4, 3)
  1727  	case ANOR:
  1728  		return OP(4, 7)
  1729  	case ASLL:
  1730  		return OP(0, 4)
  1731  	case ASRL:
  1732  		return OP(0, 6)
  1733  	case ASRA:
  1734  		return OP(0, 7)
  1735  	case ASLLV:
  1736  		return OP(2, 4)
  1737  	case ASRLV:
  1738  		return OP(2, 6)
  1739  	case ASRAV:
  1740  		return OP(2, 7)
  1741  	case AADDV:
  1742  		return OP(5, 4)
  1743  	case AADDVU:
  1744  		return OP(5, 5)
  1745  	case ASUBV:
  1746  		return OP(5, 6)
  1747  	case ASUBVU, ANEGV:
  1748  		return OP(5, 7)
  1749  	case AREM,
  1750  		ADIV:
  1751  		return OP(3, 2)
  1752  	case AREMU,
  1753  		ADIVU:
  1754  		return OP(3, 3)
  1755  	case AMUL:
  1756  		return OP(3, 0)
  1757  	case AMULU:
  1758  		return OP(3, 1)
  1759  	case AREMV,
  1760  		ADIVV:
  1761  		return OP(3, 6)
  1762  	case AREMVU,
  1763  		ADIVVU:
  1764  		return OP(3, 7)
  1765  	case AMULV:
  1766  		return OP(3, 4)
  1767  	case AMULVU:
  1768  		return OP(3, 5)
  1769  
  1770  	case AJMP:
  1771  		return OP(1, 0)
  1772  	case AJAL:
  1773  		return OP(1, 1)
  1774  
  1775  	case ABREAK:
  1776  		return OP(1, 5)
  1777  	case ASYSCALL:
  1778  		return OP(1, 4)
  1779  	case ATLBP:
  1780  		return MMU(1, 0)
  1781  	case ATLBR:
  1782  		return MMU(0, 1)
  1783  	case ATLBWI:
  1784  		return MMU(0, 2)
  1785  	case ATLBWR:
  1786  		return MMU(0, 6)
  1787  	case ARFE:
  1788  		return MMU(2, 0)
  1789  
  1790  	case ADIVF:
  1791  		return FPF(0, 3)
  1792  	case ADIVD:
  1793  		return FPD(0, 3)
  1794  	case AMULF:
  1795  		return FPF(0, 2)
  1796  	case AMULD:
  1797  		return FPD(0, 2)
  1798  	case ASUBF:
  1799  		return FPF(0, 1)
  1800  	case ASUBD:
  1801  		return FPD(0, 1)
  1802  	case AADDF:
  1803  		return FPF(0, 0)
  1804  	case AADDD:
  1805  		return FPD(0, 0)
  1806  	case ATRUNCFV:
  1807  		return FPF(1, 1)
  1808  	case ATRUNCDV:
  1809  		return FPD(1, 1)
  1810  	case ATRUNCFW:
  1811  		return FPF(1, 5)
  1812  	case ATRUNCDW:
  1813  		return FPD(1, 5)
  1814  	case AMOVFV:
  1815  		return FPF(4, 5)
  1816  	case AMOVDV:
  1817  		return FPD(4, 5)
  1818  	case AMOVVF:
  1819  		return FPV(4, 0)
  1820  	case AMOVVD:
  1821  		return FPV(4, 1)
  1822  	case AMOVFW:
  1823  		return FPF(4, 4)
  1824  	case AMOVDW:
  1825  		return FPD(4, 4)
  1826  	case AMOVWF:
  1827  		return FPW(4, 0)
  1828  	case AMOVDF:
  1829  		return FPD(4, 0)
  1830  	case AMOVWD:
  1831  		return FPW(4, 1)
  1832  	case AMOVFD:
  1833  		return FPF(4, 1)
  1834  	case AABSF:
  1835  		return FPF(0, 5)
  1836  	case AABSD:
  1837  		return FPD(0, 5)
  1838  	case AMOVF:
  1839  		return FPF(0, 6)
  1840  	case AMOVD:
  1841  		return FPD(0, 6)
  1842  	case ANEGF:
  1843  		return FPF(0, 7)
  1844  	case ANEGD:
  1845  		return FPD(0, 7)
  1846  	case ACMPEQF:
  1847  		return FPF(6, 2)
  1848  	case ACMPEQD:
  1849  		return FPD(6, 2)
  1850  	case ACMPGTF:
  1851  		return FPF(7, 4)
  1852  	case ACMPGTD:
  1853  		return FPD(7, 4)
  1854  	case ACMPGEF:
  1855  		return FPF(7, 6)
  1856  	case ACMPGED:
  1857  		return FPD(7, 6)
  1858  
  1859  	case ASQRTF:
  1860  		return FPF(0, 4)
  1861  	case ASQRTD:
  1862  		return FPD(0, 4)
  1863  
  1864  	case ASYNC:
  1865  		return OP(1, 7)
  1866  	case ANOOP:
  1867  		return 0
  1868  
  1869  	case ACMOVN:
  1870  		return OP(1, 3)
  1871  	case ACMOVZ:
  1872  		return OP(1, 2)
  1873  	case ACMOVT:
  1874  		return OP(0, 1) | (1 << 16)
  1875  	case ACMOVF:
  1876  		return OP(0, 1) | (0 << 16)
  1877  	case ACLO:
  1878  		return SP(3, 4) | OP(4, 1)
  1879  	case ACLZ:
  1880  		return SP(3, 4) | OP(4, 0)
  1881  	case AMADD:
  1882  		return SP(3, 4) | OP(0, 0)
  1883  	case AMSUB:
  1884  		return SP(3, 4) | OP(0, 4)
  1885  	}
  1886  
  1887  	if a < 0 {
  1888  		c.ctxt.Diag("bad rrr opcode -%v", -a)
  1889  	} else {
  1890  		c.ctxt.Diag("bad rrr opcode %v", a)
  1891  	}
  1892  	return 0
  1893  }
  1894  
  1895  func (c *ctxt0) opirr(a obj.As) uint32 {
  1896  	switch a {
  1897  	case AADD:
  1898  		return SP(1, 0)
  1899  	case AADDU:
  1900  		return SP(1, 1)
  1901  	case ASGT:
  1902  		return SP(1, 2)
  1903  	case ASGTU:
  1904  		return SP(1, 3)
  1905  	case AAND:
  1906  		return SP(1, 4)
  1907  	case AOR:
  1908  		return SP(1, 5)
  1909  	case AXOR:
  1910  		return SP(1, 6)
  1911  	case ALUI:
  1912  		return SP(1, 7)
  1913  	case ASLL:
  1914  		return OP(0, 0)
  1915  	case ASRL:
  1916  		return OP(0, 2)
  1917  	case ASRA:
  1918  		return OP(0, 3)
  1919  	case AADDV:
  1920  		return SP(3, 0)
  1921  	case AADDVU:
  1922  		return SP(3, 1)
  1923  
  1924  	case AJMP:
  1925  		return SP(0, 2)
  1926  	case AJAL,
  1927  		obj.ADUFFZERO,
  1928  		obj.ADUFFCOPY:
  1929  		return SP(0, 3)
  1930  	case ABEQ:
  1931  		return SP(0, 4)
  1932  	case -ABEQ:
  1933  		return SP(2, 4) /* likely */
  1934  	case ABNE:
  1935  		return SP(0, 5)
  1936  	case -ABNE:
  1937  		return SP(2, 5) /* likely */
  1938  	case ABGEZ:
  1939  		return SP(0, 1) | BCOND(0, 1)
  1940  	case -ABGEZ:
  1941  		return SP(0, 1) | BCOND(0, 3) /* likely */
  1942  	case ABGEZAL:
  1943  		return SP(0, 1) | BCOND(2, 1)
  1944  	case -ABGEZAL:
  1945  		return SP(0, 1) | BCOND(2, 3) /* likely */
  1946  	case ABGTZ:
  1947  		return SP(0, 7)
  1948  	case -ABGTZ:
  1949  		return SP(2, 7) /* likely */
  1950  	case ABLEZ:
  1951  		return SP(0, 6)
  1952  	case -ABLEZ:
  1953  		return SP(2, 6) /* likely */
  1954  	case ABLTZ:
  1955  		return SP(0, 1) | BCOND(0, 0)
  1956  	case -ABLTZ:
  1957  		return SP(0, 1) | BCOND(0, 2) /* likely */
  1958  	case ABLTZAL:
  1959  		return SP(0, 1) | BCOND(2, 0)
  1960  	case -ABLTZAL:
  1961  		return SP(0, 1) | BCOND(2, 2) /* likely */
  1962  	case ABFPT:
  1963  		return SP(2, 1) | (257 << 16)
  1964  	case -ABFPT:
  1965  		return SP(2, 1) | (259 << 16) /* likely */
  1966  	case ABFPF:
  1967  		return SP(2, 1) | (256 << 16)
  1968  	case -ABFPF:
  1969  		return SP(2, 1) | (258 << 16) /* likely */
  1970  
  1971  	case AMOVB,
  1972  		AMOVBU:
  1973  		return SP(5, 0)
  1974  	case AMOVH,
  1975  		AMOVHU:
  1976  		return SP(5, 1)
  1977  	case AMOVW,
  1978  		AMOVWU:
  1979  		return SP(5, 3)
  1980  	case AMOVV:
  1981  		return SP(7, 7)
  1982  	case AMOVF:
  1983  		return SP(7, 1)
  1984  	case AMOVD:
  1985  		return SP(7, 5)
  1986  	case AMOVWL:
  1987  		return SP(5, 2)
  1988  	case AMOVWR:
  1989  		return SP(5, 6)
  1990  	case AMOVVL:
  1991  		return SP(5, 4)
  1992  	case AMOVVR:
  1993  		return SP(5, 5)
  1994  
  1995  	case ABREAK:
  1996  		return SP(5, 7)
  1997  
  1998  	case -AMOVWL:
  1999  		return SP(4, 2)
  2000  	case -AMOVWR:
  2001  		return SP(4, 6)
  2002  	case -AMOVVL:
  2003  		return SP(3, 2)
  2004  	case -AMOVVR:
  2005  		return SP(3, 3)
  2006  	case -AMOVB:
  2007  		return SP(4, 0)
  2008  	case -AMOVBU:
  2009  		return SP(4, 4)
  2010  	case -AMOVH:
  2011  		return SP(4, 1)
  2012  	case -AMOVHU:
  2013  		return SP(4, 5)
  2014  	case -AMOVW:
  2015  		return SP(4, 3)
  2016  	case -AMOVWU:
  2017  		return SP(4, 7)
  2018  	case -AMOVV:
  2019  		return SP(6, 7)
  2020  	case -AMOVF:
  2021  		return SP(6, 1)
  2022  	case -AMOVD:
  2023  		return SP(6, 5)
  2024  
  2025  	case ASLLV:
  2026  		return OP(7, 0)
  2027  	case ASRLV:
  2028  		return OP(7, 2)
  2029  	case ASRAV:
  2030  		return OP(7, 3)
  2031  	case -ASLLV:
  2032  		return OP(7, 4)
  2033  	case -ASRLV:
  2034  		return OP(7, 6)
  2035  	case -ASRAV:
  2036  		return OP(7, 7)
  2037  
  2038  	case ATEQ:
  2039  		return OP(6, 4)
  2040  	case ATNE:
  2041  		return OP(6, 6)
  2042  	case -ALL:
  2043  		return SP(6, 0)
  2044  	case -ALLV:
  2045  		return SP(6, 4)
  2046  	case ASC:
  2047  		return SP(7, 0)
  2048  	case ASCV:
  2049  		return SP(7, 4)
  2050  	}
  2051  
  2052  	if a < 0 {
  2053  		c.ctxt.Diag("bad irr opcode -%v", -a)
  2054  	} else {
  2055  		c.ctxt.Diag("bad irr opcode %v", a)
  2056  	}
  2057  	return 0
  2058  }
  2059  
  2060  func vshift(a obj.As) bool {
  2061  	switch a {
  2062  	case ASLLV,
  2063  		ASRLV,
  2064  		ASRAV:
  2065  		return true
  2066  	}
  2067  	return false
  2068  }
  2069  
  2070  // MSA Two-bit Data Format Field Encoding
  2071  func (c *ctxt0) twobitdf(a obj.As) uint32 {
  2072  	switch a {
  2073  	case AVMOVB:
  2074  		return 0
  2075  	case AVMOVH:
  2076  		return 1
  2077  	case AVMOVW:
  2078  		return 2
  2079  	case AVMOVD:
  2080  		return 3
  2081  	default:
  2082  		c.ctxt.Diag("unsupported data format %v", a)
  2083  	}
  2084  	return 0
  2085  }
  2086  
  2087  // MSA Load/Store offset have to be multiple of size of data format
  2088  func (c *ctxt0) lsoffset(a obj.As, o int32) int32 {
  2089  	var mod int32
  2090  	switch a {
  2091  	case AVMOVB:
  2092  		mod = 1
  2093  	case AVMOVH:
  2094  		mod = 2
  2095  	case AVMOVW:
  2096  		mod = 4
  2097  	case AVMOVD:
  2098  		mod = 8
  2099  	default:
  2100  		c.ctxt.Diag("unsupported instruction:%v", a)
  2101  	}
  2102  
  2103  	if o%mod != 0 {
  2104  		c.ctxt.Diag("invalid offset for %v: %d is not a multiple of %d", a, o, mod)
  2105  	}
  2106  
  2107  	return o / mod
  2108  }
  2109  

View as plain text