Help us shape the future of Go! Take the 2026 Go Developer Survey

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

View as plain text