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  	// 6.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  	// 11.1: Integer Conditional Operations (Zicond)
  2428  	ACZERONEZ & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2429  	ACZEROEQZ & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2430  
  2431  	// 12.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  	// 13.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  	// 13.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  	// 21.5: Single-Precision Load and Store Instructions
  2473  	AFLW & obj.AMask: {enc: iFEncoding},
  2474  	AFSW & obj.AMask: {enc: sFEncoding},
  2475  
  2476  	// 21.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  	// 21.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  	// 21.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  	// 21.9: Single-Precision Floating-Point Classify Instruction
  2510  	AFCLASSS & obj.AMask: {enc: rFIEncoding},
  2511  
  2512  	// 22.3: Double-Precision Load and Store Instructions
  2513  	AFLD & obj.AMask: {enc: iFEncoding},
  2514  	AFSD & obj.AMask: {enc: sFEncoding},
  2515  
  2516  	// 22.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  	// 22.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  	// 22.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  	// 22.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  	// 28.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  	// 28.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  	// 28.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  	// 28.5.1: Compressed Integer Constant-Generation Instructions
  2582  	ACLI & obj.AMask:  {enc: ciEncoding},
  2583  	ACLUI & obj.AMask: {enc: ciEncoding},
  2584  
  2585  	// 28.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  	// 28.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  	// 28.5.5: Compressed NOP Instruction
  2606  	ACNOP & obj.AMask: {enc: ciEncoding},
  2607  
  2608  	// 28.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  	// 30.2: 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  	// 30.3: 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  	AROL & obj.AMask:   {enc: rIIIEncoding, ternary: true},
  2643  	AROLW & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2644  	AROR & obj.AMask:   {enc: rIIIEncoding, immForm: ARORI, ternary: true},
  2645  	ARORI & obj.AMask:  {enc: iIIEncoding, ternary: true},
  2646  	ARORIW & obj.AMask: {enc: iIIEncoding, ternary: true},
  2647  	ARORW & obj.AMask:  {enc: rIIIEncoding, immForm: ARORIW, ternary: true},
  2648  	AORCB & obj.AMask:  {enc: rIIEncoding},
  2649  	AREV8 & obj.AMask:  {enc: rIIEncoding},
  2650  
  2651  	// 30.4: Carry-less Multiplication (Zbc)
  2652  	ACLMUL & obj.AMask:  {enc: rIIIEncoding, ternary: true},
  2653  	ACLMULH & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2654  	ACLMULR & obj.AMask: {enc: rIIIEncoding, ternary: true},
  2655  
  2656  	// 30.5: Single-bit Instructions (Zbs)
  2657  	ABCLR & obj.AMask:  {enc: rIIIEncoding, immForm: ABCLRI, ternary: true},
  2658  	ABCLRI & obj.AMask: {enc: iIIEncoding, ternary: true},
  2659  	ABEXT & obj.AMask:  {enc: rIIIEncoding, immForm: ABEXTI, ternary: true},
  2660  	ABEXTI & obj.AMask: {enc: iIIEncoding, ternary: true},
  2661  	ABINV & obj.AMask:  {enc: rIIIEncoding, immForm: ABINVI, ternary: true},
  2662  	ABINVI & obj.AMask: {enc: iIIEncoding, ternary: true},
  2663  	ABSET & obj.AMask:  {enc: rIIIEncoding, immForm: ABSETI, ternary: true},
  2664  	ABSETI & obj.AMask: {enc: iIIEncoding, ternary: true},
  2665  
  2666  	//
  2667  	// "V" Standard Extension for Vector Operations, Version 1.0
  2668  	//
  2669  
  2670  	// 31.6: Vector Configuration-Setting Instructions
  2671  	AVSETVLI & obj.AMask:  {enc: vsetvliEncoding, immForm: AVSETIVLI},
  2672  	AVSETIVLI & obj.AMask: {enc: vsetivliEncoding},
  2673  	AVSETVL & obj.AMask:   {enc: vsetvlEncoding},
  2674  
  2675  	// 31.7.4: Vector Unit-Stride Instructions
  2676  	AVLE8V & obj.AMask:  {enc: iVEncoding},
  2677  	AVLE16V & obj.AMask: {enc: iVEncoding},
  2678  	AVLE32V & obj.AMask: {enc: iVEncoding},
  2679  	AVLE64V & obj.AMask: {enc: iVEncoding},
  2680  	AVSE8V & obj.AMask:  {enc: sVEncoding},
  2681  	AVSE16V & obj.AMask: {enc: sVEncoding},
  2682  	AVSE32V & obj.AMask: {enc: sVEncoding},
  2683  	AVSE64V & obj.AMask: {enc: sVEncoding},
  2684  	AVLMV & obj.AMask:   {enc: iVEncoding},
  2685  	AVSMV & obj.AMask:   {enc: sVEncoding},
  2686  
  2687  	// 31.7.5: Vector Constant-Stride Instructions
  2688  	AVLSE8V & obj.AMask:  {enc: iIIVEncoding},
  2689  	AVLSE16V & obj.AMask: {enc: iIIVEncoding},
  2690  	AVLSE32V & obj.AMask: {enc: iIIVEncoding},
  2691  	AVLSE64V & obj.AMask: {enc: iIIVEncoding},
  2692  	AVSSE8V & obj.AMask:  {enc: sVIIEncoding},
  2693  	AVSSE16V & obj.AMask: {enc: sVIIEncoding},
  2694  	AVSSE32V & obj.AMask: {enc: sVIIEncoding},
  2695  	AVSSE64V & obj.AMask: {enc: sVIIEncoding},
  2696  
  2697  	// 31.7.6: Vector Indexed Instructions
  2698  	AVLUXEI8V & obj.AMask:  {enc: iVIVEncoding},
  2699  	AVLUXEI16V & obj.AMask: {enc: iVIVEncoding},
  2700  	AVLUXEI32V & obj.AMask: {enc: iVIVEncoding},
  2701  	AVLUXEI64V & obj.AMask: {enc: iVIVEncoding},
  2702  	AVLOXEI8V & obj.AMask:  {enc: iVIVEncoding},
  2703  	AVLOXEI16V & obj.AMask: {enc: iVIVEncoding},
  2704  	AVLOXEI32V & obj.AMask: {enc: iVIVEncoding},
  2705  	AVLOXEI64V & obj.AMask: {enc: iVIVEncoding},
  2706  	AVSUXEI8V & obj.AMask:  {enc: sVIVEncoding},
  2707  	AVSUXEI16V & obj.AMask: {enc: sVIVEncoding},
  2708  	AVSUXEI32V & obj.AMask: {enc: sVIVEncoding},
  2709  	AVSUXEI64V & obj.AMask: {enc: sVIVEncoding},
  2710  	AVSOXEI8V & obj.AMask:  {enc: sVIVEncoding},
  2711  	AVSOXEI16V & obj.AMask: {enc: sVIVEncoding},
  2712  	AVSOXEI32V & obj.AMask: {enc: sVIVEncoding},
  2713  	AVSOXEI64V & obj.AMask: {enc: sVIVEncoding},
  2714  
  2715  	// 31.7.7: Vector Unit-Stride Fault-Only-First Loads
  2716  	AVLE8FFV & obj.AMask:  {enc: iVEncoding},
  2717  	AVLE16FFV & obj.AMask: {enc: iVEncoding},
  2718  	AVLE32FFV & obj.AMask: {enc: iVEncoding},
  2719  	AVLE64FFV & obj.AMask: {enc: iVEncoding},
  2720  
  2721  	// 31.7.8.1: Vector Unit-Stride Segment Loads and Stores
  2722  	AVLSEG2E8V & obj.AMask:    {enc: iVEncoding},
  2723  	AVLSEG3E8V & obj.AMask:    {enc: iVEncoding},
  2724  	AVLSEG4E8V & obj.AMask:    {enc: iVEncoding},
  2725  	AVLSEG5E8V & obj.AMask:    {enc: iVEncoding},
  2726  	AVLSEG6E8V & obj.AMask:    {enc: iVEncoding},
  2727  	AVLSEG7E8V & obj.AMask:    {enc: iVEncoding},
  2728  	AVLSEG8E8V & obj.AMask:    {enc: iVEncoding},
  2729  	AVLSEG2E16V & obj.AMask:   {enc: iVEncoding},
  2730  	AVLSEG3E16V & obj.AMask:   {enc: iVEncoding},
  2731  	AVLSEG4E16V & obj.AMask:   {enc: iVEncoding},
  2732  	AVLSEG5E16V & obj.AMask:   {enc: iVEncoding},
  2733  	AVLSEG6E16V & obj.AMask:   {enc: iVEncoding},
  2734  	AVLSEG7E16V & obj.AMask:   {enc: iVEncoding},
  2735  	AVLSEG8E16V & obj.AMask:   {enc: iVEncoding},
  2736  	AVLSEG2E32V & obj.AMask:   {enc: iVEncoding},
  2737  	AVLSEG3E32V & obj.AMask:   {enc: iVEncoding},
  2738  	AVLSEG4E32V & obj.AMask:   {enc: iVEncoding},
  2739  	AVLSEG5E32V & obj.AMask:   {enc: iVEncoding},
  2740  	AVLSEG6E32V & obj.AMask:   {enc: iVEncoding},
  2741  	AVLSEG7E32V & obj.AMask:   {enc: iVEncoding},
  2742  	AVLSEG8E32V & obj.AMask:   {enc: iVEncoding},
  2743  	AVLSEG2E64V & obj.AMask:   {enc: iVEncoding},
  2744  	AVLSEG3E64V & obj.AMask:   {enc: iVEncoding},
  2745  	AVLSEG4E64V & obj.AMask:   {enc: iVEncoding},
  2746  	AVLSEG5E64V & obj.AMask:   {enc: iVEncoding},
  2747  	AVLSEG6E64V & obj.AMask:   {enc: iVEncoding},
  2748  	AVLSEG7E64V & obj.AMask:   {enc: iVEncoding},
  2749  	AVLSEG8E64V & obj.AMask:   {enc: iVEncoding},
  2750  	AVSSEG2E8V & obj.AMask:    {enc: sVEncoding},
  2751  	AVSSEG3E8V & obj.AMask:    {enc: sVEncoding},
  2752  	AVSSEG4E8V & obj.AMask:    {enc: sVEncoding},
  2753  	AVSSEG5E8V & obj.AMask:    {enc: sVEncoding},
  2754  	AVSSEG6E8V & obj.AMask:    {enc: sVEncoding},
  2755  	AVSSEG7E8V & obj.AMask:    {enc: sVEncoding},
  2756  	AVSSEG8E8V & obj.AMask:    {enc: sVEncoding},
  2757  	AVSSEG2E16V & obj.AMask:   {enc: sVEncoding},
  2758  	AVSSEG3E16V & obj.AMask:   {enc: sVEncoding},
  2759  	AVSSEG4E16V & obj.AMask:   {enc: sVEncoding},
  2760  	AVSSEG5E16V & obj.AMask:   {enc: sVEncoding},
  2761  	AVSSEG6E16V & obj.AMask:   {enc: sVEncoding},
  2762  	AVSSEG7E16V & obj.AMask:   {enc: sVEncoding},
  2763  	AVSSEG8E16V & obj.AMask:   {enc: sVEncoding},
  2764  	AVSSEG2E32V & obj.AMask:   {enc: sVEncoding},
  2765  	AVSSEG3E32V & obj.AMask:   {enc: sVEncoding},
  2766  	AVSSEG4E32V & obj.AMask:   {enc: sVEncoding},
  2767  	AVSSEG5E32V & obj.AMask:   {enc: sVEncoding},
  2768  	AVSSEG6E32V & obj.AMask:   {enc: sVEncoding},
  2769  	AVSSEG7E32V & obj.AMask:   {enc: sVEncoding},
  2770  	AVSSEG8E32V & obj.AMask:   {enc: sVEncoding},
  2771  	AVSSEG2E64V & obj.AMask:   {enc: sVEncoding},
  2772  	AVSSEG3E64V & obj.AMask:   {enc: sVEncoding},
  2773  	AVSSEG4E64V & obj.AMask:   {enc: sVEncoding},
  2774  	AVSSEG5E64V & obj.AMask:   {enc: sVEncoding},
  2775  	AVSSEG6E64V & obj.AMask:   {enc: sVEncoding},
  2776  	AVSSEG7E64V & obj.AMask:   {enc: sVEncoding},
  2777  	AVSSEG8E64V & obj.AMask:   {enc: sVEncoding},
  2778  	AVLSEG2E8FFV & obj.AMask:  {enc: iVEncoding},
  2779  	AVLSEG3E8FFV & obj.AMask:  {enc: iVEncoding},
  2780  	AVLSEG4E8FFV & obj.AMask:  {enc: iVEncoding},
  2781  	AVLSEG5E8FFV & obj.AMask:  {enc: iVEncoding},
  2782  	AVLSEG6E8FFV & obj.AMask:  {enc: iVEncoding},
  2783  	AVLSEG7E8FFV & obj.AMask:  {enc: iVEncoding},
  2784  	AVLSEG8E8FFV & obj.AMask:  {enc: iVEncoding},
  2785  	AVLSEG2E16FFV & obj.AMask: {enc: iVEncoding},
  2786  	AVLSEG3E16FFV & obj.AMask: {enc: iVEncoding},
  2787  	AVLSEG4E16FFV & obj.AMask: {enc: iVEncoding},
  2788  	AVLSEG5E16FFV & obj.AMask: {enc: iVEncoding},
  2789  	AVLSEG6E16FFV & obj.AMask: {enc: iVEncoding},
  2790  	AVLSEG7E16FFV & obj.AMask: {enc: iVEncoding},
  2791  	AVLSEG8E16FFV & obj.AMask: {enc: iVEncoding},
  2792  	AVLSEG2E32FFV & obj.AMask: {enc: iVEncoding},
  2793  	AVLSEG3E32FFV & obj.AMask: {enc: iVEncoding},
  2794  	AVLSEG4E32FFV & obj.AMask: {enc: iVEncoding},
  2795  	AVLSEG5E32FFV & obj.AMask: {enc: iVEncoding},
  2796  	AVLSEG6E32FFV & obj.AMask: {enc: iVEncoding},
  2797  	AVLSEG7E32FFV & obj.AMask: {enc: iVEncoding},
  2798  	AVLSEG8E32FFV & obj.AMask: {enc: iVEncoding},
  2799  	AVLSEG2E64FFV & obj.AMask: {enc: iVEncoding},
  2800  	AVLSEG3E64FFV & obj.AMask: {enc: iVEncoding},
  2801  	AVLSEG4E64FFV & obj.AMask: {enc: iVEncoding},
  2802  	AVLSEG5E64FFV & obj.AMask: {enc: iVEncoding},
  2803  	AVLSEG6E64FFV & obj.AMask: {enc: iVEncoding},
  2804  	AVLSEG7E64FFV & obj.AMask: {enc: iVEncoding},
  2805  	AVLSEG8E64FFV & obj.AMask: {enc: iVEncoding},
  2806  
  2807  	// 31.7.8.2: Vector Constant-Stride Segment Loads and Stores
  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  
  2865  	// 31.7.8.3: Vector Indexed Segment Loads and Stores
  2866  	AVLOXSEG2EI8V & obj.AMask:  {enc: iVIVEncoding},
  2867  	AVLOXSEG3EI8V & obj.AMask:  {enc: iVIVEncoding},
  2868  	AVLOXSEG4EI8V & obj.AMask:  {enc: iVIVEncoding},
  2869  	AVLOXSEG5EI8V & obj.AMask:  {enc: iVIVEncoding},
  2870  	AVLOXSEG6EI8V & obj.AMask:  {enc: iVIVEncoding},
  2871  	AVLOXSEG7EI8V & obj.AMask:  {enc: iVIVEncoding},
  2872  	AVLOXSEG8EI8V & obj.AMask:  {enc: iVIVEncoding},
  2873  	AVLOXSEG2EI16V & obj.AMask: {enc: iVIVEncoding},
  2874  	AVLOXSEG3EI16V & obj.AMask: {enc: iVIVEncoding},
  2875  	AVLOXSEG4EI16V & obj.AMask: {enc: iVIVEncoding},
  2876  	AVLOXSEG5EI16V & obj.AMask: {enc: iVIVEncoding},
  2877  	AVLOXSEG6EI16V & obj.AMask: {enc: iVIVEncoding},
  2878  	AVLOXSEG7EI16V & obj.AMask: {enc: iVIVEncoding},
  2879  	AVLOXSEG8EI16V & obj.AMask: {enc: iVIVEncoding},
  2880  	AVLOXSEG2EI32V & obj.AMask: {enc: iVIVEncoding},
  2881  	AVLOXSEG3EI32V & obj.AMask: {enc: iVIVEncoding},
  2882  	AVLOXSEG4EI32V & obj.AMask: {enc: iVIVEncoding},
  2883  	AVLOXSEG5EI32V & obj.AMask: {enc: iVIVEncoding},
  2884  	AVLOXSEG6EI32V & obj.AMask: {enc: iVIVEncoding},
  2885  	AVLOXSEG7EI32V & obj.AMask: {enc: iVIVEncoding},
  2886  	AVLOXSEG8EI32V & obj.AMask: {enc: iVIVEncoding},
  2887  	AVLOXSEG2EI64V & obj.AMask: {enc: iVIVEncoding},
  2888  	AVLOXSEG3EI64V & obj.AMask: {enc: iVIVEncoding},
  2889  	AVLOXSEG4EI64V & obj.AMask: {enc: iVIVEncoding},
  2890  	AVLOXSEG5EI64V & obj.AMask: {enc: iVIVEncoding},
  2891  	AVLOXSEG6EI64V & obj.AMask: {enc: iVIVEncoding},
  2892  	AVLOXSEG7EI64V & obj.AMask: {enc: iVIVEncoding},
  2893  	AVLOXSEG8EI64V & obj.AMask: {enc: iVIVEncoding},
  2894  	AVSOXSEG2EI8V & obj.AMask:  {enc: sVIVEncoding},
  2895  	AVSOXSEG3EI8V & obj.AMask:  {enc: sVIVEncoding},
  2896  	AVSOXSEG4EI8V & obj.AMask:  {enc: sVIVEncoding},
  2897  	AVSOXSEG5EI8V & obj.AMask:  {enc: sVIVEncoding},
  2898  	AVSOXSEG6EI8V & obj.AMask:  {enc: sVIVEncoding},
  2899  	AVSOXSEG7EI8V & obj.AMask:  {enc: sVIVEncoding},
  2900  	AVSOXSEG8EI8V & obj.AMask:  {enc: sVIVEncoding},
  2901  	AVSOXSEG2EI16V & obj.AMask: {enc: sVIVEncoding},
  2902  	AVSOXSEG3EI16V & obj.AMask: {enc: sVIVEncoding},
  2903  	AVSOXSEG4EI16V & obj.AMask: {enc: sVIVEncoding},
  2904  	AVSOXSEG5EI16V & obj.AMask: {enc: sVIVEncoding},
  2905  	AVSOXSEG6EI16V & obj.AMask: {enc: sVIVEncoding},
  2906  	AVSOXSEG7EI16V & obj.AMask: {enc: sVIVEncoding},
  2907  	AVSOXSEG8EI16V & obj.AMask: {enc: sVIVEncoding},
  2908  	AVSOXSEG2EI32V & obj.AMask: {enc: sVIVEncoding},
  2909  	AVSOXSEG3EI32V & obj.AMask: {enc: sVIVEncoding},
  2910  	AVSOXSEG4EI32V & obj.AMask: {enc: sVIVEncoding},
  2911  	AVSOXSEG5EI32V & obj.AMask: {enc: sVIVEncoding},
  2912  	AVSOXSEG6EI32V & obj.AMask: {enc: sVIVEncoding},
  2913  	AVSOXSEG7EI32V & obj.AMask: {enc: sVIVEncoding},
  2914  	AVSOXSEG8EI32V & obj.AMask: {enc: sVIVEncoding},
  2915  	AVSOXSEG2EI64V & obj.AMask: {enc: sVIVEncoding},
  2916  	AVSOXSEG3EI64V & obj.AMask: {enc: sVIVEncoding},
  2917  	AVSOXSEG4EI64V & obj.AMask: {enc: sVIVEncoding},
  2918  	AVSOXSEG5EI64V & obj.AMask: {enc: sVIVEncoding},
  2919  	AVSOXSEG6EI64V & obj.AMask: {enc: sVIVEncoding},
  2920  	AVSOXSEG7EI64V & obj.AMask: {enc: sVIVEncoding},
  2921  	AVSOXSEG8EI64V & obj.AMask: {enc: sVIVEncoding},
  2922  	AVLUXSEG2EI8V & obj.AMask:  {enc: iVIVEncoding},
  2923  	AVLUXSEG3EI8V & obj.AMask:  {enc: iVIVEncoding},
  2924  	AVLUXSEG4EI8V & obj.AMask:  {enc: iVIVEncoding},
  2925  	AVLUXSEG5EI8V & obj.AMask:  {enc: iVIVEncoding},
  2926  	AVLUXSEG6EI8V & obj.AMask:  {enc: iVIVEncoding},
  2927  	AVLUXSEG7EI8V & obj.AMask:  {enc: iVIVEncoding},
  2928  	AVLUXSEG8EI8V & obj.AMask:  {enc: iVIVEncoding},
  2929  	AVLUXSEG2EI16V & obj.AMask: {enc: iVIVEncoding},
  2930  	AVLUXSEG3EI16V & obj.AMask: {enc: iVIVEncoding},
  2931  	AVLUXSEG4EI16V & obj.AMask: {enc: iVIVEncoding},
  2932  	AVLUXSEG5EI16V & obj.AMask: {enc: iVIVEncoding},
  2933  	AVLUXSEG6EI16V & obj.AMask: {enc: iVIVEncoding},
  2934  	AVLUXSEG7EI16V & obj.AMask: {enc: iVIVEncoding},
  2935  	AVLUXSEG8EI16V & obj.AMask: {enc: iVIVEncoding},
  2936  	AVLUXSEG2EI32V & obj.AMask: {enc: iVIVEncoding},
  2937  	AVLUXSEG3EI32V & obj.AMask: {enc: iVIVEncoding},
  2938  	AVLUXSEG4EI32V & obj.AMask: {enc: iVIVEncoding},
  2939  	AVLUXSEG5EI32V & obj.AMask: {enc: iVIVEncoding},
  2940  	AVLUXSEG6EI32V & obj.AMask: {enc: iVIVEncoding},
  2941  	AVLUXSEG7EI32V & obj.AMask: {enc: iVIVEncoding},
  2942  	AVLUXSEG8EI32V & obj.AMask: {enc: iVIVEncoding},
  2943  	AVLUXSEG2EI64V & obj.AMask: {enc: iVIVEncoding},
  2944  	AVLUXSEG3EI64V & obj.AMask: {enc: iVIVEncoding},
  2945  	AVLUXSEG4EI64V & obj.AMask: {enc: iVIVEncoding},
  2946  	AVLUXSEG5EI64V & obj.AMask: {enc: iVIVEncoding},
  2947  	AVLUXSEG6EI64V & obj.AMask: {enc: iVIVEncoding},
  2948  	AVLUXSEG7EI64V & obj.AMask: {enc: iVIVEncoding},
  2949  	AVLUXSEG8EI64V & obj.AMask: {enc: iVIVEncoding},
  2950  	AVSUXSEG2EI8V & obj.AMask:  {enc: sVIVEncoding},
  2951  	AVSUXSEG3EI8V & obj.AMask:  {enc: sVIVEncoding},
  2952  	AVSUXSEG4EI8V & obj.AMask:  {enc: sVIVEncoding},
  2953  	AVSUXSEG5EI8V & obj.AMask:  {enc: sVIVEncoding},
  2954  	AVSUXSEG6EI8V & obj.AMask:  {enc: sVIVEncoding},
  2955  	AVSUXSEG7EI8V & obj.AMask:  {enc: sVIVEncoding},
  2956  	AVSUXSEG8EI8V & obj.AMask:  {enc: sVIVEncoding},
  2957  	AVSUXSEG2EI16V & obj.AMask: {enc: sVIVEncoding},
  2958  	AVSUXSEG3EI16V & obj.AMask: {enc: sVIVEncoding},
  2959  	AVSUXSEG4EI16V & obj.AMask: {enc: sVIVEncoding},
  2960  	AVSUXSEG5EI16V & obj.AMask: {enc: sVIVEncoding},
  2961  	AVSUXSEG6EI16V & obj.AMask: {enc: sVIVEncoding},
  2962  	AVSUXSEG7EI16V & obj.AMask: {enc: sVIVEncoding},
  2963  	AVSUXSEG8EI16V & obj.AMask: {enc: sVIVEncoding},
  2964  	AVSUXSEG2EI32V & obj.AMask: {enc: sVIVEncoding},
  2965  	AVSUXSEG3EI32V & obj.AMask: {enc: sVIVEncoding},
  2966  	AVSUXSEG4EI32V & obj.AMask: {enc: sVIVEncoding},
  2967  	AVSUXSEG5EI32V & obj.AMask: {enc: sVIVEncoding},
  2968  	AVSUXSEG6EI32V & obj.AMask: {enc: sVIVEncoding},
  2969  	AVSUXSEG7EI32V & obj.AMask: {enc: sVIVEncoding},
  2970  	AVSUXSEG8EI32V & obj.AMask: {enc: sVIVEncoding},
  2971  	AVSUXSEG2EI64V & obj.AMask: {enc: sVIVEncoding},
  2972  	AVSUXSEG3EI64V & obj.AMask: {enc: sVIVEncoding},
  2973  	AVSUXSEG4EI64V & obj.AMask: {enc: sVIVEncoding},
  2974  	AVSUXSEG5EI64V & obj.AMask: {enc: sVIVEncoding},
  2975  	AVSUXSEG6EI64V & obj.AMask: {enc: sVIVEncoding},
  2976  	AVSUXSEG7EI64V & obj.AMask: {enc: sVIVEncoding},
  2977  	AVSUXSEG8EI64V & obj.AMask: {enc: sVIVEncoding},
  2978  
  2979  	// 31.7.9: Vector Load/Store Whole Register Instructions
  2980  	AVL1RE8V & obj.AMask:  {enc: iVEncoding},
  2981  	AVL1RE16V & obj.AMask: {enc: iVEncoding},
  2982  	AVL1RE32V & obj.AMask: {enc: iVEncoding},
  2983  	AVL1RE64V & obj.AMask: {enc: iVEncoding},
  2984  	AVL2RE8V & obj.AMask:  {enc: iVEncoding},
  2985  	AVL2RE16V & obj.AMask: {enc: iVEncoding},
  2986  	AVL2RE32V & obj.AMask: {enc: iVEncoding},
  2987  	AVL2RE64V & obj.AMask: {enc: iVEncoding},
  2988  	AVL4RE8V & obj.AMask:  {enc: iVEncoding},
  2989  	AVL4RE16V & obj.AMask: {enc: iVEncoding},
  2990  	AVL4RE32V & obj.AMask: {enc: iVEncoding},
  2991  	AVL4RE64V & obj.AMask: {enc: iVEncoding},
  2992  	AVL8RE8V & obj.AMask:  {enc: iVEncoding},
  2993  	AVL8RE16V & obj.AMask: {enc: iVEncoding},
  2994  	AVL8RE32V & obj.AMask: {enc: iVEncoding},
  2995  	AVL8RE64V & obj.AMask: {enc: iVEncoding},
  2996  	AVS1RV & obj.AMask:    {enc: sVEncoding},
  2997  	AVS2RV & obj.AMask:    {enc: sVEncoding},
  2998  	AVS4RV & obj.AMask:    {enc: sVEncoding},
  2999  	AVS8RV & obj.AMask:    {enc: sVEncoding},
  3000  
  3001  	// 31.11.1: Vector Single-Width Integer Add and Subtract
  3002  	AVADDVV & obj.AMask:  {enc: rVVVEncoding},
  3003  	AVADDVX & obj.AMask:  {enc: rVIVEncoding},
  3004  	AVADDVI & obj.AMask:  {enc: rVViEncoding},
  3005  	AVSUBVV & obj.AMask:  {enc: rVVVEncoding},
  3006  	AVSUBVX & obj.AMask:  {enc: rVIVEncoding},
  3007  	AVRSUBVX & obj.AMask: {enc: rVIVEncoding},
  3008  	AVRSUBVI & obj.AMask: {enc: rVViEncoding},
  3009  
  3010  	// 31.11.2: Vector Widening Integer Add/Subtract
  3011  	AVWADDUVV & obj.AMask: {enc: rVVVEncoding},
  3012  	AVWADDUVX & obj.AMask: {enc: rVIVEncoding},
  3013  	AVWSUBUVV & obj.AMask: {enc: rVVVEncoding},
  3014  	AVWSUBUVX & obj.AMask: {enc: rVIVEncoding},
  3015  	AVWADDVV & obj.AMask:  {enc: rVVVEncoding},
  3016  	AVWADDVX & obj.AMask:  {enc: rVIVEncoding},
  3017  	AVWSUBVV & obj.AMask:  {enc: rVVVEncoding},
  3018  	AVWSUBVX & obj.AMask:  {enc: rVIVEncoding},
  3019  	AVWADDUWV & obj.AMask: {enc: rVVVEncoding},
  3020  	AVWADDUWX & obj.AMask: {enc: rVIVEncoding},
  3021  	AVWSUBUWV & obj.AMask: {enc: rVVVEncoding},
  3022  	AVWSUBUWX & obj.AMask: {enc: rVIVEncoding},
  3023  	AVWADDWV & obj.AMask:  {enc: rVVVEncoding},
  3024  	AVWADDWX & obj.AMask:  {enc: rVIVEncoding},
  3025  	AVWSUBWV & obj.AMask:  {enc: rVVVEncoding},
  3026  	AVWSUBWX & obj.AMask:  {enc: rVIVEncoding},
  3027  
  3028  	// 31.11.3: Vector Integer Extension
  3029  	AVZEXTVF2 & obj.AMask: {enc: rVVEncoding},
  3030  	AVSEXTVF2 & obj.AMask: {enc: rVVEncoding},
  3031  	AVZEXTVF4 & obj.AMask: {enc: rVVEncoding},
  3032  	AVSEXTVF4 & obj.AMask: {enc: rVVEncoding},
  3033  	AVZEXTVF8 & obj.AMask: {enc: rVVEncoding},
  3034  	AVSEXTVF8 & obj.AMask: {enc: rVVEncoding},
  3035  
  3036  	// 31.11.4: Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions
  3037  	AVADCVVM & obj.AMask:  {enc: rVVVEncoding},
  3038  	AVADCVXM & obj.AMask:  {enc: rVIVEncoding},
  3039  	AVADCVIM & obj.AMask:  {enc: rVViEncoding},
  3040  	AVMADCVVM & obj.AMask: {enc: rVVVEncoding},
  3041  	AVMADCVXM & obj.AMask: {enc: rVIVEncoding},
  3042  	AVMADCVIM & obj.AMask: {enc: rVViEncoding},
  3043  	AVMADCVV & obj.AMask:  {enc: rVVVEncoding},
  3044  	AVMADCVX & obj.AMask:  {enc: rVIVEncoding},
  3045  	AVMADCVI & obj.AMask:  {enc: rVViEncoding},
  3046  	AVSBCVVM & obj.AMask:  {enc: rVVVEncoding},
  3047  	AVSBCVXM & obj.AMask:  {enc: rVIVEncoding},
  3048  	AVMSBCVVM & obj.AMask: {enc: rVVVEncoding},
  3049  	AVMSBCVXM & obj.AMask: {enc: rVIVEncoding},
  3050  	AVMSBCVV & obj.AMask:  {enc: rVVVEncoding},
  3051  	AVMSBCVX & obj.AMask:  {enc: rVIVEncoding},
  3052  
  3053  	// 31.11.5: Vector Bitwise Logical Instructions
  3054  	AVANDVV & obj.AMask: {enc: rVVVEncoding},
  3055  	AVANDVX & obj.AMask: {enc: rVIVEncoding},
  3056  	AVANDVI & obj.AMask: {enc: rVViEncoding},
  3057  	AVORVV & obj.AMask:  {enc: rVVVEncoding},
  3058  	AVORVX & obj.AMask:  {enc: rVIVEncoding},
  3059  	AVORVI & obj.AMask:  {enc: rVViEncoding},
  3060  	AVXORVV & obj.AMask: {enc: rVVVEncoding},
  3061  	AVXORVX & obj.AMask: {enc: rVIVEncoding},
  3062  	AVXORVI & obj.AMask: {enc: rVViEncoding},
  3063  
  3064  	// 31.11.6: Vector Single-Width Shift Instructions
  3065  	AVSLLVV & obj.AMask: {enc: rVVVEncoding},
  3066  	AVSLLVX & obj.AMask: {enc: rVIVEncoding},
  3067  	AVSLLVI & obj.AMask: {enc: rVVuEncoding},
  3068  	AVSRLVV & obj.AMask: {enc: rVVVEncoding},
  3069  	AVSRLVX & obj.AMask: {enc: rVIVEncoding},
  3070  	AVSRLVI & obj.AMask: {enc: rVVuEncoding},
  3071  	AVSRAVV & obj.AMask: {enc: rVVVEncoding},
  3072  	AVSRAVX & obj.AMask: {enc: rVIVEncoding},
  3073  	AVSRAVI & obj.AMask: {enc: rVVuEncoding},
  3074  
  3075  	// 31.11.7: Vector Narrowing Integer Right Shift Instructions
  3076  	AVNSRLWV & obj.AMask: {enc: rVVVEncoding},
  3077  	AVNSRLWX & obj.AMask: {enc: rVIVEncoding},
  3078  	AVNSRLWI & obj.AMask: {enc: rVVuEncoding},
  3079  	AVNSRAWV & obj.AMask: {enc: rVVVEncoding},
  3080  	AVNSRAWX & obj.AMask: {enc: rVIVEncoding},
  3081  	AVNSRAWI & obj.AMask: {enc: rVVuEncoding},
  3082  
  3083  	// 31.11.8: Vector Integer Compare Instructions
  3084  	AVMSEQVV & obj.AMask:  {enc: rVVVEncoding},
  3085  	AVMSEQVX & obj.AMask:  {enc: rVIVEncoding},
  3086  	AVMSEQVI & obj.AMask:  {enc: rVViEncoding},
  3087  	AVMSNEVV & obj.AMask:  {enc: rVVVEncoding},
  3088  	AVMSNEVX & obj.AMask:  {enc: rVIVEncoding},
  3089  	AVMSNEVI & obj.AMask:  {enc: rVViEncoding},
  3090  	AVMSLTUVV & obj.AMask: {enc: rVVVEncoding},
  3091  	AVMSLTUVX & obj.AMask: {enc: rVIVEncoding},
  3092  	AVMSLTVV & obj.AMask:  {enc: rVVVEncoding},
  3093  	AVMSLTVX & obj.AMask:  {enc: rVIVEncoding},
  3094  	AVMSLEUVV & obj.AMask: {enc: rVVVEncoding},
  3095  	AVMSLEUVX & obj.AMask: {enc: rVIVEncoding},
  3096  	AVMSLEUVI & obj.AMask: {enc: rVViEncoding},
  3097  	AVMSLEVV & obj.AMask:  {enc: rVVVEncoding},
  3098  	AVMSLEVX & obj.AMask:  {enc: rVIVEncoding},
  3099  	AVMSLEVI & obj.AMask:  {enc: rVViEncoding},
  3100  	AVMSGTUVX & obj.AMask: {enc: rVIVEncoding},
  3101  	AVMSGTUVI & obj.AMask: {enc: rVViEncoding},
  3102  	AVMSGTVX & obj.AMask:  {enc: rVIVEncoding},
  3103  	AVMSGTVI & obj.AMask:  {enc: rVViEncoding},
  3104  
  3105  	// 31.11.9: Vector Integer Min/Max Instructions
  3106  	AVMINUVV & obj.AMask: {enc: rVVVEncoding},
  3107  	AVMINUVX & obj.AMask: {enc: rVIVEncoding},
  3108  	AVMINVV & obj.AMask:  {enc: rVVVEncoding},
  3109  	AVMINVX & obj.AMask:  {enc: rVIVEncoding},
  3110  	AVMAXUVV & obj.AMask: {enc: rVVVEncoding},
  3111  	AVMAXUVX & obj.AMask: {enc: rVIVEncoding},
  3112  	AVMAXVV & obj.AMask:  {enc: rVVVEncoding},
  3113  	AVMAXVX & obj.AMask:  {enc: rVIVEncoding},
  3114  
  3115  	// 31.11.10: Vector Single-Width Integer Multiply Instructions
  3116  	AVMULVV & obj.AMask:    {enc: rVVVEncoding},
  3117  	AVMULVX & obj.AMask:    {enc: rVIVEncoding},
  3118  	AVMULHVV & obj.AMask:   {enc: rVVVEncoding},
  3119  	AVMULHVX & obj.AMask:   {enc: rVIVEncoding},
  3120  	AVMULHUVV & obj.AMask:  {enc: rVVVEncoding},
  3121  	AVMULHUVX & obj.AMask:  {enc: rVIVEncoding},
  3122  	AVMULHSUVV & obj.AMask: {enc: rVVVEncoding},
  3123  	AVMULHSUVX & obj.AMask: {enc: rVIVEncoding},
  3124  
  3125  	// 31.11.11: Vector Integer Divide Instructions
  3126  	AVDIVUVV & obj.AMask: {enc: rVVVEncoding},
  3127  	AVDIVUVX & obj.AMask: {enc: rVIVEncoding},
  3128  	AVDIVVV & obj.AMask:  {enc: rVVVEncoding},
  3129  	AVDIVVX & obj.AMask:  {enc: rVIVEncoding},
  3130  	AVREMUVV & obj.AMask: {enc: rVVVEncoding},
  3131  	AVREMUVX & obj.AMask: {enc: rVIVEncoding},
  3132  	AVREMVV & obj.AMask:  {enc: rVVVEncoding},
  3133  	AVREMVX & obj.AMask:  {enc: rVIVEncoding},
  3134  
  3135  	// 31.11.12: Vector Widening Integer Multiply Instructions
  3136  	AVWMULVV & obj.AMask:   {enc: rVVVEncoding},
  3137  	AVWMULVX & obj.AMask:   {enc: rVIVEncoding},
  3138  	AVWMULUVV & obj.AMask:  {enc: rVVVEncoding},
  3139  	AVWMULUVX & obj.AMask:  {enc: rVIVEncoding},
  3140  	AVWMULSUVV & obj.AMask: {enc: rVVVEncoding},
  3141  	AVWMULSUVX & obj.AMask: {enc: rVIVEncoding},
  3142  
  3143  	// 31.11.13: Vector Single-Width Integer Multiply-Add Instructions
  3144  	AVMACCVV & obj.AMask:  {enc: rVVVEncoding},
  3145  	AVMACCVX & obj.AMask:  {enc: rVIVEncoding},
  3146  	AVNMSACVV & obj.AMask: {enc: rVVVEncoding},
  3147  	AVNMSACVX & obj.AMask: {enc: rVIVEncoding},
  3148  	AVMADDVV & obj.AMask:  {enc: rVVVEncoding},
  3149  	AVMADDVX & obj.AMask:  {enc: rVIVEncoding},
  3150  	AVNMSUBVV & obj.AMask: {enc: rVVVEncoding},
  3151  	AVNMSUBVX & obj.AMask: {enc: rVIVEncoding},
  3152  
  3153  	// 31.11.14: Vector Widening Integer Multiply-Add Instructions
  3154  	AVWMACCUVV & obj.AMask:  {enc: rVVVEncoding},
  3155  	AVWMACCUVX & obj.AMask:  {enc: rVIVEncoding},
  3156  	AVWMACCVV & obj.AMask:   {enc: rVVVEncoding},
  3157  	AVWMACCVX & obj.AMask:   {enc: rVIVEncoding},
  3158  	AVWMACCSUVV & obj.AMask: {enc: rVVVEncoding},
  3159  	AVWMACCSUVX & obj.AMask: {enc: rVIVEncoding},
  3160  	AVWMACCUSVX & obj.AMask: {enc: rVIVEncoding},
  3161  
  3162  	// 31.11.15: Vector Integer Merge Instructions
  3163  	AVMERGEVVM & obj.AMask: {enc: rVVVEncoding},
  3164  	AVMERGEVXM & obj.AMask: {enc: rVIVEncoding},
  3165  	AVMERGEVIM & obj.AMask: {enc: rVViEncoding},
  3166  
  3167  	// 31.11.16: Vector Integer Move Instructions
  3168  	AVMVVV & obj.AMask: {enc: rVVVEncoding},
  3169  	AVMVVX & obj.AMask: {enc: rVIVEncoding},
  3170  	AVMVVI & obj.AMask: {enc: rVViEncoding},
  3171  
  3172  	// 31.12.1: Vector Single-Width Saturating Add and Subtract
  3173  	AVSADDUVV & obj.AMask: {enc: rVVVEncoding},
  3174  	AVSADDUVX & obj.AMask: {enc: rVIVEncoding},
  3175  	AVSADDUVI & obj.AMask: {enc: rVViEncoding},
  3176  	AVSADDVV & obj.AMask:  {enc: rVVVEncoding},
  3177  	AVSADDVX & obj.AMask:  {enc: rVIVEncoding},
  3178  	AVSADDVI & obj.AMask:  {enc: rVViEncoding},
  3179  	AVSSUBUVV & obj.AMask: {enc: rVVVEncoding},
  3180  	AVSSUBUVX & obj.AMask: {enc: rVIVEncoding},
  3181  	AVSSUBVV & obj.AMask:  {enc: rVVVEncoding},
  3182  	AVSSUBVX & obj.AMask:  {enc: rVIVEncoding},
  3183  
  3184  	// 31.12.2: Vector Single-Width Averaging Add and Subtract
  3185  	AVAADDUVV & obj.AMask: {enc: rVVVEncoding},
  3186  	AVAADDUVX & obj.AMask: {enc: rVIVEncoding},
  3187  	AVAADDVV & obj.AMask:  {enc: rVVVEncoding},
  3188  	AVAADDVX & obj.AMask:  {enc: rVIVEncoding},
  3189  	AVASUBUVV & obj.AMask: {enc: rVVVEncoding},
  3190  	AVASUBUVX & obj.AMask: {enc: rVIVEncoding},
  3191  	AVASUBVV & obj.AMask:  {enc: rVVVEncoding},
  3192  	AVASUBVX & obj.AMask:  {enc: rVIVEncoding},
  3193  
  3194  	// 31.12.3: Vector Single-Width Fractional Multiply with Rounding and Saturation
  3195  	AVSMULVV & obj.AMask: {enc: rVVVEncoding},
  3196  	AVSMULVX & obj.AMask: {enc: rVIVEncoding},
  3197  
  3198  	// 31.12.4: Vector Single-Width Scaling Shift Instructions
  3199  	AVSSRLVV & obj.AMask: {enc: rVVVEncoding},
  3200  	AVSSRLVX & obj.AMask: {enc: rVIVEncoding},
  3201  	AVSSRLVI & obj.AMask: {enc: rVVuEncoding},
  3202  	AVSSRAVV & obj.AMask: {enc: rVVVEncoding},
  3203  	AVSSRAVX & obj.AMask: {enc: rVIVEncoding},
  3204  	AVSSRAVI & obj.AMask: {enc: rVVuEncoding},
  3205  
  3206  	// 31.12.5: Vector Narrowing Fixed-Point Clip Instructions
  3207  	AVNCLIPUWV & obj.AMask: {enc: rVVVEncoding},
  3208  	AVNCLIPUWX & obj.AMask: {enc: rVIVEncoding},
  3209  	AVNCLIPUWI & obj.AMask: {enc: rVVuEncoding},
  3210  	AVNCLIPWV & obj.AMask:  {enc: rVVVEncoding},
  3211  	AVNCLIPWX & obj.AMask:  {enc: rVIVEncoding},
  3212  	AVNCLIPWI & obj.AMask:  {enc: rVVuEncoding},
  3213  
  3214  	// 31.13.2: Vector Single-Width Floating-Point Add/Subtract Instructions
  3215  	AVFADDVV & obj.AMask:  {enc: rVVVEncoding},
  3216  	AVFADDVF & obj.AMask:  {enc: rVFVEncoding},
  3217  	AVFSUBVV & obj.AMask:  {enc: rVVVEncoding},
  3218  	AVFSUBVF & obj.AMask:  {enc: rVFVEncoding},
  3219  	AVFRSUBVF & obj.AMask: {enc: rVFVEncoding},
  3220  
  3221  	// 31.13.3: Vector Widening Floating-Point Add/Subtract Instructions
  3222  	AVFWADDVV & obj.AMask: {enc: rVVVEncoding},
  3223  	AVFWADDVF & obj.AMask: {enc: rVFVEncoding},
  3224  	AVFWSUBVV & obj.AMask: {enc: rVVVEncoding},
  3225  	AVFWSUBVF & obj.AMask: {enc: rVFVEncoding},
  3226  	AVFWADDWV & obj.AMask: {enc: rVVVEncoding},
  3227  	AVFWADDWF & obj.AMask: {enc: rVFVEncoding},
  3228  	AVFWSUBWV & obj.AMask: {enc: rVVVEncoding},
  3229  	AVFWSUBWF & obj.AMask: {enc: rVFVEncoding},
  3230  
  3231  	// 31.13.4: Vector Single-Width Floating-Point Multiply/Divide Instructions
  3232  	AVFMULVV & obj.AMask:  {enc: rVVVEncoding},
  3233  	AVFMULVF & obj.AMask:  {enc: rVFVEncoding},
  3234  	AVFDIVVV & obj.AMask:  {enc: rVVVEncoding},
  3235  	AVFDIVVF & obj.AMask:  {enc: rVFVEncoding},
  3236  	AVFRDIVVF & obj.AMask: {enc: rVFVEncoding},
  3237  
  3238  	// 31.13.5: Vector Widening Floating-Point Multiply
  3239  	AVFWMULVV & obj.AMask: {enc: rVVVEncoding},
  3240  	AVFWMULVF & obj.AMask: {enc: rVFVEncoding},
  3241  
  3242  	// 31.13.6: Vector Single-Width Floating-Point Fused Multiply-Add Instructions
  3243  	AVFMACCVV & obj.AMask:  {enc: rVVVEncoding},
  3244  	AVFMACCVF & obj.AMask:  {enc: rVFVEncoding},
  3245  	AVFNMACCVV & obj.AMask: {enc: rVVVEncoding},
  3246  	AVFNMACCVF & obj.AMask: {enc: rVFVEncoding},
  3247  	AVFMSACVV & obj.AMask:  {enc: rVVVEncoding},
  3248  	AVFMSACVF & obj.AMask:  {enc: rVFVEncoding},
  3249  	AVFNMSACVV & obj.AMask: {enc: rVVVEncoding},
  3250  	AVFNMSACVF & obj.AMask: {enc: rVFVEncoding},
  3251  	AVFMADDVV & obj.AMask:  {enc: rVVVEncoding},
  3252  	AVFMADDVF & obj.AMask:  {enc: rVFVEncoding},
  3253  	AVFNMADDVV & obj.AMask: {enc: rVVVEncoding},
  3254  	AVFNMADDVF & obj.AMask: {enc: rVFVEncoding},
  3255  	AVFMSUBVV & obj.AMask:  {enc: rVVVEncoding},
  3256  	AVFMSUBVF & obj.AMask:  {enc: rVFVEncoding},
  3257  	AVFNMSUBVV & obj.AMask: {enc: rVVVEncoding},
  3258  	AVFNMSUBVF & obj.AMask: {enc: rVFVEncoding},
  3259  
  3260  	// 31.13.7: Vector Widening Floating-Point Fused Multiply-Add Instructions
  3261  	AVFWMACCVV & obj.AMask:  {enc: rVVVEncoding},
  3262  	AVFWMACCVF & obj.AMask:  {enc: rVFVEncoding},
  3263  	AVFWNMACCVV & obj.AMask: {enc: rVVVEncoding},
  3264  	AVFWNMACCVF & obj.AMask: {enc: rVFVEncoding},
  3265  	AVFWMSACVV & obj.AMask:  {enc: rVVVEncoding},
  3266  	AVFWMSACVF & obj.AMask:  {enc: rVFVEncoding},
  3267  	AVFWNMSACVV & obj.AMask: {enc: rVVVEncoding},
  3268  	AVFWNMSACVF & obj.AMask: {enc: rVFVEncoding},
  3269  
  3270  	// 31.13.8: Vector Floating-Point Square-Root Instruction
  3271  	AVFSQRTV & obj.AMask: {enc: rVVEncoding},
  3272  
  3273  	// 31.13.9: Vector Floating-Point Reciprocal Square-Root Estimate Instruction
  3274  	AVFRSQRT7V & obj.AMask: {enc: rVVEncoding},
  3275  
  3276  	// 31.13.10: Vector Floating-Point Reciprocal Estimate Instruction
  3277  	AVFREC7V & obj.AMask: {enc: rVVEncoding},
  3278  
  3279  	// 31.13.11: Vector Floating-Point MIN/MAX Instructions
  3280  	AVFMINVV & obj.AMask: {enc: rVVVEncoding},
  3281  	AVFMINVF & obj.AMask: {enc: rVFVEncoding},
  3282  	AVFMAXVV & obj.AMask: {enc: rVVVEncoding},
  3283  	AVFMAXVF & obj.AMask: {enc: rVFVEncoding},
  3284  
  3285  	// 31.13.12: Vector Floating-Point Sign-Injection Instructions
  3286  	AVFSGNJVV & obj.AMask:  {enc: rVVVEncoding},
  3287  	AVFSGNJVF & obj.AMask:  {enc: rVFVEncoding},
  3288  	AVFSGNJNVV & obj.AMask: {enc: rVVVEncoding},
  3289  	AVFSGNJNVF & obj.AMask: {enc: rVFVEncoding},
  3290  	AVFSGNJXVV & obj.AMask: {enc: rVVVEncoding},
  3291  	AVFSGNJXVF & obj.AMask: {enc: rVFVEncoding},
  3292  
  3293  	// 31.13.13: Vector Floating-Point Compare Instructions
  3294  	AVMFEQVV & obj.AMask: {enc: rVVVEncoding},
  3295  	AVMFEQVF & obj.AMask: {enc: rVFVEncoding},
  3296  	AVMFNEVV & obj.AMask: {enc: rVVVEncoding},
  3297  	AVMFNEVF & obj.AMask: {enc: rVFVEncoding},
  3298  	AVMFLTVV & obj.AMask: {enc: rVVVEncoding},
  3299  	AVMFLTVF & obj.AMask: {enc: rVFVEncoding},
  3300  	AVMFLEVV & obj.AMask: {enc: rVVVEncoding},
  3301  	AVMFLEVF & obj.AMask: {enc: rVFVEncoding},
  3302  	AVMFGTVF & obj.AMask: {enc: rVFVEncoding},
  3303  	AVMFGEVF & obj.AMask: {enc: rVFVEncoding},
  3304  
  3305  	// 31.13.14: Vector Floating-Point Classify Instruction
  3306  	AVFCLASSV & obj.AMask: {enc: rVVEncoding},
  3307  
  3308  	// 31.13.15: Vector Floating-Point Merge Instruction
  3309  	AVFMERGEVFM & obj.AMask: {enc: rVFVEncoding},
  3310  
  3311  	// 31.13.16: Vector Floating-Point Move Instruction
  3312  	AVFMVVF & obj.AMask: {enc: rVFVEncoding},
  3313  
  3314  	// 31.13.17: Single-Width Floating-Point/Integer Type-Convert Instructions
  3315  	AVFCVTXUFV & obj.AMask:    {enc: rVVEncoding},
  3316  	AVFCVTXFV & obj.AMask:     {enc: rVVEncoding},
  3317  	AVFCVTRTZXUFV & obj.AMask: {enc: rVVEncoding},
  3318  	AVFCVTRTZXFV & obj.AMask:  {enc: rVVEncoding},
  3319  	AVFCVTFXUV & obj.AMask:    {enc: rVVEncoding},
  3320  	AVFCVTFXV & obj.AMask:     {enc: rVVEncoding},
  3321  
  3322  	// 31.13.18: Widening Floating-Point/Integer Type-Convert Instructions
  3323  	AVFWCVTXUFV & obj.AMask:    {enc: rVVEncoding},
  3324  	AVFWCVTXFV & obj.AMask:     {enc: rVVEncoding},
  3325  	AVFWCVTRTZXUFV & obj.AMask: {enc: rVVEncoding},
  3326  	AVFWCVTRTZXFV & obj.AMask:  {enc: rVVEncoding},
  3327  	AVFWCVTFXUV & obj.AMask:    {enc: rVVEncoding},
  3328  	AVFWCVTFXV & obj.AMask:     {enc: rVVEncoding},
  3329  	AVFWCVTFFV & obj.AMask:     {enc: rVVEncoding},
  3330  
  3331  	// 31.13.19: Narrowing Floating-Point/Integer Type-Convert Instructions
  3332  	AVFNCVTXUFW & obj.AMask:    {enc: rVVEncoding},
  3333  	AVFNCVTXFW & obj.AMask:     {enc: rVVEncoding},
  3334  	AVFNCVTRTZXUFW & obj.AMask: {enc: rVVEncoding},
  3335  	AVFNCVTRTZXFW & obj.AMask:  {enc: rVVEncoding},
  3336  	AVFNCVTFXUW & obj.AMask:    {enc: rVVEncoding},
  3337  	AVFNCVTFXW & obj.AMask:     {enc: rVVEncoding},
  3338  	AVFNCVTFFW & obj.AMask:     {enc: rVVEncoding},
  3339  	AVFNCVTRODFFW & obj.AMask:  {enc: rVVEncoding},
  3340  
  3341  	// 31.14.1: Vector Single-Width Integer Reduction Instructions
  3342  	AVREDSUMVS & obj.AMask:  {enc: rVVVEncoding},
  3343  	AVREDMAXUVS & obj.AMask: {enc: rVVVEncoding},
  3344  	AVREDMAXVS & obj.AMask:  {enc: rVVVEncoding},
  3345  	AVREDMINUVS & obj.AMask: {enc: rVVVEncoding},
  3346  	AVREDMINVS & obj.AMask:  {enc: rVVVEncoding},
  3347  	AVREDANDVS & obj.AMask:  {enc: rVVVEncoding},
  3348  	AVREDORVS & obj.AMask:   {enc: rVVVEncoding},
  3349  	AVREDXORVS & obj.AMask:  {enc: rVVVEncoding},
  3350  
  3351  	// 31.14.2: Vector Widening Integer Reduction Instructions
  3352  	AVWREDSUMUVS & obj.AMask: {enc: rVVVEncoding},
  3353  	AVWREDSUMVS & obj.AMask:  {enc: rVVVEncoding},
  3354  
  3355  	// 31.14.3: Vector Single-Width Floating-Point Reduction Instructions
  3356  	AVFREDOSUMVS & obj.AMask: {enc: rVVVEncoding},
  3357  	AVFREDUSUMVS & obj.AMask: {enc: rVVVEncoding},
  3358  	AVFREDMAXVS & obj.AMask:  {enc: rVVVEncoding},
  3359  	AVFREDMINVS & obj.AMask:  {enc: rVVVEncoding},
  3360  
  3361  	// 31.14.4: Vector Widening Floating-Point Reduction Instructions
  3362  	AVFWREDOSUMVS & obj.AMask: {enc: rVVVEncoding},
  3363  	AVFWREDUSUMVS & obj.AMask: {enc: rVVVEncoding},
  3364  
  3365  	// 31.15: Vector Mask Instructions
  3366  	AVMANDMM & obj.AMask:  {enc: rVVVEncoding},
  3367  	AVMNANDMM & obj.AMask: {enc: rVVVEncoding},
  3368  	AVMANDNMM & obj.AMask: {enc: rVVVEncoding},
  3369  	AVMXORMM & obj.AMask:  {enc: rVVVEncoding},
  3370  	AVMORMM & obj.AMask:   {enc: rVVVEncoding},
  3371  	AVMNORMM & obj.AMask:  {enc: rVVVEncoding},
  3372  	AVMORNMM & obj.AMask:  {enc: rVVVEncoding},
  3373  	AVMXNORMM & obj.AMask: {enc: rVVVEncoding},
  3374  	AVCPOPM & obj.AMask:   {enc: rVIEncoding},
  3375  	AVFIRSTM & obj.AMask:  {enc: rVIEncoding},
  3376  	AVMSBFM & obj.AMask:   {enc: rVVEncoding},
  3377  	AVMSIFM & obj.AMask:   {enc: rVVEncoding},
  3378  	AVMSOFM & obj.AMask:   {enc: rVVEncoding},
  3379  	AVIOTAM & obj.AMask:   {enc: rVVEncoding},
  3380  	AVIDV & obj.AMask:     {enc: rVVEncoding},
  3381  
  3382  	// 31.16.1: Integer Scalar Move Instructions
  3383  	AVMVXS & obj.AMask: {enc: rVIEncoding},
  3384  	AVMVSX & obj.AMask: {enc: rIVEncoding},
  3385  
  3386  	// 31.16.2: Floating-Point Scalar Move Instructions
  3387  	AVFMVFS & obj.AMask: {enc: rVFEncoding},
  3388  	AVFMVSF & obj.AMask: {enc: rFVEncoding},
  3389  
  3390  	// 31.16.3: Vector Slide Instructions
  3391  	AVSLIDEUPVX & obj.AMask:     {enc: rVIVEncoding},
  3392  	AVSLIDEUPVI & obj.AMask:     {enc: rVVuEncoding},
  3393  	AVSLIDEDOWNVX & obj.AMask:   {enc: rVIVEncoding},
  3394  	AVSLIDEDOWNVI & obj.AMask:   {enc: rVVuEncoding},
  3395  	AVSLIDE1UPVX & obj.AMask:    {enc: rVIVEncoding},
  3396  	AVFSLIDE1UPVF & obj.AMask:   {enc: rVFVEncoding},
  3397  	AVSLIDE1DOWNVX & obj.AMask:  {enc: rVIVEncoding},
  3398  	AVFSLIDE1DOWNVF & obj.AMask: {enc: rVFVEncoding},
  3399  
  3400  	// 31.16.4: Vector Register Gather Instructions
  3401  	AVRGATHERVV & obj.AMask:     {enc: rVVVEncoding},
  3402  	AVRGATHEREI16VV & obj.AMask: {enc: rVVVEncoding},
  3403  	AVRGATHERVX & obj.AMask:     {enc: rVIVEncoding},
  3404  	AVRGATHERVI & obj.AMask:     {enc: rVVuEncoding},
  3405  
  3406  	// 31.16.5: Vector Compress Instruction
  3407  	AVCOMPRESSVM & obj.AMask: {enc: rVVVEncoding},
  3408  
  3409  	// 31.16.6: Whole Vector Register Move
  3410  	AVMV1RV & obj.AMask: {enc: rVVEncoding},
  3411  	AVMV2RV & obj.AMask: {enc: rVVEncoding},
  3412  	AVMV4RV & obj.AMask: {enc: rVVEncoding},
  3413  	AVMV8RV & obj.AMask: {enc: rVVEncoding},
  3414  
  3415  	// 33.2.1: Vector Basic Bit-manipulation
  3416  	AVANDNVV & obj.AMask: {enc: rVVVEncoding},
  3417  	AVANDNVX & obj.AMask: {enc: rVIVEncoding},
  3418  	AVBREVV & obj.AMask:  {enc: rVVEncoding},
  3419  	AVBREV8V & obj.AMask: {enc: rVVEncoding},
  3420  	AVREV8V & obj.AMask:  {enc: rVVEncoding},
  3421  	AVCLZV & obj.AMask:   {enc: rVVEncoding},
  3422  	AVCTZV & obj.AMask:   {enc: rVVEncoding},
  3423  	AVCPOPV & obj.AMask:  {enc: rVVEncoding},
  3424  	AVROLVV & obj.AMask:  {enc: rVVVEncoding},
  3425  	AVROLVX & obj.AMask:  {enc: rVIVEncoding},
  3426  	AVRORVV & obj.AMask:  {enc: rVVVEncoding},
  3427  	AVRORVX & obj.AMask:  {enc: rVIVEncoding},
  3428  	AVRORVI & obj.AMask:  {enc: rVVuEncoding},
  3429  	AVWSLLVV & obj.AMask: {enc: rVVVEncoding},
  3430  	AVWSLLVX & obj.AMask: {enc: rVIVEncoding},
  3431  	AVWSLLVI & obj.AMask: {enc: rVVuEncoding},
  3432  
  3433  	// 33.2.2: Vector Carryless Multiplication
  3434  	AVCLMULVV & obj.AMask:  {enc: rVVVEncoding},
  3435  	AVCLMULVX & obj.AMask:  {enc: rVIVEncoding},
  3436  	AVCLMULHVV & obj.AMask: {enc: rVVVEncoding},
  3437  	AVCLMULHVX & obj.AMask: {enc: rVIVEncoding},
  3438  
  3439  	//
  3440  	// Privileged ISA
  3441  	//
  3442  
  3443  	// 3.3.1: Environment Call and Breakpoint
  3444  	AECALL & obj.AMask:  {enc: iIIEncoding},
  3445  	AEBREAK & obj.AMask: {enc: iIIEncoding},
  3446  
  3447  	// Escape hatch
  3448  	AWORD & obj.AMask: {enc: rawEncoding},
  3449  
  3450  	// Pseudo-operations
  3451  	obj.AFUNCDATA: {enc: pseudoOpEncoding},
  3452  	obj.APCDATA:   {enc: pseudoOpEncoding},
  3453  	obj.ATEXT:     {enc: pseudoOpEncoding},
  3454  	obj.ANOP:      {enc: pseudoOpEncoding},
  3455  	obj.APCALIGN:  {enc: pseudoOpEncoding},
  3456  }
  3457  
  3458  // instructionDataForAs returns the instruction data for an obj.As.
  3459  func instructionDataForAs(as obj.As) (*instructionData, error) {
  3460  	if base := as &^ obj.AMask; base != obj.ABaseRISCV && base != 0 {
  3461  		return nil, fmt.Errorf("%v is not a RISC-V instruction", as)
  3462  	}
  3463  	asi := as & obj.AMask
  3464  	if int(asi) >= len(instructions) {
  3465  		return nil, fmt.Errorf("bad RISC-V instruction %v", as)
  3466  	}
  3467  	return &instructions[asi], nil
  3468  }
  3469  
  3470  // encodingForAs returns the encoding for an obj.As.
  3471  func encodingForAs(as obj.As) (*encoding, error) {
  3472  	insData, err := instructionDataForAs(as)
  3473  	if err != nil {
  3474  		return &badEncoding, err
  3475  	}
  3476  	if insData.enc.validate == nil {
  3477  		return &badEncoding, fmt.Errorf("no encoding for instruction %s", as)
  3478  	}
  3479  	return &insData.enc, nil
  3480  }
  3481  
  3482  // splitShiftConst attempts to split a constant into a signed 12 bit or
  3483  // 32 bit integer, with corresponding logical right shift and/or left shift.
  3484  func splitShiftConst(v int64) (imm int64, lsh int, rsh int, ok bool) {
  3485  	// See if we can reconstruct this value from a signed 32 bit integer.
  3486  	lsh = bits.TrailingZeros64(uint64(v))
  3487  	c := v >> lsh
  3488  	if int64(int32(c)) == c {
  3489  		return c, lsh, 0, true
  3490  	}
  3491  
  3492  	// See if we can reconstruct this value from a small negative constant.
  3493  	rsh = bits.LeadingZeros64(uint64(v))
  3494  	ones := bits.OnesCount64((uint64(v) >> lsh) >> 11)
  3495  	if rsh+ones+lsh+11 == 64 {
  3496  		c = signExtend(1<<11|((v>>lsh)&0x7ff), 12)
  3497  		if lsh > 0 || c != -1 {
  3498  			lsh += rsh
  3499  		}
  3500  		return c, lsh, rsh, true
  3501  	}
  3502  
  3503  	// See if we can reconstruct this value from a zero extended signed
  3504  	// 32 bit integer. This will require four instructions on rva20u64
  3505  	// and three instructions on rva22u64 or higher.
  3506  	if int64(uint32(c)) == c {
  3507  		c = int64(int32(c))
  3508  		lsh, rsh = 32, 32-lsh
  3509  		return c, lsh, rsh, true
  3510  	}
  3511  
  3512  	return 0, 0, 0, false
  3513  }
  3514  
  3515  // isShiftConst indicates whether a constant can be represented as a signed
  3516  // 32 bit integer that is left and/or right shifted.
  3517  func isShiftConst(v int64) bool {
  3518  	_, lsh, rsh, ok := splitShiftConst(v)
  3519  	return ok && (lsh > 0 || rsh > 0)
  3520  }
  3521  
  3522  // isMaterialisableConst indicates whether a constant can be materialised
  3523  // via a small sequence of instructions.
  3524  func isMaterialisableConst(v int64) bool {
  3525  	// Signed 32 bit value that can be constructed with one or two instructions
  3526  	// (ADDIW or LUI+ADDIW).
  3527  	if int64(int32(v)) == v {
  3528  		return true
  3529  	}
  3530  	return isShiftConst(v)
  3531  }
  3532  
  3533  type instruction struct {
  3534  	p      *obj.Prog // Prog that instruction is for
  3535  	as     obj.As    // Assembler opcode
  3536  	rd     uint32    // Destination register
  3537  	rs1    uint32    // Source register 1
  3538  	rs2    uint32    // Source register 2
  3539  	rs3    uint32    // Source register 3
  3540  	imm    int64     // Immediate
  3541  	funct3 uint32    // Function 3
  3542  	funct7 uint32    // Function 7 (or Function 2)
  3543  }
  3544  
  3545  func (ins *instruction) String() string {
  3546  	if ins.p == nil {
  3547  		return ins.as.String()
  3548  	}
  3549  	var suffix string
  3550  	if ins.p.As != ins.as {
  3551  		suffix = fmt.Sprintf(" (%v)", ins.as)
  3552  	}
  3553  	return fmt.Sprintf("%v%v", ins.p, suffix)
  3554  }
  3555  
  3556  func (ins *instruction) encode() (uint32, error) {
  3557  	enc, err := encodingForAs(ins.as)
  3558  	if err != nil {
  3559  		return 0, err
  3560  	}
  3561  	if enc.length <= 0 {
  3562  		return 0, fmt.Errorf("%v: encoding called for a pseudo instruction", ins.as)
  3563  	}
  3564  	return enc.encode(ins), nil
  3565  }
  3566  
  3567  func (ins *instruction) length() int {
  3568  	enc, err := encodingForAs(ins.as)
  3569  	if err != nil {
  3570  		return 0
  3571  	}
  3572  	return enc.length
  3573  }
  3574  
  3575  func (ins *instruction) validate(ctxt *obj.Link) {
  3576  	enc, err := encodingForAs(ins.as)
  3577  	if err != nil {
  3578  		ctxt.Diag("%v", err)
  3579  		return
  3580  	}
  3581  	enc.validate(ctxt, ins)
  3582  }
  3583  
  3584  func (ins *instruction) usesRegTmp() bool {
  3585  	return ins.rd == REG_TMP || ins.rs1 == REG_TMP || ins.rs2 == REG_TMP
  3586  }
  3587  
  3588  func (ins *instruction) compress() {
  3589  	switch ins.as {
  3590  	case ALW:
  3591  		if ins.rd != REG_X0 && ins.rs1 == REG_SP && isScaledImmU(ins.imm, 8, 4) {
  3592  			ins.as, ins.rs1, ins.rs2 = ACLWSP, obj.REG_NONE, ins.rs1
  3593  		} else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && isScaledImmU(ins.imm, 7, 4) {
  3594  			ins.as = ACLW
  3595  		}
  3596  
  3597  	case ALD:
  3598  		if ins.rs1 == REG_SP && ins.rd != REG_X0 && isScaledImmU(ins.imm, 9, 8) {
  3599  			ins.as, ins.rs1, ins.rs2 = ACLDSP, obj.REG_NONE, ins.rs1
  3600  		} else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && isScaledImmU(ins.imm, 8, 8) {
  3601  			ins.as = ACLD
  3602  		}
  3603  
  3604  	case AFLD:
  3605  		if ins.rs1 == REG_SP && isScaledImmU(ins.imm, 9, 8) {
  3606  			ins.as, ins.rs1, ins.rs2 = ACFLDSP, obj.REG_NONE, ins.rs1
  3607  		} else if isFloatPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && isScaledImmU(ins.imm, 8, 8) {
  3608  			ins.as = ACFLD
  3609  		}
  3610  
  3611  	case ASW:
  3612  		if ins.rd == REG_SP && isScaledImmU(ins.imm, 8, 4) {
  3613  			ins.as, ins.rs1, ins.rs2 = ACSWSP, obj.REG_NONE, ins.rs1
  3614  		} else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && isScaledImmU(ins.imm, 7, 4) {
  3615  			ins.as, ins.rd, ins.rs1, ins.rs2 = ACSW, obj.REG_NONE, ins.rd, ins.rs1
  3616  		}
  3617  
  3618  	case ASD:
  3619  		if ins.rd == REG_SP && isScaledImmU(ins.imm, 9, 8) {
  3620  			ins.as, ins.rs1, ins.rs2 = ACSDSP, obj.REG_NONE, ins.rs1
  3621  		} else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && isScaledImmU(ins.imm, 8, 8) {
  3622  			ins.as, ins.rd, ins.rs1, ins.rs2 = ACSD, obj.REG_NONE, ins.rd, ins.rs1
  3623  		}
  3624  
  3625  	case AFSD:
  3626  		if ins.rd == REG_SP && isScaledImmU(ins.imm, 9, 8) {
  3627  			ins.as, ins.rs1, ins.rs2 = ACFSDSP, obj.REG_NONE, ins.rs1
  3628  		} else if isIntPrimeReg(ins.rd) && isFloatPrimeReg(ins.rs1) && isScaledImmU(ins.imm, 8, 8) {
  3629  			ins.as, ins.rd, ins.rs1, ins.rs2 = ACFSD, obj.REG_NONE, ins.rd, ins.rs1
  3630  		}
  3631  
  3632  	case AADDI:
  3633  		if ins.rd == REG_SP && ins.rs1 == REG_SP && ins.imm != 0 && isScaledImmI(ins.imm, 10, 16) {
  3634  			ins.as = ACADDI16SP
  3635  		} else if ins.rd != REG_X0 && ins.rd == ins.rs1 && ins.imm != 0 && immIFits(ins.imm, 6) == nil {
  3636  			ins.as = ACADDI
  3637  		} else if isIntPrimeReg(ins.rd) && ins.rs1 == REG_SP && ins.imm != 0 && isScaledImmU(ins.imm, 10, 4) {
  3638  			ins.as = ACADDI4SPN
  3639  		} else if ins.rd != REG_X0 && ins.rs1 == REG_X0 && immIFits(ins.imm, 6) == nil {
  3640  			ins.as, ins.rs1 = ACLI, obj.REG_NONE
  3641  		} else if ins.rd != REG_X0 && ins.rs1 != REG_X0 && ins.imm == 0 {
  3642  			ins.as, ins.rs1, ins.rs2 = ACMV, obj.REG_NONE, ins.rs1
  3643  		} else if ins.rd == REG_X0 && ins.rs1 == REG_X0 && ins.imm == 0 {
  3644  			ins.as, ins.rs1 = ACNOP, ins.rd
  3645  		}
  3646  
  3647  	case AADDIW:
  3648  		if ins.rd == ins.rs1 && immIFits(ins.imm, 6) == nil {
  3649  			ins.as = ACADDIW
  3650  		}
  3651  
  3652  	case ALUI:
  3653  		if ins.rd != REG_X0 && ins.rd != REG_SP && ins.imm != 0 && immIFits(ins.imm, 6) == nil {
  3654  			ins.as = ACLUI
  3655  		}
  3656  
  3657  	case ASLLI:
  3658  		if ins.rd != REG_X0 && ins.rd == ins.rs1 && ins.imm != 0 {
  3659  			ins.as = ACSLLI
  3660  		}
  3661  
  3662  	case ASRLI:
  3663  		if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && ins.imm != 0 {
  3664  			ins.as = ACSRLI
  3665  		}
  3666  
  3667  	case ASRAI:
  3668  		if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && ins.imm != 0 {
  3669  			ins.as = ACSRAI
  3670  		}
  3671  
  3672  	case AANDI:
  3673  		if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && immIFits(ins.imm, 6) == nil {
  3674  			ins.as = ACANDI
  3675  		}
  3676  
  3677  	case AADD:
  3678  		if ins.rd != REG_X0 && ins.rd == ins.rs1 && ins.rs2 != REG_X0 {
  3679  			ins.as = ACADD
  3680  		} else if ins.rd != REG_X0 && ins.rd == ins.rs2 && ins.rs1 != REG_X0 {
  3681  			ins.as, ins.rs1, ins.rs2 = ACADD, ins.rs2, ins.rs1
  3682  		} else if ins.rd != REG_X0 && ins.rs1 == REG_X0 && ins.rs2 != REG_X0 {
  3683  			ins.as = ACMV
  3684  		}
  3685  
  3686  	case AADDW:
  3687  		if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && isIntPrimeReg(ins.rs2) {
  3688  			ins.as = ACADDW
  3689  		} else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && ins.rd == ins.rs2 {
  3690  			ins.as, ins.rs1, ins.rs2 = ACADDW, ins.rs2, ins.rs1
  3691  		}
  3692  
  3693  	case ASUB:
  3694  		if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && isIntPrimeReg(ins.rs2) {
  3695  			ins.as = ACSUB
  3696  		}
  3697  
  3698  	case ASUBW:
  3699  		if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && isIntPrimeReg(ins.rs2) {
  3700  			ins.as = ACSUBW
  3701  		}
  3702  
  3703  	case AAND:
  3704  		if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && isIntPrimeReg(ins.rs2) {
  3705  			ins.as = ACAND
  3706  		} else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && ins.rd == ins.rs2 {
  3707  			ins.as, ins.rs1, ins.rs2 = ACAND, ins.rs2, ins.rs1
  3708  		}
  3709  
  3710  	case AOR:
  3711  		if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && isIntPrimeReg(ins.rs2) {
  3712  			ins.as = ACOR
  3713  		} else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && ins.rd == ins.rs2 {
  3714  			ins.as, ins.rs1, ins.rs2 = ACOR, ins.rs2, ins.rs1
  3715  		}
  3716  
  3717  	case AXOR:
  3718  		if isIntPrimeReg(ins.rd) && ins.rd == ins.rs1 && isIntPrimeReg(ins.rs2) {
  3719  			ins.as = ACXOR
  3720  		} else if isIntPrimeReg(ins.rd) && isIntPrimeReg(ins.rs1) && ins.rd == ins.rs2 {
  3721  			ins.as, ins.rs1, ins.rs2 = ACXOR, ins.rs2, ins.rs1
  3722  		}
  3723  
  3724  	case AEBREAK:
  3725  		ins.as, ins.rd, ins.rs1 = ACEBREAK, obj.REG_NONE, obj.REG_NONE
  3726  	}
  3727  }
  3728  
  3729  func encodeFenceOperand(a *obj.Addr) (uint32, bool) {
  3730  	if a.Type == obj.TYPE_SPECIAL && a.Offset > int64(SPOP_FENCE_BEGIN) && a.Offset < int64(SPOP_FENCE_END) {
  3731  		return SpecialOperand(a.Offset).encode(), true
  3732  	}
  3733  	if a.Type == obj.TYPE_NONE {
  3734  		return SPOP_FENCE_IORW.encode(), true
  3735  	}
  3736  	return 0, false
  3737  }
  3738  
  3739  // instructionForProg returns the default *obj.Prog to instruction mapping.
  3740  func instructionForProg(p *obj.Prog) *instruction {
  3741  	ins := &instruction{
  3742  		as:  p.As,
  3743  		rd:  uint32(p.To.Reg),
  3744  		rs1: uint32(p.Reg),
  3745  		rs2: uint32(p.From.Reg),
  3746  		imm: p.From.Offset,
  3747  	}
  3748  	if len(p.RestArgs) == 1 {
  3749  		ins.rs3 = uint32(p.RestArgs[0].Reg)
  3750  	}
  3751  	return ins
  3752  }
  3753  
  3754  // instructionsForOpImmediate returns the machine instructions for an immediate
  3755  // operand. The instruction is specified by as and the source register is
  3756  // specified by rs, instead of the obj.Prog.
  3757  func instructionsForOpImmediate(p *obj.Prog, as obj.As, rs int16) []*instruction {
  3758  	// <opi> $imm, REG, TO
  3759  	ins := instructionForProg(p)
  3760  	ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE
  3761  
  3762  	low, high, err := Split32BitImmediate(ins.imm)
  3763  	if err != nil {
  3764  		p.Ctxt.Diag("%v: constant %d too large: %v", p, ins.imm, err)
  3765  		return nil
  3766  	}
  3767  	if high == 0 {
  3768  		return []*instruction{ins}
  3769  	}
  3770  
  3771  	// Split into two additions, if possible.
  3772  	// Do not split SP-writing instructions, as otherwise the recorded SP delta may be wrong.
  3773  	if p.Spadj == 0 && ins.as == AADDI && ins.imm >= -(1<<12) && ins.imm < 1<<12-1 {
  3774  		imm0 := ins.imm / 2
  3775  		imm1 := ins.imm - imm0
  3776  
  3777  		// ADDI $(imm/2), REG, TO
  3778  		// ADDI $(imm-imm/2), TO, TO
  3779  		ins.imm = imm0
  3780  		insADDI := &instruction{as: AADDI, rd: ins.rd, rs1: ins.rd, imm: imm1}
  3781  		return []*instruction{ins, insADDI}
  3782  	}
  3783  
  3784  	// LUI $high, TMP
  3785  	// ADDIW $low, TMP, TMP
  3786  	// <op> TMP, REG, TO
  3787  	insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
  3788  	insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP, imm: low}
  3789  	switch ins.as {
  3790  	case AADDI:
  3791  		ins.as = AADD
  3792  	case AANDI:
  3793  		ins.as = AAND
  3794  	case AORI:
  3795  		ins.as = AOR
  3796  	case AXORI:
  3797  		ins.as = AXOR
  3798  	default:
  3799  		p.Ctxt.Diag("unsupported immediate instruction %v for splitting", p)
  3800  		return nil
  3801  	}
  3802  	ins.rs2 = REG_TMP
  3803  	if low == 0 {
  3804  		return []*instruction{insLUI, ins}
  3805  	}
  3806  	return []*instruction{insLUI, insADDIW, ins}
  3807  }
  3808  
  3809  // instructionsForLoad returns the machine instructions for a load. The load
  3810  // instruction is specified by as and the base/source register is specified
  3811  // by rs, instead of the obj.Prog.
  3812  func instructionsForLoad(p *obj.Prog, as obj.As, rs int16) []*instruction {
  3813  	if p.From.Type != obj.TYPE_MEM {
  3814  		p.Ctxt.Diag("%v requires memory for source", p)
  3815  		return nil
  3816  	}
  3817  
  3818  	switch as {
  3819  	case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU, AFLW, AFLD:
  3820  	default:
  3821  		p.Ctxt.Diag("%v: unknown load instruction %v", p, as)
  3822  		return nil
  3823  	}
  3824  
  3825  	// <load> $imm, REG, TO (load $imm+(REG), TO)
  3826  	ins := instructionForProg(p)
  3827  	ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE
  3828  	ins.imm = p.From.Offset
  3829  
  3830  	low, high, err := Split32BitImmediate(ins.imm)
  3831  	if err != nil {
  3832  		p.Ctxt.Diag("%v: constant %d too large", p, ins.imm)
  3833  		return nil
  3834  	}
  3835  	if high == 0 {
  3836  		return []*instruction{ins}
  3837  	}
  3838  
  3839  	// LUI $high, TMP
  3840  	// ADD TMP, REG, TMP
  3841  	// <load> $low, TMP, TO
  3842  	insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
  3843  	insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rs1}
  3844  	ins.rs1, ins.imm = REG_TMP, low
  3845  
  3846  	return []*instruction{insLUI, insADD, ins}
  3847  }
  3848  
  3849  // instructionsForStore returns the machine instructions for a store. The store
  3850  // instruction is specified by as and the target/source register is specified
  3851  // by rd, instead of the obj.Prog.
  3852  func instructionsForStore(p *obj.Prog, as obj.As, rd int16) []*instruction {
  3853  	if p.To.Type != obj.TYPE_MEM {
  3854  		p.Ctxt.Diag("%v requires memory for destination", p)
  3855  		return nil
  3856  	}
  3857  
  3858  	switch as {
  3859  	case ASW, ASH, ASB, ASD, AFSW, AFSD:
  3860  	default:
  3861  		p.Ctxt.Diag("%v: unknown store instruction %v", p, as)
  3862  		return nil
  3863  	}
  3864  
  3865  	// <store> $imm, REG, TO (store $imm+(TO), REG)
  3866  	ins := instructionForProg(p)
  3867  	ins.as, ins.rd, ins.rs1, ins.rs2 = as, uint32(rd), uint32(p.From.Reg), obj.REG_NONE
  3868  	ins.imm = p.To.Offset
  3869  
  3870  	low, high, err := Split32BitImmediate(ins.imm)
  3871  	if err != nil {
  3872  		p.Ctxt.Diag("%v: constant %d too large", p, ins.imm)
  3873  		return nil
  3874  	}
  3875  	if high == 0 {
  3876  		return []*instruction{ins}
  3877  	}
  3878  
  3879  	// LUI $high, TMP
  3880  	// ADD TMP, TO, TMP
  3881  	// <store> $low, REG, TMP
  3882  	insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
  3883  	insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rd}
  3884  	ins.rd, ins.imm = REG_TMP, low
  3885  
  3886  	return []*instruction{insLUI, insADD, ins}
  3887  }
  3888  
  3889  func instructionsForTLS(p *obj.Prog, ins *instruction) []*instruction {
  3890  	insAddTP := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: REG_TP}
  3891  
  3892  	var inss []*instruction
  3893  	if p.Ctxt.Flag_shared {
  3894  		// TLS initial-exec mode - load TLS offset from GOT, add the thread pointer
  3895  		// register, then load from or store to the resulting memory location.
  3896  		insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
  3897  		insLoadTLSOffset := &instruction{as: ALD, rd: REG_TMP, rs1: REG_TMP}
  3898  		inss = []*instruction{insAUIPC, insLoadTLSOffset, insAddTP, ins}
  3899  	} else {
  3900  		// TLS local-exec mode - load upper TLS offset, add the lower TLS offset,
  3901  		// add the thread pointer register, then load from or store to the resulting
  3902  		// memory location. Note that this differs from the suggested three
  3903  		// instruction sequence, as the Go linker does not currently have an
  3904  		// easy way to handle relocation across 12 bytes of machine code.
  3905  		insLUI := &instruction{as: ALUI, rd: REG_TMP}
  3906  		insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP}
  3907  		inss = []*instruction{insLUI, insADDIW, insAddTP, ins}
  3908  	}
  3909  	return inss
  3910  }
  3911  
  3912  func instructionsForTLSLoad(p *obj.Prog) []*instruction {
  3913  	if p.From.Sym.Type != objabi.STLSBSS {
  3914  		p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.From.Sym)
  3915  		return nil
  3916  	}
  3917  
  3918  	ins := instructionForProg(p)
  3919  	ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), REG_TMP, obj.REG_NONE, 0
  3920  
  3921  	return instructionsForTLS(p, ins)
  3922  }
  3923  
  3924  func instructionsForTLSStore(p *obj.Prog) []*instruction {
  3925  	if p.To.Sym.Type != objabi.STLSBSS {
  3926  		p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.To.Sym)
  3927  		return nil
  3928  	}
  3929  
  3930  	ins := instructionForProg(p)
  3931  	ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
  3932  
  3933  	return instructionsForTLS(p, ins)
  3934  }
  3935  
  3936  func instructionsForMOVConst(p *obj.Prog) []*instruction {
  3937  	ins := instructionForProg(p)
  3938  	inss := []*instruction{ins}
  3939  
  3940  	// For constants larger than 32 bits in size that have trailing zeros,
  3941  	// use the value with the trailing zeros removed and then use a SLLI
  3942  	// instruction to restore the original constant.
  3943  	//
  3944  	// For example:
  3945  	//     MOV $0x8000000000000000, X10
  3946  	// becomes
  3947  	//     MOV $1, X10
  3948  	//     SLLI $63, X10, X10
  3949  	//
  3950  	// Similarly, we can construct large constants that have a consecutive
  3951  	// sequence of ones from a small negative constant, with a right and/or
  3952  	// left shift.
  3953  	//
  3954  	// For example:
  3955  	//     MOV $0x000fffffffffffda, X10
  3956  	// becomes
  3957  	//     MOV $-19, X10
  3958  	//     SLLI $13, X10
  3959  	//     SRLI $12, X10
  3960  	//
  3961  	var insSLLI, insSRLI, insMOVWU *instruction
  3962  	if err := immIFits(ins.imm, 32); err != nil {
  3963  		if c, lsh, rsh, ok := splitShiftConst(ins.imm); ok {
  3964  			ins.imm = c
  3965  			if buildcfg.GORISCV64 >= 22 && lsh == 32 && rsh == 32 {
  3966  				insMOVWU = &instruction{as: AADDUW, rd: ins.rd, rs1: ins.rd, rs2: REG_ZERO}
  3967  				lsh, rsh = 0, 0
  3968  			}
  3969  			if lsh > 0 {
  3970  				insSLLI = &instruction{as: ASLLI, rd: ins.rd, rs1: ins.rd, imm: int64(lsh)}
  3971  			}
  3972  			if rsh > 0 {
  3973  				insSRLI = &instruction{as: ASRLI, rd: ins.rd, rs1: ins.rd, imm: int64(rsh)}
  3974  			}
  3975  		}
  3976  	}
  3977  
  3978  	low, high, err := Split32BitImmediate(ins.imm)
  3979  	if err != nil {
  3980  		p.Ctxt.Diag("%v: constant %d too large: %v", p, ins.imm, err)
  3981  		return nil
  3982  	}
  3983  
  3984  	// MOV $c, R -> ADD $c, ZERO, R
  3985  	ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, REG_ZERO, obj.REG_NONE, low
  3986  
  3987  	// LUI is only necessary if the constant does not fit in 12 bits.
  3988  	if high != 0 {
  3989  		// LUI top20bits(c), R
  3990  		// ADD bottom12bits(c), R, R
  3991  		insLUI := &instruction{as: ALUI, rd: ins.rd, imm: high}
  3992  		inss = []*instruction{insLUI}
  3993  		if low != 0 {
  3994  			ins.as, ins.rs1 = AADDIW, ins.rd
  3995  			inss = append(inss, ins)
  3996  		}
  3997  	}
  3998  	if insMOVWU != nil {
  3999  		inss = append(inss, insMOVWU)
  4000  	}
  4001  	if insSLLI != nil {
  4002  		inss = append(inss, insSLLI)
  4003  	}
  4004  	if insSRLI != nil {
  4005  		inss = append(inss, insSRLI)
  4006  	}
  4007  
  4008  	return inss
  4009  }
  4010  
  4011  // instructionsForMOV returns the machine instructions for an *obj.Prog that
  4012  // uses a MOV pseudo-instruction.
  4013  func instructionsForMOV(p *obj.Prog) []*instruction {
  4014  	ins := instructionForProg(p)
  4015  	inss := []*instruction{ins}
  4016  
  4017  	if p.Reg != 0 {
  4018  		p.Ctxt.Diag("%v: illegal MOV instruction", p)
  4019  		return nil
  4020  	}
  4021  
  4022  	switch {
  4023  	case p.From.Type == obj.TYPE_CONST && p.To.Type == obj.TYPE_REG:
  4024  		// Handle constant to register moves.
  4025  		if p.As != AMOV {
  4026  			p.Ctxt.Diag("%v: unsupported constant load", p)
  4027  			return nil
  4028  		}
  4029  		return instructionsForMOVConst(p)
  4030  
  4031  	case p.From.Type == obj.TYPE_CONST && p.To.Type != obj.TYPE_REG:
  4032  		p.Ctxt.Diag("%v: constant load must target register", p)
  4033  		return nil
  4034  
  4035  	case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG:
  4036  		// Handle register to register moves.
  4037  		switch p.As {
  4038  		case AMOV:
  4039  			// MOV Ra, Rb -> ADDI $0, Ra, Rb
  4040  			ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, uint32(p.From.Reg), obj.REG_NONE, 0
  4041  		case AMOVW:
  4042  			// MOVW Ra, Rb -> ADDIW $0, Ra, Rb
  4043  			ins.as, ins.rs1, ins.rs2, ins.imm = AADDIW, uint32(p.From.Reg), obj.REG_NONE, 0
  4044  		case AMOVBU:
  4045  			// MOVBU Ra, Rb -> ANDI $255, Ra, Rb
  4046  			ins.as, ins.rs1, ins.rs2, ins.imm = AANDI, uint32(p.From.Reg), obj.REG_NONE, 255
  4047  		case AMOVF:
  4048  			// MOVF Ra, Rb -> FSGNJS Ra, Ra, Rb
  4049  			//          or -> FMVWX  Ra, Rb
  4050  			//          or -> FMVXW  Ra, Rb
  4051  			if ins.rs2 >= REG_X0 && ins.rs2 <= REG_X31 && ins.rd >= REG_F0 && ins.rd <= REG_F31 {
  4052  				ins.as = AFMVWX
  4053  			} else if ins.rs2 >= REG_F0 && ins.rs2 <= REG_F31 && ins.rd >= REG_X0 && ins.rd <= REG_X31 {
  4054  				ins.as = AFMVXW
  4055  			} else {
  4056  				ins.as, ins.rs1 = AFSGNJS, uint32(p.From.Reg)
  4057  			}
  4058  		case AMOVD:
  4059  			// MOVD Ra, Rb -> FSGNJD Ra, Ra, Rb
  4060  			//          or -> FMVDX  Ra, Rb
  4061  			//          or -> FMVXD  Ra, Rb
  4062  			if ins.rs2 >= REG_X0 && ins.rs2 <= REG_X31 && ins.rd >= REG_F0 && ins.rd <= REG_F31 {
  4063  				ins.as = AFMVDX
  4064  			} else if ins.rs2 >= REG_F0 && ins.rs2 <= REG_F31 && ins.rd >= REG_X0 && ins.rd <= REG_X31 {
  4065  				ins.as = AFMVXD
  4066  			} else {
  4067  				ins.as, ins.rs1 = AFSGNJD, uint32(p.From.Reg)
  4068  			}
  4069  		case AMOVB, AMOVH:
  4070  			if buildcfg.GORISCV64 >= 22 {
  4071  				// Use SEXTB or SEXTH to extend.
  4072  				ins.as, ins.rs1, ins.rs2 = ASEXTB, uint32(p.From.Reg), obj.REG_NONE
  4073  				if p.As == AMOVH {
  4074  					ins.as = ASEXTH
  4075  				}
  4076  			} else {
  4077  				// Use SLLI/SRAI sequence to extend.
  4078  				ins.as, ins.rs1, ins.rs2 = ASLLI, uint32(p.From.Reg), obj.REG_NONE
  4079  				if p.As == AMOVB {
  4080  					ins.imm = 56
  4081  				} else if p.As == AMOVH {
  4082  					ins.imm = 48
  4083  				}
  4084  				ins2 := &instruction{as: ASRAI, rd: ins.rd, rs1: ins.rd, imm: ins.imm}
  4085  				inss = append(inss, ins2)
  4086  			}
  4087  		case AMOVHU, AMOVWU:
  4088  			if buildcfg.GORISCV64 >= 22 {
  4089  				// Use ZEXTH or ADDUW to extend.
  4090  				ins.as, ins.rs1, ins.rs2, ins.imm = AZEXTH, uint32(p.From.Reg), obj.REG_NONE, 0
  4091  				if p.As == AMOVWU {
  4092  					ins.as, ins.rs2 = AADDUW, REG_ZERO
  4093  				}
  4094  			} else {
  4095  				// Use SLLI/SRLI sequence to extend.
  4096  				ins.as, ins.rs1, ins.rs2 = ASLLI, uint32(p.From.Reg), obj.REG_NONE
  4097  				if p.As == AMOVHU {
  4098  					ins.imm = 48
  4099  				} else if p.As == AMOVWU {
  4100  					ins.imm = 32
  4101  				}
  4102  				ins2 := &instruction{as: ASRLI, rd: ins.rd, rs1: ins.rd, imm: ins.imm}
  4103  				inss = append(inss, ins2)
  4104  			}
  4105  		}
  4106  
  4107  	case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG:
  4108  		// Memory to register loads.
  4109  		switch p.From.Name {
  4110  		case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
  4111  			// MOV c(Rs), Rd -> L $c, Rs, Rd
  4112  			inss = instructionsForLoad(p, movToLoad(p.As), addrToReg(p.From))
  4113  
  4114  		case obj.NAME_EXTERN, obj.NAME_STATIC, obj.NAME_GOTREF:
  4115  			if p.From.Sym.Type == objabi.STLSBSS {
  4116  				return instructionsForTLSLoad(p)
  4117  			}
  4118  
  4119  			// Note that the values for $off_hi and $off_lo are currently
  4120  			// zero and will be assigned during relocation. If the destination
  4121  			// is an integer register then we can use the same register for the
  4122  			// address computation, otherwise we need to use the temporary register.
  4123  			//
  4124  			// AUIPC $off_hi, Rd
  4125  			// L $off_lo, Rd, Rd
  4126  			//
  4127  			addrReg := ins.rd
  4128  			if addrReg < REG_X0 || addrReg > REG_X31 {
  4129  				addrReg = REG_TMP
  4130  			}
  4131  			insAUIPC := &instruction{as: AAUIPC, rd: addrReg}
  4132  			ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), addrReg, obj.REG_NONE, 0
  4133  			inss = []*instruction{insAUIPC, ins}
  4134  
  4135  		default:
  4136  			p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
  4137  			return nil
  4138  		}
  4139  
  4140  	case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM:
  4141  		// Register to memory stores.
  4142  		switch p.As {
  4143  		case AMOVBU, AMOVHU, AMOVWU:
  4144  			p.Ctxt.Diag("%v: unsupported unsigned store", p)
  4145  			return nil
  4146  		}
  4147  		switch p.To.Name {
  4148  		case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
  4149  			// MOV Rs, c(Rd) -> S $c, Rs, Rd
  4150  			inss = instructionsForStore(p, movToStore(p.As), addrToReg(p.To))
  4151  
  4152  		case obj.NAME_EXTERN, obj.NAME_STATIC:
  4153  			if p.To.Sym.Type == objabi.STLSBSS {
  4154  				return instructionsForTLSStore(p)
  4155  			}
  4156  
  4157  			// Note that the values for $off_hi and $off_lo are currently
  4158  			// zero and will be assigned during relocation.
  4159  			//
  4160  			// AUIPC $off_hi, Rtmp
  4161  			// S $off_lo, Rtmp, Rd
  4162  			insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
  4163  			ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
  4164  			inss = []*instruction{insAUIPC, ins}
  4165  
  4166  		default:
  4167  			p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
  4168  			return nil
  4169  		}
  4170  
  4171  	case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG:
  4172  		// MOV $sym+off(SP/SB), R
  4173  		if p.As != AMOV {
  4174  			p.Ctxt.Diag("%v: unsupported address load", p)
  4175  			return nil
  4176  		}
  4177  		switch p.From.Name {
  4178  		case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
  4179  			inss = instructionsForOpImmediate(p, AADDI, addrToReg(p.From))
  4180  
  4181  		case obj.NAME_EXTERN, obj.NAME_STATIC:
  4182  			// Note that the values for $off_hi and $off_lo are currently
  4183  			// zero and will be assigned during relocation.
  4184  			//
  4185  			// AUIPC $off_hi, R
  4186  			// ADDI $off_lo, R
  4187  			insAUIPC := &instruction{as: AAUIPC, rd: ins.rd}
  4188  			ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, ins.rd, obj.REG_NONE, 0
  4189  			inss = []*instruction{insAUIPC, ins}
  4190  
  4191  		default:
  4192  			p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
  4193  			return nil
  4194  		}
  4195  
  4196  	case p.From.Type == obj.TYPE_ADDR && p.To.Type != obj.TYPE_REG:
  4197  		p.Ctxt.Diag("%v: address load must target register", p)
  4198  		return nil
  4199  
  4200  	default:
  4201  		p.Ctxt.Diag("%v: unsupported MOV", p)
  4202  		return nil
  4203  	}
  4204  
  4205  	return inss
  4206  }
  4207  
  4208  // instructionsForRotate returns the machine instructions for a bitwise rotation.
  4209  func instructionsForRotate(p *obj.Prog, ins *instruction) []*instruction {
  4210  	if buildcfg.GORISCV64 >= 22 {
  4211  		// Rotation instructions are supported natively.
  4212  		return []*instruction{ins}
  4213  	}
  4214  
  4215  	switch ins.as {
  4216  	case AROL, AROLW, AROR, ARORW:
  4217  		// ROL -> OR (SLL x y) (SRL x (NEG y))
  4218  		// ROR -> OR (SRL x y) (SLL x (NEG y))
  4219  		sllOp, srlOp := ASLL, ASRL
  4220  		if ins.as == AROLW || ins.as == ARORW {
  4221  			sllOp, srlOp = ASLLW, ASRLW
  4222  		}
  4223  		shift1, shift2 := sllOp, srlOp
  4224  		if ins.as == AROR || ins.as == ARORW {
  4225  			shift1, shift2 = shift2, shift1
  4226  		}
  4227  		return []*instruction{
  4228  			&instruction{as: ASUB, rs1: REG_ZERO, rs2: ins.rs2, rd: REG_TMP},
  4229  			&instruction{as: shift2, rs1: ins.rs1, rs2: REG_TMP, rd: REG_TMP},
  4230  			&instruction{as: shift1, rs1: ins.rs1, rs2: ins.rs2, rd: ins.rd},
  4231  			&instruction{as: AOR, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
  4232  		}
  4233  
  4234  	case ARORI, ARORIW:
  4235  		// ROR -> OR (SLLI -x y) (SRLI x y)
  4236  		sllOp, srlOp := ASLLI, ASRLI
  4237  		sllImm := int64(int8(-ins.imm) & 63)
  4238  		if ins.as == ARORIW {
  4239  			sllOp, srlOp = ASLLIW, ASRLIW
  4240  			sllImm = int64(int8(-ins.imm) & 31)
  4241  		}
  4242  		return []*instruction{
  4243  			&instruction{as: srlOp, rs1: ins.rs1, rd: REG_TMP, imm: ins.imm},
  4244  			&instruction{as: sllOp, rs1: ins.rs1, rd: ins.rd, imm: sllImm},
  4245  			&instruction{as: AOR, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
  4246  		}
  4247  
  4248  	default:
  4249  		p.Ctxt.Diag("%v: unknown rotation", p)
  4250  		return nil
  4251  	}
  4252  }
  4253  
  4254  // instructionsForMinMax returns the machine instructions for an integer minimum or maximum.
  4255  func instructionsForMinMax(p *obj.Prog, ins *instruction) []*instruction {
  4256  	if buildcfg.GORISCV64 >= 22 {
  4257  		// Minimum and maximum instructions are supported natively.
  4258  		return []*instruction{ins}
  4259  	}
  4260  
  4261  	// Generate a move for identical inputs.
  4262  	if ins.rs1 == ins.rs2 {
  4263  		ins.as, ins.rs2, ins.imm = AADDI, obj.REG_NONE, 0
  4264  		return []*instruction{ins}
  4265  	}
  4266  
  4267  	// Ensure that if one of the source registers is the same as the destination,
  4268  	// it is processed first.
  4269  	if ins.rs1 == ins.rd {
  4270  		ins.rs1, ins.rs2 = ins.rs2, ins.rs1
  4271  	}
  4272  	sltReg1, sltReg2 := ins.rs2, ins.rs1
  4273  
  4274  	// MIN -> SLT/SUB/XOR/AND/XOR
  4275  	// MAX -> SLT/SUB/XOR/AND/XOR with swapped inputs to SLT
  4276  	switch ins.as {
  4277  	case AMIN:
  4278  		ins.as = ASLT
  4279  	case AMAX:
  4280  		ins.as, sltReg1, sltReg2 = ASLT, sltReg2, sltReg1
  4281  	case AMINU:
  4282  		ins.as = ASLTU
  4283  	case AMAXU:
  4284  		ins.as, sltReg1, sltReg2 = ASLTU, sltReg2, sltReg1
  4285  	}
  4286  	return []*instruction{
  4287  		&instruction{as: ins.as, rs1: sltReg1, rs2: sltReg2, rd: REG_TMP},
  4288  		&instruction{as: ASUB, rs1: REG_ZERO, rs2: REG_TMP, rd: REG_TMP},
  4289  		&instruction{as: AXOR, rs1: ins.rs1, rs2: ins.rs2, rd: ins.rd},
  4290  		&instruction{as: AAND, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
  4291  		&instruction{as: AXOR, rs1: ins.rs1, rs2: ins.rd, rd: ins.rd},
  4292  	}
  4293  }
  4294  
  4295  // instructionsForProg returns the machine instructions for an *obj.Prog.
  4296  func instructionsForProg(p *obj.Prog, compress bool) []*instruction {
  4297  	ins := instructionForProg(p)
  4298  	inss := []*instruction{ins}
  4299  
  4300  	if ins.as == AVSETVLI || ins.as == AVSETIVLI {
  4301  		if len(p.RestArgs) != 4 {
  4302  			p.Ctxt.Diag("incorrect number of arguments for instruction")
  4303  			return nil
  4304  		}
  4305  	} else if len(p.RestArgs) > 1 {
  4306  		p.Ctxt.Diag("too many source registers")
  4307  		return nil
  4308  	}
  4309  
  4310  	switch ins.as {
  4311  	case ACJALR, AJAL, AJALR:
  4312  		ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.To.Reg), obj.REG_NONE
  4313  		ins.imm = p.To.Offset
  4314  
  4315  	case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ:
  4316  		switch ins.as {
  4317  		case ABEQZ:
  4318  			ins.as, ins.rs1, ins.rs2 = ABEQ, REG_ZERO, uint32(p.From.Reg)
  4319  		case ABGEZ:
  4320  			ins.as, ins.rs1, ins.rs2 = ABGE, REG_ZERO, uint32(p.From.Reg)
  4321  		case ABGT:
  4322  			ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), uint32(p.Reg)
  4323  		case ABGTU:
  4324  			ins.as, ins.rs1, ins.rs2 = ABLTU, uint32(p.From.Reg), uint32(p.Reg)
  4325  		case ABGTZ:
  4326  			ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), REG_ZERO
  4327  		case ABLE:
  4328  			ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), uint32(p.Reg)
  4329  		case ABLEU:
  4330  			ins.as, ins.rs1, ins.rs2 = ABGEU, uint32(p.From.Reg), uint32(p.Reg)
  4331  		case ABLEZ:
  4332  			ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), REG_ZERO
  4333  		case ABLTZ:
  4334  			ins.as, ins.rs1, ins.rs2 = ABLT, REG_ZERO, uint32(p.From.Reg)
  4335  		case ABNEZ:
  4336  			ins.as, ins.rs1, ins.rs2 = ABNE, REG_ZERO, uint32(p.From.Reg)
  4337  		}
  4338  		ins.imm = p.To.Offset
  4339  
  4340  	case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
  4341  		inss = instructionsForMOV(p)
  4342  
  4343  	case ALW, ALWU, ALH, ALHU, ALB, ALBU, ALD, AFLW, AFLD:
  4344  		inss = instructionsForLoad(p, ins.as, p.From.Reg)
  4345  
  4346  	case ASW, ASH, ASB, ASD, AFSW, AFSD:
  4347  		inss = instructionsForStore(p, ins.as, p.To.Reg)
  4348  
  4349  	case ALRW, ALRD:
  4350  		// Set aq to use acquire access ordering
  4351  		ins.funct7 = 2
  4352  		ins.rs1, ins.rs2 = uint32(p.From.Reg), REG_ZERO
  4353  
  4354  	case AADDI, AANDI, AORI, AXORI:
  4355  		inss = instructionsForOpImmediate(p, ins.as, p.Reg)
  4356  
  4357  	case ASCW, ASCD:
  4358  		// Set release access ordering
  4359  		ins.funct7 = 1
  4360  		ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg)
  4361  
  4362  	case AAMOSWAPW, AAMOSWAPD, AAMOADDW, AAMOADDD, AAMOANDW, AAMOANDD, AAMOORW, AAMOORD,
  4363  		AAMOXORW, AAMOXORD, AAMOMINW, AAMOMIND, AAMOMINUW, AAMOMINUD, AAMOMAXW, AAMOMAXD, AAMOMAXUW, AAMOMAXUD:
  4364  		// Set aqrl to use acquire & release access ordering
  4365  		ins.funct7 = 3
  4366  		ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg)
  4367  
  4368  	case AECALL, AEBREAK:
  4369  		insEnc := encode(p.As)
  4370  		if p.To.Type == obj.TYPE_NONE {
  4371  			ins.rd = REG_ZERO
  4372  		}
  4373  		ins.rs1 = REG_ZERO
  4374  		ins.imm = insEnc.csr
  4375  
  4376  	case ARDCYCLE, ARDTIME, ARDINSTRET:
  4377  		ins.as = ACSRRS
  4378  		if p.To.Type == obj.TYPE_NONE {
  4379  			ins.rd = REG_ZERO
  4380  		}
  4381  		ins.rs1 = REG_ZERO
  4382  		switch p.As {
  4383  		case ARDCYCLE:
  4384  			ins.imm = -1024
  4385  		case ARDTIME:
  4386  			ins.imm = -1023
  4387  		case ARDINSTRET:
  4388  			ins.imm = -1022
  4389  		}
  4390  
  4391  	case ACSRC, ACSRRC, ACSRCI, ACSRRCI, ACSRR, ACSRS, ACSRSI, ACSRRS, ACSRRSI, ACSRRW, ACSRRWI, ACSRW, ACSRWI:
  4392  		switch {
  4393  		case ins.as == ACSRCI || (ins.as == ACSRC && p.From.Type == obj.TYPE_CONST):
  4394  			ins.as = ACSRRCI
  4395  			ins.rd = REG_ZERO
  4396  		case ins.as == ACSRC:
  4397  			ins.as = ACSRRC
  4398  			ins.rd = REG_ZERO
  4399  		case ins.as == ACSRSI || (ins.as == ACSRS && p.From.Type == obj.TYPE_CONST):
  4400  			ins.as = ACSRRSI
  4401  			ins.rd = REG_ZERO
  4402  		case ins.as == ACSRS:
  4403  			ins.as = ACSRRS
  4404  			ins.rd = REG_ZERO
  4405  		case ins.as == ACSRWI || (ins.as == ACSRW && p.From.Type == obj.TYPE_CONST):
  4406  			ins.as = ACSRRWI
  4407  			ins.rd = REG_ZERO
  4408  		case ins.as == ACSRW:
  4409  			ins.as = ACSRRW
  4410  			ins.rd = REG_ZERO
  4411  		default:
  4412  			if p.To.Type != obj.TYPE_REG {
  4413  				p.Ctxt.Diag("%v: needs an integer register output", p)
  4414  				return nil
  4415  			}
  4416  		}
  4417  
  4418  		if len(p.RestArgs) == 0 || p.RestArgs[0].Type != obj.TYPE_SPECIAL {
  4419  			p.Ctxt.Diag("%v: missing CSR name", p)
  4420  			return nil
  4421  		}
  4422  		if ins.as == ACSRR {
  4423  			ins.as = ACSRRS
  4424  			ins.rs1 = REG_ZERO
  4425  		} else if p.From.Type == obj.TYPE_CONST {
  4426  			imm := p.From.Offset
  4427  			if imm < 0 || imm >= 32 {
  4428  				p.Ctxt.Diag("%v: immediate out of range 0 to 31", p)
  4429  				return nil
  4430  			}
  4431  			ins.rs1 = uint32(imm) + REG_ZERO
  4432  		} else if p.From.Type == obj.TYPE_REG {
  4433  			ins.rs1 = uint32(p.From.Reg)
  4434  		} else {
  4435  			p.Ctxt.Diag("%v: integer register or immediate expected for 1st operand", p)
  4436  			return nil
  4437  		}
  4438  		csrNum := SpecialOperand(p.RestArgs[0].Offset).encode()
  4439  		if csrNum >= 1<<12 {
  4440  			p.Ctxt.Diag("%v: unknown CSR", p)
  4441  			return nil
  4442  		}
  4443  		if _, ok := CSRs[uint16(csrNum)]; !ok {
  4444  			p.Ctxt.Diag("%v: unknown CSR", p)
  4445  			return nil
  4446  		}
  4447  		ins.imm = int64(csrNum)
  4448  		if ins.imm > 2047 {
  4449  			ins.imm -= 4096
  4450  		}
  4451  		ins.rs2 = obj.REG_NONE
  4452  
  4453  	case AFENCE:
  4454  		ins.rd, ins.rs1, ins.rs2 = REG_ZERO, REG_ZERO, obj.REG_NONE
  4455  		if p.Scond == fenceTsoSuffixBit {
  4456  			if p.From.Type != obj.TYPE_NONE || p.To.Type != obj.TYPE_NONE {
  4457  				p.Ctxt.Diag("FENCE.TSO must not have operands: %v", p)
  4458  			}
  4459  			// FENCE.TSO is encoded as a FENCE instruction with fm=1000(8), pred=RW(3), succ=RW(3)
  4460  			ins.imm = signExtend((8<<8)|(3<<4)|3, 12)
  4461  		} else {
  4462  			pred, ok := encodeFenceOperand(&p.From)
  4463  			if !ok {
  4464  				p.Ctxt.Diag("invalid FENCE predecessor operand: %v", p)
  4465  			}
  4466  			succ, ok := encodeFenceOperand(&p.To)
  4467  			if !ok {
  4468  				p.Ctxt.Diag("invalid FENCE successor operand: %v", p)
  4469  			}
  4470  			// FENCE pred, succ
  4471  			// pred(4 bits), succ(4 bits)
  4472  			ins.imm = int64((pred << 4) | succ)
  4473  		}
  4474  
  4475  	case APAUSE:
  4476  		ins.as, ins.rd, ins.rs1, ins.rs2 = AFENCE, REG_ZERO, REG_ZERO, obj.REG_NONE
  4477  		ins.imm = 0x010
  4478  
  4479  	case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
  4480  		// Set the default rounding mode in funct3 to round to zero.
  4481  		if p.Scond&rmSuffixBit == 0 {
  4482  			ins.funct3 = uint32(RM_RTZ)
  4483  		} else {
  4484  			ins.funct3 = uint32(p.Scond &^ rmSuffixBit)
  4485  		}
  4486  
  4487  	case AFNES, AFNED:
  4488  		// Replace FNE[SD] with FEQ[SD] and NOT.
  4489  		if p.To.Type != obj.TYPE_REG {
  4490  			p.Ctxt.Diag("%v needs an integer register output", p)
  4491  			return nil
  4492  		}
  4493  		if ins.as == AFNES {
  4494  			ins.as = AFEQS
  4495  		} else {
  4496  			ins.as = AFEQD
  4497  		}
  4498  		ins2 := &instruction{
  4499  			as:  AXORI, // [bit] xor 1 = not [bit]
  4500  			rd:  ins.rd,
  4501  			rs1: ins.rd,
  4502  			imm: 1,
  4503  		}
  4504  		inss = append(inss, ins2)
  4505  
  4506  	case AFSQRTS, AFSQRTD:
  4507  		// These instructions expect a zero (i.e. float register 0)
  4508  		// to be the second input operand.
  4509  		ins.rs1 = uint32(p.From.Reg)
  4510  		ins.rs2 = REG_F0
  4511  
  4512  	case AFMADDS, AFMSUBS, AFNMADDS, AFNMSUBS,
  4513  		AFMADDD, AFMSUBD, AFNMADDD, AFNMSUBD:
  4514  		// Swap the first two operands so that the operands are in the same
  4515  		// order as they are in the specification: RS1, RS2, RS3, RD.
  4516  		ins.rs1, ins.rs2 = ins.rs2, ins.rs1
  4517  
  4518  	case ANEG, ANEGW:
  4519  		// NEG rs, rd -> SUB rs, X0, rd
  4520  		ins.as = ASUB
  4521  		if p.As == ANEGW {
  4522  			ins.as = ASUBW
  4523  		}
  4524  		ins.rs1 = REG_ZERO
  4525  		if ins.rd == obj.REG_NONE {
  4526  			ins.rd = ins.rs2
  4527  		}
  4528  
  4529  	case ANOT:
  4530  		// NOT rs, rd -> XORI $-1, rs, rd
  4531  		ins.as = AXORI
  4532  		ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
  4533  		if ins.rd == obj.REG_NONE {
  4534  			ins.rd = ins.rs1
  4535  		}
  4536  		ins.imm = -1
  4537  
  4538  	case ASEQZ:
  4539  		// SEQZ rs, rd -> SLTIU $1, rs, rd
  4540  		ins.as = ASLTIU
  4541  		ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
  4542  		ins.imm = 1
  4543  
  4544  	case ASNEZ:
  4545  		// SNEZ rs, rd -> SLTU rs, x0, rd
  4546  		ins.as = ASLTU
  4547  		ins.rs1 = REG_ZERO
  4548  
  4549  	case AFABSS:
  4550  		// FABSS rs, rd -> FSGNJXS rs, rs, rd
  4551  		ins.as = AFSGNJXS
  4552  		ins.rs1 = uint32(p.From.Reg)
  4553  
  4554  	case AFABSD:
  4555  		// FABSD rs, rd -> FSGNJXD rs, rs, rd
  4556  		ins.as = AFSGNJXD
  4557  		ins.rs1 = uint32(p.From.Reg)
  4558  
  4559  	case AFNEGS:
  4560  		// FNEGS rs, rd -> FSGNJNS rs, rs, rd
  4561  		ins.as = AFSGNJNS
  4562  		ins.rs1 = uint32(p.From.Reg)
  4563  
  4564  	case AFNEGD:
  4565  		// FNEGD rs, rd -> FSGNJND rs, rs, rd
  4566  		ins.as = AFSGNJND
  4567  		ins.rs1 = uint32(p.From.Reg)
  4568  
  4569  	case ACLW, ACLD, ACFLD:
  4570  		ins.rs1, ins.rs2 = ins.rs2, obj.REG_NONE
  4571  
  4572  	case ACSW, ACSD, ACFSD:
  4573  		ins.rs1, ins.rd = ins.rd, obj.REG_NONE
  4574  		ins.imm = p.To.Offset
  4575  
  4576  	case ACSWSP, ACSDSP, ACFSDSP:
  4577  		ins.imm = p.To.Offset
  4578  
  4579  	case ACANDI, ACSRLI, ACSRAI:
  4580  		ins.rs1, ins.rd = ins.rd, ins.rs1
  4581  
  4582  	case ACBEQZ, ACBNEZ:
  4583  		ins.rd, ins.rs1, ins.rs2 = obj.REG_NONE, uint32(p.From.Reg), obj.REG_NONE
  4584  		ins.imm = p.To.Offset
  4585  
  4586  	case ACJR:
  4587  		ins.rd, ins.rs1 = obj.REG_NONE, uint32(p.To.Reg)
  4588  
  4589  	case ACJ:
  4590  		ins.imm = p.To.Offset
  4591  
  4592  	case ACNOP:
  4593  		ins.rd, ins.rs1 = REG_ZERO, REG_ZERO
  4594  
  4595  	case AROL, AROLW, AROR, ARORW:
  4596  		inss = instructionsForRotate(p, ins)
  4597  
  4598  	case ARORI:
  4599  		if ins.imm < 0 || ins.imm > 63 {
  4600  			p.Ctxt.Diag("%v: immediate out of range 0 to 63", p)
  4601  		}
  4602  		inss = instructionsForRotate(p, ins)
  4603  
  4604  	case ARORIW:
  4605  		if ins.imm < 0 || ins.imm > 31 {
  4606  			p.Ctxt.Diag("%v: immediate out of range 0 to 31", p)
  4607  		}
  4608  		inss = instructionsForRotate(p, ins)
  4609  
  4610  	case ASLLI, ASRLI, ASRAI:
  4611  		if ins.imm < 0 || ins.imm > 63 {
  4612  			p.Ctxt.Diag("%v: immediate out of range 0 to 63", p)
  4613  		}
  4614  
  4615  	case ASLLIW, ASRLIW, ASRAIW:
  4616  		if ins.imm < 0 || ins.imm > 31 {
  4617  			p.Ctxt.Diag("%v: immediate out of range 0 to 31", p)
  4618  		}
  4619  
  4620  	case ACLZ, ACLZW, ACTZ, ACTZW, ACPOP, ACPOPW, ASEXTB, ASEXTH, AZEXTH:
  4621  		ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
  4622  
  4623  	case AORCB, AREV8:
  4624  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
  4625  
  4626  	case AANDN, AORN:
  4627  		if buildcfg.GORISCV64 >= 22 {
  4628  			// ANDN and ORN instructions are supported natively.
  4629  			break
  4630  		}
  4631  		// ANDN -> (AND (NOT x) y)
  4632  		// ORN  -> (OR  (NOT x) y)
  4633  		bitwiseOp, notReg := AAND, ins.rd
  4634  		if ins.as == AORN {
  4635  			bitwiseOp = AOR
  4636  		}
  4637  		if ins.rs1 == notReg {
  4638  			notReg = REG_TMP
  4639  		}
  4640  		inss = []*instruction{
  4641  			&instruction{as: AXORI, rs1: ins.rs2, rs2: obj.REG_NONE, rd: notReg, imm: -1},
  4642  			&instruction{as: bitwiseOp, rs1: ins.rs1, rs2: notReg, rd: ins.rd},
  4643  		}
  4644  
  4645  	case AXNOR:
  4646  		if buildcfg.GORISCV64 >= 22 {
  4647  			// XNOR instruction is supported natively.
  4648  			break
  4649  		}
  4650  		// XNOR -> (NOT (XOR x y))
  4651  		ins.as = AXOR
  4652  		inss = append(inss, &instruction{as: AXORI, rs1: ins.rd, rs2: obj.REG_NONE, rd: ins.rd, imm: -1})
  4653  
  4654  	case AMIN, AMAX, AMINU, AMAXU:
  4655  		inss = instructionsForMinMax(p, ins)
  4656  
  4657  	case AVSETVLI, AVSETIVLI:
  4658  		ins.rs1, ins.rs2 = ins.rs2, obj.REG_NONE
  4659  		vtype, err := EncodeVectorType(p.RestArgs[0].Offset, p.RestArgs[1].Offset, p.RestArgs[2].Offset, p.RestArgs[3].Offset)
  4660  		if err != nil {
  4661  			p.Ctxt.Diag("%v: %v", p, err)
  4662  		}
  4663  		ins.imm = vtype
  4664  		if ins.as == AVSETIVLI {
  4665  			if p.From.Type != obj.TYPE_CONST {
  4666  				p.Ctxt.Diag("%v: expected immediate value", p)
  4667  			}
  4668  			ins.rs1 = uint32(p.From.Offset)
  4669  		}
  4670  
  4671  	case AVLE8V, AVLE16V, AVLE32V, AVLE64V, AVSE8V, AVSE16V, AVSE32V, AVSE64V, AVLE8FFV, AVLE16FFV, AVLE32FFV, AVLE64FFV, AVLMV, AVSMV,
  4672  		AVLSEG2E8V, AVLSEG3E8V, AVLSEG4E8V, AVLSEG5E8V, AVLSEG6E8V, AVLSEG7E8V, AVLSEG8E8V,
  4673  		AVLSEG2E16V, AVLSEG3E16V, AVLSEG4E16V, AVLSEG5E16V, AVLSEG6E16V, AVLSEG7E16V, AVLSEG8E16V,
  4674  		AVLSEG2E32V, AVLSEG3E32V, AVLSEG4E32V, AVLSEG5E32V, AVLSEG6E32V, AVLSEG7E32V, AVLSEG8E32V,
  4675  		AVLSEG2E64V, AVLSEG3E64V, AVLSEG4E64V, AVLSEG5E64V, AVLSEG6E64V, AVLSEG7E64V, AVLSEG8E64V,
  4676  		AVSSEG2E8V, AVSSEG3E8V, AVSSEG4E8V, AVSSEG5E8V, AVSSEG6E8V, AVSSEG7E8V, AVSSEG8E8V,
  4677  		AVSSEG2E16V, AVSSEG3E16V, AVSSEG4E16V, AVSSEG5E16V, AVSSEG6E16V, AVSSEG7E16V, AVSSEG8E16V,
  4678  		AVSSEG2E32V, AVSSEG3E32V, AVSSEG4E32V, AVSSEG5E32V, AVSSEG6E32V, AVSSEG7E32V, AVSSEG8E32V,
  4679  		AVSSEG2E64V, AVSSEG3E64V, AVSSEG4E64V, AVSSEG5E64V, AVSSEG6E64V, AVSSEG7E64V, AVSSEG8E64V,
  4680  		AVLSEG2E8FFV, AVLSEG3E8FFV, AVLSEG4E8FFV, AVLSEG5E8FFV, AVLSEG6E8FFV, AVLSEG7E8FFV, AVLSEG8E8FFV,
  4681  		AVLSEG2E16FFV, AVLSEG3E16FFV, AVLSEG4E16FFV, AVLSEG5E16FFV, AVLSEG6E16FFV, AVLSEG7E16FFV, AVLSEG8E16FFV,
  4682  		AVLSEG2E32FFV, AVLSEG3E32FFV, AVLSEG4E32FFV, AVLSEG5E32FFV, AVLSEG6E32FFV, AVLSEG7E32FFV, AVLSEG8E32FFV,
  4683  		AVLSEG2E64FFV, AVLSEG3E64FFV, AVLSEG4E64FFV, AVLSEG5E64FFV, AVLSEG6E64FFV, AVLSEG7E64FFV, AVLSEG8E64FFV:
  4684  		// Set mask bit
  4685  		switch {
  4686  		case ins.rs1 == obj.REG_NONE:
  4687  			ins.funct7 |= 1 // unmasked
  4688  		case ins.rs1 != REG_V0:
  4689  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4690  		}
  4691  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
  4692  
  4693  	case AVLSE8V, AVLSE16V, AVLSE32V, AVLSE64V,
  4694  		AVLUXEI8V, AVLUXEI16V, AVLUXEI32V, AVLUXEI64V, AVLOXEI8V, AVLOXEI16V, AVLOXEI32V, AVLOXEI64V,
  4695  		AVLSSEG2E8V, AVLSSEG3E8V, AVLSSEG4E8V, AVLSSEG5E8V, AVLSSEG6E8V, AVLSSEG7E8V, AVLSSEG8E8V,
  4696  		AVLSSEG2E16V, AVLSSEG3E16V, AVLSSEG4E16V, AVLSSEG5E16V, AVLSSEG6E16V, AVLSSEG7E16V, AVLSSEG8E16V,
  4697  		AVLSSEG2E32V, AVLSSEG3E32V, AVLSSEG4E32V, AVLSSEG5E32V, AVLSSEG6E32V, AVLSSEG7E32V, AVLSSEG8E32V,
  4698  		AVLSSEG2E64V, AVLSSEG3E64V, AVLSSEG4E64V, AVLSSEG5E64V, AVLSSEG6E64V, AVLSSEG7E64V, AVLSSEG8E64V,
  4699  		AVLOXSEG2EI8V, AVLOXSEG3EI8V, AVLOXSEG4EI8V, AVLOXSEG5EI8V, AVLOXSEG6EI8V, AVLOXSEG7EI8V, AVLOXSEG8EI8V,
  4700  		AVLOXSEG2EI16V, AVLOXSEG3EI16V, AVLOXSEG4EI16V, AVLOXSEG5EI16V, AVLOXSEG6EI16V, AVLOXSEG7EI16V, AVLOXSEG8EI16V,
  4701  		AVLOXSEG2EI32V, AVLOXSEG3EI32V, AVLOXSEG4EI32V, AVLOXSEG5EI32V, AVLOXSEG6EI32V, AVLOXSEG7EI32V, AVLOXSEG8EI32V,
  4702  		AVLOXSEG2EI64V, AVLOXSEG3EI64V, AVLOXSEG4EI64V, AVLOXSEG5EI64V, AVLOXSEG6EI64V, AVLOXSEG7EI64V, AVLOXSEG8EI64V,
  4703  		AVLUXSEG2EI8V, AVLUXSEG3EI8V, AVLUXSEG4EI8V, AVLUXSEG5EI8V, AVLUXSEG6EI8V, AVLUXSEG7EI8V, AVLUXSEG8EI8V,
  4704  		AVLUXSEG2EI16V, AVLUXSEG3EI16V, AVLUXSEG4EI16V, AVLUXSEG5EI16V, AVLUXSEG6EI16V, AVLUXSEG7EI16V, AVLUXSEG8EI16V,
  4705  		AVLUXSEG2EI32V, AVLUXSEG3EI32V, AVLUXSEG4EI32V, AVLUXSEG5EI32V, AVLUXSEG6EI32V, AVLUXSEG7EI32V, AVLUXSEG8EI32V,
  4706  		AVLUXSEG2EI64V, AVLUXSEG3EI64V, AVLUXSEG4EI64V, AVLUXSEG5EI64V, AVLUXSEG6EI64V, AVLUXSEG7EI64V, AVLUXSEG8EI64V:
  4707  		// Set mask bit
  4708  		switch {
  4709  		case ins.rs3 == obj.REG_NONE:
  4710  			ins.funct7 |= 1 // unmasked
  4711  		case ins.rs3 != REG_V0:
  4712  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4713  		}
  4714  		ins.rs1, ins.rs2, ins.rs3 = ins.rs2, ins.rs1, obj.REG_NONE
  4715  
  4716  	case AVSSE8V, AVSSE16V, AVSSE32V, AVSSE64V,
  4717  		AVSUXEI8V, AVSUXEI16V, AVSUXEI32V, AVSUXEI64V, AVSOXEI8V, AVSOXEI16V, AVSOXEI32V, AVSOXEI64V,
  4718  		AVSSSEG2E8V, AVSSSEG3E8V, AVSSSEG4E8V, AVSSSEG5E8V, AVSSSEG6E8V, AVSSSEG7E8V, AVSSSEG8E8V,
  4719  		AVSSSEG2E16V, AVSSSEG3E16V, AVSSSEG4E16V, AVSSSEG5E16V, AVSSSEG6E16V, AVSSSEG7E16V, AVSSSEG8E16V,
  4720  		AVSSSEG2E32V, AVSSSEG3E32V, AVSSSEG4E32V, AVSSSEG5E32V, AVSSSEG6E32V, AVSSSEG7E32V, AVSSSEG8E32V,
  4721  		AVSSSEG2E64V, AVSSSEG3E64V, AVSSSEG4E64V, AVSSSEG5E64V, AVSSSEG6E64V, AVSSSEG7E64V, AVSSSEG8E64V,
  4722  		AVSOXSEG2EI8V, AVSOXSEG3EI8V, AVSOXSEG4EI8V, AVSOXSEG5EI8V, AVSOXSEG6EI8V, AVSOXSEG7EI8V, AVSOXSEG8EI8V,
  4723  		AVSOXSEG2EI16V, AVSOXSEG3EI16V, AVSOXSEG4EI16V, AVSOXSEG5EI16V, AVSOXSEG6EI16V, AVSOXSEG7EI16V, AVSOXSEG8EI16V,
  4724  		AVSOXSEG2EI32V, AVSOXSEG3EI32V, AVSOXSEG4EI32V, AVSOXSEG5EI32V, AVSOXSEG6EI32V, AVSOXSEG7EI32V, AVSOXSEG8EI32V,
  4725  		AVSOXSEG2EI64V, AVSOXSEG3EI64V, AVSOXSEG4EI64V, AVSOXSEG5EI64V, AVSOXSEG6EI64V, AVSOXSEG7EI64V, AVSOXSEG8EI64V,
  4726  		AVSUXSEG2EI8V, AVSUXSEG3EI8V, AVSUXSEG4EI8V, AVSUXSEG5EI8V, AVSUXSEG6EI8V, AVSUXSEG7EI8V, AVSUXSEG8EI8V,
  4727  		AVSUXSEG2EI16V, AVSUXSEG3EI16V, AVSUXSEG4EI16V, AVSUXSEG5EI16V, AVSUXSEG6EI16V, AVSUXSEG7EI16V, AVSUXSEG8EI16V,
  4728  		AVSUXSEG2EI32V, AVSUXSEG3EI32V, AVSUXSEG4EI32V, AVSUXSEG5EI32V, AVSUXSEG6EI32V, AVSUXSEG7EI32V, AVSUXSEG8EI32V,
  4729  		AVSUXSEG2EI64V, AVSUXSEG3EI64V, AVSUXSEG4EI64V, AVSUXSEG5EI64V, AVSUXSEG6EI64V, AVSUXSEG7EI64V, AVSUXSEG8EI64V:
  4730  		// Set mask bit
  4731  		switch {
  4732  		case ins.rs3 == obj.REG_NONE:
  4733  			ins.funct7 |= 1 // unmasked
  4734  		case ins.rs3 != REG_V0:
  4735  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4736  		}
  4737  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = ins.rs2, ins.rd, ins.rs1, obj.REG_NONE
  4738  
  4739  	case AVL1RV, AVL1RE8V, AVL1RE16V, AVL1RE32V, AVL1RE64V, AVL2RV, AVL2RE8V, AVL2RE16V, AVL2RE32V, AVL2RE64V,
  4740  		AVL4RV, AVL4RE8V, AVL4RE16V, AVL4RE32V, AVL4RE64V, AVL8RV, AVL8RE8V, AVL8RE16V, AVL8RE32V, AVL8RE64V:
  4741  		switch ins.as {
  4742  		case AVL1RV:
  4743  			ins.as = AVL1RE8V
  4744  		case AVL2RV:
  4745  			ins.as = AVL2RE8V
  4746  		case AVL4RV:
  4747  			ins.as = AVL4RE8V
  4748  		case AVL8RV:
  4749  			ins.as = AVL8RE8V
  4750  		}
  4751  		if ins.rs1 != obj.REG_NONE {
  4752  			p.Ctxt.Diag("%v: too many operands for instruction", p)
  4753  		}
  4754  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
  4755  
  4756  	case AVS1RV, AVS2RV, AVS4RV, AVS8RV:
  4757  		if ins.rs1 != obj.REG_NONE {
  4758  			p.Ctxt.Diag("%v: too many operands for instruction", p)
  4759  		}
  4760  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
  4761  
  4762  	case AVADDVV, AVADDVX, AVSUBVV, AVSUBVX, AVRSUBVX, AVWADDUVV, AVWADDUVX, AVWSUBUVV, AVWSUBUVX,
  4763  		AVWADDVV, AVWADDVX, AVWSUBVV, AVWSUBVX, AVWADDUWV, AVWADDUWX, AVWSUBUWV, AVWSUBUWX,
  4764  		AVWADDWV, AVWADDWX, AVWSUBWV, AVWSUBWX, AVANDVV, AVANDVX, AVORVV, AVORVX, AVXORVV, AVXORVX,
  4765  		AVSLLVV, AVSLLVX, AVSRLVV, AVSRLVX, AVSRAVV, AVSRAVX,
  4766  		AVMSEQVV, AVMSEQVX, AVMSNEVV, AVMSNEVX, AVMSLTUVV, AVMSLTUVX, AVMSLTVV, AVMSLTVX,
  4767  		AVMSLEUVV, AVMSLEUVX, AVMSLEVV, AVMSLEVX, AVMSGTUVX, AVMSGTVX,
  4768  		AVMINUVV, AVMINUVX, AVMINVV, AVMINVX, AVMAXUVV, AVMAXUVX, AVMAXVV, AVMAXVX,
  4769  		AVMULVV, AVMULVX, AVMULHVV, AVMULHVX, AVMULHUVV, AVMULHUVX, AVMULHSUVV, AVMULHSUVX,
  4770  		AVDIVUVV, AVDIVUVX, AVDIVVV, AVDIVVX, AVREMUVV, AVREMUVX, AVREMVV, AVREMVX,
  4771  		AVWMULVV, AVWMULVX, AVWMULUVV, AVWMULUVX, AVWMULSUVV, AVWMULSUVX, AVNSRLWV, AVNSRLWX, AVNSRAWV, AVNSRAWX,
  4772  		AVSADDUVV, AVSADDUVX, AVSADDUVI, AVSADDVV, AVSADDVX, AVSADDVI, AVSSUBUVV, AVSSUBUVX, AVSSUBVV, AVSSUBVX,
  4773  		AVAADDUVV, AVAADDUVX, AVAADDVV, AVAADDVX, AVASUBUVV, AVASUBUVX, AVASUBVV, AVASUBVX,
  4774  		AVSMULVV, AVSMULVX, AVSSRLVV, AVSSRLVX, AVSSRLVI, AVSSRAVV, AVSSRAVX, AVSSRAVI,
  4775  		AVNCLIPUWV, AVNCLIPUWX, AVNCLIPUWI, AVNCLIPWV, AVNCLIPWX, AVNCLIPWI,
  4776  		AVFADDVV, AVFADDVF, AVFSUBVV, AVFSUBVF, AVFRSUBVF,
  4777  		AVFWADDVV, AVFWADDVF, AVFWSUBVV, AVFWSUBVF, AVFWADDWV, AVFWADDWF, AVFWSUBWV, AVFWSUBWF,
  4778  		AVFMULVV, AVFMULVF, AVFDIVVV, AVFDIVVF, AVFRDIVVF, AVFWMULVV, AVFWMULVF,
  4779  		AVFMINVV, AVFMINVF, AVFMAXVV, AVFMAXVF,
  4780  		AVFSGNJVV, AVFSGNJVF, AVFSGNJNVV, AVFSGNJNVF, AVFSGNJXVV, AVFSGNJXVF,
  4781  		AVMFEQVV, AVMFEQVF, AVMFNEVV, AVMFNEVF, AVMFLTVV, AVMFLTVF, AVMFLEVV, AVMFLEVF, AVMFGTVF, AVMFGEVF,
  4782  		AVREDSUMVS, AVREDMAXUVS, AVREDMAXVS, AVREDMINUVS, AVREDMINVS, AVREDANDVS, AVREDORVS, AVREDXORVS,
  4783  		AVWREDSUMUVS, AVWREDSUMVS, AVFREDOSUMVS, AVFREDUSUMVS, AVFREDMAXVS, AVFREDMINVS, AVFWREDOSUMVS, AVFWREDUSUMVS,
  4784  		AVSLIDEUPVX, AVSLIDEDOWNVX, AVSLIDE1UPVX, AVFSLIDE1UPVF, AVSLIDE1DOWNVX, AVFSLIDE1DOWNVF,
  4785  		AVRGATHERVV, AVRGATHEREI16VV, AVRGATHERVX,
  4786  		AVANDNVV, AVANDNVX, AVROLVV, AVROLVX, AVRORVV, AVRORVX,
  4787  		AVWSLLVV, AVWSLLVX, AVCLMULVV, AVCLMULVX, AVCLMULHVV, AVCLMULHVX:
  4788  		// Set mask bit
  4789  		switch {
  4790  		case ins.rs3 == obj.REG_NONE:
  4791  			ins.funct7 |= 1 // unmasked
  4792  		case ins.rs3 != REG_V0:
  4793  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4794  		}
  4795  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), obj.REG_NONE
  4796  
  4797  	case AVFMACCVV, AVFMACCVF, AVFNMACCVV, AVFNMACCVF, AVFMSACVV, AVFMSACVF, AVFNMSACVV, AVFNMSACVF,
  4798  		AVFMADDVV, AVFMADDVF, AVFNMADDVV, AVFNMADDVF, AVFMSUBVV, AVFMSUBVF, AVFNMSUBVV, AVFNMSUBVF,
  4799  		AVFWMACCVV, AVFWMACCVF, AVFWNMACCVV, AVFWNMACCVF, AVFWMSACVV, AVFWMSACVF, AVFWNMSACVV, AVFWNMSACVF,
  4800  		AVMACCVV, AVMACCVX, AVNMSACVV, AVNMSACVX, AVMADDVV, AVMADDVX, AVNMSUBVV, AVNMSUBVX,
  4801  		AVWMACCUVV, AVWMACCUVX, AVWMACCVV, AVWMACCVX, AVWMACCSUVV, AVWMACCSUVX, AVWMACCUSVX:
  4802  		switch {
  4803  		case ins.rs3 == obj.REG_NONE:
  4804  			ins.funct7 |= 1 // unmasked
  4805  		case ins.rs3 != REG_V0:
  4806  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4807  		}
  4808  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.Reg), uint32(p.From.Reg), obj.REG_NONE
  4809  
  4810  	case AVADDVI, AVRSUBVI, AVANDVI, AVORVI, AVXORVI, AVMSEQVI, AVMSNEVI, AVMSLEUVI, AVMSLEVI, AVMSGTUVI, AVMSGTVI,
  4811  		AVSLLVI, AVSRLVI, AVSRAVI, AVNSRLWI, AVNSRAWI, AVRGATHERVI, AVSLIDEUPVI, AVSLIDEDOWNVI,
  4812  		AVRORVI, AVWSLLVI:
  4813  		// Set mask bit
  4814  		switch {
  4815  		case ins.rs3 == obj.REG_NONE:
  4816  			ins.funct7 |= 1 // unmasked
  4817  		case ins.rs3 != REG_V0:
  4818  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4819  		}
  4820  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), obj.REG_NONE, uint32(p.Reg), obj.REG_NONE
  4821  
  4822  	case AVZEXTVF2, AVSEXTVF2, AVZEXTVF4, AVSEXTVF4, AVZEXTVF8, AVSEXTVF8,
  4823  		AVFSQRTV, AVFRSQRT7V, AVFREC7V, AVFCLASSV,
  4824  		AVFCVTXUFV, AVFCVTXFV, AVFCVTRTZXUFV, AVFCVTRTZXFV, AVFCVTFXUV, AVFCVTFXV,
  4825  		AVFWCVTXUFV, AVFWCVTXFV, AVFWCVTRTZXUFV, AVFWCVTRTZXFV, AVFWCVTFXUV, AVFWCVTFXV,
  4826  		AVFWCVTFFV, AVFNCVTXUFW, AVFNCVTXFW, AVFNCVTRTZXUFW, AVFNCVTRTZXFW, AVFNCVTFXUW,
  4827  		AVFNCVTFXW, AVFNCVTFFW, AVFNCVTRODFFW,
  4828  		AVBREVV, AVBREV8V, AVREV8V, AVCLZV, AVCTZV, AVCPOPV:
  4829  		// Set mask bit
  4830  		switch {
  4831  		case ins.rs1 == obj.REG_NONE:
  4832  			ins.funct7 |= 1 // unmasked
  4833  		case ins.rs1 != REG_V0:
  4834  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4835  		}
  4836  		ins.rs1 = obj.REG_NONE
  4837  
  4838  	case AVMVVV, AVMVVX:
  4839  		if ins.rs1 != obj.REG_NONE {
  4840  			p.Ctxt.Diag("%v: too many operands for instruction", p)
  4841  		}
  4842  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), REG_V0
  4843  
  4844  	case AVMVVI:
  4845  		if ins.rs1 != obj.REG_NONE {
  4846  			p.Ctxt.Diag("%v: too many operands for instruction", p)
  4847  		}
  4848  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), obj.REG_NONE, REG_V0
  4849  
  4850  	case AVFMVVF:
  4851  		ins.funct7 |= 1 // unmasked
  4852  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), REG_V0
  4853  
  4854  	case AVADCVIM, AVADCVVM, AVADCVXM, AVSBCVVM, AVSBCVXM:
  4855  		if ins.rd == REG_V0 {
  4856  			p.Ctxt.Diag("%v: invalid destination register V0", p)
  4857  		}
  4858  		fallthrough
  4859  
  4860  	case AVMADCVVM, AVMADCVXM, AVMSBCVVM, AVMSBCVXM, AVMADCVIM, AVMERGEVVM, AVMERGEVXM, AVMERGEVIM, AVFMERGEVFM:
  4861  		if ins.rs3 != REG_V0 {
  4862  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4863  		}
  4864  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg), obj.REG_NONE
  4865  
  4866  	case AVMADCVV, AVMADCVX, AVMSBCVV, AVMSBCVX, AVMADCVI:
  4867  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)
  4868  
  4869  	case AVNEGV, AVWCVTXXV, AVWCVTUXXV, AVNCVTXXW:
  4870  		// Set mask bit
  4871  		switch {
  4872  		case ins.rs1 == obj.REG_NONE:
  4873  			ins.funct7 |= 1 // unmasked
  4874  		case ins.rs1 != REG_V0:
  4875  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4876  		}
  4877  		switch ins.as {
  4878  		case AVNEGV:
  4879  			ins.as = AVRSUBVX
  4880  		case AVWCVTXXV:
  4881  			ins.as = AVWADDVX
  4882  		case AVWCVTUXXV:
  4883  			ins.as = AVWADDUVX
  4884  		case AVNCVTXXW:
  4885  			ins.as = AVNSRLWX
  4886  		}
  4887  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), REG_X0, uint32(p.From.Reg)
  4888  
  4889  	case AVNOTV:
  4890  		// Set mask bit
  4891  		switch {
  4892  		case ins.rs1 == obj.REG_NONE:
  4893  			ins.funct7 |= 1 // unmasked
  4894  		case ins.rs1 != REG_V0:
  4895  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4896  		}
  4897  		ins.as = AVXORVI
  4898  		ins.rd, ins.rs1, ins.rs2, ins.imm = uint32(p.To.Reg), obj.REG_NONE, uint32(p.From.Reg), -1
  4899  
  4900  	case AVMSGTVV, AVMSGTUVV, AVMSGEVV, AVMSGEUVV, AVMFGTVV, AVMFGEVV:
  4901  		// Set mask bit
  4902  		switch {
  4903  		case ins.rs3 == obj.REG_NONE:
  4904  			ins.funct7 |= 1 // unmasked
  4905  		case ins.rs3 != REG_V0:
  4906  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4907  		}
  4908  		switch ins.as {
  4909  		case AVMSGTVV:
  4910  			ins.as = AVMSLTVV
  4911  		case AVMSGTUVV:
  4912  			ins.as = AVMSLTUVV
  4913  		case AVMSGEVV:
  4914  			ins.as = AVMSLEVV
  4915  		case AVMSGEUVV:
  4916  			ins.as = AVMSLEUVV
  4917  		case AVMFGTVV:
  4918  			ins.as = AVMFLTVV
  4919  		case AVMFGEVV:
  4920  			ins.as = AVMFLEVV
  4921  		}
  4922  		ins.rd, ins.rs1, ins.rs2, ins.rs3 = uint32(p.To.Reg), uint32(p.Reg), uint32(p.From.Reg), obj.REG_NONE
  4923  
  4924  	case AVMSLTVI, AVMSLTUVI, AVMSGEVI, AVMSGEUVI:
  4925  		// Set mask bit
  4926  		switch {
  4927  		case ins.rs3 == obj.REG_NONE:
  4928  			ins.funct7 |= 1 // unmasked
  4929  		case ins.rs3 != REG_V0:
  4930  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4931  		}
  4932  		switch ins.as {
  4933  		case AVMSLTVI:
  4934  			ins.as = AVMSLEVI
  4935  		case AVMSLTUVI:
  4936  			ins.as = AVMSLEUVI
  4937  		case AVMSGEVI:
  4938  			ins.as = AVMSGTVI
  4939  		case AVMSGEUVI:
  4940  			ins.as = AVMSGTUVI
  4941  		}
  4942  		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
  4943  
  4944  	case AVFABSV, AVFNEGV:
  4945  		// Set mask bit
  4946  		switch {
  4947  		case ins.rs1 == obj.REG_NONE:
  4948  			ins.funct7 |= 1 // unmasked
  4949  		case ins.rs1 != REG_V0:
  4950  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4951  		}
  4952  		switch ins.as {
  4953  		case AVFABSV:
  4954  			ins.as = AVFSGNJXVV
  4955  		case AVFNEGV:
  4956  			ins.as = AVFSGNJNVV
  4957  		}
  4958  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.From.Reg)
  4959  
  4960  	case AVMANDMM, AVMNANDMM, AVMANDNMM, AVMXORMM, AVMORMM, AVMNORMM, AVMORNMM, AVMXNORMM, AVMMVM, AVMNOTM, AVCOMPRESSVM:
  4961  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), uint32(p.Reg)
  4962  		switch ins.as {
  4963  		case AVMMVM:
  4964  			ins.as, ins.rs2 = AVMANDMM, ins.rs1
  4965  		case AVMNOTM:
  4966  			ins.as, ins.rs2 = AVMNANDMM, ins.rs1
  4967  		}
  4968  
  4969  	case AVMCLRM, AVMSETM:
  4970  		ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.From.Reg), uint32(p.From.Reg)
  4971  		switch ins.as {
  4972  		case AVMCLRM:
  4973  			ins.as = AVMXORMM
  4974  		case AVMSETM:
  4975  			ins.as = AVMXNORMM
  4976  		}
  4977  
  4978  	case AVCPOPM, AVFIRSTM, AVMSBFM, AVMSIFM, AVMSOFM, AVIOTAM:
  4979  		// Set mask bit
  4980  		switch {
  4981  		case ins.rs1 == obj.REG_NONE:
  4982  			ins.funct7 |= 1 // unmasked
  4983  		case ins.rs1 != REG_V0:
  4984  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4985  		}
  4986  		ins.rs1 = obj.REG_NONE
  4987  
  4988  	case AVIDV:
  4989  		// Set mask bit
  4990  		switch {
  4991  		case ins.rd == obj.REG_NONE:
  4992  			ins.funct7 |= 1 // unmasked
  4993  		case ins.rd != obj.REG_NONE && ins.rs2 != REG_V0:
  4994  			p.Ctxt.Diag("%v: invalid vector mask register", p)
  4995  		}
  4996  		if ins.rd == obj.REG_NONE {
  4997  			ins.rd = uint32(p.From.Reg)
  4998  		}
  4999  		ins.rs1, ins.rs2 = obj.REG_NONE, REG_V0
  5000  	}
  5001  
  5002  	// Only compress instructions when there is no relocation, since
  5003  	// relocation relies on knowledge about the exact instructions that
  5004  	// are in use.
  5005  	if compress && p.Mark&NEED_RELOC == 0 {
  5006  		for _, ins := range inss {
  5007  			ins.compress()
  5008  		}
  5009  	}
  5010  
  5011  	for _, ins := range inss {
  5012  		ins.p = p
  5013  	}
  5014  
  5015  	return inss
  5016  }
  5017  
  5018  // assemble emits machine code.
  5019  // It is called at the very end of the assembly process.
  5020  func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
  5021  	if ctxt.Retpoline {
  5022  		ctxt.Diag("-spectre=ret not supported on riscv")
  5023  		ctxt.Retpoline = false // don't keep printing
  5024  	}
  5025  
  5026  	// If errors were encountered during preprocess/validation, proceeding
  5027  	// and attempting to encode said instructions will only lead to panics.
  5028  	if ctxt.Errors > 0 {
  5029  		return
  5030  	}
  5031  
  5032  	for p := cursym.Func().Text; p != nil; p = p.Link {
  5033  		switch p.As {
  5034  		case AJAL:
  5035  			if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC {
  5036  				cursym.AddRel(ctxt, obj.Reloc{
  5037  					Type: objabi.R_RISCV_JAL,
  5038  					Off:  int32(p.Pc),
  5039  					Siz:  4,
  5040  					Sym:  p.To.Sym,
  5041  					Add:  p.To.Offset,
  5042  				})
  5043  			}
  5044  
  5045  		case ACJALR, AJALR:
  5046  			if p.To.Sym != nil {
  5047  				ctxt.Diag("%v: unexpected AJALR with to symbol", p)
  5048  			}
  5049  
  5050  		case AAUIPC, AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
  5051  			var addr *obj.Addr
  5052  			var rt objabi.RelocType
  5053  			if p.Mark&NEED_CALL_RELOC == NEED_CALL_RELOC {
  5054  				rt = objabi.R_RISCV_CALL
  5055  				addr = &p.From
  5056  			} else if p.Mark&NEED_PCREL_ITYPE_RELOC == NEED_PCREL_ITYPE_RELOC {
  5057  				rt = objabi.R_RISCV_PCREL_ITYPE
  5058  				addr = &p.From
  5059  			} else if p.Mark&NEED_PCREL_STYPE_RELOC == NEED_PCREL_STYPE_RELOC {
  5060  				rt = objabi.R_RISCV_PCREL_STYPE
  5061  				addr = &p.To
  5062  			} else if p.Mark&NEED_GOT_PCREL_ITYPE_RELOC == NEED_GOT_PCREL_ITYPE_RELOC {
  5063  				rt = objabi.R_RISCV_GOT_PCREL_ITYPE
  5064  				addr = &p.From
  5065  			} else {
  5066  				break
  5067  			}
  5068  			if p.As == AAUIPC {
  5069  				if p.Link == nil {
  5070  					ctxt.Diag("AUIPC needing PC-relative reloc missing following instruction")
  5071  					break
  5072  				}
  5073  				addr = &p.RestArgs[0].Addr
  5074  			}
  5075  			if addr.Sym == nil {
  5076  				ctxt.Diag("PC-relative relocation missing symbol")
  5077  				break
  5078  			}
  5079  			if addr.Sym.Type == objabi.STLSBSS {
  5080  				if ctxt.Flag_shared {
  5081  					rt = objabi.R_RISCV_TLS_IE
  5082  				} else {
  5083  					rt = objabi.R_RISCV_TLS_LE
  5084  				}
  5085  			}
  5086  
  5087  			cursym.AddRel(ctxt, obj.Reloc{
  5088  				Type: rt,
  5089  				Off:  int32(p.Pc),
  5090  				Siz:  8,
  5091  				Sym:  addr.Sym,
  5092  				Add:  addr.Offset,
  5093  			})
  5094  
  5095  		case obj.APCALIGN:
  5096  			alignedValue := p.From.Offset
  5097  			v := pcAlignPadLength(p.Pc, alignedValue)
  5098  			offset := p.Pc
  5099  			for ; v >= 4; v -= 4 {
  5100  				// NOP (ADDI $0, X0, X0)
  5101  				cursym.WriteBytes(ctxt, offset, []byte{0x13, 0x00, 0x00, 0x00})
  5102  				offset += 4
  5103  			}
  5104  			if v == 2 {
  5105  				// CNOP
  5106  				cursym.WriteBytes(ctxt, offset, []byte{0x01, 0x00})
  5107  				offset += 2
  5108  			} else if v != 0 {
  5109  				ctxt.Diag("bad PCALIGN pad length")
  5110  			}
  5111  			continue
  5112  		}
  5113  
  5114  		offset := p.Pc
  5115  		for _, ins := range instructionsForProg(p, ctxt.CompressInstructions) {
  5116  			if ic, err := ins.encode(); err == nil {
  5117  				cursym.WriteInt(ctxt, offset, ins.length(), int64(ic))
  5118  				offset += int64(ins.length())
  5119  			}
  5120  			if ins.usesRegTmp() {
  5121  				p.Mark |= USES_REG_TMP
  5122  			}
  5123  		}
  5124  	}
  5125  
  5126  	obj.MarkUnsafePoints(ctxt, cursym.Func().Text, newprog, isUnsafePoint, nil)
  5127  }
  5128  
  5129  func isUnsafePoint(p *obj.Prog) bool {
  5130  	return p.Mark&USES_REG_TMP == USES_REG_TMP || p.From.Reg == REG_TMP || p.To.Reg == REG_TMP || p.Reg == REG_TMP
  5131  }
  5132  
  5133  func ParseSuffix(prog *obj.Prog, cond string) (err error) {
  5134  	cond = strings.TrimPrefix(cond, ".")
  5135  	switch prog.As {
  5136  	case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
  5137  		prog.Scond, err = rmSuffixEncode(cond)
  5138  	case AFENCE:
  5139  		if cond == "TSO" {
  5140  			prog.Scond = fenceTsoSuffixBit
  5141  		} else {
  5142  			err = fmt.Errorf("unrecognized suffix .%q", cond)
  5143  		}
  5144  	default:
  5145  		if cond != "" {
  5146  			err = fmt.Errorf("unrecognized suffix .%q", cond)
  5147  		}
  5148  	}
  5149  	return
  5150  }
  5151  
  5152  var LinkRISCV64 = obj.LinkArch{
  5153  	Arch:           sys.ArchRISCV64,
  5154  	Init:           buildop,
  5155  	Preprocess:     preprocess,
  5156  	Assemble:       assemble,
  5157  	Progedit:       progedit,
  5158  	UnaryDst:       unaryDst,
  5159  	DWARFRegisters: RISCV64DWARFRegisters,
  5160  }
  5161  

View as plain text