mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +02:00
riscv: float/double call convention implementation
RISC-V uses a0-a7 registers for argument passing. Float/double arguments use f0-f7 first and continue in a0-a7 if needed. Once registers are consumed, stack is used. This commit changes how lightening passes arguments in order to allow this behavior.
This commit is contained in:
parent
ce8b8e4778
commit
7c20ba7767
3 changed files with 64 additions and 1 deletions
|
@ -807,6 +807,14 @@ abi_mem_to_gpr(jit_state_t *_jit, enum jit_operand_abi abi,
|
||||||
case JIT_OPERAND_ABI_INT16:
|
case JIT_OPERAND_ABI_INT16:
|
||||||
jit_ldxi_s(_jit, dst, base, offset);
|
jit_ldxi_s(_jit, dst, base, offset);
|
||||||
break;
|
break;
|
||||||
|
case JIT_OPERAND_ABI_FLOAT:
|
||||||
|
{
|
||||||
|
jit_fpr_t tmp = get_temp_fpr(_jit);
|
||||||
|
jit_ldxi_f(_jit, tmp, base, offset);
|
||||||
|
jit_movr_i_f(_jit, dst, tmp);
|
||||||
|
unget_temp_fpr(_jit);
|
||||||
|
break;
|
||||||
|
}
|
||||||
#if __WORDSIZE == 32
|
#if __WORDSIZE == 32
|
||||||
case JIT_OPERAND_ABI_UINT32:
|
case JIT_OPERAND_ABI_UINT32:
|
||||||
case JIT_OPERAND_ABI_POINTER:
|
case JIT_OPERAND_ABI_POINTER:
|
||||||
|
@ -823,6 +831,14 @@ abi_mem_to_gpr(jit_state_t *_jit, enum jit_operand_abi abi,
|
||||||
case JIT_OPERAND_ABI_INT64:
|
case JIT_OPERAND_ABI_INT64:
|
||||||
jit_ldxi_l(_jit, dst, base, offset);
|
jit_ldxi_l(_jit, dst, base, offset);
|
||||||
break;
|
break;
|
||||||
|
case JIT_OPERAND_ABI_DOUBLE:
|
||||||
|
{
|
||||||
|
jit_fpr_t tmp = get_temp_fpr(_jit);
|
||||||
|
jit_ldxi_d(_jit, tmp, base, offset);
|
||||||
|
jit_movr_l_d(_jit, dst, tmp);
|
||||||
|
unget_temp_fpr(_jit);
|
||||||
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
|
@ -887,7 +903,8 @@ enum move_kind {
|
||||||
MOVE_KIND_ENUM(IMM, MEM),
|
MOVE_KIND_ENUM(IMM, MEM),
|
||||||
MOVE_KIND_ENUM(GPR, MEM),
|
MOVE_KIND_ENUM(GPR, MEM),
|
||||||
MOVE_KIND_ENUM(FPR, MEM),
|
MOVE_KIND_ENUM(FPR, MEM),
|
||||||
MOVE_KIND_ENUM(MEM, MEM)
|
MOVE_KIND_ENUM(MEM, MEM),
|
||||||
|
MOVE_KIND_ENUM(FPR, GPR)
|
||||||
};
|
};
|
||||||
#undef MOVE_KIND_ENUM
|
#undef MOVE_KIND_ENUM
|
||||||
|
|
||||||
|
@ -901,6 +918,14 @@ move_operand(jit_state_t *_jit, jit_operand_t dst, jit_operand_t src)
|
||||||
case MOVE_GPR_TO_GPR:
|
case MOVE_GPR_TO_GPR:
|
||||||
return jit_movr(_jit, dst.loc.gpr.gpr, src.loc.gpr.gpr);
|
return jit_movr(_jit, dst.loc.gpr.gpr, src.loc.gpr.gpr);
|
||||||
|
|
||||||
|
case MOVE_FPR_TO_GPR:
|
||||||
|
#if __WORDSIZE > 32
|
||||||
|
if (src.abi == JIT_OPERAND_ABI_DOUBLE)
|
||||||
|
return jit_movr_l_d(_jit, dst.loc.gpr.gpr, src.loc.fpr);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
return jit_movr_i_f(_jit, dst.loc.gpr.gpr, src.loc.fpr);
|
||||||
|
|
||||||
case MOVE_MEM_TO_GPR:
|
case MOVE_MEM_TO_GPR:
|
||||||
return abi_mem_to_gpr(_jit, src.abi, dst.loc.gpr.gpr, src.loc.mem.base,
|
return abi_mem_to_gpr(_jit, src.abi, dst.loc.gpr.gpr, src.loc.mem.base,
|
||||||
src.loc.mem.offset);
|
src.loc.mem.offset);
|
||||||
|
|
|
@ -103,6 +103,10 @@ static void absr_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||||
// Transfer operations
|
// Transfer operations
|
||||||
static void movr_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
static void movr_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||||
static void movr_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
static void movr_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||||
|
static void movr_i_f(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||||
|
static void movr_l_d(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||||
|
static void movr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||||
|
static void movr_d_l(jit_state_t *_jit, int32_t r0, int32_t r1);
|
||||||
|
|
||||||
// Argument management
|
// Argument management
|
||||||
static void retr_f(jit_state_t *_jit, int32_t u);
|
static void retr_f(jit_state_t *_jit, int32_t u);
|
||||||
|
@ -398,6 +402,27 @@ movr_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||||
if (r0 != r1)
|
if (r0 != r1)
|
||||||
em_wp(_jit, _FMV_D(r0, r1));
|
em_wp(_jit, _FMV_D(r0, r1));
|
||||||
}
|
}
|
||||||
|
static void
|
||||||
|
movr_i_f(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||||
|
{
|
||||||
|
em_wp(_jit, _FMV_X_W(r0, r1));
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
movr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||||
|
{
|
||||||
|
em_wp(_jit, _FMV_W_X(r0, r1));
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
movr_l_d(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||||
|
{
|
||||||
|
em_wp(_jit, _FMV_X_D(r0, r1));
|
||||||
|
}
|
||||||
|
static void
|
||||||
|
movr_d_l(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||||
|
{
|
||||||
|
em_wp(_jit, _FMV_D_X(r0, r1));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
truncr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1)
|
truncr_f_i(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -111,6 +111,16 @@ reset_abi_arg_iterator(struct abi_arg_iterator *iter, size_t argc,
|
||||||
static void
|
static void
|
||||||
next_abi_arg(struct abi_arg_iterator *iter, jit_operand_t *arg)
|
next_abi_arg(struct abi_arg_iterator *iter, jit_operand_t *arg)
|
||||||
{
|
{
|
||||||
|
// RISC-V Calling convention:
|
||||||
|
// https://riscv.org/wp-content/uploads/2015/01/riscv-calling.pdf
|
||||||
|
//
|
||||||
|
// The RISC-V calling convention passes arguments in registers when possible.
|
||||||
|
// Up to eight integer registers, a0–a7, and up to eight floating-point
|
||||||
|
// registers, fa0–fa7, are used for this purpose.
|
||||||
|
//
|
||||||
|
// If argument i < 8 is a floating-point type, it is passed in floating-point
|
||||||
|
// register fai; otherwise, it is passed in integer register ai.
|
||||||
|
|
||||||
ASSERT(iter->arg_idx < iter->argc);
|
ASSERT(iter->arg_idx < iter->argc);
|
||||||
enum jit_operand_abi abi = iter->args[iter->arg_idx].abi;
|
enum jit_operand_abi abi = iter->args[iter->arg_idx].abi;
|
||||||
iter->arg_idx++;
|
iter->arg_idx++;
|
||||||
|
@ -121,6 +131,9 @@ next_abi_arg(struct abi_arg_iterator *iter, jit_operand_t *arg)
|
||||||
if (is_fpr_arg(abi) && iter->fpr_idx < abi_fpr_arg_count) {
|
if (is_fpr_arg(abi) && iter->fpr_idx < abi_fpr_arg_count) {
|
||||||
*arg = jit_operand_fpr (abi, abi_fpr_args[iter->fpr_idx++]);
|
*arg = jit_operand_fpr (abi, abi_fpr_args[iter->fpr_idx++]);
|
||||||
return;
|
return;
|
||||||
|
} else if (is_fpr_arg(abi) && iter->gpr_idx < abi_gpr_arg_count) {
|
||||||
|
*arg = jit_operand_gpr (abi, abi_gpr_args[iter->gpr_idx++]);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
*arg = jit_operand_mem (abi, JIT_SP, iter->stack_size);
|
*arg = jit_operand_mem (abi, JIT_SP, iter->stack_size);
|
||||||
#if __WORDSIZE == 32
|
#if __WORDSIZE == 32
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue