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