| Register | ABI | Name | Description | Saver |
|---|---|---|---|---|
| x10–11 | a0–1 | Function | arguments/return values | Caller |
| x12–17 | a2–7 | Function | arguments | Caller |
What if I have ten arguments, where is the place for values to be saved? I can't find information about this.
| Register | ABI | Name | Description | Saver |
|---|---|---|---|---|
| x10–11 | a0–1 | Function | arguments/return values | Caller |
| x12–17 | a2–7 | Function | arguments | Caller |
What if I have ten arguments, where is the place for values to be saved? I can't find information about this.
The remaining arguments that don't fit in registers will be passed on stack, just like any other calling conventions. Where else can they be? See the ABI:
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 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.
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 XLEN bits are passed in a register and the remaining bits are 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.
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. ...
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 (i.e., 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 (i.e. the last argument register may be left unused due to the aligned register pair rule).
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-cc.adoc