mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-27 21:40:34 +02:00
aarch64: Add initial jit_va_ calls to aarch64
* lib/jit_aarch64-cpu.c, lib/jit_aarch64-fpu.c, lib/jit_aarch64.c: Add base support to jit vararg functions to the aarch64 backend.
This commit is contained in:
parent
6329945281
commit
0986ae8a86
4 changed files with 238 additions and 0 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
2015-05-30 Paulo Andrade <pcpa@gnu.org>
|
||||||
|
|
||||||
|
* lib/jit_aarch64-cpu.c, lib/jit_aarch64-fpu.c,
|
||||||
|
lib/jit_aarch64.c: Add base support to jit vararg
|
||||||
|
functions to the aarch64 backend.
|
||||||
|
|
||||||
2015-05-27 Paulo Andrade <pcpa@gnu.org>
|
2015-05-27 Paulo Andrade <pcpa@gnu.org>
|
||||||
|
|
||||||
* include/lightning.h, include/lightning/jit_private.h,
|
* include/lightning.h, include/lightning/jit_private.h,
|
||||||
|
|
|
@ -212,6 +212,8 @@ typedef union {
|
||||||
} instr_t;
|
} instr_t;
|
||||||
# define stack_framesize 160
|
# define stack_framesize 160
|
||||||
# define ii(i) *_jit->pc.ui++ = i
|
# define ii(i) *_jit->pc.ui++ = i
|
||||||
|
# define ldr(r0,r1) ldr_l(r0,r1)
|
||||||
|
# define ldxr(r0,r1,r2) ldxr_l(r0,r1,r2)
|
||||||
# define ldxi(r0,r1,i0) ldxi_l(r0,r1,i0)
|
# define ldxi(r0,r1,i0) ldxi_l(r0,r1,i0)
|
||||||
# define stxi(i0,r0,r1) stxi_l(i0,r0,r1)
|
# define stxi(i0,r0,r1) stxi_l(i0,r0,r1)
|
||||||
# define FP_REGNO 0x1d
|
# define FP_REGNO 0x1d
|
||||||
|
@ -782,6 +784,10 @@ static jit_word_t _calli_p(jit_state_t*,jit_word_t);
|
||||||
static void _prolog(jit_state_t*,jit_node_t*);
|
static void _prolog(jit_state_t*,jit_node_t*);
|
||||||
# define epilog(i0) _epilog(_jit,i0)
|
# define epilog(i0) _epilog(_jit,i0)
|
||||||
static void _epilog(jit_state_t*,jit_node_t*);
|
static void _epilog(jit_state_t*,jit_node_t*);
|
||||||
|
# define vastart(r0) _vastart(_jit, r0)
|
||||||
|
static void _vastart(jit_state_t*, jit_int32_t);
|
||||||
|
# define vaarg(r0, r1) _vaarg(_jit, r0, r1)
|
||||||
|
static void _vaarg(jit_state_t*, jit_int32_t, jit_int32_t);
|
||||||
# define patch_at(jump,label) _patch_at(_jit,jump,label)
|
# define patch_at(jump,label) _patch_at(_jit,jump,label)
|
||||||
static void _patch_at(jit_state_t*,jit_word_t,jit_word_t);
|
static void _patch_at(jit_state_t*,jit_word_t,jit_word_t);
|
||||||
#endif
|
#endif
|
||||||
|
@ -2241,6 +2247,24 @@ _prolog(jit_state_t *_jit, jit_node_t *node)
|
||||||
stxi_i(_jitc->function->aoffoff, FP_REGNO, rn(reg));
|
stxi_i(_jitc->function->aoffoff, FP_REGNO, rn(reg));
|
||||||
jit_unget_reg(reg);
|
jit_unget_reg(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_jitc->function->self.call & jit_call_varargs) {
|
||||||
|
/* Save gp registers in the save area, if any is a vararg */
|
||||||
|
for (reg = 8 - _jitc->function->vagp / -8;
|
||||||
|
jit_arg_reg_p(reg); ++reg)
|
||||||
|
stxi(_jitc->function->vaoff + offsetof(jit_va_list_t, x0) +
|
||||||
|
reg * 8, FP_REGNO, rn(JIT_RA0 - reg));
|
||||||
|
|
||||||
|
for (reg = 8 - _jitc->function->vafp / -16;
|
||||||
|
jit_arg_f_reg_p(reg); ++reg)
|
||||||
|
/* Save fp registers in the save area, if any is a vararg */
|
||||||
|
/* Note that the full 16 byte register is not saved, because
|
||||||
|
* lightning only handles float and double, and, while
|
||||||
|
* attempting to provide a va_list compatible pointer as
|
||||||
|
* jit_va_start return, does not guarantee it (on all ports). */
|
||||||
|
stxi_d(_jitc->function->vaoff + offsetof(jit_va_list_t, q0) +
|
||||||
|
reg * 16 + offsetof(jit_qreg_t, l), FP_REGNO, rn(_V0 - reg));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -2285,6 +2309,94 @@ _epilog(jit_state_t *_jit, jit_node_t *node)
|
||||||
RET();
|
RET();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_vastart(jit_state_t *_jit, jit_int32_t r0)
|
||||||
|
{
|
||||||
|
jit_int32_t reg;
|
||||||
|
|
||||||
|
assert(_jitc->function->self.call & jit_call_varargs);
|
||||||
|
|
||||||
|
/* Return jit_va_list_t in the register argument */
|
||||||
|
addi(r0, FP_REGNO, _jitc->function->vaoff);
|
||||||
|
|
||||||
|
reg = jit_get_reg(jit_class_gpr);
|
||||||
|
|
||||||
|
/* Initialize stack pointer to the first stack argument. */
|
||||||
|
addi(rn(reg), FP_REGNO, _jitc->function->self.size);
|
||||||
|
stxi(offsetof(jit_va_list_t, stack), r0, rn(reg));
|
||||||
|
|
||||||
|
/* Initialize gp top pointer to the first stack argument. */
|
||||||
|
addi(rn(reg), r0, va_gp_top_offset);
|
||||||
|
stxi(offsetof(jit_va_list_t, gptop), r0, rn(reg));
|
||||||
|
|
||||||
|
/* Initialize fp top pointer to the first stack argument. */
|
||||||
|
addi(rn(reg), r0, va_fp_top_offset);
|
||||||
|
stxi(offsetof(jit_va_list_t, fptop), r0, rn(reg));
|
||||||
|
|
||||||
|
/* Initialize gp offset in the save area. */
|
||||||
|
movi(rn(reg), _jitc->function->vagp);
|
||||||
|
stxi_i(offsetof(jit_va_list_t, gpoff), r0, rn(reg));
|
||||||
|
|
||||||
|
/* Initialize fp offset in the save area. */
|
||||||
|
movi(rn(reg), _jitc->function->vafp);
|
||||||
|
stxi_i(offsetof(jit_va_list_t, fpoff), r0, rn(reg));
|
||||||
|
|
||||||
|
jit_unget_reg(reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_vaarg(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
||||||
|
{
|
||||||
|
jit_word_t ge_code;
|
||||||
|
jit_word_t lt_code;
|
||||||
|
jit_int32_t rg0, rg1;
|
||||||
|
|
||||||
|
assert(_jitc->function->self.call & jit_call_varargs);
|
||||||
|
|
||||||
|
rg0 = jit_get_reg(jit_class_gpr);
|
||||||
|
rg1 = jit_get_reg(jit_class_gpr);
|
||||||
|
|
||||||
|
/* Load the gp offset in save area in the first temporary. */
|
||||||
|
ldxi_i(rn(rg0), r1, offsetof(jit_va_list_t, gpoff));
|
||||||
|
|
||||||
|
/* Jump over if there are no remaining arguments in the save area. */
|
||||||
|
ge_code = bgei(_jit->pc.w, rn(rg0), 0);
|
||||||
|
|
||||||
|
/* Load the gp save pointer in the second temporary. */
|
||||||
|
ldxi(rn(rg1), r1, offsetof(jit_va_list_t, gptop));
|
||||||
|
|
||||||
|
/* Load the vararg argument in the first argument. */
|
||||||
|
ldxr(r0, rn(rg1), rn(rg0));
|
||||||
|
|
||||||
|
/* Update the gp offset. */
|
||||||
|
addi(rn(rg0), rn(rg0), 8);
|
||||||
|
stxi_i(offsetof(jit_va_list_t, gpoff), r1, rn(rg0));
|
||||||
|
|
||||||
|
/* Will only need one temporary register below. */
|
||||||
|
jit_unget_reg(rg1);
|
||||||
|
|
||||||
|
/* Jump over overflow code. */
|
||||||
|
lt_code = jmpi_p(_jit->pc.w);
|
||||||
|
|
||||||
|
/* Where to land if argument is in overflow area. */
|
||||||
|
patch_at(ge_code, _jit->pc.w);
|
||||||
|
|
||||||
|
/* Load stack pointer. */
|
||||||
|
ldxi(rn(rg0), r1, offsetof(jit_va_list_t, stack));
|
||||||
|
|
||||||
|
/* Load argument. */
|
||||||
|
ldr(r0, rn(rg0));
|
||||||
|
|
||||||
|
/* Update stack pointer. */
|
||||||
|
addi(rn(rg0), rn(rg0), 8);
|
||||||
|
stxi(offsetof(jit_va_list_t, stack), r1, rn(rg0));
|
||||||
|
|
||||||
|
/* Where to land if argument is in gp save area. */
|
||||||
|
patch_at(lt_code, _jit->pc.w);
|
||||||
|
|
||||||
|
jit_unget_reg(rg0);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_patch_at(jit_state_t *_jit, jit_word_t instr, jit_word_t label)
|
_patch_at(jit_state_t *_jit, jit_word_t instr, jit_word_t label)
|
||||||
{
|
{
|
||||||
|
|
|
@ -310,6 +310,8 @@ static jit_word_t _bltgti_d(jit_state_t*,jit_word_t,jit_int32_t,jit_float64_t);
|
||||||
# define bordi_d(i0,r0,i1) dbcci(BCC_VC,i0,r0,i1)
|
# define bordi_d(i0,r0,i1) dbcci(BCC_VC,i0,r0,i1)
|
||||||
# define bunordr_d(i0,r0,r1) dbccr(BCC_VS,i0,r0,r1)
|
# define bunordr_d(i0,r0,r1) dbccr(BCC_VS,i0,r0,r1)
|
||||||
# define bunordi_d(i0,r0,i1) dbcci(BCC_VS,i0,r0,i1)
|
# define bunordi_d(i0,r0,i1) dbcci(BCC_VS,i0,r0,i1)
|
||||||
|
# define vaarg_d(r0, r1) _vaarg_d(_jit, r0, r1)
|
||||||
|
static void _vaarg_d(jit_state_t*, jit_int32_t, jit_int32_t);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if CODE
|
#if CODE
|
||||||
|
@ -856,4 +858,57 @@ _bltgtr_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
|
||||||
return (w);
|
return (w);
|
||||||
}
|
}
|
||||||
dbopi(ltgt)
|
dbopi(ltgt)
|
||||||
|
|
||||||
|
static void
|
||||||
|
_vaarg_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
|
||||||
|
{
|
||||||
|
jit_word_t ge_code;
|
||||||
|
jit_word_t lt_code;
|
||||||
|
jit_int32_t rg0, rg1;
|
||||||
|
|
||||||
|
assert(_jitc->function->self.call & jit_call_varargs);
|
||||||
|
|
||||||
|
rg0 = jit_get_reg(jit_class_gpr);
|
||||||
|
rg1 = jit_get_reg(jit_class_gpr);
|
||||||
|
|
||||||
|
/* Load the fp offset in save area in the first temporary. */
|
||||||
|
ldxi_i(rn(rg0), r1, offsetof(jit_va_list_t, fpoff));
|
||||||
|
|
||||||
|
/* Jump over if there are no remaining arguments in the save area. */
|
||||||
|
ge_code = bgei(_jit->pc.w, rn(rg0), 0);
|
||||||
|
|
||||||
|
/* Load the gp save pointer in the second temporary. */
|
||||||
|
ldxi(rn(rg1), r1, offsetof(jit_va_list_t, fptop));
|
||||||
|
|
||||||
|
/* Load the vararg argument in the first argument. */
|
||||||
|
ldxr_d(r0, rn(rg1), rn(rg0));
|
||||||
|
|
||||||
|
/* Update the fp offset. */
|
||||||
|
addi(rn(rg0), rn(rg0), 16);
|
||||||
|
stxi_i(offsetof(jit_va_list_t, fpoff), r1, rn(rg0));
|
||||||
|
|
||||||
|
/* Will only need one temporary register below. */
|
||||||
|
jit_unget_reg(rg1);
|
||||||
|
|
||||||
|
/* Jump over overflow code. */
|
||||||
|
lt_code = jmpi_p(_jit->pc.w);
|
||||||
|
|
||||||
|
/* Where to land if argument is in overflow area. */
|
||||||
|
patch_at(ge_code, _jit->pc.w);
|
||||||
|
|
||||||
|
/* Load stack pointer. */
|
||||||
|
ldxi(rn(rg0), r1, offsetof(jit_va_list_t, stack));
|
||||||
|
|
||||||
|
/* Load argument. */
|
||||||
|
ldr(r0, rn(rg0));
|
||||||
|
|
||||||
|
/* Update stack pointer. */
|
||||||
|
addi(rn(rg0), rn(rg0), 8);
|
||||||
|
stxi(offsetof(jit_va_list_t, stack), r1, rn(rg0));
|
||||||
|
|
||||||
|
/* Where to land if argument is in gp save area. */
|
||||||
|
patch_at(lt_code, _jit->pc.w);
|
||||||
|
|
||||||
|
jit_unget_reg(rg0);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,6 +22,41 @@
|
||||||
#define jit_arg_reg_p(i) ((i) >= 0 && (i) < 8)
|
#define jit_arg_reg_p(i) ((i) >= 0 && (i) < 8)
|
||||||
#define jit_arg_f_reg_p(i) ((i) >= 0 && (i) < 8)
|
#define jit_arg_f_reg_p(i) ((i) >= 0 && (i) < 8)
|
||||||
|
|
||||||
|
typedef struct jit_qreg {
|
||||||
|
jit_float64_t l;
|
||||||
|
jit_float64_t h;
|
||||||
|
} jit_qreg_t;
|
||||||
|
|
||||||
|
#define va_gp_min_offset -64
|
||||||
|
#define va_gp_top_offset offsetof(jit_va_list_t, q0)
|
||||||
|
#define va_fp_min_offset -128
|
||||||
|
#define va_fp_top_offset sizeof(jit_va_list_t)
|
||||||
|
typedef struct jit_va_list {
|
||||||
|
jit_pointer_t stack;
|
||||||
|
jit_pointer_t gptop;
|
||||||
|
jit_pointer_t fptop;
|
||||||
|
jit_int32_t gpoff;
|
||||||
|
jit_int32_t fpoff;
|
||||||
|
|
||||||
|
jit_int64_t x0;
|
||||||
|
jit_int64_t x1;
|
||||||
|
jit_int64_t x2;
|
||||||
|
jit_int64_t x3;
|
||||||
|
jit_int64_t x4;
|
||||||
|
jit_int64_t x5;
|
||||||
|
jit_int64_t x6;
|
||||||
|
jit_int64_t x7;
|
||||||
|
|
||||||
|
jit_qreg_t q0;
|
||||||
|
jit_qreg_t q1;
|
||||||
|
jit_qreg_t q2;
|
||||||
|
jit_qreg_t q3;
|
||||||
|
jit_qreg_t q4;
|
||||||
|
jit_qreg_t q5;
|
||||||
|
jit_qreg_t q6;
|
||||||
|
jit_qreg_t q7;
|
||||||
|
} jit_va_list_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prototypes
|
* Prototypes
|
||||||
*/
|
*/
|
||||||
|
@ -295,6 +330,23 @@ _jit_ellipsis(jit_state_t *_jit)
|
||||||
else {
|
else {
|
||||||
assert(!(_jitc->function->self.call & jit_call_varargs));
|
assert(!(_jitc->function->self.call & jit_call_varargs));
|
||||||
_jitc->function->self.call |= jit_call_varargs;
|
_jitc->function->self.call |= jit_call_varargs;
|
||||||
|
|
||||||
|
/* Allocate va_list like object in the stack,
|
||||||
|
* with enough space to save all argument
|
||||||
|
* registers, and use fixed offsets for them. */
|
||||||
|
_jitc->function->vaoff = jit_allocai(sizeof(jit_va_list_t));
|
||||||
|
|
||||||
|
/* Initialize gp offset in save area. */
|
||||||
|
if (jit_arg_reg_p(_jitc->function->self.argi))
|
||||||
|
_jitc->function->vagp = (8 - _jitc->function->self.argi) * -8;
|
||||||
|
else
|
||||||
|
_jitc->function->vagp = va_gp_min_offset;
|
||||||
|
|
||||||
|
/* Initialize fp offset in save area. */
|
||||||
|
if (jit_arg_f_reg_p(_jitc->function->self.argf))
|
||||||
|
_jitc->function->vafp = (8 - _jitc->function->self.argf) * -16;
|
||||||
|
else
|
||||||
|
_jitc->function->vafp = va_fp_min_offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,6 +355,7 @@ _jit_arg(jit_state_t *_jit)
|
||||||
{
|
{
|
||||||
jit_int32_t offset;
|
jit_int32_t offset;
|
||||||
assert(_jitc->function);
|
assert(_jitc->function);
|
||||||
|
assert(!(_jitc->function->self.call & jit_call_varargs));
|
||||||
if (jit_arg_reg_p(_jitc->function->self.argi))
|
if (jit_arg_reg_p(_jitc->function->self.argi))
|
||||||
offset = _jitc->function->self.argi++;
|
offset = _jitc->function->self.argi++;
|
||||||
else {
|
else {
|
||||||
|
@ -317,6 +370,7 @@ _jit_arg_f(jit_state_t *_jit)
|
||||||
{
|
{
|
||||||
jit_int32_t offset;
|
jit_int32_t offset;
|
||||||
assert(_jitc->function);
|
assert(_jitc->function);
|
||||||
|
assert(!(_jitc->function->self.call & jit_call_varargs));
|
||||||
if (jit_arg_f_reg_p(_jitc->function->self.argf))
|
if (jit_arg_f_reg_p(_jitc->function->self.argf))
|
||||||
offset = _jitc->function->self.argf++;
|
offset = _jitc->function->self.argf++;
|
||||||
else {
|
else {
|
||||||
|
@ -331,6 +385,7 @@ _jit_arg_d(jit_state_t *_jit)
|
||||||
{
|
{
|
||||||
jit_int32_t offset;
|
jit_int32_t offset;
|
||||||
assert(_jitc->function);
|
assert(_jitc->function);
|
||||||
|
assert(!(_jitc->function->self.call & jit_call_varargs));
|
||||||
if (jit_arg_f_reg_p(_jitc->function->self.argf))
|
if (jit_arg_f_reg_p(_jitc->function->self.argf))
|
||||||
offset = _jitc->function->self.argf++;
|
offset = _jitc->function->self.argf++;
|
||||||
else {
|
else {
|
||||||
|
@ -1268,9 +1323,19 @@ _emit_code(jit_state_t *_jit)
|
||||||
epilog(node);
|
epilog(node);
|
||||||
_jitc->function = NULL;
|
_jitc->function = NULL;
|
||||||
break;
|
break;
|
||||||
|
case jit_code_va_start:
|
||||||
|
vastart(rn(node->u.w));
|
||||||
|
break;
|
||||||
|
case jit_code_va_arg:
|
||||||
|
vaarg(rn(node->u.w), rn(node->v.w));
|
||||||
|
break;
|
||||||
|
case jit_code_va_arg_d:
|
||||||
|
vaarg_d(rn(node->u.w), rn(node->v.w));
|
||||||
|
break;
|
||||||
case jit_code_live:
|
case jit_code_live:
|
||||||
case jit_code_arg:
|
case jit_code_arg:
|
||||||
case jit_code_arg_f: case jit_code_arg_d:
|
case jit_code_arg_f: case jit_code_arg_d:
|
||||||
|
case jit_code_va_end:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue