1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-11 16:20:19 +02:00

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.
This commit is contained in:
pcpa 2014-11-20 15:05:13 -02:00
parent 7b449aa063
commit 3f397228f5
7 changed files with 131 additions and 30 deletions

View file

@ -1,3 +1,20 @@
2014-11-20 Paulo Andrade <pcpa@gnu.org>
* 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 <pcpa@gnu.org> 2014-11-08 Paulo Andrade <pcpa@gnu.org>
* include/lightning/jit_private.h, lib/jit_aarch64.c, * include/lightning/jit_private.h, lib/jit_aarch64.c,

View file

@ -92,6 +92,8 @@ EXTRA_DIST = \
check.sh \ check.sh \
check.x87.sh \ check.x87.sh \
check.arm.sh check.swf.sh \ check.arm.sh check.swf.sh \
check.arm.swf.sh \
check.arm4.swf.sh \
check.nodata.sh \ check.nodata.sh \
check.x87.nodata.sh \ check.x87.nodata.sh \
run-test all.tst run-test all.tst
@ -213,6 +215,53 @@ swf_TESTS = \
$(swf_TESTS): check.swf.sh $(swf_TESTS): check.swf.sh
$(LN_S) $(srcdir)/check.swf.sh $@ $(LN_S) $(srcdir)/check.swf.sh $@
TESTS += $(swf_TESTS) 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 endif
if test_nodata if test_nodata

15
check/check.arm.swf.sh Executable file
View file

@ -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

15
check/check.arm4.swf.sh Executable file
View file

@ -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

View file

@ -31,7 +31,7 @@
# define jit_thumb_p() jit_cpu.thumb # define jit_thumb_p() jit_cpu.thumb
# define jit_no_set_flags() _jitc->no_set_flags # define jit_no_set_flags() _jitc->no_set_flags
# define jit_armv5_p() (jit_cpu.version >= 5) # 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_armv6_p() (jit_cpu.version >= 6)
# define jit_armv7r_p() 0 # define jit_armv7r_p() 0
# define stack_framesize 48 # 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 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 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 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 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 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 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) # 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 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 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 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 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 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) # define STRDN(rt,rn,rm) CC_STRDN(ARM_CC_AL,rt,rn,rm)

View file

@ -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)) { 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); STRDIN(r1, _FP_REGNO, swf_off(r0) + 8);
else { else {
swf_strin(r1, _FP_REGNO, swf_off(r0) + 8); 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(r1)) {
if (jit_fpr_p(r0) && !jit_thumb_p() && jit_armv5e_p() && if (jit_fpr_p(r0) && !jit_thumb_p() && jit_armv5e_p() &&
r0 != r1 && (reg = jit_get_reg_pair()) != JIT_NOREG) { r0 != r1 && (reg = jit_get_reg_pair()) != JIT_NOREG) {
LDRDIN(rn(reg), _FP_REGNO, swf_off(r1) + 4); LDRDIN(rn(reg), _FP_REGNO, swf_off(r1) + 8);
swf_bici(rn(reg), rn(reg), 0x80000000); swf_bici(rn(reg) + 1, rn(reg) + 1, 0x80000000);
STRDIN(rn(reg), _FP_REGNO, swf_off(r0) + 4); STRDIN(rn(reg), _FP_REGNO, swf_off(r0) + 8);
jit_unget_reg_pair(reg); jit_unget_reg_pair(reg);
} }
else { 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(r1)) {
if (jit_fpr_p(r0) && !jit_thumb_p() && jit_armv5e_p() && if (jit_fpr_p(r0) && !jit_thumb_p() && jit_armv5e_p() &&
r0 != r1 && (reg = jit_get_reg_pair()) != JIT_NOREG) { r0 != r1 && (reg = jit_get_reg_pair()) != JIT_NOREG) {
LDRDIN(rn(reg), _FP_REGNO, swf_off(r1) + 4); LDRDIN(rn(reg), _FP_REGNO, swf_off(r1) + 8);
EORI(rn(reg), rn(reg), encode_arm_immediate(0x80000000)); EORI(rn(reg) + 1, rn(reg) + 1, encode_arm_immediate(0x80000000));
STRDIN(rn(reg), _FP_REGNO, swf_off(r0) + 4); STRDIN(rn(reg), _FP_REGNO, swf_off(r0) + 8);
jit_unget_reg_pair(reg); jit_unget_reg_pair(reg);
} }
else { else {
@ -2197,7 +2197,7 @@ _swf_ldr_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1)
jit_unget_reg(reg); 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); LDRDI(r0, r1, 0);
else { else {
ldxi_i(r0, r1, 0); 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); swf_strin(rn(rg0), _FP_REGNO, swf_off(r0) + 4);
jit_unget_reg(rg0); 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); LDRDI(r0, rn(rg1), 0);
else { else {
ldxi_i(r0, rn(rg1), 0); 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 { else {
if (!jit_thumb_p() && jit_armv5e_p()) if (!jit_thumb_p() && jit_armv5e_p() && !(r0 & 1))
LDRD(r0, r1, r2); LDRD(r0, r1, r2);
else { else {
rg1 = jit_get_reg(jit_class_gpr); 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 { 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); 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); LDRDIN(r0, r1, -i0);
else if (i0 >= 0 && i0 + 4 <= 4095) { else if (i0 >= 0 && i0 + 4 <= 4095) {
ldxi_i(r0, r1, i0); 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 { else {
if (!jit_thumb_p() && jit_armv5e_p()) if (!jit_thumb_p() && jit_armv5e_p() && !(r1 & 1))
STRDI(r1, r0, 0); STRDI(r1, r0, 0);
else { else {
stxi_i(0, r0, r1); 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 { else {
rg1 = jit_get_reg(jit_class_gpr); rg1 = jit_get_reg(jit_class_gpr);
movi(rn(rg1), i0); 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); STRDI(r0, rn(rg1), 0);
else { else {
stxi_i(0, rn(rg1), r0); 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 { else {
if (!jit_thumb_p() && jit_armv5e_p()) if (!jit_thumb_p() && jit_armv5e_p() && !(r2 & 1))
STRD(r0, r1, r2); STRD(r0, r1, r2);
else { else {
rg1 = jit_get_reg(jit_class_gpr); 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); STRDI(rn(rg0), r0, i0);
else else
STRDIN(rn(rg0), r0, -i0); STRDIN(rn(rg0), r0, -i0);
jit_unget_reg_pair(rg0);
} }
else if (i0 >= 0 && i0 + 4 <= 4095) { else if (i0 >= 0 && i0 + 4 <= 4095) {
rg0 = jit_get_reg(jit_class_gpr); 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 { 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); 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); STRDIN(r1, r0, -i0);
else if (i0 >= 0 && i0 + 4 <= 4095) { else if (i0 >= 0 && i0 + 4 <= 4095) {
stxi_i(i0, r0, r1); stxi_i(i0, r0, r1);

View file

@ -84,12 +84,6 @@ jit_init_debug(const char *progname)
disasm_info.mach = bfd_mach_i386_i386; disasm_info.mach = bfd_mach_i386_i386;
# endif # endif
# 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__) # if defined(__powerpc__)
disasm_info.arch = bfd_arch_powerpc; disasm_info.arch = bfd_arch_powerpc;
disasm_info.mach = bfd_mach_ppc64; disasm_info.mach = bfd_mach_ppc64;
@ -204,8 +198,15 @@ void
_jit_disassemble(jit_state_t *_jit) _jit_disassemble(jit_state_t *_jit)
{ {
#if DISASSEMBLER #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); disassemble(_jit->code.ptr, _jit->pc.uc - _jit->code.ptr);
}
#endif #endif
} }
@ -326,8 +327,7 @@ _disassemble(jit_state_t *_jit, jit_pointer_t code, jit_int32_t length)
again: again:
if (data_info) { if (data_info) {
while (_jitc->data_info.ptr[data_offset].code < pc) { 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; data_info = 0;
goto again; goto again;
} }