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

View as plain text