Source file src/cmd/internal/obj/riscv/obj.go

     1  // Copyright © 2015 The Go Authors.  All rights reserved.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package riscv
    22  
    23  import (
    24  	"cmd/internal/obj"
    25  	"cmd/internal/objabi"
    26  	"cmd/internal/src"
    27  	"cmd/internal/sys"
    28  	"fmt"
    29  	"internal/abi"
    30  	"internal/buildcfg"
    31  	"log"
    32  	"math/bits"
    33  	"strings"
    34  )
    35  
    36  func buildop(ctxt *obj.Link) {}
    37  
    38  func jalToSym(ctxt *obj.Link, p *obj.Prog, lr int16) {
    39  	switch p.As {
    40  	case obj.ACALL, obj.AJMP, obj.ARET, obj.ADUFFZERO, obj.ADUFFCOPY:
    41  	default:
    42  		ctxt.Diag("unexpected Prog in jalToSym: %v", p)
    43  		return
    44  	}
    45  
    46  	p.As = AJAL
    47  	p.Mark |= NEED_JAL_RELOC
    48  	p.From.Type = obj.TYPE_REG
    49  	p.From.Reg = lr
    50  	p.Reg = obj.REG_NONE
    51  }
    52  
    53  // progedit is called individually for each *obj.Prog. It normalizes instruction
    54  // formats and eliminates as many pseudo-instructions as possible.
    55  func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
    56  	insData, err := instructionDataForAs(p.As)
    57  	if err != nil {
    58  		panic(fmt.Sprintf("failed to lookup instruction data for %v: %v", p.As, err))
    59  	}
    60  
    61  	// Expand binary instructions to ternary ones.
    62  	if p.Reg == obj.REG_NONE {
    63  		if insData.ternary {
    64  			p.Reg = p.To.Reg
    65  		}
    66  	}
    67  
    68  	// Rewrite instructions with constant operands to refer to the immediate
    69  	// form of the instruction.
    70  	if p.From.Type == obj.TYPE_CONST {
    71  		switch p.As {
    72  		case ASUB:
    73  			p.As, p.From.Offset = AADDI, -p.From.Offset
    74  		case ASUBW:
    75  			p.As, p.From.Offset = AADDIW, -p.From.Offset
    76  		default:
    77  			if insData.immForm != obj.AXXX {
    78  				p.As = insData.immForm
    79  			}
    80  		}
    81  	}
    82  
    83  	switch p.As {
    84  	case obj.AJMP:
    85  		// Turn JMP into JAL ZERO or JALR ZERO.
    86  		p.From.Type = obj.TYPE_REG
    87  		p.From.Reg = REG_ZERO
    88  
    89  		switch p.To.Type {
    90  		case obj.TYPE_BRANCH:
    91  			p.As = AJAL
    92  		case obj.TYPE_MEM:
    93  			switch p.To.Name {
    94  			case obj.NAME_NONE:
    95  				p.As = AJALR
    96  			case obj.NAME_EXTERN, obj.NAME_STATIC:
    97  				// Handled in preprocess.
    98  			default:
    99  				ctxt.Diag("unsupported name %d for %v", p.To.Name, p)
   100  			}
   101  		default:
   102  			panic(fmt.Sprintf("unhandled type %+v", p.To.Type))
   103  		}
   104  
   105  	case obj.ACALL:
   106  		switch p.To.Type {
   107  		case obj.TYPE_MEM:
   108  			// Handled in preprocess.
   109  		case obj.TYPE_REG:
   110  			p.As = AJALR
   111  			p.From.Type = obj.TYPE_REG
   112  			p.From.Reg = REG_LR
   113  		default:
   114  			ctxt.Diag("unknown destination type %+v in CALL: %v", p.To.Type, p)
   115  		}
   116  
   117  	case obj.AUNDEF:
   118  		p.As = AEBREAK
   119  
   120  	case AFMVXS:
   121  		// FMVXS is the old name for FMVXW.
   122  		p.As = AFMVXW
   123  
   124  	case AFMVSX:
   125  		// FMVSX is the old name for FMVWX.
   126  		p.As = AFMVWX
   127  
   128  	case ASCALL:
   129  		// SCALL is the old name for ECALL.
   130  		p.As = AECALL
   131  
   132  	case ASBREAK:
   133  		// SBREAK is the old name for EBREAK.
   134  		p.As = AEBREAK
   135  
   136  	case AMOV:
   137  		if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE && p.From.Reg == obj.REG_NONE && int64(int32(p.From.Offset)) != p.From.Offset {
   138  			if isShiftConst(p.From.Offset) {
   139  				break
   140  			}
   141  			// Put >32-bit constants in memory and load them.
   142  			p.From.Type = obj.TYPE_MEM
   143  			p.From.Sym = ctxt.Int64Sym(p.From.Offset)
   144  			p.From.Name = obj.NAME_EXTERN
   145  			p.From.Offset = 0
   146  		}
   147  
   148  	case AMOVD:
   149  		if p.From.Type == obj.TYPE_FCONST && p.From.Name == obj.NAME_NONE && p.From.Reg == obj.REG_NONE {
   150  			f64 := p.From.Val.(float64)
   151  			p.From.Type = obj.TYPE_MEM
   152  			p.From.Sym = ctxt.Float64Sym(f64)
   153  			p.From.Name = obj.NAME_EXTERN
   154  			p.From.Offset = 0
   155  		}
   156  	}
   157  
   158  	if ctxt.Flag_dynlink {
   159  		rewriteToUseGot(ctxt, p, newprog)
   160  	}
   161  }
   162  
   163  // Rewrite p, if necessary, to access global data via the global offset table.
   164  func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
   165  	if p.As == obj.ADUFFCOPY || p.As == obj.ADUFFZERO {
   166  		//     ADUFFxxx $offset
   167  		// becomes
   168  		//     MOV runtime.duffxxx@GOT, REG_TMP
   169  		//     ADD $offset, REG_TMP
   170  		//     CALL REG_TMP
   171  		var sym *obj.LSym
   172  		if p.As == obj.ADUFFCOPY {
   173  			sym = ctxt.LookupABI("runtime.duffcopy", obj.ABIInternal)
   174  		} else {
   175  			sym = ctxt.LookupABI("runtime.duffzero", obj.ABIInternal)
   176  		}
   177  		offset := p.To.Offset
   178  		p.As = AMOV
   179  		p.From.Type = obj.TYPE_MEM
   180  		p.From.Name = obj.NAME_GOTREF
   181  		p.From.Sym = sym
   182  		p.To.Type = obj.TYPE_REG
   183  		p.To.Reg = REG_TMP
   184  		p.To.Name = obj.NAME_NONE
   185  		p.To.Offset = 0
   186  		p.To.Sym = nil
   187  
   188  		p1 := obj.Appendp(p, newprog)
   189  		p1.As = AADD
   190  		p1.From.Type = obj.TYPE_CONST
   191  		p1.From.Offset = offset
   192  		p1.To.Type = obj.TYPE_REG
   193  		p1.To.Reg = REG_TMP
   194  
   195  		p2 := obj.Appendp(p1, newprog)
   196  		p2.As = obj.ACALL
   197  		p2.To.Type = obj.TYPE_REG
   198  		p2.To.Reg = REG_TMP
   199  	}
   200  
   201  	// We only care about global data: NAME_EXTERN means a global
   202  	// symbol in the Go sense and p.Sym.Local is true for a few internally
   203  	// defined symbols.
   204  	if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
   205  		// MOV $sym, Rx becomes MOV sym@GOT, Rx
   206  		// MOV $sym+<off>, Rx becomes MOV sym@GOT, Rx; ADD <off>, Rx
   207  		if p.As != AMOV {
   208  			ctxt.Diag("don't know how to handle TYPE_ADDR in %v with -dynlink", p)
   209  		}
   210  		if p.To.Type != obj.TYPE_REG {
   211  			ctxt.Diag("don't know how to handle LD instruction to non-register in %v with -dynlink", p)
   212  		}
   213  		p.From.Type = obj.TYPE_MEM
   214  		p.From.Name = obj.NAME_GOTREF
   215  		if p.From.Offset != 0 {
   216  			q := obj.Appendp(p, newprog)
   217  			q.As = AADD
   218  			q.From.Type = obj.TYPE_CONST
   219  			q.From.Offset = p.From.Offset
   220  			q.To = p.To
   221  			p.From.Offset = 0
   222  		}
   223  
   224  	}
   225  
   226  	if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN {
   227  		ctxt.Diag("don't know how to handle %v with -dynlink", p)
   228  	}
   229  
   230  	var source *obj.Addr
   231  	// MOVx sym, Ry becomes MOV sym@GOT, X31; MOVx (X31), Ry
   232  	// MOVx Ry, sym becomes MOV sym@GOT, X31; MOV Ry, (X31)
   233  	// An addition may be inserted between the two MOVs if there is an offset.
   234  	if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
   235  		if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
   236  			ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
   237  		}
   238  		source = &p.From
   239  	} else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
   240  		source = &p.To
   241  	} else {
   242  		return
   243  	}
   244  	if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
   245  		return
   246  	}
   247  	if source.Sym.Type == objabi.STLSBSS {
   248  		return
   249  	}
   250  	if source.Type != obj.TYPE_MEM {
   251  		ctxt.Diag("don't know how to handle %v with -dynlink", p)
   252  	}
   253  	p1 := obj.Appendp(p, newprog)
   254  	p1.As = AMOV
   255  	p1.From.Type = obj.TYPE_MEM
   256  	p1.From.Sym = source.Sym
   257  	p1.From.Name = obj.NAME_GOTREF
   258  	p1.To.Type = obj.TYPE_REG
   259  	p1.To.Reg = REG_TMP
   260  
   261  	p2 := obj.Appendp(p1, newprog)
   262  	p2.As = p.As
   263  	p2.From = p.From
   264  	p2.To = p.To
   265  	if p.From.Name == obj.NAME_EXTERN {
   266  		p2.From.Reg = REG_TMP
   267  		p2.From.Name = obj.NAME_NONE
   268  		p2.From.Sym = nil
   269  	} else if p.To.Name == obj.NAME_EXTERN {
   270  		p2.To.Reg = REG_TMP
   271  		p2.To.Name = obj.NAME_NONE
   272  		p2.To.Sym = nil
   273  	} else {
   274  		return
   275  	}
   276  	obj.Nopout(p)
   277  
   278  }
   279  
   280  // addrToReg extracts the register from an Addr, handling special Addr.Names.
   281  func addrToReg(a obj.Addr) int16 {
   282  	switch a.Name {
   283  	case obj.NAME_PARAM, obj.NAME_AUTO:
   284  		return REG_SP
   285  	}
   286  	return a.Reg
   287  }
   288  
   289  // movToLoad converts a MOV mnemonic into the corresponding load instruction.
   290  func movToLoad(mnemonic obj.As) obj.As {
   291  	switch mnemonic {
   292  	case AMOV:
   293  		return ALD
   294  	case AMOVB:
   295  		return ALB
   296  	case AMOVH:
   297  		return ALH
   298  	case AMOVW:
   299  		return ALW
   300  	case AMOVBU:
   301  		return ALBU
   302  	case AMOVHU:
   303  		return ALHU
   304  	case AMOVWU:
   305  		return ALWU
   306  	case AMOVF:
   307  		return AFLW
   308  	case AMOVD:
   309  		return AFLD
   310  	default:
   311  		panic(fmt.Sprintf("%+v is not a MOV", mnemonic))
   312  	}
   313  }
   314  
   315  // movToStore converts a MOV mnemonic into the corresponding store instruction.
   316  func movToStore(mnemonic obj.As) obj.As {
   317  	switch mnemonic {
   318  	case AMOV:
   319  		return ASD
   320  	case AMOVB:
   321  		return ASB
   322  	case AMOVH:
   323  		return ASH
   324  	case AMOVW:
   325  		return ASW
   326  	case AMOVF:
   327  		return AFSW
   328  	case AMOVD:
   329  		return AFSD
   330  	default:
   331  		panic(fmt.Sprintf("%+v is not a MOV", mnemonic))
   332  	}
   333  }
   334  
   335  // markRelocs marks an obj.Prog that specifies a MOV pseudo-instruction and
   336  // requires relocation.
   337  func markRelocs(p *obj.Prog) {
   338  	switch p.As {
   339  	case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
   340  		switch {
   341  		case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG:
   342  			switch p.From.Name {
   343  			case obj.NAME_EXTERN, obj.NAME_STATIC:
   344  				p.Mark |= NEED_PCREL_ITYPE_RELOC
   345  			case obj.NAME_GOTREF:
   346  				p.Mark |= NEED_GOT_PCREL_ITYPE_RELOC
   347  			}
   348  		case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG:
   349  			switch p.From.Name {
   350  			case obj.NAME_EXTERN, obj.NAME_STATIC:
   351  				p.Mark |= NEED_PCREL_ITYPE_RELOC
   352  			case obj.NAME_GOTREF:
   353  				p.Mark |= NEED_GOT_PCREL_ITYPE_RELOC
   354  			}
   355  		case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM:
   356  			switch p.To.Name {
   357  			case obj.NAME_EXTERN, obj.NAME_STATIC:
   358  				p.Mark |= NEED_PCREL_STYPE_RELOC
   359  			}
   360  		}
   361  	}
   362  }
   363  
   364  // InvertBranch inverts the condition of a conditional branch.
   365  func InvertBranch(as obj.As) obj.As {
   366  	switch as {
   367  	case ABEQ:
   368  		return ABNE
   369  	case ABEQZ:
   370  		return ABNEZ
   371  	case ABGE:
   372  		return ABLT
   373  	case ABGEU:
   374  		return ABLTU
   375  	case ABGEZ:
   376  		return ABLTZ
   377  	case ABGT:
   378  		return ABLE
   379  	case ABGTU:
   380  		return ABLEU
   381  	case ABGTZ:
   382  		return ABLEZ
   383  	case ABLE:
   384  		return ABGT
   385  	case ABLEU:
   386  		return ABGTU
   387  	case ABLEZ:
   388  		return ABGTZ
   389  	case ABLT:
   390  		return ABGE
   391  	case ABLTU:
   392  		return ABGEU
   393  	case ABLTZ:
   394  		return ABGEZ
   395  	case ABNE:
   396  		return ABEQ
   397  	case ABNEZ:
   398  		return ABEQZ
   399  	default:
   400  		panic("InvertBranch: not a branch")
   401  	}
   402  }
   403  
   404  // containsCall reports whether the symbol contains a CALL (or equivalent)
   405  // instruction. Must be called after progedit.
   406  func containsCall(sym *obj.LSym) bool {
   407  	// CALLs are CALL or JAL(R) with link register LR.
   408  	for p := sym.Func().Text; p != nil; p = p.Link {
   409  		switch p.As {
   410  		case obj.ACALL, obj.ADUFFZERO, obj.ADUFFCOPY:
   411  			return true
   412  		case AJAL, AJALR:
   413  			if p.From.Type == obj.TYPE_REG && p.From.Reg == REG_LR {
   414  				return true
   415  			}
   416  		}
   417  	}
   418  
   419  	return false
   420  }
   421  
   422  // setPCs sets the Pc field in all instructions reachable from p.
   423  // It uses pc as the initial value and returns the next available pc.
   424  func setPCs(p *obj.Prog, pc int64) int64 {
   425  	for ; p != nil; p = p.Link {
   426  		p.Pc = pc
   427  		for _, ins := range instructionsForProg(p) {
   428  			pc += int64(ins.length())
   429  		}
   430  
   431  		if p.As == obj.APCALIGN {
   432  			alignedValue := p.From.Offset
   433  			v := pcAlignPadLength(pc, alignedValue)
   434  			pc += int64(v)
   435  		}
   436  	}
   437  	return pc
   438  }
   439  
   440  // stackOffset updates Addr offsets based on the current stack size.
   441  //
   442  // The stack looks like:
   443  // -------------------
   444  // |                 |
   445  // |      PARAMs     |
   446  // |                 |
   447  // |                 |
   448  // -------------------
   449  // |    Parent RA    |   SP on function entry
   450  // -------------------
   451  // |                 |
   452  // |                 |
   453  // |       AUTOs     |
   454  // |                 |
   455  // |                 |
   456  // -------------------
   457  // |        RA       |   SP during function execution
   458  // -------------------
   459  //
   460  // FixedFrameSize makes other packages aware of the space allocated for RA.
   461  //
   462  // A nicer version of this diagram can be found on slide 21 of the presentation
   463  // attached to https://golang.org/issue/16922#issuecomment-243748180.
   464  func stackOffset(a *obj.Addr, stacksize int64) {
   465  	switch a.Name {
   466  	case obj.NAME_AUTO:
   467  		// Adjust to the top of AUTOs.
   468  		a.Offset += stacksize
   469  	case obj.NAME_PARAM:
   470  		// Adjust to the bottom of PARAMs.
   471  		a.Offset += stacksize + 8
   472  	}
   473  }
   474  
   475  // preprocess generates prologue and epilogue code, computes PC-relative branch
   476  // and jump offsets, and resolves pseudo-registers.
   477  //
   478  // preprocess is called once per linker symbol.
   479  //
   480  // When preprocess finishes, all instructions in the symbol are either
   481  // concrete, real RISC-V instructions or directive pseudo-ops like TEXT,
   482  // PCDATA, and FUNCDATA.
   483  func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
   484  	if cursym.Func().Text == nil || cursym.Func().Text.Link == nil {
   485  		return
   486  	}
   487  
   488  	// Generate the prologue.
   489  	text := cursym.Func().Text
   490  	if text.As != obj.ATEXT {
   491  		ctxt.Diag("preprocess: found symbol that does not start with TEXT directive")
   492  		return
   493  	}
   494  
   495  	stacksize := text.To.Offset
   496  	if stacksize == -8 {
   497  		// Historical way to mark NOFRAME.
   498  		text.From.Sym.Set(obj.AttrNoFrame, true)
   499  		stacksize = 0
   500  	}
   501  	if stacksize < 0 {
   502  		ctxt.Diag("negative frame size %d - did you mean NOFRAME?", stacksize)
   503  	}
   504  	if text.From.Sym.NoFrame() {
   505  		if stacksize != 0 {
   506  			ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", stacksize)
   507  		}
   508  	}
   509  
   510  	if !containsCall(cursym) {
   511  		text.From.Sym.Set(obj.AttrLeaf, true)
   512  		if stacksize == 0 {
   513  			// A leaf function with no locals has no frame.
   514  			text.From.Sym.Set(obj.AttrNoFrame, true)
   515  		}
   516  	}
   517  
   518  	// Save LR unless there is no frame.
   519  	if !text.From.Sym.NoFrame() {
   520  		stacksize += ctxt.Arch.FixedFrameSize
   521  	}
   522  
   523  	cursym.Func().Args = text.To.Val.(int32)
   524  	cursym.Func().Locals = int32(stacksize)
   525  
   526  	prologue := text
   527  
   528  	if !cursym.Func().Text.From.Sym.NoSplit() {
   529  		prologue = stacksplit(ctxt, prologue, cursym, newprog, stacksize) // emit split check
   530  	}
   531  
   532  	q := prologue
   533  
   534  	if stacksize != 0 {
   535  		prologue = ctxt.StartUnsafePoint(prologue, newprog)
   536  
   537  		// Actually save LR.
   538  		prologue = obj.Appendp(prologue, newprog)
   539  		prologue.As = AMOV
   540  		prologue.Pos = q.Pos
   541  		prologue.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
   542  		prologue.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: -stacksize}
   543  
   544  		// Insert stack adjustment.
   545  		prologue = obj.Appendp(prologue, newprog)
   546  		prologue.As = AADDI
   547  		prologue.Pos = q.Pos
   548  		prologue.Pos = prologue.Pos.WithXlogue(src.PosPrologueEnd)
   549  		prologue.From = obj.Addr{Type: obj.TYPE_CONST, Offset: -stacksize}
   550  		prologue.Reg = REG_SP
   551  		prologue.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
   552  		prologue.Spadj = int32(stacksize)
   553  
   554  		prologue = ctxt.EndUnsafePoint(prologue, newprog, -1)
   555  
   556  		// On Linux, in a cgo binary we may get a SIGSETXID signal early on
   557  		// before the signal stack is set, as glibc doesn't allow us to block
   558  		// SIGSETXID. So a signal may land on the current stack and clobber
   559  		// the content below the SP. We store the LR again after the SP is
   560  		// decremented.
   561  		prologue = obj.Appendp(prologue, newprog)
   562  		prologue.As = AMOV
   563  		prologue.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
   564  		prologue.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0}
   565  	}
   566  
   567  	if cursym.Func().Text.From.Sym.Wrapper() {
   568  		// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
   569  		//
   570  		//   MOV g_panic(g), X5
   571  		//   BNE X5, ZERO, adjust
   572  		// end:
   573  		//   NOP
   574  		// ...rest of function..
   575  		// adjust:
   576  		//   MOV panic_argp(X5), X6
   577  		//   ADD $(autosize+FIXED_FRAME), SP, X7
   578  		//   BNE X6, X7, end
   579  		//   ADD $FIXED_FRAME, SP, X6
   580  		//   MOV X6, panic_argp(X5)
   581  		//   JMP end
   582  		//
   583  		// The NOP is needed to give the jumps somewhere to land.
   584  
   585  		ldpanic := obj.Appendp(prologue, newprog)
   586  
   587  		ldpanic.As = AMOV
   588  		ldpanic.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REGG, Offset: 4 * int64(ctxt.Arch.PtrSize)} // G.panic
   589  		ldpanic.Reg = obj.REG_NONE
   590  		ldpanic.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X5}
   591  
   592  		bneadj := obj.Appendp(ldpanic, newprog)
   593  		bneadj.As = ABNE
   594  		bneadj.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X5}
   595  		bneadj.Reg = REG_ZERO
   596  		bneadj.To.Type = obj.TYPE_BRANCH
   597  
   598  		endadj := obj.Appendp(bneadj, newprog)
   599  		endadj.As = obj.ANOP
   600  
   601  		last := endadj
   602  		for last.Link != nil {
   603  			last = last.Link
   604  		}
   605  
   606  		getargp := obj.Appendp(last, newprog)
   607  		getargp.As = AMOV
   608  		getargp.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_X5, Offset: 0} // Panic.argp
   609  		getargp.Reg = obj.REG_NONE
   610  		getargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X6}
   611  
   612  		bneadj.To.SetTarget(getargp)
   613  
   614  		calcargp := obj.Appendp(getargp, newprog)
   615  		calcargp.As = AADDI
   616  		calcargp.From = obj.Addr{Type: obj.TYPE_CONST, Offset: stacksize + ctxt.Arch.FixedFrameSize}
   617  		calcargp.Reg = REG_SP
   618  		calcargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X7}
   619  
   620  		testargp := obj.Appendp(calcargp, newprog)
   621  		testargp.As = ABNE
   622  		testargp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X6}
   623  		testargp.Reg = REG_X7
   624  		testargp.To.Type = obj.TYPE_BRANCH
   625  		testargp.To.SetTarget(endadj)
   626  
   627  		adjargp := obj.Appendp(testargp, newprog)
   628  		adjargp.As = AADDI
   629  		adjargp.From = obj.Addr{Type: obj.TYPE_CONST, Offset: int64(ctxt.Arch.PtrSize)}
   630  		adjargp.Reg = REG_SP
   631  		adjargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X6}
   632  
   633  		setargp := obj.Appendp(adjargp, newprog)
   634  		setargp.As = AMOV
   635  		setargp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X6}
   636  		setargp.Reg = obj.REG_NONE
   637  		setargp.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_X5, Offset: 0} // Panic.argp
   638  
   639  		godone := obj.Appendp(setargp, newprog)
   640  		godone.As = AJAL
   641  		godone.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
   642  		godone.To.Type = obj.TYPE_BRANCH
   643  		godone.To.SetTarget(endadj)
   644  	}
   645  
   646  	// Update stack-based offsets.
   647  	for p := cursym.Func().Text; p != nil; p = p.Link {
   648  		stackOffset(&p.From, stacksize)
   649  		stackOffset(&p.To, stacksize)
   650  	}
   651  
   652  	// Additional instruction rewriting.
   653  	for p := cursym.Func().Text; p != nil; p = p.Link {
   654  		switch p.As {
   655  		case obj.AGETCALLERPC:
   656  			if cursym.Leaf() {
   657  				// MOV LR, Rd
   658  				p.As = AMOV
   659  				p.From.Type = obj.TYPE_REG
   660  				p.From.Reg = REG_LR
   661  			} else {
   662  				// MOV (RSP), Rd
   663  				p.As = AMOV
   664  				p.From.Type = obj.TYPE_MEM
   665  				p.From.Reg = REG_SP
   666  			}
   667  
   668  		case obj.ACALL, obj.ADUFFZERO, obj.ADUFFCOPY:
   669  			switch p.To.Type {
   670  			case obj.TYPE_MEM:
   671  				jalToSym(ctxt, p, REG_LR)
   672  			}
   673  
   674  		case obj.AJMP:
   675  			switch p.To.Type {
   676  			case obj.TYPE_MEM:
   677  				switch p.To.Name {
   678  				case obj.NAME_EXTERN, obj.NAME_STATIC:
   679  					jalToSym(ctxt, p, REG_ZERO)
   680  				}
   681  			}
   682  
   683  		case obj.ARET:
   684  			// Replace RET with epilogue.
   685  			retJMP := p.To.Sym
   686  
   687  			if stacksize != 0 {
   688  				// Restore LR.
   689  				p.As = AMOV
   690  				p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0}
   691  				p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
   692  				p = obj.Appendp(p, newprog)
   693  
   694  				p.As = AADDI
   695  				p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: stacksize}
   696  				p.Reg = REG_SP
   697  				p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
   698  				p.Spadj = int32(-stacksize)
   699  				p = obj.Appendp(p, newprog)
   700  			}
   701  
   702  			if retJMP != nil {
   703  				p.As = obj.ARET
   704  				p.To.Sym = retJMP
   705  				jalToSym(ctxt, p, REG_ZERO)
   706  			} else {
   707  				p.As = AJALR
   708  				p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
   709  				p.Reg = obj.REG_NONE
   710  				p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
   711  			}
   712  
   713  			// "Add back" the stack removed in the previous instruction.
   714  			//
   715  			// This is to avoid confusing pctospadj, which sums
   716  			// Spadj from function entry to each PC, and shouldn't
   717  			// count adjustments from earlier epilogues, since they
   718  			// won't affect later PCs.
   719  			p.Spadj = int32(stacksize)
   720  
   721  		case AADDI:
   722  			// Refine Spadjs account for adjustment via ADDI instruction.
   723  			if p.To.Type == obj.TYPE_REG && p.To.Reg == REG_SP && p.From.Type == obj.TYPE_CONST {
   724  				p.Spadj = int32(-p.From.Offset)
   725  			}
   726  		}
   727  
   728  		if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.Spadj == 0 {
   729  			f := cursym.Func()
   730  			if f.FuncFlag&abi.FuncFlagSPWrite == 0 {
   731  				f.FuncFlag |= abi.FuncFlagSPWrite
   732  				if ctxt.Debugvlog || !ctxt.IsAsm {
   733  					ctxt.Logf("auto-SPWRITE: %s %v\n", cursym.Name, p)
   734  					if !ctxt.IsAsm {
   735  						ctxt.Diag("invalid auto-SPWRITE in non-assembly")
   736  						ctxt.DiagFlush()
   737  						log.Fatalf("bad SPWRITE")
   738  					}
   739  				}
   740  			}
   741  		}
   742  	}
   743  
   744  	var callCount int
   745  	for p := cursym.Func().Text; p != nil; p = p.Link {
   746  		markRelocs(p)
   747  		if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC {
   748  			callCount++
   749  		}
   750  	}
   751  	const callTrampSize = 8 // 2 machine instructions.
   752  	maxTrampSize := int64(callCount * callTrampSize)
   753  
   754  	// Compute instruction addresses.  Once we do that, we need to check for
   755  	// overextended jumps and branches.  Within each iteration, Pc differences
   756  	// are always lower bounds (since the program gets monotonically longer,
   757  	// a fixed point will be reached).  No attempt to handle functions > 2GiB.
   758  	for {
   759  		big, rescan := false, false
   760  		maxPC := setPCs(cursym.Func().Text, 0)
   761  		if maxPC+maxTrampSize > (1 << 20) {
   762  			big = true
   763  		}
   764  
   765  		for p := cursym.Func().Text; p != nil; p = p.Link {
   766  			switch p.As {
   767  			case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ:
   768  				if p.To.Type != obj.TYPE_BRANCH {
   769  					ctxt.Diag("%v: instruction with branch-like opcode lacks destination", p)
   770  					break
   771  				}
   772  				offset := p.To.Target().Pc - p.Pc
   773  				if offset < -4096 || 4096 <= offset {
   774  					// Branch is long.  Replace it with a jump.
   775  					jmp := obj.Appendp(p, newprog)
   776  					jmp.As = AJAL
   777  					jmp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
   778  					jmp.To = obj.Addr{Type: obj.TYPE_BRANCH}
   779  					jmp.To.SetTarget(p.To.Target())
   780  
   781  					p.As = InvertBranch(p.As)
   782  					p.To.SetTarget(jmp.Link)
   783  
   784  					// We may have made previous branches too long,
   785  					// so recheck them.
   786  					rescan = true
   787  				}
   788  			case AJAL:
   789  				// Linker will handle the intersymbol case and trampolines.
   790  				if p.To.Target() == nil {
   791  					if !big {
   792  						break
   793  					}
   794  					// This function is going to be too large for JALs
   795  					// to reach trampolines. Replace with AUIPC+JALR.
   796  					jmp := obj.Appendp(p, newprog)
   797  					jmp.As = AJALR
   798  					jmp.From = p.From
   799  					jmp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
   800  
   801  					p.As = AAUIPC
   802  					p.Mark = (p.Mark &^ NEED_JAL_RELOC) | NEED_CALL_RELOC
   803  					p.AddRestSource(obj.Addr{Type: obj.TYPE_CONST, Offset: p.To.Offset, Sym: p.To.Sym})
   804  					p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0}
   805  					p.Reg = obj.REG_NONE
   806  					p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
   807  
   808  					rescan = true
   809  					break
   810  				}
   811  				offset := p.To.Target().Pc - p.Pc
   812  				if offset < -(1<<20) || (1<<20) <= offset {
   813  					// Replace with 2-instruction sequence. This assumes
   814  					// that TMP is not live across J instructions, since
   815  					// it is reserved by SSA.
   816  					jmp := obj.Appendp(p, newprog)
   817  					jmp.As = AJALR
   818  					jmp.From = p.From
   819  					jmp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
   820  
   821  					// p.From is not generally valid, however will be
   822  					// fixed up in the next loop.
   823  					p.As = AAUIPC
   824  					p.From = obj.Addr{Type: obj.TYPE_BRANCH, Sym: p.From.Sym}
   825  					p.From.SetTarget(p.To.Target())
   826  					p.Reg = obj.REG_NONE
   827  					p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
   828  
   829  					rescan = true
   830  				}
   831  			}
   832  		}
   833  
   834  		// Return if errors have been detected up to this point. Continuing
   835  		// may lead to duplicate errors being output.
   836  		if ctxt.Errors > 0 {
   837  			return
   838  		}
   839  		if !rescan {
   840  			break
   841  		}
   842  	}
   843  
   844  	// Now that there are no long branches, resolve branch and jump targets.
   845  	// At this point, instruction rewriting which changes the number of
   846  	// instructions will break everything--don't do it!
   847  	for p := cursym.Func().Text; p != nil; p = p.Link {
   848  		switch p.As {
   849  		case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ:
   850  			switch p.To.Type {
   851  			case obj.TYPE_BRANCH:
   852  				p.To.Type, p.To.Offset = obj.TYPE_CONST, p.To.Target().Pc-p.Pc
   853  			case obj.TYPE_MEM:
   854  				if ctxt.Errors == 0 {
   855  					// An error should have already been reported for this instruction
   856  					panic("unhandled type")
   857  				}
   858  			}
   859  
   860  		case AJAL:
   861  			// Linker will handle the intersymbol case and trampolines.
   862  			if p.To.Target() != nil {
   863  				p.To.Type, p.To.Offset = obj.TYPE_CONST, p.To.Target().Pc-p.Pc
   864  			}
   865  
   866  		case AAUIPC:
   867  			if p.From.Type == obj.TYPE_BRANCH {
   868  				low, high, err := Split32BitImmediate(p.From.Target().Pc - p.Pc)
   869  				if err != nil {
   870  					ctxt.Diag("%v: jump displacement %d too large", p, p.To.Target().Pc-p.Pc)
   871  				}
   872  				p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high, Sym: cursym}
   873  				p.Link.To.Offset = low
   874  			}
   875  
   876  		case obj.APCALIGN:
   877  			alignedValue := p.From.Offset
   878  			if (alignedValue&(alignedValue-1) != 0) || 4 > alignedValue || alignedValue > 2048 {
   879  				ctxt.Diag("alignment value of an instruction must be a power of two and in the range [4, 2048], got %d\n", alignedValue)
   880  			}
   881  			// Update the current text symbol alignment value.
   882  			if int32(alignedValue) > cursym.Func().Align {
   883  				cursym.Func().Align = int32(alignedValue)
   884  			}
   885  		}
   886  	}
   887  
   888  	// Validate all instructions - this provides nice error messages.
   889  	for p := cursym.Func().Text; p != nil; p = p.Link {
   890  		for _, ins := range instructionsForProg(p) {
   891  			ins.validate(ctxt)
   892  		}
   893  	}
   894  }
   895  
   896  func pcAlignPadLength(pc int64, alignedValue int64) int {
   897  	return int(-pc & (alignedValue - 1))
   898  }
   899  
   900  func stacksplit(ctxt *obj.Link, p *obj.Prog, cursym *obj.LSym, newprog obj.ProgAlloc, framesize int64) *obj.Prog {
   901  	// Leaf function with no frame is effectively NOSPLIT.
   902  	if framesize == 0 {
   903  		return p
   904  	}
   905  
   906  	if ctxt.Flag_maymorestack != "" {
   907  		// Save LR and REGCTXT
   908  		const frameSize = 16
   909  		p = ctxt.StartUnsafePoint(p, newprog)
   910  
   911  		// Spill Arguments. This has to happen before we open
   912  		// any more frame space.
   913  		p = cursym.Func().SpillRegisterArgs(p, newprog)
   914  
   915  		// MOV LR, -16(SP)
   916  		p = obj.Appendp(p, newprog)
   917  		p.As = AMOV
   918  		p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
   919  		p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: -frameSize}
   920  		// ADDI $-16, SP
   921  		p = obj.Appendp(p, newprog)
   922  		p.As = AADDI
   923  		p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: -frameSize}
   924  		p.Reg = REG_SP
   925  		p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
   926  		p.Spadj = frameSize
   927  		// MOV REGCTXT, 8(SP)
   928  		p = obj.Appendp(p, newprog)
   929  		p.As = AMOV
   930  		p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_CTXT}
   931  		p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 8}
   932  
   933  		// CALL maymorestack
   934  		p = obj.Appendp(p, newprog)
   935  		p.As = obj.ACALL
   936  		p.To.Type = obj.TYPE_BRANCH
   937  		// See ../x86/obj6.go
   938  		p.To.Sym = ctxt.LookupABI(ctxt.Flag_maymorestack, cursym.ABI())
   939  		jalToSym(ctxt, p, REG_X5)
   940  
   941  		// Restore LR and REGCTXT
   942  
   943  		// MOV 8(SP), REGCTXT
   944  		p = obj.Appendp(p, newprog)
   945  		p.As = AMOV
   946  		p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 8}
   947  		p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_CTXT}
   948  		// MOV (SP), LR
   949  		p = obj.Appendp(p, newprog)
   950  		p.As = AMOV
   951  		p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0}
   952  		p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
   953  		// ADDI $16, SP
   954  		p = obj.Appendp(p, newprog)
   955  		p.As = AADDI
   956  		p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: frameSize}
   957  		p.Reg = REG_SP
   958  		p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
   959  		p.Spadj = -frameSize
   960  
   961  		// Unspill arguments
   962  		p = cursym.Func().UnspillRegisterArgs(p, newprog)
   963  		p = ctxt.EndUnsafePoint(p, newprog, -1)
   964  	}
   965  
   966  	// Jump back to here after morestack returns.
   967  	startPred := p
   968  
   969  	// MOV	g_stackguard(g), X6
   970  	p = obj.Appendp(p, newprog)
   971  	p.As = AMOV
   972  	p.From.Type = obj.TYPE_MEM
   973  	p.From.Reg = REGG
   974  	p.From.Offset = 2 * int64(ctxt.Arch.PtrSize) // G.stackguard0
   975  	if cursym.CFunc() {
   976  		p.From.Offset = 3 * int64(ctxt.Arch.PtrSize) // G.stackguard1
   977  	}
   978  	p.To.Type = obj.TYPE_REG
   979  	p.To.Reg = REG_X6
   980  
   981  	// Mark the stack bound check and morestack call async nonpreemptible.
   982  	// If we get preempted here, when resumed the preemption request is
   983  	// cleared, but we'll still call morestack, which will double the stack
   984  	// unnecessarily. See issue #35470.
   985  	p = ctxt.StartUnsafePoint(p, newprog)
   986  
   987  	var to_done, to_more *obj.Prog
   988  
   989  	if framesize <= abi.StackSmall {
   990  		// small stack
   991  		//	// if SP > stackguard { goto done }
   992  		//	BLTU	stackguard, SP, done
   993  		p = obj.Appendp(p, newprog)
   994  		p.As = ABLTU
   995  		p.From.Type = obj.TYPE_REG
   996  		p.From.Reg = REG_X6
   997  		p.Reg = REG_SP
   998  		p.To.Type = obj.TYPE_BRANCH
   999  		to_done = p
  1000  	} else {
  1001  		// large stack: SP-framesize < stackguard-StackSmall
  1002  		offset := int64(framesize) - abi.StackSmall
  1003  		if framesize > abi.StackBig {
  1004  			// Such a large stack we need to protect against underflow.
  1005  			// The runtime guarantees SP > objabi.StackBig, but
  1006  			// framesize is large enough that SP-framesize may
  1007  			// underflow, causing a direct comparison with the
  1008  			// stack guard to incorrectly succeed. We explicitly
  1009  			// guard against underflow.
  1010  			//
  1011  			//	MOV	$(framesize-StackSmall), X7
  1012  			//	BLTU	SP, X7, label-of-call-to-morestack
  1013  
  1014  			p = obj.Appendp(p, newprog)
  1015  			p.As = AMOV
  1016  			p.From.Type = obj.TYPE_CONST
  1017  			p.From.Offset = offset
  1018  			p.To.Type = obj.TYPE_REG
  1019  			p.To.Reg = REG_X7
  1020  
  1021  			p = obj.Appendp(p, newprog)
  1022  			p.As = ABLTU
  1023  			p.From.Type = obj.TYPE_REG
  1024  			p.From.Reg = REG_SP
  1025  			p.Reg = REG_X7
  1026  			p.To.Type = obj.TYPE_BRANCH
  1027  			to_more = p
  1028  		}
  1029  
  1030  		// Check against the stack guard. We've ensured this won't underflow.
  1031  		//	ADD	$-(framesize-StackSmall), SP, X7
  1032  		//	// if X7 > stackguard { goto done }
  1033  		//	BLTU	stackguard, X7, done
  1034  		p = obj.Appendp(p, newprog)
  1035  		p.As = AADDI
  1036  		p.From.Type = obj.TYPE_CONST
  1037  		p.From.Offset = -offset
  1038  		p.Reg = REG_SP
  1039  		p.To.Type = obj.TYPE_REG
  1040  		p.To.Reg = REG_X7
  1041  
  1042  		p = obj.Appendp(p, newprog)
  1043  		p.As = ABLTU
  1044  		p.From.Type = obj.TYPE_REG
  1045  		p.From.Reg = REG_X6
  1046  		p.Reg = REG_X7
  1047  		p.To.Type = obj.TYPE_BRANCH
  1048  		to_done = p
  1049  	}
  1050  
  1051  	// Spill the register args that could be clobbered by the
  1052  	// morestack code
  1053  	p = ctxt.EmitEntryStackMap(cursym, p, newprog)
  1054  	p = cursym.Func().SpillRegisterArgs(p, newprog)
  1055  
  1056  	// CALL runtime.morestack(SB)
  1057  	p = obj.Appendp(p, newprog)
  1058  	p.As = obj.ACALL
  1059  	p.To.Type = obj.TYPE_BRANCH
  1060  
  1061  	if cursym.CFunc() {
  1062  		p.To.Sym = ctxt.Lookup("runtime.morestackc")
  1063  	} else if !cursym.Func().Text.From.Sym.NeedCtxt() {
  1064  		p.To.Sym = ctxt.Lookup("runtime.morestack_noctxt")
  1065  	} else {
  1066  		p.To.Sym = ctxt.Lookup("runtime.morestack")
  1067  	}
  1068  	if to_more != nil {
  1069  		to_more.To.SetTarget(p)
  1070  	}
  1071  	jalToSym(ctxt, p, REG_X5)
  1072  
  1073  	// The instructions which unspill regs should be preemptible.
  1074  	p = ctxt.EndUnsafePoint(p, newprog, -1)
  1075  	p = cursym.Func().UnspillRegisterArgs(p, newprog)
  1076  
  1077  	// JMP start
  1078  	p = obj.Appendp(p, newprog)
  1079  	p.As = AJAL
  1080  	p.To = obj.Addr{Type: obj.TYPE_BRANCH}
  1081  	p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
  1082  	p.To.SetTarget(startPred.Link)
  1083  
  1084  	// placeholder for to_done's jump target
  1085  	p = obj.Appendp(p, newprog)
  1086  	p.As = obj.ANOP // zero-width place holder
  1087  	to_done.To.SetTarget(p)
  1088  
  1089  	return p
  1090  }
  1091  
  1092  // signExtend sign extends val starting at bit bit.
  1093  func signExtend(val int64, bit uint) int64 {
  1094  	return val << (64 - bit) >> (64 - bit)
  1095  }
  1096  
  1097  // Split32BitImmediate splits a signed 32-bit immediate into a signed 20-bit
  1098  // upper immediate and a signed 12-bit lower immediate to be added to the upper
  1099  // result. For example, high may be used in LUI and low in a following ADDI to
  1100  // generate a full 32-bit constant.
  1101  func Split32BitImmediate(imm int64) (low, high int64, err error) {
  1102  	if err := immIFits(imm, 32); err != nil {
  1103  		return 0, 0, err
  1104  	}
  1105  
  1106  	// Nothing special needs to be done if the immediate fits in 12 bits.
  1107  	if err := immIFits(imm, 12); err == nil {
  1108  		return imm, 0, nil
  1109  	}
  1110  
  1111  	high = imm >> 12
  1112  
  1113  	// The bottom 12 bits will be treated as signed.
  1114  	//
  1115  	// If that will result in a negative 12 bit number, add 1 to
  1116  	// our upper bits to adjust for the borrow.
  1117  	//
  1118  	// It is not possible for this increment to overflow. To
  1119  	// overflow, the 20 top bits would be 1, and the sign bit for
  1120  	// the low 12 bits would be set, in which case the entire 32
  1121  	// bit pattern fits in a 12 bit signed value.
  1122  	if imm&(1<<11) != 0 {
  1123  		high++
  1124  	}
  1125  
  1126  	low = signExtend(imm, 12)
  1127  	high = signExtend(high, 20)
  1128  
  1129  	return low, high, nil
  1130  }
  1131  
  1132  func regVal(r, min, max uint32) uint32 {
  1133  	if r < min || r > max {
  1134  		panic(fmt.Sprintf("register out of range, want %d <= %d <= %d", min, r, max))
  1135  	}
  1136  	return r - min
  1137  }
  1138  
  1139  // regI returns an integer register.
  1140  func regI(r uint32) uint32 {
  1141  	return regVal(r, REG_X0, REG_X31)
  1142  }
  1143  
  1144  // regF returns a float register.
  1145  func regF(r uint32) uint32 {
  1146  	return regVal(r, REG_F0, REG_F31)
  1147  }
  1148  
  1149  // regV returns a vector register.
  1150  func regV(r uint32) uint32 {
  1151  	return regVal(r, REG_V0, REG_V31)
  1152  }
  1153  
  1154  // regAddr extracts a register from an Addr.
  1155  func regAddr(a obj.Addr, min, max uint32) uint32 {
  1156  	if a.Type != obj.TYPE_REG {
  1157  		panic(fmt.Sprintf("ill typed: %+v", a))
  1158  	}
  1159  	return regVal(uint32(a.Reg), min, max)
  1160  }
  1161  
  1162  // regIAddr extracts the integer register from an Addr.
  1163  func regIAddr(a obj.Addr) uint32 {
  1164  	return regAddr(a, REG_X0, REG_X31)
  1165  }
  1166  
  1167  // regFAddr extracts the float register from an Addr.
  1168  func regFAddr(a obj.Addr) uint32 {
  1169  	return regAddr(a, REG_F0, REG_F31)
  1170  }
  1171  
  1172  // immEven checks that the immediate is a multiple of two. If it
  1173  // is not, an error is returned.
  1174  func immEven(x int64) error {
  1175  	if x&1 != 0 {
  1176  		return fmt.Errorf("immediate %#x is not a multiple of two", x)
  1177  	}
  1178  	return nil
  1179  }
  1180  
  1181  func immFits(x int64, nbits uint, signed bool) error {
  1182  	label := "unsigned"
  1183  	min, max := int64(0), int64(1)<<nbits-1
  1184  	if signed {
  1185  		label = "signed"
  1186  		sbits := nbits - 1
  1187  		min, max = int64(-1)<<sbits, int64(1)<<sbits-1
  1188  	}
  1189  	if x < min || x > max {
  1190  		if nbits <= 16 {
  1191  			return fmt.Errorf("%s immediate %d must be in range [%d, %d] (%d bits)", label, x, min, max, nbits)
  1192  		}
  1193  		return fmt.Errorf("%s immediate %#x must be in range [%#x, %#x] (%d bits)", label, x, min, max, nbits)
  1194  	}
  1195  	return nil
  1196  }
  1197  
  1198  // immIFits checks whether the immediate value x fits in nbits bits
  1199  // as a signed integer. If it does not, an error is returned.
  1200  func immIFits(x int64, nbits uint) error {
  1201  	return immFits(x, nbits, true)
  1202  }
  1203  
  1204  // immI extracts the signed integer of the specified size from an immediate.
  1205  func immI(as obj.As, imm int64, nbits uint) uint32 {
  1206  	if err := immIFits(imm, nbits); err != nil {
  1207  		panic(fmt.Sprintf("%v: %v", as, err))
  1208  	}
  1209  	return uint32(imm) & ((1 << nbits) - 1)
  1210  }
  1211  
  1212  func wantImmI(ctxt *obj.Link, ins *instruction, imm int64, nbits uint) {
  1213  	if err := immIFits(imm, nbits); err != nil {
  1214  		ctxt.Diag("%v: %v", ins, err)
  1215  	}
  1216  }
  1217  
  1218  // immUFits checks whether the immediate value x fits in nbits bits
  1219  // as an unsigned integer. If it does not, an error is returned.
  1220  func immUFits(x int64, nbits uint) error {
  1221  	return immFits(x, nbits, false)
  1222  }
  1223  
  1224  // immU extracts the unsigned integer of the specified size from an immediate.
  1225  func immU(as obj.As, imm int64, nbits uint) uint32 {
  1226  	if err := immUFits(imm, nbits); err != nil {
  1227  		panic(fmt.Sprintf("%v: %v", as, err))
  1228  	}
  1229  	return uint32(imm) & ((1 << nbits) - 1)
  1230  }
  1231  
  1232  func wantImmU(ctxt *obj.Link, ins *instruction, imm int64, nbits uint) {
  1233  	if err := immUFits(imm, nbits); err != nil {
  1234  		ctxt.Diag("%v: %v", ins, err)
  1235  	}
  1236  }
  1237  
  1238  func wantReg(ctxt *obj.Link, ins *instruction, pos string, descr string, r, min, max uint32) {
  1239  	if r < min || r > max {
  1240  		var suffix string
  1241  		if r != obj.REG_NONE {
  1242  			suffix = fmt.Sprintf(" but got non-%s register %s", descr, RegName(int(r)))
  1243  		}
  1244  		ctxt.Diag("%v: expected %s register in %s position%s", ins, descr, pos, suffix)
  1245  	}
  1246  }
  1247  
  1248  func wantNoneReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
  1249  	if r != obj.REG_NONE {
  1250  		ctxt.Diag("%v: expected no register in %s but got register %s", ins, pos, RegName(int(r)))
  1251  	}
  1252  }
  1253  
  1254  // wantIntReg checks that r is an integer register.
  1255  func wantIntReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
  1256  	wantReg(ctxt, ins, pos, "integer", r, REG_X0, REG_X31)
  1257  }
  1258  
  1259  // wantFloatReg checks that r is a floating-point register.
  1260  func wantFloatReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
  1261  	wantReg(ctxt, ins, pos, "float", r, REG_F0, REG_F31)
  1262  }
  1263  
  1264  // wantVectorReg checks that r is a vector register.
  1265  func wantVectorReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
  1266  	wantReg(ctxt, ins, pos, "vector", r, REG_V0, REG_V31)
  1267  }
  1268  
  1269  // wantEvenOffset checks that the offset is a multiple of two.
  1270  func wantEvenOffset(ctxt *obj.Link, ins *instruction, offset int64) {
  1271  	if err := immEven(offset); err != nil {
  1272  		ctxt.Diag("%v: %v", ins, err)
  1273  	}
  1274  }
  1275  
  1276  func validateRII(ctxt *obj.Link, ins *instruction) {
  1277  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1278  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1279  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1280  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1281  }
  1282  
  1283  func validateRIII(ctxt *obj.Link, ins *instruction) {
  1284  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1285  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1286  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1287  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1288  }
  1289  
  1290  func validateRFFF(ctxt *obj.Link, ins *instruction) {
  1291  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1292  	wantFloatReg(ctxt, ins, "rs1", ins.rs1)
  1293  	wantFloatReg(ctxt, ins, "rs2", ins.rs2)
  1294  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1295  }
  1296  
  1297  func validateRFFFF(ctxt *obj.Link, ins *instruction) {
  1298  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1299  	wantFloatReg(ctxt, ins, "rs1", ins.rs1)
  1300  	wantFloatReg(ctxt, ins, "rs2", ins.rs2)
  1301  	wantFloatReg(ctxt, ins, "rs3", ins.rs3)
  1302  }
  1303  
  1304  func validateRFFI(ctxt *obj.Link, ins *instruction) {
  1305  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1306  	wantFloatReg(ctxt, ins, "rs1", ins.rs1)
  1307  	wantFloatReg(ctxt, ins, "rs2", ins.rs2)
  1308  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1309  }
  1310  
  1311  func validateRFI(ctxt *obj.Link, ins *instruction) {
  1312  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1313  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1314  	wantFloatReg(ctxt, ins, "rs2", ins.rs2)
  1315  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1316  }
  1317  
  1318  func validateRIF(ctxt *obj.Link, ins *instruction) {
  1319  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1320  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1321  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1322  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1323  }
  1324  
  1325  func validateRFF(ctxt *obj.Link, ins *instruction) {
  1326  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1327  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1328  	wantFloatReg(ctxt, ins, "rs2", ins.rs2)
  1329  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1330  }
  1331  
  1332  func validateRVIV(ctxt *obj.Link, ins *instruction) {
  1333  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1334  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1335  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1336  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1337  }
  1338  
  1339  func validateRVV(ctxt *obj.Link, ins *instruction) {
  1340  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1341  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1342  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1343  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1344  }
  1345  
  1346  func validateRVVi(ctxt *obj.Link, ins *instruction) {
  1347  	wantImmI(ctxt, ins, ins.imm, 5)
  1348  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1349  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1350  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1351  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1352  }
  1353  
  1354  func validateRVVu(ctxt *obj.Link, ins *instruction) {
  1355  	wantImmU(ctxt, ins, ins.imm, 5)
  1356  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1357  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1358  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1359  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1360  }
  1361  
  1362  func validateRVVV(ctxt *obj.Link, ins *instruction) {
  1363  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1364  	wantVectorReg(ctxt, ins, "vs1", ins.rs1)
  1365  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1366  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1367  }
  1368  
  1369  func validateIII(ctxt *obj.Link, ins *instruction) {
  1370  	wantImmI(ctxt, ins, ins.imm, 12)
  1371  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1372  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1373  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1374  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1375  }
  1376  
  1377  func validateIF(ctxt *obj.Link, ins *instruction) {
  1378  	wantImmI(ctxt, ins, ins.imm, 12)
  1379  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1380  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1381  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1382  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1383  }
  1384  
  1385  func validateIV(ctxt *obj.Link, ins *instruction) {
  1386  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1387  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1388  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1389  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1390  }
  1391  
  1392  func validateIIIV(ctxt *obj.Link, ins *instruction) {
  1393  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1394  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1395  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1396  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1397  }
  1398  
  1399  func validateIVIV(ctxt *obj.Link, ins *instruction) {
  1400  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1401  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1402  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1403  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1404  }
  1405  
  1406  func validateSI(ctxt *obj.Link, ins *instruction) {
  1407  	wantImmI(ctxt, ins, ins.imm, 12)
  1408  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1409  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1410  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1411  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1412  }
  1413  
  1414  func validateSF(ctxt *obj.Link, ins *instruction) {
  1415  	wantImmI(ctxt, ins, ins.imm, 12)
  1416  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1417  	wantFloatReg(ctxt, ins, "rs1", ins.rs1)
  1418  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1419  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1420  }
  1421  
  1422  func validateSV(ctxt *obj.Link, ins *instruction) {
  1423  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1424  	wantVectorReg(ctxt, ins, "vs1", ins.rs1)
  1425  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1426  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1427  }
  1428  
  1429  func validateSVII(ctxt *obj.Link, ins *instruction) {
  1430  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1431  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1432  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1433  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1434  }
  1435  
  1436  func validateSVIV(ctxt *obj.Link, ins *instruction) {
  1437  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1438  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1439  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1440  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1441  }
  1442  
  1443  func validateB(ctxt *obj.Link, ins *instruction) {
  1444  	// Offsets are multiples of two, so accept 13 bit immediates for the
  1445  	// 12 bit slot. We implicitly drop the least significant bit in encodeB.
  1446  	wantEvenOffset(ctxt, ins, ins.imm)
  1447  	wantImmI(ctxt, ins, ins.imm, 13)
  1448  	wantNoneReg(ctxt, ins, "rd", ins.rd)
  1449  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1450  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1451  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1452  }
  1453  
  1454  func validateU(ctxt *obj.Link, ins *instruction) {
  1455  	wantImmI(ctxt, ins, ins.imm, 20)
  1456  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1457  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1458  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1459  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1460  }
  1461  
  1462  func validateJ(ctxt *obj.Link, ins *instruction) {
  1463  	// Offsets are multiples of two, so accept 21 bit immediates for the
  1464  	// 20 bit slot. We implicitly drop the least significant bit in encodeJ.
  1465  	wantEvenOffset(ctxt, ins, ins.imm)
  1466  	wantImmI(ctxt, ins, ins.imm, 21)
  1467  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1468  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1469  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1470  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1471  }
  1472  
  1473  func validateVsetvli(ctxt *obj.Link, ins *instruction) {
  1474  	wantImmU(ctxt, ins, ins.imm, 11)
  1475  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1476  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1477  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1478  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1479  }
  1480  
  1481  func validateVsetivli(ctxt *obj.Link, ins *instruction) {
  1482  	wantImmU(ctxt, ins, ins.imm, 10)
  1483  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1484  	wantImmU(ctxt, ins, int64(ins.rs1), 5)
  1485  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1486  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1487  }
  1488  
  1489  func validateVsetvl(ctxt *obj.Link, ins *instruction) {
  1490  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1491  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1492  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1493  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1494  }
  1495  
  1496  func validateRaw(ctxt *obj.Link, ins *instruction) {
  1497  	// Treat the raw value specially as a 32-bit unsigned integer.
  1498  	// Nobody wants to enter negative machine code.
  1499  	if ins.imm < 0 || 1<<32 <= ins.imm {
  1500  		ctxt.Diag("%v: immediate %d in raw position cannot be larger than 32 bits", ins.as, ins.imm)
  1501  	}
  1502  }
  1503  
  1504  // extractBitAndShift extracts the specified bit from the given immediate,
  1505  // before shifting it to the requested position and returning it.
  1506  func extractBitAndShift(imm uint32, bit, pos int) uint32 {
  1507  	return ((imm >> bit) & 1) << pos
  1508  }
  1509  
  1510  // encodeR encodes an R-type RISC-V instruction.
  1511  func encodeR(as obj.As, rs1, rs2, rd, funct3, funct7 uint32) uint32 {
  1512  	enc := encode(as)
  1513  	if enc == nil {
  1514  		panic("encodeR: could not encode instruction")
  1515  	}
  1516  	if enc.rs1 != 0 && rs1 != 0 {
  1517  		panic("encodeR: instruction uses rs1, but rs1 is nonzero")
  1518  	}
  1519  	if enc.rs2 != 0 && rs2 != 0 {
  1520  		panic("encodeR: instruction uses rs2, but rs2 is nonzero")
  1521  	}
  1522  	funct3 |= enc.funct3
  1523  	funct7 |= enc.funct7
  1524  	rs1 |= enc.rs1
  1525  	rs2 |= enc.rs2
  1526  	return funct7<<25 | rs2<<20 | rs1<<15 | funct3<<12 | rd<<7 | enc.opcode
  1527  }
  1528  
  1529  // encodeR4 encodes an R4-type RISC-V instruction.
  1530  func encodeR4(as obj.As, rs1, rs2, rs3, rd, funct3, funct2 uint32) uint32 {
  1531  	enc := encode(as)
  1532  	if enc == nil {
  1533  		panic("encodeR4: could not encode instruction")
  1534  	}
  1535  	if enc.rs2 != 0 {
  1536  		panic("encodeR4: instruction uses rs2")
  1537  	}
  1538  	funct2 |= enc.funct7
  1539  	if funct2&^3 != 0 {
  1540  		panic("encodeR4: funct2 requires more than 2 bits")
  1541  	}
  1542  	return rs3<<27 | funct2<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | funct3<<12 | rd<<7 | enc.opcode
  1543  }
  1544  
  1545  func encodeRII(ins *instruction) uint32 {
  1546  	return encodeR(ins.as, regI(ins.rs1), 0, regI(ins.rd), ins.funct3, ins.funct7)
  1547  }
  1548  
  1549  func encodeRIII(ins *instruction) uint32 {
  1550  	return encodeR(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
  1551  }
  1552  
  1553  func encodeRFFF(ins *instruction) uint32 {
  1554  	return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rd), ins.funct3, ins.funct7)
  1555  }
  1556  
  1557  func encodeRFFFF(ins *instruction) uint32 {
  1558  	return encodeR4(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rs3), regF(ins.rd), ins.funct3, ins.funct7)
  1559  }
  1560  
  1561  func encodeRFFI(ins *instruction) uint32 {
  1562  	return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
  1563  }
  1564  
  1565  func encodeRFI(ins *instruction) uint32 {
  1566  	return encodeR(ins.as, regF(ins.rs2), 0, regI(ins.rd), ins.funct3, ins.funct7)
  1567  }
  1568  
  1569  func encodeRIF(ins *instruction) uint32 {
  1570  	return encodeR(ins.as, regI(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7)
  1571  }
  1572  
  1573  func encodeRFF(ins *instruction) uint32 {
  1574  	return encodeR(ins.as, regF(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7)
  1575  }
  1576  
  1577  func encodeRVV(ins *instruction) uint32 {
  1578  	return encodeR(ins.as, 0, regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
  1579  }
  1580  
  1581  func encodeRVVi(ins *instruction) uint32 {
  1582  	return encodeR(ins.as, immI(ins.as, ins.imm, 5), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
  1583  }
  1584  
  1585  func encodeRVVu(ins *instruction) uint32 {
  1586  	return encodeR(ins.as, immU(ins.as, ins.imm, 5), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
  1587  }
  1588  
  1589  func encodeRVIV(ins *instruction) uint32 {
  1590  	return encodeR(ins.as, regI(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
  1591  }
  1592  
  1593  func encodeRVVV(ins *instruction) uint32 {
  1594  	return encodeR(ins.as, regV(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
  1595  }
  1596  
  1597  // encodeI encodes an I-type RISC-V instruction.
  1598  func encodeI(as obj.As, rs1, rd, imm, funct7 uint32) uint32 {
  1599  	enc := encode(as)
  1600  	if enc == nil {
  1601  		panic("encodeI: could not encode instruction")
  1602  	}
  1603  	imm |= uint32(enc.csr)
  1604  	return funct7<<25 | imm<<20 | rs1<<15 | enc.funct3<<12 | rd<<7 | enc.opcode
  1605  }
  1606  
  1607  func encodeIII(ins *instruction) uint32 {
  1608  	return encodeI(ins.as, regI(ins.rs1), regI(ins.rd), uint32(ins.imm), 0)
  1609  }
  1610  
  1611  func encodeIF(ins *instruction) uint32 {
  1612  	return encodeI(ins.as, regI(ins.rs1), regF(ins.rd), uint32(ins.imm), 0)
  1613  }
  1614  
  1615  func encodeIV(ins *instruction) uint32 {
  1616  	return encodeI(ins.as, regI(ins.rs1), regV(ins.rd), uint32(ins.imm), ins.funct7)
  1617  }
  1618  
  1619  func encodeIIIV(ins *instruction) uint32 {
  1620  	return encodeI(ins.as, regI(ins.rs1), regV(ins.rd), regI(ins.rs2), ins.funct7)
  1621  }
  1622  
  1623  func encodeIVIV(ins *instruction) uint32 {
  1624  	return encodeI(ins.as, regI(ins.rs1), regV(ins.rd), regV(ins.rs2), ins.funct7)
  1625  }
  1626  
  1627  // encodeS encodes an S-type RISC-V instruction.
  1628  func encodeS(as obj.As, rs1, rs2, imm, funct7 uint32) uint32 {
  1629  	enc := encode(as)
  1630  	if enc == nil {
  1631  		panic("encodeS: could not encode instruction")
  1632  	}
  1633  	if enc.rs2 != 0 && rs2 != 0 {
  1634  		panic("encodeS: instruction uses rs2, but rs2 was nonzero")
  1635  	}
  1636  	rs2 |= enc.rs2
  1637  	imm |= uint32(enc.csr) &^ 0x1f
  1638  	return funct7<<25 | (imm>>5)<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | (imm&0x1f)<<7 | enc.opcode
  1639  }
  1640  
  1641  func encodeSI(ins *instruction) uint32 {
  1642  	return encodeS(ins.as, regI(ins.rd), regI(ins.rs1), uint32(ins.imm), 0)
  1643  }
  1644  
  1645  func encodeSF(ins *instruction) uint32 {
  1646  	return encodeS(ins.as, regI(ins.rd), regF(ins.rs1), uint32(ins.imm), 0)
  1647  }
  1648  
  1649  func encodeSV(ins *instruction) uint32 {
  1650  	return encodeS(ins.as, regI(ins.rd), 0, regV(ins.rs1), ins.funct7)
  1651  }
  1652  
  1653  func encodeSVII(ins *instruction) uint32 {
  1654  	return encodeS(ins.as, regI(ins.rs1), regI(ins.rs2), regV(ins.rd), ins.funct7)
  1655  }
  1656  
  1657  func encodeSVIV(ins *instruction) uint32 {
  1658  	return encodeS(ins.as, regI(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct7)
  1659  }
  1660  
  1661  // encodeBImmediate encodes an immediate for a B-type RISC-V instruction.
  1662  func encodeBImmediate(imm uint32) uint32 {
  1663  	return (imm>>12)<<31 | ((imm>>5)&0x3f)<<25 | ((imm>>1)&0xf)<<8 | ((imm>>11)&0x1)<<7
  1664  }
  1665  
  1666  // encodeB encodes a B-type RISC-V instruction.
  1667  func encodeB(ins *instruction) uint32 {
  1668  	imm := immI(ins.as, ins.imm, 13)
  1669  	rs2 := regI(ins.rs1)
  1670  	rs1 := regI(ins.rs2)
  1671  	enc := encode(ins.as)
  1672  	if enc == nil {
  1673  		panic("encodeB: could not encode instruction")
  1674  	}
  1675  	return encodeBImmediate(imm) | rs2<<20 | rs1<<15 | enc.funct3<<12 | enc.opcode
  1676  }
  1677  
  1678  // encodeU encodes a U-type RISC-V instruction.
  1679  func encodeU(ins *instruction) uint32 {
  1680  	// The immediates for encodeU are the upper 20 bits of a 32 bit value.
  1681  	// Rather than have the user/compiler generate a 32 bit constant, the
  1682  	// bottommost bits of which must all be zero, instead accept just the
  1683  	// top bits.
  1684  	imm := immI(ins.as, ins.imm, 20)
  1685  	rd := regI(ins.rd)
  1686  	enc := encode(ins.as)
  1687  	if enc == nil {
  1688  		panic("encodeU: could not encode instruction")
  1689  	}
  1690  	return imm<<12 | rd<<7 | enc.opcode
  1691  }
  1692  
  1693  // encodeJImmediate encodes an immediate for a J-type RISC-V instruction.
  1694  func encodeJImmediate(imm uint32) uint32 {
  1695  	return (imm>>20)<<31 | ((imm>>1)&0x3ff)<<21 | ((imm>>11)&0x1)<<20 | ((imm>>12)&0xff)<<12
  1696  }
  1697  
  1698  // encodeJ encodes a J-type RISC-V instruction.
  1699  func encodeJ(ins *instruction) uint32 {
  1700  	imm := immI(ins.as, ins.imm, 21)
  1701  	rd := regI(ins.rd)
  1702  	enc := encode(ins.as)
  1703  	if enc == nil {
  1704  		panic("encodeJ: could not encode instruction")
  1705  	}
  1706  	return encodeJImmediate(imm) | rd<<7 | enc.opcode
  1707  }
  1708  
  1709  // encodeCBImmediate encodes an immediate for a CB-type RISC-V instruction.
  1710  func encodeCBImmediate(imm uint32) uint32 {
  1711  	// Bit order - [8|4:3|7:6|2:1|5]
  1712  	bits := extractBitAndShift(imm, 8, 7)
  1713  	bits |= extractBitAndShift(imm, 4, 6)
  1714  	bits |= extractBitAndShift(imm, 3, 5)
  1715  	bits |= extractBitAndShift(imm, 7, 4)
  1716  	bits |= extractBitAndShift(imm, 6, 3)
  1717  	bits |= extractBitAndShift(imm, 2, 2)
  1718  	bits |= extractBitAndShift(imm, 1, 1)
  1719  	bits |= extractBitAndShift(imm, 5, 0)
  1720  	return (bits>>5)<<10 | (bits&0x1f)<<2
  1721  }
  1722  
  1723  // encodeCJImmediate encodes an immediate for a CJ-type RISC-V instruction.
  1724  func encodeCJImmediate(imm uint32) uint32 {
  1725  	// Bit order - [11|4|9:8|10|6|7|3:1|5]
  1726  	bits := extractBitAndShift(imm, 11, 10)
  1727  	bits |= extractBitAndShift(imm, 4, 9)
  1728  	bits |= extractBitAndShift(imm, 9, 8)
  1729  	bits |= extractBitAndShift(imm, 8, 7)
  1730  	bits |= extractBitAndShift(imm, 10, 6)
  1731  	bits |= extractBitAndShift(imm, 6, 5)
  1732  	bits |= extractBitAndShift(imm, 7, 4)
  1733  	bits |= extractBitAndShift(imm, 3, 3)
  1734  	bits |= extractBitAndShift(imm, 2, 2)
  1735  	bits |= extractBitAndShift(imm, 1, 1)
  1736  	bits |= extractBitAndShift(imm, 5, 0)
  1737  	return bits << 2
  1738  }
  1739  
  1740  func encodeVset(as obj.As, rs1, rs2, rd uint32) uint32 {
  1741  	enc := encode(as)
  1742  	if enc == nil {
  1743  		panic("encodeVset: could not encode instruction")
  1744  	}
  1745  	return enc.funct7<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | rd<<7 | enc.opcode
  1746  }
  1747  
  1748  func encodeVsetvli(ins *instruction) uint32 {
  1749  	vtype := immU(ins.as, ins.imm, 11)
  1750  	return encodeVset(ins.as, regI(ins.rs1), vtype, regI(ins.rd))
  1751  }
  1752  
  1753  func encodeVsetivli(ins *instruction) uint32 {
  1754  	vtype := immU(ins.as, ins.imm, 10)
  1755  	avl := immU(ins.as, int64(ins.rs1), 5)
  1756  	return encodeVset(ins.as, avl, vtype, regI(ins.rd))
  1757  }
  1758  
  1759  func encodeVsetvl(ins *instruction) uint32 {
  1760  	return encodeVset(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd))
  1761  }
  1762  
  1763  func encodeRawIns(ins *instruction) uint32 {
  1764  	// Treat the raw value specially as a 32-bit unsigned integer.
  1765  	// Nobody wants to enter negative machine code.
  1766  	if ins.imm < 0 || 1<<32 <= ins.imm {
  1767  		panic(fmt.Sprintf("immediate %d cannot fit in 32 bits", ins.imm))
  1768  	}
  1769  	return uint32(ins.imm)
  1770  }
  1771  
  1772  func EncodeBImmediate(imm int64) (int64, error) {
  1773  	if err := immIFits(imm, 13); err != nil {
  1774  		return 0, err
  1775  	}
  1776  	if err := immEven(imm); err != nil {
  1777  		return 0, err
  1778  	}
  1779  	return int64(encodeBImmediate(uint32(imm))), nil
  1780  }
  1781  
  1782  func EncodeCBImmediate(imm int64) (int64, error) {
  1783  	if err := immIFits(imm, 9); err != nil {
  1784  		return 0, err
  1785  	}
  1786  	if err := immEven(imm); err != nil {
  1787  		return 0, err
  1788  	}
  1789  	return int64(encodeCBImmediate(uint32(imm))), nil
  1790  }
  1791  
  1792  func EncodeCJImmediate(imm int64) (int64, error) {
  1793  	if err := immIFits(imm, 12); err != nil {
  1794  		return 0, err
  1795  	}
  1796  	if err := immEven(imm); err != nil {
  1797  		return 0, err
  1798  	}
  1799  	return int64(encodeCJImmediate(uint32(imm))), nil
  1800  }
  1801  
  1802  func EncodeIImmediate(imm int64) (int64, error) {
  1803  	if err := immIFits(imm, 12); err != nil {
  1804  		return 0, err
  1805  	}
  1806  	return imm << 20, nil
  1807  }
  1808  
  1809  func EncodeJImmediate(imm int64) (int64, error) {
  1810  	if err := immIFits(imm, 21); err != nil {
  1811  		return 0, err
  1812  	}
  1813  	if err := immEven(imm); err != nil {
  1814  		return 0, err
  1815  	}
  1816  	return int64(encodeJImmediate(uint32(imm))), nil
  1817  }
  1818  
  1819  func EncodeSImmediate(imm int64) (int64, error) {
  1820  	if err := immIFits(imm, 12); err != nil {
  1821  		return 0, err
  1822  	}
  1823  	return ((imm >> 5) << 25) | ((imm & 0x1f) << 7), nil
  1824  }
  1825  
  1826  func EncodeUImmediate(imm int64) (int64, error) {
  1827  	if err := immIFits(imm, 20); err != nil {
  1828  		return 0, err
  1829  	}
  1830  	return imm << 12, nil
  1831  }
  1832  
  1833  func EncodeVectorType(vsew, vlmul, vtail, vmask int64) (int64, error) {
  1834  	vsewSO := SpecialOperand(vsew)
  1835  	if vsewSO < SPOP_E8 || vsewSO > SPOP_E64 {
  1836  		return -1, fmt.Errorf("invalid vector selected element width %q", vsewSO)
  1837  	}
  1838  	vlmulSO := SpecialOperand(vlmul)
  1839  	if vlmulSO < SPOP_M1 || vlmulSO > SPOP_MF8 {
  1840  		return -1, fmt.Errorf("invalid vector register group multiplier %q", vlmulSO)
  1841  	}
  1842  	vtailSO := SpecialOperand(vtail)
  1843  	if vtailSO != SPOP_TA && vtailSO != SPOP_TU {
  1844  		return -1, fmt.Errorf("invalid vector tail policy %q", vtailSO)
  1845  	}
  1846  	vmaskSO := SpecialOperand(vmask)
  1847  	if vmaskSO != SPOP_MA && vmaskSO != SPOP_MU {
  1848  		return -1, fmt.Errorf("invalid vector mask policy %q", vmaskSO)
  1849  	}
  1850  	vtype := vmaskSO.encode()<<7 | vtailSO.encode()<<6 | vsewSO.encode()<<3 | vlmulSO.encode()
  1851  	return int64(vtype), nil
  1852  }
  1853  
  1854  type encoding struct {
  1855  	encode   func(*instruction) uint32     // encode returns the machine code for an instruction
  1856  	validate func(*obj.Link, *instruction) // validate validates an instruction
  1857  	length   int                           // length of encoded instruction; 0 for pseudo-ops, 4 otherwise
  1858  }
  1859  
  1860  var (
  1861  	// Encodings have the following naming convention:
  1862  	//
  1863  	//  1. the instruction encoding (R/I/S/B/U/J), in lowercase
  1864  	//  2. zero or more register operand identifiers (I = integer
  1865  	//     register, F = float register, V = vector register), in uppercase
  1866  	//  3. the word "Encoding"
  1867  	//
  1868  	// For example, rIIIEncoding indicates an R-type instruction with two
  1869  	// integer register inputs and an integer register output; sFEncoding
  1870  	// indicates an S-type instruction with rs2 being a float register.
  1871  
  1872  	rIIIEncoding  = encoding{encode: encodeRIII, validate: validateRIII, length: 4}
  1873  	rIIEncoding   = encoding{encode: encodeRII, validate: validateRII, length: 4}
  1874  	rFFFEncoding  = encoding{encode: encodeRFFF, validate: validateRFFF, length: 4}
  1875  	rFFFFEncoding = encoding{encode: encodeRFFFF, validate: validateRFFFF, length: 4}
  1876  	rFFIEncoding  = encoding{encode: encodeRFFI, validate: validateRFFI, length: 4}
  1877  	rFIEncoding   = encoding{encode: encodeRFI, validate: validateRFI, length: 4}
  1878  	rIFEncoding   = encoding{encode: encodeRIF, validate: validateRIF, length: 4}
  1879  	rFFEncoding   = encoding{encode: encodeRFF, validate: validateRFF, length: 4}
  1880  	rVVEncoding   = encoding{encode: encodeRVV, validate: validateRVV, length: 4}
  1881  	rVViEncoding  = encoding{encode: encodeRVVi, validate: validateRVVi, length: 4}
  1882  	rVVuEncoding  = encoding{encode: encodeRVVu, validate: validateRVVu, length: 4}
  1883  	rVIVEncoding  = encoding{encode: encodeRVIV, validate: validateRVIV, length: 4}
  1884  	rVVVEncoding  = encoding{encode: encodeRVVV, validate: validateRVVV, length: 4}
  1885  
  1886  	iIIEncoding  = encoding{encode: encodeIII, validate: validateIII, length: 4}
  1887  	iFEncoding   = encoding{encode: encodeIF, validate: validateIF, length: 4}
  1888  	iVEncoding   = encoding{encode: encodeIV, validate: validateIV, length: 4}
  1889  	iIIVEncoding = encoding{encode: encodeIIIV, validate: validateIIIV, length: 4}
  1890  	iVIVEncoding = encoding{encode: encodeIVIV, validate: validateIVIV, length: 4}
  1891  
  1892  	sIEncoding   = encoding{encode: encodeSI, validate: validateSI, length: 4}
  1893  	sFEncoding   = encoding{encode: encodeSF, validate: validateSF, length: 4}
  1894  	sVEncoding   = encoding{encode: encodeSV, validate: validateSV, length: 4}
  1895  	sVIIEncoding = encoding{encode: encodeSVII, validate: validateSVII, length: 4}
  1896  	sVIVEncoding = encoding{encode: encodeSVIV, validate: validateSVIV, length: 4}
  1897  
  1898  	bEncoding = encoding{encode: encodeB, validate: validateB, length: 4}
  1899  	uEncoding = encoding{encode: encodeU, validate: validateU, length: 4}
  1900  	jEncoding = encoding{encode: encodeJ, validate: validateJ, length: 4}
  1901  
  1902  	// Encodings for vector configuration setting instruction.
  1903  	vsetvliEncoding  = encoding{encode: encodeVsetvli, validate: validateVsetvli, length: 4}
  1904  	vsetivliEncoding = encoding{encode: encodeVsetivli, validate: validateVsetivli, length: 4}
  1905  	vsetvlEncoding   = encoding{encode: encodeVsetvl, validate: validateVsetvl, length: 4}
  1906  
  1907  	// rawEncoding encodes a raw instruction byte sequence.
  1908  	rawEncoding = encoding{encode: encodeRawIns, validate: validateRaw, length: 4}
  1909  
  1910  	// pseudoOpEncoding panics if encoding is attempted, but does no validation.
  1911  	pseudoOpEncoding = encoding{encode: nil, validate: func(*obj.Link, *instruction) {}, length: 0}
  1912  
  1913  	// badEncoding is used when an invalid op is encountered.
  1914  	// An error has already been generated, so let anything else through.
  1915  	badEncoding = encoding{encode: func(*instruction) uint32 { return 0 }, validate: func(*obj.Link, *instruction) {}, length: 0}
  1916  )
  1917  
  1918  // instructionData specifies details relating to a RISC-V instruction.
  1919  type instructionData struct {
  1920  	enc     encoding
  1921  	immForm obj.As // immediate form of this instruction
  1922  	ternary bool
  1923  }
  1924  
  1925  // instructions contains details of RISC-V instructions, including
  1926  // their encoding type. Entries are masked with obj.AMask to keep
  1927  // indices small.
  1928  var instructions = [ALAST & obj.AMask]instructionData{
  1929  	//
  1930  	// Unprivileged ISA
  1931  	//
  1932  
  1933  	// 2.4: Integer Computational Instructions
  1934  	AADDI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  1935  	ASLTI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  1936  	ASLTIU & obj.AMask: {enc: iIIEncoding, ternary: true},
  1937  	AANDI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  1938  	AORI & obj.AMask:   {enc: iIIEncoding, ternary: true},
  1939  	AXORI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  1940  	ASLLI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  1941  	ASRLI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  1942  	ASRAI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  1943  	ALUI & obj.AMask:   {enc: uEncoding},
  1944  	AAUIPC & obj.AMask: {enc: uEncoding},
  1945  	AADD & obj.AMask:   {enc: rIIIEncoding, immForm: AADDI, ternary: true},
  1946  	ASLT & obj.AMask:   {enc: rIIIEncoding, immForm: ASLTI, ternary: true},
  1947  	ASLTU & obj.AMask:  {enc: rIIIEncoding, immForm: ASLTIU, ternary: true},
  1948  	AAND & obj.AMask:   {enc: rIIIEncoding, immForm: AANDI, ternary: true},
  1949  	AOR & obj.AMask:    {enc: rIIIEncoding, immForm: AORI, ternary: true},
  1950  	AXOR & obj.AMask:   {enc: rIIIEncoding, immForm: AXORI, ternary: true},
  1951  	ASLL & obj.AMask:   {enc: rIIIEncoding, immForm: ASLLI, ternary: true},
  1952  	ASRL & obj.AMask:   {enc: rIIIEncoding, immForm: ASRLI, ternary: true},
  1953  	ASUB & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  1954  	ASRA & obj.AMask:   {enc: rIIIEncoding, immForm: ASRAI, ternary: true},
  1955  
  1956  	// 2.5: Control Transfer Instructions
  1957  	AJAL & obj.AMask:  {enc: jEncoding},
  1958  	AJALR & obj.AMask: {enc: iIIEncoding},
  1959  	ABEQ & obj.AMask:  {enc: bEncoding},
  1960  	ABNE & obj.AMask:  {enc: bEncoding},
  1961  	ABLT & obj.AMask:  {enc: bEncoding},
  1962  	ABLTU & obj.AMask: {enc: bEncoding},
  1963  	ABGE & obj.AMask:  {enc: bEncoding},
  1964  	ABGEU & obj.AMask: {enc: bEncoding},
  1965  
  1966  	// 2.6: Load and Store Instructions
  1967  	ALW & obj.AMask:  {enc: iIIEncoding},
  1968  	ALWU & obj.AMask: {enc: iIIEncoding},
  1969  	ALH & obj.AMask:  {enc: iIIEncoding},
  1970  	ALHU & obj.AMask: {enc: iIIEncoding},
  1971  	ALB & obj.AMask:  {enc: iIIEncoding},
  1972  	ALBU & obj.AMask: {enc: iIIEncoding},
  1973  	ASW & obj.AMask:  {enc: sIEncoding},
  1974  	ASH & obj.AMask:  {enc: sIEncoding},
  1975  	ASB & obj.AMask:  {enc: sIEncoding},
  1976  
  1977  	// 2.7: Memory Ordering
  1978  	AFENCE & obj.AMask: {enc: iIIEncoding},
  1979  
  1980  	// 4.2: Integer Computational Instructions (RV64I)
  1981  	AADDIW & obj.AMask: {enc: iIIEncoding, ternary: true},
  1982  	ASLLIW & obj.AMask: {enc: iIIEncoding, ternary: true},
  1983  	ASRLIW & obj.AMask: {enc: iIIEncoding, ternary: true},
  1984  	ASRAIW & obj.AMask: {enc: iIIEncoding, ternary: true},
  1985  	AADDW & obj.AMask:  {enc: rIIIEncoding, immForm: AADDIW, ternary: true},
  1986  	ASLLW & obj.AMask:  {enc: rIIIEncoding, immForm: ASLLIW, ternary: true},
  1987  	ASRLW & obj.AMask:  {enc: rIIIEncoding, immForm: ASRLIW, ternary: true},
  1988  	ASUBW & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  1989  	ASRAW & obj.AMask:  {enc: rIIIEncoding, immForm: ASRAIW, ternary: true},
  1990  
  1991  	// 4.3: Load and Store Instructions (RV64I)
  1992  	ALD & obj.AMask: {enc: iIIEncoding},
  1993  	ASD & obj.AMask: {enc: sIEncoding},
  1994  
  1995  	// 7.1: CSR Instructions
  1996  	ACSRRS & obj.AMask: {enc: iIIEncoding},
  1997  
  1998  	// 13.1: Multiplication Operations
  1999  	AMUL & obj.AMask:    {enc: rIIIEncoding, ternary: true},
  2000  	AMULH & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2001  	AMULHU & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2002  	AMULHSU & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2003  	AMULW & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2004  	ADIV & obj.AMask:    {enc: rIIIEncoding, ternary: true},
  2005  	ADIVU & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2006  	AREM & obj.AMask:    {enc: rIIIEncoding, ternary: true},
  2007  	AREMU & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2008  	ADIVW & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2009  	ADIVUW & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2010  	AREMW & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2011  	AREMUW & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2012  
  2013  	// 14.2: Load-Reserved/Store-Conditional Instructions (Zalrsc)
  2014  	ALRW & obj.AMask: {enc: rIIIEncoding},
  2015  	ALRD & obj.AMask: {enc: rIIIEncoding},
  2016  	ASCW & obj.AMask: {enc: rIIIEncoding},
  2017  	ASCD & obj.AMask: {enc: rIIIEncoding},
  2018  
  2019  	// 14.4: Atomic Memory Operations (Zaamo)
  2020  	AAMOSWAPW & obj.AMask: {enc: rIIIEncoding},
  2021  	AAMOSWAPD & obj.AMask: {enc: rIIIEncoding},
  2022  	AAMOADDW & obj.AMask:  {enc: rIIIEncoding},
  2023  	AAMOADDD & obj.AMask:  {enc: rIIIEncoding},
  2024  	AAMOANDW & obj.AMask:  {enc: rIIIEncoding},
  2025  	AAMOANDD & obj.AMask:  {enc: rIIIEncoding},
  2026  	AAMOORW & obj.AMask:   {enc: rIIIEncoding},
  2027  	AAMOORD & obj.AMask:   {enc: rIIIEncoding},
  2028  	AAMOXORW & obj.AMask:  {enc: rIIIEncoding},
  2029  	AAMOXORD & obj.AMask:  {enc: rIIIEncoding},
  2030  	AAMOMAXW & obj.AMask:  {enc: rIIIEncoding},
  2031  	AAMOMAXD & obj.AMask:  {enc: rIIIEncoding},
  2032  	AAMOMAXUW & obj.AMask: {enc: rIIIEncoding},
  2033  	AAMOMAXUD & obj.AMask: {enc: rIIIEncoding},
  2034  	AAMOMINW & obj.AMask:  {enc: rIIIEncoding},
  2035  	AAMOMIND & obj.AMask:  {enc: rIIIEncoding},
  2036  	AAMOMINUW & obj.AMask: {enc: rIIIEncoding},
  2037  	AAMOMINUD & obj.AMask: {enc: rIIIEncoding},
  2038  
  2039  	// 20.5: Single-Precision Load and Store Instructions
  2040  	AFLW & obj.AMask: {enc: iFEncoding},
  2041  	AFSW & obj.AMask: {enc: sFEncoding},
  2042  
  2043  	// 20.6: Single-Precision Floating-Point Computational Instructions
  2044  	AFADDS & obj.AMask:   {enc: rFFFEncoding},
  2045  	AFSUBS & obj.AMask:   {enc: rFFFEncoding},
  2046  	AFMULS & obj.AMask:   {enc: rFFFEncoding},
  2047  	AFDIVS & obj.AMask:   {enc: rFFFEncoding},
  2048  	AFMINS & obj.AMask:   {enc: rFFFEncoding},
  2049  	AFMAXS & obj.AMask:   {enc: rFFFEncoding},
  2050  	AFSQRTS & obj.AMask:  {enc: rFFFEncoding},
  2051  	AFMADDS & obj.AMask:  {enc: rFFFFEncoding},
  2052  	AFMSUBS & obj.AMask:  {enc: rFFFFEncoding},
  2053  	AFNMSUBS & obj.AMask: {enc: rFFFFEncoding},
  2054  	AFNMADDS & obj.AMask: {enc: rFFFFEncoding},
  2055  
  2056  	// 20.7: Single-Precision Floating-Point Conversion and Move Instructions
  2057  	AFCVTWS & obj.AMask:  {enc: rFIEncoding},
  2058  	AFCVTLS & obj.AMask:  {enc: rFIEncoding},
  2059  	AFCVTSW & obj.AMask:  {enc: rIFEncoding},
  2060  	AFCVTSL & obj.AMask:  {enc: rIFEncoding},
  2061  	AFCVTWUS & obj.AMask: {enc: rFIEncoding},
  2062  	AFCVTLUS & obj.AMask: {enc: rFIEncoding},
  2063  	AFCVTSWU & obj.AMask: {enc: rIFEncoding},
  2064  	AFCVTSLU & obj.AMask: {enc: rIFEncoding},
  2065  	AFSGNJS & obj.AMask:  {enc: rFFFEncoding},
  2066  	AFSGNJNS & obj.AMask: {enc: rFFFEncoding},
  2067  	AFSGNJXS & obj.AMask: {enc: rFFFEncoding},
  2068  	AFMVXW & obj.AMask:   {enc: rFIEncoding},
  2069  	AFMVWX & obj.AMask:   {enc: rIFEncoding},
  2070  
  2071  	// 20.8: Single-Precision Floating-Point Compare Instructions
  2072  	AFEQS & obj.AMask: {enc: rFFIEncoding},
  2073  	AFLTS & obj.AMask: {enc: rFFIEncoding},
  2074  	AFLES & obj.AMask: {enc: rFFIEncoding},
  2075  
  2076  	// 20.9: Single-Precision Floating-Point Classify Instruction
  2077  	AFCLASSS & obj.AMask: {enc: rFIEncoding},
  2078  
  2079  	// 12.3: Double-Precision Load and Store Instructions
  2080  	AFLD & obj.AMask: {enc: iFEncoding},
  2081  	AFSD & obj.AMask: {enc: sFEncoding},
  2082  
  2083  	// 21.4: Double-Precision Floating-Point Computational Instructions
  2084  	AFADDD & obj.AMask:   {enc: rFFFEncoding},
  2085  	AFSUBD & obj.AMask:   {enc: rFFFEncoding},
  2086  	AFMULD & obj.AMask:   {enc: rFFFEncoding},
  2087  	AFDIVD & obj.AMask:   {enc: rFFFEncoding},
  2088  	AFMIND & obj.AMask:   {enc: rFFFEncoding},
  2089  	AFMAXD & obj.AMask:   {enc: rFFFEncoding},
  2090  	AFSQRTD & obj.AMask:  {enc: rFFFEncoding},
  2091  	AFMADDD & obj.AMask:  {enc: rFFFFEncoding},
  2092  	AFMSUBD & obj.AMask:  {enc: rFFFFEncoding},
  2093  	AFNMSUBD & obj.AMask: {enc: rFFFFEncoding},
  2094  	AFNMADDD & obj.AMask: {enc: rFFFFEncoding},
  2095  
  2096  	// 21.5: Double-Precision Floating-Point Conversion and Move Instructions
  2097  	AFCVTWD & obj.AMask:  {enc: rFIEncoding},
  2098  	AFCVTLD & obj.AMask:  {enc: rFIEncoding},
  2099  	AFCVTDW & obj.AMask:  {enc: rIFEncoding},
  2100  	AFCVTDL & obj.AMask:  {enc: rIFEncoding},
  2101  	AFCVTWUD & obj.AMask: {enc: rFIEncoding},
  2102  	AFCVTLUD & obj.AMask: {enc: rFIEncoding},
  2103  	AFCVTDWU & obj.AMask: {enc: rIFEncoding},
  2104  	AFCVTDLU & obj.AMask: {enc: rIFEncoding},
  2105  	AFCVTSD & obj.AMask:  {enc: rFFEncoding},
  2106  	AFCVTDS & obj.AMask:  {enc: rFFEncoding},
  2107  	AFSGNJD & obj.AMask:  {enc: rFFFEncoding},
  2108  	AFSGNJND & obj.AMask: {enc: rFFFEncoding},
  2109  	AFSGNJXD & obj.AMask: {enc: rFFFEncoding},
  2110  	AFMVXD & obj.AMask:   {enc: rFIEncoding},
  2111  	AFMVDX & obj.AMask:   {enc: rIFEncoding},
  2112  
  2113  	// 21.6: Double-Precision Floating-Point Compare Instructions
  2114  	AFEQD & obj.AMask: {enc: rFFIEncoding},
  2115  	AFLTD & obj.AMask: {enc: rFFIEncoding},
  2116  	AFLED & obj.AMask: {enc: rFFIEncoding},
  2117  
  2118  	// 21.7: Double-Precision Floating-Point Classify Instruction
  2119  	AFCLASSD & obj.AMask: {enc: rFIEncoding},
  2120  
  2121  	//
  2122  	// "B" Extension for Bit Manipulation, Version 1.0.0
  2123  	//
  2124  
  2125  	// 28.4.1: Address Generation Instructions (Zba)
  2126  	AADDUW & obj.AMask:    {enc: rIIIEncoding, ternary: true},
  2127  	ASH1ADD & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2128  	ASH1ADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2129  	ASH2ADD & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2130  	ASH2ADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2131  	ASH3ADD & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2132  	ASH3ADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2133  	ASLLIUW & obj.AMask:   {enc: iIIEncoding, ternary: true},
  2134  
  2135  	// 28.4.2: Basic Bit Manipulation (Zbb)
  2136  	AANDN & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2137  	ACLZ & obj.AMask:   {enc: rIIEncoding},
  2138  	ACLZW & obj.AMask:  {enc: rIIEncoding},
  2139  	ACPOP & obj.AMask:  {enc: rIIEncoding},
  2140  	ACPOPW & obj.AMask: {enc: rIIEncoding},
  2141  	ACTZ & obj.AMask:   {enc: rIIEncoding},
  2142  	ACTZW & obj.AMask:  {enc: rIIEncoding},
  2143  	AMAX & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2144  	AMAXU & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2145  	AMIN & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2146  	AMINU & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2147  	AORN & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2148  	ASEXTB & obj.AMask: {enc: rIIEncoding},
  2149  	ASEXTH & obj.AMask: {enc: rIIEncoding},
  2150  	AXNOR & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2151  	AZEXTH & obj.AMask: {enc: rIIEncoding},
  2152  
  2153  	// 28.4.3: Bitwise Rotation (Zbb)
  2154  	AROL & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2155  	AROLW & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2156  	AROR & obj.AMask:   {enc: rIIIEncoding, immForm: ARORI, ternary: true},
  2157  	ARORI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  2158  	ARORIW & obj.AMask: {enc: iIIEncoding, ternary: true},
  2159  	ARORW & obj.AMask:  {enc: rIIIEncoding, immForm: ARORIW, ternary: true},
  2160  	AORCB & obj.AMask:  {enc: rIIEncoding},
  2161  	AREV8 & obj.AMask:  {enc: rIIEncoding},
  2162  
  2163  	// 28.4.4: Single-bit Instructions (Zbs)
  2164  	ABCLR & obj.AMask:  {enc: rIIIEncoding, immForm: ABCLRI, ternary: true},
  2165  	ABCLRI & obj.AMask: {enc: iIIEncoding, ternary: true},
  2166  	ABEXT & obj.AMask:  {enc: rIIIEncoding, immForm: ABEXTI, ternary: true},
  2167  	ABEXTI & obj.AMask: {enc: iIIEncoding, ternary: true},
  2168  	ABINV & obj.AMask:  {enc: rIIIEncoding, immForm: ABINVI, ternary: true},
  2169  	ABINVI & obj.AMask: {enc: iIIEncoding, ternary: true},
  2170  	ABSET & obj.AMask:  {enc: rIIIEncoding, immForm: ABSETI, ternary: true},
  2171  	ABSETI & obj.AMask: {enc: iIIEncoding, ternary: true},
  2172  
  2173  	//
  2174  	// "V" Standard Extension for Vector Operations, Version 1.0
  2175  	//
  2176  
  2177  	// 31.6: Vector Configuration-Setting Instructions
  2178  	AVSETVLI & obj.AMask:  {enc: vsetvliEncoding, immForm: AVSETIVLI},
  2179  	AVSETIVLI & obj.AMask: {enc: vsetivliEncoding},
  2180  	AVSETVL & obj.AMask:   {enc: vsetvlEncoding},
  2181  
  2182  	// 31.7.4: Vector Unit-Stride Instructions
  2183  	AVLE8V & obj.AMask:  {enc: iVEncoding},
  2184  	AVLE16V & obj.AMask: {enc: iVEncoding},
  2185  	AVLE32V & obj.AMask: {enc: iVEncoding},
  2186  	AVLE64V & obj.AMask: {enc: iVEncoding},
  2187  	AVSE8V & obj.AMask:  {enc: sVEncoding},
  2188  	AVSE16V & obj.AMask: {enc: sVEncoding},
  2189  	AVSE32V & obj.AMask: {enc: sVEncoding},
  2190  	AVSE64V & obj.AMask: {enc: sVEncoding},
  2191  	AVLMV & obj.AMask:   {enc: iVEncoding},
  2192  	AVSMV & obj.AMask:   {enc: sVEncoding},
  2193  
  2194  	// 31.7.5: Vector Strided Instructions
  2195  	AVLSE8V & obj.AMask:  {enc: iIIVEncoding},
  2196  	AVLSE16V & obj.AMask: {enc: iIIVEncoding},
  2197  	AVLSE32V & obj.AMask: {enc: iIIVEncoding},
  2198  	AVLSE64V & obj.AMask: {enc: iIIVEncoding},
  2199  	AVSSE8V & obj.AMask:  {enc: sVIIEncoding},
  2200  	AVSSE16V & obj.AMask: {enc: sVIIEncoding},
  2201  	AVSSE32V & obj.AMask: {enc: sVIIEncoding},
  2202  	AVSSE64V & obj.AMask: {enc: sVIIEncoding},
  2203  
  2204  	// 31.7.6: Vector Indexed Instructions
  2205  	AVLUXEI8V & obj.AMask:  {enc: iVIVEncoding},
  2206  	AVLUXEI16V & obj.AMask: {enc: iVIVEncoding},
  2207  	AVLUXEI32V & obj.AMask: {enc: iVIVEncoding},
  2208  	AVLUXEI64V & obj.AMask: {enc: iVIVEncoding},
  2209  	AVLOXEI8V & obj.AMask:  {enc: iVIVEncoding},
  2210  	AVLOXEI16V & obj.AMask: {enc: iVIVEncoding},
  2211  	AVLOXEI32V & obj.AMask: {enc: iVIVEncoding},
  2212  	AVLOXEI64V & obj.AMask: {enc: iVIVEncoding},
  2213  	AVSUXEI8V & obj.AMask:  {enc: sVIVEncoding},
  2214  	AVSUXEI16V & obj.AMask: {enc: sVIVEncoding},
  2215  	AVSUXEI32V & obj.AMask: {enc: sVIVEncoding},
  2216  	AVSUXEI64V & obj.AMask: {enc: sVIVEncoding},
  2217  	AVSOXEI8V & obj.AMask:  {enc: sVIVEncoding},
  2218  	AVSOXEI16V & obj.AMask: {enc: sVIVEncoding},
  2219  	AVSOXEI32V & obj.AMask: {enc: sVIVEncoding},
  2220  	AVSOXEI64V & obj.AMask: {enc: sVIVEncoding},
  2221  
  2222  	// 31.7.9: Vector Load/Store Whole Register Instructions
  2223  	AVL1RE8V & obj.AMask:  {enc: iVEncoding},
  2224  	AVL1RE16V & obj.AMask: {enc: iVEncoding},
  2225  	AVL1RE32V & obj.AMask: {enc: iVEncoding},
  2226  	AVL1RE64V & obj.AMask: {enc: iVEncoding},
  2227  	AVL2RE8V & obj.AMask:  {enc: iVEncoding},
  2228  	AVL2RE16V & obj.AMask: {enc: iVEncoding},
  2229  	AVL2RE32V & obj.AMask: {enc: iVEncoding},
  2230  	AVL2RE64V & obj.AMask: {enc: iVEncoding},
  2231  	AVL4RE8V & obj.AMask:  {enc: iVEncoding},
  2232  	AVL4RE16V & obj.AMask: {enc: iVEncoding},
  2233  	AVL4RE32V & obj.AMask: {enc: iVEncoding},
  2234  	AVL4RE64V & obj.AMask: {enc: iVEncoding},
  2235  	AVL8RE8V & obj.AMask:  {enc: iVEncoding},
  2236  	AVL8RE16V & obj.AMask: {enc: iVEncoding},
  2237  	AVL8RE32V & obj.AMask: {enc: iVEncoding},
  2238  	AVL8RE64V & obj.AMask: {enc: iVEncoding},
  2239  	AVS1RV & obj.AMask:    {enc: sVEncoding},
  2240  	AVS2RV & obj.AMask:    {enc: sVEncoding},
  2241  	AVS4RV & obj.AMask:    {enc: sVEncoding},
  2242  	AVS8RV & obj.AMask:    {enc: sVEncoding},
  2243  
  2244  	// 31.11.1: Vector Single-Width Integer Add and Subtract
  2245  	AVADDVV & obj.AMask:  {enc: rVVVEncoding},
  2246  	AVADDVX & obj.AMask:  {enc: rVIVEncoding},
  2247  	AVADDVI & obj.AMask:  {enc: rVViEncoding},
  2248  	AVSUBVV & obj.AMask:  {enc: rVVVEncoding},
  2249  	AVSUBVX & obj.AMask:  {enc: rVIVEncoding},
  2250  	AVRSUBVX & obj.AMask: {enc: rVIVEncoding},
  2251  	AVRSUBVI & obj.AMask: {enc: rVViEncoding},
  2252  
  2253  	// 31.11.2: Vector Widening Integer Add/Subtract
  2254  	AVWADDUVV & obj.AMask: {enc: rVVVEncoding},
  2255  	AVWADDUVX & obj.AMask: {enc: rVIVEncoding},
  2256  	AVWSUBUVV & obj.AMask: {enc: rVVVEncoding},
  2257  	AVWSUBUVX & obj.AMask: {enc: rVIVEncoding},
  2258  	AVWADDVV & obj.AMask:  {enc: rVVVEncoding},
  2259  	AVWADDVX & obj.AMask:  {enc: rVIVEncoding},
  2260  	AVWSUBVV & obj.AMask:  {enc: rVVVEncoding},
  2261  	AVWSUBVX & obj.AMask:  {enc: rVIVEncoding},
  2262  	AVWADDUWV & obj.AMask: {enc: rVVVEncoding},
  2263  	AVWADDUWX & obj.AMask: {enc: rVIVEncoding},
  2264  	AVWSUBUWV & obj.AMask: {enc: rVVVEncoding},
  2265  	AVWSUBUWX & obj.AMask: {enc: rVIVEncoding},
  2266  	AVWADDWV & obj.AMask:  {enc: rVVVEncoding},
  2267  	AVWADDWX & obj.AMask:  {enc: rVIVEncoding},
  2268  	AVWSUBWV & obj.AMask:  {enc: rVVVEncoding},
  2269  	AVWSUBWX & obj.AMask:  {enc: rVIVEncoding},
  2270  
  2271  	// 31.11.3: Vector Integer Extension
  2272  	AVZEXTVF2 & obj.AMask: {enc: rVVEncoding},
  2273  	AVSEXTVF2 & obj.AMask: {enc: rVVEncoding},
  2274  	AVZEXTVF4 & obj.AMask: {enc: rVVEncoding},
  2275  	AVSEXTVF4 & obj.AMask: {enc: rVVEncoding},
  2276  	AVZEXTVF8 & obj.AMask: {enc: rVVEncoding},
  2277  	AVSEXTVF8 & obj.AMask: {enc: rVVEncoding},
  2278  
  2279  	// 31.11.4: Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions
  2280  	AVADCVVM & obj.AMask:  {enc: rVVVEncoding},
  2281  	AVADCVXM & obj.AMask:  {enc: rVIVEncoding},
  2282  	AVADCVIM & obj.AMask:  {enc: rVViEncoding},
  2283  	AVMADCVVM & obj.AMask: {enc: rVVVEncoding},
  2284  	AVMADCVXM & obj.AMask: {enc: rVIVEncoding},
  2285  	AVMADCVIM & obj.AMask: {enc: rVViEncoding},
  2286  	AVMADCVV & obj.AMask:  {enc: rVVVEncoding},
  2287  	AVMADCVX & obj.AMask:  {enc: rVIVEncoding},
  2288  	AVMADCVI & obj.AMask:  {enc: rVViEncoding},
  2289  	AVSBCVVM & obj.AMask:  {enc: rVVVEncoding},
  2290  	AVSBCVXM & obj.AMask:  {enc: rVIVEncoding},
  2291  	AVMSBCVVM & obj.AMask: {enc: rVVVEncoding},
  2292  	AVMSBCVXM & obj.AMask: {enc: rVIVEncoding},
  2293  	AVMSBCVV & obj.AMask:  {enc: rVVVEncoding},
  2294  	AVMSBCVX & obj.AMask:  {enc: rVIVEncoding},
  2295  
  2296  	// 31.11.5: Vector Bitwise Logical Instructions
  2297  	AVANDVV & obj.AMask: {enc: rVVVEncoding},
  2298  	AVANDVX & obj.AMask: {enc: rVIVEncoding},
  2299  	AVANDVI & obj.AMask: {enc: rVViEncoding},
  2300  	AVORVV & obj.AMask:  {enc: rVVVEncoding},
  2301  	AVORVX & obj.AMask:  {enc: rVIVEncoding},
  2302  	AVORVI & obj.AMask:  {enc: rVViEncoding},
  2303  	AVXORVV & obj.AMask: {enc: rVVVEncoding},
  2304  	AVXORVX & obj.AMask: {enc: rVIVEncoding},
  2305  	AVXORVI & obj.AMask: {enc: rVViEncoding},
  2306  
  2307  	// 31.11.6: Vector Single-Width Shift Instructions
  2308  	AVSLLVV & obj.AMask: {enc: rVVVEncoding},
  2309  	AVSLLVX & obj.AMask: {enc: rVIVEncoding},
  2310  	AVSLLVI & obj.AMask: {enc: rVVuEncoding},
  2311  	AVSRLVV & obj.AMask: {enc: rVVVEncoding},
  2312  	AVSRLVX & obj.AMask: {enc: rVIVEncoding},
  2313  	AVSRLVI & obj.AMask: {enc: rVVuEncoding},
  2314  	AVSRAVV & obj.AMask: {enc: rVVVEncoding},
  2315  	AVSRAVX & obj.AMask: {enc: rVIVEncoding},
  2316  	AVSRAVI & obj.AMask: {enc: rVVuEncoding},
  2317  
  2318  	// 31.11.7: Vector Narrowing Integer Right Shift Instructions
  2319  	AVNSRLWV & obj.AMask: {enc: rVVVEncoding},
  2320  	AVNSRLWX & obj.AMask: {enc: rVIVEncoding},
  2321  	AVNSRLWI & obj.AMask: {enc: rVVuEncoding},
  2322  	AVNSRAWV & obj.AMask: {enc: rVVVEncoding},
  2323  	AVNSRAWX & obj.AMask: {enc: rVIVEncoding},
  2324  	AVNSRAWI & obj.AMask: {enc: rVVuEncoding},
  2325  
  2326  	// 31.11.8: Vector Integer Compare Instructions
  2327  	AVMSEQVV & obj.AMask:  {enc: rVVVEncoding},
  2328  	AVMSEQVX & obj.AMask:  {enc: rVIVEncoding},
  2329  	AVMSEQVI & obj.AMask:  {enc: rVViEncoding},
  2330  	AVMSNEVV & obj.AMask:  {enc: rVVVEncoding},
  2331  	AVMSNEVX & obj.AMask:  {enc: rVIVEncoding},
  2332  	AVMSNEVI & obj.AMask:  {enc: rVViEncoding},
  2333  	AVMSLTUVV & obj.AMask: {enc: rVVVEncoding},
  2334  	AVMSLTUVX & obj.AMask: {enc: rVIVEncoding},
  2335  	AVMSLTVV & obj.AMask:  {enc: rVVVEncoding},
  2336  	AVMSLTVX & obj.AMask:  {enc: rVIVEncoding},
  2337  	AVMSLEUVV & obj.AMask: {enc: rVVVEncoding},
  2338  	AVMSLEUVX & obj.AMask: {enc: rVIVEncoding},
  2339  	AVMSLEUVI & obj.AMask: {enc: rVViEncoding},
  2340  	AVMSLEVV & obj.AMask:  {enc: rVVVEncoding},
  2341  	AVMSLEVX & obj.AMask:  {enc: rVIVEncoding},
  2342  	AVMSLEVI & obj.AMask:  {enc: rVViEncoding},
  2343  	AVMSGTUVX & obj.AMask: {enc: rVIVEncoding},
  2344  	AVMSGTUVI & obj.AMask: {enc: rVViEncoding},
  2345  	AVMSGTVX & obj.AMask:  {enc: rVIVEncoding},
  2346  	AVMSGTVI & obj.AMask:  {enc: rVViEncoding},
  2347  
  2348  	// 31.11.9: Vector Integer Min/Max Instructions
  2349  	AVMINUVV & obj.AMask: {enc: rVVVEncoding},
  2350  	AVMINUVX & obj.AMask: {enc: rVIVEncoding},
  2351  	AVMINVV & obj.AMask:  {enc: rVVVEncoding},
  2352  	AVMINVX & obj.AMask:  {enc: rVIVEncoding},
  2353  	AVMAXUVV & obj.AMask: {enc: rVVVEncoding},
  2354  	AVMAXUVX & obj.AMask: {enc: rVIVEncoding},
  2355  	AVMAXVV & obj.AMask:  {enc: rVVVEncoding},
  2356  	AVMAXVX & obj.AMask:  {enc: rVIVEncoding},
  2357  
  2358  	// 31.11.10: Vector Single-Width Integer Multiply Instructions
  2359  	AVMULVV & obj.AMask:    {enc: rVVVEncoding},
  2360  	AVMULVX & obj.AMask:    {enc: rVIVEncoding},
  2361  	AVMULHVV & obj.AMask:   {enc: rVVVEncoding},
  2362  	AVMULHVX & obj.AMask:   {enc: rVIVEncoding},
  2363  	AVMULHUVV & obj.AMask:  {enc: rVVVEncoding},
  2364  	AVMULHUVX & obj.AMask:  {enc: rVIVEncoding},
  2365  	AVMULHSUVV & obj.AMask: {enc: rVVVEncoding},
  2366  	AVMULHSUVX & obj.AMask: {enc: rVIVEncoding},
  2367  
  2368  	// 31.11.11: Vector Integer Divide Instructions
  2369  	AVDIVUVV & obj.AMask: {enc: rVVVEncoding},
  2370  	AVDIVUVX & obj.AMask: {enc: rVIVEncoding},
  2371  	AVDIVVV & obj.AMask:  {enc: rVVVEncoding},
  2372  	AVDIVVX & obj.AMask:  {enc: rVIVEncoding},
  2373  	AVREMUVV & obj.AMask: {enc: rVVVEncoding},
  2374  	AVREMUVX & obj.AMask: {enc: rVIVEncoding},
  2375  	AVREMVV & obj.AMask:  {enc: rVVVEncoding},
  2376  	AVREMVX & obj.AMask:  {enc: rVIVEncoding},
  2377  
  2378  	// 31.11.12: Vector Widening Integer Multiply Instructions
  2379  	AVWMULVV & obj.AMask:   {enc: rVVVEncoding},
  2380  	AVWMULVX & obj.AMask:   {enc: rVIVEncoding},
  2381  	AVWMULUVV & obj.AMask:  {enc: rVVVEncoding},
  2382  	AVWMULUVX & obj.AMask:  {enc: rVIVEncoding},
  2383  	AVWMULSUVV & obj.AMask: {enc: rVVVEncoding},
  2384  	AVWMULSUVX & obj.AMask: {enc: rVIVEncoding},
  2385  
  2386  	// 31.11.13: Vector Single-Width Integer Multiply-Add Instructions
  2387  	AVMACCVV & obj.AMask:  {enc: rVVVEncoding},
  2388  	AVMACCVX & obj.AMask:  {enc: rVIVEncoding},
  2389  	AVNMSACVV & obj.AMask: {enc: rVVVEncoding},
  2390  	AVNMSACVX & obj.AMask: {enc: rVIVEncoding},
  2391  	AVMADDVV & obj.AMask:  {enc: rVVVEncoding},
  2392  	AVMADDVX & obj.AMask:  {enc: rVIVEncoding},
  2393  	AVNMSUBVV & obj.AMask: {enc: rVVVEncoding},
  2394  	AVNMSUBVX & obj.AMask: {enc: rVIVEncoding},
  2395  
  2396  	// 31.11.14: Vector Widening Integer Multiply-Add Instructions
  2397  	AVWMACCUVV & obj.AMask:  {enc: rVVVEncoding},
  2398  	AVWMACCUVX & obj.AMask:  {enc: rVIVEncoding},
  2399  	AVWMACCVV & obj.AMask:   {enc: rVVVEncoding},
  2400  	AVWMACCVX & obj.AMask:   {enc: rVIVEncoding},
  2401  	AVWMACCSUVV & obj.AMask: {enc: rVVVEncoding},
  2402  	AVWMACCSUVX & obj.AMask: {enc: rVIVEncoding},
  2403  	AVWMACCUSVX & obj.AMask: {enc: rVIVEncoding},
  2404  
  2405  	// 31.11.15: Vector Integer Merge Instructions
  2406  	AVMERGEVVM & obj.AMask: {enc: rVVVEncoding},
  2407  	AVMERGEVXM & obj.AMask: {enc: rVIVEncoding},
  2408  	AVMERGEVIM & obj.AMask: {enc: rVViEncoding},
  2409  
  2410  	// 31.11.16: Vector Integer Move Instructions
  2411  	AVMVVV & obj.AMask: {enc: rVVVEncoding},
  2412  	AVMVVX & obj.AMask: {enc: rVIVEncoding},
  2413  	AVMVVI & obj.AMask: {enc: rVViEncoding},
  2414  
  2415  	// 31.12.1: Vector Single-Width Saturating Add and Subtract
  2416  	AVSADDUVV & obj.AMask: {enc: rVVVEncoding},
  2417  	AVSADDUVX & obj.AMask: {enc: rVIVEncoding},
  2418  	AVSADDUVI & obj.AMask: {enc: rVViEncoding},
  2419  	AVSADDVV & obj.AMask:  {enc: rVVVEncoding},
  2420  	AVSADDVX & obj.AMask:  {enc: rVIVEncoding},
  2421  	AVSADDVI & obj.AMask:  {enc: rVViEncoding},
  2422  	AVSSUBUVV & obj.AMask: {enc: rVVVEncoding},
  2423  	AVSSUBUVX & obj.AMask: {enc: rVIVEncoding},
  2424  	AVSSUBVV & obj.AMask:  {enc: rVVVEncoding},
  2425  	AVSSUBVX & obj.AMask:  {enc: rVIVEncoding},
  2426  
  2427  	// 31.12.2: Vector Single-Width Averaging Add and Subtract
  2428  	AVAADDUVV & obj.AMask: {enc: rVVVEncoding},
  2429  	AVAADDUVX & obj.AMask: {enc: rVIVEncoding},
  2430  	AVAADDVV & obj.AMask:  {enc: rVVVEncoding},
  2431  	AVAADDVX & obj.AMask:  {enc: rVIVEncoding},
  2432  	AVASUBUVV & obj.AMask: {enc: rVVVEncoding},
  2433  	AVASUBUVX & obj.AMask: {enc: rVIVEncoding},
  2434  	AVASUBVV & obj.AMask:  {enc: rVVVEncoding},
  2435  	AVASUBVX & obj.AMask:  {enc: rVIVEncoding},
  2436  
  2437  	// 31.12.3: Vector Single-Width Fractional Multiply with Rounding and Saturation
  2438  	AVSMULVV & obj.AMask: {enc: rVVVEncoding},
  2439  	AVSMULVX & obj.AMask: {enc: rVIVEncoding},
  2440  
  2441  	// 31.12.4: Vector Single-Width Scaling Shift Instructions
  2442  	AVSSRLVV & obj.AMask: {enc: rVVVEncoding},
  2443  	AVSSRLVX & obj.AMask: {enc: rVIVEncoding},
  2444  	AVSSRLVI & obj.AMask: {enc: rVVuEncoding},
  2445  	AVSSRAVV & obj.AMask: {enc: rVVVEncoding},
  2446  	AVSSRAVX & obj.AMask: {enc: rVIVEncoding},
  2447  	AVSSRAVI & obj.AMask: {enc: rVVuEncoding},
  2448  
  2449  	// 31.12.5: Vector Narrowing Fixed-Point Clip Instructions
  2450  	AVNCLIPUWV & obj.AMask: {enc: rVVVEncoding},
  2451  	AVNCLIPUWX & obj.AMask: {enc: rVIVEncoding},
  2452  	AVNCLIPUWI & obj.AMask: {enc: rVVuEncoding},
  2453  	AVNCLIPWV & obj.AMask:  {enc: rVVVEncoding},
  2454  	AVNCLIPWX & obj.AMask:  {enc: rVIVEncoding},
  2455  	AVNCLIPWI & obj.AMask:  {enc: rVVuEncoding},
  2456  
  2457  	//
  2458  	// Privileged ISA
  2459  	//
  2460  
  2461  	// 3.3.1: Environment Call and Breakpoint
  2462  	AECALL & obj.AMask:  {enc: iIIEncoding},
  2463  	AEBREAK & obj.AMask: {enc: iIIEncoding},
  2464  
  2465  	// Escape hatch
  2466  	AWORD & obj.AMask: {enc: rawEncoding},
  2467  
  2468  	// Pseudo-operations
  2469  	obj.AFUNCDATA: {enc: pseudoOpEncoding},
  2470  	obj.APCDATA:   {enc: pseudoOpEncoding},
  2471  	obj.ATEXT:     {enc: pseudoOpEncoding},
  2472  	obj.ANOP:      {enc: pseudoOpEncoding},
  2473  	obj.ADUFFZERO: {enc: pseudoOpEncoding},
  2474  	obj.ADUFFCOPY: {enc: pseudoOpEncoding},
  2475  	obj.APCALIGN:  {enc: pseudoOpEncoding},
  2476  }
  2477  
  2478  // instructionDataForAs returns the instruction data for an obj.As.
  2479  func instructionDataForAs(as obj.As) (*instructionData, error) {
  2480  	if base := as &^ obj.AMask; base != obj.ABaseRISCV && base != 0 {
  2481  		return nil, fmt.Errorf("%v is not a RISC-V instruction", as)
  2482  	}
  2483  	asi := as & obj.AMask
  2484  	if int(asi) >= len(instructions) {
  2485  		return nil, fmt.Errorf("bad RISC-V instruction %v", as)
  2486  	}
  2487  	return &instructions[asi], nil
  2488  }
  2489  
  2490  // encodingForAs returns the encoding for an obj.As.
  2491  func encodingForAs(as obj.As) (*encoding, error) {
  2492  	insData, err := instructionDataForAs(as)
  2493  	if err != nil {
  2494  		return &badEncoding, err
  2495  	}
  2496  	if insData.enc.validate == nil {
  2497  		return &badEncoding, fmt.Errorf("no encoding for instruction %s", as)
  2498  	}
  2499  	return &insData.enc, nil
  2500  }
  2501  
  2502  // splitShiftConst attempts to split a constant into a signed 12 bit or
  2503  // 32 bit integer, with corresponding logical right shift and/or left shift.
  2504  func splitShiftConst(v int64) (imm int64, lsh int, rsh int, ok bool) {
  2505  	// See if we can reconstruct this value from a signed 32 bit integer.
  2506  	lsh = bits.TrailingZeros64(uint64(v))
  2507  	c := v >> lsh
  2508  	if int64(int32(c)) == c {
  2509  		return c, lsh, 0, true
  2510  	}
  2511  
  2512  	// See if we can reconstruct this value from a small negative constant.
  2513  	rsh = bits.LeadingZeros64(uint64(v))
  2514  	ones := bits.OnesCount64((uint64(v) >> lsh) >> 11)
  2515  	c = signExtend(1<<11|((v>>lsh)&0x7ff), 12)
  2516  	if rsh+ones+lsh+11 == 64 {
  2517  		if lsh > 0 || c != -1 {
  2518  			lsh += rsh
  2519  		}
  2520  		return c, lsh, rsh, true
  2521  	}
  2522  
  2523  	return 0, 0, 0, false
  2524  }
  2525  
  2526  // isShiftConst indicates whether a constant can be represented as a signed
  2527  // 32 bit integer that is left shifted.
  2528  func isShiftConst(v int64) bool {
  2529  	_, lsh, rsh, ok := splitShiftConst(v)
  2530  	return ok && (lsh > 0 || rsh > 0)
  2531  }
  2532  
  2533  type instruction struct {
  2534  	p      *obj.Prog // Prog that instruction is for
  2535  	as     obj.As    // Assembler opcode
  2536  	rd     uint32    // Destination register
  2537  	rs1    uint32    // Source register 1
  2538  	rs2    uint32    // Source register 2
  2539  	rs3    uint32    // Source register 3
  2540  	imm    int64     // Immediate
  2541  	funct3 uint32    // Function 3
  2542  	funct7 uint32    // Function 7 (or Function 2)
  2543  }
  2544  
  2545  func (ins *instruction) String() string {
  2546  	if ins.p == nil {
  2547  		return ins.as.String()
  2548  	}
  2549  	var suffix string
  2550  	if ins.p.As != ins.as {
  2551  		suffix = fmt.Sprintf(" (%v)", ins.as)
  2552  	}
  2553  	return fmt.Sprintf("%v%v", ins.p, suffix)
  2554  }
  2555  
  2556  func (ins *instruction) encode() (uint32, error) {
  2557  	enc, err := encodingForAs(ins.as)
  2558  	if err != nil {
  2559  		return 0, err
  2560  	}
  2561  	if enc.length <= 0 {
  2562  		return 0, fmt.Errorf("%v: encoding called for a pseudo instruction", ins.as)
  2563  	}
  2564  	return enc.encode(ins), nil
  2565  }
  2566  
  2567  func (ins *instruction) length() int {
  2568  	enc, err := encodingForAs(ins.as)
  2569  	if err != nil {
  2570  		return 0
  2571  	}
  2572  	return enc.length
  2573  }
  2574  
  2575  func (ins *instruction) validate(ctxt *obj.Link) {
  2576  	enc, err := encodingForAs(ins.as)
  2577  	if err != nil {
  2578  		ctxt.Diag(err.Error())
  2579  		return
  2580  	}
  2581  	enc.validate(ctxt, ins)
  2582  }
  2583  
  2584  func (ins *instruction) usesRegTmp() bool {
  2585  	return ins.rd == REG_TMP || ins.rs1 == REG_TMP || ins.rs2 == REG_TMP
  2586  }
  2587  
  2588  // instructionForProg returns the default *obj.Prog to instruction mapping.
  2589  func instructionForProg(p *obj.Prog) *instruction {
  2590  	ins := &instruction{
  2591  		as:  p.As,
  2592  		rd:  uint32(p.To.Reg),
  2593  		rs1: uint32(p.Reg),
  2594  		rs2: uint32(p.From.Reg),
  2595  		imm: p.From.Offset,
  2596  	}
  2597  	if len(p.RestArgs) == 1 {
  2598  		ins.rs3 = uint32(p.RestArgs[0].Reg)
  2599  	}
  2600  	return ins
  2601  }
  2602  
  2603  // instructionsForOpImmediate returns the machine instructions for an immediate
  2604  // operand. The instruction is specified by as and the source register is
  2605  // specified by rs, instead of the obj.Prog.
  2606  func instructionsForOpImmediate(p *obj.Prog, as obj.As, rs int16) []*instruction {
  2607  	// <opi> $imm, REG, TO
  2608  	ins := instructionForProg(p)
  2609  	ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE
  2610  
  2611  	low, high, err := Split32BitImmediate(ins.imm)
  2612  	if err != nil {
  2613  		p.Ctxt.Diag("%v: constant %d too large", p, ins.imm, err)
  2614  		return nil
  2615  	}
  2616  	if high == 0 {
  2617  		return []*instruction{ins}
  2618  	}
  2619  
  2620  	// Split into two additions, if possible.
  2621  	// Do not split SP-writing instructions, as otherwise the recorded SP delta may be wrong.
  2622  	if p.Spadj == 0 && ins.as == AADDI && ins.imm >= -(1<<12) && ins.imm < 1<<12-1 {
  2623  		imm0 := ins.imm / 2
  2624  		imm1 := ins.imm - imm0
  2625  
  2626  		// ADDI $(imm/2), REG, TO
  2627  		// ADDI $(imm-imm/2), TO, TO
  2628  		ins.imm = imm0
  2629  		insADDI := &instruction{as: AADDI, rd: ins.rd, rs1: ins.rd, imm: imm1}
  2630  		return []*instruction{ins, insADDI}
  2631  	}
  2632  
  2633  	// LUI $high, TMP
  2634  	// ADDIW $low, TMP, TMP
  2635  	// <op> TMP, REG, TO
  2636  	insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
  2637  	insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP, imm: low}
  2638  	switch ins.as {
  2639  	case AADDI:
  2640  		ins.as = AADD
  2641  	case AANDI:
  2642  		ins.as = AAND
  2643  	case AORI:
  2644  		ins.as = AOR
  2645  	case AXORI:
  2646  		ins.as = AXOR
  2647  	default:
  2648  		p.Ctxt.Diag("unsupported immediate instruction %v for splitting", p)
  2649  		return nil
  2650  	}
  2651  	ins.rs2 = REG_TMP
  2652  	if low == 0 {
  2653  		return []*instruction{insLUI, ins}
  2654  	}
  2655  	return []*instruction{insLUI, insADDIW, ins}
  2656  }
  2657  
  2658  // instructionsForLoad returns the machine instructions for a load. The load
  2659  // instruction is specified by as and the base/source register is specified
  2660  // by rs, instead of the obj.Prog.
  2661  func instructionsForLoad(p *obj.Prog, as obj.As, rs int16) []*instruction {
  2662  	if p.From.Type != obj.TYPE_MEM {
  2663  		p.Ctxt.Diag("%v requires memory for source", p)
  2664  		return nil
  2665  	}
  2666  
  2667  	switch as {
  2668  	case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU, AFLW, AFLD:
  2669  	default:
  2670  		p.Ctxt.Diag("%v: unknown load instruction %v", p, as)
  2671  		return nil
  2672  	}
  2673  
  2674  	// <load> $imm, REG, TO (load $imm+(REG), TO)
  2675  	ins := instructionForProg(p)
  2676  	ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE
  2677  	ins.imm = p.From.Offset
  2678  
  2679  	low, high, err := Split32BitImmediate(ins.imm)
  2680  	if err != nil {
  2681  		p.Ctxt.Diag("%v: constant %d too large", p, ins.imm)
  2682  		return nil
  2683  	}
  2684  	if high == 0 {
  2685  		return []*instruction{ins}
  2686  	}
  2687  
  2688  	// LUI $high, TMP
  2689  	// ADD TMP, REG, TMP
  2690  	// <load> $low, TMP, TO
  2691  	insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
  2692  	insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rs1}
  2693  	ins.rs1, ins.imm = REG_TMP, low
  2694  
  2695  	return []*instruction{insLUI, insADD, ins}
  2696  }
  2697  
  2698  // instructionsForStore returns the machine instructions for a store. The store
  2699  // instruction is specified by as and the target/source register is specified
  2700  // by rd, instead of the obj.Prog.
  2701  func instructionsForStore(p *obj.Prog, as obj.As, rd int16) []*instruction {
  2702  	if p.To.Type != obj.TYPE_MEM {
  2703  		p.Ctxt.Diag("%v requires memory for destination", p)
  2704  		return nil
  2705  	}
  2706  
  2707  	switch as {
  2708  	case ASW, ASH, ASB, ASD, AFSW, AFSD:
  2709  	default:
  2710  		p.Ctxt.Diag("%v: unknown store instruction %v", p, as)
  2711  		return nil
  2712  	}
  2713  
  2714  	// <store> $imm, REG, TO (store $imm+(TO), REG)
  2715  	ins := instructionForProg(p)
  2716  	ins.as, ins.rd, ins.rs1, ins.rs2 = as, uint32(rd), uint32(p.From.Reg), obj.REG_NONE
  2717  	ins.imm = p.To.Offset
  2718  
  2719  	low, high, err := Split32BitImmediate(ins.imm)
  2720  	if err != nil {
  2721  		p.Ctxt.Diag("%v: constant %d too large", p, ins.imm)
  2722  		return nil
  2723  	}
  2724  	if high == 0 {
  2725  		return []*instruction{ins}
  2726  	}
  2727  
  2728  	// LUI $high, TMP
  2729  	// ADD TMP, TO, TMP
  2730  	// <store> $low, REG, TMP
  2731  	insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
  2732  	insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rd}
  2733  	ins.rd, ins.imm = REG_TMP, low
  2734  
  2735  	return []*instruction{insLUI, insADD, ins}
  2736  }
  2737  
  2738  func instructionsForTLS(p *obj.Prog, ins *instruction) []*instruction {
  2739  	insAddTP := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: REG_TP}
  2740  
  2741  	var inss []*instruction
  2742  	if p.Ctxt.Flag_shared {
  2743  		// TLS initial-exec mode - load TLS offset from GOT, add the thread pointer
  2744  		// register, then load from or store to the resulting memory location.
  2745  		insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
  2746  		insLoadTLSOffset := &instruction{as: ALD, rd: REG_TMP, rs1: REG_TMP}
  2747  		inss = []*instruction{insAUIPC, insLoadTLSOffset, insAddTP, ins}
  2748  	} else {
  2749  		// TLS local-exec mode - load upper TLS offset, add the lower TLS offset,
  2750  		// add the thread pointer register, then load from or store to the resulting
  2751  		// memory location. Note that this differs from the suggested three
  2752  		// instruction sequence, as the Go linker does not currently have an
  2753  		// easy way to handle relocation across 12 bytes of machine code.
  2754  		insLUI := &instruction{as: ALUI, rd: REG_TMP}
  2755  		insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP}
  2756  		inss = []*instruction{insLUI, insADDIW, insAddTP, ins}
  2757  	}
  2758  	return inss
  2759  }
  2760  
  2761  func instructionsForTLSLoad(p *obj.Prog) []*instruction {
  2762  	if p.From.Sym.Type != objabi.STLSBSS {
  2763  		p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.From.Sym)
  2764  		return nil
  2765  	}
  2766  
  2767  	ins := instructionForProg(p)
  2768  	ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), REG_TMP, obj.REG_NONE, 0
  2769  
  2770  	return instructionsForTLS(p, ins)
  2771  }
  2772  
  2773  func instructionsForTLSStore(p *obj.Prog) []*instruction {
  2774  	if p.To.Sym.Type != objabi.STLSBSS {
  2775  		p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.To.Sym)
  2776  		return nil
  2777  	}
  2778  
  2779  	ins := instructionForProg(p)
  2780  	ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
  2781  
  2782  	return instructionsForTLS(p, ins)
  2783  }
  2784  
  2785  // instructionsForMOV returns the machine instructions for an *obj.Prog that
  2786  // uses a MOV pseudo-instruction.
  2787  func instructionsForMOV(p *obj.Prog) []*instruction {
  2788  	ins := instructionForProg(p)
  2789  	inss := []*instruction{ins}
  2790  
  2791  	if p.Reg != 0 {
  2792  		p.Ctxt.Diag("%v: illegal MOV instruction", p)
  2793  		return nil
  2794  	}
  2795  
  2796  	switch {
  2797  	case p.From.Type == obj.TYPE_CONST && p.To.Type == obj.TYPE_REG:
  2798  		// Handle constant to register moves.
  2799  		if p.As != AMOV {
  2800  			p.Ctxt.Diag("%v: unsupported constant load", p)
  2801  			return nil
  2802  		}
  2803  
  2804  		// For constants larger than 32 bits in size that have trailing zeros,
  2805  		// use the value with the trailing zeros removed and then use a SLLI
  2806  		// instruction to restore the original constant.
  2807  		//
  2808  		// For example:
  2809  		//     MOV $0x8000000000000000, X10
  2810  		// becomes
  2811  		//     MOV $1, X10
  2812  		//     SLLI $63, X10, X10
  2813  		//
  2814  		// Similarly, we can construct large constants that have a consecutive
  2815  		// sequence of ones from a small negative constant, with a right and/or
  2816  		// left shift.
  2817  		//
  2818  		// For example:
  2819  		//     MOV $0x000fffffffffffda, X10
  2820  		// becomes
  2821  		//     MOV $-19, X10
  2822  		//     SLLI $13, X10
  2823  		//     SRLI $12, X10
  2824  		//
  2825  		var insSLLI, insSRLI *instruction
  2826  		if err := immIFits(ins.imm, 32); err != nil {
  2827  			if c, lsh, rsh, ok := splitShiftConst(ins.imm); ok {
  2828  				ins.imm = c
  2829  				if lsh > 0 {
  2830  					insSLLI = &instruction{as: ASLLI, rd: ins.rd, rs1: ins.rd, imm: int64(lsh)}
  2831  				}
  2832  				if rsh > 0 {
  2833  					insSRLI = &instruction{as: ASRLI, rd: ins.rd, rs1: ins.rd, imm: int64(rsh)}
  2834  				}
  2835  			}
  2836  		}
  2837  
  2838  		low, high, err := Split32BitImmediate(ins.imm)
  2839  		if err != nil {
  2840  			p.Ctxt.Diag("%v: constant %d too large: %v", p, ins.imm, err)
  2841  			return nil
  2842  		}
  2843  
  2844  		// MOV $c, R -> ADD $c, ZERO, R
  2845  		ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, REG_ZERO, obj.REG_NONE, low
  2846  
  2847  		// LUI is only necessary if the constant does not fit in 12 bits.
  2848  		if high != 0 {
  2849  			// LUI top20bits(c), R
  2850  			// ADD bottom12bits(c), R, R
  2851  			insLUI := &instruction{as: ALUI, rd: ins.rd, imm: high}
  2852  			inss = []*instruction{insLUI}
  2853  			if low != 0 {
  2854  				ins.as, ins.rs1 = AADDIW, ins.rd
  2855  				inss = append(inss, ins)
  2856  			}
  2857  		}
  2858  		if insSLLI != nil {
  2859  			inss = append(inss, insSLLI)
  2860  		}
  2861  		if insSRLI != nil {
  2862  			inss = append(inss, insSRLI)
  2863  		}
  2864  
  2865  	case p.From.Type == obj.TYPE_CONST && p.To.Type != obj.TYPE_REG:
  2866  		p.Ctxt.Diag("%v: constant load must target register", p)
  2867  		return nil
  2868  
  2869  	case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG:
  2870  		// Handle register to register moves.
  2871  		switch p.As {
  2872  		case AMOV: // MOV Ra, Rb -> ADDI $0, Ra, Rb
  2873  			ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, uint32(p.From.Reg), obj.REG_NONE, 0
  2874  		case AMOVW: // MOVW Ra, Rb -> ADDIW $0, Ra, Rb
  2875  			ins.as, ins.rs1, ins.rs2, ins.imm = AADDIW, uint32(p.From.Reg), obj.REG_NONE, 0
  2876  		case AMOVBU: // MOVBU Ra, Rb -> ANDI $255, Ra, Rb
  2877  			ins.as, ins.rs1, ins.rs2, ins.imm = AANDI, uint32(p.From.Reg), obj.REG_NONE, 255
  2878  		case AMOVF: // MOVF Ra, Rb -> FSGNJS Ra, Ra, Rb
  2879  			ins.as, ins.rs1 = AFSGNJS, uint32(p.From.Reg)
  2880  		case AMOVD: // MOVD Ra, Rb -> FSGNJD Ra, Ra, Rb
  2881  			ins.as, ins.rs1 = AFSGNJD, uint32(p.From.Reg)
  2882  		case AMOVB, AMOVH:
  2883  			if buildcfg.GORISCV64 >= 22 {
  2884  				// Use SEXTB or SEXTH to extend.
  2885  				ins.as, ins.rs1, ins.rs2 = ASEXTB, uint32(p.From.Reg), obj.REG_NONE
  2886  				if p.As == AMOVH {
  2887  					ins.as = ASEXTH
  2888  				}
  2889  			} else {
  2890  				// Use SLLI/SRAI sequence to extend.
  2891  				ins.as, ins.rs1, ins.rs2 = ASLLI, uint32(p.From.Reg), obj.REG_NONE
  2892  				if p.As == AMOVB {
  2893  					ins.imm = 56
  2894  				} else if p.As == AMOVH {
  2895  					ins.imm = 48
  2896  				}
  2897  				ins2 := &instruction{as: ASRAI, rd: ins.rd, rs1: ins.rd, imm: ins.imm}
  2898  				inss = append(inss, ins2)
  2899  			}
  2900  		case AMOVHU, AMOVWU:
  2901  			if buildcfg.GORISCV64 >= 22 {
  2902  				// Use ZEXTH or ADDUW to extend.
  2903  				ins.as, ins.rs1, ins.rs2, ins.imm = AZEXTH, uint32(p.From.Reg), obj.REG_NONE, 0
  2904  				if p.As == AMOVWU {
  2905  					ins.as, ins.rs2 = AADDUW, REG_ZERO
  2906  				}
  2907  			} else {
  2908  				// Use SLLI/SRLI sequence to extend.
  2909  				ins.as, ins.rs1, ins.rs2 = ASLLI, uint32(p.From.Reg), obj.REG_NONE
  2910  				if p.As == AMOVHU {
  2911  					ins.imm = 48
  2912  				} else if p.As == AMOVWU {
  2913  					ins.imm = 32
  2914  				}
  2915  				ins2 := &instruction{as: ASRLI, rd: ins.rd, rs1: ins.rd, imm: ins.imm}
  2916  				inss = append(inss, ins2)
  2917  			}
  2918  		}
  2919  
  2920  	case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG:
  2921  		// Memory to register loads.
  2922  		switch p.From.Name {
  2923  		case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
  2924  			// MOV c(Rs), Rd -> L $c, Rs, Rd
  2925  			inss = instructionsForLoad(p, movToLoad(p.As), addrToReg(p.From))
  2926  
  2927  		case obj.NAME_EXTERN, obj.NAME_STATIC, obj.NAME_GOTREF:
  2928  			if p.From.Sym.Type == objabi.STLSBSS {
  2929  				return instructionsForTLSLoad(p)
  2930  			}
  2931  
  2932  			// Note that the values for $off_hi and $off_lo are currently
  2933  			// zero and will be assigned during relocation. If the destination
  2934  			// is an integer register then we can use the same register for the
  2935  			// address computation, otherwise we need to use the temporary register.
  2936  			//
  2937  			// AUIPC $off_hi, Rd
  2938  			// L $off_lo, Rd, Rd
  2939  			//
  2940  			addrReg := ins.rd
  2941  			if addrReg < REG_X0 || addrReg > REG_X31 {
  2942  				addrReg = REG_TMP
  2943  			}
  2944  			insAUIPC := &instruction{as: AAUIPC, rd: addrReg}
  2945  			ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), addrReg, obj.REG_NONE, 0
  2946  			inss = []*instruction{insAUIPC, ins}
  2947  
  2948  		default:
  2949  			p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
  2950  			return nil
  2951  		}
  2952  
  2953  	case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM:
  2954  		// Register to memory stores.
  2955  		switch p.As {
  2956  		case AMOVBU, AMOVHU, AMOVWU:
  2957  			p.Ctxt.Diag("%v: unsupported unsigned store", p)
  2958  			return nil
  2959  		}
  2960  		switch p.To.Name {
  2961  		case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
  2962  			// MOV Rs, c(Rd) -> S $c, Rs, Rd
  2963  			inss = instructionsForStore(p, movToStore(p.As), addrToReg(p.To))
  2964  
  2965  		case obj.NAME_EXTERN, obj.NAME_STATIC:
  2966  			if p.To.Sym.Type == objabi.STLSBSS {
  2967  				return instructionsForTLSStore(p)
  2968  			}
  2969  
  2970  			// Note that the values for $off_hi and $off_lo are currently
  2971  			// zero and will be assigned during relocation.
  2972  			//
  2973  			// AUIPC $off_hi, Rtmp
  2974  			// S $off_lo, Rtmp, Rd
  2975  			insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
  2976  			ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
  2977  			inss = []*instruction{insAUIPC, ins}
  2978  
  2979  		default:
  2980  			p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
  2981  			return nil
  2982  		}
  2983  
  2984  	case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG:
  2985  		// MOV $sym+off(SP/SB), R
  2986  		if p.As != AMOV {
  2987  			p.Ctxt.Diag("%v: unsupported address load", p)
  2988  			return nil
  2989  		}
  2990  		switch p.From.Name {
  2991  		case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
  2992  			inss = instructionsForOpImmediate(p, AADDI, addrToReg(p.From))
  2993  
  2994  		case obj.NAME_EXTERN, obj.NAME_STATIC:
  2995  			// Note that the values for $off_hi and $off_lo are currently
  2996  			// zero and will be assigned during relocation.
  2997  			//
  2998  			// AUIPC $off_hi, R
  2999  			// ADDI $off_lo, R
  3000  			insAUIPC := &instruction{as: AAUIPC, rd: ins.rd}
  3001  			ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, ins.rd, obj.REG_NONE, 0
  3002  			inss = []*instruction{insAUIPC, ins}
  3003  
  3004  		default:
  3005  			p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
  3006  			return nil
  3007  		}
  3008  
  3009  	case p.From.Type == obj.TYPE_ADDR && p.To.Type != obj.TYPE_REG:
  3010  		p.Ctxt.Diag("%v: address load must target register", p)
  3011  		return nil
  3012  
  3013  	default:
  3014  		p.Ctxt.Diag("%v: unsupported MOV", p)
  3015  		return nil
  3016  	}
  3017  
  3018  	return inss
  3019  }
  3020  
  3021  // instructionsForRotate returns the machine instructions for a bitwise rotation.
  3022  func instructionsForRotate(p *obj.Prog, ins *instruction) []*instruction {
  3023  	if buildcfg.GORISCV64 >= 22 {
  3024  		// Rotation instructions are supported natively.
  3025  		return []*instruction{ins}
  3026  	}
  3027  
  3028  	switch ins.as {
  3029  	case AROL, AROLW, AROR, ARORW:
  3030  		// ROL -> OR (SLL x y) (SRL x (NEG y))
  3031  		// ROR -> OR (SRL x y) (SLL x (NEG y))
  3032  		sllOp, srlOp := ASLL, ASRL
  3033  		if ins.as == AROLW || ins.as == ARORW {
  3034  			sllOp, srlOp = ASLLW, ASRLW
  3035  		}
  3036  		shift1, shift2 := sllOp, srlOp
  3037  		if ins.as == AROR || ins.as == ARORW {
  3038  			shift1, shift2 = shift2, shift1
  3039  		}
  3040  		return []*instruction{
  3041  			&instruction{as: ASUB, rs1: REG_ZERO, rs2: ins.rs2, rd: REG_TMP},
  3042  			&instruction{as: shift2, rs1: ins.rs1, rs2: REG_TMP, rd: REG_TMP},
  3043  			&instruction{as: shift1, rs1: ins.rs1, rs2: ins.rs2, rd: ins.rd},
  3044  			&instruction{as: AOR, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
  3045  		}
  3046  
  3047  	case ARORI, ARORIW:
  3048  		// ROR -> OR (SLLI -x y) (SRLI x y)
  3049  		sllOp, srlOp := ASLLI, ASRLI
  3050  		sllImm := int64(int8(-ins.imm) & 63)
  3051  		if ins.as == ARORIW {
  3052  			sllOp, srlOp = ASLLIW, ASRLIW
  3053  			sllImm = int64(int8(-ins.imm) & 31)
  3054  		}
  3055  		return []*instruction{
  3056  			&instruction{as: srlOp, rs1: ins.rs1, rd: REG_TMP, imm: ins.imm},
  3057  			&instruction{as: sllOp, rs1: ins.rs1, rd: ins.rd, imm: sllImm},
  3058  			&instruction{as: AOR, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
  3059  		}
  3060  
  3061  	default:
  3062  		p.Ctxt.Diag("%v: unknown rotation", p)
  3063  		return nil
  3064  	}
  3065  }
  3066  
  3067  // instructionsForMinMax returns the machine instructions for an integer minimum or maximum.
  3068  func instructionsForMinMax(p *obj.Prog, ins *instruction) []*instruction {
  3069  	if buildcfg.GORISCV64 >= 22 {
  3070  		// Minimum and maximum instructions are supported natively.
  3071  		return []*instruction{ins}
  3072  	}
  3073  
  3074  	// Generate a move for identical inputs.
  3075  	if ins.rs1 == ins.rs2 {
  3076  		ins.as, ins.rs2, ins.imm = AADDI, obj.REG_NONE, 0
  3077  		return []*instruction{ins}
  3078  	}
  3079  
  3080  	// Ensure that if one of the source registers is the same as the destination,
  3081  	// it is processed first.
  3082  	if ins.rs1 == ins.rd {
  3083  		ins.rs1, ins.rs2 = ins.rs2, ins.rs1
  3084  	}
  3085  	sltReg1, sltReg2 := ins.rs2, ins.rs1
  3086  
  3087  	// MIN -> SLT/SUB/XOR/AND/XOR
  3088  	// MAX -> SLT/SUB/XOR/AND/XOR with swapped inputs to SLT
  3089  	switch ins.as {
  3090  	case AMIN:
  3091  		ins.as = ASLT
  3092  	case AMAX:
  3093  		ins.as, sltReg1, sltReg2 = ASLT, sltReg2, sltReg1
  3094  	case AMINU:
  3095  		ins.as = ASLTU
  3096  	case AMAXU:
  3097  		ins.as, sltReg1, sltReg2 = ASLTU, sltReg2, sltReg1
  3098  	}
  3099  	return []*instruction{
  3100  		&instruction{as: ins.as, rs1: sltReg1, rs2: sltReg2, rd: REG_TMP},
  3101  		&instruction{as: ASUB, rs1: REG_ZERO, rs2: REG_TMP, rd: REG_TMP},
  3102  		&instruction{as: AXOR, rs1: ins.rs1, rs2: ins.rs2, rd: ins.rd},
  3103  		&instruction{as: AAND, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
  3104  		&instruction{as: AXOR, rs1: ins.rs1, rs2: ins.rd, rd: ins.rd},
  3105  	}
  3106  }
  3107  
  3108  // instructionsForProg returns the machine instructions for an *obj.Prog.
  3109  func instructionsForProg(p *obj.Prog) []*instruction {
  3110  	ins := instructionForProg(p)
  3111  	inss := []*instruction{ins}
  3112  
  3113  	if ins.as == AVSETVLI || ins.as == AVSETIVLI {
  3114  		if len(p.RestArgs) != 4 {
  3115  			p.Ctxt.Diag("incorrect number of arguments for instruction")
  3116  			return nil
  3117  		}
  3118  	} else if len(p.RestArgs) > 1 {
  3119  		p.Ctxt.Diag("too many source registers")
  3120  		return nil
  3121  	}
  3122  
  3123  	switch ins.as {
  3124  	case AJAL, AJALR:
  3125  		ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.To.Reg), obj.REG_NONE
  3126  		ins.imm = p.To.Offset
  3127  
  3128  	case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ:
  3129  		switch ins.as {
  3130  		case ABEQZ:
  3131  			ins.as, ins.rs1, ins.rs2 = ABEQ, REG_ZERO, uint32(p.From.Reg)
  3132  		case ABGEZ:
  3133  			ins.as, ins.rs1, ins.rs2 = ABGE, REG_ZERO, uint32(p.From.Reg)
  3134  		case ABGT:
  3135  			ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), uint32(p.Reg)
  3136  		case ABGTU:
  3137  			ins.as, ins.rs1, ins.rs2 = ABLTU, uint32(p.From.Reg), uint32(p.Reg)
  3138  		case ABGTZ:
  3139  			ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), REG_ZERO
  3140  		case ABLE:
  3141  			ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), uint32(p.Reg)
  3142  		case ABLEU:
  3143  			ins.as, ins.rs1, ins.rs2 = ABGEU, uint32(p.From.Reg), uint32(p.Reg)
  3144  		case ABLEZ:
  3145  			ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), REG_ZERO
  3146  		case ABLTZ:
  3147  			ins.as, ins.rs1, ins.rs2 = ABLT, REG_ZERO, uint32(p.From.Reg)
  3148  		case ABNEZ:
  3149  			ins.as, ins.rs1, ins.rs2 = ABNE, REG_ZERO, uint32(p.From.Reg)
  3150  		}
  3151  		ins.imm = p.To.Offset
  3152  
  3153  	case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
  3154  		inss = instructionsForMOV(p)
  3155  
  3156  	case ALW, ALWU, ALH, ALHU, ALB, ALBU, ALD, AFLW, AFLD:
  3157  		inss = instructionsForLoad(p, ins.as, p.From.Reg)
  3158  
  3159  	case ASW, ASH, ASB, ASD, AFSW, AFSD:
  3160  		inss = instructionsForStore(p, ins.as, p.To.Reg)
  3161  
  3162  	case ALRW, ALRD:
  3163  		// Set aq to use acquire access ordering
  3164  		ins.funct7 = 2
  3165  		ins.rs1, ins.rs2 = uint32(p.From.Reg), REG_ZERO
  3166  
  3167  	case AADDI, AANDI, AORI, AXORI:
  3168  		inss = instructionsForOpImmediate(p, ins.as, p.Reg)
  3169  
  3170  	case ASCW, ASCD:
  3171  		// Set release access ordering
  3172  		ins.funct7 = 1
  3173  		ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg)
  3174  
  3175  	case AAMOSWAPW, AAMOSWAPD, AAMOADDW, AAMOADDD, AAMOANDW, AAMOANDD, AAMOORW, AAMOORD,
  3176  		AAMOXORW, AAMOXORD, AAMOMINW, AAMOMIND, AAMOMINUW, AAMOMINUD, AAMOMAXW, AAMOMAXD, AAMOMAXUW, AAMOMAXUD:
  3177  		// Set aqrl to use acquire & release access ordering
  3178  		ins.funct7 = 3
  3179  		ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg)
  3180  
  3181  	case AECALL, AEBREAK:
  3182  		insEnc := encode(p.As)
  3183  		if p.To.Type == obj.TYPE_NONE {
  3184  			ins.rd = REG_ZERO
  3185  		}
  3186  		ins.rs1 = REG_ZERO
  3187  		ins.imm = insEnc.csr
  3188  
  3189  	case ARDCYCLE, ARDTIME, ARDINSTRET:
  3190  		ins.as = ACSRRS
  3191  		if p.To.Type == obj.TYPE_NONE {
  3192  			ins.rd = REG_ZERO
  3193  		}
  3194  		ins.rs1 = REG_ZERO
  3195  		switch p.As {
  3196  		case ARDCYCLE:
  3197  			ins.imm = -1024
  3198  		case ARDTIME:
  3199  			ins.imm = -1023
  3200  		case ARDINSTRET:
  3201  			ins.imm = -1022
  3202  		}
  3203  
  3204  	case AFENCE:
  3205  		ins.rd, ins.rs1, ins.rs2 = REG_ZERO, REG_ZERO, obj.REG_NONE
  3206  		ins.imm = 0x0ff
  3207  
  3208  	case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
  3209  		// Set the default rounding mode in funct3 to round to zero.
  3210  		if p.Scond&rmSuffixBit == 0 {
  3211  			ins.funct3 = uint32(RM_RTZ)
  3212  		} else {
  3213  			ins.funct3 = uint32(p.Scond &^ rmSuffixBit)
  3214  		}
  3215  
  3216  	case AFNES, AFNED:
  3217  		// Replace FNE[SD] with FEQ[SD] and NOT.
  3218  		if p.To.Type != obj.TYPE_REG {
  3219  			p.Ctxt.Diag("%v needs an integer register output", p)
  3220  			return nil
  3221  		}
  3222  		if ins.as == AFNES {
  3223  			ins.as = AFEQS
  3224  		} else {
  3225  			ins.as = AFEQD
  3226  		}
  3227  		ins2 := &instruction{
  3228  			as:  AXORI, // [bit] xor 1 = not [bit]
  3229  			rd:  ins.rd,
  3230  			rs1: ins.rd,
  3231  			imm: 1,
  3232  		}
  3233  		inss = append(inss, ins2)
  3234  
  3235  	case AFSQRTS, AFSQRTD:
  3236  		// These instructions expect a zero (i.e. float register 0)
  3237  		// to be the second input operand.
  3238  		ins.rs1 = uint32(p.From.Reg)
  3239  		ins.rs2 = REG_F0
  3240  
  3241  	case AFMADDS, AFMSUBS, AFNMADDS, AFNMSUBS,
  3242  		AFMADDD, AFMSUBD, AFNMADDD, AFNMSUBD:
  3243  		// Swap the first two operands so that the operands are in the same
  3244  		// order as they are in the specification: RS1, RS2, RS3, RD.
  3245  		ins.rs1, ins.rs2 = ins.rs2, ins.rs1
  3246  
  3247  	case ANEG, ANEGW:
  3248  		// NEG rs, rd -> SUB rs, X0, rd
  3249  		ins.as = ASUB
  3250  		if p.As == ANEGW {
  3251  			ins.as = ASUBW
  3252  		}
  3253  		ins.rs1 = REG_ZERO
  3254  		if ins.rd == obj.REG_NONE {
  3255  			ins.rd = ins.rs2
  3256  		}
  3257  
  3258  	case ANOT:
  3259  		// NOT rs, rd -> XORI $-1, rs, rd
  3260  		ins.as = AXORI
  3261  		ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
  3262  		if ins.rd == obj.REG_NONE {
  3263  			ins.rd = ins.rs1
  3264  		}
  3265  		ins.imm = -1
  3266  
  3267  	case ASEQZ:
  3268  		// SEQZ rs, rd -> SLTIU $1, rs, rd
  3269  		ins.as = ASLTIU
  3270  		ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
  3271  		ins.imm = 1
  3272  
  3273  	case ASNEZ:
  3274  		// SNEZ rs, rd -> SLTU rs, x0, rd
  3275  		ins.as = ASLTU
  3276  		ins.rs1 = REG_ZERO
  3277  
  3278  	case AFABSS:
  3279  		// FABSS rs, rd -> FSGNJXS rs, rs, rd
  3280  		ins.as = AFSGNJXS
  3281  		ins.rs1 = uint32(p.From.Reg)
  3282  
  3283  	case AFABSD:
  3284  		// FABSD rs, rd -> FSGNJXD rs, rs, rd
  3285  		ins.as = AFSGNJXD
  3286  		ins.rs1 = uint32(p.From.Reg)
  3287  
  3288  	case AFNEGS:
  3289  		// FNEGS rs, rd -> FSGNJNS rs, rs, rd
  3290  		ins.as = AFSGNJNS
  3291  		ins.rs1 = uint32(p.From.Reg)
  3292  
  3293  	case AFNEGD:
  3294  		// FNEGD rs, rd -> FSGNJND rs, rs, rd
  3295  		ins.as = AFSGNJND
  3296  		ins.rs1 = uint32(p.From.Reg)
  3297  
  3298  	case AROL, AROLW, AROR, ARORW:
  3299  		inss = instructionsForRotate(p, ins)
  3300  
  3301  	case ARORI:
  3302  		if ins.imm < 0 || ins.imm > 63 {
  3303  			p.Ctxt.Diag("%v: immediate out of range 0 to 63", p)
  3304  		}
  3305  		inss = instructionsForRotate(p, ins)
  3306  
  3307  	case ARORIW:
  3308  		if ins.imm < 0 || ins.imm > 31 {
  3309  			p.Ctxt.Diag("%v: immediate out of range 0 to 31", p)
  3310  		}
  3311  		inss = instructionsForRotate(p, ins)
  3312  
  3313  	case ASLLI, ASRLI, ASRAI:
  3314  		if ins.imm < 0 || ins.imm > 63 {
  3315  			p.Ctxt.Diag("%v: immediate out of range 0 to 63", p)
  3316  		}
  3317  
  3318  	case ASLLIW, ASRLIW, ASRAIW:
  3319  		if ins.imm < 0 || ins.imm > 31 {
  3320  			p.Ctxt.Diag("%v: immediate out of range 0 to 31", p)
  3321  		}
  3322  
  3323  	case ACLZ, ACLZW, ACTZ, ACTZW, ACPOP, ACPOPW, ASEXTB, ASEXTH, AZEXTH:
  3324  		ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
  3325  
  3326  	case AORCB, AREV8:
  3327  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
  3328  
  3329  	case AANDN, AORN:
  3330  		if buildcfg.GORISCV64 >= 22 {
  3331  			// ANDN and ORN instructions are supported natively.
  3332  			break
  3333  		}
  3334  		// ANDN -> (AND (NOT x) y)
  3335  		// ORN  -> (OR  (NOT x) y)
  3336  		bitwiseOp, notReg := AAND, ins.rd
  3337  		if ins.as == AORN {
  3338  			bitwiseOp = AOR
  3339  		}
  3340  		if ins.rs1 == notReg {
  3341  			notReg = REG_TMP
  3342  		}
  3343  		inss = []*instruction{
  3344  			&instruction{as: AXORI, rs1: ins.rs2, rs2: obj.REG_NONE, rd: notReg, imm: -1},
  3345  			&instruction{as: bitwiseOp, rs1: ins.rs1, rs2: notReg, rd: ins.rd},
  3346  		}
  3347  
  3348  	case AXNOR:
  3349  		if buildcfg.GORISCV64 >= 22 {
  3350  			// XNOR instruction is supported natively.
  3351  			break
  3352  		}
  3353  		// XNOR -> (NOT (XOR x y))
  3354  		ins.as = AXOR
  3355  		inss = append(inss, &instruction{as: AXORI, rs1: ins.rd, rs2: obj.REG_NONE, rd: ins.rd, imm: -1})
  3356  
  3357  	case AMIN, AMAX, AMINU, AMAXU:
  3358  		inss = instructionsForMinMax(p, ins)
  3359  
  3360  	case AVSETVLI, AVSETIVLI:
  3361  		ins.rs1, ins.rs2 = ins.rs2, obj.REG_NONE
  3362  		vtype, err := EncodeVectorType(p.RestArgs[0].Offset, p.RestArgs[1].Offset, p.RestArgs[2].Offset, p.RestArgs[3].Offset)
  3363  		if err != nil {
  3364  			p.Ctxt.Diag("%v: %v", p, err)
  3365  		}
  3366  		ins.imm = int64(vtype)
  3367  		if ins.as == AVSETIVLI {
  3368  			if p.From.Type != obj.TYPE_CONST {
  3369  				p.Ctxt.Diag("%v: expected immediate value", p)
  3370  			}
  3371  			ins.rs1 = uint32(p.From.Offset)
  3372  		}
  3373  
  3374  	case AVLE8V, AVLE16V, AVLE32V, AVLE64V, AVSE8V, AVSE16V, AVSE32V, AVSE64V, AVLMV, AVSMV:
  3375  		// Set mask bit
  3376  		switch {
  3377  		case ins.rs1 == obj.REG_NONE:
  3378  			ins.funct7 |= 1 // unmasked
  3379  		case ins.rs1 != REG_V0:
  3380  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3381  		}
  3382  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
  3383  
  3384  	case AVLSE8V, AVLSE16V, AVLSE32V, AVLSE64V,
  3385  		AVLUXEI8V, AVLUXEI16V, AVLUXEI32V, AVLUXEI64V, AVLOXEI8V, AVLOXEI16V, AVLOXEI32V, AVLOXEI64V:
  3386  		// Set mask bit
  3387  		switch {
  3388  		case ins.rs3 == obj.REG_NONE:
  3389  			ins.funct7 |= 1 // unmasked
  3390  		case ins.rs3 != REG_V0:
  3391  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3392  		}
  3393  		ins.rs1, ins.rs2, ins.rs3 = ins.rs2, ins.rs1, obj.REG_NONE
  3394  
  3395  	case AVSSE8V, AVSSE16V, AVSSE32V, AVSSE64V,
  3396  		AVSUXEI8V, AVSUXEI16V, AVSUXEI32V, AVSUXEI64V, AVSOXEI8V, AVSOXEI16V, AVSOXEI32V, AVSOXEI64V:
  3397  		// Set mask bit
  3398  		switch {
  3399  		case ins.rs3 == obj.REG_NONE:
  3400  			ins.funct7 |= 1 // unmasked
  3401  		case ins.rs3 != REG_V0:
  3402  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3403  		}
  3404  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = ins.rs2, ins.rd, ins.rs1, obj.REG_NONE
  3405  
  3406  	case AVL1RV, AVL1RE8V, AVL1RE16V, AVL1RE32V, AVL1RE64V, AVL2RV, AVL2RE8V, AVL2RE16V, AVL2RE32V, AVL2RE64V,
  3407  		AVL4RV, AVL4RE8V, AVL4RE16V, AVL4RE32V, AVL4RE64V, AVL8RV, AVL8RE8V, AVL8RE16V, AVL8RE32V, AVL8RE64V:
  3408  		switch ins.as {
  3409  		case AVL1RV:
  3410  			ins.as = AVL1RE8V
  3411  		case AVL2RV:
  3412  			ins.as = AVL2RE8V
  3413  		case AVL4RV:
  3414  			ins.as = AVL4RE8V
  3415  		case AVL8RV:
  3416  			ins.as = AVL8RE8V
  3417  		}
  3418  		if ins.rs1 != obj.REG_NONE {
  3419  			p.Ctxt.Diag("%v: too many operands for instruction", p)
  3420  		}
  3421  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
  3422  
  3423  	case AVS1RV, AVS2RV, AVS4RV, AVS8RV:
  3424  		if ins.rs1 != obj.REG_NONE {
  3425  			p.Ctxt.Diag("%v: too many operands for instruction", p)
  3426  		}
  3427  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
  3428  
  3429  	case AVADDVV, AVADDVX, AVSUBVV, AVSUBVX, AVRSUBVX, AVWADDUVV, AVWADDUVX, AVWSUBUVV, AVWSUBUVX,
  3430  		AVWADDVV, AVWADDVX, AVWSUBVV, AVWSUBVX, AVWADDUWV, AVWADDUWX, AVWSUBUWV, AVWSUBUWX,
  3431  		AVWADDWV, AVWADDWX, AVWSUBWV, AVWSUBWX, AVANDVV, AVANDVX, AVORVV, AVORVX, AVXORVV, AVXORVX,
  3432  		AVSLLVV, AVSLLVX, AVSRLVV, AVSRLVX, AVSRAVV, AVSRAVX,
  3433  		AVMSEQVV, AVMSEQVX, AVMSNEVV, AVMSNEVX, AVMSLTUVV, AVMSLTUVX, AVMSLTVV, AVMSLTVX,
  3434  		AVMSLEUVV, AVMSLEUVX, AVMSLEVV, AVMSLEVX, AVMSGTUVX, AVMSGTVX,
  3435  		AVMINUVV, AVMINUVX, AVMINVV, AVMINVX, AVMAXUVV, AVMAXUVX, AVMAXVV, AVMAXVX,
  3436  		AVMULVV, AVMULVX, AVMULHVV, AVMULHVX, AVMULHUVV, AVMULHUVX, AVMULHSUVV, AVMULHSUVX,
  3437  		AVDIVUVV, AVDIVUVX, AVDIVVV, AVDIVVX, AVREMUVV, AVREMUVX, AVREMVV, AVREMVX,
  3438  		AVWMULVV, AVWMULVX, AVWMULUVV, AVWMULUVX, AVWMULSUVV, AVWMULSUVX, AVNSRLWV, AVNSRLWX, AVNSRAWV, AVNSRAWX,
  3439  		AVMACCVV, AVMACCVX, AVNMSACVV, AVNMSACVX, AVMADDVV, AVMADDVX, AVNMSUBVV, AVNMSUBVX,
  3440  		AVWMACCUVV, AVWMACCUVX, AVWMACCVV, AVWMACCVX, AVWMACCSUVV, AVWMACCSUVX, AVWMACCUSVX,
  3441  		AVSADDUVV, AVSADDUVX, AVSADDUVI, AVSADDVV, AVSADDVX, AVSADDVI, AVSSUBUVV, AVSSUBUVX, AVSSUBVV, AVSSUBVX,
  3442  		AVAADDUVV, AVAADDUVX, AVAADDVV, AVAADDVX, AVASUBUVV, AVASUBUVX, AVASUBVV, AVASUBVX,
  3443  		AVSMULVV, AVSMULVX, AVSSRLVV, AVSSRLVX, AVSSRLVI, AVSSRAVV, AVSSRAVX, AVSSRAVI,
  3444  		AVNCLIPUWV, AVNCLIPUWX, AVNCLIPUWI, AVNCLIPWV, AVNCLIPWX, AVNCLIPWI:
  3445  		// Set mask bit
  3446  		switch {
  3447  		case ins.rs3 == obj.REG_NONE:
  3448  			ins.funct7 |= 1 // unmasked
  3449  		case ins.rs3 != REG_V0:
  3450  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3451  		}
  3452  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), obj.REG_NONE
  3453  
  3454  	case AVADDVI, AVRSUBVI, AVANDVI, AVORVI, AVXORVI, AVMSEQVI, AVMSNEVI, AVMSLEUVI, AVMSLEVI, AVMSGTUVI, AVMSGTVI,
  3455  		AVSLLVI, AVSRLVI, AVSRAVI, AVNSRLWI, AVNSRAWI:
  3456  		// Set mask bit
  3457  		switch {
  3458  		case ins.rs3 == obj.REG_NONE:
  3459  			ins.funct7 |= 1 // unmasked
  3460  		case ins.rs3 != REG_V0:
  3461  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3462  		}
  3463  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), obj.REG_NONE, uint32(p.Reg), obj.REG_NONE
  3464  
  3465  	case AVZEXTVF2, AVSEXTVF2, AVZEXTVF4, AVSEXTVF4, AVZEXTVF8, AVSEXTVF8:
  3466  		// Set mask bit
  3467  		switch {
  3468  		case ins.rs1 == obj.REG_NONE:
  3469  			ins.funct7 |= 1 // unmasked
  3470  		case ins.rs1 != REG_V0:
  3471  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3472  		}
  3473  		ins.rs1 = obj.REG_NONE
  3474  
  3475  	case AVMVVV, AVMVVX:
  3476  		if ins.rs1 != obj.REG_NONE {
  3477  			p.Ctxt.Diag("%v: too many operands for instruction", p)
  3478  		}
  3479  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), REG_V0
  3480  
  3481  	case AVMVVI:
  3482  		if ins.rs1 != obj.REG_NONE {
  3483  			p.Ctxt.Diag("%v: too many operands for instruction", p)
  3484  		}
  3485  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), obj.REG_NONE, REG_V0
  3486  
  3487  	case AVADCVVM, AVADCVXM, AVMADCVVM, AVMADCVXM, AVSBCVVM, AVSBCVXM, AVMSBCVVM, AVMSBCVXM, AVADCVIM, AVMADCVIM,
  3488  		AVMERGEVVM, AVMERGEVXM, AVMERGEVIM:
  3489  		if ins.rs3 != REG_V0 {
  3490  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3491  		}
  3492  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), obj.REG_NONE
  3493  
  3494  	case AVMADCVV, AVMADCVX, AVMSBCVV, AVMSBCVX, AVMADCVI:
  3495  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)
  3496  
  3497  	case AVNEGV, AVWCVTXXV, AVWCVTUXXV, AVNCVTXXW:
  3498  		// Set mask bit
  3499  		switch {
  3500  		case ins.rs1 == obj.REG_NONE:
  3501  			ins.funct7 |= 1 // unmasked
  3502  		case ins.rs1 != REG_V0:
  3503  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3504  		}
  3505  		switch ins.as {
  3506  		case AVNEGV:
  3507  			ins.as = AVRSUBVX
  3508  		case AVWCVTXXV:
  3509  			ins.as = AVWADDVX
  3510  		case AVWCVTUXXV:
  3511  			ins.as = AVWADDUVX
  3512  		case AVNCVTXXW:
  3513  			ins.as = AVNSRLWX
  3514  		}
  3515  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), REG_X0, uint32(p.From.Reg)
  3516  
  3517  	case AVNOTV:
  3518  		// Set mask bit
  3519  		switch {
  3520  		case ins.rs1 == obj.REG_NONE:
  3521  			ins.funct7 |= 1 // unmasked
  3522  		case ins.rs1 != REG_V0:
  3523  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3524  		}
  3525  		ins.as = AVXORVI
  3526  		ins.rd, ins.rs1, ins.rs2, ins.imm = uint32(p.To.Reg), obj.REG_NONE, uint32(p.From.Reg), -1
  3527  
  3528  	case AVMSGTVV, AVMSGTUVV, AVMSGEVV, AVMSGEUVV:
  3529  		// Set mask bit
  3530  		switch {
  3531  		case ins.rs3 == obj.REG_NONE:
  3532  			ins.funct7 |= 1 // unmasked
  3533  		case ins.rs3 != REG_V0:
  3534  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3535  		}
  3536  		switch ins.as {
  3537  		case AVMSGTVV:
  3538  			ins.as = AVMSLTVV
  3539  		case AVMSGTUVV:
  3540  			ins.as = AVMSLTUVV
  3541  		case AVMSGEVV:
  3542  			ins.as = AVMSLEVV
  3543  		case AVMSGEUVV:
  3544  			ins.as = AVMSLEUVV
  3545  		}
  3546  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.Reg), uint32(p.From.Reg), obj.REG_NONE
  3547  
  3548  	case AVMSLTVI, AVMSLTUVI, AVMSGEVI, AVMSGEUVI:
  3549  		// Set mask bit
  3550  		switch {
  3551  		case ins.rs3 == obj.REG_NONE:
  3552  			ins.funct7 |= 1 // unmasked
  3553  		case ins.rs3 != REG_V0:
  3554  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3555  		}
  3556  		switch ins.as {
  3557  		case AVMSLTVI:
  3558  			ins.as = AVMSLEVI
  3559  		case AVMSLTUVI:
  3560  			ins.as = AVMSLEUVI
  3561  		case AVMSGEVI:
  3562  			ins.as = AVMSGTVI
  3563  		case AVMSGEUVI:
  3564  			ins.as = AVMSGTUVI
  3565  		}
  3566  		ins.rd, ins.rs1, ins.rs2, ins.rs3, ins.imm = uint32(p.To.Reg), obj.REG_NONE, uint32(p.Reg), obj.REG_NONE, ins.imm-1
  3567  	}
  3568  
  3569  	for _, ins := range inss {
  3570  		ins.p = p
  3571  	}
  3572  
  3573  	return inss
  3574  }
  3575  
  3576  // assemble emits machine code.
  3577  // It is called at the very end of the assembly process.
  3578  func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
  3579  	if ctxt.Retpoline {
  3580  		ctxt.Diag("-spectre=ret not supported on riscv")
  3581  		ctxt.Retpoline = false // don't keep printing
  3582  	}
  3583  
  3584  	// If errors were encountered during preprocess/validation, proceeding
  3585  	// and attempting to encode said instructions will only lead to panics.
  3586  	if ctxt.Errors > 0 {
  3587  		return
  3588  	}
  3589  
  3590  	for p := cursym.Func().Text; p != nil; p = p.Link {
  3591  		switch p.As {
  3592  		case AJAL:
  3593  			if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC {
  3594  				cursym.AddRel(ctxt, obj.Reloc{
  3595  					Type: objabi.R_RISCV_JAL,
  3596  					Off:  int32(p.Pc),
  3597  					Siz:  4,
  3598  					Sym:  p.To.Sym,
  3599  					Add:  p.To.Offset,
  3600  				})
  3601  			}
  3602  		case AJALR:
  3603  			if p.To.Sym != nil {
  3604  				ctxt.Diag("%v: unexpected AJALR with to symbol", p)
  3605  			}
  3606  
  3607  		case AAUIPC, AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
  3608  			var addr *obj.Addr
  3609  			var rt objabi.RelocType
  3610  			if p.Mark&NEED_CALL_RELOC == NEED_CALL_RELOC {
  3611  				rt = objabi.R_RISCV_CALL
  3612  				addr = &p.From
  3613  			} else if p.Mark&NEED_PCREL_ITYPE_RELOC == NEED_PCREL_ITYPE_RELOC {
  3614  				rt = objabi.R_RISCV_PCREL_ITYPE
  3615  				addr = &p.From
  3616  			} else if p.Mark&NEED_PCREL_STYPE_RELOC == NEED_PCREL_STYPE_RELOC {
  3617  				rt = objabi.R_RISCV_PCREL_STYPE
  3618  				addr = &p.To
  3619  			} else if p.Mark&NEED_GOT_PCREL_ITYPE_RELOC == NEED_GOT_PCREL_ITYPE_RELOC {
  3620  				rt = objabi.R_RISCV_GOT_PCREL_ITYPE
  3621  				addr = &p.From
  3622  			} else {
  3623  				break
  3624  			}
  3625  			if p.As == AAUIPC {
  3626  				if p.Link == nil {
  3627  					ctxt.Diag("AUIPC needing PC-relative reloc missing following instruction")
  3628  					break
  3629  				}
  3630  				addr = &p.RestArgs[0].Addr
  3631  			}
  3632  			if addr.Sym == nil {
  3633  				ctxt.Diag("PC-relative relocation missing symbol")
  3634  				break
  3635  			}
  3636  			if addr.Sym.Type == objabi.STLSBSS {
  3637  				if ctxt.Flag_shared {
  3638  					rt = objabi.R_RISCV_TLS_IE
  3639  				} else {
  3640  					rt = objabi.R_RISCV_TLS_LE
  3641  				}
  3642  			}
  3643  
  3644  			cursym.AddRel(ctxt, obj.Reloc{
  3645  				Type: rt,
  3646  				Off:  int32(p.Pc),
  3647  				Siz:  8,
  3648  				Sym:  addr.Sym,
  3649  				Add:  addr.Offset,
  3650  			})
  3651  
  3652  		case obj.APCALIGN:
  3653  			alignedValue := p.From.Offset
  3654  			v := pcAlignPadLength(p.Pc, alignedValue)
  3655  			offset := p.Pc
  3656  			for ; v >= 4; v -= 4 {
  3657  				// NOP
  3658  				cursym.WriteBytes(ctxt, offset, []byte{0x13, 0, 0, 0})
  3659  				offset += 4
  3660  			}
  3661  			continue
  3662  		}
  3663  
  3664  		offset := p.Pc
  3665  		for _, ins := range instructionsForProg(p) {
  3666  			if ic, err := ins.encode(); err == nil {
  3667  				cursym.WriteInt(ctxt, offset, ins.length(), int64(ic))
  3668  				offset += int64(ins.length())
  3669  			}
  3670  			if ins.usesRegTmp() {
  3671  				p.Mark |= USES_REG_TMP
  3672  			}
  3673  		}
  3674  	}
  3675  
  3676  	obj.MarkUnsafePoints(ctxt, cursym.Func().Text, newprog, isUnsafePoint, nil)
  3677  }
  3678  
  3679  func isUnsafePoint(p *obj.Prog) bool {
  3680  	return p.Mark&USES_REG_TMP == USES_REG_TMP || p.From.Reg == REG_TMP || p.To.Reg == REG_TMP || p.Reg == REG_TMP
  3681  }
  3682  
  3683  func ParseSuffix(prog *obj.Prog, cond string) (err error) {
  3684  	switch prog.As {
  3685  	case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
  3686  		prog.Scond, err = rmSuffixEncode(strings.TrimPrefix(cond, "."))
  3687  	}
  3688  	return
  3689  }
  3690  
  3691  var LinkRISCV64 = obj.LinkArch{
  3692  	Arch:           sys.ArchRISCV64,
  3693  	Init:           buildop,
  3694  	Preprocess:     preprocess,
  3695  	Assemble:       assemble,
  3696  	Progedit:       progedit,
  3697  	UnaryDst:       unaryDst,
  3698  	DWARFRegisters: RISCV64DWARFRegisters,
  3699  }
  3700  

View as plain text