diff --git a/ChangeLog b/ChangeLog index 6de334244..f6aa2bea6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-06-19 Paulo Andrade + + * lib/jit_hppa-cpu.c, lib/jit_hppa-fpu.c, lib/jit_hppa.c: + Add base support to jit vararg functions to the hppa backend. + 2015-06-10 Paulo Andrade * lib/jit_ia64-cpu.c, lib/jit_ia64-fpu.c, lib/jit_ia64.c: diff --git a/lib/jit_hppa-cpu.c b/lib/jit_hppa-cpu.c index 9d8431bdd..637925c89 100644 --- a/lib/jit_hppa-cpu.c +++ b/lib/jit_hppa-cpu.c @@ -802,6 +802,7 @@ static void _ldi_us(jit_state_t*,jit_int32_t,jit_word_t); #define ldxr_us(r0,r1,r2) LDH(r2,r1,r0) #define ldxi_us(r0,r1,i0) _ldxi_us(_jit,r0,r1,i0) static void _ldxi_us(jit_state_t*,jit_int32_t,jit_int32_t,jit_word_t); +#define ldr(r0,r1) ldr_ui(r0,r1) #define ldr_i(r0,r1) ldr_ui(r0,r1) #define ldr_ui(r0,r1) LDWI(_R0_REGNO,r1,r0) #define ldi_i(r0,i0) ldi_ui(r0,i0) @@ -919,6 +920,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 @@ -1666,10 +1671,14 @@ static void _subi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0) { jit_int32_t reg; - reg = jit_get_reg(jit_class_gpr); - movi(rn(reg), i0); - subr(r0, r1, rn(reg)); - jit_unget_reg(reg); + if (i0 >= -1023 && i0 <= 1024) + addi(r0, r1, -i0); + else { + reg = jit_get_reg(jit_class_gpr); + movi(rn(reg), i0); + subr(r0, r1, rn(reg)); + jit_unget_reg(reg); + } } static void @@ -2688,6 +2697,11 @@ _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 = 3; regno >= _jitc->function->vagp; --regno) + stxi(params_offset - regno * 4 - 4, _FP_REGNO, rn(_R26 - regno)); + } } static void @@ -2720,6 +2734,25 @@ _epilog(jit_state_t *_jit, jit_node_t *node) #endif } +static void +_vastart(jit_state_t *_jit, jit_int32_t r0) +{ + /* Initialize stack pointer to the first stack argument. */ + addi(r0, _FP_REGNO, params_offset - _jitc->function->vagp * 4); +} + +static void +_vaarg(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1) +{ + assert(_jitc->function->self.call & jit_call_varargs); + + /* Update vararg stack pointer. */ + subi(r1, r1, 4); + + /* Load argument. */ + ldr(r0, r1); +} + static void _patch_at(jit_state_t *_jit, jit_word_t instr, jit_word_t label) { diff --git a/lib/jit_hppa-fpu.c b/lib/jit_hppa-fpu.c index a49ce9640..7cd264eda 100644 --- a/lib/jit_hppa-fpu.c +++ b/lib/jit_hppa-fpu.c @@ -30,7 +30,8 @@ #define f39(o,b,x,t) _f39(_jit,o,b,x,t) static void _f39(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t); #define f40(o,b,x,r) _f40(_jit,o,b,x,r) -static void _f40(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t); +static void _f40(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t) + maybe_unused; #define f41(o,b,x,t) _f41(_jit,o,b,x,t) static void _f41(jit_state_t*,jit_int32_t,jit_int32_t,jit_int32_t,jit_int32_t); #define f42(o,b,i,r) _f42(_jit,o,b,i,r) @@ -486,6 +487,8 @@ static jit_word_t _bcmpi_d(jit_state_t*,jit_word_t, #define bunordi_f(i0,r0,i1) bcmpi_f(FCMP_UNORD,i0,r0,i1) #define bunordr_d(i0,r0,r1) bcmpr_d(FCMP_UNORD,i0,r0,r1) #define bunordi_d(i0,r0,i1) bcmpi_d(FCMP_UNORD,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 #if CODE @@ -1013,4 +1016,24 @@ _bcmpi_d(jit_state_t *_jit, jit_word_t c, jit_unget_reg(reg); return (w); } + +static void +_vaarg_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1) +{ + jit_int32_t reg; + + assert(_jitc->function->self.call & jit_call_varargs); + + /* Align pointer if required. */ + reg = jit_get_reg(jit_class_gpr); + andi(rn(reg), r1, 7); + subr(r1, r1, rn(reg)); + jit_unget_reg(reg); + + /* Adjust vararg stack pointer. */ + subi(r1, r1, 8); + + /* Load argument. */ + ldr_d(r0, r1); +} #endif diff --git a/lib/jit_hppa.c b/lib/jit_hppa.c index ed6f43ee4..d977aa79e 100644 --- a/lib/jit_hppa.c +++ b/lib/jit_hppa.c @@ -29,6 +29,11 @@ # include "jit_hppa-fpu.c" #undef PROTO +/* + * Types + */ +typedef jit_pointer_t jit_va_list; + /* * Prototypes */ @@ -295,6 +300,8 @@ _jit_ellipsis(jit_state_t *_jit) else { assert(!(_jitc->function->self.call & jit_call_varargs)); _jitc->function->self.call |= jit_call_varargs; + + _jitc->function->vagp = _jitc->function->self.argi; } } @@ -531,6 +538,7 @@ _jit_pushargr_f(jit_state_t *_jit, jit_int32_t u) if (jit_arg_reg_p(_jitc->function->call.argi)) { jit_movr_f(_F4 - _jitc->function->call.argi, u); #if !defined(__hpux) + /* HP-UX appears to always pass float arguments in gpr registers */ if (_jitc->function->call.call & jit_call_varargs) #endif { @@ -553,6 +561,7 @@ _jit_pushargi_f(jit_state_t *_jit, jit_float32_t u) if (jit_arg_reg_p(_jitc->function->call.argi)) { jit_movi_f(_F4 - _jitc->function->call.argi, u); #if !defined(__hpux) + /* HP-UX appears to always pass float arguments in gpr registers */ if (_jitc->function->call.call & jit_call_varargs) #endif { @@ -583,6 +592,7 @@ _jit_pushargr_d(jit_state_t *_jit, jit_int32_t u) if (jit_arg_reg_p(_jitc->function->call.argi)) { jit_movr_d(_F4 - (_jitc->function->call.argi + 1), u); #if !defined(__hpux) + /* HP-UX appears to always pass float arguments in gpr registers */ if (_jitc->function->call.call & jit_call_varargs) #endif { @@ -615,6 +625,7 @@ _jit_pushargi_d(jit_state_t *_jit, jit_float64_t u) if (jit_arg_reg_p(_jitc->function->call.argi)) { jit_movi_d(_F4 - (_jitc->function->call.argi + 1), u); #if !defined(__hpux) + /* HP-UX appears to always pass float arguments in gpr registers */ if (_jitc->function->call.call & jit_call_varargs) #endif { @@ -1251,9 +1262,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();