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

View as plain text