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

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

View as plain text