github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/src/cmd/internal/obj/mips/asm0.go (about)

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