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

View as plain text