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