github.com/Filosottile/go@v0.0.0-20170906193555-dbed9972d994/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  			log.Fatalf("bad code")
   897  
   898  		case AABSF:
   899  			opset(AMOVFD, r0)
   900  			opset(AMOVDF, r0)
   901  			opset(AMOVWF, r0)
   902  			opset(AMOVFW, r0)
   903  			opset(AMOVWD, r0)
   904  			opset(AMOVDW, r0)
   905  			opset(ANEGF, r0)
   906  			opset(ANEGD, r0)
   907  			opset(AABSD, r0)
   908  			opset(ATRUNCDW, r0)
   909  			opset(ATRUNCFW, r0)
   910  			opset(ASQRTF, r0)
   911  			opset(ASQRTD, r0)
   912  
   913  		case AMOVVF:
   914  			opset(AMOVVD, r0)
   915  			opset(AMOVFV, r0)
   916  			opset(AMOVDV, r0)
   917  			opset(ATRUNCDV, r0)
   918  			opset(ATRUNCFV, r0)
   919  
   920  		case AADD:
   921  			opset(ASGT, r0)
   922  			opset(ASGTU, r0)
   923  			opset(AADDU, r0)
   924  
   925  		case AADDV:
   926  			opset(AADDVU, r0)
   927  
   928  		case AADDF:
   929  			opset(ADIVF, r0)
   930  			opset(ADIVD, r0)
   931  			opset(AMULF, r0)
   932  			opset(AMULD, r0)
   933  			opset(ASUBF, r0)
   934  			opset(ASUBD, r0)
   935  			opset(AADDD, r0)
   936  
   937  		case AAND:
   938  			opset(AOR, r0)
   939  			opset(AXOR, r0)
   940  
   941  		case ABEQ:
   942  			opset(ABNE, r0)
   943  
   944  		case ABLEZ:
   945  			opset(ABGEZ, r0)
   946  			opset(ABGEZAL, r0)
   947  			opset(ABLTZ, r0)
   948  			opset(ABLTZAL, r0)
   949  			opset(ABGTZ, r0)
   950  
   951  		case AMOVB:
   952  			opset(AMOVH, r0)
   953  
   954  		case AMOVBU:
   955  			opset(AMOVHU, r0)
   956  
   957  		case AMUL:
   958  			opset(AREM, r0)
   959  			opset(AREMU, r0)
   960  			opset(ADIVU, r0)
   961  			opset(AMULU, r0)
   962  			opset(ADIV, r0)
   963  
   964  		case AMULV:
   965  			opset(ADIVV, r0)
   966  			opset(ADIVVU, r0)
   967  			opset(AMULVU, r0)
   968  			opset(AREMV, r0)
   969  			opset(AREMVU, r0)
   970  
   971  		case ASLL:
   972  			opset(ASRL, r0)
   973  			opset(ASRA, r0)
   974  
   975  		case ASLLV:
   976  			opset(ASRAV, r0)
   977  			opset(ASRLV, r0)
   978  
   979  		case ASUB:
   980  			opset(ASUBU, r0)
   981  			opset(ANOR, r0)
   982  
   983  		case ASUBV:
   984  			opset(ASUBVU, r0)
   985  
   986  		case ASYSCALL:
   987  			opset(ASYNC, r0)
   988  			opset(ANOOP, r0)
   989  			opset(ATLBP, r0)
   990  			opset(ATLBR, r0)
   991  			opset(ATLBWI, r0)
   992  			opset(ATLBWR, r0)
   993  
   994  		case ACMPEQF:
   995  			opset(ACMPGTF, r0)
   996  			opset(ACMPGTD, r0)
   997  			opset(ACMPGEF, r0)
   998  			opset(ACMPGED, r0)
   999  			opset(ACMPEQD, r0)
  1000  
  1001  		case ABFPT:
  1002  			opset(ABFPF, r0)
  1003  
  1004  		case AMOVWL:
  1005  			opset(AMOVWR, r0)
  1006  
  1007  		case AMOVVL:
  1008  			opset(AMOVVR, r0)
  1009  
  1010  		case AMOVW,
  1011  			AMOVD,
  1012  			AMOVF,
  1013  			AMOVV,
  1014  			ABREAK,
  1015  			ARFE,
  1016  			AJAL,
  1017  			AJMP,
  1018  			AMOVWU,
  1019  			ALL,
  1020  			ALLV,
  1021  			ASC,
  1022  			ASCV,
  1023  			AWORD,
  1024  			obj.ANOP,
  1025  			obj.ATEXT,
  1026  			obj.AUNDEF,
  1027  			obj.AFUNCDATA,
  1028  			obj.APCDATA,
  1029  			obj.ADUFFZERO,
  1030  			obj.ADUFFCOPY:
  1031  			break
  1032  
  1033  		case ACMOVN:
  1034  			opset(ACMOVZ, r0)
  1035  
  1036  		case ACMOVT:
  1037  			opset(ACMOVF, r0)
  1038  
  1039  		case ACLO:
  1040  			opset(ACLZ, r0)
  1041  
  1042  		case ATEQ:
  1043  			opset(ATNE, r0)
  1044  		}
  1045  	}
  1046  }
  1047  
  1048  func OP(x uint32, y uint32) uint32 {
  1049  	return x<<3 | y<<0
  1050  }
  1051  
  1052  func SP(x uint32, y uint32) uint32 {
  1053  	return x<<29 | y<<26
  1054  }
  1055  
  1056  func BCOND(x uint32, y uint32) uint32 {
  1057  	return x<<19 | y<<16
  1058  }
  1059  
  1060  func MMU(x uint32, y uint32) uint32 {
  1061  	return SP(2, 0) | 16<<21 | x<<3 | y<<0
  1062  }
  1063  
  1064  func FPF(x uint32, y uint32) uint32 {
  1065  	return SP(2, 1) | 16<<21 | x<<3 | y<<0
  1066  }
  1067  
  1068  func FPD(x uint32, y uint32) uint32 {
  1069  	return SP(2, 1) | 17<<21 | x<<3 | y<<0
  1070  }
  1071  
  1072  func FPW(x uint32, y uint32) uint32 {
  1073  	return SP(2, 1) | 20<<21 | x<<3 | y<<0
  1074  }
  1075  
  1076  func FPV(x uint32, y uint32) uint32 {
  1077  	return SP(2, 1) | 21<<21 | x<<3 | y<<0
  1078  }
  1079  
  1080  func OP_RRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
  1081  	return op | (r1&31)<<16 | (r2&31)<<21 | (r3&31)<<11
  1082  }
  1083  
  1084  func OP_IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
  1085  	return op | i&0xFFFF | (r2&31)<<21 | (r3&31)<<16
  1086  }
  1087  
  1088  func OP_SRR(op uint32, s uint32, r2 uint32, r3 uint32) uint32 {
  1089  	return op | (s&31)<<6 | (r2&31)<<16 | (r3&31)<<11
  1090  }
  1091  
  1092  func OP_FRRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
  1093  	return op | (r1&31)<<16 | (r2&31)<<11 | (r3&31)<<6
  1094  }
  1095  
  1096  func OP_JMP(op uint32, i uint32) uint32 {
  1097  	return op | i&0x3FFFFFF
  1098  }
  1099  
  1100  func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
  1101  	o1 := uint32(0)
  1102  	o2 := uint32(0)
  1103  	o3 := uint32(0)
  1104  	o4 := uint32(0)
  1105  
  1106  	add := AADDU
  1107  
  1108  	if c.ctxt.Arch.Family == sys.MIPS64 {
  1109  		add = AADDVU
  1110  	}
  1111  	switch o.type_ {
  1112  	default:
  1113  		c.ctxt.Diag("unknown type %d %v", o.type_)
  1114  		prasm(p)
  1115  
  1116  	case 0: /* pseudo ops */
  1117  		break
  1118  
  1119  	case 1: /* mov r1,r2 ==> OR r1,r0,r2 */
  1120  		a := AOR
  1121  		if p.As == AMOVW && c.ctxt.Arch.Family == sys.MIPS64 {
  1122  			a = AADDU // sign-extended to high 32 bits
  1123  		}
  1124  		o1 = OP_RRR(c.oprrr(a), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg))
  1125  
  1126  	case 2: /* add/sub r1,[r2],r3 */
  1127  		r := int(p.Reg)
  1128  
  1129  		if r == 0 {
  1130  			r = int(p.To.Reg)
  1131  		}
  1132  		o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
  1133  
  1134  	case 3: /* mov $soreg, r ==> or/add $i,o,r */
  1135  		v := c.regoff(&p.From)
  1136  
  1137  		r := int(p.From.Reg)
  1138  		if r == 0 {
  1139  			r = int(o.param)
  1140  		}
  1141  		a := add
  1142  		if o.a1 == C_ANDCON {
  1143  			a = AOR
  1144  		}
  1145  
  1146  		o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
  1147  
  1148  	case 4: /* add $scon,[r1],r2 */
  1149  		v := c.regoff(&p.From)
  1150  
  1151  		r := int(p.Reg)
  1152  		if r == 0 {
  1153  			r = int(p.To.Reg)
  1154  		}
  1155  
  1156  		o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  1157  
  1158  	case 5: /* syscall */
  1159  		o1 = c.oprrr(p.As)
  1160  
  1161  	case 6: /* beq r1,[r2],sbra */
  1162  		v := int32(0)
  1163  		if p.Pcond == nil {
  1164  			v = int32(-4) >> 2
  1165  		} else {
  1166  			v = int32(p.Pcond.Pc-p.Pc-4) >> 2
  1167  		}
  1168  		if (v<<16)>>16 != v {
  1169  			c.ctxt.Diag("short branch too far\n%v", p)
  1170  		}
  1171  		o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(p.From.Reg), uint32(p.Reg))
  1172  		// for ABFPT and ABFPF only: always fill delay slot with 0
  1173  		// see comments in func preprocess for details.
  1174  		o2 = 0
  1175  
  1176  	case 7: /* mov r, soreg ==> sw o(r) */
  1177  		r := int(p.To.Reg)
  1178  		if r == 0 {
  1179  			r = int(o.param)
  1180  		}
  1181  		v := c.regoff(&p.To)
  1182  		o1 = OP_IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.From.Reg))
  1183  
  1184  	case 8: /* mov soreg, r ==> lw o(r) */
  1185  		r := int(p.From.Reg)
  1186  		if r == 0 {
  1187  			r = int(o.param)
  1188  		}
  1189  		v := c.regoff(&p.From)
  1190  		o1 = OP_IRR(c.opirr(-p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  1191  
  1192  	case 9: /* sll r1,[r2],r3 */
  1193  		r := int(p.Reg)
  1194  
  1195  		if r == 0 {
  1196  			r = int(p.To.Reg)
  1197  		}
  1198  		o1 = OP_RRR(c.oprrr(p.As), uint32(r), uint32(p.From.Reg), uint32(p.To.Reg))
  1199  
  1200  	case 10: /* add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2 */
  1201  		v := c.regoff(&p.From)
  1202  		a := AOR
  1203  		if v < 0 {
  1204  			a = AADDU
  1205  		}
  1206  		o1 = OP_IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
  1207  		r := int(p.Reg)
  1208  		if r == 0 {
  1209  			r = int(p.To.Reg)
  1210  		}
  1211  		o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  1212  
  1213  	case 11: /* jmp lbra */
  1214  		v := int32(0)
  1215  		if c.aclass(&p.To) == C_SBRA && p.To.Sym == nil && p.As == AJMP {
  1216  			// use PC-relative branch for short branches
  1217  			// BEQ	R0, R0, sbra
  1218  			if p.Pcond == nil {
  1219  				v = int32(-4) >> 2
  1220  			} else {
  1221  				v = int32(p.Pcond.Pc-p.Pc-4) >> 2
  1222  			}
  1223  			if (v<<16)>>16 == v {
  1224  				o1 = OP_IRR(c.opirr(ABEQ), uint32(v), uint32(REGZERO), uint32(REGZERO))
  1225  				break
  1226  			}
  1227  		}
  1228  		if p.Pcond == nil {
  1229  			v = int32(p.Pc) >> 2
  1230  		} else {
  1231  			v = int32(p.Pcond.Pc) >> 2
  1232  		}
  1233  		o1 = OP_JMP(c.opirr(p.As), uint32(v))
  1234  		if p.To.Sym == nil {
  1235  			p.To.Sym = c.cursym.Func.Text.From.Sym
  1236  			p.To.Offset = p.Pcond.Pc
  1237  		}
  1238  		rel := obj.Addrel(c.cursym)
  1239  		rel.Off = int32(c.pc)
  1240  		rel.Siz = 4
  1241  		rel.Sym = p.To.Sym
  1242  		rel.Add = p.To.Offset
  1243  		if p.As == AJAL {
  1244  			rel.Type = objabi.R_CALLMIPS
  1245  		} else {
  1246  			rel.Type = objabi.R_JMPMIPS
  1247  		}
  1248  
  1249  	case 12: /* movbs r,r */
  1250  		v := 16
  1251  		if p.As == AMOVB {
  1252  			v = 24
  1253  		}
  1254  		o1 = OP_SRR(c.opirr(ASLL), uint32(v), uint32(p.From.Reg), uint32(p.To.Reg))
  1255  		o2 = OP_SRR(c.opirr(ASRA), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
  1256  
  1257  	case 13: /* movbu r,r */
  1258  		if p.As == AMOVBU {
  1259  			o1 = OP_IRR(c.opirr(AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg))
  1260  		} else {
  1261  			o1 = OP_IRR(c.opirr(AAND), uint32(0xffff), uint32(p.From.Reg), uint32(p.To.Reg))
  1262  		}
  1263  
  1264  	case 14: /* movwu r,r */
  1265  		o1 = OP_SRR(c.opirr(-ASLLV), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
  1266  		o2 = OP_SRR(c.opirr(-ASRLV), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
  1267  
  1268  	case 15: /* teq $c r,r */
  1269  		v := c.regoff(&p.From)
  1270  		r := int(p.Reg)
  1271  		if r == 0 {
  1272  			r = REGZERO
  1273  		}
  1274  		/* only use 10 bits of trap code */
  1275  		o1 = OP_IRR(c.opirr(p.As), (uint32(v)&0x3FF)<<6, uint32(p.Reg), uint32(p.To.Reg))
  1276  
  1277  	case 16: /* sll $c,[r1],r2 */
  1278  		v := c.regoff(&p.From)
  1279  		r := int(p.Reg)
  1280  		if r == 0 {
  1281  			r = int(p.To.Reg)
  1282  		}
  1283  
  1284  		/* OP_SRR will use only the low 5 bits of the shift value */
  1285  		if v >= 32 && vshift(p.As) {
  1286  			o1 = OP_SRR(c.opirr(-p.As), uint32(v-32), uint32(r), uint32(p.To.Reg))
  1287  		} else {
  1288  			o1 = OP_SRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  1289  		}
  1290  
  1291  	case 17:
  1292  		o1 = OP_RRR(c.oprrr(p.As), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg))
  1293  
  1294  	case 18: /* jmp [r1],0(r2) */
  1295  		r := int(p.Reg)
  1296  		if r == 0 {
  1297  			r = int(o.param)
  1298  		}
  1299  		o1 = OP_RRR(c.oprrr(p.As), uint32(0), uint32(p.To.Reg), uint32(r))
  1300  		rel := obj.Addrel(c.cursym)
  1301  		rel.Off = int32(c.pc)
  1302  		rel.Siz = 0
  1303  		rel.Type = objabi.R_CALLIND
  1304  
  1305  	case 19: /* mov $lcon,r ==> lu+or */
  1306  		v := c.regoff(&p.From)
  1307  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
  1308  		o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
  1309  
  1310  	case 20: /* mov lo/hi,r */
  1311  		a := OP(2, 0) /* mfhi */
  1312  		if p.From.Reg == REG_LO {
  1313  			a = OP(2, 2) /* mflo */
  1314  		}
  1315  		o1 = OP_RRR(a, uint32(REGZERO), uint32(REGZERO), uint32(p.To.Reg))
  1316  
  1317  	case 21: /* mov r,lo/hi */
  1318  		a := OP(2, 1) /* mthi */
  1319  		if p.To.Reg == REG_LO {
  1320  			a = OP(2, 3) /* mtlo */
  1321  		}
  1322  		o1 = OP_RRR(a, uint32(REGZERO), uint32(p.From.Reg), uint32(REGZERO))
  1323  
  1324  	case 22: /* mul r1,r2 [r3]*/
  1325  		if p.To.Reg != 0 {
  1326  			r := int(p.Reg)
  1327  			if r == 0 {
  1328  				r = int(p.To.Reg)
  1329  			}
  1330  			a := SP(3, 4) | 2 /* mul */
  1331  			o1 = OP_RRR(a, uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
  1332  		} else {
  1333  			o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(p.Reg), uint32(REGZERO))
  1334  		}
  1335  
  1336  	case 23: /* add $lcon,r1,r2 ==> lu+or+add */
  1337  		v := c.regoff(&p.From)
  1338  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
  1339  		o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
  1340  		r := int(p.Reg)
  1341  		if r == 0 {
  1342  			r = int(p.To.Reg)
  1343  		}
  1344  		o3 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  1345  
  1346  	case 24: /* mov $ucon,r ==> lu r */
  1347  		v := c.regoff(&p.From)
  1348  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(p.To.Reg))
  1349  
  1350  	case 25: /* add/and $ucon,[r1],r2 ==> lu $con,t; add t,[r1],r2 */
  1351  		v := c.regoff(&p.From)
  1352  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
  1353  		r := int(p.Reg)
  1354  		if r == 0 {
  1355  			r = int(p.To.Reg)
  1356  		}
  1357  		o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  1358  
  1359  	case 26: /* mov $lsext/auto/oreg,r ==> lu+or+add */
  1360  		v := c.regoff(&p.From)
  1361  		o1 = OP_IRR(c.opirr(ALUI), uint32(v>>16), uint32(REGZERO), uint32(REGTMP))
  1362  		o2 = OP_IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
  1363  		r := int(p.From.Reg)
  1364  		if r == 0 {
  1365  			r = int(o.param)
  1366  		}
  1367  		o3 = OP_RRR(c.oprrr(add), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  1368  
  1369  	case 27: /* mov [sl]ext/auto/oreg,fr ==> lwc1 o(r) */
  1370  		v := c.regoff(&p.From)
  1371  		r := int(p.From.Reg)
  1372  		if r == 0 {
  1373  			r = int(o.param)
  1374  		}
  1375  		a := -AMOVF
  1376  		if p.As == AMOVD {
  1377  			a = -AMOVD
  1378  		}
  1379  		switch o.size {
  1380  		case 12:
  1381  			o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
  1382  			o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  1383  			o3 = OP_IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
  1384  
  1385  		case 4:
  1386  			o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
  1387  		}
  1388  
  1389  	case 28: /* mov fr,[sl]ext/auto/oreg ==> swc1 o(r) */
  1390  		v := c.regoff(&p.To)
  1391  		r := int(p.To.Reg)
  1392  		if r == 0 {
  1393  			r = int(o.param)
  1394  		}
  1395  		a := AMOVF
  1396  		if p.As == AMOVD {
  1397  			a = AMOVD
  1398  		}
  1399  		switch o.size {
  1400  		case 12:
  1401  			o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
  1402  			o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  1403  			o3 = OP_IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
  1404  
  1405  		case 4:
  1406  			o1 = OP_IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.From.Reg))
  1407  		}
  1408  
  1409  	case 30: /* movw r,fr */
  1410  		a := SP(2, 1) | (4 << 21) /* mtc1 */
  1411  		o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
  1412  
  1413  	case 31: /* movw fr,r */
  1414  		a := SP(2, 1) | (0 << 21) /* mtc1 */
  1415  		o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
  1416  
  1417  	case 32: /* fadd fr1,[fr2],fr3 */
  1418  		r := int(p.Reg)
  1419  		if r == 0 {
  1420  			r = int(p.To.Reg)
  1421  		}
  1422  		o1 = OP_FRRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
  1423  
  1424  	case 33: /* fabs fr1, fr3 */
  1425  		o1 = OP_FRRR(c.oprrr(p.As), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
  1426  
  1427  	case 34: /* mov $con,fr ==> or/add $i,t; mov t,fr */
  1428  		v := c.regoff(&p.From)
  1429  		a := AADDU
  1430  		if o.a1 == C_ANDCON {
  1431  			a = AOR
  1432  		}
  1433  		o1 = OP_IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
  1434  		o2 = OP_RRR(SP(2, 1)|(4<<21), uint32(REGTMP), uint32(0), uint32(p.To.Reg)) /* mtc1 */
  1435  
  1436  	case 35: /* mov r,lext/auto/oreg ==> sw o(REGTMP) */
  1437  		v := c.regoff(&p.To)
  1438  		r := int(p.To.Reg)
  1439  		if r == 0 {
  1440  			r = int(o.param)
  1441  		}
  1442  		o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
  1443  		o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  1444  		o3 = OP_IRR(c.opirr(p.As), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
  1445  
  1446  	case 36: /* mov lext/auto/oreg,r ==> lw o(REGTMP) */
  1447  		v := c.regoff(&p.From)
  1448  		r := int(p.From.Reg)
  1449  		if r == 0 {
  1450  			r = int(o.param)
  1451  		}
  1452  		o1 = OP_IRR(c.opirr(ALUI), uint32((v+1<<15)>>16), uint32(REGZERO), uint32(REGTMP))
  1453  		o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  1454  		o3 = OP_IRR(c.opirr(-p.As), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
  1455  
  1456  	case 37: /* movw r,mr */
  1457  		a := SP(2, 0) | (4 << 21) /* mtc0 */
  1458  		if p.As == AMOVV {
  1459  			a = SP(2, 0) | (5 << 21) /* dmtc0 */
  1460  		}
  1461  		o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
  1462  
  1463  	case 38: /* movw mr,r */
  1464  		a := SP(2, 0) | (0 << 21) /* mfc0 */
  1465  		if p.As == AMOVV {
  1466  			a = SP(2, 0) | (1 << 21) /* dmfc0 */
  1467  		}
  1468  		o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
  1469  
  1470  	case 40: /* word */
  1471  		o1 = uint32(c.regoff(&p.From))
  1472  
  1473  	case 41: /* movw f,fcr */
  1474  		o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(REGZERO), uint32(0), uint32(p.To.Reg))    /* mfcc1 */
  1475  		o2 = OP_RRR(SP(2, 1)|(6<<21), uint32(p.From.Reg), uint32(0), uint32(p.To.Reg)) /* mtcc1 */
  1476  
  1477  	case 42: /* movw fcr,r */
  1478  		o1 = OP_RRR(SP(2, 1)|(2<<21), uint32(p.To.Reg), uint32(0), uint32(p.From.Reg)) /* mfcc1 */
  1479  
  1480  	case 47: /* movv r,fr */
  1481  		a := SP(2, 1) | (5 << 21) /* dmtc1 */
  1482  		o1 = OP_RRR(a, uint32(p.From.Reg), uint32(0), uint32(p.To.Reg))
  1483  
  1484  	case 48: /* movv fr,r */
  1485  		a := SP(2, 1) | (1 << 21) /* dmtc1 */
  1486  		o1 = OP_RRR(a, uint32(p.To.Reg), uint32(0), uint32(p.From.Reg))
  1487  
  1488  	case 49: /* undef */
  1489  		o1 = 52 /* trap -- teq r0, r0 */
  1490  
  1491  	/* relocation operations */
  1492  	case 50: /* mov r,addr ==> lu + add REGSB, REGTMP + sw o(REGTMP) */
  1493  		o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP))
  1494  		rel := obj.Addrel(c.cursym)
  1495  		rel.Off = int32(c.pc)
  1496  		rel.Siz = 4
  1497  		rel.Sym = p.To.Sym
  1498  		rel.Add = p.To.Offset
  1499  		rel.Type = objabi.R_ADDRMIPSU
  1500  		o2 = OP_IRR(c.opirr(p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
  1501  		rel2 := obj.Addrel(c.cursym)
  1502  		rel2.Off = int32(c.pc + 4)
  1503  		rel2.Siz = 4
  1504  		rel2.Sym = p.To.Sym
  1505  		rel2.Add = p.To.Offset
  1506  		rel2.Type = objabi.R_ADDRMIPS
  1507  
  1508  		if o.size == 12 {
  1509  			o3 = o2
  1510  			o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
  1511  			rel2.Off += 4
  1512  		}
  1513  
  1514  	case 51: /* mov addr,r ==> lu + add REGSB, REGTMP + lw o(REGTMP) */
  1515  		o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(REGTMP))
  1516  		rel := obj.Addrel(c.cursym)
  1517  		rel.Off = int32(c.pc)
  1518  		rel.Siz = 4
  1519  		rel.Sym = p.From.Sym
  1520  		rel.Add = p.From.Offset
  1521  		rel.Type = objabi.R_ADDRMIPSU
  1522  		o2 = OP_IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
  1523  		rel2 := obj.Addrel(c.cursym)
  1524  		rel2.Off = int32(c.pc + 4)
  1525  		rel2.Siz = 4
  1526  		rel2.Sym = p.From.Sym
  1527  		rel2.Add = p.From.Offset
  1528  		rel2.Type = objabi.R_ADDRMIPS
  1529  
  1530  		if o.size == 12 {
  1531  			o3 = o2
  1532  			o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(REGTMP), uint32(REGTMP))
  1533  			rel2.Off += 4
  1534  		}
  1535  
  1536  	case 52: /* mov $lext, r ==> lu + add REGSB, r + add */
  1537  		o1 = OP_IRR(c.opirr(ALUI), uint32(0), uint32(REGZERO), uint32(p.To.Reg))
  1538  		rel := obj.Addrel(c.cursym)
  1539  		rel.Off = int32(c.pc)
  1540  		rel.Siz = 4
  1541  		rel.Sym = p.From.Sym
  1542  		rel.Add = p.From.Offset
  1543  		rel.Type = objabi.R_ADDRMIPSU
  1544  		o2 = OP_IRR(c.opirr(add), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
  1545  		rel2 := obj.Addrel(c.cursym)
  1546  		rel2.Off = int32(c.pc + 4)
  1547  		rel2.Siz = 4
  1548  		rel2.Sym = p.From.Sym
  1549  		rel2.Add = p.From.Offset
  1550  		rel2.Type = objabi.R_ADDRMIPS
  1551  
  1552  		if o.size == 12 {
  1553  			o3 = o2
  1554  			o2 = OP_RRR(c.oprrr(AADDVU), uint32(REGSB), uint32(p.To.Reg), uint32(p.To.Reg))
  1555  			rel2.Off += 4
  1556  		}
  1557  
  1558  	case 53: /* mov r, tlsvar ==> rdhwr + sw o(r3) */
  1559  		// clobbers R3 !
  1560  		// load thread pointer with RDHWR, R3 is used for fast kernel emulation on Linux
  1561  		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
  1562  		o2 = OP_IRR(c.opirr(p.As), uint32(0), uint32(REG_R3), uint32(p.From.Reg))
  1563  		rel := obj.Addrel(c.cursym)
  1564  		rel.Off = int32(c.pc + 4)
  1565  		rel.Siz = 4
  1566  		rel.Sym = p.To.Sym
  1567  		rel.Add = p.To.Offset
  1568  		rel.Type = objabi.R_ADDRMIPSTLS
  1569  
  1570  	case 54: /* mov tlsvar, r ==> rdhwr + lw o(r3) */
  1571  		// clobbers R3 !
  1572  		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
  1573  		o2 = OP_IRR(c.opirr(-p.As), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
  1574  		rel := obj.Addrel(c.cursym)
  1575  		rel.Off = int32(c.pc + 4)
  1576  		rel.Siz = 4
  1577  		rel.Sym = p.From.Sym
  1578  		rel.Add = p.From.Offset
  1579  		rel.Type = objabi.R_ADDRMIPSTLS
  1580  
  1581  	case 55: /* mov $tlsvar, r ==> rdhwr + add */
  1582  		// clobbers R3 !
  1583  		o1 = (037<<26 + 073) | (29 << 11) | (3 << 16) // rdhwr $29, r3
  1584  		o2 = OP_IRR(c.opirr(add), uint32(0), uint32(REG_R3), uint32(p.To.Reg))
  1585  		rel := obj.Addrel(c.cursym)
  1586  		rel.Off = int32(c.pc + 4)
  1587  		rel.Siz = 4
  1588  		rel.Sym = p.From.Sym
  1589  		rel.Add = p.From.Offset
  1590  		rel.Type = objabi.R_ADDRMIPSTLS
  1591  	}
  1592  
  1593  	out[0] = o1
  1594  	out[1] = o2
  1595  	out[2] = o3
  1596  	out[3] = o4
  1597  	return
  1598  }
  1599  
  1600  func (c *ctxt0) vregoff(a *obj.Addr) int64 {
  1601  	c.instoffset = 0
  1602  	c.aclass(a)
  1603  	return c.instoffset
  1604  }
  1605  
  1606  func (c *ctxt0) regoff(a *obj.Addr) int32 {
  1607  	return int32(c.vregoff(a))
  1608  }
  1609  
  1610  func (c *ctxt0) oprrr(a obj.As) uint32 {
  1611  	switch a {
  1612  	case AADD:
  1613  		return OP(4, 0)
  1614  	case AADDU:
  1615  		return OP(4, 1)
  1616  	case ASGT:
  1617  		return OP(5, 2)
  1618  	case ASGTU:
  1619  		return OP(5, 3)
  1620  	case AAND:
  1621  		return OP(4, 4)
  1622  	case AOR:
  1623  		return OP(4, 5)
  1624  	case AXOR:
  1625  		return OP(4, 6)
  1626  	case ASUB:
  1627  		return OP(4, 2)
  1628  	case ASUBU:
  1629  		return OP(4, 3)
  1630  	case ANOR:
  1631  		return OP(4, 7)
  1632  	case ASLL:
  1633  		return OP(0, 4)
  1634  	case ASRL:
  1635  		return OP(0, 6)
  1636  	case ASRA:
  1637  		return OP(0, 7)
  1638  	case ASLLV:
  1639  		return OP(2, 4)
  1640  	case ASRLV:
  1641  		return OP(2, 6)
  1642  	case ASRAV:
  1643  		return OP(2, 7)
  1644  	case AADDV:
  1645  		return OP(5, 4)
  1646  	case AADDVU:
  1647  		return OP(5, 5)
  1648  	case ASUBV:
  1649  		return OP(5, 6)
  1650  	case ASUBVU:
  1651  		return OP(5, 7)
  1652  	case AREM,
  1653  		ADIV:
  1654  		return OP(3, 2)
  1655  	case AREMU,
  1656  		ADIVU:
  1657  		return OP(3, 3)
  1658  	case AMUL:
  1659  		return OP(3, 0)
  1660  	case AMULU:
  1661  		return OP(3, 1)
  1662  	case AREMV,
  1663  		ADIVV:
  1664  		return OP(3, 6)
  1665  	case AREMVU,
  1666  		ADIVVU:
  1667  		return OP(3, 7)
  1668  	case AMULV:
  1669  		return OP(3, 4)
  1670  	case AMULVU:
  1671  		return OP(3, 5)
  1672  
  1673  	case AJMP:
  1674  		return OP(1, 0)
  1675  	case AJAL:
  1676  		return OP(1, 1)
  1677  
  1678  	case ABREAK:
  1679  		return OP(1, 5)
  1680  	case ASYSCALL:
  1681  		return OP(1, 4)
  1682  	case ATLBP:
  1683  		return MMU(1, 0)
  1684  	case ATLBR:
  1685  		return MMU(0, 1)
  1686  	case ATLBWI:
  1687  		return MMU(0, 2)
  1688  	case ATLBWR:
  1689  		return MMU(0, 6)
  1690  	case ARFE:
  1691  		return MMU(2, 0)
  1692  
  1693  	case ADIVF:
  1694  		return FPF(0, 3)
  1695  	case ADIVD:
  1696  		return FPD(0, 3)
  1697  	case AMULF:
  1698  		return FPF(0, 2)
  1699  	case AMULD:
  1700  		return FPD(0, 2)
  1701  	case ASUBF:
  1702  		return FPF(0, 1)
  1703  	case ASUBD:
  1704  		return FPD(0, 1)
  1705  	case AADDF:
  1706  		return FPF(0, 0)
  1707  	case AADDD:
  1708  		return FPD(0, 0)
  1709  	case ATRUNCFV:
  1710  		return FPF(1, 1)
  1711  	case ATRUNCDV:
  1712  		return FPD(1, 1)
  1713  	case ATRUNCFW:
  1714  		return FPF(1, 5)
  1715  	case ATRUNCDW:
  1716  		return FPD(1, 5)
  1717  	case AMOVFV:
  1718  		return FPF(4, 5)
  1719  	case AMOVDV:
  1720  		return FPD(4, 5)
  1721  	case AMOVVF:
  1722  		return FPV(4, 0)
  1723  	case AMOVVD:
  1724  		return FPV(4, 1)
  1725  	case AMOVFW:
  1726  		return FPF(4, 4)
  1727  	case AMOVDW:
  1728  		return FPD(4, 4)
  1729  	case AMOVWF:
  1730  		return FPW(4, 0)
  1731  	case AMOVDF:
  1732  		return FPD(4, 0)
  1733  	case AMOVWD:
  1734  		return FPW(4, 1)
  1735  	case AMOVFD:
  1736  		return FPF(4, 1)
  1737  	case AABSF:
  1738  		return FPF(0, 5)
  1739  	case AABSD:
  1740  		return FPD(0, 5)
  1741  	case AMOVF:
  1742  		return FPF(0, 6)
  1743  	case AMOVD:
  1744  		return FPD(0, 6)
  1745  	case ANEGF:
  1746  		return FPF(0, 7)
  1747  	case ANEGD:
  1748  		return FPD(0, 7)
  1749  	case ACMPEQF:
  1750  		return FPF(6, 2)
  1751  	case ACMPEQD:
  1752  		return FPD(6, 2)
  1753  	case ACMPGTF:
  1754  		return FPF(7, 4)
  1755  	case ACMPGTD:
  1756  		return FPD(7, 4)
  1757  	case ACMPGEF:
  1758  		return FPF(7, 6)
  1759  	case ACMPGED:
  1760  		return FPD(7, 6)
  1761  
  1762  	case ASQRTF:
  1763  		return FPF(0, 4)
  1764  	case ASQRTD:
  1765  		return FPD(0, 4)
  1766  
  1767  	case ASYNC:
  1768  		return OP(1, 7)
  1769  	case ANOOP:
  1770  		return 0
  1771  
  1772  	case ACMOVN:
  1773  		return OP(1, 3)
  1774  	case ACMOVZ:
  1775  		return OP(1, 2)
  1776  	case ACMOVT:
  1777  		return OP(0, 1) | (1 << 16)
  1778  	case ACMOVF:
  1779  		return OP(0, 1) | (0 << 16)
  1780  	case ACLO:
  1781  		return SP(3, 4) | OP(4, 1)
  1782  	case ACLZ:
  1783  		return SP(3, 4) | OP(4, 0)
  1784  	}
  1785  
  1786  	if a < 0 {
  1787  		c.ctxt.Diag("bad rrr opcode -%v", -a)
  1788  	} else {
  1789  		c.ctxt.Diag("bad rrr opcode %v", a)
  1790  	}
  1791  	return 0
  1792  }
  1793  
  1794  func (c *ctxt0) opirr(a obj.As) uint32 {
  1795  	switch a {
  1796  	case AADD:
  1797  		return SP(1, 0)
  1798  	case AADDU:
  1799  		return SP(1, 1)
  1800  	case ASGT:
  1801  		return SP(1, 2)
  1802  	case ASGTU:
  1803  		return SP(1, 3)
  1804  	case AAND:
  1805  		return SP(1, 4)
  1806  	case AOR:
  1807  		return SP(1, 5)
  1808  	case AXOR:
  1809  		return SP(1, 6)
  1810  	case ALUI:
  1811  		return SP(1, 7)
  1812  	case ASLL:
  1813  		return OP(0, 0)
  1814  	case ASRL:
  1815  		return OP(0, 2)
  1816  	case ASRA:
  1817  		return OP(0, 3)
  1818  	case AADDV:
  1819  		return SP(3, 0)
  1820  	case AADDVU:
  1821  		return SP(3, 1)
  1822  
  1823  	case AJMP:
  1824  		return SP(0, 2)
  1825  	case AJAL,
  1826  		obj.ADUFFZERO,
  1827  		obj.ADUFFCOPY:
  1828  		return SP(0, 3)
  1829  	case ABEQ:
  1830  		return SP(0, 4)
  1831  	case -ABEQ:
  1832  		return SP(2, 4) /* likely */
  1833  	case ABNE:
  1834  		return SP(0, 5)
  1835  	case -ABNE:
  1836  		return SP(2, 5) /* likely */
  1837  	case ABGEZ:
  1838  		return SP(0, 1) | BCOND(0, 1)
  1839  	case -ABGEZ:
  1840  		return SP(0, 1) | BCOND(0, 3) /* likely */
  1841  	case ABGEZAL:
  1842  		return SP(0, 1) | BCOND(2, 1)
  1843  	case -ABGEZAL:
  1844  		return SP(0, 1) | BCOND(2, 3) /* likely */
  1845  	case ABGTZ:
  1846  		return SP(0, 7)
  1847  	case -ABGTZ:
  1848  		return SP(2, 7) /* likely */
  1849  	case ABLEZ:
  1850  		return SP(0, 6)
  1851  	case -ABLEZ:
  1852  		return SP(2, 6) /* likely */
  1853  	case ABLTZ:
  1854  		return SP(0, 1) | BCOND(0, 0)
  1855  	case -ABLTZ:
  1856  		return SP(0, 1) | BCOND(0, 2) /* likely */
  1857  	case ABLTZAL:
  1858  		return SP(0, 1) | BCOND(2, 0)
  1859  	case -ABLTZAL:
  1860  		return SP(0, 1) | BCOND(2, 2) /* likely */
  1861  	case ABFPT:
  1862  		return SP(2, 1) | (257 << 16)
  1863  	case -ABFPT:
  1864  		return SP(2, 1) | (259 << 16) /* likely */
  1865  	case ABFPF:
  1866  		return SP(2, 1) | (256 << 16)
  1867  	case -ABFPF:
  1868  		return SP(2, 1) | (258 << 16) /* likely */
  1869  
  1870  	case AMOVB,
  1871  		AMOVBU:
  1872  		return SP(5, 0)
  1873  	case AMOVH,
  1874  		AMOVHU:
  1875  		return SP(5, 1)
  1876  	case AMOVW,
  1877  		AMOVWU:
  1878  		return SP(5, 3)
  1879  	case AMOVV:
  1880  		return SP(7, 7)
  1881  	case AMOVF:
  1882  		return SP(7, 1)
  1883  	case AMOVD:
  1884  		return SP(7, 5)
  1885  	case AMOVWL:
  1886  		return SP(5, 2)
  1887  	case AMOVWR:
  1888  		return SP(5, 6)
  1889  	case AMOVVL:
  1890  		return SP(5, 4)
  1891  	case AMOVVR:
  1892  		return SP(5, 5)
  1893  
  1894  	case ABREAK:
  1895  		return SP(5, 7)
  1896  
  1897  	case -AMOVWL:
  1898  		return SP(4, 2)
  1899  	case -AMOVWR:
  1900  		return SP(4, 6)
  1901  	case -AMOVVL:
  1902  		return SP(3, 2)
  1903  	case -AMOVVR:
  1904  		return SP(3, 3)
  1905  	case -AMOVB:
  1906  		return SP(4, 0)
  1907  	case -AMOVBU:
  1908  		return SP(4, 4)
  1909  	case -AMOVH:
  1910  		return SP(4, 1)
  1911  	case -AMOVHU:
  1912  		return SP(4, 5)
  1913  	case -AMOVW:
  1914  		return SP(4, 3)
  1915  	case -AMOVWU:
  1916  		return SP(4, 7)
  1917  	case -AMOVV:
  1918  		return SP(6, 7)
  1919  	case -AMOVF:
  1920  		return SP(6, 1)
  1921  	case -AMOVD:
  1922  		return SP(6, 5)
  1923  
  1924  	case ASLLV:
  1925  		return OP(7, 0)
  1926  	case ASRLV:
  1927  		return OP(7, 2)
  1928  	case ASRAV:
  1929  		return OP(7, 3)
  1930  	case -ASLLV:
  1931  		return OP(7, 4)
  1932  	case -ASRLV:
  1933  		return OP(7, 6)
  1934  	case -ASRAV:
  1935  		return OP(7, 7)
  1936  
  1937  	case ATEQ:
  1938  		return OP(6, 4)
  1939  	case ATNE:
  1940  		return OP(6, 6)
  1941  	case -ALL:
  1942  		return SP(6, 0)
  1943  	case -ALLV:
  1944  		return SP(6, 4)
  1945  	case ASC:
  1946  		return SP(7, 0)
  1947  	case ASCV:
  1948  		return SP(7, 4)
  1949  	}
  1950  
  1951  	if a < 0 {
  1952  		c.ctxt.Diag("bad irr opcode -%v", -a)
  1953  	} else {
  1954  		c.ctxt.Diag("bad irr opcode %v", a)
  1955  	}
  1956  	return 0
  1957  }
  1958  
  1959  func vshift(a obj.As) bool {
  1960  	switch a {
  1961  	case ASLLV,
  1962  		ASRLV,
  1963  		ASRAV:
  1964  		return true
  1965  	}
  1966  	return false
  1967  }