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 validateRFV(ctxt *obj.Link, ins *instruction) {
  1319  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1320  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1321  	wantFloatReg(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 validateRIF(ctxt *obj.Link, ins *instruction) {
  1333  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1334  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1335  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1336  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1337  }
  1338  
  1339  func validateRIV(ctxt *obj.Link, ins *instruction) {
  1340  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1341  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1342  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1343  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1344  }
  1345  
  1346  func validateRVF(ctxt *obj.Link, ins *instruction) {
  1347  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1348  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1349  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1350  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1351  }
  1352  
  1353  func validateRVFV(ctxt *obj.Link, ins *instruction) {
  1354  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1355  	wantFloatReg(ctxt, ins, "rs1", ins.rs1)
  1356  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1357  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1358  }
  1359  
  1360  func validateRVI(ctxt *obj.Link, ins *instruction) {
  1361  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1362  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1363  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1364  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1365  }
  1366  
  1367  func validateRVIV(ctxt *obj.Link, ins *instruction) {
  1368  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1369  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1370  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1371  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1372  }
  1373  
  1374  func validateRVV(ctxt *obj.Link, ins *instruction) {
  1375  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1376  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1377  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1378  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1379  }
  1380  
  1381  func validateRVVi(ctxt *obj.Link, ins *instruction) {
  1382  	wantImmI(ctxt, ins, ins.imm, 5)
  1383  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1384  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1385  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1386  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1387  }
  1388  
  1389  func validateRVVu(ctxt *obj.Link, ins *instruction) {
  1390  	wantImmU(ctxt, ins, ins.imm, 5)
  1391  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1392  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1393  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1394  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1395  }
  1396  
  1397  func validateRVVV(ctxt *obj.Link, ins *instruction) {
  1398  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1399  	wantVectorReg(ctxt, ins, "vs1", ins.rs1)
  1400  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1401  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1402  }
  1403  
  1404  func validateIII(ctxt *obj.Link, ins *instruction) {
  1405  	wantImmI(ctxt, ins, ins.imm, 12)
  1406  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1407  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1408  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1409  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1410  }
  1411  
  1412  func validateIF(ctxt *obj.Link, ins *instruction) {
  1413  	wantImmI(ctxt, ins, ins.imm, 12)
  1414  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1415  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1416  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1417  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1418  }
  1419  
  1420  func validateIV(ctxt *obj.Link, ins *instruction) {
  1421  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1422  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1423  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1424  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1425  }
  1426  
  1427  func validateIIIV(ctxt *obj.Link, ins *instruction) {
  1428  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1429  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1430  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1431  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1432  }
  1433  
  1434  func validateIVIV(ctxt *obj.Link, ins *instruction) {
  1435  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1436  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1437  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1438  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1439  }
  1440  
  1441  func validateSI(ctxt *obj.Link, ins *instruction) {
  1442  	wantImmI(ctxt, ins, ins.imm, 12)
  1443  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1444  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1445  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1446  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1447  }
  1448  
  1449  func validateSF(ctxt *obj.Link, ins *instruction) {
  1450  	wantImmI(ctxt, ins, ins.imm, 12)
  1451  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1452  	wantFloatReg(ctxt, ins, "rs1", ins.rs1)
  1453  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1454  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1455  }
  1456  
  1457  func validateSV(ctxt *obj.Link, ins *instruction) {
  1458  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1459  	wantVectorReg(ctxt, ins, "vs1", ins.rs1)
  1460  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1461  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1462  }
  1463  
  1464  func validateSVII(ctxt *obj.Link, ins *instruction) {
  1465  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1466  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1467  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1468  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1469  }
  1470  
  1471  func validateSVIV(ctxt *obj.Link, ins *instruction) {
  1472  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1473  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1474  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1475  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1476  }
  1477  
  1478  func validateB(ctxt *obj.Link, ins *instruction) {
  1479  	// Offsets are multiples of two, so accept 13 bit immediates for the
  1480  	// 12 bit slot. We implicitly drop the least significant bit in encodeB.
  1481  	wantEvenOffset(ctxt, ins, ins.imm)
  1482  	wantImmI(ctxt, ins, ins.imm, 13)
  1483  	wantNoneReg(ctxt, ins, "rd", ins.rd)
  1484  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1485  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1486  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1487  }
  1488  
  1489  func validateU(ctxt *obj.Link, ins *instruction) {
  1490  	wantImmI(ctxt, ins, ins.imm, 20)
  1491  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1492  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1493  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1494  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1495  }
  1496  
  1497  func validateJ(ctxt *obj.Link, ins *instruction) {
  1498  	// Offsets are multiples of two, so accept 21 bit immediates for the
  1499  	// 20 bit slot. We implicitly drop the least significant bit in encodeJ.
  1500  	wantEvenOffset(ctxt, ins, ins.imm)
  1501  	wantImmI(ctxt, ins, ins.imm, 21)
  1502  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1503  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1504  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1505  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1506  }
  1507  
  1508  func validateVsetvli(ctxt *obj.Link, ins *instruction) {
  1509  	wantImmU(ctxt, ins, ins.imm, 11)
  1510  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1511  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1512  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1513  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1514  }
  1515  
  1516  func validateVsetivli(ctxt *obj.Link, ins *instruction) {
  1517  	wantImmU(ctxt, ins, ins.imm, 10)
  1518  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1519  	wantImmU(ctxt, ins, int64(ins.rs1), 5)
  1520  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1521  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1522  }
  1523  
  1524  func validateVsetvl(ctxt *obj.Link, ins *instruction) {
  1525  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1526  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1527  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1528  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1529  }
  1530  
  1531  func validateRaw(ctxt *obj.Link, ins *instruction) {
  1532  	// Treat the raw value specially as a 32-bit unsigned integer.
  1533  	// Nobody wants to enter negative machine code.
  1534  	if ins.imm < 0 || 1<<32 <= ins.imm {
  1535  		ctxt.Diag("%v: immediate %d in raw position cannot be larger than 32 bits", ins.as, ins.imm)
  1536  	}
  1537  }
  1538  
  1539  // extractBitAndShift extracts the specified bit from the given immediate,
  1540  // before shifting it to the requested position and returning it.
  1541  func extractBitAndShift(imm uint32, bit, pos int) uint32 {
  1542  	return ((imm >> bit) & 1) << pos
  1543  }
  1544  
  1545  // encodeR encodes an R-type RISC-V instruction.
  1546  func encodeR(as obj.As, rs1, rs2, rd, funct3, funct7 uint32) uint32 {
  1547  	enc := encode(as)
  1548  	if enc == nil {
  1549  		panic("encodeR: could not encode instruction")
  1550  	}
  1551  	if enc.rs1 != 0 && rs1 != 0 {
  1552  		panic("encodeR: instruction uses rs1, but rs1 is nonzero")
  1553  	}
  1554  	if enc.rs2 != 0 && rs2 != 0 {
  1555  		panic("encodeR: instruction uses rs2, but rs2 is nonzero")
  1556  	}
  1557  	funct3 |= enc.funct3
  1558  	funct7 |= enc.funct7
  1559  	rs1 |= enc.rs1
  1560  	rs2 |= enc.rs2
  1561  	return funct7<<25 | rs2<<20 | rs1<<15 | funct3<<12 | rd<<7 | enc.opcode
  1562  }
  1563  
  1564  // encodeR4 encodes an R4-type RISC-V instruction.
  1565  func encodeR4(as obj.As, rs1, rs2, rs3, rd, funct3, funct2 uint32) uint32 {
  1566  	enc := encode(as)
  1567  	if enc == nil {
  1568  		panic("encodeR4: could not encode instruction")
  1569  	}
  1570  	if enc.rs2 != 0 {
  1571  		panic("encodeR4: instruction uses rs2")
  1572  	}
  1573  	funct2 |= enc.funct7
  1574  	if funct2&^3 != 0 {
  1575  		panic("encodeR4: funct2 requires more than 2 bits")
  1576  	}
  1577  	return rs3<<27 | funct2<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | funct3<<12 | rd<<7 | enc.opcode
  1578  }
  1579  
  1580  func encodeRII(ins *instruction) uint32 {
  1581  	return encodeR(ins.as, regI(ins.rs1), 0, regI(ins.rd), ins.funct3, ins.funct7)
  1582  }
  1583  
  1584  func encodeRIII(ins *instruction) uint32 {
  1585  	return encodeR(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
  1586  }
  1587  
  1588  func encodeRFFF(ins *instruction) uint32 {
  1589  	return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rd), ins.funct3, ins.funct7)
  1590  }
  1591  
  1592  func encodeRFFFF(ins *instruction) uint32 {
  1593  	return encodeR4(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rs3), regF(ins.rd), ins.funct3, ins.funct7)
  1594  }
  1595  
  1596  func encodeRFFI(ins *instruction) uint32 {
  1597  	return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
  1598  }
  1599  
  1600  func encodeRFI(ins *instruction) uint32 {
  1601  	return encodeR(ins.as, regF(ins.rs2), 0, regI(ins.rd), ins.funct3, ins.funct7)
  1602  }
  1603  
  1604  func encodeRFF(ins *instruction) uint32 {
  1605  	return encodeR(ins.as, regF(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7)
  1606  }
  1607  
  1608  func encodeRFV(ins *instruction) uint32 {
  1609  	return encodeR(ins.as, regF(ins.rs2), 0, regV(ins.rd), ins.funct3, ins.funct7)
  1610  }
  1611  
  1612  func encodeRIF(ins *instruction) uint32 {
  1613  	return encodeR(ins.as, regI(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7)
  1614  }
  1615  
  1616  func encodeRIV(ins *instruction) uint32 {
  1617  	return encodeR(ins.as, regI(ins.rs2), 0, regV(ins.rd), ins.funct3, ins.funct7)
  1618  }
  1619  
  1620  func encodeRVF(ins *instruction) uint32 {
  1621  	return encodeR(ins.as, 0, regV(ins.rs2), regF(ins.rd), ins.funct3, ins.funct7)
  1622  }
  1623  
  1624  func encodeRVFV(ins *instruction) uint32 {
  1625  	return encodeR(ins.as, regF(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
  1626  }
  1627  
  1628  func encodeRVI(ins *instruction) uint32 {
  1629  	return encodeR(ins.as, 0, regV(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
  1630  }
  1631  
  1632  func encodeRVIV(ins *instruction) uint32 {
  1633  	return encodeR(ins.as, regI(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
  1634  }
  1635  
  1636  func encodeRVV(ins *instruction) uint32 {
  1637  	return encodeR(ins.as, 0, regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
  1638  }
  1639  
  1640  func encodeRVVi(ins *instruction) uint32 {
  1641  	return encodeR(ins.as, immI(ins.as, ins.imm, 5), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
  1642  }
  1643  
  1644  func encodeRVVu(ins *instruction) uint32 {
  1645  	return encodeR(ins.as, immU(ins.as, ins.imm, 5), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
  1646  }
  1647  
  1648  func encodeRVVV(ins *instruction) uint32 {
  1649  	return encodeR(ins.as, regV(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
  1650  }
  1651  
  1652  // encodeI encodes an I-type RISC-V instruction.
  1653  func encodeI(as obj.As, rs1, rd, imm, funct7 uint32) uint32 {
  1654  	enc := encode(as)
  1655  	if enc == nil {
  1656  		panic("encodeI: could not encode instruction")
  1657  	}
  1658  	imm |= uint32(enc.csr)
  1659  	return funct7<<25 | imm<<20 | rs1<<15 | enc.funct3<<12 | rd<<7 | enc.opcode
  1660  }
  1661  
  1662  func encodeIII(ins *instruction) uint32 {
  1663  	return encodeI(ins.as, regI(ins.rs1), regI(ins.rd), uint32(ins.imm), 0)
  1664  }
  1665  
  1666  func encodeIF(ins *instruction) uint32 {
  1667  	return encodeI(ins.as, regI(ins.rs1), regF(ins.rd), uint32(ins.imm), 0)
  1668  }
  1669  
  1670  func encodeIV(ins *instruction) uint32 {
  1671  	return encodeI(ins.as, regI(ins.rs1), regV(ins.rd), uint32(ins.imm), ins.funct7)
  1672  }
  1673  
  1674  func encodeIIIV(ins *instruction) uint32 {
  1675  	return encodeI(ins.as, regI(ins.rs1), regV(ins.rd), regI(ins.rs2), ins.funct7)
  1676  }
  1677  
  1678  func encodeIVIV(ins *instruction) uint32 {
  1679  	return encodeI(ins.as, regI(ins.rs1), regV(ins.rd), regV(ins.rs2), ins.funct7)
  1680  }
  1681  
  1682  // encodeS encodes an S-type RISC-V instruction.
  1683  func encodeS(as obj.As, rs1, rs2, imm, funct7 uint32) uint32 {
  1684  	enc := encode(as)
  1685  	if enc == nil {
  1686  		panic("encodeS: could not encode instruction")
  1687  	}
  1688  	if enc.rs2 != 0 && rs2 != 0 {
  1689  		panic("encodeS: instruction uses rs2, but rs2 was nonzero")
  1690  	}
  1691  	rs2 |= enc.rs2
  1692  	imm |= uint32(enc.csr) &^ 0x1f
  1693  	return funct7<<25 | (imm>>5)<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | (imm&0x1f)<<7 | enc.opcode
  1694  }
  1695  
  1696  func encodeSI(ins *instruction) uint32 {
  1697  	return encodeS(ins.as, regI(ins.rd), regI(ins.rs1), uint32(ins.imm), 0)
  1698  }
  1699  
  1700  func encodeSF(ins *instruction) uint32 {
  1701  	return encodeS(ins.as, regI(ins.rd), regF(ins.rs1), uint32(ins.imm), 0)
  1702  }
  1703  
  1704  func encodeSV(ins *instruction) uint32 {
  1705  	return encodeS(ins.as, regI(ins.rd), 0, regV(ins.rs1), ins.funct7)
  1706  }
  1707  
  1708  func encodeSVII(ins *instruction) uint32 {
  1709  	return encodeS(ins.as, regI(ins.rs1), regI(ins.rs2), regV(ins.rd), ins.funct7)
  1710  }
  1711  
  1712  func encodeSVIV(ins *instruction) uint32 {
  1713  	return encodeS(ins.as, regI(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct7)
  1714  }
  1715  
  1716  // encodeBImmediate encodes an immediate for a B-type RISC-V instruction.
  1717  func encodeBImmediate(imm uint32) uint32 {
  1718  	return (imm>>12)<<31 | ((imm>>5)&0x3f)<<25 | ((imm>>1)&0xf)<<8 | ((imm>>11)&0x1)<<7
  1719  }
  1720  
  1721  // encodeB encodes a B-type RISC-V instruction.
  1722  func encodeB(ins *instruction) uint32 {
  1723  	imm := immI(ins.as, ins.imm, 13)
  1724  	rs2 := regI(ins.rs1)
  1725  	rs1 := regI(ins.rs2)
  1726  	enc := encode(ins.as)
  1727  	if enc == nil {
  1728  		panic("encodeB: could not encode instruction")
  1729  	}
  1730  	return encodeBImmediate(imm) | rs2<<20 | rs1<<15 | enc.funct3<<12 | enc.opcode
  1731  }
  1732  
  1733  // encodeU encodes a U-type RISC-V instruction.
  1734  func encodeU(ins *instruction) uint32 {
  1735  	// The immediates for encodeU are the upper 20 bits of a 32 bit value.
  1736  	// Rather than have the user/compiler generate a 32 bit constant, the
  1737  	// bottommost bits of which must all be zero, instead accept just the
  1738  	// top bits.
  1739  	imm := immI(ins.as, ins.imm, 20)
  1740  	rd := regI(ins.rd)
  1741  	enc := encode(ins.as)
  1742  	if enc == nil {
  1743  		panic("encodeU: could not encode instruction")
  1744  	}
  1745  	return imm<<12 | rd<<7 | enc.opcode
  1746  }
  1747  
  1748  // encodeJImmediate encodes an immediate for a J-type RISC-V instruction.
  1749  func encodeJImmediate(imm uint32) uint32 {
  1750  	return (imm>>20)<<31 | ((imm>>1)&0x3ff)<<21 | ((imm>>11)&0x1)<<20 | ((imm>>12)&0xff)<<12
  1751  }
  1752  
  1753  // encodeJ encodes a J-type RISC-V instruction.
  1754  func encodeJ(ins *instruction) uint32 {
  1755  	imm := immI(ins.as, ins.imm, 21)
  1756  	rd := regI(ins.rd)
  1757  	enc := encode(ins.as)
  1758  	if enc == nil {
  1759  		panic("encodeJ: could not encode instruction")
  1760  	}
  1761  	return encodeJImmediate(imm) | rd<<7 | enc.opcode
  1762  }
  1763  
  1764  // encodeCBImmediate encodes an immediate for a CB-type RISC-V instruction.
  1765  func encodeCBImmediate(imm uint32) uint32 {
  1766  	// Bit order - [8|4:3|7:6|2:1|5]
  1767  	bits := extractBitAndShift(imm, 8, 7)
  1768  	bits |= extractBitAndShift(imm, 4, 6)
  1769  	bits |= extractBitAndShift(imm, 3, 5)
  1770  	bits |= extractBitAndShift(imm, 7, 4)
  1771  	bits |= extractBitAndShift(imm, 6, 3)
  1772  	bits |= extractBitAndShift(imm, 2, 2)
  1773  	bits |= extractBitAndShift(imm, 1, 1)
  1774  	bits |= extractBitAndShift(imm, 5, 0)
  1775  	return (bits>>5)<<10 | (bits&0x1f)<<2
  1776  }
  1777  
  1778  // encodeCJImmediate encodes an immediate for a CJ-type RISC-V instruction.
  1779  func encodeCJImmediate(imm uint32) uint32 {
  1780  	// Bit order - [11|4|9:8|10|6|7|3:1|5]
  1781  	bits := extractBitAndShift(imm, 11, 10)
  1782  	bits |= extractBitAndShift(imm, 4, 9)
  1783  	bits |= extractBitAndShift(imm, 9, 8)
  1784  	bits |= extractBitAndShift(imm, 8, 7)
  1785  	bits |= extractBitAndShift(imm, 10, 6)
  1786  	bits |= extractBitAndShift(imm, 6, 5)
  1787  	bits |= extractBitAndShift(imm, 7, 4)
  1788  	bits |= extractBitAndShift(imm, 3, 3)
  1789  	bits |= extractBitAndShift(imm, 2, 2)
  1790  	bits |= extractBitAndShift(imm, 1, 1)
  1791  	bits |= extractBitAndShift(imm, 5, 0)
  1792  	return bits << 2
  1793  }
  1794  
  1795  func encodeVset(as obj.As, rs1, rs2, rd uint32) uint32 {
  1796  	enc := encode(as)
  1797  	if enc == nil {
  1798  		panic("encodeVset: could not encode instruction")
  1799  	}
  1800  	return enc.funct7<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | rd<<7 | enc.opcode
  1801  }
  1802  
  1803  func encodeVsetvli(ins *instruction) uint32 {
  1804  	vtype := immU(ins.as, ins.imm, 11)
  1805  	return encodeVset(ins.as, regI(ins.rs1), vtype, regI(ins.rd))
  1806  }
  1807  
  1808  func encodeVsetivli(ins *instruction) uint32 {
  1809  	vtype := immU(ins.as, ins.imm, 10)
  1810  	avl := immU(ins.as, int64(ins.rs1), 5)
  1811  	return encodeVset(ins.as, avl, vtype, regI(ins.rd))
  1812  }
  1813  
  1814  func encodeVsetvl(ins *instruction) uint32 {
  1815  	return encodeVset(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd))
  1816  }
  1817  
  1818  func encodeRawIns(ins *instruction) uint32 {
  1819  	// Treat the raw value specially as a 32-bit unsigned integer.
  1820  	// Nobody wants to enter negative machine code.
  1821  	if ins.imm < 0 || 1<<32 <= ins.imm {
  1822  		panic(fmt.Sprintf("immediate %d cannot fit in 32 bits", ins.imm))
  1823  	}
  1824  	return uint32(ins.imm)
  1825  }
  1826  
  1827  func EncodeBImmediate(imm int64) (int64, error) {
  1828  	if err := immIFits(imm, 13); err != nil {
  1829  		return 0, err
  1830  	}
  1831  	if err := immEven(imm); err != nil {
  1832  		return 0, err
  1833  	}
  1834  	return int64(encodeBImmediate(uint32(imm))), nil
  1835  }
  1836  
  1837  func EncodeCBImmediate(imm int64) (int64, error) {
  1838  	if err := immIFits(imm, 9); err != nil {
  1839  		return 0, err
  1840  	}
  1841  	if err := immEven(imm); err != nil {
  1842  		return 0, err
  1843  	}
  1844  	return int64(encodeCBImmediate(uint32(imm))), nil
  1845  }
  1846  
  1847  func EncodeCJImmediate(imm int64) (int64, error) {
  1848  	if err := immIFits(imm, 12); err != nil {
  1849  		return 0, err
  1850  	}
  1851  	if err := immEven(imm); err != nil {
  1852  		return 0, err
  1853  	}
  1854  	return int64(encodeCJImmediate(uint32(imm))), nil
  1855  }
  1856  
  1857  func EncodeIImmediate(imm int64) (int64, error) {
  1858  	if err := immIFits(imm, 12); err != nil {
  1859  		return 0, err
  1860  	}
  1861  	return imm << 20, nil
  1862  }
  1863  
  1864  func EncodeJImmediate(imm int64) (int64, error) {
  1865  	if err := immIFits(imm, 21); err != nil {
  1866  		return 0, err
  1867  	}
  1868  	if err := immEven(imm); err != nil {
  1869  		return 0, err
  1870  	}
  1871  	return int64(encodeJImmediate(uint32(imm))), nil
  1872  }
  1873  
  1874  func EncodeSImmediate(imm int64) (int64, error) {
  1875  	if err := immIFits(imm, 12); err != nil {
  1876  		return 0, err
  1877  	}
  1878  	return ((imm >> 5) << 25) | ((imm & 0x1f) << 7), nil
  1879  }
  1880  
  1881  func EncodeUImmediate(imm int64) (int64, error) {
  1882  	if err := immIFits(imm, 20); err != nil {
  1883  		return 0, err
  1884  	}
  1885  	return imm << 12, nil
  1886  }
  1887  
  1888  func EncodeVectorType(vsew, vlmul, vtail, vmask int64) (int64, error) {
  1889  	vsewSO := SpecialOperand(vsew)
  1890  	if vsewSO < SPOP_E8 || vsewSO > SPOP_E64 {
  1891  		return -1, fmt.Errorf("invalid vector selected element width %q", vsewSO)
  1892  	}
  1893  	vlmulSO := SpecialOperand(vlmul)
  1894  	if vlmulSO < SPOP_M1 || vlmulSO > SPOP_MF8 {
  1895  		return -1, fmt.Errorf("invalid vector register group multiplier %q", vlmulSO)
  1896  	}
  1897  	vtailSO := SpecialOperand(vtail)
  1898  	if vtailSO != SPOP_TA && vtailSO != SPOP_TU {
  1899  		return -1, fmt.Errorf("invalid vector tail policy %q", vtailSO)
  1900  	}
  1901  	vmaskSO := SpecialOperand(vmask)
  1902  	if vmaskSO != SPOP_MA && vmaskSO != SPOP_MU {
  1903  		return -1, fmt.Errorf("invalid vector mask policy %q", vmaskSO)
  1904  	}
  1905  	vtype := vmaskSO.encode()<<7 | vtailSO.encode()<<6 | vsewSO.encode()<<3 | vlmulSO.encode()
  1906  	return int64(vtype), nil
  1907  }
  1908  
  1909  type encoding struct {
  1910  	encode   func(*instruction) uint32     // encode returns the machine code for an instruction
  1911  	validate func(*obj.Link, *instruction) // validate validates an instruction
  1912  	length   int                           // length of encoded instruction; 0 for pseudo-ops, 4 otherwise
  1913  }
  1914  
  1915  var (
  1916  	// Encodings have the following naming convention:
  1917  	//
  1918  	//  1. the instruction encoding (R/I/S/B/U/J), in lowercase
  1919  	//  2. zero or more register operand identifiers (I = integer
  1920  	//     register, F = float register, V = vector register), in uppercase
  1921  	//  3. the word "Encoding"
  1922  	//
  1923  	// For example, rIIIEncoding indicates an R-type instruction with two
  1924  	// integer register inputs and an integer register output; sFEncoding
  1925  	// indicates an S-type instruction with rs2 being a float register.
  1926  
  1927  	rIIIEncoding  = encoding{encode: encodeRIII, validate: validateRIII, length: 4}
  1928  	rIIEncoding   = encoding{encode: encodeRII, validate: validateRII, length: 4}
  1929  	rFFFEncoding  = encoding{encode: encodeRFFF, validate: validateRFFF, length: 4}
  1930  	rFFFFEncoding = encoding{encode: encodeRFFFF, validate: validateRFFFF, length: 4}
  1931  	rFFIEncoding  = encoding{encode: encodeRFFI, validate: validateRFFI, length: 4}
  1932  	rFIEncoding   = encoding{encode: encodeRFI, validate: validateRFI, length: 4}
  1933  	rFVEncoding   = encoding{encode: encodeRFV, validate: validateRFV, length: 4}
  1934  	rIFEncoding   = encoding{encode: encodeRIF, validate: validateRIF, length: 4}
  1935  	rIVEncoding   = encoding{encode: encodeRIV, validate: validateRIV, length: 4}
  1936  	rFFEncoding   = encoding{encode: encodeRFF, validate: validateRFF, length: 4}
  1937  	rVFEncoding   = encoding{encode: encodeRVF, validate: validateRVF, length: 4}
  1938  	rVFVEncoding  = encoding{encode: encodeRVFV, validate: validateRVFV, length: 4}
  1939  	rVIEncoding   = encoding{encode: encodeRVI, validate: validateRVI, length: 4}
  1940  	rVIVEncoding  = encoding{encode: encodeRVIV, validate: validateRVIV, length: 4}
  1941  	rVVEncoding   = encoding{encode: encodeRVV, validate: validateRVV, length: 4}
  1942  	rVViEncoding  = encoding{encode: encodeRVVi, validate: validateRVVi, length: 4}
  1943  	rVVuEncoding  = encoding{encode: encodeRVVu, validate: validateRVVu, length: 4}
  1944  	rVVVEncoding  = encoding{encode: encodeRVVV, validate: validateRVVV, length: 4}
  1945  
  1946  	iIIEncoding  = encoding{encode: encodeIII, validate: validateIII, length: 4}
  1947  	iFEncoding   = encoding{encode: encodeIF, validate: validateIF, length: 4}
  1948  	iVEncoding   = encoding{encode: encodeIV, validate: validateIV, length: 4}
  1949  	iIIVEncoding = encoding{encode: encodeIIIV, validate: validateIIIV, length: 4}
  1950  	iVIVEncoding = encoding{encode: encodeIVIV, validate: validateIVIV, length: 4}
  1951  
  1952  	sIEncoding   = encoding{encode: encodeSI, validate: validateSI, length: 4}
  1953  	sFEncoding   = encoding{encode: encodeSF, validate: validateSF, length: 4}
  1954  	sVEncoding   = encoding{encode: encodeSV, validate: validateSV, length: 4}
  1955  	sVIIEncoding = encoding{encode: encodeSVII, validate: validateSVII, length: 4}
  1956  	sVIVEncoding = encoding{encode: encodeSVIV, validate: validateSVIV, length: 4}
  1957  
  1958  	bEncoding = encoding{encode: encodeB, validate: validateB, length: 4}
  1959  	uEncoding = encoding{encode: encodeU, validate: validateU, length: 4}
  1960  	jEncoding = encoding{encode: encodeJ, validate: validateJ, length: 4}
  1961  
  1962  	// Encodings for vector configuration setting instruction.
  1963  	vsetvliEncoding  = encoding{encode: encodeVsetvli, validate: validateVsetvli, length: 4}
  1964  	vsetivliEncoding = encoding{encode: encodeVsetivli, validate: validateVsetivli, length: 4}
  1965  	vsetvlEncoding   = encoding{encode: encodeVsetvl, validate: validateVsetvl, length: 4}
  1966  
  1967  	// rawEncoding encodes a raw instruction byte sequence.
  1968  	rawEncoding = encoding{encode: encodeRawIns, validate: validateRaw, length: 4}
  1969  
  1970  	// pseudoOpEncoding panics if encoding is attempted, but does no validation.
  1971  	pseudoOpEncoding = encoding{encode: nil, validate: func(*obj.Link, *instruction) {}, length: 0}
  1972  
  1973  	// badEncoding is used when an invalid op is encountered.
  1974  	// An error has already been generated, so let anything else through.
  1975  	badEncoding = encoding{encode: func(*instruction) uint32 { return 0 }, validate: func(*obj.Link, *instruction) {}, length: 0}
  1976  )
  1977  
  1978  // instructionData specifies details relating to a RISC-V instruction.
  1979  type instructionData struct {
  1980  	enc     encoding
  1981  	immForm obj.As // immediate form of this instruction
  1982  	ternary bool
  1983  }
  1984  
  1985  // instructions contains details of RISC-V instructions, including
  1986  // their encoding type. Entries are masked with obj.AMask to keep
  1987  // indices small.
  1988  var instructions = [ALAST & obj.AMask]instructionData{
  1989  	//
  1990  	// Unprivileged ISA
  1991  	//
  1992  
  1993  	// 2.4: Integer Computational Instructions
  1994  	AADDI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  1995  	ASLTI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  1996  	ASLTIU & obj.AMask: {enc: iIIEncoding, ternary: true},
  1997  	AANDI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  1998  	AORI & obj.AMask:   {enc: iIIEncoding, ternary: true},
  1999  	AXORI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  2000  	ASLLI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  2001  	ASRLI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  2002  	ASRAI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  2003  	ALUI & obj.AMask:   {enc: uEncoding},
  2004  	AAUIPC & obj.AMask: {enc: uEncoding},
  2005  	AADD & obj.AMask:   {enc: rIIIEncoding, immForm: AADDI, ternary: true},
  2006  	ASLT & obj.AMask:   {enc: rIIIEncoding, immForm: ASLTI, ternary: true},
  2007  	ASLTU & obj.AMask:  {enc: rIIIEncoding, immForm: ASLTIU, ternary: true},
  2008  	AAND & obj.AMask:   {enc: rIIIEncoding, immForm: AANDI, ternary: true},
  2009  	AOR & obj.AMask:    {enc: rIIIEncoding, immForm: AORI, ternary: true},
  2010  	AXOR & obj.AMask:   {enc: rIIIEncoding, immForm: AXORI, ternary: true},
  2011  	ASLL & obj.AMask:   {enc: rIIIEncoding, immForm: ASLLI, ternary: true},
  2012  	ASRL & obj.AMask:   {enc: rIIIEncoding, immForm: ASRLI, ternary: true},
  2013  	ASUB & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2014  	ASRA & obj.AMask:   {enc: rIIIEncoding, immForm: ASRAI, ternary: true},
  2015  
  2016  	// 2.5: Control Transfer Instructions
  2017  	AJAL & obj.AMask:  {enc: jEncoding},
  2018  	AJALR & obj.AMask: {enc: iIIEncoding},
  2019  	ABEQ & obj.AMask:  {enc: bEncoding},
  2020  	ABNE & obj.AMask:  {enc: bEncoding},
  2021  	ABLT & obj.AMask:  {enc: bEncoding},
  2022  	ABLTU & obj.AMask: {enc: bEncoding},
  2023  	ABGE & obj.AMask:  {enc: bEncoding},
  2024  	ABGEU & obj.AMask: {enc: bEncoding},
  2025  
  2026  	// 2.6: Load and Store Instructions
  2027  	ALW & obj.AMask:  {enc: iIIEncoding},
  2028  	ALWU & obj.AMask: {enc: iIIEncoding},
  2029  	ALH & obj.AMask:  {enc: iIIEncoding},
  2030  	ALHU & obj.AMask: {enc: iIIEncoding},
  2031  	ALB & obj.AMask:  {enc: iIIEncoding},
  2032  	ALBU & obj.AMask: {enc: iIIEncoding},
  2033  	ASW & obj.AMask:  {enc: sIEncoding},
  2034  	ASH & obj.AMask:  {enc: sIEncoding},
  2035  	ASB & obj.AMask:  {enc: sIEncoding},
  2036  
  2037  	// 2.7: Memory Ordering
  2038  	AFENCE & obj.AMask: {enc: iIIEncoding},
  2039  
  2040  	// 4.2: Integer Computational Instructions (RV64I)
  2041  	AADDIW & obj.AMask: {enc: iIIEncoding, ternary: true},
  2042  	ASLLIW & obj.AMask: {enc: iIIEncoding, ternary: true},
  2043  	ASRLIW & obj.AMask: {enc: iIIEncoding, ternary: true},
  2044  	ASRAIW & obj.AMask: {enc: iIIEncoding, ternary: true},
  2045  	AADDW & obj.AMask:  {enc: rIIIEncoding, immForm: AADDIW, ternary: true},
  2046  	ASLLW & obj.AMask:  {enc: rIIIEncoding, immForm: ASLLIW, ternary: true},
  2047  	ASRLW & obj.AMask:  {enc: rIIIEncoding, immForm: ASRLIW, ternary: true},
  2048  	ASUBW & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2049  	ASRAW & obj.AMask:  {enc: rIIIEncoding, immForm: ASRAIW, ternary: true},
  2050  
  2051  	// 4.3: Load and Store Instructions (RV64I)
  2052  	ALD & obj.AMask: {enc: iIIEncoding},
  2053  	ASD & obj.AMask: {enc: sIEncoding},
  2054  
  2055  	// 7.1: CSR Instructions
  2056  	ACSRRS & obj.AMask: {enc: iIIEncoding},
  2057  
  2058  	// 13.1: Multiplication Operations
  2059  	AMUL & obj.AMask:    {enc: rIIIEncoding, ternary: true},
  2060  	AMULH & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2061  	AMULHU & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2062  	AMULHSU & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2063  	AMULW & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2064  	ADIV & obj.AMask:    {enc: rIIIEncoding, ternary: true},
  2065  	ADIVU & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2066  	AREM & obj.AMask:    {enc: rIIIEncoding, ternary: true},
  2067  	AREMU & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2068  	ADIVW & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2069  	ADIVUW & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2070  	AREMW & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2071  	AREMUW & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2072  
  2073  	// 14.2: Load-Reserved/Store-Conditional Instructions (Zalrsc)
  2074  	ALRW & obj.AMask: {enc: rIIIEncoding},
  2075  	ALRD & obj.AMask: {enc: rIIIEncoding},
  2076  	ASCW & obj.AMask: {enc: rIIIEncoding},
  2077  	ASCD & obj.AMask: {enc: rIIIEncoding},
  2078  
  2079  	// 14.4: Atomic Memory Operations (Zaamo)
  2080  	AAMOSWAPW & obj.AMask: {enc: rIIIEncoding},
  2081  	AAMOSWAPD & obj.AMask: {enc: rIIIEncoding},
  2082  	AAMOADDW & obj.AMask:  {enc: rIIIEncoding},
  2083  	AAMOADDD & obj.AMask:  {enc: rIIIEncoding},
  2084  	AAMOANDW & obj.AMask:  {enc: rIIIEncoding},
  2085  	AAMOANDD & obj.AMask:  {enc: rIIIEncoding},
  2086  	AAMOORW & obj.AMask:   {enc: rIIIEncoding},
  2087  	AAMOORD & obj.AMask:   {enc: rIIIEncoding},
  2088  	AAMOXORW & obj.AMask:  {enc: rIIIEncoding},
  2089  	AAMOXORD & obj.AMask:  {enc: rIIIEncoding},
  2090  	AAMOMAXW & obj.AMask:  {enc: rIIIEncoding},
  2091  	AAMOMAXD & obj.AMask:  {enc: rIIIEncoding},
  2092  	AAMOMAXUW & obj.AMask: {enc: rIIIEncoding},
  2093  	AAMOMAXUD & obj.AMask: {enc: rIIIEncoding},
  2094  	AAMOMINW & obj.AMask:  {enc: rIIIEncoding},
  2095  	AAMOMIND & obj.AMask:  {enc: rIIIEncoding},
  2096  	AAMOMINUW & obj.AMask: {enc: rIIIEncoding},
  2097  	AAMOMINUD & obj.AMask: {enc: rIIIEncoding},
  2098  
  2099  	// 20.5: Single-Precision Load and Store Instructions
  2100  	AFLW & obj.AMask: {enc: iFEncoding},
  2101  	AFSW & obj.AMask: {enc: sFEncoding},
  2102  
  2103  	// 20.6: Single-Precision Floating-Point Computational Instructions
  2104  	AFADDS & obj.AMask:   {enc: rFFFEncoding},
  2105  	AFSUBS & obj.AMask:   {enc: rFFFEncoding},
  2106  	AFMULS & obj.AMask:   {enc: rFFFEncoding},
  2107  	AFDIVS & obj.AMask:   {enc: rFFFEncoding},
  2108  	AFMINS & obj.AMask:   {enc: rFFFEncoding},
  2109  	AFMAXS & obj.AMask:   {enc: rFFFEncoding},
  2110  	AFSQRTS & obj.AMask:  {enc: rFFFEncoding},
  2111  	AFMADDS & obj.AMask:  {enc: rFFFFEncoding},
  2112  	AFMSUBS & obj.AMask:  {enc: rFFFFEncoding},
  2113  	AFNMSUBS & obj.AMask: {enc: rFFFFEncoding},
  2114  	AFNMADDS & obj.AMask: {enc: rFFFFEncoding},
  2115  
  2116  	// 20.7: Single-Precision Floating-Point Conversion and Move Instructions
  2117  	AFCVTWS & obj.AMask:  {enc: rFIEncoding},
  2118  	AFCVTLS & obj.AMask:  {enc: rFIEncoding},
  2119  	AFCVTSW & obj.AMask:  {enc: rIFEncoding},
  2120  	AFCVTSL & obj.AMask:  {enc: rIFEncoding},
  2121  	AFCVTWUS & obj.AMask: {enc: rFIEncoding},
  2122  	AFCVTLUS & obj.AMask: {enc: rFIEncoding},
  2123  	AFCVTSWU & obj.AMask: {enc: rIFEncoding},
  2124  	AFCVTSLU & obj.AMask: {enc: rIFEncoding},
  2125  	AFSGNJS & obj.AMask:  {enc: rFFFEncoding},
  2126  	AFSGNJNS & obj.AMask: {enc: rFFFEncoding},
  2127  	AFSGNJXS & obj.AMask: {enc: rFFFEncoding},
  2128  	AFMVXW & obj.AMask:   {enc: rFIEncoding},
  2129  	AFMVWX & obj.AMask:   {enc: rIFEncoding},
  2130  
  2131  	// 20.8: Single-Precision Floating-Point Compare Instructions
  2132  	AFEQS & obj.AMask: {enc: rFFIEncoding},
  2133  	AFLTS & obj.AMask: {enc: rFFIEncoding},
  2134  	AFLES & obj.AMask: {enc: rFFIEncoding},
  2135  
  2136  	// 20.9: Single-Precision Floating-Point Classify Instruction
  2137  	AFCLASSS & obj.AMask: {enc: rFIEncoding},
  2138  
  2139  	// 12.3: Double-Precision Load and Store Instructions
  2140  	AFLD & obj.AMask: {enc: iFEncoding},
  2141  	AFSD & obj.AMask: {enc: sFEncoding},
  2142  
  2143  	// 21.4: Double-Precision Floating-Point Computational Instructions
  2144  	AFADDD & obj.AMask:   {enc: rFFFEncoding},
  2145  	AFSUBD & obj.AMask:   {enc: rFFFEncoding},
  2146  	AFMULD & obj.AMask:   {enc: rFFFEncoding},
  2147  	AFDIVD & obj.AMask:   {enc: rFFFEncoding},
  2148  	AFMIND & obj.AMask:   {enc: rFFFEncoding},
  2149  	AFMAXD & obj.AMask:   {enc: rFFFEncoding},
  2150  	AFSQRTD & obj.AMask:  {enc: rFFFEncoding},
  2151  	AFMADDD & obj.AMask:  {enc: rFFFFEncoding},
  2152  	AFMSUBD & obj.AMask:  {enc: rFFFFEncoding},
  2153  	AFNMSUBD & obj.AMask: {enc: rFFFFEncoding},
  2154  	AFNMADDD & obj.AMask: {enc: rFFFFEncoding},
  2155  
  2156  	// 21.5: Double-Precision Floating-Point Conversion and Move Instructions
  2157  	AFCVTWD & obj.AMask:  {enc: rFIEncoding},
  2158  	AFCVTLD & obj.AMask:  {enc: rFIEncoding},
  2159  	AFCVTDW & obj.AMask:  {enc: rIFEncoding},
  2160  	AFCVTDL & obj.AMask:  {enc: rIFEncoding},
  2161  	AFCVTWUD & obj.AMask: {enc: rFIEncoding},
  2162  	AFCVTLUD & obj.AMask: {enc: rFIEncoding},
  2163  	AFCVTDWU & obj.AMask: {enc: rIFEncoding},
  2164  	AFCVTDLU & obj.AMask: {enc: rIFEncoding},
  2165  	AFCVTSD & obj.AMask:  {enc: rFFEncoding},
  2166  	AFCVTDS & obj.AMask:  {enc: rFFEncoding},
  2167  	AFSGNJD & obj.AMask:  {enc: rFFFEncoding},
  2168  	AFSGNJND & obj.AMask: {enc: rFFFEncoding},
  2169  	AFSGNJXD & obj.AMask: {enc: rFFFEncoding},
  2170  	AFMVXD & obj.AMask:   {enc: rFIEncoding},
  2171  	AFMVDX & obj.AMask:   {enc: rIFEncoding},
  2172  
  2173  	// 21.6: Double-Precision Floating-Point Compare Instructions
  2174  	AFEQD & obj.AMask: {enc: rFFIEncoding},
  2175  	AFLTD & obj.AMask: {enc: rFFIEncoding},
  2176  	AFLED & obj.AMask: {enc: rFFIEncoding},
  2177  
  2178  	// 21.7: Double-Precision Floating-Point Classify Instruction
  2179  	AFCLASSD & obj.AMask: {enc: rFIEncoding},
  2180  
  2181  	//
  2182  	// "B" Extension for Bit Manipulation, Version 1.0.0
  2183  	//
  2184  
  2185  	// 28.4.1: Address Generation Instructions (Zba)
  2186  	AADDUW & obj.AMask:    {enc: rIIIEncoding, ternary: true},
  2187  	ASH1ADD & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2188  	ASH1ADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2189  	ASH2ADD & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2190  	ASH2ADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2191  	ASH3ADD & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2192  	ASH3ADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2193  	ASLLIUW & obj.AMask:   {enc: iIIEncoding, ternary: true},
  2194  
  2195  	// 28.4.2: Basic Bit Manipulation (Zbb)
  2196  	AANDN & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2197  	ACLZ & obj.AMask:   {enc: rIIEncoding},
  2198  	ACLZW & obj.AMask:  {enc: rIIEncoding},
  2199  	ACPOP & obj.AMask:  {enc: rIIEncoding},
  2200  	ACPOPW & obj.AMask: {enc: rIIEncoding},
  2201  	ACTZ & obj.AMask:   {enc: rIIEncoding},
  2202  	ACTZW & obj.AMask:  {enc: rIIEncoding},
  2203  	AMAX & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2204  	AMAXU & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2205  	AMIN & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2206  	AMINU & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2207  	AORN & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2208  	ASEXTB & obj.AMask: {enc: rIIEncoding},
  2209  	ASEXTH & obj.AMask: {enc: rIIEncoding},
  2210  	AXNOR & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2211  	AZEXTH & obj.AMask: {enc: rIIEncoding},
  2212  
  2213  	// 28.4.3: Bitwise Rotation (Zbb)
  2214  	AROL & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2215  	AROLW & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2216  	AROR & obj.AMask:   {enc: rIIIEncoding, immForm: ARORI, ternary: true},
  2217  	ARORI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  2218  	ARORIW & obj.AMask: {enc: iIIEncoding, ternary: true},
  2219  	ARORW & obj.AMask:  {enc: rIIIEncoding, immForm: ARORIW, ternary: true},
  2220  	AORCB & obj.AMask:  {enc: rIIEncoding},
  2221  	AREV8 & obj.AMask:  {enc: rIIEncoding},
  2222  
  2223  	// 28.4.4: Single-bit Instructions (Zbs)
  2224  	ABCLR & obj.AMask:  {enc: rIIIEncoding, immForm: ABCLRI, ternary: true},
  2225  	ABCLRI & obj.AMask: {enc: iIIEncoding, ternary: true},
  2226  	ABEXT & obj.AMask:  {enc: rIIIEncoding, immForm: ABEXTI, ternary: true},
  2227  	ABEXTI & obj.AMask: {enc: iIIEncoding, ternary: true},
  2228  	ABINV & obj.AMask:  {enc: rIIIEncoding, immForm: ABINVI, ternary: true},
  2229  	ABINVI & obj.AMask: {enc: iIIEncoding, ternary: true},
  2230  	ABSET & obj.AMask:  {enc: rIIIEncoding, immForm: ABSETI, ternary: true},
  2231  	ABSETI & obj.AMask: {enc: iIIEncoding, ternary: true},
  2232  
  2233  	//
  2234  	// "V" Standard Extension for Vector Operations, Version 1.0
  2235  	//
  2236  
  2237  	// 31.6: Vector Configuration-Setting Instructions
  2238  	AVSETVLI & obj.AMask:  {enc: vsetvliEncoding, immForm: AVSETIVLI},
  2239  	AVSETIVLI & obj.AMask: {enc: vsetivliEncoding},
  2240  	AVSETVL & obj.AMask:   {enc: vsetvlEncoding},
  2241  
  2242  	// 31.7.4: Vector Unit-Stride Instructions
  2243  	AVLE8V & obj.AMask:  {enc: iVEncoding},
  2244  	AVLE16V & obj.AMask: {enc: iVEncoding},
  2245  	AVLE32V & obj.AMask: {enc: iVEncoding},
  2246  	AVLE64V & obj.AMask: {enc: iVEncoding},
  2247  	AVSE8V & obj.AMask:  {enc: sVEncoding},
  2248  	AVSE16V & obj.AMask: {enc: sVEncoding},
  2249  	AVSE32V & obj.AMask: {enc: sVEncoding},
  2250  	AVSE64V & obj.AMask: {enc: sVEncoding},
  2251  	AVLMV & obj.AMask:   {enc: iVEncoding},
  2252  	AVSMV & obj.AMask:   {enc: sVEncoding},
  2253  
  2254  	// 31.7.5: Vector Strided Instructions
  2255  	AVLSE8V & obj.AMask:  {enc: iIIVEncoding},
  2256  	AVLSE16V & obj.AMask: {enc: iIIVEncoding},
  2257  	AVLSE32V & obj.AMask: {enc: iIIVEncoding},
  2258  	AVLSE64V & obj.AMask: {enc: iIIVEncoding},
  2259  	AVSSE8V & obj.AMask:  {enc: sVIIEncoding},
  2260  	AVSSE16V & obj.AMask: {enc: sVIIEncoding},
  2261  	AVSSE32V & obj.AMask: {enc: sVIIEncoding},
  2262  	AVSSE64V & obj.AMask: {enc: sVIIEncoding},
  2263  
  2264  	// 31.7.6: Vector Indexed Instructions
  2265  	AVLUXEI8V & obj.AMask:  {enc: iVIVEncoding},
  2266  	AVLUXEI16V & obj.AMask: {enc: iVIVEncoding},
  2267  	AVLUXEI32V & obj.AMask: {enc: iVIVEncoding},
  2268  	AVLUXEI64V & obj.AMask: {enc: iVIVEncoding},
  2269  	AVLOXEI8V & obj.AMask:  {enc: iVIVEncoding},
  2270  	AVLOXEI16V & obj.AMask: {enc: iVIVEncoding},
  2271  	AVLOXEI32V & obj.AMask: {enc: iVIVEncoding},
  2272  	AVLOXEI64V & obj.AMask: {enc: iVIVEncoding},
  2273  	AVSUXEI8V & obj.AMask:  {enc: sVIVEncoding},
  2274  	AVSUXEI16V & obj.AMask: {enc: sVIVEncoding},
  2275  	AVSUXEI32V & obj.AMask: {enc: sVIVEncoding},
  2276  	AVSUXEI64V & obj.AMask: {enc: sVIVEncoding},
  2277  	AVSOXEI8V & obj.AMask:  {enc: sVIVEncoding},
  2278  	AVSOXEI16V & obj.AMask: {enc: sVIVEncoding},
  2279  	AVSOXEI32V & obj.AMask: {enc: sVIVEncoding},
  2280  	AVSOXEI64V & obj.AMask: {enc: sVIVEncoding},
  2281  
  2282  	// 31.7.9: Vector Load/Store Whole Register Instructions
  2283  	AVL1RE8V & obj.AMask:  {enc: iVEncoding},
  2284  	AVL1RE16V & obj.AMask: {enc: iVEncoding},
  2285  	AVL1RE32V & obj.AMask: {enc: iVEncoding},
  2286  	AVL1RE64V & obj.AMask: {enc: iVEncoding},
  2287  	AVL2RE8V & obj.AMask:  {enc: iVEncoding},
  2288  	AVL2RE16V & obj.AMask: {enc: iVEncoding},
  2289  	AVL2RE32V & obj.AMask: {enc: iVEncoding},
  2290  	AVL2RE64V & obj.AMask: {enc: iVEncoding},
  2291  	AVL4RE8V & obj.AMask:  {enc: iVEncoding},
  2292  	AVL4RE16V & obj.AMask: {enc: iVEncoding},
  2293  	AVL4RE32V & obj.AMask: {enc: iVEncoding},
  2294  	AVL4RE64V & obj.AMask: {enc: iVEncoding},
  2295  	AVL8RE8V & obj.AMask:  {enc: iVEncoding},
  2296  	AVL8RE16V & obj.AMask: {enc: iVEncoding},
  2297  	AVL8RE32V & obj.AMask: {enc: iVEncoding},
  2298  	AVL8RE64V & obj.AMask: {enc: iVEncoding},
  2299  	AVS1RV & obj.AMask:    {enc: sVEncoding},
  2300  	AVS2RV & obj.AMask:    {enc: sVEncoding},
  2301  	AVS4RV & obj.AMask:    {enc: sVEncoding},
  2302  	AVS8RV & obj.AMask:    {enc: sVEncoding},
  2303  
  2304  	// 31.11.1: Vector Single-Width Integer Add and Subtract
  2305  	AVADDVV & obj.AMask:  {enc: rVVVEncoding},
  2306  	AVADDVX & obj.AMask:  {enc: rVIVEncoding},
  2307  	AVADDVI & obj.AMask:  {enc: rVViEncoding},
  2308  	AVSUBVV & obj.AMask:  {enc: rVVVEncoding},
  2309  	AVSUBVX & obj.AMask:  {enc: rVIVEncoding},
  2310  	AVRSUBVX & obj.AMask: {enc: rVIVEncoding},
  2311  	AVRSUBVI & obj.AMask: {enc: rVViEncoding},
  2312  
  2313  	// 31.11.2: Vector Widening Integer Add/Subtract
  2314  	AVWADDUVV & obj.AMask: {enc: rVVVEncoding},
  2315  	AVWADDUVX & obj.AMask: {enc: rVIVEncoding},
  2316  	AVWSUBUVV & obj.AMask: {enc: rVVVEncoding},
  2317  	AVWSUBUVX & obj.AMask: {enc: rVIVEncoding},
  2318  	AVWADDVV & obj.AMask:  {enc: rVVVEncoding},
  2319  	AVWADDVX & obj.AMask:  {enc: rVIVEncoding},
  2320  	AVWSUBVV & obj.AMask:  {enc: rVVVEncoding},
  2321  	AVWSUBVX & obj.AMask:  {enc: rVIVEncoding},
  2322  	AVWADDUWV & obj.AMask: {enc: rVVVEncoding},
  2323  	AVWADDUWX & obj.AMask: {enc: rVIVEncoding},
  2324  	AVWSUBUWV & obj.AMask: {enc: rVVVEncoding},
  2325  	AVWSUBUWX & obj.AMask: {enc: rVIVEncoding},
  2326  	AVWADDWV & obj.AMask:  {enc: rVVVEncoding},
  2327  	AVWADDWX & obj.AMask:  {enc: rVIVEncoding},
  2328  	AVWSUBWV & obj.AMask:  {enc: rVVVEncoding},
  2329  	AVWSUBWX & obj.AMask:  {enc: rVIVEncoding},
  2330  
  2331  	// 31.11.3: Vector Integer Extension
  2332  	AVZEXTVF2 & obj.AMask: {enc: rVVEncoding},
  2333  	AVSEXTVF2 & obj.AMask: {enc: rVVEncoding},
  2334  	AVZEXTVF4 & obj.AMask: {enc: rVVEncoding},
  2335  	AVSEXTVF4 & obj.AMask: {enc: rVVEncoding},
  2336  	AVZEXTVF8 & obj.AMask: {enc: rVVEncoding},
  2337  	AVSEXTVF8 & obj.AMask: {enc: rVVEncoding},
  2338  
  2339  	// 31.11.4: Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions
  2340  	AVADCVVM & obj.AMask:  {enc: rVVVEncoding},
  2341  	AVADCVXM & obj.AMask:  {enc: rVIVEncoding},
  2342  	AVADCVIM & obj.AMask:  {enc: rVViEncoding},
  2343  	AVMADCVVM & obj.AMask: {enc: rVVVEncoding},
  2344  	AVMADCVXM & obj.AMask: {enc: rVIVEncoding},
  2345  	AVMADCVIM & obj.AMask: {enc: rVViEncoding},
  2346  	AVMADCVV & obj.AMask:  {enc: rVVVEncoding},
  2347  	AVMADCVX & obj.AMask:  {enc: rVIVEncoding},
  2348  	AVMADCVI & obj.AMask:  {enc: rVViEncoding},
  2349  	AVSBCVVM & obj.AMask:  {enc: rVVVEncoding},
  2350  	AVSBCVXM & obj.AMask:  {enc: rVIVEncoding},
  2351  	AVMSBCVVM & obj.AMask: {enc: rVVVEncoding},
  2352  	AVMSBCVXM & obj.AMask: {enc: rVIVEncoding},
  2353  	AVMSBCVV & obj.AMask:  {enc: rVVVEncoding},
  2354  	AVMSBCVX & obj.AMask:  {enc: rVIVEncoding},
  2355  
  2356  	// 31.11.5: Vector Bitwise Logical Instructions
  2357  	AVANDVV & obj.AMask: {enc: rVVVEncoding},
  2358  	AVANDVX & obj.AMask: {enc: rVIVEncoding},
  2359  	AVANDVI & obj.AMask: {enc: rVViEncoding},
  2360  	AVORVV & obj.AMask:  {enc: rVVVEncoding},
  2361  	AVORVX & obj.AMask:  {enc: rVIVEncoding},
  2362  	AVORVI & obj.AMask:  {enc: rVViEncoding},
  2363  	AVXORVV & obj.AMask: {enc: rVVVEncoding},
  2364  	AVXORVX & obj.AMask: {enc: rVIVEncoding},
  2365  	AVXORVI & obj.AMask: {enc: rVViEncoding},
  2366  
  2367  	// 31.11.6: Vector Single-Width Shift Instructions
  2368  	AVSLLVV & obj.AMask: {enc: rVVVEncoding},
  2369  	AVSLLVX & obj.AMask: {enc: rVIVEncoding},
  2370  	AVSLLVI & obj.AMask: {enc: rVVuEncoding},
  2371  	AVSRLVV & obj.AMask: {enc: rVVVEncoding},
  2372  	AVSRLVX & obj.AMask: {enc: rVIVEncoding},
  2373  	AVSRLVI & obj.AMask: {enc: rVVuEncoding},
  2374  	AVSRAVV & obj.AMask: {enc: rVVVEncoding},
  2375  	AVSRAVX & obj.AMask: {enc: rVIVEncoding},
  2376  	AVSRAVI & obj.AMask: {enc: rVVuEncoding},
  2377  
  2378  	// 31.11.7: Vector Narrowing Integer Right Shift Instructions
  2379  	AVNSRLWV & obj.AMask: {enc: rVVVEncoding},
  2380  	AVNSRLWX & obj.AMask: {enc: rVIVEncoding},
  2381  	AVNSRLWI & obj.AMask: {enc: rVVuEncoding},
  2382  	AVNSRAWV & obj.AMask: {enc: rVVVEncoding},
  2383  	AVNSRAWX & obj.AMask: {enc: rVIVEncoding},
  2384  	AVNSRAWI & obj.AMask: {enc: rVVuEncoding},
  2385  
  2386  	// 31.11.8: Vector Integer Compare Instructions
  2387  	AVMSEQVV & obj.AMask:  {enc: rVVVEncoding},
  2388  	AVMSEQVX & obj.AMask:  {enc: rVIVEncoding},
  2389  	AVMSEQVI & obj.AMask:  {enc: rVViEncoding},
  2390  	AVMSNEVV & obj.AMask:  {enc: rVVVEncoding},
  2391  	AVMSNEVX & obj.AMask:  {enc: rVIVEncoding},
  2392  	AVMSNEVI & obj.AMask:  {enc: rVViEncoding},
  2393  	AVMSLTUVV & obj.AMask: {enc: rVVVEncoding},
  2394  	AVMSLTUVX & obj.AMask: {enc: rVIVEncoding},
  2395  	AVMSLTVV & obj.AMask:  {enc: rVVVEncoding},
  2396  	AVMSLTVX & obj.AMask:  {enc: rVIVEncoding},
  2397  	AVMSLEUVV & obj.AMask: {enc: rVVVEncoding},
  2398  	AVMSLEUVX & obj.AMask: {enc: rVIVEncoding},
  2399  	AVMSLEUVI & obj.AMask: {enc: rVViEncoding},
  2400  	AVMSLEVV & obj.AMask:  {enc: rVVVEncoding},
  2401  	AVMSLEVX & obj.AMask:  {enc: rVIVEncoding},
  2402  	AVMSLEVI & obj.AMask:  {enc: rVViEncoding},
  2403  	AVMSGTUVX & obj.AMask: {enc: rVIVEncoding},
  2404  	AVMSGTUVI & obj.AMask: {enc: rVViEncoding},
  2405  	AVMSGTVX & obj.AMask:  {enc: rVIVEncoding},
  2406  	AVMSGTVI & obj.AMask:  {enc: rVViEncoding},
  2407  
  2408  	// 31.11.9: Vector Integer Min/Max Instructions
  2409  	AVMINUVV & obj.AMask: {enc: rVVVEncoding},
  2410  	AVMINUVX & obj.AMask: {enc: rVIVEncoding},
  2411  	AVMINVV & obj.AMask:  {enc: rVVVEncoding},
  2412  	AVMINVX & obj.AMask:  {enc: rVIVEncoding},
  2413  	AVMAXUVV & obj.AMask: {enc: rVVVEncoding},
  2414  	AVMAXUVX & obj.AMask: {enc: rVIVEncoding},
  2415  	AVMAXVV & obj.AMask:  {enc: rVVVEncoding},
  2416  	AVMAXVX & obj.AMask:  {enc: rVIVEncoding},
  2417  
  2418  	// 31.11.10: Vector Single-Width Integer Multiply Instructions
  2419  	AVMULVV & obj.AMask:    {enc: rVVVEncoding},
  2420  	AVMULVX & obj.AMask:    {enc: rVIVEncoding},
  2421  	AVMULHVV & obj.AMask:   {enc: rVVVEncoding},
  2422  	AVMULHVX & obj.AMask:   {enc: rVIVEncoding},
  2423  	AVMULHUVV & obj.AMask:  {enc: rVVVEncoding},
  2424  	AVMULHUVX & obj.AMask:  {enc: rVIVEncoding},
  2425  	AVMULHSUVV & obj.AMask: {enc: rVVVEncoding},
  2426  	AVMULHSUVX & obj.AMask: {enc: rVIVEncoding},
  2427  
  2428  	// 31.11.11: Vector Integer Divide Instructions
  2429  	AVDIVUVV & obj.AMask: {enc: rVVVEncoding},
  2430  	AVDIVUVX & obj.AMask: {enc: rVIVEncoding},
  2431  	AVDIVVV & obj.AMask:  {enc: rVVVEncoding},
  2432  	AVDIVVX & obj.AMask:  {enc: rVIVEncoding},
  2433  	AVREMUVV & obj.AMask: {enc: rVVVEncoding},
  2434  	AVREMUVX & obj.AMask: {enc: rVIVEncoding},
  2435  	AVREMVV & obj.AMask:  {enc: rVVVEncoding},
  2436  	AVREMVX & obj.AMask:  {enc: rVIVEncoding},
  2437  
  2438  	// 31.11.12: Vector Widening Integer Multiply Instructions
  2439  	AVWMULVV & obj.AMask:   {enc: rVVVEncoding},
  2440  	AVWMULVX & obj.AMask:   {enc: rVIVEncoding},
  2441  	AVWMULUVV & obj.AMask:  {enc: rVVVEncoding},
  2442  	AVWMULUVX & obj.AMask:  {enc: rVIVEncoding},
  2443  	AVWMULSUVV & obj.AMask: {enc: rVVVEncoding},
  2444  	AVWMULSUVX & obj.AMask: {enc: rVIVEncoding},
  2445  
  2446  	// 31.11.13: Vector Single-Width Integer Multiply-Add Instructions
  2447  	AVMACCVV & obj.AMask:  {enc: rVVVEncoding},
  2448  	AVMACCVX & obj.AMask:  {enc: rVIVEncoding},
  2449  	AVNMSACVV & obj.AMask: {enc: rVVVEncoding},
  2450  	AVNMSACVX & obj.AMask: {enc: rVIVEncoding},
  2451  	AVMADDVV & obj.AMask:  {enc: rVVVEncoding},
  2452  	AVMADDVX & obj.AMask:  {enc: rVIVEncoding},
  2453  	AVNMSUBVV & obj.AMask: {enc: rVVVEncoding},
  2454  	AVNMSUBVX & obj.AMask: {enc: rVIVEncoding},
  2455  
  2456  	// 31.11.14: Vector Widening Integer Multiply-Add Instructions
  2457  	AVWMACCUVV & obj.AMask:  {enc: rVVVEncoding},
  2458  	AVWMACCUVX & obj.AMask:  {enc: rVIVEncoding},
  2459  	AVWMACCVV & obj.AMask:   {enc: rVVVEncoding},
  2460  	AVWMACCVX & obj.AMask:   {enc: rVIVEncoding},
  2461  	AVWMACCSUVV & obj.AMask: {enc: rVVVEncoding},
  2462  	AVWMACCSUVX & obj.AMask: {enc: rVIVEncoding},
  2463  	AVWMACCUSVX & obj.AMask: {enc: rVIVEncoding},
  2464  
  2465  	// 31.11.15: Vector Integer Merge Instructions
  2466  	AVMERGEVVM & obj.AMask: {enc: rVVVEncoding},
  2467  	AVMERGEVXM & obj.AMask: {enc: rVIVEncoding},
  2468  	AVMERGEVIM & obj.AMask: {enc: rVViEncoding},
  2469  
  2470  	// 31.11.16: Vector Integer Move Instructions
  2471  	AVMVVV & obj.AMask: {enc: rVVVEncoding},
  2472  	AVMVVX & obj.AMask: {enc: rVIVEncoding},
  2473  	AVMVVI & obj.AMask: {enc: rVViEncoding},
  2474  
  2475  	// 31.12.1: Vector Single-Width Saturating Add and Subtract
  2476  	AVSADDUVV & obj.AMask: {enc: rVVVEncoding},
  2477  	AVSADDUVX & obj.AMask: {enc: rVIVEncoding},
  2478  	AVSADDUVI & obj.AMask: {enc: rVViEncoding},
  2479  	AVSADDVV & obj.AMask:  {enc: rVVVEncoding},
  2480  	AVSADDVX & obj.AMask:  {enc: rVIVEncoding},
  2481  	AVSADDVI & obj.AMask:  {enc: rVViEncoding},
  2482  	AVSSUBUVV & obj.AMask: {enc: rVVVEncoding},
  2483  	AVSSUBUVX & obj.AMask: {enc: rVIVEncoding},
  2484  	AVSSUBVV & obj.AMask:  {enc: rVVVEncoding},
  2485  	AVSSUBVX & obj.AMask:  {enc: rVIVEncoding},
  2486  
  2487  	// 31.12.2: Vector Single-Width Averaging Add and Subtract
  2488  	AVAADDUVV & obj.AMask: {enc: rVVVEncoding},
  2489  	AVAADDUVX & obj.AMask: {enc: rVIVEncoding},
  2490  	AVAADDVV & obj.AMask:  {enc: rVVVEncoding},
  2491  	AVAADDVX & obj.AMask:  {enc: rVIVEncoding},
  2492  	AVASUBUVV & obj.AMask: {enc: rVVVEncoding},
  2493  	AVASUBUVX & obj.AMask: {enc: rVIVEncoding},
  2494  	AVASUBVV & obj.AMask:  {enc: rVVVEncoding},
  2495  	AVASUBVX & obj.AMask:  {enc: rVIVEncoding},
  2496  
  2497  	// 31.12.3: Vector Single-Width Fractional Multiply with Rounding and Saturation
  2498  	AVSMULVV & obj.AMask: {enc: rVVVEncoding},
  2499  	AVSMULVX & obj.AMask: {enc: rVIVEncoding},
  2500  
  2501  	// 31.12.4: Vector Single-Width Scaling Shift Instructions
  2502  	AVSSRLVV & obj.AMask: {enc: rVVVEncoding},
  2503  	AVSSRLVX & obj.AMask: {enc: rVIVEncoding},
  2504  	AVSSRLVI & obj.AMask: {enc: rVVuEncoding},
  2505  	AVSSRAVV & obj.AMask: {enc: rVVVEncoding},
  2506  	AVSSRAVX & obj.AMask: {enc: rVIVEncoding},
  2507  	AVSSRAVI & obj.AMask: {enc: rVVuEncoding},
  2508  
  2509  	// 31.12.5: Vector Narrowing Fixed-Point Clip Instructions
  2510  	AVNCLIPUWV & obj.AMask: {enc: rVVVEncoding},
  2511  	AVNCLIPUWX & obj.AMask: {enc: rVIVEncoding},
  2512  	AVNCLIPUWI & obj.AMask: {enc: rVVuEncoding},
  2513  	AVNCLIPWV & obj.AMask:  {enc: rVVVEncoding},
  2514  	AVNCLIPWX & obj.AMask:  {enc: rVIVEncoding},
  2515  	AVNCLIPWI & obj.AMask:  {enc: rVVuEncoding},
  2516  
  2517  	// 31.13.2: Vector Single-Width Floating-Point Add/Subtract Instructions
  2518  	AVFADDVV & obj.AMask:  {enc: rVVVEncoding},
  2519  	AVFADDVF & obj.AMask:  {enc: rVFVEncoding},
  2520  	AVFSUBVV & obj.AMask:  {enc: rVVVEncoding},
  2521  	AVFSUBVF & obj.AMask:  {enc: rVFVEncoding},
  2522  	AVFRSUBVF & obj.AMask: {enc: rVFVEncoding},
  2523  
  2524  	// 31.13.3: Vector Widening Floating-Point Add/Subtract Instructions
  2525  	AVFWADDVV & obj.AMask: {enc: rVVVEncoding},
  2526  	AVFWADDVF & obj.AMask: {enc: rVFVEncoding},
  2527  	AVFWSUBVV & obj.AMask: {enc: rVVVEncoding},
  2528  	AVFWSUBVF & obj.AMask: {enc: rVFVEncoding},
  2529  	AVFWADDWV & obj.AMask: {enc: rVVVEncoding},
  2530  	AVFWADDWF & obj.AMask: {enc: rVFVEncoding},
  2531  	AVFWSUBWV & obj.AMask: {enc: rVVVEncoding},
  2532  	AVFWSUBWF & obj.AMask: {enc: rVFVEncoding},
  2533  
  2534  	// 31.13.4: Vector Single-Width Floating-Point Multiply/Divide Instructions
  2535  	AVFMULVV & obj.AMask:  {enc: rVVVEncoding},
  2536  	AVFMULVF & obj.AMask:  {enc: rVFVEncoding},
  2537  	AVFDIVVV & obj.AMask:  {enc: rVVVEncoding},
  2538  	AVFDIVVF & obj.AMask:  {enc: rVFVEncoding},
  2539  	AVFRDIVVF & obj.AMask: {enc: rVFVEncoding},
  2540  
  2541  	// 31.13.5: Vector Widening Floating-Point Multiply
  2542  	AVFWMULVV & obj.AMask: {enc: rVVVEncoding},
  2543  	AVFWMULVF & obj.AMask: {enc: rVFVEncoding},
  2544  
  2545  	// 31.13.6: Vector Single-Width Floating-Point Fused Multiply-Add Instructions
  2546  	AVFMACCVV & obj.AMask:  {enc: rVVVEncoding},
  2547  	AVFMACCVF & obj.AMask:  {enc: rVFVEncoding},
  2548  	AVFNMACCVV & obj.AMask: {enc: rVVVEncoding},
  2549  	AVFNMACCVF & obj.AMask: {enc: rVFVEncoding},
  2550  	AVFMSACVV & obj.AMask:  {enc: rVVVEncoding},
  2551  	AVFMSACVF & obj.AMask:  {enc: rVFVEncoding},
  2552  	AVFNMSACVV & obj.AMask: {enc: rVVVEncoding},
  2553  	AVFNMSACVF & obj.AMask: {enc: rVFVEncoding},
  2554  	AVFMADDVV & obj.AMask:  {enc: rVVVEncoding},
  2555  	AVFMADDVF & obj.AMask:  {enc: rVFVEncoding},
  2556  	AVFNMADDVV & obj.AMask: {enc: rVVVEncoding},
  2557  	AVFNMADDVF & obj.AMask: {enc: rVFVEncoding},
  2558  	AVFMSUBVV & obj.AMask:  {enc: rVVVEncoding},
  2559  	AVFMSUBVF & obj.AMask:  {enc: rVFVEncoding},
  2560  	AVFNMSUBVV & obj.AMask: {enc: rVVVEncoding},
  2561  	AVFNMSUBVF & obj.AMask: {enc: rVFVEncoding},
  2562  
  2563  	// 31.13.7: Vector Widening Floating-Point Fused Multiply-Add Instructions
  2564  	AVFWMACCVV & obj.AMask:  {enc: rVVVEncoding},
  2565  	AVFWMACCVF & obj.AMask:  {enc: rVFVEncoding},
  2566  	AVFWNMACCVV & obj.AMask: {enc: rVVVEncoding},
  2567  	AVFWNMACCVF & obj.AMask: {enc: rVFVEncoding},
  2568  	AVFWMSACVV & obj.AMask:  {enc: rVVVEncoding},
  2569  	AVFWMSACVF & obj.AMask:  {enc: rVFVEncoding},
  2570  	AVFWNMSACVV & obj.AMask: {enc: rVVVEncoding},
  2571  	AVFWNMSACVF & obj.AMask: {enc: rVFVEncoding},
  2572  
  2573  	// 31.13.8: Vector Floating-Point Square-Root Instruction
  2574  	AVFSQRTV & obj.AMask: {enc: rVVEncoding},
  2575  
  2576  	// 31.13.9: Vector Floating-Point Reciprocal Square-Root Estimate Instruction
  2577  	AVFRSQRT7V & obj.AMask: {enc: rVVEncoding},
  2578  
  2579  	// 31.13.10: Vector Floating-Point Reciprocal Estimate Instruction
  2580  	AVFREC7V & obj.AMask: {enc: rVVEncoding},
  2581  
  2582  	// 31.13.11: Vector Floating-Point MIN/MAX Instructions
  2583  	AVFMINVV & obj.AMask: {enc: rVVVEncoding},
  2584  	AVFMINVF & obj.AMask: {enc: rVFVEncoding},
  2585  	AVFMAXVV & obj.AMask: {enc: rVVVEncoding},
  2586  	AVFMAXVF & obj.AMask: {enc: rVFVEncoding},
  2587  
  2588  	// 31.13.12: Vector Floating-Point Sign-Injection Instructions
  2589  	AVFSGNJVV & obj.AMask:  {enc: rVVVEncoding},
  2590  	AVFSGNJVF & obj.AMask:  {enc: rVFVEncoding},
  2591  	AVFSGNJNVV & obj.AMask: {enc: rVVVEncoding},
  2592  	AVFSGNJNVF & obj.AMask: {enc: rVFVEncoding},
  2593  	AVFSGNJXVV & obj.AMask: {enc: rVVVEncoding},
  2594  	AVFSGNJXVF & obj.AMask: {enc: rVFVEncoding},
  2595  
  2596  	// 31.13.13: Vector Floating-Point Compare Instructions
  2597  	AVMFEQVV & obj.AMask: {enc: rVVVEncoding},
  2598  	AVMFEQVF & obj.AMask: {enc: rVFVEncoding},
  2599  	AVMFNEVV & obj.AMask: {enc: rVVVEncoding},
  2600  	AVMFNEVF & obj.AMask: {enc: rVFVEncoding},
  2601  	AVMFLTVV & obj.AMask: {enc: rVVVEncoding},
  2602  	AVMFLTVF & obj.AMask: {enc: rVFVEncoding},
  2603  	AVMFLEVV & obj.AMask: {enc: rVVVEncoding},
  2604  	AVMFLEVF & obj.AMask: {enc: rVFVEncoding},
  2605  	AVMFGTVF & obj.AMask: {enc: rVFVEncoding},
  2606  	AVMFGEVF & obj.AMask: {enc: rVFVEncoding},
  2607  
  2608  	// 31.13.14: Vector Floating-Point Classify Instruction
  2609  	AVFCLASSV & obj.AMask: {enc: rVVEncoding},
  2610  
  2611  	// 31.13.15: Vector Floating-Point Merge Instruction
  2612  	AVFMERGEVFM & obj.AMask: {enc: rVFVEncoding},
  2613  
  2614  	// 31.13.16: Vector Floating-Point Move Instruction
  2615  	AVFMVVF & obj.AMask: {enc: rVFVEncoding},
  2616  
  2617  	// 31.13.17: Single-Width Floating-Point/Integer Type-Convert Instructions
  2618  	AVFCVTXUFV & obj.AMask:    {enc: rVVEncoding},
  2619  	AVFCVTXFV & obj.AMask:     {enc: rVVEncoding},
  2620  	AVFCVTRTZXUFV & obj.AMask: {enc: rVVEncoding},
  2621  	AVFCVTRTZXFV & obj.AMask:  {enc: rVVEncoding},
  2622  	AVFCVTFXUV & obj.AMask:    {enc: rVVEncoding},
  2623  	AVFCVTFXV & obj.AMask:     {enc: rVVEncoding},
  2624  
  2625  	// 31.13.18: Widening Floating-Point/Integer Type-Convert Instructions
  2626  	AVFWCVTXUFV & obj.AMask:    {enc: rVVEncoding},
  2627  	AVFWCVTXFV & obj.AMask:     {enc: rVVEncoding},
  2628  	AVFWCVTRTZXUFV & obj.AMask: {enc: rVVEncoding},
  2629  	AVFWCVTRTZXFV & obj.AMask:  {enc: rVVEncoding},
  2630  	AVFWCVTFXUV & obj.AMask:    {enc: rVVEncoding},
  2631  	AVFWCVTFXV & obj.AMask:     {enc: rVVEncoding},
  2632  	AVFWCVTFFV & obj.AMask:     {enc: rVVEncoding},
  2633  
  2634  	// 31.13.19: Narrowing Floating-Point/Integer Type-Convert Instructions
  2635  	AVFNCVTXUFW & obj.AMask:    {enc: rVVEncoding},
  2636  	AVFNCVTXFW & obj.AMask:     {enc: rVVEncoding},
  2637  	AVFNCVTRTZXUFW & obj.AMask: {enc: rVVEncoding},
  2638  	AVFNCVTRTZXFW & obj.AMask:  {enc: rVVEncoding},
  2639  	AVFNCVTFXUW & obj.AMask:    {enc: rVVEncoding},
  2640  	AVFNCVTFXW & obj.AMask:     {enc: rVVEncoding},
  2641  	AVFNCVTFFW & obj.AMask:     {enc: rVVEncoding},
  2642  	AVFNCVTRODFFW & obj.AMask:  {enc: rVVEncoding},
  2643  
  2644  	// 31.14.1: Vector Single-Width Integer Reduction Instructions
  2645  	AVREDSUMVS & obj.AMask:  {enc: rVVVEncoding},
  2646  	AVREDMAXUVS & obj.AMask: {enc: rVVVEncoding},
  2647  	AVREDMAXVS & obj.AMask:  {enc: rVVVEncoding},
  2648  	AVREDMINUVS & obj.AMask: {enc: rVVVEncoding},
  2649  	AVREDMINVS & obj.AMask:  {enc: rVVVEncoding},
  2650  	AVREDANDVS & obj.AMask:  {enc: rVVVEncoding},
  2651  	AVREDORVS & obj.AMask:   {enc: rVVVEncoding},
  2652  	AVREDXORVS & obj.AMask:  {enc: rVVVEncoding},
  2653  
  2654  	// 31.14.2: Vector Widening Integer Reduction Instructions
  2655  	AVWREDSUMUVS & obj.AMask: {enc: rVVVEncoding},
  2656  	AVWREDSUMVS & obj.AMask:  {enc: rVVVEncoding},
  2657  
  2658  	// 31.14.3: Vector Single-Width Floating-Point Reduction Instructions
  2659  	AVFREDOSUMVS & obj.AMask: {enc: rVVVEncoding},
  2660  	AVFREDUSUMVS & obj.AMask: {enc: rVVVEncoding},
  2661  	AVFREDMAXVS & obj.AMask:  {enc: rVVVEncoding},
  2662  	AVFREDMINVS & obj.AMask:  {enc: rVVVEncoding},
  2663  
  2664  	// 31.14.4: Vector Widening Floating-Point Reduction Instructions
  2665  	AVFWREDOSUMVS & obj.AMask: {enc: rVVVEncoding},
  2666  	AVFWREDUSUMVS & obj.AMask: {enc: rVVVEncoding},
  2667  
  2668  	// 31.15: Vector Mask Instructions
  2669  	AVMANDMM & obj.AMask:  {enc: rVVVEncoding},
  2670  	AVMNANDMM & obj.AMask: {enc: rVVVEncoding},
  2671  	AVMANDNMM & obj.AMask: {enc: rVVVEncoding},
  2672  	AVMXORMM & obj.AMask:  {enc: rVVVEncoding},
  2673  	AVMORMM & obj.AMask:   {enc: rVVVEncoding},
  2674  	AVMNORMM & obj.AMask:  {enc: rVVVEncoding},
  2675  	AVMORNMM & obj.AMask:  {enc: rVVVEncoding},
  2676  	AVMXNORMM & obj.AMask: {enc: rVVVEncoding},
  2677  	AVCPOPM & obj.AMask:   {enc: rVIEncoding},
  2678  	AVFIRSTM & obj.AMask:  {enc: rVIEncoding},
  2679  	AVMSBFM & obj.AMask:   {enc: rVVEncoding},
  2680  	AVMSIFM & obj.AMask:   {enc: rVVEncoding},
  2681  	AVMSOFM & obj.AMask:   {enc: rVVEncoding},
  2682  	AVIOTAM & obj.AMask:   {enc: rVVEncoding},
  2683  	AVIDV & obj.AMask:     {enc: rVVEncoding},
  2684  
  2685  	// 31.16.1: Integer Scalar Move Instructions
  2686  	AVMVXS & obj.AMask: {enc: rVIEncoding},
  2687  	AVMVSX & obj.AMask: {enc: rIVEncoding},
  2688  
  2689  	// 31.16.2: Floating-Point Scalar Move Instructions
  2690  	AVFMVFS & obj.AMask: {enc: rVFEncoding},
  2691  	AVFMVSF & obj.AMask: {enc: rFVEncoding},
  2692  
  2693  	// 31.16.3: Vector Slide Instructions
  2694  	AVSLIDEUPVX & obj.AMask:     {enc: rVIVEncoding},
  2695  	AVSLIDEUPVI & obj.AMask:     {enc: rVVuEncoding},
  2696  	AVSLIDEDOWNVX & obj.AMask:   {enc: rVIVEncoding},
  2697  	AVSLIDEDOWNVI & obj.AMask:   {enc: rVVuEncoding},
  2698  	AVSLIDE1UPVX & obj.AMask:    {enc: rVIVEncoding},
  2699  	AVFSLIDE1UPVF & obj.AMask:   {enc: rVFVEncoding},
  2700  	AVSLIDE1DOWNVX & obj.AMask:  {enc: rVIVEncoding},
  2701  	AVFSLIDE1DOWNVF & obj.AMask: {enc: rVFVEncoding},
  2702  
  2703  	// 31.16.4: Vector Register Gather Instructions
  2704  	AVRGATHERVV & obj.AMask:     {enc: rVVVEncoding},
  2705  	AVRGATHEREI16VV & obj.AMask: {enc: rVVVEncoding},
  2706  	AVRGATHERVX & obj.AMask:     {enc: rVIVEncoding},
  2707  	AVRGATHERVI & obj.AMask:     {enc: rVVuEncoding},
  2708  
  2709  	// 31.16.5: Vector Compress Instruction
  2710  	AVCOMPRESSVM & obj.AMask: {enc: rVVVEncoding},
  2711  
  2712  	// 31.16.6: Whole Vector Register Move
  2713  	AVMV1RV & obj.AMask: {enc: rVVEncoding},
  2714  	AVMV2RV & obj.AMask: {enc: rVVEncoding},
  2715  	AVMV4RV & obj.AMask: {enc: rVVEncoding},
  2716  	AVMV8RV & obj.AMask: {enc: rVVEncoding},
  2717  
  2718  	//
  2719  	// Privileged ISA
  2720  	//
  2721  
  2722  	// 3.3.1: Environment Call and Breakpoint
  2723  	AECALL & obj.AMask:  {enc: iIIEncoding},
  2724  	AEBREAK & obj.AMask: {enc: iIIEncoding},
  2725  
  2726  	// Escape hatch
  2727  	AWORD & obj.AMask: {enc: rawEncoding},
  2728  
  2729  	// Pseudo-operations
  2730  	obj.AFUNCDATA: {enc: pseudoOpEncoding},
  2731  	obj.APCDATA:   {enc: pseudoOpEncoding},
  2732  	obj.ATEXT:     {enc: pseudoOpEncoding},
  2733  	obj.ANOP:      {enc: pseudoOpEncoding},
  2734  	obj.ADUFFZERO: {enc: pseudoOpEncoding},
  2735  	obj.ADUFFCOPY: {enc: pseudoOpEncoding},
  2736  	obj.APCALIGN:  {enc: pseudoOpEncoding},
  2737  }
  2738  
  2739  // instructionDataForAs returns the instruction data for an obj.As.
  2740  func instructionDataForAs(as obj.As) (*instructionData, error) {
  2741  	if base := as &^ obj.AMask; base != obj.ABaseRISCV && base != 0 {
  2742  		return nil, fmt.Errorf("%v is not a RISC-V instruction", as)
  2743  	}
  2744  	asi := as & obj.AMask
  2745  	if int(asi) >= len(instructions) {
  2746  		return nil, fmt.Errorf("bad RISC-V instruction %v", as)
  2747  	}
  2748  	return &instructions[asi], nil
  2749  }
  2750  
  2751  // encodingForAs returns the encoding for an obj.As.
  2752  func encodingForAs(as obj.As) (*encoding, error) {
  2753  	insData, err := instructionDataForAs(as)
  2754  	if err != nil {
  2755  		return &badEncoding, err
  2756  	}
  2757  	if insData.enc.validate == nil {
  2758  		return &badEncoding, fmt.Errorf("no encoding for instruction %s", as)
  2759  	}
  2760  	return &insData.enc, nil
  2761  }
  2762  
  2763  // splitShiftConst attempts to split a constant into a signed 12 bit or
  2764  // 32 bit integer, with corresponding logical right shift and/or left shift.
  2765  func splitShiftConst(v int64) (imm int64, lsh int, rsh int, ok bool) {
  2766  	// See if we can reconstruct this value from a signed 32 bit integer.
  2767  	lsh = bits.TrailingZeros64(uint64(v))
  2768  	c := v >> lsh
  2769  	if int64(int32(c)) == c {
  2770  		return c, lsh, 0, true
  2771  	}
  2772  
  2773  	// See if we can reconstruct this value from a small negative constant.
  2774  	rsh = bits.LeadingZeros64(uint64(v))
  2775  	ones := bits.OnesCount64((uint64(v) >> lsh) >> 11)
  2776  	c = signExtend(1<<11|((v>>lsh)&0x7ff), 12)
  2777  	if rsh+ones+lsh+11 == 64 {
  2778  		if lsh > 0 || c != -1 {
  2779  			lsh += rsh
  2780  		}
  2781  		return c, lsh, rsh, true
  2782  	}
  2783  
  2784  	return 0, 0, 0, false
  2785  }
  2786  
  2787  // isShiftConst indicates whether a constant can be represented as a signed
  2788  // 32 bit integer that is left shifted.
  2789  func isShiftConst(v int64) bool {
  2790  	_, lsh, rsh, ok := splitShiftConst(v)
  2791  	return ok && (lsh > 0 || rsh > 0)
  2792  }
  2793  
  2794  type instruction struct {
  2795  	p      *obj.Prog // Prog that instruction is for
  2796  	as     obj.As    // Assembler opcode
  2797  	rd     uint32    // Destination register
  2798  	rs1    uint32    // Source register 1
  2799  	rs2    uint32    // Source register 2
  2800  	rs3    uint32    // Source register 3
  2801  	imm    int64     // Immediate
  2802  	funct3 uint32    // Function 3
  2803  	funct7 uint32    // Function 7 (or Function 2)
  2804  }
  2805  
  2806  func (ins *instruction) String() string {
  2807  	if ins.p == nil {
  2808  		return ins.as.String()
  2809  	}
  2810  	var suffix string
  2811  	if ins.p.As != ins.as {
  2812  		suffix = fmt.Sprintf(" (%v)", ins.as)
  2813  	}
  2814  	return fmt.Sprintf("%v%v", ins.p, suffix)
  2815  }
  2816  
  2817  func (ins *instruction) encode() (uint32, error) {
  2818  	enc, err := encodingForAs(ins.as)
  2819  	if err != nil {
  2820  		return 0, err
  2821  	}
  2822  	if enc.length <= 0 {
  2823  		return 0, fmt.Errorf("%v: encoding called for a pseudo instruction", ins.as)
  2824  	}
  2825  	return enc.encode(ins), nil
  2826  }
  2827  
  2828  func (ins *instruction) length() int {
  2829  	enc, err := encodingForAs(ins.as)
  2830  	if err != nil {
  2831  		return 0
  2832  	}
  2833  	return enc.length
  2834  }
  2835  
  2836  func (ins *instruction) validate(ctxt *obj.Link) {
  2837  	enc, err := encodingForAs(ins.as)
  2838  	if err != nil {
  2839  		ctxt.Diag(err.Error())
  2840  		return
  2841  	}
  2842  	enc.validate(ctxt, ins)
  2843  }
  2844  
  2845  func (ins *instruction) usesRegTmp() bool {
  2846  	return ins.rd == REG_TMP || ins.rs1 == REG_TMP || ins.rs2 == REG_TMP
  2847  }
  2848  
  2849  // instructionForProg returns the default *obj.Prog to instruction mapping.
  2850  func instructionForProg(p *obj.Prog) *instruction {
  2851  	ins := &instruction{
  2852  		as:  p.As,
  2853  		rd:  uint32(p.To.Reg),
  2854  		rs1: uint32(p.Reg),
  2855  		rs2: uint32(p.From.Reg),
  2856  		imm: p.From.Offset,
  2857  	}
  2858  	if len(p.RestArgs) == 1 {
  2859  		ins.rs3 = uint32(p.RestArgs[0].Reg)
  2860  	}
  2861  	return ins
  2862  }
  2863  
  2864  // instructionsForOpImmediate returns the machine instructions for an immediate
  2865  // operand. The instruction is specified by as and the source register is
  2866  // specified by rs, instead of the obj.Prog.
  2867  func instructionsForOpImmediate(p *obj.Prog, as obj.As, rs int16) []*instruction {
  2868  	// <opi> $imm, REG, TO
  2869  	ins := instructionForProg(p)
  2870  	ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE
  2871  
  2872  	low, high, err := Split32BitImmediate(ins.imm)
  2873  	if err != nil {
  2874  		p.Ctxt.Diag("%v: constant %d too large", p, ins.imm, err)
  2875  		return nil
  2876  	}
  2877  	if high == 0 {
  2878  		return []*instruction{ins}
  2879  	}
  2880  
  2881  	// Split into two additions, if possible.
  2882  	// Do not split SP-writing instructions, as otherwise the recorded SP delta may be wrong.
  2883  	if p.Spadj == 0 && ins.as == AADDI && ins.imm >= -(1<<12) && ins.imm < 1<<12-1 {
  2884  		imm0 := ins.imm / 2
  2885  		imm1 := ins.imm - imm0
  2886  
  2887  		// ADDI $(imm/2), REG, TO
  2888  		// ADDI $(imm-imm/2), TO, TO
  2889  		ins.imm = imm0
  2890  		insADDI := &instruction{as: AADDI, rd: ins.rd, rs1: ins.rd, imm: imm1}
  2891  		return []*instruction{ins, insADDI}
  2892  	}
  2893  
  2894  	// LUI $high, TMP
  2895  	// ADDIW $low, TMP, TMP
  2896  	// <op> TMP, REG, TO
  2897  	insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
  2898  	insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP, imm: low}
  2899  	switch ins.as {
  2900  	case AADDI:
  2901  		ins.as = AADD
  2902  	case AANDI:
  2903  		ins.as = AAND
  2904  	case AORI:
  2905  		ins.as = AOR
  2906  	case AXORI:
  2907  		ins.as = AXOR
  2908  	default:
  2909  		p.Ctxt.Diag("unsupported immediate instruction %v for splitting", p)
  2910  		return nil
  2911  	}
  2912  	ins.rs2 = REG_TMP
  2913  	if low == 0 {
  2914  		return []*instruction{insLUI, ins}
  2915  	}
  2916  	return []*instruction{insLUI, insADDIW, ins}
  2917  }
  2918  
  2919  // instructionsForLoad returns the machine instructions for a load. The load
  2920  // instruction is specified by as and the base/source register is specified
  2921  // by rs, instead of the obj.Prog.
  2922  func instructionsForLoad(p *obj.Prog, as obj.As, rs int16) []*instruction {
  2923  	if p.From.Type != obj.TYPE_MEM {
  2924  		p.Ctxt.Diag("%v requires memory for source", p)
  2925  		return nil
  2926  	}
  2927  
  2928  	switch as {
  2929  	case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU, AFLW, AFLD:
  2930  	default:
  2931  		p.Ctxt.Diag("%v: unknown load instruction %v", p, as)
  2932  		return nil
  2933  	}
  2934  
  2935  	// <load> $imm, REG, TO (load $imm+(REG), TO)
  2936  	ins := instructionForProg(p)
  2937  	ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE
  2938  	ins.imm = p.From.Offset
  2939  
  2940  	low, high, err := Split32BitImmediate(ins.imm)
  2941  	if err != nil {
  2942  		p.Ctxt.Diag("%v: constant %d too large", p, ins.imm)
  2943  		return nil
  2944  	}
  2945  	if high == 0 {
  2946  		return []*instruction{ins}
  2947  	}
  2948  
  2949  	// LUI $high, TMP
  2950  	// ADD TMP, REG, TMP
  2951  	// <load> $low, TMP, TO
  2952  	insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
  2953  	insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rs1}
  2954  	ins.rs1, ins.imm = REG_TMP, low
  2955  
  2956  	return []*instruction{insLUI, insADD, ins}
  2957  }
  2958  
  2959  // instructionsForStore returns the machine instructions for a store. The store
  2960  // instruction is specified by as and the target/source register is specified
  2961  // by rd, instead of the obj.Prog.
  2962  func instructionsForStore(p *obj.Prog, as obj.As, rd int16) []*instruction {
  2963  	if p.To.Type != obj.TYPE_MEM {
  2964  		p.Ctxt.Diag("%v requires memory for destination", p)
  2965  		return nil
  2966  	}
  2967  
  2968  	switch as {
  2969  	case ASW, ASH, ASB, ASD, AFSW, AFSD:
  2970  	default:
  2971  		p.Ctxt.Diag("%v: unknown store instruction %v", p, as)
  2972  		return nil
  2973  	}
  2974  
  2975  	// <store> $imm, REG, TO (store $imm+(TO), REG)
  2976  	ins := instructionForProg(p)
  2977  	ins.as, ins.rd, ins.rs1, ins.rs2 = as, uint32(rd), uint32(p.From.Reg), obj.REG_NONE
  2978  	ins.imm = p.To.Offset
  2979  
  2980  	low, high, err := Split32BitImmediate(ins.imm)
  2981  	if err != nil {
  2982  		p.Ctxt.Diag("%v: constant %d too large", p, ins.imm)
  2983  		return nil
  2984  	}
  2985  	if high == 0 {
  2986  		return []*instruction{ins}
  2987  	}
  2988  
  2989  	// LUI $high, TMP
  2990  	// ADD TMP, TO, TMP
  2991  	// <store> $low, REG, TMP
  2992  	insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
  2993  	insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rd}
  2994  	ins.rd, ins.imm = REG_TMP, low
  2995  
  2996  	return []*instruction{insLUI, insADD, ins}
  2997  }
  2998  
  2999  func instructionsForTLS(p *obj.Prog, ins *instruction) []*instruction {
  3000  	insAddTP := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: REG_TP}
  3001  
  3002  	var inss []*instruction
  3003  	if p.Ctxt.Flag_shared {
  3004  		// TLS initial-exec mode - load TLS offset from GOT, add the thread pointer
  3005  		// register, then load from or store to the resulting memory location.
  3006  		insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
  3007  		insLoadTLSOffset := &instruction{as: ALD, rd: REG_TMP, rs1: REG_TMP}
  3008  		inss = []*instruction{insAUIPC, insLoadTLSOffset, insAddTP, ins}
  3009  	} else {
  3010  		// TLS local-exec mode - load upper TLS offset, add the lower TLS offset,
  3011  		// add the thread pointer register, then load from or store to the resulting
  3012  		// memory location. Note that this differs from the suggested three
  3013  		// instruction sequence, as the Go linker does not currently have an
  3014  		// easy way to handle relocation across 12 bytes of machine code.
  3015  		insLUI := &instruction{as: ALUI, rd: REG_TMP}
  3016  		insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP}
  3017  		inss = []*instruction{insLUI, insADDIW, insAddTP, ins}
  3018  	}
  3019  	return inss
  3020  }
  3021  
  3022  func instructionsForTLSLoad(p *obj.Prog) []*instruction {
  3023  	if p.From.Sym.Type != objabi.STLSBSS {
  3024  		p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.From.Sym)
  3025  		return nil
  3026  	}
  3027  
  3028  	ins := instructionForProg(p)
  3029  	ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), REG_TMP, obj.REG_NONE, 0
  3030  
  3031  	return instructionsForTLS(p, ins)
  3032  }
  3033  
  3034  func instructionsForTLSStore(p *obj.Prog) []*instruction {
  3035  	if p.To.Sym.Type != objabi.STLSBSS {
  3036  		p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.To.Sym)
  3037  		return nil
  3038  	}
  3039  
  3040  	ins := instructionForProg(p)
  3041  	ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
  3042  
  3043  	return instructionsForTLS(p, ins)
  3044  }
  3045  
  3046  // instructionsForMOV returns the machine instructions for an *obj.Prog that
  3047  // uses a MOV pseudo-instruction.
  3048  func instructionsForMOV(p *obj.Prog) []*instruction {
  3049  	ins := instructionForProg(p)
  3050  	inss := []*instruction{ins}
  3051  
  3052  	if p.Reg != 0 {
  3053  		p.Ctxt.Diag("%v: illegal MOV instruction", p)
  3054  		return nil
  3055  	}
  3056  
  3057  	switch {
  3058  	case p.From.Type == obj.TYPE_CONST && p.To.Type == obj.TYPE_REG:
  3059  		// Handle constant to register moves.
  3060  		if p.As != AMOV {
  3061  			p.Ctxt.Diag("%v: unsupported constant load", p)
  3062  			return nil
  3063  		}
  3064  
  3065  		// For constants larger than 32 bits in size that have trailing zeros,
  3066  		// use the value with the trailing zeros removed and then use a SLLI
  3067  		// instruction to restore the original constant.
  3068  		//
  3069  		// For example:
  3070  		//     MOV $0x8000000000000000, X10
  3071  		// becomes
  3072  		//     MOV $1, X10
  3073  		//     SLLI $63, X10, X10
  3074  		//
  3075  		// Similarly, we can construct large constants that have a consecutive
  3076  		// sequence of ones from a small negative constant, with a right and/or
  3077  		// left shift.
  3078  		//
  3079  		// For example:
  3080  		//     MOV $0x000fffffffffffda, X10
  3081  		// becomes
  3082  		//     MOV $-19, X10
  3083  		//     SLLI $13, X10
  3084  		//     SRLI $12, X10
  3085  		//
  3086  		var insSLLI, insSRLI *instruction
  3087  		if err := immIFits(ins.imm, 32); err != nil {
  3088  			if c, lsh, rsh, ok := splitShiftConst(ins.imm); ok {
  3089  				ins.imm = c
  3090  				if lsh > 0 {
  3091  					insSLLI = &instruction{as: ASLLI, rd: ins.rd, rs1: ins.rd, imm: int64(lsh)}
  3092  				}
  3093  				if rsh > 0 {
  3094  					insSRLI = &instruction{as: ASRLI, rd: ins.rd, rs1: ins.rd, imm: int64(rsh)}
  3095  				}
  3096  			}
  3097  		}
  3098  
  3099  		low, high, err := Split32BitImmediate(ins.imm)
  3100  		if err != nil {
  3101  			p.Ctxt.Diag("%v: constant %d too large: %v", p, ins.imm, err)
  3102  			return nil
  3103  		}
  3104  
  3105  		// MOV $c, R -> ADD $c, ZERO, R
  3106  		ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, REG_ZERO, obj.REG_NONE, low
  3107  
  3108  		// LUI is only necessary if the constant does not fit in 12 bits.
  3109  		if high != 0 {
  3110  			// LUI top20bits(c), R
  3111  			// ADD bottom12bits(c), R, R
  3112  			insLUI := &instruction{as: ALUI, rd: ins.rd, imm: high}
  3113  			inss = []*instruction{insLUI}
  3114  			if low != 0 {
  3115  				ins.as, ins.rs1 = AADDIW, ins.rd
  3116  				inss = append(inss, ins)
  3117  			}
  3118  		}
  3119  		if insSLLI != nil {
  3120  			inss = append(inss, insSLLI)
  3121  		}
  3122  		if insSRLI != nil {
  3123  			inss = append(inss, insSRLI)
  3124  		}
  3125  
  3126  	case p.From.Type == obj.TYPE_CONST && p.To.Type != obj.TYPE_REG:
  3127  		p.Ctxt.Diag("%v: constant load must target register", p)
  3128  		return nil
  3129  
  3130  	case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG:
  3131  		// Handle register to register moves.
  3132  		switch p.As {
  3133  		case AMOV: // MOV Ra, Rb -> ADDI $0, Ra, Rb
  3134  			ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, uint32(p.From.Reg), obj.REG_NONE, 0
  3135  		case AMOVW: // MOVW Ra, Rb -> ADDIW $0, Ra, Rb
  3136  			ins.as, ins.rs1, ins.rs2, ins.imm = AADDIW, uint32(p.From.Reg), obj.REG_NONE, 0
  3137  		case AMOVBU: // MOVBU Ra, Rb -> ANDI $255, Ra, Rb
  3138  			ins.as, ins.rs1, ins.rs2, ins.imm = AANDI, uint32(p.From.Reg), obj.REG_NONE, 255
  3139  		case AMOVF: // MOVF Ra, Rb -> FSGNJS Ra, Ra, Rb
  3140  			ins.as, ins.rs1 = AFSGNJS, uint32(p.From.Reg)
  3141  		case AMOVD: // MOVD Ra, Rb -> FSGNJD Ra, Ra, Rb
  3142  			ins.as, ins.rs1 = AFSGNJD, uint32(p.From.Reg)
  3143  		case AMOVB, AMOVH:
  3144  			if buildcfg.GORISCV64 >= 22 {
  3145  				// Use SEXTB or SEXTH to extend.
  3146  				ins.as, ins.rs1, ins.rs2 = ASEXTB, uint32(p.From.Reg), obj.REG_NONE
  3147  				if p.As == AMOVH {
  3148  					ins.as = ASEXTH
  3149  				}
  3150  			} else {
  3151  				// Use SLLI/SRAI sequence to extend.
  3152  				ins.as, ins.rs1, ins.rs2 = ASLLI, uint32(p.From.Reg), obj.REG_NONE
  3153  				if p.As == AMOVB {
  3154  					ins.imm = 56
  3155  				} else if p.As == AMOVH {
  3156  					ins.imm = 48
  3157  				}
  3158  				ins2 := &instruction{as: ASRAI, rd: ins.rd, rs1: ins.rd, imm: ins.imm}
  3159  				inss = append(inss, ins2)
  3160  			}
  3161  		case AMOVHU, AMOVWU:
  3162  			if buildcfg.GORISCV64 >= 22 {
  3163  				// Use ZEXTH or ADDUW to extend.
  3164  				ins.as, ins.rs1, ins.rs2, ins.imm = AZEXTH, uint32(p.From.Reg), obj.REG_NONE, 0
  3165  				if p.As == AMOVWU {
  3166  					ins.as, ins.rs2 = AADDUW, REG_ZERO
  3167  				}
  3168  			} else {
  3169  				// Use SLLI/SRLI sequence to extend.
  3170  				ins.as, ins.rs1, ins.rs2 = ASLLI, uint32(p.From.Reg), obj.REG_NONE
  3171  				if p.As == AMOVHU {
  3172  					ins.imm = 48
  3173  				} else if p.As == AMOVWU {
  3174  					ins.imm = 32
  3175  				}
  3176  				ins2 := &instruction{as: ASRLI, rd: ins.rd, rs1: ins.rd, imm: ins.imm}
  3177  				inss = append(inss, ins2)
  3178  			}
  3179  		}
  3180  
  3181  	case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG:
  3182  		// Memory to register loads.
  3183  		switch p.From.Name {
  3184  		case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
  3185  			// MOV c(Rs), Rd -> L $c, Rs, Rd
  3186  			inss = instructionsForLoad(p, movToLoad(p.As), addrToReg(p.From))
  3187  
  3188  		case obj.NAME_EXTERN, obj.NAME_STATIC, obj.NAME_GOTREF:
  3189  			if p.From.Sym.Type == objabi.STLSBSS {
  3190  				return instructionsForTLSLoad(p)
  3191  			}
  3192  
  3193  			// Note that the values for $off_hi and $off_lo are currently
  3194  			// zero and will be assigned during relocation. If the destination
  3195  			// is an integer register then we can use the same register for the
  3196  			// address computation, otherwise we need to use the temporary register.
  3197  			//
  3198  			// AUIPC $off_hi, Rd
  3199  			// L $off_lo, Rd, Rd
  3200  			//
  3201  			addrReg := ins.rd
  3202  			if addrReg < REG_X0 || addrReg > REG_X31 {
  3203  				addrReg = REG_TMP
  3204  			}
  3205  			insAUIPC := &instruction{as: AAUIPC, rd: addrReg}
  3206  			ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), addrReg, obj.REG_NONE, 0
  3207  			inss = []*instruction{insAUIPC, ins}
  3208  
  3209  		default:
  3210  			p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
  3211  			return nil
  3212  		}
  3213  
  3214  	case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM:
  3215  		// Register to memory stores.
  3216  		switch p.As {
  3217  		case AMOVBU, AMOVHU, AMOVWU:
  3218  			p.Ctxt.Diag("%v: unsupported unsigned store", p)
  3219  			return nil
  3220  		}
  3221  		switch p.To.Name {
  3222  		case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
  3223  			// MOV Rs, c(Rd) -> S $c, Rs, Rd
  3224  			inss = instructionsForStore(p, movToStore(p.As), addrToReg(p.To))
  3225  
  3226  		case obj.NAME_EXTERN, obj.NAME_STATIC:
  3227  			if p.To.Sym.Type == objabi.STLSBSS {
  3228  				return instructionsForTLSStore(p)
  3229  			}
  3230  
  3231  			// Note that the values for $off_hi and $off_lo are currently
  3232  			// zero and will be assigned during relocation.
  3233  			//
  3234  			// AUIPC $off_hi, Rtmp
  3235  			// S $off_lo, Rtmp, Rd
  3236  			insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
  3237  			ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
  3238  			inss = []*instruction{insAUIPC, ins}
  3239  
  3240  		default:
  3241  			p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
  3242  			return nil
  3243  		}
  3244  
  3245  	case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG:
  3246  		// MOV $sym+off(SP/SB), R
  3247  		if p.As != AMOV {
  3248  			p.Ctxt.Diag("%v: unsupported address load", p)
  3249  			return nil
  3250  		}
  3251  		switch p.From.Name {
  3252  		case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
  3253  			inss = instructionsForOpImmediate(p, AADDI, addrToReg(p.From))
  3254  
  3255  		case obj.NAME_EXTERN, obj.NAME_STATIC:
  3256  			// Note that the values for $off_hi and $off_lo are currently
  3257  			// zero and will be assigned during relocation.
  3258  			//
  3259  			// AUIPC $off_hi, R
  3260  			// ADDI $off_lo, R
  3261  			insAUIPC := &instruction{as: AAUIPC, rd: ins.rd}
  3262  			ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, ins.rd, obj.REG_NONE, 0
  3263  			inss = []*instruction{insAUIPC, ins}
  3264  
  3265  		default:
  3266  			p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
  3267  			return nil
  3268  		}
  3269  
  3270  	case p.From.Type == obj.TYPE_ADDR && p.To.Type != obj.TYPE_REG:
  3271  		p.Ctxt.Diag("%v: address load must target register", p)
  3272  		return nil
  3273  
  3274  	default:
  3275  		p.Ctxt.Diag("%v: unsupported MOV", p)
  3276  		return nil
  3277  	}
  3278  
  3279  	return inss
  3280  }
  3281  
  3282  // instructionsForRotate returns the machine instructions for a bitwise rotation.
  3283  func instructionsForRotate(p *obj.Prog, ins *instruction) []*instruction {
  3284  	if buildcfg.GORISCV64 >= 22 {
  3285  		// Rotation instructions are supported natively.
  3286  		return []*instruction{ins}
  3287  	}
  3288  
  3289  	switch ins.as {
  3290  	case AROL, AROLW, AROR, ARORW:
  3291  		// ROL -> OR (SLL x y) (SRL x (NEG y))
  3292  		// ROR -> OR (SRL x y) (SLL x (NEG y))
  3293  		sllOp, srlOp := ASLL, ASRL
  3294  		if ins.as == AROLW || ins.as == ARORW {
  3295  			sllOp, srlOp = ASLLW, ASRLW
  3296  		}
  3297  		shift1, shift2 := sllOp, srlOp
  3298  		if ins.as == AROR || ins.as == ARORW {
  3299  			shift1, shift2 = shift2, shift1
  3300  		}
  3301  		return []*instruction{
  3302  			&instruction{as: ASUB, rs1: REG_ZERO, rs2: ins.rs2, rd: REG_TMP},
  3303  			&instruction{as: shift2, rs1: ins.rs1, rs2: REG_TMP, rd: REG_TMP},
  3304  			&instruction{as: shift1, rs1: ins.rs1, rs2: ins.rs2, rd: ins.rd},
  3305  			&instruction{as: AOR, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
  3306  		}
  3307  
  3308  	case ARORI, ARORIW:
  3309  		// ROR -> OR (SLLI -x y) (SRLI x y)
  3310  		sllOp, srlOp := ASLLI, ASRLI
  3311  		sllImm := int64(int8(-ins.imm) & 63)
  3312  		if ins.as == ARORIW {
  3313  			sllOp, srlOp = ASLLIW, ASRLIW
  3314  			sllImm = int64(int8(-ins.imm) & 31)
  3315  		}
  3316  		return []*instruction{
  3317  			&instruction{as: srlOp, rs1: ins.rs1, rd: REG_TMP, imm: ins.imm},
  3318  			&instruction{as: sllOp, rs1: ins.rs1, rd: ins.rd, imm: sllImm},
  3319  			&instruction{as: AOR, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
  3320  		}
  3321  
  3322  	default:
  3323  		p.Ctxt.Diag("%v: unknown rotation", p)
  3324  		return nil
  3325  	}
  3326  }
  3327  
  3328  // instructionsForMinMax returns the machine instructions for an integer minimum or maximum.
  3329  func instructionsForMinMax(p *obj.Prog, ins *instruction) []*instruction {
  3330  	if buildcfg.GORISCV64 >= 22 {
  3331  		// Minimum and maximum instructions are supported natively.
  3332  		return []*instruction{ins}
  3333  	}
  3334  
  3335  	// Generate a move for identical inputs.
  3336  	if ins.rs1 == ins.rs2 {
  3337  		ins.as, ins.rs2, ins.imm = AADDI, obj.REG_NONE, 0
  3338  		return []*instruction{ins}
  3339  	}
  3340  
  3341  	// Ensure that if one of the source registers is the same as the destination,
  3342  	// it is processed first.
  3343  	if ins.rs1 == ins.rd {
  3344  		ins.rs1, ins.rs2 = ins.rs2, ins.rs1
  3345  	}
  3346  	sltReg1, sltReg2 := ins.rs2, ins.rs1
  3347  
  3348  	// MIN -> SLT/SUB/XOR/AND/XOR
  3349  	// MAX -> SLT/SUB/XOR/AND/XOR with swapped inputs to SLT
  3350  	switch ins.as {
  3351  	case AMIN:
  3352  		ins.as = ASLT
  3353  	case AMAX:
  3354  		ins.as, sltReg1, sltReg2 = ASLT, sltReg2, sltReg1
  3355  	case AMINU:
  3356  		ins.as = ASLTU
  3357  	case AMAXU:
  3358  		ins.as, sltReg1, sltReg2 = ASLTU, sltReg2, sltReg1
  3359  	}
  3360  	return []*instruction{
  3361  		&instruction{as: ins.as, rs1: sltReg1, rs2: sltReg2, rd: REG_TMP},
  3362  		&instruction{as: ASUB, rs1: REG_ZERO, rs2: REG_TMP, rd: REG_TMP},
  3363  		&instruction{as: AXOR, rs1: ins.rs1, rs2: ins.rs2, rd: ins.rd},
  3364  		&instruction{as: AAND, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
  3365  		&instruction{as: AXOR, rs1: ins.rs1, rs2: ins.rd, rd: ins.rd},
  3366  	}
  3367  }
  3368  
  3369  // instructionsForProg returns the machine instructions for an *obj.Prog.
  3370  func instructionsForProg(p *obj.Prog) []*instruction {
  3371  	ins := instructionForProg(p)
  3372  	inss := []*instruction{ins}
  3373  
  3374  	if ins.as == AVSETVLI || ins.as == AVSETIVLI {
  3375  		if len(p.RestArgs) != 4 {
  3376  			p.Ctxt.Diag("incorrect number of arguments for instruction")
  3377  			return nil
  3378  		}
  3379  	} else if len(p.RestArgs) > 1 {
  3380  		p.Ctxt.Diag("too many source registers")
  3381  		return nil
  3382  	}
  3383  
  3384  	switch ins.as {
  3385  	case AJAL, AJALR:
  3386  		ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.To.Reg), obj.REG_NONE
  3387  		ins.imm = p.To.Offset
  3388  
  3389  	case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ:
  3390  		switch ins.as {
  3391  		case ABEQZ:
  3392  			ins.as, ins.rs1, ins.rs2 = ABEQ, REG_ZERO, uint32(p.From.Reg)
  3393  		case ABGEZ:
  3394  			ins.as, ins.rs1, ins.rs2 = ABGE, REG_ZERO, uint32(p.From.Reg)
  3395  		case ABGT:
  3396  			ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), uint32(p.Reg)
  3397  		case ABGTU:
  3398  			ins.as, ins.rs1, ins.rs2 = ABLTU, uint32(p.From.Reg), uint32(p.Reg)
  3399  		case ABGTZ:
  3400  			ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), REG_ZERO
  3401  		case ABLE:
  3402  			ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), uint32(p.Reg)
  3403  		case ABLEU:
  3404  			ins.as, ins.rs1, ins.rs2 = ABGEU, uint32(p.From.Reg), uint32(p.Reg)
  3405  		case ABLEZ:
  3406  			ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), REG_ZERO
  3407  		case ABLTZ:
  3408  			ins.as, ins.rs1, ins.rs2 = ABLT, REG_ZERO, uint32(p.From.Reg)
  3409  		case ABNEZ:
  3410  			ins.as, ins.rs1, ins.rs2 = ABNE, REG_ZERO, uint32(p.From.Reg)
  3411  		}
  3412  		ins.imm = p.To.Offset
  3413  
  3414  	case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
  3415  		inss = instructionsForMOV(p)
  3416  
  3417  	case ALW, ALWU, ALH, ALHU, ALB, ALBU, ALD, AFLW, AFLD:
  3418  		inss = instructionsForLoad(p, ins.as, p.From.Reg)
  3419  
  3420  	case ASW, ASH, ASB, ASD, AFSW, AFSD:
  3421  		inss = instructionsForStore(p, ins.as, p.To.Reg)
  3422  
  3423  	case ALRW, ALRD:
  3424  		// Set aq to use acquire access ordering
  3425  		ins.funct7 = 2
  3426  		ins.rs1, ins.rs2 = uint32(p.From.Reg), REG_ZERO
  3427  
  3428  	case AADDI, AANDI, AORI, AXORI:
  3429  		inss = instructionsForOpImmediate(p, ins.as, p.Reg)
  3430  
  3431  	case ASCW, ASCD:
  3432  		// Set release access ordering
  3433  		ins.funct7 = 1
  3434  		ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg)
  3435  
  3436  	case AAMOSWAPW, AAMOSWAPD, AAMOADDW, AAMOADDD, AAMOANDW, AAMOANDD, AAMOORW, AAMOORD,
  3437  		AAMOXORW, AAMOXORD, AAMOMINW, AAMOMIND, AAMOMINUW, AAMOMINUD, AAMOMAXW, AAMOMAXD, AAMOMAXUW, AAMOMAXUD:
  3438  		// Set aqrl to use acquire & release access ordering
  3439  		ins.funct7 = 3
  3440  		ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg)
  3441  
  3442  	case AECALL, AEBREAK:
  3443  		insEnc := encode(p.As)
  3444  		if p.To.Type == obj.TYPE_NONE {
  3445  			ins.rd = REG_ZERO
  3446  		}
  3447  		ins.rs1 = REG_ZERO
  3448  		ins.imm = insEnc.csr
  3449  
  3450  	case ARDCYCLE, ARDTIME, ARDINSTRET:
  3451  		ins.as = ACSRRS
  3452  		if p.To.Type == obj.TYPE_NONE {
  3453  			ins.rd = REG_ZERO
  3454  		}
  3455  		ins.rs1 = REG_ZERO
  3456  		switch p.As {
  3457  		case ARDCYCLE:
  3458  			ins.imm = -1024
  3459  		case ARDTIME:
  3460  			ins.imm = -1023
  3461  		case ARDINSTRET:
  3462  			ins.imm = -1022
  3463  		}
  3464  
  3465  	case AFENCE:
  3466  		ins.rd, ins.rs1, ins.rs2 = REG_ZERO, REG_ZERO, obj.REG_NONE
  3467  		ins.imm = 0x0ff
  3468  
  3469  	case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
  3470  		// Set the default rounding mode in funct3 to round to zero.
  3471  		if p.Scond&rmSuffixBit == 0 {
  3472  			ins.funct3 = uint32(RM_RTZ)
  3473  		} else {
  3474  			ins.funct3 = uint32(p.Scond &^ rmSuffixBit)
  3475  		}
  3476  
  3477  	case AFNES, AFNED:
  3478  		// Replace FNE[SD] with FEQ[SD] and NOT.
  3479  		if p.To.Type != obj.TYPE_REG {
  3480  			p.Ctxt.Diag("%v needs an integer register output", p)
  3481  			return nil
  3482  		}
  3483  		if ins.as == AFNES {
  3484  			ins.as = AFEQS
  3485  		} else {
  3486  			ins.as = AFEQD
  3487  		}
  3488  		ins2 := &instruction{
  3489  			as:  AXORI, // [bit] xor 1 = not [bit]
  3490  			rd:  ins.rd,
  3491  			rs1: ins.rd,
  3492  			imm: 1,
  3493  		}
  3494  		inss = append(inss, ins2)
  3495  
  3496  	case AFSQRTS, AFSQRTD:
  3497  		// These instructions expect a zero (i.e. float register 0)
  3498  		// to be the second input operand.
  3499  		ins.rs1 = uint32(p.From.Reg)
  3500  		ins.rs2 = REG_F0
  3501  
  3502  	case AFMADDS, AFMSUBS, AFNMADDS, AFNMSUBS,
  3503  		AFMADDD, AFMSUBD, AFNMADDD, AFNMSUBD:
  3504  		// Swap the first two operands so that the operands are in the same
  3505  		// order as they are in the specification: RS1, RS2, RS3, RD.
  3506  		ins.rs1, ins.rs2 = ins.rs2, ins.rs1
  3507  
  3508  	case ANEG, ANEGW:
  3509  		// NEG rs, rd -> SUB rs, X0, rd
  3510  		ins.as = ASUB
  3511  		if p.As == ANEGW {
  3512  			ins.as = ASUBW
  3513  		}
  3514  		ins.rs1 = REG_ZERO
  3515  		if ins.rd == obj.REG_NONE {
  3516  			ins.rd = ins.rs2
  3517  		}
  3518  
  3519  	case ANOT:
  3520  		// NOT rs, rd -> XORI $-1, rs, rd
  3521  		ins.as = AXORI
  3522  		ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
  3523  		if ins.rd == obj.REG_NONE {
  3524  			ins.rd = ins.rs1
  3525  		}
  3526  		ins.imm = -1
  3527  
  3528  	case ASEQZ:
  3529  		// SEQZ rs, rd -> SLTIU $1, rs, rd
  3530  		ins.as = ASLTIU
  3531  		ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
  3532  		ins.imm = 1
  3533  
  3534  	case ASNEZ:
  3535  		// SNEZ rs, rd -> SLTU rs, x0, rd
  3536  		ins.as = ASLTU
  3537  		ins.rs1 = REG_ZERO
  3538  
  3539  	case AFABSS:
  3540  		// FABSS rs, rd -> FSGNJXS rs, rs, rd
  3541  		ins.as = AFSGNJXS
  3542  		ins.rs1 = uint32(p.From.Reg)
  3543  
  3544  	case AFABSD:
  3545  		// FABSD rs, rd -> FSGNJXD rs, rs, rd
  3546  		ins.as = AFSGNJXD
  3547  		ins.rs1 = uint32(p.From.Reg)
  3548  
  3549  	case AFNEGS:
  3550  		// FNEGS rs, rd -> FSGNJNS rs, rs, rd
  3551  		ins.as = AFSGNJNS
  3552  		ins.rs1 = uint32(p.From.Reg)
  3553  
  3554  	case AFNEGD:
  3555  		// FNEGD rs, rd -> FSGNJND rs, rs, rd
  3556  		ins.as = AFSGNJND
  3557  		ins.rs1 = uint32(p.From.Reg)
  3558  
  3559  	case AROL, AROLW, AROR, ARORW:
  3560  		inss = instructionsForRotate(p, ins)
  3561  
  3562  	case ARORI:
  3563  		if ins.imm < 0 || ins.imm > 63 {
  3564  			p.Ctxt.Diag("%v: immediate out of range 0 to 63", p)
  3565  		}
  3566  		inss = instructionsForRotate(p, ins)
  3567  
  3568  	case ARORIW:
  3569  		if ins.imm < 0 || ins.imm > 31 {
  3570  			p.Ctxt.Diag("%v: immediate out of range 0 to 31", p)
  3571  		}
  3572  		inss = instructionsForRotate(p, ins)
  3573  
  3574  	case ASLLI, ASRLI, ASRAI:
  3575  		if ins.imm < 0 || ins.imm > 63 {
  3576  			p.Ctxt.Diag("%v: immediate out of range 0 to 63", p)
  3577  		}
  3578  
  3579  	case ASLLIW, ASRLIW, ASRAIW:
  3580  		if ins.imm < 0 || ins.imm > 31 {
  3581  			p.Ctxt.Diag("%v: immediate out of range 0 to 31", p)
  3582  		}
  3583  
  3584  	case ACLZ, ACLZW, ACTZ, ACTZW, ACPOP, ACPOPW, ASEXTB, ASEXTH, AZEXTH:
  3585  		ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
  3586  
  3587  	case AORCB, AREV8:
  3588  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
  3589  
  3590  	case AANDN, AORN:
  3591  		if buildcfg.GORISCV64 >= 22 {
  3592  			// ANDN and ORN instructions are supported natively.
  3593  			break
  3594  		}
  3595  		// ANDN -> (AND (NOT x) y)
  3596  		// ORN  -> (OR  (NOT x) y)
  3597  		bitwiseOp, notReg := AAND, ins.rd
  3598  		if ins.as == AORN {
  3599  			bitwiseOp = AOR
  3600  		}
  3601  		if ins.rs1 == notReg {
  3602  			notReg = REG_TMP
  3603  		}
  3604  		inss = []*instruction{
  3605  			&instruction{as: AXORI, rs1: ins.rs2, rs2: obj.REG_NONE, rd: notReg, imm: -1},
  3606  			&instruction{as: bitwiseOp, rs1: ins.rs1, rs2: notReg, rd: ins.rd},
  3607  		}
  3608  
  3609  	case AXNOR:
  3610  		if buildcfg.GORISCV64 >= 22 {
  3611  			// XNOR instruction is supported natively.
  3612  			break
  3613  		}
  3614  		// XNOR -> (NOT (XOR x y))
  3615  		ins.as = AXOR
  3616  		inss = append(inss, &instruction{as: AXORI, rs1: ins.rd, rs2: obj.REG_NONE, rd: ins.rd, imm: -1})
  3617  
  3618  	case AMIN, AMAX, AMINU, AMAXU:
  3619  		inss = instructionsForMinMax(p, ins)
  3620  
  3621  	case AVSETVLI, AVSETIVLI:
  3622  		ins.rs1, ins.rs2 = ins.rs2, obj.REG_NONE
  3623  		vtype, err := EncodeVectorType(p.RestArgs[0].Offset, p.RestArgs[1].Offset, p.RestArgs[2].Offset, p.RestArgs[3].Offset)
  3624  		if err != nil {
  3625  			p.Ctxt.Diag("%v: %v", p, err)
  3626  		}
  3627  		ins.imm = int64(vtype)
  3628  		if ins.as == AVSETIVLI {
  3629  			if p.From.Type != obj.TYPE_CONST {
  3630  				p.Ctxt.Diag("%v: expected immediate value", p)
  3631  			}
  3632  			ins.rs1 = uint32(p.From.Offset)
  3633  		}
  3634  
  3635  	case AVLE8V, AVLE16V, AVLE32V, AVLE64V, AVSE8V, AVSE16V, AVSE32V, AVSE64V, AVLMV, AVSMV:
  3636  		// Set mask bit
  3637  		switch {
  3638  		case ins.rs1 == obj.REG_NONE:
  3639  			ins.funct7 |= 1 // unmasked
  3640  		case ins.rs1 != REG_V0:
  3641  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3642  		}
  3643  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
  3644  
  3645  	case AVLSE8V, AVLSE16V, AVLSE32V, AVLSE64V,
  3646  		AVLUXEI8V, AVLUXEI16V, AVLUXEI32V, AVLUXEI64V, AVLOXEI8V, AVLOXEI16V, AVLOXEI32V, AVLOXEI64V:
  3647  		// Set mask bit
  3648  		switch {
  3649  		case ins.rs3 == obj.REG_NONE:
  3650  			ins.funct7 |= 1 // unmasked
  3651  		case ins.rs3 != REG_V0:
  3652  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3653  		}
  3654  		ins.rs1, ins.rs2, ins.rs3 = ins.rs2, ins.rs1, obj.REG_NONE
  3655  
  3656  	case AVSSE8V, AVSSE16V, AVSSE32V, AVSSE64V,
  3657  		AVSUXEI8V, AVSUXEI16V, AVSUXEI32V, AVSUXEI64V, AVSOXEI8V, AVSOXEI16V, AVSOXEI32V, AVSOXEI64V:
  3658  		// Set mask bit
  3659  		switch {
  3660  		case ins.rs3 == obj.REG_NONE:
  3661  			ins.funct7 |= 1 // unmasked
  3662  		case ins.rs3 != REG_V0:
  3663  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3664  		}
  3665  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = ins.rs2, ins.rd, ins.rs1, obj.REG_NONE
  3666  
  3667  	case AVL1RV, AVL1RE8V, AVL1RE16V, AVL1RE32V, AVL1RE64V, AVL2RV, AVL2RE8V, AVL2RE16V, AVL2RE32V, AVL2RE64V,
  3668  		AVL4RV, AVL4RE8V, AVL4RE16V, AVL4RE32V, AVL4RE64V, AVL8RV, AVL8RE8V, AVL8RE16V, AVL8RE32V, AVL8RE64V:
  3669  		switch ins.as {
  3670  		case AVL1RV:
  3671  			ins.as = AVL1RE8V
  3672  		case AVL2RV:
  3673  			ins.as = AVL2RE8V
  3674  		case AVL4RV:
  3675  			ins.as = AVL4RE8V
  3676  		case AVL8RV:
  3677  			ins.as = AVL8RE8V
  3678  		}
  3679  		if ins.rs1 != obj.REG_NONE {
  3680  			p.Ctxt.Diag("%v: too many operands for instruction", p)
  3681  		}
  3682  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
  3683  
  3684  	case AVS1RV, AVS2RV, AVS4RV, AVS8RV:
  3685  		if ins.rs1 != obj.REG_NONE {
  3686  			p.Ctxt.Diag("%v: too many operands for instruction", p)
  3687  		}
  3688  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
  3689  
  3690  	case AVADDVV, AVADDVX, AVSUBVV, AVSUBVX, AVRSUBVX, AVWADDUVV, AVWADDUVX, AVWSUBUVV, AVWSUBUVX,
  3691  		AVWADDVV, AVWADDVX, AVWSUBVV, AVWSUBVX, AVWADDUWV, AVWADDUWX, AVWSUBUWV, AVWSUBUWX,
  3692  		AVWADDWV, AVWADDWX, AVWSUBWV, AVWSUBWX, AVANDVV, AVANDVX, AVORVV, AVORVX, AVXORVV, AVXORVX,
  3693  		AVSLLVV, AVSLLVX, AVSRLVV, AVSRLVX, AVSRAVV, AVSRAVX,
  3694  		AVMSEQVV, AVMSEQVX, AVMSNEVV, AVMSNEVX, AVMSLTUVV, AVMSLTUVX, AVMSLTVV, AVMSLTVX,
  3695  		AVMSLEUVV, AVMSLEUVX, AVMSLEVV, AVMSLEVX, AVMSGTUVX, AVMSGTVX,
  3696  		AVMINUVV, AVMINUVX, AVMINVV, AVMINVX, AVMAXUVV, AVMAXUVX, AVMAXVV, AVMAXVX,
  3697  		AVMULVV, AVMULVX, AVMULHVV, AVMULHVX, AVMULHUVV, AVMULHUVX, AVMULHSUVV, AVMULHSUVX,
  3698  		AVDIVUVV, AVDIVUVX, AVDIVVV, AVDIVVX, AVREMUVV, AVREMUVX, AVREMVV, AVREMVX,
  3699  		AVWMULVV, AVWMULVX, AVWMULUVV, AVWMULUVX, AVWMULSUVV, AVWMULSUVX, AVNSRLWV, AVNSRLWX, AVNSRAWV, AVNSRAWX,
  3700  		AVMACCVV, AVMACCVX, AVNMSACVV, AVNMSACVX, AVMADDVV, AVMADDVX, AVNMSUBVV, AVNMSUBVX,
  3701  		AVWMACCUVV, AVWMACCUVX, AVWMACCVV, AVWMACCVX, AVWMACCSUVV, AVWMACCSUVX, AVWMACCUSVX,
  3702  		AVSADDUVV, AVSADDUVX, AVSADDUVI, AVSADDVV, AVSADDVX, AVSADDVI, AVSSUBUVV, AVSSUBUVX, AVSSUBVV, AVSSUBVX,
  3703  		AVAADDUVV, AVAADDUVX, AVAADDVV, AVAADDVX, AVASUBUVV, AVASUBUVX, AVASUBVV, AVASUBVX,
  3704  		AVSMULVV, AVSMULVX, AVSSRLVV, AVSSRLVX, AVSSRLVI, AVSSRAVV, AVSSRAVX, AVSSRAVI,
  3705  		AVNCLIPUWV, AVNCLIPUWX, AVNCLIPUWI, AVNCLIPWV, AVNCLIPWX, AVNCLIPWI,
  3706  		AVFADDVV, AVFADDVF, AVFSUBVV, AVFSUBVF, AVFRSUBVF,
  3707  		AVFWADDVV, AVFWADDVF, AVFWSUBVV, AVFWSUBVF, AVFWADDWV, AVFWADDWF, AVFWSUBWV, AVFWSUBWF,
  3708  		AVFMULVV, AVFMULVF, AVFDIVVV, AVFDIVVF, AVFRDIVVF, AVFWMULVV, AVFWMULVF,
  3709  		AVFMINVV, AVFMINVF, AVFMAXVV, AVFMAXVF,
  3710  		AVFSGNJVV, AVFSGNJVF, AVFSGNJNVV, AVFSGNJNVF, AVFSGNJXVV, AVFSGNJXVF,
  3711  		AVMFEQVV, AVMFEQVF, AVMFNEVV, AVMFNEVF, AVMFLTVV, AVMFLTVF, AVMFLEVV, AVMFLEVF, AVMFGTVF, AVMFGEVF,
  3712  		AVREDSUMVS, AVREDMAXUVS, AVREDMAXVS, AVREDMINUVS, AVREDMINVS, AVREDANDVS, AVREDORVS, AVREDXORVS,
  3713  		AVWREDSUMUVS, AVWREDSUMVS, AVFREDOSUMVS, AVFREDUSUMVS, AVFREDMAXVS, AVFREDMINVS, AVFWREDOSUMVS, AVFWREDUSUMVS,
  3714  		AVSLIDEUPVX, AVSLIDEDOWNVX, AVSLIDE1UPVX, AVFSLIDE1UPVF, AVSLIDE1DOWNVX, AVFSLIDE1DOWNVF,
  3715  		AVRGATHERVV, AVRGATHEREI16VV, AVRGATHERVX:
  3716  		// Set mask bit
  3717  		switch {
  3718  		case ins.rs3 == obj.REG_NONE:
  3719  			ins.funct7 |= 1 // unmasked
  3720  		case ins.rs3 != REG_V0:
  3721  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3722  		}
  3723  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), obj.REG_NONE
  3724  
  3725  	case AVFMACCVV, AVFMACCVF, AVFNMACCVV, AVFNMACCVF, AVFMSACVV, AVFMSACVF, AVFNMSACVV, AVFNMSACVF,
  3726  		AVFMADDVV, AVFMADDVF, AVFNMADDVV, AVFNMADDVF, AVFMSUBVV, AVFMSUBVF, AVFNMSUBVV, AVFNMSUBVF,
  3727  		AVFWMACCVV, AVFWMACCVF, AVFWNMACCVV, AVFWNMACCVF, AVFWMSACVV, AVFWMSACVF, AVFWNMSACVV, AVFWNMSACVF:
  3728  		switch {
  3729  		case ins.rs3 == obj.REG_NONE:
  3730  			ins.funct7 |= 1 // unmasked
  3731  		case ins.rs3 != REG_V0:
  3732  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3733  		}
  3734  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.Reg), uint32(p.From.Reg), obj.REG_NONE
  3735  
  3736  	case AVADDVI, AVRSUBVI, AVANDVI, AVORVI, AVXORVI, AVMSEQVI, AVMSNEVI, AVMSLEUVI, AVMSLEVI, AVMSGTUVI, AVMSGTVI,
  3737  		AVSLLVI, AVSRLVI, AVSRAVI, AVNSRLWI, AVNSRAWI, AVRGATHERVI, AVSLIDEUPVI, AVSLIDEDOWNVI:
  3738  		// Set mask bit
  3739  		switch {
  3740  		case ins.rs3 == obj.REG_NONE:
  3741  			ins.funct7 |= 1 // unmasked
  3742  		case ins.rs3 != REG_V0:
  3743  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3744  		}
  3745  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), obj.REG_NONE, uint32(p.Reg), obj.REG_NONE
  3746  
  3747  	case AVZEXTVF2, AVSEXTVF2, AVZEXTVF4, AVSEXTVF4, AVZEXTVF8, AVSEXTVF8, AVFSQRTV, AVFRSQRT7V, AVFREC7V, AVFCLASSV,
  3748  		AVFCVTXUFV, AVFCVTXFV, AVFCVTRTZXUFV, AVFCVTRTZXFV, AVFCVTFXUV, AVFCVTFXV,
  3749  		AVFWCVTXUFV, AVFWCVTXFV, AVFWCVTRTZXUFV, AVFWCVTRTZXFV, AVFWCVTFXUV, AVFWCVTFXV, AVFWCVTFFV,
  3750  		AVFNCVTXUFW, AVFNCVTXFW, AVFNCVTRTZXUFW, AVFNCVTRTZXFW, AVFNCVTFXUW, AVFNCVTFXW, AVFNCVTFFW, AVFNCVTRODFFW:
  3751  		// Set mask bit
  3752  		switch {
  3753  		case ins.rs1 == obj.REG_NONE:
  3754  			ins.funct7 |= 1 // unmasked
  3755  		case ins.rs1 != REG_V0:
  3756  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3757  		}
  3758  		ins.rs1 = obj.REG_NONE
  3759  
  3760  	case AVMVVV, AVMVVX:
  3761  		if ins.rs1 != obj.REG_NONE {
  3762  			p.Ctxt.Diag("%v: too many operands for instruction", p)
  3763  		}
  3764  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), REG_V0
  3765  
  3766  	case AVMVVI:
  3767  		if ins.rs1 != obj.REG_NONE {
  3768  			p.Ctxt.Diag("%v: too many operands for instruction", p)
  3769  		}
  3770  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), obj.REG_NONE, REG_V0
  3771  
  3772  	case AVFMVVF:
  3773  		ins.funct7 |= 1 // unmasked
  3774  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), REG_V0
  3775  
  3776  	case AVADCVIM, AVADCVVM, AVADCVXM, AVSBCVVM, AVSBCVXM:
  3777  		if ins.rd == REG_V0 {
  3778  			p.Ctxt.Diag("%v: invalid destination register V0", p)
  3779  		}
  3780  		fallthrough
  3781  
  3782  	case AVMADCVVM, AVMADCVXM, AVMSBCVVM, AVMSBCVXM, AVMADCVIM, AVMERGEVVM, AVMERGEVXM, AVMERGEVIM, AVFMERGEVFM:
  3783  		if ins.rs3 != REG_V0 {
  3784  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3785  		}
  3786  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), obj.REG_NONE
  3787  
  3788  	case AVMADCVV, AVMADCVX, AVMSBCVV, AVMSBCVX, AVMADCVI:
  3789  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)
  3790  
  3791  	case AVNEGV, AVWCVTXXV, AVWCVTUXXV, AVNCVTXXW:
  3792  		// Set mask bit
  3793  		switch {
  3794  		case ins.rs1 == obj.REG_NONE:
  3795  			ins.funct7 |= 1 // unmasked
  3796  		case ins.rs1 != REG_V0:
  3797  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3798  		}
  3799  		switch ins.as {
  3800  		case AVNEGV:
  3801  			ins.as = AVRSUBVX
  3802  		case AVWCVTXXV:
  3803  			ins.as = AVWADDVX
  3804  		case AVWCVTUXXV:
  3805  			ins.as = AVWADDUVX
  3806  		case AVNCVTXXW:
  3807  			ins.as = AVNSRLWX
  3808  		}
  3809  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), REG_X0, uint32(p.From.Reg)
  3810  
  3811  	case AVNOTV:
  3812  		// Set mask bit
  3813  		switch {
  3814  		case ins.rs1 == obj.REG_NONE:
  3815  			ins.funct7 |= 1 // unmasked
  3816  		case ins.rs1 != REG_V0:
  3817  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3818  		}
  3819  		ins.as = AVXORVI
  3820  		ins.rd, ins.rs1, ins.rs2, ins.imm = uint32(p.To.Reg), obj.REG_NONE, uint32(p.From.Reg), -1
  3821  
  3822  	case AVMSGTVV, AVMSGTUVV, AVMSGEVV, AVMSGEUVV, AVMFGTVV, AVMFGEVV:
  3823  		// Set mask bit
  3824  		switch {
  3825  		case ins.rs3 == obj.REG_NONE:
  3826  			ins.funct7 |= 1 // unmasked
  3827  		case ins.rs3 != REG_V0:
  3828  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3829  		}
  3830  		switch ins.as {
  3831  		case AVMSGTVV:
  3832  			ins.as = AVMSLTVV
  3833  		case AVMSGTUVV:
  3834  			ins.as = AVMSLTUVV
  3835  		case AVMSGEVV:
  3836  			ins.as = AVMSLEVV
  3837  		case AVMSGEUVV:
  3838  			ins.as = AVMSLEUVV
  3839  		case AVMFGTVV:
  3840  			ins.as = AVMFLTVV
  3841  		case AVMFGEVV:
  3842  			ins.as = AVMFLEVV
  3843  		}
  3844  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.Reg), uint32(p.From.Reg), obj.REG_NONE
  3845  
  3846  	case AVMSLTVI, AVMSLTUVI, AVMSGEVI, AVMSGEUVI:
  3847  		// Set mask bit
  3848  		switch {
  3849  		case ins.rs3 == obj.REG_NONE:
  3850  			ins.funct7 |= 1 // unmasked
  3851  		case ins.rs3 != REG_V0:
  3852  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3853  		}
  3854  		switch ins.as {
  3855  		case AVMSLTVI:
  3856  			ins.as = AVMSLEVI
  3857  		case AVMSLTUVI:
  3858  			ins.as = AVMSLEUVI
  3859  		case AVMSGEVI:
  3860  			ins.as = AVMSGTVI
  3861  		case AVMSGEUVI:
  3862  			ins.as = AVMSGTUVI
  3863  		}
  3864  		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
  3865  
  3866  	case AVFABSV, AVFNEGV:
  3867  		// Set mask bit
  3868  		switch {
  3869  		case ins.rs1 == obj.REG_NONE:
  3870  			ins.funct7 |= 1 // unmasked
  3871  		case ins.rs1 != REG_V0:
  3872  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3873  		}
  3874  		switch ins.as {
  3875  		case AVFABSV:
  3876  			ins.as = AVFSGNJXVV
  3877  		case AVFNEGV:
  3878  			ins.as = AVFSGNJNVV
  3879  		}
  3880  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.From.Reg)
  3881  
  3882  	case AVMANDMM, AVMNANDMM, AVMANDNMM, AVMXORMM, AVMORMM, AVMNORMM, AVMORNMM, AVMXNORMM, AVMMVM, AVMNOTM, AVCOMPRESSVM:
  3883  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)
  3884  		switch ins.as {
  3885  		case AVMMVM:
  3886  			ins.as, ins.rs2 = AVMANDMM, ins.rs1
  3887  		case AVMNOTM:
  3888  			ins.as, ins.rs2 = AVMNANDMM, ins.rs1
  3889  		}
  3890  
  3891  	case AVMCLRM, AVMSETM:
  3892  		ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.From.Reg), uint32(p.From.Reg)
  3893  		switch ins.as {
  3894  		case AVMCLRM:
  3895  			ins.as = AVMXORMM
  3896  		case AVMSETM:
  3897  			ins.as = AVMXNORMM
  3898  		}
  3899  
  3900  	case AVCPOPM, AVFIRSTM, AVMSBFM, AVMSIFM, AVMSOFM, AVIOTAM:
  3901  		// Set mask bit
  3902  		switch {
  3903  		case ins.rs1 == obj.REG_NONE:
  3904  			ins.funct7 |= 1 // unmasked
  3905  		case ins.rs1 != REG_V0:
  3906  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3907  		}
  3908  		ins.rs1 = obj.REG_NONE
  3909  
  3910  	case AVIDV:
  3911  		// Set mask bit
  3912  		switch {
  3913  		case ins.rd == obj.REG_NONE:
  3914  			ins.funct7 |= 1 // unmasked
  3915  		case ins.rd != obj.REG_NONE && ins.rs2 != REG_V0:
  3916  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  3917  		}
  3918  		if ins.rd == obj.REG_NONE {
  3919  			ins.rd = uint32(p.From.Reg)
  3920  		}
  3921  		ins.rs1, ins.rs2 = obj.REG_NONE, REG_V0
  3922  	}
  3923  
  3924  	for _, ins := range inss {
  3925  		ins.p = p
  3926  	}
  3927  
  3928  	return inss
  3929  }
  3930  
  3931  // assemble emits machine code.
  3932  // It is called at the very end of the assembly process.
  3933  func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
  3934  	if ctxt.Retpoline {
  3935  		ctxt.Diag("-spectre=ret not supported on riscv")
  3936  		ctxt.Retpoline = false // don't keep printing
  3937  	}
  3938  
  3939  	// If errors were encountered during preprocess/validation, proceeding
  3940  	// and attempting to encode said instructions will only lead to panics.
  3941  	if ctxt.Errors > 0 {
  3942  		return
  3943  	}
  3944  
  3945  	for p := cursym.Func().Text; p != nil; p = p.Link {
  3946  		switch p.As {
  3947  		case AJAL:
  3948  			if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC {
  3949  				cursym.AddRel(ctxt, obj.Reloc{
  3950  					Type: objabi.R_RISCV_JAL,
  3951  					Off:  int32(p.Pc),
  3952  					Siz:  4,
  3953  					Sym:  p.To.Sym,
  3954  					Add:  p.To.Offset,
  3955  				})
  3956  			}
  3957  		case AJALR:
  3958  			if p.To.Sym != nil {
  3959  				ctxt.Diag("%v: unexpected AJALR with to symbol", p)
  3960  			}
  3961  
  3962  		case AAUIPC, AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
  3963  			var addr *obj.Addr
  3964  			var rt objabi.RelocType
  3965  			if p.Mark&NEED_CALL_RELOC == NEED_CALL_RELOC {
  3966  				rt = objabi.R_RISCV_CALL
  3967  				addr = &p.From
  3968  			} else if p.Mark&NEED_PCREL_ITYPE_RELOC == NEED_PCREL_ITYPE_RELOC {
  3969  				rt = objabi.R_RISCV_PCREL_ITYPE
  3970  				addr = &p.From
  3971  			} else if p.Mark&NEED_PCREL_STYPE_RELOC == NEED_PCREL_STYPE_RELOC {
  3972  				rt = objabi.R_RISCV_PCREL_STYPE
  3973  				addr = &p.To
  3974  			} else if p.Mark&NEED_GOT_PCREL_ITYPE_RELOC == NEED_GOT_PCREL_ITYPE_RELOC {
  3975  				rt = objabi.R_RISCV_GOT_PCREL_ITYPE
  3976  				addr = &p.From
  3977  			} else {
  3978  				break
  3979  			}
  3980  			if p.As == AAUIPC {
  3981  				if p.Link == nil {
  3982  					ctxt.Diag("AUIPC needing PC-relative reloc missing following instruction")
  3983  					break
  3984  				}
  3985  				addr = &p.RestArgs[0].Addr
  3986  			}
  3987  			if addr.Sym == nil {
  3988  				ctxt.Diag("PC-relative relocation missing symbol")
  3989  				break
  3990  			}
  3991  			if addr.Sym.Type == objabi.STLSBSS {
  3992  				if ctxt.Flag_shared {
  3993  					rt = objabi.R_RISCV_TLS_IE
  3994  				} else {
  3995  					rt = objabi.R_RISCV_TLS_LE
  3996  				}
  3997  			}
  3998  
  3999  			cursym.AddRel(ctxt, obj.Reloc{
  4000  				Type: rt,
  4001  				Off:  int32(p.Pc),
  4002  				Siz:  8,
  4003  				Sym:  addr.Sym,
  4004  				Add:  addr.Offset,
  4005  			})
  4006  
  4007  		case obj.APCALIGN:
  4008  			alignedValue := p.From.Offset
  4009  			v := pcAlignPadLength(p.Pc, alignedValue)
  4010  			offset := p.Pc
  4011  			for ; v >= 4; v -= 4 {
  4012  				// NOP
  4013  				cursym.WriteBytes(ctxt, offset, []byte{0x13, 0, 0, 0})
  4014  				offset += 4
  4015  			}
  4016  			continue
  4017  		}
  4018  
  4019  		offset := p.Pc
  4020  		for _, ins := range instructionsForProg(p) {
  4021  			if ic, err := ins.encode(); err == nil {
  4022  				cursym.WriteInt(ctxt, offset, ins.length(), int64(ic))
  4023  				offset += int64(ins.length())
  4024  			}
  4025  			if ins.usesRegTmp() {
  4026  				p.Mark |= USES_REG_TMP
  4027  			}
  4028  		}
  4029  	}
  4030  
  4031  	obj.MarkUnsafePoints(ctxt, cursym.Func().Text, newprog, isUnsafePoint, nil)
  4032  }
  4033  
  4034  func isUnsafePoint(p *obj.Prog) bool {
  4035  	return p.Mark&USES_REG_TMP == USES_REG_TMP || p.From.Reg == REG_TMP || p.To.Reg == REG_TMP || p.Reg == REG_TMP
  4036  }
  4037  
  4038  func ParseSuffix(prog *obj.Prog, cond string) (err error) {
  4039  	switch prog.As {
  4040  	case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
  4041  		prog.Scond, err = rmSuffixEncode(strings.TrimPrefix(cond, "."))
  4042  	}
  4043  	return
  4044  }
  4045  
  4046  var LinkRISCV64 = obj.LinkArch{
  4047  	Arch:           sys.ArchRISCV64,
  4048  	Init:           buildop,
  4049  	Preprocess:     preprocess,
  4050  	Assemble:       assemble,
  4051  	Progedit:       progedit,
  4052  	UnaryDst:       unaryDst,
  4053  	DWARFRegisters: RISCV64DWARFRegisters,
  4054  }
  4055  

View as plain text