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