diff options
author | Mike Pall <mike> | 2011-10-19 00:18:36 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2011-10-19 00:18:36 +0200 |
commit | 45df079c01efbd237b7f2ae4ee3569c83769cf44 (patch) | |
tree | 387d4f49ec992a02577f131a0ec9420e0b203995 /src | |
parent | 2fcd56258284501c6ac874d26a61ea65a05480af (diff) | |
download | luajit-45df079c01efbd237b7f2ae4ee3569c83769cf44.tar.gz luajit-45df079c01efbd237b7f2ae4ee3569c83769cf44.tar.bz2 luajit-45df079c01efbd237b7f2ae4ee3569c83769cf44.zip |
FFI/x86: Fix CONV.u32.num rounding.
Diffstat (limited to 'src')
-rw-r--r-- | src/lj_asm_x86.h | 30 |
1 files changed, 10 insertions, 20 deletions
diff --git a/src/lj_asm_x86.h b/src/lj_asm_x86.h index f4ac0c10..21ab7c25 100644 --- a/src/lj_asm_x86.h +++ b/src/lj_asm_x86.h | |||
@@ -620,33 +620,23 @@ static void asm_conv(ASMState *as, IRIns *ir) | |||
620 | x86Op op = st == IRT_NUM ? | 620 | x86Op op = st == IRT_NUM ? |
621 | ((ir->op2 & IRCONV_TRUNC) ? XO_CVTTSD2SI : XO_CVTSD2SI) : | 621 | ((ir->op2 & IRCONV_TRUNC) ? XO_CVTTSD2SI : XO_CVTSD2SI) : |
622 | ((ir->op2 & IRCONV_TRUNC) ? XO_CVTTSS2SI : XO_CVTSS2SI); | 622 | ((ir->op2 & IRCONV_TRUNC) ? XO_CVTTSS2SI : XO_CVTSS2SI); |
623 | if (LJ_32 && irt_isu32(ir->t)) { /* FP to U32 conversion on x86. */ | 623 | if (LJ_64 ? irt_isu64(ir->t) : irt_isu32(ir->t)) { |
624 | /* u32 = (int32_t)(number - 2^31) + 2^31 */ | 624 | /* LJ_64: For inputs >= 2^63 add -2^64, convert again. */ |
625 | Reg tmp = ra_noreg(IR(lref)->r) ? ra_alloc1(as, lref, RSET_FPR) : | 625 | /* LJ_32: For inputs >= 2^31 add -2^31, convert again and add 2^31. */ |
626 | ra_scratch(as, RSET_FPR); | ||
627 | emit_gri(as, XG_ARITHi(XOg_ADD), dest, (int32_t)0x80000000); | ||
628 | emit_rr(as, op, dest, tmp); | ||
629 | if (st == IRT_NUM) | ||
630 | emit_rma(as, XO_ADDSD, tmp, | ||
631 | lj_ir_k64_find(as->J, U64x(c1e00000,00000000))); | ||
632 | else | ||
633 | emit_rma(as, XO_ADDSS, tmp, | ||
634 | lj_ir_k64_find(as->J, U64x(00000000,cf000000))); | ||
635 | ra_left(as, tmp, lref); | ||
636 | } else if (LJ_64 && irt_isu64(ir->t)) { | ||
637 | /* For inputs in [2^63,2^64-1] add -2^64 and convert again. */ | ||
638 | Reg tmp = ra_noreg(IR(lref)->r) ? ra_alloc1(as, lref, RSET_FPR) : | 626 | Reg tmp = ra_noreg(IR(lref)->r) ? ra_alloc1(as, lref, RSET_FPR) : |
639 | ra_scratch(as, RSET_FPR); | 627 | ra_scratch(as, RSET_FPR); |
640 | MCLabel l_end = emit_label(as); | 628 | MCLabel l_end = emit_label(as); |
629 | if (LJ_32) | ||
630 | emit_gri(as, XG_ARITHi(XOg_ADD), dest, (int32_t)0x80000000); | ||
641 | emit_rr(as, op, dest|REX_64, tmp); | 631 | emit_rr(as, op, dest|REX_64, tmp); |
642 | if (st == IRT_NUM) | 632 | if (st == IRT_NUM) |
643 | emit_rma(as, XO_ADDSD, tmp, | 633 | emit_rma(as, XO_ADDSD, tmp, lj_ir_k64_find(as->J, |
644 | lj_ir_k64_find(as->J, U64x(c3f00000,00000000))); | 634 | LJ_64 ? U64x(c3f00000,00000000) : U64x(c1e00000,00000000))); |
645 | else | 635 | else |
646 | emit_rma(as, XO_ADDSS, tmp, | 636 | emit_rma(as, XO_ADDSS, tmp, lj_ir_k64_find(as->J, |
647 | lj_ir_k64_find(as->J, U64x(00000000,df800000))); | 637 | LJ_64 ? U64x(00000000,df800000) : U64x(00000000,cf000000))); |
648 | emit_sjcc(as, CC_NS, l_end); | 638 | emit_sjcc(as, CC_NS, l_end); |
649 | emit_rr(as, XO_TEST, dest|REX_64, dest); /* Check if dest < 2^63. */ | 639 | emit_rr(as, XO_TEST, dest|REX_64, dest); /* Check if dest negative. */ |
650 | emit_rr(as, op, dest|REX_64, tmp); | 640 | emit_rr(as, op, dest|REX_64, tmp); |
651 | ra_left(as, tmp, lref); | 641 | ra_left(as, tmp, lref); |
652 | } else { | 642 | } else { |