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  

View as plain text