diff options
author | Mike Pall <mike> | 2011-01-02 20:43:58 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2011-01-02 20:43:58 +0100 |
commit | e66b5b6eeefa0cadfd80a859c71d41c2f9e076b8 (patch) | |
tree | 7f9dec9509ff5862339fdad16339743c86291889 /src | |
parent | 55a9be7809e6fa85f8051a85b8085cc8a9d36734 (diff) | |
download | luajit-e66b5b6eeefa0cadfd80a859c71d41c2f9e076b8.tar.gz luajit-e66b5b6eeefa0cadfd80a859c71d41c2f9e076b8.tar.bz2 luajit-e66b5b6eeefa0cadfd80a859c71d41c2f9e076b8.zip |
Improve uint64_t <-> FP conversions in x64 backend.
Diffstat (limited to 'src')
-rw-r--r-- | src/lj_asm.c | 30 | ||||
-rw-r--r-- | src/lj_ir.c | 6 | ||||
-rw-r--r-- | src/lj_iropt.h | 1 |
3 files changed, 21 insertions, 16 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c index 14d6d849..18944da4 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c | |||
@@ -1641,18 +1641,15 @@ static void asm_conv(ASMState *as, IRIns *ir) | |||
1641 | return; | 1641 | return; |
1642 | #endif | 1642 | #endif |
1643 | } else { /* Integer to FP conversion. */ | 1643 | } else { /* Integer to FP conversion. */ |
1644 | Reg tmp = (LJ_64 && st == IRT_U64) ? ra_scratch(as, RSET_GPR) : RID_NONE; | ||
1645 | Reg left = (LJ_64 && (st == IRT_U32 || st == IRT_U64)) ? | 1644 | Reg left = (LJ_64 && (st == IRT_U32 || st == IRT_U64)) ? |
1646 | ra_alloc1(as, lref, RSET_GPR) : | 1645 | ra_alloc1(as, lref, RSET_GPR) : |
1647 | asm_fuseload(as, lref, RSET_GPR); | 1646 | asm_fuseload(as, lref, RSET_GPR); |
1648 | if (LJ_64 && st == IRT_U64) { | 1647 | if (LJ_64 && st == IRT_U64) { |
1649 | Reg tmpn = ra_scratch(as, rset_exclude(RSET_FPR, dest)); | ||
1650 | MCLabel l_end = emit_label(as); | 1648 | MCLabel l_end = emit_label(as); |
1651 | emit_rr(as, XO_ADDSD, dest, tmpn); | 1649 | const void *k = lj_ir_k64_find(as->J, U64x(43f00000,00000000)); |
1652 | emit_rr(as, XO_MOVD, tmpn|REX_64, tmp); | 1650 | emit_rma(as, XO_ADDSD, dest, k); /* Add 2^64 to compensate. */ |
1653 | emit_loadu64(as, tmp, U64x(43f00000,00000000)); | ||
1654 | emit_sjcc(as, CC_NS, l_end); | 1651 | emit_sjcc(as, CC_NS, l_end); |
1655 | emit_rr(as, XO_TEST, left|REX_64, left); | 1652 | emit_rr(as, XO_TEST, left|REX_64, left); /* Check if u64 >= 2^63. */ |
1656 | } | 1653 | } |
1657 | emit_mrm(as, irt_isnum(ir->t) ? XO_CVTSI2SD : XO_CVTSI2SS, | 1654 | emit_mrm(as, irt_isnum(ir->t) ? XO_CVTSI2SD : XO_CVTSI2SS, |
1658 | dest|((LJ_64 && (st64 || st == IRT_U32)) ? REX_64 : 0), left); | 1655 | dest|((LJ_64 && (st64 || st == IRT_U32)) ? REX_64 : 0), left); |
@@ -1675,15 +1672,22 @@ static void asm_conv(ASMState *as, IRIns *ir) | |||
1675 | ((ir->op2 & IRCONV_TRUNC) ? XO_CVTTSD2SI : XO_CVTSD2SI) : | 1672 | ((ir->op2 & IRCONV_TRUNC) ? XO_CVTTSD2SI : XO_CVTSD2SI) : |
1676 | ((ir->op2 & IRCONV_TRUNC) ? XO_CVTTSS2SI : XO_CVTSS2SI); | 1673 | ((ir->op2 & IRCONV_TRUNC) ? XO_CVTTSS2SI : XO_CVTSS2SI); |
1677 | if (LJ_64 && irt_isu64(ir->t)) { | 1674 | if (LJ_64 && irt_isu64(ir->t)) { |
1678 | Reg left = ra_alloc1(as, lref, RSET_FPR); | 1675 | const void *k = lj_ir_k64_find(as->J, U64x(c3f00000,00000000)); |
1679 | Reg tmpn = ra_scratch(as, rset_exclude(RSET_FPR, left)); | ||
1680 | MCLabel l_end = emit_label(as); | 1676 | MCLabel l_end = emit_label(as); |
1681 | emit_rr(as, op, dest|REX_64, tmpn); | 1677 | Reg left = IR(lref)->r; |
1682 | emit_rr(as, XO_ADDSD, tmpn, left); | 1678 | /* For inputs in [2^63,2^64-1] add -2^64 and convert again. */ |
1683 | emit_rr(as, XO_MOVD, tmpn|REX_64, dest); | 1679 | if (ra_hasreg(left)) { |
1684 | emit_loadu64(as, dest, U64x(c3f00000,00000000)); | 1680 | Reg tmpn = ra_scratch(as, rset_exclude(RSET_FPR, left)); |
1681 | emit_rr(as, op, dest|REX_64, tmpn); | ||
1682 | emit_rr(as, XO_ADDSD, tmpn, left); | ||
1683 | emit_rma(as, XMM_MOVRM(as), tmpn, k); | ||
1684 | } else { | ||
1685 | left = ra_allocref(as, lref, RSET_FPR); | ||
1686 | emit_rr(as, op, dest|REX_64, left); | ||
1687 | emit_rma(as, XO_ADDSD, left, k); | ||
1688 | } | ||
1685 | emit_sjcc(as, CC_NS, l_end); | 1689 | emit_sjcc(as, CC_NS, l_end); |
1686 | emit_rr(as, XO_TEST, dest|REX_64, dest); | 1690 | emit_rr(as, XO_TEST, dest|REX_64, dest); /* Check if dest < 2^63. */ |
1687 | emit_rr(as, op, dest|REX_64, left); | 1691 | emit_rr(as, op, dest|REX_64, left); |
1688 | } else { | 1692 | } else { |
1689 | Reg left = asm_fuseload(as, lref, RSET_FPR); | 1693 | Reg left = asm_fuseload(as, lref, RSET_FPR); |
diff --git a/src/lj_ir.c b/src/lj_ir.c index 3217bc1e..89be71aa 100644 --- a/src/lj_ir.c +++ b/src/lj_ir.c | |||
@@ -195,7 +195,7 @@ void lj_ir_k64_freeall(jit_State *J) | |||
195 | } | 195 | } |
196 | 196 | ||
197 | /* Find 64 bit constant in chained array or add it. */ | 197 | /* Find 64 bit constant in chained array or add it. */ |
198 | static cTValue *ir_k64_find(jit_State *J, uint64_t u64) | 198 | cTValue *lj_ir_k64_find(jit_State *J, uint64_t u64) |
199 | { | 199 | { |
200 | K64Array *k, *kp = NULL; | 200 | K64Array *k, *kp = NULL; |
201 | TValue *ntv; | 201 | TValue *ntv; |
@@ -249,13 +249,13 @@ found: | |||
249 | /* Intern FP constant, given by its 64 bit pattern. */ | 249 | /* Intern FP constant, given by its 64 bit pattern. */ |
250 | TRef lj_ir_knum_u64(jit_State *J, uint64_t u64) | 250 | TRef lj_ir_knum_u64(jit_State *J, uint64_t u64) |
251 | { | 251 | { |
252 | return lj_ir_k64(J, IR_KNUM, ir_k64_find(J, u64)); | 252 | return lj_ir_k64(J, IR_KNUM, lj_ir_k64_find(J, u64)); |
253 | } | 253 | } |
254 | 254 | ||
255 | /* Intern 64 bit integer constant. */ | 255 | /* Intern 64 bit integer constant. */ |
256 | TRef lj_ir_kint64(jit_State *J, uint64_t u64) | 256 | TRef lj_ir_kint64(jit_State *J, uint64_t u64) |
257 | { | 257 | { |
258 | return lj_ir_k64(J, IR_KINT64, ir_k64_find(J, u64)); | 258 | return lj_ir_k64(J, IR_KINT64, lj_ir_k64_find(J, u64)); |
259 | } | 259 | } |
260 | 260 | ||
261 | /* Check whether a number is int and return it. -0 is NOT considered an int. */ | 261 | /* Check whether a number is int and return it. -0 is NOT considered an int. */ |
diff --git a/src/lj_iropt.h b/src/lj_iropt.h index 4739f846..12943d25 100644 --- a/src/lj_iropt.h +++ b/src/lj_iropt.h | |||
@@ -41,6 +41,7 @@ static LJ_AINLINE IRRef lj_ir_nextins(jit_State *J) | |||
41 | LJ_FUNC TRef LJ_FASTCALL lj_ir_kint(jit_State *J, int32_t k); | 41 | LJ_FUNC TRef LJ_FASTCALL lj_ir_kint(jit_State *J, int32_t k); |
42 | LJ_FUNC void lj_ir_k64_freeall(jit_State *J); | 42 | LJ_FUNC void lj_ir_k64_freeall(jit_State *J); |
43 | LJ_FUNC TRef lj_ir_k64(jit_State *J, IROp op, cTValue *tv); | 43 | LJ_FUNC TRef lj_ir_k64(jit_State *J, IROp op, cTValue *tv); |
44 | LJ_FUNC cTValue *lj_ir_k64_find(jit_State *J, uint64_t u64); | ||
44 | LJ_FUNC TRef lj_ir_knum_u64(jit_State *J, uint64_t u64); | 45 | LJ_FUNC TRef lj_ir_knum_u64(jit_State *J, uint64_t u64); |
45 | LJ_FUNC TRef lj_ir_knumint(jit_State *J, lua_Number n); | 46 | LJ_FUNC TRef lj_ir_knumint(jit_State *J, lua_Number n); |
46 | LJ_FUNC TRef lj_ir_kint64(jit_State *J, uint64_t u64); | 47 | LJ_FUNC TRef lj_ir_kint64(jit_State *J, uint64_t u64); |