//	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
//	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
//	Portions Copyright © 1997-1999 Vita Nuova Limited
//	Portions Copyright © 2000-2008 Vita Nuova Holdings Limited (www.vitanuova.com)
//	Portions Copyright © 2004,2006 Bruce Ellis
//	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
//	Revisions Copyright © 2000-2008 Lucent Technologies Inc. and others
//	Portions Copyright © 2009 The Go Authors.  All rights reserved.
//	Portions Copyright © 2019 The Go Authors.  All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package riscv

import (
	"errors"
	"fmt"

	"cmd/internal/obj"
)

//go:generate go run ../stringer.go -i $GOFILE -o anames.go -p riscv

const (
	// Base register numberings.
	REG_X0 = obj.RBaseRISCV + iota
	REG_X1
	REG_X2
	REG_X3
	REG_X4
	REG_X5
	REG_X6
	REG_X7
	REG_X8
	REG_X9
	REG_X10
	REG_X11
	REG_X12
	REG_X13
	REG_X14
	REG_X15
	REG_X16
	REG_X17
	REG_X18
	REG_X19
	REG_X20
	REG_X21
	REG_X22
	REG_X23
	REG_X24
	REG_X25
	REG_X26
	REG_X27
	REG_X28
	REG_X29
	REG_X30
	REG_X31

	// Floating Point register numberings.
	REG_F0
	REG_F1
	REG_F2
	REG_F3
	REG_F4
	REG_F5
	REG_F6
	REG_F7
	REG_F8
	REG_F9
	REG_F10
	REG_F11
	REG_F12
	REG_F13
	REG_F14
	REG_F15
	REG_F16
	REG_F17
	REG_F18
	REG_F19
	REG_F20
	REG_F21
	REG_F22
	REG_F23
	REG_F24
	REG_F25
	REG_F26
	REG_F27
	REG_F28
	REG_F29
	REG_F30
	REG_F31

	// Vector register numberings.
	REG_V0
	REG_V1
	REG_V2
	REG_V3
	REG_V4
	REG_V5
	REG_V6
	REG_V7
	REG_V8
	REG_V9
	REG_V10
	REG_V11
	REG_V12
	REG_V13
	REG_V14
	REG_V15
	REG_V16
	REG_V17
	REG_V18
	REG_V19
	REG_V20
	REG_V21
	REG_V22
	REG_V23
	REG_V24
	REG_V25
	REG_V26
	REG_V27
	REG_V28
	REG_V29
	REG_V30
	REG_V31

	// This marks the end of the register numbering.
	REG_END

	// General registers reassigned to ABI names.
	REG_ZERO = REG_X0
	REG_RA   = REG_X1 // aka REG_LR
	REG_SP   = REG_X2
	REG_GP   = REG_X3 // aka REG_SB
	REG_TP   = REG_X4
	REG_T0   = REG_X5
	REG_T1   = REG_X6
	REG_T2   = REG_X7
	REG_S0   = REG_X8
	REG_S1   = REG_X9
	REG_A0   = REG_X10
	REG_A1   = REG_X11
	REG_A2   = REG_X12
	REG_A3   = REG_X13
	REG_A4   = REG_X14
	REG_A5   = REG_X15
	REG_A6   = REG_X16
	REG_A7   = REG_X17
	REG_S2   = REG_X18
	REG_S3   = REG_X19
	REG_S4   = REG_X20
	REG_S5   = REG_X21
	REG_S6   = REG_X22
	REG_S7   = REG_X23
	REG_S8   = REG_X24
	REG_S9   = REG_X25
	REG_S10  = REG_X26 // aka REG_CTXT
	REG_S11  = REG_X27 // aka REG_G
	REG_T3   = REG_X28
	REG_T4   = REG_X29
	REG_T5   = REG_X30
	REG_T6   = REG_X31 // aka REG_TMP

	// Go runtime register names.
	REG_CTXT = REG_S10 // Context for closures.
	REG_G    = REG_S11 // G pointer.
	REG_LR   = REG_RA  // Link register.
	REG_TMP  = REG_T6  // Reserved for assembler use.

	// ABI names for floating point registers.
	REG_FT0  = REG_F0
	REG_FT1  = REG_F1
	REG_FT2  = REG_F2
	REG_FT3  = REG_F3
	REG_FT4  = REG_F4
	REG_FT5  = REG_F5
	REG_FT6  = REG_F6
	REG_FT7  = REG_F7
	REG_FS0  = REG_F8
	REG_FS1  = REG_F9
	REG_FA0  = REG_F10
	REG_FA1  = REG_F11
	REG_FA2  = REG_F12
	REG_FA3  = REG_F13
	REG_FA4  = REG_F14
	REG_FA5  = REG_F15
	REG_FA6  = REG_F16
	REG_FA7  = REG_F17
	REG_FS2  = REG_F18
	REG_FS3  = REG_F19
	REG_FS4  = REG_F20
	REG_FS5  = REG_F21
	REG_FS6  = REG_F22
	REG_FS7  = REG_F23
	REG_FS8  = REG_F24
	REG_FS9  = REG_F25
	REG_FS10 = REG_F26
	REG_FS11 = REG_F27
	REG_FT8  = REG_F28
	REG_FT9  = REG_F29
	REG_FT10 = REG_F30
	REG_FT11 = REG_F31

	// Names generated by the SSA compiler.
	REGSP = REG_SP
	REGG  = REG_G
)

// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-dwarf.adoc#dwarf-register-numbers
var RISCV64DWARFRegisters = map[int16]int16{
	// Integer Registers.
	REG_X0:  0,
	REG_X1:  1,
	REG_X2:  2,
	REG_X3:  3,
	REG_X4:  4,
	REG_X5:  5,
	REG_X6:  6,
	REG_X7:  7,
	REG_X8:  8,
	REG_X9:  9,
	REG_X10: 10,
	REG_X11: 11,
	REG_X12: 12,
	REG_X13: 13,
	REG_X14: 14,
	REG_X15: 15,
	REG_X16: 16,
	REG_X17: 17,
	REG_X18: 18,
	REG_X19: 19,
	REG_X20: 20,
	REG_X21: 21,
	REG_X22: 22,
	REG_X23: 23,
	REG_X24: 24,
	REG_X25: 25,
	REG_X26: 26,
	REG_X27: 27,
	REG_X28: 28,
	REG_X29: 29,
	REG_X30: 30,
	REG_X31: 31,

	// Floating-Point Registers.
	REG_F0:  32,
	REG_F1:  33,
	REG_F2:  34,
	REG_F3:  35,
	REG_F4:  36,
	REG_F5:  37,
	REG_F6:  38,
	REG_F7:  39,
	REG_F8:  40,
	REG_F9:  41,
	REG_F10: 42,
	REG_F11: 43,
	REG_F12: 44,
	REG_F13: 45,
	REG_F14: 46,
	REG_F15: 47,
	REG_F16: 48,
	REG_F17: 49,
	REG_F18: 50,
	REG_F19: 51,
	REG_F20: 52,
	REG_F21: 53,
	REG_F22: 54,
	REG_F23: 55,
	REG_F24: 56,
	REG_F25: 57,
	REG_F26: 58,
	REG_F27: 59,
	REG_F28: 60,
	REG_F29: 61,
	REG_F30: 62,
	REG_F31: 63,
}

// Prog.Mark flags.
const (
	// USES_REG_TMP indicates that a machine instruction generated from the
	// corresponding *obj.Prog uses the temporary register.
	USES_REG_TMP = 1 << iota

	// NEED_JAL_RELOC is set on JAL instructions to indicate that a
	// R_RISCV_JAL relocation is needed.
	NEED_JAL_RELOC

	// NEED_CALL_RELOC is set on an AUIPC instruction to indicate that it
	// is the first instruction in an AUIPC + JAL pair that needs a
	// R_RISCV_CALL relocation.
	NEED_CALL_RELOC

	// NEED_PCREL_ITYPE_RELOC is set on AUIPC instructions to indicate that
	// it is the first instruction in an AUIPC + I-type pair that needs a
	// R_RISCV_PCREL_ITYPE relocation.
	NEED_PCREL_ITYPE_RELOC

	// NEED_PCREL_STYPE_RELOC is set on AUIPC instructions to indicate that
	// it is the first instruction in an AUIPC + S-type pair that needs a
	// R_RISCV_PCREL_STYPE relocation.
	NEED_PCREL_STYPE_RELOC

	// NEED_GOT_PCREL_ITYPE_RELOC is set on AUIPC instructions to indicate that
	// it is the first instruction in an AUIPC + I-type pair that needs a
	// R_RISCV_GOT_PCREL_ITYPE relocation.
	NEED_GOT_PCREL_ITYPE_RELOC
)

// RISC-V mnemonics, as defined in the "opcodes" and "opcodes-pseudo" files
// at https://github.com/riscv/riscv-opcodes.
//
// As well as some pseudo-mnemonics (e.g. MOV) used only in the assembler.
//
// See also "The RISC-V Instruction Set Manual" at https://riscv.org/technical/specifications/.
//
// If you modify this table, you MUST run 'go generate' to regenerate anames.go!
const (
	//
	// Unprivileged ISA (version 20240411)
	//

	// 2.4: Integer Computational Instructions
	AADDI = obj.ABaseRISCV + obj.A_ARCHSPECIFIC + iota
	ASLTI
	ASLTIU
	AANDI
	AORI
	AXORI
	ASLLI
	ASRLI
	ASRAI
	ALUI
	AAUIPC
	AADD
	ASLT
	ASLTU
	AAND
	AOR
	AXOR
	ASLL
	ASRL
	ASUB
	ASRA

	// 2.5: Control Transfer Instructions
	AJAL
	AJALR
	ABEQ
	ABNE
	ABLT
	ABLTU
	ABGE
	ABGEU

	// 2.6: Load and Store Instructions
	ALW
	ALWU
	ALH
	ALHU
	ALB
	ALBU
	ASW
	ASH
	ASB

	// 2.7: Memory Ordering Instructions
	AFENCE

	// 4.2: Integer Computational Instructions (RV64I)
	AADDIW
	ASLLIW
	ASRLIW
	ASRAIW
	AADDW
	ASLLW
	ASRLW
	ASUBW
	ASRAW

	// 4.3: Load and Store Instructions (RV64I)
	ALD
	ASD

	// 7.1: CSR Instructions (Zicsr)
	ACSRRW
	ACSRRS
	ACSRRC
	ACSRRWI
	ACSRRSI
	ACSRRCI

	// 13.1: Multiplication Operations
	AMUL
	AMULH
	AMULHU
	AMULHSU
	AMULW

	// 13.2: Division Operations
	ADIV
	ADIVU
	AREM
	AREMU
	ADIVW
	ADIVUW
	AREMW
	AREMUW

	// 14.2: Load-Reserved/Store-Conditional Instructions (Zalrsc)
	ALRD
	ASCD
	ALRW
	ASCW

	// 14.4: Atomic Memory Operations (Zaamo)
	AAMOSWAPD
	AAMOADDD
	AAMOANDD
	AAMOORD
	AAMOXORD
	AAMOMAXD
	AAMOMAXUD
	AAMOMIND
	AAMOMINUD
	AAMOSWAPW
	AAMOADDW
	AAMOANDW
	AAMOORW
	AAMOXORW
	AAMOMAXW
	AAMOMAXUW
	AAMOMINW
	AAMOMINUW

	// 20.5: Single-Precision Load and Store Instructions
	AFLW
	AFSW

	// 20.6: Single-Precision Floating-Point Computational Instructions
	AFADDS
	AFSUBS
	AFMULS
	AFDIVS
	AFMINS
	AFMAXS
	AFSQRTS
	AFMADDS
	AFMSUBS
	AFNMADDS
	AFNMSUBS

	// 20.7: Single-Precision Floating-Point Conversion and Move Instructions
	AFCVTWS
	AFCVTLS
	AFCVTSW
	AFCVTSL
	AFCVTWUS
	AFCVTLUS
	AFCVTSWU
	AFCVTSLU
	AFSGNJS
	AFSGNJNS
	AFSGNJXS
	AFMVXS
	AFMVSX
	AFMVXW
	AFMVWX

	// 20.8: Single-Precision Floating-Point Compare Instructions
	AFEQS
	AFLTS
	AFLES

	// 20.9: Single-Precision Floating-Point Classify Instruction
	AFCLASSS

	// 21.3: Double-Precision Load and Store Instructions
	AFLD
	AFSD

	// 21.4: Double-Precision Floating-Point Computational Instructions
	AFADDD
	AFSUBD
	AFMULD
	AFDIVD
	AFMIND
	AFMAXD
	AFSQRTD
	AFMADDD
	AFMSUBD
	AFNMADDD
	AFNMSUBD

	// 21.5: Double-Precision Floating-Point Conversion and Move Instructions
	AFCVTWD
	AFCVTLD
	AFCVTDW
	AFCVTDL
	AFCVTWUD
	AFCVTLUD
	AFCVTDWU
	AFCVTDLU
	AFCVTSD
	AFCVTDS
	AFSGNJD
	AFSGNJND
	AFSGNJXD
	AFMVXD
	AFMVDX

	// 21.6: Double-Precision Floating-Point Compare Instructions
	AFEQD
	AFLTD
	AFLED

	// 21.7: Double-Precision Floating-Point Classify Instruction
	AFCLASSD

	// 22.1 Quad-Precision Load and Store Instructions
	AFLQ
	AFSQ

	// 22.2: Quad-Precision Computational Instructions
	AFADDQ
	AFSUBQ
	AFMULQ
	AFDIVQ
	AFMINQ
	AFMAXQ
	AFSQRTQ
	AFMADDQ
	AFMSUBQ
	AFNMADDQ
	AFNMSUBQ

	// 22.3 Quad-Precision Convert and Move Instructions
	AFCVTWQ
	AFCVTLQ
	AFCVTSQ
	AFCVTDQ
	AFCVTQW
	AFCVTQL
	AFCVTQS
	AFCVTQD
	AFCVTWUQ
	AFCVTLUQ
	AFCVTQWU
	AFCVTQLU
	AFSGNJQ
	AFSGNJNQ
	AFSGNJXQ

	// 22.4 Quad-Precision Floating-Point Compare Instructions
	AFEQQ
	AFLEQ
	AFLTQ

	// 22.5 Quad-Precision Floating-Point Classify Instruction
	AFCLASSQ

	//
	// "B" Extension for Bit Manipulation, Version 1.0.0
	//

	// 28.4.1: Address Generation Instructions (Zba)
	AADDUW
	ASH1ADD
	ASH1ADDUW
	ASH2ADD
	ASH2ADDUW
	ASH3ADD
	ASH3ADDUW
	ASLLIUW

	// 28.4.2: Basic Bit Manipulation (Zbb)
	AANDN
	AORN
	AXNOR
	ACLZ
	ACLZW
	ACTZ
	ACTZW
	ACPOP
	ACPOPW
	AMAX
	AMAXU
	AMIN
	AMINU
	ASEXTB
	ASEXTH
	AZEXTH

	// 28.4.3: Bitwise Rotation (Zbb)
	AROL
	AROLW
	AROR
	ARORI
	ARORIW
	ARORW
	AORCB
	AREV8

	// 28.4.4: Single-bit Instructions (Zbs)
	ABCLR
	ABCLRI
	ABEXT
	ABEXTI
	ABINV
	ABINVI
	ABSET
	ABSETI

	//
	// "V" Standard Extension for Vector Operations, Version 1.0
	//

	// 31.6: Configuration-Setting Instructions
	AVSETVLI
	AVSETIVLI
	AVSETVL

	// 31.7.4: Vector Unit-Stride Instructions
	AVLE8V
	AVLE16V
	AVLE32V
	AVLE64V
	AVSE8V
	AVSE16V
	AVSE32V
	AVSE64V
	AVLMV
	AVSMV

	// 31.7.5: Vector Strided Instructions
	AVLSE8V
	AVLSE16V
	AVLSE32V
	AVLSE64V
	AVSSE8V
	AVSSE16V
	AVSSE32V
	AVSSE64V

	// 31.7.6: Vector Indexed Instructions
	AVLUXEI8V
	AVLUXEI16V
	AVLUXEI32V
	AVLUXEI64V
	AVLOXEI8V
	AVLOXEI16V
	AVLOXEI32V
	AVLOXEI64V
	AVSUXEI8V
	AVSUXEI16V
	AVSUXEI32V
	AVSUXEI64V
	AVSOXEI8V
	AVSOXEI16V
	AVSOXEI32V
	AVSOXEI64V

	// 31.7.7: Unit-stride Fault-Only-First Loads
	AVLE8FFV
	AVLE16FFV
	AVLE32FFV
	AVLE64FFV

	// 31.7.9: Vector Load/Store Whole Register Instructions
	AVL1RE8V
	AVL1RE16V
	AVL1RE32V
	AVL1RE64V
	AVL2RE8V
	AVL2RE16V
	AVL2RE32V
	AVL2RE64V
	AVL4RE8V
	AVL4RE16V
	AVL4RE32V
	AVL4RE64V
	AVL8RE8V
	AVL8RE16V
	AVL8RE32V
	AVL8RE64V
	AVS1RV
	AVS2RV
	AVS4RV
	AVS8RV

	// 31.11.1: Vector Single-Width Integer Add and Subtract
	AVADDVV
	AVADDVX
	AVADDVI
	AVSUBVV
	AVSUBVX
	AVRSUBVX
	AVRSUBVI

	// 31.11.2: Vector Widening Integer Add/Subtract
	AVWADDUVV
	AVWADDUVX
	AVWSUBUVV
	AVWSUBUVX
	AVWADDVV
	AVWADDVX
	AVWSUBVV
	AVWSUBVX
	AVWADDUWV
	AVWADDUWX
	AVWSUBUWV
	AVWSUBUWX
	AVWADDWV
	AVWADDWX
	AVWSUBWV
	AVWSUBWX

	// 31.11.3: Vector Integer Extension
	AVZEXTVF2
	AVSEXTVF2
	AVZEXTVF4
	AVSEXTVF4
	AVZEXTVF8
	AVSEXTVF8

	// 31.11.4: Vector Integer Add-with-Carry / Subtract-with-Borrow Instructions
	AVADCVVM
	AVADCVXM
	AVADCVIM
	AVMADCVVM
	AVMADCVXM
	AVMADCVIM
	AVMADCVV
	AVMADCVX
	AVMADCVI
	AVSBCVVM
	AVSBCVXM
	AVMSBCVVM
	AVMSBCVXM
	AVMSBCVV
	AVMSBCVX

	// 31.11.5: Vector Bitwise Logical Instructions
	AVANDVV
	AVANDVX
	AVANDVI
	AVORVV
	AVORVX
	AVORVI
	AVXORVV
	AVXORVX
	AVXORVI

	// 31.11.6: Vector Single-Width Shift Instructions
	AVSLLVV
	AVSLLVX
	AVSLLVI
	AVSRLVV
	AVSRLVX
	AVSRLVI
	AVSRAVV
	AVSRAVX
	AVSRAVI

	// 31.11.7: Vector Narrowing Integer Right Shift Instructions
	AVNSRLWV
	AVNSRLWX
	AVNSRLWI
	AVNSRAWV
	AVNSRAWX
	AVNSRAWI

	// 31.11.8: Vector Integer Compare Instructions
	AVMSEQVV
	AVMSEQVX
	AVMSEQVI
	AVMSNEVV
	AVMSNEVX
	AVMSNEVI
	AVMSLTUVV
	AVMSLTUVX
	AVMSLTVV
	AVMSLTVX
	AVMSLEUVV
	AVMSLEUVX
	AVMSLEUVI
	AVMSLEVV
	AVMSLEVX
	AVMSLEVI
	AVMSGTUVX
	AVMSGTUVI
	AVMSGTVX
	AVMSGTVI

	// 31.11.9: Vector Integer Min/Max Instructions
	AVMINUVV
	AVMINUVX
	AVMINVV
	AVMINVX
	AVMAXUVV
	AVMAXUVX
	AVMAXVV
	AVMAXVX

	// 31.11.10: Vector Single-Width Integer Multiply Instructions
	AVMULVV
	AVMULVX
	AVMULHVV
	AVMULHVX
	AVMULHUVV
	AVMULHUVX
	AVMULHSUVV
	AVMULHSUVX

	// 31.11.11: Vector Integer Divide Instructions
	AVDIVUVV
	AVDIVUVX
	AVDIVVV
	AVDIVVX
	AVREMUVV
	AVREMUVX
	AVREMVV
	AVREMVX

	// 31.11.12: Vector Widening Integer Multiply Instructions
	AVWMULVV
	AVWMULVX
	AVWMULUVV
	AVWMULUVX
	AVWMULSUVV
	AVWMULSUVX

	// 31.11.13: Vector Single-Width Integer Multiply-Add Instructions
	AVMACCVV
	AVMACCVX
	AVNMSACVV
	AVNMSACVX
	AVMADDVV
	AVMADDVX
	AVNMSUBVV
	AVNMSUBVX

	// 31.11.14: Vector Widening Integer Multiply-Add Instructions
	AVWMACCUVV
	AVWMACCUVX
	AVWMACCVV
	AVWMACCVX
	AVWMACCSUVV
	AVWMACCSUVX
	AVWMACCUSVX

	// 31.11.15: Vector Integer Merge Instructions
	AVMERGEVVM
	AVMERGEVXM
	AVMERGEVIM

	// 31.11.16: Vector Integer Move Instructions
	AVMVVV
	AVMVVX
	AVMVVI

	// 31.12.1: Vector Single-Width Saturating Add and Subtract
	AVSADDUVV
	AVSADDUVX
	AVSADDUVI
	AVSADDVV
	AVSADDVX
	AVSADDVI
	AVSSUBUVV
	AVSSUBUVX
	AVSSUBVV
	AVSSUBVX

	// 31.12.2: Vector Single-Width Averaging Add and Subtract
	AVAADDUVV
	AVAADDUVX
	AVAADDVV
	AVAADDVX
	AVASUBUVV
	AVASUBUVX
	AVASUBVV
	AVASUBVX

	// 31.12.3: Vector Single-Width Fractional Multiply with Rounding and Saturation
	AVSMULVV
	AVSMULVX

	// 31.12.4: Vector Single-Width Scaling Shift Instructions
	AVSSRLVV
	AVSSRLVX
	AVSSRLVI
	AVSSRAVV
	AVSSRAVX
	AVSSRAVI

	// 31.12.5: Vector Narrowing Fixed-Point Clip Instructions
	AVNCLIPUWV
	AVNCLIPUWX
	AVNCLIPUWI
	AVNCLIPWV
	AVNCLIPWX
	AVNCLIPWI

	// 31.13.2: Vector Single-Width Floating-Point Add/Subtract Instructions
	AVFADDVV
	AVFADDVF
	AVFSUBVV
	AVFSUBVF
	AVFRSUBVF

	// 31.13.3: Vector Widening Floating-Point Add/Subtract Instructions
	AVFWADDVV
	AVFWADDVF
	AVFWSUBVV
	AVFWSUBVF
	AVFWADDWV
	AVFWADDWF
	AVFWSUBWV
	AVFWSUBWF

	// 31.13.4: Vector Single-Width Floating-Point Multiply/Divide Instructions
	AVFMULVV
	AVFMULVF
	AVFDIVVV
	AVFDIVVF
	AVFRDIVVF

	// 31.13.5: Vector Widening Floating-Point Multiply
	AVFWMULVV
	AVFWMULVF

	// 31.13.6: Vector Single-Width Floating-Point Fused Multiply-Add Instructions
	AVFMACCVV
	AVFMACCVF
	AVFNMACCVV
	AVFNMACCVF
	AVFMSACVV
	AVFMSACVF
	AVFNMSACVV
	AVFNMSACVF
	AVFMADDVV
	AVFMADDVF
	AVFNMADDVV
	AVFNMADDVF
	AVFMSUBVV
	AVFMSUBVF
	AVFNMSUBVV
	AVFNMSUBVF

	// 31.13.7: Vector Widening Floating-Point Fused Multiply-Add Instructions
	AVFWMACCVV
	AVFWMACCVF
	AVFWNMACCVV
	AVFWNMACCVF
	AVFWMSACVV
	AVFWMSACVF
	AVFWNMSACVV
	AVFWNMSACVF

	// 31.13.8: Vector Floating-Point Square-Root Instruction
	AVFSQRTV

	// 31.13.9: Vector Floating-Point Reciprocal Square-Root Estimate Instruction
	AVFRSQRT7V

	// 31.13.10: Vector Floating-Point Reciprocal Estimate Instruction
	AVFREC7V

	// 31.13.11: Vector Floating-Point MIN/MAX Instructions
	AVFMINVV
	AVFMINVF
	AVFMAXVV
	AVFMAXVF

	// 31.13.12: Vector Floating-Point Sign-Injection Instructions
	AVFSGNJVV
	AVFSGNJVF
	AVFSGNJNVV
	AVFSGNJNVF
	AVFSGNJXVV
	AVFSGNJXVF

	// 31.13.13: Vector Floating-Point Compare Instructions
	AVMFEQVV
	AVMFEQVF
	AVMFNEVV
	AVMFNEVF
	AVMFLTVV
	AVMFLTVF
	AVMFLEVV
	AVMFLEVF
	AVMFGTVF
	AVMFGEVF

	// 31.13.14: Vector Floating-Point Classify Instruction
	AVFCLASSV

	// 31.13.15: Vector Floating-Point Merge Instruction
	AVFMERGEVFM

	// 31.13.16: Vector Floating-Point Move Instruction
	AVFMVVF

	// 31.13.17: Single-Width Floating-Point/Integer Type-Convert Instructions
	AVFCVTXUFV
	AVFCVTXFV
	AVFCVTRTZXUFV
	AVFCVTRTZXFV
	AVFCVTFXUV
	AVFCVTFXV

	// 31.13.18: Widening Floating-Point/Integer Type-Convert Instructions
	AVFWCVTXUFV
	AVFWCVTXFV
	AVFWCVTRTZXUFV
	AVFWCVTRTZXFV
	AVFWCVTFXUV
	AVFWCVTFXV
	AVFWCVTFFV

	// 31.13.19: Narrowing Floating-Point/Integer Type-Convert Instructions
	AVFNCVTXUFW
	AVFNCVTXFW
	AVFNCVTRTZXUFW
	AVFNCVTRTZXFW
	AVFNCVTFXUW
	AVFNCVTFXW
	AVFNCVTFFW
	AVFNCVTRODFFW

	// 31.14.1: Vector Single-Width Integer Reduction Instructions
	AVREDSUMVS
	AVREDMAXUVS
	AVREDMAXVS
	AVREDMINUVS
	AVREDMINVS
	AVREDANDVS
	AVREDORVS
	AVREDXORVS

	// 31.14.2: Vector Widening Integer Reduction Instructions
	AVWREDSUMUVS
	AVWREDSUMVS

	// 31.14.3: Vector Single-Width Floating-Point Reduction Instructions
	AVFREDOSUMVS
	AVFREDUSUMVS
	AVFREDMAXVS
	AVFREDMINVS

	// 31.14.4: Vector Widening Floating-Point Reduction Instructions
	AVFWREDOSUMVS
	AVFWREDUSUMVS

	// 31.15: Vector Mask Instructions
	AVMANDMM
	AVMNANDMM
	AVMANDNMM
	AVMXORMM
	AVMORMM
	AVMNORMM
	AVMORNMM
	AVMXNORMM
	AVCPOPM
	AVFIRSTM
	AVMSBFM
	AVMSIFM
	AVMSOFM
	AVIOTAM
	AVIDV

	// 31.16.1: Integer Scalar Move Instructions
	AVMVXS
	AVMVSX

	// 31.16.2: Floating-Point Scalar Move Instructions
	AVFMVFS
	AVFMVSF

	// 31.16.3: Vector Slide Instructions
	AVSLIDEUPVX
	AVSLIDEUPVI
	AVSLIDEDOWNVX
	AVSLIDEDOWNVI
	AVSLIDE1UPVX
	AVFSLIDE1UPVF
	AVSLIDE1DOWNVX
	AVFSLIDE1DOWNVF

	// 31.16.4: Vector Register Gather Instructions
	AVRGATHERVV
	AVRGATHEREI16VV
	AVRGATHERVX
	AVRGATHERVI

	// 31.16.5: Vector Compress Instruction
	AVCOMPRESSVM

	// 31.16.6: Whole Vector Register Move
	AVMV1RV
	AVMV2RV
	AVMV4RV
	AVMV8RV

	//
	// Privileged ISA (version 20240411)
	//

	// 3.3.1: Environment Call and Breakpoint
	AECALL
	ASCALL
	AEBREAK
	ASBREAK

	// 3.3.2: Trap-Return Instructions
	AMRET
	ASRET
	ADRET

	// 3.3.3: Wait for Interrupt
	AWFI

	// 10.2: Supervisor Memory-Management Fence Instruction
	ASFENCEVMA

	// The escape hatch. Inserts a single 32-bit word.
	AWORD

	// Pseudo-instructions.  These get translated by the assembler into other
	// instructions, based on their operands.
	ABEQZ
	ABGEZ
	ABGT
	ABGTU
	ABGTZ
	ABLE
	ABLEU
	ABLEZ
	ABLTZ
	ABNEZ
	AFABSD
	AFABSS
	AFNED
	AFNEGD
	AFNEGS
	AFNES
	AMOV
	AMOVB
	AMOVBU
	AMOVD
	AMOVF
	AMOVH
	AMOVHU
	AMOVW
	AMOVWU
	ANEG
	ANEGW
	ANOT
	ARDCYCLE
	ARDINSTRET
	ARDTIME
	ASEQZ
	ASNEZ
	AVFABSV
	AVFNEGV
	AVL1RV
	AVL2RV
	AVL4RV
	AVL8RV
	AVMCLRM
	AVMFGEVV
	AVMFGTVV
	AVMMVM
	AVMNOTM
	AVMSETM
	AVMSGEUVI
	AVMSGEUVV
	AVMSGEVI
	AVMSGEVV
	AVMSGTUVV
	AVMSGTVV
	AVMSLTUVI
	AVMSLTVI
	AVNCVTXXW
	AVNEGV
	AVNOTV
	AVWCVTUXXV
	AVWCVTXXV

	// End marker
	ALAST
)

// opSuffix encoding to uint8 which fit into p.Scond
var rmSuffixSet = map[string]uint8{
	"RNE": RM_RNE,
	"RTZ": RM_RTZ,
	"RDN": RM_RDN,
	"RUP": RM_RUP,
	"RMM": RM_RMM,
}

const rmSuffixBit uint8 = 1 << 7

func rmSuffixEncode(s string) (uint8, error) {
	if s == "" {
		return 0, errors.New("empty suffix")
	}
	enc, ok := rmSuffixSet[s]
	if !ok {
		return 0, fmt.Errorf("invalid encoding for unknown suffix:%q", s)
	}
	return enc | rmSuffixBit, nil
}

func rmSuffixString(u uint8) (string, error) {
	if u&rmSuffixBit == 0 {
		return "", fmt.Errorf("invalid suffix, require round mode bit:%x", u)
	}

	u &^= rmSuffixBit
	for k, v := range rmSuffixSet {
		if v == u {
			return k, nil
		}
	}
	return "", fmt.Errorf("unknown suffix:%x", u)
}

const (
	RM_RNE uint8 = iota // Round to Nearest, ties to Even
	RM_RTZ              // Round towards Zero
	RM_RDN              // Round Down
	RM_RUP              // Round Up
	RM_RMM              // Round to Nearest, ties to Max Magnitude
)

type SpecialOperand int

const (
	SPOP_BEGIN SpecialOperand = obj.SpecialOperandRISCVBase

	// Vector mask policy.
	SPOP_MA SpecialOperand = obj.SpecialOperandRISCVBase + iota - 1
	SPOP_MU

	// Vector tail policy.
	SPOP_TA
	SPOP_TU

	// Vector register group multiplier (VLMUL).
	SPOP_M1
	SPOP_M2
	SPOP_M4
	SPOP_M8
	SPOP_MF2
	SPOP_MF4
	SPOP_MF8

	// Vector selected element width (VSEW).
	SPOP_E8
	SPOP_E16
	SPOP_E32
	SPOP_E64

	SPOP_END
)

var specialOperands = map[SpecialOperand]struct {
	encoding uint32
	name     string
}{
	SPOP_MA: {encoding: 1, name: "MA"},
	SPOP_MU: {encoding: 0, name: "MU"},

	SPOP_TA: {encoding: 1, name: "TA"},
	SPOP_TU: {encoding: 0, name: "TU"},

	SPOP_M1:  {encoding: 0, name: "M1"},
	SPOP_M2:  {encoding: 1, name: "M2"},
	SPOP_M4:  {encoding: 2, name: "M4"},
	SPOP_M8:  {encoding: 3, name: "M8"},
	SPOP_MF8: {encoding: 5, name: "MF8"},
	SPOP_MF4: {encoding: 6, name: "MF4"},
	SPOP_MF2: {encoding: 7, name: "MF2"},

	SPOP_E8:  {encoding: 0, name: "E8"},
	SPOP_E16: {encoding: 1, name: "E16"},
	SPOP_E32: {encoding: 2, name: "E32"},
	SPOP_E64: {encoding: 3, name: "E64"},
}

func (so SpecialOperand) encode() uint32 {
	op, ok := specialOperands[so]
	if ok {
		return op.encoding
	}
	return 0
}

func (so SpecialOperand) String() string {
	op, ok := specialOperands[so]
	if ok {
		return op.name
	}
	return ""
}

// All unary instructions which write to their arguments (as opposed to reading
// from them) go here. The assembly parser uses this information to populate
// its AST in a semantically reasonable way.
//
// Any instructions not listed here are assumed to either be non-unary or to read
// from its argument.
var unaryDst = map[obj.As]bool{
	ARDCYCLE:   true,
	ARDTIME:    true,
	ARDINSTRET: true,
}

// Instruction encoding masks.
const (
	// BTypeImmMask is a mask including only the immediate portion of
	// B-type instructions.
	BTypeImmMask = 0xfe000f80

	// CBTypeImmMask is a mask including only the immediate portion of
	// CB-type instructions.
	CBTypeImmMask = 0x1c7c

	// CJTypeImmMask is a mask including only the immediate portion of
	// CJ-type instructions.
	CJTypeImmMask = 0x1f7c

	// ITypeImmMask is a mask including only the immediate portion of
	// I-type instructions.
	ITypeImmMask = 0xfff00000

	// JTypeImmMask is a mask including only the immediate portion of
	// J-type instructions.
	JTypeImmMask = 0xfffff000

	// STypeImmMask is a mask including only the immediate portion of
	// S-type instructions.
	STypeImmMask = 0xfe000f80

	// UTypeImmMask is a mask including only the immediate portion of
	// U-type instructions.
	UTypeImmMask = 0xfffff000
)
