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"
    33  	"math/bits"
    34  	"strings"
    35  )
    36  
    37  func buildop(ctxt *obj.Link) {}
    38  
    39  func jalToSym(ctxt *obj.Link, p *obj.Prog, lr int16) {
    40  	switch p.As {
    41  	case obj.ACALL, obj.AJMP, obj.ARET:
    42  	default:
    43  		ctxt.Diag("unexpected Prog in jalToSym: %v", p)
    44  		return
    45  	}
    46  
    47  	p.As = AJAL
    48  	p.Mark |= NEED_JAL_RELOC
    49  	p.From.Type = obj.TYPE_REG
    50  	p.From.Reg = lr
    51  	p.Reg = obj.REG_NONE
    52  }
    53  
    54  // progedit is called individually for each *obj.Prog. It normalizes instruction
    55  // formats and eliminates as many pseudo-instructions as possible.
    56  func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
    57  	insData, err := instructionDataForAs(p.As)
    58  	if err != nil {
    59  		panic(fmt.Sprintf("failed to lookup instruction data for %v: %v", p.As, err))
    60  	}
    61  
    62  	// Expand binary instructions to ternary ones.
    63  	if p.Reg == obj.REG_NONE {
    64  		if insData.ternary {
    65  			p.Reg = p.To.Reg
    66  		}
    67  	}
    68  
    69  	// Rewrite instructions with constant operands to refer to the immediate
    70  	// form of the instruction.
    71  	if p.From.Type == obj.TYPE_CONST {
    72  		switch p.As {
    73  		case ACSUB:
    74  			p.As, p.From.Offset = ACADDI, -p.From.Offset
    75  		case ACSUBW:
    76  			p.As, p.From.Offset = ACADDIW, -p.From.Offset
    77  		case ASUB:
    78  			p.As, p.From.Offset = AADDI, -p.From.Offset
    79  		case ASUBW:
    80  			p.As, p.From.Offset = AADDIW, -p.From.Offset
    81  		default:
    82  			if insData.immForm != obj.AXXX {
    83  				p.As = insData.immForm
    84  			}
    85  		}
    86  	}
    87  
    88  	switch p.As {
    89  	case obj.AJMP:
    90  		// Turn JMP into JAL ZERO or JALR ZERO.
    91  		p.From.Type = obj.TYPE_REG
    92  		p.From.Reg = REG_ZERO
    93  
    94  		switch p.To.Type {
    95  		case obj.TYPE_BRANCH:
    96  			p.As = AJAL
    97  		case obj.TYPE_MEM:
    98  			switch p.To.Name {
    99  			case obj.NAME_NONE:
   100  				p.As = AJALR
   101  			case obj.NAME_EXTERN, obj.NAME_STATIC:
   102  				// Handled in preprocess.
   103  			default:
   104  				ctxt.Diag("unsupported name %d for %v", p.To.Name, p)
   105  			}
   106  		default:
   107  			panic(fmt.Sprintf("unhandled type %+v", p.To.Type))
   108  		}
   109  
   110  	case obj.ACALL:
   111  		switch p.To.Type {
   112  		case obj.TYPE_MEM:
   113  			// Handled in preprocess.
   114  		case obj.TYPE_REG:
   115  			p.As = AJALR
   116  			p.From.Type = obj.TYPE_REG
   117  			p.From.Reg = REG_LR
   118  		default:
   119  			ctxt.Diag("unknown destination type %+v in CALL: %v", p.To.Type, p)
   120  		}
   121  
   122  	case obj.AUNDEF:
   123  		p.As = AEBREAK
   124  
   125  	case AFMVXS:
   126  		// FMVXS is the old name for FMVXW.
   127  		p.As = AFMVXW
   128  
   129  	case AFMVSX:
   130  		// FMVSX is the old name for FMVWX.
   131  		p.As = AFMVWX
   132  
   133  	case ASCALL:
   134  		// SCALL is the old name for ECALL.
   135  		p.As = AECALL
   136  
   137  	case ASBREAK:
   138  		// SBREAK is the old name for EBREAK.
   139  		p.As = AEBREAK
   140  
   141  	case AMOV:
   142  		if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE && p.From.Reg == obj.REG_NONE {
   143  			if isMaterialisableConst(p.From.Offset) {
   144  				break
   145  			}
   146  			// Put non-materialisable constants in memory and load them.
   147  			p.From.Type = obj.TYPE_MEM
   148  			p.From.Sym = ctxt.Int64Sym(p.From.Offset)
   149  			p.From.Name = obj.NAME_EXTERN
   150  			p.From.Offset = 0
   151  		}
   152  
   153  	case AMOVF:
   154  		if p.From.Type == obj.TYPE_FCONST && p.From.Name == obj.NAME_NONE && p.From.Reg == obj.REG_NONE {
   155  			f64 := p.From.Val.(float64)
   156  			f32 := float32(f64)
   157  			if math.Float32bits(f32) == 0 {
   158  				p.From.Type = obj.TYPE_REG
   159  				p.From.Reg = REG_ZERO
   160  				break
   161  			}
   162  			p.From.Type = obj.TYPE_MEM
   163  			p.From.Sym = ctxt.Float32Sym(f32)
   164  			p.From.Name = obj.NAME_EXTERN
   165  			p.From.Offset = 0
   166  		}
   167  
   168  	case AMOVD:
   169  		if p.From.Type == obj.TYPE_FCONST && p.From.Name == obj.NAME_NONE && p.From.Reg == obj.REG_NONE {
   170  			f64 := p.From.Val.(float64)
   171  			if math.Float64bits(f64) == 0 {
   172  				p.From.Type = obj.TYPE_REG
   173  				p.From.Reg = REG_ZERO
   174  				break
   175  			}
   176  			p.From.Type = obj.TYPE_MEM
   177  			p.From.Sym = ctxt.Float64Sym(f64)
   178  			p.From.Name = obj.NAME_EXTERN
   179  			p.From.Offset = 0
   180  		}
   181  	}
   182  
   183  	if ctxt.Flag_dynlink {
   184  		rewriteToUseGot(ctxt, p, newprog)
   185  	}
   186  }
   187  
   188  // Rewrite p, if necessary, to access global data via the global offset table.
   189  func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
   190  	// We only care about global data: NAME_EXTERN means a global
   191  	// symbol in the Go sense and p.Sym.Local is true for a few internally
   192  	// defined symbols.
   193  	if p.From.Type == obj.TYPE_ADDR && p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
   194  		// MOV $sym, Rx becomes MOV sym@GOT, Rx
   195  		// MOV $sym+<off>, Rx becomes MOV sym@GOT, Rx; ADD <off>, Rx
   196  		if p.As != AMOV {
   197  			ctxt.Diag("don't know how to handle TYPE_ADDR in %v with -dynlink", p)
   198  		}
   199  		if p.To.Type != obj.TYPE_REG {
   200  			ctxt.Diag("don't know how to handle LD instruction to non-register in %v with -dynlink", p)
   201  		}
   202  		p.From.Type = obj.TYPE_MEM
   203  		p.From.Name = obj.NAME_GOTREF
   204  		if p.From.Offset != 0 {
   205  			q := obj.Appendp(p, newprog)
   206  			q.As = AADD
   207  			q.From.Type = obj.TYPE_CONST
   208  			q.From.Offset = p.From.Offset
   209  			q.To = p.To
   210  			p.From.Offset = 0
   211  		}
   212  
   213  	}
   214  
   215  	if p.GetFrom3() != nil && p.GetFrom3().Name == obj.NAME_EXTERN {
   216  		ctxt.Diag("don't know how to handle %v with -dynlink", p)
   217  	}
   218  
   219  	var source *obj.Addr
   220  	// MOVx sym, Ry becomes MOV sym@GOT, X31; MOVx (X31), Ry
   221  	// MOVx Ry, sym becomes MOV sym@GOT, X31; MOV Ry, (X31)
   222  	// An addition may be inserted between the two MOVs if there is an offset.
   223  	if p.From.Name == obj.NAME_EXTERN && !p.From.Sym.Local() {
   224  		if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
   225  			ctxt.Diag("cannot handle NAME_EXTERN on both sides in %v with -dynlink", p)
   226  		}
   227  		source = &p.From
   228  	} else if p.To.Name == obj.NAME_EXTERN && !p.To.Sym.Local() {
   229  		source = &p.To
   230  	} else {
   231  		return
   232  	}
   233  	if p.As == obj.ATEXT || p.As == obj.AFUNCDATA || p.As == obj.ACALL || p.As == obj.ARET || p.As == obj.AJMP {
   234  		return
   235  	}
   236  	if source.Sym.Type == objabi.STLSBSS {
   237  		return
   238  	}
   239  	if source.Type != obj.TYPE_MEM {
   240  		ctxt.Diag("don't know how to handle %v with -dynlink", p)
   241  	}
   242  	p1 := obj.Appendp(p, newprog)
   243  	p1.As = AMOV
   244  	p1.From.Type = obj.TYPE_MEM
   245  	p1.From.Sym = source.Sym
   246  	p1.From.Name = obj.NAME_GOTREF
   247  	p1.To.Type = obj.TYPE_REG
   248  	p1.To.Reg = REG_TMP
   249  
   250  	p2 := obj.Appendp(p1, newprog)
   251  	p2.As = p.As
   252  	p2.From = p.From
   253  	p2.To = p.To
   254  	if p.From.Name == obj.NAME_EXTERN {
   255  		p2.From.Reg = REG_TMP
   256  		p2.From.Name = obj.NAME_NONE
   257  		p2.From.Sym = nil
   258  	} else if p.To.Name == obj.NAME_EXTERN {
   259  		p2.To.Reg = REG_TMP
   260  		p2.To.Name = obj.NAME_NONE
   261  		p2.To.Sym = nil
   262  	} else {
   263  		return
   264  	}
   265  	obj.Nopout(p)
   266  
   267  }
   268  
   269  // addrToReg extracts the register from an Addr, handling special Addr.Names.
   270  func addrToReg(a obj.Addr) int16 {
   271  	switch a.Name {
   272  	case obj.NAME_PARAM, obj.NAME_AUTO:
   273  		return REG_SP
   274  	}
   275  	return a.Reg
   276  }
   277  
   278  // movToLoad converts a MOV mnemonic into the corresponding load instruction.
   279  func movToLoad(mnemonic obj.As) obj.As {
   280  	switch mnemonic {
   281  	case AMOV:
   282  		return ALD
   283  	case AMOVB:
   284  		return ALB
   285  	case AMOVH:
   286  		return ALH
   287  	case AMOVW:
   288  		return ALW
   289  	case AMOVBU:
   290  		return ALBU
   291  	case AMOVHU:
   292  		return ALHU
   293  	case AMOVWU:
   294  		return ALWU
   295  	case AMOVF:
   296  		return AFLW
   297  	case AMOVD:
   298  		return AFLD
   299  	default:
   300  		panic(fmt.Sprintf("%+v is not a MOV", mnemonic))
   301  	}
   302  }
   303  
   304  // movToStore converts a MOV mnemonic into the corresponding store instruction.
   305  func movToStore(mnemonic obj.As) obj.As {
   306  	switch mnemonic {
   307  	case AMOV:
   308  		return ASD
   309  	case AMOVB:
   310  		return ASB
   311  	case AMOVH:
   312  		return ASH
   313  	case AMOVW:
   314  		return ASW
   315  	case AMOVF:
   316  		return AFSW
   317  	case AMOVD:
   318  		return AFSD
   319  	default:
   320  		panic(fmt.Sprintf("%+v is not a MOV", mnemonic))
   321  	}
   322  }
   323  
   324  // markRelocs marks an obj.Prog that specifies a MOV pseudo-instruction and
   325  // requires relocation.
   326  func markRelocs(p *obj.Prog) {
   327  	switch p.As {
   328  	case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
   329  		switch {
   330  		case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG:
   331  			switch p.From.Name {
   332  			case obj.NAME_EXTERN, obj.NAME_STATIC:
   333  				p.Mark |= NEED_PCREL_ITYPE_RELOC
   334  			case obj.NAME_GOTREF:
   335  				p.Mark |= NEED_GOT_PCREL_ITYPE_RELOC
   336  			}
   337  		case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG:
   338  			switch p.From.Name {
   339  			case obj.NAME_EXTERN, obj.NAME_STATIC:
   340  				p.Mark |= NEED_PCREL_ITYPE_RELOC
   341  			case obj.NAME_GOTREF:
   342  				p.Mark |= NEED_GOT_PCREL_ITYPE_RELOC
   343  			}
   344  		case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM:
   345  			switch p.To.Name {
   346  			case obj.NAME_EXTERN, obj.NAME_STATIC:
   347  				p.Mark |= NEED_PCREL_STYPE_RELOC
   348  			}
   349  		}
   350  	}
   351  }
   352  
   353  // InvertBranch inverts the condition of a conditional branch.
   354  func InvertBranch(as obj.As) obj.As {
   355  	switch as {
   356  	case ABEQ:
   357  		return ABNE
   358  	case ABEQZ:
   359  		return ABNEZ
   360  	case ABGE:
   361  		return ABLT
   362  	case ABGEU:
   363  		return ABLTU
   364  	case ABGEZ:
   365  		return ABLTZ
   366  	case ABGT:
   367  		return ABLE
   368  	case ABGTU:
   369  		return ABLEU
   370  	case ABGTZ:
   371  		return ABLEZ
   372  	case ABLE:
   373  		return ABGT
   374  	case ABLEU:
   375  		return ABGTU
   376  	case ABLEZ:
   377  		return ABGTZ
   378  	case ABLT:
   379  		return ABGE
   380  	case ABLTU:
   381  		return ABGEU
   382  	case ABLTZ:
   383  		return ABGEZ
   384  	case ABNE:
   385  		return ABEQ
   386  	case ABNEZ:
   387  		return ABEQZ
   388  	case ACBEQZ:
   389  		return ACBNEZ
   390  	case ACBNEZ:
   391  		return ACBEQZ
   392  	default:
   393  		panic("InvertBranch: not a branch")
   394  	}
   395  }
   396  
   397  // containsCall reports whether the symbol contains a CALL (or equivalent)
   398  // instruction. Must be called after progedit.
   399  func containsCall(sym *obj.LSym) bool {
   400  	// CALLs are CALL or JAL(R) with link register LR.
   401  	for p := sym.Func().Text; p != nil; p = p.Link {
   402  		switch p.As {
   403  		case obj.ACALL:
   404  			return true
   405  		case ACJALR, AJAL, AJALR:
   406  			if p.From.Type == obj.TYPE_REG && p.From.Reg == REG_LR {
   407  				return true
   408  			}
   409  		}
   410  	}
   411  
   412  	return false
   413  }
   414  
   415  // setPCs sets the Pc field in all instructions reachable from p.
   416  // It uses pc as the initial value and returns the next available pc.
   417  func setPCs(p *obj.Prog, pc int64, compress bool) int64 {
   418  	for ; p != nil; p = p.Link {
   419  		p.Pc = pc
   420  		for _, ins := range instructionsForProg(p, compress) {
   421  			pc += int64(ins.length())
   422  		}
   423  
   424  		if p.As == obj.APCALIGN {
   425  			alignedValue := p.From.Offset
   426  			v := pcAlignPadLength(pc, alignedValue)
   427  			pc += int64(v)
   428  		}
   429  	}
   430  	return pc
   431  }
   432  
   433  // stackOffset updates Addr offsets based on the current stack size.
   434  //
   435  // The stack looks like:
   436  // -------------------
   437  // |                 |
   438  // |      PARAMs     |
   439  // |                 |
   440  // |                 |
   441  // -------------------
   442  // |    Parent RA    |   SP on function entry
   443  // -------------------
   444  // |                 |
   445  // |                 |
   446  // |       AUTOs     |
   447  // |                 |
   448  // |                 |
   449  // -------------------
   450  // |        RA       |   SP during function execution
   451  // -------------------
   452  //
   453  // FixedFrameSize makes other packages aware of the space allocated for RA.
   454  //
   455  // A nicer version of this diagram can be found on slide 21 of the presentation
   456  // attached to https://golang.org/issue/16922#issuecomment-243748180.
   457  func stackOffset(a *obj.Addr, stacksize int64) {
   458  	switch a.Name {
   459  	case obj.NAME_AUTO:
   460  		// Adjust to the top of AUTOs.
   461  		a.Offset += stacksize
   462  	case obj.NAME_PARAM:
   463  		// Adjust to the bottom of PARAMs.
   464  		a.Offset += stacksize + 8
   465  	}
   466  }
   467  
   468  // preprocess generates prologue and epilogue code, computes PC-relative branch
   469  // and jump offsets, and resolves pseudo-registers.
   470  //
   471  // preprocess is called once per linker symbol.
   472  //
   473  // When preprocess finishes, all instructions in the symbol are either
   474  // concrete, real RISC-V instructions or directive pseudo-ops like TEXT,
   475  // PCDATA, and FUNCDATA.
   476  func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
   477  	if cursym.Func().Text == nil || cursym.Func().Text.Link == nil {
   478  		return
   479  	}
   480  
   481  	// Generate the prologue.
   482  	text := cursym.Func().Text
   483  	if text.As != obj.ATEXT {
   484  		ctxt.Diag("preprocess: found symbol that does not start with TEXT directive")
   485  		return
   486  	}
   487  
   488  	stacksize := text.To.Offset
   489  	if stacksize == -8 {
   490  		// Historical way to mark NOFRAME.
   491  		text.From.Sym.Set(obj.AttrNoFrame, true)
   492  		stacksize = 0
   493  	}
   494  	if stacksize < 0 {
   495  		ctxt.Diag("negative frame size %d - did you mean NOFRAME?", stacksize)
   496  	}
   497  	if text.From.Sym.NoFrame() {
   498  		if stacksize != 0 {
   499  			ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", stacksize)
   500  		}
   501  	}
   502  
   503  	if !containsCall(cursym) {
   504  		text.From.Sym.Set(obj.AttrLeaf, true)
   505  		if stacksize == 0 {
   506  			// A leaf function with no locals has no frame.
   507  			text.From.Sym.Set(obj.AttrNoFrame, true)
   508  		}
   509  	}
   510  
   511  	// Save LR unless there is no frame.
   512  	if !text.From.Sym.NoFrame() {
   513  		stacksize += ctxt.Arch.FixedFrameSize
   514  	}
   515  
   516  	cursym.Func().Args = text.To.Val.(int32)
   517  	cursym.Func().Locals = int32(stacksize)
   518  
   519  	prologue := text
   520  
   521  	if !cursym.Func().Text.From.Sym.NoSplit() {
   522  		prologue = stacksplit(ctxt, prologue, cursym, newprog, stacksize) // emit split check
   523  	}
   524  
   525  	q := prologue
   526  
   527  	if stacksize != 0 {
   528  		prologue = ctxt.StartUnsafePoint(prologue, newprog)
   529  
   530  		// Actually save LR.
   531  		prologue = obj.Appendp(prologue, newprog)
   532  		prologue.As = AMOV
   533  		prologue.Pos = q.Pos
   534  		prologue.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
   535  		prologue.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: -stacksize}
   536  
   537  		// Insert stack adjustment.
   538  		prologue = obj.Appendp(prologue, newprog)
   539  		prologue.As = AADDI
   540  		prologue.Pos = q.Pos
   541  		prologue.Pos = prologue.Pos.WithXlogue(src.PosPrologueEnd)
   542  		prologue.From = obj.Addr{Type: obj.TYPE_CONST, Offset: -stacksize}
   543  		prologue.Reg = REG_SP
   544  		prologue.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
   545  		prologue.Spadj = int32(stacksize)
   546  
   547  		prologue = ctxt.EndUnsafePoint(prologue, newprog, -1)
   548  
   549  		// On Linux, in a cgo binary we may get a SIGSETXID signal early on
   550  		// before the signal stack is set, as glibc doesn't allow us to block
   551  		// SIGSETXID. So a signal may land on the current stack and clobber
   552  		// the content below the SP. We store the LR again after the SP is
   553  		// decremented.
   554  		prologue = obj.Appendp(prologue, newprog)
   555  		prologue.As = AMOV
   556  		prologue.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
   557  		prologue.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0}
   558  	}
   559  
   560  	// Update stack-based offsets.
   561  	for p := cursym.Func().Text; p != nil; p = p.Link {
   562  		stackOffset(&p.From, stacksize)
   563  		stackOffset(&p.To, stacksize)
   564  	}
   565  
   566  	// Additional instruction rewriting.
   567  	for p := cursym.Func().Text; p != nil; p = p.Link {
   568  		switch p.As {
   569  		case obj.AGETCALLERPC:
   570  			if cursym.Leaf() {
   571  				// MOV LR, Rd
   572  				p.As = AMOV
   573  				p.From.Type = obj.TYPE_REG
   574  				p.From.Reg = REG_LR
   575  			} else {
   576  				// MOV (RSP), Rd
   577  				p.As = AMOV
   578  				p.From.Type = obj.TYPE_MEM
   579  				p.From.Reg = REG_SP
   580  			}
   581  
   582  		case obj.ACALL:
   583  			switch p.To.Type {
   584  			case obj.TYPE_MEM:
   585  				jalToSym(ctxt, p, REG_LR)
   586  			}
   587  
   588  		case obj.AJMP:
   589  			switch p.To.Type {
   590  			case obj.TYPE_MEM:
   591  				switch p.To.Name {
   592  				case obj.NAME_EXTERN, obj.NAME_STATIC:
   593  					jalToSym(ctxt, p, REG_ZERO)
   594  				}
   595  			}
   596  
   597  		case obj.ARET:
   598  			// Replace RET with epilogue.
   599  			retJMP, retReg := p.To.Sym, p.To.Reg
   600  			if retReg == obj.REG_NONE {
   601  				retReg = REG_LR
   602  			}
   603  
   604  			if stacksize != 0 {
   605  				// Restore LR.
   606  				p.As = AMOV
   607  				p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0}
   608  				p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
   609  				p = obj.Appendp(p, newprog)
   610  
   611  				p.As = AADDI
   612  				p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: stacksize}
   613  				p.Reg = REG_SP
   614  				p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
   615  				p.Spadj = int32(-stacksize)
   616  				p = obj.Appendp(p, newprog)
   617  			}
   618  
   619  			if retJMP != nil {
   620  				p.As = obj.ARET
   621  				p.To.Sym = retJMP
   622  				jalToSym(ctxt, p, REG_ZERO)
   623  			} else {
   624  				p.As = AJALR
   625  				p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
   626  				p.Reg = obj.REG_NONE
   627  				p.To = obj.Addr{Type: obj.TYPE_REG, Reg: retReg}
   628  			}
   629  
   630  			// "Add back" the stack removed in the previous instruction.
   631  			//
   632  			// This is to avoid confusing pctospadj, which sums
   633  			// Spadj from function entry to each PC, and shouldn't
   634  			// count adjustments from earlier epilogues, since they
   635  			// won't affect later PCs.
   636  			p.Spadj = int32(stacksize)
   637  
   638  		case AADDI:
   639  			// Refine Spadjs account for adjustment via ADDI instruction.
   640  			if p.To.Type == obj.TYPE_REG && p.To.Reg == REG_SP && p.From.Type == obj.TYPE_CONST {
   641  				p.Spadj = int32(-p.From.Offset)
   642  			}
   643  		}
   644  
   645  		if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.Spadj == 0 {
   646  			f := cursym.Func()
   647  			if f.FuncFlag&abi.FuncFlagSPWrite == 0 {
   648  				f.FuncFlag |= abi.FuncFlagSPWrite
   649  				if ctxt.Debugvlog || !ctxt.IsAsm {
   650  					ctxt.Logf("auto-SPWRITE: %s %v\n", cursym.Name, p)
   651  					if !ctxt.IsAsm {
   652  						ctxt.Diag("invalid auto-SPWRITE in non-assembly")
   653  						ctxt.DiagFlush()
   654  						log.Fatalf("bad SPWRITE")
   655  					}
   656  				}
   657  			}
   658  		}
   659  	}
   660  
   661  	var callCount int
   662  	for p := cursym.Func().Text; p != nil; p = p.Link {
   663  		markRelocs(p)
   664  		if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC {
   665  			callCount++
   666  		}
   667  	}
   668  	const callTrampSize = 8 // 2 machine instructions.
   669  	maxTrampSize := int64(callCount * callTrampSize)
   670  
   671  	// Compute instruction addresses.  Once we do that, we need to check for
   672  	// overextended jumps and branches.  Within each iteration, Pc differences
   673  	// are always lower bounds (since the program gets monotonically longer,
   674  	// a fixed point will be reached).  No attempt to handle functions > 2GiB.
   675  	for {
   676  		big, rescan := false, false
   677  		maxPC := setPCs(cursym.Func().Text, 0, ctxt.CompressInstructions)
   678  		if maxPC+maxTrampSize > (1 << 20) {
   679  			big = true
   680  		}
   681  
   682  		for p := cursym.Func().Text; p != nil; p = p.Link {
   683  			switch p.As {
   684  			case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ, ACBEQZ, ACBNEZ, ACJ:
   685  				if p.To.Type != obj.TYPE_BRANCH {
   686  					ctxt.Diag("%v: instruction with branch-like opcode lacks destination", p)
   687  					break
   688  				}
   689  				offset := p.To.Target().Pc - p.Pc
   690  				if offset < -4096 || 4096 <= offset {
   691  					// Branch is long.  Replace it with a jump.
   692  					jmp := obj.Appendp(p, newprog)
   693  					jmp.As = AJAL
   694  					jmp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
   695  					jmp.To = obj.Addr{Type: obj.TYPE_BRANCH}
   696  					jmp.To.SetTarget(p.To.Target())
   697  
   698  					p.As = InvertBranch(p.As)
   699  					p.To.SetTarget(jmp.Link)
   700  
   701  					// We may have made previous branches too long,
   702  					// so recheck them.
   703  					rescan = true
   704  				}
   705  			case AJAL:
   706  				// Linker will handle the intersymbol case and trampolines.
   707  				if p.To.Target() == nil {
   708  					if !big {
   709  						break
   710  					}
   711  					// This function is going to be too large for JALs
   712  					// to reach trampolines. Replace with AUIPC+JALR.
   713  					jmp := obj.Appendp(p, newprog)
   714  					jmp.As = AJALR
   715  					jmp.From = p.From
   716  					jmp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
   717  
   718  					p.As = AAUIPC
   719  					p.Mark = (p.Mark &^ NEED_JAL_RELOC) | NEED_CALL_RELOC
   720  					p.AddRestSource(obj.Addr{Type: obj.TYPE_CONST, Offset: p.To.Offset, Sym: p.To.Sym})
   721  					p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0}
   722  					p.Reg = obj.REG_NONE
   723  					p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
   724  
   725  					rescan = true
   726  					break
   727  				}
   728  				offset := p.To.Target().Pc - p.Pc
   729  				if offset < -(1<<20) || (1<<20) <= offset {
   730  					// Replace with 2-instruction sequence. This assumes
   731  					// that TMP is not live across J instructions, since
   732  					// it is reserved by SSA.
   733  					jmp := obj.Appendp(p, newprog)
   734  					jmp.As = AJALR
   735  					jmp.From = p.From
   736  					jmp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
   737  
   738  					// p.From is not generally valid, however will be
   739  					// fixed up in the next loop.
   740  					p.As = AAUIPC
   741  					p.From = obj.Addr{Type: obj.TYPE_BRANCH, Sym: p.From.Sym}
   742  					p.From.SetTarget(p.To.Target())
   743  					p.Reg = obj.REG_NONE
   744  					p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
   745  
   746  					rescan = true
   747  				}
   748  			}
   749  		}
   750  
   751  		// Return if errors have been detected up to this point. Continuing
   752  		// may lead to duplicate errors being output.
   753  		if ctxt.Errors > 0 {
   754  			return
   755  		}
   756  		if !rescan {
   757  			break
   758  		}
   759  	}
   760  
   761  	// Now that there are no long branches, resolve branch and jump targets.
   762  	// At this point, instruction rewriting which changes the number of
   763  	// instructions will break everything--don't do it!
   764  	for p := cursym.Func().Text; p != nil; p = p.Link {
   765  		switch p.As {
   766  		case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ, ACBEQZ, ACBNEZ, ACJ:
   767  			switch p.To.Type {
   768  			case obj.TYPE_BRANCH:
   769  				p.To.Type, p.To.Offset = obj.TYPE_CONST, p.To.Target().Pc-p.Pc
   770  			case obj.TYPE_MEM:
   771  				if ctxt.Errors == 0 {
   772  					// An error should have already been reported for this instruction
   773  					panic("unhandled type")
   774  				}
   775  			}
   776  
   777  		case AJAL:
   778  			// Linker will handle the intersymbol case and trampolines.
   779  			if p.To.Target() != nil {
   780  				p.To.Type, p.To.Offset = obj.TYPE_CONST, p.To.Target().Pc-p.Pc
   781  			}
   782  
   783  		case AAUIPC:
   784  			if p.From.Type == obj.TYPE_BRANCH {
   785  				low, high, err := Split32BitImmediate(p.From.Target().Pc - p.Pc)
   786  				if err != nil {
   787  					ctxt.Diag("%v: jump displacement %d too large", p, p.To.Target().Pc-p.Pc)
   788  				}
   789  				p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high, Sym: cursym}
   790  				p.Link.To.Offset = low
   791  			}
   792  
   793  		case obj.APCALIGN:
   794  			alignedValue := p.From.Offset
   795  			if (alignedValue&(alignedValue-1) != 0) || 4 > alignedValue || alignedValue > 2048 {
   796  				ctxt.Diag("alignment value of an instruction must be a power of two and in the range [4, 2048], got %d\n", alignedValue)
   797  			}
   798  			// Update the current text symbol alignment value.
   799  			if int16(alignedValue) > cursym.Align {
   800  				cursym.Align = int16(alignedValue)
   801  			}
   802  		}
   803  	}
   804  
   805  	// Validate all instructions - this provides nice error messages.
   806  	for p := cursym.Func().Text; p != nil; p = p.Link {
   807  		for _, ins := range instructionsForProg(p, ctxt.CompressInstructions) {
   808  			ins.validate(ctxt)
   809  		}
   810  	}
   811  }
   812  
   813  func pcAlignPadLength(pc int64, alignedValue int64) int {
   814  	return int(-pc & (alignedValue - 1))
   815  }
   816  
   817  func stacksplit(ctxt *obj.Link, p *obj.Prog, cursym *obj.LSym, newprog obj.ProgAlloc, framesize int64) *obj.Prog {
   818  	// Leaf function with no frame is effectively NOSPLIT.
   819  	if framesize == 0 {
   820  		return p
   821  	}
   822  
   823  	if ctxt.Flag_maymorestack != "" {
   824  		// Save LR and REGCTXT
   825  		const frameSize = 16
   826  		p = ctxt.StartUnsafePoint(p, newprog)
   827  
   828  		// Spill Arguments. This has to happen before we open
   829  		// any more frame space.
   830  		p = cursym.Func().SpillRegisterArgs(p, newprog)
   831  
   832  		// MOV LR, -16(SP)
   833  		p = obj.Appendp(p, newprog)
   834  		p.As = AMOV
   835  		p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
   836  		p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: -frameSize}
   837  		// ADDI $-16, SP
   838  		p = obj.Appendp(p, newprog)
   839  		p.As = AADDI
   840  		p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: -frameSize}
   841  		p.Reg = REG_SP
   842  		p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
   843  		p.Spadj = frameSize
   844  		// MOV REGCTXT, 8(SP)
   845  		p = obj.Appendp(p, newprog)
   846  		p.As = AMOV
   847  		p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_CTXT}
   848  		p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 8}
   849  
   850  		// CALL maymorestack
   851  		p = obj.Appendp(p, newprog)
   852  		p.As = obj.ACALL
   853  		p.To.Type = obj.TYPE_BRANCH
   854  		// See ../x86/obj6.go
   855  		p.To.Sym = ctxt.LookupABI(ctxt.Flag_maymorestack, cursym.ABI())
   856  		jalToSym(ctxt, p, REG_X5)
   857  
   858  		// Restore LR and REGCTXT
   859  
   860  		// MOV 8(SP), REGCTXT
   861  		p = obj.Appendp(p, newprog)
   862  		p.As = AMOV
   863  		p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 8}
   864  		p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_CTXT}
   865  		// MOV (SP), LR
   866  		p = obj.Appendp(p, newprog)
   867  		p.As = AMOV
   868  		p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0}
   869  		p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
   870  		// ADDI $16, SP
   871  		p = obj.Appendp(p, newprog)
   872  		p.As = AADDI
   873  		p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: frameSize}
   874  		p.Reg = REG_SP
   875  		p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
   876  		p.Spadj = -frameSize
   877  
   878  		// Unspill arguments
   879  		p = cursym.Func().UnspillRegisterArgs(p, newprog)
   880  		p = ctxt.EndUnsafePoint(p, newprog, -1)
   881  	}
   882  
   883  	// Jump back to here after morestack returns.
   884  	startPred := p
   885  
   886  	// MOV	g_stackguard(g), X6
   887  	p = obj.Appendp(p, newprog)
   888  	p.As = AMOV
   889  	p.From.Type = obj.TYPE_MEM
   890  	p.From.Reg = REGG
   891  	p.From.Offset = 2 * int64(ctxt.Arch.PtrSize) // G.stackguard0
   892  	if cursym.CFunc() {
   893  		p.From.Offset = 3 * int64(ctxt.Arch.PtrSize) // G.stackguard1
   894  	}
   895  	p.To.Type = obj.TYPE_REG
   896  	p.To.Reg = REG_X6
   897  
   898  	// Mark the stack bound check and morestack call async nonpreemptible.
   899  	// If we get preempted here, when resumed the preemption request is
   900  	// cleared, but we'll still call morestack, which will double the stack
   901  	// unnecessarily. See issue #35470.
   902  	p = ctxt.StartUnsafePoint(p, newprog)
   903  
   904  	var to_done, to_more *obj.Prog
   905  
   906  	if framesize <= abi.StackSmall {
   907  		// small stack
   908  		//	// if SP > stackguard { goto done }
   909  		//	BLTU	stackguard, SP, done
   910  		p = obj.Appendp(p, newprog)
   911  		p.As = ABLTU
   912  		p.From.Type = obj.TYPE_REG
   913  		p.From.Reg = REG_X6
   914  		p.Reg = REG_SP
   915  		p.To.Type = obj.TYPE_BRANCH
   916  		to_done = p
   917  	} else {
   918  		// large stack: SP-framesize < stackguard-StackSmall
   919  		offset := framesize - abi.StackSmall
   920  		if framesize > abi.StackBig {
   921  			// Such a large stack we need to protect against underflow.
   922  			// The runtime guarantees SP > objabi.StackBig, but
   923  			// framesize is large enough that SP-framesize may
   924  			// underflow, causing a direct comparison with the
   925  			// stack guard to incorrectly succeed. We explicitly
   926  			// guard against underflow.
   927  			//
   928  			//	MOV	$(framesize-StackSmall), X7
   929  			//	BLTU	SP, X7, label-of-call-to-morestack
   930  
   931  			p = obj.Appendp(p, newprog)
   932  			p.As = AMOV
   933  			p.From.Type = obj.TYPE_CONST
   934  			p.From.Offset = offset
   935  			p.To.Type = obj.TYPE_REG
   936  			p.To.Reg = REG_X7
   937  
   938  			p = obj.Appendp(p, newprog)
   939  			p.As = ABLTU
   940  			p.From.Type = obj.TYPE_REG
   941  			p.From.Reg = REG_SP
   942  			p.Reg = REG_X7
   943  			p.To.Type = obj.TYPE_BRANCH
   944  			to_more = p
   945  		}
   946  
   947  		// Check against the stack guard. We've ensured this won't underflow.
   948  		//	ADD	$-(framesize-StackSmall), SP, X7
   949  		//	// if X7 > stackguard { goto done }
   950  		//	BLTU	stackguard, X7, done
   951  		p = obj.Appendp(p, newprog)
   952  		p.As = AADDI
   953  		p.From.Type = obj.TYPE_CONST
   954  		p.From.Offset = -offset
   955  		p.Reg = REG_SP
   956  		p.To.Type = obj.TYPE_REG
   957  		p.To.Reg = REG_X7
   958  
   959  		p = obj.Appendp(p, newprog)
   960  		p.As = ABLTU
   961  		p.From.Type = obj.TYPE_REG
   962  		p.From.Reg = REG_X6
   963  		p.Reg = REG_X7
   964  		p.To.Type = obj.TYPE_BRANCH
   965  		to_done = p
   966  	}
   967  
   968  	// Spill the register args that could be clobbered by the
   969  	// morestack code
   970  	p = ctxt.EmitEntryStackMap(cursym, p, newprog)
   971  	p = cursym.Func().SpillRegisterArgs(p, newprog)
   972  
   973  	// CALL runtime.morestack(SB)
   974  	p = obj.Appendp(p, newprog)
   975  	p.As = obj.ACALL
   976  	p.To.Type = obj.TYPE_BRANCH
   977  
   978  	if cursym.CFunc() {
   979  		p.To.Sym = ctxt.Lookup("runtime.morestackc")
   980  	} else if !cursym.Func().Text.From.Sym.NeedCtxt() {
   981  		p.To.Sym = ctxt.Lookup("runtime.morestack_noctxt")
   982  	} else {
   983  		p.To.Sym = ctxt.Lookup("runtime.morestack")
   984  	}
   985  	if to_more != nil {
   986  		to_more.To.SetTarget(p)
   987  	}
   988  	jalToSym(ctxt, p, REG_X5)
   989  
   990  	// The instructions which unspill regs should be preemptible.
   991  	p = ctxt.EndUnsafePoint(p, newprog, -1)
   992  	p = cursym.Func().UnspillRegisterArgs(p, newprog)
   993  
   994  	// JMP start
   995  	p = obj.Appendp(p, newprog)
   996  	p.As = AJAL
   997  	p.To = obj.Addr{Type: obj.TYPE_BRANCH}
   998  	p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
   999  	p.To.SetTarget(startPred.Link)
  1000  
  1001  	// placeholder for to_done's jump target
  1002  	p = obj.Appendp(p, newprog)
  1003  	p.As = obj.ANOP // zero-width place holder
  1004  	to_done.To.SetTarget(p)
  1005  
  1006  	return p
  1007  }
  1008  
  1009  // signExtend sign extends val starting at bit bit.
  1010  func signExtend(val int64, bit uint) int64 {
  1011  	return val << (64 - bit) >> (64 - bit)
  1012  }
  1013  
  1014  // Split32BitImmediate splits a signed 32-bit immediate into a signed 20-bit
  1015  // upper immediate and a signed 12-bit lower immediate to be added to the upper
  1016  // result. For example, high may be used in LUI and low in a following ADDI to
  1017  // generate a full 32-bit constant.
  1018  func Split32BitImmediate(imm int64) (low, high int64, err error) {
  1019  	if err := immIFits(imm, 32); err != nil {
  1020  		return 0, 0, err
  1021  	}
  1022  
  1023  	// Nothing special needs to be done if the immediate fits in 12 bits.
  1024  	if err := immIFits(imm, 12); err == nil {
  1025  		return imm, 0, nil
  1026  	}
  1027  
  1028  	high = imm >> 12
  1029  
  1030  	// The bottom 12 bits will be treated as signed.
  1031  	//
  1032  	// If that will result in a negative 12 bit number, add 1 to
  1033  	// our upper bits to adjust for the borrow.
  1034  	//
  1035  	// It is not possible for this increment to overflow. To
  1036  	// overflow, the 20 top bits would be 1, and the sign bit for
  1037  	// the low 12 bits would be set, in which case the entire 32
  1038  	// bit pattern fits in a 12 bit signed value.
  1039  	if imm&(1<<11) != 0 {
  1040  		high++
  1041  	}
  1042  
  1043  	low = signExtend(imm, 12)
  1044  	high = signExtend(high, 20)
  1045  
  1046  	return low, high, nil
  1047  }
  1048  
  1049  func regVal(r, min, max uint32) uint32 {
  1050  	if r < min || r > max {
  1051  		panic(fmt.Sprintf("register out of range, want %d <= %d <= %d", min, r, max))
  1052  	}
  1053  	return r - min
  1054  }
  1055  
  1056  // regCI returns an integer register for use in a compressed instruction.
  1057  func regCI(r uint32) uint32 {
  1058  	return regVal(r, REG_X8, REG_X15)
  1059  }
  1060  
  1061  // regCF returns a float register for use in a compressed instruction.
  1062  func regCF(r uint32) uint32 {
  1063  	return regVal(r, REG_F8, REG_F15)
  1064  }
  1065  
  1066  // regI returns an integer register.
  1067  func regI(r uint32) uint32 {
  1068  	return regVal(r, REG_X0, REG_X31)
  1069  }
  1070  
  1071  // regF returns a float register.
  1072  func regF(r uint32) uint32 {
  1073  	return regVal(r, REG_F0, REG_F31)
  1074  }
  1075  
  1076  // regV returns a vector register.
  1077  func regV(r uint32) uint32 {
  1078  	return regVal(r, REG_V0, REG_V31)
  1079  }
  1080  
  1081  // immEven checks that the immediate is a multiple of two. If it
  1082  // is not, an error is returned.
  1083  func immEven(x int64) error {
  1084  	if x&1 != 0 {
  1085  		return fmt.Errorf("immediate %#x is not a multiple of two", x)
  1086  	}
  1087  	return nil
  1088  }
  1089  
  1090  func immFits(x int64, nbits uint, signed bool) error {
  1091  	label := "unsigned"
  1092  	min, max := int64(0), int64(1)<<nbits-1
  1093  	if signed {
  1094  		label = "signed"
  1095  		sbits := nbits - 1
  1096  		min, max = int64(-1)<<sbits, int64(1)<<sbits-1
  1097  	}
  1098  	if x < min || x > max {
  1099  		if nbits <= 16 {
  1100  			return fmt.Errorf("%s immediate %d must be in range [%d, %d] (%d bits)", label, x, min, max, nbits)
  1101  		}
  1102  		return fmt.Errorf("%s immediate %#x must be in range [%#x, %#x] (%d bits)", label, x, min, max, nbits)
  1103  	}
  1104  	return nil
  1105  }
  1106  
  1107  // immIFits checks whether the immediate value x fits in nbits bits
  1108  // as a signed integer. If it does not, an error is returned.
  1109  func immIFits(x int64, nbits uint) error {
  1110  	return immFits(x, nbits, true)
  1111  }
  1112  
  1113  // immI extracts the signed integer of the specified size from an immediate.
  1114  func immI(as obj.As, imm int64, nbits uint) uint32 {
  1115  	if err := immIFits(imm, nbits); err != nil {
  1116  		panic(fmt.Sprintf("%v: %v", as, err))
  1117  	}
  1118  	return uint32(imm) & ((1 << nbits) - 1)
  1119  }
  1120  
  1121  func wantImmI(ctxt *obj.Link, ins *instruction, imm int64, nbits uint) {
  1122  	if err := immIFits(imm, nbits); err != nil {
  1123  		ctxt.Diag("%v: %v", ins, err)
  1124  	}
  1125  }
  1126  
  1127  // immUFits checks whether the immediate value x fits in nbits bits
  1128  // as an unsigned integer. If it does not, an error is returned.
  1129  func immUFits(x int64, nbits uint) error {
  1130  	return immFits(x, nbits, false)
  1131  }
  1132  
  1133  // immU extracts the unsigned integer of the specified size from an immediate.
  1134  func immU(as obj.As, imm int64, nbits uint) uint32 {
  1135  	if err := immUFits(imm, nbits); err != nil {
  1136  		panic(fmt.Sprintf("%v: %v", as, err))
  1137  	}
  1138  	return uint32(imm) & ((1 << nbits) - 1)
  1139  }
  1140  
  1141  func wantImmU(ctxt *obj.Link, ins *instruction, imm int64, nbits uint) {
  1142  	if err := immUFits(imm, nbits); err != nil {
  1143  		ctxt.Diag("%v: %v", ins, err)
  1144  	}
  1145  }
  1146  
  1147  func isScaledImmI(imm int64, nbits uint, scale int64) bool {
  1148  	return immFits(imm, nbits, true) == nil && imm%scale == 0
  1149  }
  1150  
  1151  func isScaledImmU(imm int64, nbits uint, scale int64) bool {
  1152  	return immFits(imm, nbits, false) == nil && imm%scale == 0
  1153  }
  1154  
  1155  func wantScaledImm(ctxt *obj.Link, ins *instruction, imm int64, nbits uint, scale int64, signed bool) {
  1156  	if err := immFits(imm, nbits, signed); err != nil {
  1157  		ctxt.Diag("%v: %v", ins, err)
  1158  		return
  1159  	}
  1160  	if imm%scale != 0 {
  1161  		ctxt.Diag("%v: unsigned immediate %d must be a multiple of %d", ins, imm, scale)
  1162  	}
  1163  }
  1164  
  1165  func wantScaledImmI(ctxt *obj.Link, ins *instruction, imm int64, nbits uint, scale int64) {
  1166  	wantScaledImm(ctxt, ins, imm, nbits, scale, true)
  1167  }
  1168  
  1169  func wantScaledImmU(ctxt *obj.Link, ins *instruction, imm int64, nbits uint, scale int64) {
  1170  	wantScaledImm(ctxt, ins, imm, nbits, scale, false)
  1171  }
  1172  
  1173  func wantReg(ctxt *obj.Link, ins *instruction, pos string, descr string, r, min, max uint32) {
  1174  	if r < min || r > max {
  1175  		var suffix string
  1176  		if r != obj.REG_NONE {
  1177  			suffix = fmt.Sprintf(" but got non-%s register %s", descr, RegName(int(r)))
  1178  		}
  1179  		ctxt.Diag("%v: expected %s register in %s position%s", ins, descr, pos, suffix)
  1180  	}
  1181  }
  1182  
  1183  func wantNoneReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
  1184  	if r != obj.REG_NONE {
  1185  		ctxt.Diag("%v: expected no register in %s but got register %s", ins, pos, RegName(int(r)))
  1186  	}
  1187  }
  1188  
  1189  // wantIntReg checks that r is an integer register.
  1190  func wantIntReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
  1191  	wantReg(ctxt, ins, pos, "integer", r, REG_X0, REG_X31)
  1192  }
  1193  
  1194  func isIntPrimeReg(r uint32) bool {
  1195  	return r >= REG_X8 && r <= REG_X15
  1196  }
  1197  
  1198  // wantIntPrimeReg checks that r is an integer register that can be used
  1199  // in a prime register field of a compressed instruction.
  1200  func wantIntPrimeReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
  1201  	wantReg(ctxt, ins, pos, "integer prime", r, REG_X8, REG_X15)
  1202  }
  1203  
  1204  // wantFloatReg checks that r is a floating-point register.
  1205  func wantFloatReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
  1206  	wantReg(ctxt, ins, pos, "float", r, REG_F0, REG_F31)
  1207  }
  1208  
  1209  func isFloatPrimeReg(r uint32) bool {
  1210  	return r >= REG_F8 && r <= REG_F15
  1211  }
  1212  
  1213  // wantFloatPrimeReg checks that r is an floating-point register that can
  1214  // be used in a prime register field of a compressed instruction.
  1215  func wantFloatPrimeReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
  1216  	wantReg(ctxt, ins, pos, "float prime", r, REG_F8, REG_F15)
  1217  }
  1218  
  1219  // wantVectorReg checks that r is a vector register.
  1220  func wantVectorReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
  1221  	wantReg(ctxt, ins, pos, "vector", r, REG_V0, REG_V31)
  1222  }
  1223  
  1224  // wantEvenOffset checks that the offset is a multiple of two.
  1225  func wantEvenOffset(ctxt *obj.Link, ins *instruction, offset int64) {
  1226  	if err := immEven(offset); err != nil {
  1227  		ctxt.Diag("%v: %v", ins, err)
  1228  	}
  1229  }
  1230  
  1231  func validateCA(ctxt *obj.Link, ins *instruction) {
  1232  	wantIntPrimeReg(ctxt, ins, "rd", ins.rd)
  1233  	if ins.rd != ins.rs1 {
  1234  		ctxt.Diag("%v: rd must be the same as rs1", ins)
  1235  	}
  1236  	wantIntPrimeReg(ctxt, ins, "rs2", ins.rs2)
  1237  }
  1238  
  1239  func validateCB(ctxt *obj.Link, ins *instruction) {
  1240  	if (ins.as == ACSRAI || ins.as == ACSRLI) && ins.imm == 0 {
  1241  		ctxt.Diag("%v: immediate cannot be zero", ins)
  1242  	} else if ins.as == ACSRAI || ins.as == ACSRLI {
  1243  		wantImmU(ctxt, ins, ins.imm, 6)
  1244  	} else if ins.as == ACBEQZ || ins.as == ACBNEZ {
  1245  		wantImmI(ctxt, ins, ins.imm, 9)
  1246  	} else {
  1247  		wantImmI(ctxt, ins, ins.imm, 6)
  1248  	}
  1249  	if ins.as == ACBEQZ || ins.as == ACBNEZ {
  1250  		wantNoneReg(ctxt, ins, "rd", ins.rd)
  1251  		wantIntPrimeReg(ctxt, ins, "rs1", ins.rs1)
  1252  	} else {
  1253  		wantIntPrimeReg(ctxt, ins, "rd", ins.rd)
  1254  		if ins.rd != ins.rs1 {
  1255  			ctxt.Diag("%v: rd must be the same as rs1", ins)
  1256  		}
  1257  	}
  1258  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1259  }
  1260  
  1261  func validateCI(ctxt *obj.Link, ins *instruction) {
  1262  	if ins.as != ACNOP && ins.rd == REG_X0 {
  1263  		ctxt.Diag("%v: cannot use register X0 in rd", ins)
  1264  	}
  1265  	if ins.as == ACLUI && ins.rd == REG_X2 {
  1266  		ctxt.Diag("%v: cannot use register SP/X2 in rd", ins)
  1267  	}
  1268  	if ins.as != ACLI && ins.as != ACLUI && ins.as != ACLWSP && ins.as != ACLDSP && ins.as != ACFLDSP && ins.rd != ins.rs1 {
  1269  		ctxt.Diag("%v: rd must be the same as rs1", ins)
  1270  	}
  1271  	if ins.as == ACADDI16SP && ins.rd != REG_SP {
  1272  		ctxt.Diag("%v: rd must be SP/X2", ins)
  1273  	}
  1274  	if (ins.as == ACLWSP || ins.as == ACLDSP || ins.as == ACFLDSP) && ins.rs2 != REG_SP {
  1275  		ctxt.Diag("%v: rs2 must be SP/X2", ins)
  1276  	}
  1277  	if (ins.as == ACADDI || ins.as == ACADDI16SP || ins.as == ACLUI || ins.as == ACSLLI) && ins.imm == 0 {
  1278  		ctxt.Diag("%v: immediate cannot be zero", ins)
  1279  	} else if ins.as == ACSLLI {
  1280  		wantImmU(ctxt, ins, ins.imm, 6)
  1281  	} else if ins.as == ACLWSP {
  1282  		wantScaledImmU(ctxt, ins, ins.imm, 8, 4)
  1283  	} else if ins.as == ACLDSP || ins.as == ACFLDSP {
  1284  		wantScaledImmU(ctxt, ins, ins.imm, 9, 8)
  1285  	} else if ins.as == ACADDI16SP {
  1286  		wantScaledImmI(ctxt, ins, ins.imm, 10, 16)
  1287  	} else {
  1288  		wantImmI(ctxt, ins, ins.imm, 6)
  1289  	}
  1290  	switch ins.as {
  1291  	case ACNOP, ACADDI, ACADDIW, ACSLLI:
  1292  		wantIntReg(ctxt, ins, "rd", ins.rd)
  1293  		wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1294  		wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1295  	case ACLWSP, ACLDSP:
  1296  		wantIntReg(ctxt, ins, "rd", ins.rd)
  1297  		wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1298  		wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1299  	case ACFLDSP:
  1300  		wantFloatReg(ctxt, ins, "rd", ins.rd)
  1301  		wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1302  		wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1303  	case ACADDI16SP:
  1304  		wantIntReg(ctxt, ins, "rd", ins.rd)
  1305  		wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1306  		wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1307  	default:
  1308  		wantIntReg(ctxt, ins, "rd", ins.rd)
  1309  		wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1310  		wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1311  	}
  1312  }
  1313  
  1314  func validateCIW(ctxt *obj.Link, ins *instruction) {
  1315  	wantScaledImmU(ctxt, ins, ins.imm, 10, 4)
  1316  	wantIntPrimeReg(ctxt, ins, "rd", ins.rd)
  1317  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1318  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1319  	if ins.imm == 0 {
  1320  		ctxt.Diag("%v: immediate cannot be zero", ins)
  1321  	}
  1322  	if ins.rs1 != REG_SP {
  1323  		ctxt.Diag("%v: SP/X2 must be in rs1", ins)
  1324  	}
  1325  }
  1326  
  1327  func validateCJ(ctxt *obj.Link, ins *instruction) {
  1328  	wantEvenOffset(ctxt, ins, ins.imm)
  1329  	wantImmI(ctxt, ins, ins.imm, 12)
  1330  	if ins.as != ACJ {
  1331  		wantNoneReg(ctxt, ins, "rd", ins.rd)
  1332  		wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1333  		wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1334  		if ins.rs1 == REG_X0 {
  1335  			ctxt.Diag("%v: cannot use register X0 in rs1", ins)
  1336  		}
  1337  	}
  1338  }
  1339  
  1340  func validateCL(ctxt *obj.Link, ins *instruction) {
  1341  	if ins.as == ACLW {
  1342  		wantScaledImmU(ctxt, ins, ins.imm, 7, 4)
  1343  	} else if ins.as == ACLD || ins.as == ACFLD {
  1344  		wantScaledImmU(ctxt, ins, ins.imm, 8, 8)
  1345  	} else {
  1346  		wantImmI(ctxt, ins, ins.imm, 5)
  1347  	}
  1348  	if ins.as == ACFLD {
  1349  		wantFloatPrimeReg(ctxt, ins, "rd", ins.rd)
  1350  	} else {
  1351  		wantIntPrimeReg(ctxt, ins, "rd", ins.rd)
  1352  	}
  1353  	wantIntPrimeReg(ctxt, ins, "rs1", ins.rs1)
  1354  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1355  }
  1356  
  1357  func validateCR(ctxt *obj.Link, ins *instruction) {
  1358  	switch ins.as {
  1359  	case ACJR, ACJALR:
  1360  		wantNoneReg(ctxt, ins, "rd", ins.rd)
  1361  		wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1362  		wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1363  		if ins.rs1 == REG_X0 {
  1364  			ctxt.Diag("%v: cannot use register X0 in rs1", ins)
  1365  		}
  1366  	case ACMV:
  1367  		wantIntReg(ctxt, ins, "rd", ins.rd)
  1368  		wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1369  		wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1370  		if ins.rd == REG_X0 {
  1371  			ctxt.Diag("%v: cannot use register X0 in rd", ins)
  1372  		}
  1373  		if ins.rs2 == REG_X0 {
  1374  			ctxt.Diag("%v: cannot use register X0 in rs2", ins)
  1375  		}
  1376  	case ACEBREAK:
  1377  		wantNoneReg(ctxt, ins, "rd", ins.rd)
  1378  		wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1379  		wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1380  	case ACADD:
  1381  		wantIntReg(ctxt, ins, "rd", ins.rd)
  1382  		if ins.rd == REG_X0 {
  1383  			ctxt.Diag("%v: cannot use register X0 in rd", ins)
  1384  		}
  1385  		if ins.rd != ins.rs1 {
  1386  			ctxt.Diag("%v: rd must be the same as rs1", ins)
  1387  		}
  1388  		wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1389  		if ins.rs2 == REG_X0 {
  1390  			ctxt.Diag("%v: cannot use register X0 in rs2", ins)
  1391  		}
  1392  	}
  1393  }
  1394  
  1395  func validateCS(ctxt *obj.Link, ins *instruction) {
  1396  	if ins.as == ACSW {
  1397  		wantScaledImmU(ctxt, ins, ins.imm, 7, 4)
  1398  	} else if ins.as == ACSD || ins.as == ACFSD {
  1399  		wantScaledImmU(ctxt, ins, ins.imm, 8, 8)
  1400  	} else {
  1401  		wantImmI(ctxt, ins, ins.imm, 5)
  1402  	}
  1403  	wantNoneReg(ctxt, ins, "rd", ins.rd)
  1404  	wantIntPrimeReg(ctxt, ins, "rs1", ins.rs1)
  1405  	if ins.as == ACFSD {
  1406  		wantFloatPrimeReg(ctxt, ins, "rs2", ins.rs2)
  1407  	} else {
  1408  		wantIntPrimeReg(ctxt, ins, "rs2", ins.rs2)
  1409  	}
  1410  }
  1411  
  1412  func validateCSS(ctxt *obj.Link, ins *instruction) {
  1413  	if ins.rd != REG_SP {
  1414  		ctxt.Diag("%v: rd must be SP/X2", ins)
  1415  	}
  1416  	if ins.as == ACSWSP {
  1417  		wantScaledImmU(ctxt, ins, ins.imm, 8, 4)
  1418  	} else if ins.as == ACSDSP || ins.as == ACFSDSP {
  1419  		wantScaledImmU(ctxt, ins, ins.imm, 9, 8)
  1420  	} else {
  1421  		wantImmI(ctxt, ins, ins.imm, 6)
  1422  	}
  1423  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1424  	if ins.as == ACFSDSP {
  1425  		wantFloatReg(ctxt, ins, "rs2", ins.rs2)
  1426  	} else {
  1427  		wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1428  	}
  1429  }
  1430  
  1431  func validateRII(ctxt *obj.Link, ins *instruction) {
  1432  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1433  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1434  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1435  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1436  }
  1437  
  1438  func validateRIII(ctxt *obj.Link, ins *instruction) {
  1439  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1440  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1441  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1442  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1443  }
  1444  
  1445  func validateRFFF(ctxt *obj.Link, ins *instruction) {
  1446  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1447  	wantFloatReg(ctxt, ins, "rs1", ins.rs1)
  1448  	wantFloatReg(ctxt, ins, "rs2", ins.rs2)
  1449  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1450  }
  1451  
  1452  func validateRFFFF(ctxt *obj.Link, ins *instruction) {
  1453  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1454  	wantFloatReg(ctxt, ins, "rs1", ins.rs1)
  1455  	wantFloatReg(ctxt, ins, "rs2", ins.rs2)
  1456  	wantFloatReg(ctxt, ins, "rs3", ins.rs3)
  1457  }
  1458  
  1459  func validateRFFI(ctxt *obj.Link, ins *instruction) {
  1460  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1461  	wantFloatReg(ctxt, ins, "rs1", ins.rs1)
  1462  	wantFloatReg(ctxt, ins, "rs2", ins.rs2)
  1463  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1464  }
  1465  
  1466  func validateRFI(ctxt *obj.Link, ins *instruction) {
  1467  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1468  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1469  	wantFloatReg(ctxt, ins, "rs2", ins.rs2)
  1470  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1471  }
  1472  
  1473  func validateRFV(ctxt *obj.Link, ins *instruction) {
  1474  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1475  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1476  	wantFloatReg(ctxt, ins, "rs2", ins.rs2)
  1477  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1478  }
  1479  
  1480  func validateRFF(ctxt *obj.Link, ins *instruction) {
  1481  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1482  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1483  	wantFloatReg(ctxt, ins, "rs2", ins.rs2)
  1484  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1485  }
  1486  
  1487  func validateRIF(ctxt *obj.Link, ins *instruction) {
  1488  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1489  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1490  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1491  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1492  }
  1493  
  1494  func validateRIV(ctxt *obj.Link, ins *instruction) {
  1495  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1496  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1497  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1498  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1499  }
  1500  
  1501  func validateRVF(ctxt *obj.Link, ins *instruction) {
  1502  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1503  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1504  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1505  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1506  }
  1507  
  1508  func validateRVFV(ctxt *obj.Link, ins *instruction) {
  1509  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1510  	wantFloatReg(ctxt, ins, "rs1", ins.rs1)
  1511  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1512  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1513  }
  1514  
  1515  func validateRVI(ctxt *obj.Link, ins *instruction) {
  1516  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1517  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1518  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1519  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1520  }
  1521  
  1522  func validateRVIV(ctxt *obj.Link, ins *instruction) {
  1523  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1524  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1525  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1526  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1527  }
  1528  
  1529  func validateRVV(ctxt *obj.Link, ins *instruction) {
  1530  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1531  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1532  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1533  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1534  }
  1535  
  1536  func validateRVVi(ctxt *obj.Link, ins *instruction) {
  1537  	wantImmI(ctxt, ins, ins.imm, 5)
  1538  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1539  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1540  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1541  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1542  }
  1543  
  1544  func validateRVVu(ctxt *obj.Link, ins *instruction) {
  1545  	wantImmU(ctxt, ins, ins.imm, 5)
  1546  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1547  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1548  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1549  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1550  }
  1551  
  1552  func validateRVVV(ctxt *obj.Link, ins *instruction) {
  1553  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1554  	wantVectorReg(ctxt, ins, "vs1", ins.rs1)
  1555  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1556  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1557  }
  1558  
  1559  func validateIII(ctxt *obj.Link, ins *instruction) {
  1560  	wantImmI(ctxt, ins, ins.imm, 12)
  1561  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1562  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1563  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1564  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1565  }
  1566  
  1567  func validateIF(ctxt *obj.Link, ins *instruction) {
  1568  	wantImmI(ctxt, ins, ins.imm, 12)
  1569  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1570  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1571  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1572  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1573  }
  1574  
  1575  func validateIV(ctxt *obj.Link, ins *instruction) {
  1576  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1577  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1578  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1579  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1580  }
  1581  
  1582  func validateIIIV(ctxt *obj.Link, ins *instruction) {
  1583  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1584  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1585  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1586  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1587  }
  1588  
  1589  func validateIVIV(ctxt *obj.Link, ins *instruction) {
  1590  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1591  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1592  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1593  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1594  }
  1595  
  1596  func validateSI(ctxt *obj.Link, ins *instruction) {
  1597  	wantImmI(ctxt, ins, ins.imm, 12)
  1598  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1599  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1600  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1601  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1602  }
  1603  
  1604  func validateSF(ctxt *obj.Link, ins *instruction) {
  1605  	wantImmI(ctxt, ins, ins.imm, 12)
  1606  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1607  	wantFloatReg(ctxt, ins, "rs1", ins.rs1)
  1608  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1609  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1610  }
  1611  
  1612  func validateSV(ctxt *obj.Link, ins *instruction) {
  1613  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1614  	wantVectorReg(ctxt, ins, "vs1", ins.rs1)
  1615  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1616  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1617  }
  1618  
  1619  func validateSVII(ctxt *obj.Link, ins *instruction) {
  1620  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1621  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1622  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1623  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1624  }
  1625  
  1626  func validateSVIV(ctxt *obj.Link, ins *instruction) {
  1627  	wantVectorReg(ctxt, ins, "vd", ins.rd)
  1628  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1629  	wantVectorReg(ctxt, ins, "vs2", ins.rs2)
  1630  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1631  }
  1632  
  1633  func validateB(ctxt *obj.Link, ins *instruction) {
  1634  	// Offsets are multiples of two, so accept 13 bit immediates for the
  1635  	// 12 bit slot. We implicitly drop the least significant bit in encodeB.
  1636  	wantEvenOffset(ctxt, ins, ins.imm)
  1637  	wantImmI(ctxt, ins, ins.imm, 13)
  1638  	wantNoneReg(ctxt, ins, "rd", ins.rd)
  1639  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1640  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1641  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1642  }
  1643  
  1644  func validateU(ctxt *obj.Link, ins *instruction) {
  1645  	wantImmI(ctxt, ins, ins.imm, 20)
  1646  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1647  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1648  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1649  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1650  }
  1651  
  1652  func validateJ(ctxt *obj.Link, ins *instruction) {
  1653  	// Offsets are multiples of two, so accept 21 bit immediates for the
  1654  	// 20 bit slot. We implicitly drop the least significant bit in encodeJ.
  1655  	wantEvenOffset(ctxt, ins, ins.imm)
  1656  	wantImmI(ctxt, ins, ins.imm, 21)
  1657  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1658  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1659  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1660  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1661  }
  1662  
  1663  func validateVsetvli(ctxt *obj.Link, ins *instruction) {
  1664  	wantImmU(ctxt, ins, ins.imm, 11)
  1665  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1666  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1667  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1668  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1669  }
  1670  
  1671  func validateVsetivli(ctxt *obj.Link, ins *instruction) {
  1672  	wantImmU(ctxt, ins, ins.imm, 10)
  1673  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1674  	wantImmU(ctxt, ins, int64(ins.rs1), 5)
  1675  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1676  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1677  }
  1678  
  1679  func validateVsetvl(ctxt *obj.Link, ins *instruction) {
  1680  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1681  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1682  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1683  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1684  }
  1685  
  1686  func validateRaw(ctxt *obj.Link, ins *instruction) {
  1687  	// Treat the raw value specially as a 32-bit unsigned integer.
  1688  	// Nobody wants to enter negative machine code.
  1689  	wantImmU(ctxt, ins, ins.imm, 32)
  1690  }
  1691  
  1692  // compressedEncoding returns the fixed instruction encoding for a compressed
  1693  // instruction.
  1694  func compressedEncoding(as obj.As) uint32 {
  1695  	enc := encode(as)
  1696  	if enc == nil {
  1697  		panic("compressedEncoding: could not encode instruction")
  1698  	}
  1699  
  1700  	// TODO: this can be removed once encode is reworked to return the
  1701  	// necessary bits.
  1702  	op := uint32(0)
  1703  	switch as {
  1704  	case ACSUB:
  1705  		op = 0b100011<<10 | 0b00<<5
  1706  	case ACXOR:
  1707  		op = 0b100011<<10 | 0b01<<5
  1708  	case ACOR:
  1709  		op = 0b100011<<10 | 0b10<<5
  1710  	case ACAND:
  1711  		op = 0b100011<<10 | 0b11<<5
  1712  	case ACSUBW:
  1713  		op = 0b100111<<10 | 0b00<<5
  1714  	case ACADDW:
  1715  		op = 0b100111<<10 | 0b01<<5
  1716  	case ACBEQZ:
  1717  		op = 0b110 << 13
  1718  	case ACBNEZ:
  1719  		op = 0b111 << 13
  1720  	case ACANDI:
  1721  		op = 0b100<<13 | 0b10<<10
  1722  	case ACSRAI:
  1723  		op = 0b100<<13 | 0b01<<10
  1724  	case ACSRLI:
  1725  		op = 0b100<<13 | 0b00<<10
  1726  	case ACLI:
  1727  		op = 0b010 << 13
  1728  	case ACLUI:
  1729  		op = 0b011 << 13
  1730  	case ACLWSP:
  1731  		op = 0b010 << 13
  1732  	case ACLDSP:
  1733  		op = 0b011 << 13
  1734  	case ACFLDSP:
  1735  		op = 0b001 << 13
  1736  	case ACADDIW:
  1737  		op = 0b001 << 13
  1738  	case ACADDI16SP:
  1739  		op = 0b011 << 13
  1740  	case ACADDI4SPN:
  1741  		op = 0b000 << 13
  1742  	case ACJ:
  1743  		op = 0b101 << 13
  1744  	case ACLW:
  1745  		op = 0b010 << 13
  1746  	case ACLD:
  1747  		op = 0b011 << 13
  1748  	case ACFLD:
  1749  		op = 0b001 << 13
  1750  	case ACJR:
  1751  		op = 0b1000 << 12
  1752  	case ACMV:
  1753  		op = 0b1000 << 12
  1754  	case ACEBREAK:
  1755  		op = 0b1001 << 12
  1756  	case ACJALR:
  1757  		op = 0b1001 << 12
  1758  	case ACADD:
  1759  		op = 0b1001 << 12
  1760  	case ACSW:
  1761  		op = 0b110 << 13
  1762  	case ACSD:
  1763  		op = 0b111 << 13
  1764  	case ACFSD:
  1765  		op = 0b101 << 13
  1766  	case ACSWSP:
  1767  		op = 0b110 << 13
  1768  	case ACSDSP:
  1769  		op = 0b111 << 13
  1770  	case ACFSDSP:
  1771  		op = 0b101 << 13
  1772  	}
  1773  
  1774  	return op | enc.opcode
  1775  }
  1776  
  1777  // encodeBitPattern encodes an immediate value by extracting the specified
  1778  // bit pattern from the given immediate. Each value in the pattern specifies
  1779  // the position of the bit to extract from the immediate, which are then
  1780  // encoded in sequence.
  1781  func encodeBitPattern(imm uint32, pattern []int) uint32 {
  1782  	outImm := uint32(0)
  1783  	for _, bit := range pattern {
  1784  		outImm = outImm<<1 | (imm>>bit)&1
  1785  	}
  1786  	return outImm
  1787  }
  1788  
  1789  // encodeCA encodes a compressed arithmetic (CA-type) instruction.
  1790  func encodeCA(ins *instruction) uint32 {
  1791  	return compressedEncoding(ins.as) | regCI(ins.rd)<<7 | regCI(ins.rs2)<<2
  1792  }
  1793  
  1794  // encodeCBImmediate encodes an immediate for a CB-type RISC-V instruction.
  1795  func encodeCBImmediate(imm uint32) uint32 {
  1796  	// Bit order - [8|4:3|7:6|2:1|5]
  1797  	bits := encodeBitPattern(imm, []int{8, 4, 3, 7, 6, 2, 1, 5})
  1798  	return (bits>>5)<<10 | (bits&0x1f)<<2
  1799  }
  1800  
  1801  // encodeCB encodes a compressed branch (CB-type) instruction.
  1802  func encodeCB(ins *instruction) uint32 {
  1803  	imm := uint32(0)
  1804  	if ins.as == ACBEQZ || ins.as == ACBNEZ {
  1805  		imm = immI(ins.as, ins.imm, 9)
  1806  		imm = encodeBitPattern(imm, []int{8, 4, 3, 7, 6, 2, 1, 5})
  1807  	} else if ins.as == ACANDI {
  1808  		imm = immI(ins.as, ins.imm, 6)
  1809  		imm = (imm>>5)<<7 | imm&0x1f
  1810  	} else if ins.as == ACSRAI || ins.as == ACSRLI {
  1811  		imm = immU(ins.as, ins.imm, 6)
  1812  		imm = (imm>>5)<<7 | imm&0x1f
  1813  	}
  1814  	return compressedEncoding(ins.as) | (imm>>5)<<10 | regCI(ins.rs1)<<7 | (imm&0x1f)<<2
  1815  }
  1816  
  1817  // encodeCI encodes a compressed immediate (CI-type) instruction.
  1818  func encodeCI(ins *instruction) uint32 {
  1819  	imm := uint32(ins.imm)
  1820  	if ins.as == ACLWSP {
  1821  		// Bit order [5:2|7:6]
  1822  		imm = encodeBitPattern(imm, []int{5, 4, 3, 2, 7, 6})
  1823  	} else if ins.as == ACLDSP || ins.as == ACFLDSP {
  1824  		// Bit order [5:3|8:6]
  1825  		imm = encodeBitPattern(imm, []int{5, 4, 3, 8, 7, 6})
  1826  	} else if ins.as == ACADDI16SP {
  1827  		// Bit order [9|4|6|8:7|5]
  1828  		imm = encodeBitPattern(imm, []int{9, 4, 6, 8, 7, 5})
  1829  	}
  1830  	rd := uint32(0)
  1831  	if ins.as == ACFLDSP {
  1832  		rd = regF(ins.rd)
  1833  	} else {
  1834  		rd = regI(ins.rd)
  1835  	}
  1836  	return compressedEncoding(ins.as) | ((imm>>5)&0x1)<<12 | rd<<7 | (imm&0x1f)<<2
  1837  }
  1838  
  1839  // encodeCIW encodes a compressed immediate wide (CIW-type) instruction.
  1840  func encodeCIW(ins *instruction) uint32 {
  1841  	imm := uint32(ins.imm)
  1842  	if ins.as == ACADDI4SPN {
  1843  		// Bit order [5:4|9:6|2|3]
  1844  		imm = encodeBitPattern(imm, []int{5, 4, 9, 8, 7, 6, 2, 3})
  1845  	}
  1846  	return compressedEncoding(ins.as) | imm<<5 | regCI(ins.rd)<<2
  1847  }
  1848  
  1849  // encodeCJImmediate encodes an immediate for a CJ-type RISC-V instruction.
  1850  func encodeCJImmediate(imm uint32) uint32 {
  1851  	// Bit order - [11|4|9:8|10|6|7|3:1|5]
  1852  	bits := encodeBitPattern(imm, []int{11, 4, 9, 8, 10, 6, 7, 3, 2, 1, 5})
  1853  	return bits << 2
  1854  }
  1855  
  1856  // encodeCJ encodes a compressed jump (CJ-type) instruction.
  1857  func encodeCJ(ins *instruction) uint32 {
  1858  	return compressedEncoding(ins.as) | encodeCJImmediate(uint32(ins.imm))
  1859  }
  1860  
  1861  // encodeCL encodes a compressed load (CL-type) instruction.
  1862  func encodeCL(ins *instruction) uint32 {
  1863  	imm := uint32(ins.imm)
  1864  	if ins.as == ACLW {
  1865  		// Bit order [5:2|6]
  1866  		imm = encodeBitPattern(imm, []int{5, 4, 3, 2, 6})
  1867  	} else if ins.as == ACLD || ins.as == ACFLD {
  1868  		// Bit order [5:3|7:6]
  1869  		imm = encodeBitPattern(imm, []int{5, 4, 3, 7, 6})
  1870  	}
  1871  	rd := uint32(0)
  1872  	if ins.as == ACFLD {
  1873  		rd = regCF(ins.rd)
  1874  	} else {
  1875  		rd = regCI(ins.rd)
  1876  	}
  1877  	return compressedEncoding(ins.as) | (imm>>2)<<10 | regCI(ins.rs1)<<7 | (imm&0x3)<<5 | rd<<2
  1878  }
  1879  
  1880  // encodeCR encodes a compressed register (CR-type) instruction.
  1881  func encodeCR(ins *instruction) uint32 {
  1882  	rs1, rs2 := uint32(0), uint32(0)
  1883  	switch ins.as {
  1884  	case ACJR, ACJALR:
  1885  		rs1 = regI(ins.rs1)
  1886  	case ACMV:
  1887  		rs1, rs2 = regI(ins.rd), regI(ins.rs2)
  1888  	case ACADD:
  1889  		rs1, rs2 = regI(ins.rs1), regI(ins.rs2)
  1890  	}
  1891  	return compressedEncoding(ins.as) | rs1<<7 | rs2<<2
  1892  }
  1893  
  1894  // encodeCS encodes a compressed store (CS-type) instruction.
  1895  func encodeCS(ins *instruction) uint32 {
  1896  	imm := uint32(ins.imm)
  1897  	if ins.as == ACSW {
  1898  		// Bit order [5:3|2|6]
  1899  		imm = encodeBitPattern(imm, []int{5, 4, 3, 2, 6})
  1900  	} else if ins.as == ACSD || ins.as == ACFSD {
  1901  		// Bit order [5:3|7:6]
  1902  		imm = encodeBitPattern(imm, []int{5, 4, 3, 7, 6})
  1903  	}
  1904  	rs2 := uint32(0)
  1905  	if ins.as == ACFSD {
  1906  		rs2 = regCF(ins.rs2)
  1907  	} else {
  1908  		rs2 = regCI(ins.rs2)
  1909  	}
  1910  	return compressedEncoding(ins.as) | ((imm>>2)&0x7)<<10 | regCI(ins.rs1)<<7 | (imm&3)<<5 | rs2<<2
  1911  }
  1912  
  1913  // encodeCSS encodes a compressed stack-relative store (CSS-type) instruction.
  1914  func encodeCSS(ins *instruction) uint32 {
  1915  	imm := uint32(ins.imm)
  1916  	if ins.as == ACSWSP {
  1917  		// Bit order [5:2|7:6]
  1918  		imm = encodeBitPattern(imm, []int{5, 4, 3, 2, 7, 6})
  1919  	} else if ins.as == ACSDSP || ins.as == ACFSDSP {
  1920  		// Bit order [5:3|8:6]
  1921  		imm = encodeBitPattern(imm, []int{5, 4, 3, 8, 7, 6})
  1922  	}
  1923  	rs2 := uint32(0)
  1924  	if ins.as == ACFSDSP {
  1925  		rs2 = regF(ins.rs2)
  1926  	} else {
  1927  		rs2 = regI(ins.rs2)
  1928  	}
  1929  	return compressedEncoding(ins.as) | imm<<7 | rs2<<2
  1930  }
  1931  
  1932  // encodeR encodes an R-type RISC-V instruction.
  1933  func encodeR(as obj.As, rs1, rs2, rd, funct3, funct7 uint32) uint32 {
  1934  	enc := encode(as)
  1935  	if enc == nil {
  1936  		panic("encodeR: could not encode instruction")
  1937  	}
  1938  	if enc.rs1 != 0 && rs1 != 0 {
  1939  		panic("encodeR: instruction uses rs1, but rs1 is nonzero")
  1940  	}
  1941  	if enc.rs2 != 0 && rs2 != 0 {
  1942  		panic("encodeR: instruction uses rs2, but rs2 is nonzero")
  1943  	}
  1944  	funct3 |= enc.funct3
  1945  	funct7 |= enc.funct7
  1946  	rs1 |= enc.rs1
  1947  	rs2 |= enc.rs2
  1948  	return funct7<<25 | rs2<<20 | rs1<<15 | funct3<<12 | rd<<7 | enc.opcode
  1949  }
  1950  
  1951  // encodeR4 encodes an R4-type RISC-V instruction.
  1952  func encodeR4(as obj.As, rs1, rs2, rs3, rd, funct3, funct2 uint32) uint32 {
  1953  	enc := encode(as)
  1954  	if enc == nil {
  1955  		panic("encodeR4: could not encode instruction")
  1956  	}
  1957  	if enc.rs2 != 0 {
  1958  		panic("encodeR4: instruction uses rs2")
  1959  	}
  1960  	funct2 |= enc.funct7
  1961  	if funct2&^3 != 0 {
  1962  		panic("encodeR4: funct2 requires more than 2 bits")
  1963  	}
  1964  	return rs3<<27 | funct2<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | funct3<<12 | rd<<7 | enc.opcode
  1965  }
  1966  
  1967  func encodeRII(ins *instruction) uint32 {
  1968  	return encodeR(ins.as, regI(ins.rs1), 0, regI(ins.rd), ins.funct3, ins.funct7)
  1969  }
  1970  
  1971  func encodeRIII(ins *instruction) uint32 {
  1972  	return encodeR(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
  1973  }
  1974  
  1975  func encodeRFFF(ins *instruction) uint32 {
  1976  	return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rd), ins.funct3, ins.funct7)
  1977  }
  1978  
  1979  func encodeRFFFF(ins *instruction) uint32 {
  1980  	return encodeR4(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rs3), regF(ins.rd), ins.funct3, ins.funct7)
  1981  }
  1982  
  1983  func encodeRFFI(ins *instruction) uint32 {
  1984  	return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
  1985  }
  1986  
  1987  func encodeRFI(ins *instruction) uint32 {
  1988  	return encodeR(ins.as, regF(ins.rs2), 0, regI(ins.rd), ins.funct3, ins.funct7)
  1989  }
  1990  
  1991  func encodeRFF(ins *instruction) uint32 {
  1992  	return encodeR(ins.as, regF(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7)
  1993  }
  1994  
  1995  func encodeRFV(ins *instruction) uint32 {
  1996  	return encodeR(ins.as, regF(ins.rs2), 0, regV(ins.rd), ins.funct3, ins.funct7)
  1997  }
  1998  
  1999  func encodeRIF(ins *instruction) uint32 {
  2000  	return encodeR(ins.as, regI(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7)
  2001  }
  2002  
  2003  func encodeRIV(ins *instruction) uint32 {
  2004  	return encodeR(ins.as, regI(ins.rs2), 0, regV(ins.rd), ins.funct3, ins.funct7)
  2005  }
  2006  
  2007  func encodeRVF(ins *instruction) uint32 {
  2008  	return encodeR(ins.as, 0, regV(ins.rs2), regF(ins.rd), ins.funct3, ins.funct7)
  2009  }
  2010  
  2011  func encodeRVFV(ins *instruction) uint32 {
  2012  	return encodeR(ins.as, regF(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
  2013  }
  2014  
  2015  func encodeRVI(ins *instruction) uint32 {
  2016  	return encodeR(ins.as, 0, regV(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
  2017  }
  2018  
  2019  func encodeRVIV(ins *instruction) uint32 {
  2020  	return encodeR(ins.as, regI(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
  2021  }
  2022  
  2023  func encodeRVV(ins *instruction) uint32 {
  2024  	return encodeR(ins.as, 0, regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
  2025  }
  2026  
  2027  func encodeRVVi(ins *instruction) uint32 {
  2028  	return encodeR(ins.as, immI(ins.as, ins.imm, 5), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
  2029  }
  2030  
  2031  func encodeRVVu(ins *instruction) uint32 {
  2032  	return encodeR(ins.as, immU(ins.as, ins.imm, 5), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
  2033  }
  2034  
  2035  func encodeRVVV(ins *instruction) uint32 {
  2036  	return encodeR(ins.as, regV(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct3, ins.funct7)
  2037  }
  2038  
  2039  // encodeI encodes an I-type RISC-V instruction.
  2040  func encodeI(as obj.As, rs1, rd, imm, funct7 uint32) uint32 {
  2041  	enc := encode(as)
  2042  	if enc == nil {
  2043  		panic("encodeI: could not encode instruction")
  2044  	}
  2045  	imm |= uint32(enc.csr)
  2046  	return funct7<<25 | imm<<20 | rs1<<15 | enc.funct3<<12 | rd<<7 | enc.opcode
  2047  }
  2048  
  2049  func encodeIII(ins *instruction) uint32 {
  2050  	return encodeI(ins.as, regI(ins.rs1), regI(ins.rd), uint32(ins.imm), 0)
  2051  }
  2052  
  2053  func encodeIF(ins *instruction) uint32 {
  2054  	return encodeI(ins.as, regI(ins.rs1), regF(ins.rd), uint32(ins.imm), 0)
  2055  }
  2056  
  2057  func encodeIV(ins *instruction) uint32 {
  2058  	return encodeI(ins.as, regI(ins.rs1), regV(ins.rd), uint32(ins.imm), ins.funct7)
  2059  }
  2060  
  2061  func encodeIIIV(ins *instruction) uint32 {
  2062  	return encodeI(ins.as, regI(ins.rs1), regV(ins.rd), regI(ins.rs2), ins.funct7)
  2063  }
  2064  
  2065  func encodeIVIV(ins *instruction) uint32 {
  2066  	return encodeI(ins.as, regI(ins.rs1), regV(ins.rd), regV(ins.rs2), ins.funct7)
  2067  }
  2068  
  2069  // encodeS encodes an S-type RISC-V instruction.
  2070  func encodeS(as obj.As, rs1, rs2, imm, funct7 uint32) uint32 {
  2071  	enc := encode(as)
  2072  	if enc == nil {
  2073  		panic("encodeS: could not encode instruction")
  2074  	}
  2075  	if enc.rs2 != 0 && rs2 != 0 {
  2076  		panic("encodeS: instruction uses rs2, but rs2 was nonzero")
  2077  	}
  2078  	rs2 |= enc.rs2
  2079  	imm |= uint32(enc.csr) &^ 0x1f
  2080  	return funct7<<25 | (imm>>5)<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | (imm&0x1f)<<7 | enc.opcode
  2081  }
  2082  
  2083  func encodeSI(ins *instruction) uint32 {
  2084  	return encodeS(ins.as, regI(ins.rd), regI(ins.rs1), uint32(ins.imm), 0)
  2085  }
  2086  
  2087  func encodeSF(ins *instruction) uint32 {
  2088  	return encodeS(ins.as, regI(ins.rd), regF(ins.rs1), uint32(ins.imm), 0)
  2089  }
  2090  
  2091  func encodeSV(ins *instruction) uint32 {
  2092  	return encodeS(ins.as, regI(ins.rd), 0, regV(ins.rs1), ins.funct7)
  2093  }
  2094  
  2095  func encodeSVII(ins *instruction) uint32 {
  2096  	return encodeS(ins.as, regI(ins.rs1), regI(ins.rs2), regV(ins.rd), ins.funct7)
  2097  }
  2098  
  2099  func encodeSVIV(ins *instruction) uint32 {
  2100  	return encodeS(ins.as, regI(ins.rs1), regV(ins.rs2), regV(ins.rd), ins.funct7)
  2101  }
  2102  
  2103  // encodeBImmediate encodes an immediate for a B-type RISC-V instruction.
  2104  func encodeBImmediate(imm uint32) uint32 {
  2105  	return (imm>>12)<<31 | ((imm>>5)&0x3f)<<25 | ((imm>>1)&0xf)<<8 | ((imm>>11)&0x1)<<7
  2106  }
  2107  
  2108  // encodeB encodes a B-type RISC-V instruction.
  2109  func encodeB(ins *instruction) uint32 {
  2110  	imm := immI(ins.as, ins.imm, 13)
  2111  	rs2 := regI(ins.rs1)
  2112  	rs1 := regI(ins.rs2)
  2113  	enc := encode(ins.as)
  2114  	if enc == nil {
  2115  		panic("encodeB: could not encode instruction")
  2116  	}
  2117  	return encodeBImmediate(imm) | rs2<<20 | rs1<<15 | enc.funct3<<12 | enc.opcode
  2118  }
  2119  
  2120  // encodeU encodes a U-type RISC-V instruction.
  2121  func encodeU(ins *instruction) uint32 {
  2122  	// The immediates for encodeU are the upper 20 bits of a 32 bit value.
  2123  	// Rather than have the user/compiler generate a 32 bit constant, the
  2124  	// bottommost bits of which must all be zero, instead accept just the
  2125  	// top bits.
  2126  	imm := immI(ins.as, ins.imm, 20)
  2127  	rd := regI(ins.rd)
  2128  	enc := encode(ins.as)
  2129  	if enc == nil {
  2130  		panic("encodeU: could not encode instruction")
  2131  	}
  2132  	return imm<<12 | rd<<7 | enc.opcode
  2133  }
  2134  
  2135  // encodeJImmediate encodes an immediate for a J-type RISC-V instruction.
  2136  func encodeJImmediate(imm uint32) uint32 {
  2137  	return (imm>>20)<<31 | ((imm>>1)&0x3ff)<<21 | ((imm>>11)&0x1)<<20 | ((imm>>12)&0xff)<<12
  2138  }
  2139  
  2140  // encodeJ encodes a J-type RISC-V instruction.
  2141  func encodeJ(ins *instruction) uint32 {
  2142  	imm := immI(ins.as, ins.imm, 21)
  2143  	rd := regI(ins.rd)
  2144  	enc := encode(ins.as)
  2145  	if enc == nil {
  2146  		panic("encodeJ: could not encode instruction")
  2147  	}
  2148  	return encodeJImmediate(imm) | rd<<7 | enc.opcode
  2149  }
  2150  
  2151  func encodeVset(as obj.As, rs1, rs2, rd uint32) uint32 {
  2152  	enc := encode(as)
  2153  	if enc == nil {
  2154  		panic("encodeVset: could not encode instruction")
  2155  	}
  2156  	return enc.funct7<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | rd<<7 | enc.opcode
  2157  }
  2158  
  2159  func encodeVsetvli(ins *instruction) uint32 {
  2160  	vtype := immU(ins.as, ins.imm, 11)
  2161  	return encodeVset(ins.as, regI(ins.rs1), vtype, regI(ins.rd))
  2162  }
  2163  
  2164  func encodeVsetivli(ins *instruction) uint32 {
  2165  	vtype := immU(ins.as, ins.imm, 10)
  2166  	avl := immU(ins.as, int64(ins.rs1), 5)
  2167  	return encodeVset(ins.as, avl, vtype, regI(ins.rd))
  2168  }
  2169  
  2170  func encodeVsetvl(ins *instruction) uint32 {
  2171  	return encodeVset(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd))
  2172  }
  2173  
  2174  func encodeRawIns(ins *instruction) uint32 {
  2175  	// Treat the raw value specially as a 32-bit unsigned integer.
  2176  	// Nobody wants to enter negative machine code.
  2177  	return immU(ins.as, ins.imm, 32)
  2178  }
  2179  
  2180  func EncodeBImmediate(imm int64) (int64, error) {
  2181  	if err := immIFits(imm, 13); err != nil {
  2182  		return 0, err
  2183  	}
  2184  	if err := immEven(imm); err != nil {
  2185  		return 0, err
  2186  	}
  2187  	return int64(encodeBImmediate(uint32(imm))), nil
  2188  }
  2189  
  2190  func EncodeCBImmediate(imm int64) (int64, error) {
  2191  	if err := immIFits(imm, 9); err != nil {
  2192  		return 0, err
  2193  	}
  2194  	if err := immEven(imm); err != nil {
  2195  		return 0, err
  2196  	}
  2197  	return int64(encodeCBImmediate(uint32(imm))), nil
  2198  }
  2199  
  2200  func EncodeCJImmediate(imm int64) (int64, error) {
  2201  	if err := immIFits(imm, 12); err != nil {
  2202  		return 0, err
  2203  	}
  2204  	if err := immEven(imm); err != nil {
  2205  		return 0, err
  2206  	}
  2207  	return int64(encodeCJImmediate(uint32(imm))), nil
  2208  }
  2209  
  2210  func EncodeIImmediate(imm int64) (int64, error) {
  2211  	if err := immIFits(imm, 12); err != nil {
  2212  		return 0, err
  2213  	}
  2214  	return imm << 20, nil
  2215  }
  2216  
  2217  func EncodeJImmediate(imm int64) (int64, error) {
  2218  	if err := immIFits(imm, 21); err != nil {
  2219  		return 0, err
  2220  	}
  2221  	if err := immEven(imm); err != nil {
  2222  		return 0, err
  2223  	}
  2224  	return int64(encodeJImmediate(uint32(imm))), nil
  2225  }
  2226  
  2227  func EncodeSImmediate(imm int64) (int64, error) {
  2228  	if err := immIFits(imm, 12); err != nil {
  2229  		return 0, err
  2230  	}
  2231  	return ((imm >> 5) << 25) | ((imm & 0x1f) << 7), nil
  2232  }
  2233  
  2234  func EncodeUImmediate(imm int64) (int64, error) {
  2235  	if err := immIFits(imm, 20); err != nil {
  2236  		return 0, err
  2237  	}
  2238  	return imm << 12, nil
  2239  }
  2240  
  2241  func EncodeVectorType(vsew, vlmul, vtail, vmask int64) (int64, error) {
  2242  	vsewSO := SpecialOperand(vsew)
  2243  	if vsewSO < SPOP_E8 || vsewSO > SPOP_E64 {
  2244  		return -1, fmt.Errorf("invalid vector selected element width %q", vsewSO)
  2245  	}
  2246  	vlmulSO := SpecialOperand(vlmul)
  2247  	if vlmulSO < SPOP_M1 || vlmulSO > SPOP_MF8 {
  2248  		return -1, fmt.Errorf("invalid vector register group multiplier %q", vlmulSO)
  2249  	}
  2250  	vtailSO := SpecialOperand(vtail)
  2251  	if vtailSO != SPOP_TA && vtailSO != SPOP_TU {
  2252  		return -1, fmt.Errorf("invalid vector tail policy %q", vtailSO)
  2253  	}
  2254  	vmaskSO := SpecialOperand(vmask)
  2255  	if vmaskSO != SPOP_MA && vmaskSO != SPOP_MU {
  2256  		return -1, fmt.Errorf("invalid vector mask policy %q", vmaskSO)
  2257  	}
  2258  	vtype := vmaskSO.encode()<<7 | vtailSO.encode()<<6 | vsewSO.encode()<<3 | vlmulSO.encode()
  2259  	return int64(vtype), nil
  2260  }
  2261  
  2262  type encoding struct {
  2263  	encode   func(*instruction) uint32     // encode returns the machine code for an instruction
  2264  	validate func(*obj.Link, *instruction) // validate validates an instruction
  2265  	length   int                           // length of encoded instruction; 0 for pseudo-ops, 2 for compressed instructions, 4 otherwise
  2266  }
  2267  
  2268  var (
  2269  	// Encodings have the following naming convention:
  2270  	//
  2271  	//  1. the instruction encoding (R/I/S/B/U/J), in lowercase
  2272  	//  2. zero or more register operand identifiers (I = integer
  2273  	//     register, F = float register, V = vector register), in uppercase
  2274  	//  3. the word "Encoding"
  2275  	//
  2276  	// For example, rIIIEncoding indicates an R-type instruction with two
  2277  	// integer register inputs and an integer register output; sFEncoding
  2278  	// indicates an S-type instruction with rs2 being a float register.
  2279  
  2280  	rIIIEncoding  = encoding{encode: encodeRIII, validate: validateRIII, length: 4}
  2281  	rIIEncoding   = encoding{encode: encodeRII, validate: validateRII, length: 4}
  2282  	rFFFEncoding  = encoding{encode: encodeRFFF, validate: validateRFFF, length: 4}
  2283  	rFFFFEncoding = encoding{encode: encodeRFFFF, validate: validateRFFFF, length: 4}
  2284  	rFFIEncoding  = encoding{encode: encodeRFFI, validate: validateRFFI, length: 4}
  2285  	rFIEncoding   = encoding{encode: encodeRFI, validate: validateRFI, length: 4}
  2286  	rFVEncoding   = encoding{encode: encodeRFV, validate: validateRFV, length: 4}
  2287  	rIFEncoding   = encoding{encode: encodeRIF, validate: validateRIF, length: 4}
  2288  	rIVEncoding   = encoding{encode: encodeRIV, validate: validateRIV, length: 4}
  2289  	rFFEncoding   = encoding{encode: encodeRFF, validate: validateRFF, length: 4}
  2290  	rVFEncoding   = encoding{encode: encodeRVF, validate: validateRVF, length: 4}
  2291  	rVFVEncoding  = encoding{encode: encodeRVFV, validate: validateRVFV, length: 4}
  2292  	rVIEncoding   = encoding{encode: encodeRVI, validate: validateRVI, length: 4}
  2293  	rVIVEncoding  = encoding{encode: encodeRVIV, validate: validateRVIV, length: 4}
  2294  	rVVEncoding   = encoding{encode: encodeRVV, validate: validateRVV, length: 4}
  2295  	rVViEncoding  = encoding{encode: encodeRVVi, validate: validateRVVi, length: 4}
  2296  	rVVuEncoding  = encoding{encode: encodeRVVu, validate: validateRVVu, length: 4}
  2297  	rVVVEncoding  = encoding{encode: encodeRVVV, validate: validateRVVV, length: 4}
  2298  
  2299  	iIIEncoding  = encoding{encode: encodeIII, validate: validateIII, length: 4}
  2300  	iFEncoding   = encoding{encode: encodeIF, validate: validateIF, length: 4}
  2301  	iVEncoding   = encoding{encode: encodeIV, validate: validateIV, length: 4}
  2302  	iIIVEncoding = encoding{encode: encodeIIIV, validate: validateIIIV, length: 4}
  2303  	iVIVEncoding = encoding{encode: encodeIVIV, validate: validateIVIV, length: 4}
  2304  
  2305  	sIEncoding   = encoding{encode: encodeSI, validate: validateSI, length: 4}
  2306  	sFEncoding   = encoding{encode: encodeSF, validate: validateSF, length: 4}
  2307  	sVEncoding   = encoding{encode: encodeSV, validate: validateSV, length: 4}
  2308  	sVIIEncoding = encoding{encode: encodeSVII, validate: validateSVII, length: 4}
  2309  	sVIVEncoding = encoding{encode: encodeSVIV, validate: validateSVIV, length: 4}
  2310  
  2311  	bEncoding = encoding{encode: encodeB, validate: validateB, length: 4}
  2312  	uEncoding = encoding{encode: encodeU, validate: validateU, length: 4}
  2313  	jEncoding = encoding{encode: encodeJ, validate: validateJ, length: 4}
  2314  
  2315  	// Compressed encodings.
  2316  	caEncoding  = encoding{encode: encodeCA, validate: validateCA, length: 2}
  2317  	cbEncoding  = encoding{encode: encodeCB, validate: validateCB, length: 2}
  2318  	ciEncoding  = encoding{encode: encodeCI, validate: validateCI, length: 2}
  2319  	ciwEncoding = encoding{encode: encodeCIW, validate: validateCIW, length: 2}
  2320  	cjEncoding  = encoding{encode: encodeCJ, validate: validateCJ, length: 2}
  2321  	clEncoding  = encoding{encode: encodeCL, validate: validateCL, length: 2}
  2322  	crEncoding  = encoding{encode: encodeCR, validate: validateCR, length: 2}
  2323  	csEncoding  = encoding{encode: encodeCS, validate: validateCS, length: 2}
  2324  	cssEncoding = encoding{encode: encodeCSS, validate: validateCSS, length: 2}
  2325  
  2326  	// Encodings for vector configuration setting instruction.
  2327  	vsetvliEncoding  = encoding{encode: encodeVsetvli, validate: validateVsetvli, length: 4}
  2328  	vsetivliEncoding = encoding{encode: encodeVsetivli, validate: validateVsetivli, length: 4}
  2329  	vsetvlEncoding   = encoding{encode: encodeVsetvl, validate: validateVsetvl, length: 4}
  2330  
  2331  	// rawEncoding encodes a raw instruction byte sequence.
  2332  	rawEncoding = encoding{encode: encodeRawIns, validate: validateRaw, length: 4}
  2333  
  2334  	// pseudoOpEncoding panics if encoding is attempted, but does no validation.
  2335  	pseudoOpEncoding = encoding{encode: nil, validate: func(*obj.Link, *instruction) {}, length: 0}
  2336  
  2337  	// badEncoding is used when an invalid op is encountered.
  2338  	// An error has already been generated, so let anything else through.
  2339  	badEncoding = encoding{encode: func(*instruction) uint32 { return 0 }, validate: func(*obj.Link, *instruction) {}, length: 0}
  2340  )
  2341  
  2342  // instructionData specifies details relating to a RISC-V instruction.
  2343  type instructionData struct {
  2344  	enc     encoding
  2345  	immForm obj.As // immediate form of this instruction
  2346  	ternary bool
  2347  }
  2348  
  2349  // instructions contains details of RISC-V instructions, including
  2350  // their encoding type. Entries are masked with obj.AMask to keep
  2351  // indices small.
  2352  var instructions = [ALAST & obj.AMask]instructionData{
  2353  	//
  2354  	// Unprivileged ISA
  2355  	//
  2356  
  2357  	// 2.4: Integer Computational Instructions
  2358  	AADDI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  2359  	ASLTI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  2360  	ASLTIU & obj.AMask: {enc: iIIEncoding, ternary: true},
  2361  	AANDI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  2362  	AORI & obj.AMask:   {enc: iIIEncoding, ternary: true},
  2363  	AXORI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  2364  	ASLLI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  2365  	ASRLI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  2366  	ASRAI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  2367  	ALUI & obj.AMask:   {enc: uEncoding},
  2368  	AAUIPC & obj.AMask: {enc: uEncoding},
  2369  	AADD & obj.AMask:   {enc: rIIIEncoding, immForm: AADDI, ternary: true},
  2370  	ASLT & obj.AMask:   {enc: rIIIEncoding, immForm: ASLTI, ternary: true},
  2371  	ASLTU & obj.AMask:  {enc: rIIIEncoding, immForm: ASLTIU, ternary: true},
  2372  	AAND & obj.AMask:   {enc: rIIIEncoding, immForm: AANDI, ternary: true},
  2373  	AOR & obj.AMask:    {enc: rIIIEncoding, immForm: AORI, ternary: true},
  2374  	AXOR & obj.AMask:   {enc: rIIIEncoding, immForm: AXORI, ternary: true},
  2375  	ASLL & obj.AMask:   {enc: rIIIEncoding, immForm: ASLLI, ternary: true},
  2376  	ASRL & obj.AMask:   {enc: rIIIEncoding, immForm: ASRLI, ternary: true},
  2377  	ASUB & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2378  	ASRA & obj.AMask:   {enc: rIIIEncoding, immForm: ASRAI, ternary: true},
  2379  
  2380  	// 2.5: Control Transfer Instructions
  2381  	AJAL & obj.AMask:  {enc: jEncoding},
  2382  	AJALR & obj.AMask: {enc: iIIEncoding},
  2383  	ABEQ & obj.AMask:  {enc: bEncoding},
  2384  	ABNE & obj.AMask:  {enc: bEncoding},
  2385  	ABLT & obj.AMask:  {enc: bEncoding},
  2386  	ABLTU & obj.AMask: {enc: bEncoding},
  2387  	ABGE & obj.AMask:  {enc: bEncoding},
  2388  	ABGEU & obj.AMask: {enc: bEncoding},
  2389  
  2390  	// 2.6: Load and Store Instructions
  2391  	ALW & obj.AMask:  {enc: iIIEncoding},
  2392  	ALWU & obj.AMask: {enc: iIIEncoding},
  2393  	ALH & obj.AMask:  {enc: iIIEncoding},
  2394  	ALHU & obj.AMask: {enc: iIIEncoding},
  2395  	ALB & obj.AMask:  {enc: iIIEncoding},
  2396  	ALBU & obj.AMask: {enc: iIIEncoding},
  2397  	ASW & obj.AMask:  {enc: sIEncoding},
  2398  	ASH & obj.AMask:  {enc: sIEncoding},
  2399  	ASB & obj.AMask:  {enc: sIEncoding},
  2400  
  2401  	// 2.7: Memory Ordering
  2402  	AFENCE & obj.AMask: {enc: iIIEncoding},
  2403  
  2404  	// 4.2: Integer Computational Instructions (RV64I)
  2405  	AADDIW & obj.AMask: {enc: iIIEncoding, ternary: true},
  2406  	ASLLIW & obj.AMask: {enc: iIIEncoding, ternary: true},
  2407  	ASRLIW & obj.AMask: {enc: iIIEncoding, ternary: true},
  2408  	ASRAIW & obj.AMask: {enc: iIIEncoding, ternary: true},
  2409  	AADDW & obj.AMask:  {enc: rIIIEncoding, immForm: AADDIW, ternary: true},
  2410  	ASLLW & obj.AMask:  {enc: rIIIEncoding, immForm: ASLLIW, ternary: true},
  2411  	ASRLW & obj.AMask:  {enc: rIIIEncoding, immForm: ASRLIW, ternary: true},
  2412  	ASUBW & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2413  	ASRAW & obj.AMask:  {enc: rIIIEncoding, immForm: ASRAIW, ternary: true},
  2414  
  2415  	// 4.3: Load and Store Instructions (RV64I)
  2416  	ALD & obj.AMask: {enc: iIIEncoding},
  2417  	ASD & obj.AMask: {enc: sIEncoding},
  2418  
  2419  	// 7.1: CSR Instructions
  2420  	ACSRRC & obj.AMask:  {enc: iIIEncoding, immForm: ACSRRCI},
  2421  	ACSRRCI & obj.AMask: {enc: iIIEncoding},
  2422  	ACSRRS & obj.AMask:  {enc: iIIEncoding, immForm: ACSRRSI},
  2423  	ACSRRSI & obj.AMask: {enc: iIIEncoding},
  2424  	ACSRRW & obj.AMask:  {enc: iIIEncoding, immForm: ACSRRWI},
  2425  	ACSRRWI & obj.AMask: {enc: iIIEncoding},
  2426  
  2427  	// 12.3: "Zicond" Extension for Integer Conditional Operations
  2428  	ACZERONEZ & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2429  	ACZEROEQZ & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2430  
  2431  	// 13.1: Multiplication Operations
  2432  	AMUL & obj.AMask:    {enc: rIIIEncoding, ternary: true},
  2433  	AMULH & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2434  	AMULHU & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2435  	AMULHSU & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2436  	AMULW & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2437  	ADIV & obj.AMask:    {enc: rIIIEncoding, ternary: true},
  2438  	ADIVU & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2439  	AREM & obj.AMask:    {enc: rIIIEncoding, ternary: true},
  2440  	AREMU & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2441  	ADIVW & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2442  	ADIVUW & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2443  	AREMW & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2444  	AREMUW & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2445  
  2446  	// 14.2: Load-Reserved/Store-Conditional Instructions (Zalrsc)
  2447  	ALRW & obj.AMask: {enc: rIIIEncoding},
  2448  	ALRD & obj.AMask: {enc: rIIIEncoding},
  2449  	ASCW & obj.AMask: {enc: rIIIEncoding},
  2450  	ASCD & obj.AMask: {enc: rIIIEncoding},
  2451  
  2452  	// 14.4: Atomic Memory Operations (Zaamo)
  2453  	AAMOSWAPW & obj.AMask: {enc: rIIIEncoding},
  2454  	AAMOSWAPD & obj.AMask: {enc: rIIIEncoding},
  2455  	AAMOADDW & obj.AMask:  {enc: rIIIEncoding},
  2456  	AAMOADDD & obj.AMask:  {enc: rIIIEncoding},
  2457  	AAMOANDW & obj.AMask:  {enc: rIIIEncoding},
  2458  	AAMOANDD & obj.AMask:  {enc: rIIIEncoding},
  2459  	AAMOORW & obj.AMask:   {enc: rIIIEncoding},
  2460  	AAMOORD & obj.AMask:   {enc: rIIIEncoding},
  2461  	AAMOXORW & obj.AMask:  {enc: rIIIEncoding},
  2462  	AAMOXORD & obj.AMask:  {enc: rIIIEncoding},
  2463  	AAMOMAXW & obj.AMask:  {enc: rIIIEncoding},
  2464  	AAMOMAXD & obj.AMask:  {enc: rIIIEncoding},
  2465  	AAMOMAXUW & obj.AMask: {enc: rIIIEncoding},
  2466  	AAMOMAXUD & obj.AMask: {enc: rIIIEncoding},
  2467  	AAMOMINW & obj.AMask:  {enc: rIIIEncoding},
  2468  	AAMOMIND & obj.AMask:  {enc: rIIIEncoding},
  2469  	AAMOMINUW & obj.AMask: {enc: rIIIEncoding},
  2470  	AAMOMINUD & obj.AMask: {enc: rIIIEncoding},
  2471  
  2472  	// 20.5: Single-Precision Load and Store Instructions
  2473  	AFLW & obj.AMask: {enc: iFEncoding},
  2474  	AFSW & obj.AMask: {enc: sFEncoding},
  2475  
  2476  	// 20.6: Single-Precision Floating-Point Computational Instructions
  2477  	AFADDS & obj.AMask:   {enc: rFFFEncoding},
  2478  	AFSUBS & obj.AMask:   {enc: rFFFEncoding},
  2479  	AFMULS & obj.AMask:   {enc: rFFFEncoding},
  2480  	AFDIVS & obj.AMask:   {enc: rFFFEncoding},
  2481  	AFMINS & obj.AMask:   {enc: rFFFEncoding},
  2482  	AFMAXS & obj.AMask:   {enc: rFFFEncoding},
  2483  	AFSQRTS & obj.AMask:  {enc: rFFFEncoding},
  2484  	AFMADDS & obj.AMask:  {enc: rFFFFEncoding},
  2485  	AFMSUBS & obj.AMask:  {enc: rFFFFEncoding},
  2486  	AFNMSUBS & obj.AMask: {enc: rFFFFEncoding},
  2487  	AFNMADDS & obj.AMask: {enc: rFFFFEncoding},
  2488  
  2489  	// 20.7: Single-Precision Floating-Point Conversion and Move Instructions
  2490  	AFCVTWS & obj.AMask:  {enc: rFIEncoding},
  2491  	AFCVTLS & obj.AMask:  {enc: rFIEncoding},
  2492  	AFCVTSW & obj.AMask:  {enc: rIFEncoding},
  2493  	AFCVTSL & obj.AMask:  {enc: rIFEncoding},
  2494  	AFCVTWUS & obj.AMask: {enc: rFIEncoding},
  2495  	AFCVTLUS & obj.AMask: {enc: rFIEncoding},
  2496  	AFCVTSWU & obj.AMask: {enc: rIFEncoding},
  2497  	AFCVTSLU & obj.AMask: {enc: rIFEncoding},
  2498  	AFSGNJS & obj.AMask:  {enc: rFFFEncoding},
  2499  	AFSGNJNS & obj.AMask: {enc: rFFFEncoding},
  2500  	AFSGNJXS & obj.AMask: {enc: rFFFEncoding},
  2501  	AFMVXW & obj.AMask:   {enc: rFIEncoding},
  2502  	AFMVWX & obj.AMask:   {enc: rIFEncoding},
  2503  
  2504  	// 20.8: Single-Precision Floating-Point Compare Instructions
  2505  	AFEQS & obj.AMask: {enc: rFFIEncoding},
  2506  	AFLTS & obj.AMask: {enc: rFFIEncoding},
  2507  	AFLES & obj.AMask: {enc: rFFIEncoding},
  2508  
  2509  	// 20.9: Single-Precision Floating-Point Classify Instruction
  2510  	AFCLASSS & obj.AMask: {enc: rFIEncoding},
  2511  
  2512  	// 12.3: Double-Precision Load and Store Instructions
  2513  	AFLD & obj.AMask: {enc: iFEncoding},
  2514  	AFSD & obj.AMask: {enc: sFEncoding},
  2515  
  2516  	// 21.4: Double-Precision Floating-Point Computational Instructions
  2517  	AFADDD & obj.AMask:   {enc: rFFFEncoding},
  2518  	AFSUBD & obj.AMask:   {enc: rFFFEncoding},
  2519  	AFMULD & obj.AMask:   {enc: rFFFEncoding},
  2520  	AFDIVD & obj.AMask:   {enc: rFFFEncoding},
  2521  	AFMIND & obj.AMask:   {enc: rFFFEncoding},
  2522  	AFMAXD & obj.AMask:   {enc: rFFFEncoding},
  2523  	AFSQRTD & obj.AMask:  {enc: rFFFEncoding},
  2524  	AFMADDD & obj.AMask:  {enc: rFFFFEncoding},
  2525  	AFMSUBD & obj.AMask:  {enc: rFFFFEncoding},
  2526  	AFNMSUBD & obj.AMask: {enc: rFFFFEncoding},
  2527  	AFNMADDD & obj.AMask: {enc: rFFFFEncoding},
  2528  
  2529  	// 21.5: Double-Precision Floating-Point Conversion and Move Instructions
  2530  	AFCVTWD & obj.AMask:  {enc: rFIEncoding},
  2531  	AFCVTLD & obj.AMask:  {enc: rFIEncoding},
  2532  	AFCVTDW & obj.AMask:  {enc: rIFEncoding},
  2533  	AFCVTDL & obj.AMask:  {enc: rIFEncoding},
  2534  	AFCVTWUD & obj.AMask: {enc: rFIEncoding},
  2535  	AFCVTLUD & obj.AMask: {enc: rFIEncoding},
  2536  	AFCVTDWU & obj.AMask: {enc: rIFEncoding},
  2537  	AFCVTDLU & obj.AMask: {enc: rIFEncoding},
  2538  	AFCVTSD & obj.AMask:  {enc: rFFEncoding},
  2539  	AFCVTDS & obj.AMask:  {enc: rFFEncoding},
  2540  	AFSGNJD & obj.AMask:  {enc: rFFFEncoding},
  2541  	AFSGNJND & obj.AMask: {enc: rFFFEncoding},
  2542  	AFSGNJXD & obj.AMask: {enc: rFFFEncoding},
  2543  	AFMVXD & obj.AMask:   {enc: rFIEncoding},
  2544  	AFMVDX & obj.AMask:   {enc: rIFEncoding},
  2545  
  2546  	// 21.6: Double-Precision Floating-Point Compare Instructions
  2547  	AFEQD & obj.AMask: {enc: rFFIEncoding},
  2548  	AFLTD & obj.AMask: {enc: rFFIEncoding},
  2549  	AFLED & obj.AMask: {enc: rFFIEncoding},
  2550  
  2551  	// 21.7: Double-Precision Floating-Point Classify Instruction
  2552  	AFCLASSD & obj.AMask: {enc: rFIEncoding},
  2553  
  2554  	//
  2555  	// "C" Extension for Compressed Instructions, Version 2.0
  2556  	//
  2557  
  2558  	// 26.3.1: Compressed Stack-Pointer-Based Loads and Stores
  2559  	ACLWSP & obj.AMask:  {enc: ciEncoding},
  2560  	ACLDSP & obj.AMask:  {enc: ciEncoding},
  2561  	ACFLDSP & obj.AMask: {enc: ciEncoding},
  2562  	ACSWSP & obj.AMask:  {enc: cssEncoding},
  2563  	ACSDSP & obj.AMask:  {enc: cssEncoding},
  2564  	ACFSDSP & obj.AMask: {enc: cssEncoding},
  2565  
  2566  	// 26.3.2: Compressed Register-Based Loads and Stores
  2567  	ACLW & obj.AMask:  {enc: clEncoding},
  2568  	ACLD & obj.AMask:  {enc: clEncoding},
  2569  	ACFLD & obj.AMask: {enc: clEncoding},
  2570  	ACSW & obj.AMask:  {enc: csEncoding},
  2571  	ACSD & obj.AMask:  {enc: csEncoding},
  2572  	ACFSD & obj.AMask: {enc: csEncoding},
  2573  
  2574  	// 26.4: Compressed Control Transfer Instructions
  2575  	ACJ & obj.AMask:    {enc: cjEncoding},
  2576  	ACJR & obj.AMask:   {enc: crEncoding},
  2577  	ACJALR & obj.AMask: {enc: crEncoding},
  2578  	ACBEQZ & obj.AMask: {enc: cbEncoding},
  2579  	ACBNEZ & obj.AMask: {enc: cbEncoding},
  2580  
  2581  	// 26.5.1: Compressed Integer Constant-Generation Instructions
  2582  	ACLI & obj.AMask:  {enc: ciEncoding},
  2583  	ACLUI & obj.AMask: {enc: ciEncoding},
  2584  
  2585  	// 26.5.2: Compressed Integer Register-Immediate Operations
  2586  	ACADDI & obj.AMask:     {enc: ciEncoding, ternary: true},
  2587  	ACADDIW & obj.AMask:    {enc: ciEncoding, ternary: true},
  2588  	ACADDI16SP & obj.AMask: {enc: ciEncoding, ternary: true},
  2589  	ACADDI4SPN & obj.AMask: {enc: ciwEncoding, ternary: true},
  2590  	ACSLLI & obj.AMask:     {enc: ciEncoding, ternary: true},
  2591  	ACSRLI & obj.AMask:     {enc: cbEncoding, ternary: true},
  2592  	ACSRAI & obj.AMask:     {enc: cbEncoding, ternary: true},
  2593  	ACANDI & obj.AMask:     {enc: cbEncoding, ternary: true},
  2594  
  2595  	// 26.5.3: Compressed Integer Register-Register Operations
  2596  	ACMV & obj.AMask:   {enc: crEncoding},
  2597  	ACADD & obj.AMask:  {enc: crEncoding, immForm: ACADDI, ternary: true},
  2598  	ACAND & obj.AMask:  {enc: caEncoding, immForm: ACANDI, ternary: true},
  2599  	ACOR & obj.AMask:   {enc: caEncoding, ternary: true},
  2600  	ACXOR & obj.AMask:  {enc: caEncoding, ternary: true},
  2601  	ACSUB & obj.AMask:  {enc: caEncoding, ternary: true},
  2602  	ACADDW & obj.AMask: {enc: caEncoding, immForm: ACADDIW, ternary: true},
  2603  	ACSUBW & obj.AMask: {enc: caEncoding, ternary: true},
  2604  
  2605  	// 26.5.5: Compressed NOP Instruction
  2606  	ACNOP & obj.AMask: {enc: ciEncoding},
  2607  
  2608  	// 26.5.6: Compressed Breakpoint Instruction
  2609  	ACEBREAK & obj.AMask: {enc: crEncoding},
  2610  
  2611  	//
  2612  	// "B" Extension for Bit Manipulation, Version 1.0.0
  2613  	//
  2614  
  2615  	// 28.4.1: Address Generation Instructions (Zba)
  2616  	AADDUW & obj.AMask:    {enc: rIIIEncoding, ternary: true},
  2617  	ASH1ADD & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2618  	ASH1ADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2619  	ASH2ADD & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2620  	ASH2ADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2621  	ASH3ADD & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2622  	ASH3ADDUW & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2623  	ASLLIUW & obj.AMask:   {enc: iIIEncoding, ternary: true},
  2624  
  2625  	// 28.4.2: Basic Bit Manipulation (Zbb)
  2626  	AANDN & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2627  	ACLZ & obj.AMask:   {enc: rIIEncoding},
  2628  	ACLZW & obj.AMask:  {enc: rIIEncoding},
  2629  	ACPOP & obj.AMask:  {enc: rIIEncoding},
  2630  	ACPOPW & obj.AMask: {enc: rIIEncoding},
  2631  	ACTZ & obj.AMask:   {enc: rIIEncoding},
  2632  	ACTZW & obj.AMask:  {enc: rIIEncoding},
  2633  	AMAX & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2634  	AMAXU & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2635  	AMIN & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2636  	AMINU & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2637  	AORN & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2638  	ASEXTB & obj.AMask: {enc: rIIEncoding},
  2639  	ASEXTH & obj.AMask: {enc: rIIEncoding},
  2640  	AXNOR & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2641  	AZEXTH & obj.AMask: {enc: rIIEncoding},
  2642  
  2643  	// 28.4.2: Bitwise Rotation (Zbb)
  2644  	AROL & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2645  	AROLW & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2646  	AROR & obj.AMask:   {enc: rIIIEncoding, immForm: ARORI, ternary: true},
  2647  	ARORI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  2648  	ARORIW & obj.AMask: {enc: iIIEncoding, ternary: true},
  2649  	ARORW & obj.AMask:  {enc: rIIIEncoding, immForm: ARORIW, ternary: true},
  2650  	AORCB & obj.AMask:  {enc: rIIEncoding},
  2651  	AREV8 & obj.AMask:  {enc: rIIEncoding},
  2652  
  2653  	// 28.4.3: Carry-less Multiplication (Zbc)
  2654  	ACLMUL & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2655  	ACLMULH & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2656  	ACLMULR & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2657  
  2658  	// 28.4.4: Single-bit Instructions (Zbs)
  2659  	ABCLR & obj.AMask:  {enc: rIIIEncoding, immForm: ABCLRI, ternary: true},
  2660  	ABCLRI & obj.AMask: {enc: iIIEncoding, ternary: true},
  2661  	ABEXT & obj.AMask:  {enc: rIIIEncoding, immForm: ABEXTI, ternary: true},
  2662  	ABEXTI & obj.AMask: {enc: iIIEncoding, ternary: true},
  2663  	ABINV & obj.AMask:  {enc: rIIIEncoding, immForm: ABINVI, ternary: true},
  2664  	ABINVI & obj.AMask: {enc: iIIEncoding, ternary: true},
  2665  	ABSET & obj.AMask:  {enc: rIIIEncoding, immForm: ABSETI, ternary: true},
  2666  	ABSETI & obj.AMask: {enc: iIIEncoding, ternary: true},
  2667  
  2668  	//
  2669  	// "V" Standard Extension for Vector Operations, Version 1.0
  2670  	//
  2671  
  2672  	// 31.6: Vector Configuration-Setting Instructions
  2673  	AVSETVLI & obj.AMask:  {enc: vsetvliEncoding, immForm: AVSETIVLI},
  2674  	AVSETIVLI & obj.AMask: {enc: vsetivliEncoding},
  2675  	AVSETVL & obj.AMask:   {enc: vsetvlEncoding},
  2676  
  2677  	// 31.7.4: Vector Unit-Stride Instructions
  2678  	AVLE8V & obj.AMask:  {enc: iVEncoding},
  2679  	AVLE16V & obj.AMask: {enc: iVEncoding},
  2680  	AVLE32V & obj.AMask: {enc: iVEncoding},
  2681  	AVLE64V & obj.AMask: {enc: iVEncoding},
  2682  	AVSE8V & obj.AMask:  {enc: sVEncoding},
  2683  	AVSE16V & obj.AMask: {enc: sVEncoding},
  2684  	AVSE32V & obj.AMask: {enc: sVEncoding},
  2685  	AVSE64V & obj.AMask: {enc: sVEncoding},
  2686  	AVLMV & obj.AMask:   {enc: iVEncoding},
  2687  	AVSMV & obj.AMask:   {enc: sVEncoding},
  2688  
  2689  	// 31.7.5: Vector Strided Instructions
  2690  	AVLSE8V & obj.AMask:  {enc: iIIVEncoding},
  2691  	AVLSE16V & obj.AMask: {enc: iIIVEncoding},
  2692  	AVLSE32V & obj.AMask: {enc: iIIVEncoding},
  2693  	AVLSE64V & obj.AMask: {enc: iIIVEncoding},
  2694  	AVSSE8V & obj.AMask:  {enc: sVIIEncoding},
  2695  	AVSSE16V & obj.AMask: {enc: sVIIEncoding},
  2696  	AVSSE32V & obj.AMask: {enc: sVIIEncoding},
  2697  	AVSSE64V & obj.AMask: {enc: sVIIEncoding},
  2698  
  2699  	// 31.7.6: Vector Indexed Instructions
  2700  	AVLUXEI8V & obj.AMask:  {enc: iVIVEncoding},
  2701  	AVLUXEI16V & obj.AMask: {enc: iVIVEncoding},
  2702  	AVLUXEI32V & obj.AMask: {enc: iVIVEncoding},
  2703  	AVLUXEI64V & obj.AMask: {enc: iVIVEncoding},
  2704  	AVLOXEI8V & obj.AMask:  {enc: iVIVEncoding},
  2705  	AVLOXEI16V & obj.AMask: {enc: iVIVEncoding},
  2706  	AVLOXEI32V & obj.AMask: {enc: iVIVEncoding},
  2707  	AVLOXEI64V & obj.AMask: {enc: iVIVEncoding},
  2708  	AVSUXEI8V & obj.AMask:  {enc: sVIVEncoding},
  2709  	AVSUXEI16V & obj.AMask: {enc: sVIVEncoding},
  2710  	AVSUXEI32V & obj.AMask: {enc: sVIVEncoding},
  2711  	AVSUXEI64V & obj.AMask: {enc: sVIVEncoding},
  2712  	AVSOXEI8V & obj.AMask:  {enc: sVIVEncoding},
  2713  	AVSOXEI16V & obj.AMask: {enc: sVIVEncoding},
  2714  	AVSOXEI32V & obj.AMask: {enc: sVIVEncoding},
  2715  	AVSOXEI64V & obj.AMask: {enc: sVIVEncoding},
  2716  
  2717  	// 31.7.7: Unit-stride Fault-Only-First Loads
  2718  	AVLE8FFV & obj.AMask:  {enc: iVEncoding},
  2719  	AVLE16FFV & obj.AMask: {enc: iVEncoding},
  2720  	AVLE32FFV & obj.AMask: {enc: iVEncoding},
  2721  	AVLE64FFV & obj.AMask: {enc: iVEncoding},
  2722  
  2723  	// 31.7.8: Vector Load/Store Segment Instructions
  2724  	AVLSEG2E8V & obj.AMask:     {enc: iVEncoding},
  2725  	AVLSEG3E8V & obj.AMask:     {enc: iVEncoding},
  2726  	AVLSEG4E8V & obj.AMask:     {enc: iVEncoding},
  2727  	AVLSEG5E8V & obj.AMask:     {enc: iVEncoding},
  2728  	AVLSEG6E8V & obj.AMask:     {enc: iVEncoding},
  2729  	AVLSEG7E8V & obj.AMask:     {enc: iVEncoding},
  2730  	AVLSEG8E8V & obj.AMask:     {enc: iVEncoding},
  2731  	AVLSEG2E16V & obj.AMask:    {enc: iVEncoding},
  2732  	AVLSEG3E16V & obj.AMask:    {enc: iVEncoding},
  2733  	AVLSEG4E16V & obj.AMask:    {enc: iVEncoding},
  2734  	AVLSEG5E16V & obj.AMask:    {enc: iVEncoding},
  2735  	AVLSEG6E16V & obj.AMask:    {enc: iVEncoding},
  2736  	AVLSEG7E16V & obj.AMask:    {enc: iVEncoding},
  2737  	AVLSEG8E16V & obj.AMask:    {enc: iVEncoding},
  2738  	AVLSEG2E32V & obj.AMask:    {enc: iVEncoding},
  2739  	AVLSEG3E32V & obj.AMask:    {enc: iVEncoding},
  2740  	AVLSEG4E32V & obj.AMask:    {enc: iVEncoding},
  2741  	AVLSEG5E32V & obj.AMask:    {enc: iVEncoding},
  2742  	AVLSEG6E32V & obj.AMask:    {enc: iVEncoding},
  2743  	AVLSEG7E32V & obj.AMask:    {enc: iVEncoding},
  2744  	AVLSEG8E32V & obj.AMask:    {enc: iVEncoding},
  2745  	AVLSEG2E64V & obj.AMask:    {enc: iVEncoding},
  2746  	AVLSEG3E64V & obj.AMask:    {enc: iVEncoding},
  2747  	AVLSEG4E64V & obj.AMask:    {enc: iVEncoding},
  2748  	AVLSEG5E64V & obj.AMask:    {enc: iVEncoding},
  2749  	AVLSEG6E64V & obj.AMask:    {enc: iVEncoding},
  2750  	AVLSEG7E64V & obj.AMask:    {enc: iVEncoding},
  2751  	AVLSEG8E64V & obj.AMask:    {enc: iVEncoding},
  2752  	AVSSEG2E8V & obj.AMask:     {enc: sVEncoding},
  2753  	AVSSEG3E8V & obj.AMask:     {enc: sVEncoding},
  2754  	AVSSEG4E8V & obj.AMask:     {enc: sVEncoding},
  2755  	AVSSEG5E8V & obj.AMask:     {enc: sVEncoding},
  2756  	AVSSEG6E8V & obj.AMask:     {enc: sVEncoding},
  2757  	AVSSEG7E8V & obj.AMask:     {enc: sVEncoding},
  2758  	AVSSEG8E8V & obj.AMask:     {enc: sVEncoding},
  2759  	AVSSEG2E16V & obj.AMask:    {enc: sVEncoding},
  2760  	AVSSEG3E16V & obj.AMask:    {enc: sVEncoding},
  2761  	AVSSEG4E16V & obj.AMask:    {enc: sVEncoding},
  2762  	AVSSEG5E16V & obj.AMask:    {enc: sVEncoding},
  2763  	AVSSEG6E16V & obj.AMask:    {enc: sVEncoding},
  2764  	AVSSEG7E16V & obj.AMask:    {enc: sVEncoding},
  2765  	AVSSEG8E16V & obj.AMask:    {enc: sVEncoding},
  2766  	AVSSEG2E32V & obj.AMask:    {enc: sVEncoding},
  2767  	AVSSEG3E32V & obj.AMask:    {enc: sVEncoding},
  2768  	AVSSEG4E32V & obj.AMask:    {enc: sVEncoding},
  2769  	AVSSEG5E32V & obj.AMask:    {enc: sVEncoding},
  2770  	AVSSEG6E32V & obj.AMask:    {enc: sVEncoding},
  2771  	AVSSEG7E32V & obj.AMask:    {enc: sVEncoding},
  2772  	AVSSEG8E32V & obj.AMask:    {enc: sVEncoding},
  2773  	AVSSEG2E64V & obj.AMask:    {enc: sVEncoding},
  2774  	AVSSEG3E64V & obj.AMask:    {enc: sVEncoding},
  2775  	AVSSEG4E64V & obj.AMask:    {enc: sVEncoding},
  2776  	AVSSEG5E64V & obj.AMask:    {enc: sVEncoding},
  2777  	AVSSEG6E64V & obj.AMask:    {enc: sVEncoding},
  2778  	AVSSEG7E64V & obj.AMask:    {enc: sVEncoding},
  2779  	AVSSEG8E64V & obj.AMask:    {enc: sVEncoding},
  2780  	AVLSEG2E8FFV & obj.AMask:   {enc: iVEncoding},
  2781  	AVLSEG3E8FFV & obj.AMask:   {enc: iVEncoding},
  2782  	AVLSEG4E8FFV & obj.AMask:   {enc: iVEncoding},
  2783  	AVLSEG5E8FFV & obj.AMask:   {enc: iVEncoding},
  2784  	AVLSEG6E8FFV & obj.AMask:   {enc: iVEncoding},
  2785  	AVLSEG7E8FFV & obj.AMask:   {enc: iVEncoding},
  2786  	AVLSEG8E8FFV & obj.AMask:   {enc: iVEncoding},
  2787  	AVLSEG2E16FFV & obj.AMask:  {enc: iVEncoding},
  2788  	AVLSEG3E16FFV & obj.AMask:  {enc: iVEncoding},
  2789  	AVLSEG4E16FFV & obj.AMask:  {enc: iVEncoding},
  2790  	AVLSEG5E16FFV & obj.AMask:  {enc: iVEncoding},
  2791  	AVLSEG6E16FFV & obj.AMask:  {enc: iVEncoding},
  2792  	AVLSEG7E16FFV & obj.AMask:  {enc: iVEncoding},
  2793  	AVLSEG8E16FFV & obj.AMask:  {enc: iVEncoding},
  2794  	AVLSEG2E32FFV & obj.AMask:  {enc: iVEncoding},
  2795  	AVLSEG3E32FFV & obj.AMask:  {enc: iVEncoding},
  2796  	AVLSEG4E32FFV & obj.AMask:  {enc: iVEncoding},
  2797  	AVLSEG5E32FFV & obj.AMask:  {enc: iVEncoding},
  2798  	AVLSEG6E32FFV & obj.AMask:  {enc: iVEncoding},
  2799  	AVLSEG7E32FFV & obj.AMask:  {enc: iVEncoding},
  2800  	AVLSEG8E32FFV & obj.AMask:  {enc: iVEncoding},
  2801  	AVLSEG2E64FFV & obj.AMask:  {enc: iVEncoding},
  2802  	AVLSEG3E64FFV & obj.AMask:  {enc: iVEncoding},
  2803  	AVLSEG4E64FFV & obj.AMask:  {enc: iVEncoding},
  2804  	AVLSEG5E64FFV & obj.AMask:  {enc: iVEncoding},
  2805  	AVLSEG6E64FFV & obj.AMask:  {enc: iVEncoding},
  2806  	AVLSEG7E64FFV & obj.AMask:  {enc: iVEncoding},
  2807  	AVLSEG8E64FFV & obj.AMask:  {enc: iVEncoding},
  2808  	AVLSSEG2E8V & obj.AMask:    {enc: iIIVEncoding},
  2809  	AVLSSEG3E8V & obj.AMask:    {enc: iIIVEncoding},
  2810  	AVLSSEG4E8V & obj.AMask:    {enc: iIIVEncoding},
  2811  	AVLSSEG5E8V & obj.AMask:    {enc: iIIVEncoding},
  2812  	AVLSSEG6E8V & obj.AMask:    {enc: iIIVEncoding},
  2813  	AVLSSEG7E8V & obj.AMask:    {enc: iIIVEncoding},
  2814  	AVLSSEG8E8V & obj.AMask:    {enc: iIIVEncoding},
  2815  	AVLSSEG2E16V & obj.AMask:   {enc: iIIVEncoding},
  2816  	AVLSSEG3E16V & obj.AMask:   {enc: iIIVEncoding},
  2817  	AVLSSEG4E16V & obj.AMask:   {enc: iIIVEncoding},
  2818  	AVLSSEG5E16V & obj.AMask:   {enc: iIIVEncoding},
  2819  	AVLSSEG6E16V & obj.AMask:   {enc: iIIVEncoding},
  2820  	AVLSSEG7E16V & obj.AMask:   {enc: iIIVEncoding},
  2821  	AVLSSEG8E16V & obj.AMask:   {enc: iIIVEncoding},
  2822  	AVLSSEG2E32V & obj.AMask:   {enc: iIIVEncoding},
  2823  	AVLSSEG3E32V & obj.AMask:   {enc: iIIVEncoding},
  2824  	AVLSSEG4E32V & obj.AMask:   {enc: iIIVEncoding},
  2825  	AVLSSEG5E32V & obj.AMask:   {enc: iIIVEncoding},
  2826  	AVLSSEG6E32V & obj.AMask:   {enc: iIIVEncoding},
  2827  	AVLSSEG7E32V & obj.AMask:   {enc: iIIVEncoding},
  2828  	AVLSSEG8E32V & obj.AMask:   {enc: iIIVEncoding},
  2829  	AVLSSEG2E64V & obj.AMask:   {enc: iIIVEncoding},
  2830  	AVLSSEG3E64V & obj.AMask:   {enc: iIIVEncoding},
  2831  	AVLSSEG4E64V & obj.AMask:   {enc: iIIVEncoding},
  2832  	AVLSSEG5E64V & obj.AMask:   {enc: iIIVEncoding},
  2833  	AVLSSEG6E64V & obj.AMask:   {enc: iIIVEncoding},
  2834  	AVLSSEG7E64V & obj.AMask:   {enc: iIIVEncoding},
  2835  	AVLSSEG8E64V & obj.AMask:   {enc: iIIVEncoding},
  2836  	AVSSSEG2E8V & obj.AMask:    {enc: sVIIEncoding},
  2837  	AVSSSEG3E8V & obj.AMask:    {enc: sVIIEncoding},
  2838  	AVSSSEG4E8V & obj.AMask:    {enc: sVIIEncoding},
  2839  	AVSSSEG5E8V & obj.AMask:    {enc: sVIIEncoding},
  2840  	AVSSSEG6E8V & obj.AMask:    {enc: sVIIEncoding},
  2841  	AVSSSEG7E8V & obj.AMask:    {enc: sVIIEncoding},
  2842  	AVSSSEG8E8V & obj.AMask:    {enc: sVIIEncoding},
  2843  	AVSSSEG2E16V & obj.AMask:   {enc: sVIIEncoding},
  2844  	AVSSSEG3E16V & obj.AMask:   {enc: sVIIEncoding},
  2845  	AVSSSEG4E16V & obj.AMask:   {enc: sVIIEncoding},
  2846  	AVSSSEG5E16V & obj.AMask:   {enc: sVIIEncoding},
  2847  	AVSSSEG6E16V & obj.AMask:   {enc: sVIIEncoding},
  2848  	AVSSSEG7E16V & obj.AMask:   {enc: sVIIEncoding},
  2849  	AVSSSEG8E16V & obj.AMask:   {enc: sVIIEncoding},
  2850  	AVSSSEG2E32V & obj.AMask:   {enc: sVIIEncoding},
  2851  	AVSSSEG3E32V & obj.AMask:   {enc: sVIIEncoding},
  2852  	AVSSSEG4E32V & obj.AMask:   {enc: sVIIEncoding},
  2853  	AVSSSEG5E32V & obj.AMask:   {enc: sVIIEncoding},
  2854  	AVSSSEG6E32V & obj.AMask:   {enc: sVIIEncoding},
  2855  	AVSSSEG7E32V & obj.AMask:   {enc: sVIIEncoding},
  2856  	AVSSSEG8E32V & obj.AMask:   {enc: sVIIEncoding},
  2857  	AVSSSEG2E64V & obj.AMask:   {enc: sVIIEncoding},
  2858  	AVSSSEG3E64V & obj.AMask:   {enc: sVIIEncoding},
  2859  	AVSSSEG4E64V & obj.AMask:   {enc: sVIIEncoding},
  2860  	AVSSSEG5E64V & obj.AMask:   {enc: sVIIEncoding},
  2861  	AVSSSEG6E64V & obj.AMask:   {enc: sVIIEncoding},
  2862  	AVSSSEG7E64V & obj.AMask:   {enc: sVIIEncoding},
  2863  	AVSSSEG8E64V & obj.AMask:   {enc: sVIIEncoding},
  2864  	AVLOXSEG2EI8V & obj.AMask:  {enc: iVIVEncoding},
  2865  	AVLOXSEG3EI8V & obj.AMask:  {enc: iVIVEncoding},
  2866  	AVLOXSEG4EI8V & obj.AMask:  {enc: iVIVEncoding},
  2867  	AVLOXSEG5EI8V & obj.AMask:  {enc: iVIVEncoding},
  2868  	AVLOXSEG6EI8V & obj.AMask:  {enc: iVIVEncoding},
  2869  	AVLOXSEG7EI8V & obj.AMask:  {enc: iVIVEncoding},
  2870  	AVLOXSEG8EI8V & obj.AMask:  {enc: iVIVEncoding},
  2871  	AVLOXSEG2EI16V & obj.AMask: {enc: iVIVEncoding},
  2872  	AVLOXSEG3EI16V & obj.AMask: {enc: iVIVEncoding},
  2873  	AVLOXSEG4EI16V & obj.AMask: {enc: iVIVEncoding},
  2874  	AVLOXSEG5EI16V & obj.AMask: {enc: iVIVEncoding},
  2875  	AVLOXSEG6EI16V & obj.AMask: {enc: iVIVEncoding},
  2876  	AVLOXSEG7EI16V & obj.AMask: {enc: iVIVEncoding},
  2877  	AVLOXSEG8EI16V & obj.AMask: {enc: iVIVEncoding},
  2878  	AVLOXSEG2EI32V & obj.AMask: {enc: iVIVEncoding},
  2879  	AVLOXSEG3EI32V & obj.AMask: {enc: iVIVEncoding},
  2880  	AVLOXSEG4EI32V & obj.AMask: {enc: iVIVEncoding},
  2881  	AVLOXSEG5EI32V & obj.AMask: {enc: iVIVEncoding},
  2882  	AVLOXSEG6EI32V & obj.AMask: {enc: iVIVEncoding},
  2883  	AVLOXSEG7EI32V & obj.AMask: {enc: iVIVEncoding},
  2884  	AVLOXSEG8EI32V & obj.AMask: {enc: iVIVEncoding},
  2885  	AVLOXSEG2EI64V & obj.AMask: {enc: iVIVEncoding},
  2886  	AVLOXSEG3EI64V & obj.AMask: {enc: iVIVEncoding},
  2887  	AVLOXSEG4EI64V & obj.AMask: {enc: iVIVEncoding},
  2888  	AVLOXSEG5EI64V & obj.AMask: {enc: iVIVEncoding},
  2889  	AVLOXSEG6EI64V & obj.AMask: {enc: iVIVEncoding},
  2890  	AVLOXSEG7EI64V & obj.AMask: {enc: iVIVEncoding},
  2891  	AVLOXSEG8EI64V & obj.AMask: {enc: iVIVEncoding},
  2892  	AVSOXSEG2EI8V & obj.AMask:  {enc: sVIVEncoding},
  2893  	AVSOXSEG3EI8V & obj.AMask:  {enc: sVIVEncoding},
  2894  	AVSOXSEG4EI8V & obj.AMask:  {enc: sVIVEncoding},
  2895  	AVSOXSEG5EI8V & obj.AMask:  {enc: sVIVEncoding},
  2896  	AVSOXSEG6EI8V & obj.AMask:  {enc: sVIVEncoding},
  2897  	AVSOXSEG7EI8V & obj.AMask:  {enc: sVIVEncoding},
  2898  	AVSOXSEG8EI8V & obj.AMask:  {enc: sVIVEncoding},
  2899  	AVSOXSEG2EI16V & obj.AMask: {enc: sVIVEncoding},
  2900  	AVSOXSEG3EI16V & obj.AMask: {enc: sVIVEncoding},
  2901  	AVSOXSEG4EI16V & obj.AMask: {enc: sVIVEncoding},
  2902  	AVSOXSEG5EI16V & obj.AMask: {enc: sVIVEncoding},
  2903  	AVSOXSEG6EI16V & obj.AMask: {enc: sVIVEncoding},
  2904  	AVSOXSEG7EI16V & obj.AMask: {enc: sVIVEncoding},
  2905  	AVSOXSEG8EI16V & obj.AMask: {enc: sVIVEncoding},
  2906  	AVSOXSEG2EI32V & obj.AMask: {enc: sVIVEncoding},
  2907  	AVSOXSEG3EI32V & obj.AMask: {enc: sVIVEncoding},
  2908  	AVSOXSEG4EI32V & obj.AMask: {enc: sVIVEncoding},
  2909  	AVSOXSEG5EI32V & obj.AMask: {enc: sVIVEncoding},
  2910  	AVSOXSEG6EI32V & obj.AMask: {enc: sVIVEncoding},
  2911  	AVSOXSEG7EI32V & obj.AMask: {enc: sVIVEncoding},
  2912  	AVSOXSEG8EI32V & obj.AMask: {enc: sVIVEncoding},
  2913  	AVSOXSEG2EI64V & obj.AMask: {enc: sVIVEncoding},
  2914  	AVSOXSEG3EI64V & obj.AMask: {enc: sVIVEncoding},
  2915  	AVSOXSEG4EI64V & obj.AMask: {enc: sVIVEncoding},
  2916  	AVSOXSEG5EI64V & obj.AMask: {enc: sVIVEncoding},
  2917  	AVSOXSEG6EI64V & obj.AMask: {enc: sVIVEncoding},
  2918  	AVSOXSEG7EI64V & obj.AMask: {enc: sVIVEncoding},
  2919  	AVSOXSEG8EI64V & obj.AMask: {enc: sVIVEncoding},
  2920  	AVLUXSEG2EI8V & obj.AMask:  {enc: iVIVEncoding},
  2921  	AVLUXSEG3EI8V & obj.AMask:  {enc: iVIVEncoding},
  2922  	AVLUXSEG4EI8V & obj.AMask:  {enc: iVIVEncoding},
  2923  	AVLUXSEG5EI8V & obj.AMask:  {enc: iVIVEncoding},
  2924  	AVLUXSEG6EI8V & obj.AMask:  {enc: iVIVEncoding},
  2925  	AVLUXSEG7EI8V & obj.AMask:  {enc: iVIVEncoding},
  2926  	AVLUXSEG8EI8V & obj.AMask:  {enc: iVIVEncoding},
  2927  	AVLUXSEG2EI16V & obj.AMask: {enc: iVIVEncoding},
  2928  	AVLUXSEG3EI16V & obj.AMask: {enc: iVIVEncoding},
  2929  	AVLUXSEG4EI16V & obj.AMask: {enc: iVIVEncoding},
  2930  	AVLUXSEG5EI16V & obj.AMask: {enc: iVIVEncoding},
  2931  	AVLUXSEG6EI16V & obj.AMask: {enc: iVIVEncoding},
  2932  	AVLUXSEG7EI16V & obj.AMask: {enc: iVIVEncoding},
  2933  	AVLUXSEG8EI16V & obj.AMask: {enc: iVIVEncoding},
  2934  	AVLUXSEG2EI32V & obj.AMask: {enc: iVIVEncoding},
  2935  	AVLUXSEG3EI32V & obj.AMask: {enc: iVIVEncoding},
  2936  	AVLUXSEG4EI32V & obj.AMask: {enc: iVIVEncoding},
  2937  	AVLUXSEG5EI32V & obj.AMask: {enc: iVIVEncoding},
  2938  	AVLUXSEG6EI32V & obj.AMask: {enc: iVIVEncoding},
  2939  	AVLUXSEG7EI32V & obj.AMask: {enc: iVIVEncoding},
  2940  	AVLUXSEG8EI32V & obj.AMask: {enc: iVIVEncoding},
  2941  	AVLUXSEG2EI64V & obj.AMask: {enc: iVIVEncoding},
  2942  	AVLUXSEG3EI64V & obj.AMask: {enc: iVIVEncoding},
  2943  	AVLUXSEG4EI64V & obj.AMask: {enc: iVIVEncoding},
  2944  	AVLUXSEG5EI64V & obj.AMask: {enc: iVIVEncoding},
  2945  	AVLUXSEG6EI64V & obj.AMask: {enc: iVIVEncoding},
  2946  	AVLUXSEG7EI64V & obj.AMask: {enc: iVIVEncoding},
  2947  	AVLUXSEG8EI64V & obj.AMask: {enc: iVIVEncoding},
  2948  	AVSUXSEG2EI8V & obj.AMask:  {enc: sVIVEncoding},
  2949  	AVSUXSEG3EI8V & obj.AMask:  {enc: sVIVEncoding},
  2950  	AVSUXSEG4EI8V & obj.AMask:  {enc: sVIVEncoding},
  2951  	AVSUXSEG5EI8V & obj.AMask:  {enc: sVIVEncoding},
  2952  	AVSUXSEG6EI8V & obj.AMask:  {enc: sVIVEncoding},
  2953  	AVSUXSEG7EI8V & obj.AMask:  {enc: sVIVEncoding},
  2954  	AVSUXSEG8EI8V & obj.AMask:  {enc: sVIVEncoding},
  2955  	AVSUXSEG2EI16V & obj.AMask: {enc: sVIVEncoding},
  2956  	AVSUXSEG3EI16V & obj.AMask: {enc: sVIVEncoding},
  2957  	AVSUXSEG4EI16V & obj.AMask: {enc: sVIVEncoding},
  2958  	AVSUXSEG5EI16V & obj.AMask: {enc: sVIVEncoding},
  2959  	AVSUXSEG6EI16V & obj.AMask: {enc: sVIVEncoding},
  2960  	AVSUXSEG7EI16V & obj.AMask: {enc: sVIVEncoding},
  2961  	AVSUXSEG8EI16V & obj.AMask: {enc: sVIVEncoding},
  2962  	AVSUXSEG2EI32V & obj.AMask: {enc: sVIVEncoding},
  2963  	AVSUXSEG3EI32V & obj.AMask: {enc: sVIVEncoding},
  2964  	AVSUXSEG4EI32V & obj.AMask: {enc: sVIVEncoding},
  2965  	AVSUXSEG5EI32V & obj.AMask: {enc: sVIVEncoding},
  2966  	AVSUXSEG6EI32V & obj.AMask: {enc: sVIVEncoding},
  2967  	AVSUXSEG7EI32V & obj.AMask: {enc: sVIVEncoding},
  2968  	AVSUXSEG8EI32V & obj.AMask: {enc: sVIVEncoding},
  2969  	AVSUXSEG2EI64V & obj.AMask: {enc: sVIVEncoding},
  2970  	AVSUXSEG3EI64V & obj.AMask: {enc: sVIVEncoding},
  2971  	AVSUXSEG4EI64V & obj.AMask: {enc: sVIVEncoding},
  2972  	AVSUXSEG5EI64V & obj.AMask: {enc: sVIVEncoding},
  2973  	AVSUXSEG6EI64V & obj.AMask: {enc: sVIVEncoding},
  2974  	AVSUXSEG7EI64V & obj.AMask: {enc: sVIVEncoding},
  2975  	AVSUXSEG8EI64V & obj.AMask: {enc: sVIVEncoding},
  2976  
  2977  	// 31.7.9: Vector Load/Store Whole Register Instructions
  2978  	AVL1RE8V & obj.AMask:  {enc: iVEncoding},
  2979  	AVL1RE16V & obj.AMask: {enc: iVEncoding},
  2980  	AVL1RE32V & obj.AMask: {enc: iVEncoding},
  2981  	AVL1RE64V & obj.AMask: {enc: iVEncoding},
  2982  	AVL2RE8V & obj.AMask:  {enc: iVEncoding},
  2983  	AVL2RE16V & obj.AMask: {enc: iVEncoding},
  2984  	AVL2RE32V & obj.AMask: {enc: iVEncoding},
  2985  	AVL2RE64V & obj.AMask: {enc: iVEncoding},
  2986  	AVL4RE8V & obj.AMask:  {enc: iVEncoding},
  2987  	AVL4RE16V & obj.AMask: {enc: iVEncoding},
  2988  	AVL4RE32V & obj.AMask: {enc: iVEncoding},
  2989  	AVL4RE64V & obj.AMask: {enc: iVEncoding},
  2990  	AVL8RE8V & obj.AMask:  {enc: iVEncoding},
  2991  	AVL8RE16V & obj.AMask: {enc: iVEncoding},
  2992  	AVL8RE32V & obj.AMask: {enc: iVEncoding},
  2993  	AVL8RE64V & obj.AMask: {enc: iVEncoding},
  2994  	AVS1RV & obj.AMask:    {enc: sVEncoding},
  2995  	AVS2RV & obj.AMask:    {enc: sVEncoding},
  2996  	AVS4RV & obj.AMask:    {enc: sVEncoding},
  2997  	AVS8RV & obj.AMask:    {enc: sVEncoding},
  2998  
  2999  	// 31.11.1: Vector Single-Width Integer Add and Subtract
  3000  	AVADDVV & obj.AMask:  {enc: rVVVEncoding},
  3001  	AVADDVX & obj.AMask:  {enc: rVIVEncoding},
  3002  	AVADDVI & obj.AMask:  {enc: rVViEncoding},
  3003  	AVSUBVV & obj.AMask:  {enc: rVVVEncoding},
  3004  	AVSUBVX & obj.AMask:  {enc: rVIVEncoding},
  3005  	AVRSUBVX & obj.AMask: {enc: rVIVEncoding},
  3006  	AVRSUBVI & obj.AMask: {enc: rVViEncoding},
  3007  
  3008  	// 31.11.2: Vector Widening Integer Add/Subtract
  3009  	AVWADDUVV & obj.AMask: {enc: rVVVEncoding},
  3010  	AVWADDUVX & obj.AMask: {enc: rVIVEncoding},
  3011  	AVWSUBUVV & obj.AMask: {enc: rVVVEncoding},
  3012  	AVWSUBUVX & obj.AMask: {enc: rVIVEncoding},
  3013  	AVWADDVV & obj.AMask:  {enc: rVVVEncoding},
  3014  	AVWADDVX & obj.AMask:  {enc: rVIVEncoding},
  3015  	AVWSUBVV & obj.AMask:  {enc: rVVVEncoding},
  3016  	AVWSUBVX & obj.AMask:  {enc: rVIVEncoding},
  3017  	AVWADDUWV & obj.AMask: {enc: rVVVEncoding},
  3018  	AVWADDUWX & obj.AMask: {enc: rVIVEncoding},
  3019  	AVWSUBUWV & obj.AMask: {enc: rVVVEncoding},
  3020  	AVWSUBUWX & obj.AMask: {enc: rVIVEncoding},
  3021  	AVWADDWV & obj.AMask:  {enc: rVVVEncoding},
  3022  	AVWADDWX & obj.AMask:  {enc: rVIVEncoding},
  3023  	AVWSUBWV & obj.AMask:  {enc: rVVVEncoding},
  3024  	AVWSUBWX & obj.AMask:  {enc: rVIVEncoding},
  3025  
  3026  	// 31.11.3: Vector Integer Extension
  3027  	AVZEXTVF2 & obj.AMask: {enc: rVVEncoding},
  3028  	AVSEXTVF2 & obj.AMask: {enc: rVVEncoding},
  3029  	AVZEXTVF4 & obj.AMask: {enc: rVVEncoding},
  3030  	AVSEXTVF4 & obj.AMask: {enc: rVVEncoding},
  3031  	AVZEXTVF8 & obj.AMask: {enc: rVVEncoding},
  3032  	AVSEXTVF8 & obj.AMask: {enc: rVVEncoding},
  3033  
  3034  	// 31.11.4: Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions
  3035  	AVADCVVM & obj.AMask:  {enc: rVVVEncoding},
  3036  	AVADCVXM & obj.AMask:  {enc: rVIVEncoding},
  3037  	AVADCVIM & obj.AMask:  {enc: rVViEncoding},
  3038  	AVMADCVVM & obj.AMask: {enc: rVVVEncoding},
  3039  	AVMADCVXM & obj.AMask: {enc: rVIVEncoding},
  3040  	AVMADCVIM & obj.AMask: {enc: rVViEncoding},
  3041  	AVMADCVV & obj.AMask:  {enc: rVVVEncoding},
  3042  	AVMADCVX & obj.AMask:  {enc: rVIVEncoding},
  3043  	AVMADCVI & obj.AMask:  {enc: rVViEncoding},
  3044  	AVSBCVVM & obj.AMask:  {enc: rVVVEncoding},
  3045  	AVSBCVXM & obj.AMask:  {enc: rVIVEncoding},
  3046  	AVMSBCVVM & obj.AMask: {enc: rVVVEncoding},
  3047  	AVMSBCVXM & obj.AMask: {enc: rVIVEncoding},
  3048  	AVMSBCVV & obj.AMask:  {enc: rVVVEncoding},
  3049  	AVMSBCVX & obj.AMask:  {enc: rVIVEncoding},
  3050  
  3051  	// 31.11.5: Vector Bitwise Logical Instructions
  3052  	AVANDVV & obj.AMask: {enc: rVVVEncoding},
  3053  	AVANDVX & obj.AMask: {enc: rVIVEncoding},
  3054  	AVANDVI & obj.AMask: {enc: rVViEncoding},
  3055  	AVORVV & obj.AMask:  {enc: rVVVEncoding},
  3056  	AVORVX & obj.AMask:  {enc: rVIVEncoding},
  3057  	AVORVI & obj.AMask:  {enc: rVViEncoding},
  3058  	AVXORVV & obj.AMask: {enc: rVVVEncoding},
  3059  	AVXORVX & obj.AMask: {enc: rVIVEncoding},
  3060  	AVXORVI & obj.AMask: {enc: rVViEncoding},
  3061  
  3062  	// 31.11.6: Vector Single-Width Shift Instructions
  3063  	AVSLLVV & obj.AMask: {enc: rVVVEncoding},
  3064  	AVSLLVX & obj.AMask: {enc: rVIVEncoding},
  3065  	AVSLLVI & obj.AMask: {enc: rVVuEncoding},
  3066  	AVSRLVV & obj.AMask: {enc: rVVVEncoding},
  3067  	AVSRLVX & obj.AMask: {enc: rVIVEncoding},
  3068  	AVSRLVI & obj.AMask: {enc: rVVuEncoding},
  3069  	AVSRAVV & obj.AMask: {enc: rVVVEncoding},
  3070  	AVSRAVX & obj.AMask: {enc: rVIVEncoding},
  3071  	AVSRAVI & obj.AMask: {enc: rVVuEncoding},
  3072  
  3073  	// 31.11.7: Vector Narrowing Integer Right Shift Instructions
  3074  	AVNSRLWV & obj.AMask: {enc: rVVVEncoding},
  3075  	AVNSRLWX & obj.AMask: {enc: rVIVEncoding},
  3076  	AVNSRLWI & obj.AMask: {enc: rVVuEncoding},
  3077  	AVNSRAWV & obj.AMask: {enc: rVVVEncoding},
  3078  	AVNSRAWX & obj.AMask: {enc: rVIVEncoding},
  3079  	AVNSRAWI & obj.AMask: {enc: rVVuEncoding},
  3080  
  3081  	// 31.11.8: Vector Integer Compare Instructions
  3082  	AVMSEQVV & obj.AMask:  {enc: rVVVEncoding},
  3083  	AVMSEQVX & obj.AMask:  {enc: rVIVEncoding},
  3084  	AVMSEQVI & obj.AMask:  {enc: rVViEncoding},
  3085  	AVMSNEVV & obj.AMask:  {enc: rVVVEncoding},
  3086  	AVMSNEVX & obj.AMask:  {enc: rVIVEncoding},
  3087  	AVMSNEVI & obj.AMask:  {enc: rVViEncoding},
  3088  	AVMSLTUVV & obj.AMask: {enc: rVVVEncoding},
  3089  	AVMSLTUVX & obj.AMask: {enc: rVIVEncoding},
  3090  	AVMSLTVV & obj.AMask:  {enc: rVVVEncoding},
  3091  	AVMSLTVX & obj.AMask:  {enc: rVIVEncoding},
  3092  	AVMSLEUVV & obj.AMask: {enc: rVVVEncoding},
  3093  	AVMSLEUVX & obj.AMask: {enc: rVIVEncoding},
  3094  	AVMSLEUVI & obj.AMask: {enc: rVViEncoding},
  3095  	AVMSLEVV & obj.AMask:  {enc: rVVVEncoding},
  3096  	AVMSLEVX & obj.AMask:  {enc: rVIVEncoding},
  3097  	AVMSLEVI & obj.AMask:  {enc: rVViEncoding},
  3098  	AVMSGTUVX & obj.AMask: {enc: rVIVEncoding},
  3099  	AVMSGTUVI & obj.AMask: {enc: rVViEncoding},
  3100  	AVMSGTVX & obj.AMask:  {enc: rVIVEncoding},
  3101  	AVMSGTVI & obj.AMask:  {enc: rVViEncoding},
  3102  
  3103  	// 31.11.9: Vector Integer Min/Max Instructions
  3104  	AVMINUVV & obj.AMask: {enc: rVVVEncoding},
  3105  	AVMINUVX & obj.AMask: {enc: rVIVEncoding},
  3106  	AVMINVV & obj.AMask:  {enc: rVVVEncoding},
  3107  	AVMINVX & obj.AMask:  {enc: rVIVEncoding},
  3108  	AVMAXUVV & obj.AMask: {enc: rVVVEncoding},
  3109  	AVMAXUVX & obj.AMask: {enc: rVIVEncoding},
  3110  	AVMAXVV & obj.AMask:  {enc: rVVVEncoding},
  3111  	AVMAXVX & obj.AMask:  {enc: rVIVEncoding},
  3112  
  3113  	// 31.11.10: Vector Single-Width Integer Multiply Instructions
  3114  	AVMULVV & obj.AMask:    {enc: rVVVEncoding},
  3115  	AVMULVX & obj.AMask:    {enc: rVIVEncoding},
  3116  	AVMULHVV & obj.AMask:   {enc: rVVVEncoding},
  3117  	AVMULHVX & obj.AMask:   {enc: rVIVEncoding},
  3118  	AVMULHUVV & obj.AMask:  {enc: rVVVEncoding},
  3119  	AVMULHUVX & obj.AMask:  {enc: rVIVEncoding},
  3120  	AVMULHSUVV & obj.AMask: {enc: rVVVEncoding},
  3121  	AVMULHSUVX & obj.AMask: {enc: rVIVEncoding},
  3122  
  3123  	// 31.11.11: Vector Integer Divide Instructions
  3124  	AVDIVUVV & obj.AMask: {enc: rVVVEncoding},
  3125  	AVDIVUVX & obj.AMask: {enc: rVIVEncoding},
  3126  	AVDIVVV & obj.AMask:  {enc: rVVVEncoding},
  3127  	AVDIVVX & obj.AMask:  {enc: rVIVEncoding},
  3128  	AVREMUVV & obj.AMask: {enc: rVVVEncoding},
  3129  	AVREMUVX & obj.AMask: {enc: rVIVEncoding},
  3130  	AVREMVV & obj.AMask:  {enc: rVVVEncoding},
  3131  	AVREMVX & obj.AMask:  {enc: rVIVEncoding},
  3132  
  3133  	// 31.11.12: Vector Widening Integer Multiply Instructions
  3134  	AVWMULVV & obj.AMask:   {enc: rVVVEncoding},
  3135  	AVWMULVX & obj.AMask:   {enc: rVIVEncoding},
  3136  	AVWMULUVV & obj.AMask:  {enc: rVVVEncoding},
  3137  	AVWMULUVX & obj.AMask:  {enc: rVIVEncoding},
  3138  	AVWMULSUVV & obj.AMask: {enc: rVVVEncoding},
  3139  	AVWMULSUVX & obj.AMask: {enc: rVIVEncoding},
  3140  
  3141  	// 31.11.13: Vector Single-Width Integer Multiply-Add Instructions
  3142  	AVMACCVV & obj.AMask:  {enc: rVVVEncoding},
  3143  	AVMACCVX & obj.AMask:  {enc: rVIVEncoding},
  3144  	AVNMSACVV & obj.AMask: {enc: rVVVEncoding},
  3145  	AVNMSACVX & obj.AMask: {enc: rVIVEncoding},
  3146  	AVMADDVV & obj.AMask:  {enc: rVVVEncoding},
  3147  	AVMADDVX & obj.AMask:  {enc: rVIVEncoding},
  3148  	AVNMSUBVV & obj.AMask: {enc: rVVVEncoding},
  3149  	AVNMSUBVX & obj.AMask: {enc: rVIVEncoding},
  3150  
  3151  	// 31.11.14: Vector Widening Integer Multiply-Add Instructions
  3152  	AVWMACCUVV & obj.AMask:  {enc: rVVVEncoding},
  3153  	AVWMACCUVX & obj.AMask:  {enc: rVIVEncoding},
  3154  	AVWMACCVV & obj.AMask:   {enc: rVVVEncoding},
  3155  	AVWMACCVX & obj.AMask:   {enc: rVIVEncoding},
  3156  	AVWMACCSUVV & obj.AMask: {enc: rVVVEncoding},
  3157  	AVWMACCSUVX & obj.AMask: {enc: rVIVEncoding},
  3158  	AVWMACCUSVX & obj.AMask: {enc: rVIVEncoding},
  3159  
  3160  	// 31.11.15: Vector Integer Merge Instructions
  3161  	AVMERGEVVM & obj.AMask: {enc: rVVVEncoding},
  3162  	AVMERGEVXM & obj.AMask: {enc: rVIVEncoding},
  3163  	AVMERGEVIM & obj.AMask: {enc: rVViEncoding},
  3164  
  3165  	// 31.11.16: Vector Integer Move Instructions
  3166  	AVMVVV & obj.AMask: {enc: rVVVEncoding},
  3167  	AVMVVX & obj.AMask: {enc: rVIVEncoding},
  3168  	AVMVVI & obj.AMask: {enc: rVViEncoding},
  3169  
  3170  	// 31.12.1: Vector Single-Width Saturating Add and Subtract
  3171  	AVSADDUVV & obj.AMask: {enc: rVVVEncoding},
  3172  	AVSADDUVX & obj.AMask: {enc: rVIVEncoding},
  3173  	AVSADDUVI & obj.AMask: {enc: rVViEncoding},
  3174  	AVSADDVV & obj.AMask:  {enc: rVVVEncoding},
  3175  	AVSADDVX & obj.AMask:  {enc: rVIVEncoding},
  3176  	AVSADDVI & obj.AMask:  {enc: rVViEncoding},
  3177  	AVSSUBUVV & obj.AMask: {enc: rVVVEncoding},
  3178  	AVSSUBUVX & obj.AMask: {enc: rVIVEncoding},
  3179  	AVSSUBVV & obj.AMask:  {enc: rVVVEncoding},
  3180  	AVSSUBVX & obj.AMask:  {enc: rVIVEncoding},
  3181  
  3182  	// 31.12.2: Vector Single-Width Averaging Add and Subtract
  3183  	AVAADDUVV & obj.AMask: {enc: rVVVEncoding},
  3184  	AVAADDUVX & obj.AMask: {enc: rVIVEncoding},
  3185  	AVAADDVV & obj.AMask:  {enc: rVVVEncoding},
  3186  	AVAADDVX & obj.AMask:  {enc: rVIVEncoding},
  3187  	AVASUBUVV & obj.AMask: {enc: rVVVEncoding},
  3188  	AVASUBUVX & obj.AMask: {enc: rVIVEncoding},
  3189  	AVASUBVV & obj.AMask:  {enc: rVVVEncoding},
  3190  	AVASUBVX & obj.AMask:  {enc: rVIVEncoding},
  3191  
  3192  	// 31.12.3: Vector Single-Width Fractional Multiply with Rounding and Saturation
  3193  	AVSMULVV & obj.AMask: {enc: rVVVEncoding},
  3194  	AVSMULVX & obj.AMask: {enc: rVIVEncoding},
  3195  
  3196  	// 31.12.4: Vector Single-Width Scaling Shift Instructions
  3197  	AVSSRLVV & obj.AMask: {enc: rVVVEncoding},
  3198  	AVSSRLVX & obj.AMask: {enc: rVIVEncoding},
  3199  	AVSSRLVI & obj.AMask: {enc: rVVuEncoding},
  3200  	AVSSRAVV & obj.AMask: {enc: rVVVEncoding},
  3201  	AVSSRAVX & obj.AMask: {enc: rVIVEncoding},
  3202  	AVSSRAVI & obj.AMask: {enc: rVVuEncoding},
  3203  
  3204  	// 31.12.5: Vector Narrowing Fixed-Point Clip Instructions
  3205  	AVNCLIPUWV & obj.AMask: {enc: rVVVEncoding},
  3206  	AVNCLIPUWX & obj.AMask: {enc: rVIVEncoding},
  3207  	AVNCLIPUWI & obj.AMask: {enc: rVVuEncoding},
  3208  	AVNCLIPWV & obj.AMask:  {enc: rVVVEncoding},
  3209  	AVNCLIPWX & obj.AMask:  {enc: rVIVEncoding},
  3210  	AVNCLIPWI & obj.AMask:  {enc: rVVuEncoding},
  3211  
  3212  	// 31.13.2: Vector Single-Width Floating-Point Add/Subtract Instructions
  3213  	AVFADDVV & obj.AMask:  {enc: rVVVEncoding},
  3214  	AVFADDVF & obj.AMask:  {enc: rVFVEncoding},
  3215  	AVFSUBVV & obj.AMask:  {enc: rVVVEncoding},
  3216  	AVFSUBVF & obj.AMask:  {enc: rVFVEncoding},
  3217  	AVFRSUBVF & obj.AMask: {enc: rVFVEncoding},
  3218  
  3219  	// 31.13.3: Vector Widening Floating-Point Add/Subtract Instructions
  3220  	AVFWADDVV & obj.AMask: {enc: rVVVEncoding},
  3221  	AVFWADDVF & obj.AMask: {enc: rVFVEncoding},
  3222  	AVFWSUBVV & obj.AMask: {enc: rVVVEncoding},
  3223  	AVFWSUBVF & obj.AMask: {enc: rVFVEncoding},
  3224  	AVFWADDWV & obj.AMask: {enc: rVVVEncoding},
  3225  	AVFWADDWF & obj.AMask: {enc: rVFVEncoding},
  3226  	AVFWSUBWV & obj.AMask: {enc: rVVVEncoding},
  3227  	AVFWSUBWF & obj.AMask: {enc: rVFVEncoding},
  3228  
  3229  	// 31.13.4: Vector Single-Width Floating-Point Multiply/Divide Instructions
  3230  	AVFMULVV & obj.AMask:  {enc: rVVVEncoding},
  3231  	AVFMULVF & obj.AMask:  {enc: rVFVEncoding},
  3232  	AVFDIVVV & obj.AMask:  {enc: rVVVEncoding},
  3233  	AVFDIVVF & obj.AMask:  {enc: rVFVEncoding},
  3234  	AVFRDIVVF & obj.AMask: {enc: rVFVEncoding},
  3235  
  3236  	// 31.13.5: Vector Widening Floating-Point Multiply
  3237  	AVFWMULVV & obj.AMask: {enc: rVVVEncoding},
  3238  	AVFWMULVF & obj.AMask: {enc: rVFVEncoding},
  3239  
  3240  	// 31.13.6: Vector Single-Width Floating-Point Fused Multiply-Add Instructions
  3241  	AVFMACCVV & obj.AMask:  {enc: rVVVEncoding},
  3242  	AVFMACCVF & obj.AMask:  {enc: rVFVEncoding},
  3243  	AVFNMACCVV & obj.AMask: {enc: rVVVEncoding},
  3244  	AVFNMACCVF & obj.AMask: {enc: rVFVEncoding},
  3245  	AVFMSACVV & obj.AMask:  {enc: rVVVEncoding},
  3246  	AVFMSACVF & obj.AMask:  {enc: rVFVEncoding},
  3247  	AVFNMSACVV & obj.AMask: {enc: rVVVEncoding},
  3248  	AVFNMSACVF & obj.AMask: {enc: rVFVEncoding},
  3249  	AVFMADDVV & obj.AMask:  {enc: rVVVEncoding},
  3250  	AVFMADDVF & obj.AMask:  {enc: rVFVEncoding},
  3251  	AVFNMADDVV & obj.AMask: {enc: rVVVEncoding},
  3252  	AVFNMADDVF & obj.AMask: {enc: rVFVEncoding},
  3253  	AVFMSUBVV & obj.AMask:  {enc: rVVVEncoding},
  3254  	AVFMSUBVF & obj.AMask:  {enc: rVFVEncoding},
  3255  	AVFNMSUBVV & obj.AMask: {enc: rVVVEncoding},
  3256  	AVFNMSUBVF & obj.AMask: {enc: rVFVEncoding},
  3257  
  3258  	// 31.13.7: Vector Widening Floating-Point Fused Multiply-Add Instructions
  3259  	AVFWMACCVV & obj.AMask:  {enc: rVVVEncoding},
  3260  	AVFWMACCVF & obj.AMask:  {enc: rVFVEncoding},
  3261  	AVFWNMACCVV & obj.AMask: {enc: rVVVEncoding},
  3262  	AVFWNMACCVF & obj.AMask: {enc: rVFVEncoding},
  3263  	AVFWMSACVV & obj.AMask:  {enc: rVVVEncoding},
  3264  	AVFWMSACVF & obj.AMask:  {enc: rVFVEncoding},
  3265  	AVFWNMSACVV & obj.AMask: {enc: rVVVEncoding},
  3266  	AVFWNMSACVF & obj.AMask: {enc: rVFVEncoding},
  3267  
  3268  	// 31.13.8: Vector Floating-Point Square-Root Instruction
  3269  	AVFSQRTV & obj.AMask: {enc: rVVEncoding},
  3270  
  3271  	// 31.13.9: Vector Floating-Point Reciprocal Square-Root Estimate Instruction
  3272  	AVFRSQRT7V & obj.AMask: {enc: rVVEncoding},
  3273  
  3274  	// 31.13.10: Vector Floating-Point Reciprocal Estimate Instruction
  3275  	AVFREC7V & obj.AMask: {enc: rVVEncoding},
  3276  
  3277  	// 31.13.11: Vector Floating-Point MIN/MAX Instructions
  3278  	AVFMINVV & obj.AMask: {enc: rVVVEncoding},
  3279  	AVFMINVF & obj.AMask: {enc: rVFVEncoding},
  3280  	AVFMAXVV & obj.AMask: {enc: rVVVEncoding},
  3281  	AVFMAXVF & obj.AMask: {enc: rVFVEncoding},
  3282  
  3283  	// 31.13.12: Vector Floating-Point Sign-Injection Instructions
  3284  	AVFSGNJVV & obj.AMask:  {enc: rVVVEncoding},
  3285  	AVFSGNJVF & obj.AMask:  {enc: rVFVEncoding},
  3286  	AVFSGNJNVV & obj.AMask: {enc: rVVVEncoding},
  3287  	AVFSGNJNVF & obj.AMask: {enc: rVFVEncoding},
  3288  	AVFSGNJXVV & obj.AMask: {enc: rVVVEncoding},
  3289  	AVFSGNJXVF & obj.AMask: {enc: rVFVEncoding},
  3290  
  3291  	// 31.13.13: Vector Floating-Point Compare Instructions
  3292  	AVMFEQVV & obj.AMask: {enc: rVVVEncoding},
  3293  	AVMFEQVF & obj.AMask: {enc: rVFVEncoding},
  3294  	AVMFNEVV & obj.AMask: {enc: rVVVEncoding},
  3295  	AVMFNEVF & obj.AMask: {enc: rVFVEncoding},
  3296  	AVMFLTVV & obj.AMask: {enc: rVVVEncoding},
  3297  	AVMFLTVF & obj.AMask: {enc: rVFVEncoding},
  3298  	AVMFLEVV & obj.AMask: {enc: rVVVEncoding},
  3299  	AVMFLEVF & obj.AMask: {enc: rVFVEncoding},
  3300  	AVMFGTVF & obj.AMask: {enc: rVFVEncoding},
  3301  	AVMFGEVF & obj.AMask: {enc: rVFVEncoding},
  3302  
  3303  	// 31.13.14: Vector Floating-Point Classify Instruction
  3304  	AVFCLASSV & obj.AMask: {enc: rVVEncoding},
  3305  
  3306  	// 31.13.15: Vector Floating-Point Merge Instruction
  3307  	AVFMERGEVFM & obj.AMask: {enc: rVFVEncoding},
  3308  
  3309  	// 31.13.16: Vector Floating-Point Move Instruction
  3310  	AVFMVVF & obj.AMask: {enc: rVFVEncoding},
  3311  
  3312  	// 31.13.17: Single-Width Floating-Point/Integer Type-Convert Instructions
  3313  	AVFCVTXUFV & obj.AMask:    {enc: rVVEncoding},
  3314  	AVFCVTXFV & obj.AMask:     {enc: rVVEncoding},
  3315  	AVFCVTRTZXUFV & obj.AMask: {enc: rVVEncoding},
  3316  	AVFCVTRTZXFV & obj.AMask:  {enc: rVVEncoding},
  3317  	AVFCVTFXUV & obj.AMask:    {enc: rVVEncoding},
  3318  	AVFCVTFXV & obj.AMask:     {enc: rVVEncoding},
  3319  
  3320  	// 31.13.18: Widening Floating-Point/Integer Type-Convert Instructions
  3321  	AVFWCVTXUFV & obj.AMask:    {enc: rVVEncoding},
  3322  	AVFWCVTXFV & obj.AMask:     {enc: rVVEncoding},
  3323  	AVFWCVTRTZXUFV & obj.AMask: {enc: rVVEncoding},
  3324  	AVFWCVTRTZXFV & obj.AMask:  {enc: rVVEncoding},
  3325  	AVFWCVTFXUV & obj.AMask:    {enc: rVVEncoding},
  3326  	AVFWCVTFXV & obj.AMask:     {enc: rVVEncoding},
  3327  	AVFWCVTFFV & obj.AMask:     {enc: rVVEncoding},
  3328  
  3329  	// 31.13.19: Narrowing Floating-Point/Integer Type-Convert Instructions
  3330  	AVFNCVTXUFW & obj.AMask:    {enc: rVVEncoding},
  3331  	AVFNCVTXFW & obj.AMask:     {enc: rVVEncoding},
  3332  	AVFNCVTRTZXUFW & obj.AMask: {enc: rVVEncoding},
  3333  	AVFNCVTRTZXFW & obj.AMask:  {enc: rVVEncoding},
  3334  	AVFNCVTFXUW & obj.AMask:    {enc: rVVEncoding},
  3335  	AVFNCVTFXW & obj.AMask:     {enc: rVVEncoding},
  3336  	AVFNCVTFFW & obj.AMask:     {enc: rVVEncoding},
  3337  	AVFNCVTRODFFW & obj.AMask:  {enc: rVVEncoding},
  3338  
  3339  	// 31.14.1: Vector Single-Width Integer Reduction Instructions
  3340  	AVREDSUMVS & obj.AMask:  {enc: rVVVEncoding},
  3341  	AVREDMAXUVS & obj.AMask: {enc: rVVVEncoding},
  3342  	AVREDMAXVS & obj.AMask:  {enc: rVVVEncoding},
  3343  	AVREDMINUVS & obj.AMask: {enc: rVVVEncoding},
  3344  	AVREDMINVS & obj.AMask:  {enc: rVVVEncoding},
  3345  	AVREDANDVS & obj.AMask:  {enc: rVVVEncoding},
  3346  	AVREDORVS & obj.AMask:   {enc: rVVVEncoding},
  3347  	AVREDXORVS & obj.AMask:  {enc: rVVVEncoding},
  3348  
  3349  	// 31.14.2: Vector Widening Integer Reduction Instructions
  3350  	AVWREDSUMUVS & obj.AMask: {enc: rVVVEncoding},
  3351  	AVWREDSUMVS & obj.AMask:  {enc: rVVVEncoding},
  3352  
  3353  	// 31.14.3: Vector Single-Width Floating-Point Reduction Instructions
  3354  	AVFREDOSUMVS & obj.AMask: {enc: rVVVEncoding},
  3355  	AVFREDUSUMVS & obj.AMask: {enc: rVVVEncoding},
  3356  	AVFREDMAXVS & obj.AMask:  {enc: rVVVEncoding},
  3357  	AVFREDMINVS & obj.AMask:  {enc: rVVVEncoding},
  3358  
  3359  	// 31.14.4: Vector Widening Floating-Point Reduction Instructions
  3360  	AVFWREDOSUMVS & obj.AMask: {enc: rVVVEncoding},
  3361  	AVFWREDUSUMVS & obj.AMask: {enc: rVVVEncoding},
  3362  
  3363  	// 31.15: Vector Mask Instructions
  3364  	AVMANDMM & obj.AMask:  {enc: rVVVEncoding},
  3365  	AVMNANDMM & obj.AMask: {enc: rVVVEncoding},
  3366  	AVMANDNMM & obj.AMask: {enc: rVVVEncoding},
  3367  	AVMXORMM & obj.AMask:  {enc: rVVVEncoding},
  3368  	AVMORMM & obj.AMask:   {enc: rVVVEncoding},
  3369  	AVMNORMM & obj.AMask:  {enc: rVVVEncoding},
  3370  	AVMORNMM & obj.AMask:  {enc: rVVVEncoding},
  3371  	AVMXNORMM & obj.AMask: {enc: rVVVEncoding},
  3372  	AVCPOPM & obj.AMask:   {enc: rVIEncoding},
  3373  	AVFIRSTM & obj.AMask:  {enc: rVIEncoding},
  3374  	AVMSBFM & obj.AMask:   {enc: rVVEncoding},
  3375  	AVMSIFM & obj.AMask:   {enc: rVVEncoding},
  3376  	AVMSOFM & obj.AMask:   {enc: rVVEncoding},
  3377  	AVIOTAM & obj.AMask:   {enc: rVVEncoding},
  3378  	AVIDV & obj.AMask:     {enc: rVVEncoding},
  3379  
  3380  	// 31.16.1: Integer Scalar Move Instructions
  3381  	AVMVXS & obj.AMask: {enc: rVIEncoding},
  3382  	AVMVSX & obj.AMask: {enc: rIVEncoding},
  3383  
  3384  	// 31.16.2: Floating-Point Scalar Move Instructions
  3385  	AVFMVFS & obj.AMask: {enc: rVFEncoding},
  3386  	AVFMVSF & obj.AMask: {enc: rFVEncoding},
  3387  
  3388  	// 31.16.3: Vector Slide Instructions
  3389  	AVSLIDEUPVX & obj.AMask:     {enc: rVIVEncoding},
  3390  	AVSLIDEUPVI & obj.AMask:     {enc: rVVuEncoding},
  3391  	AVSLIDEDOWNVX & obj.AMask:   {enc: rVIVEncoding},
  3392  	AVSLIDEDOWNVI & obj.AMask:   {enc: rVVuEncoding},
  3393  	AVSLIDE1UPVX & obj.AMask:    {enc: rVIVEncoding},
  3394  	AVFSLIDE1UPVF & obj.AMask:   {enc: rVFVEncoding},
  3395  	AVSLIDE1DOWNVX & obj.AMask:  {enc: rVIVEncoding},
  3396  	AVFSLIDE1DOWNVF & obj.AMask: {enc: rVFVEncoding},
  3397  
  3398  	// 31.16.4: Vector Register Gather Instructions
  3399  	AVRGATHERVV & obj.AMask:     {enc: rVVVEncoding},
  3400  	AVRGATHEREI16VV & obj.AMask: {enc: rVVVEncoding},
  3401  	AVRGATHERVX & obj.AMask:     {enc: rVIVEncoding},
  3402  	AVRGATHERVI & obj.AMask:     {enc: rVVuEncoding},
  3403  
  3404  	// 31.16.5: Vector Compress Instruction
  3405  	AVCOMPRESSVM & obj.AMask: {enc: rVVVEncoding},
  3406  
  3407  	// 31.16.6: Whole Vector Register Move
  3408  	AVMV1RV & obj.AMask: {enc: rVVEncoding},
  3409  	AVMV2RV & obj.AMask: {enc: rVVEncoding},
  3410  	AVMV4RV & obj.AMask: {enc: rVVEncoding},
  3411  	AVMV8RV & obj.AMask: {enc: rVVEncoding},
  3412  
  3413  	//
  3414  	// Privileged ISA
  3415  	//
  3416  
  3417  	// 3.3.1: Environment Call and Breakpoint
  3418  	AECALL & obj.AMask:  {enc: iIIEncoding},
  3419  	AEBREAK & obj.AMask: {enc: iIIEncoding},
  3420  
  3421  	// Escape hatch
  3422  	AWORD & obj.AMask: {enc: rawEncoding},
  3423  
  3424  	// Pseudo-operations
  3425  	obj.AFUNCDATA: {enc: pseudoOpEncoding},
  3426  	obj.APCDATA:   {enc: pseudoOpEncoding},
  3427  	obj.ATEXT:     {enc: pseudoOpEncoding},
  3428  	obj.ANOP:      {enc: pseudoOpEncoding},
  3429  	obj.APCALIGN:  {enc: pseudoOpEncoding},
  3430  }
  3431  
  3432  // instructionDataForAs returns the instruction data for an obj.As.
  3433  func instructionDataForAs(as obj.As) (*instructionData, error) {
  3434  	if base := as &^ obj.AMask; base != obj.ABaseRISCV && base != 0 {
  3435  		return nil, fmt.Errorf("%v is not a RISC-V instruction", as)
  3436  	}
  3437  	asi := as & obj.AMask
  3438  	if int(asi) >= len(instructions) {
  3439  		return nil, fmt.Errorf("bad RISC-V instruction %v", as)
  3440  	}
  3441  	return &instructions[asi], nil
  3442  }
  3443  
  3444  // encodingForAs returns the encoding for an obj.As.
  3445  func encodingForAs(as obj.As) (*encoding, error) {
  3446  	insData, err := instructionDataForAs(as)
  3447  	if err != nil {
  3448  		return &badEncoding, err
  3449  	}
  3450  	if insData.enc.validate == nil {
  3451  		return &badEncoding, fmt.Errorf("no encoding for instruction %s", as)
  3452  	}
  3453  	return &insData.enc, nil
  3454  }
  3455  
  3456  // splitShiftConst attempts to split a constant into a signed 12 bit or
  3457  // 32 bit integer, with corresponding logical right shift and/or left shift.
  3458  func splitShiftConst(v int64) (imm int64, lsh int, rsh int, ok bool) {
  3459  	// See if we can reconstruct this value from a signed 32 bit integer.
  3460  	lsh = bits.TrailingZeros64(uint64(v))
  3461  	c := v >> lsh
  3462  	if int64(int32(c)) == c {
  3463  		return c, lsh, 0, true
  3464  	}
  3465  
  3466  	// See if we can reconstruct this value from a small negative constant.
  3467  	rsh = bits.LeadingZeros64(uint64(v))
  3468  	ones := bits.OnesCount64((uint64(v) >> lsh) >> 11)
  3469  	if rsh+ones+lsh+11 == 64 {
  3470  		c = signExtend(1<<11|((v>>lsh)&0x7ff), 12)
  3471  		if lsh > 0 || c != -1 {
  3472  			lsh += rsh
  3473  		}
  3474  		return c, lsh, rsh, true
  3475  	}
  3476  
  3477  	// See if we can reconstruct this value from a zero extended signed
  3478  	// 32 bit integer. This will require four instructions on rva20u64
  3479  	// and three instructions on rva22u64 or higher.
  3480  	if int64(uint32(c)) == c {
  3481  		c = int64(int32(c))
  3482  		lsh, rsh = 32, 32-lsh
  3483  		return c, lsh, rsh, true
  3484  	}
  3485  
  3486  	return 0, 0, 0, false
  3487  }
  3488  
  3489  // isShiftConst indicates whether a constant can be represented as a signed
  3490  // 32 bit integer that is left and/or right shifted.
  3491  func isShiftConst(v int64) bool {
  3492  	_, lsh, rsh, ok := splitShiftConst(v)
  3493  	return ok && (lsh > 0 || rsh > 0)
  3494  }
  3495  
  3496  // isMaterialisableConst indicates whether a constant can be materialised
  3497  // via a small sequence of instructions.
  3498  func isMaterialisableConst(v int64) bool {
  3499  	// Signed 32 bit value that can be constructed with one or two instructions
  3500  	// (ADDIW or LUI+ADDIW).
  3501  	if int64(int32(v)) == v {
  3502  		return true
  3503  	}
  3504  	return isShiftConst(v)
  3505  }
  3506  
  3507  type instruction struct {
  3508  	p      *obj.Prog // Prog that instruction is for
  3509  	as     obj.As    // Assembler opcode
  3510  	rd     uint32    // Destination register
  3511  	rs1    uint32    // Source register 1
  3512  	rs2    uint32    // Source register 2
  3513  	rs3    uint32    // Source register 3
  3514  	imm    int64     // Immediate
  3515  	funct3 uint32    // Function 3
  3516  	funct7 uint32    // Function 7 (or Function 2)
  3517  }
  3518  
  3519  func (ins *instruction) String() string {
  3520  	if ins.p == nil {
  3521  		return ins.as.String()
  3522  	}
  3523  	var suffix string
  3524  	if ins.p.As != ins.as {
  3525  		suffix = fmt.Sprintf(" (%v)", ins.as)
  3526  	}
  3527  	return fmt.Sprintf("%v%v", ins.p, suffix)
  3528  }
  3529  
  3530  func (ins *instruction) encode() (uint32, error) {
  3531  	enc, err := encodingForAs(ins.as)
  3532  	if err != nil {
  3533  		return 0, err
  3534  	}
  3535  	if enc.length <= 0 {
  3536  		return 0, fmt.Errorf("%v: encoding called for a pseudo instruction", ins.as)
  3537  	}
  3538  	return enc.encode(ins), nil
  3539  }
  3540  
  3541  func (ins *instruction) length() int {
  3542  	enc, err := encodingForAs(ins.as)
  3543  	if err != nil {
  3544  		return 0
  3545  	}
  3546  	return enc.length
  3547  }
  3548  
  3549  func (ins *instruction) validate(ctxt *obj.Link) {
  3550  	enc, err := encodingForAs(ins.as)
  3551  	if err != nil {
  3552  		ctxt.Diag("%v", err)
  3553  		return
  3554  	}
  3555  	enc.validate(ctxt, ins)
  3556  }
  3557  
  3558  func (ins *instruction) usesRegTmp() bool {
  3559  	return ins.rd == REG_TMP || ins.rs1 == REG_TMP || ins.rs2 == REG_TMP
  3560  }
  3561  
  3562  func (ins *instruction) compress() {
  3563  	switch ins.as {
  3564  	case ALW:
  3565  		if ins.rd != REG_X0 && ins.rs1 == REG_SP && isScaledImmU(ins.imm, 8, 4) {
  3566  			ins.as, ins.rs1, ins.rs2 = ACLWSP, obj.REG_NONE, ins.rs1
  3567  		} else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && isScaledImmU(ins.imm, 7, 4) {
  3568  			ins.as = ACLW
  3569  		}
  3570  
  3571  	case ALD:
  3572  		if ins.rs1 == REG_SP && ins.rd != REG_X0 && isScaledImmU(ins.imm, 9, 8) {
  3573  			ins.as, ins.rs1, ins.rs2 = ACLDSP, obj.REG_NONE, ins.rs1
  3574  		} else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && isScaledImmU(ins.imm, 8, 8) {
  3575  			ins.as = ACLD
  3576  		}
  3577  
  3578  	case AFLD:
  3579  		if ins.rs1 == REG_SP && isScaledImmU(ins.imm, 9, 8) {
  3580  			ins.as, ins.rs1, ins.rs2 = ACFLDSP, obj.REG_NONE, ins.rs1
  3581  		} else if isFloatPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && isScaledImmU(ins.imm, 8, 8) {
  3582  			ins.as = ACFLD
  3583  		}
  3584  
  3585  	case ASW:
  3586  		if ins.rd == REG_SP && isScaledImmU(ins.imm, 8, 4) {
  3587  			ins.as, ins.rs1, ins.rs2 = ACSWSP, obj.REG_NONE, ins.rs1
  3588  		} else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && isScaledImmU(ins.imm, 7, 4) {
  3589  			ins.as, ins.rd, ins.rs1, ins.rs2 = ACSW, obj.REG_NONE, ins.rd, ins.rs1
  3590  		}
  3591  
  3592  	case ASD:
  3593  		if ins.rd == REG_SP && isScaledImmU(ins.imm, 9, 8) {
  3594  			ins.as, ins.rs1, ins.rs2 = ACSDSP, obj.REG_NONE, ins.rs1
  3595  		} else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && isScaledImmU(ins.imm, 8, 8) {
  3596  			ins.as, ins.rd, ins.rs1, ins.rs2 = ACSD, obj.REG_NONE, ins.rd, ins.rs1
  3597  		}
  3598  
  3599  	case AFSD:
  3600  		if ins.rd == REG_SP && isScaledImmU(ins.imm, 9, 8) {
  3601  			ins.as, ins.rs1, ins.rs2 = ACFSDSP, obj.REG_NONE, ins.rs1
  3602  		} else if isIntPrimeReg(ins.rd) && isFloatPrimeReg(ins.rs1) && isScaledImmU(ins.imm, 8, 8) {
  3603  			ins.as, ins.rd, ins.rs1, ins.rs2 = ACFSD, obj.REG_NONE, ins.rd, ins.rs1
  3604  		}
  3605  
  3606  	case AADDI:
  3607  		if ins.rd == REG_SP && ins.rs1 == REG_SP && ins.imm != 0 && isScaledImmI(ins.imm, 10, 16) {
  3608  			ins.as = ACADDI16SP
  3609  		} else if ins.rd != REG_X0 && ins.rd == ins.rs1 && ins.imm != 0 && immIFits(ins.imm, 6) == nil {
  3610  			ins.as = ACADDI
  3611  		} else if isIntPrimeReg(ins.rd) && ins.rs1 == REG_SP && ins.imm != 0 && isScaledImmU(ins.imm, 10, 4) {
  3612  			ins.as = ACADDI4SPN
  3613  		} else if ins.rd != REG_X0 && ins.rs1 == REG_X0 && immIFits(ins.imm, 6) == nil {
  3614  			ins.as, ins.rs1 = ACLI, obj.REG_NONE
  3615  		} else if ins.rd != REG_X0 && ins.rs1 != REG_X0 && ins.imm == 0 {
  3616  			ins.as, ins.rs1, ins.rs2 = ACMV, obj.REG_NONE, ins.rs1
  3617  		} else if ins.rd == REG_X0 && ins.rs1 == REG_X0 && ins.imm == 0 {
  3618  			ins.as, ins.rs1 = ACNOP, ins.rd
  3619  		}
  3620  
  3621  	case AADDIW:
  3622  		if ins.rd == ins.rs1 && immIFits(ins.imm, 6) == nil {
  3623  			ins.as = ACADDIW
  3624  		}
  3625  
  3626  	case ALUI:
  3627  		if ins.rd != REG_X0 && ins.rd != REG_SP && ins.imm != 0 && immIFits(ins.imm, 6) == nil {
  3628  			ins.as = ACLUI
  3629  		}
  3630  
  3631  	case ASLLI:
  3632  		if ins.rd != REG_X0 && ins.rd == ins.rs1 && ins.imm != 0 {
  3633  			ins.as = ACSLLI
  3634  		}
  3635  
  3636  	case ASRLI:
  3637  		if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && ins.imm != 0 {
  3638  			ins.as = ACSRLI
  3639  		}
  3640  
  3641  	case ASRAI:
  3642  		if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && ins.imm != 0 {
  3643  			ins.as = ACSRAI
  3644  		}
  3645  
  3646  	case AANDI:
  3647  		if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && immIFits(ins.imm, 6) == nil {
  3648  			ins.as = ACANDI
  3649  		}
  3650  
  3651  	case AADD:
  3652  		if ins.rd != REG_X0 && ins.rd == ins.rs1 && ins.rs2 != REG_X0 {
  3653  			ins.as = ACADD
  3654  		} else if ins.rd != REG_X0 && ins.rd == ins.rs2 && ins.rs1 != REG_X0 {
  3655  			ins.as, ins.rs1, ins.rs2 = ACADD, ins.rs2, ins.rs1
  3656  		} else if ins.rd != REG_X0 && ins.rs1 == REG_X0 && ins.rs2 != REG_X0 {
  3657  			ins.as = ACMV
  3658  		}
  3659  
  3660  	case AADDW:
  3661  		if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && isIntPrimeReg(ins.rs2) {
  3662  			ins.as = ACADDW
  3663  		} else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && ins.rd == ins.rs2 {
  3664  			ins.as, ins.rs1, ins.rs2 = ACADDW, ins.rs2, ins.rs1
  3665  		}
  3666  
  3667  	case ASUB:
  3668  		if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && isIntPrimeReg(ins.rs2) {
  3669  			ins.as = ACSUB
  3670  		}
  3671  
  3672  	case ASUBW:
  3673  		if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && isIntPrimeReg(ins.rs2) {
  3674  			ins.as = ACSUBW
  3675  		}
  3676  
  3677  	case AAND:
  3678  		if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && isIntPrimeReg(ins.rs2) {
  3679  			ins.as = ACAND
  3680  		} else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && ins.rd == ins.rs2 {
  3681  			ins.as, ins.rs1, ins.rs2 = ACAND, ins.rs2, ins.rs1
  3682  		}
  3683  
  3684  	case AOR:
  3685  		if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && isIntPrimeReg(ins.rs2) {
  3686  			ins.as = ACOR
  3687  		} else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && ins.rd == ins.rs2 {
  3688  			ins.as, ins.rs1, ins.rs2 = ACOR, ins.rs2, ins.rs1
  3689  		}
  3690  
  3691  	case AXOR:
  3692  		if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && isIntPrimeReg(ins.rs2) {
  3693  			ins.as = ACXOR
  3694  		} else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && ins.rd == ins.rs2 {
  3695  			ins.as, ins.rs1, ins.rs2 = ACXOR, ins.rs2, ins.rs1
  3696  		}
  3697  
  3698  	case AEBREAK:
  3699  		ins.as, ins.rd, ins.rs1 = ACEBREAK, obj.REG_NONE, obj.REG_NONE
  3700  	}
  3701  }
  3702  
  3703  func encodeFenceOperand(a *obj.Addr) (uint32, bool) {
  3704  	if a.Type == obj.TYPE_SPECIAL && a.Offset > int64(SPOP_FENCE_BEGIN) && a.Offset < int64(SPOP_FENCE_END) {
  3705  		return SpecialOperand(a.Offset).encode(), true
  3706  	}
  3707  	if a.Type == obj.TYPE_NONE {
  3708  		return SPOP_FENCE_IORW.encode(), true
  3709  	}
  3710  	return 0, false
  3711  }
  3712  
  3713  // instructionForProg returns the default *obj.Prog to instruction mapping.
  3714  func instructionForProg(p *obj.Prog) *instruction {
  3715  	ins := &instruction{
  3716  		as:  p.As,
  3717  		rd:  uint32(p.To.Reg),
  3718  		rs1: uint32(p.Reg),
  3719  		rs2: uint32(p.From.Reg),
  3720  		imm: p.From.Offset,
  3721  	}
  3722  	if len(p.RestArgs) == 1 {
  3723  		ins.rs3 = uint32(p.RestArgs[0].Reg)
  3724  	}
  3725  	return ins
  3726  }
  3727  
  3728  // instructionsForOpImmediate returns the machine instructions for an immediate
  3729  // operand. The instruction is specified by as and the source register is
  3730  // specified by rs, instead of the obj.Prog.
  3731  func instructionsForOpImmediate(p *obj.Prog, as obj.As, rs int16) []*instruction {
  3732  	// <opi> $imm, REG, TO
  3733  	ins := instructionForProg(p)
  3734  	ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE
  3735  
  3736  	low, high, err := Split32BitImmediate(ins.imm)
  3737  	if err != nil {
  3738  		p.Ctxt.Diag("%v: constant %d too large: %v", p, ins.imm, err)
  3739  		return nil
  3740  	}
  3741  	if high == 0 {
  3742  		return []*instruction{ins}
  3743  	}
  3744  
  3745  	// Split into two additions, if possible.
  3746  	// Do not split SP-writing instructions, as otherwise the recorded SP delta may be wrong.
  3747  	if p.Spadj == 0 && ins.as == AADDI && ins.imm >= -(1<<12) && ins.imm < 1<<12-1 {
  3748  		imm0 := ins.imm / 2
  3749  		imm1 := ins.imm - imm0
  3750  
  3751  		// ADDI $(imm/2), REG, TO
  3752  		// ADDI $(imm-imm/2), TO, TO
  3753  		ins.imm = imm0
  3754  		insADDI := &instruction{as: AADDI, rd: ins.rd, rs1: ins.rd, imm: imm1}
  3755  		return []*instruction{ins, insADDI}
  3756  	}
  3757  
  3758  	// LUI $high, TMP
  3759  	// ADDIW $low, TMP, TMP
  3760  	// <op> TMP, REG, TO
  3761  	insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
  3762  	insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP, imm: low}
  3763  	switch ins.as {
  3764  	case AADDI:
  3765  		ins.as = AADD
  3766  	case AANDI:
  3767  		ins.as = AAND
  3768  	case AORI:
  3769  		ins.as = AOR
  3770  	case AXORI:
  3771  		ins.as = AXOR
  3772  	default:
  3773  		p.Ctxt.Diag("unsupported immediate instruction %v for splitting", p)
  3774  		return nil
  3775  	}
  3776  	ins.rs2 = REG_TMP
  3777  	if low == 0 {
  3778  		return []*instruction{insLUI, ins}
  3779  	}
  3780  	return []*instruction{insLUI, insADDIW, ins}
  3781  }
  3782  
  3783  // instructionsForLoad returns the machine instructions for a load. The load
  3784  // instruction is specified by as and the base/source register is specified
  3785  // by rs, instead of the obj.Prog.
  3786  func instructionsForLoad(p *obj.Prog, as obj.As, rs int16) []*instruction {
  3787  	if p.From.Type != obj.TYPE_MEM {
  3788  		p.Ctxt.Diag("%v requires memory for source", p)
  3789  		return nil
  3790  	}
  3791  
  3792  	switch as {
  3793  	case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU, AFLW, AFLD:
  3794  	default:
  3795  		p.Ctxt.Diag("%v: unknown load instruction %v", p, as)
  3796  		return nil
  3797  	}
  3798  
  3799  	// <load> $imm, REG, TO (load $imm+(REG), TO)
  3800  	ins := instructionForProg(p)
  3801  	ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE
  3802  	ins.imm = p.From.Offset
  3803  
  3804  	low, high, err := Split32BitImmediate(ins.imm)
  3805  	if err != nil {
  3806  		p.Ctxt.Diag("%v: constant %d too large", p, ins.imm)
  3807  		return nil
  3808  	}
  3809  	if high == 0 {
  3810  		return []*instruction{ins}
  3811  	}
  3812  
  3813  	// LUI $high, TMP
  3814  	// ADD TMP, REG, TMP
  3815  	// <load> $low, TMP, TO
  3816  	insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
  3817  	insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rs1}
  3818  	ins.rs1, ins.imm = REG_TMP, low
  3819  
  3820  	return []*instruction{insLUI, insADD, ins}
  3821  }
  3822  
  3823  // instructionsForStore returns the machine instructions for a store. The store
  3824  // instruction is specified by as and the target/source register is specified
  3825  // by rd, instead of the obj.Prog.
  3826  func instructionsForStore(p *obj.Prog, as obj.As, rd int16) []*instruction {
  3827  	if p.To.Type != obj.TYPE_MEM {
  3828  		p.Ctxt.Diag("%v requires memory for destination", p)
  3829  		return nil
  3830  	}
  3831  
  3832  	switch as {
  3833  	case ASW, ASH, ASB, ASD, AFSW, AFSD:
  3834  	default:
  3835  		p.Ctxt.Diag("%v: unknown store instruction %v", p, as)
  3836  		return nil
  3837  	}
  3838  
  3839  	// <store> $imm, REG, TO (store $imm+(TO), REG)
  3840  	ins := instructionForProg(p)
  3841  	ins.as, ins.rd, ins.rs1, ins.rs2 = as, uint32(rd), uint32(p.From.Reg), obj.REG_NONE
  3842  	ins.imm = p.To.Offset
  3843  
  3844  	low, high, err := Split32BitImmediate(ins.imm)
  3845  	if err != nil {
  3846  		p.Ctxt.Diag("%v: constant %d too large", p, ins.imm)
  3847  		return nil
  3848  	}
  3849  	if high == 0 {
  3850  		return []*instruction{ins}
  3851  	}
  3852  
  3853  	// LUI $high, TMP
  3854  	// ADD TMP, TO, TMP
  3855  	// <store> $low, REG, TMP
  3856  	insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
  3857  	insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rd}
  3858  	ins.rd, ins.imm = REG_TMP, low
  3859  
  3860  	return []*instruction{insLUI, insADD, ins}
  3861  }
  3862  
  3863  func instructionsForTLS(p *obj.Prog, ins *instruction) []*instruction {
  3864  	insAddTP := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: REG_TP}
  3865  
  3866  	var inss []*instruction
  3867  	if p.Ctxt.Flag_shared {
  3868  		// TLS initial-exec mode - load TLS offset from GOT, add the thread pointer
  3869  		// register, then load from or store to the resulting memory location.
  3870  		insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
  3871  		insLoadTLSOffset := &instruction{as: ALD, rd: REG_TMP, rs1: REG_TMP}
  3872  		inss = []*instruction{insAUIPC, insLoadTLSOffset, insAddTP, ins}
  3873  	} else {
  3874  		// TLS local-exec mode - load upper TLS offset, add the lower TLS offset,
  3875  		// add the thread pointer register, then load from or store to the resulting
  3876  		// memory location. Note that this differs from the suggested three
  3877  		// instruction sequence, as the Go linker does not currently have an
  3878  		// easy way to handle relocation across 12 bytes of machine code.
  3879  		insLUI := &instruction{as: ALUI, rd: REG_TMP}
  3880  		insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP}
  3881  		inss = []*instruction{insLUI, insADDIW, insAddTP, ins}
  3882  	}
  3883  	return inss
  3884  }
  3885  
  3886  func instructionsForTLSLoad(p *obj.Prog) []*instruction {
  3887  	if p.From.Sym.Type != objabi.STLSBSS {
  3888  		p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.From.Sym)
  3889  		return nil
  3890  	}
  3891  
  3892  	ins := instructionForProg(p)
  3893  	ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), REG_TMP, obj.REG_NONE, 0
  3894  
  3895  	return instructionsForTLS(p, ins)
  3896  }
  3897  
  3898  func instructionsForTLSStore(p *obj.Prog) []*instruction {
  3899  	if p.To.Sym.Type != objabi.STLSBSS {
  3900  		p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.To.Sym)
  3901  		return nil
  3902  	}
  3903  
  3904  	ins := instructionForProg(p)
  3905  	ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
  3906  
  3907  	return instructionsForTLS(p, ins)
  3908  }
  3909  
  3910  func instructionsForMOVConst(p *obj.Prog) []*instruction {
  3911  	ins := instructionForProg(p)
  3912  	inss := []*instruction{ins}
  3913  
  3914  	// For constants larger than 32 bits in size that have trailing zeros,
  3915  	// use the value with the trailing zeros removed and then use a SLLI
  3916  	// instruction to restore the original constant.
  3917  	//
  3918  	// For example:
  3919  	//     MOV $0x8000000000000000, X10
  3920  	// becomes
  3921  	//     MOV $1, X10
  3922  	//     SLLI $63, X10, X10
  3923  	//
  3924  	// Similarly, we can construct large constants that have a consecutive
  3925  	// sequence of ones from a small negative constant, with a right and/or
  3926  	// left shift.
  3927  	//
  3928  	// For example:
  3929  	//     MOV $0x000fffffffffffda, X10
  3930  	// becomes
  3931  	//     MOV $-19, X10
  3932  	//     SLLI $13, X10
  3933  	//     SRLI $12, X10
  3934  	//
  3935  	var insSLLI, insSRLI, insMOVWU *instruction
  3936  	if err := immIFits(ins.imm, 32); err != nil {
  3937  		if c, lsh, rsh, ok := splitShiftConst(ins.imm); ok {
  3938  			ins.imm = c
  3939  			if buildcfg.GORISCV64 >= 22 && lsh == 32 && rsh == 32 {
  3940  				insMOVWU = &instruction{as: AADDUW, rd: ins.rd, rs1: ins.rd, rs2: REG_ZERO}
  3941  				lsh, rsh = 0, 0
  3942  			}
  3943  			if lsh > 0 {
  3944  				insSLLI = &instruction{as: ASLLI, rd: ins.rd, rs1: ins.rd, imm: int64(lsh)}
  3945  			}
  3946  			if rsh > 0 {
  3947  				insSRLI = &instruction{as: ASRLI, rd: ins.rd, rs1: ins.rd, imm: int64(rsh)}
  3948  			}
  3949  		}
  3950  	}
  3951  
  3952  	low, high, err := Split32BitImmediate(ins.imm)
  3953  	if err != nil {
  3954  		p.Ctxt.Diag("%v: constant %d too large: %v", p, ins.imm, err)
  3955  		return nil
  3956  	}
  3957  
  3958  	// MOV $c, R -> ADD $c, ZERO, R
  3959  	ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, REG_ZERO, obj.REG_NONE, low
  3960  
  3961  	// LUI is only necessary if the constant does not fit in 12 bits.
  3962  	if high != 0 {
  3963  		// LUI top20bits(c), R
  3964  		// ADD bottom12bits(c), R, R
  3965  		insLUI := &instruction{as: ALUI, rd: ins.rd, imm: high}
  3966  		inss = []*instruction{insLUI}
  3967  		if low != 0 {
  3968  			ins.as, ins.rs1 = AADDIW, ins.rd
  3969  			inss = append(inss, ins)
  3970  		}
  3971  	}
  3972  	if insMOVWU != nil {
  3973  		inss = append(inss, insMOVWU)
  3974  	}
  3975  	if insSLLI != nil {
  3976  		inss = append(inss, insSLLI)
  3977  	}
  3978  	if insSRLI != nil {
  3979  		inss = append(inss, insSRLI)
  3980  	}
  3981  
  3982  	return inss
  3983  }
  3984  
  3985  // instructionsForMOV returns the machine instructions for an *obj.Prog that
  3986  // uses a MOV pseudo-instruction.
  3987  func instructionsForMOV(p *obj.Prog) []*instruction {
  3988  	ins := instructionForProg(p)
  3989  	inss := []*instruction{ins}
  3990  
  3991  	if p.Reg != 0 {
  3992  		p.Ctxt.Diag("%v: illegal MOV instruction", p)
  3993  		return nil
  3994  	}
  3995  
  3996  	switch {
  3997  	case p.From.Type == obj.TYPE_CONST && p.To.Type == obj.TYPE_REG:
  3998  		// Handle constant to register moves.
  3999  		if p.As != AMOV {
  4000  			p.Ctxt.Diag("%v: unsupported constant load", p)
  4001  			return nil
  4002  		}
  4003  		return instructionsForMOVConst(p)
  4004  
  4005  	case p.From.Type == obj.TYPE_CONST && p.To.Type != obj.TYPE_REG:
  4006  		p.Ctxt.Diag("%v: constant load must target register", p)
  4007  		return nil
  4008  
  4009  	case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG:
  4010  		// Handle register to register moves.
  4011  		switch p.As {
  4012  		case AMOV:
  4013  			// MOV Ra, Rb -> ADDI $0, Ra, Rb
  4014  			ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, uint32(p.From.Reg), obj.REG_NONE, 0
  4015  		case AMOVW:
  4016  			// MOVW Ra, Rb -> ADDIW $0, Ra, Rb
  4017  			ins.as, ins.rs1, ins.rs2, ins.imm = AADDIW, uint32(p.From.Reg), obj.REG_NONE, 0
  4018  		case AMOVBU:
  4019  			// MOVBU Ra, Rb -> ANDI $255, Ra, Rb
  4020  			ins.as, ins.rs1, ins.rs2, ins.imm = AANDI, uint32(p.From.Reg), obj.REG_NONE, 255
  4021  		case AMOVF:
  4022  			// MOVF Ra, Rb -> FSGNJS Ra, Ra, Rb
  4023  			//          or -> FMVWX  Ra, Rb
  4024  			//          or -> FMVXW  Ra, Rb
  4025  			if ins.rs2 >= REG_X0 && ins.rs2 <= REG_X31 && ins.rd >= REG_F0 && ins.rd <= REG_F31 {
  4026  				ins.as = AFMVWX
  4027  			} else if ins.rs2 >= REG_F0 && ins.rs2 <= REG_F31 && ins.rd >= REG_X0 && ins.rd <= REG_X31 {
  4028  				ins.as = AFMVXW
  4029  			} else {
  4030  				ins.as, ins.rs1 = AFSGNJS, uint32(p.From.Reg)
  4031  			}
  4032  		case AMOVD:
  4033  			// MOVD Ra, Rb -> FSGNJD Ra, Ra, Rb
  4034  			//          or -> FMVDX  Ra, Rb
  4035  			//          or -> FMVXD  Ra, Rb
  4036  			if ins.rs2 >= REG_X0 && ins.rs2 <= REG_X31 && ins.rd >= REG_F0 && ins.rd <= REG_F31 {
  4037  				ins.as = AFMVDX
  4038  			} else if ins.rs2 >= REG_F0 && ins.rs2 <= REG_F31 && ins.rd >= REG_X0 && ins.rd <= REG_X31 {
  4039  				ins.as = AFMVXD
  4040  			} else {
  4041  				ins.as, ins.rs1 = AFSGNJD, uint32(p.From.Reg)
  4042  			}
  4043  		case AMOVB, AMOVH:
  4044  			if buildcfg.GORISCV64 >= 22 {
  4045  				// Use SEXTB or SEXTH to extend.
  4046  				ins.as, ins.rs1, ins.rs2 = ASEXTB, uint32(p.From.Reg), obj.REG_NONE
  4047  				if p.As == AMOVH {
  4048  					ins.as = ASEXTH
  4049  				}
  4050  			} else {
  4051  				// Use SLLI/SRAI sequence to extend.
  4052  				ins.as, ins.rs1, ins.rs2 = ASLLI, uint32(p.From.Reg), obj.REG_NONE
  4053  				if p.As == AMOVB {
  4054  					ins.imm = 56
  4055  				} else if p.As == AMOVH {
  4056  					ins.imm = 48
  4057  				}
  4058  				ins2 := &instruction{as: ASRAI, rd: ins.rd, rs1: ins.rd, imm: ins.imm}
  4059  				inss = append(inss, ins2)
  4060  			}
  4061  		case AMOVHU, AMOVWU:
  4062  			if buildcfg.GORISCV64 >= 22 {
  4063  				// Use ZEXTH or ADDUW to extend.
  4064  				ins.as, ins.rs1, ins.rs2, ins.imm = AZEXTH, uint32(p.From.Reg), obj.REG_NONE, 0
  4065  				if p.As == AMOVWU {
  4066  					ins.as, ins.rs2 = AADDUW, REG_ZERO
  4067  				}
  4068  			} else {
  4069  				// Use SLLI/SRLI sequence to extend.
  4070  				ins.as, ins.rs1, ins.rs2 = ASLLI, uint32(p.From.Reg), obj.REG_NONE
  4071  				if p.As == AMOVHU {
  4072  					ins.imm = 48
  4073  				} else if p.As == AMOVWU {
  4074  					ins.imm = 32
  4075  				}
  4076  				ins2 := &instruction{as: ASRLI, rd: ins.rd, rs1: ins.rd, imm: ins.imm}
  4077  				inss = append(inss, ins2)
  4078  			}
  4079  		}
  4080  
  4081  	case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG:
  4082  		// Memory to register loads.
  4083  		switch p.From.Name {
  4084  		case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
  4085  			// MOV c(Rs), Rd -> L $c, Rs, Rd
  4086  			inss = instructionsForLoad(p, movToLoad(p.As), addrToReg(p.From))
  4087  
  4088  		case obj.NAME_EXTERN, obj.NAME_STATIC, obj.NAME_GOTREF:
  4089  			if p.From.Sym.Type == objabi.STLSBSS {
  4090  				return instructionsForTLSLoad(p)
  4091  			}
  4092  
  4093  			// Note that the values for $off_hi and $off_lo are currently
  4094  			// zero and will be assigned during relocation. If the destination
  4095  			// is an integer register then we can use the same register for the
  4096  			// address computation, otherwise we need to use the temporary register.
  4097  			//
  4098  			// AUIPC $off_hi, Rd
  4099  			// L $off_lo, Rd, Rd
  4100  			//
  4101  			addrReg := ins.rd
  4102  			if addrReg < REG_X0 || addrReg > REG_X31 {
  4103  				addrReg = REG_TMP
  4104  			}
  4105  			insAUIPC := &instruction{as: AAUIPC, rd: addrReg}
  4106  			ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), addrReg, obj.REG_NONE, 0
  4107  			inss = []*instruction{insAUIPC, ins}
  4108  
  4109  		default:
  4110  			p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
  4111  			return nil
  4112  		}
  4113  
  4114  	case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM:
  4115  		// Register to memory stores.
  4116  		switch p.As {
  4117  		case AMOVBU, AMOVHU, AMOVWU:
  4118  			p.Ctxt.Diag("%v: unsupported unsigned store", p)
  4119  			return nil
  4120  		}
  4121  		switch p.To.Name {
  4122  		case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
  4123  			// MOV Rs, c(Rd) -> S $c, Rs, Rd
  4124  			inss = instructionsForStore(p, movToStore(p.As), addrToReg(p.To))
  4125  
  4126  		case obj.NAME_EXTERN, obj.NAME_STATIC:
  4127  			if p.To.Sym.Type == objabi.STLSBSS {
  4128  				return instructionsForTLSStore(p)
  4129  			}
  4130  
  4131  			// Note that the values for $off_hi and $off_lo are currently
  4132  			// zero and will be assigned during relocation.
  4133  			//
  4134  			// AUIPC $off_hi, Rtmp
  4135  			// S $off_lo, Rtmp, Rd
  4136  			insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
  4137  			ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
  4138  			inss = []*instruction{insAUIPC, ins}
  4139  
  4140  		default:
  4141  			p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
  4142  			return nil
  4143  		}
  4144  
  4145  	case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG:
  4146  		// MOV $sym+off(SP/SB), R
  4147  		if p.As != AMOV {
  4148  			p.Ctxt.Diag("%v: unsupported address load", p)
  4149  			return nil
  4150  		}
  4151  		switch p.From.Name {
  4152  		case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
  4153  			inss = instructionsForOpImmediate(p, AADDI, addrToReg(p.From))
  4154  
  4155  		case obj.NAME_EXTERN, obj.NAME_STATIC:
  4156  			// Note that the values for $off_hi and $off_lo are currently
  4157  			// zero and will be assigned during relocation.
  4158  			//
  4159  			// AUIPC $off_hi, R
  4160  			// ADDI $off_lo, R
  4161  			insAUIPC := &instruction{as: AAUIPC, rd: ins.rd}
  4162  			ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, ins.rd, obj.REG_NONE, 0
  4163  			inss = []*instruction{insAUIPC, ins}
  4164  
  4165  		default:
  4166  			p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
  4167  			return nil
  4168  		}
  4169  
  4170  	case p.From.Type == obj.TYPE_ADDR && p.To.Type != obj.TYPE_REG:
  4171  		p.Ctxt.Diag("%v: address load must target register", p)
  4172  		return nil
  4173  
  4174  	default:
  4175  		p.Ctxt.Diag("%v: unsupported MOV", p)
  4176  		return nil
  4177  	}
  4178  
  4179  	return inss
  4180  }
  4181  
  4182  // instructionsForRotate returns the machine instructions for a bitwise rotation.
  4183  func instructionsForRotate(p *obj.Prog, ins *instruction) []*instruction {
  4184  	if buildcfg.GORISCV64 >= 22 {
  4185  		// Rotation instructions are supported natively.
  4186  		return []*instruction{ins}
  4187  	}
  4188  
  4189  	switch ins.as {
  4190  	case AROL, AROLW, AROR, ARORW:
  4191  		// ROL -> OR (SLL x y) (SRL x (NEG y))
  4192  		// ROR -> OR (SRL x y) (SLL x (NEG y))
  4193  		sllOp, srlOp := ASLL, ASRL
  4194  		if ins.as == AROLW || ins.as == ARORW {
  4195  			sllOp, srlOp = ASLLW, ASRLW
  4196  		}
  4197  		shift1, shift2 := sllOp, srlOp
  4198  		if ins.as == AROR || ins.as == ARORW {
  4199  			shift1, shift2 = shift2, shift1
  4200  		}
  4201  		return []*instruction{
  4202  			&instruction{as: ASUB, rs1: REG_ZERO, rs2: ins.rs2, rd: REG_TMP},
  4203  			&instruction{as: shift2, rs1: ins.rs1, rs2: REG_TMP, rd: REG_TMP},
  4204  			&instruction{as: shift1, rs1: ins.rs1, rs2: ins.rs2, rd: ins.rd},
  4205  			&instruction{as: AOR, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
  4206  		}
  4207  
  4208  	case ARORI, ARORIW:
  4209  		// ROR -> OR (SLLI -x y) (SRLI x y)
  4210  		sllOp, srlOp := ASLLI, ASRLI
  4211  		sllImm := int64(int8(-ins.imm) & 63)
  4212  		if ins.as == ARORIW {
  4213  			sllOp, srlOp = ASLLIW, ASRLIW
  4214  			sllImm = int64(int8(-ins.imm) & 31)
  4215  		}
  4216  		return []*instruction{
  4217  			&instruction{as: srlOp, rs1: ins.rs1, rd: REG_TMP, imm: ins.imm},
  4218  			&instruction{as: sllOp, rs1: ins.rs1, rd: ins.rd, imm: sllImm},
  4219  			&instruction{as: AOR, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
  4220  		}
  4221  
  4222  	default:
  4223  		p.Ctxt.Diag("%v: unknown rotation", p)
  4224  		return nil
  4225  	}
  4226  }
  4227  
  4228  // instructionsForMinMax returns the machine instructions for an integer minimum or maximum.
  4229  func instructionsForMinMax(p *obj.Prog, ins *instruction) []*instruction {
  4230  	if buildcfg.GORISCV64 >= 22 {
  4231  		// Minimum and maximum instructions are supported natively.
  4232  		return []*instruction{ins}
  4233  	}
  4234  
  4235  	// Generate a move for identical inputs.
  4236  	if ins.rs1 == ins.rs2 {
  4237  		ins.as, ins.rs2, ins.imm = AADDI, obj.REG_NONE, 0
  4238  		return []*instruction{ins}
  4239  	}
  4240  
  4241  	// Ensure that if one of the source registers is the same as the destination,
  4242  	// it is processed first.
  4243  	if ins.rs1 == ins.rd {
  4244  		ins.rs1, ins.rs2 = ins.rs2, ins.rs1
  4245  	}
  4246  	sltReg1, sltReg2 := ins.rs2, ins.rs1
  4247  
  4248  	// MIN -> SLT/SUB/XOR/AND/XOR
  4249  	// MAX -> SLT/SUB/XOR/AND/XOR with swapped inputs to SLT
  4250  	switch ins.as {
  4251  	case AMIN:
  4252  		ins.as = ASLT
  4253  	case AMAX:
  4254  		ins.as, sltReg1, sltReg2 = ASLT, sltReg2, sltReg1
  4255  	case AMINU:
  4256  		ins.as = ASLTU
  4257  	case AMAXU:
  4258  		ins.as, sltReg1, sltReg2 = ASLTU, sltReg2, sltReg1
  4259  	}
  4260  	return []*instruction{
  4261  		&instruction{as: ins.as, rs1: sltReg1, rs2: sltReg2, rd: REG_TMP},
  4262  		&instruction{as: ASUB, rs1: REG_ZERO, rs2: REG_TMP, rd: REG_TMP},
  4263  		&instruction{as: AXOR, rs1: ins.rs1, rs2: ins.rs2, rd: ins.rd},
  4264  		&instruction{as: AAND, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
  4265  		&instruction{as: AXOR, rs1: ins.rs1, rs2: ins.rd, rd: ins.rd},
  4266  	}
  4267  }
  4268  
  4269  // instructionsForProg returns the machine instructions for an *obj.Prog.
  4270  func instructionsForProg(p *obj.Prog, compress bool) []*instruction {
  4271  	ins := instructionForProg(p)
  4272  	inss := []*instruction{ins}
  4273  
  4274  	if ins.as == AVSETVLI || ins.as == AVSETIVLI {
  4275  		if len(p.RestArgs) != 4 {
  4276  			p.Ctxt.Diag("incorrect number of arguments for instruction")
  4277  			return nil
  4278  		}
  4279  	} else if len(p.RestArgs) > 1 {
  4280  		p.Ctxt.Diag("too many source registers")
  4281  		return nil
  4282  	}
  4283  
  4284  	switch ins.as {
  4285  	case ACJALR, AJAL, AJALR:
  4286  		ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.To.Reg), obj.REG_NONE
  4287  		ins.imm = p.To.Offset
  4288  
  4289  	case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ:
  4290  		switch ins.as {
  4291  		case ABEQZ:
  4292  			ins.as, ins.rs1, ins.rs2 = ABEQ, REG_ZERO, uint32(p.From.Reg)
  4293  		case ABGEZ:
  4294  			ins.as, ins.rs1, ins.rs2 = ABGE, REG_ZERO, uint32(p.From.Reg)
  4295  		case ABGT:
  4296  			ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), uint32(p.Reg)
  4297  		case ABGTU:
  4298  			ins.as, ins.rs1, ins.rs2 = ABLTU, uint32(p.From.Reg), uint32(p.Reg)
  4299  		case ABGTZ:
  4300  			ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), REG_ZERO
  4301  		case ABLE:
  4302  			ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), uint32(p.Reg)
  4303  		case ABLEU:
  4304  			ins.as, ins.rs1, ins.rs2 = ABGEU, uint32(p.From.Reg), uint32(p.Reg)
  4305  		case ABLEZ:
  4306  			ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), REG_ZERO
  4307  		case ABLTZ:
  4308  			ins.as, ins.rs1, ins.rs2 = ABLT, REG_ZERO, uint32(p.From.Reg)
  4309  		case ABNEZ:
  4310  			ins.as, ins.rs1, ins.rs2 = ABNE, REG_ZERO, uint32(p.From.Reg)
  4311  		}
  4312  		ins.imm = p.To.Offset
  4313  
  4314  	case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
  4315  		inss = instructionsForMOV(p)
  4316  
  4317  	case ALW, ALWU, ALH, ALHU, ALB, ALBU, ALD, AFLW, AFLD:
  4318  		inss = instructionsForLoad(p, ins.as, p.From.Reg)
  4319  
  4320  	case ASW, ASH, ASB, ASD, AFSW, AFSD:
  4321  		inss = instructionsForStore(p, ins.as, p.To.Reg)
  4322  
  4323  	case ALRW, ALRD:
  4324  		// Set aq to use acquire access ordering
  4325  		ins.funct7 = 2
  4326  		ins.rs1, ins.rs2 = uint32(p.From.Reg), REG_ZERO
  4327  
  4328  	case AADDI, AANDI, AORI, AXORI:
  4329  		inss = instructionsForOpImmediate(p, ins.as, p.Reg)
  4330  
  4331  	case ASCW, ASCD:
  4332  		// Set release access ordering
  4333  		ins.funct7 = 1
  4334  		ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg)
  4335  
  4336  	case AAMOSWAPW, AAMOSWAPD, AAMOADDW, AAMOADDD, AAMOANDW, AAMOANDD, AAMOORW, AAMOORD,
  4337  		AAMOXORW, AAMOXORD, AAMOMINW, AAMOMIND, AAMOMINUW, AAMOMINUD, AAMOMAXW, AAMOMAXD, AAMOMAXUW, AAMOMAXUD:
  4338  		// Set aqrl to use acquire & release access ordering
  4339  		ins.funct7 = 3
  4340  		ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg)
  4341  
  4342  	case AECALL, AEBREAK:
  4343  		insEnc := encode(p.As)
  4344  		if p.To.Type == obj.TYPE_NONE {
  4345  			ins.rd = REG_ZERO
  4346  		}
  4347  		ins.rs1 = REG_ZERO
  4348  		ins.imm = insEnc.csr
  4349  
  4350  	case ARDCYCLE, ARDTIME, ARDINSTRET:
  4351  		ins.as = ACSRRS
  4352  		if p.To.Type == obj.TYPE_NONE {
  4353  			ins.rd = REG_ZERO
  4354  		}
  4355  		ins.rs1 = REG_ZERO
  4356  		switch p.As {
  4357  		case ARDCYCLE:
  4358  			ins.imm = -1024
  4359  		case ARDTIME:
  4360  			ins.imm = -1023
  4361  		case ARDINSTRET:
  4362  			ins.imm = -1022
  4363  		}
  4364  
  4365  	case ACSRRC, ACSRRCI, ACSRRS, ACSRRSI, ACSRRW, ACSRRWI:
  4366  		if len(p.RestArgs) == 0 || p.RestArgs[0].Type != obj.TYPE_SPECIAL {
  4367  			p.Ctxt.Diag("%v: missing CSR name", p)
  4368  			return nil
  4369  		}
  4370  		if p.From.Type == obj.TYPE_CONST {
  4371  			imm := p.From.Offset
  4372  			if imm < 0 || imm >= 32 {
  4373  				p.Ctxt.Diag("%v: immediate out of range 0 to 31", p)
  4374  				return nil
  4375  			}
  4376  			ins.rs1 = uint32(imm) + REG_ZERO
  4377  		} else if p.From.Type == obj.TYPE_REG {
  4378  			ins.rs1 = uint32(p.From.Reg)
  4379  		} else {
  4380  			p.Ctxt.Diag("%v: integer register or immediate expected for 1st operand", p)
  4381  			return nil
  4382  		}
  4383  		if p.To.Type != obj.TYPE_REG {
  4384  			p.Ctxt.Diag("%v: needs an integer register output", p)
  4385  			return nil
  4386  		}
  4387  		csrNum := SpecialOperand(p.RestArgs[0].Offset).encode()
  4388  		if csrNum >= 1<<12 {
  4389  			p.Ctxt.Diag("%v: unknown CSR", p)
  4390  			return nil
  4391  		}
  4392  		if _, ok := CSRs[uint16(csrNum)]; !ok {
  4393  			p.Ctxt.Diag("%v: unknown CSR", p)
  4394  			return nil
  4395  		}
  4396  		ins.imm = int64(csrNum)
  4397  		if ins.imm > 2047 {
  4398  			ins.imm -= 4096
  4399  		}
  4400  		ins.rs2 = obj.REG_NONE
  4401  
  4402  	case AFENCE:
  4403  		ins.rd, ins.rs1, ins.rs2 = REG_ZERO, REG_ZERO, obj.REG_NONE
  4404  		if p.Scond == fenceTsoSuffixBit {
  4405  			if p.From.Type != obj.TYPE_NONE || p.To.Type != obj.TYPE_NONE {
  4406  				p.Ctxt.Diag("FENCE.TSO must not have operands: %v", p)
  4407  			}
  4408  			// FENCE.TSO is encoded as a FENCE instruction with fm=1000(8), pred=RW(3), succ=RW(3)
  4409  			ins.imm = signExtend((8<<8)|(3<<4)|3, 12)
  4410  		} else {
  4411  			pred, ok := encodeFenceOperand(&p.From)
  4412  			if !ok {
  4413  				p.Ctxt.Diag("invalid FENCE predecessor operand: %v", p)
  4414  			}
  4415  			succ, ok := encodeFenceOperand(&p.To)
  4416  			if !ok {
  4417  				p.Ctxt.Diag("invalid FENCE successor operand: %v", p)
  4418  			}
  4419  			// FENCE pred, succ
  4420  			// pred(4 bits), succ(4 bits)
  4421  			ins.imm = int64((pred << 4) | succ)
  4422  		}
  4423  
  4424  	case APAUSE:
  4425  		ins.as, ins.rd, ins.rs1, ins.rs2 = AFENCE, REG_ZERO, REG_ZERO, obj.REG_NONE
  4426  		ins.imm = 0x010
  4427  
  4428  	case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
  4429  		// Set the default rounding mode in funct3 to round to zero.
  4430  		if p.Scond&rmSuffixBit == 0 {
  4431  			ins.funct3 = uint32(RM_RTZ)
  4432  		} else {
  4433  			ins.funct3 = uint32(p.Scond &^ rmSuffixBit)
  4434  		}
  4435  
  4436  	case AFNES, AFNED:
  4437  		// Replace FNE[SD] with FEQ[SD] and NOT.
  4438  		if p.To.Type != obj.TYPE_REG {
  4439  			p.Ctxt.Diag("%v needs an integer register output", p)
  4440  			return nil
  4441  		}
  4442  		if ins.as == AFNES {
  4443  			ins.as = AFEQS
  4444  		} else {
  4445  			ins.as = AFEQD
  4446  		}
  4447  		ins2 := &instruction{
  4448  			as:  AXORI, // [bit] xor 1 = not [bit]
  4449  			rd:  ins.rd,
  4450  			rs1: ins.rd,
  4451  			imm: 1,
  4452  		}
  4453  		inss = append(inss, ins2)
  4454  
  4455  	case AFSQRTS, AFSQRTD:
  4456  		// These instructions expect a zero (i.e. float register 0)
  4457  		// to be the second input operand.
  4458  		ins.rs1 = uint32(p.From.Reg)
  4459  		ins.rs2 = REG_F0
  4460  
  4461  	case AFMADDS, AFMSUBS, AFNMADDS, AFNMSUBS,
  4462  		AFMADDD, AFMSUBD, AFNMADDD, AFNMSUBD:
  4463  		// Swap the first two operands so that the operands are in the same
  4464  		// order as they are in the specification: RS1, RS2, RS3, RD.
  4465  		ins.rs1, ins.rs2 = ins.rs2, ins.rs1
  4466  
  4467  	case ANEG, ANEGW:
  4468  		// NEG rs, rd -> SUB rs, X0, rd
  4469  		ins.as = ASUB
  4470  		if p.As == ANEGW {
  4471  			ins.as = ASUBW
  4472  		}
  4473  		ins.rs1 = REG_ZERO
  4474  		if ins.rd == obj.REG_NONE {
  4475  			ins.rd = ins.rs2
  4476  		}
  4477  
  4478  	case ANOT:
  4479  		// NOT rs, rd -> XORI $-1, rs, rd
  4480  		ins.as = AXORI
  4481  		ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
  4482  		if ins.rd == obj.REG_NONE {
  4483  			ins.rd = ins.rs1
  4484  		}
  4485  		ins.imm = -1
  4486  
  4487  	case ASEQZ:
  4488  		// SEQZ rs, rd -> SLTIU $1, rs, rd
  4489  		ins.as = ASLTIU
  4490  		ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
  4491  		ins.imm = 1
  4492  
  4493  	case ASNEZ:
  4494  		// SNEZ rs, rd -> SLTU rs, x0, rd
  4495  		ins.as = ASLTU
  4496  		ins.rs1 = REG_ZERO
  4497  
  4498  	case AFABSS:
  4499  		// FABSS rs, rd -> FSGNJXS rs, rs, rd
  4500  		ins.as = AFSGNJXS
  4501  		ins.rs1 = uint32(p.From.Reg)
  4502  
  4503  	case AFABSD:
  4504  		// FABSD rs, rd -> FSGNJXD rs, rs, rd
  4505  		ins.as = AFSGNJXD
  4506  		ins.rs1 = uint32(p.From.Reg)
  4507  
  4508  	case AFNEGS:
  4509  		// FNEGS rs, rd -> FSGNJNS rs, rs, rd
  4510  		ins.as = AFSGNJNS
  4511  		ins.rs1 = uint32(p.From.Reg)
  4512  
  4513  	case AFNEGD:
  4514  		// FNEGD rs, rd -> FSGNJND rs, rs, rd
  4515  		ins.as = AFSGNJND
  4516  		ins.rs1 = uint32(p.From.Reg)
  4517  
  4518  	case ACLW, ACLD, ACFLD:
  4519  		ins.rs1, ins.rs2 = ins.rs2, obj.REG_NONE
  4520  
  4521  	case ACSW, ACSD, ACFSD:
  4522  		ins.rs1, ins.rd = ins.rd, obj.REG_NONE
  4523  		ins.imm = p.To.Offset
  4524  
  4525  	case ACSWSP, ACSDSP, ACFSDSP:
  4526  		ins.imm = p.To.Offset
  4527  
  4528  	case ACANDI, ACSRLI, ACSRAI:
  4529  		ins.rs1, ins.rd = ins.rd, ins.rs1
  4530  
  4531  	case ACBEQZ, ACBNEZ:
  4532  		ins.rd, ins.rs1, ins.rs2 = obj.REG_NONE, uint32(p.From.Reg), obj.REG_NONE
  4533  		ins.imm = p.To.Offset
  4534  
  4535  	case ACJR:
  4536  		ins.rd, ins.rs1 = obj.REG_NONE, uint32(p.To.Reg)
  4537  
  4538  	case ACJ:
  4539  		ins.imm = p.To.Offset
  4540  
  4541  	case ACNOP:
  4542  		ins.rd, ins.rs1 = REG_ZERO, REG_ZERO
  4543  
  4544  	case AROL, AROLW, AROR, ARORW:
  4545  		inss = instructionsForRotate(p, ins)
  4546  
  4547  	case ARORI:
  4548  		if ins.imm < 0 || ins.imm > 63 {
  4549  			p.Ctxt.Diag("%v: immediate out of range 0 to 63", p)
  4550  		}
  4551  		inss = instructionsForRotate(p, ins)
  4552  
  4553  	case ARORIW:
  4554  		if ins.imm < 0 || ins.imm > 31 {
  4555  			p.Ctxt.Diag("%v: immediate out of range 0 to 31", p)
  4556  		}
  4557  		inss = instructionsForRotate(p, ins)
  4558  
  4559  	case ASLLI, ASRLI, ASRAI:
  4560  		if ins.imm < 0 || ins.imm > 63 {
  4561  			p.Ctxt.Diag("%v: immediate out of range 0 to 63", p)
  4562  		}
  4563  
  4564  	case ASLLIW, ASRLIW, ASRAIW:
  4565  		if ins.imm < 0 || ins.imm > 31 {
  4566  			p.Ctxt.Diag("%v: immediate out of range 0 to 31", p)
  4567  		}
  4568  
  4569  	case ACLZ, ACLZW, ACTZ, ACTZW, ACPOP, ACPOPW, ASEXTB, ASEXTH, AZEXTH:
  4570  		ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
  4571  
  4572  	case AORCB, AREV8:
  4573  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
  4574  
  4575  	case AANDN, AORN:
  4576  		if buildcfg.GORISCV64 >= 22 {
  4577  			// ANDN and ORN instructions are supported natively.
  4578  			break
  4579  		}
  4580  		// ANDN -> (AND (NOT x) y)
  4581  		// ORN  -> (OR  (NOT x) y)
  4582  		bitwiseOp, notReg := AAND, ins.rd
  4583  		if ins.as == AORN {
  4584  			bitwiseOp = AOR
  4585  		}
  4586  		if ins.rs1 == notReg {
  4587  			notReg = REG_TMP
  4588  		}
  4589  		inss = []*instruction{
  4590  			&instruction{as: AXORI, rs1: ins.rs2, rs2: obj.REG_NONE, rd: notReg, imm: -1},
  4591  			&instruction{as: bitwiseOp, rs1: ins.rs1, rs2: notReg, rd: ins.rd},
  4592  		}
  4593  
  4594  	case AXNOR:
  4595  		if buildcfg.GORISCV64 >= 22 {
  4596  			// XNOR instruction is supported natively.
  4597  			break
  4598  		}
  4599  		// XNOR -> (NOT (XOR x y))
  4600  		ins.as = AXOR
  4601  		inss = append(inss, &instruction{as: AXORI, rs1: ins.rd, rs2: obj.REG_NONE, rd: ins.rd, imm: -1})
  4602  
  4603  	case AMIN, AMAX, AMINU, AMAXU:
  4604  		inss = instructionsForMinMax(p, ins)
  4605  
  4606  	case AVSETVLI, AVSETIVLI:
  4607  		ins.rs1, ins.rs2 = ins.rs2, obj.REG_NONE
  4608  		vtype, err := EncodeVectorType(p.RestArgs[0].Offset, p.RestArgs[1].Offset, p.RestArgs[2].Offset, p.RestArgs[3].Offset)
  4609  		if err != nil {
  4610  			p.Ctxt.Diag("%v: %v", p, err)
  4611  		}
  4612  		ins.imm = vtype
  4613  		if ins.as == AVSETIVLI {
  4614  			if p.From.Type != obj.TYPE_CONST {
  4615  				p.Ctxt.Diag("%v: expected immediate value", p)
  4616  			}
  4617  			ins.rs1 = uint32(p.From.Offset)
  4618  		}
  4619  
  4620  	case AVLE8V, AVLE16V, AVLE32V, AVLE64V, AVSE8V, AVSE16V, AVSE32V, AVSE64V, AVLE8FFV, AVLE16FFV, AVLE32FFV, AVLE64FFV, AVLMV, AVSMV,
  4621  		AVLSEG2E8V, AVLSEG3E8V, AVLSEG4E8V, AVLSEG5E8V, AVLSEG6E8V, AVLSEG7E8V, AVLSEG8E8V,
  4622  		AVLSEG2E16V, AVLSEG3E16V, AVLSEG4E16V, AVLSEG5E16V, AVLSEG6E16V, AVLSEG7E16V, AVLSEG8E16V,
  4623  		AVLSEG2E32V, AVLSEG3E32V, AVLSEG4E32V, AVLSEG5E32V, AVLSEG6E32V, AVLSEG7E32V, AVLSEG8E32V,
  4624  		AVLSEG2E64V, AVLSEG3E64V, AVLSEG4E64V, AVLSEG5E64V, AVLSEG6E64V, AVLSEG7E64V, AVLSEG8E64V,
  4625  		AVSSEG2E8V, AVSSEG3E8V, AVSSEG4E8V, AVSSEG5E8V, AVSSEG6E8V, AVSSEG7E8V, AVSSEG8E8V,
  4626  		AVSSEG2E16V, AVSSEG3E16V, AVSSEG4E16V, AVSSEG5E16V, AVSSEG6E16V, AVSSEG7E16V, AVSSEG8E16V,
  4627  		AVSSEG2E32V, AVSSEG3E32V, AVSSEG4E32V, AVSSEG5E32V, AVSSEG6E32V, AVSSEG7E32V, AVSSEG8E32V,
  4628  		AVSSEG2E64V, AVSSEG3E64V, AVSSEG4E64V, AVSSEG5E64V, AVSSEG6E64V, AVSSEG7E64V, AVSSEG8E64V,
  4629  		AVLSEG2E8FFV, AVLSEG3E8FFV, AVLSEG4E8FFV, AVLSEG5E8FFV, AVLSEG6E8FFV, AVLSEG7E8FFV, AVLSEG8E8FFV,
  4630  		AVLSEG2E16FFV, AVLSEG3E16FFV, AVLSEG4E16FFV, AVLSEG5E16FFV, AVLSEG6E16FFV, AVLSEG7E16FFV, AVLSEG8E16FFV,
  4631  		AVLSEG2E32FFV, AVLSEG3E32FFV, AVLSEG4E32FFV, AVLSEG5E32FFV, AVLSEG6E32FFV, AVLSEG7E32FFV, AVLSEG8E32FFV,
  4632  		AVLSEG2E64FFV, AVLSEG3E64FFV, AVLSEG4E64FFV, AVLSEG5E64FFV, AVLSEG6E64FFV, AVLSEG7E64FFV, AVLSEG8E64FFV:
  4633  		// Set mask bit
  4634  		switch {
  4635  		case ins.rs1 == obj.REG_NONE:
  4636  			ins.funct7 |= 1 // unmasked
  4637  		case ins.rs1 != REG_V0:
  4638  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4639  		}
  4640  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
  4641  
  4642  	case AVLSE8V, AVLSE16V, AVLSE32V, AVLSE64V,
  4643  		AVLUXEI8V, AVLUXEI16V, AVLUXEI32V, AVLUXEI64V, AVLOXEI8V, AVLOXEI16V, AVLOXEI32V, AVLOXEI64V,
  4644  		AVLSSEG2E8V, AVLSSEG3E8V, AVLSSEG4E8V, AVLSSEG5E8V, AVLSSEG6E8V, AVLSSEG7E8V, AVLSSEG8E8V,
  4645  		AVLSSEG2E16V, AVLSSEG3E16V, AVLSSEG4E16V, AVLSSEG5E16V, AVLSSEG6E16V, AVLSSEG7E16V, AVLSSEG8E16V,
  4646  		AVLSSEG2E32V, AVLSSEG3E32V, AVLSSEG4E32V, AVLSSEG5E32V, AVLSSEG6E32V, AVLSSEG7E32V, AVLSSEG8E32V,
  4647  		AVLSSEG2E64V, AVLSSEG3E64V, AVLSSEG4E64V, AVLSSEG5E64V, AVLSSEG6E64V, AVLSSEG7E64V, AVLSSEG8E64V,
  4648  		AVLOXSEG2EI8V, AVLOXSEG3EI8V, AVLOXSEG4EI8V, AVLOXSEG5EI8V, AVLOXSEG6EI8V, AVLOXSEG7EI8V, AVLOXSEG8EI8V,
  4649  		AVLOXSEG2EI16V, AVLOXSEG3EI16V, AVLOXSEG4EI16V, AVLOXSEG5EI16V, AVLOXSEG6EI16V, AVLOXSEG7EI16V, AVLOXSEG8EI16V,
  4650  		AVLOXSEG2EI32V, AVLOXSEG3EI32V, AVLOXSEG4EI32V, AVLOXSEG5EI32V, AVLOXSEG6EI32V, AVLOXSEG7EI32V, AVLOXSEG8EI32V,
  4651  		AVLOXSEG2EI64V, AVLOXSEG3EI64V, AVLOXSEG4EI64V, AVLOXSEG5EI64V, AVLOXSEG6EI64V, AVLOXSEG7EI64V, AVLOXSEG8EI64V,
  4652  		AVLUXSEG2EI8V, AVLUXSEG3EI8V, AVLUXSEG4EI8V, AVLUXSEG5EI8V, AVLUXSEG6EI8V, AVLUXSEG7EI8V, AVLUXSEG8EI8V,
  4653  		AVLUXSEG2EI16V, AVLUXSEG3EI16V, AVLUXSEG4EI16V, AVLUXSEG5EI16V, AVLUXSEG6EI16V, AVLUXSEG7EI16V, AVLUXSEG8EI16V,
  4654  		AVLUXSEG2EI32V, AVLUXSEG3EI32V, AVLUXSEG4EI32V, AVLUXSEG5EI32V, AVLUXSEG6EI32V, AVLUXSEG7EI32V, AVLUXSEG8EI32V,
  4655  		AVLUXSEG2EI64V, AVLUXSEG3EI64V, AVLUXSEG4EI64V, AVLUXSEG5EI64V, AVLUXSEG6EI64V, AVLUXSEG7EI64V, AVLUXSEG8EI64V:
  4656  		// Set mask bit
  4657  		switch {
  4658  		case ins.rs3 == obj.REG_NONE:
  4659  			ins.funct7 |= 1 // unmasked
  4660  		case ins.rs3 != REG_V0:
  4661  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4662  		}
  4663  		ins.rs1, ins.rs2, ins.rs3 = ins.rs2, ins.rs1, obj.REG_NONE
  4664  
  4665  	case AVSSE8V, AVSSE16V, AVSSE32V, AVSSE64V,
  4666  		AVSUXEI8V, AVSUXEI16V, AVSUXEI32V, AVSUXEI64V, AVSOXEI8V, AVSOXEI16V, AVSOXEI32V, AVSOXEI64V,
  4667  		AVSSSEG2E8V, AVSSSEG3E8V, AVSSSEG4E8V, AVSSSEG5E8V, AVSSSEG6E8V, AVSSSEG7E8V, AVSSSEG8E8V,
  4668  		AVSSSEG2E16V, AVSSSEG3E16V, AVSSSEG4E16V, AVSSSEG5E16V, AVSSSEG6E16V, AVSSSEG7E16V, AVSSSEG8E16V,
  4669  		AVSSSEG2E32V, AVSSSEG3E32V, AVSSSEG4E32V, AVSSSEG5E32V, AVSSSEG6E32V, AVSSSEG7E32V, AVSSSEG8E32V,
  4670  		AVSSSEG2E64V, AVSSSEG3E64V, AVSSSEG4E64V, AVSSSEG5E64V, AVSSSEG6E64V, AVSSSEG7E64V, AVSSSEG8E64V,
  4671  		AVSOXSEG2EI8V, AVSOXSEG3EI8V, AVSOXSEG4EI8V, AVSOXSEG5EI8V, AVSOXSEG6EI8V, AVSOXSEG7EI8V, AVSOXSEG8EI8V,
  4672  		AVSOXSEG2EI16V, AVSOXSEG3EI16V, AVSOXSEG4EI16V, AVSOXSEG5EI16V, AVSOXSEG6EI16V, AVSOXSEG7EI16V, AVSOXSEG8EI16V,
  4673  		AVSOXSEG2EI32V, AVSOXSEG3EI32V, AVSOXSEG4EI32V, AVSOXSEG5EI32V, AVSOXSEG6EI32V, AVSOXSEG7EI32V, AVSOXSEG8EI32V,
  4674  		AVSOXSEG2EI64V, AVSOXSEG3EI64V, AVSOXSEG4EI64V, AVSOXSEG5EI64V, AVSOXSEG6EI64V, AVSOXSEG7EI64V, AVSOXSEG8EI64V,
  4675  		AVSUXSEG2EI8V, AVSUXSEG3EI8V, AVSUXSEG4EI8V, AVSUXSEG5EI8V, AVSUXSEG6EI8V, AVSUXSEG7EI8V, AVSUXSEG8EI8V,
  4676  		AVSUXSEG2EI16V, AVSUXSEG3EI16V, AVSUXSEG4EI16V, AVSUXSEG5EI16V, AVSUXSEG6EI16V, AVSUXSEG7EI16V, AVSUXSEG8EI16V,
  4677  		AVSUXSEG2EI32V, AVSUXSEG3EI32V, AVSUXSEG4EI32V, AVSUXSEG5EI32V, AVSUXSEG6EI32V, AVSUXSEG7EI32V, AVSUXSEG8EI32V,
  4678  		AVSUXSEG2EI64V, AVSUXSEG3EI64V, AVSUXSEG4EI64V, AVSUXSEG5EI64V, AVSUXSEG6EI64V, AVSUXSEG7EI64V, AVSUXSEG8EI64V:
  4679  		// Set mask bit
  4680  		switch {
  4681  		case ins.rs3 == obj.REG_NONE:
  4682  			ins.funct7 |= 1 // unmasked
  4683  		case ins.rs3 != REG_V0:
  4684  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4685  		}
  4686  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = ins.rs2, ins.rd, ins.rs1, obj.REG_NONE
  4687  
  4688  	case AVL1RV, AVL1RE8V, AVL1RE16V, AVL1RE32V, AVL1RE64V, AVL2RV, AVL2RE8V, AVL2RE16V, AVL2RE32V, AVL2RE64V,
  4689  		AVL4RV, AVL4RE8V, AVL4RE16V, AVL4RE32V, AVL4RE64V, AVL8RV, AVL8RE8V, AVL8RE16V, AVL8RE32V, AVL8RE64V:
  4690  		switch ins.as {
  4691  		case AVL1RV:
  4692  			ins.as = AVL1RE8V
  4693  		case AVL2RV:
  4694  			ins.as = AVL2RE8V
  4695  		case AVL4RV:
  4696  			ins.as = AVL4RE8V
  4697  		case AVL8RV:
  4698  			ins.as = AVL8RE8V
  4699  		}
  4700  		if ins.rs1 != obj.REG_NONE {
  4701  			p.Ctxt.Diag("%v: too many operands for instruction", p)
  4702  		}
  4703  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
  4704  
  4705  	case AVS1RV, AVS2RV, AVS4RV, AVS8RV:
  4706  		if ins.rs1 != obj.REG_NONE {
  4707  			p.Ctxt.Diag("%v: too many operands for instruction", p)
  4708  		}
  4709  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
  4710  
  4711  	case AVADDVV, AVADDVX, AVSUBVV, AVSUBVX, AVRSUBVX, AVWADDUVV, AVWADDUVX, AVWSUBUVV, AVWSUBUVX,
  4712  		AVWADDVV, AVWADDVX, AVWSUBVV, AVWSUBVX, AVWADDUWV, AVWADDUWX, AVWSUBUWV, AVWSUBUWX,
  4713  		AVWADDWV, AVWADDWX, AVWSUBWV, AVWSUBWX, AVANDVV, AVANDVX, AVORVV, AVORVX, AVXORVV, AVXORVX,
  4714  		AVSLLVV, AVSLLVX, AVSRLVV, AVSRLVX, AVSRAVV, AVSRAVX,
  4715  		AVMSEQVV, AVMSEQVX, AVMSNEVV, AVMSNEVX, AVMSLTUVV, AVMSLTUVX, AVMSLTVV, AVMSLTVX,
  4716  		AVMSLEUVV, AVMSLEUVX, AVMSLEVV, AVMSLEVX, AVMSGTUVX, AVMSGTVX,
  4717  		AVMINUVV, AVMINUVX, AVMINVV, AVMINVX, AVMAXUVV, AVMAXUVX, AVMAXVV, AVMAXVX,
  4718  		AVMULVV, AVMULVX, AVMULHVV, AVMULHVX, AVMULHUVV, AVMULHUVX, AVMULHSUVV, AVMULHSUVX,
  4719  		AVDIVUVV, AVDIVUVX, AVDIVVV, AVDIVVX, AVREMUVV, AVREMUVX, AVREMVV, AVREMVX,
  4720  		AVWMULVV, AVWMULVX, AVWMULUVV, AVWMULUVX, AVWMULSUVV, AVWMULSUVX, AVNSRLWV, AVNSRLWX, AVNSRAWV, AVNSRAWX,
  4721  		AVSADDUVV, AVSADDUVX, AVSADDUVI, AVSADDVV, AVSADDVX, AVSADDVI, AVSSUBUVV, AVSSUBUVX, AVSSUBVV, AVSSUBVX,
  4722  		AVAADDUVV, AVAADDUVX, AVAADDVV, AVAADDVX, AVASUBUVV, AVASUBUVX, AVASUBVV, AVASUBVX,
  4723  		AVSMULVV, AVSMULVX, AVSSRLVV, AVSSRLVX, AVSSRLVI, AVSSRAVV, AVSSRAVX, AVSSRAVI,
  4724  		AVNCLIPUWV, AVNCLIPUWX, AVNCLIPUWI, AVNCLIPWV, AVNCLIPWX, AVNCLIPWI,
  4725  		AVFADDVV, AVFADDVF, AVFSUBVV, AVFSUBVF, AVFRSUBVF,
  4726  		AVFWADDVV, AVFWADDVF, AVFWSUBVV, AVFWSUBVF, AVFWADDWV, AVFWADDWF, AVFWSUBWV, AVFWSUBWF,
  4727  		AVFMULVV, AVFMULVF, AVFDIVVV, AVFDIVVF, AVFRDIVVF, AVFWMULVV, AVFWMULVF,
  4728  		AVFMINVV, AVFMINVF, AVFMAXVV, AVFMAXVF,
  4729  		AVFSGNJVV, AVFSGNJVF, AVFSGNJNVV, AVFSGNJNVF, AVFSGNJXVV, AVFSGNJXVF,
  4730  		AVMFEQVV, AVMFEQVF, AVMFNEVV, AVMFNEVF, AVMFLTVV, AVMFLTVF, AVMFLEVV, AVMFLEVF, AVMFGTVF, AVMFGEVF,
  4731  		AVREDSUMVS, AVREDMAXUVS, AVREDMAXVS, AVREDMINUVS, AVREDMINVS, AVREDANDVS, AVREDORVS, AVREDXORVS,
  4732  		AVWREDSUMUVS, AVWREDSUMVS, AVFREDOSUMVS, AVFREDUSUMVS, AVFREDMAXVS, AVFREDMINVS, AVFWREDOSUMVS, AVFWREDUSUMVS,
  4733  		AVSLIDEUPVX, AVSLIDEDOWNVX, AVSLIDE1UPVX, AVFSLIDE1UPVF, AVSLIDE1DOWNVX, AVFSLIDE1DOWNVF,
  4734  		AVRGATHERVV, AVRGATHEREI16VV, AVRGATHERVX:
  4735  		// Set mask bit
  4736  		switch {
  4737  		case ins.rs3 == obj.REG_NONE:
  4738  			ins.funct7 |= 1 // unmasked
  4739  		case ins.rs3 != REG_V0:
  4740  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4741  		}
  4742  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), obj.REG_NONE
  4743  
  4744  	case AVFMACCVV, AVFMACCVF, AVFNMACCVV, AVFNMACCVF, AVFMSACVV, AVFMSACVF, AVFNMSACVV, AVFNMSACVF,
  4745  		AVFMADDVV, AVFMADDVF, AVFNMADDVV, AVFNMADDVF, AVFMSUBVV, AVFMSUBVF, AVFNMSUBVV, AVFNMSUBVF,
  4746  		AVFWMACCVV, AVFWMACCVF, AVFWNMACCVV, AVFWNMACCVF, AVFWMSACVV, AVFWMSACVF, AVFWNMSACVV, AVFWNMSACVF,
  4747  		AVMACCVV, AVMACCVX, AVNMSACVV, AVNMSACVX, AVMADDVV, AVMADDVX, AVNMSUBVV, AVNMSUBVX,
  4748  		AVWMACCUVV, AVWMACCUVX, AVWMACCVV, AVWMACCVX, AVWMACCSUVV, AVWMACCSUVX, AVWMACCUSVX:
  4749  		switch {
  4750  		case ins.rs3 == obj.REG_NONE:
  4751  			ins.funct7 |= 1 // unmasked
  4752  		case ins.rs3 != REG_V0:
  4753  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4754  		}
  4755  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.Reg), uint32(p.From.Reg), obj.REG_NONE
  4756  
  4757  	case AVADDVI, AVRSUBVI, AVANDVI, AVORVI, AVXORVI, AVMSEQVI, AVMSNEVI, AVMSLEUVI, AVMSLEVI, AVMSGTUVI, AVMSGTVI,
  4758  		AVSLLVI, AVSRLVI, AVSRAVI, AVNSRLWI, AVNSRAWI, AVRGATHERVI, AVSLIDEUPVI, AVSLIDEDOWNVI:
  4759  		// Set mask bit
  4760  		switch {
  4761  		case ins.rs3 == obj.REG_NONE:
  4762  			ins.funct7 |= 1 // unmasked
  4763  		case ins.rs3 != REG_V0:
  4764  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4765  		}
  4766  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), obj.REG_NONE, uint32(p.Reg), obj.REG_NONE
  4767  
  4768  	case AVZEXTVF2, AVSEXTVF2, AVZEXTVF4, AVSEXTVF4, AVZEXTVF8, AVSEXTVF8, AVFSQRTV, AVFRSQRT7V, AVFREC7V, AVFCLASSV,
  4769  		AVFCVTXUFV, AVFCVTXFV, AVFCVTRTZXUFV, AVFCVTRTZXFV, AVFCVTFXUV, AVFCVTFXV,
  4770  		AVFWCVTXUFV, AVFWCVTXFV, AVFWCVTRTZXUFV, AVFWCVTRTZXFV, AVFWCVTFXUV, AVFWCVTFXV, AVFWCVTFFV,
  4771  		AVFNCVTXUFW, AVFNCVTXFW, AVFNCVTRTZXUFW, AVFNCVTRTZXFW, AVFNCVTFXUW, AVFNCVTFXW, AVFNCVTFFW, AVFNCVTRODFFW:
  4772  		// Set mask bit
  4773  		switch {
  4774  		case ins.rs1 == obj.REG_NONE:
  4775  			ins.funct7 |= 1 // unmasked
  4776  		case ins.rs1 != REG_V0:
  4777  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4778  		}
  4779  		ins.rs1 = obj.REG_NONE
  4780  
  4781  	case AVMVVV, AVMVVX:
  4782  		if ins.rs1 != obj.REG_NONE {
  4783  			p.Ctxt.Diag("%v: too many operands for instruction", p)
  4784  		}
  4785  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), REG_V0
  4786  
  4787  	case AVMVVI:
  4788  		if ins.rs1 != obj.REG_NONE {
  4789  			p.Ctxt.Diag("%v: too many operands for instruction", p)
  4790  		}
  4791  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), obj.REG_NONE, REG_V0
  4792  
  4793  	case AVFMVVF:
  4794  		ins.funct7 |= 1 // unmasked
  4795  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), REG_V0
  4796  
  4797  	case AVADCVIM, AVADCVVM, AVADCVXM, AVSBCVVM, AVSBCVXM:
  4798  		if ins.rd == REG_V0 {
  4799  			p.Ctxt.Diag("%v: invalid destination register V0", p)
  4800  		}
  4801  		fallthrough
  4802  
  4803  	case AVMADCVVM, AVMADCVXM, AVMSBCVVM, AVMSBCVXM, AVMADCVIM, AVMERGEVVM, AVMERGEVXM, AVMERGEVIM, AVFMERGEVFM:
  4804  		if ins.rs3 != REG_V0 {
  4805  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4806  		}
  4807  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), obj.REG_NONE
  4808  
  4809  	case AVMADCVV, AVMADCVX, AVMSBCVV, AVMSBCVX, AVMADCVI:
  4810  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)
  4811  
  4812  	case AVNEGV, AVWCVTXXV, AVWCVTUXXV, AVNCVTXXW:
  4813  		// Set mask bit
  4814  		switch {
  4815  		case ins.rs1 == obj.REG_NONE:
  4816  			ins.funct7 |= 1 // unmasked
  4817  		case ins.rs1 != REG_V0:
  4818  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4819  		}
  4820  		switch ins.as {
  4821  		case AVNEGV:
  4822  			ins.as = AVRSUBVX
  4823  		case AVWCVTXXV:
  4824  			ins.as = AVWADDVX
  4825  		case AVWCVTUXXV:
  4826  			ins.as = AVWADDUVX
  4827  		case AVNCVTXXW:
  4828  			ins.as = AVNSRLWX
  4829  		}
  4830  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), REG_X0, uint32(p.From.Reg)
  4831  
  4832  	case AVNOTV:
  4833  		// Set mask bit
  4834  		switch {
  4835  		case ins.rs1 == obj.REG_NONE:
  4836  			ins.funct7 |= 1 // unmasked
  4837  		case ins.rs1 != REG_V0:
  4838  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4839  		}
  4840  		ins.as = AVXORVI
  4841  		ins.rd, ins.rs1, ins.rs2, ins.imm = uint32(p.To.Reg), obj.REG_NONE, uint32(p.From.Reg), -1
  4842  
  4843  	case AVMSGTVV, AVMSGTUVV, AVMSGEVV, AVMSGEUVV, AVMFGTVV, AVMFGEVV:
  4844  		// Set mask bit
  4845  		switch {
  4846  		case ins.rs3 == obj.REG_NONE:
  4847  			ins.funct7 |= 1 // unmasked
  4848  		case ins.rs3 != REG_V0:
  4849  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4850  		}
  4851  		switch ins.as {
  4852  		case AVMSGTVV:
  4853  			ins.as = AVMSLTVV
  4854  		case AVMSGTUVV:
  4855  			ins.as = AVMSLTUVV
  4856  		case AVMSGEVV:
  4857  			ins.as = AVMSLEVV
  4858  		case AVMSGEUVV:
  4859  			ins.as = AVMSLEUVV
  4860  		case AVMFGTVV:
  4861  			ins.as = AVMFLTVV
  4862  		case AVMFGEVV:
  4863  			ins.as = AVMFLEVV
  4864  		}
  4865  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.Reg), uint32(p.From.Reg), obj.REG_NONE
  4866  
  4867  	case AVMSLTVI, AVMSLTUVI, AVMSGEVI, AVMSGEUVI:
  4868  		// Set mask bit
  4869  		switch {
  4870  		case ins.rs3 == obj.REG_NONE:
  4871  			ins.funct7 |= 1 // unmasked
  4872  		case ins.rs3 != REG_V0:
  4873  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4874  		}
  4875  		switch ins.as {
  4876  		case AVMSLTVI:
  4877  			ins.as = AVMSLEVI
  4878  		case AVMSLTUVI:
  4879  			ins.as = AVMSLEUVI
  4880  		case AVMSGEVI:
  4881  			ins.as = AVMSGTVI
  4882  		case AVMSGEUVI:
  4883  			ins.as = AVMSGTUVI
  4884  		}
  4885  		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
  4886  
  4887  	case AVFABSV, AVFNEGV:
  4888  		// Set mask bit
  4889  		switch {
  4890  		case ins.rs1 == obj.REG_NONE:
  4891  			ins.funct7 |= 1 // unmasked
  4892  		case ins.rs1 != REG_V0:
  4893  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4894  		}
  4895  		switch ins.as {
  4896  		case AVFABSV:
  4897  			ins.as = AVFSGNJXVV
  4898  		case AVFNEGV:
  4899  			ins.as = AVFSGNJNVV
  4900  		}
  4901  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.From.Reg)
  4902  
  4903  	case AVMANDMM, AVMNANDMM, AVMANDNMM, AVMXORMM, AVMORMM, AVMNORMM, AVMORNMM, AVMXNORMM, AVMMVM, AVMNOTM, AVCOMPRESSVM:
  4904  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)
  4905  		switch ins.as {
  4906  		case AVMMVM:
  4907  			ins.as, ins.rs2 = AVMANDMM, ins.rs1
  4908  		case AVMNOTM:
  4909  			ins.as, ins.rs2 = AVMNANDMM, ins.rs1
  4910  		}
  4911  
  4912  	case AVMCLRM, AVMSETM:
  4913  		ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.From.Reg), uint32(p.From.Reg)
  4914  		switch ins.as {
  4915  		case AVMCLRM:
  4916  			ins.as = AVMXORMM
  4917  		case AVMSETM:
  4918  			ins.as = AVMXNORMM
  4919  		}
  4920  
  4921  	case AVCPOPM, AVFIRSTM, AVMSBFM, AVMSIFM, AVMSOFM, AVIOTAM:
  4922  		// Set mask bit
  4923  		switch {
  4924  		case ins.rs1 == obj.REG_NONE:
  4925  			ins.funct7 |= 1 // unmasked
  4926  		case ins.rs1 != REG_V0:
  4927  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4928  		}
  4929  		ins.rs1 = obj.REG_NONE
  4930  
  4931  	case AVIDV:
  4932  		// Set mask bit
  4933  		switch {
  4934  		case ins.rd == obj.REG_NONE:
  4935  			ins.funct7 |= 1 // unmasked
  4936  		case ins.rd != obj.REG_NONE && ins.rs2 != REG_V0:
  4937  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4938  		}
  4939  		if ins.rd == obj.REG_NONE {
  4940  			ins.rd = uint32(p.From.Reg)
  4941  		}
  4942  		ins.rs1, ins.rs2 = obj.REG_NONE, REG_V0
  4943  	}
  4944  
  4945  	// Only compress instructions when there is no relocation, since
  4946  	// relocation relies on knowledge about the exact instructions that
  4947  	// are in use.
  4948  	if compress && p.Mark&NEED_RELOC == 0 {
  4949  		for _, ins := range inss {
  4950  			ins.compress()
  4951  		}
  4952  	}
  4953  
  4954  	for _, ins := range inss {
  4955  		ins.p = p
  4956  	}
  4957  
  4958  	return inss
  4959  }
  4960  
  4961  // assemble emits machine code.
  4962  // It is called at the very end of the assembly process.
  4963  func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
  4964  	if ctxt.Retpoline {
  4965  		ctxt.Diag("-spectre=ret not supported on riscv")
  4966  		ctxt.Retpoline = false // don't keep printing
  4967  	}
  4968  
  4969  	// If errors were encountered during preprocess/validation, proceeding
  4970  	// and attempting to encode said instructions will only lead to panics.
  4971  	if ctxt.Errors > 0 {
  4972  		return
  4973  	}
  4974  
  4975  	for p := cursym.Func().Text; p != nil; p = p.Link {
  4976  		switch p.As {
  4977  		case AJAL:
  4978  			if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC {
  4979  				cursym.AddRel(ctxt, obj.Reloc{
  4980  					Type: objabi.R_RISCV_JAL,
  4981  					Off:  int32(p.Pc),
  4982  					Siz:  4,
  4983  					Sym:  p.To.Sym,
  4984  					Add:  p.To.Offset,
  4985  				})
  4986  			}
  4987  
  4988  		case ACJALR, AJALR:
  4989  			if p.To.Sym != nil {
  4990  				ctxt.Diag("%v: unexpected AJALR with to symbol", p)
  4991  			}
  4992  
  4993  		case AAUIPC, AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
  4994  			var addr *obj.Addr
  4995  			var rt objabi.RelocType
  4996  			if p.Mark&NEED_CALL_RELOC == NEED_CALL_RELOC {
  4997  				rt = objabi.R_RISCV_CALL
  4998  				addr = &p.From
  4999  			} else if p.Mark&NEED_PCREL_ITYPE_RELOC == NEED_PCREL_ITYPE_RELOC {
  5000  				rt = objabi.R_RISCV_PCREL_ITYPE
  5001  				addr = &p.From
  5002  			} else if p.Mark&NEED_PCREL_STYPE_RELOC == NEED_PCREL_STYPE_RELOC {
  5003  				rt = objabi.R_RISCV_PCREL_STYPE
  5004  				addr = &p.To
  5005  			} else if p.Mark&NEED_GOT_PCREL_ITYPE_RELOC == NEED_GOT_PCREL_ITYPE_RELOC {
  5006  				rt = objabi.R_RISCV_GOT_PCREL_ITYPE
  5007  				addr = &p.From
  5008  			} else {
  5009  				break
  5010  			}
  5011  			if p.As == AAUIPC {
  5012  				if p.Link == nil {
  5013  					ctxt.Diag("AUIPC needing PC-relative reloc missing following instruction")
  5014  					break
  5015  				}
  5016  				addr = &p.RestArgs[0].Addr
  5017  			}
  5018  			if addr.Sym == nil {
  5019  				ctxt.Diag("PC-relative relocation missing symbol")
  5020  				break
  5021  			}
  5022  			if addr.Sym.Type == objabi.STLSBSS {
  5023  				if ctxt.Flag_shared {
  5024  					rt = objabi.R_RISCV_TLS_IE
  5025  				} else {
  5026  					rt = objabi.R_RISCV_TLS_LE
  5027  				}
  5028  			}
  5029  
  5030  			cursym.AddRel(ctxt, obj.Reloc{
  5031  				Type: rt,
  5032  				Off:  int32(p.Pc),
  5033  				Siz:  8,
  5034  				Sym:  addr.Sym,
  5035  				Add:  addr.Offset,
  5036  			})
  5037  
  5038  		case obj.APCALIGN:
  5039  			alignedValue := p.From.Offset
  5040  			v := pcAlignPadLength(p.Pc, alignedValue)
  5041  			offset := p.Pc
  5042  			for ; v >= 4; v -= 4 {
  5043  				// NOP (ADDI $0, X0, X0)
  5044  				cursym.WriteBytes(ctxt, offset, []byte{0x13, 0x00, 0x00, 0x00})
  5045  				offset += 4
  5046  			}
  5047  			if v == 2 {
  5048  				// CNOP
  5049  				cursym.WriteBytes(ctxt, offset, []byte{0x01, 0x00})
  5050  				offset += 2
  5051  			} else if v != 0 {
  5052  				ctxt.Diag("bad PCALIGN pad length")
  5053  			}
  5054  			continue
  5055  		}
  5056  
  5057  		offset := p.Pc
  5058  		for _, ins := range instructionsForProg(p, ctxt.CompressInstructions) {
  5059  			if ic, err := ins.encode(); err == nil {
  5060  				cursym.WriteInt(ctxt, offset, ins.length(), int64(ic))
  5061  				offset += int64(ins.length())
  5062  			}
  5063  			if ins.usesRegTmp() {
  5064  				p.Mark |= USES_REG_TMP
  5065  			}
  5066  		}
  5067  	}
  5068  
  5069  	obj.MarkUnsafePoints(ctxt, cursym.Func().Text, newprog, isUnsafePoint, nil)
  5070  }
  5071  
  5072  func isUnsafePoint(p *obj.Prog) bool {
  5073  	return p.Mark&USES_REG_TMP == USES_REG_TMP || p.From.Reg == REG_TMP || p.To.Reg == REG_TMP || p.Reg == REG_TMP
  5074  }
  5075  
  5076  func ParseSuffix(prog *obj.Prog, cond string) (err error) {
  5077  	cond = strings.TrimPrefix(cond, ".")
  5078  	switch prog.As {
  5079  	case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
  5080  		prog.Scond, err = rmSuffixEncode(cond)
  5081  	case AFENCE:
  5082  		if cond == "TSO" {
  5083  			prog.Scond = fenceTsoSuffixBit
  5084  		} else {
  5085  			err = fmt.Errorf("unrecognized suffix .%q", cond)
  5086  		}
  5087  	default:
  5088  		if cond != "" {
  5089  			err = fmt.Errorf("unrecognized suffix .%q", cond)
  5090  		}
  5091  	}
  5092  	return
  5093  }
  5094  
  5095  var LinkRISCV64 = obj.LinkArch{
  5096  	Arch:           sys.ArchRISCV64,
  5097  	Init:           buildop,
  5098  	Preprocess:     preprocess,
  5099  	Assemble:       assemble,
  5100  	Progedit:       progedit,
  5101  	UnaryDst:       unaryDst,
  5102  	DWARFRegisters: RISCV64DWARFRegisters,
  5103  }
  5104  

View as plain text