// 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 // FP 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 // 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 ) // 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/specifications/. // // If you modify this table, you MUST run 'go generate' to regenerate anames.go! const ( // Unprivileged ISA (Document Version 20190608-Base-Ratified) // 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 AFENCETSO APAUSE // 5.2: Integer Computational Instructions (RV64I) AADDIW ASLLIW ASRLIW ASRAIW AADDW ASLLW ASRLW ASUBW ASRAW // 5.3: Load and Store Instructions (RV64I) ALD ASD // 7.1: Multiplication Operations AMUL AMULH AMULHU AMULHSU AMULW ADIV ADIVU AREM AREMU ADIVW ADIVUW AREMW AREMUW // 8.2: Load-Reserved/Store-Conditional Instructions ALRD ASCD ALRW ASCW // 8.3: Atomic Memory Operations AAMOSWAPD AAMOADDD AAMOANDD AAMOORD AAMOXORD AAMOMAXD AAMOMAXUD AAMOMIND AAMOMINUD AAMOSWAPW AAMOADDW AAMOANDW AAMOORW AAMOXORW AAMOMAXW AAMOMAXUW AAMOMINW AAMOMINUW // 10.1: Base Counters and Timers ARDCYCLE ARDCYCLEH ARDTIME ARDTIMEH ARDINSTRET ARDINSTRETH // 11.2: Floating-Point Control and Status Register AFRCSR AFSCSR AFRRM AFSRM AFRFLAGS AFSFLAGS AFSRMI AFSFLAGSI // 11.5: Single-Precision Load and Store Instructions AFLW AFSW // 11.6: Single-Precision Floating-Point Computational Instructions AFADDS AFSUBS AFMULS AFDIVS AFMINS AFMAXS AFSQRTS AFMADDS AFMSUBS AFNMADDS AFNMSUBS // 11.7: Single-Precision Floating-Point Conversion and Move Instructions AFCVTWS AFCVTLS AFCVTSW AFCVTSL AFCVTWUS AFCVTLUS AFCVTSWU AFCVTSLU AFSGNJS AFSGNJNS AFSGNJXS AFMVXS AFMVSX AFMVXW AFMVWX // 11.8: Single-Precision Floating-Point Compare Instructions AFEQS AFLTS AFLES // 11.9: Single-Precision Floating-Point Classify Instruction AFCLASSS // 12.3: Double-Precision Load and Store Instructions AFLD AFSD // 12.4: Double-Precision Floating-Point Computational Instructions AFADDD AFSUBD AFMULD AFDIVD AFMIND AFMAXD AFSQRTD AFMADDD AFMSUBD AFNMADDD AFNMSUBD // 12.5: Double-Precision Floating-Point Conversion and Move Instructions AFCVTWD AFCVTLD AFCVTDW AFCVTDL AFCVTWUD AFCVTLUD AFCVTDWU AFCVTDLU AFCVTSD AFCVTDS AFSGNJD AFSGNJND AFSGNJXD AFMVXD AFMVDX // 12.6: Double-Precision Floating-Point Compare Instructions AFEQD AFLTD AFLED // 12.7: Double-Precision Floating-Point Classify Instruction AFCLASSD // 13.1 Quad-Precision Load and Store Instructions AFLQ AFSQ // 13.2: Quad-Precision Computational Instructions AFADDQ AFSUBQ AFMULQ AFDIVQ AFMINQ AFMAXQ AFSQRTQ AFMADDQ AFMSUBQ AFNMADDQ AFNMSUBQ // 13.3 Quad-Precision Convert and Move Instructions AFCVTWQ AFCVTLQ AFCVTSQ AFCVTDQ AFCVTQW AFCVTQL AFCVTQS AFCVTQD AFCVTWUQ AFCVTLUQ AFCVTQWU AFCVTQLU AFSGNJQ AFSGNJNQ AFSGNJXQ // 13.4 Quad-Precision Floating-Point Compare Instructions AFEQQ AFLEQ AFLTQ // 13.5 Quad-Precision Floating-Point Classify Instruction AFCLASSQ // Privileged ISA (Version 20190608-Priv-MSU-Ratified) // 3.1.9: Instructions to Access CSRs ACSRRW ACSRRS ACSRRC ACSRRWI ACSRRSI ACSRRCI // 3.2.1: Environment Call and Breakpoint AECALL ASCALL AEBREAK ASBREAK // 3.2.2: Trap-Return Instructions AMRET ASRET ADRET // 3.2.3: Wait for Interrupt AWFI // 4.2.1: Supervisor Memory-Management Fence Instruction ASFENCEVMA // // RISC-V Bit-Manipulation ISA-extensions (1.0) // // 1.1: Address Generation Instructions (Zba) AADDUW ASH1ADD ASH1ADDUW ASH2ADD ASH2ADDUW ASH3ADD ASH3ADDUW ASLLIUW // 1.2: Basic Bit Manipulation (Zbb) AANDN AORN AXNOR ACLZ ACLZW ACTZ ACTZW ACPOP ACPOPW AMAX AMAXU AMIN AMINU ASEXTB ASEXTH AZEXTH // 1.3: Bitwise Rotation (Zbb) AROL AROLW AROR ARORI ARORIW ARORW AORCB AREV8 // 1.5: Single-bit Instructions (Zbs) ABCLR ABCLRI ABEXT ABEXTI ABINV ABINVI ABSET ABSETI // 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 AFNEGD AFNEGS AFNED AFNES AMOV AMOVB AMOVBU AMOVF AMOVD AMOVH AMOVHU AMOVW AMOVWU ANEG ANEGW ANOT ASEQZ ASNEZ // 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 ) // 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, ARDCYCLEH: true, ARDTIME: true, ARDTIMEH: true, ARDINSTRET: true, ARDINSTRETH: 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 )