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