Source file src/cmd/internal/obj/riscv/doc.go
1 // Copyright 2025 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 /* 6 Package riscv implements the riscv64 assembler. 7 8 # Register naming 9 10 The integer registers are named X0 through to X31, however X4 must be accessed 11 through its RISC-V ABI name, TP, and X27, which holds a pointer to the Go 12 routine structure, must be referred to as g. Additionally, when building in 13 shared mode, X3 is unavailable and must be accessed via its RISC-V ABI name, 14 GP. 15 16 The floating-point registers are named F0 through to F31. 17 18 The vector registers are named V0 through to V31. 19 20 Both integer and floating-point registers can be referred to by their RISC-V 21 ABI names, e.g., A0 or FT0, with the exception that X27 cannot be referred to 22 by its RISC-V ABI name, S11. It must be referred to as g. 23 24 Some of the integer registers are used by the Go runtime and assembler - X26 is 25 the closure pointer, X27 points to the Go routine structure and X31 is a 26 temporary register used by the Go assembler. Use of X31 should be avoided in 27 hand written assembly code as its value could be altered by the instruction 28 sequences emitted by the assembler. 29 30 # Instruction naming 31 32 Many RISC-V instructions contain one or more suffixes in their names. In the 33 [RISC-V ISA Manual] these suffixes are separated from themselves and the 34 name of the instruction mnemonic with a dot ('.'). In the Go assembler, the 35 separators are omitted and the suffixes are written in upper case. 36 37 Example: 38 39 FMVWX <=> fmv.w.x 40 41 # Rounding modes 42 43 The Go toolchain does not set the FCSR register and requires the desired 44 rounding mode to be explicitly encoded within floating-point instructions. 45 The syntax the Go assembler uses to specify the rounding modes differs 46 from the syntax in the RISC-V specifications. In the [RISC-V ISA Manual] 47 the rounding mode is given as an extra operand at the end of an 48 assembly language instruction. In the Go assembler, the rounding modes are 49 converted to uppercase and follow the instruction mnemonic from which they 50 are separated with a dot ('.'). 51 52 Example: 53 54 FCVTLUS.RNE F0, X5 <=> fcvt.lu.s x5, f0, rne 55 56 RTZ is assumed if the rounding mode is omitted. 57 58 # RISC-V extensions 59 60 By default the Go compiler targets the [rva20u64] profile. This profile mandates 61 all the general RISC-V instructions, allowing Go to use integer, multiplication, 62 division, floating-point and atomic instructions without having to 63 perform compile time or runtime checks to verify that their use is appropriate 64 for the target hardware. All widely available riscv64 devices support at least 65 [rva20u64]. The Go toolchain can be instructed to target later RISC-V profiles, 66 including, [rva22u64] and [rva23u64], via the GORISCV64 environment variable. 67 Instructions that are provided by newer profiles cannot typically be used in 68 handwritten assembly code without compile time guards (or runtime checks) 69 that ensure they are hardware supported. 70 71 The file asm_riscv64.h defines macros for each RISC-V extension that is enabled 72 by setting the GORISCV64 environment variable to a value other than [rva20u64]. 73 For example, if GORISCV64=rva22u64 the macros hasZba, hasZbb and hasZbs will be 74 defined. If GORISCV64=rva23u64 hasV will be defined in addition to hasZba, 75 hasZbb and hasZbs. These macros can be used to determine whether it's safe 76 to use an instruction in hand-written assembly. 77 78 It is not always necessary to include asm_riscv64.h and use #ifdefs in your 79 code to safely take advantage of instructions present in the [rva22u64] 80 profile. In some cases the assembler can generate [rva20u64] compatible code 81 even when an [rva22u64] instruction is used in an assembly source file. When 82 GORISCV64=rva20u64 the assembler will synthesize certain [rva22u64] 83 instructions, e.g., ANDN, using multiple [rva20u64] instructions. Instructions 84 such as ANDN can then be freely used in assembly code without checking to see 85 whether the instruction is supported by the target profile. When building a 86 source file containing the ANDN instruction with GORISCV64=rva22u64 the 87 assembler will emit the Zbb ANDN instruction directly. When building the same 88 source file with GORISCV64=rva20u64 the assembler will emit multiple [rva20u64] 89 instructions to synthesize ANDN. 90 91 The assembler will also use [rva22u64] instructions to implement the zero and 92 sign extension instructions, e.g., MOVB and MOVHU, when GORISCV64=rva22u64 or 93 greater. 94 95 The instructions not implemented in the default profile ([rva20u64]) that can 96 be safely used in assembly code without compile time checks are: 97 98 - ANDN 99 - MAX 100 - MAXU 101 - MIN 102 - MINU 103 - MOVB 104 - MOVH 105 - MOVHU 106 - MOVWU 107 - ORN 108 - ROL 109 - ROLW 110 - ROR 111 - RORI 112 - RORIW 113 - RORW 114 - XNOR 115 116 # Operand ordering 117 118 The ordering used for instruction operands in the Go assembler differs from the 119 ordering defined in the [RISC-V ISA Manual]. 120 121 1. R-Type instructions 122 123 R-Type instructions are written in the reverse order to that given in the 124 [RISC-V ISA Manual], with the register order being rs2, rs1, rd. 125 126 Examples: 127 128 ADD X10, X11, X12 <=> add x12, x11, x10 129 FADDD F10, F11, F12 <=> fadd.d f12, f11, f10 130 131 2. I-Type arithmetic instructions 132 133 I-Type arithmetic instructions (not loads, fences, ebreak, ecall) use the same 134 ordering as the R-Type instructions, typically, imm12, rs1, rd. 135 136 Examples: 137 138 ADDI $1, X11, X12 <=> add x12, x11, 1 139 SLTI $1, X11, X12 <=> slti x12, x11, 1 140 141 3. Loads and Stores 142 143 Load instructions are written with the source operand (whether it be a register 144 or a memory address), first followed by the destination operand. 145 146 Examples: 147 148 MOV 16(X2), X10 <=> ld x10, 16(x2) 149 MOV X10, (X2) <=> sd x10, 0(x2) 150 151 4. Branch instructions 152 153 The branch instructions use the same operand ordering as is given in the 154 [RISC-V ISA Manual], e.g., rs1, rs2, label. 155 156 Example: 157 158 BLT X12, X23, loop1 <=> blt x12, x23, loop1 159 160 BLT X12, X23, label will jump to label if X12 < X23. Note this is not the 161 same ordering as is used for the SLT instructions. 162 163 5. FMA instructions 164 165 The Go assembler uses a different ordering for the RISC-V FMA operands to 166 the ordering given in the [RISC-V ISA Manual]. The operands are rotated one 167 place to the left, so that the destination operand comes last. 168 169 Example: 170 171 FMADDS F1, F2, F3, F4 <=> fmadd.s f4, f1, f2, f3 172 173 6. AMO instructions 174 175 The ordering used for the AMO operations is rs2, rs1, rd, i.e., the operands 176 as specified in the [RISC-V ISA Manual] are rotated one place to the left. 177 178 Example: 179 180 AMOSWAPW X5, (X6), X7 <=> amoswap.w x7, x5, (x6) 181 182 7. Vector instructions 183 184 The VSETVLI instruction uses the same symbolic names as the [RISC-V ISA Manual] 185 to represent the components of vtype, with the exception 186 that they are written in upper case. The ordering of the operands in the Go 187 assembler differs from the [RISC-V ISA Manual] in that the operands are 188 rotated one place to the left so that the destination register, the register 189 that holds the new vl, is the last operand. 190 191 Example: 192 193 VSETVLI X10, E8, M1, TU, MU, X12 <=> vsetvli x12, x10, e8, m1, tu, mu 194 195 Vector load and store instructions follow the pattern set by scalar loads and 196 stores, i.e., the source is always the first operand and the destination the 197 last. However, the ordering of the operands of these instructions is 198 complicated by the optional mask register and, in some cases, the use of an 199 additional stride or index register. In the Go assembler the index and stride 200 registers appear as the second operand in indexed or strided loads and stores, 201 while the mask register, if present, is always the penultimate operand. 202 203 Examples: 204 205 VLE8V (X10), V3 <=> vle8.v v3, (x10) 206 VSE8V V3, (X10) <=> vse8.v v3, (x10) 207 VLE8V (X10), V0, V3 <=> vle8.v v3, (x10), v0.t 208 VSE8V V3, V0, (X10) <=> vse8.v v3, (x10), v0.t 209 VLSE8V (X10), X11, V3 <=> vlse8.v v3, (x10), x11 210 VSSE8V V3, X11, (X10) <=> vsse8.v v3, (x10), x11 211 VLSE8V (X10), X11, V0, V3 <=> vlse8.v v3, (x10), x11, v0.t 212 VSSE8V V3, X11, V0, (X10) <=> vsse8.v v3, (x10), x11, v0.t 213 VLUXEI8V (X10), V2, V3 <=> vluxei8.v v3, (x10), v2 214 VSUXEI8V V3, V2, (X10) <=> vsuxei8.v v3, (x10), v2 215 VLUXEI8V (X10), V2, V0, V3 <=> vluxei8.v v3, (x10), v2, v0.t 216 VSUXEI8V V3, V2, V0, (X10) <=> vsuxei8.v v3, (x10), v2, v0.t 217 VL1RE8V (X10), V3 <=> vl1re8.v v3, (x10) 218 VS1RV V3, (X11) <=> vs1r.v v3, (x11) 219 220 The ordering of operands for two and three argument vector arithmetic instructions is 221 reversed in the Go assembler. 222 223 Examples: 224 225 VMVVV V2, V3 <=> vmv.v.v v3, v2 226 VADDVV V1, V2, V3 <=> vadd.vv v3, v2, v1 227 VADDVX X10, V2, V3 <=> vadd.vx v3, v2, x10 228 VMADCVI $15, V2, V3 <=> vmadc.vi v3, v2, 15 229 230 The mask register, when specified, is always the penultimate operand in a vector 231 arithmetic instruction, appearing before the destination register. 232 233 Examples: 234 235 VANDVV V1, V2, V0, V3 <=> vand.vv v3, v2, v1, v0.t 236 237 # Ternary instructions 238 239 The Go assembler allows the second operand to be omitted from most ternary 240 instructions if it matches the third (destination) operand. 241 242 Examples: 243 244 ADD X10, X12, X12 <=> ADD X10, X12 245 ANDI $3, X12, X12 <=> ANDI $3, X12 246 247 The use of this abbreviated syntax is encouraged. 248 249 # Ordering of atomic instructions 250 251 It is not possible to specify the ordering bits in the FENCE, LR, SC or AMO 252 instructions. The FENCE instruction is always emitted as a full fence, the 253 acquire and release bits are always set for the AMO instructions, the acquire 254 bit is always set for the LR instructions while the release bit is set for 255 the SC instructions. 256 257 # Immediate operands 258 259 In many cases, where an R-Type instruction has a corresponding I-Type 260 instruction, the R-Type mnemonic can be used in place of the I-Type mnemonic. 261 The assembler assumes that the immediate form of the instruction was intended 262 when the first operand is given as an immediate value rather than a register. 263 264 Example: 265 266 AND $3, X12, X13 <=> ANDI $3, X12, X13 267 268 # Integer constant materialization 269 270 The MOV instruction can be used to set a register to the value of any 64 bit 271 constant literal. The way this is achieved by the assembler varies depending 272 on the value of the constant. Where possible the assembler will synthesize the 273 constant using one or more RISC-V arithmetic instructions. If it is unable 274 to easily materialize the constant it will load the 64 bit literal from memory. 275 276 A 32 bit constant literal can be specified as an argument to ADDI, ANDI, ORI and 277 XORI. If the specified literal does not fit into 12 bits the assembler will 278 generate extra instructions to synthesize it. 279 280 Integer constants provided as operands to all other instructions must fit into 281 the number of bits allowed by the instructions' encodings for immediate values. 282 Otherwise, an error will be generated. 283 284 # Floating point constant materialization 285 286 The MOVF and MOVD instructions can be used to set a register to the value 287 of any 32 bit or 64 bit floating point constant literal, respectively. Unless 288 the constant literal is 0.0, MOVF and MOVD will be encoded as FLW and FLD 289 instructions that load the constant from a location within the program's 290 binary. 291 292 [RISC-V ISA Manual]: https://github.com/riscv/riscv-isa-manual 293 [rva20u64]: https://github.com/riscv/riscv-profiles/blob/main/src/profiles.adoc#51-rva20u64-profile 294 [rva22u64]: https://github.com/riscv/riscv-profiles/blob/main/src/profiles.adoc#rva22u64-profile 295 [rva23u64]: https://github.com/riscv/riscv-profiles/blob/main/src/rva23-profile.adoc#rva23u64-profile 296 */ 297 package riscv 298