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

View as plain text