From 3f397228f5f1f27f3a8a264530a11895fbc9fb79 Mon Sep 17 00:00:00 2001 From: pcpa Date: Thu, 20 Nov 2014 15:05:13 -0200 Subject: [PATCH] ARM: Correct several inconsistencies with ldrd and strd * lib/jit_disasm.c: Change thumb or arm disassemble based on jit code before disassembly. * lib/jit_arm-cpu.c: Correct reversed arguments to LDRD and STRD instructions, and correct checking for support of those. * lib/jit_arm-swf.c: Correct wrong use of LDRD and STRD and only use those if the register is even. * check/check.arm.swf.sh, check/check.arm4.swf.sh: New files to test LDRD and STRD, as well as the alternate code path when those are not available, in the .arm4. test case. * check/Makefile.am: Update for the new test cases. --- ChangeLog | 17 ++++++++++++++ check/Makefile.am | 49 +++++++++++++++++++++++++++++++++++++++++ check/check.arm.swf.sh | 15 +++++++++++++ check/check.arm4.swf.sh | 15 +++++++++++++ lib/jit_arm-cpu.c | 8 +++---- lib/jit_arm-swf.c | 39 ++++++++++++++++++-------------- lib/jit_disasm.c | 18 +++++++-------- 7 files changed, 131 insertions(+), 30 deletions(-) create mode 100755 check/check.arm.swf.sh create mode 100755 check/check.arm4.swf.sh diff --git a/ChangeLog b/ChangeLog index fc1670dac..3263ef315 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2014-11-20 Paulo Andrade + + * lib/jit_disasm.c: Change thumb or arm disassemble based on + jit code before disassembly. + + * lib/jit_arm-cpu.c: Correct reversed arguments to LDRD and + STRD instructions, and correct checking for support of those. + + * lib/jit_arm-swf.c: Correct wrong use of LDRD and STRD and + only use those if the register is even. + + * check/check.arm.swf.sh, check/check.arm4.swf.sh: New files + to test LDRD and STRD, as well as the alternate code path + when those are not available, in the .arm4. test case. + + * check/Makefile.am: Update for the new test cases. + 2014-11-08 Paulo Andrade * include/lightning/jit_private.h, lib/jit_aarch64.c, diff --git a/check/Makefile.am b/check/Makefile.am index b736f5038..ca6afe90c 100644 --- a/check/Makefile.am +++ b/check/Makefile.am @@ -92,6 +92,8 @@ EXTRA_DIST = \ check.sh \ check.x87.sh \ check.arm.sh check.swf.sh \ + check.arm.swf.sh \ + check.arm4.swf.sh \ check.nodata.sh \ check.x87.nodata.sh \ run-test all.tst @@ -213,6 +215,53 @@ swf_TESTS = \ $(swf_TESTS): check.swf.sh $(LN_S) $(srcdir)/check.swf.sh $@ TESTS += $(swf_TESTS) +if test_arm_arm +#arm_swf_TESTS = $(addsuffix .arm.swf, $(base_TESTS)) +arm_swf_TESTS = \ + 3to2.arm.swf add.arm.swf allocai.arm.swf \ + bp.arm.swf divi.arm.swf fib.arm.swf rpn.arm.swf \ + ldstr.arm.swf ldsti.arm.swf \ + ldstxr.arm.swf ldstxi.arm.swf \ + ldstr-c.arm.swf ldstxr-c.arm.swf ldstxi-c.arm.swf \ + cvt.arm.swf branch.arm.swf \ + alu_add.arm.swf alux_add.arm.swf \ + alu_sub.arm.swf alux_sub.arm.swf alu_rsb.arm.swf \ + alu_mul.arm.swf alu_div.arm.swf alu_rem.arm.swf \ + alu_and.arm.swf alu_or.arm.swf alu_xor.arm.swf \ + alu_lsh.arm.swf alu_rsh.arm.swf \ + alu_com.arm.swf alu_neg.arm.swf \ + fop_abs.arm.swf fop_sqrt.arm.swf \ + varargs.arm.swf stack.arm.swf \ + clobber.arm.swf carry.arm.swf call.arm.swf \ + float.arm.swf jmpr.arm.swf tramp.arm.swf range.arm.swf +$(arm_swf_TESTS): check.arm.swf.sh + $(LN_S) $(srcdir)/check.arm.swf.sh $@ +TESTS += $(arm_swf_TESTS) +endif +if test_arm_arm +#arm4_swf_TESTS = $(addsuffix .arm4.swf, $(base_TESTS)) +arm4_swf_TESTS = \ + 3to2.arm4.swf add.arm4.swf allocai.arm4.swf \ + bp.arm4.swf divi.arm4.swf fib.arm4.swf rpn.arm4.swf \ + ldstr.arm4.swf ldsti.arm4.swf \ + ldstxr.arm4.swf ldstxi.arm4.swf \ + ldstr-c.arm4.swf ldstxr-c.arm4.swf ldstxi-c.arm4.swf \ + cvt.arm4.swf branch.arm4.swf \ + alu_add.arm4.swf alux_add.arm4.swf \ + alu_sub.arm4.swf alux_sub.arm4.swf alu_rsb.arm4.swf \ + alu_mul.arm4.swf alu_div.arm4.swf alu_rem.arm4.swf \ + alu_and.arm4.swf alu_or.arm4.swf alu_xor.arm4.swf \ + alu_lsh.arm4.swf alu_rsh.arm4.swf \ + alu_com.arm4.swf alu_neg.arm4.swf \ + fop_abs.arm4.swf fop_sqrt.arm4.swf \ + varargs.arm4.swf stack.arm4.swf \ + clobber.arm4.swf carry.arm4.swf call.arm4.swf \ + float.arm4.swf jmpr.arm4.swf tramp.arm4.swf \ + range.arm4.swf +$(arm4_swf_TESTS): check.arm4.swf.sh + $(LN_S) $(srcdir)/check.arm4.swf.sh $@ +TESTS += $(arm4_swf_TESTS) +endif endif if test_nodata diff --git a/check/check.arm.swf.sh b/check/check.arm.swf.sh new file mode 100755 index 000000000..378b6d7d9 --- /dev/null +++ b/check/check.arm.swf.sh @@ -0,0 +1,15 @@ +#!/bin/sh +test=`basename $0 | sed -e 's|\.arm\.swf$||'` +./lightning -mthumb=0 -mvfp=0 $srcdir/$test.tst | tr -d \\r > $test.out +if test $? != 0; then + exit $? +fi + +cmp -s $srcdir/$test.ok $test.out +result=$? +if test $result != 0; then + diff $srcdir/$test.ok $test.out + rm $test.out + exit 1 +fi +rm $test.out diff --git a/check/check.arm4.swf.sh b/check/check.arm4.swf.sh new file mode 100755 index 000000000..21926b622 --- /dev/null +++ b/check/check.arm4.swf.sh @@ -0,0 +1,15 @@ +#!/bin/sh +test=`basename $0 | sed -e 's|\.arm4\.swf$||'` +./lightning -mcpu=4 -mthumb=0 -mvfp=0 $srcdir/$test.tst | tr -d \\r > $test.out +if test $? != 0; then + exit $? +fi + +cmp -s $srcdir/$test.ok $test.out +result=$? +if test $result != 0; then + diff $srcdir/$test.ok $test.out + rm $test.out + exit 1 +fi +rm $test.out diff --git a/lib/jit_arm-cpu.c b/lib/jit_arm-cpu.c index 552bce3d8..aabccef8b 100644 --- a/lib/jit_arm-cpu.c +++ b/lib/jit_arm-cpu.c @@ -31,7 +31,7 @@ # define jit_thumb_p() jit_cpu.thumb # define jit_no_set_flags() _jitc->no_set_flags # define jit_armv5_p() (jit_cpu.version >= 5) -# define jit_armv5e_p() (jit_cpu.version >= 5 && jit_cpu.extend) +# define jit_armv5e_p() (jit_cpu.version > 5 || (jit_cpu.version == 5 && jit_cpu.extend)) # define jit_armv6_p() (jit_cpu.version >= 6) # define jit_armv7r_p() 0 # define stack_framesize 48 @@ -709,9 +709,9 @@ static void _torl(jit_state_t*,int,int,int) maybe_unused; # define LDRD(rt,rn,rm) CC_LDRD(ARM_CC_AL,rt,rn,rm) # define T2_LDRDI(rt,rt2,rn,im) torrri8(THUMB2_LDRDI|ARM_P,rn,rt,rt2,im) # define CC_LDRDN(cc,rt,rn,rm) corrr(cc,ARM_LDRD,rn,rt,rm) -# define LDRDN(rd,rn,rm) CC_LDRDN(ARM_CC_AL,rn,rt,rm) +# define LDRDN(rd,rn,rm) CC_LDRDN(ARM_CC_AL,rt,rn,rm) # define CC_LDRDI(cc,rt,rn,im) corri8(cc,ARM_LDRDI|ARM_P,rn,rt,im) -# define LDRDI(rt,rn,im) CC_LDRDI(ARM_CC_AL,rn,rt,im) +# define LDRDI(rt,rn,im) CC_LDRDI(ARM_CC_AL,rt,rn,im) # define CC_LDRDIN(cc,rt,rn,im) corri8(cc,ARM_LDRDI,rn,rt,im) # define LDRDIN(rt,rn,im) CC_LDRDIN(ARM_CC_AL,rt,rn,im) # define T2_LDRDIN(rt,rt2,rn,im) torrri8(THUMB2_LDRDI,rn,rt,rt2,im) @@ -758,7 +758,7 @@ static void _torl(jit_state_t*,int,int,int) maybe_unused; # define CC_STRIN(cc,rt,rn,im) corri(cc,ARM_STRI,rn,rt,im) # define STRIN(rt,rn,im) CC_STRIN(ARM_CC_AL,rt,rn,im) # define T2_STRIN(rt,rn,im) torri8(THUMB2_STRI,rn,rt,im) -# define CC_STRD(cc,rt,rn,rm) corrr(cc,ARM_STRD|ARM_P,rt,rn,rm) +# define CC_STRD(cc,rt,rn,rm) corrr(cc,ARM_STRD|ARM_P,rn,rt,rm) # define STRD(rt,rn,rm) CC_STRD(ARM_CC_AL,rt,rn,rm) # define CC_STRDN(cc,rt,rn,rm) corrr(cc,ARM_STRD,rn,rt,rm) # define STRDN(rt,rn,rm) CC_STRDN(ARM_CC_AL,rt,rn,rm) diff --git a/lib/jit_arm-swf.c b/lib/jit_arm-swf.c index 8afd9e54a..d4774e918 100644 --- a/lib/jit_arm-swf.c +++ b/lib/jit_arm-swf.c @@ -1870,7 +1870,7 @@ _swf_movr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1) } } else if (jit_fpr_p(r0)) { - if (!jit_thumb_p() && jit_armv5e_p()) + if (!jit_thumb_p() && jit_armv5e_p() && !(r1 & 1)) STRDIN(r1, _FP_REGNO, swf_off(r0) + 8); else { swf_strin(r1, _FP_REGNO, swf_off(r0) + 8); @@ -1967,9 +1967,9 @@ _swf_absr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1) if (jit_fpr_p(r1)) { if (jit_fpr_p(r0) && !jit_thumb_p() && jit_armv5e_p() && r0 != r1 && (reg = jit_get_reg_pair()) != JIT_NOREG) { - LDRDIN(rn(reg), _FP_REGNO, swf_off(r1) + 4); - swf_bici(rn(reg), rn(reg), 0x80000000); - STRDIN(rn(reg), _FP_REGNO, swf_off(r0) + 4); + LDRDIN(rn(reg), _FP_REGNO, swf_off(r1) + 8); + swf_bici(rn(reg) + 1, rn(reg) + 1, 0x80000000); + STRDIN(rn(reg), _FP_REGNO, swf_off(r0) + 8); jit_unget_reg_pair(reg); } else { @@ -2039,9 +2039,9 @@ _swf_negr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1) if (jit_fpr_p(r1)) { if (jit_fpr_p(r0) && !jit_thumb_p() && jit_armv5e_p() && r0 != r1 && (reg = jit_get_reg_pair()) != JIT_NOREG) { - LDRDIN(rn(reg), _FP_REGNO, swf_off(r1) + 4); - EORI(rn(reg), rn(reg), encode_arm_immediate(0x80000000)); - STRDIN(rn(reg), _FP_REGNO, swf_off(r0) + 4); + LDRDIN(rn(reg), _FP_REGNO, swf_off(r1) + 8); + EORI(rn(reg) + 1, rn(reg) + 1, encode_arm_immediate(0x80000000)); + STRDIN(rn(reg), _FP_REGNO, swf_off(r0) + 8); jit_unget_reg_pair(reg); } else { @@ -2197,7 +2197,7 @@ _swf_ldr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1) jit_unget_reg(reg); } } - else if (!jit_thumb_p() && jit_armv5e_p()) + else if (!jit_thumb_p() && jit_armv5e_p() && !(r0 & 1)) LDRDI(r0, r1, 0); else { ldxi_i(r0, r1, 0); @@ -2241,7 +2241,7 @@ _swf_ldi_d(jit_state_t *_jit, jit_int32_t r0, jit_word_t i0) swf_strin(rn(rg0), _FP_REGNO, swf_off(r0) + 4); jit_unget_reg(rg0); } - else if (!jit_thumb_p() && jit_armv5e_p()) + else if (!jit_thumb_p() && jit_armv5e_p() && !(r0 & 1)) LDRDI(r0, rn(rg1), 0); else { ldxi_i(r0, rn(rg1), 0); @@ -2289,7 +2289,7 @@ _swf_ldxr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2) } } else { - if (!jit_thumb_p() && jit_armv5e_p()) + if (!jit_thumb_p() && jit_armv5e_p() && !(r0 & 1)) LDRD(r0, r1, r2); else { rg1 = jit_get_reg(jit_class_gpr); @@ -2360,9 +2360,11 @@ _swf_ldxi_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0) } } else { - if (!jit_thumb_p() && jit_armv5e_p() && i0 >= 0 && i0 <= 255) + if (!jit_thumb_p() && jit_armv5e_p() && + i0 >= 0 && i0 <= 255 && !(r0 & 1)) LDRDI(r0, r1, i0); - else if (!jit_thumb_p() && jit_armv5e_p() && i0 < 0 && i0 >= -255) + else if (!jit_thumb_p() && jit_armv5e_p() && + i0 < 0 && i0 >= -255 && !(r0 & 1)) LDRDIN(r0, r1, -i0); else if (i0 >= 0 && i0 + 4 <= 4095) { ldxi_i(r0, r1, i0); @@ -2417,7 +2419,7 @@ _swf_str_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1) } } else { - if (!jit_thumb_p() && jit_armv5e_p()) + if (!jit_thumb_p() && jit_armv5e_p() && !(r1 & 1)) STRDI(r1, r0, 0); else { stxi_i(0, r0, r1); @@ -2469,7 +2471,7 @@ _swf_sti_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0) else { rg1 = jit_get_reg(jit_class_gpr); movi(rn(rg1), i0); - if (!jit_thumb_p() && jit_armv5e_p()) + if (!jit_thumb_p() && jit_armv5e_p() && !(r0 & 1)) STRDI(r0, rn(rg1), 0); else { stxi_i(0, rn(rg1), r0); @@ -2517,7 +2519,7 @@ _swf_stxr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_int32_t r2) } } else { - if (!jit_thumb_p() && jit_armv5e_p()) + if (!jit_thumb_p() && jit_armv5e_p() && !(r2 & 1)) STRD(r0, r1, r2); else { rg1 = jit_get_reg(jit_class_gpr); @@ -2556,6 +2558,7 @@ _swf_stxi_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1) STRDI(rn(rg0), r0, i0); else STRDIN(rn(rg0), r0, -i0); + jit_unget_reg_pair(rg0); } else if (i0 >= 0 && i0 + 4 <= 4095) { rg0 = jit_get_reg(jit_class_gpr); @@ -2587,9 +2590,11 @@ _swf_stxi_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1) } } else { - if (!jit_thumb_p() && jit_armv5e_p() && i0 >= 0 && i0 <= 255) + if (!jit_thumb_p() && jit_armv5e_p() && + i0 >= 0 && i0 <= 255 && !(r1 & 1)) STRDI(r1, r0, i0); - else if (!jit_thumb_p() && jit_armv5e_p() && i0 < 0 && i0 >= -255) + else if (!jit_thumb_p() && jit_armv5e_p() && + i0 < 0 && i0 >= -255 && !(r1 & 1)) STRDIN(r1, r0, -i0); else if (i0 >= 0 && i0 + 4 <= 4095) { stxi_i(i0, r0, r1); diff --git a/lib/jit_disasm.c b/lib/jit_disasm.c index 6f9227dd2..51c678465 100644 --- a/lib/jit_disasm.c +++ b/lib/jit_disasm.c @@ -84,12 +84,6 @@ jit_init_debug(const char *progname) disasm_info.mach = bfd_mach_i386_i386; # endif # endif -# if defined(__arm__) - /* FIXME add mapping for prolog switching to arm and possible jump - * before first prolog also in arm mode */ - if (jit_cpu.thumb) - disasm_info.disassembler_options = "force-thumb"; -# endif # if defined(__powerpc__) disasm_info.arch = bfd_arch_powerpc; disasm_info.mach = bfd_mach_ppc64; @@ -204,8 +198,15 @@ void _jit_disassemble(jit_state_t *_jit) { #if DISASSEMBLER - if (disasm_bfd) + if (disasm_bfd) { +# if defined(__arm__) + /* FIXME add mapping for prolog switching to arm and possible jump + * before first prolog also in arm mode */ + disasm_info.disassembler_options = jit_cpu.thumb ? "force-thumb" : ""; +# endif + disassemble(_jit->code.ptr, _jit->pc.uc - _jit->code.ptr); + } #endif } @@ -326,8 +327,7 @@ _disassemble(jit_state_t *_jit, jit_pointer_t code, jit_int32_t length) again: if (data_info) { while (_jitc->data_info.ptr[data_offset].code < pc) { - data_offset += 2; - if (data_offset >= _jitc->data_info.length) { + if (++data_offset >= _jitc->data_info.length) { data_info = 0; goto again; }