RISCV 5 RISC-V calling rules

RISCV - 1 RV32/64G instruction set list
RISCV - 2 "Zicsr", CSR Instructions
RISCV -3 RV32I/RV64I basic integer instruction set
RISCV - 4 ISA extension naming convention

1 Register Convention

1.1 Integer Register Convention

insert image description here

In the RISCV standard ABI, procedures should not modify the integer registers tp and gp, because signal handlers may rely upon their values . their value.
The presence of a frame pointer is optional. If a frame pointer exists it must reside in x8 (s0), the register remains callee-saved. The
presence of a frame pointer is optional. If a frame pointer is present, it must be located in the x8 (s0) register, which will hold the call-save state.
x10-x11 are also used as return value registers r0-r1.

1.2 Floating-point Register Convention

insert image description here
*: Floating-point values ​​in callee-saved registers are only preserved across calls if they are no larger than the width of a floating-point register in the targeted ABI. Therefore, these registers can always be considered temporaries if targeting the base integer calling convention.
Floating-point values ​​in Callee-saved registers are preserved across calls only if they are not larger than the width of the floating-point registers in the target ABI. Therefore, these registers can always be considered scratch registers if the base integer calling convention is used.

2. Procedure Calling Convention

2.1 Integer Calling Convention

The base integer calling convention provides eight argument registers, a0-a7, the first two of which are also used to return values(r0-r1). The base
integer calling convention provides eight argument registers (a0-a7), of which the first two One is also used for the return value (r0-r1).
Scalars that are at most XLEN bits wide are passed in a single argument register, or on the stack by value if none is available. When passed in registers or on the stack, integer scalars narrower than XLEN bits are widened according to the sign of their type up to 32 bits, then sign-extended to XLEN bits. When passed in registers or on the stack, floating-point types narrower than XLEN bits are widened to XLEN bits, with the upper bits undefined. Scalars with a width of at most XLEN
bits will be passed as a single argument register, or passed on the stack as a value if there is no register. When passed in registers or on the stack, integer scalars that are less than XLEN bits wide are signed widened to 32 bits for their type, and then signed widened to XLEN bits. Floating-point types smaller than XLEN bits are extended to XLEN bits when passed in registers or on the stack, with the upper bits undefined.
Scalars that are 2×XLEN bits wide are passed in a pair of argument registers, with the low-order XLEN bits in the lower-numbered register and the high-order XLEN bits in the higher-numbered register. If no argument registers are available , the scalar is passed on the stack by value. If exactly one register is available, the low-order XLEN bits are passed in the register and the high-order XLEN bits are passed on the stack. A scalar with a width of 2×XLEN
bits are passed in a pair of argument registers, with the low-order XLEN bits in the lower-numbered register and the high-order XLEN bits in the higher-numbered register. If there are no argument registers, the scalar is passed on the stack by value. If exactly one register is available, the low-order XLEN bits are passed in the register and the high-order XLEN bits are passed on the stack. Scalars wider than 2×XLEN are passed by reference and are replaced in the argument list with the address
.

Aggregates whose total size is no more than XLEN bits are passed in a register, with the fields laid out as though they were passed in memory. If no register is available, the aggregate is passed on the stack. Aggregates whose total size is no more than 2×XLEN bits are passed in a pair of registers; if only one register is available, the first half is passed in a register and the second half is passed on the stack. If no registers are available, the aggregate is passed on the stack. Bits unused due to padding, and bits past the end of an aggregate whose size in bits is not divisible by XLEN, are undefined
. pass the same. If there are no registers, aggregates are passed on the stack. Aggregates whose total size does not exceed 2×XLEN bits are passed in a pair of registers; if only one register is available, the first half is passed in registers and the second half is passed on the stack. If there are no registers, the total is passed on the stack. Bits not used due to padding, and bits beyond the end of the set whose bit size is not divisible by XLEN are undefined.

Aggregates or scalars passed on the stack are aligned to the greater of the type alignment and XLEN bits, but never more than the stack alignment. value, but never exceeds the stack alignment.
Aggregates larger than 2×XLEN bits are passed by reference and are replaced in the argument list with the address, as are C++ aggregates with nontrivial copy constructors, destructors, or vtables. Aggregates larger than 2×XLEN bits are passed by reference and are replaced in
the Address substitution in parameter lists, as well as C++ aggregates with non-simple copy constructors, destructors, or vtables.
Empty structs or union arguments or return values ​​are ignored by C compilers which support them as a nonstandard extension. This is not the case for C++, which requires them to be sized types. Empty structures, union arguments or return values ​​will be compiled by
C ignored by the C compiler because it is supported as a non-standard extension by the C compiler. C++, on the other hand, requires them to be sized types.
Bitfields are packed in little-endian fashion. A bitfield that would span the alignment boundary of its integer type is padded to begin at the next alignment boundary. For example, struct { int x : 10; int y : 12; } is a 32 -bit type with x in bits 9-0, y in bits 21-10, and bits 31-22 undefined. By contrast, struct { short x : 10; short y : 12; } is a 32-bit type with x in bits 9-0, y in bits 27-16, and bits 31-28 and 15-10 undefined.
Bit fields are packed in little endian. A bit-field that crosses an alignment boundary of its integer type is padded to begin at the next alignment boundary. For example, struct { int x : 10; int y : 12; } is a 32-bit type, where x is in bits 9-0, y is in bits 21-10, and bits 31-22 are undefined. In contrast, struct { short x : 10; short y : 12; } is a 32-bit type, where x is in bits 9-0, y is in bits 27-16, and bits 31-28 and 15-10 are not definition.
Arguments passed by reference may be modified by the callee.
Arguments passed by reference may be modified by the callee.
Floating-point reals are passed the same way as aggregates of the same size, complex floating-point numbers are passed the same way as a struct containing two floating-point reals. (This constraint changes when the integer calling convention is augmented by the hardware floating-point calling convention.)
Floating-point reals are passed in the same way as aggregate numbers of the same size, and complex floating-points are passed in the same way as structures containing two floating-point reals. (This restriction will change when the integer calling convention is added to the hardware floating-point calling specification).
In the base integer calling convention, variadic arguments are passed in the same manner as named arguments, with one exception. Variadic arguments with 2×XLEN-bit alignment and size at most 2×XLEN bits are passed in an aligned register pair (ie, the first register in the pair is even-numbered), or on the stack by value if none is available. After a variadic argument has been passed on the stack, all future arguments will also be passed on the stack (ie the last argument register may be left unused due to the aligned register pair rule).
In the base integer call specification, variadic arguments are passed in the same way as named arguments, with one exception. Variadic arguments with an alignment of 2×XLEN bits and a size of at most 2×XLEN bits, passed in aligned register pairs (that is, the first register in a pair is even), or in the value's The form is passed to the stack. After a variable parameter is passed to the stack, all subsequent parameters will also be passed to the stack (that is, due to register alignment rules, the last parameter register may not be used).
Values ​​are returned in the same manner as a first named argument of the same type would be passed. If such an argument would have been passed by reference, the caller allocates memory for the return value, and passes the address as an implicit first parameter.
A value is returned in the same way as the first named parameter of the same type is passed. If the parameter is passed by reference, the caller will allocate memory for the return value and pass the address as the implicit first parameter.
The stack grows downwards (towards lower addresses) and the stack pointer shall be aligned to a 128-bit boundary upon procedure entry. The first argument passed on the stack is located at offset zero of the stack pointer on function entry; ed At correspondingly higher addresses.
The stack grows downward (toward lower addresses), and the stack pointer should be aligned to a 128-bit boundary at program entry. The first argument passed on the stack is at offset zero of the stack pointer on function entry; subsequent arguments are stored at correspondingly higher addresses.
In the standard ABI, the stack pointer must remain aligned throughout procedure execution. Non-standard ABI code must realign the stack pointer prior to invoking standard ABI procedures. The operating system must realign the stack pointer prior to invoking a signal handler; hence, POSIX Signal Handler's Not Realign the Stack Pointer. In Systems that Service Interrupts USING The Interruptee's Stack, The Interrupt Service IGN The Stack Pointer if Linked with Any Code that uses a non-Standard Stack-Alignment Discipline, but need not realign the stack. pointer if all code adheres to the standard ABI.
In the standard ABI, the stack pointer must remain aligned throughout program execution. Non-standard ABI code must realign the stack pointer before calling standard ABI routines. The operating system must realign the stack pointer before calling a function handler; therefore, POSIX function handlers do not need to realign the stack pointer. Using an interrupt stack in a system that provides interrupt servicing, the stack pointer must be realigned if the interrupt service routine is connected to any code that uses non-standard stack alignment rules, but not if all code obeys the standard ABI .

Procedures must not rely upon the persistence of stack -allocated data whose addresses lie below the stack pointer.
Registers S0-S11 SHALL Be Preserved Across Procedure Calls. No Floating-Point Registers, if present, are preserved across calls. Teger Calling Convention is Augmented by the Hardware Flontpoint Calling Convention.
) Retained across program calls. Floating-point registers (if present) are not preserved across calls. (This property will change when the hardware floating-point calling convention adds integer calling conventions).

2.2 Hardware Floating-point Calling Convention

The hardware floating-point calling convention adds eight floating-point argument registers, fa0-fa7, the first two of which are also used to return values. Values ​​are passed in floating-point registers whenever possible, whether or not the integer registers have been exhausted.
The hardware floating-point call specification adds 8 floating-point parameter registers (fa0-fa7), the first two of which are also used for return values. Regardless of whether integer registers are exhausted, values ​​are passed using floating-point registers whenever possible. The remainder of this section applies only to named
arguments. Variadic arguments are passed according to the integer calling convention.
Varargs are passed according to the integer call specification.
For the purposes of this section, FLEN refers to the width of a floating-point register in the ABI. The ABI's FLEN must be no wider than the ISA's FLEN. The ISA might have wider floating-point registers than the ABI.
For the purposes of this section, FLEN refers to the width of floating-point registers in the ABI. The ABI's FLEN must not be wider than the ISA's FLEN. The ISA may have wider floating point registers than the ABI.
For the purposes of this section, “struct” refers to a C struct with its hierarchy flattened, including any array fields. That is, struct { struct { float f[1]; } g[2]; } and struct { float f; float g; } are treated the same. Fields containing empty structs or unions are ignored while flattening, even in C++, unless they have nontrivial copy constructors or destructors. Fields containing zero-length bit-fields are ignored while flattening. Attributes such as aligned or packed do not interfere with a struct’s eligibility for being passed in registers according to the rules below, i.e. struct { int i; double d; } and struct attribute packed { int i; double d } are treated the same, as are struct { float f; float g; } and struct { float f; float g attribute aligned (8); }.
A real floating-point argument is passed in a floating-point argument register if it is no more than FLEN bits wide and at least one floating-point argument register is available. Otherwise, it is passed according to the integer calling convention. When a floating-point argument narrower than FLEN bits is passed in a floating-point register, it is 1-extended (NaN-boxed) to FLEN bits.
If the width of the real floating-point parameter does not exceed FLEN bits, and there is at least one floating-point parameter register is available, the parameter is passed in the floating-point parameter register. Otherwise, it is passed according to the integer call specification. When passing a floating-point argument with a width smaller than FLEN bits in a floating-point argument register, it is 1-extended (NaN-boxed) to FLEN bits.
A struct containing just one floating-point real is passed as though it were a standalone floating-point real
.
A struct containing two floating-point reals is passed in two floating-point registers, if neither is more than FLEN bits wide and at least two floating-point argument registers are available. (The registers need not be an aligned pair.) Otherwise, it is passed according to the integer calling convention.
A structure containing two floating-point real numbers is passed to two floating-point registers if neither floating-point register is wider than FLEN bits and at least two floating-point parameter registers are available middle. (The registers do not have to be an aligned pair.) Otherwise, it is passed according to the integer call specification.
A complex floating-point number, or a struct containing just one complex floating-point number, is passed as though it were a struct containing two floating-point reals
. as if it were a structure containing two floating point real numbers.
A struct containing one floating-point real and one integer (or bitfield), in either order, is passed in a floating-point register and an integer register, without extending the integer to XLEN bits, provided the floating-point real is no more than FLEN bits wide and the integer is no more than XLEN bits wide, and at least one floating-point argument register and at least one integer argument register is available. Otherwise, it is passed according to the integer calling convention. Contains a floating-
point Structures of real numbers and an integer (or bit-field) (regardless of order) are passed into floating-point and integer registers without extending the integer to XLEN bits, provided that the floating-point real number does not exceed FLEN bits wide and the integer does not exceed XLEN bits wide, and at least 1 floating point parameter register and at least 1 integer parameter register are available. Otherwise, it is passed according to the integer calling convention.
Unions are never flattened and are
always passed according to the integer calling convention.
Values ​​are returned in the same manner as a first named argument of the same type would be passed
.
Floating-point registers fs0-fs11 shall be preserved across procedure calls, provided they hold values ​​no more than FLEN bits wide
.

2.3 ILP32E Calling Convention

The ILP32E calling convention is designed to be usable with the RV32E ISA. This calling convention is the same as the integer calling convention, except for the following differences. The stack pointer need only be aligned to a 32-bit boundary. Registers x16-x31 do not participate in the calling convention, so there are only six argument registers, a0-a5, only two callee-saved registers, s0-s1, and only three temporaries, t0-t2. The ILP32E calling specification is designed for use with the RV32E ISA
. This calling specification is the same as the integer calling specification with the following differences. The stack pointer need only be aligned on 32-bit boundaries. Registers x16-x31 do not participate in the call specification, so there are only 6 parameter registers (a0-a5), 2 value-holding registers (s0-s1), and 3 scratch registers (t0-t2). If used with an ISA that has any of the registers x16-x31 and f0-f31, then these registers are considered temporary
.
.
The ILP32E calling convention is not compatible with ISAs that have registers that require load and store alignments of more than 32 bits. In particular, this calling convention must not be used with the D ISA extension. The ILP32E calling convention and registers that require more than 32
bits ISA incompatible for load and store permutations. In particular, this calling specification must not be used with the D ISA extension.

2.4 Named ABIs

This specification defines the following named ABIs:
ILP32
Integer calling-convention only, hardware floating-point calling convention is not used (i.e. ELFCLASS32 and EF_RISCV_FLOAT_ABI_SOFT).
ILP32F
ILP32 with hardware floating-point calling convention for FLEN=32 (i.e. ELFCLASS32 and EF_RISCV_FLOAT_ABI_SINGLE).
ILP32D
ILP32 with hardware floating-point calling convention for FLEN=64 (i.e. ELFCLASS32 and EF_RISCV_FLOAT_ABI_DOUBLE).
ILP32E
ILP32E calling-convention only, hardware floating-point calling convention is not used (i.e. ELFCLASS32, EF_RISCV_FLOAT_ABI_SOFT, and EF_RISCV_RVE).
LP64
Integer calling-convention only, hardware floating-point calling convention is not used (i.e. ELFCLASS64 and EF_RISCV_FLOAT_ABI_SOFT).
LP64F
LP64 with hardware floating-point calling convention for FLEN=32 (i.e. ELFCLASS64 and EF_RISCV_FLOAT_ABI_SINGLE).
LP64D
LP64 with hardware floating-point calling convention for FLEN=64 (i.e. ELFCLASS64 and EF_RISCV_FLOAT_ABI_DOUBLE).
LP64Q
LP64 with hardware floating-point calling convention for FLEN=128 (i.e. ELFCLASS64 and EF_RISCV_FLOAT_ABI_QUAD).

The ILP32* ABIs are only compatible with RV32* ISAs, and the LP64* ABIs are only compatible with RV64* ISAs. A future version of this specification may define an ILP32 ABI for the RV64 ISA, but currently this is not a supported operating mode .The F ABIs require the F ISA extension, the D ABIs require the D ISA extension, and the LP64Q ABI requires the Q ISA extension. The ILP32 ABI is
only
compatible with the RV32
ISA, and the LP64
ABI is only compatible with the RV64
ISA. A future version of the specification may define an ILP32 ABI for the RV64 ISA, but this is currently not a supported mode of operation. The *F ABI requires the *F ISA extension, the *D ABI requires the D ISA extension, and the LP64Q ABI requires the Q ISA extension.
note
: This means code targeting the Zfinx extension always uses the ILP32, ILP32E or LP64 integer calling-convention only ABIs as there is no dedicated hardware floating-point register file. Or the LP64 Integer Call Specification ABI, since there is no dedicated hardware floating-point register file.

2.5 Default ABIs


While various different ABIs are technically possible, for software compatibility reasons it is strongly recommended to use the following default ABIs for specific architectures: Architectures use the following default ABIs:
on RV32G : ILP32D
on RV64G : LP64D

Note : Although RV64GQ systems can technically use LP64Q, it is strongly recommended to use LP64D on general-purpose RV64GQ systems for compatibility with standard RV64G software.
On the Q system Use LP64D for compatibility with standard RV64G software.

3. C/C++ type details

3.1 C/C++ type sizes and alignments

There are two conventions for C/C++ type sizes and alignments
.

3.1.1 ILP32, ILP32F, ILP32D, and ILP32E

Use the following type sizes and alignments (based on the ILP32 convention):
Use the following type sizes and alignments (based on the ILP32 convention):
insert image description here

3.1.2 LP64, LP64F, LP64D, and LP64Q

Use the following type sizes and alignments (based on the LP64 convention)
:
insert image description here
insert image description here
The alignment of max_align_t is 16.
The alignment of max_align_t is 16.
CHAR_BIT is 8.
CHAR_BIT is 8.
Structs and unions are aligned to the alignment of their most strictly aligned member. The size of any object is a multiple of its alignment
. The size of any object is a multiple of its alignment.

3.2 C/C++ type representations

char is unsigned.
char is unsigned. Booleans (bool/_Bool) stored in memory or when being passed as scalar arguments are either 0
(false) or 1 (true).
false), or 1 (true).
A null pointer (for all types) has the value zero
.
_Float16 is as defined in the C ISO/IEC TS 18661-3 extension.
_Float16 is defined in the C ISO/IEC TS 18661-3 extension.
_Complex types have the same layout as a struct containing two fields of the corresponding real type (float, double, or long double), with the first member holding the real part and the second member holding the imaginary part
. The two fields containing the corresponding real type (float, double, or long double) have the same structure, with the first member representing the real part and the second representing the imaginary part.

3.3 va_list, va_start, and va_arg

The va_list type is void*. A callee with variadic arguments is responsible for copying the contents of registers used to pass variadic arguments to the vararg save area, which must be contiguous with arguments passed on the stack. The va_start macro initializes its va_list argument to point to the start of the vararg save area. The va_arg macro will increment its va_list argument according to the size of the given type, taking into account the rules about 2×XLEN aligned arguments being passed in “aligned” register pairs
. void*. The callee with varargs is responsible for copying the contents of the registers used to pass the varargs into the vararg save area, which must be adjacent to the passed parameters on the stack. The va_start macro initializes its va_list argument to point to the start of the vararg holding area. The va_arg macro will increment the va_list argument by the size of the given type, taking into account the rule that 2×XLEN aligned arguments are passed in "aligned" register pairs.

4 Linux-specific ABI

Note : This section of the RISC-V calling convention specification only applies to Linux-based systems.
Note : This section of the RISC-V calling convention specification only applies to Linux-based systems. In order to ensure compatibility between different implementations
of the C library for Linux, we provide some extra definitions which only apply on those systems. These are noted in this section.
Some additional definitions that apply only to these systems. This section explains these definitions.

4.1 Linux-specific C type sizes and alignments

The following definitions apply for all ABIs defined in this document. Here there is no differentiation between ILP32 and LP64 abis
. No distinction is made here between ILP32 and LP64 abis.
insert image description here

4.2 Linux-specific C type representations

The following definitions apply for all ABIs defined in this document. Here there is no differentiation between ILP32 and LP64 abis
. No distinction is made here between ILP32 and LP64 Abis.
wchar_t is signed.
wchar_t is signed.
wint_t is unsigned.
wint_t is unsigned.

Guess you like

Origin blog.csdn.net/u014100559/article/details/132072462