diff --git a/ChangeLog b/ChangeLog index c50e5eb1b..291441056 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2015-06-06 Paulo Andrade + + * lib/jit_mips-cpu.c, lib/jit_mips-fpu.c, lib/jit_mips.c: + Add base support to jit vararg functions to the mips backend. + Currently only supported on the o32 abi, until access to a + n32 system is arranged. + 2015-06-05 Paulo Andrade * lib/jit_ppc-cpu.c, lib/jit_ppc-fpu.c, lib/jit_ppc.c: diff --git a/lib/jit_mips-cpu.c b/lib/jit_mips-cpu.c index ac5ca8e3d..f43a3fa5f 100644 --- a/lib/jit_mips-cpu.c +++ b/lib/jit_mips-cpu.c @@ -92,12 +92,14 @@ typedef union { # else # define stack_framesize 112 # endif +# define ldr(u,v) ldr_i(u,v) # define ldi(u,v) ldi_i(u,v) # define ldxi(u,v,w) ldxi_i(u,v,w) # define sti(u,v) sti_i(u,v) # define stxi(u,v,w) stxi_i(u,v,w) # else # define stack_framesize 144 +# define ldr(u,v) ldr_l(u,v) # define ldi(u,v) ldi_l(u,v) # define ldxi(u,v,w) ldxi_l(u,v,w) # define sti(u,v) sti_l(u,v) @@ -737,6 +739,10 @@ static jit_word_t _calli_p(jit_state_t*,jit_word_t); static void _prolog(jit_state_t*,jit_node_t*); # define epilog(node) _epilog(_jit,node) 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_abs(instr,label) _patch_abs(_jit,instr,label) static void _patch_abs(jit_state_t*,jit_word_t,jit_word_t); #define patch_at(jump,label) _patch_at(_jit,jump,label) @@ -2948,6 +2954,13 @@ _prolog(jit_state_t *_jit, jit_node_t *node) stxi_i(_jitc->function->aoffoff, _BP_REGNO, rn(index)); jit_unget_reg(index); } + + if (_jitc->function->self.call & jit_call_varargs) { + index = _jitc->function->vagp; + offset = stack_framesize + index * sizeof(jit_word_t); + for (; jit_arg_reg_p(index); ++index, offset += sizeof(jit_word_t)) + stxi(offset, _BP_REGNO, rn(_A0 - index)); + } } static void @@ -2977,6 +2990,46 @@ _epilog(jit_state_t *_jit, jit_node_t *node) addi(_SP_REGNO, _SP_REGNO, stack_framesize); } +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, _BP_REGNO, _jitc->function->vaoff); + reg = jit_get_reg(jit_class_gpr); + + /* Initialize stack pointer to the first stack argument. */ + addi(rn(reg), _BP_REGNO, stack_framesize + + _jitc->function->vagp * sizeof(jit_word_t)); + stxi(offsetof(jit_va_list_t, stack), r0, rn(reg)); + + jit_unget_reg(reg); +} + +static void +_vaarg(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1) +{ + jit_int32_t reg; + + assert(_jitc->function->self.call & jit_call_varargs); + reg = jit_get_reg(jit_class_gpr); + + /* Load varargs stack pointer. */ + ldxi(rn(reg), r1, offsetof(jit_va_list_t, stack)); + + /* Load argument. */ + ldr(r0, rn(reg)); + + /* Update vararg stack pointer. */ + addi(rn(reg), rn(reg), sizeof(jit_word_t)); + stxi(offsetof(jit_va_list_t, stack), r1, rn(reg)); + + jit_unget_reg(reg); +} + static void _patch_abs(jit_state_t *_jit, jit_word_t instr, jit_word_t label) { diff --git a/lib/jit_mips-fpu.c b/lib/jit_mips-fpu.c index 88abccfdc..0294bdeeb 100644 --- a/lib/jit_mips-fpu.c +++ b/lib/jit_mips-fpu.c @@ -543,6 +543,8 @@ static jit_word_t _bunordr_d(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t); # define bunordi_d(i0, r0, i1) _bunordi_d(_jit, i0, r0, i1) static jit_word_t _bunordi_d(jit_state_t*, jit_word_t, jit_int32_t, jit_float64_t*); +# define vaarg_d(r0, r1) _vaarg_d(_jit, r0, r1) +static void _vaarg_d(jit_state_t*, jit_int32_t, jit_int32_t); #endif #if CODE @@ -1774,6 +1776,34 @@ _bunordr_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r1, jit_int32_t r2) return (w); } dbopi(unord) + +static void +_vaarg_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1) +{ + jit_int32_t reg, aln; + + assert(_jitc->function->self.call & jit_call_varargs); + reg = jit_get_reg(jit_class_gpr); + + /* Load varargs stack pointer. */ + ldxi(rn(reg), r1, offsetof(jit_va_list_t, stack)); + + /* Align, if required. */ + aln = jit_get_reg(jit_class_gpr); + andi(rn(aln), rn(reg), 7); + addr(rn(reg), rn(reg), rn(aln)); + jit_unget_reg(aln); + + /* Load argument. */ + ldr_d(r0, rn(reg)); + + /* Update vararg stack pointer. */ + addi(rn(reg), rn(reg), sizeof(jit_float64_t)); + stxi(offsetof(jit_va_list_t, stack), r1, rn(reg)); + + jit_unget_reg(reg); +} + # undef fopi # undef fbopi # undef dopi diff --git a/lib/jit_mips.c b/lib/jit_mips.c index 1d925797e..ccf76641a 100644 --- a/lib/jit_mips.c +++ b/lib/jit_mips.c @@ -53,6 +53,13 @@ # define I_DISP STACK_SLOT - sizeof(jit_int32_t) #endif +/* + * Types + */ +typedef struct jit_va_list { + jit_pointer_t stack; +} jit_va_list_t; + /* * Prototypes */ @@ -326,6 +333,11 @@ _jit_ellipsis(jit_state_t *_jit) else { assert(!(_jitc->function->self.call & jit_call_varargs)); _jitc->function->self.call |= jit_call_varargs; + + /* Allocate va_list like object in the stack. */ + _jitc->function->vaoff = jit_allocai(sizeof(jit_va_list_t)); + + _jitc->function->vagp = _jitc->function->self.argi; } } @@ -1577,9 +1589,19 @@ _emit_code(jit_state_t *_jit) (jit_float64_t *)node->w.n->u.w); break; #endif + 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_arg: case jit_code_arg_f: case jit_code_arg_d: + case jit_code_va_end: break; default: abort();