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