From cc217f0608093238fbd70386eb6ceba7f45bad69 Mon Sep 17 00:00:00 2001 From: pcpa Date: Tue, 5 May 2015 20:55:05 -0300 Subject: [PATCH] ppc: Add initial jit_va_ calls to ppc * lib/jit_ppc-cpu.c, lib/jit_ppc-fpu.c, lib/jit_ppc.c: Add base support to jit vararg functions to the PowerPC backend. --- ChangeLog | 5 +++++ lib/jit_ppc-cpu.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++ lib/jit_ppc-fpu.c | 25 +++++++++++++++++++++ lib/jit_ppc.c | 23 ++++++++++++++++++++ 4 files changed, 108 insertions(+) diff --git a/ChangeLog b/ChangeLog index 7d12c546b..c50e5eb1b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-06-05 Paulo Andrade + + * lib/jit_ppc-cpu.c, lib/jit_ppc-fpu.c, lib/jit_ppc.c: + Add base support to jit vararg functions to the PowerPC backend. + 2015-06-02 Paulo Andrade * lib/jit_s390-cpu.c, lib/jit_s390-fpu.c, lib/jit_s390.c: diff --git a/lib/jit_ppc-cpu.c b/lib/jit_ppc-cpu.c index 2d01e506e..24244d21a 100644 --- a/lib/jit_ppc-cpu.c +++ b/lib/jit_ppc-cpu.c @@ -854,6 +854,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_at(i,l) _patch_at(_jit,i,l) static void _patch_at(jit_state_t*,jit_word_t,jit_word_t); #endif @@ -3280,6 +3284,12 @@ _prolog(jit_state_t *_jit, jit_node_t *node) stxi_i(_jitc->function->aoffoff, _FP_REGNO, rn(regno)); jit_unget_reg(regno); } + + if (_jitc->function->self.call & jit_call_varargs) { + for (regno = _jitc->function->vagp; jit_arg_reg_p(regno); ++regno) + stxi(gpr_save_area - (8 - regno) * sizeof(jit_word_t), + _FP_REGNO, rn(JIT_RA0 - regno)); + } } static void @@ -3329,6 +3339,51 @@ _epilog(jit_state_t *_jit, jit_node_t *node) BLR(); } +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. + * The -16 is to account for the 4 argument registers + * always saved, and _jitc->function->vagp is to account + * for declared arguments. */ + addi(rn(reg), _FP_REGNO, gpr_save_area - + 8 * sizeof(jit_word_t) + _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 inv, reg; + + assert(_jitc->function->self.call & jit_call_varargs); + reg = jit_get_reg(jit_class_gpr); + if ((inv = reg == _R0)) 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); + if (inv) jit_unget_reg(_R0); +} + static void _patch_at(jit_state_t *_jit, jit_word_t instr, jit_word_t label) { diff --git a/lib/jit_ppc-fpu.c b/lib/jit_ppc-fpu.c index 77b52434b..778195459 100644 --- a/lib/jit_ppc-fpu.c +++ b/lib/jit_ppc-fpu.c @@ -399,6 +399,8 @@ static void _sti_d(jit_state_t*,jit_word_t,jit_int32_t); static void _stxr_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t); # define stxi_d(i0,r0,r1) _stxi_d(_jit,i0,r0,r1) static void _stxi_d(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_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 @@ -1179,4 +1181,27 @@ _stxi_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1) jit_unget_reg(reg); } } + +static void +_vaarg_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1) +{ + jit_int32_t inv, reg; + + assert(_jitc->function->self.call & jit_call_varargs); + reg = jit_get_reg(jit_class_gpr); + if ((inv = reg == _R0)) reg = jit_get_reg(jit_class_gpr); + + /* Load varargs stack pointer. */ + ldxi(rn(reg), r1, offsetof(jit_va_list_t, stack)); + + /* 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); + if (inv) jit_unget_reg(_R0); +} #endif diff --git a/lib/jit_ppc.c b/lib/jit_ppc.c index 0b134bf0a..650f70f64 100644 --- a/lib/jit_ppc.c +++ b/lib/jit_ppc.c @@ -33,6 +33,13 @@ # define F_DISP (__WORDSIZE >> 3) - sizeof(jit_float32_t) #endif +/* + * Types + */ +typedef struct jit_va_list { + jit_pointer_t stack; +} jit_va_list_t; + /* * Prototypes */ @@ -306,6 +313,12 @@ _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; + _jitc->function->vafp = _jitc->function->self.argf; } } @@ -1436,9 +1449,19 @@ _emit_code(jit_state_t *_jit) epilog(node); _jitc->function = NULL; 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_arg: case jit_code_arg_f: case jit_code_arg_d: + case jit_code_va_end: break; default: abort();