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