github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/obj/loong64/asm.go (about)

     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  	"fmt"
     9  	"log"
    10  	"sort"
    11  
    12  	"github.com/go-asm/go/cmd/obj"
    13  	"github.com/go-asm/go/cmd/objabi"
    14  )
    15  
    16  // ctxt0 holds state while assembling a single function.
    17  // Each function gets a fresh ctxt0.
    18  // This allows for multiple functions to be safely concurrently assembled.
    19  type ctxt0 struct {
    20  	ctxt       *obj.Link
    21  	newprog    obj.ProgAlloc
    22  	cursym     *obj.LSym
    23  	autosize   int32
    24  	instoffset int64
    25  	pc         int64
    26  }
    27  
    28  // Instruction layout.
    29  
    30  const (
    31  	FuncAlign = 4
    32  	loopAlign = 16
    33  )
    34  
    35  type Optab struct {
    36  	as    obj.As
    37  	from1 uint8
    38  	reg   uint8
    39  	from3 uint8
    40  	to1   uint8
    41  	to2   uint8
    42  	type_ int8
    43  	size  int8
    44  	param int16
    45  	flag  uint8
    46  }
    47  
    48  const (
    49  	NOTUSETMP = 1 << iota // p expands to multiple instructions, but does NOT use REGTMP
    50  
    51  	// branchLoopHead marks loop entry.
    52  	// Used to insert padding for under-aligned loops.
    53  	branchLoopHead
    54  )
    55  
    56  var optab = []Optab{
    57  	{obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, C_NONE, 0, 0, 0, 0},
    58  
    59  	{AMOVW, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 1, 4, 0, 0},
    60  	{AMOVV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 1, 4, 0, 0},
    61  	{AMOVB, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 12, 8, 0, NOTUSETMP},
    62  	{AMOVBU, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 13, 4, 0, 0},
    63  	{AMOVWU, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 14, 8, 0, NOTUSETMP},
    64  
    65  	{ASUB, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    66  	{ASUBV, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    67  	{AADD, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    68  	{AADDV, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    69  	{AAND, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    70  	{ASUB, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    71  	{ASUBV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    72  	{AADD, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    73  	{AADDV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    74  	{AAND, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    75  	{ANEGW, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    76  	{ANEGV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    77  	{AMASKEQZ, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
    78  
    79  	{ASLL, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 9, 4, 0, 0},
    80  	{ASLL, C_REG, C_REG, C_NONE, C_REG, C_NONE, 9, 4, 0, 0},
    81  	{ASLLV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 9, 4, 0, 0},
    82  	{ASLLV, C_REG, C_REG, C_NONE, C_REG, C_NONE, 9, 4, 0, 0},
    83  	{ACLO, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 9, 4, 0, 0},
    84  
    85  	{AADDF, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 32, 4, 0, 0},
    86  	{AADDF, C_FREG, C_REG, C_NONE, C_FREG, C_NONE, 32, 4, 0, 0},
    87  	{ACMPEQF, C_FREG, C_REG, C_NONE, C_NONE, C_NONE, 32, 4, 0, 0},
    88  	{AABSF, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 33, 4, 0, 0},
    89  	{AMOVVF, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 33, 4, 0, 0},
    90  	{AMOVF, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 33, 4, 0, 0},
    91  	{AMOVD, C_FREG, C_NONE, C_NONE, C_FREG, C_NONE, 33, 4, 0, 0},
    92  
    93  	{AMOVW, C_REG, C_NONE, C_NONE, C_SEXT, C_NONE, 7, 4, 0, 0},
    94  	{AMOVWU, C_REG, C_NONE, C_NONE, C_SEXT, C_NONE, 7, 4, 0, 0},
    95  	{AMOVV, C_REG, C_NONE, C_NONE, C_SEXT, C_NONE, 7, 4, 0, 0},
    96  	{AMOVB, C_REG, C_NONE, C_NONE, C_SEXT, C_NONE, 7, 4, 0, 0},
    97  	{AMOVBU, C_REG, C_NONE, C_NONE, C_SEXT, C_NONE, 7, 4, 0, 0},
    98  	{AMOVWL, C_REG, C_NONE, C_NONE, C_SEXT, C_NONE, 7, 4, 0, 0},
    99  	{AMOVVL, C_REG, C_NONE, C_NONE, C_SEXT, C_NONE, 7, 4, 0, 0},
   100  	{AMOVW, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
   101  	{AMOVWU, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
   102  	{AMOVV, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
   103  	{AMOVB, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
   104  	{AMOVBU, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
   105  	{AMOVWL, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
   106  	{AMOVVL, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
   107  	{AMOVW, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
   108  	{AMOVWU, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
   109  	{AMOVV, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
   110  	{AMOVB, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
   111  	{AMOVBU, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
   112  	{AMOVWL, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
   113  	{AMOVVL, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
   114  	{ASC, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
   115  	{ASCV, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
   116  
   117  	{AMOVW, C_SEXT, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, 0, 0},
   118  	{AMOVWU, C_SEXT, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, 0, 0},
   119  	{AMOVV, C_SEXT, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, 0, 0},
   120  	{AMOVB, C_SEXT, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, 0, 0},
   121  	{AMOVBU, C_SEXT, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, 0, 0},
   122  	{AMOVWL, C_SEXT, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, 0, 0},
   123  	{AMOVVL, C_SEXT, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, 0, 0},
   124  	{AMOVW, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
   125  	{AMOVWU, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
   126  	{AMOVV, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
   127  	{AMOVB, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
   128  	{AMOVBU, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
   129  	{AMOVWL, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
   130  	{AMOVVL, C_SAUTO, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGSP, 0},
   131  	{AMOVW, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
   132  	{AMOVWU, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
   133  	{AMOVV, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
   134  	{AMOVB, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
   135  	{AMOVBU, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
   136  	{AMOVWL, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
   137  	{AMOVVL, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
   138  	{ALL, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
   139  	{ALLV, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 8, 4, REGZERO, 0},
   140  
   141  	{AMOVW, C_REG, C_NONE, C_NONE, C_LEXT, C_NONE, 35, 12, 0, 0},
   142  	{AMOVWU, C_REG, C_NONE, C_NONE, C_LEXT, C_NONE, 35, 12, 0, 0},
   143  	{AMOVV, C_REG, C_NONE, C_NONE, C_LEXT, C_NONE, 35, 12, 0, 0},
   144  	{AMOVB, C_REG, C_NONE, C_NONE, C_LEXT, C_NONE, 35, 12, 0, 0},
   145  	{AMOVBU, C_REG, C_NONE, C_NONE, C_LEXT, C_NONE, 35, 12, 0, 0},
   146  	{AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
   147  	{AMOVWU, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
   148  	{AMOVV, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
   149  	{AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
   150  	{AMOVBU, C_REG, C_NONE, C_NONE, C_LAUTO, C_NONE, 35, 12, REGSP, 0},
   151  	{AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 35, 12, REGZERO, 0},
   152  	{AMOVWU, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 35, 12, REGZERO, 0},
   153  	{AMOVV, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 35, 12, REGZERO, 0},
   154  	{AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 35, 12, REGZERO, 0},
   155  	{AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 35, 12, REGZERO, 0},
   156  	{ASC, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 35, 12, REGZERO, 0},
   157  	{AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
   158  	{AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
   159  	{AMOVWU, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
   160  	{AMOVV, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
   161  	{AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
   162  	{AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
   163  	{AMOVBU, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
   164  	{AMOVBU, C_REG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
   165  	{AMOVW, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
   166  	{AMOVWU, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
   167  	{AMOVV, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
   168  	{AMOVB, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
   169  	{AMOVBU, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
   170  
   171  	{AMOVW, C_LEXT, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, 0, 0},
   172  	{AMOVWU, C_LEXT, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, 0, 0},
   173  	{AMOVV, C_LEXT, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, 0, 0},
   174  	{AMOVB, C_LEXT, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, 0, 0},
   175  	{AMOVBU, C_LEXT, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, 0, 0},
   176  	{AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
   177  	{AMOVWU, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
   178  	{AMOVV, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
   179  	{AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
   180  	{AMOVBU, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
   181  	{AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
   182  	{AMOVWU, C_LOREG, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
   183  	{AMOVV, C_LOREG, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
   184  	{AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
   185  	{AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGZERO, 0},
   186  	{AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
   187  	{AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
   188  	{AMOVWU, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
   189  	{AMOVV, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
   190  	{AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
   191  	{AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
   192  	{AMOVBU, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
   193  	{AMOVBU, C_ADDR, C_NONE, C_NONE, C_REG, C_NONE, 51, 8, 0, 0},
   194  	{AMOVW, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
   195  	{AMOVWU, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
   196  	{AMOVV, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
   197  	{AMOVB, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
   198  	{AMOVBU, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
   199  
   200  	{AMOVW, C_SECON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, 0, 0},
   201  	{AMOVV, C_SECON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, 0, 0},
   202  	{AMOVW, C_SACON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGSP, 0},
   203  	{AMOVV, C_SACON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGSP, 0},
   204  	{AMOVW, C_LECON, C_NONE, C_NONE, C_REG, C_NONE, 52, 8, 0, NOTUSETMP},
   205  	{AMOVW, C_LECON, C_NONE, C_NONE, C_REG, C_NONE, 52, 8, 0, NOTUSETMP},
   206  	{AMOVV, C_LECON, C_NONE, C_NONE, C_REG, C_NONE, 52, 8, 0, NOTUSETMP},
   207  
   208  	{AMOVW, C_LACON, C_NONE, C_NONE, C_REG, C_NONE, 26, 12, REGSP, 0},
   209  	{AMOVV, C_LACON, C_NONE, C_NONE, C_REG, C_NONE, 26, 12, REGSP, 0},
   210  	{AMOVW, C_ADDCON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGZERO, 0},
   211  	{AMOVV, C_ADDCON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGZERO, 0},
   212  	{AMOVW, C_ANDCON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGZERO, 0},
   213  	{AMOVV, C_ANDCON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGZERO, 0},
   214  	{AMOVW, C_STCON, C_NONE, C_NONE, C_REG, C_NONE, 55, 12, 0, 0},
   215  	{AMOVV, C_STCON, C_NONE, C_NONE, C_REG, C_NONE, 55, 12, 0, 0},
   216  
   217  	{AMOVW, C_UCON, C_NONE, C_NONE, C_REG, C_NONE, 24, 4, 0, 0},
   218  	{AMOVV, C_UCON, C_NONE, C_NONE, C_REG, C_NONE, 24, 4, 0, 0},
   219  	{AMOVW, C_LCON, C_NONE, C_NONE, C_REG, C_NONE, 19, 8, 0, NOTUSETMP},
   220  	{AMOVV, C_LCON, C_NONE, C_NONE, C_REG, C_NONE, 19, 8, 0, NOTUSETMP},
   221  	{AMOVV, C_DCON, C_NONE, C_NONE, C_REG, C_NONE, 59, 16, 0, NOTUSETMP},
   222  
   223  	{AMUL, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
   224  	{AMUL, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
   225  	{AMULV, C_REG, C_NONE, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
   226  	{AMULV, C_REG, C_REG, C_NONE, C_REG, C_NONE, 2, 4, 0, 0},
   227  
   228  	{AADD, C_ADD0CON, C_REG, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
   229  	{AADD, C_ADD0CON, C_NONE, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
   230  	{AADD, C_ANDCON, C_REG, C_NONE, C_REG, C_NONE, 10, 8, 0, 0},
   231  	{AADD, C_ANDCON, C_NONE, C_NONE, C_REG, C_NONE, 10, 8, 0, 0},
   232  
   233  	{AADDV, C_ADD0CON, C_REG, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
   234  	{AADDV, C_ADD0CON, C_NONE, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
   235  	{AADDV, C_ANDCON, C_REG, C_NONE, C_REG, C_NONE, 10, 8, 0, 0},
   236  	{AADDV, C_ANDCON, C_NONE, C_NONE, C_REG, C_NONE, 10, 8, 0, 0},
   237  
   238  	{AAND, C_AND0CON, C_REG, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
   239  	{AAND, C_AND0CON, C_NONE, C_NONE, C_REG, C_NONE, 4, 4, 0, 0},
   240  	{AAND, C_ADDCON, C_REG, C_NONE, C_REG, C_NONE, 10, 8, 0, 0},
   241  	{AAND, C_ADDCON, C_NONE, C_NONE, C_REG, C_NONE, 10, 8, 0, 0},
   242  
   243  	{AADD, C_UCON, C_REG, C_NONE, C_REG, C_NONE, 25, 8, 0, 0},
   244  	{AADD, C_UCON, C_NONE, C_NONE, C_REG, C_NONE, 25, 8, 0, 0},
   245  	{AADDV, C_UCON, C_REG, C_NONE, C_REG, C_NONE, 25, 8, 0, 0},
   246  	{AADDV, C_UCON, C_NONE, C_NONE, C_REG, C_NONE, 25, 8, 0, 0},
   247  	{AAND, C_UCON, C_REG, C_NONE, C_REG, C_NONE, 25, 8, 0, 0},
   248  	{AAND, C_UCON, C_NONE, C_NONE, C_REG, C_NONE, 25, 8, 0, 0},
   249  
   250  	{AADD, C_LCON, C_NONE, C_NONE, C_REG, C_NONE, 23, 12, 0, 0},
   251  	{AADDV, C_LCON, C_NONE, C_NONE, C_REG, C_NONE, 23, 12, 0, 0},
   252  	{AAND, C_LCON, C_NONE, C_NONE, C_REG, C_NONE, 23, 12, 0, 0},
   253  	{AADD, C_LCON, C_REG, C_NONE, C_REG, C_NONE, 23, 12, 0, 0},
   254  	{AADDV, C_LCON, C_REG, C_NONE, C_REG, C_NONE, 23, 12, 0, 0},
   255  	{AAND, C_LCON, C_REG, C_NONE, C_REG, C_NONE, 23, 12, 0, 0},
   256  
   257  	{AADDV, C_DCON, C_NONE, C_NONE, C_REG, C_NONE, 60, 20, 0, 0},
   258  	{AADDV, C_DCON, C_REG, C_NONE, C_REG, C_NONE, 60, 20, 0, 0},
   259  
   260  	{ASLL, C_SCON, C_REG, C_NONE, C_REG, C_NONE, 16, 4, 0, 0},
   261  	{ASLL, C_SCON, C_NONE, C_NONE, C_REG, C_NONE, 16, 4, 0, 0},
   262  
   263  	{ASLLV, C_SCON, C_REG, C_NONE, C_REG, C_NONE, 16, 4, 0, 0},
   264  	{ASLLV, C_SCON, C_NONE, C_NONE, C_REG, C_NONE, 16, 4, 0, 0},
   265  
   266  	{ASYSCALL, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 5, 4, 0, 0},
   267  
   268  	{ABEQ, C_REG, C_REG, C_NONE, C_SBRA, C_NONE, 6, 4, 0, 0},
   269  	{ABEQ, C_REG, C_NONE, C_NONE, C_SBRA, C_NONE, 6, 4, 0, 0},
   270  	{ABLEZ, C_REG, C_NONE, C_NONE, C_SBRA, C_NONE, 6, 4, 0, 0},
   271  	{ABFPT, C_NONE, C_NONE, C_NONE, C_SBRA, C_NONE, 6, 4, 0, NOTUSETMP},
   272  
   273  	{AJMP, C_NONE, C_NONE, C_NONE, C_LBRA, C_NONE, 11, 4, 0, 0}, // b
   274  	{AJAL, C_NONE, C_NONE, C_NONE, C_LBRA, C_NONE, 11, 4, 0, 0}, // bl
   275  
   276  	{AJMP, C_NONE, C_NONE, C_NONE, C_ZOREG, C_NONE, 18, 4, REGZERO, 0}, // jirl r0, rj, 0
   277  	{AJAL, C_NONE, C_NONE, C_NONE, C_ZOREG, C_NONE, 18, 4, REGLINK, 0}, // jirl r1, rj, 0
   278  
   279  	{AMOVW, C_SEXT, C_NONE, C_NONE, C_FREG, C_NONE, 27, 4, 0, 0},
   280  	{AMOVF, C_SEXT, C_NONE, C_NONE, C_FREG, C_NONE, 27, 4, 0, 0},
   281  	{AMOVD, C_SEXT, C_NONE, C_NONE, C_FREG, C_NONE, 27, 4, 0, 0},
   282  	{AMOVW, C_SAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 27, 4, REGSP, 0},
   283  	{AMOVF, C_SAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 27, 4, REGSP, 0},
   284  	{AMOVD, C_SAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 27, 4, REGSP, 0},
   285  	{AMOVW, C_SOREG, C_NONE, C_NONE, C_FREG, C_NONE, 27, 4, REGZERO, 0},
   286  	{AMOVF, C_SOREG, C_NONE, C_NONE, C_FREG, C_NONE, 27, 4, REGZERO, 0},
   287  	{AMOVD, C_SOREG, C_NONE, C_NONE, C_FREG, C_NONE, 27, 4, REGZERO, 0},
   288  
   289  	{AMOVW, C_LEXT, C_NONE, C_NONE, C_FREG, C_NONE, 27, 12, 0, 0},
   290  	{AMOVF, C_LEXT, C_NONE, C_NONE, C_FREG, C_NONE, 27, 12, 0, 0},
   291  	{AMOVD, C_LEXT, C_NONE, C_NONE, C_FREG, C_NONE, 27, 12, 0, 0},
   292  	{AMOVW, C_LAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 27, 12, REGSP, 0},
   293  	{AMOVF, C_LAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 27, 12, REGSP, 0},
   294  	{AMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, C_NONE, 27, 12, REGSP, 0},
   295  	{AMOVW, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 27, 12, REGZERO, 0},
   296  	{AMOVF, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 27, 12, REGZERO, 0},
   297  	{AMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, C_NONE, 27, 12, REGZERO, 0},
   298  	{AMOVF, C_ADDR, C_NONE, C_NONE, C_FREG, C_NONE, 51, 8, 0, 0},
   299  	{AMOVF, C_ADDR, C_NONE, C_NONE, C_FREG, C_NONE, 51, 8, 0, 0},
   300  	{AMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, C_NONE, 51, 8, 0, 0},
   301  	{AMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, C_NONE, 51, 8, 0, 0},
   302  
   303  	{AMOVW, C_FREG, C_NONE, C_NONE, C_SEXT, C_NONE, 28, 4, 0, 0},
   304  	{AMOVF, C_FREG, C_NONE, C_NONE, C_SEXT, C_NONE, 28, 4, 0, 0},
   305  	{AMOVD, C_FREG, C_NONE, C_NONE, C_SEXT, C_NONE, 28, 4, 0, 0},
   306  	{AMOVW, C_FREG, C_NONE, C_NONE, C_SAUTO, C_NONE, 28, 4, REGSP, 0},
   307  	{AMOVF, C_FREG, C_NONE, C_NONE, C_SAUTO, C_NONE, 28, 4, REGSP, 0},
   308  	{AMOVD, C_FREG, C_NONE, C_NONE, C_SAUTO, C_NONE, 28, 4, REGSP, 0},
   309  	{AMOVW, C_FREG, C_NONE, C_NONE, C_SOREG, C_NONE, 28, 4, REGZERO, 0},
   310  	{AMOVF, C_FREG, C_NONE, C_NONE, C_SOREG, C_NONE, 28, 4, REGZERO, 0},
   311  	{AMOVD, C_FREG, C_NONE, C_NONE, C_SOREG, C_NONE, 28, 4, REGZERO, 0},
   312  
   313  	{AMOVW, C_FREG, C_NONE, C_NONE, C_LEXT, C_NONE, 28, 12, 0, 0},
   314  	{AMOVF, C_FREG, C_NONE, C_NONE, C_LEXT, C_NONE, 28, 12, 0, 0},
   315  	{AMOVD, C_FREG, C_NONE, C_NONE, C_LEXT, C_NONE, 28, 12, 0, 0},
   316  	{AMOVW, C_FREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 28, 12, REGSP, 0},
   317  	{AMOVF, C_FREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 28, 12, REGSP, 0},
   318  	{AMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, C_NONE, 28, 12, REGSP, 0},
   319  	{AMOVW, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 28, 12, REGZERO, 0},
   320  	{AMOVF, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 28, 12, REGZERO, 0},
   321  	{AMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, C_NONE, 28, 12, REGZERO, 0},
   322  	{AMOVF, C_FREG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
   323  	{AMOVF, C_FREG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
   324  	{AMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
   325  	{AMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, C_NONE, 50, 8, 0, 0},
   326  
   327  	{AMOVW, C_REG, C_NONE, C_NONE, C_FREG, C_NONE, 30, 4, 0, 0},
   328  	{AMOVW, C_FREG, C_NONE, C_NONE, C_REG, C_NONE, 31, 4, 0, 0},
   329  	{AMOVV, C_REG, C_NONE, C_NONE, C_FREG, C_NONE, 47, 4, 0, 0},
   330  	{AMOVV, C_FREG, C_NONE, C_NONE, C_REG, C_NONE, 48, 4, 0, 0},
   331  
   332  	{AMOVV, C_FCCREG, C_NONE, C_NONE, C_REG, C_NONE, 63, 4, 0, 0},
   333  	{AMOVV, C_REG, C_NONE, C_NONE, C_FCCREG, C_NONE, 64, 4, 0, 0},
   334  
   335  	{AMOVW, C_ADDCON, C_NONE, C_NONE, C_FREG, C_NONE, 34, 8, 0, 0},
   336  	{AMOVW, C_ANDCON, C_NONE, C_NONE, C_FREG, C_NONE, 34, 8, 0, 0},
   337  
   338  	{AMOVB, C_REG, C_NONE, C_NONE, C_TLS_IE, C_NONE, 56, 16, 0, 0},
   339  	{AMOVW, C_REG, C_NONE, C_NONE, C_TLS_IE, C_NONE, 56, 16, 0, 0},
   340  	{AMOVV, C_REG, C_NONE, C_NONE, C_TLS_IE, C_NONE, 56, 16, 0, 0},
   341  	{AMOVBU, C_REG, C_NONE, C_NONE, C_TLS_IE, C_NONE, 56, 16, 0, 0},
   342  	{AMOVWU, C_REG, C_NONE, C_NONE, C_TLS_IE, C_NONE, 56, 16, 0, 0},
   343  
   344  	{AMOVB, C_TLS_IE, C_NONE, C_NONE, C_REG, C_NONE, 57, 16, 0, 0},
   345  	{AMOVW, C_TLS_IE, C_NONE, C_NONE, C_REG, C_NONE, 57, 16, 0, 0},
   346  	{AMOVV, C_TLS_IE, C_NONE, C_NONE, C_REG, C_NONE, 57, 16, 0, 0},
   347  	{AMOVBU, C_TLS_IE, C_NONE, C_NONE, C_REG, C_NONE, 57, 16, 0, 0},
   348  	{AMOVWU, C_TLS_IE, C_NONE, C_NONE, C_REG, C_NONE, 57, 16, 0, 0},
   349  
   350  	{AWORD, C_LCON, C_NONE, C_NONE, C_NONE, C_NONE, 40, 4, 0, 0},
   351  	{AWORD, C_DCON, C_NONE, C_NONE, C_NONE, C_NONE, 61, 4, 0, 0},
   352  
   353  	{AMOVV, C_GOTADDR, C_NONE, C_NONE, C_REG, C_NONE, 65, 8, 0, 0},
   354  
   355  	{ATEQ, C_SCON, C_REG, C_NONE, C_REG, C_NONE, 15, 8, 0, 0},
   356  	{ATEQ, C_SCON, C_NONE, C_NONE, C_REG, C_NONE, 15, 8, 0, 0},
   357  
   358  	{ABREAK, C_REG, C_NONE, C_NONE, C_SEXT, C_NONE, 7, 4, 0, 0}, // really CACHE instruction
   359  	{ABREAK, C_REG, C_NONE, C_NONE, C_SAUTO, C_NONE, 7, 4, REGSP, 0},
   360  	{ABREAK, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 7, 4, REGZERO, 0},
   361  	{ABREAK, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 5, 4, 0, 0},
   362  
   363  	{ARDTIMELW, C_NONE, C_NONE, C_NONE, C_REG, C_REG, 62, 4, 0, 0},
   364  	{ARDTIMEHW, C_NONE, C_NONE, C_NONE, C_REG, C_REG, 62, 4, 0, 0},
   365  	{ARDTIMED, C_NONE, C_NONE, C_NONE, C_REG, C_REG, 62, 4, 0, 0},
   366  
   367  	{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 49, 4, 0, 0},
   368  	{obj.APCALIGN, C_SCON, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
   369  	{obj.APCDATA, C_LCON, C_NONE, C_NONE, C_LCON, C_NONE, 0, 0, 0, 0},
   370  	{obj.APCDATA, C_DCON, C_NONE, C_NONE, C_DCON, C_NONE, 0, 0, 0, 0},
   371  	{obj.AFUNCDATA, C_SCON, C_NONE, C_NONE, C_ADDR, C_NONE, 0, 0, 0, 0},
   372  	{obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
   373  	{obj.ANOP, C_LCON, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0}, // nop variants, see #40689
   374  	{obj.ANOP, C_DCON, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0}, // nop variants, see #40689
   375  	{obj.ANOP, C_REG, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
   376  	{obj.ANOP, C_FREG, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
   377  	{obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_LBRA, C_NONE, 11, 4, 0, 0}, // same as AJMP
   378  	{obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_LBRA, C_NONE, 11, 4, 0, 0}, // same as AJMP
   379  
   380  	{obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0},
   381  }
   382  
   383  // pcAlignPadLength returns the number of bytes required to align pc to alignedValue,
   384  // reporting an error if alignedValue is not a power of two or is out of range.
   385  func pcAlignPadLength(ctxt *obj.Link, pc int64, alignedValue int64) int {
   386  	if !((alignedValue&(alignedValue-1) == 0) && 8 <= alignedValue && alignedValue <= 2048) {
   387  		ctxt.Diag("alignment value of an instruction must be a power of two and in the range [8, 2048], got %d\n", alignedValue)
   388  	}
   389  	return int(-pc & (alignedValue - 1))
   390  }
   391  
   392  var oprange [ALAST & obj.AMask][]Optab
   393  
   394  var xcmp [C_NCLASS][C_NCLASS]bool
   395  
   396  func span0(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
   397  	if ctxt.Retpoline {
   398  		ctxt.Diag("-spectre=ret not supported on loong64")
   399  		ctxt.Retpoline = false // don't keep printing
   400  	}
   401  
   402  	p := cursym.Func().Text
   403  	if p == nil || p.Link == nil { // handle external functions and ELF section symbols
   404  		return
   405  	}
   406  
   407  	c := ctxt0{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset + ctxt.Arch.FixedFrameSize)}
   408  
   409  	if oprange[AOR&obj.AMask] == nil {
   410  		c.ctxt.Diag("loong64 ops not initialized, call loong64.buildop first")
   411  	}
   412  
   413  	pc := int64(0)
   414  	p.Pc = pc
   415  
   416  	var m int
   417  	var o *Optab
   418  	for p = p.Link; p != nil; p = p.Link {
   419  		p.Pc = pc
   420  		o = c.oplook(p)
   421  		m = int(o.size)
   422  		if m == 0 {
   423  			switch p.As {
   424  			case obj.APCALIGN:
   425  				alignedValue := p.From.Offset
   426  				m = pcAlignPadLength(ctxt, pc, alignedValue)
   427  				// Update the current text symbol alignment value.
   428  				if int32(alignedValue) > cursym.Func().Align {
   429  					cursym.Func().Align = int32(alignedValue)
   430  				}
   431  				break
   432  			case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
   433  				continue
   434  			default:
   435  				c.ctxt.Diag("zero-width instruction\n%v", p)
   436  			}
   437  		}
   438  
   439  		pc += int64(m)
   440  	}
   441  
   442  	c.cursym.Size = pc
   443  
   444  	// mark loop entry instructions for padding
   445  	// loop entrances are defined as targets of backward branches
   446  	for p = c.cursym.Func().Text.Link; p != nil; p = p.Link {
   447  		if q := p.To.Target(); q != nil && q.Pc < p.Pc {
   448  			q.Mark |= branchLoopHead
   449  		}
   450  	}
   451  
   452  	// Run these passes until convergence.
   453  	bflag := 1
   454  	var otxt int64
   455  	var q *obj.Prog
   456  	for bflag != 0 {
   457  		bflag = 0
   458  		pc = 0
   459  		prev := c.cursym.Func().Text
   460  		for p = prev.Link; p != nil; prev, p = p, p.Link {
   461  			p.Pc = pc
   462  			o = c.oplook(p)
   463  
   464  			// Prepend a PCALIGN $loopAlign to each of the loop heads
   465  			// that need padding, if not already done so (because this
   466  			// pass may execute more than once).
   467  			//
   468  			// This needs to come before any pass that look at pc,
   469  			// because pc will be adjusted if padding happens.
   470  			if p.Mark&branchLoopHead != 0 && pc&(loopAlign-1) != 0 &&
   471  				!(prev.As == obj.APCALIGN && prev.From.Offset >= loopAlign) {
   472  				q = c.newprog()
   473  				prev.Link = q
   474  				q.Link = p
   475  				q.Pc = pc
   476  				q.As = obj.APCALIGN
   477  				q.From.Type = obj.TYPE_CONST
   478  				q.From.Offset = loopAlign
   479  				// Don't associate the synthesized PCALIGN with
   480  				// the original source position, for deterministic
   481  				// mapping between source and corresponding asm.
   482  				// q.Pos = p.Pos
   483  
   484  				// Manually make the PCALIGN come into effect,
   485  				// since this loop iteration is for p.
   486  				pc += int64(pcAlignPadLength(ctxt, pc, loopAlign))
   487  				p.Pc = pc
   488  			}
   489  
   490  			// very large conditional branches
   491  			//
   492  			// if any procedure is large enough to
   493  			// generate a large SBRA branch, then
   494  			// generate extra passes putting branches
   495  			// around jmps to fix. this is rare.
   496  			if o.type_ == 6 && p.To.Target() != nil {
   497  				otxt = p.To.Target().Pc - pc
   498  				if otxt < -(1<<17)+10 || otxt >= (1<<17)-10 {
   499  					q = c.newprog()
   500  					q.Link = p.Link
   501  					p.Link = q
   502  					q.As = AJMP
   503  					q.Pos = p.Pos
   504  					q.To.Type = obj.TYPE_BRANCH
   505  					q.To.SetTarget(p.To.Target())
   506  					p.To.SetTarget(q)
   507  					q = c.newprog()
   508  					q.Link = p.Link
   509  					p.Link = q
   510  					q.As = AJMP
   511  					q.Pos = p.Pos
   512  					q.To.Type = obj.TYPE_BRANCH
   513  					q.To.SetTarget(q.Link.Link)
   514  					bflag = 1
   515  				}
   516  			}
   517  
   518  			m = int(o.size)
   519  			if m == 0 {
   520  				switch p.As {
   521  				case obj.APCALIGN:
   522  					alignedValue := p.From.Offset
   523  					m = pcAlignPadLength(ctxt, pc, alignedValue)
   524  					break
   525  				case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
   526  					continue
   527  				default:
   528  					c.ctxt.Diag("zero-width instruction\n%v", p)
   529  				}
   530  			}
   531  
   532  			pc += int64(m)
   533  		}
   534  
   535  		c.cursym.Size = pc
   536  	}
   537  	pc += -pc & (FuncAlign - 1)
   538  	c.cursym.Size = pc
   539  
   540  	// lay out the code, emitting code and data relocations.
   541  
   542  	c.cursym.Grow(c.cursym.Size)
   543  
   544  	bp := c.cursym.P
   545  	var i int32
   546  	var out [5]uint32
   547  	for p := c.cursym.Func().Text.Link; p != nil; p = p.Link {
   548  		c.pc = p.Pc
   549  		o = c.oplook(p)
   550  		if int(o.size) > 4*len(out) {
   551  			log.Fatalf("out array in span0 is too small, need at least %d for %v", o.size/4, p)
   552  		}
   553  		if p.As == obj.APCALIGN {
   554  			alignedValue := p.From.Offset
   555  			v := pcAlignPadLength(c.ctxt, p.Pc, alignedValue)
   556  			for i = 0; i < int32(v/4); i++ {
   557  				// emit ANOOP instruction by the padding size
   558  				c.ctxt.Arch.ByteOrder.PutUint32(bp, c.oprrr(ANOOP))
   559  				bp = bp[4:]
   560  			}
   561  			continue
   562  		}
   563  		c.asmout(p, o, out[:])
   564  		for i = 0; i < int32(o.size/4); i++ {
   565  			c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
   566  			bp = bp[4:]
   567  		}
   568  	}
   569  
   570  	// Mark nonpreemptible instruction sequences.
   571  	// We use REGTMP as a scratch register during call injection,
   572  	// so instruction sequences that use REGTMP are unsafe to
   573  	// preempt asynchronously.
   574  	obj.MarkUnsafePoints(c.ctxt, c.cursym.Func().Text, c.newprog, c.isUnsafePoint, c.isRestartable)
   575  }
   576  
   577  // isUnsafePoint returns whether p is an unsafe point.
   578  func (c *ctxt0) isUnsafePoint(p *obj.Prog) bool {
   579  	// If p explicitly uses REGTMP, it's unsafe to preempt, because the
   580  	// preemption sequence clobbers REGTMP.
   581  	return p.From.Reg == REGTMP || p.To.Reg == REGTMP || p.Reg == REGTMP
   582  }
   583  
   584  // isRestartable returns whether p is a multi-instruction sequence that,
   585  // if preempted, can be restarted.
   586  func (c *ctxt0) isRestartable(p *obj.Prog) bool {
   587  	if c.isUnsafePoint(p) {
   588  		return false
   589  	}
   590  	// If p is a multi-instruction sequence with uses REGTMP inserted by
   591  	// the assembler in order to materialize a large constant/offset, we
   592  	// can restart p (at the start of the instruction sequence), recompute
   593  	// the content of REGTMP, upon async preemption. Currently, all cases
   594  	// of assembler-inserted REGTMP fall into this category.
   595  	// If p doesn't use REGTMP, it can be simply preempted, so we don't
   596  	// mark it.
   597  	o := c.oplook(p)
   598  	return o.size > 4 && o.flag&NOTUSETMP == 0
   599  }
   600  
   601  func isint32(v int64) bool {
   602  	return int64(int32(v)) == v
   603  }
   604  
   605  func isuint32(v uint64) bool {
   606  	return uint64(uint32(v)) == v
   607  }
   608  
   609  func (c *ctxt0) aclass(a *obj.Addr) int {
   610  	switch a.Type {
   611  	case obj.TYPE_NONE:
   612  		return C_NONE
   613  
   614  	case obj.TYPE_REG:
   615  		if REG_R0 <= a.Reg && a.Reg <= REG_R31 {
   616  			return C_REG
   617  		}
   618  		if REG_F0 <= a.Reg && a.Reg <= REG_F31 {
   619  			return C_FREG
   620  		}
   621  		if REG_FCSR0 <= a.Reg && a.Reg <= REG_FCSR31 {
   622  			return C_FCSRREG
   623  		}
   624  		if REG_FCC0 <= a.Reg && a.Reg <= REG_FCC31 {
   625  			return C_FCCREG
   626  		}
   627  		return C_GOK
   628  
   629  	case obj.TYPE_MEM:
   630  		switch a.Name {
   631  		case obj.NAME_EXTERN,
   632  			obj.NAME_STATIC:
   633  			if a.Sym == nil {
   634  				break
   635  			}
   636  			c.instoffset = a.Offset
   637  			if a.Sym != nil { // use relocation
   638  				if a.Sym.Type == objabi.STLSBSS {
   639  					if c.ctxt.Flag_shared {
   640  						return C_TLS_IE
   641  					} else {
   642  						return C_TLS_LE
   643  					}
   644  				}
   645  				return C_ADDR
   646  			}
   647  			return C_LEXT
   648  
   649  		case obj.NAME_AUTO:
   650  			if a.Reg == REGSP {
   651  				// unset base register for better printing, since
   652  				// a.Offset is still relative to pseudo-SP.
   653  				a.Reg = obj.REG_NONE
   654  			}
   655  			c.instoffset = int64(c.autosize) + a.Offset
   656  			if c.instoffset >= -BIG && c.instoffset < BIG {
   657  				return C_SAUTO
   658  			}
   659  			return C_LAUTO
   660  
   661  		case obj.NAME_PARAM:
   662  			if a.Reg == REGSP {
   663  				// unset base register for better printing, since
   664  				// a.Offset is still relative to pseudo-FP.
   665  				a.Reg = obj.REG_NONE
   666  			}
   667  			c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.Arch.FixedFrameSize
   668  			if c.instoffset >= -BIG && c.instoffset < BIG {
   669  				return C_SAUTO
   670  			}
   671  			return C_LAUTO
   672  
   673  		case obj.NAME_NONE:
   674  			c.instoffset = a.Offset
   675  			if c.instoffset == 0 {
   676  				return C_ZOREG
   677  			}
   678  			if c.instoffset >= -BIG && c.instoffset < BIG {
   679  				return C_SOREG
   680  			}
   681  			return C_LOREG
   682  
   683  		case obj.NAME_GOTREF:
   684  			return C_GOTADDR
   685  		}
   686  
   687  		return C_GOK
   688  
   689  	case obj.TYPE_TEXTSIZE:
   690  		return C_TEXTSIZE
   691  
   692  	case obj.TYPE_CONST,
   693  		obj.TYPE_ADDR:
   694  		switch a.Name {
   695  		case obj.NAME_NONE:
   696  			c.instoffset = a.Offset
   697  			if a.Reg != 0 {
   698  				if -BIG <= c.instoffset && c.instoffset <= BIG {
   699  					return C_SACON
   700  				}
   701  				if isint32(c.instoffset) {
   702  					return C_LACON
   703  				}
   704  				return C_DACON
   705  			}
   706  
   707  		case obj.NAME_EXTERN,
   708  			obj.NAME_STATIC:
   709  			s := a.Sym
   710  			if s == nil {
   711  				return C_GOK
   712  			}
   713  
   714  			c.instoffset = a.Offset
   715  			if s.Type == objabi.STLSBSS {
   716  				return C_STCON // address of TLS variable
   717  			}
   718  			return C_LECON
   719  
   720  		case obj.NAME_AUTO:
   721  			if a.Reg == REGSP {
   722  				// unset base register for better printing, since
   723  				// a.Offset is still relative to pseudo-SP.
   724  				a.Reg = obj.REG_NONE
   725  			}
   726  			c.instoffset = int64(c.autosize) + a.Offset
   727  			if c.instoffset >= -BIG && c.instoffset < BIG {
   728  				return C_SACON
   729  			}
   730  			return C_LACON
   731  
   732  		case obj.NAME_PARAM:
   733  			if a.Reg == REGSP {
   734  				// unset base register for better printing, since
   735  				// a.Offset is still relative to pseudo-FP.
   736  				a.Reg = obj.REG_NONE
   737  			}
   738  			c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.Arch.FixedFrameSize
   739  			if c.instoffset >= -BIG && c.instoffset < BIG {
   740  				return C_SACON
   741  			}
   742  			return C_LACON
   743  
   744  		default:
   745  			return C_GOK
   746  		}
   747  
   748  		if c.instoffset != int64(int32(c.instoffset)) {
   749  			return C_DCON
   750  		}
   751  
   752  		if c.instoffset >= 0 {
   753  			if c.instoffset == 0 {
   754  				return C_ZCON
   755  			}
   756  			if c.instoffset <= 0x7ff {
   757  				return C_SCON
   758  			}
   759  			if c.instoffset <= 0xfff {
   760  				return C_ANDCON
   761  			}
   762  			if c.instoffset&0xfff == 0 && isuint32(uint64(c.instoffset)) { // && ((instoffset & (1<<31)) == 0)
   763  				return C_UCON
   764  			}
   765  			if isint32(c.instoffset) || isuint32(uint64(c.instoffset)) {
   766  				return C_LCON
   767  			}
   768  			return C_LCON
   769  		}
   770  
   771  		if c.instoffset >= -0x800 {
   772  			return C_ADDCON
   773  		}
   774  		if c.instoffset&0xfff == 0 && isint32(c.instoffset) {
   775  			return C_UCON
   776  		}
   777  		if isint32(c.instoffset) {
   778  			return C_LCON
   779  		}
   780  		return C_LCON
   781  
   782  	case obj.TYPE_BRANCH:
   783  		return C_SBRA
   784  	}
   785  
   786  	return C_GOK
   787  }
   788  
   789  func prasm(p *obj.Prog) {
   790  	fmt.Printf("%v\n", p)
   791  }
   792  
   793  func (c *ctxt0) oplook(p *obj.Prog) *Optab {
   794  	if oprange[AOR&obj.AMask] == nil {
   795  		c.ctxt.Diag("loong64 ops not initialized, call loong64.buildop first")
   796  	}
   797  
   798  	a1 := int(p.Optab)
   799  	if a1 != 0 {
   800  		return &optab[a1-1]
   801  	}
   802  
   803  	// first source operand
   804  	a1 = int(p.From.Class)
   805  	if a1 == 0 {
   806  		a1 = c.aclass(&p.From) + 1
   807  		p.From.Class = int8(a1)
   808  	}
   809  	a1--
   810  
   811  	// first destination operand
   812  	a4 := int(p.To.Class)
   813  	if a4 == 0 {
   814  		a4 = c.aclass(&p.To) + 1
   815  		p.To.Class = int8(a4)
   816  	}
   817  	a4--
   818  
   819  	// 2nd source operand
   820  	a2 := C_NONE
   821  	if p.Reg != 0 {
   822  		a2 = C_REG
   823  	}
   824  
   825  	// 2nd destination operand
   826  	a5 := C_NONE
   827  	if p.RegTo2 != 0 {
   828  		a5 = C_REG
   829  	}
   830  
   831  	// 3rd source operand
   832  	a3 := C_NONE
   833  	if len(p.RestArgs) > 0 {
   834  		a3 = int(p.RestArgs[0].Class)
   835  		if a3 == 0 {
   836  			a3 = c.aclass(&p.RestArgs[0].Addr) + 1
   837  			p.RestArgs[0].Class = int8(a3)
   838  		}
   839  		a3--
   840  	}
   841  
   842  	ops := oprange[p.As&obj.AMask]
   843  	c1 := &xcmp[a1]
   844  	c4 := &xcmp[a4]
   845  	for i := range ops {
   846  		op := &ops[i]
   847  		if (int(op.reg) == a2) && int(op.from3) == a3 && c1[op.from1] && c4[op.to1] && (int(op.to2) == a5) {
   848  			p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
   849  			return op
   850  		}
   851  	}
   852  
   853  	c.ctxt.Diag("illegal combination %v %v %v %v %v %v", p.As, DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4), DRconv(a5))
   854  	prasm(p)
   855  	// Turn illegal instruction into an UNDEF, avoid crashing in asmout.
   856  	return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 49, 4, 0, 0}
   857  }
   858  
   859  func cmp(a int, b int) bool {
   860  	if a == b {
   861  		return true
   862  	}
   863  	switch a {
   864  	case C_DCON:
   865  		if b == C_LCON {
   866  			return true
   867  		}
   868  		fallthrough
   869  	case C_LCON:
   870  		if b == C_ZCON || b == C_SCON || b == C_UCON || b == C_ADDCON || b == C_ANDCON {
   871  			return true
   872  		}
   873  
   874  	case C_ADD0CON:
   875  		if b == C_ADDCON {
   876  			return true
   877  		}
   878  		fallthrough
   879  
   880  	case C_ADDCON:
   881  		if b == C_ZCON || b == C_SCON {
   882  			return true
   883  		}
   884  
   885  	case C_AND0CON:
   886  		if b == C_ANDCON {
   887  			return true
   888  		}
   889  		fallthrough
   890  
   891  	case C_ANDCON:
   892  		if b == C_ZCON || b == C_SCON {
   893  			return true
   894  		}
   895  
   896  	case C_UCON:
   897  		if b == C_ZCON {
   898  			return true
   899  		}
   900  
   901  	case C_SCON:
   902  		if b == C_ZCON {
   903  			return true
   904  		}
   905  
   906  	case C_LACON:
   907  		if b == C_SACON {
   908  			return true
   909  		}
   910  
   911  	case C_LBRA:
   912  		if b == C_SBRA {
   913  			return true
   914  		}
   915  
   916  	case C_LEXT:
   917  		if b == C_SEXT {
   918  			return true
   919  		}
   920  
   921  	case C_LAUTO:
   922  		if b == C_SAUTO {
   923  			return true
   924  		}
   925  
   926  	case C_REG:
   927  		if b == C_ZCON {
   928  			return true
   929  		}
   930  
   931  	case C_LOREG:
   932  		if b == C_ZOREG || b == C_SOREG {
   933  			return true
   934  		}
   935  
   936  	case C_SOREG:
   937  		if b == C_ZOREG {
   938  			return true
   939  		}
   940  	}
   941  
   942  	return false
   943  }
   944  
   945  type ocmp []Optab
   946  
   947  func (x ocmp) Len() int {
   948  	return len(x)
   949  }
   950  
   951  func (x ocmp) Swap(i, j int) {
   952  	x[i], x[j] = x[j], x[i]
   953  }
   954  
   955  func (x ocmp) Less(i, j int) bool {
   956  	p1 := &x[i]
   957  	p2 := &x[j]
   958  	n := int(p1.as) - int(p2.as)
   959  	if n != 0 {
   960  		return n < 0
   961  	}
   962  	n = int(p1.from1) - int(p2.from1)
   963  	if n != 0 {
   964  		return n < 0
   965  	}
   966  	n = int(p1.reg) - int(p2.reg)
   967  	if n != 0 {
   968  		return n < 0
   969  	}
   970  	n = int(p1.to1) - int(p2.to1)
   971  	if n != 0 {
   972  		return n < 0
   973  	}
   974  	return false
   975  }
   976  
   977  func opset(a, b0 obj.As) {
   978  	oprange[a&obj.AMask] = oprange[b0]
   979  }
   980  
   981  func buildop(ctxt *obj.Link) {
   982  	if ctxt.DiagFunc == nil {
   983  		ctxt.DiagFunc = func(format string, args ...interface{}) {
   984  			log.Printf(format, args...)
   985  		}
   986  	}
   987  
   988  	if oprange[AOR&obj.AMask] != nil {
   989  		// Already initialized; stop now.
   990  		// This happens in the cmd/asm tests,
   991  		// each of which re-initializes the arch.
   992  		return
   993  	}
   994  
   995  	var n int
   996  
   997  	for i := 0; i < C_NCLASS; i++ {
   998  		for n = 0; n < C_NCLASS; n++ {
   999  			if cmp(n, i) {
  1000  				xcmp[i][n] = true
  1001  			}
  1002  		}
  1003  	}
  1004  	for n = 0; optab[n].as != obj.AXXX; n++ {
  1005  	}
  1006  	sort.Sort(ocmp(optab[:n]))
  1007  	for i := 0; i < n; i++ {
  1008  		r := optab[i].as
  1009  		r0 := r & obj.AMask
  1010  		start := i
  1011  		for optab[i].as == r {
  1012  			i++
  1013  		}
  1014  		oprange[r0] = optab[start:i]
  1015  		i--
  1016  
  1017  		switch r {
  1018  		default:
  1019  			ctxt.Diag("unknown op in build: %v", r)
  1020  			ctxt.DiagFlush()
  1021  			log.Fatalf("bad code")
  1022  
  1023  		case AABSF:
  1024  			opset(AMOVFD, r0)
  1025  			opset(AMOVDF, r0)
  1026  			opset(AMOVWF, r0)
  1027  			opset(AMOVFW, r0)
  1028  			opset(AMOVWD, r0)
  1029  			opset(AMOVDW, r0)
  1030  			opset(ANEGF, r0)
  1031  			opset(ANEGD, r0)
  1032  			opset(AABSD, r0)
  1033  			opset(ATRUNCDW, r0)
  1034  			opset(ATRUNCFW, r0)
  1035  			opset(ASQRTF, r0)
  1036  			opset(ASQRTD, r0)
  1037  
  1038  		case AMOVVF:
  1039  			opset(AMOVVD, r0)
  1040  			opset(AMOVFV, r0)
  1041  			opset(AMOVDV, r0)
  1042  			opset(ATRUNCDV, r0)
  1043  			opset(ATRUNCFV, r0)
  1044  
  1045  		case AADD:
  1046  			opset(ASGT, r0)
  1047  			opset(ASGTU, r0)
  1048  			opset(AADDU, r0)
  1049  
  1050  		case AADDV:
  1051  			opset(AADDVU, r0)
  1052  
  1053  		case AADDF:
  1054  			opset(ADIVF, r0)
  1055  			opset(ADIVD, r0)
  1056  			opset(AMULF, r0)
  1057  			opset(AMULD, r0)
  1058  			opset(ASUBF, r0)
  1059  			opset(ASUBD, r0)
  1060  			opset(AADDD, r0)
  1061  
  1062  		case AAND:
  1063  			opset(AOR, r0)
  1064  			opset(AXOR, r0)
  1065  
  1066  		case ABEQ:
  1067  			opset(ABNE, r0)
  1068  			opset(ABLT, r0)
  1069  			opset(ABGE, r0)
  1070  			opset(ABGEU, r0)
  1071  			opset(ABLTU, r0)
  1072  
  1073  		case ABLEZ:
  1074  			opset(ABGEZ, r0)
  1075  			opset(ABLTZ, r0)
  1076  			opset(ABGTZ, r0)
  1077  
  1078  		case AMOVB:
  1079  			opset(AMOVH, r0)
  1080  
  1081  		case AMOVBU:
  1082  			opset(AMOVHU, r0)
  1083  
  1084  		case AMUL:
  1085  			opset(AMULU, r0)
  1086  			opset(AMULH, r0)
  1087  			opset(AMULHU, r0)
  1088  			opset(AREM, r0)
  1089  			opset(AREMU, r0)
  1090  			opset(ADIV, r0)
  1091  			opset(ADIVU, r0)
  1092  
  1093  		case AMULV:
  1094  			opset(AMULVU, r0)
  1095  			opset(AMULHV, r0)
  1096  			opset(AMULHVU, r0)
  1097  			opset(AREMV, r0)
  1098  			opset(AREMVU, r0)
  1099  			opset(ADIVV, r0)
  1100  			opset(ADIVVU, r0)
  1101  
  1102  		case ASLL:
  1103  			opset(ASRL, r0)
  1104  			opset(ASRA, r0)
  1105  			opset(AROTR, r0)
  1106  
  1107  		case ASLLV:
  1108  			opset(ASRAV, r0)
  1109  			opset(ASRLV, r0)
  1110  			opset(AROTRV, r0)
  1111  
  1112  		case ASUB:
  1113  			opset(ASUBU, r0)
  1114  			opset(ANOR, r0)
  1115  
  1116  		case ASUBV:
  1117  			opset(ASUBVU, r0)
  1118  
  1119  		case ASYSCALL:
  1120  			opset(ADBAR, r0)
  1121  			opset(ANOOP, r0)
  1122  
  1123  		case ACMPEQF:
  1124  			opset(ACMPGTF, r0)
  1125  			opset(ACMPGTD, r0)
  1126  			opset(ACMPGEF, r0)
  1127  			opset(ACMPGED, r0)
  1128  			opset(ACMPEQD, r0)
  1129  
  1130  		case ABFPT:
  1131  			opset(ABFPF, r0)
  1132  
  1133  		case AMOVWL:
  1134  			opset(AMOVWR, r0)
  1135  
  1136  		case AMOVVL:
  1137  			opset(AMOVVR, r0)
  1138  
  1139  		case AMOVW,
  1140  			AMOVD,
  1141  			AMOVF,
  1142  			AMOVV,
  1143  			ABREAK,
  1144  			ARFE,
  1145  			AJAL,
  1146  			AJMP,
  1147  			AMOVWU,
  1148  			ALL,
  1149  			ALLV,
  1150  			ASC,
  1151  			ASCV,
  1152  			ANEGW,
  1153  			ANEGV,
  1154  			AWORD,
  1155  			ARDTIMELW,
  1156  			ARDTIMEHW,
  1157  			ARDTIMED,
  1158  			obj.ANOP,
  1159  			obj.ATEXT,
  1160  			obj.AUNDEF,
  1161  			obj.AFUNCDATA,
  1162  			obj.APCALIGN,
  1163  			obj.APCDATA,
  1164  			obj.ADUFFZERO,
  1165  			obj.ADUFFCOPY:
  1166  			break
  1167  
  1168  		case ACLO:
  1169  			opset(ACLZ, r0)
  1170  
  1171  		case ATEQ:
  1172  			opset(ATNE, r0)
  1173  
  1174  		case AMASKEQZ:
  1175  			opset(AMASKNEZ, r0)
  1176  		}
  1177  	}
  1178  }
  1179  
  1180  func OP(x uint32, y uint32) uint32 {
  1181  	return x<<3 | y<<0
  1182  }
  1183  
  1184  func SP(x uint32, y uint32) uint32 {
  1185  	return x<<29 | y<<26
  1186  }
  1187  
  1188  func OP_TEN(x uint32, y uint32) uint32 {
  1189  	return x<<21 | y<<10
  1190  }
  1191  
  1192  // r1 -> rk
  1193  // r2 -> rj
  1194  // r3 -> rd
  1195  func OP_RRR(op uint32, r1 uint32, r2 uint32, r3 uint32) uint32 {
  1196  	return op | (r1&0x1F)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
  1197  }
  1198  
  1199  // r2 -> rj
  1200  // r3 -> rd
  1201  func OP_RR(op uint32, r2 uint32, r3 uint32) uint32 {
  1202  	return op | (r2&0x1F)<<5 | (r3&0x1F)<<0
  1203  }
  1204  
  1205  func OP_16IR_5I(op uint32, i uint32, r2 uint32) uint32 {
  1206  	return op | (i&0xFFFF)<<10 | (r2&0x1F)<<5 | ((i >> 16) & 0x1F)
  1207  }
  1208  
  1209  func OP_16IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
  1210  	return op | (i&0xFFFF)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
  1211  }
  1212  
  1213  func OP_12IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
  1214  	return op | (i&0xFFF)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
  1215  }
  1216  
  1217  func OP_IR(op uint32, i uint32, r2 uint32) uint32 {
  1218  	return op | (i&0xFFFFF)<<5 | (r2&0x1F)<<0 // ui20, rd5
  1219  }
  1220  
  1221  // Encoding for the 'b' or 'bl' instruction.
  1222  func OP_B_BL(op uint32, i uint32) uint32 {
  1223  	return op | ((i & 0xFFFF) << 10) | ((i >> 16) & 0x3FF)
  1224  }
  1225  
  1226  func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
  1227  	o1 := uint32(0)
  1228  	o2 := uint32(0)
  1229  	o3 := uint32(0)
  1230  	o4 := uint32(0)
  1231  	o5 := uint32(0)
  1232  
  1233  	add := AADDU
  1234  	add = AADDVU
  1235  
  1236  	switch o.type_ {
  1237  	default:
  1238  		c.ctxt.Diag("unknown type %d %v", o.type_)
  1239  		prasm(p)
  1240  
  1241  	case 0: // pseudo ops
  1242  		break
  1243  
  1244  	case 1: // mov r1,r2 ==> OR r1,r0,r2
  1245  		a := AOR
  1246  		if p.As == AMOVW {
  1247  			a = ASLL
  1248  		}
  1249  		o1 = OP_RRR(c.oprrr(a), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg))
  1250  
  1251  	case 2: // add/sub r1,[r2],r3
  1252  		r := int(p.Reg)
  1253  		if p.As == ANEGW || p.As == ANEGV {
  1254  			r = REGZERO
  1255  		}
  1256  		if r == 0 {
  1257  			r = int(p.To.Reg)
  1258  		}
  1259  		o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
  1260  
  1261  	case 3: // mov $soreg, r ==> or/add $i,o,r
  1262  		v := c.regoff(&p.From)
  1263  
  1264  		r := int(p.From.Reg)
  1265  		if r == 0 {
  1266  			r = int(o.param)
  1267  		}
  1268  		a := add
  1269  		if o.from1 == C_ANDCON {
  1270  			a = AOR
  1271  		}
  1272  
  1273  		o1 = OP_12IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
  1274  
  1275  	case 4: // add $scon,[r1],r2
  1276  		v := c.regoff(&p.From)
  1277  
  1278  		r := int(p.Reg)
  1279  		if r == 0 {
  1280  			r = int(p.To.Reg)
  1281  		}
  1282  
  1283  		o1 = OP_12IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  1284  
  1285  	case 5: // syscall
  1286  		o1 = c.oprrr(p.As)
  1287  
  1288  	case 6: // beq r1,[r2],sbra
  1289  		v := int32(0)
  1290  		if p.To.Target() != nil {
  1291  			v = int32(p.To.Target().Pc-p.Pc) >> 2
  1292  		}
  1293  		as, rd, rj, width := p.As, p.Reg, p.From.Reg, 16
  1294  		switch as {
  1295  		case ABGTZ, ABLEZ:
  1296  			rd, rj = rj, rd
  1297  		case ABFPT, ABFPF:
  1298  			width = 21
  1299  			// FCC0 is the implicit source operand, now that we
  1300  			// don't register-allocate from the FCC bank.
  1301  			rd = REG_FCC0
  1302  		case ABEQ, ABNE:
  1303  			if rd == 0 || rd == REGZERO || rj == REGZERO {
  1304  				// BEQZ/BNEZ can be encoded with 21-bit offsets.
  1305  				width = 21
  1306  				as = -as
  1307  				if rj == 0 || rj == REGZERO {
  1308  					rj = rd
  1309  				}
  1310  			}
  1311  		}
  1312  		switch width {
  1313  		case 21:
  1314  			if (v<<11)>>11 != v {
  1315  				c.ctxt.Diag("21 bit-width, short branch too far\n%v", p)
  1316  			}
  1317  			o1 = OP_16IR_5I(c.opirr(as), uint32(v), uint32(rj))
  1318  		case 16:
  1319  			if (v<<16)>>16 != v {
  1320  				c.ctxt.Diag("16 bit-width, short branch too far\n%v", p)
  1321  			}
  1322  			o1 = OP_16IRR(c.opirr(as), uint32(v), uint32(rj), uint32(rd))
  1323  		default:
  1324  			c.ctxt.Diag("unexpected branch encoding\n%v", p)
  1325  		}
  1326  
  1327  	case 7: // mov r, soreg
  1328  		r := int(p.To.Reg)
  1329  		if r == 0 {
  1330  			r = int(o.param)
  1331  		}
  1332  		v := c.regoff(&p.To)
  1333  		o1 = OP_12IRR(c.opirr(p.As), uint32(v), uint32(r), uint32(p.From.Reg))
  1334  
  1335  	case 8: // mov soreg, r
  1336  		r := int(p.From.Reg)
  1337  		if r == 0 {
  1338  			r = int(o.param)
  1339  		}
  1340  		v := c.regoff(&p.From)
  1341  		o1 = OP_12IRR(c.opirr(-p.As), uint32(v), uint32(r), uint32(p.To.Reg))
  1342  
  1343  	case 9: // sll r1,[r2],r3
  1344  		if p.As != ACLO && p.As != ACLZ {
  1345  			r := int(p.Reg)
  1346  			if r == 0 {
  1347  				r = int(p.To.Reg)
  1348  			}
  1349  			o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
  1350  		} else { // clo r1,r2
  1351  			o1 = OP_RR(c.oprr(p.As), uint32(p.From.Reg), uint32(p.To.Reg))
  1352  		}
  1353  
  1354  	case 10: // add $con,[r1],r2 ==> mov $con, t; add t,[r1],r2
  1355  		v := c.regoff(&p.From)
  1356  		a := AOR
  1357  		if v < 0 {
  1358  			a = AADDU
  1359  		}
  1360  		o1 = OP_12IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
  1361  		r := int(p.Reg)
  1362  		if r == 0 {
  1363  			r = int(p.To.Reg)
  1364  		}
  1365  		o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  1366  
  1367  	case 11: // jmp lbra
  1368  		v := int32(0)
  1369  		if p.To.Target() != nil {
  1370  			v = int32(p.To.Target().Pc-p.Pc) >> 2
  1371  		}
  1372  		o1 = OP_B_BL(c.opirr(p.As), uint32(v))
  1373  		if p.To.Sym == nil {
  1374  			if p.As == AJMP {
  1375  				break
  1376  			}
  1377  			p.To.Sym = c.cursym.Func().Text.From.Sym
  1378  			p.To.Offset = p.To.Target().Pc
  1379  		}
  1380  		rel := obj.Addrel(c.cursym)
  1381  		rel.Off = int32(c.pc)
  1382  		rel.Siz = 4
  1383  		rel.Sym = p.To.Sym
  1384  		rel.Add = p.To.Offset
  1385  		rel.Type = objabi.R_CALLLOONG64
  1386  
  1387  	case 12: // movbs r,r
  1388  		// NOTE: this case does not use REGTMP. If it ever does,
  1389  		// remove the NOTUSETMP flag in optab.
  1390  		v := 16
  1391  		if p.As == AMOVB {
  1392  			v = 24
  1393  		}
  1394  		o1 = OP_16IRR(c.opirr(ASLL), uint32(v), uint32(p.From.Reg), uint32(p.To.Reg))
  1395  		o2 = OP_16IRR(c.opirr(ASRA), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
  1396  
  1397  	case 13: // movbu r,r
  1398  		if p.As == AMOVBU {
  1399  			o1 = OP_12IRR(c.opirr(AAND), uint32(0xff), uint32(p.From.Reg), uint32(p.To.Reg))
  1400  		} else {
  1401  			// bstrpick.d (msbd=15, lsbd=0)
  1402  			o1 = (0x33c0 << 10) | ((uint32(p.From.Reg) & 0x1f) << 5) | (uint32(p.To.Reg) & 0x1F)
  1403  		}
  1404  
  1405  	case 14: // movwu r,r
  1406  		// NOTE: this case does not use REGTMP. If it ever does,
  1407  		// remove the NOTUSETMP flag in optab.
  1408  		o1 = OP_16IRR(c.opirr(-ASLLV), uint32(32)&0x3f, uint32(p.From.Reg), uint32(p.To.Reg))
  1409  		o2 = OP_16IRR(c.opirr(-ASRLV), uint32(32)&0x3f, uint32(p.To.Reg), uint32(p.To.Reg))
  1410  
  1411  	case 15: // teq $c r,r
  1412  		v := c.regoff(&p.From)
  1413  		r := int(p.Reg)
  1414  		if r == 0 {
  1415  			r = REGZERO
  1416  		}
  1417  		/*
  1418  			teq c, r1, r2
  1419  			fallthrough
  1420  			==>
  1421  			bne r1, r2, 2
  1422  			break c
  1423  			fallthrough
  1424  		*/
  1425  		if p.As == ATEQ {
  1426  			o1 = OP_16IRR(c.opirr(ABNE), uint32(2), uint32(r), uint32(p.To.Reg))
  1427  		} else { // ATNE
  1428  			o1 = OP_16IRR(c.opirr(ABEQ), uint32(2), uint32(r), uint32(p.To.Reg))
  1429  		}
  1430  		o2 = c.oprrr(ABREAK) | (uint32(v) & 0x7FFF)
  1431  
  1432  	case 16: // sll $c,[r1],r2
  1433  		v := c.regoff(&p.From)
  1434  		r := int(p.Reg)
  1435  		if r == 0 {
  1436  			r = int(p.To.Reg)
  1437  		}
  1438  
  1439  		// instruction ending with V:6-digit immediate, others:5-digit immediate
  1440  		if v >= 32 && vshift(p.As) {
  1441  			o1 = OP_16IRR(c.opirr(p.As), uint32(v)&0x3f, uint32(r), uint32(p.To.Reg))
  1442  		} else {
  1443  			o1 = OP_16IRR(c.opirr(p.As), uint32(v)&0x1f, uint32(r), uint32(p.To.Reg))
  1444  		}
  1445  
  1446  	case 17:
  1447  		o1 = OP_RRR(c.oprrr(p.As), uint32(REGZERO), uint32(p.From.Reg), uint32(p.To.Reg))
  1448  
  1449  	case 18: // jmp [r1],0(r2)
  1450  		r := int(p.Reg)
  1451  		if r == 0 {
  1452  			r = int(o.param)
  1453  		}
  1454  		o1 = OP_RRR(c.oprrr(p.As), uint32(0), uint32(p.To.Reg), uint32(r))
  1455  		if p.As == obj.ACALL {
  1456  			rel := obj.Addrel(c.cursym)
  1457  			rel.Off = int32(c.pc)
  1458  			rel.Siz = 0
  1459  			rel.Type = objabi.R_CALLIND
  1460  		}
  1461  
  1462  	case 19: // mov $lcon,r
  1463  		// NOTE: this case does not use REGTMP. If it ever does,
  1464  		// remove the NOTUSETMP flag in optab.
  1465  		v := c.regoff(&p.From)
  1466  		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(p.To.Reg))
  1467  		o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
  1468  
  1469  	case 23: // add $lcon,r1,r2
  1470  		v := c.regoff(&p.From)
  1471  		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
  1472  		o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
  1473  		r := int(p.Reg)
  1474  		if r == 0 {
  1475  			r = int(p.To.Reg)
  1476  		}
  1477  		o3 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  1478  
  1479  	case 24: // mov $ucon,r
  1480  		v := c.regoff(&p.From)
  1481  		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(p.To.Reg))
  1482  
  1483  	case 25: // add/and $ucon,[r1],r2
  1484  		v := c.regoff(&p.From)
  1485  		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
  1486  		r := int(p.Reg)
  1487  		if r == 0 {
  1488  			r = int(p.To.Reg)
  1489  		}
  1490  		o2 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  1491  
  1492  	case 26: // mov $lsext/auto/oreg,r
  1493  		v := c.regoff(&p.From)
  1494  		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
  1495  		o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
  1496  		r := int(p.From.Reg)
  1497  		if r == 0 {
  1498  			r = int(o.param)
  1499  		}
  1500  		o3 = OP_RRR(c.oprrr(add), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  1501  
  1502  	case 27: // mov [sl]ext/auto/oreg,fr
  1503  		v := c.regoff(&p.From)
  1504  		r := int(p.From.Reg)
  1505  		if r == 0 {
  1506  			r = int(o.param)
  1507  		}
  1508  		a := -AMOVF
  1509  		if p.As == AMOVD {
  1510  			a = -AMOVD
  1511  		}
  1512  		switch o.size {
  1513  		case 12:
  1514  			o1 = OP_IR(c.opir(ALU12IW), uint32((v+1<<11)>>12), uint32(REGTMP))
  1515  			o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  1516  			o3 = OP_12IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
  1517  
  1518  		case 4:
  1519  			o1 = OP_12IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.To.Reg))
  1520  		}
  1521  
  1522  	case 28: // mov fr,[sl]ext/auto/oreg
  1523  		v := c.regoff(&p.To)
  1524  		r := int(p.To.Reg)
  1525  		if r == 0 {
  1526  			r = int(o.param)
  1527  		}
  1528  		a := AMOVF
  1529  		if p.As == AMOVD {
  1530  			a = AMOVD
  1531  		}
  1532  		switch o.size {
  1533  		case 12:
  1534  			o1 = OP_IR(c.opir(ALU12IW), uint32((v+1<<11)>>12), uint32(REGTMP))
  1535  			o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  1536  			o3 = OP_12IRR(c.opirr(a), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
  1537  
  1538  		case 4:
  1539  			o1 = OP_12IRR(c.opirr(a), uint32(v), uint32(r), uint32(p.From.Reg))
  1540  		}
  1541  
  1542  	case 30: // movw r,fr
  1543  		a := OP_TEN(8, 1321) // movgr2fr.w
  1544  		o1 = OP_RR(a, uint32(p.From.Reg), uint32(p.To.Reg))
  1545  
  1546  	case 31: // movw fr,r
  1547  		a := OP_TEN(8, 1325) // movfr2gr.s
  1548  		o1 = OP_RR(a, uint32(p.From.Reg), uint32(p.To.Reg))
  1549  
  1550  	case 32: // fadd fr1,[fr2],fr3
  1551  		r := int(p.Reg)
  1552  		if r == 0 {
  1553  			r = int(p.To.Reg)
  1554  		}
  1555  		o1 = OP_RRR(c.oprrr(p.As), uint32(p.From.Reg), uint32(r), uint32(p.To.Reg))
  1556  
  1557  	case 33: // fabs fr1, fr3
  1558  		o1 = OP_RRR(c.oprrr(p.As), uint32(0), uint32(p.From.Reg), uint32(p.To.Reg))
  1559  
  1560  	case 34: // mov $con,fr
  1561  		v := c.regoff(&p.From)
  1562  		a := AADDU
  1563  		if o.from1 == C_ANDCON {
  1564  			a = AOR
  1565  		}
  1566  		o1 = OP_12IRR(c.opirr(a), uint32(v), uint32(0), uint32(REGTMP))
  1567  		o2 = OP_RR(OP_TEN(8, 1321), uint32(REGTMP), uint32(p.To.Reg)) // movgr2fr.w
  1568  
  1569  	case 35: // mov r,lext/auto/oreg
  1570  		v := c.regoff(&p.To)
  1571  		r := int(p.To.Reg)
  1572  		if r == 0 {
  1573  			r = int(o.param)
  1574  		}
  1575  		o1 = OP_IR(c.opir(ALU12IW), uint32((v+1<<11)>>12), uint32(REGTMP))
  1576  		o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  1577  		o3 = OP_12IRR(c.opirr(p.As), uint32(v), uint32(REGTMP), uint32(p.From.Reg))
  1578  
  1579  	case 36: // mov lext/auto/oreg,r
  1580  		v := c.regoff(&p.From)
  1581  		r := int(p.From.Reg)
  1582  		if r == 0 {
  1583  			r = int(o.param)
  1584  		}
  1585  		o1 = OP_IR(c.opir(ALU12IW), uint32((v+1<<11)>>12), uint32(REGTMP))
  1586  		o2 = OP_RRR(c.oprrr(add), uint32(r), uint32(REGTMP), uint32(REGTMP))
  1587  		o3 = OP_12IRR(c.opirr(-p.As), uint32(v), uint32(REGTMP), uint32(p.To.Reg))
  1588  
  1589  	case 40: // word
  1590  		o1 = uint32(c.regoff(&p.From))
  1591  
  1592  	case 47: // movv r,fr
  1593  		a := OP_TEN(8, 1322) // movgr2fr.d
  1594  		o1 = OP_RR(a, uint32(p.From.Reg), uint32(p.To.Reg))
  1595  
  1596  	case 48: // movv fr,r
  1597  		a := OP_TEN(8, 1326) // movfr2gr.d
  1598  		o1 = OP_RR(a, uint32(p.From.Reg), uint32(p.To.Reg))
  1599  
  1600  	case 49: // undef
  1601  		o1 = c.oprrr(ABREAK)
  1602  
  1603  	// relocation operations
  1604  	case 50: // mov r,addr ==> pcalau12i + sw
  1605  		o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(REGTMP))
  1606  		rel := obj.Addrel(c.cursym)
  1607  		rel.Off = int32(c.pc)
  1608  		rel.Siz = 4
  1609  		rel.Sym = p.To.Sym
  1610  		rel.Add = p.To.Offset
  1611  		rel.Type = objabi.R_ADDRLOONG64U
  1612  
  1613  		o2 = OP_12IRR(c.opirr(p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
  1614  		rel2 := obj.Addrel(c.cursym)
  1615  		rel2.Off = int32(c.pc + 4)
  1616  		rel2.Siz = 4
  1617  		rel2.Sym = p.To.Sym
  1618  		rel2.Add = p.To.Offset
  1619  		rel2.Type = objabi.R_ADDRLOONG64
  1620  
  1621  	case 51: // mov addr,r ==> pcalau12i + lw
  1622  		o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(REGTMP))
  1623  		rel := obj.Addrel(c.cursym)
  1624  		rel.Off = int32(c.pc)
  1625  		rel.Siz = 4
  1626  		rel.Sym = p.From.Sym
  1627  		rel.Add = p.From.Offset
  1628  		rel.Type = objabi.R_ADDRLOONG64U
  1629  		o2 = OP_12IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
  1630  		rel2 := obj.Addrel(c.cursym)
  1631  		rel2.Off = int32(c.pc + 4)
  1632  		rel2.Siz = 4
  1633  		rel2.Sym = p.From.Sym
  1634  		rel2.Add = p.From.Offset
  1635  		rel2.Type = objabi.R_ADDRLOONG64
  1636  
  1637  	case 52: // mov $lext, r
  1638  		// NOTE: this case does not use REGTMP. If it ever does,
  1639  		// remove the NOTUSETMP flag in optab.
  1640  		o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(p.To.Reg))
  1641  		rel := obj.Addrel(c.cursym)
  1642  		rel.Off = int32(c.pc)
  1643  		rel.Siz = 4
  1644  		rel.Sym = p.From.Sym
  1645  		rel.Add = p.From.Offset
  1646  		rel.Type = objabi.R_ADDRLOONG64U
  1647  		o2 = OP_12IRR(c.opirr(add), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
  1648  		rel2 := obj.Addrel(c.cursym)
  1649  		rel2.Off = int32(c.pc + 4)
  1650  		rel2.Siz = 4
  1651  		rel2.Sym = p.From.Sym
  1652  		rel2.Add = p.From.Offset
  1653  		rel2.Type = objabi.R_ADDRLOONG64
  1654  
  1655  	case 53: // mov r, tlsvar ==>  lu12i.w + ori + add r2, regtmp + sw o(regtmp)
  1656  		// NOTE: this case does not use REGTMP. If it ever does,
  1657  		// remove the NOTUSETMP flag in optab.
  1658  		o1 = OP_IR(c.opir(ALU12IW), uint32(0), uint32(REGTMP))
  1659  		rel := obj.Addrel(c.cursym)
  1660  		rel.Off = int32(c.pc)
  1661  		rel.Siz = 4
  1662  		rel.Sym = p.To.Sym
  1663  		rel.Add = p.To.Offset
  1664  		rel.Type = objabi.R_ADDRLOONG64TLSU
  1665  		o2 = OP_12IRR(c.opirr(AOR), uint32(0), uint32(REGTMP), uint32(REGTMP))
  1666  		rel2 := obj.Addrel(c.cursym)
  1667  		rel2.Off = int32(c.pc + 4)
  1668  		rel2.Siz = 4
  1669  		rel2.Sym = p.To.Sym
  1670  		rel2.Add = p.To.Offset
  1671  		rel2.Type = objabi.R_ADDRLOONG64TLS
  1672  		o3 = OP_RRR(c.oprrr(AADDV), uint32(REG_R2), uint32(REGTMP), uint32(REGTMP))
  1673  		o4 = OP_12IRR(c.opirr(p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
  1674  
  1675  	case 54: // lu12i.w + ori + add r2, regtmp + lw o(regtmp)
  1676  		// NOTE: this case does not use REGTMP. If it ever does,
  1677  		// remove the NOTUSETMP flag in optab.
  1678  		o1 = OP_IR(c.opir(ALU12IW), uint32(0), uint32(REGTMP))
  1679  		rel := obj.Addrel(c.cursym)
  1680  		rel.Off = int32(c.pc)
  1681  		rel.Siz = 4
  1682  		rel.Sym = p.From.Sym
  1683  		rel.Add = p.From.Offset
  1684  		rel.Type = objabi.R_ADDRLOONG64TLSU
  1685  		o2 = OP_12IRR(c.opirr(AOR), uint32(0), uint32(REGTMP), uint32(REGTMP))
  1686  		rel2 := obj.Addrel(c.cursym)
  1687  		rel2.Off = int32(c.pc + 4)
  1688  		rel2.Siz = 4
  1689  		rel2.Sym = p.From.Sym
  1690  		rel2.Add = p.From.Offset
  1691  		rel2.Type = objabi.R_ADDRLOONG64TLS
  1692  		o3 = OP_RRR(c.oprrr(AADDV), uint32(REG_R2), uint32(REGTMP), uint32(REGTMP))
  1693  		o4 = OP_12IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
  1694  
  1695  	case 55: //  lu12i.w + ori + add r2, regtmp
  1696  		// NOTE: this case does not use REGTMP. If it ever does,
  1697  		// remove the NOTUSETMP flag in optab.
  1698  		o1 = OP_IR(c.opir(ALU12IW), uint32(0), uint32(REGTMP))
  1699  		rel := obj.Addrel(c.cursym)
  1700  		rel.Off = int32(c.pc)
  1701  		rel.Siz = 4
  1702  		rel.Sym = p.From.Sym
  1703  		rel.Add = p.From.Offset
  1704  		rel.Type = objabi.R_ADDRLOONG64TLSU
  1705  		o2 = OP_12IRR(c.opirr(AOR), uint32(0), uint32(REGTMP), uint32(REGTMP))
  1706  		rel2 := obj.Addrel(c.cursym)
  1707  		rel2.Off = int32(c.pc + 4)
  1708  		rel2.Siz = 4
  1709  		rel2.Sym = p.From.Sym
  1710  		rel2.Add = p.From.Offset
  1711  		rel2.Type = objabi.R_ADDRLOONG64TLS
  1712  		o3 = OP_RRR(c.oprrr(AADDV), uint32(REG_R2), uint32(REGTMP), uint32(p.To.Reg))
  1713  
  1714  	case 56: // mov r, tlsvar IE model ==> (pcalau12i + ld.d)tlsvar@got + add.d + st.d
  1715  		o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(REGTMP))
  1716  		rel := obj.Addrel(c.cursym)
  1717  		rel.Off = int32(c.pc)
  1718  		rel.Siz = 4
  1719  		rel.Sym = p.To.Sym
  1720  		rel.Add = 0x0
  1721  		rel.Type = objabi.R_LOONG64_TLS_IE_PCREL_HI
  1722  		o2 = OP_12IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(REGTMP))
  1723  		rel2 := obj.Addrel(c.cursym)
  1724  		rel2.Off = int32(c.pc + 4)
  1725  		rel2.Siz = 4
  1726  		rel2.Sym = p.To.Sym
  1727  		rel2.Add = 0x0
  1728  		rel2.Type = objabi.R_LOONG64_TLS_IE_LO
  1729  		o3 = OP_RRR(c.oprrr(AADDVU), uint32(REGTMP), uint32(REG_R2), uint32(REGTMP))
  1730  		o4 = OP_12IRR(c.opirr(p.As), uint32(0), uint32(REGTMP), uint32(p.From.Reg))
  1731  
  1732  	case 57: // mov tlsvar, r IE model ==> (pcalau12i + ld.d)tlsvar@got + add.d + ld.d
  1733  		o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(REGTMP))
  1734  		rel := obj.Addrel(c.cursym)
  1735  		rel.Off = int32(c.pc)
  1736  		rel.Siz = 4
  1737  		rel.Sym = p.From.Sym
  1738  		rel.Add = 0x0
  1739  		rel.Type = objabi.R_LOONG64_TLS_IE_PCREL_HI
  1740  		o2 = OP_12IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(REGTMP))
  1741  		rel2 := obj.Addrel(c.cursym)
  1742  		rel2.Off = int32(c.pc + 4)
  1743  		rel2.Siz = 4
  1744  		rel2.Sym = p.From.Sym
  1745  		rel2.Add = 0x0
  1746  		rel2.Type = objabi.R_LOONG64_TLS_IE_LO
  1747  		o3 = OP_RRR(c.oprrr(AADDVU), uint32(REGTMP), uint32(REG_R2), uint32(REGTMP))
  1748  		o4 = OP_12IRR(c.opirr(-p.As), uint32(0), uint32(REGTMP), uint32(p.To.Reg))
  1749  
  1750  	case 59: // mov $dcon,r
  1751  		// NOTE: this case does not use REGTMP. If it ever does,
  1752  		// remove the NOTUSETMP flag in optab.
  1753  		v := c.vregoff(&p.From)
  1754  		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(p.To.Reg))
  1755  		o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(p.To.Reg), uint32(p.To.Reg))
  1756  		o3 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(p.To.Reg))
  1757  		o4 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(p.To.Reg), uint32(p.To.Reg))
  1758  
  1759  	case 60: // add $dcon,r1,r2
  1760  		v := c.vregoff(&p.From)
  1761  		o1 = OP_IR(c.opir(ALU12IW), uint32(v>>12), uint32(REGTMP))
  1762  		o2 = OP_12IRR(c.opirr(AOR), uint32(v), uint32(REGTMP), uint32(REGTMP))
  1763  		o3 = OP_IR(c.opir(ALU32ID), uint32(v>>32), uint32(REGTMP))
  1764  		o4 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(REGTMP), uint32(REGTMP))
  1765  		r := int(p.Reg)
  1766  		if r == 0 {
  1767  			r = int(p.To.Reg)
  1768  		}
  1769  		o5 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
  1770  
  1771  	case 61: // word C_DCON
  1772  		o1 = uint32(c.vregoff(&p.From))
  1773  		o2 = uint32(c.vregoff(&p.From) >> 32)
  1774  
  1775  	case 62: // rdtimex rd, rj
  1776  		o1 = OP_RR(c.oprr(p.As), uint32(p.To.Reg), uint32(p.RegTo2))
  1777  
  1778  	case 63: // movv c_fcc0, c_reg ==> movcf2gr rd, cj
  1779  		a := OP_TEN(8, 1335)
  1780  		o1 = OP_RR(a, uint32(p.From.Reg), uint32(p.To.Reg))
  1781  
  1782  	case 64: // movv c_reg, c_fcc0 ==> movgr2cf cd, rj
  1783  		a := OP_TEN(8, 1334)
  1784  		o1 = OP_RR(a, uint32(p.From.Reg), uint32(p.To.Reg))
  1785  
  1786  	case 65: // mov sym@GOT, r ==> pcalau12i + ld.d
  1787  		o1 = OP_IR(c.opir(APCALAU12I), uint32(0), uint32(p.To.Reg))
  1788  		rel := obj.Addrel(c.cursym)
  1789  		rel.Off = int32(c.pc)
  1790  		rel.Siz = 4
  1791  		rel.Sym = p.From.Sym
  1792  		rel.Type = objabi.R_LOONG64_GOT_HI
  1793  		rel.Add = 0x0
  1794  		o2 = OP_12IRR(c.opirr(-p.As), uint32(0), uint32(p.To.Reg), uint32(p.To.Reg))
  1795  		rel2 := obj.Addrel(c.cursym)
  1796  		rel2.Off = int32(c.pc + 4)
  1797  		rel2.Siz = 4
  1798  		rel2.Sym = p.From.Sym
  1799  		rel2.Type = objabi.R_LOONG64_GOT_LO
  1800  		rel2.Add = 0x0
  1801  	}
  1802  
  1803  	out[0] = o1
  1804  	out[1] = o2
  1805  	out[2] = o3
  1806  	out[3] = o4
  1807  	out[4] = o5
  1808  }
  1809  
  1810  func (c *ctxt0) vregoff(a *obj.Addr) int64 {
  1811  	c.instoffset = 0
  1812  	c.aclass(a)
  1813  	return c.instoffset
  1814  }
  1815  
  1816  func (c *ctxt0) regoff(a *obj.Addr) int32 {
  1817  	return int32(c.vregoff(a))
  1818  }
  1819  
  1820  func (c *ctxt0) oprrr(a obj.As) uint32 {
  1821  	switch a {
  1822  	case AADD:
  1823  		return 0x20 << 15
  1824  	case AADDU:
  1825  		return 0x20 << 15
  1826  	case ASGT:
  1827  		return 0x24 << 15 // SLT
  1828  	case ASGTU:
  1829  		return 0x25 << 15 // SLTU
  1830  	case AMASKEQZ:
  1831  		return 0x26 << 15
  1832  	case AMASKNEZ:
  1833  		return 0x27 << 15
  1834  	case AAND:
  1835  		return 0x29 << 15
  1836  	case AOR:
  1837  		return 0x2a << 15
  1838  	case AXOR:
  1839  		return 0x2b << 15
  1840  	case ASUB:
  1841  		return 0x22 << 15
  1842  	case ASUBU, ANEGW:
  1843  		return 0x22 << 15
  1844  	case ANOR:
  1845  		return 0x28 << 15
  1846  	case ASLL:
  1847  		return 0x2e << 15
  1848  	case ASRL:
  1849  		return 0x2f << 15
  1850  	case ASRA:
  1851  		return 0x30 << 15
  1852  	case AROTR:
  1853  		return 0x36 << 15
  1854  	case ASLLV:
  1855  		return 0x31 << 15
  1856  	case ASRLV:
  1857  		return 0x32 << 15
  1858  	case ASRAV:
  1859  		return 0x33 << 15
  1860  	case AROTRV:
  1861  		return 0x37 << 15
  1862  	case AADDV:
  1863  		return 0x21 << 15
  1864  	case AADDVU:
  1865  		return 0x21 << 15
  1866  	case ASUBV:
  1867  		return 0x23 << 15
  1868  	case ASUBVU, ANEGV:
  1869  		return 0x23 << 15
  1870  
  1871  	case AMUL:
  1872  		return 0x38 << 15 // mul.w
  1873  	case AMULU:
  1874  		return 0x38 << 15 // mul.w
  1875  	case AMULH:
  1876  		return 0x39 << 15 // mulh.w
  1877  	case AMULHU:
  1878  		return 0x3a << 15 // mulhu.w
  1879  	case AMULV:
  1880  		return 0x3b << 15 // mul.d
  1881  	case AMULVU:
  1882  		return 0x3b << 15 // mul.d
  1883  	case AMULHV:
  1884  		return 0x3c << 15 // mulh.d
  1885  	case AMULHVU:
  1886  		return 0x3d << 15 // mulhu.d
  1887  	case ADIV:
  1888  		return 0x40 << 15 // div.w
  1889  	case ADIVU:
  1890  		return 0x42 << 15 // div.wu
  1891  	case ADIVV:
  1892  		return 0x44 << 15 // div.d
  1893  	case ADIVVU:
  1894  		return 0x46 << 15 // div.du
  1895  	case AREM:
  1896  		return 0x41 << 15 // mod.w
  1897  	case AREMU:
  1898  		return 0x43 << 15 // mod.wu
  1899  	case AREMV:
  1900  		return 0x45 << 15 // mod.d
  1901  	case AREMVU:
  1902  		return 0x47 << 15 // mod.du
  1903  
  1904  	case AJMP:
  1905  		return 0x13 << 26 // jirl r0, rj, 0
  1906  	case AJAL:
  1907  		return (0x13 << 26) | 1 // jirl r1, rj, 0
  1908  
  1909  	case ABREAK:
  1910  		return 0x54 << 15
  1911  	case ASYSCALL:
  1912  		return 0x56 << 15
  1913  	case ADIVF:
  1914  		return 0x20d << 15
  1915  	case ADIVD:
  1916  		return 0x20e << 15
  1917  	case AMULF:
  1918  		return 0x209 << 15
  1919  	case AMULD:
  1920  		return 0x20a << 15
  1921  	case ASUBF:
  1922  		return 0x205 << 15
  1923  	case ASUBD:
  1924  		return 0x206 << 15
  1925  	case AADDF:
  1926  		return 0x201 << 15
  1927  	case AADDD:
  1928  		return 0x202 << 15
  1929  	case ATRUNCFV:
  1930  		return 0x46a9 << 10
  1931  	case ATRUNCDV:
  1932  		return 0x46aa << 10
  1933  	case ATRUNCFW:
  1934  		return 0x46a1 << 10
  1935  	case ATRUNCDW:
  1936  		return 0x46a2 << 10
  1937  	case AMOVFV:
  1938  		return 0x46c9 << 10
  1939  	case AMOVDV:
  1940  		return 0x46ca << 10
  1941  	case AMOVVF:
  1942  		return 0x4746 << 10
  1943  	case AMOVVD:
  1944  		return 0x474a << 10
  1945  	case AMOVFW:
  1946  		return 0x46c1 << 10
  1947  	case AMOVDW:
  1948  		return 0x46c2 << 10
  1949  	case AMOVWF:
  1950  		return 0x4744 << 10
  1951  	case AMOVDF:
  1952  		return 0x4646 << 10
  1953  	case AMOVWD:
  1954  		return 0x4748 << 10
  1955  	case AMOVFD:
  1956  		return 0x4649 << 10
  1957  	case AABSF:
  1958  		return 0x4501 << 10
  1959  	case AABSD:
  1960  		return 0x4502 << 10
  1961  	case AMOVF:
  1962  		return 0x4525 << 10
  1963  	case AMOVD:
  1964  		return 0x4526 << 10
  1965  	case ANEGF:
  1966  		return 0x4505 << 10
  1967  	case ANEGD:
  1968  		return 0x4506 << 10
  1969  	case ACMPEQF:
  1970  		return 0x0c1<<20 | 0x4<<15 // FCMP.CEQ.S
  1971  	case ACMPEQD:
  1972  		return 0x0c2<<20 | 0x4<<15 // FCMP.CEQ.D
  1973  	case ACMPGED:
  1974  		return 0x0c2<<20 | 0x7<<15 // FCMP.SLE.D
  1975  	case ACMPGEF:
  1976  		return 0x0c1<<20 | 0x7<<15 // FCMP.SLE.S
  1977  	case ACMPGTD:
  1978  		return 0x0c2<<20 | 0x3<<15 // FCMP.SLT.D
  1979  	case ACMPGTF:
  1980  		return 0x0c1<<20 | 0x3<<15 // FCMP.SLT.S
  1981  
  1982  	case ASQRTF:
  1983  		return 0x4511 << 10
  1984  	case ASQRTD:
  1985  		return 0x4512 << 10
  1986  
  1987  	case ADBAR:
  1988  		return 0x70e4 << 15
  1989  	case ANOOP:
  1990  		// andi r0, r0, 0
  1991  		return 0x03400000
  1992  	}
  1993  
  1994  	if a < 0 {
  1995  		c.ctxt.Diag("bad rrr opcode -%v", -a)
  1996  	} else {
  1997  		c.ctxt.Diag("bad rrr opcode %v", a)
  1998  	}
  1999  	return 0
  2000  }
  2001  
  2002  func (c *ctxt0) oprr(a obj.As) uint32 {
  2003  	switch a {
  2004  	case ACLO:
  2005  		return 0x4 << 10
  2006  	case ACLZ:
  2007  		return 0x5 << 10
  2008  	case ARDTIMELW:
  2009  		return 0x18 << 10
  2010  	case ARDTIMEHW:
  2011  		return 0x19 << 10
  2012  	case ARDTIMED:
  2013  		return 0x1a << 10
  2014  	}
  2015  
  2016  	c.ctxt.Diag("bad rr opcode %v", a)
  2017  	return 0
  2018  }
  2019  
  2020  func (c *ctxt0) opir(a obj.As) uint32 {
  2021  	switch a {
  2022  	case ALU12IW:
  2023  		return 0x0a << 25
  2024  	case ALU32ID:
  2025  		return 0x0b << 25
  2026  	case APCALAU12I:
  2027  		return 0x0d << 25
  2028  	case APCADDU12I:
  2029  		return 0x0e << 25
  2030  	}
  2031  	return 0
  2032  }
  2033  
  2034  func (c *ctxt0) opirr(a obj.As) uint32 {
  2035  	switch a {
  2036  	case AADD, AADDU:
  2037  		return 0x00a << 22
  2038  	case ASGT:
  2039  		return 0x008 << 22
  2040  	case ASGTU:
  2041  		return 0x009 << 22
  2042  	case AAND:
  2043  		return 0x00d << 22
  2044  	case AOR:
  2045  		return 0x00e << 22
  2046  	case ALU52ID:
  2047  		return 0x00c << 22
  2048  	case AXOR:
  2049  		return 0x00f << 22
  2050  	case ASLL:
  2051  		return 0x00081 << 15
  2052  	case ASRL:
  2053  		return 0x00089 << 15
  2054  	case ASRA:
  2055  		return 0x00091 << 15
  2056  	case AROTR:
  2057  		return 0x00099 << 15
  2058  	case AADDV:
  2059  		return 0x00b << 22
  2060  	case AADDVU:
  2061  		return 0x00b << 22
  2062  
  2063  	case AJMP:
  2064  		return 0x14 << 26
  2065  	case AJAL,
  2066  		obj.ADUFFZERO,
  2067  		obj.ADUFFCOPY:
  2068  		return 0x15 << 26
  2069  
  2070  	case AJIRL:
  2071  		return 0x13 << 26
  2072  	case ABLTU:
  2073  		return 0x1a << 26
  2074  	case ABLT, ABLTZ, ABGTZ:
  2075  		return 0x18 << 26
  2076  	case ABGEU:
  2077  		return 0x1b << 26
  2078  	case ABGE, ABGEZ, ABLEZ:
  2079  		return 0x19 << 26
  2080  	case -ABEQ: // beqz
  2081  		return 0x10 << 26
  2082  	case -ABNE: // bnez
  2083  		return 0x11 << 26
  2084  	case ABEQ:
  2085  		return 0x16 << 26
  2086  	case ABNE:
  2087  		return 0x17 << 26
  2088  	case ABFPT:
  2089  		return 0x12<<26 | 0x1<<8
  2090  	case ABFPF:
  2091  		return 0x12<<26 | 0x0<<8
  2092  
  2093  	case AMOVB,
  2094  		AMOVBU:
  2095  		return 0x0a4 << 22
  2096  	case AMOVH,
  2097  		AMOVHU:
  2098  		return 0x0a5 << 22
  2099  	case AMOVW,
  2100  		AMOVWU:
  2101  		return 0x0a6 << 22
  2102  	case AMOVV:
  2103  		return 0x0a7 << 22
  2104  	case AMOVF:
  2105  		return 0x0ad << 22
  2106  	case AMOVD:
  2107  		return 0x0af << 22
  2108  	case AMOVWL:
  2109  		return 0x0bc << 22
  2110  	case AMOVWR:
  2111  		return 0x0bd << 22
  2112  	case AMOVVL:
  2113  		return 0x0be << 22
  2114  	case AMOVVR:
  2115  		return 0x0bf << 22
  2116  
  2117  	case ABREAK:
  2118  		return 0x018 << 22
  2119  
  2120  	case -AMOVWL:
  2121  		return 0x0b8 << 22
  2122  	case -AMOVWR:
  2123  		return 0x0b9 << 22
  2124  	case -AMOVVL:
  2125  		return 0x0ba << 22
  2126  	case -AMOVVR:
  2127  		return 0x0bb << 22
  2128  	case -AMOVB:
  2129  		return 0x0a0 << 22
  2130  	case -AMOVBU:
  2131  		return 0x0a8 << 22
  2132  	case -AMOVH:
  2133  		return 0x0a1 << 22
  2134  	case -AMOVHU:
  2135  		return 0x0a9 << 22
  2136  	case -AMOVW:
  2137  		return 0x0a2 << 22
  2138  	case -AMOVWU:
  2139  		return 0x0aa << 22
  2140  	case -AMOVV:
  2141  		return 0x0a3 << 22
  2142  	case -AMOVF:
  2143  		return 0x0ac << 22
  2144  	case -AMOVD:
  2145  		return 0x0ae << 22
  2146  
  2147  	case ASLLV,
  2148  		-ASLLV:
  2149  		return 0x0041 << 16
  2150  	case ASRLV,
  2151  		-ASRLV:
  2152  		return 0x0045 << 16
  2153  	case ASRAV,
  2154  		-ASRAV:
  2155  		return 0x0049 << 16
  2156  	case AROTRV,
  2157  		-AROTRV:
  2158  		return 0x004d << 16
  2159  	case -ALL:
  2160  		return 0x020 << 24
  2161  	case -ALLV:
  2162  		return 0x022 << 24
  2163  	case ASC:
  2164  		return 0x021 << 24
  2165  	case ASCV:
  2166  		return 0x023 << 24
  2167  	}
  2168  
  2169  	if a < 0 {
  2170  		c.ctxt.Diag("bad irr opcode -%v", -a)
  2171  	} else {
  2172  		c.ctxt.Diag("bad irr opcode %v", a)
  2173  	}
  2174  	return 0
  2175  }
  2176  
  2177  func vshift(a obj.As) bool {
  2178  	switch a {
  2179  	case ASLLV,
  2180  		ASRLV,
  2181  		ASRAV,
  2182  		AROTRV:
  2183  		return true
  2184  	}
  2185  	return false
  2186  }