Source file src/cmd/internal/obj/loong64/asm.go

     1  // Copyright 2022 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package loong64
     6  
     7  import (
     8  	"cmd/internal/obj"
     9  	"cmd/internal/objabi"
    10  	"fmt"
    11  	"log"
    12  	"math/bits"
    13  	"slices"
    14  )
    15  
    16  // ctxt0 holds state while assembling a single function.
    17  // Each function gets a fresh ctxt0.
    18  // This allows for multiple functions to be safely concurrently assembled.
    19  type ctxt0 struct {
    20  	ctxt       *obj.Link
    21  	newprog    obj.ProgAlloc
    22  	cursym     *obj.LSym
    23  	autosize   int32
    24  	instoffset int64
    25  	pc         int64
    26  }
    27  
    28  // Instruction layout.
    29  
    30  const (
    31  	FuncAlign = 4
    32  	loopAlign = 16
    33  )
    34  
    35  type Optab struct {
    36  	as    obj.As
    37  	from1 uint8
    38  	reg   uint8
    39  	from3 uint8
    40  	to1   uint8
    41  	to2   uint8
    42  	type_ int8
    43  	size  int8
    44  	param int16
    45  	flag  uint8
    46  }
    47  
    48  const (
    49  	NOTUSETMP = 1 << iota // p expands to multiple instructions, but does NOT use REGTMP
    50  
    51  	// branchLoopHead marks loop entry.
    52  	// Used to insert padding for under-aligned loops.
    53  	branchLoopHead
    54  )
    55  
    56  var optab = []Optab{
    57  	{obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, C_NONE, 0, 0, 0, 0},
    58  
    59  	{ASUB, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    60  	{ASUB, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    61  
    62  	{AADD, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    63  	{AADD, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    64  	{AADD, C_US12CON, C_REG, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
    65  	{AADD, C_US12CON, C_NONE, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
    66  	{AADD, C_U12CON, C_REG, C_NONE, C_REG, C_NONE, 10, 8, 0, 0},
    67  	{AADD, C_U12CON, C_NONE, C_NONE, C_REG, C_NONE, 10, 8, 0, 0},
    68  	{AADD, C_32CON, C_NONE, C_NONE, C_REG, C_NONE, 24, 12, 0, 0},
    69  	{AADD, C_32CON, C_REG, C_NONE, C_REG, C_NONE, 24, 12, 0, 0},
    70  	{AADD, C_32CON20_0, C_REG, C_NONE, C_REG, C_NONE, 26, 8, 0, 0},
    71  	{AADD, C_32CON20_0, C_NONE, C_NONE, C_REG, C_NONE, 26, 8, 0, 0},
    72  
    73  	{AADDV, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    74  	{AADDV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    75  	{AADDV, C_US12CON, C_REG, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
    76  	{AADDV, C_US12CON, C_NONE, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
    77  	{AADDV, C_U12CON, C_REG, C_NONE, C_REG, C_NONE, 10, 8, 0, 0},
    78  	{AADDV, C_U12CON, C_NONE, C_NONE, C_REG, C_NONE, 10, 8, 0, 0},
    79  	{AADDV, C_32CON, C_NONE, C_NONE, C_REG, C_NONE, 24, 12, 0, 0},
    80  	{AADDV, C_32CON, C_REG, C_NONE, C_REG, C_NONE, 24, 12, 0, 0},
    81  	{AADDV, C_32CON20_0, C_REG, C_NONE, C_REG, C_NONE, 26, 8, 0, 0},
    82  	{AADDV, C_32CON20_0, C_NONE, C_NONE, C_REG, C_NONE, 26, 8, 0, 0},
    83  	{AADDV, C_DCON, C_NONE, C_NONE, C_REG, C_NONE, 60, 20, 0, 0},
    84  	{AADDV, C_DCON, C_REG, C_NONE, C_REG, C_NONE, 60, 20, 0, 0},
    85  	{AADDV, C_DCON12_0, C_NONE, C_NONE, C_REG, C_NONE, 70, 8, 0, 0},
    86  	{AADDV, C_DCON12_0, C_REG, C_NONE, C_REG, C_NONE, 70, 8, 0, 0},
    87  	{AADDV, C_DCON12_20S, C_NONE, C_NONE, C_REG, C_NONE, 71, 12, 0, 0},
    88  	{AADDV, C_DCON12_20S, C_REG, C_NONE, C_REG, C_NONE, 71, 12, 0, 0},
    89  	{AADDV, C_DCON32_12S, C_NONE, C_NONE, C_REG, C_NONE, 72, 16, 0, 0},
    90  	{AADDV, C_DCON32_12S, C_REG, C_NONE, C_REG, C_NONE, 72, 16, 0, 0},
    91  
    92  	{AAND, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    93  	{AAND, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    94  	{AAND, C_UU12CON, C_REG, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
    95  	{AAND, C_UU12CON, C_NONE, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
    96  	{AAND, C_S12CON, C_REG, C_NONE, C_REG, C_NONE, 10, 8, 0, 0},
    97  	{AAND, C_S12CON, C_NONE, C_NONE, C_REG, C_NONE, 10, 8, 0, 0},
    98  	{AAND, C_32CON, C_REG, C_NONE, C_REG, C_NONE, 24, 12, 0, 0},
    99  	{AAND, C_32CON, C_NONE, C_NONE, C_REG, C_NONE, 24, 12, 0, 0},
   100  	{AAND, C_32CON20_0, C_REG, C_NONE, C_REG, C_NONE, 26, 8, 0, 0},
   101  	{AAND, C_32CON20_0, C_NONE, C_NONE, C_REG, C_NONE, 26, 8, 0, 0},
   102  	{AAND, C_DCON, C_NONE, C_NONE, C_REG, C_NONE, 60, 20, 0, 0},
   103  	{AAND, C_DCON, C_REG, C_NONE, C_REG, C_NONE, 60, 20, 0, 0},
   104  	{AAND, C_DCON12_0, C_NONE, C_NONE, C_REG, C_NONE, 70, 8, 0, 0},
   105  	{AAND, C_DCON12_0, C_REG, C_NONE, C_REG, C_NONE, 70, 8, 0, 0},
   106  	{AAND, C_DCON12_20S, C_NONE, C_NONE, C_REG, C_NONE, 71, 12, 0, 0},
   107  	{AAND, C_DCON12_20S, C_REG, C_NONE, C_REG, C_NONE, 71, 12, 0, 0},
   108  	{AAND, C_DCON32_12S, C_NONE, C_NONE, C_REG, C_NONE, 72, 16, 0, 0},
   109  	{AAND, C_DCON32_12S, C_REG, C_NONE, C_REG, C_NONE, 72, 16, 0, 0},
   110  
   111  	{ASLL, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
   112  	{ASLL, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
   113  	{ASLL, C_U5CON, C_REG, C_NONE, C_REG, C_NONE, 16, 4, 0, 0},
   114  	{ASLL, C_U5CON, C_NONE, C_NONE, C_REG, C_NONE, 16, 4, 0, 0},
   115  	{ASLLV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
   116  	{ASLLV, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
   117  	{ASLLV, C_U6CON, C_REG, C_NONE, C_REG, C_NONE, 16, 4, 0, 0},
   118  	{ASLLV, C_U6CON, C_NONE, C_NONE, C_REG, C_NONE, 16, 4, 0, 0},
   119  
   120  	{AADDV16, C_32CON, C_REG, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
   121  	{AADDV16, C_32CON, C_NONE, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
   122  
   123  	// memory access
   124  	{AMOVB, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
   125  	{AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
   126  	{AMOVB, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
   127  	{AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
   128  	{AMOVB, C_REG, C_NONE, C_NONE, C_SOREG_12, C_NONE, 7, 4, REGZERO, 0},
   129  	{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG_32, C_NONE, 35, 12, REGZERO, 0},
   130  	{AMOVB, C_SOREG_12, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
   131  	{AMOVB, C_LOREG_32, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
   132  	{AMOVB, C_REG, C_NONE, C_NONE, C_ROFF, C_NONE, 20, 4, 0, 0},
   133  	{AMOVB, C_ROFF, C_NONE, C_NONE, C_REG, C_NONE, 21, 4, 0, 0},
   134  	// variable access
   135  	{AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
   136  	{AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
   137  	// TLS access
   138  	{AMOVB, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
   139  	{AMOVB, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
   140  	{AMOVB, C_REG, C_NONE, C_NONE, C_TLS_IE, C_NONE, 56, 16, 0, 0},
   141  	{AMOVB, C_TLS_IE, C_NONE, C_NONE, C_REG, C_NONE, 57, 16, 0, 0},
   142  	// moving data between registers
   143  	{AMOVB, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 1, 4, 0, 0},
   144  
   145  	// memory access
   146  	{AMOVBU, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
   147  	{AMOVBU, C_REG, C_NONE, C_NONE, C_SOREG_12, C_NONE, 7, 4, REGZERO, 0},
   148  	{AMOVBU, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
   149  	{AMOVBU, C_SOREG_12, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
   150  	{AMOVBU, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
   151  	{AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG_32, C_NONE, 35, 12, REGZERO, 0},
   152  	{AMOVBU, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
   153  	{AMOVBU, C_LOREG_32, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
   154  	{AMOVBU, C_ROFF, C_NONE, C_NONE, C_REG, C_NONE, 21, 4, 0, 0},
   155  	// variable access
   156  	{AMOVBU, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
   157  	{AMOVBU, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
   158  	// TLS access
   159  	{AMOVBU, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
   160  	{AMOVBU, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
   161  	{AMOVBU, C_REG, C_NONE, C_NONE, C_TLS_IE, C_NONE, 56, 16, 0, 0},
   162  	{AMOVBU, C_TLS_IE, C_NONE, C_NONE, C_REG, C_NONE, 57, 16, 0, 0},
   163  	// moving data between registers
   164  	{AMOVBU, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 1, 4, 0, 0},
   165  
   166  	// memory access
   167  	{AMOVW, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
   168  	{AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
   169  	{AMOVW, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
   170  	{AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
   171  	{AMOVW, C_REG, C_NONE, C_NONE, C_SOREG_12, C_NONE, 7, 4, REGZERO, 0},
   172  	{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG_32, C_NONE, 35, 12, REGZERO, 0},
   173  	{AMOVW, C_SOREG_12, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
   174  	{AMOVW, C_LOREG_32, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
   175  	{AMOVW, C_REG, C_NONE, C_NONE, C_ROFF, C_NONE, 20, 4, 0, 0},
   176  	{AMOVW, C_ROFF, C_NONE, C_NONE, C_REG, C_NONE, 21, 4, 0, 0},
   177  	// variable access
   178  	{AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
   179  	{AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
   180  	// TLS access
   181  	{AMOVW, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
   182  	{AMOVW, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
   183  	{AMOVW, C_REG, C_NONE, C_NONE, C_TLS_IE, C_NONE, 56, 16, 0, 0},
   184  	{AMOVW, C_TLS_IE, C_NONE, C_NONE, C_REG, C_NONE, 57, 16, 0, 0},
   185  	// moving data between registers
   186  	{AMOVW, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 1, 4, 0, 0},
   187  	{AMOVW, C_REG, C_NONE, C_NONE, C_FREG, C_NONE, 30, 4, 0, 0},
   188  	{AMOVW, C_FREG, C_NONE, C_NONE, C_REG, C_NONE, 30, 4, 0, 0},
   189  	// immediate load
   190  	{AMOVW, C_12CON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGZERO, 0},
   191  	{AMOVW, C_32CON, C_NONE, C_NONE, C_REG, C_NONE, 19, 8, 0, NOTUSETMP},
   192  	{AMOVW, C_32CON20_0, C_NONE, C_NONE, C_REG, C_NONE, 25, 4, 0, 0},
   193  	{AMOVW, C_12CON, C_NONE, C_NONE, C_FREG, C_NONE, 34, 8, 0, 0},
   194  	// get a stack address
   195  	{AMOVW, C_SACON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGSP, 0},
   196  	{AMOVW, C_LACON, C_NONE, C_NONE, C_REG, C_NONE, 27, 12, REGSP, 0},
   197  
   198  	// memory access
   199  	{AMOVV, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
   200  	{AMOVV, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
   201  	{AMOVV, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
   202  	{AMOVV, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
   203  	{AMOVV, C_REG, C_NONE, C_NONE, C_SOREG_12, C_NONE, 7, 4, REGZERO, 0},
   204  	{AMOVV, C_REG, C_NONE, C_NONE, C_LOREG_32, C_NONE, 35, 12, REGZERO, 0},
   205  	{AMOVV, C_SOREG_12, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
   206  	{AMOVV, C_LOREG_32, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
   207  	{AMOVV, C_REG, C_NONE, C_NONE, C_ROFF, C_NONE, 20, 4, 0, 0},
   208  	{AMOVV, C_ROFF, C_NONE, C_NONE, C_REG, C_NONE, 21, 4, 0, 0},
   209  	// variable access, need relocation
   210  	{AMOVV, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
   211  	{AMOVV, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
   212  	// TLS access
   213  	{AMOVV, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
   214  	{AMOVV, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
   215  	{AMOVV, C_REG, C_NONE, C_NONE, C_TLS_IE, C_NONE, 56, 16, 0, 0},
   216  	{AMOVV, C_TLS_IE, C_NONE, C_NONE, C_REG, C_NONE, 57, 16, 0, 0},
   217  	// moving data between registers
   218  	{AMOVV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 1, 4, 0, 0},
   219  	{AMOVV, C_FCCREG, C_NONE, C_NONE, C_REG, C_NONE, 30, 4, 0, 0},
   220  	{AMOVV, C_FCSRREG, C_NONE, C_NONE, C_REG, C_NONE, 30, 4, 0, 0},
   221  	{AMOVV, C_REG, C_NONE, C_NONE, C_FCCREG, C_NONE, 30, 4, 0, 0},
   222  	{AMOVV, C_REG, C_NONE, C_NONE, C_FREG, C_NONE, 30, 4, 0, 0},
   223  	{AMOVV, C_FREG, C_NONE, C_NONE, C_REG, C_NONE, 30, 4, 0, 0},
   224  	{AMOVV, C_REG, C_NONE, C_NONE, C_FCSRREG, C_NONE, 30, 4, 0, 0},
   225  	{AMOVV, C_FREG, C_NONE, C_NONE, C_FCCREG, C_NONE, 30, 4, 0, 0},
   226  	{AMOVV, C_FCCREG, C_NONE, C_NONE, C_FREG, C_NONE, 30, 4, 0, 0},
   227  	// immediate load
   228  	{AMOVV, C_12CON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGZERO, 0},
   229  	{AMOVV, C_32CON, C_NONE, C_NONE, C_REG, C_NONE, 19, 8, 0, NOTUSETMP},
   230  	{AMOVV, C_32CON20_0, C_NONE, C_NONE, C_REG, C_NONE, 25, 4, 0, 0},
   231  	{AMOVV, C_DCON12_0, C_NONE, C_NONE, C_REG, C_NONE, 67, 4, 0, NOTUSETMP},
   232  	{AMOVV, C_DCON12_20S, C_NONE, C_NONE, C_REG, C_NONE, 68, 8, 0, NOTUSETMP},
   233  	{AMOVV, C_DCON32_12S, C_NONE, C_NONE, C_REG, C_NONE, 69, 12, 0, NOTUSETMP},
   234  	{AMOVV, C_DCON, C_NONE, C_NONE, C_REG, C_NONE, 59, 16, 0, NOTUSETMP},
   235  	// get a stack address
   236  	{AMOVV, C_SACON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGSP, 0},
   237  	{AMOVV, C_LACON, C_NONE, C_NONE, C_REG, C_NONE, 27, 12, REGSP, 0},
   238  	// get an external address, need relocation
   239  	{AMOVV, C_EXTADDR, C_NONE, C_NONE, C_REG, C_NONE, 52, 8, 0, NOTUSETMP},
   240  	// get a got address, need relocation
   241  	{AMOVV, C_GOTADDR, C_NONE, C_NONE, C_REG, C_NONE, 65, 8, 0, 0},
   242  
   243  	// memory access
   244  	{AVMOVQ, C_VREG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGZERO, 0},
   245  	{AVMOVQ, C_VREG, C_NONE, C_NONE, C_SOREG_12, C_NONE, 7, 4, REGZERO, 0},
   246  	{AVMOVQ, C_SAUTO, C_NONE, C_NONE, C_VREG, C_NONE, 8, 4, REGZERO, 0},
   247  	{AVMOVQ, C_SOREG_12, C_NONE, C_NONE, C_VREG, C_NONE, 8, 4, REGZERO, 0},
   248  	{AVMOVQ, C_VREG, C_NONE, C_NONE, C_ROFF, C_NONE, 20, 4, 0, 0},
   249  	{AVMOVQ, C_ROFF, C_NONE, C_NONE, C_VREG, C_NONE, 21, 4, 0, 0},
   250  	{AVMOVQ, C_SOREG_12, C_NONE, C_NONE, C_ARNG, C_NONE, 42, 4, 0, 0}, // vldrepl.{b/h/w/d}
   251  	{AVMOVQ, C_ELEM, C_NONE, C_NONE, C_SOREG_12, C_NONE, 43, 4, 0, 0}, // vstelm.{b/h/w/d}
   252  	// moving data between registers
   253  	{AVMOVQ, C_VREG, C_NONE, C_NONE, C_VREG, C_NONE, 1, 4, 0, 0},
   254  	{AVMOVQ, C_REG, C_NONE, C_NONE, C_ELEM, C_NONE, 39, 4, 0, 0},  // vinsgr2vr.{b/h/w/d}
   255  	{AVMOVQ, C_ELEM, C_NONE, C_NONE, C_REG, C_NONE, 40, 4, 0, 0},  // vpickve2gr.{b/h/w/d}
   256  	{AVMOVQ, C_ELEM, C_NONE, C_NONE, C_ARNG, C_NONE, 40, 4, 0, 0}, // vreplvei.{b/h/w/d}
   257  	{AVMOVQ, C_REG, C_NONE, C_NONE, C_ARNG, C_NONE, 41, 4, 0, 0},  // vreplgr2vr.{b/h/w/d}
   258  
   259  	// memory access
   260  	{AXVMOVQ, C_XREG, C_NONE, C_NONE, C_SOREG_12, C_NONE, 7, 4, REGZERO, 0},
   261  	{AXVMOVQ, C_XREG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGZERO, 0},
   262  	{AXVMOVQ, C_SOREG_12, C_NONE, C_NONE, C_XREG, C_NONE, 8, 4, REGZERO, 0},
   263  	{AXVMOVQ, C_SAUTO, C_NONE, C_NONE, C_XREG, C_NONE, 8, 4, REGZERO, 0},
   264  	{AXVMOVQ, C_XREG, C_NONE, C_NONE, C_ROFF, C_NONE, 20, 4, 0, 0},
   265  	{AXVMOVQ, C_ROFF, C_NONE, C_NONE, C_XREG, C_NONE, 21, 4, 0, 0},
   266  	{AXVMOVQ, C_SOREG_12, C_NONE, C_NONE, C_ARNG, C_NONE, 42, 4, 0, 0}, // xvldrepl.{b/h/w/d}
   267  	{AXVMOVQ, C_ELEM, C_NONE, C_NONE, C_SOREG_12, C_NONE, 43, 4, 0, 0}, // xvstelm.{b/h/w/d}
   268  	// moving data between registers
   269  	{AXVMOVQ, C_XREG, C_NONE, C_NONE, C_XREG, C_NONE, 1, 4, 0, 0},
   270  	{AXVMOVQ, C_REG, C_NONE, C_NONE, C_ELEM, C_NONE, 39, 4, 0, 0},  // vinsgr2vr.{b/h/w/d}
   271  	{AXVMOVQ, C_XREG, C_NONE, C_NONE, C_ELEM, C_NONE, 39, 4, 0, 0}, // xvinsve0.{w/d}
   272  	{AXVMOVQ, C_ELEM, C_NONE, C_NONE, C_REG, C_NONE, 40, 4, 0, 0},  // vpickve2gr.{b/h/w/d}
   273  	{AXVMOVQ, C_ELEM, C_NONE, C_NONE, C_XREG, C_NONE, 40, 4, 0, 0}, // xvpickve.{w/d}
   274  	{AXVMOVQ, C_REG, C_NONE, C_NONE, C_ARNG, C_NONE, 41, 4, 0, 0},  // xvreplgr2vr.{b/h/w/d}
   275  	{AXVMOVQ, C_XREG, C_NONE, C_NONE, C_ARNG, C_NONE, 41, 4, 0, 0}, // xvreplve0.{b/h/w/d/q}
   276  
   277  	// memory access
   278  	{AMOVWP, C_REG, C_NONE, C_NONE, C_SOREG_16, C_NONE, 73, 4, 0, 0},
   279  	{AMOVWP, C_REG, C_NONE, C_NONE, C_LOREG_32, C_NONE, 73, 12, 0, 0},
   280  	{AMOVWP, C_REG, C_NONE, C_NONE, C_LOREG_64, C_NONE, 73, 24, 0, 0},
   281  	{AMOVWP, C_SOREG_16, C_NONE, C_NONE, C_REG, C_NONE, 74, 4, 0, 0},
   282  	{AMOVWP, C_LOREG_32, C_NONE, C_NONE, C_REG, C_NONE, 74, 12, 0, 0},
   283  	{AMOVWP, C_LOREG_64, C_NONE, C_NONE, C_REG, C_NONE, 74, 24, 0, 0},
   284  
   285  	// condition branch
   286  	{ABEQ, C_REG, C_REG, C_NONE, C_BRAN, C_NONE, 6, 4, 0, 0},
   287  	{ABEQ, C_REG, C_NONE, C_NONE, C_BRAN, C_NONE, 6, 4, 0, 0},
   288  	{ABLEZ, C_REG, C_NONE, C_NONE, C_BRAN, C_NONE, 6, 4, 0, 0},
   289  	{ABFPT, C_NONE, C_NONE, C_NONE, C_BRAN, C_NONE, 6, 4, 0, 0},
   290  	{ABFPT, C_FCCREG, C_NONE, C_NONE, C_BRAN, C_NONE, 6, 4, 0, 0},
   291  	// jmp and call
   292  	{AJMP, C_NONE, C_NONE, C_NONE, C_BRAN, C_NONE, 11, 4, 0, 0},        // b
   293  	{AJAL, C_NONE, C_NONE, C_NONE, C_BRAN, C_NONE, 11, 4, 0, 0},        // bl
   294  	{AJMP, C_NONE, C_NONE, C_NONE, C_ZOREG, C_NONE, 18, 4, REGZERO, 0}, // jirl r0, rj, 0
   295  	{AJAL, C_NONE, C_NONE, C_NONE, C_ZOREG, C_NONE, 18, 4, REGLINK, 0}, // jirl r1, rj, 0
   296  
   297  	{ABSTRPICKW, C_U6CON, C_REG, C_U6CON, C_REG, C_NONE, 17, 4, 0, 0},
   298  	{ABSTRPICKW, C_U6CON, C_REG, C_ZCON, C_REG, C_NONE, 17, 4, 0, 0},
   299  	{ABSTRPICKW, C_ZCON, C_REG, C_ZCON, C_REG, C_NONE, 17, 4, 0, 0},
   300  
   301  	// preload
   302  	{APRELD, C_SOREG_12, C_U5CON, C_NONE, C_NONE, C_NONE, 47, 4, 0, 0},
   303  	{APRELDX, C_SOREG_16, C_DCON, C_U5CON, C_NONE, C_NONE, 48, 20, 0, 0},
   304  
   305  	{AMASKEQZ, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
   306  
   307  	{ACMPEQF, C_FREG, C_FREG, C_NONE, C_FCCREG, C_NONE, 2, 4, 0, 0},
   308  
   309  	{ARDTIMELW, C_NONE, C_NONE, C_NONE, C_REG, C_REG, 62, 4, 0, 0},
   310  
   311  	{AALSLV, C_U3CON, C_REG, C_REG, C_REG, C_NONE, 64, 4, 0, 0},
   312  
   313  	{AAMSWAPW, C_REG, C_NONE, C_NONE, C_ZOREG, C_REG, 66, 4, 0, 0},
   314  
   315  	{ASCQ, C_REG, C_REG, C_NONE, C_ZOREG, C_NONE, 45, 4, 0, 0},
   316  	{ALLACQW, C_ZOREG, C_NONE, C_NONE, C_REG, C_NONE, 46, 4, 0, 0},
   317  	{ASCRELW, C_REG, C_NONE, C_NONE, C_ZOREG, C_NONE, 46, 4, 0, 0},
   318  
   319  	{ASYSCALL, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 5, 4, 0, 0},
   320  	{ASYSCALL, C_U15CON, C_NONE, C_NONE, C_NONE, C_NONE, 5, 4, 0, 0},
   321  
   322  	{AFMADDF, C_FREG, C_FREG, C_NONE, C_FREG, C_NONE, 37, 4, 0, 0},
   323  	{AFMADDF, C_FREG, C_FREG, C_FREG, C_FREG, C_NONE, 37, 4, 0, 0},
   324  
   325  	{AADDF, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 2, 4, 0, 0},
   326  	{AADDF, C_FREG, C_FREG, C_NONE, C_FREG, C_NONE, 2, 4, 0, 0},
   327  
   328  	{AFSEL, C_FCCREG, C_FREG, C_FREG, C_FREG, C_NONE, 33, 4, 0, 0},
   329  	{AFSEL, C_FCCREG, C_FREG, C_NONE, C_FREG, C_NONE, 33, 4, 0, 0},
   330  
   331  	{ACLOW, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 9, 4, 0, 0},
   332  	{AABSF, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 9, 4, 0, 0},
   333  
   334  	{AVSETEQV, C_VREG, C_NONE, C_NONE, C_FCCREG, C_NONE, 9, 4, 0, 0},
   335  	{AXVSETEQV, C_XREG, C_NONE, C_NONE, C_FCCREG, C_NONE, 9, 4, 0, 0},
   336  
   337  	{AVPCNTB, C_VREG, C_NONE, C_NONE, C_VREG, C_NONE, 9, 4, 0, 0},
   338  	{AXVPCNTB, C_XREG, C_NONE, C_NONE, C_XREG, C_NONE, 9, 4, 0, 0},
   339  
   340  	// memory access
   341  	{AMOVF, C_SOREG_12, C_NONE, C_NONE, C_FREG, C_NONE, 28, 4, REGZERO, 0},
   342  	{AMOVF, C_LOREG_32, C_NONE, C_NONE, C_FREG, C_NONE, 28, 12, REGZERO, 0},
   343  	{AMOVF, C_FREG, C_NONE, C_NONE, C_SOREG_12, C_NONE, 29, 4, REGZERO, 0},
   344  	{AMOVF, C_FREG, C_NONE, C_NONE, C_LOREG_32, C_NONE, 29, 12, REGZERO, 0},
   345  	{AMOVF, C_FREG, C_NONE, C_NONE, C_ROFF, C_NONE, 20, 4, 0, 0},
   346  	{AMOVF, C_ROFF, C_NONE, C_NONE, C_FREG, C_NONE, 21, 4, 0, 0},
   347  	// variable access
   348  	{AMOVF, C_FREG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
   349  	{AMOVF, C_ADDR, C_NONE, C_NONE, C_FREG, C_NONE, 51, 8, 0, 0},
   350  	// moving data between registers
   351  	{AMOVF, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 9, 4, 0, 0},
   352  	// load data from stack
   353  	{AMOVF, C_SAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 28, 4, REGSP, 0},
   354  	{AMOVF, C_LAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 28, 12, REGSP, 0},
   355  	// store data to stack
   356  	{AMOVF, C_FREG, C_NONE, C_NONE, C_SAUTO, C_NONE, 29, 4, REGSP, 0},
   357  	{AMOVF, C_FREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 29, 12, REGSP, 0},
   358  
   359  	{AVSHUFB, C_VREG, C_VREG, C_VREG, C_VREG, C_NONE, 37, 4, 0, 0},
   360  	{AXVSHUFB, C_XREG, C_XREG, C_XREG, C_XREG, C_NONE, 37, 4, 0, 0},
   361  
   362  	{AVSEQB, C_VREG, C_VREG, C_NONE, C_VREG, C_NONE, 2, 4, 0, 0},
   363  	{AVSEQB, C_S5CON, C_VREG, C_NONE, C_VREG, C_NONE, 22, 4, 0, 0},
   364  	{AXVSEQB, C_XREG, C_XREG, C_NONE, C_XREG, C_NONE, 2, 4, 0, 0},
   365  	{AXVSEQB, C_S5CON, C_XREG, C_NONE, C_XREG, C_NONE, 22, 4, 0, 0},
   366  
   367  	{AVSLTBU, C_VREG, C_VREG, C_NONE, C_VREG, C_NONE, 2, 4, 0, 0},
   368  	{AVSLTBU, C_U5CON, C_VREG, C_NONE, C_VREG, C_NONE, 31, 4, 0, 0},
   369  	{AXVSLTBU, C_XREG, C_XREG, C_NONE, C_XREG, C_NONE, 2, 4, 0, 0},
   370  	{AXVSLTBU, C_U5CON, C_XREG, C_NONE, C_XREG, C_NONE, 31, 4, 0, 0},
   371  
   372  	{AVANDB, C_U8CON, C_VREG, C_NONE, C_VREG, C_NONE, 23, 4, 0, 0},
   373  	{AVANDB, C_U8CON, C_NONE, C_NONE, C_VREG, C_NONE, 23, 4, 0, 0},
   374  	{AXVANDB, C_U8CON, C_XREG, C_NONE, C_XREG, C_NONE, 23, 4, 0, 0},
   375  	{AXVANDB, C_U8CON, C_NONE, C_NONE, C_XREG, C_NONE, 23, 4, 0, 0},
   376  
   377  	{AVADDB, C_VREG, C_VREG, C_NONE, C_VREG, C_NONE, 2, 4, 0, 0},
   378  	{AVADDB, C_VREG, C_NONE, C_NONE, C_VREG, C_NONE, 2, 4, 0, 0},
   379  	{AXVADDB, C_XREG, C_XREG, C_NONE, C_XREG, C_NONE, 2, 4, 0, 0},
   380  	{AXVADDB, C_XREG, C_NONE, C_NONE, C_XREG, C_NONE, 2, 4, 0, 0},
   381  
   382  	{AVADDBU, C_U5CON, C_VREG, C_NONE, C_VREG, C_NONE, 31, 4, 0, 0},
   383  	{AVADDBU, C_U5CON, C_NONE, C_NONE, C_VREG, C_NONE, 31, 4, 0, 0},
   384  	{AXVADDBU, C_U5CON, C_XREG, C_NONE, C_XREG, C_NONE, 31, 4, 0, 0},
   385  	{AXVADDBU, C_U5CON, C_NONE, C_NONE, C_XREG, C_NONE, 31, 4, 0, 0},
   386  
   387  	{AVSLLB, C_VREG, C_VREG, C_NONE, C_VREG, C_NONE, 2, 4, 0, 0},
   388  	{AVSLLB, C_VREG, C_NONE, C_NONE, C_VREG, C_NONE, 2, 4, 0, 0},
   389  	{AVSLLB, C_U3CON, C_VREG, C_NONE, C_VREG, C_NONE, 13, 4, 0, 0},
   390  	{AVSLLB, C_U3CON, C_NONE, C_NONE, C_VREG, C_NONE, 13, 4, 0, 0},
   391  	{AXVSLLB, C_XREG, C_XREG, C_NONE, C_XREG, C_NONE, 2, 4, 0, 0},
   392  	{AXVSLLB, C_XREG, C_NONE, C_NONE, C_XREG, C_NONE, 2, 4, 0, 0},
   393  	{AXVSLLB, C_U3CON, C_XREG, C_NONE, C_XREG, C_NONE, 13, 4, 0, 0},
   394  	{AXVSLLB, C_U3CON, C_NONE, C_NONE, C_XREG, C_NONE, 13, 4, 0, 0},
   395  
   396  	{AVSLLH, C_VREG, C_VREG, C_NONE, C_VREG, C_NONE, 2, 4, 0, 0},
   397  	{AVSLLH, C_VREG, C_NONE, C_NONE, C_VREG, C_NONE, 2, 4, 0, 0},
   398  	{AVSLLH, C_U4CON, C_VREG, C_NONE, C_VREG, C_NONE, 14, 4, 0, 0},
   399  	{AVSLLH, C_U4CON, C_NONE, C_NONE, C_VREG, C_NONE, 14, 4, 0, 0},
   400  	{AXVSLLH, C_XREG, C_XREG, C_NONE, C_XREG, C_NONE, 2, 4, 0, 0},
   401  	{AXVSLLH, C_XREG, C_NONE, C_NONE, C_XREG, C_NONE, 2, 4, 0, 0},
   402  	{AXVSLLH, C_U4CON, C_XREG, C_NONE, C_XREG, C_NONE, 14, 4, 0, 0},
   403  	{AXVSLLH, C_U4CON, C_NONE, C_NONE, C_XREG, C_NONE, 14, 4, 0, 0},
   404  
   405  	{AVSLLW, C_VREG, C_VREG, C_NONE, C_VREG, C_NONE, 2, 4, 0, 0},
   406  	{AVSLLW, C_VREG, C_NONE, C_NONE, C_VREG, C_NONE, 2, 4, 0, 0},
   407  	{AVSLLW, C_U5CON, C_VREG, C_NONE, C_VREG, C_NONE, 31, 4, 0, 0},
   408  	{AVSLLW, C_U5CON, C_NONE, C_NONE, C_VREG, C_NONE, 31, 4, 0, 0},
   409  	{AXVSLLW, C_XREG, C_XREG, C_NONE, C_XREG, C_NONE, 2, 4, 0, 0},
   410  	{AXVSLLW, C_XREG, C_NONE, C_NONE, C_XREG, C_NONE, 2, 4, 0, 0},
   411  	{AXVSLLW, C_U5CON, C_XREG, C_NONE, C_XREG, C_NONE, 31, 4, 0, 0},
   412  	{AXVSLLW, C_U5CON, C_NONE, C_NONE, C_XREG, C_NONE, 31, 4, 0, 0},
   413  
   414  	{AVSLLV, C_VREG, C_VREG, C_NONE, C_VREG, C_NONE, 2, 4, 0, 0},
   415  	{AVSLLV, C_VREG, C_NONE, C_NONE, C_VREG, C_NONE, 2, 4, 0, 0},
   416  	{AVSLLV, C_U6CON, C_VREG, C_NONE, C_VREG, C_NONE, 32, 4, 0, 0},
   417  	{AVSLLV, C_U6CON, C_NONE, C_NONE, C_VREG, C_NONE, 32, 4, 0, 0},
   418  	{AXVSLLV, C_XREG, C_XREG, C_NONE, C_XREG, C_NONE, 2, 4, 0, 0},
   419  	{AXVSLLV, C_XREG, C_NONE, C_NONE, C_XREG, C_NONE, 2, 4, 0, 0},
   420  	{AXVSLLV, C_U6CON, C_XREG, C_NONE, C_XREG, C_NONE, 32, 4, 0, 0},
   421  	{AXVSLLV, C_U6CON, C_NONE, C_NONE, C_XREG, C_NONE, 32, 4, 0, 0},
   422  
   423  	{AWORD, C_32CON, C_NONE, C_NONE, C_NONE, C_NONE, 38, 4, 0, 0},
   424  	{AWORD, C_DCON, C_NONE, C_NONE, C_NONE, C_NONE, 61, 4, 0, 0},
   425  
   426  	{ANOOP, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 49, 4, 0, 0},
   427  
   428  	{ANEGW, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
   429  	{ATEQ, C_US12CON, C_REG, C_NONE, C_REG, C_NONE, 15, 8, 0, 0},
   430  	{ATEQ, C_US12CON, C_NONE, C_NONE, C_REG, C_NONE, 15, 8, 0, 0},
   431  
   432  	{obj.APCALIGN, C_U12CON, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
   433  	{obj.APCDATA, C_32CON, C_NONE, C_NONE, C_32CON, C_NONE, 0, 0, 0, 0},
   434  	{obj.APCDATA, C_DCON, C_NONE, C_NONE, C_DCON, C_NONE, 0, 0, 0, 0},
   435  	{obj.AFUNCDATA, C_U12CON, C_NONE, C_NONE, C_ADDR, C_NONE, 0, 0, 0, 0},
   436  	{obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
   437  	{obj.ANOP, C_32CON, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0}, // nop variants, see #40689
   438  	{obj.ANOP, C_DCON, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},  // nop variants, see #40689
   439  	{obj.ANOP, C_REG, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
   440  	{obj.ANOP, C_FREG, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
   441  }
   442  
   443  func IsAtomicInst(as obj.As) bool {
   444  	_, ok := atomicInst[as]
   445  
   446  	return ok
   447  }
   448  
   449  // pcAlignPadLength returns the number of bytes required to align pc to alignedValue,
   450  // reporting an error if alignedValue is not a power of two or is out of range.
   451  func pcAlignPadLength(ctxt *obj.Link, pc int64, alignedValue int64) int {
   452  	if !((alignedValue&(alignedValue-1) == 0) && 8 <= alignedValue && alignedValue <= 2048) {
   453  		ctxt.Diag("alignment value of an instruction must be a power of two and in the range [8, 2048], got %d\n", alignedValue)
   454  	}
   455  	return int(-pc & (alignedValue - 1))
   456  }
   457  
   458  var oprange [ALAST & obj.AMask][]Optab
   459  
   460  var xcmp [C_NCLASS][C_NCLASS]bool
   461  
   462  func span0(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
   463  	if ctxt.Retpoline {
   464  		ctxt.Diag("-spectre=ret not supported on loong64")
   465  		ctxt.Retpoline = false // don't keep printing
   466  	}
   467  
   468  	p := cursym.Func().Text
   469  	if p == nil || p.Link == nil { // handle external functions and ELF section symbols
   470  		return
   471  	}
   472  
   473  	c := ctxt0{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset + ctxt.Arch.FixedFrameSize)}
   474  
   475  	if oprange[AOR&obj.AMask] == nil {
   476  		c.ctxt.Diag("loong64 ops not initialized, call loong64.buildop first")
   477  	}
   478  
   479  	pc := int64(0)
   480  	p.Pc = pc
   481  
   482  	var m int
   483  	var o *Optab
   484  	for p = p.Link; p != nil; p = p.Link {
   485  		p.Pc = pc
   486  		o = c.oplook(p)
   487  		m = int(o.size)
   488  		if m == 0 {
   489  			switch p.As {
   490  			case obj.APCALIGN:
   491  				alignedValue := p.From.Offset
   492  				m = pcAlignPadLength(ctxt, pc, alignedValue)
   493  				// Update the current text symbol alignment value.
   494  				if int16(alignedValue) > cursym.Align {
   495  					cursym.Align = int16(alignedValue)
   496  				}
   497  				break
   498  			case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
   499  				continue
   500  			default:
   501  				c.ctxt.Diag("zero-width instruction\n%v", p)
   502  			}
   503  		}
   504  
   505  		pc += int64(m)
   506  	}
   507  
   508  	c.cursym.Size = pc
   509  
   510  	// mark loop entry instructions for padding
   511  	// loop entrances are defined as targets of backward branches
   512  	for p = c.cursym.Func().Text.Link; p != nil; p = p.Link {
   513  		if q := p.To.Target(); q != nil && q.Pc < p.Pc {
   514  			q.Mark |= branchLoopHead
   515  		}
   516  	}
   517  
   518  	// Run these passes until convergence.
   519  	for {
   520  		rescan := false
   521  		pc = 0
   522  		prev := c.cursym.Func().Text
   523  		for p = prev.Link; p != nil; prev, p = p, p.Link {
   524  			p.Pc = pc
   525  			o = c.oplook(p)
   526  
   527  			// Prepend a PCALIGN $loopAlign to each of the loop heads
   528  			// that need padding, if not already done so (because this
   529  			// pass may execute more than once).
   530  			//
   531  			// This needs to come before any pass that look at pc,
   532  			// because pc will be adjusted if padding happens.
   533  			if p.Mark&branchLoopHead != 0 && pc&(loopAlign-1) != 0 &&
   534  				!(prev.As == obj.APCALIGN && prev.From.Offset >= loopAlign) {
   535  				q := c.newprog()
   536  				prev.Link = q
   537  				q.Link = p
   538  				q.Pc = pc
   539  				q.As = obj.APCALIGN
   540  				q.From.Type = obj.TYPE_CONST
   541  				q.From.Offset = loopAlign
   542  				// Don't associate the synthesized PCALIGN with
   543  				// the original source position, for deterministic
   544  				// mapping between source and corresponding asm.
   545  				// q.Pos = p.Pos
   546  
   547  				// Manually make the PCALIGN come into effect,
   548  				// since this loop iteration is for p.
   549  				pc += int64(pcAlignPadLength(ctxt, pc, loopAlign))
   550  				p.Pc = pc
   551  				rescan = true
   552  			}
   553  
   554  			// very large conditional branches
   555  			//
   556  			// if any procedure is large enough to generate a large SBRA branch, then
   557  			// generate extra passes putting branches around jmps to fix. this is rare.
   558  			if o.type_ == 6 && p.To.Target() != nil {
   559  				otxt := p.To.Target().Pc - pc
   560  
   561  				// On loong64, the immediate value field of the conditional branch instructions
   562  				// BFPT and BFPT is 21 bits, and the others are 16 bits. The jump target address
   563  				// is to logically shift the immediate value in the instruction code to the left
   564  				// by 2 bits and then sign extend.
   565  				bound := int64(1 << (18 - 1))
   566  
   567  				switch p.As {
   568  				case ABFPT, ABFPF:
   569  					bound = int64(1 << (23 - 1))
   570  				}
   571  
   572  				if otxt < -bound || otxt >= bound {
   573  					q := c.newprog()
   574  					q.Link = p.Link
   575  					p.Link = q
   576  					q.As = AJMP
   577  					q.Pos = p.Pos
   578  					q.To.Type = obj.TYPE_BRANCH
   579  					q.To.SetTarget(p.To.Target())
   580  					p.To.SetTarget(q)
   581  					q = c.newprog()
   582  					q.Link = p.Link
   583  					p.Link = q
   584  					q.As = AJMP
   585  					q.Pos = p.Pos
   586  					q.To.Type = obj.TYPE_BRANCH
   587  					q.To.SetTarget(q.Link.Link)
   588  					rescan = true
   589  				}
   590  			}
   591  
   592  			m = int(o.size)
   593  			if m == 0 {
   594  				switch p.As {
   595  				case obj.APCALIGN:
   596  					alignedValue := p.From.Offset
   597  					m = pcAlignPadLength(ctxt, pc, alignedValue)
   598  					break
   599  				case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
   600  					continue
   601  				default:
   602  					c.ctxt.Diag("zero-width instruction\n%v", p)
   603  				}
   604  			}
   605  
   606  			pc += int64(m)
   607  		}
   608  
   609  		c.cursym.Size = pc
   610  
   611  		if !rescan {
   612  			break
   613  		}
   614  	}
   615  
   616  	pc += -pc & (FuncAlign - 1)
   617  	c.cursym.Size = pc
   618  
   619  	// lay out the code, emitting code and data relocations.
   620  
   621  	c.cursym.Grow(c.cursym.Size)
   622  
   623  	bp := c.cursym.P
   624  	var i int32
   625  	var out [6]uint32
   626  	for p := c.cursym.Func().Text.Link; p != nil; p = p.Link {
   627  		c.pc = p.Pc
   628  		o = c.oplook(p)
   629  		if int(o.size) > 4*len(out) {
   630  			log.Fatalf("out array in span0 is too small, need at least %d for %v", o.size/4, p)
   631  		}
   632  		if p.As == obj.APCALIGN {
   633  			alignedValue := p.From.Offset
   634  			v := pcAlignPadLength(c.ctxt, p.Pc, alignedValue)
   635  			for i = 0; i < int32(v/4); i++ {
   636  				// emit ANOOP instruction by the padding size
   637  				c.ctxt.Arch.ByteOrder.PutUint32(bp, OP_12IRR(c.opirr(AAND), 0, 0, 0))
   638  				bp = bp[4:]
   639  			}
   640  			continue
   641  		}
   642  		c.asmout(p, o, out[:])
   643  		for i = 0; i < int32(o.size/4); i++ {
   644  			c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
   645  			bp = bp[4:]
   646  		}
   647  	}
   648  
   649  	// Mark nonpreemptible instruction sequences.
   650  	// We use REGTMP as a scratch register during call injection,
   651  	// so instruction sequences that use REGTMP are unsafe to
   652  	// preempt asynchronously.
   653  	obj.MarkUnsafePoints(c.ctxt, c.cursym.Func().Text, c.newprog, c.isUnsafePoint, c.isRestartable)
   654  
   655  	// Now that we know byte offsets, we can generate jump table entries.
   656  	for _, jt := range cursym.Func().JumpTables {
   657  		for i, p := range jt.Targets {
   658  			// The ith jumptable entry points to the p.Pc'th
   659  			// byte in the function symbol s.
   660  			jt.Sym.WriteAddr(ctxt, int64(i)*8, 8, cursym, p.Pc)
   661  		}
   662  	}
   663  }
   664  
   665  // isUnsafePoint returns whether p is an unsafe point.
   666  func (c *ctxt0) isUnsafePoint(p *obj.Prog) bool {
   667  	// If p explicitly uses REGTMP, it's unsafe to preempt, because the
   668  	// preemption sequence clobbers REGTMP.
   669  	return p.From.Reg == REGTMP || p.To.Reg == REGTMP || p.Reg == REGTMP
   670  }
   671  
   672  // isRestartable returns whether p is a multi-instruction sequence that,
   673  // if preempted, can be restarted.
   674  func (c *ctxt0) isRestartable(p *obj.Prog) bool {
   675  	if c.isUnsafePoint(p) {
   676  		return false
   677  	}
   678  	// If p is a multi-instruction sequence with uses REGTMP inserted by
   679  	// the assembler in order to materialize a large constant/offset, we
   680  	// can restart p (at the start of the instruction sequence), recompute
   681  	// the content of REGTMP, upon async preemption. Currently, all cases
   682  	// of assembler-inserted REGTMP fall into this category.
   683  	// If p doesn't use REGTMP, it can be simply preempted, so we don't
   684  	// mark it.
   685  	o := c.oplook(p)
   686  	return o.size > 4 && o.flag&NOTUSETMP == 0
   687  }
   688  
   689  func isint32(v int64) bool {
   690  	return int64(int32(v)) == v
   691  }
   692  
   693  func (c *ctxt0) aclass(a *obj.Addr) int {
   694  	switch a.Type {
   695  	case obj.TYPE_NONE:
   696  		return C_NONE
   697  
   698  	case obj.TYPE_REG:
   699  		return c.rclass(a.Reg)
   700  
   701  	case obj.TYPE_MEM:
   702  		switch a.Name {
   703  		case obj.NAME_EXTERN,
   704  			obj.NAME_STATIC:
   705  			if a.Sym == nil {
   706  				break
   707  			}
   708  			c.instoffset = a.Offset
   709  			if a.Sym.Type == objabi.STLSBSS {
   710  				if c.ctxt.Flag_shared {
   711  					return C_TLS_IE
   712  				} else {
   713  					return C_TLS_LE
   714  				}
   715  			}
   716  			return C_ADDR
   717  
   718  		case obj.NAME_AUTO:
   719  			if a.Reg == REGSP {
   720  				// unset base register for better printing, since
   721  				// a.Offset is still relative to pseudo-SP.
   722  				a.Reg = obj.REG_NONE
   723  			}
   724  			c.instoffset = int64(c.autosize) + a.Offset
   725  			if c.instoffset >= -BIG_12 && c.instoffset < BIG_12 {
   726  				return C_SAUTO
   727  			}
   728  			return C_LAUTO
   729  
   730  		case obj.NAME_PARAM:
   731  			if a.Reg == REGSP {
   732  				// unset base register for better printing, since
   733  				// a.Offset is still relative to pseudo-FP.
   734  				a.Reg = obj.REG_NONE
   735  			}
   736  			c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.Arch.FixedFrameSize
   737  			if c.instoffset >= -BIG_12 && c.instoffset < BIG_12 {
   738  				return C_SAUTO
   739  			}
   740  			return C_LAUTO
   741  
   742  		case obj.NAME_NONE:
   743  			if a.Index != 0 {
   744  				if a.Offset != 0 {
   745  					return C_GOK
   746  				}
   747  				// register offset
   748  				return C_ROFF
   749  			}
   750  
   751  			c.instoffset = a.Offset
   752  			if c.instoffset == 0 {
   753  				return C_ZOREG
   754  			}
   755  			if c.instoffset >= -BIG_8 && c.instoffset < BIG_8 {
   756  				return C_SOREG_8
   757  			} else if c.instoffset >= -BIG_9 && c.instoffset < BIG_9 {
   758  				return C_SOREG_9
   759  			} else if c.instoffset >= -BIG_10 && c.instoffset < BIG_10 {
   760  				return C_SOREG_10
   761  			} else if c.instoffset >= -BIG_11 && c.instoffset < BIG_11 {
   762  				return C_SOREG_11
   763  			} else if c.instoffset >= -BIG_12 && c.instoffset < BIG_12 {
   764  				return C_SOREG_12
   765  			} else if c.instoffset >= -BIG_16 && c.instoffset < BIG_16 {
   766  				return C_SOREG_16
   767  			} else if c.instoffset >= -BIG_32 && c.instoffset < BIG_32 {
   768  				return C_LOREG_32
   769  			} else {
   770  				return C_LOREG_64
   771  			}
   772  
   773  		case obj.NAME_GOTREF:
   774  			return C_GOTADDR
   775  		}
   776  
   777  		return C_GOK
   778  
   779  	case obj.TYPE_TEXTSIZE:
   780  		return C_TEXTSIZE
   781  
   782  	case obj.TYPE_CONST,
   783  		obj.TYPE_ADDR:
   784  		switch a.Name {
   785  		case obj.NAME_NONE:
   786  			c.instoffset = a.Offset
   787  			if a.Reg != 0 {
   788  				if -BIG_12 <= c.instoffset && c.instoffset <= BIG_12 {
   789  					return C_SACON
   790  				}
   791  				if isint32(c.instoffset) {
   792  					return C_LACON
   793  				}
   794  				return C_DACON
   795  			}
   796  
   797  		case obj.NAME_EXTERN,
   798  			obj.NAME_STATIC:
   799  			s := a.Sym
   800  			if s == nil {
   801  				return C_GOK
   802  			}
   803  
   804  			c.instoffset = a.Offset
   805  			if s.Type == objabi.STLSBSS {
   806  				c.ctxt.Diag("taking address of TLS variable is not supported")
   807  			}
   808  			return C_EXTADDR
   809  
   810  		case obj.NAME_AUTO:
   811  			if a.Reg == REGSP {
   812  				// unset base register for better printing, since
   813  				// a.Offset is still relative to pseudo-SP.
   814  				a.Reg = obj.REG_NONE
   815  			}
   816  			c.instoffset = int64(c.autosize) + a.Offset
   817  			if c.instoffset >= -BIG_12 && c.instoffset < BIG_12 {
   818  				return C_SACON
   819  			}
   820  			return C_LACON
   821  
   822  		case obj.NAME_PARAM:
   823  			if a.Reg == REGSP {
   824  				// unset base register for better printing, since
   825  				// a.Offset is still relative to pseudo-FP.
   826  				a.Reg = obj.REG_NONE
   827  			}
   828  			c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.Arch.FixedFrameSize
   829  			if c.instoffset >= -BIG_12 && c.instoffset < BIG_12 {
   830  				return C_SACON
   831  			}
   832  			return C_LACON
   833  
   834  		default:
   835  			return C_GOK
   836  		}
   837  
   838  		if c.instoffset != int64(int32(c.instoffset)) {
   839  			return dconClass(c.instoffset)
   840  		}
   841  
   842  		if c.instoffset >= 0 {
   843  			sbits := bits.Len64(uint64(c.instoffset))
   844  			switch {
   845  			case sbits <= 8:
   846  				return C_ZCON + sbits
   847  			case sbits <= 12:
   848  				if c.instoffset <= 0x7ff {
   849  					return C_US12CON
   850  				}
   851  				return C_U12CON
   852  			case sbits <= 13:
   853  				if c.instoffset&0xfff == 0 {
   854  					return C_U13CON20_0
   855  				}
   856  				return C_U13CON
   857  			case sbits <= 15:
   858  				if c.instoffset&0xfff == 0 {
   859  					return C_U15CON20_0
   860  				}
   861  				return C_U15CON
   862  			}
   863  		} else {
   864  			sbits := bits.Len64(uint64(^c.instoffset))
   865  			switch {
   866  			case sbits < 5:
   867  				return C_S5CON
   868  			case sbits < 12:
   869  				return C_S12CON
   870  			case sbits < 13:
   871  				if c.instoffset&0xfff == 0 {
   872  					return C_S13CON20_0
   873  				}
   874  				return C_S13CON
   875  			}
   876  		}
   877  
   878  		if c.instoffset&0xfff == 0 {
   879  			return C_32CON20_0
   880  		}
   881  		return C_32CON
   882  
   883  	case obj.TYPE_BRANCH:
   884  		return C_BRAN
   885  	}
   886  
   887  	return C_GOK
   888  }
   889  
   890  // The constants here define the data characteristics within the bit field range.
   891  //
   892  //	ALL1: The data in the bit field is all 1
   893  //	ALL0: The data in the bit field is all 0
   894  //	ST1: The data in the bit field starts with 1, but not all 1
   895  //	ST0: The data in the bit field starts with 0, but not all 0
   896  const (
   897  	ALL1 = iota
   898  	ALL0
   899  	ST1
   900  	ST0
   901  )
   902  
   903  // mask returns the mask of the specified bit field, which is used to help determine
   904  // the data characteristics of the immediate value at the specified bit.
   905  func mask(suf int8, len int8) (uint64, uint64) {
   906  	if len == 12 {
   907  		if suf == 0 {
   908  			return 0xfff, 0x800
   909  		} else { // suf == 52
   910  			return 0xfff0000000000000, 0x8000000000000000
   911  		}
   912  	} else { // len == 20
   913  		if suf == 12 {
   914  			return 0xfffff000, 0x80000000
   915  		} else { // suf == 32
   916  			return 0xfffff00000000, 0x8000000000000
   917  		}
   918  	}
   919  }
   920  
   921  // bitField return a number represent status of val in bit field
   922  //
   923  //	suf: The starting bit of the bit field
   924  //	len: The length of the bit field
   925  func bitField(val int64, suf int8, len int8) int8 {
   926  	mask1, mask2 := mask(suf, len)
   927  	if uint64(val)&mask1 == mask1 {
   928  		return ALL1
   929  	} else if uint64(val)&mask1 == 0x0 {
   930  		return ALL0
   931  	} else if uint64(val)&mask2 == mask2 {
   932  		return ST1
   933  	} else {
   934  		return ST0
   935  	}
   936  }
   937  
   938  // Loading an immediate value larger than 32 bits requires four instructions
   939  // on loong64 (lu12i.w + ori + lu32i.d + lu52i.d), but in some special cases,
   940  // we can use the sign extension and zero extension features of the instruction
   941  // to fill in the high-order data (all 0 or all 1), which can save one to
   942  // three instructions.
   943  //
   944  //	| 63 ~ 52 | 51 ~ 32 | 31 ~ 12 | 11 ~ 0 |
   945  //	| lu52i.d | lu32i.d | lu12i.w |   ori  |
   946  func dconClass(offset int64) int {
   947  	tzb := bits.TrailingZeros64(uint64(offset))
   948  	hi12 := bitField(offset, 52, 12)
   949  	hi20 := bitField(offset, 32, 20)
   950  	lo20 := bitField(offset, 12, 20)
   951  	lo12 := bitField(offset, 0, 12)
   952  	if tzb >= 52 {
   953  		return C_DCON12_0 // lu52i.d
   954  	}
   955  	if tzb >= 32 {
   956  		if ((hi20 == ALL1 || hi20 == ST1) && hi12 == ALL1) || ((hi20 == ALL0 || hi20 == ST0) && hi12 == ALL0) {
   957  			return C_DCON20S_0 // addi.w + lu32i.d
   958  		}
   959  		return C_DCON32_0 // addi.w + lu32i.d + lu52i.d
   960  	}
   961  	if tzb >= 12 {
   962  		if lo20 == ST1 || lo20 == ALL1 {
   963  			if hi20 == ALL1 {
   964  				return C_DCON12_20S // lu12i.w + lu52i.d
   965  			}
   966  			if (hi20 == ST1 && hi12 == ALL1) || ((hi20 == ST0 || hi20 == ALL0) && hi12 == ALL0) {
   967  				return C_DCON20S_20 // lu12i.w + lu32i.d
   968  			}
   969  			return C_DCON32_20 // lu12i.w + lu32i.d + lu52i.d
   970  		}
   971  		if hi20 == ALL0 {
   972  			return C_DCON12_20S // lu12i.w + lu52i.d
   973  		}
   974  		if (hi20 == ST0 && hi12 == ALL0) || ((hi20 == ST1 || hi20 == ALL1) && hi12 == ALL1) {
   975  			return C_DCON20S_20 // lu12i.w + lu32i.d
   976  		}
   977  		return C_DCON32_20 // lu12i.w + lu32i.d + lu52i.d
   978  	}
   979  	if lo12 == ST1 || lo12 == ALL1 {
   980  		if lo20 == ALL1 {
   981  			if hi20 == ALL1 {
   982  				return C_DCON12_12S // addi.d + lu52i.d
   983  			}
   984  			if (hi20 == ST1 && hi12 == ALL1) || ((hi20 == ST0 || hi20 == ALL0) && hi12 == ALL0) {
   985  				return C_DCON20S_12S // addi.w + lu32i.d
   986  			}
   987  			return C_DCON32_12S // addi.w + lu32i.d + lu52i.d
   988  		}
   989  		if lo20 == ST1 {
   990  			if hi20 == ALL1 {
   991  
   992  				return C_DCON12_32S // lu12i.w + ori + lu52i.d
   993  			}
   994  			if (hi20 == ST1 && hi12 == ALL1) || ((hi20 == ST0 || hi20 == ALL0) && hi12 == ALL0) {
   995  				return C_DCON20S_32 // lu12i.w + ori + lu32i.d
   996  			}
   997  			return C_DCON // lu12i.w + ori + lu32i.d + lu52i.d
   998  		}
   999  		if lo20 == ALL0 {
  1000  			if hi20 == ALL0 {
  1001  				return C_DCON12_12U // ori + lu52i.d
  1002  			}
  1003  			if ((hi20 == ST1 || hi20 == ALL1) && hi12 == ALL1) || (hi20 == ST0 && hi12 == ALL0) {
  1004  				return C_DCON20S_12U // ori + lu32i.d
  1005  			}
  1006  			return C_DCON32_12U // ori + lu32i.d + lu52i.d
  1007  		}
  1008  		if hi20 == ALL0 {
  1009  			return C_DCON12_32S // lu12i.w + ori + lu52i.d
  1010  		}
  1011  		if ((hi20 == ST1 || hi20 == ALL1) && hi12 == ALL1) || (hi20 == ST0 && hi12 == ALL0) {
  1012  			return C_DCON20S_32 // lu12i.w + ori + lu32i.d
  1013  		}
  1014  		return C_DCON // lu12i.w + ori + lu32i.d + lu52i.d
  1015  	}
  1016  	if lo20 == ALL0 {
  1017  		if hi20 == ALL0 {
  1018  			return C_DCON12_12U // ori + lu52i.d
  1019  		}
  1020  		if ((hi20 == ST1 || hi20 == ALL1) && hi12 == ALL1) || (hi20 == ST0 && hi12 == ALL0) {
  1021  			return C_DCON20S_12U // ori + lu32i.d
  1022  		}
  1023  		return C_DCON32_12U // ori + lu32i.d + lu52i.d
  1024  	}
  1025  	if lo20 == ST1 || lo20 == ALL1 {
  1026  		if hi20 == ALL1 {
  1027  			return C_DCON12_32S // lu12i.w + ori + lu52i.d
  1028  		}
  1029  		if (hi20 == ST1 && hi12 == ALL1) || ((hi20 == ST0 || hi20 == ALL0) && hi12 == ALL0) {
  1030  			return C_DCON20S_32 // lu12i.w + ori + lu32i.d
  1031  		}
  1032  		return C_DCON
  1033  	}
  1034  	if hi20 == ALL0 {
  1035  		return C_DCON12_32S // lu12i.w + ori + lu52i.d
  1036  	}
  1037  	if ((hi20 == ST1 || hi20 == ALL1) && hi12 == ALL1) || (hi20 == ST0 && hi12 == ALL0) {
  1038  		return C_DCON20S_32 // lu12i.w + ori + lu32i.d
  1039  	}
  1040  	return C_DCON
  1041  }
  1042  
  1043  // In Loong64,there are 8 CFRs, denoted as fcc0-fcc7.
  1044  // There are 4 FCSRs, denoted as fcsr0-fcsr3.
  1045  func (c *ctxt0) rclass(r int16) int {
  1046  	switch {
  1047  	case REG_R0 <= r && r <= REG_R31:
  1048  		return C_REG
  1049  	case REG_F0 <= r && r <= REG_F31:
  1050  		return C_FREG
  1051  	case REG_FCC0 <= r && r <= REG_FCC7:
  1052  		return C_FCCREG
  1053  	case REG_FCSR0 <= r && r <= REG_FCSR3:
  1054  		return C_FCSRREG
  1055  	case REG_V0 <= r && r <= REG_V31:
  1056  		return C_VREG
  1057  	case REG_X0 <= r && r <= REG_X31:
  1058  		return C_XREG
  1059  	case r >= REG_ARNG && r < REG_ELEM:
  1060  		return C_ARNG
  1061  	case r >= REG_ELEM && r < REG_ELEM_END:
  1062  		return C_ELEM
  1063  	}
  1064  
  1065  	return C_GOK
  1066  }
  1067  
  1068  func oclass(a *obj.Addr) int {
  1069  	return int(a.Class) - 1
  1070  }
  1071  
  1072  func prasm(p *obj.Prog) {
  1073  	fmt.Printf("%v\n", p)
  1074  }
  1075  
  1076  func (c *ctxt0) oplook(p *obj.Prog) *Optab {
  1077  	if oprange[AOR&obj.AMask] == nil {
  1078  		c.ctxt.Diag("loong64 ops not initialized, call loong64.buildop first")
  1079  	}
  1080  
  1081  	restArgsIndex := 0
  1082  	restArgsLen := len(p.RestArgs)
  1083  	if restArgsLen > 2 {
  1084  		c.ctxt.Diag("too many RestArgs: got %v, maximum is 2\n", restArgsLen)
  1085  		return nil
  1086  	}
  1087  
  1088  	restArgsv := [2]int{C_NONE + 1, C_NONE + 1}
  1089  	for i, ap := range p.RestArgs {
  1090  		restArgsv[i] = int(ap.Addr.Class)
  1091  		if restArgsv[i] == 0 {
  1092  			restArgsv[i] = c.aclass(&ap.Addr) + 1
  1093  			ap.Addr.Class = int8(restArgsv[i])
  1094  		}
  1095  	}
  1096  
  1097  	a1 := int(p.Optab)
  1098  	if a1 != 0 {
  1099  		return &optab[a1-1]
  1100  	}
  1101  
  1102  	// first source operand
  1103  	a1 = int(p.From.Class)
  1104  	if a1 == 0 {
  1105  		a1 = c.aclass(&p.From) + 1
  1106  		p.From.Class = int8(a1)
  1107  	}
  1108  	a1--
  1109  
  1110  	// first destination operand
  1111  	a4 := int(p.To.Class)
  1112  	if a4 == 0 {
  1113  		a4 = c.aclass(&p.To) + 1
  1114  		p.To.Class = int8(a4)
  1115  	}
  1116  	a4--
  1117  
  1118  	// 2nd source operand
  1119  	a2 := C_NONE
  1120  	if p.Reg != 0 {
  1121  		a2 = c.rclass(p.Reg)
  1122  	} else if restArgsLen > 0 {
  1123  		a2 = restArgsv[restArgsIndex] - 1
  1124  		restArgsIndex++
  1125  	}
  1126  
  1127  	// 2nd destination operand
  1128  	a5 := C_NONE
  1129  	if p.RegTo2 != 0 {
  1130  		a5 = C_REG
  1131  	}
  1132  
  1133  	// 3rd source operand
  1134  	a3 := C_NONE
  1135  	if restArgsLen > 0 && restArgsIndex < restArgsLen {
  1136  		a3 = restArgsv[restArgsIndex] - 1
  1137  		restArgsIndex++
  1138  	}
  1139  
  1140  	ops := oprange[p.As&obj.AMask]
  1141  	c1 := &xcmp[a1]
  1142  	c2 := &xcmp[a2]
  1143  	c3 := &xcmp[a3]
  1144  	c4 := &xcmp[a4]
  1145  	c5 := &xcmp[a5]
  1146  	for i := range ops {
  1147  		op := &ops[i]
  1148  		if c1[op.from1] && c2[op.reg] && c3[op.from3] && c4[op.to1] && c5[op.to2] {
  1149  			p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
  1150  			return op
  1151  		}
  1152  	}
  1153  
  1154  	c.ctxt.Diag("illegal combination %v %v %v %v %v %v", p.As, DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4), DRconv(a5))
  1155  	prasm(p)
  1156  	// Turn illegal instruction into an UNDEF, avoid crashing in asmout.
  1157  	return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 49, 4, 0, 0}
  1158  }
  1159  
  1160  func cmp(a int, b int) bool {
  1161  	if a == b {
  1162  		return true
  1163  	}
  1164  	switch a {
  1165  	case C_DCON:
  1166  		return cmp(C_32CON, b) || cmp(C_DCON12_20S, b) || cmp(C_DCON32_12S, b) || b == C_DCON12_0
  1167  	case C_32CON:
  1168  		return cmp(C_32CON20_0, b) || cmp(C_U15CON, b) || cmp(C_13CON, b) || cmp(C_12CON, b)
  1169  	case C_32CON20_0:
  1170  		return b == C_U15CON20_0 || b == C_U13CON20_0 || b == C_S13CON20_0 || b == C_ZCON
  1171  	case C_U15CON:
  1172  		return cmp(C_U12CON, b) || b == C_U15CON20_0 || b == C_U13CON20_0 || b == C_U13CON
  1173  	case C_13CON:
  1174  		return cmp(C_U13CON, b) || cmp(C_S13CON, b)
  1175  	case C_U13CON:
  1176  		return cmp(C_12CON, b) || b == C_U13CON20_0
  1177  	case C_S13CON:
  1178  		return cmp(C_12CON, b) || b == C_S13CON20_0
  1179  	case C_12CON:
  1180  		return cmp(C_U12CON, b) || cmp(C_S12CON, b)
  1181  	case C_UU12CON:
  1182  		return cmp(C_U12CON, b)
  1183  	case C_U12CON:
  1184  		return cmp(C_U8CON, b) || b == C_US12CON
  1185  	case C_U8CON:
  1186  		return cmp(C_U7CON, b)
  1187  	case C_U7CON:
  1188  		return cmp(C_U6CON, b)
  1189  	case C_U6CON:
  1190  		return cmp(C_U5CON, b)
  1191  	case C_U5CON:
  1192  		return cmp(C_U4CON, b)
  1193  	case C_U4CON:
  1194  		return cmp(C_U3CON, b)
  1195  	case C_U3CON:
  1196  		return cmp(C_U2CON, b)
  1197  	case C_U2CON:
  1198  		return cmp(C_U1CON, b)
  1199  	case C_U1CON:
  1200  		return cmp(C_ZCON, b)
  1201  	case C_US12CON:
  1202  		return cmp(C_S12CON, b)
  1203  	case C_S12CON:
  1204  		return cmp(C_S5CON, b) || cmp(C_U8CON, b) || b == C_US12CON
  1205  	case C_S5CON:
  1206  		return cmp(C_ZCON, b) || cmp(C_U4CON, b)
  1207  
  1208  	case C_DCON12_20S:
  1209  		if b == C_DCON20S_20 || b == C_DCON12_12S ||
  1210  			b == C_DCON20S_12S || b == C_DCON12_12U ||
  1211  			b == C_DCON20S_12U || b == C_DCON20S_0 {
  1212  			return true
  1213  		}
  1214  
  1215  	case C_DCON32_12S:
  1216  		if b == C_DCON32_20 || b == C_DCON12_32S ||
  1217  			b == C_DCON20S_32 || b == C_DCON32_12U ||
  1218  			b == C_DCON32_0 {
  1219  			return true
  1220  		}
  1221  
  1222  	case C_LACON:
  1223  		return b == C_SACON
  1224  
  1225  	case C_LAUTO:
  1226  		return b == C_SAUTO
  1227  
  1228  	case C_REG:
  1229  		return b == C_ZCON
  1230  
  1231  	case C_LOREG_64:
  1232  		if b == C_ZOREG || b == C_SOREG_8 ||
  1233  			b == C_SOREG_9 || b == C_SOREG_10 ||
  1234  			b == C_SOREG_11 || b == C_SOREG_12 ||
  1235  			b == C_SOREG_16 || b == C_LOREG_32 {
  1236  			return true
  1237  		}
  1238  
  1239  	case C_LOREG_32:
  1240  		return cmp(C_SOREG_16, b)
  1241  
  1242  	case C_SOREG_16:
  1243  		return cmp(C_SOREG_12, b)
  1244  
  1245  	case C_SOREG_12:
  1246  		return cmp(C_SOREG_11, b)
  1247  
  1248  	case C_SOREG_11:
  1249  		return cmp(C_SOREG_10, b)
  1250  
  1251  	case C_SOREG_10:
  1252  		return cmp(C_SOREG_9, b)
  1253  
  1254  	case C_SOREG_9:
  1255  		return cmp(C_SOREG_8, b)
  1256  
  1257  	case C_SOREG_8:
  1258  		return b == C_ZOREG
  1259  	}
  1260  
  1261  	return false
  1262  }
  1263  
  1264  func ocmp(p1, p2 Optab) int {
  1265  	if p1.as != p2.as {
  1266  		return int(p1.as) - int(p2.as)
  1267  	}
  1268  	if p1.from1 != p2.from1 {
  1269  		return int(p1.from1) - int(p2.from1)
  1270  	}
  1271  	if p1.reg != p2.reg {
  1272  		return int(p1.reg) - int(p2.reg)
  1273  	}
  1274  	if p1.to1 != p2.to1 {
  1275  		return int(p1.to1) - int(p2.to1)
  1276  	}
  1277  	return 0
  1278  }
  1279  
  1280  func opset(a, b0 obj.As) {
  1281  	oprange[a&obj.AMask] = oprange[b0]
  1282  }
  1283  
  1284  func buildop(ctxt *obj.Link) {
  1285  	if ctxt.DiagFunc == nil {
  1286  		ctxt.DiagFunc = func(format string, args ...any) {
  1287  			log.Printf(format, args...)
  1288  		}
  1289  	}
  1290  
  1291  	if oprange[AOR&obj.AMask] != nil {
  1292  		// Already initialized; stop now.
  1293  		// This happens in the cmd/asm tests,
  1294  		// each of which re-initializes the arch.
  1295  		return
  1296  	}
  1297  
  1298  	for i := range C_NCLASS {
  1299  		for j := range C_NCLASS {
  1300  			if cmp(j, i) {
  1301  				xcmp[i][j] = true
  1302  			}
  1303  		}
  1304  	}
  1305  
  1306  	slices.SortFunc(optab, ocmp)
  1307  	for i := 0; i < len(optab); i++ {
  1308  		as, start := optab[i].as, i
  1309  		for ; i < len(optab)-1; i++ {
  1310  			if optab[i+1].as != as {
  1311  				break
  1312  			}
  1313  		}
  1314  		r0 := as & obj.AMask
  1315  		oprange[r0] = optab[start : i+1]
  1316  		switch as {
  1317  		default:
  1318  			ctxt.Diag("unknown op in build: %v", as)
  1319  			ctxt.DiagFlush()
  1320  			log.Fatalf("bad code")
  1321  
  1322  		case AABSF:
  1323  			opset(AMOVFD, r0)
  1324  			opset(AMOVDF, r0)
  1325  			opset(AMOVWF, r0)
  1326  			opset(AMOVFW, r0)
  1327  			opset(AMOVWD, r0)
  1328  			opset(AMOVDW, r0)
  1329  			opset(AMOVVF, r0)
  1330  			opset(AMOVVD, r0)
  1331  			opset(AMOVFV, r0)
  1332  			opset(AMOVDV, r0)
  1333  			opset(AFFINTFW, r0)
  1334  			opset(AFFINTFV, r0)
  1335  			opset(AFFINTDW, r0)
  1336  			opset(AFFINTDV, r0)
  1337  			opset(AFTINTWF, r0)
  1338  			opset(AFTINTWD, r0)
  1339  			opset(AFTINTVF, r0)
  1340  			opset(AFTINTVD, r0)
  1341  			opset(AFRINTF, r0)
  1342  			opset(AFRINTD, r0)
  1343  			opset(ANEGF, r0)
  1344  			opset(ANEGD, r0)
  1345  			opset(AABSD, r0)
  1346  			opset(ATRUNCDW, r0)
  1347  			opset(ATRUNCFW, r0)
  1348  			opset(ASQRTF, r0)
  1349  			opset(ASQRTD, r0)
  1350  			opset(AFCLASSF, r0)
  1351  			opset(AFCLASSD, r0)
  1352  			opset(AFLOGBF, r0)
  1353  			opset(AFLOGBD, r0)
  1354  			opset(ATRUNCDV, r0)
  1355  			opset(ATRUNCFV, r0)
  1356  			opset(AFTINTRPWF, r0)
  1357  			opset(AFTINTRPWD, r0)
  1358  			opset(AFTINTRPVF, r0)
  1359  			opset(AFTINTRPVD, r0)
  1360  			opset(AFTINTRMWF, r0)
  1361  			opset(AFTINTRMWD, r0)
  1362  			opset(AFTINTRMVF, r0)
  1363  			opset(AFTINTRMVD, r0)
  1364  			opset(AFTINTRZWF, r0)
  1365  			opset(AFTINTRZWD, r0)
  1366  			opset(AFTINTRZVF, r0)
  1367  			opset(AFTINTRZVD, r0)
  1368  			opset(AFTINTRNEWF, r0)
  1369  			opset(AFTINTRNEWD, r0)
  1370  			opset(AFTINTRNEVF, r0)
  1371  			opset(AFTINTRNEVD, r0)
  1372  
  1373  		case AADD:
  1374  			opset(AADDW, r0)
  1375  			opset(ASGT, r0)
  1376  			opset(ASGTU, r0)
  1377  
  1378  		case AADDV:
  1379  			opset(AADDVU, r0)
  1380  
  1381  		case AADDF:
  1382  			opset(ADIVF, r0)
  1383  			opset(ADIVD, r0)
  1384  			opset(AMULF, r0)
  1385  			opset(AMULD, r0)
  1386  			opset(ASUBF, r0)
  1387  			opset(ASUBD, r0)
  1388  			opset(AADDD, r0)
  1389  			opset(AFMINF, r0)
  1390  			opset(AFMIND, r0)
  1391  			opset(AFMAXF, r0)
  1392  			opset(AFMAXD, r0)
  1393  			opset(AFCOPYSGF, r0)
  1394  			opset(AFCOPYSGD, r0)
  1395  			opset(AFSCALEBF, r0)
  1396  			opset(AFSCALEBD, r0)
  1397  			opset(AFMAXAF, r0)
  1398  			opset(AFMAXAD, r0)
  1399  			opset(AFMINAF, r0)
  1400  			opset(AFMINAD, r0)
  1401  
  1402  		case AFMADDF:
  1403  			opset(AFMADDD, r0)
  1404  			opset(AFMSUBF, r0)
  1405  			opset(AFMSUBD, r0)
  1406  			opset(AFNMADDF, r0)
  1407  			opset(AFNMADDD, r0)
  1408  			opset(AFNMSUBF, r0)
  1409  			opset(AFNMSUBD, r0)
  1410  
  1411  		case AAND:
  1412  			opset(AOR, r0)
  1413  			opset(AXOR, r0)
  1414  			opset(AORN, r0)
  1415  			opset(AANDN, r0)
  1416  
  1417  		case ABEQ:
  1418  			opset(ABNE, r0)
  1419  			opset(ABLT, r0)
  1420  			opset(ABGE, r0)
  1421  			opset(ABGEU, r0)
  1422  			opset(ABLTU, r0)
  1423  
  1424  		case ABLEZ:
  1425  			opset(ABGEZ, r0)
  1426  			opset(ABLTZ, r0)
  1427  			opset(ABGTZ, r0)
  1428  
  1429  		case AMOVB:
  1430  			opset(AMOVH, r0)
  1431  
  1432  		case AMOVBU:
  1433  			opset(AMOVHU, r0)
  1434  			opset(AMOVWU, r0)
  1435  
  1436  		case AMOVWP:
  1437  			opset(AMOVVP, r0)
  1438  			opset(ASC, r0)
  1439  			opset(ASCW, r0)
  1440  			opset(ASCV, r0)
  1441  			opset(ALL, r0)
  1442  			opset(ALLW, r0)
  1443  			opset(ALLV, r0)
  1444  
  1445  		case ASLL:
  1446  			opset(ASRL, r0)
  1447  			opset(ASRA, r0)
  1448  			opset(AROTR, r0)
  1449  
  1450  		case ASLLV:
  1451  			opset(ASRAV, r0)
  1452  			opset(ASRLV, r0)
  1453  			opset(AROTRV, r0)
  1454  
  1455  		case ABSTRPICKW:
  1456  			opset(ABSTRPICKV, r0)
  1457  			opset(ABSTRINSW, r0)
  1458  			opset(ABSTRINSV, r0)
  1459  
  1460  		case ASUB:
  1461  			opset(ASUBW, r0)
  1462  			opset(ANOR, r0)
  1463  			opset(ASUBV, r0)
  1464  			opset(ASUBVU, r0)
  1465  			opset(AMUL, r0)
  1466  			opset(AMULW, r0)
  1467  			opset(AMULH, r0)
  1468  			opset(AMULHU, r0)
  1469  			opset(AREM, r0)
  1470  			opset(AREMW, r0)
  1471  			opset(AREMU, r0)
  1472  			opset(AREMWU, r0)
  1473  			opset(ADIV, r0)
  1474  			opset(ADIVW, r0)
  1475  			opset(ADIVU, r0)
  1476  			opset(ADIVWU, r0)
  1477  			opset(AMULV, r0)
  1478  			opset(AMULVU, r0)
  1479  			opset(AMULHV, r0)
  1480  			opset(AMULHVU, r0)
  1481  			opset(AREMV, r0)
  1482  			opset(AREMVU, r0)
  1483  			opset(ADIVV, r0)
  1484  			opset(ADIVVU, r0)
  1485  			opset(AMULWVW, r0)
  1486  			opset(AMULWVWU, r0)
  1487  
  1488  		case ASYSCALL:
  1489  			opset(ADBAR, r0)
  1490  			opset(AIBAR, r0)
  1491  			opset(ABREAK, r0)
  1492  
  1493  		case ACMPEQF:
  1494  			opset(ACMPGTF, r0)
  1495  			opset(ACMPGTD, r0)
  1496  			opset(ACMPGEF, r0)
  1497  			opset(ACMPGED, r0)
  1498  			opset(ACMPEQD, r0)
  1499  
  1500  		case ABFPT:
  1501  			opset(ABFPF, r0)
  1502  
  1503  		case AALSLV:
  1504  			opset(AALSLW, r0)
  1505  			opset(AALSLWU, r0)
  1506  
  1507  		case ANEGW:
  1508  			opset(ANEGV, r0)
  1509  
  1510  		case AMOVF:
  1511  			opset(AMOVD, r0)
  1512  
  1513  		case AVSHUFB:
  1514  			opset(AVBITSELV, r0)
  1515  
  1516  		case AXVSHUFB:
  1517  			opset(AXVBITSELV, r0)
  1518  
  1519  		case AMOVW,
  1520  			AMOVV,
  1521  			ARFE,
  1522  			AJAL,
  1523  			AJMP,
  1524  			AVMOVQ,
  1525  			AXVMOVQ,
  1526  			AWORD,
  1527  			APRELD,
  1528  			APRELDX,
  1529  			AFSEL,
  1530  			AADDV16,
  1531  			ASCQ,
  1532  			obj.ANOP,
  1533  			obj.ATEXT,
  1534  			obj.AFUNCDATA,
  1535  			obj.APCALIGN,
  1536  			obj.APCDATA:
  1537  			break
  1538  
  1539  		case ARDTIMELW:
  1540  			opset(ARDTIMEHW, r0)
  1541  			opset(ARDTIMED, r0)
  1542  
  1543  		case ACLOW:
  1544  			opset(ACLZW, r0)
  1545  			opset(ACTOW, r0)
  1546  			opset(ACTZW, r0)
  1547  			opset(ACLOV, r0)
  1548  			opset(ACLZV, r0)
  1549  			opset(ACTOV, r0)
  1550  			opset(ACTZV, r0)
  1551  			opset(AREVB2H, r0)
  1552  			opset(AREVB4H, r0)
  1553  			opset(AREVB2W, r0)
  1554  			opset(AREVBV, r0)
  1555  			opset(AREVH2W, r0)
  1556  			opset(AREVHV, r0)
  1557  			opset(ABITREV4B, r0)
  1558  			opset(ABITREV8B, r0)
  1559  			opset(ABITREVW, r0)
  1560  			opset(ABITREVV, r0)
  1561  			opset(AEXTWB, r0)
  1562  			opset(AEXTWH, r0)
  1563  			opset(ACPUCFG, r0)
  1564  
  1565  		case ATEQ:
  1566  			opset(ATNE, r0)
  1567  
  1568  		case AMASKEQZ:
  1569  			opset(AMASKNEZ, r0)
  1570  			opset(ACRCWBW, r0)
  1571  			opset(ACRCWHW, r0)
  1572  			opset(ACRCWWW, r0)
  1573  			opset(ACRCWVW, r0)
  1574  			opset(ACRCCWBW, r0)
  1575  			opset(ACRCCWHW, r0)
  1576  			opset(ACRCCWWW, r0)
  1577  			opset(ACRCCWVW, r0)
  1578  
  1579  		case ANOOP:
  1580  			opset(obj.AUNDEF, r0)
  1581  
  1582  		case AAMSWAPW:
  1583  			for i := range atomicInst {
  1584  				if i == AAMSWAPW {
  1585  					continue
  1586  				}
  1587  				opset(i, r0)
  1588  			}
  1589  
  1590  		case ALLACQW:
  1591  			opset(ALLACQV, r0)
  1592  
  1593  		case ASCRELW:
  1594  			opset(ASCRELV, r0)
  1595  
  1596  		// vseq.b vd, vj, vk
  1597  		// vseqi.b vd, vj, si5
  1598  		case AVSEQB:
  1599  			opset(AVSEQH, r0)
  1600  			opset(AVSEQW, r0)
  1601  			opset(AVSEQV, r0)
  1602  			opset(AVSLTB, r0)
  1603  			opset(AVSLTH, r0)
  1604  			opset(AVSLTW, r0)
  1605  			opset(AVSLTV, r0)
  1606  
  1607  		// xvseq.b xd, xj, xk
  1608  		// xvseqi.b xd, xj, si5
  1609  		case AXVSEQB:
  1610  			opset(AXVSEQH, r0)
  1611  			opset(AXVSEQW, r0)
  1612  			opset(AXVSEQV, r0)
  1613  			opset(AXVSLTB, r0)
  1614  			opset(AXVSLTH, r0)
  1615  			opset(AXVSLTW, r0)
  1616  			opset(AXVSLTV, r0)
  1617  
  1618  		// vslt.bu vd, vj, vk
  1619  		// vslti.bu vd, vj, ui5
  1620  		case AVSLTBU:
  1621  			opset(AVSLTHU, r0)
  1622  			opset(AVSLTWU, r0)
  1623  			opset(AVSLTVU, r0)
  1624  
  1625  		// xvslt.bu xd, xj, xk
  1626  		// xvslti.bu xd, xj, ui5
  1627  		case AXVSLTBU:
  1628  			opset(AXVSLTHU, r0)
  1629  			opset(AXVSLTWU, r0)
  1630  			opset(AXVSLTVU, r0)
  1631  
  1632  		// vandi.b vd, vj, ui8
  1633  		case AVANDB:
  1634  			opset(AVORB, r0)
  1635  			opset(AVXORB, r0)
  1636  			opset(AVNORB, r0)
  1637  			opset(AVSHUF4IB, r0)
  1638  			opset(AVSHUF4IH, r0)
  1639  			opset(AVSHUF4IW, r0)
  1640  			opset(AVSHUF4IV, r0)
  1641  			opset(AVPERMIW, r0)
  1642  			opset(AVEXTRINSB, r0)
  1643  			opset(AVEXTRINSH, r0)
  1644  			opset(AVEXTRINSW, r0)
  1645  			opset(AVEXTRINSV, r0)
  1646  			opset(AVBITSELB, r0)
  1647  
  1648  		// xvandi.b xd, xj, ui8
  1649  		case AXVANDB:
  1650  			opset(AXVORB, r0)
  1651  			opset(AXVXORB, r0)
  1652  			opset(AXVNORB, r0)
  1653  			opset(AXVSHUF4IB, r0)
  1654  			opset(AXVSHUF4IH, r0)
  1655  			opset(AXVSHUF4IW, r0)
  1656  			opset(AXVSHUF4IV, r0)
  1657  			opset(AXVPERMIW, r0)
  1658  			opset(AXVPERMIV, r0)
  1659  			opset(AXVPERMIQ, r0)
  1660  			opset(AXVEXTRINSB, r0)
  1661  			opset(AXVEXTRINSH, r0)
  1662  			opset(AXVEXTRINSW, r0)
  1663  			opset(AXVEXTRINSV, r0)
  1664  			opset(AXVBITSELB, r0)
  1665  
  1666  		// vadd.b vd, vj, vk
  1667  		case AVADDB:
  1668  			opset(AVADDH, r0)
  1669  			opset(AVADDW, r0)
  1670  			opset(AVADDV, r0)
  1671  			opset(AVADDQ, r0)
  1672  			opset(AVSUBB, r0)
  1673  			opset(AVSUBH, r0)
  1674  			opset(AVSUBW, r0)
  1675  			opset(AVSUBV, r0)
  1676  			opset(AVSUBQ, r0)
  1677  			opset(AVSADDB, r0)
  1678  			opset(AVSADDH, r0)
  1679  			opset(AVSADDW, r0)
  1680  			opset(AVSADDV, r0)
  1681  			opset(AVSSUBB, r0)
  1682  			opset(AVSSUBH, r0)
  1683  			opset(AVSSUBW, r0)
  1684  			opset(AVSSUBV, r0)
  1685  			opset(AVSADDBU, r0)
  1686  			opset(AVSADDHU, r0)
  1687  			opset(AVSADDWU, r0)
  1688  			opset(AVSADDVU, r0)
  1689  			opset(AVSSUBBU, r0)
  1690  			opset(AVSSUBHU, r0)
  1691  			opset(AVSSUBWU, r0)
  1692  			opset(AVSSUBVU, r0)
  1693  			opset(AVANDV, r0)
  1694  			opset(AVORV, r0)
  1695  			opset(AVXORV, r0)
  1696  			opset(AVNORV, r0)
  1697  			opset(AVANDNV, r0)
  1698  			opset(AVORNV, r0)
  1699  			opset(AVILVLB, r0)
  1700  			opset(AVILVLH, r0)
  1701  			opset(AVILVLW, r0)
  1702  			opset(AVILVLV, r0)
  1703  			opset(AVILVHB, r0)
  1704  			opset(AVILVHH, r0)
  1705  			opset(AVILVHW, r0)
  1706  			opset(AVILVHV, r0)
  1707  			opset(AVMULB, r0)
  1708  			opset(AVMULH, r0)
  1709  			opset(AVMULW, r0)
  1710  			opset(AVMULV, r0)
  1711  			opset(AVMUHB, r0)
  1712  			opset(AVMUHH, r0)
  1713  			opset(AVMUHW, r0)
  1714  			opset(AVMUHV, r0)
  1715  			opset(AVMUHBU, r0)
  1716  			opset(AVMUHHU, r0)
  1717  			opset(AVMUHWU, r0)
  1718  			opset(AVMUHVU, r0)
  1719  			opset(AVDIVB, r0)
  1720  			opset(AVDIVH, r0)
  1721  			opset(AVDIVW, r0)
  1722  			opset(AVDIVV, r0)
  1723  			opset(AVMODB, r0)
  1724  			opset(AVMODH, r0)
  1725  			opset(AVMODW, r0)
  1726  			opset(AVMODV, r0)
  1727  			opset(AVDIVBU, r0)
  1728  			opset(AVDIVHU, r0)
  1729  			opset(AVDIVWU, r0)
  1730  			opset(AVDIVVU, r0)
  1731  			opset(AVMODBU, r0)
  1732  			opset(AVMODHU, r0)
  1733  			opset(AVMODWU, r0)
  1734  			opset(AVMODVU, r0)
  1735  			opset(AVMULWEVHB, r0)
  1736  			opset(AVMULWEVWH, r0)
  1737  			opset(AVMULWEVVW, r0)
  1738  			opset(AVMULWEVQV, r0)
  1739  			opset(AVMULWODHB, r0)
  1740  			opset(AVMULWODWH, r0)
  1741  			opset(AVMULWODVW, r0)
  1742  			opset(AVMULWODQV, r0)
  1743  			opset(AVMULWEVHBU, r0)
  1744  			opset(AVMULWEVWHU, r0)
  1745  			opset(AVMULWEVVWU, r0)
  1746  			opset(AVMULWEVQVU, r0)
  1747  			opset(AVMULWODHBU, r0)
  1748  			opset(AVMULWODWHU, r0)
  1749  			opset(AVMULWODVWU, r0)
  1750  			opset(AVMULWODQVU, r0)
  1751  			opset(AVMULWEVHBUB, r0)
  1752  			opset(AVMULWEVWHUH, r0)
  1753  			opset(AVMULWEVVWUW, r0)
  1754  			opset(AVMULWEVQVUV, r0)
  1755  			opset(AVMULWODHBUB, r0)
  1756  			opset(AVMULWODWHUH, r0)
  1757  			opset(AVMULWODVWUW, r0)
  1758  			opset(AVMULWODQVUV, r0)
  1759  			opset(AVADDF, r0)
  1760  			opset(AVADDD, r0)
  1761  			opset(AVSUBF, r0)
  1762  			opset(AVSUBD, r0)
  1763  			opset(AVMULF, r0)
  1764  			opset(AVMULD, r0)
  1765  			opset(AVDIVF, r0)
  1766  			opset(AVDIVD, r0)
  1767  			opset(AVSHUFH, r0)
  1768  			opset(AVSHUFW, r0)
  1769  			opset(AVSHUFV, r0)
  1770  			opset(AVADDWEVHB, r0)
  1771  			opset(AVADDWEVWH, r0)
  1772  			opset(AVADDWEVVW, r0)
  1773  			opset(AVADDWEVQV, r0)
  1774  			opset(AVSUBWEVHB, r0)
  1775  			opset(AVSUBWEVWH, r0)
  1776  			opset(AVSUBWEVVW, r0)
  1777  			opset(AVSUBWEVQV, r0)
  1778  			opset(AVADDWODHB, r0)
  1779  			opset(AVADDWODWH, r0)
  1780  			opset(AVADDWODVW, r0)
  1781  			opset(AVADDWODQV, r0)
  1782  			opset(AVSUBWODHB, r0)
  1783  			opset(AVSUBWODWH, r0)
  1784  			opset(AVSUBWODVW, r0)
  1785  			opset(AVSUBWODQV, r0)
  1786  			opset(AVADDWEVHBU, r0)
  1787  			opset(AVADDWEVWHU, r0)
  1788  			opset(AVADDWEVVWU, r0)
  1789  			opset(AVADDWEVQVU, r0)
  1790  			opset(AVSUBWEVHBU, r0)
  1791  			opset(AVSUBWEVWHU, r0)
  1792  			opset(AVSUBWEVVWU, r0)
  1793  			opset(AVSUBWEVQVU, r0)
  1794  			opset(AVADDWODHBU, r0)
  1795  			opset(AVADDWODWHU, r0)
  1796  			opset(AVADDWODVWU, r0)
  1797  			opset(AVADDWODQVU, r0)
  1798  			opset(AVSUBWODHBU, r0)
  1799  			opset(AVSUBWODWHU, r0)
  1800  			opset(AVSUBWODVWU, r0)
  1801  			opset(AVSUBWODQVU, r0)
  1802  			opset(AVMADDB, r0)
  1803  			opset(AVMADDH, r0)
  1804  			opset(AVMADDW, r0)
  1805  			opset(AVMADDV, r0)
  1806  			opset(AVMSUBB, r0)
  1807  			opset(AVMSUBH, r0)
  1808  			opset(AVMSUBW, r0)
  1809  			opset(AVMSUBV, r0)
  1810  			opset(AVMADDWEVHB, r0)
  1811  			opset(AVMADDWEVWH, r0)
  1812  			opset(AVMADDWEVVW, r0)
  1813  			opset(AVMADDWEVQV, r0)
  1814  			opset(AVMADDWODHB, r0)
  1815  			opset(AVMADDWODWH, r0)
  1816  			opset(AVMADDWODVW, r0)
  1817  			opset(AVMADDWODQV, r0)
  1818  			opset(AVMADDWEVHBU, r0)
  1819  			opset(AVMADDWEVWHU, r0)
  1820  			opset(AVMADDWEVVWU, r0)
  1821  			opset(AVMADDWEVQVU, r0)
  1822  			opset(AVMADDWODHBU, r0)
  1823  			opset(AVMADDWODWHU, r0)
  1824  			opset(AVMADDWODVWU, r0)
  1825  			opset(AVMADDWODQVU, r0)
  1826  			opset(AVMADDWEVHBUB, r0)
  1827  			opset(AVMADDWEVWHUH, r0)
  1828  			opset(AVMADDWEVVWUW, r0)
  1829  			opset(AVMADDWEVQVUV, r0)
  1830  			opset(AVMADDWODHBUB, r0)
  1831  			opset(AVMADDWODWHUH, r0)
  1832  			opset(AVMADDWODVWUW, r0)
  1833  			opset(AVMADDWODQVUV, r0)
  1834  
  1835  		// xvadd.b xd, xj, xk
  1836  		case AXVADDB:
  1837  			opset(AXVADDH, r0)
  1838  			opset(AXVADDW, r0)
  1839  			opset(AXVADDV, r0)
  1840  			opset(AXVADDQ, r0)
  1841  			opset(AXVSUBB, r0)
  1842  			opset(AXVSUBH, r0)
  1843  			opset(AXVSUBW, r0)
  1844  			opset(AXVSUBV, r0)
  1845  			opset(AXVSUBQ, r0)
  1846  			opset(AXVSADDB, r0)
  1847  			opset(AXVSADDH, r0)
  1848  			opset(AXVSADDW, r0)
  1849  			opset(AXVSADDV, r0)
  1850  			opset(AXVSSUBB, r0)
  1851  			opset(AXVSSUBH, r0)
  1852  			opset(AXVSSUBW, r0)
  1853  			opset(AXVSSUBV, r0)
  1854  			opset(AXVSADDBU, r0)
  1855  			opset(AXVSADDHU, r0)
  1856  			opset(AXVSADDWU, r0)
  1857  			opset(AXVSADDVU, r0)
  1858  			opset(AXVSSUBBU, r0)
  1859  			opset(AXVSSUBHU, r0)
  1860  			opset(AXVSSUBWU, r0)
  1861  			opset(AXVSSUBVU, r0)
  1862  			opset(AXVANDV, r0)
  1863  			opset(AXVORV, r0)
  1864  			opset(AXVXORV, r0)
  1865  			opset(AXVNORV, r0)
  1866  			opset(AXVANDNV, r0)
  1867  			opset(AXVORNV, r0)
  1868  			opset(AXVILVLB, r0)
  1869  			opset(AXVILVLH, r0)
  1870  			opset(AXVILVLW, r0)
  1871  			opset(AXVILVLV, r0)
  1872  			opset(AXVILVHB, r0)
  1873  			opset(AXVILVHH, r0)
  1874  			opset(AXVILVHW, r0)
  1875  			opset(AXVILVHV, r0)
  1876  			opset(AXVMULB, r0)
  1877  			opset(AXVMULH, r0)
  1878  			opset(AXVMULW, r0)
  1879  			opset(AXVMULV, r0)
  1880  			opset(AXVMUHB, r0)
  1881  			opset(AXVMUHH, r0)
  1882  			opset(AXVMUHW, r0)
  1883  			opset(AXVMUHV, r0)
  1884  			opset(AXVMUHBU, r0)
  1885  			opset(AXVMUHHU, r0)
  1886  			opset(AXVMUHWU, r0)
  1887  			opset(AXVMUHVU, r0)
  1888  			opset(AXVDIVB, r0)
  1889  			opset(AXVDIVH, r0)
  1890  			opset(AXVDIVW, r0)
  1891  			opset(AXVDIVV, r0)
  1892  			opset(AXVMODB, r0)
  1893  			opset(AXVMODH, r0)
  1894  			opset(AXVMODW, r0)
  1895  			opset(AXVMODV, r0)
  1896  			opset(AXVDIVBU, r0)
  1897  			opset(AXVDIVHU, r0)
  1898  			opset(AXVDIVWU, r0)
  1899  			opset(AXVDIVVU, r0)
  1900  			opset(AXVMODBU, r0)
  1901  			opset(AXVMODHU, r0)
  1902  			opset(AXVMODWU, r0)
  1903  			opset(AXVMODVU, r0)
  1904  			opset(AXVMULWEVHB, r0)
  1905  			opset(AXVMULWEVWH, r0)
  1906  			opset(AXVMULWEVVW, r0)
  1907  			opset(AXVMULWEVQV, r0)
  1908  			opset(AXVMULWODHB, r0)
  1909  			opset(AXVMULWODWH, r0)
  1910  			opset(AXVMULWODVW, r0)
  1911  			opset(AXVMULWODQV, r0)
  1912  			opset(AXVMULWEVHBU, r0)
  1913  			opset(AXVMULWEVWHU, r0)
  1914  			opset(AXVMULWEVVWU, r0)
  1915  			opset(AXVMULWEVQVU, r0)
  1916  			opset(AXVMULWODHBU, r0)
  1917  			opset(AXVMULWODWHU, r0)
  1918  			opset(AXVMULWODVWU, r0)
  1919  			opset(AXVMULWODQVU, r0)
  1920  			opset(AXVMULWEVHBUB, r0)
  1921  			opset(AXVMULWEVWHUH, r0)
  1922  			opset(AXVMULWEVVWUW, r0)
  1923  			opset(AXVMULWEVQVUV, r0)
  1924  			opset(AXVMULWODHBUB, r0)
  1925  			opset(AXVMULWODWHUH, r0)
  1926  			opset(AXVMULWODVWUW, r0)
  1927  			opset(AXVMULWODQVUV, r0)
  1928  			opset(AXVADDF, r0)
  1929  			opset(AXVADDD, r0)
  1930  			opset(AXVSUBF, r0)
  1931  			opset(AXVSUBD, r0)
  1932  			opset(AXVMULF, r0)
  1933  			opset(AXVMULD, r0)
  1934  			opset(AXVDIVF, r0)
  1935  			opset(AXVDIVD, r0)
  1936  			opset(AXVSHUFH, r0)
  1937  			opset(AXVSHUFW, r0)
  1938  			opset(AXVSHUFV, r0)
  1939  			opset(AXVADDWEVHB, r0)
  1940  			opset(AXVADDWEVWH, r0)
  1941  			opset(AXVADDWEVVW, r0)
  1942  			opset(AXVADDWEVQV, r0)
  1943  			opset(AXVSUBWEVHB, r0)
  1944  			opset(AXVSUBWEVWH, r0)
  1945  			opset(AXVSUBWEVVW, r0)
  1946  			opset(AXVSUBWEVQV, r0)
  1947  			opset(AXVADDWODHB, r0)
  1948  			opset(AXVADDWODWH, r0)
  1949  			opset(AXVADDWODVW, r0)
  1950  			opset(AXVADDWODQV, r0)
  1951  			opset(AXVSUBWODHB, r0)
  1952  			opset(AXVSUBWODWH, r0)
  1953  			opset(AXVSUBWODVW, r0)
  1954  			opset(AXVSUBWODQV, r0)
  1955  			opset(AXVADDWEVHBU, r0)
  1956  			opset(AXVADDWEVWHU, r0)
  1957  			opset(AXVADDWEVVWU, r0)
  1958  			opset(AXVADDWEVQVU, r0)
  1959  			opset(AXVSUBWEVHBU, r0)
  1960  			opset(AXVSUBWEVWHU, r0)
  1961  			opset(AXVSUBWEVVWU, r0)
  1962  			opset(AXVSUBWEVQVU, r0)
  1963  			opset(AXVADDWODHBU, r0)
  1964  			opset(AXVADDWODWHU, r0)
  1965  			opset(AXVADDWODVWU, r0)
  1966  			opset(AXVADDWODQVU, r0)
  1967  			opset(AXVSUBWODHBU, r0)
  1968  			opset(AXVSUBWODWHU, r0)
  1969  			opset(AXVSUBWODVWU, r0)
  1970  			opset(AXVSUBWODQVU, r0)
  1971  			opset(AXVMADDB, r0)
  1972  			opset(AXVMADDH, r0)
  1973  			opset(AXVMADDW, r0)
  1974  			opset(AXVMADDV, r0)
  1975  			opset(AXVMSUBB, r0)
  1976  			opset(AXVMSUBH, r0)
  1977  			opset(AXVMSUBW, r0)
  1978  			opset(AXVMSUBV, r0)
  1979  			opset(AXVMADDWEVHB, r0)
  1980  			opset(AXVMADDWEVWH, r0)
  1981  			opset(AXVMADDWEVVW, r0)
  1982  			opset(AXVMADDWEVQV, r0)
  1983  			opset(AXVMADDWODHB, r0)
  1984  			opset(AXVMADDWODWH, r0)
  1985  			opset(AXVMADDWODVW, r0)
  1986  			opset(AXVMADDWODQV, r0)
  1987  			opset(AXVMADDWEVHBU, r0)
  1988  			opset(AXVMADDWEVWHU, r0)
  1989  			opset(AXVMADDWEVVWU, r0)
  1990  			opset(AXVMADDWEVQVU, r0)
  1991  			opset(AXVMADDWODHBU, r0)
  1992  			opset(AXVMADDWODWHU, r0)
  1993  			opset(AXVMADDWODVWU, r0)
  1994  			opset(AXVMADDWODQVU, r0)
  1995  			opset(AXVMADDWEVHBUB, r0)
  1996  			opset(AXVMADDWEVWHUH, r0)
  1997  			opset(AXVMADDWEVVWUW, r0)
  1998  			opset(AXVMADDWEVQVUV, r0)
  1999  			opset(AXVMADDWODHBUB, r0)
  2000  			opset(AXVMADDWODWHUH, r0)
  2001  			opset(AXVMADDWODVWUW, r0)
  2002  			opset(AXVMADDWODQVUV, r0)
  2003  
  2004  		// vpcnt.b vd, vj
  2005  		case AVPCNTB:
  2006  			opset(AVPCNTH, r0)
  2007  			opset(AVPCNTW, r0)
  2008  			opset(AVPCNTV, r0)
  2009  			opset(AVFSQRTF, r0)
  2010  			opset(AVFSQRTD, r0)
  2011  			opset(AVFRECIPF, r0)
  2012  			opset(AVFRECIPD, r0)
  2013  			opset(AVFRSQRTF, r0)
  2014  			opset(AVFRSQRTD, r0)
  2015  			opset(AVNEGB, r0)
  2016  			opset(AVNEGH, r0)
  2017  			opset(AVNEGW, r0)
  2018  			opset(AVNEGV, r0)
  2019  			opset(AVFRINTRNEF, r0)
  2020  			opset(AVFRINTRNED, r0)
  2021  			opset(AVFRINTRZF, r0)
  2022  			opset(AVFRINTRZD, r0)
  2023  			opset(AVFRINTRPF, r0)
  2024  			opset(AVFRINTRPD, r0)
  2025  			opset(AVFRINTRMF, r0)
  2026  			opset(AVFRINTRMD, r0)
  2027  			opset(AVFRINTF, r0)
  2028  			opset(AVFRINTD, r0)
  2029  			opset(AVFCLASSF, r0)
  2030  			opset(AVFCLASSD, r0)
  2031  
  2032  		// xvpcnt.b xd, xj
  2033  		case AXVPCNTB:
  2034  			opset(AXVPCNTH, r0)
  2035  			opset(AXVPCNTW, r0)
  2036  			opset(AXVPCNTV, r0)
  2037  			opset(AXVFSQRTF, r0)
  2038  			opset(AXVFSQRTD, r0)
  2039  			opset(AXVFRECIPF, r0)
  2040  			opset(AXVFRECIPD, r0)
  2041  			opset(AXVFRSQRTF, r0)
  2042  			opset(AXVFRSQRTD, r0)
  2043  			opset(AXVNEGB, r0)
  2044  			opset(AXVNEGH, r0)
  2045  			opset(AXVNEGW, r0)
  2046  			opset(AXVNEGV, r0)
  2047  			opset(AXVFRINTRNEF, r0)
  2048  			opset(AXVFRINTRNED, r0)
  2049  			opset(AXVFRINTRZF, r0)
  2050  			opset(AXVFRINTRZD, r0)
  2051  			opset(AXVFRINTRPF, r0)
  2052  			opset(AXVFRINTRPD, r0)
  2053  			opset(AXVFRINTRMF, r0)
  2054  			opset(AXVFRINTRMD, r0)
  2055  			opset(AXVFRINTF, r0)
  2056  			opset(AXVFRINTD, r0)
  2057  			opset(AXVFCLASSF, r0)
  2058  			opset(AXVFCLASSD, r0)
  2059  
  2060  		// vsll.b vd, vj, vk
  2061  		// vslli.b vd, vj, ui3
  2062  		case AVSLLB:
  2063  			opset(AVSRLB, r0)
  2064  			opset(AVSRAB, r0)
  2065  			opset(AVROTRB, r0)
  2066  			opset(AVBITCLRB, r0)
  2067  			opset(AVBITSETB, r0)
  2068  			opset(AVBITREVB, r0)
  2069  
  2070  		// xvsll.b xd, xj, xk
  2071  		// xvslli.b xd, xj, ui3
  2072  		case AXVSLLB:
  2073  			opset(AXVSRLB, r0)
  2074  			opset(AXVSRAB, r0)
  2075  			opset(AXVROTRB, r0)
  2076  			opset(AXVBITCLRB, r0)
  2077  			opset(AXVBITSETB, r0)
  2078  			opset(AXVBITREVB, r0)
  2079  
  2080  		// vsll.h vd, vj, vk
  2081  		// vslli.h vd, vj, ui4
  2082  		case AVSLLH:
  2083  			opset(AVSRLH, r0)
  2084  			opset(AVSRAH, r0)
  2085  			opset(AVROTRH, r0)
  2086  			opset(AVBITCLRH, r0)
  2087  			opset(AVBITSETH, r0)
  2088  			opset(AVBITREVH, r0)
  2089  
  2090  		// xvsll.h xd, xj, xk
  2091  		// xvslli.h xd, xj, ui4
  2092  		case AXVSLLH:
  2093  			opset(AXVSRLH, r0)
  2094  			opset(AXVSRAH, r0)
  2095  			opset(AXVROTRH, r0)
  2096  			opset(AXVBITCLRH, r0)
  2097  			opset(AXVBITSETH, r0)
  2098  			opset(AXVBITREVH, r0)
  2099  
  2100  		// vsll.w vd, vj, vk
  2101  		// vslli.w vd, vj, ui5
  2102  		case AVSLLW:
  2103  			opset(AVSRLW, r0)
  2104  			opset(AVSRAW, r0)
  2105  			opset(AVROTRW, r0)
  2106  			opset(AVBITCLRW, r0)
  2107  			opset(AVBITSETW, r0)
  2108  			opset(AVBITREVW, r0)
  2109  
  2110  		// xvsll.w xd, xj, xk
  2111  		// xvslli.w xd, xj, ui5
  2112  		case AXVSLLW:
  2113  			opset(AXVSRLW, r0)
  2114  			opset(AXVSRAW, r0)
  2115  			opset(AXVROTRW, r0)
  2116  			opset(AXVBITCLRW, r0)
  2117  			opset(AXVBITSETW, r0)
  2118  			opset(AXVBITREVW, r0)
  2119  
  2120  		// vsll.d vd, vj, vk
  2121  		// vslli.d vd, vj, ui6
  2122  		case AVSLLV:
  2123  			opset(AVSRLV, r0)
  2124  			opset(AVSRAV, r0)
  2125  			opset(AVROTRV, r0)
  2126  			opset(AVBITCLRV, r0)
  2127  			opset(AVBITSETV, r0)
  2128  			opset(AVBITREVV, r0)
  2129  
  2130  		// xvsll.d xd, xj, xk
  2131  		// xvslli.d xd, xj, ui6
  2132  		case AXVSLLV:
  2133  			opset(AXVSRLV, r0)
  2134  			opset(AXVSRAV, r0)
  2135  			opset(AXVROTRV, r0)
  2136  			opset(AXVBITCLRV, r0)
  2137  			opset(AXVBITSETV, r0)
  2138  			opset(AXVBITREVV, r0)
  2139  
  2140  		// vaddi.bu vd, vj, ui5
  2141  		case AVADDBU:
  2142  			opset(AVADDHU, r0)
  2143  			opset(AVADDWU, r0)
  2144  			opset(AVADDVU, r0)
  2145  			opset(AVSUBBU, r0)
  2146  			opset(AVSUBHU, r0)
  2147  			opset(AVSUBWU, r0)
  2148  			opset(AVSUBVU, r0)
  2149  
  2150  		// xvaddi.bu xd, xj, ui5
  2151  		case AXVADDBU:
  2152  			opset(AXVADDHU, r0)
  2153  			opset(AXVADDWU, r0)
  2154  			opset(AXVADDVU, r0)
  2155  			opset(AXVSUBBU, r0)
  2156  			opset(AXVSUBHU, r0)
  2157  			opset(AXVSUBWU, r0)
  2158  			opset(AXVSUBVU, r0)
  2159  
  2160  		// vseteqz.v cd, vj
  2161  		case AVSETEQV:
  2162  			opset(AVSETNEV, r0)
  2163  			opset(AVSETANYEQB, r0)
  2164  			opset(AVSETANYEQH, r0)
  2165  			opset(AVSETANYEQW, r0)
  2166  			opset(AVSETANYEQV, r0)
  2167  			opset(AVSETALLNEB, r0)
  2168  			opset(AVSETALLNEH, r0)
  2169  			opset(AVSETALLNEW, r0)
  2170  			opset(AVSETALLNEV, r0)
  2171  
  2172  		// xvseteqz.v cd, xj
  2173  		case AXVSETEQV:
  2174  			opset(AXVSETNEV, r0)
  2175  			opset(AXVSETANYEQB, r0)
  2176  			opset(AXVSETANYEQH, r0)
  2177  			opset(AXVSETANYEQW, r0)
  2178  			opset(AXVSETANYEQV, r0)
  2179  			opset(AXVSETALLNEB, r0)
  2180  			opset(AXVSETALLNEH, r0)
  2181  			opset(AXVSETALLNEW, r0)
  2182  			opset(AXVSETALLNEV, r0)
  2183  
  2184  		}
  2185  	}
  2186  }
  2187  
  2188  func OP_RRRR(op uint32, r1 uint32, r2 uint32, r3 uint32, r4 uint32) uint32 {
  2189  	return op | (r1&0x1F)<<15 | (r2&0x1F)<<10 | (r3&0x1F)<<5 | (r4 & 0x1F)
  2190  }
  2191  
  2192  // r1 -> rk
  2193  // r2 -> rj
  2194  // r3 -> rd
  2195  func OP_RRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
  2196  	return op | (r1&0x1F)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
  2197  }
  2198  
  2199  // r2 -> rj
  2200  // r3 -> rd
  2201  func OP_RR(op uint32, r2 uint32, r3 uint32) uint32 {
  2202  	return op | (r2&0x1F)<<5 | (r3&0x1F)<<0
  2203  }
  2204  
  2205  func OP_2IRRR(op uint32, i uint32, r2 uint32, r3 uint32, r4 uint32) uint32 {
  2206  	return op | (i&0x3)<<15 | (r2&0x1F)<<10 | (r3&0x1F)<<5 | (r4&0x1F)<<0
  2207  }
  2208  
  2209  func OP_16IR_5I(op uint32, i uint32, r2 uint32) uint32 {
  2210  	return op | (i&0xFFFF)<<10 | (r2&0x1F)<<5 | ((i >> 16) & 0x1F)
  2211  }
  2212  
  2213  func OP_16IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
  2214  	return op | (i&0xFFFF)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
  2215  }
  2216  
  2217  func OP_14IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
  2218  	return op | (i&0x3FFF)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
  2219  }
  2220  
  2221  func OP_12IR_5I(op uint32, i1 uint32, r2 uint32, i2 uint32) uint32 {
  2222  	return op | (i1&0xFFF)<<10 | (r2&0x1F)<<5 | (i2&0x1F)<<0
  2223  }
  2224  
  2225  func OP_12IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
  2226  	return op | (i&0xFFF)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
  2227  }
  2228  
  2229  func OP_11IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
  2230  	return op | (i&0x7FF)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
  2231  }
  2232  
  2233  func OP_10IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
  2234  	return op | (i&0x3FF)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
  2235  }
  2236  
  2237  func OP_9IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
  2238  	return op | (i&0x1FF)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
  2239  }
  2240  
  2241  func OP_8IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
  2242  	return op | (i&0xFF)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
  2243  }
  2244  
  2245  func OP_6IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
  2246  	return op | (i&0x3F)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
  2247  }
  2248  
  2249  func OP_5IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
  2250  	return op | (i&0x1F)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
  2251  }
  2252  
  2253  func OP_4IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
  2254  	return op | (i&0xF)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
  2255  }
  2256  
  2257  func OP_3IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
  2258  	return op | (i&0x7)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
  2259  }
  2260  
  2261  func OP_IR(op uint32, i uint32, r2 uint32) uint32 {
  2262  	return op | (i&0xFFFFF)<<5 | (r2&0x1F)<<0 // ui20, rd5
  2263  }
  2264  
  2265  func OP_15I(op uint32, i uint32) uint32 {
  2266  	return op | (i&0x7FFF)<<0
  2267  }
  2268  
  2269  // i1 -> msb
  2270  // r2 -> rj
  2271  // i3 -> lsb
  2272  // r4 -> rd
  2273  func OP_IRIR(op uint32, i1 uint32, r2 uint32, i3 uint32, r4 uint32) uint32 {
  2274  	return op | (i1 << 16) | (r2&0x1F)<<5 | (i3 << 10) | (r4&0x1F)<<0
  2275  }
  2276  
  2277  // Encoding for the 'b' or 'bl' instruction.
  2278  func OP_B_BL(op uint32, i uint32) uint32 {
  2279  	return op | ((i & 0xFFFF) << 10) | ((i >> 16) & 0x3FF)
  2280  }
  2281  
  2282  func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
  2283  	o1 := uint32(0)
  2284  	o2 := uint32(0)
  2285  	o3 := uint32(0)
  2286  	o4 := uint32(0)
  2287  	o5 := uint32(0)
  2288  	o6 := uint32(0)
  2289  
  2290  	add := AADDVU
  2291  
  2292  	switch o.type_ {
  2293  	default:
  2294  		c.ctxt.Diag("unknown type %d", o.type_)
  2295  		prasm(p)
  2296  
  2297  	case 0: // pseudo ops
  2298  		break
  2299  
  2300  	case 1: // mov rj, rd
  2301  		switch p.As {
  2302  		case AMOVB:
  2303  			o1 = OP_RR(c.oprr(AEXTWB), uint32(p.From.Reg), uint32(p.To.Reg))
  2304  		case AMOVH:
  2305  			o1 = OP_RR(c.oprr(AEXTWH), uint32(p.From.Reg), uint32(p.To.Reg))
  2306  		case AMOVW:
  2307  			o1 = OP_RRR(c.oprrr(ASLL), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg))
  2308  		case AMOVV:
  2309  			o1 = OP_RRR(c.oprrr(AOR), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg))
  2310  		case AMOVBU:
  2311  			o1 = OP_12IRR(c.opirr(AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg))
  2312  		case AMOVHU:
  2313  			o1 = OP_IRIR(c.opirir(ABSTRPICKV), 15, uint32(p.From.Reg), 0, uint32(p.To.Reg))
  2314  		case AMOVWU:
  2315  			o1 = OP_IRIR(c.opirir(ABSTRPICKV), 31, uint32(p.From.Reg), 0, uint32(p.To.Reg))
  2316  		case AVMOVQ:
  2317  			o1 = OP_6IRR(c.opirr(AVSLLV), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
  2318  		case AXVMOVQ:
  2319  			o1 = OP_6IRR(c.opirr(AXVSLLV), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
  2320  		default:
  2321  			c.ctxt.Diag("unexpected encoding\n%v", p)
  2322  		}
  2323  
  2324  	case 2: // add/sub r1,[r2],r3
  2325  		r := int(p.Reg)
  2326  		if p.As == ANEGW || p.As == ANEGV {
  2327  			r = REGZERO
  2328  		}
  2329  		if r == 0 {
  2330  			r = int(p.To.Reg)
  2331  		}
  2332  		o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
  2333  
  2334  	case 3: // mov $soreg, r ==> or/add $i,o,r
  2335  		v := c.regoff(&p.From)
  2336  
  2337  		r := int(p.From.Reg)
  2338  		if r == 0 {
  2339  			r = int(o.param)
  2340  		}
  2341  		a := add
  2342  		if o.from1 == C_12CON && v > 0 {
  2343  			a = AOR
  2344  		}
  2345  
  2346  		o1 = OP_12IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
  2347  
  2348  	case 4: // add $scon,[r1],r2
  2349  		v := c.regoff(&p.From)
  2350  		r := int(p.Reg)
  2351  		if r == 0 {
  2352  			r = int(p.To.Reg)
  2353  		}
  2354  		if p.As == AADDV16 {
  2355  			if v&65535 != 0 {
  2356  				c.ctxt.Diag("%v: the constant must be a multiple of 65536.\n", p)
  2357  			}
  2358  			o1 = OP_16IRR(c.opirr(p.As), uint32(v>>16), uint32(r), uint32(p.To.Reg))
  2359  		} else {
  2360  			o1 = OP_12IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  2361  		}
  2362  
  2363  	case 5: // syscall
  2364  		v := c.regoff(&p.From)
  2365  		o1 = OP_15I(c.opi(p.As), uint32(v))
  2366  
  2367  	case 6: // beq r1,[r2],sbra
  2368  		v := int32(0)
  2369  		if p.To.Target() != nil {
  2370  			v = int32(p.To.Target().Pc-p.Pc) >> 2
  2371  		}
  2372  		as, rd, rj, width := p.As, p.Reg, p.From.Reg, 16
  2373  		switch as {
  2374  		case ABGTZ, ABLEZ:
  2375  			rd, rj = rj, rd
  2376  		case ABFPT, ABFPF:
  2377  			width = 21
  2378  			// FCC0 is the implicit source operand, now that we
  2379  			// don't register-allocate from the FCC bank.
  2380  			if rj == 0 {
  2381  				rj = REG_FCC0
  2382  			}
  2383  		case ABEQ, ABNE:
  2384  			if rd == 0 || rd == REGZERO || rj == REGZERO {
  2385  				// BEQZ/BNEZ can be encoded with 21-bit offsets.
  2386  				width = 21
  2387  				as = -as
  2388  				if rj == 0 || rj == REGZERO {
  2389  					rj = rd
  2390  				}
  2391  			}
  2392  		}
  2393  		switch width {
  2394  		case 21:
  2395  			if (v<<11)>>11 != v {
  2396  				c.ctxt.Diag("21 bit-width, short branch too far\n%v", p)
  2397  			}
  2398  			o1 = OP_16IR_5I(c.opirr(as), uint32(v), uint32(rj))
  2399  		case 16:
  2400  			if (v<<16)>>16 != v {
  2401  				c.ctxt.Diag("16 bit-width, short branch too far\n%v", p)
  2402  			}
  2403  			o1 = OP_16IRR(c.opirr(as), uint32(v), uint32(rj), uint32(rd))
  2404  		default:
  2405  			c.ctxt.Diag("unexpected branch encoding\n%v", p)
  2406  		}
  2407  
  2408  	case 7: // mov r, soreg
  2409  		r := int(p.To.Reg)
  2410  		if r == 0 {
  2411  			r = int(o.param)
  2412  		}
  2413  		v := c.regoff(&p.To)
  2414  		o1 = OP_12IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.From.Reg))
  2415  
  2416  	case 8: // mov soreg, r
  2417  		r := int(p.From.Reg)
  2418  		if r == 0 {
  2419  			r = int(o.param)
  2420  		}
  2421  		v := c.regoff(&p.From)
  2422  		o1 = OP_12IRR(c.opirr(-p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  2423  
  2424  	case 9: // sll r1,[r2],r3
  2425  		o1 = OP_RR(c.oprr(p.As), uint32(p.From.Reg), uint32(p.To.Reg))
  2426  
  2427  	case 10: // add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2
  2428  		v := c.regoff(&p.From)
  2429  		a := AOR
  2430  		if v < 0 {
  2431  			a = AADD
  2432  		}
  2433  		o1 = OP_12IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
  2434  		r := int(p.Reg)
  2435  		if r == 0 {
  2436  			r = int(p.To.Reg)
  2437  		}
  2438  		o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  2439  
  2440  	case 11: // jmp lbra
  2441  		v := int32(0)
  2442  		if p.To.Target() != nil {
  2443  			v = int32(p.To.Target().Pc-p.Pc) >> 2
  2444  			if v < -1<<25 || v >= 1<<25 {
  2445  				c.ctxt.Diag("branch too far \n%v", p)
  2446  			}
  2447  		}
  2448  		o1 = OP_B_BL(c.opirr(p.As), uint32(v))
  2449  		if p.To.Sym != nil {
  2450  			c.cursym.AddRel(c.ctxt, obj.Reloc{
  2451  				Type: objabi.R_CALLLOONG64,
  2452  				Off:  int32(c.pc),
  2453  				Siz:  4,
  2454  				Sym:  p.To.Sym,
  2455  				Add:  p.To.Offset,
  2456  			})
  2457  		}
  2458  
  2459  	case 13: // vsll $ui3, [vr1], vr2
  2460  		v := c.regoff(&p.From)
  2461  		r := int(p.Reg)
  2462  		if r == 0 {
  2463  			r = int(p.To.Reg)
  2464  		}
  2465  		o1 = OP_3IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  2466  
  2467  	case 14: // vsll $ui4, [vr1], vr2
  2468  		v := c.regoff(&p.From)
  2469  		r := int(p.Reg)
  2470  		if r == 0 {
  2471  			r = int(p.To.Reg)
  2472  		}
  2473  		o1 = OP_4IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  2474  
  2475  	case 15: // teq $c r,r
  2476  		v := c.regoff(&p.From)
  2477  		r := int(p.Reg)
  2478  		if r == 0 {
  2479  			r = REGZERO
  2480  		}
  2481  		/*
  2482  			teq c, r1, r2
  2483  			fallthrough
  2484  			==>
  2485  			bne r1, r2, 2
  2486  			break c
  2487  			fallthrough
  2488  		*/
  2489  		if p.As == ATEQ {
  2490  			o1 = OP_16IRR(c.opirr(ABNE), uint32(2), uint32(r), uint32(p.To.Reg))
  2491  		} else { // ATNE
  2492  			o1 = OP_16IRR(c.opirr(ABEQ), uint32(2), uint32(r), uint32(p.To.Reg))
  2493  		}
  2494  		o2 = OP_15I(c.opi(ABREAK), uint32(v))
  2495  
  2496  	case 16: // sll $c,[r1],r2
  2497  		v := c.regoff(&p.From)
  2498  		r := int(p.Reg)
  2499  		if r == 0 {
  2500  			r = int(p.To.Reg)
  2501  		}
  2502  
  2503  		// instruction ending with V:6-digit immediate, others:5-digit immediate
  2504  		if v >= 32 && vshift(p.As) {
  2505  			o1 = OP_16IRR(c.opirr(p.As), uint32(v)&0x3f, uint32(r), uint32(p.To.Reg))
  2506  		} else {
  2507  			o1 = OP_16IRR(c.opirr(p.As), uint32(v)&0x1f, uint32(r), uint32(p.To.Reg))
  2508  		}
  2509  
  2510  	case 17: // bstrpickw $msbw, r1, $lsbw, r2
  2511  		rd, rj := p.To.Reg, p.Reg
  2512  		if rj == obj.REG_NONE {
  2513  			rj = rd
  2514  		}
  2515  		msb, lsb := p.From.Offset, p.GetFrom3().Offset
  2516  
  2517  		// check the range of msb and lsb
  2518  		var b uint32
  2519  		if p.As == ABSTRPICKW || p.As == ABSTRINSW {
  2520  			b = 32
  2521  		} else {
  2522  			b = 64
  2523  		}
  2524  		if lsb < 0 || uint32(lsb) >= b || msb < 0 || uint32(msb) >= b || uint32(lsb) > uint32(msb) {
  2525  			c.ctxt.Diag("illegal bit number\n%v", p)
  2526  		}
  2527  
  2528  		o1 = OP_IRIR(c.opirir(p.As), uint32(msb), uint32(rj), uint32(lsb), uint32(rd))
  2529  
  2530  	case 18: // jmp [r1],0(r2)
  2531  		r := int(p.Reg)
  2532  		if r == 0 {
  2533  			r = int(o.param)
  2534  		}
  2535  		o1 = OP_RRR(c.oprrr(p.As), uint32(0), uint32(p.To.Reg), uint32(r))
  2536  		if p.As == obj.ACALL {
  2537  			c.cursym.AddRel(c.ctxt, obj.Reloc{
  2538  				Type: objabi.R_CALLIND,
  2539  				Off:  int32(c.pc),
  2540  			})
  2541  		}
  2542  
  2543  	case 19: // mov $lcon,r
  2544  		// NOTE: this case does not use REGTMP. If it ever does,
  2545  		// remove the NOTUSETMP flag in optab.
  2546  		v := c.regoff(&p.From)
  2547  		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(p.To.Reg))
  2548  		o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
  2549  
  2550  	case 20: // mov Rsrc, (Rbase)(Roff)
  2551  		o1 = OP_RRR(c.oprrr(p.As), uint32(p.To.Index), uint32(p.To.Reg), uint32(p.From.Reg))
  2552  
  2553  	case 21: // mov (Rbase)(Roff), Rdst
  2554  		o1 = OP_RRR(c.oprrr(-p.As), uint32(p.From.Index), uint32(p.From.Reg), uint32(p.To.Reg))
  2555  
  2556  	case 22: // add $si5,[r1],r2
  2557  		v := c.regoff(&p.From)
  2558  		r := int(p.Reg)
  2559  		if r == 0 {
  2560  			r = int(p.To.Reg)
  2561  		}
  2562  
  2563  		o1 = OP_5IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  2564  
  2565  	case 23: // add $ui8,[r1],r2
  2566  		v := c.regoff(&p.From)
  2567  		r := int(p.Reg)
  2568  		if r == 0 {
  2569  			r = int(p.To.Reg)
  2570  		}
  2571  
  2572  		// the operand range available for instructions VSHUF4IV and XVSHUF4IV is [0, 15]
  2573  		if p.As == AVSHUF4IV || p.As == AXVSHUF4IV {
  2574  			operand := uint32(v)
  2575  			c.checkoperand(p, operand, 15)
  2576  		}
  2577  
  2578  		o1 = OP_8IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  2579  
  2580  	case 24: // add $lcon,r1,r2
  2581  		v := c.regoff(&p.From)
  2582  		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
  2583  		o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
  2584  		r := int(p.Reg)
  2585  		if r == 0 {
  2586  			r = int(p.To.Reg)
  2587  		}
  2588  		o3 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  2589  
  2590  	case 25: // mov $ucon,r
  2591  		v := c.regoff(&p.From)
  2592  		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(p.To.Reg))
  2593  
  2594  	case 26: // add/and $ucon,[r1],r2
  2595  		v := c.regoff(&p.From)
  2596  		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
  2597  		r := int(p.Reg)
  2598  		if r == 0 {
  2599  			r = int(p.To.Reg)
  2600  		}
  2601  		o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  2602  
  2603  	case 27: // mov $lsext/auto/oreg,r
  2604  		v := c.regoff(&p.From)
  2605  		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
  2606  		o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
  2607  		r := int(p.From.Reg)
  2608  		if r == 0 {
  2609  			r = int(o.param)
  2610  		}
  2611  		o3 = OP_RRR(c.oprrr(add), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  2612  
  2613  	case 28: // mov [sl]ext/auto/oreg,fr
  2614  		v := c.regoff(&p.From)
  2615  		r := int(p.From.Reg)
  2616  		if r == 0 {
  2617  			r = int(o.param)
  2618  		}
  2619  		switch o.size {
  2620  		case 12:
  2621  			o1 = OP_IR(c.opir(ALU12IW), uint32((v+1<<11)>>12), uint32(REGTMP))
  2622  			o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  2623  			o3 = OP_12IRR(c.opirr(-p.As), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
  2624  
  2625  		case 4:
  2626  			o1 = OP_12IRR(c.opirr(-p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  2627  		}
  2628  
  2629  	case 29: // mov fr,[sl]ext/auto/oreg
  2630  		v := c.regoff(&p.To)
  2631  		r := int(p.To.Reg)
  2632  		if r == 0 {
  2633  			r = int(o.param)
  2634  		}
  2635  		switch o.size {
  2636  		case 12:
  2637  			o1 = OP_IR(c.opir(ALU12IW), uint32((v+1<<11)>>12), uint32(REGTMP))
  2638  			o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  2639  			o3 = OP_12IRR(c.opirr(p.As), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
  2640  
  2641  		case 4:
  2642  			o1 = OP_12IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.From.Reg))
  2643  		}
  2644  
  2645  	case 30: // mov gr/fr/fcc/fcsr, fr/fcc/fcsr/gr
  2646  		a := c.specialFpMovInst(p.As, oclass(&p.From), oclass(&p.To))
  2647  		o1 = OP_RR(a, uint32(p.From.Reg), uint32(p.To.Reg))
  2648  
  2649  	case 31: // vsll $ui5, [vr1], vr2
  2650  		v := c.regoff(&p.From)
  2651  		r := int(p.Reg)
  2652  		if r == 0 {
  2653  			r = int(p.To.Reg)
  2654  		}
  2655  		o1 = OP_5IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  2656  
  2657  	case 32: // vsll $ui6, [vr1], vr2
  2658  		v := c.regoff(&p.From)
  2659  		r := int(p.Reg)
  2660  		if r == 0 {
  2661  			r = int(p.To.Reg)
  2662  		}
  2663  		o1 = OP_6IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  2664  
  2665  	case 33: // fsel ca, fk, [fj], fd
  2666  		ca := uint32(p.From.Reg)
  2667  		fk := uint32(p.Reg)
  2668  		fd := uint32(p.To.Reg)
  2669  		fj := fd
  2670  		if len(p.RestArgs) > 0 {
  2671  			fj = uint32(p.GetFrom3().Reg)
  2672  		}
  2673  		o1 = 0x340<<18 | (ca&0x7)<<15 | (fk&0x1F)<<10 | (fj&0x1F)<<5 | (fd & 0x1F)
  2674  
  2675  	case 34: // mov $con,fr
  2676  		v := c.regoff(&p.From)
  2677  		a := AADD
  2678  		if v > 0 {
  2679  			a = AOR
  2680  		}
  2681  		a2 := c.specialFpMovInst(p.As, C_REG, oclass(&p.To))
  2682  		o1 = OP_12IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
  2683  		o2 = OP_RR(a2, uint32(REGTMP), uint32(p.To.Reg))
  2684  
  2685  	case 35: // mov r,lext/auto/oreg
  2686  		v := c.regoff(&p.To)
  2687  		r := int(p.To.Reg)
  2688  		if r == 0 {
  2689  			r = int(o.param)
  2690  		}
  2691  		o1 = OP_IR(c.opir(ALU12IW), uint32((v+1<<11)>>12), uint32(REGTMP))
  2692  		o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  2693  		o3 = OP_12IRR(c.opirr(p.As), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
  2694  
  2695  	case 36: // mov lext/auto/oreg,r
  2696  		v := c.regoff(&p.From)
  2697  		r := int(p.From.Reg)
  2698  		if r == 0 {
  2699  			r = int(o.param)
  2700  		}
  2701  		o1 = OP_IR(c.opir(ALU12IW), uint32((v+1<<11)>>12), uint32(REGTMP))
  2702  		o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  2703  		o3 = OP_12IRR(c.opirr(-p.As), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
  2704  
  2705  	case 37: // fmadd r1, r2, [r3], r4
  2706  		r := int(p.To.Reg)
  2707  		if len(p.RestArgs) > 0 {
  2708  			r = int(p.GetFrom3().Reg)
  2709  		}
  2710  		o1 = OP_RRRR(c.oprrrr(p.As), uint32(p.From.Reg), uint32(p.Reg), uint32(r), uint32(p.To.Reg))
  2711  
  2712  	case 38: // word
  2713  		o1 = uint32(c.regoff(&p.From))
  2714  
  2715  	case 39: // vmov Rn, Vd.<T>[index]
  2716  		v, m := c.specialLsxMovInst(p.As, p.From.Reg, p.To.Reg, false)
  2717  		if v == 0 {
  2718  			c.ctxt.Diag("illegal arng type combination: %v\n", p)
  2719  		}
  2720  
  2721  		rj := uint32(p.From.Reg & EXT_REG_MASK)
  2722  		rd := uint32(p.To.Reg & EXT_REG_MASK)
  2723  		index := uint32(p.To.Index)
  2724  		c.checkindex(p, index, m)
  2725  		o1 = v | (index << 10) | (rj << 5) | rd
  2726  
  2727  	case 40: // vmov Vd.<T>[index], Rn
  2728  		v, m := c.specialLsxMovInst(p.As, p.From.Reg, p.To.Reg, false)
  2729  		if v == 0 {
  2730  			c.ctxt.Diag("illegal arng type combination: %v\n", p)
  2731  		}
  2732  
  2733  		rj := uint32(p.From.Reg & EXT_REG_MASK)
  2734  		rd := uint32(p.To.Reg & EXT_REG_MASK)
  2735  		index := uint32(p.From.Index)
  2736  		c.checkindex(p, index, m)
  2737  		o1 = v | (index << 10) | (rj << 5) | rd
  2738  
  2739  	case 41: // vmov Rn, Vd.<T>
  2740  		v, _ := c.specialLsxMovInst(p.As, p.From.Reg, p.To.Reg, false)
  2741  		if v == 0 {
  2742  			c.ctxt.Diag("illegal arng type combination: %v\n", p)
  2743  		}
  2744  
  2745  		rj := uint32(p.From.Reg & EXT_REG_MASK)
  2746  		rd := uint32(p.To.Reg & EXT_REG_MASK)
  2747  		o1 = v | (rj << 5) | rd
  2748  
  2749  	case 42: // vmov offset(vj), vd.<T>
  2750  		v, _ := c.specialLsxMovInst(p.As, p.From.Reg, p.To.Reg, true)
  2751  		if v == 0 {
  2752  			c.ctxt.Diag("illegal arng type combination: %v\n", p)
  2753  		}
  2754  
  2755  		si := c.regoff(&p.From)
  2756  		Rj := uint32(p.From.Reg & EXT_REG_MASK)
  2757  		Vd := uint32(p.To.Reg & EXT_REG_MASK)
  2758  		switch v & 0xc00000 {
  2759  		case 0x800000: // [x]vldrepl.b
  2760  			o1 = OP_12IRR(v, uint32(si), Rj, Vd)
  2761  		case 0x400000: // [x]vldrepl.h
  2762  			if si&1 != 0 {
  2763  				c.ctxt.Diag("%v: offset must be a multiple of 2.\n", p)
  2764  			}
  2765  			o1 = OP_11IRR(v, uint32(si>>1), Rj, Vd)
  2766  		case 0x0:
  2767  			switch v & 0x300000 {
  2768  			case 0x200000: // [x]vldrepl.w
  2769  				if si&3 != 0 {
  2770  					c.ctxt.Diag("%v: offset must be a multiple of 4.\n", p)
  2771  				}
  2772  				o1 = OP_10IRR(v, uint32(si>>2), Rj, Vd)
  2773  			case 0x100000: // [x]vldrepl.d
  2774  				if si&7 != 0 {
  2775  					c.ctxt.Diag("%v: offset must be a multiple of 8.\n", p)
  2776  				}
  2777  				o1 = OP_9IRR(v, uint32(si>>3), Rj, Vd)
  2778  			}
  2779  		}
  2780  
  2781  	case 43: // vmov Vd.<T>[index], offset(Rj)  ->  [x]vstelm.{b/h/w/d}
  2782  		v, m := c.specialLsxMovInst(p.As, p.From.Reg, p.To.Reg, true)
  2783  		if v == 0 {
  2784  			c.ctxt.Diag("illegal arng type combination: %v\n", p)
  2785  		}
  2786  
  2787  		vd := uint32(p.From.Reg & EXT_REG_MASK)
  2788  		rj := uint32(p.To.Reg & EXT_REG_MASK)
  2789  		index := uint32(p.From.Index)
  2790  		c.checkindex(p, index, m)
  2791  
  2792  		si := c.regoff(&p.To)
  2793  		switch v & 0x00F00000 {
  2794  		case 0x00100000: // [x]vstelm.d
  2795  			if si&7 != 0 {
  2796  				c.ctxt.Diag("%v: offset must be a multiple of 8.\n", p)
  2797  			}
  2798  			o1 = v | (index << 18) | ((uint32(si>>3) & 0xff) << 10) | (rj << 5) | vd
  2799  		case 0x00200000: // [x]vstelm.w
  2800  			if si&3 != 0 {
  2801  				c.ctxt.Diag("%v: offset must be a multiple of 4.\n", p)
  2802  			}
  2803  			o1 = v | (index << 18) | ((uint32(si>>2) & 0xff) << 10) | (rj << 5) | vd
  2804  		case 0x00400000: // [x]vstelm.h
  2805  			if si&1 != 0 {
  2806  				c.ctxt.Diag("%v: offset must be a multiple of 2.\n", p)
  2807  			}
  2808  			o1 = v | (index << 18) | ((uint32(si>>1) & 0xff) << 10) | (rj << 5) | vd
  2809  		case 0x00800000: // [x]vstelm.b
  2810  			o1 = v | (index << 18) | ((uint32(si) & 0xff) << 10) | (rj << 5) | vd
  2811  		}
  2812  
  2813  	case 45:
  2814  		// sc.q rd, rk, (rj)
  2815  		o1 = OP_RRR(c.oprrr(p.As), uint32(p.Reg), uint32(p.To.Reg), uint32(p.From.Reg))
  2816  
  2817  	case 46:
  2818  		// ll.acq.{w/d}  (rj), rd
  2819  		rj := uint32(p.From.Reg)
  2820  		rd := uint32(p.To.Reg)
  2821  
  2822  		switch p.As {
  2823  		case ASCRELW, ASCRELV:
  2824  			rj = uint32(p.To.Reg)
  2825  			rd = uint32(p.From.Reg)
  2826  		}
  2827  
  2828  		o1 = OP_RR(c.oprr(p.As), rj, rd)
  2829  
  2830  	case 47: // preld  offset(Rbase), $hint
  2831  		offs := c.regoff(&p.From)
  2832  		hint := p.GetFrom3().Offset
  2833  		o1 = OP_12IR_5I(c.opiir(p.As), uint32(offs), uint32(p.From.Reg), uint32(hint))
  2834  
  2835  	case 48: // preldx offset(Rbase), $n, $hint
  2836  		offs := c.regoff(&p.From)
  2837  		hint := p.RestArgs[1].Offset
  2838  		n := uint64(p.GetFrom3().Offset)
  2839  
  2840  		addrSeq := (n >> 0) & 0x1
  2841  		blkSize := (n >> 1) & 0x7ff
  2842  		blkNums := (n >> 12) & 0x1ff
  2843  		stride := (n >> 21) & 0xffff
  2844  
  2845  		if blkSize > 1024 {
  2846  			c.ctxt.Diag("%v: block_size amount out of range[16, 1024]: %v\n", p, blkSize)
  2847  		}
  2848  
  2849  		if blkNums > 256 {
  2850  			c.ctxt.Diag("%v: block_nums amount out of range[1, 256]: %v\n", p, blkNums)
  2851  		}
  2852  
  2853  		v := (uint64(offs) & 0xffff)
  2854  		v += addrSeq << 16
  2855  		v += ((blkSize / 16) - 1) << 20
  2856  		v += (blkNums - 1) << 32
  2857  		v += stride << 44
  2858  
  2859  		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
  2860  		o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
  2861  		o3 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(REGTMP))
  2862  		o4 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(REGTMP), uint32(REGTMP))
  2863  		o5 = OP_5IRR(c.opirr(p.As), uint32(REGTMP), uint32(p.From.Reg), uint32(hint))
  2864  
  2865  	case 49:
  2866  		if p.As == ANOOP {
  2867  			// andi r0, r0, 0
  2868  			o1 = OP_12IRR(c.opirr(AAND), 0, 0, 0)
  2869  		} else {
  2870  			// undef
  2871  			o1 = OP_15I(c.opi(ABREAK), 0)
  2872  		}
  2873  
  2874  	// relocation operations
  2875  	case 50: // mov r,addr ==> pcalau12i + sw
  2876  		o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(REGTMP))
  2877  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  2878  			Type: objabi.R_LOONG64_ADDR_HI,
  2879  			Off:  int32(c.pc),
  2880  			Siz:  4,
  2881  			Sym:  p.To.Sym,
  2882  			Add:  p.To.Offset,
  2883  		})
  2884  		o2 = OP_12IRR(c.opirr(p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
  2885  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  2886  			Type: objabi.R_LOONG64_ADDR_LO,
  2887  			Off:  int32(c.pc + 4),
  2888  			Siz:  4,
  2889  			Sym:  p.To.Sym,
  2890  			Add:  p.To.Offset,
  2891  		})
  2892  
  2893  	case 51: // mov addr,r ==> pcalau12i + lw
  2894  		o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(REGTMP))
  2895  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  2896  			Type: objabi.R_LOONG64_ADDR_HI,
  2897  			Off:  int32(c.pc),
  2898  			Siz:  4,
  2899  			Sym:  p.From.Sym,
  2900  			Add:  p.From.Offset,
  2901  		})
  2902  		o2 = OP_12IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
  2903  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  2904  			Type: objabi.R_LOONG64_ADDR_LO,
  2905  			Off:  int32(c.pc + 4),
  2906  			Siz:  4,
  2907  			Sym:  p.From.Sym,
  2908  			Add:  p.From.Offset,
  2909  		})
  2910  
  2911  	case 52: // mov $ext, r
  2912  		// NOTE: this case does not use REGTMP. If it ever does,
  2913  		// remove the NOTUSETMP flag in optab.
  2914  		o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(p.To.Reg))
  2915  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  2916  			Type: objabi.R_LOONG64_ADDR_HI,
  2917  			Off:  int32(c.pc),
  2918  			Siz:  4,
  2919  			Sym:  p.From.Sym,
  2920  			Add:  p.From.Offset,
  2921  		})
  2922  		o2 = OP_12IRR(c.opirr(add), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
  2923  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  2924  			Type: objabi.R_LOONG64_ADDR_LO,
  2925  			Off:  int32(c.pc + 4),
  2926  			Siz:  4,
  2927  			Sym:  p.From.Sym,
  2928  			Add:  p.From.Offset,
  2929  		})
  2930  
  2931  	case 53: // mov r, tlsvar ==>  lu12i.w + ori + add r2, regtmp + sw o(regtmp)
  2932  		// NOTE: this case does not use REGTMP. If it ever does,
  2933  		// remove the NOTUSETMP flag in optab.
  2934  		o1 = OP_IR(c.opir(ALU12IW), uint32(0), uint32(REGTMP))
  2935  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  2936  			Type: objabi.R_LOONG64_TLS_LE_HI,
  2937  			Off:  int32(c.pc),
  2938  			Siz:  4,
  2939  			Sym:  p.To.Sym,
  2940  			Add:  p.To.Offset,
  2941  		})
  2942  		o2 = OP_12IRR(c.opirr(AOR), uint32(0), uint32(REGTMP), uint32(REGTMP))
  2943  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  2944  			Type: objabi.R_LOONG64_TLS_LE_LO,
  2945  			Off:  int32(c.pc + 4),
  2946  			Siz:  4,
  2947  			Sym:  p.To.Sym,
  2948  			Add:  p.To.Offset,
  2949  		})
  2950  		o3 = OP_RRR(c.oprrr(AADDV), uint32(REG_R2), uint32(REGTMP), uint32(REGTMP))
  2951  		o4 = OP_12IRR(c.opirr(p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
  2952  
  2953  	case 54: // lu12i.w + ori + add r2, regtmp + lw o(regtmp)
  2954  		// NOTE: this case does not use REGTMP. If it ever does,
  2955  		// remove the NOTUSETMP flag in optab.
  2956  		o1 = OP_IR(c.opir(ALU12IW), uint32(0), uint32(REGTMP))
  2957  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  2958  			Type: objabi.R_LOONG64_TLS_LE_HI,
  2959  			Off:  int32(c.pc),
  2960  			Siz:  4,
  2961  			Sym:  p.From.Sym,
  2962  			Add:  p.From.Offset,
  2963  		})
  2964  		o2 = OP_12IRR(c.opirr(AOR), uint32(0), uint32(REGTMP), uint32(REGTMP))
  2965  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  2966  			Type: objabi.R_LOONG64_TLS_LE_LO,
  2967  			Off:  int32(c.pc + 4),
  2968  			Siz:  4,
  2969  			Sym:  p.From.Sym,
  2970  			Add:  p.From.Offset,
  2971  		})
  2972  		o3 = OP_RRR(c.oprrr(AADDV), uint32(REG_R2), uint32(REGTMP), uint32(REGTMP))
  2973  		o4 = OP_12IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
  2974  
  2975  	case 56: // mov r, tlsvar IE model ==> (pcalau12i + ld.d)tlsvar@got + add.d + st.d
  2976  		o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(REGTMP))
  2977  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  2978  			Type: objabi.R_LOONG64_TLS_IE_HI,
  2979  			Off:  int32(c.pc),
  2980  			Siz:  4,
  2981  			Sym:  p.To.Sym,
  2982  		})
  2983  		o2 = OP_12IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(REGTMP))
  2984  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  2985  			Type: objabi.R_LOONG64_TLS_IE_LO,
  2986  			Off:  int32(c.pc + 4),
  2987  			Siz:  4,
  2988  			Sym:  p.To.Sym,
  2989  		})
  2990  		o3 = OP_RRR(c.oprrr(AADDVU), uint32(REGTMP), uint32(REG_R2), uint32(REGTMP))
  2991  		o4 = OP_12IRR(c.opirr(p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
  2992  
  2993  	case 57: // mov tlsvar, r IE model ==> (pcalau12i + ld.d)tlsvar@got + add.d + ld.d
  2994  		o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(REGTMP))
  2995  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  2996  			Type: objabi.R_LOONG64_TLS_IE_HI,
  2997  			Off:  int32(c.pc),
  2998  			Siz:  4,
  2999  			Sym:  p.From.Sym,
  3000  		})
  3001  		o2 = OP_12IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(REGTMP))
  3002  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  3003  			Type: objabi.R_LOONG64_TLS_IE_LO,
  3004  			Off:  int32(c.pc + 4),
  3005  			Siz:  4,
  3006  			Sym:  p.From.Sym,
  3007  		})
  3008  		o3 = OP_RRR(c.oprrr(AADDVU), uint32(REGTMP), uint32(REG_R2), uint32(REGTMP))
  3009  		o4 = OP_12IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
  3010  
  3011  	case 59: // mov $dcon,r
  3012  		// NOTE: this case does not use REGTMP. If it ever does,
  3013  		// remove the NOTUSETMP flag in optab.
  3014  		v := c.vregoff(&p.From)
  3015  		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(p.To.Reg))
  3016  		o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
  3017  		o3 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(p.To.Reg))
  3018  		o4 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(p.To.Reg), uint32(p.To.Reg))
  3019  
  3020  	case 60: // add $dcon,r1,r2
  3021  		v := c.vregoff(&p.From)
  3022  		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
  3023  		o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
  3024  		o3 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(REGTMP))
  3025  		o4 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(REGTMP), uint32(REGTMP))
  3026  		r := int(p.Reg)
  3027  		if r == 0 {
  3028  			r = int(p.To.Reg)
  3029  		}
  3030  		o5 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  3031  
  3032  	case 61: // word C_DCON
  3033  		o1 = uint32(c.vregoff(&p.From))
  3034  		o2 = uint32(c.vregoff(&p.From) >> 32)
  3035  
  3036  	case 62: // rdtimex rd, rj
  3037  		o1 = OP_RR(c.oprr(p.As), uint32(p.To.Reg), uint32(p.RegTo2))
  3038  
  3039  	case 64: // alsl rd, rj, rk, sa2
  3040  		sa := p.From.Offset - 1
  3041  		if sa < 0 || sa > 3 {
  3042  			c.ctxt.Diag("%v: shift amount out of range[1, 4].\n", p)
  3043  		}
  3044  		r := p.GetFrom3().Reg
  3045  		o1 = OP_2IRRR(c.opirrr(p.As), uint32(sa), uint32(r), uint32(p.Reg), uint32(p.To.Reg))
  3046  
  3047  	case 65: // mov sym@GOT, r ==> pcalau12i + ld.d
  3048  		o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(p.To.Reg))
  3049  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  3050  			Type: objabi.R_LOONG64_GOT_HI,
  3051  			Off:  int32(c.pc),
  3052  			Siz:  4,
  3053  			Sym:  p.From.Sym,
  3054  		})
  3055  		o2 = OP_12IRR(c.opirr(-p.As), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
  3056  		c.cursym.AddRel(c.ctxt, obj.Reloc{
  3057  			Type: objabi.R_LOONG64_GOT_LO,
  3058  			Off:  int32(c.pc + 4),
  3059  			Siz:  4,
  3060  			Sym:  p.From.Sym,
  3061  		})
  3062  
  3063  	case 66: // am* From, To, RegTo2 ==> am* RegTo2, From, To
  3064  		rk := p.From.Reg
  3065  		rj := p.To.Reg
  3066  		rd := p.RegTo2
  3067  
  3068  		// See section 2.2.7.1 of https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html
  3069  		// for the register usage constraints.
  3070  		if rd == rj || rd == rk {
  3071  			c.ctxt.Diag("illegal register combination: %v\n", p)
  3072  		}
  3073  		o1 = OP_RRR(atomicInst[p.As], uint32(rk), uint32(rj), uint32(rd))
  3074  
  3075  	case 67: // mov $dcon12_0, r
  3076  		v := c.vregoff(&p.From)
  3077  		o1 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(0), uint32(p.To.Reg))
  3078  
  3079  	case 68: // mov $dcon12_20S, r
  3080  		v := c.vregoff(&p.From)
  3081  		contype := c.aclass(&p.From)
  3082  		switch contype {
  3083  		default: // C_DCON12_20S
  3084  			o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(p.To.Reg))
  3085  			o2 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(p.To.Reg), uint32(p.To.Reg))
  3086  		case C_DCON20S_20:
  3087  			o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(p.To.Reg))
  3088  			o2 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(p.To.Reg))
  3089  		case C_DCON12_12S:
  3090  			o1 = OP_12IRR(c.opirr(AADDV), uint32(v), uint32(0), uint32(p.To.Reg))
  3091  			o2 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(p.To.Reg), uint32(p.To.Reg))
  3092  		case C_DCON20S_12S, C_DCON20S_0:
  3093  			o1 = OP_12IRR(c.opirr(AADD), uint32(v), uint32(0), uint32(p.To.Reg))
  3094  			o2 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(p.To.Reg))
  3095  		case C_DCON12_12U:
  3096  			o1 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(0), uint32(p.To.Reg))
  3097  			o2 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(p.To.Reg), uint32(p.To.Reg))
  3098  		case C_DCON20S_12U:
  3099  			o1 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(0), uint32(p.To.Reg))
  3100  			o2 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(p.To.Reg))
  3101  		}
  3102  
  3103  	case 69: // mov $dcon32_12S, r
  3104  		v := c.vregoff(&p.From)
  3105  		contype := c.aclass(&p.From)
  3106  		switch contype {
  3107  		default: // C_DCON32_12S, C_DCON32_0
  3108  			o1 = OP_12IRR(c.opirr(AADD), uint32(v), uint32(0), uint32(p.To.Reg))
  3109  			o2 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(p.To.Reg))
  3110  			o3 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(p.To.Reg), uint32(p.To.Reg))
  3111  		case C_DCON32_20:
  3112  			o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(p.To.Reg))
  3113  			o2 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(p.To.Reg))
  3114  			o3 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(p.To.Reg), uint32(p.To.Reg))
  3115  		case C_DCON12_32S:
  3116  			o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(p.To.Reg))
  3117  			o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
  3118  			o3 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(p.To.Reg), uint32(p.To.Reg))
  3119  		case C_DCON20S_32:
  3120  			o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(p.To.Reg))
  3121  			o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
  3122  			o3 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(p.To.Reg))
  3123  		case C_DCON32_12U:
  3124  			o1 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(0), uint32(p.To.Reg))
  3125  			o2 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(p.To.Reg))
  3126  			o3 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(p.To.Reg), uint32(p.To.Reg))
  3127  		}
  3128  
  3129  	case 70: // add $dcon12_0,[r1],r2
  3130  		v := c.vregoff(&p.From)
  3131  		r := int(p.Reg)
  3132  		if r == 0 {
  3133  			r = int(p.To.Reg)
  3134  		}
  3135  		o1 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(0), uint32(REGTMP))
  3136  		o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  3137  
  3138  	case 71: // add $dcon12_20S,[r1],r2
  3139  		v := c.vregoff(&p.From)
  3140  		r := int(p.Reg)
  3141  		if r == 0 {
  3142  			r = int(p.To.Reg)
  3143  		}
  3144  		contype := c.aclass(&p.From)
  3145  		switch contype {
  3146  		default: // C_DCON12_20S
  3147  			o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
  3148  			o2 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(REGTMP), uint32(REGTMP))
  3149  		case C_DCON20S_20:
  3150  			o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
  3151  			o2 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(REGTMP))
  3152  		case C_DCON12_12S:
  3153  			o1 = OP_12IRR(c.opirr(AADDV), uint32(v), uint32(0), uint32(REGTMP))
  3154  			o2 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(REGTMP), uint32(REGTMP))
  3155  		case C_DCON20S_12S, C_DCON20S_0:
  3156  			o1 = OP_12IRR(c.opirr(AADD), uint32(v), uint32(0), uint32(REGTMP))
  3157  			o2 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(REGTMP))
  3158  		case C_DCON12_12U:
  3159  			o1 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(0), uint32(REGTMP))
  3160  			o2 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(REGTMP), uint32(REGTMP))
  3161  		case C_DCON20S_12U:
  3162  			o1 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(0), uint32(REGTMP))
  3163  			o2 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(REGTMP))
  3164  		}
  3165  		o3 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  3166  
  3167  	case 72: // add $dcon32_12S,[r1],r2
  3168  		v := c.vregoff(&p.From)
  3169  		r := int(p.Reg)
  3170  		if r == 0 {
  3171  			r = int(p.To.Reg)
  3172  		}
  3173  		contype := c.aclass(&p.From)
  3174  		switch contype {
  3175  		default: // C_DCON32_12S, C_DCON32_0
  3176  			o1 = OP_12IRR(c.opirr(AADD), uint32(v), uint32(0), uint32(REGTMP))
  3177  			o2 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(REGTMP))
  3178  			o3 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(REGTMP), uint32(REGTMP))
  3179  		case C_DCON32_20:
  3180  			o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
  3181  			o2 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(REGTMP))
  3182  			o3 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(REGTMP), uint32(REGTMP))
  3183  		case C_DCON12_32S:
  3184  			o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
  3185  			o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
  3186  			o3 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(REGTMP), uint32(REGTMP))
  3187  		case C_DCON20S_32:
  3188  			o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
  3189  			o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
  3190  			o3 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(REGTMP))
  3191  		case C_DCON32_12U:
  3192  			o1 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(0), uint32(REGTMP))
  3193  			o2 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(REGTMP))
  3194  			o3 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(REGTMP), uint32(REGTMP))
  3195  		}
  3196  		o4 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  3197  
  3198  	case 73:
  3199  		v := c.vregoff(&p.To)
  3200  		r := p.To.Reg
  3201  		if v&3 != 0 {
  3202  			c.ctxt.Diag("%v: offset must be a multiple of 4.\n", p)
  3203  		}
  3204  
  3205  		switch o.size {
  3206  		case 4: // 16 bit
  3207  			o1 = OP_14IRR(c.opirr(p.As), uint32(v>>2), uint32(r), uint32(p.From.Reg))
  3208  		case 12: // 32 bit
  3209  			o1 = OP_16IRR(c.opirr(AADDV16), uint32(v>>16), uint32(REG_R0), uint32(REGTMP))
  3210  			o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  3211  			o3 = OP_14IRR(c.opirr(p.As), uint32(v>>2), uint32(REGTMP), uint32(p.From.Reg))
  3212  		case 24: // 64 bit
  3213  			o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
  3214  			o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
  3215  			o3 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(REGTMP))
  3216  			o4 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(REGTMP), uint32(REGTMP))
  3217  			o5 = OP_RRR(c.oprrr(add), uint32(REGTMP), uint32(r), uint32(r))
  3218  			o6 = OP_14IRR(c.opirr(p.As), uint32(0), uint32(r), uint32(p.From.Reg))
  3219  		}
  3220  
  3221  	case 74:
  3222  		v := c.vregoff(&p.From)
  3223  		r := p.From.Reg
  3224  		if v&3 != 0 {
  3225  			c.ctxt.Diag("%v: offset must be a multiple of 4.\n", p)
  3226  		}
  3227  
  3228  		switch o.size {
  3229  		case 4: // 16 bit
  3230  			o1 = OP_14IRR(c.opirr(-p.As), uint32(v>>2), uint32(r), uint32(p.To.Reg))
  3231  		case 12: // 32 bit
  3232  			o1 = OP_16IRR(c.opirr(AADDV16), uint32(v>>16), uint32(REG_R0), uint32(REGTMP))
  3233  			o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  3234  			o3 = OP_14IRR(c.opirr(-p.As), uint32(v>>2), uint32(REGTMP), uint32(p.To.Reg))
  3235  		case 24: // 64 bit
  3236  			o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
  3237  			o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
  3238  			o3 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(REGTMP))
  3239  			o4 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(REGTMP), uint32(REGTMP))
  3240  			o5 = OP_RRR(c.oprrr(add), uint32(REGTMP), uint32(r), uint32(r))
  3241  			o6 = OP_14IRR(c.opirr(p.As), uint32(0), uint32(r), uint32(p.To.Reg))
  3242  		}
  3243  
  3244  	}
  3245  
  3246  	out[0] = o1
  3247  	out[1] = o2
  3248  	out[2] = o3
  3249  	out[3] = o4
  3250  	out[4] = o5
  3251  	out[5] = o6
  3252  }
  3253  
  3254  // checkoperand checks if operand >= 0 && operand <= maxoperand
  3255  func (c *ctxt0) checkoperand(p *obj.Prog, operand uint32, mask uint32) {
  3256  	if (operand & ^mask) != 0 {
  3257  		c.ctxt.Diag("operand out of range 0 to %d: %v", mask, p)
  3258  	}
  3259  }
  3260  
  3261  // checkindex checks if index >= 0 && index <= maxindex
  3262  func (c *ctxt0) checkindex(p *obj.Prog, index uint32, mask uint32) {
  3263  	if (index & ^mask) != 0 {
  3264  		c.ctxt.Diag("register element index out of range 0 to %d: %v", mask, p)
  3265  	}
  3266  }
  3267  
  3268  func (c *ctxt0) vregoff(a *obj.Addr) int64 {
  3269  	c.instoffset = 0
  3270  	c.aclass(a)
  3271  	return c.instoffset
  3272  }
  3273  
  3274  func (c *ctxt0) regoff(a *obj.Addr) int32 {
  3275  	return int32(c.vregoff(a))
  3276  }
  3277  
  3278  func (c *ctxt0) oprrrr(a obj.As) uint32 {
  3279  	op, ok := oprrrr[a]
  3280  	if ok {
  3281  		return op
  3282  	}
  3283  	c.ctxt.Diag("bad rrrr opcode %v", a)
  3284  	return 0
  3285  }
  3286  
  3287  func (c *ctxt0) oprrr(a obj.As) uint32 {
  3288  	op, ok := oprrr[a]
  3289  	if ok {
  3290  		return op
  3291  	}
  3292  	c.ctxt.Diag("bad rrr opcode %v", a)
  3293  	return 0
  3294  }
  3295  
  3296  func (c *ctxt0) oprr(a obj.As) uint32 {
  3297  	op, ok := oprr[a]
  3298  	if ok {
  3299  		return op
  3300  	}
  3301  	c.ctxt.Diag("bad rr opcode %v", a)
  3302  	return 0
  3303  }
  3304  
  3305  func (c *ctxt0) opi(a obj.As) uint32 {
  3306  	op, ok := opi[a]
  3307  	if ok {
  3308  		return op
  3309  	}
  3310  	c.ctxt.Diag("bad i opcode %v", a)
  3311  	return 0
  3312  }
  3313  
  3314  func (c *ctxt0) opir(a obj.As) uint32 {
  3315  	op, ok := opir[a]
  3316  	if ok {
  3317  		return op
  3318  	}
  3319  	c.ctxt.Diag("bad ir opcode %v", a)
  3320  	return 0
  3321  }
  3322  
  3323  func (c *ctxt0) opirr(a obj.As) uint32 {
  3324  	op, ok := opirr[a]
  3325  	if ok {
  3326  		return op
  3327  	}
  3328  	c.ctxt.Diag("bad irr opcode %v", a)
  3329  	return 0
  3330  }
  3331  
  3332  func (c *ctxt0) opirrr(a obj.As) uint32 {
  3333  	op, ok := opirrr[a]
  3334  	if ok {
  3335  		return op
  3336  	}
  3337  	c.ctxt.Diag("bad irrr opcode %v", a)
  3338  	return 0
  3339  }
  3340  
  3341  func (c *ctxt0) opirir(a obj.As) uint32 {
  3342  	op, ok := opirir[a]
  3343  	if ok {
  3344  		return op
  3345  	}
  3346  	c.ctxt.Diag("bad irir opcode %v", a)
  3347  	return 0
  3348  }
  3349  
  3350  func (c *ctxt0) opiir(a obj.As) uint32 {
  3351  	op, ok := opiir[a]
  3352  	if ok {
  3353  		return op
  3354  	}
  3355  	c.ctxt.Diag("bad iir opcode %v", a)
  3356  	return 0
  3357  }
  3358  
  3359  func vshift(a obj.As) bool {
  3360  	switch a {
  3361  	case ASLLV,
  3362  		ASRLV,
  3363  		ASRAV,
  3364  		AROTRV:
  3365  		return true
  3366  	}
  3367  	return false
  3368  }
  3369  

View as plain text