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

View as plain text