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  
    57  	// Expand binary instructions to ternary ones.
    58  	if p.Reg == obj.REG_NONE {
    59  		switch p.As {
    60  		case AADDI, ASLTI, ASLTIU, AANDI, AORI, AXORI, ASLLI, ASRLI, ASRAI,
    61  			AADDIW, ASLLIW, ASRLIW, ASRAIW, AADDW, ASUBW, ASLLW, ASRLW, ASRAW,
    62  			AADD, AAND, AOR, AXOR, ASLL, ASRL, ASUB, ASRA,
    63  			AMUL, AMULH, AMULHU, AMULHSU, AMULW, ADIV, ADIVU, ADIVW, ADIVUW,
    64  			AREM, AREMU, AREMW, AREMUW,
    65  			AADDUW, ASH1ADD, ASH1ADDUW, ASH2ADD, ASH2ADDUW, ASH3ADD, ASH3ADDUW, ASLLIUW,
    66  			AANDN, AORN, AXNOR, AMAX, AMAXU, AMIN, AMINU, AROL, AROLW, AROR, ARORW, ARORI, ARORIW,
    67  			ABCLR, ABCLRI, ABEXT, ABEXTI, ABINV, ABINVI, ABSET, ABSETI:
    68  			p.Reg = p.To.Reg
    69  		}
    70  	}
    71  
    72  	// Rewrite instructions with constant operands to refer to the immediate
    73  	// form of the instruction.
    74  	if p.From.Type == obj.TYPE_CONST {
    75  		switch p.As {
    76  		case AADD:
    77  			p.As = AADDI
    78  		case ASUB:
    79  			p.As, p.From.Offset = AADDI, -p.From.Offset
    80  		case ASLT:
    81  			p.As = ASLTI
    82  		case ASLTU:
    83  			p.As = ASLTIU
    84  		case AAND:
    85  			p.As = AANDI
    86  		case AOR:
    87  			p.As = AORI
    88  		case AXOR:
    89  			p.As = AXORI
    90  		case ASLL:
    91  			p.As = ASLLI
    92  		case ASRL:
    93  			p.As = ASRLI
    94  		case ASRA:
    95  			p.As = ASRAI
    96  		case AADDW:
    97  			p.As = AADDIW
    98  		case ASUBW:
    99  			p.As, p.From.Offset = AADDIW, -p.From.Offset
   100  		case ASLLW:
   101  			p.As = ASLLIW
   102  		case ASRLW:
   103  			p.As = ASRLIW
   104  		case ASRAW:
   105  			p.As = ASRAIW
   106  		case AROR:
   107  			p.As = ARORI
   108  		case ARORW:
   109  			p.As = ARORIW
   110  		case ABCLR:
   111  			p.As = ABCLRI
   112  		case ABEXT:
   113  			p.As = ABEXTI
   114  		case ABINV:
   115  			p.As = ABINVI
   116  		case ABSET:
   117  			p.As = ABSETI
   118  		}
   119  	}
   120  
   121  	switch p.As {
   122  	case obj.AJMP:
   123  		// Turn JMP into JAL ZERO or JALR ZERO.
   124  		p.From.Type = obj.TYPE_REG
   125  		p.From.Reg = REG_ZERO
   126  
   127  		switch p.To.Type {
   128  		case obj.TYPE_BRANCH:
   129  			p.As = AJAL
   130  		case obj.TYPE_MEM:
   131  			switch p.To.Name {
   132  			case obj.NAME_NONE:
   133  				p.As = AJALR
   134  			case obj.NAME_EXTERN, obj.NAME_STATIC:
   135  				// Handled in preprocess.
   136  			default:
   137  				ctxt.Diag("unsupported name %d for %v", p.To.Name, p)
   138  			}
   139  		default:
   140  			panic(fmt.Sprintf("unhandled type %+v", p.To.Type))
   141  		}
   142  
   143  	case obj.ACALL:
   144  		switch p.To.Type {
   145  		case obj.TYPE_MEM:
   146  			// Handled in preprocess.
   147  		case obj.TYPE_REG:
   148  			p.As = AJALR
   149  			p.From.Type = obj.TYPE_REG
   150  			p.From.Reg = REG_LR
   151  		default:
   152  			ctxt.Diag("unknown destination type %+v in CALL: %v", p.To.Type, p)
   153  		}
   154  
   155  	case obj.AUNDEF:
   156  		p.As = AEBREAK
   157  
   158  	case AFMVXS:
   159  		// FMVXS is the old name for FMVXW.
   160  		p.As = AFMVXW
   161  
   162  	case AFMVSX:
   163  		// FMVSX is the old name for FMVWX.
   164  		p.As = AFMVWX
   165  
   166  	case ASCALL:
   167  		// SCALL is the old name for ECALL.
   168  		p.As = AECALL
   169  
   170  	case ASBREAK:
   171  		// SBREAK is the old name for EBREAK.
   172  		p.As = AEBREAK
   173  
   174  	case AMOV:
   175  		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 {
   176  			ctz := bits.TrailingZeros64(uint64(p.From.Offset))
   177  			val := p.From.Offset >> ctz
   178  			if int64(int32(val)) == val {
   179  				// It's ok. We can handle constants with many trailing zeros.
   180  				break
   181  			}
   182  			// Put >32-bit constants in memory and load them.
   183  			p.From.Type = obj.TYPE_MEM
   184  			p.From.Sym = ctxt.Int64Sym(p.From.Offset)
   185  			p.From.Name = obj.NAME_EXTERN
   186  			p.From.Offset = 0
   187  		}
   188  	}
   189  }
   190  
   191  // addrToReg extracts the register from an Addr, handling special Addr.Names.
   192  func addrToReg(a obj.Addr) int16 {
   193  	switch a.Name {
   194  	case obj.NAME_PARAM, obj.NAME_AUTO:
   195  		return REG_SP
   196  	}
   197  	return a.Reg
   198  }
   199  
   200  // movToLoad converts a MOV mnemonic into the corresponding load instruction.
   201  func movToLoad(mnemonic obj.As) obj.As {
   202  	switch mnemonic {
   203  	case AMOV:
   204  		return ALD
   205  	case AMOVB:
   206  		return ALB
   207  	case AMOVH:
   208  		return ALH
   209  	case AMOVW:
   210  		return ALW
   211  	case AMOVBU:
   212  		return ALBU
   213  	case AMOVHU:
   214  		return ALHU
   215  	case AMOVWU:
   216  		return ALWU
   217  	case AMOVF:
   218  		return AFLW
   219  	case AMOVD:
   220  		return AFLD
   221  	default:
   222  		panic(fmt.Sprintf("%+v is not a MOV", mnemonic))
   223  	}
   224  }
   225  
   226  // movToStore converts a MOV mnemonic into the corresponding store instruction.
   227  func movToStore(mnemonic obj.As) obj.As {
   228  	switch mnemonic {
   229  	case AMOV:
   230  		return ASD
   231  	case AMOVB:
   232  		return ASB
   233  	case AMOVH:
   234  		return ASH
   235  	case AMOVW:
   236  		return ASW
   237  	case AMOVF:
   238  		return AFSW
   239  	case AMOVD:
   240  		return AFSD
   241  	default:
   242  		panic(fmt.Sprintf("%+v is not a MOV", mnemonic))
   243  	}
   244  }
   245  
   246  // markRelocs marks an obj.Prog that specifies a MOV pseudo-instruction and
   247  // requires relocation.
   248  func markRelocs(p *obj.Prog) {
   249  	switch p.As {
   250  	case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
   251  		switch {
   252  		case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG:
   253  			switch p.From.Name {
   254  			case obj.NAME_EXTERN, obj.NAME_STATIC:
   255  				p.Mark |= NEED_PCREL_ITYPE_RELOC
   256  			}
   257  		case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG:
   258  			switch p.From.Name {
   259  			case obj.NAME_EXTERN, obj.NAME_STATIC:
   260  				p.Mark |= NEED_PCREL_ITYPE_RELOC
   261  			}
   262  		case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM:
   263  			switch p.To.Name {
   264  			case obj.NAME_EXTERN, obj.NAME_STATIC:
   265  				p.Mark |= NEED_PCREL_STYPE_RELOC
   266  			}
   267  		}
   268  	}
   269  }
   270  
   271  // InvertBranch inverts the condition of a conditional branch.
   272  func InvertBranch(as obj.As) obj.As {
   273  	switch as {
   274  	case ABEQ:
   275  		return ABNE
   276  	case ABEQZ:
   277  		return ABNEZ
   278  	case ABGE:
   279  		return ABLT
   280  	case ABGEU:
   281  		return ABLTU
   282  	case ABGEZ:
   283  		return ABLTZ
   284  	case ABGT:
   285  		return ABLE
   286  	case ABGTU:
   287  		return ABLEU
   288  	case ABGTZ:
   289  		return ABLEZ
   290  	case ABLE:
   291  		return ABGT
   292  	case ABLEU:
   293  		return ABGTU
   294  	case ABLEZ:
   295  		return ABGTZ
   296  	case ABLT:
   297  		return ABGE
   298  	case ABLTU:
   299  		return ABGEU
   300  	case ABLTZ:
   301  		return ABGEZ
   302  	case ABNE:
   303  		return ABEQ
   304  	case ABNEZ:
   305  		return ABEQZ
   306  	default:
   307  		panic("InvertBranch: not a branch")
   308  	}
   309  }
   310  
   311  // containsCall reports whether the symbol contains a CALL (or equivalent)
   312  // instruction. Must be called after progedit.
   313  func containsCall(sym *obj.LSym) bool {
   314  	// CALLs are CALL or JAL(R) with link register LR.
   315  	for p := sym.Func().Text; p != nil; p = p.Link {
   316  		switch p.As {
   317  		case obj.ACALL, obj.ADUFFZERO, obj.ADUFFCOPY:
   318  			return true
   319  		case AJAL, AJALR:
   320  			if p.From.Type == obj.TYPE_REG && p.From.Reg == REG_LR {
   321  				return true
   322  			}
   323  		}
   324  	}
   325  
   326  	return false
   327  }
   328  
   329  // setPCs sets the Pc field in all instructions reachable from p.
   330  // It uses pc as the initial value and returns the next available pc.
   331  func setPCs(p *obj.Prog, pc int64) int64 {
   332  	for ; p != nil; p = p.Link {
   333  		p.Pc = pc
   334  		for _, ins := range instructionsForProg(p) {
   335  			pc += int64(ins.length())
   336  		}
   337  
   338  		if p.As == obj.APCALIGN {
   339  			alignedValue := p.From.Offset
   340  			v := pcAlignPadLength(pc, alignedValue)
   341  			pc += int64(v)
   342  		}
   343  	}
   344  	return pc
   345  }
   346  
   347  // stackOffset updates Addr offsets based on the current stack size.
   348  //
   349  // The stack looks like:
   350  // -------------------
   351  // |                 |
   352  // |      PARAMs     |
   353  // |                 |
   354  // |                 |
   355  // -------------------
   356  // |    Parent RA    |   SP on function entry
   357  // -------------------
   358  // |                 |
   359  // |                 |
   360  // |       AUTOs     |
   361  // |                 |
   362  // |                 |
   363  // -------------------
   364  // |        RA       |   SP during function execution
   365  // -------------------
   366  //
   367  // FixedFrameSize makes other packages aware of the space allocated for RA.
   368  //
   369  // A nicer version of this diagram can be found on slide 21 of the presentation
   370  // attached to https://golang.org/issue/16922#issuecomment-243748180.
   371  func stackOffset(a *obj.Addr, stacksize int64) {
   372  	switch a.Name {
   373  	case obj.NAME_AUTO:
   374  		// Adjust to the top of AUTOs.
   375  		a.Offset += stacksize
   376  	case obj.NAME_PARAM:
   377  		// Adjust to the bottom of PARAMs.
   378  		a.Offset += stacksize + 8
   379  	}
   380  }
   381  
   382  // preprocess generates prologue and epilogue code, computes PC-relative branch
   383  // and jump offsets, and resolves pseudo-registers.
   384  //
   385  // preprocess is called once per linker symbol.
   386  //
   387  // When preprocess finishes, all instructions in the symbol are either
   388  // concrete, real RISC-V instructions or directive pseudo-ops like TEXT,
   389  // PCDATA, and FUNCDATA.
   390  func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
   391  	if cursym.Func().Text == nil || cursym.Func().Text.Link == nil {
   392  		return
   393  	}
   394  
   395  	// Generate the prologue.
   396  	text := cursym.Func().Text
   397  	if text.As != obj.ATEXT {
   398  		ctxt.Diag("preprocess: found symbol that does not start with TEXT directive")
   399  		return
   400  	}
   401  
   402  	stacksize := text.To.Offset
   403  	if stacksize == -8 {
   404  		// Historical way to mark NOFRAME.
   405  		text.From.Sym.Set(obj.AttrNoFrame, true)
   406  		stacksize = 0
   407  	}
   408  	if stacksize < 0 {
   409  		ctxt.Diag("negative frame size %d - did you mean NOFRAME?", stacksize)
   410  	}
   411  	if text.From.Sym.NoFrame() {
   412  		if stacksize != 0 {
   413  			ctxt.Diag("NOFRAME functions must have a frame size of 0, not %d", stacksize)
   414  		}
   415  	}
   416  
   417  	if !containsCall(cursym) {
   418  		text.From.Sym.Set(obj.AttrLeaf, true)
   419  		if stacksize == 0 {
   420  			// A leaf function with no locals has no frame.
   421  			text.From.Sym.Set(obj.AttrNoFrame, true)
   422  		}
   423  	}
   424  
   425  	// Save LR unless there is no frame.
   426  	if !text.From.Sym.NoFrame() {
   427  		stacksize += ctxt.Arch.FixedFrameSize
   428  	}
   429  
   430  	cursym.Func().Args = text.To.Val.(int32)
   431  	cursym.Func().Locals = int32(stacksize)
   432  
   433  	prologue := text
   434  
   435  	if !cursym.Func().Text.From.Sym.NoSplit() {
   436  		prologue = stacksplit(ctxt, prologue, cursym, newprog, stacksize) // emit split check
   437  	}
   438  
   439  	q := prologue
   440  
   441  	if stacksize != 0 {
   442  		prologue = ctxt.StartUnsafePoint(prologue, newprog)
   443  
   444  		// Actually save LR.
   445  		prologue = obj.Appendp(prologue, newprog)
   446  		prologue.As = AMOV
   447  		prologue.Pos = q.Pos
   448  		prologue.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
   449  		prologue.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: -stacksize}
   450  
   451  		// Insert stack adjustment.
   452  		prologue = obj.Appendp(prologue, newprog)
   453  		prologue.As = AADDI
   454  		prologue.Pos = q.Pos
   455  		prologue.Pos = prologue.Pos.WithXlogue(src.PosPrologueEnd)
   456  		prologue.From = obj.Addr{Type: obj.TYPE_CONST, Offset: -stacksize}
   457  		prologue.Reg = REG_SP
   458  		prologue.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
   459  		prologue.Spadj = int32(stacksize)
   460  
   461  		prologue = ctxt.EndUnsafePoint(prologue, newprog, -1)
   462  
   463  		// On Linux, in a cgo binary we may get a SIGSETXID signal early on
   464  		// before the signal stack is set, as glibc doesn't allow us to block
   465  		// SIGSETXID. So a signal may land on the current stack and clobber
   466  		// the content below the SP. We store the LR again after the SP is
   467  		// decremented.
   468  		prologue = obj.Appendp(prologue, newprog)
   469  		prologue.As = AMOV
   470  		prologue.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
   471  		prologue.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0}
   472  	}
   473  
   474  	if cursym.Func().Text.From.Sym.Wrapper() {
   475  		// if(g->panic != nil && g->panic->argp == FP) g->panic->argp = bottom-of-frame
   476  		//
   477  		//   MOV g_panic(g), X5
   478  		//   BNE X5, ZERO, adjust
   479  		// end:
   480  		//   NOP
   481  		// ...rest of function..
   482  		// adjust:
   483  		//   MOV panic_argp(X5), X6
   484  		//   ADD $(autosize+FIXED_FRAME), SP, X7
   485  		//   BNE X6, X7, end
   486  		//   ADD $FIXED_FRAME, SP, X6
   487  		//   MOV X6, panic_argp(X5)
   488  		//   JMP end
   489  		//
   490  		// The NOP is needed to give the jumps somewhere to land.
   491  
   492  		ldpanic := obj.Appendp(prologue, newprog)
   493  
   494  		ldpanic.As = AMOV
   495  		ldpanic.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REGG, Offset: 4 * int64(ctxt.Arch.PtrSize)} // G.panic
   496  		ldpanic.Reg = obj.REG_NONE
   497  		ldpanic.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X5}
   498  
   499  		bneadj := obj.Appendp(ldpanic, newprog)
   500  		bneadj.As = ABNE
   501  		bneadj.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X5}
   502  		bneadj.Reg = REG_ZERO
   503  		bneadj.To.Type = obj.TYPE_BRANCH
   504  
   505  		endadj := obj.Appendp(bneadj, newprog)
   506  		endadj.As = obj.ANOP
   507  
   508  		last := endadj
   509  		for last.Link != nil {
   510  			last = last.Link
   511  		}
   512  
   513  		getargp := obj.Appendp(last, newprog)
   514  		getargp.As = AMOV
   515  		getargp.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_X5, Offset: 0} // Panic.argp
   516  		getargp.Reg = obj.REG_NONE
   517  		getargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X6}
   518  
   519  		bneadj.To.SetTarget(getargp)
   520  
   521  		calcargp := obj.Appendp(getargp, newprog)
   522  		calcargp.As = AADDI
   523  		calcargp.From = obj.Addr{Type: obj.TYPE_CONST, Offset: stacksize + ctxt.Arch.FixedFrameSize}
   524  		calcargp.Reg = REG_SP
   525  		calcargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X7}
   526  
   527  		testargp := obj.Appendp(calcargp, newprog)
   528  		testargp.As = ABNE
   529  		testargp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X6}
   530  		testargp.Reg = REG_X7
   531  		testargp.To.Type = obj.TYPE_BRANCH
   532  		testargp.To.SetTarget(endadj)
   533  
   534  		adjargp := obj.Appendp(testargp, newprog)
   535  		adjargp.As = AADDI
   536  		adjargp.From = obj.Addr{Type: obj.TYPE_CONST, Offset: int64(ctxt.Arch.PtrSize)}
   537  		adjargp.Reg = REG_SP
   538  		adjargp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X6}
   539  
   540  		setargp := obj.Appendp(adjargp, newprog)
   541  		setargp.As = AMOV
   542  		setargp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_X6}
   543  		setargp.Reg = obj.REG_NONE
   544  		setargp.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_X5, Offset: 0} // Panic.argp
   545  
   546  		godone := obj.Appendp(setargp, newprog)
   547  		godone.As = AJAL
   548  		godone.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
   549  		godone.To.Type = obj.TYPE_BRANCH
   550  		godone.To.SetTarget(endadj)
   551  	}
   552  
   553  	// Update stack-based offsets.
   554  	for p := cursym.Func().Text; p != nil; p = p.Link {
   555  		stackOffset(&p.From, stacksize)
   556  		stackOffset(&p.To, stacksize)
   557  	}
   558  
   559  	// Additional instruction rewriting.
   560  	for p := cursym.Func().Text; p != nil; p = p.Link {
   561  		switch p.As {
   562  		case obj.AGETCALLERPC:
   563  			if cursym.Leaf() {
   564  				// MOV LR, Rd
   565  				p.As = AMOV
   566  				p.From.Type = obj.TYPE_REG
   567  				p.From.Reg = REG_LR
   568  			} else {
   569  				// MOV (RSP), Rd
   570  				p.As = AMOV
   571  				p.From.Type = obj.TYPE_MEM
   572  				p.From.Reg = REG_SP
   573  			}
   574  
   575  		case obj.ACALL, obj.ADUFFZERO, obj.ADUFFCOPY:
   576  			switch p.To.Type {
   577  			case obj.TYPE_MEM:
   578  				jalToSym(ctxt, p, REG_LR)
   579  			}
   580  
   581  		case obj.AJMP:
   582  			switch p.To.Type {
   583  			case obj.TYPE_MEM:
   584  				switch p.To.Name {
   585  				case obj.NAME_EXTERN, obj.NAME_STATIC:
   586  					jalToSym(ctxt, p, REG_ZERO)
   587  				}
   588  			}
   589  
   590  		case obj.ARET:
   591  			// Replace RET with epilogue.
   592  			retJMP := p.To.Sym
   593  
   594  			if stacksize != 0 {
   595  				// Restore LR.
   596  				p.As = AMOV
   597  				p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0}
   598  				p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
   599  				p = obj.Appendp(p, newprog)
   600  
   601  				p.As = AADDI
   602  				p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: stacksize}
   603  				p.Reg = REG_SP
   604  				p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
   605  				p.Spadj = int32(-stacksize)
   606  				p = obj.Appendp(p, newprog)
   607  			}
   608  
   609  			if retJMP != nil {
   610  				p.As = obj.ARET
   611  				p.To.Sym = retJMP
   612  				jalToSym(ctxt, p, REG_ZERO)
   613  			} else {
   614  				p.As = AJALR
   615  				p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
   616  				p.Reg = obj.REG_NONE
   617  				p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
   618  			}
   619  
   620  			// "Add back" the stack removed in the previous instruction.
   621  			//
   622  			// This is to avoid confusing pctospadj, which sums
   623  			// Spadj from function entry to each PC, and shouldn't
   624  			// count adjustments from earlier epilogues, since they
   625  			// won't affect later PCs.
   626  			p.Spadj = int32(stacksize)
   627  
   628  		case AADDI:
   629  			// Refine Spadjs account for adjustment via ADDI instruction.
   630  			if p.To.Type == obj.TYPE_REG && p.To.Reg == REG_SP && p.From.Type == obj.TYPE_CONST {
   631  				p.Spadj = int32(-p.From.Offset)
   632  			}
   633  		}
   634  
   635  		if p.To.Type == obj.TYPE_REG && p.To.Reg == REGSP && p.Spadj == 0 {
   636  			f := cursym.Func()
   637  			if f.FuncFlag&abi.FuncFlagSPWrite == 0 {
   638  				f.FuncFlag |= abi.FuncFlagSPWrite
   639  				if ctxt.Debugvlog || !ctxt.IsAsm {
   640  					ctxt.Logf("auto-SPWRITE: %s %v\n", cursym.Name, p)
   641  					if !ctxt.IsAsm {
   642  						ctxt.Diag("invalid auto-SPWRITE in non-assembly")
   643  						ctxt.DiagFlush()
   644  						log.Fatalf("bad SPWRITE")
   645  					}
   646  				}
   647  			}
   648  		}
   649  	}
   650  
   651  	var callCount int
   652  	for p := cursym.Func().Text; p != nil; p = p.Link {
   653  		markRelocs(p)
   654  		if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC {
   655  			callCount++
   656  		}
   657  	}
   658  	const callTrampSize = 8 // 2 machine instructions.
   659  	maxTrampSize := int64(callCount * callTrampSize)
   660  
   661  	// Compute instruction addresses.  Once we do that, we need to check for
   662  	// overextended jumps and branches.  Within each iteration, Pc differences
   663  	// are always lower bounds (since the program gets monotonically longer,
   664  	// a fixed point will be reached).  No attempt to handle functions > 2GiB.
   665  	for {
   666  		big, rescan := false, false
   667  		maxPC := setPCs(cursym.Func().Text, 0)
   668  		if maxPC+maxTrampSize > (1 << 20) {
   669  			big = true
   670  		}
   671  
   672  		for p := cursym.Func().Text; p != nil; p = p.Link {
   673  			switch p.As {
   674  			case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ:
   675  				if p.To.Type != obj.TYPE_BRANCH {
   676  					panic("assemble: instruction with branch-like opcode lacks destination")
   677  				}
   678  				offset := p.To.Target().Pc - p.Pc
   679  				if offset < -4096 || 4096 <= offset {
   680  					// Branch is long.  Replace it with a jump.
   681  					jmp := obj.Appendp(p, newprog)
   682  					jmp.As = AJAL
   683  					jmp.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
   684  					jmp.To = obj.Addr{Type: obj.TYPE_BRANCH}
   685  					jmp.To.SetTarget(p.To.Target())
   686  
   687  					p.As = InvertBranch(p.As)
   688  					p.To.SetTarget(jmp.Link)
   689  
   690  					// We may have made previous branches too long,
   691  					// so recheck them.
   692  					rescan = true
   693  				}
   694  			case AJAL:
   695  				// Linker will handle the intersymbol case and trampolines.
   696  				if p.To.Target() == nil {
   697  					if !big {
   698  						break
   699  					}
   700  					// This function is going to be too large for JALs
   701  					// to reach trampolines. Replace with AUIPC+JALR.
   702  					jmp := obj.Appendp(p, newprog)
   703  					jmp.As = AJALR
   704  					jmp.From = p.From
   705  					jmp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
   706  
   707  					p.As = AAUIPC
   708  					p.Mark = (p.Mark &^ NEED_JAL_RELOC) | NEED_CALL_RELOC
   709  					p.AddRestSource(obj.Addr{Type: obj.TYPE_CONST, Offset: p.To.Offset, Sym: p.To.Sym})
   710  					p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: 0}
   711  					p.Reg = obj.REG_NONE
   712  					p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
   713  
   714  					rescan = true
   715  					break
   716  				}
   717  				offset := p.To.Target().Pc - p.Pc
   718  				if offset < -(1<<20) || (1<<20) <= offset {
   719  					// Replace with 2-instruction sequence. This assumes
   720  					// that TMP is not live across J instructions, since
   721  					// it is reserved by SSA.
   722  					jmp := obj.Appendp(p, newprog)
   723  					jmp.As = AJALR
   724  					jmp.From = p.From
   725  					jmp.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
   726  
   727  					// p.From is not generally valid, however will be
   728  					// fixed up in the next loop.
   729  					p.As = AAUIPC
   730  					p.From = obj.Addr{Type: obj.TYPE_BRANCH, Sym: p.From.Sym}
   731  					p.From.SetTarget(p.To.Target())
   732  					p.Reg = obj.REG_NONE
   733  					p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
   734  
   735  					rescan = true
   736  				}
   737  			}
   738  		}
   739  
   740  		if !rescan {
   741  			break
   742  		}
   743  	}
   744  
   745  	// Now that there are no long branches, resolve branch and jump targets.
   746  	// At this point, instruction rewriting which changes the number of
   747  	// instructions will break everything--don't do it!
   748  	for p := cursym.Func().Text; p != nil; p = p.Link {
   749  		switch p.As {
   750  		case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ:
   751  			switch p.To.Type {
   752  			case obj.TYPE_BRANCH:
   753  				p.To.Type, p.To.Offset = obj.TYPE_CONST, p.To.Target().Pc-p.Pc
   754  			case obj.TYPE_MEM:
   755  				panic("unhandled type")
   756  			}
   757  
   758  		case AJAL:
   759  			// Linker will handle the intersymbol case and trampolines.
   760  			if p.To.Target() != nil {
   761  				p.To.Type, p.To.Offset = obj.TYPE_CONST, p.To.Target().Pc-p.Pc
   762  			}
   763  
   764  		case AAUIPC:
   765  			if p.From.Type == obj.TYPE_BRANCH {
   766  				low, high, err := Split32BitImmediate(p.From.Target().Pc - p.Pc)
   767  				if err != nil {
   768  					ctxt.Diag("%v: jump displacement %d too large", p, p.To.Target().Pc-p.Pc)
   769  				}
   770  				p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high, Sym: cursym}
   771  				p.Link.To.Offset = low
   772  			}
   773  
   774  		case obj.APCALIGN:
   775  			alignedValue := p.From.Offset
   776  			if (alignedValue&(alignedValue-1) != 0) || 4 > alignedValue || alignedValue > 2048 {
   777  				ctxt.Diag("alignment value of an instruction must be a power of two and in the range [4, 2048], got %d\n", alignedValue)
   778  			}
   779  			// Update the current text symbol alignment value.
   780  			if int32(alignedValue) > cursym.Func().Align {
   781  				cursym.Func().Align = int32(alignedValue)
   782  			}
   783  		}
   784  	}
   785  
   786  	// Validate all instructions - this provides nice error messages.
   787  	for p := cursym.Func().Text; p != nil; p = p.Link {
   788  		for _, ins := range instructionsForProg(p) {
   789  			ins.validate(ctxt)
   790  		}
   791  	}
   792  }
   793  
   794  func pcAlignPadLength(pc int64, alignedValue int64) int {
   795  	return int(-pc & (alignedValue - 1))
   796  }
   797  
   798  func stacksplit(ctxt *obj.Link, p *obj.Prog, cursym *obj.LSym, newprog obj.ProgAlloc, framesize int64) *obj.Prog {
   799  	// Leaf function with no frame is effectively NOSPLIT.
   800  	if framesize == 0 {
   801  		return p
   802  	}
   803  
   804  	if ctxt.Flag_maymorestack != "" {
   805  		// Save LR and REGCTXT
   806  		const frameSize = 16
   807  		p = ctxt.StartUnsafePoint(p, newprog)
   808  
   809  		// Spill Arguments. This has to happen before we open
   810  		// any more frame space.
   811  		p = cursym.Func().SpillRegisterArgs(p, newprog)
   812  
   813  		// MOV LR, -16(SP)
   814  		p = obj.Appendp(p, newprog)
   815  		p.As = AMOV
   816  		p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
   817  		p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: -frameSize}
   818  		// ADDI $-16, SP
   819  		p = obj.Appendp(p, newprog)
   820  		p.As = AADDI
   821  		p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: -frameSize}
   822  		p.Reg = REG_SP
   823  		p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
   824  		p.Spadj = frameSize
   825  		// MOV REGCTXT, 8(SP)
   826  		p = obj.Appendp(p, newprog)
   827  		p.As = AMOV
   828  		p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_CTXT}
   829  		p.To = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 8}
   830  
   831  		// CALL maymorestack
   832  		p = obj.Appendp(p, newprog)
   833  		p.As = obj.ACALL
   834  		p.To.Type = obj.TYPE_BRANCH
   835  		// See ../x86/obj6.go
   836  		p.To.Sym = ctxt.LookupABI(ctxt.Flag_maymorestack, cursym.ABI())
   837  		jalToSym(ctxt, p, REG_X5)
   838  
   839  		// Restore LR and REGCTXT
   840  
   841  		// MOV 8(SP), REGCTXT
   842  		p = obj.Appendp(p, newprog)
   843  		p.As = AMOV
   844  		p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 8}
   845  		p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_CTXT}
   846  		// MOV (SP), LR
   847  		p = obj.Appendp(p, newprog)
   848  		p.As = AMOV
   849  		p.From = obj.Addr{Type: obj.TYPE_MEM, Reg: REG_SP, Offset: 0}
   850  		p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_LR}
   851  		// ADDI $16, SP
   852  		p = obj.Appendp(p, newprog)
   853  		p.As = AADDI
   854  		p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: frameSize}
   855  		p.Reg = REG_SP
   856  		p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_SP}
   857  		p.Spadj = -frameSize
   858  
   859  		// Unspill arguments
   860  		p = cursym.Func().UnspillRegisterArgs(p, newprog)
   861  		p = ctxt.EndUnsafePoint(p, newprog, -1)
   862  	}
   863  
   864  	// Jump back to here after morestack returns.
   865  	startPred := p
   866  
   867  	// MOV	g_stackguard(g), X6
   868  	p = obj.Appendp(p, newprog)
   869  	p.As = AMOV
   870  	p.From.Type = obj.TYPE_MEM
   871  	p.From.Reg = REGG
   872  	p.From.Offset = 2 * int64(ctxt.Arch.PtrSize) // G.stackguard0
   873  	if cursym.CFunc() {
   874  		p.From.Offset = 3 * int64(ctxt.Arch.PtrSize) // G.stackguard1
   875  	}
   876  	p.To.Type = obj.TYPE_REG
   877  	p.To.Reg = REG_X6
   878  
   879  	// Mark the stack bound check and morestack call async nonpreemptible.
   880  	// If we get preempted here, when resumed the preemption request is
   881  	// cleared, but we'll still call morestack, which will double the stack
   882  	// unnecessarily. See issue #35470.
   883  	p = ctxt.StartUnsafePoint(p, newprog)
   884  
   885  	var to_done, to_more *obj.Prog
   886  
   887  	if framesize <= abi.StackSmall {
   888  		// small stack
   889  		//	// if SP > stackguard { goto done }
   890  		//	BLTU	stackguard, SP, done
   891  		p = obj.Appendp(p, newprog)
   892  		p.As = ABLTU
   893  		p.From.Type = obj.TYPE_REG
   894  		p.From.Reg = REG_X6
   895  		p.Reg = REG_SP
   896  		p.To.Type = obj.TYPE_BRANCH
   897  		to_done = p
   898  	} else {
   899  		// large stack: SP-framesize < stackguard-StackSmall
   900  		offset := int64(framesize) - abi.StackSmall
   901  		if framesize > abi.StackBig {
   902  			// Such a large stack we need to protect against underflow.
   903  			// The runtime guarantees SP > objabi.StackBig, but
   904  			// framesize is large enough that SP-framesize may
   905  			// underflow, causing a direct comparison with the
   906  			// stack guard to incorrectly succeed. We explicitly
   907  			// guard against underflow.
   908  			//
   909  			//	MOV	$(framesize-StackSmall), X7
   910  			//	BLTU	SP, X7, label-of-call-to-morestack
   911  
   912  			p = obj.Appendp(p, newprog)
   913  			p.As = AMOV
   914  			p.From.Type = obj.TYPE_CONST
   915  			p.From.Offset = offset
   916  			p.To.Type = obj.TYPE_REG
   917  			p.To.Reg = REG_X7
   918  
   919  			p = obj.Appendp(p, newprog)
   920  			p.As = ABLTU
   921  			p.From.Type = obj.TYPE_REG
   922  			p.From.Reg = REG_SP
   923  			p.Reg = REG_X7
   924  			p.To.Type = obj.TYPE_BRANCH
   925  			to_more = p
   926  		}
   927  
   928  		// Check against the stack guard. We've ensured this won't underflow.
   929  		//	ADD	$-(framesize-StackSmall), SP, X7
   930  		//	// if X7 > stackguard { goto done }
   931  		//	BLTU	stackguard, X7, done
   932  		p = obj.Appendp(p, newprog)
   933  		p.As = AADDI
   934  		p.From.Type = obj.TYPE_CONST
   935  		p.From.Offset = -offset
   936  		p.Reg = REG_SP
   937  		p.To.Type = obj.TYPE_REG
   938  		p.To.Reg = REG_X7
   939  
   940  		p = obj.Appendp(p, newprog)
   941  		p.As = ABLTU
   942  		p.From.Type = obj.TYPE_REG
   943  		p.From.Reg = REG_X6
   944  		p.Reg = REG_X7
   945  		p.To.Type = obj.TYPE_BRANCH
   946  		to_done = p
   947  	}
   948  
   949  	// Spill the register args that could be clobbered by the
   950  	// morestack code
   951  	p = ctxt.EmitEntryStackMap(cursym, p, newprog)
   952  	p = cursym.Func().SpillRegisterArgs(p, newprog)
   953  
   954  	// CALL runtime.morestack(SB)
   955  	p = obj.Appendp(p, newprog)
   956  	p.As = obj.ACALL
   957  	p.To.Type = obj.TYPE_BRANCH
   958  
   959  	if cursym.CFunc() {
   960  		p.To.Sym = ctxt.Lookup("runtime.morestackc")
   961  	} else if !cursym.Func().Text.From.Sym.NeedCtxt() {
   962  		p.To.Sym = ctxt.Lookup("runtime.morestack_noctxt")
   963  	} else {
   964  		p.To.Sym = ctxt.Lookup("runtime.morestack")
   965  	}
   966  	if to_more != nil {
   967  		to_more.To.SetTarget(p)
   968  	}
   969  	jalToSym(ctxt, p, REG_X5)
   970  
   971  	// The instructions which unspill regs should be preemptible.
   972  	p = ctxt.EndUnsafePoint(p, newprog, -1)
   973  	p = cursym.Func().UnspillRegisterArgs(p, newprog)
   974  
   975  	// JMP start
   976  	p = obj.Appendp(p, newprog)
   977  	p.As = AJAL
   978  	p.To = obj.Addr{Type: obj.TYPE_BRANCH}
   979  	p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_ZERO}
   980  	p.To.SetTarget(startPred.Link)
   981  
   982  	// placeholder for to_done's jump target
   983  	p = obj.Appendp(p, newprog)
   984  	p.As = obj.ANOP // zero-width place holder
   985  	to_done.To.SetTarget(p)
   986  
   987  	return p
   988  }
   989  
   990  // signExtend sign extends val starting at bit bit.
   991  func signExtend(val int64, bit uint) int64 {
   992  	return val << (64 - bit) >> (64 - bit)
   993  }
   994  
   995  // Split32BitImmediate splits a signed 32-bit immediate into a signed 20-bit
   996  // upper immediate and a signed 12-bit lower immediate to be added to the upper
   997  // result. For example, high may be used in LUI and low in a following ADDI to
   998  // generate a full 32-bit constant.
   999  func Split32BitImmediate(imm int64) (low, high int64, err error) {
  1000  	if err := immIFits(imm, 32); err != nil {
  1001  		return 0, 0, err
  1002  	}
  1003  
  1004  	// Nothing special needs to be done if the immediate fits in 12 bits.
  1005  	if err := immIFits(imm, 12); err == nil {
  1006  		return imm, 0, nil
  1007  	}
  1008  
  1009  	high = imm >> 12
  1010  
  1011  	// The bottom 12 bits will be treated as signed.
  1012  	//
  1013  	// If that will result in a negative 12 bit number, add 1 to
  1014  	// our upper bits to adjust for the borrow.
  1015  	//
  1016  	// It is not possible for this increment to overflow. To
  1017  	// overflow, the 20 top bits would be 1, and the sign bit for
  1018  	// the low 12 bits would be set, in which case the entire 32
  1019  	// bit pattern fits in a 12 bit signed value.
  1020  	if imm&(1<<11) != 0 {
  1021  		high++
  1022  	}
  1023  
  1024  	low = signExtend(imm, 12)
  1025  	high = signExtend(high, 20)
  1026  
  1027  	return low, high, nil
  1028  }
  1029  
  1030  func regVal(r, min, max uint32) uint32 {
  1031  	if r < min || r > max {
  1032  		panic(fmt.Sprintf("register out of range, want %d <= %d <= %d", min, r, max))
  1033  	}
  1034  	return r - min
  1035  }
  1036  
  1037  // regI returns an integer register.
  1038  func regI(r uint32) uint32 {
  1039  	return regVal(r, REG_X0, REG_X31)
  1040  }
  1041  
  1042  // regF returns a float register.
  1043  func regF(r uint32) uint32 {
  1044  	return regVal(r, REG_F0, REG_F31)
  1045  }
  1046  
  1047  // regV returns a vector register.
  1048  func regV(r uint32) uint32 {
  1049  	return regVal(r, REG_V0, REG_V31)
  1050  }
  1051  
  1052  // regAddr extracts a register from an Addr.
  1053  func regAddr(a obj.Addr, min, max uint32) uint32 {
  1054  	if a.Type != obj.TYPE_REG {
  1055  		panic(fmt.Sprintf("ill typed: %+v", a))
  1056  	}
  1057  	return regVal(uint32(a.Reg), min, max)
  1058  }
  1059  
  1060  // regIAddr extracts the integer register from an Addr.
  1061  func regIAddr(a obj.Addr) uint32 {
  1062  	return regAddr(a, REG_X0, REG_X31)
  1063  }
  1064  
  1065  // regFAddr extracts the float register from an Addr.
  1066  func regFAddr(a obj.Addr) uint32 {
  1067  	return regAddr(a, REG_F0, REG_F31)
  1068  }
  1069  
  1070  // immEven checks that the immediate is a multiple of two. If it
  1071  // is not, an error is returned.
  1072  func immEven(x int64) error {
  1073  	if x&1 != 0 {
  1074  		return fmt.Errorf("immediate %#x is not a multiple of two", x)
  1075  	}
  1076  	return nil
  1077  }
  1078  
  1079  // immIFits checks whether the immediate value x fits in nbits bits
  1080  // as a signed integer. If it does not, an error is returned.
  1081  func immIFits(x int64, nbits uint) error {
  1082  	nbits--
  1083  	min := int64(-1) << nbits
  1084  	max := int64(1)<<nbits - 1
  1085  	if x < min || x > max {
  1086  		if nbits <= 16 {
  1087  			return fmt.Errorf("signed immediate %d must be in range [%d, %d] (%d bits)", x, min, max, nbits)
  1088  		}
  1089  		return fmt.Errorf("signed immediate %#x must be in range [%#x, %#x] (%d bits)", x, min, max, nbits)
  1090  	}
  1091  	return nil
  1092  }
  1093  
  1094  // immI extracts the signed integer of the specified size from an immediate.
  1095  func immI(as obj.As, imm int64, nbits uint) uint32 {
  1096  	if err := immIFits(imm, nbits); err != nil {
  1097  		panic(fmt.Sprintf("%v: %v", as, err))
  1098  	}
  1099  	return uint32(imm)
  1100  }
  1101  
  1102  func wantImmI(ctxt *obj.Link, ins *instruction, imm int64, nbits uint) {
  1103  	if err := immIFits(imm, nbits); err != nil {
  1104  		ctxt.Diag("%v: %v", ins, err)
  1105  	}
  1106  }
  1107  
  1108  func wantReg(ctxt *obj.Link, ins *instruction, pos string, descr string, r, min, max uint32) {
  1109  	if r < min || r > max {
  1110  		var suffix string
  1111  		if r != obj.REG_NONE {
  1112  			suffix = fmt.Sprintf(" but got non-%s register %s", descr, RegName(int(r)))
  1113  		}
  1114  		ctxt.Diag("%v: expected %s register in %s position%s", ins, descr, pos, suffix)
  1115  	}
  1116  }
  1117  
  1118  func wantNoneReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
  1119  	if r != obj.REG_NONE {
  1120  		ctxt.Diag("%v: expected no register in %s but got register %s", ins, pos, RegName(int(r)))
  1121  	}
  1122  }
  1123  
  1124  // wantIntReg checks that r is an integer register.
  1125  func wantIntReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
  1126  	wantReg(ctxt, ins, pos, "integer", r, REG_X0, REG_X31)
  1127  }
  1128  
  1129  // wantFloatReg checks that r is a floating-point register.
  1130  func wantFloatReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
  1131  	wantReg(ctxt, ins, pos, "float", r, REG_F0, REG_F31)
  1132  }
  1133  
  1134  // wantVectorReg checks that r is a vector register.
  1135  func wantVectorReg(ctxt *obj.Link, ins *instruction, pos string, r uint32) {
  1136  	wantReg(ctxt, ins, pos, "vector", r, REG_V0, REG_V31)
  1137  }
  1138  
  1139  // wantEvenOffset checks that the offset is a multiple of two.
  1140  func wantEvenOffset(ctxt *obj.Link, ins *instruction, offset int64) {
  1141  	if err := immEven(offset); err != nil {
  1142  		ctxt.Diag("%v: %v", ins, err)
  1143  	}
  1144  }
  1145  
  1146  func validateRII(ctxt *obj.Link, ins *instruction) {
  1147  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1148  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1149  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1150  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1151  }
  1152  
  1153  func validateRIII(ctxt *obj.Link, ins *instruction) {
  1154  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1155  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1156  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1157  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1158  }
  1159  
  1160  func validateRFFF(ctxt *obj.Link, ins *instruction) {
  1161  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1162  	wantFloatReg(ctxt, ins, "rs1", ins.rs1)
  1163  	wantFloatReg(ctxt, ins, "rs2", ins.rs2)
  1164  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1165  }
  1166  
  1167  func validateRFFFF(ctxt *obj.Link, ins *instruction) {
  1168  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1169  	wantFloatReg(ctxt, ins, "rs1", ins.rs1)
  1170  	wantFloatReg(ctxt, ins, "rs2", ins.rs2)
  1171  	wantFloatReg(ctxt, ins, "rs3", ins.rs3)
  1172  }
  1173  
  1174  func validateRFFI(ctxt *obj.Link, ins *instruction) {
  1175  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1176  	wantFloatReg(ctxt, ins, "rs1", ins.rs1)
  1177  	wantFloatReg(ctxt, ins, "rs2", ins.rs2)
  1178  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1179  }
  1180  
  1181  func validateRFI(ctxt *obj.Link, ins *instruction) {
  1182  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1183  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1184  	wantFloatReg(ctxt, ins, "rs2", ins.rs2)
  1185  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1186  }
  1187  
  1188  func validateRIF(ctxt *obj.Link, ins *instruction) {
  1189  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1190  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1191  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1192  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1193  }
  1194  
  1195  func validateRFF(ctxt *obj.Link, ins *instruction) {
  1196  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1197  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1198  	wantFloatReg(ctxt, ins, "rs2", ins.rs2)
  1199  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1200  }
  1201  
  1202  func validateIII(ctxt *obj.Link, ins *instruction) {
  1203  	wantImmI(ctxt, ins, ins.imm, 12)
  1204  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1205  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1206  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1207  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1208  }
  1209  
  1210  func validateIF(ctxt *obj.Link, ins *instruction) {
  1211  	wantImmI(ctxt, ins, ins.imm, 12)
  1212  	wantFloatReg(ctxt, ins, "rd", ins.rd)
  1213  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1214  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1215  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1216  }
  1217  
  1218  func validateSI(ctxt *obj.Link, ins *instruction) {
  1219  	wantImmI(ctxt, ins, ins.imm, 12)
  1220  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1221  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1222  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1223  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1224  }
  1225  
  1226  func validateSF(ctxt *obj.Link, ins *instruction) {
  1227  	wantImmI(ctxt, ins, ins.imm, 12)
  1228  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1229  	wantFloatReg(ctxt, ins, "rs1", ins.rs1)
  1230  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1231  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1232  }
  1233  
  1234  func validateB(ctxt *obj.Link, ins *instruction) {
  1235  	// Offsets are multiples of two, so accept 13 bit immediates for the
  1236  	// 12 bit slot. We implicitly drop the least significant bit in encodeB.
  1237  	wantEvenOffset(ctxt, ins, ins.imm)
  1238  	wantImmI(ctxt, ins, ins.imm, 13)
  1239  	wantNoneReg(ctxt, ins, "rd", ins.rd)
  1240  	wantIntReg(ctxt, ins, "rs1", ins.rs1)
  1241  	wantIntReg(ctxt, ins, "rs2", ins.rs2)
  1242  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1243  }
  1244  
  1245  func validateU(ctxt *obj.Link, ins *instruction) {
  1246  	wantImmI(ctxt, ins, ins.imm, 20)
  1247  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1248  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1249  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1250  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1251  }
  1252  
  1253  func validateJ(ctxt *obj.Link, ins *instruction) {
  1254  	// Offsets are multiples of two, so accept 21 bit immediates for the
  1255  	// 20 bit slot. We implicitly drop the least significant bit in encodeJ.
  1256  	wantEvenOffset(ctxt, ins, ins.imm)
  1257  	wantImmI(ctxt, ins, ins.imm, 21)
  1258  	wantIntReg(ctxt, ins, "rd", ins.rd)
  1259  	wantNoneReg(ctxt, ins, "rs1", ins.rs1)
  1260  	wantNoneReg(ctxt, ins, "rs2", ins.rs2)
  1261  	wantNoneReg(ctxt, ins, "rs3", ins.rs3)
  1262  }
  1263  
  1264  func validateRaw(ctxt *obj.Link, ins *instruction) {
  1265  	// Treat the raw value specially as a 32-bit unsigned integer.
  1266  	// Nobody wants to enter negative machine code.
  1267  	if ins.imm < 0 || 1<<32 <= ins.imm {
  1268  		ctxt.Diag("%v: immediate %d in raw position cannot be larger than 32 bits", ins.as, ins.imm)
  1269  	}
  1270  }
  1271  
  1272  // extractBitAndShift extracts the specified bit from the given immediate,
  1273  // before shifting it to the requested position and returning it.
  1274  func extractBitAndShift(imm uint32, bit, pos int) uint32 {
  1275  	return ((imm >> bit) & 1) << pos
  1276  }
  1277  
  1278  // encodeR encodes an R-type RISC-V instruction.
  1279  func encodeR(as obj.As, rs1, rs2, rd, funct3, funct7 uint32) uint32 {
  1280  	enc := encode(as)
  1281  	if enc == nil {
  1282  		panic("encodeR: could not encode instruction")
  1283  	}
  1284  	if enc.rs2 != 0 && rs2 != 0 {
  1285  		panic("encodeR: instruction uses rs2, but rs2 was nonzero")
  1286  	}
  1287  	return funct7<<25 | enc.funct7<<25 | enc.rs2<<20 | rs2<<20 | rs1<<15 | enc.funct3<<12 | funct3<<12 | rd<<7 | enc.opcode
  1288  }
  1289  
  1290  // encodeR4 encodes an R4-type RISC-V instruction.
  1291  func encodeR4(as obj.As, rs1, rs2, rs3, rd, funct3, funct2 uint32) uint32 {
  1292  	enc := encode(as)
  1293  	if enc == nil {
  1294  		panic("encodeR4: could not encode instruction")
  1295  	}
  1296  	if enc.rs2 != 0 {
  1297  		panic("encodeR4: instruction uses rs2")
  1298  	}
  1299  	funct2 |= enc.funct7
  1300  	if funct2&^3 != 0 {
  1301  		panic("encodeR4: funct2 requires more than 2 bits")
  1302  	}
  1303  	return rs3<<27 | funct2<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | funct3<<12 | rd<<7 | enc.opcode
  1304  }
  1305  
  1306  func encodeRII(ins *instruction) uint32 {
  1307  	return encodeR(ins.as, regI(ins.rs1), 0, regI(ins.rd), ins.funct3, ins.funct7)
  1308  }
  1309  
  1310  func encodeRIII(ins *instruction) uint32 {
  1311  	return encodeR(ins.as, regI(ins.rs1), regI(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
  1312  }
  1313  
  1314  func encodeRFFF(ins *instruction) uint32 {
  1315  	return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rd), ins.funct3, ins.funct7)
  1316  }
  1317  
  1318  func encodeRFFFF(ins *instruction) uint32 {
  1319  	return encodeR4(ins.as, regF(ins.rs1), regF(ins.rs2), regF(ins.rs3), regF(ins.rd), ins.funct3, ins.funct7)
  1320  }
  1321  
  1322  func encodeRFFI(ins *instruction) uint32 {
  1323  	return encodeR(ins.as, regF(ins.rs1), regF(ins.rs2), regI(ins.rd), ins.funct3, ins.funct7)
  1324  }
  1325  
  1326  func encodeRFI(ins *instruction) uint32 {
  1327  	return encodeR(ins.as, regF(ins.rs2), 0, regI(ins.rd), ins.funct3, ins.funct7)
  1328  }
  1329  
  1330  func encodeRIF(ins *instruction) uint32 {
  1331  	return encodeR(ins.as, regI(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7)
  1332  }
  1333  
  1334  func encodeRFF(ins *instruction) uint32 {
  1335  	return encodeR(ins.as, regF(ins.rs2), 0, regF(ins.rd), ins.funct3, ins.funct7)
  1336  }
  1337  
  1338  // encodeI encodes an I-type RISC-V instruction.
  1339  func encodeI(as obj.As, rs1, rd, imm uint32) uint32 {
  1340  	enc := encode(as)
  1341  	if enc == nil {
  1342  		panic("encodeI: could not encode instruction")
  1343  	}
  1344  	imm |= uint32(enc.csr)
  1345  	return imm<<20 | rs1<<15 | enc.funct3<<12 | rd<<7 | enc.opcode
  1346  }
  1347  
  1348  func encodeIII(ins *instruction) uint32 {
  1349  	return encodeI(ins.as, regI(ins.rs1), regI(ins.rd), uint32(ins.imm))
  1350  }
  1351  
  1352  func encodeIF(ins *instruction) uint32 {
  1353  	return encodeI(ins.as, regI(ins.rs1), regF(ins.rd), uint32(ins.imm))
  1354  }
  1355  
  1356  // encodeS encodes an S-type RISC-V instruction.
  1357  func encodeS(as obj.As, rs1, rs2, imm uint32) uint32 {
  1358  	enc := encode(as)
  1359  	if enc == nil {
  1360  		panic("encodeS: could not encode instruction")
  1361  	}
  1362  	return (imm>>5)<<25 | rs2<<20 | rs1<<15 | enc.funct3<<12 | (imm&0x1f)<<7 | enc.opcode
  1363  }
  1364  
  1365  func encodeSI(ins *instruction) uint32 {
  1366  	return encodeS(ins.as, regI(ins.rd), regI(ins.rs1), uint32(ins.imm))
  1367  }
  1368  
  1369  func encodeSF(ins *instruction) uint32 {
  1370  	return encodeS(ins.as, regI(ins.rd), regF(ins.rs1), uint32(ins.imm))
  1371  }
  1372  
  1373  // encodeBImmediate encodes an immediate for a B-type RISC-V instruction.
  1374  func encodeBImmediate(imm uint32) uint32 {
  1375  	return (imm>>12)<<31 | ((imm>>5)&0x3f)<<25 | ((imm>>1)&0xf)<<8 | ((imm>>11)&0x1)<<7
  1376  }
  1377  
  1378  // encodeB encodes a B-type RISC-V instruction.
  1379  func encodeB(ins *instruction) uint32 {
  1380  	imm := immI(ins.as, ins.imm, 13)
  1381  	rs2 := regI(ins.rs1)
  1382  	rs1 := regI(ins.rs2)
  1383  	enc := encode(ins.as)
  1384  	if enc == nil {
  1385  		panic("encodeB: could not encode instruction")
  1386  	}
  1387  	return encodeBImmediate(imm) | rs2<<20 | rs1<<15 | enc.funct3<<12 | enc.opcode
  1388  }
  1389  
  1390  // encodeU encodes a U-type RISC-V instruction.
  1391  func encodeU(ins *instruction) uint32 {
  1392  	// The immediates for encodeU are the upper 20 bits of a 32 bit value.
  1393  	// Rather than have the user/compiler generate a 32 bit constant, the
  1394  	// bottommost bits of which must all be zero, instead accept just the
  1395  	// top bits.
  1396  	imm := immI(ins.as, ins.imm, 20)
  1397  	rd := regI(ins.rd)
  1398  	enc := encode(ins.as)
  1399  	if enc == nil {
  1400  		panic("encodeU: could not encode instruction")
  1401  	}
  1402  	return imm<<12 | rd<<7 | enc.opcode
  1403  }
  1404  
  1405  // encodeJImmediate encodes an immediate for a J-type RISC-V instruction.
  1406  func encodeJImmediate(imm uint32) uint32 {
  1407  	return (imm>>20)<<31 | ((imm>>1)&0x3ff)<<21 | ((imm>>11)&0x1)<<20 | ((imm>>12)&0xff)<<12
  1408  }
  1409  
  1410  // encodeJ encodes a J-type RISC-V instruction.
  1411  func encodeJ(ins *instruction) uint32 {
  1412  	imm := immI(ins.as, ins.imm, 21)
  1413  	rd := regI(ins.rd)
  1414  	enc := encode(ins.as)
  1415  	if enc == nil {
  1416  		panic("encodeJ: could not encode instruction")
  1417  	}
  1418  	return encodeJImmediate(imm) | rd<<7 | enc.opcode
  1419  }
  1420  
  1421  // encodeCBImmediate encodes an immediate for a CB-type RISC-V instruction.
  1422  func encodeCBImmediate(imm uint32) uint32 {
  1423  	// Bit order - [8|4:3|7:6|2:1|5]
  1424  	bits := extractBitAndShift(imm, 8, 7)
  1425  	bits |= extractBitAndShift(imm, 4, 6)
  1426  	bits |= extractBitAndShift(imm, 3, 5)
  1427  	bits |= extractBitAndShift(imm, 7, 4)
  1428  	bits |= extractBitAndShift(imm, 6, 3)
  1429  	bits |= extractBitAndShift(imm, 2, 2)
  1430  	bits |= extractBitAndShift(imm, 1, 1)
  1431  	bits |= extractBitAndShift(imm, 5, 0)
  1432  	return (bits>>5)<<10 | (bits&0x1f)<<2
  1433  }
  1434  
  1435  // encodeCJImmediate encodes an immediate for a CJ-type RISC-V instruction.
  1436  func encodeCJImmediate(imm uint32) uint32 {
  1437  	// Bit order - [11|4|9:8|10|6|7|3:1|5]
  1438  	bits := extractBitAndShift(imm, 11, 10)
  1439  	bits |= extractBitAndShift(imm, 4, 9)
  1440  	bits |= extractBitAndShift(imm, 9, 8)
  1441  	bits |= extractBitAndShift(imm, 8, 7)
  1442  	bits |= extractBitAndShift(imm, 10, 6)
  1443  	bits |= extractBitAndShift(imm, 6, 5)
  1444  	bits |= extractBitAndShift(imm, 7, 4)
  1445  	bits |= extractBitAndShift(imm, 3, 3)
  1446  	bits |= extractBitAndShift(imm, 2, 2)
  1447  	bits |= extractBitAndShift(imm, 1, 1)
  1448  	bits |= extractBitAndShift(imm, 5, 0)
  1449  	return bits << 2
  1450  }
  1451  
  1452  func encodeRawIns(ins *instruction) uint32 {
  1453  	// Treat the raw value specially as a 32-bit unsigned integer.
  1454  	// Nobody wants to enter negative machine code.
  1455  	if ins.imm < 0 || 1<<32 <= ins.imm {
  1456  		panic(fmt.Sprintf("immediate %d cannot fit in 32 bits", ins.imm))
  1457  	}
  1458  	return uint32(ins.imm)
  1459  }
  1460  
  1461  func EncodeBImmediate(imm int64) (int64, error) {
  1462  	if err := immIFits(imm, 13); err != nil {
  1463  		return 0, err
  1464  	}
  1465  	if err := immEven(imm); err != nil {
  1466  		return 0, err
  1467  	}
  1468  	return int64(encodeBImmediate(uint32(imm))), nil
  1469  }
  1470  
  1471  func EncodeCBImmediate(imm int64) (int64, error) {
  1472  	if err := immIFits(imm, 9); err != nil {
  1473  		return 0, err
  1474  	}
  1475  	if err := immEven(imm); err != nil {
  1476  		return 0, err
  1477  	}
  1478  	return int64(encodeCBImmediate(uint32(imm))), nil
  1479  }
  1480  
  1481  func EncodeCJImmediate(imm int64) (int64, error) {
  1482  	if err := immIFits(imm, 12); err != nil {
  1483  		return 0, err
  1484  	}
  1485  	if err := immEven(imm); err != nil {
  1486  		return 0, err
  1487  	}
  1488  	return int64(encodeCJImmediate(uint32(imm))), nil
  1489  }
  1490  
  1491  func EncodeIImmediate(imm int64) (int64, error) {
  1492  	if err := immIFits(imm, 12); err != nil {
  1493  		return 0, err
  1494  	}
  1495  	return imm << 20, nil
  1496  }
  1497  
  1498  func EncodeJImmediate(imm int64) (int64, error) {
  1499  	if err := immIFits(imm, 21); err != nil {
  1500  		return 0, err
  1501  	}
  1502  	if err := immEven(imm); err != nil {
  1503  		return 0, err
  1504  	}
  1505  	return int64(encodeJImmediate(uint32(imm))), nil
  1506  }
  1507  
  1508  func EncodeSImmediate(imm int64) (int64, error) {
  1509  	if err := immIFits(imm, 12); err != nil {
  1510  		return 0, err
  1511  	}
  1512  	return ((imm >> 5) << 25) | ((imm & 0x1f) << 7), nil
  1513  }
  1514  
  1515  func EncodeUImmediate(imm int64) (int64, error) {
  1516  	if err := immIFits(imm, 20); err != nil {
  1517  		return 0, err
  1518  	}
  1519  	return imm << 12, nil
  1520  }
  1521  
  1522  type encoding struct {
  1523  	encode   func(*instruction) uint32     // encode returns the machine code for an instruction
  1524  	validate func(*obj.Link, *instruction) // validate validates an instruction
  1525  	length   int                           // length of encoded instruction; 0 for pseudo-ops, 4 otherwise
  1526  }
  1527  
  1528  var (
  1529  	// Encodings have the following naming convention:
  1530  	//
  1531  	//  1. the instruction encoding (R/I/S/B/U/J), in lowercase
  1532  	//  2. zero or more register operand identifiers (I = integer
  1533  	//     register, F = float register), in uppercase
  1534  	//  3. the word "Encoding"
  1535  	//
  1536  	// For example, rIIIEncoding indicates an R-type instruction with two
  1537  	// integer register inputs and an integer register output; sFEncoding
  1538  	// indicates an S-type instruction with rs2 being a float register.
  1539  
  1540  	rIIIEncoding  = encoding{encode: encodeRIII, validate: validateRIII, length: 4}
  1541  	rIIEncoding   = encoding{encode: encodeRII, validate: validateRII, length: 4}
  1542  	rFFFEncoding  = encoding{encode: encodeRFFF, validate: validateRFFF, length: 4}
  1543  	rFFFFEncoding = encoding{encode: encodeRFFFF, validate: validateRFFFF, length: 4}
  1544  	rFFIEncoding  = encoding{encode: encodeRFFI, validate: validateRFFI, length: 4}
  1545  	rFIEncoding   = encoding{encode: encodeRFI, validate: validateRFI, length: 4}
  1546  	rIFEncoding   = encoding{encode: encodeRIF, validate: validateRIF, length: 4}
  1547  	rFFEncoding   = encoding{encode: encodeRFF, validate: validateRFF, length: 4}
  1548  
  1549  	iIIEncoding = encoding{encode: encodeIII, validate: validateIII, length: 4}
  1550  	iFEncoding  = encoding{encode: encodeIF, validate: validateIF, length: 4}
  1551  
  1552  	sIEncoding = encoding{encode: encodeSI, validate: validateSI, length: 4}
  1553  	sFEncoding = encoding{encode: encodeSF, validate: validateSF, length: 4}
  1554  
  1555  	bEncoding = encoding{encode: encodeB, validate: validateB, length: 4}
  1556  	uEncoding = encoding{encode: encodeU, validate: validateU, length: 4}
  1557  	jEncoding = encoding{encode: encodeJ, validate: validateJ, length: 4}
  1558  
  1559  	// rawEncoding encodes a raw instruction byte sequence.
  1560  	rawEncoding = encoding{encode: encodeRawIns, validate: validateRaw, length: 4}
  1561  
  1562  	// pseudoOpEncoding panics if encoding is attempted, but does no validation.
  1563  	pseudoOpEncoding = encoding{encode: nil, validate: func(*obj.Link, *instruction) {}, length: 0}
  1564  
  1565  	// badEncoding is used when an invalid op is encountered.
  1566  	// An error has already been generated, so let anything else through.
  1567  	badEncoding = encoding{encode: func(*instruction) uint32 { return 0 }, validate: func(*obj.Link, *instruction) {}, length: 0}
  1568  )
  1569  
  1570  // encodings contains the encodings for RISC-V instructions.
  1571  // Instructions are masked with obj.AMask to keep indices small.
  1572  var encodings = [ALAST & obj.AMask]encoding{
  1573  
  1574  	// Unprivileged ISA
  1575  
  1576  	// 2.4: Integer Computational Instructions
  1577  	AADDI & obj.AMask:  iIIEncoding,
  1578  	ASLTI & obj.AMask:  iIIEncoding,
  1579  	ASLTIU & obj.AMask: iIIEncoding,
  1580  	AANDI & obj.AMask:  iIIEncoding,
  1581  	AORI & obj.AMask:   iIIEncoding,
  1582  	AXORI & obj.AMask:  iIIEncoding,
  1583  	ASLLI & obj.AMask:  iIIEncoding,
  1584  	ASRLI & obj.AMask:  iIIEncoding,
  1585  	ASRAI & obj.AMask:  iIIEncoding,
  1586  	ALUI & obj.AMask:   uEncoding,
  1587  	AAUIPC & obj.AMask: uEncoding,
  1588  	AADD & obj.AMask:   rIIIEncoding,
  1589  	ASLT & obj.AMask:   rIIIEncoding,
  1590  	ASLTU & obj.AMask:  rIIIEncoding,
  1591  	AAND & obj.AMask:   rIIIEncoding,
  1592  	AOR & obj.AMask:    rIIIEncoding,
  1593  	AXOR & obj.AMask:   rIIIEncoding,
  1594  	ASLL & obj.AMask:   rIIIEncoding,
  1595  	ASRL & obj.AMask:   rIIIEncoding,
  1596  	ASUB & obj.AMask:   rIIIEncoding,
  1597  	ASRA & obj.AMask:   rIIIEncoding,
  1598  
  1599  	// 2.5: Control Transfer Instructions
  1600  	AJAL & obj.AMask:  jEncoding,
  1601  	AJALR & obj.AMask: iIIEncoding,
  1602  	ABEQ & obj.AMask:  bEncoding,
  1603  	ABNE & obj.AMask:  bEncoding,
  1604  	ABLT & obj.AMask:  bEncoding,
  1605  	ABLTU & obj.AMask: bEncoding,
  1606  	ABGE & obj.AMask:  bEncoding,
  1607  	ABGEU & obj.AMask: bEncoding,
  1608  
  1609  	// 2.6: Load and Store Instructions
  1610  	ALW & obj.AMask:  iIIEncoding,
  1611  	ALWU & obj.AMask: iIIEncoding,
  1612  	ALH & obj.AMask:  iIIEncoding,
  1613  	ALHU & obj.AMask: iIIEncoding,
  1614  	ALB & obj.AMask:  iIIEncoding,
  1615  	ALBU & obj.AMask: iIIEncoding,
  1616  	ASW & obj.AMask:  sIEncoding,
  1617  	ASH & obj.AMask:  sIEncoding,
  1618  	ASB & obj.AMask:  sIEncoding,
  1619  
  1620  	// 2.7: Memory Ordering
  1621  	AFENCE & obj.AMask: iIIEncoding,
  1622  
  1623  	// 5.2: Integer Computational Instructions (RV64I)
  1624  	AADDIW & obj.AMask: iIIEncoding,
  1625  	ASLLIW & obj.AMask: iIIEncoding,
  1626  	ASRLIW & obj.AMask: iIIEncoding,
  1627  	ASRAIW & obj.AMask: iIIEncoding,
  1628  	AADDW & obj.AMask:  rIIIEncoding,
  1629  	ASLLW & obj.AMask:  rIIIEncoding,
  1630  	ASRLW & obj.AMask:  rIIIEncoding,
  1631  	ASUBW & obj.AMask:  rIIIEncoding,
  1632  	ASRAW & obj.AMask:  rIIIEncoding,
  1633  
  1634  	// 5.3: Load and Store Instructions (RV64I)
  1635  	ALD & obj.AMask: iIIEncoding,
  1636  	ASD & obj.AMask: sIEncoding,
  1637  
  1638  	// 7.1: CSR Instructions
  1639  	ACSRRS & obj.AMask: iIIEncoding,
  1640  
  1641  	// 7.1: Multiplication Operations
  1642  	AMUL & obj.AMask:    rIIIEncoding,
  1643  	AMULH & obj.AMask:   rIIIEncoding,
  1644  	AMULHU & obj.AMask:  rIIIEncoding,
  1645  	AMULHSU & obj.AMask: rIIIEncoding,
  1646  	AMULW & obj.AMask:   rIIIEncoding,
  1647  	ADIV & obj.AMask:    rIIIEncoding,
  1648  	ADIVU & obj.AMask:   rIIIEncoding,
  1649  	AREM & obj.AMask:    rIIIEncoding,
  1650  	AREMU & obj.AMask:   rIIIEncoding,
  1651  	ADIVW & obj.AMask:   rIIIEncoding,
  1652  	ADIVUW & obj.AMask:  rIIIEncoding,
  1653  	AREMW & obj.AMask:   rIIIEncoding,
  1654  	AREMUW & obj.AMask:  rIIIEncoding,
  1655  
  1656  	// 8.2: Load-Reserved/Store-Conditional
  1657  	ALRW & obj.AMask: rIIIEncoding,
  1658  	ALRD & obj.AMask: rIIIEncoding,
  1659  	ASCW & obj.AMask: rIIIEncoding,
  1660  	ASCD & obj.AMask: rIIIEncoding,
  1661  
  1662  	// 8.3: Atomic Memory Operations
  1663  	AAMOSWAPW & obj.AMask: rIIIEncoding,
  1664  	AAMOSWAPD & obj.AMask: rIIIEncoding,
  1665  	AAMOADDW & obj.AMask:  rIIIEncoding,
  1666  	AAMOADDD & obj.AMask:  rIIIEncoding,
  1667  	AAMOANDW & obj.AMask:  rIIIEncoding,
  1668  	AAMOANDD & obj.AMask:  rIIIEncoding,
  1669  	AAMOORW & obj.AMask:   rIIIEncoding,
  1670  	AAMOORD & obj.AMask:   rIIIEncoding,
  1671  	AAMOXORW & obj.AMask:  rIIIEncoding,
  1672  	AAMOXORD & obj.AMask:  rIIIEncoding,
  1673  	AAMOMAXW & obj.AMask:  rIIIEncoding,
  1674  	AAMOMAXD & obj.AMask:  rIIIEncoding,
  1675  	AAMOMAXUW & obj.AMask: rIIIEncoding,
  1676  	AAMOMAXUD & obj.AMask: rIIIEncoding,
  1677  	AAMOMINW & obj.AMask:  rIIIEncoding,
  1678  	AAMOMIND & obj.AMask:  rIIIEncoding,
  1679  	AAMOMINUW & obj.AMask: rIIIEncoding,
  1680  	AAMOMINUD & obj.AMask: rIIIEncoding,
  1681  
  1682  	// 11.5: Single-Precision Load and Store Instructions
  1683  	AFLW & obj.AMask: iFEncoding,
  1684  	AFSW & obj.AMask: sFEncoding,
  1685  
  1686  	// 11.6: Single-Precision Floating-Point Computational Instructions
  1687  	AFADDS & obj.AMask:   rFFFEncoding,
  1688  	AFSUBS & obj.AMask:   rFFFEncoding,
  1689  	AFMULS & obj.AMask:   rFFFEncoding,
  1690  	AFDIVS & obj.AMask:   rFFFEncoding,
  1691  	AFMINS & obj.AMask:   rFFFEncoding,
  1692  	AFMAXS & obj.AMask:   rFFFEncoding,
  1693  	AFSQRTS & obj.AMask:  rFFFEncoding,
  1694  	AFMADDS & obj.AMask:  rFFFFEncoding,
  1695  	AFMSUBS & obj.AMask:  rFFFFEncoding,
  1696  	AFNMSUBS & obj.AMask: rFFFFEncoding,
  1697  	AFNMADDS & obj.AMask: rFFFFEncoding,
  1698  
  1699  	// 11.7: Single-Precision Floating-Point Conversion and Move Instructions
  1700  	AFCVTWS & obj.AMask:  rFIEncoding,
  1701  	AFCVTLS & obj.AMask:  rFIEncoding,
  1702  	AFCVTSW & obj.AMask:  rIFEncoding,
  1703  	AFCVTSL & obj.AMask:  rIFEncoding,
  1704  	AFCVTWUS & obj.AMask: rFIEncoding,
  1705  	AFCVTLUS & obj.AMask: rFIEncoding,
  1706  	AFCVTSWU & obj.AMask: rIFEncoding,
  1707  	AFCVTSLU & obj.AMask: rIFEncoding,
  1708  	AFSGNJS & obj.AMask:  rFFFEncoding,
  1709  	AFSGNJNS & obj.AMask: rFFFEncoding,
  1710  	AFSGNJXS & obj.AMask: rFFFEncoding,
  1711  	AFMVXW & obj.AMask:   rFIEncoding,
  1712  	AFMVWX & obj.AMask:   rIFEncoding,
  1713  
  1714  	// 11.8: Single-Precision Floating-Point Compare Instructions
  1715  	AFEQS & obj.AMask: rFFIEncoding,
  1716  	AFLTS & obj.AMask: rFFIEncoding,
  1717  	AFLES & obj.AMask: rFFIEncoding,
  1718  
  1719  	// 11.9: Single-Precision Floating-Point Classify Instruction
  1720  	AFCLASSS & obj.AMask: rFIEncoding,
  1721  
  1722  	// 12.3: Double-Precision Load and Store Instructions
  1723  	AFLD & obj.AMask: iFEncoding,
  1724  	AFSD & obj.AMask: sFEncoding,
  1725  
  1726  	// 12.4: Double-Precision Floating-Point Computational Instructions
  1727  	AFADDD & obj.AMask:   rFFFEncoding,
  1728  	AFSUBD & obj.AMask:   rFFFEncoding,
  1729  	AFMULD & obj.AMask:   rFFFEncoding,
  1730  	AFDIVD & obj.AMask:   rFFFEncoding,
  1731  	AFMIND & obj.AMask:   rFFFEncoding,
  1732  	AFMAXD & obj.AMask:   rFFFEncoding,
  1733  	AFSQRTD & obj.AMask:  rFFFEncoding,
  1734  	AFMADDD & obj.AMask:  rFFFFEncoding,
  1735  	AFMSUBD & obj.AMask:  rFFFFEncoding,
  1736  	AFNMSUBD & obj.AMask: rFFFFEncoding,
  1737  	AFNMADDD & obj.AMask: rFFFFEncoding,
  1738  
  1739  	// 12.5: Double-Precision Floating-Point Conversion and Move Instructions
  1740  	AFCVTWD & obj.AMask:  rFIEncoding,
  1741  	AFCVTLD & obj.AMask:  rFIEncoding,
  1742  	AFCVTDW & obj.AMask:  rIFEncoding,
  1743  	AFCVTDL & obj.AMask:  rIFEncoding,
  1744  	AFCVTWUD & obj.AMask: rFIEncoding,
  1745  	AFCVTLUD & obj.AMask: rFIEncoding,
  1746  	AFCVTDWU & obj.AMask: rIFEncoding,
  1747  	AFCVTDLU & obj.AMask: rIFEncoding,
  1748  	AFCVTSD & obj.AMask:  rFFEncoding,
  1749  	AFCVTDS & obj.AMask:  rFFEncoding,
  1750  	AFSGNJD & obj.AMask:  rFFFEncoding,
  1751  	AFSGNJND & obj.AMask: rFFFEncoding,
  1752  	AFSGNJXD & obj.AMask: rFFFEncoding,
  1753  	AFMVXD & obj.AMask:   rFIEncoding,
  1754  	AFMVDX & obj.AMask:   rIFEncoding,
  1755  
  1756  	// 12.6: Double-Precision Floating-Point Compare Instructions
  1757  	AFEQD & obj.AMask: rFFIEncoding,
  1758  	AFLTD & obj.AMask: rFFIEncoding,
  1759  	AFLED & obj.AMask: rFFIEncoding,
  1760  
  1761  	// 12.7: Double-Precision Floating-Point Classify Instruction
  1762  	AFCLASSD & obj.AMask: rFIEncoding,
  1763  
  1764  	// Privileged ISA
  1765  
  1766  	// 3.2.1: Environment Call and Breakpoint
  1767  	AECALL & obj.AMask:  iIIEncoding,
  1768  	AEBREAK & obj.AMask: iIIEncoding,
  1769  
  1770  	//
  1771  	// RISC-V Bit-Manipulation ISA-extensions (1.0)
  1772  	//
  1773  
  1774  	// 1.1: Address Generation Instructions (Zba)
  1775  	AADDUW & obj.AMask:    rIIIEncoding,
  1776  	ASH1ADD & obj.AMask:   rIIIEncoding,
  1777  	ASH1ADDUW & obj.AMask: rIIIEncoding,
  1778  	ASH2ADD & obj.AMask:   rIIIEncoding,
  1779  	ASH2ADDUW & obj.AMask: rIIIEncoding,
  1780  	ASH3ADD & obj.AMask:   rIIIEncoding,
  1781  	ASH3ADDUW & obj.AMask: rIIIEncoding,
  1782  	ASLLIUW & obj.AMask:   iIIEncoding,
  1783  
  1784  	// 1.2: Basic Bit Manipulation (Zbb)
  1785  	AANDN & obj.AMask:  rIIIEncoding,
  1786  	ACLZ & obj.AMask:   rIIEncoding,
  1787  	ACLZW & obj.AMask:  rIIEncoding,
  1788  	ACPOP & obj.AMask:  rIIEncoding,
  1789  	ACPOPW & obj.AMask: rIIEncoding,
  1790  	ACTZ & obj.AMask:   rIIEncoding,
  1791  	ACTZW & obj.AMask:  rIIEncoding,
  1792  	AMAX & obj.AMask:   rIIIEncoding,
  1793  	AMAXU & obj.AMask:  rIIIEncoding,
  1794  	AMIN & obj.AMask:   rIIIEncoding,
  1795  	AMINU & obj.AMask:  rIIIEncoding,
  1796  	AORN & obj.AMask:   rIIIEncoding,
  1797  	ASEXTB & obj.AMask: rIIEncoding,
  1798  	ASEXTH & obj.AMask: rIIEncoding,
  1799  	AXNOR & obj.AMask:  rIIIEncoding,
  1800  	AZEXTH & obj.AMask: rIIEncoding,
  1801  
  1802  	// 1.3: Bitwise Rotation (Zbb)
  1803  	AROL & obj.AMask:   rIIIEncoding,
  1804  	AROLW & obj.AMask:  rIIIEncoding,
  1805  	AROR & obj.AMask:   rIIIEncoding,
  1806  	ARORI & obj.AMask:  iIIEncoding,
  1807  	ARORIW & obj.AMask: iIIEncoding,
  1808  	ARORW & obj.AMask:  rIIIEncoding,
  1809  	AORCB & obj.AMask:  iIIEncoding,
  1810  	AREV8 & obj.AMask:  iIIEncoding,
  1811  
  1812  	// 1.5: Single-bit Instructions (Zbs)
  1813  	ABCLR & obj.AMask:  rIIIEncoding,
  1814  	ABCLRI & obj.AMask: iIIEncoding,
  1815  	ABEXT & obj.AMask:  rIIIEncoding,
  1816  	ABEXTI & obj.AMask: iIIEncoding,
  1817  	ABINV & obj.AMask:  rIIIEncoding,
  1818  	ABINVI & obj.AMask: iIIEncoding,
  1819  	ABSET & obj.AMask:  rIIIEncoding,
  1820  	ABSETI & obj.AMask: iIIEncoding,
  1821  
  1822  	// Escape hatch
  1823  	AWORD & obj.AMask: rawEncoding,
  1824  
  1825  	// Pseudo-operations
  1826  	obj.AFUNCDATA: pseudoOpEncoding,
  1827  	obj.APCDATA:   pseudoOpEncoding,
  1828  	obj.ATEXT:     pseudoOpEncoding,
  1829  	obj.ANOP:      pseudoOpEncoding,
  1830  	obj.ADUFFZERO: pseudoOpEncoding,
  1831  	obj.ADUFFCOPY: pseudoOpEncoding,
  1832  	obj.APCALIGN:  pseudoOpEncoding,
  1833  }
  1834  
  1835  // encodingForAs returns the encoding for an obj.As.
  1836  func encodingForAs(as obj.As) (encoding, error) {
  1837  	if base := as &^ obj.AMask; base != obj.ABaseRISCV && base != 0 {
  1838  		return badEncoding, fmt.Errorf("encodingForAs: not a RISC-V instruction %s", as)
  1839  	}
  1840  	asi := as & obj.AMask
  1841  	if int(asi) >= len(encodings) {
  1842  		return badEncoding, fmt.Errorf("encodingForAs: bad RISC-V instruction %s", as)
  1843  	}
  1844  	enc := encodings[asi]
  1845  	if enc.validate == nil {
  1846  		return badEncoding, fmt.Errorf("encodingForAs: no encoding for instruction %s", as)
  1847  	}
  1848  	return enc, nil
  1849  }
  1850  
  1851  type instruction struct {
  1852  	p      *obj.Prog // Prog that instruction is for
  1853  	as     obj.As    // Assembler opcode
  1854  	rd     uint32    // Destination register
  1855  	rs1    uint32    // Source register 1
  1856  	rs2    uint32    // Source register 2
  1857  	rs3    uint32    // Source register 3
  1858  	imm    int64     // Immediate
  1859  	funct3 uint32    // Function 3
  1860  	funct7 uint32    // Function 7 (or Function 2)
  1861  }
  1862  
  1863  func (ins *instruction) String() string {
  1864  	if ins.p == nil {
  1865  		return ins.as.String()
  1866  	}
  1867  	var suffix string
  1868  	if ins.p.As != ins.as {
  1869  		suffix = fmt.Sprintf(" (%v)", ins.as)
  1870  	}
  1871  	return fmt.Sprintf("%v%v", ins.p, suffix)
  1872  }
  1873  
  1874  func (ins *instruction) encode() (uint32, error) {
  1875  	enc, err := encodingForAs(ins.as)
  1876  	if err != nil {
  1877  		return 0, err
  1878  	}
  1879  	if enc.length <= 0 {
  1880  		return 0, fmt.Errorf("%v: encoding called for a pseudo instruction", ins.as)
  1881  	}
  1882  	return enc.encode(ins), nil
  1883  }
  1884  
  1885  func (ins *instruction) length() int {
  1886  	enc, err := encodingForAs(ins.as)
  1887  	if err != nil {
  1888  		return 0
  1889  	}
  1890  	return enc.length
  1891  }
  1892  
  1893  func (ins *instruction) validate(ctxt *obj.Link) {
  1894  	enc, err := encodingForAs(ins.as)
  1895  	if err != nil {
  1896  		ctxt.Diag(err.Error())
  1897  		return
  1898  	}
  1899  	enc.validate(ctxt, ins)
  1900  }
  1901  
  1902  func (ins *instruction) usesRegTmp() bool {
  1903  	return ins.rd == REG_TMP || ins.rs1 == REG_TMP || ins.rs2 == REG_TMP
  1904  }
  1905  
  1906  // instructionForProg returns the default *obj.Prog to instruction mapping.
  1907  func instructionForProg(p *obj.Prog) *instruction {
  1908  	ins := &instruction{
  1909  		as:  p.As,
  1910  		rd:  uint32(p.To.Reg),
  1911  		rs1: uint32(p.Reg),
  1912  		rs2: uint32(p.From.Reg),
  1913  		imm: p.From.Offset,
  1914  	}
  1915  	if len(p.RestArgs) == 1 {
  1916  		ins.rs3 = uint32(p.RestArgs[0].Reg)
  1917  	}
  1918  	return ins
  1919  }
  1920  
  1921  // instructionsForOpImmediate returns the machine instructions for an immediate
  1922  // operand. The instruction is specified by as and the source register is
  1923  // specified by rs, instead of the obj.Prog.
  1924  func instructionsForOpImmediate(p *obj.Prog, as obj.As, rs int16) []*instruction {
  1925  	// <opi> $imm, REG, TO
  1926  	ins := instructionForProg(p)
  1927  	ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE
  1928  
  1929  	low, high, err := Split32BitImmediate(ins.imm)
  1930  	if err != nil {
  1931  		p.Ctxt.Diag("%v: constant %d too large", p, ins.imm, err)
  1932  		return nil
  1933  	}
  1934  	if high == 0 {
  1935  		return []*instruction{ins}
  1936  	}
  1937  
  1938  	// Split into two additions, if possible.
  1939  	// Do not split SP-writing instructions, as otherwise the recorded SP delta may be wrong.
  1940  	if p.Spadj == 0 && ins.as == AADDI && ins.imm >= -(1<<12) && ins.imm < 1<<12-1 {
  1941  		imm0 := ins.imm / 2
  1942  		imm1 := ins.imm - imm0
  1943  
  1944  		// ADDI $(imm/2), REG, TO
  1945  		// ADDI $(imm-imm/2), TO, TO
  1946  		ins.imm = imm0
  1947  		insADDI := &instruction{as: AADDI, rd: ins.rd, rs1: ins.rd, imm: imm1}
  1948  		return []*instruction{ins, insADDI}
  1949  	}
  1950  
  1951  	// LUI $high, TMP
  1952  	// ADDIW $low, TMP, TMP
  1953  	// <op> TMP, REG, TO
  1954  	insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
  1955  	insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP, imm: low}
  1956  	switch ins.as {
  1957  	case AADDI:
  1958  		ins.as = AADD
  1959  	case AANDI:
  1960  		ins.as = AAND
  1961  	case AORI:
  1962  		ins.as = AOR
  1963  	case AXORI:
  1964  		ins.as = AXOR
  1965  	default:
  1966  		p.Ctxt.Diag("unsupported immediate instruction %v for splitting", p)
  1967  		return nil
  1968  	}
  1969  	ins.rs2 = REG_TMP
  1970  	if low == 0 {
  1971  		return []*instruction{insLUI, ins}
  1972  	}
  1973  	return []*instruction{insLUI, insADDIW, ins}
  1974  }
  1975  
  1976  // instructionsForLoad returns the machine instructions for a load. The load
  1977  // instruction is specified by as and the base/source register is specified
  1978  // by rs, instead of the obj.Prog.
  1979  func instructionsForLoad(p *obj.Prog, as obj.As, rs int16) []*instruction {
  1980  	if p.From.Type != obj.TYPE_MEM {
  1981  		p.Ctxt.Diag("%v requires memory for source", p)
  1982  		return nil
  1983  	}
  1984  
  1985  	switch as {
  1986  	case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU, AFLW, AFLD:
  1987  	default:
  1988  		p.Ctxt.Diag("%v: unknown load instruction %v", p, as)
  1989  		return nil
  1990  	}
  1991  
  1992  	// <load> $imm, REG, TO (load $imm+(REG), TO)
  1993  	ins := instructionForProg(p)
  1994  	ins.as, ins.rs1, ins.rs2 = as, uint32(rs), obj.REG_NONE
  1995  	ins.imm = p.From.Offset
  1996  
  1997  	low, high, err := Split32BitImmediate(ins.imm)
  1998  	if err != nil {
  1999  		p.Ctxt.Diag("%v: constant %d too large", p, ins.imm)
  2000  		return nil
  2001  	}
  2002  	if high == 0 {
  2003  		return []*instruction{ins}
  2004  	}
  2005  
  2006  	// LUI $high, TMP
  2007  	// ADD TMP, REG, TMP
  2008  	// <load> $low, TMP, TO
  2009  	insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
  2010  	insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rs1}
  2011  	ins.rs1, ins.imm = REG_TMP, low
  2012  
  2013  	return []*instruction{insLUI, insADD, ins}
  2014  }
  2015  
  2016  // instructionsForStore returns the machine instructions for a store. The store
  2017  // instruction is specified by as and the target/source register is specified
  2018  // by rd, instead of the obj.Prog.
  2019  func instructionsForStore(p *obj.Prog, as obj.As, rd int16) []*instruction {
  2020  	if p.To.Type != obj.TYPE_MEM {
  2021  		p.Ctxt.Diag("%v requires memory for destination", p)
  2022  		return nil
  2023  	}
  2024  
  2025  	switch as {
  2026  	case ASW, ASH, ASB, ASD, AFSW, AFSD:
  2027  	default:
  2028  		p.Ctxt.Diag("%v: unknown store instruction %v", p, as)
  2029  		return nil
  2030  	}
  2031  
  2032  	// <store> $imm, REG, TO (store $imm+(TO), REG)
  2033  	ins := instructionForProg(p)
  2034  	ins.as, ins.rd, ins.rs1, ins.rs2 = as, uint32(rd), uint32(p.From.Reg), obj.REG_NONE
  2035  	ins.imm = p.To.Offset
  2036  
  2037  	low, high, err := Split32BitImmediate(ins.imm)
  2038  	if err != nil {
  2039  		p.Ctxt.Diag("%v: constant %d too large", p, ins.imm)
  2040  		return nil
  2041  	}
  2042  	if high == 0 {
  2043  		return []*instruction{ins}
  2044  	}
  2045  
  2046  	// LUI $high, TMP
  2047  	// ADD TMP, TO, TMP
  2048  	// <store> $low, REG, TMP
  2049  	insLUI := &instruction{as: ALUI, rd: REG_TMP, imm: high}
  2050  	insADD := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: ins.rd}
  2051  	ins.rd, ins.imm = REG_TMP, low
  2052  
  2053  	return []*instruction{insLUI, insADD, ins}
  2054  }
  2055  
  2056  func instructionsForTLS(p *obj.Prog, ins *instruction) []*instruction {
  2057  	insAddTP := &instruction{as: AADD, rd: REG_TMP, rs1: REG_TMP, rs2: REG_TP}
  2058  
  2059  	var inss []*instruction
  2060  	if p.Ctxt.Flag_shared {
  2061  		// TLS initial-exec mode - load TLS offset from GOT, add the thread pointer
  2062  		// register, then load from or store to the resulting memory location.
  2063  		insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
  2064  		insLoadTLSOffset := &instruction{as: ALD, rd: REG_TMP, rs1: REG_TMP}
  2065  		inss = []*instruction{insAUIPC, insLoadTLSOffset, insAddTP, ins}
  2066  	} else {
  2067  		// TLS local-exec mode - load upper TLS offset, add the lower TLS offset,
  2068  		// add the thread pointer register, then load from or store to the resulting
  2069  		// memory location. Note that this differs from the suggested three
  2070  		// instruction sequence, as the Go linker does not currently have an
  2071  		// easy way to handle relocation across 12 bytes of machine code.
  2072  		insLUI := &instruction{as: ALUI, rd: REG_TMP}
  2073  		insADDIW := &instruction{as: AADDIW, rd: REG_TMP, rs1: REG_TMP}
  2074  		inss = []*instruction{insLUI, insADDIW, insAddTP, ins}
  2075  	}
  2076  	return inss
  2077  }
  2078  
  2079  func instructionsForTLSLoad(p *obj.Prog) []*instruction {
  2080  	if p.From.Sym.Type != objabi.STLSBSS {
  2081  		p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.From.Sym)
  2082  		return nil
  2083  	}
  2084  
  2085  	ins := instructionForProg(p)
  2086  	ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), REG_TMP, obj.REG_NONE, 0
  2087  
  2088  	return instructionsForTLS(p, ins)
  2089  }
  2090  
  2091  func instructionsForTLSStore(p *obj.Prog) []*instruction {
  2092  	if p.To.Sym.Type != objabi.STLSBSS {
  2093  		p.Ctxt.Diag("%v: %v is not a TLS symbol", p, p.To.Sym)
  2094  		return nil
  2095  	}
  2096  
  2097  	ins := instructionForProg(p)
  2098  	ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
  2099  
  2100  	return instructionsForTLS(p, ins)
  2101  }
  2102  
  2103  // instructionsForMOV returns the machine instructions for an *obj.Prog that
  2104  // uses a MOV pseudo-instruction.
  2105  func instructionsForMOV(p *obj.Prog) []*instruction {
  2106  	ins := instructionForProg(p)
  2107  	inss := []*instruction{ins}
  2108  
  2109  	if p.Reg != 0 {
  2110  		p.Ctxt.Diag("%v: illegal MOV instruction", p)
  2111  		return nil
  2112  	}
  2113  
  2114  	switch {
  2115  	case p.From.Type == obj.TYPE_CONST && p.To.Type == obj.TYPE_REG:
  2116  		// Handle constant to register moves.
  2117  		if p.As != AMOV {
  2118  			p.Ctxt.Diag("%v: unsupported constant load", p)
  2119  			return nil
  2120  		}
  2121  
  2122  		// For constants larger than 32 bits in size that have trailing zeros,
  2123  		// use the value with the trailing zeros removed and then use a SLLI
  2124  		// instruction to restore the original constant.
  2125  		// For example:
  2126  		// 	MOV $0x8000000000000000, X10
  2127  		// becomes
  2128  		// 	MOV $1, X10
  2129  		// 	SLLI $63, X10, X10
  2130  		var insSLLI *instruction
  2131  		if err := immIFits(ins.imm, 32); err != nil {
  2132  			ctz := bits.TrailingZeros64(uint64(ins.imm))
  2133  			if err := immIFits(ins.imm>>ctz, 32); err == nil {
  2134  				ins.imm = ins.imm >> ctz
  2135  				insSLLI = &instruction{as: ASLLI, rd: ins.rd, rs1: ins.rd, imm: int64(ctz)}
  2136  			}
  2137  		}
  2138  
  2139  		low, high, err := Split32BitImmediate(ins.imm)
  2140  		if err != nil {
  2141  			p.Ctxt.Diag("%v: constant %d too large: %v", p, ins.imm, err)
  2142  			return nil
  2143  		}
  2144  
  2145  		// MOV $c, R -> ADD $c, ZERO, R
  2146  		ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, REG_ZERO, obj.REG_NONE, low
  2147  
  2148  		// LUI is only necessary if the constant does not fit in 12 bits.
  2149  		if high != 0 {
  2150  			// LUI top20bits(c), R
  2151  			// ADD bottom12bits(c), R, R
  2152  			insLUI := &instruction{as: ALUI, rd: ins.rd, imm: high}
  2153  			inss = []*instruction{insLUI}
  2154  			if low != 0 {
  2155  				ins.as, ins.rs1 = AADDIW, ins.rd
  2156  				inss = append(inss, ins)
  2157  			}
  2158  		}
  2159  		if insSLLI != nil {
  2160  			inss = append(inss, insSLLI)
  2161  		}
  2162  
  2163  	case p.From.Type == obj.TYPE_CONST && p.To.Type != obj.TYPE_REG:
  2164  		p.Ctxt.Diag("%v: constant load must target register", p)
  2165  		return nil
  2166  
  2167  	case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG:
  2168  		// Handle register to register moves.
  2169  		switch p.As {
  2170  		case AMOV: // MOV Ra, Rb -> ADDI $0, Ra, Rb
  2171  			ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, uint32(p.From.Reg), obj.REG_NONE, 0
  2172  		case AMOVW: // MOVW Ra, Rb -> ADDIW $0, Ra, Rb
  2173  			ins.as, ins.rs1, ins.rs2, ins.imm = AADDIW, uint32(p.From.Reg), obj.REG_NONE, 0
  2174  		case AMOVBU: // MOVBU Ra, Rb -> ANDI $255, Ra, Rb
  2175  			ins.as, ins.rs1, ins.rs2, ins.imm = AANDI, uint32(p.From.Reg), obj.REG_NONE, 255
  2176  		case AMOVF: // MOVF Ra, Rb -> FSGNJS Ra, Ra, Rb
  2177  			ins.as, ins.rs1 = AFSGNJS, uint32(p.From.Reg)
  2178  		case AMOVD: // MOVD Ra, Rb -> FSGNJD Ra, Ra, Rb
  2179  			ins.as, ins.rs1 = AFSGNJD, uint32(p.From.Reg)
  2180  		case AMOVB, AMOVH:
  2181  			if buildcfg.GORISCV64 >= 22 {
  2182  				// Use SEXTB or SEXTH to extend.
  2183  				ins.as, ins.rs1, ins.rs2 = ASEXTB, uint32(p.From.Reg), obj.REG_NONE
  2184  				if p.As == AMOVH {
  2185  					ins.as = ASEXTH
  2186  				}
  2187  			} else {
  2188  				// Use SLLI/SRAI sequence to extend.
  2189  				ins.as, ins.rs1, ins.rs2 = ASLLI, uint32(p.From.Reg), obj.REG_NONE
  2190  				if p.As == AMOVB {
  2191  					ins.imm = 56
  2192  				} else if p.As == AMOVH {
  2193  					ins.imm = 48
  2194  				}
  2195  				ins2 := &instruction{as: ASRAI, rd: ins.rd, rs1: ins.rd, imm: ins.imm}
  2196  				inss = append(inss, ins2)
  2197  			}
  2198  		case AMOVHU, AMOVWU:
  2199  			if buildcfg.GORISCV64 >= 22 {
  2200  				// Use ZEXTH or ADDUW to extend.
  2201  				ins.as, ins.rs1, ins.rs2, ins.imm = AZEXTH, uint32(p.From.Reg), obj.REG_NONE, 0
  2202  				if p.As == AMOVWU {
  2203  					ins.as, ins.rs2 = AADDUW, REG_ZERO
  2204  				}
  2205  			} else {
  2206  				// Use SLLI/SRLI sequence to extend.
  2207  				ins.as, ins.rs1, ins.rs2 = ASLLI, uint32(p.From.Reg), obj.REG_NONE
  2208  				if p.As == AMOVHU {
  2209  					ins.imm = 48
  2210  				} else if p.As == AMOVWU {
  2211  					ins.imm = 32
  2212  				}
  2213  				ins2 := &instruction{as: ASRLI, rd: ins.rd, rs1: ins.rd, imm: ins.imm}
  2214  				inss = append(inss, ins2)
  2215  			}
  2216  		}
  2217  
  2218  	case p.From.Type == obj.TYPE_MEM && p.To.Type == obj.TYPE_REG:
  2219  		// Memory to register loads.
  2220  		switch p.From.Name {
  2221  		case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
  2222  			// MOV c(Rs), Rd -> L $c, Rs, Rd
  2223  			inss = instructionsForLoad(p, movToLoad(p.As), addrToReg(p.From))
  2224  
  2225  		case obj.NAME_EXTERN, obj.NAME_STATIC:
  2226  			if p.From.Sym.Type == objabi.STLSBSS {
  2227  				return instructionsForTLSLoad(p)
  2228  			}
  2229  
  2230  			// Note that the values for $off_hi and $off_lo are currently
  2231  			// zero and will be assigned during relocation.
  2232  			//
  2233  			// AUIPC $off_hi, Rd
  2234  			// L $off_lo, Rd, Rd
  2235  			insAUIPC := &instruction{as: AAUIPC, rd: ins.rd}
  2236  			ins.as, ins.rs1, ins.rs2, ins.imm = movToLoad(p.As), ins.rd, obj.REG_NONE, 0
  2237  			inss = []*instruction{insAUIPC, ins}
  2238  
  2239  		default:
  2240  			p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
  2241  			return nil
  2242  		}
  2243  
  2244  	case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_MEM:
  2245  		// Register to memory stores.
  2246  		switch p.As {
  2247  		case AMOVBU, AMOVHU, AMOVWU:
  2248  			p.Ctxt.Diag("%v: unsupported unsigned store", p)
  2249  			return nil
  2250  		}
  2251  		switch p.To.Name {
  2252  		case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
  2253  			// MOV Rs, c(Rd) -> S $c, Rs, Rd
  2254  			inss = instructionsForStore(p, movToStore(p.As), addrToReg(p.To))
  2255  
  2256  		case obj.NAME_EXTERN, obj.NAME_STATIC:
  2257  			if p.To.Sym.Type == objabi.STLSBSS {
  2258  				return instructionsForTLSStore(p)
  2259  			}
  2260  
  2261  			// Note that the values for $off_hi and $off_lo are currently
  2262  			// zero and will be assigned during relocation.
  2263  			//
  2264  			// AUIPC $off_hi, Rtmp
  2265  			// S $off_lo, Rtmp, Rd
  2266  			insAUIPC := &instruction{as: AAUIPC, rd: REG_TMP}
  2267  			ins.as, ins.rd, ins.rs1, ins.rs2, ins.imm = movToStore(p.As), REG_TMP, uint32(p.From.Reg), obj.REG_NONE, 0
  2268  			inss = []*instruction{insAUIPC, ins}
  2269  
  2270  		default:
  2271  			p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
  2272  			return nil
  2273  		}
  2274  
  2275  	case p.From.Type == obj.TYPE_ADDR && p.To.Type == obj.TYPE_REG:
  2276  		// MOV $sym+off(SP/SB), R
  2277  		if p.As != AMOV {
  2278  			p.Ctxt.Diag("%v: unsupported address load", p)
  2279  			return nil
  2280  		}
  2281  		switch p.From.Name {
  2282  		case obj.NAME_AUTO, obj.NAME_PARAM, obj.NAME_NONE:
  2283  			inss = instructionsForOpImmediate(p, AADDI, addrToReg(p.From))
  2284  
  2285  		case obj.NAME_EXTERN, obj.NAME_STATIC:
  2286  			// Note that the values for $off_hi and $off_lo are currently
  2287  			// zero and will be assigned during relocation.
  2288  			//
  2289  			// AUIPC $off_hi, R
  2290  			// ADDI $off_lo, R
  2291  			insAUIPC := &instruction{as: AAUIPC, rd: ins.rd}
  2292  			ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, ins.rd, obj.REG_NONE, 0
  2293  			inss = []*instruction{insAUIPC, ins}
  2294  
  2295  		default:
  2296  			p.Ctxt.Diag("unsupported name %d for %v", p.From.Name, p)
  2297  			return nil
  2298  		}
  2299  
  2300  	case p.From.Type == obj.TYPE_ADDR && p.To.Type != obj.TYPE_REG:
  2301  		p.Ctxt.Diag("%v: address load must target register", p)
  2302  		return nil
  2303  
  2304  	default:
  2305  		p.Ctxt.Diag("%v: unsupported MOV", p)
  2306  		return nil
  2307  	}
  2308  
  2309  	return inss
  2310  }
  2311  
  2312  // instructionsForRotate returns the machine instructions for a bitwise rotation.
  2313  func instructionsForRotate(p *obj.Prog, ins *instruction) []*instruction {
  2314  	if buildcfg.GORISCV64 >= 22 {
  2315  		// Rotation instructions are supported natively.
  2316  		return []*instruction{ins}
  2317  	}
  2318  
  2319  	switch ins.as {
  2320  	case AROL, AROLW, AROR, ARORW:
  2321  		// ROL -> OR (SLL x y) (SRL x (NEG y))
  2322  		// ROR -> OR (SRL x y) (SLL x (NEG y))
  2323  		sllOp, srlOp := ASLL, ASRL
  2324  		if ins.as == AROLW || ins.as == ARORW {
  2325  			sllOp, srlOp = ASLLW, ASRLW
  2326  		}
  2327  		shift1, shift2 := sllOp, srlOp
  2328  		if ins.as == AROR || ins.as == ARORW {
  2329  			shift1, shift2 = shift2, shift1
  2330  		}
  2331  		return []*instruction{
  2332  			&instruction{as: ASUB, rs1: REG_ZERO, rs2: ins.rs2, rd: REG_TMP},
  2333  			&instruction{as: shift2, rs1: ins.rs1, rs2: REG_TMP, rd: REG_TMP},
  2334  			&instruction{as: shift1, rs1: ins.rs1, rs2: ins.rs2, rd: ins.rd},
  2335  			&instruction{as: AOR, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
  2336  		}
  2337  
  2338  	case ARORI, ARORIW:
  2339  		// ROR -> OR (SLLI -x y) (SRLI x y)
  2340  		sllOp, srlOp := ASLLI, ASRLI
  2341  		sllImm := int64(int8(-ins.imm) & 63)
  2342  		if ins.as == ARORIW {
  2343  			sllOp, srlOp = ASLLIW, ASRLIW
  2344  			sllImm = int64(int8(-ins.imm) & 31)
  2345  		}
  2346  		return []*instruction{
  2347  			&instruction{as: srlOp, rs1: ins.rs1, rd: REG_TMP, imm: ins.imm},
  2348  			&instruction{as: sllOp, rs1: ins.rs1, rd: ins.rd, imm: sllImm},
  2349  			&instruction{as: AOR, rs1: REG_TMP, rs2: ins.rd, rd: ins.rd},
  2350  		}
  2351  
  2352  	default:
  2353  		p.Ctxt.Diag("%v: unknown rotation", p)
  2354  		return nil
  2355  	}
  2356  }
  2357  
  2358  // instructionsForProg returns the machine instructions for an *obj.Prog.
  2359  func instructionsForProg(p *obj.Prog) []*instruction {
  2360  	ins := instructionForProg(p)
  2361  	inss := []*instruction{ins}
  2362  
  2363  	if len(p.RestArgs) > 1 {
  2364  		p.Ctxt.Diag("too many source registers")
  2365  		return nil
  2366  	}
  2367  
  2368  	switch ins.as {
  2369  	case AJAL, AJALR:
  2370  		ins.rd, ins.rs1, ins.rs2 = uint32(p.From.Reg), uint32(p.To.Reg), obj.REG_NONE
  2371  		ins.imm = p.To.Offset
  2372  
  2373  	case ABEQ, ABEQZ, ABGE, ABGEU, ABGEZ, ABGT, ABGTU, ABGTZ, ABLE, ABLEU, ABLEZ, ABLT, ABLTU, ABLTZ, ABNE, ABNEZ:
  2374  		switch ins.as {
  2375  		case ABEQZ:
  2376  			ins.as, ins.rs1, ins.rs2 = ABEQ, REG_ZERO, uint32(p.From.Reg)
  2377  		case ABGEZ:
  2378  			ins.as, ins.rs1, ins.rs2 = ABGE, REG_ZERO, uint32(p.From.Reg)
  2379  		case ABGT:
  2380  			ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), uint32(p.Reg)
  2381  		case ABGTU:
  2382  			ins.as, ins.rs1, ins.rs2 = ABLTU, uint32(p.From.Reg), uint32(p.Reg)
  2383  		case ABGTZ:
  2384  			ins.as, ins.rs1, ins.rs2 = ABLT, uint32(p.From.Reg), REG_ZERO
  2385  		case ABLE:
  2386  			ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), uint32(p.Reg)
  2387  		case ABLEU:
  2388  			ins.as, ins.rs1, ins.rs2 = ABGEU, uint32(p.From.Reg), uint32(p.Reg)
  2389  		case ABLEZ:
  2390  			ins.as, ins.rs1, ins.rs2 = ABGE, uint32(p.From.Reg), REG_ZERO
  2391  		case ABLTZ:
  2392  			ins.as, ins.rs1, ins.rs2 = ABLT, REG_ZERO, uint32(p.From.Reg)
  2393  		case ABNEZ:
  2394  			ins.as, ins.rs1, ins.rs2 = ABNE, REG_ZERO, uint32(p.From.Reg)
  2395  		}
  2396  		ins.imm = p.To.Offset
  2397  
  2398  	case AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
  2399  		inss = instructionsForMOV(p)
  2400  
  2401  	case ALW, ALWU, ALH, ALHU, ALB, ALBU, ALD, AFLW, AFLD:
  2402  		inss = instructionsForLoad(p, ins.as, p.From.Reg)
  2403  
  2404  	case ASW, ASH, ASB, ASD, AFSW, AFSD:
  2405  		inss = instructionsForStore(p, ins.as, p.To.Reg)
  2406  
  2407  	case ALRW, ALRD:
  2408  		// Set aq to use acquire access ordering
  2409  		ins.funct7 = 2
  2410  		ins.rs1, ins.rs2 = uint32(p.From.Reg), REG_ZERO
  2411  
  2412  	case AADDI, AANDI, AORI, AXORI:
  2413  		inss = instructionsForOpImmediate(p, ins.as, p.Reg)
  2414  
  2415  	case ASCW, ASCD:
  2416  		// Set release access ordering
  2417  		ins.funct7 = 1
  2418  		ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg)
  2419  
  2420  	case AAMOSWAPW, AAMOSWAPD, AAMOADDW, AAMOADDD, AAMOANDW, AAMOANDD, AAMOORW, AAMOORD,
  2421  		AAMOXORW, AAMOXORD, AAMOMINW, AAMOMIND, AAMOMINUW, AAMOMINUD, AAMOMAXW, AAMOMAXD, AAMOMAXUW, AAMOMAXUD:
  2422  		// Set aqrl to use acquire & release access ordering
  2423  		ins.funct7 = 3
  2424  		ins.rd, ins.rs1, ins.rs2 = uint32(p.RegTo2), uint32(p.To.Reg), uint32(p.From.Reg)
  2425  
  2426  	case AECALL, AEBREAK:
  2427  		insEnc := encode(p.As)
  2428  		if p.To.Type == obj.TYPE_NONE {
  2429  			ins.rd = REG_ZERO
  2430  		}
  2431  		ins.rs1 = REG_ZERO
  2432  		ins.imm = insEnc.csr
  2433  
  2434  	case ARDCYCLE, ARDTIME, ARDINSTRET:
  2435  		ins.as = ACSRRS
  2436  		if p.To.Type == obj.TYPE_NONE {
  2437  			ins.rd = REG_ZERO
  2438  		}
  2439  		ins.rs1 = REG_ZERO
  2440  		switch p.As {
  2441  		case ARDCYCLE:
  2442  			ins.imm = -1024
  2443  		case ARDTIME:
  2444  			ins.imm = -1023
  2445  		case ARDINSTRET:
  2446  			ins.imm = -1022
  2447  		}
  2448  
  2449  	case AFENCE:
  2450  		ins.rd, ins.rs1, ins.rs2 = REG_ZERO, REG_ZERO, obj.REG_NONE
  2451  		ins.imm = 0x0ff
  2452  
  2453  	case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
  2454  		// Set the default rounding mode in funct3 to round to zero.
  2455  		if p.Scond&rmSuffixBit == 0 {
  2456  			ins.funct3 = uint32(RM_RTZ)
  2457  		} else {
  2458  			ins.funct3 = uint32(p.Scond &^ rmSuffixBit)
  2459  		}
  2460  
  2461  	case AFNES, AFNED:
  2462  		// Replace FNE[SD] with FEQ[SD] and NOT.
  2463  		if p.To.Type != obj.TYPE_REG {
  2464  			p.Ctxt.Diag("%v needs an integer register output", p)
  2465  			return nil
  2466  		}
  2467  		if ins.as == AFNES {
  2468  			ins.as = AFEQS
  2469  		} else {
  2470  			ins.as = AFEQD
  2471  		}
  2472  		ins2 := &instruction{
  2473  			as:  AXORI, // [bit] xor 1 = not [bit]
  2474  			rd:  ins.rd,
  2475  			rs1: ins.rd,
  2476  			imm: 1,
  2477  		}
  2478  		inss = append(inss, ins2)
  2479  
  2480  	case AFSQRTS, AFSQRTD:
  2481  		// These instructions expect a zero (i.e. float register 0)
  2482  		// to be the second input operand.
  2483  		ins.rs1 = uint32(p.From.Reg)
  2484  		ins.rs2 = REG_F0
  2485  
  2486  	case AFMADDS, AFMSUBS, AFNMADDS, AFNMSUBS,
  2487  		AFMADDD, AFMSUBD, AFNMADDD, AFNMSUBD:
  2488  		// Swap the first two operands so that the operands are in the same
  2489  		// order as they are in the specification: RS1, RS2, RS3, RD.
  2490  		ins.rs1, ins.rs2 = ins.rs2, ins.rs1
  2491  
  2492  	case ANEG, ANEGW:
  2493  		// NEG rs, rd -> SUB rs, X0, rd
  2494  		ins.as = ASUB
  2495  		if p.As == ANEGW {
  2496  			ins.as = ASUBW
  2497  		}
  2498  		ins.rs1 = REG_ZERO
  2499  		if ins.rd == obj.REG_NONE {
  2500  			ins.rd = ins.rs2
  2501  		}
  2502  
  2503  	case ANOT:
  2504  		// NOT rs, rd -> XORI $-1, rs, rd
  2505  		ins.as = AXORI
  2506  		ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
  2507  		if ins.rd == obj.REG_NONE {
  2508  			ins.rd = ins.rs1
  2509  		}
  2510  		ins.imm = -1
  2511  
  2512  	case ASEQZ:
  2513  		// SEQZ rs, rd -> SLTIU $1, rs, rd
  2514  		ins.as = ASLTIU
  2515  		ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
  2516  		ins.imm = 1
  2517  
  2518  	case ASNEZ:
  2519  		// SNEZ rs, rd -> SLTU rs, x0, rd
  2520  		ins.as = ASLTU
  2521  		ins.rs1 = REG_ZERO
  2522  
  2523  	case AFABSS:
  2524  		// FABSS rs, rd -> FSGNJXS rs, rs, rd
  2525  		ins.as = AFSGNJXS
  2526  		ins.rs1 = uint32(p.From.Reg)
  2527  
  2528  	case AFABSD:
  2529  		// FABSD rs, rd -> FSGNJXD rs, rs, rd
  2530  		ins.as = AFSGNJXD
  2531  		ins.rs1 = uint32(p.From.Reg)
  2532  
  2533  	case AFNEGS:
  2534  		// FNEGS rs, rd -> FSGNJNS rs, rs, rd
  2535  		ins.as = AFSGNJNS
  2536  		ins.rs1 = uint32(p.From.Reg)
  2537  
  2538  	case AFNEGD:
  2539  		// FNEGD rs, rd -> FSGNJND rs, rs, rd
  2540  		ins.as = AFSGNJND
  2541  		ins.rs1 = uint32(p.From.Reg)
  2542  
  2543  	case AROL, AROLW, AROR, ARORW:
  2544  		inss = instructionsForRotate(p, ins)
  2545  
  2546  	case ARORI:
  2547  		if ins.imm < 0 || ins.imm > 63 {
  2548  			p.Ctxt.Diag("%v: immediate out of range 0 to 63", p)
  2549  		}
  2550  		inss = instructionsForRotate(p, ins)
  2551  
  2552  	case ARORIW:
  2553  		if ins.imm < 0 || ins.imm > 31 {
  2554  			p.Ctxt.Diag("%v: immediate out of range 0 to 31", p)
  2555  		}
  2556  		inss = instructionsForRotate(p, ins)
  2557  
  2558  	case ASLLI, ASRLI, ASRAI:
  2559  		if ins.imm < 0 || ins.imm > 63 {
  2560  			p.Ctxt.Diag("%v: immediate out of range 0 to 63", p)
  2561  		}
  2562  
  2563  	case ASLLIW, ASRLIW, ASRAIW:
  2564  		if ins.imm < 0 || ins.imm > 31 {
  2565  			p.Ctxt.Diag("%v: immediate out of range 0 to 31", p)
  2566  		}
  2567  
  2568  	case ACLZ, ACLZW, ACTZ, ACTZW, ACPOP, ACPOPW, ASEXTB, ASEXTH, AZEXTH:
  2569  		ins.rs1, ins.rs2 = uint32(p.From.Reg), obj.REG_NONE
  2570  
  2571  	case AORCB, AREV8:
  2572  		ins.rd, ins.rs1, ins.rs2 = uint32(p.To.Reg), uint32(p.From.Reg), obj.REG_NONE
  2573  
  2574  	case AANDN, AORN:
  2575  		if buildcfg.GORISCV64 >= 22 {
  2576  			// ANDN and ORN instructions are supported natively.
  2577  			break
  2578  		}
  2579  		// ANDN -> (AND (NOT x) y)
  2580  		// ORN  -> (OR  (NOT x) y)
  2581  		bitwiseOp, notReg := AAND, ins.rd
  2582  		if ins.as == AORN {
  2583  			bitwiseOp = AOR
  2584  		}
  2585  		if ins.rs1 == notReg {
  2586  			notReg = REG_TMP
  2587  		}
  2588  		inss = []*instruction{
  2589  			&instruction{as: AXORI, rs1: ins.rs2, rs2: obj.REG_NONE, rd: notReg, imm: -1},
  2590  			&instruction{as: bitwiseOp, rs1: ins.rs1, rs2: notReg, rd: ins.rd},
  2591  		}
  2592  
  2593  	case AXNOR:
  2594  		if buildcfg.GORISCV64 >= 22 {
  2595  			// XNOR instruction is supported natively.
  2596  			break
  2597  		}
  2598  		// XNOR -> (NOT (XOR x y))
  2599  		ins.as = AXOR
  2600  		inss = append(inss, &instruction{as: AXORI, rs1: ins.rd, rs2: obj.REG_NONE, rd: ins.rd, imm: -1})
  2601  	}
  2602  
  2603  	for _, ins := range inss {
  2604  		ins.p = p
  2605  	}
  2606  
  2607  	return inss
  2608  }
  2609  
  2610  // assemble emits machine code.
  2611  // It is called at the very end of the assembly process.
  2612  func assemble(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
  2613  	if ctxt.Retpoline {
  2614  		ctxt.Diag("-spectre=ret not supported on riscv")
  2615  		ctxt.Retpoline = false // don't keep printing
  2616  	}
  2617  
  2618  	// If errors were encountered during preprocess/validation, proceeding
  2619  	// and attempting to encode said instructions will only lead to panics.
  2620  	if ctxt.Errors > 0 {
  2621  		return
  2622  	}
  2623  
  2624  	for p := cursym.Func().Text; p != nil; p = p.Link {
  2625  		switch p.As {
  2626  		case AJAL:
  2627  			if p.Mark&NEED_JAL_RELOC == NEED_JAL_RELOC {
  2628  				cursym.AddRel(ctxt, obj.Reloc{
  2629  					Type: objabi.R_RISCV_JAL,
  2630  					Off:  int32(p.Pc),
  2631  					Siz:  4,
  2632  					Sym:  p.To.Sym,
  2633  					Add:  p.To.Offset,
  2634  				})
  2635  			}
  2636  		case AJALR:
  2637  			if p.To.Sym != nil {
  2638  				ctxt.Diag("%v: unexpected AJALR with to symbol", p)
  2639  			}
  2640  
  2641  		case AAUIPC, AMOV, AMOVB, AMOVH, AMOVW, AMOVBU, AMOVHU, AMOVWU, AMOVF, AMOVD:
  2642  			var addr *obj.Addr
  2643  			var rt objabi.RelocType
  2644  			if p.Mark&NEED_CALL_RELOC == NEED_CALL_RELOC {
  2645  				rt = objabi.R_RISCV_CALL
  2646  				addr = &p.From
  2647  			} else if p.Mark&NEED_PCREL_ITYPE_RELOC == NEED_PCREL_ITYPE_RELOC {
  2648  				rt = objabi.R_RISCV_PCREL_ITYPE
  2649  				addr = &p.From
  2650  			} else if p.Mark&NEED_PCREL_STYPE_RELOC == NEED_PCREL_STYPE_RELOC {
  2651  				rt = objabi.R_RISCV_PCREL_STYPE
  2652  				addr = &p.To
  2653  			} else {
  2654  				break
  2655  			}
  2656  			if p.As == AAUIPC {
  2657  				if p.Link == nil {
  2658  					ctxt.Diag("AUIPC needing PC-relative reloc missing following instruction")
  2659  					break
  2660  				}
  2661  				addr = &p.RestArgs[0].Addr
  2662  			}
  2663  			if addr.Sym == nil {
  2664  				ctxt.Diag("PC-relative relocation missing symbol")
  2665  				break
  2666  			}
  2667  			if addr.Sym.Type == objabi.STLSBSS {
  2668  				if ctxt.Flag_shared {
  2669  					rt = objabi.R_RISCV_TLS_IE
  2670  				} else {
  2671  					rt = objabi.R_RISCV_TLS_LE
  2672  				}
  2673  			}
  2674  
  2675  			cursym.AddRel(ctxt, obj.Reloc{
  2676  				Type: rt,
  2677  				Off:  int32(p.Pc),
  2678  				Siz:  8,
  2679  				Sym:  addr.Sym,
  2680  				Add:  addr.Offset,
  2681  			})
  2682  
  2683  		case obj.APCALIGN:
  2684  			alignedValue := p.From.Offset
  2685  			v := pcAlignPadLength(p.Pc, alignedValue)
  2686  			offset := p.Pc
  2687  			for ; v >= 4; v -= 4 {
  2688  				// NOP
  2689  				cursym.WriteBytes(ctxt, offset, []byte{0x13, 0, 0, 0})
  2690  				offset += 4
  2691  			}
  2692  			continue
  2693  		}
  2694  
  2695  		offset := p.Pc
  2696  		for _, ins := range instructionsForProg(p) {
  2697  			if ic, err := ins.encode(); err == nil {
  2698  				cursym.WriteInt(ctxt, offset, ins.length(), int64(ic))
  2699  				offset += int64(ins.length())
  2700  			}
  2701  			if ins.usesRegTmp() {
  2702  				p.Mark |= USES_REG_TMP
  2703  			}
  2704  		}
  2705  	}
  2706  
  2707  	obj.MarkUnsafePoints(ctxt, cursym.Func().Text, newprog, isUnsafePoint, nil)
  2708  }
  2709  
  2710  func isUnsafePoint(p *obj.Prog) bool {
  2711  	return p.Mark&USES_REG_TMP == USES_REG_TMP || p.From.Reg == REG_TMP || p.To.Reg == REG_TMP || p.Reg == REG_TMP
  2712  }
  2713  
  2714  func ParseSuffix(prog *obj.Prog, cond string) (err error) {
  2715  	switch prog.As {
  2716  	case AFCVTWS, AFCVTLS, AFCVTWUS, AFCVTLUS, AFCVTWD, AFCVTLD, AFCVTWUD, AFCVTLUD:
  2717  		prog.Scond, err = rmSuffixEncode(strings.TrimPrefix(cond, "."))
  2718  	}
  2719  	return
  2720  }
  2721  
  2722  var LinkRISCV64 = obj.LinkArch{
  2723  	Arch:           sys.ArchRISCV64,
  2724  	Init:           buildop,
  2725  	Preprocess:     preprocess,
  2726  	Assemble:       assemble,
  2727  	Progedit:       progedit,
  2728  	UnaryDst:       unaryDst,
  2729  	DWARFRegisters: RISCV64DWARFRegisters,
  2730  }
  2731  

View as plain text