diff --git a/ChangeLog b/ChangeLog index ca0855444..8611bda43 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2012-12-04 Paulo Andrade + + * include/lightning/jit_mips.h, lib/jit_mips-cpu.c, + lib/jit_mips-fpu.c, lib/jit_mips.c: Correct float/double + argument handling and make the mips backend pass the initial + test cases. + + * include/lightning.h, ib/jit_print.c, lib/lightning.c: + Add extra enum values for argument handling functions that + could not be abstracted to the current codes, that is, when + float values need to move from/to gpr from/to fpr. It would + be more tempting to add such primitives, but they would have + wordsize limitations, and it is not expected to add codes + with one gpr argument for 64 bit and two for 32 bit. + + * lib/jit_ppc.c: Check _jit->function before calling jit_epilog() + to avoid a runtime exception. + 2012-12-04 Paulo Andrade * include/lightning/jit_mips.h, lib/jit_mips.c: Update to diff --git a/include/lightning.h b/include/lightning.h index f4fb5aeaf..4209005a6 100644 --- a/include/lightning.h +++ b/include/lightning.h @@ -433,6 +433,7 @@ typedef enum { #define jit_arg_f() _jit_arg_f(_jit) #define jit_getarg_f(u,v) _jit_getarg_f(_jit,u,v) + jit_code_getarg_f, #define jit_addr_f(u,v,w) jit_new_node_www(jit_code_addr_f,u,v,w) #define jit_addi_f(u,v,w) jit_new_node_wwf(jit_code_addi_f,u,v,w) @@ -568,6 +569,7 @@ typedef enum { #define jit_pushargr_f(u) _jit_pushargr_f(_jit,u) #define jit_pushargi_f(u) _jit_pushargi_f(_jit,u) + jit_code_pushargr_f, jit_code_pushargi_f, #define jit_retr_f(u) _jit_retr_f(_jit,u) #define jit_reti_f(u) _jit_reti_f(_jit,u) #define jit_retval_f(u) _jit_retval_f(_jit,u) @@ -575,6 +577,7 @@ typedef enum { #define jit_arg_d() _jit_arg_d(_jit) #define jit_getarg_d(u,v) _jit_getarg_d(_jit,u,v) + jit_code_getarg_d, #define jit_addr_d(u,v,w) jit_new_node_www(jit_code_addr_d,u,v,w) #define jit_addi_d(u,v,w) jit_new_node_wwd(jit_code_addi_d,u,v,w) @@ -711,6 +714,7 @@ typedef enum { #define jit_pushargr_d(u) _jit_pushargr_d(_jit,u) #define jit_pushargi_d(u) _jit_pushargi_d(_jit,u) + jit_code_pushargr_d, jit_code_pushargi_d, #define jit_retr_d(u) _jit_retr_d(_jit,u) #define jit_reti_d(u) _jit_reti_d(_jit,u) #define jit_retval_d(u) _jit_retval_d(_jit,u) diff --git a/include/lightning/jit_mips.h b/include/lightning/jit_mips.h index 5a0043bc3..505e06669 100644 --- a/include/lightning/jit_mips.h +++ b/include/lightning/jit_mips.h @@ -88,7 +88,7 @@ typedef enum { _F16, _F18, _F20, _F22, _F24, _F26, _F28, _F30, #define JIT_FA0 _F12 #define JIT_FA1 _F14 - _F12, _F14, + _F14, _F12, #define JIT_NOREG _NOREG _NOREG, } jit_reg_t; diff --git a/lib/jit_mips-cpu.c b/lib/jit_mips-cpu.c index 9ab14e7fe..5f04e4d2d 100644 --- a/lib/jit_mips-cpu.c +++ b/lib/jit_mips-cpu.c @@ -76,7 +76,7 @@ typedef union { # define sti(u, v) sti_i(u, v) # define stxi(u, v, w) stxi_i(u, v, w) # else -# define stack_framesize 142 +# define stack_framesize 144 # 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) diff --git a/lib/jit_mips-fpu.c b/lib/jit_mips-fpu.c index be7e98480..bddbc4ae2 100644 --- a/lib/jit_mips-fpu.c +++ b/lib/jit_mips-fpu.c @@ -208,6 +208,10 @@ static void _divi_d(jit_state_t*,jit_int32_t,jit_int32_t,jit_float64_t*); # define absr_d(r0,r1) ABS_D(r0,r1) # define negr_f(r0,r1) NEG_S(r0,r1) # define negr_d(r0,r1) NEG_D(r0,r1) +# define getarg_f(r0, r1) MTC1(r1, r0) +# define pushargr_f(r0, r1) MFC1(r1, r0) +# define pushargi_f(r0, i0) _pushargi_f(_jit, r0, i0) +static void _pushargi_f(jit_state_t*,jit_int32_t,jit_float32_t*); # define extr_f(r0, r1) _extr_f(_jit, r0, r1) static void _extr_f(jit_state_t*,jit_int32_t,jit_int32_t); # define truncr_f_i(r0, r1) _truncr_f_i(_jit, r0, r1) @@ -235,6 +239,12 @@ static void _stxi_f(jit_state_t*,jit_word_t,jit_int32_t,jit_int32_t); static void _movr_f(jit_state_t*,jit_int32_t,jit_int32_t); # define movi_f(r0, i0) _movi_f(_jit, r0, i0) static void _movi_f(jit_state_t*,jit_int32_t,jit_float32_t*); +# define getarg_d(r0, r1) _getarg_d(_jit, r0, r1) +static void _getarg_d(jit_state_t*,jit_int32_t,jit_int32_t); +# define pushargr_d(r0, r1) _pushargr_d(_jit, r0, r1) +static void _pushargr_d(jit_state_t*,jit_int32_t,jit_int32_t); +# define pushargi_d(r0, i0) _pushargi_d(_jit, r0, i0) +static void _pushargi_d(jit_state_t*,jit_int32_t,jit_float64_t*); # define extr_d(r0, r1) _extr_d(_jit, r0, r1) static void _extr_d(jit_state_t*,jit_int32_t,jit_int32_t); # define truncr_d_i(r0, r1) _truncr_d_i(_jit, r0, r1) @@ -566,6 +576,18 @@ fopi(sub) fopi(mul) fopi(div) +static void +_pushargi_f(jit_state_t *_jit, jit_int32_t r0, jit_float32_t *i0) +{ + union { + jit_int32_t i; + jit_float32_t f; + } data; + + data.f = *i0; + movi(r0, data.i); +} + static void _extr_f(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1) { @@ -706,6 +728,46 @@ dopi(sub) dopi(mul) dopi(div) +static void +_getarg_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1) +{ +# if __WORDSIZE == 32 + MTC1(r1, r0); + MTC1(r1 + 1, r0 + 1); +# else + DMTC1(r1, r0); +# endif +} + +static void +_pushargr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1) +{ +# if __WORDSIZE == 32 + MFC1(r0, r1); + MFC1(r0 + 1, r1 + 1); +# else + DMFC1(r0, r1); +# endif +} + +static void +_pushargi_d(jit_state_t *_jit, jit_int32_t r0, jit_float64_t *i0) +{ + union { + jit_int32_t i[2]; + jit_int64_t l; + jit_float64_t d; + } data; + + data.d = *i0; +# if __WORDSIZE == 64 + movi(r0, data.l); +# else + movi(r0, data.i[0]); + movi(r0 + 1, data.i[1]); + # endif +} + static void _extr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1) { diff --git a/lib/jit_mips.c b/lib/jit_mips.c index 1fc1c0957..2e220b246 100644 --- a/lib/jit_mips.c +++ b/lib/jit_mips.c @@ -240,6 +240,10 @@ _jit_arg(jit_state_t *_jit) jit_int32_t offset; assert(_jit->function); + if (_jit->function->self.argf) { + _jit->function->self.argi = _jit->function->self.argf; + _jit->function->self.argf = 0; + } if (_jit->function->self.argi < 4) offset = _jit->function->self.argi++; else @@ -260,27 +264,26 @@ _jit_arg_f(jit_state_t *_jit) jit_int32_t offset; assert(_jit->function); - if (_jit->function->self.argi) { - if (_jit->function->self.argi & 1) - ++_jit->function->self.argi; - _jit->function->self.argf = _jit->function->self.argi; - } - if ((offset = _jit->function->self.argf) < 4) { - offset = _jit->function->self.argf; - _jit->function->self.argf += 2; - if (_jit->function->self.argi) - _jit->function->self.argi = _jit->function->self.argf; + offset = (_jit->function->self.size - stack_framesize) >> 2; + if (offset < 4) { + if (!_jit->function->self.argi) { + offset += 4; + _jit->function->self.argf += 2; + } + else + _jit->function->self.argi += 2; } else offset = _jit->function->self.size; - _jit->function->self.size += sizeof(jit_word_t); + _jit->function->self.size += sizeof(jit_float32_t); return (offset); } jit_bool_t _jit_arg_f_reg_p(jit_state_t *_jit, jit_int32_t offset) { - return (offset >= 0 && offset < 4); + /* 0-3 integer register, 4-7 float register */ + return (offset >= 0 && offset < 8); } jit_int32_t @@ -289,16 +292,21 @@ _jit_arg_d(jit_state_t *_jit) jit_int32_t offset; assert(_jit->function); - if (_jit->function->self.argi) { - if (_jit->function->self.argi & 1) - ++_jit->function->self.argi; - _jit->function->self.argf = _jit->function->self.argi; - } - if ((offset = _jit->function->self.argf) < 4) { - offset = _jit->function->self.argf; - _jit->function->self.argf += 2; - if (_jit->function->self.argi) + if (_jit->function->self.size & 7) { + _jit->function->self.size += 4; + if (_jit->function->self.size < 16 && !_jit->function->self.argi) { _jit->function->self.argi = _jit->function->self.argf; + _jit->function->self.argf = 0; + } + } + offset = (_jit->function->self.size - stack_framesize) >> 2; + if (offset < 4) { + if (!_jit->function->self.argi) { + offset += 4; + _jit->function->self.argf += 2; + } + else + _jit->function->self.argi += 2; } else offset = _jit->function->self.size; @@ -386,9 +394,9 @@ void _jit_getarg_f(jit_state_t *_jit, jit_int32_t u, jit_int32_t v) { if (v < 4) - jit_extr_f(u, _A0 - v); + jit_new_node_ww(jit_code_getarg_f, u, _A0 - (v >> 1)); else if (v < 8) - jit_movr_f(u, _F12 + ((v - 4) >> 1)); + jit_movr_f(u, _F12 - ((v - 4) >> 1)); else jit_ldxi_f(u, _FP, v); } @@ -397,9 +405,9 @@ void _jit_getarg_d(jit_state_t *_jit, jit_int32_t u, jit_int32_t v) { if (v < 4) - jit_extr_d(u, _A0 - v); + jit_new_node_ww(jit_code_getarg_d, u, _A0 - (v >> 1)); else if (v < 8) - jit_movr_d(u, _F12 + ((v - 4) >> 1)); + jit_movr_d(u, _F12 - ((v - 4) >> 1)); else jit_ldxi_d(u, _FP, v); } @@ -408,6 +416,10 @@ void _jit_pushargr(jit_state_t *_jit, jit_int32_t u) { assert(_jit->function); + if (_jit->function->call.argf) { + _jit->function->call.argi = _jit->function->call.argf; + _jit->function->call.argf = 0; + } if (_jit->function->call.argi < 4) { jit_movr(_A0 - _jit->function->call.argi, u); ++_jit->function->call.argi; @@ -423,6 +435,10 @@ _jit_pushargi(jit_state_t *_jit, jit_word_t u) jit_int32_t regno; assert(_jit->function); + if (_jit->function->call.argf) { + _jit->function->call.argi = _jit->function->call.argf; + _jit->function->call.argf = 0; + } if (_jit->function->call.argi < 4) { jit_movi(_A0 - _jit->function->call.argi, u); ++_jit->function->call.argi; @@ -440,44 +456,60 @@ void _jit_pushargr_f(jit_state_t *_jit, jit_int32_t u) { assert(_jit->function); - if (_jit->function->call.argf < 4) { - jit_movr_f(JIT_FA0 - (_jit->function->call.argf >> 1), u); + if (_jit->function->call.argi) { + jit_new_node_ww(jit_code_pushargr_f, + _A0 - _jit->function->call.argi, u); + _jit->function->call.argi += 2; + } + else if (_jit->function->call.argf < 4) { + jit_movr_f(_F12 - (_jit->function->call.argf >> 1), u); _jit->function->call.argf += 2; - /* if _jit->function->call.argi, actually move to integer register */ } else jit_stxi_f(_jit->function->call.size, JIT_SP, u); - _jit->function->call.size += sizeof(jit_word_t); + _jit->function->call.size += sizeof(jit_float32_t); } void _jit_pushargi_f(jit_state_t *_jit, jit_float32_t u) { - jit_int32_t regno; + jit_int32_t regno; - assert(_jit->function); - if (_jit->function->call.argf < 4) { - jit_movi_f(JIT_FA0 - _jit->function->call.argf, u); + if (_jit->function->call.argi) { + if (_jit->function->call.argi & 1) + ++_jit->function->call.argi; + jit_new_node_wf(jit_code_pushargi_f, + _A0 - _jit->function->call.argi, u); + _jit->function->call.argi += 2; + } + else if (_jit->function->call.argf < 4) { + jit_movi_f(_F12 - (_jit->function->call.argf >> 1), u); _jit->function->call.argf += 2; - /* if _jit->function->call.argi, actually move to integer register */ } else { + assert(_jit->function); regno = jit_get_reg(jit_class_fpr); jit_movi_f(regno, u); jit_stxi_f(_jit->function->call.size, JIT_SP, regno); jit_unget_reg(regno); } - _jit->function->call.size += sizeof(jit_word_t); + _jit->function->call.size += sizeof(jit_float32_t); } void _jit_pushargr_d(jit_state_t *_jit, jit_int32_t u) { assert(_jit->function); - if (_jit->function->call.argf < 4) { - jit_movr_d(JIT_FA0 - (_jit->function->call.argf >> 1), u); + if (_jit->function->call.argi) { + if (_jit->function->call.argi & 1) + ++_jit->function->call.argi; + jit_new_node_ww(jit_code_pushargr_d, + _A0 - _jit->function->call.argi, u); + _jit->function->call.argi += 2; + } + else if (_jit->function->call.argf < 4) { + jit_movr_d(_F12 - (_jit->function->call.argf >> 1), u); _jit->function->call.argf += 2; - /* if _jit->function->call.argi, actually move to integer register */ } else jit_stxi_d(_jit->function->call.size, JIT_SP, u); @@ -487,18 +519,24 @@ _jit_pushargr_d(jit_state_t *_jit, jit_int32_t u) void _jit_pushargi_d(jit_state_t *_jit, jit_float64_t u) { - jit_int32_t regno; + jit_int32_t regno; - assert(_jit->function); - if (_jit->function->call.argf < 4) { - jit_movi_d(JIT_FA0 - _jit->function->call.argf, u); + if (_jit->function->call.argi) { + if (_jit->function->call.argi & 1) + ++_jit->function->call.argi; + jit_new_node_wd(jit_code_pushargi_d, + _A0 - _jit->function->call.argi, u); + _jit->function->call.argi += 2; + } + else if (_jit->function->call.argf < 4) { + jit_movi_d(_F12 - (_jit->function->call.argf >> 1), u); _jit->function->call.argf += 2; - /* if _jit->function->call.argi, actually move to integer register */ } else { + assert(_jit->function); regno = jit_get_reg(jit_class_fpr); - jit_movi_d(regno, u); - jit_stxi_d(_jit->function->call.size, JIT_SP, regno); + jit_movi_f(regno, u); + jit_stxi_f(_jit->function->call.size, JIT_SP, regno); jit_unget_reg(regno); } _jit->function->call.size += sizeof(jit_float64_t); @@ -639,7 +677,8 @@ _jit_emit(jit_state_t *_jit) jit_int32_t patch_offset; } undo; - jit_epilog(); + if (_jit->function) + jit_epilog(); jit_optimize(); _jit->emit = 1; @@ -862,6 +901,8 @@ _jit_emit(jit_state_t *_jit) else movi(rn(node->u.w), node->v.w); break; + case_rr(neg,); + case_rr(com,); case_rrr(lt,); case_rrw(lt,); case_rrr(lt, _u); @@ -1142,6 +1183,22 @@ _jit_emit(jit_state_t *_jit) epilog(node); _jit->function = NULL; break; + case jit_code_getarg_f: + getarg_f(rn(node->u.w), rn(node->v.w)); + break; + case_rr(pusharg, _f); + case jit_code_pushargi_f: + assert(node->flag & jit_flag_data); + pushargi_f(rn(node->u.w), (jit_float32_t *)node->v.n->u.w); + break; + case jit_code_getarg_d: + getarg_d(rn(node->u.w), rn(node->v.w)); + break; + case_rr(pusharg, _d); + case jit_code_pushargi_d: + assert(node->flag & jit_flag_data); + pushargi_d(rn(node->u.w), (jit_float64_t *)node->v.n->u.w); + break; default: abort(); } diff --git a/lib/jit_ppc.c b/lib/jit_ppc.c index a27a2283e..35b0f91e8 100644 --- a/lib/jit_ppc.c +++ b/lib/jit_ppc.c @@ -564,7 +564,8 @@ _jit_emit(jit_state_t *_jit) jit_int32_t patch_offset; } undo; - jit_epilog(); + if (_jit->function) + jit_epilog(); jit_optimize(); _jit->emit = 1; diff --git a/lib/jit_print.c b/lib/jit_print.c index 01a5c783d..151ddba61 100644 --- a/lib/jit_print.c +++ b/lib/jit_print.c @@ -118,6 +118,7 @@ static char *code_name[] = { "jmpr", "jmpi", "callr", "calli", "epilog", + "getarg_f", "addr_f", "addi_f", "subr_f", "subi_f", "mulr_f", "muli_f", @@ -159,7 +160,9 @@ static char *code_name[] = { "bltgtr_f", "bltgti_f", "bordr_f", "bordi_f", "bunordr_f", "bunordi_f", + "pushargr_f", "pushargi_f", "retval_f", + "getarg_d", "addr_d", "addi_d", "subr_d", "subi_d", "mulr_d", "muli_d", @@ -201,6 +204,7 @@ static char *code_name[] = { "bltgtr_d", "bltgti_d", "bordr_d", "bordi_d", "bunordr_d", "bunordi_d", + "pushargr_d", "pushargi_d", "retval_d", }; diff --git a/lib/lightning.c b/lib/lightning.c index 3595611c7..ac06ffe99 100644 --- a/lib/lightning.c +++ b/lib/lightning.c @@ -765,6 +765,9 @@ _jit_classify(jit_state_t *_jit, jit_code_t code) case jit_code_callr: case jit_code_jmpr: mask = jit_cc_a0_reg|jit_cc_a0_jmp; break; + case jit_code_pushargr_f: case jit_code_pushargr_d: + mask = jit_cc_a0_reg|jit_cc_a1_reg; + break; case jit_code_retval_f: case jit_code_retval_d: mask = jit_cc_a0_reg|jit_cc_a0_chg; break; @@ -774,10 +777,10 @@ _jit_classify(jit_state_t *_jit, jit_code_t code) case jit_code_ldi_d: mask = jit_cc_a0_reg|jit_cc_a0_chg|jit_cc_a1_int; break; - case jit_code_movi_f: + case jit_code_movi_f: case jit_code_pushargi_f: mask = jit_cc_a0_reg|jit_cc_a0_chg|jit_cc_a1_flt; break; - case jit_code_movi_d: + case jit_code_movi_d: case jit_code_pushargi_d: mask = jit_cc_a0_reg|jit_cc_a0_chg|jit_cc_a1_dbl; break; case jit_code_negr: case jit_code_comr: case jit_code_movr: @@ -793,6 +796,7 @@ _jit_classify(jit_state_t *_jit, jit_code_t code) case jit_code_negr_d: case jit_code_absr_d: case jit_code_sqrtr_d: case jit_code_movr_d: case jit_code_extr_d: case jit_code_extr_f_d: case jit_code_ldr_d: + case jit_code_getarg_f: case jit_code_getarg_d: mask = jit_cc_a0_reg|jit_cc_a0_chg|jit_cc_a1_reg; break; case jit_code_addi: case jit_code_addxi: case jit_code_addci: