diff options
author | Mike Pall <mike> | 2011-01-02 18:24:31 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2011-01-02 18:24:31 +0100 |
commit | 0005b2c2b91d3d3c115b1e5d12b32715c0ea77a6 (patch) | |
tree | 8a745a631db9c6954fd22f248ddcf2c9b2022a3b /src | |
parent | ddfa7fc246569f2fb7a664efcca73ac0e047d876 (diff) | |
download | luajit-0005b2c2b91d3d3c115b1e5d12b32715c0ea77a6.tar.gz luajit-0005b2c2b91d3d3c115b1e5d12b32715c0ea77a6.tar.bz2 luajit-0005b2c2b91d3d3c115b1e5d12b32715c0ea77a6.zip |
Add support for uint64_t <-> FP conversions to x64 backend.
Diffstat (limited to 'src')
-rw-r--r-- | src/lj_asm.c | 49 | ||||
-rw-r--r-- | src/lj_obj.h | 3 |
2 files changed, 35 insertions, 17 deletions
diff --git a/src/lj_asm.c b/src/lj_asm.c index 8127b2eb..14d6d849 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c | |||
@@ -1641,8 +1641,19 @@ 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 left = (LJ_64 && st == IRT_U32) ? ra_alloc1(as, lref, RSET_GPR) : | 1644 | Reg tmp = (LJ_64 && st == IRT_U64) ? ra_scratch(as, RSET_GPR) : RID_NONE; |
1645 | asm_fuseload(as, lref, RSET_GPR); | 1645 | Reg left = (LJ_64 && (st == IRT_U32 || st == IRT_U64)) ? |
1646 | ra_alloc1(as, lref, RSET_GPR) : | ||
1647 | asm_fuseload(as, lref, RSET_GPR); | ||
1648 | if (LJ_64 && st == IRT_U64) { | ||
1649 | Reg tmpn = ra_scratch(as, rset_exclude(RSET_FPR, dest)); | ||
1650 | MCLabel l_end = emit_label(as); | ||
1651 | emit_rr(as, XO_ADDSD, dest, tmpn); | ||
1652 | emit_rr(as, XO_MOVD, tmpn|REX_64, tmp); | ||
1653 | emit_loadu64(as, tmp, U64x(43f00000,00000000)); | ||
1654 | emit_sjcc(as, CC_NS, l_end); | ||
1655 | emit_rr(as, XO_TEST, left|REX_64, left); | ||
1656 | } | ||
1646 | emit_mrm(as, irt_isnum(ir->t) ? XO_CVTSI2SD : XO_CVTSI2SS, | 1657 | emit_mrm(as, irt_isnum(ir->t) ? XO_CVTSI2SD : XO_CVTSI2SS, |
1647 | dest|((LJ_64 && (st64 || st == IRT_U32)) ? REX_64 : 0), left); | 1658 | dest|((LJ_64 && (st64 || st == IRT_U32)) ? REX_64 : 0), left); |
1648 | } | 1659 | } |
@@ -1657,24 +1668,32 @@ static void asm_conv(ASMState *as, IRIns *ir) | |||
1657 | /* NYI: number to 64 bit integer or uint32_t conversion. */ | 1668 | /* NYI: number to 64 bit integer or uint32_t conversion. */ |
1658 | setintV(&as->J->errinfo, ir->o); | 1669 | setintV(&as->J->errinfo, ir->o); |
1659 | lj_trace_err_info(as->J, LJ_TRERR_NYIIR); | 1670 | lj_trace_err_info(as->J, LJ_TRERR_NYIIR); |
1660 | #else | ||
1661 | } else if (irt_isu64(ir->t)) { | ||
1662 | /* NYI: number to uint64_t conversion. */ | ||
1663 | setintV(&as->J->errinfo, ir->o); | ||
1664 | lj_trace_err_info(as->J, LJ_TRERR_NYIIR); | ||
1665 | #endif | 1671 | #endif |
1666 | } else { | 1672 | } else { |
1667 | Reg dest = ra_dest(as, ir, RSET_GPR); | 1673 | Reg dest = ra_dest(as, ir, RSET_GPR); |
1668 | Reg left = asm_fuseload(as, ir->op1, RSET_FPR); | ||
1669 | x86Op op = st == IRT_NUM ? | 1674 | x86Op op = st == IRT_NUM ? |
1670 | ((ir->op2 & IRCONV_TRUNC) ? XO_CVTTSD2SI : XO_CVTSD2SI) : | 1675 | ((ir->op2 & IRCONV_TRUNC) ? XO_CVTTSD2SI : XO_CVTSD2SI) : |
1671 | ((ir->op2 & IRCONV_TRUNC) ? XO_CVTTSS2SI : XO_CVTSS2SI); | 1676 | ((ir->op2 & IRCONV_TRUNC) ? XO_CVTTSS2SI : XO_CVTSS2SI); |
1672 | if (LJ_64 && irt_isu32(ir->t)) | 1677 | if (LJ_64 && irt_isu64(ir->t)) { |
1673 | emit_rr(as, XO_MOV, dest, dest); /* Zero upper 32 bits. */ | 1678 | Reg left = ra_alloc1(as, lref, RSET_FPR); |
1674 | emit_mrm(as, op, | 1679 | Reg tmpn = ra_scratch(as, rset_exclude(RSET_FPR, left)); |
1675 | dest|((LJ_64 && | 1680 | MCLabel l_end = emit_label(as); |
1676 | (irt_is64(ir->t) || irt_isu32(ir->t))) ? REX_64 : 0), | 1681 | emit_rr(as, op, dest|REX_64, tmpn); |
1677 | left); | 1682 | emit_rr(as, XO_ADDSD, tmpn, left); |
1683 | emit_rr(as, XO_MOVD, tmpn|REX_64, dest); | ||
1684 | emit_loadu64(as, dest, U64x(c3f00000,00000000)); | ||
1685 | emit_sjcc(as, CC_NS, l_end); | ||
1686 | emit_rr(as, XO_TEST, dest|REX_64, dest); | ||
1687 | emit_rr(as, op, dest|REX_64, left); | ||
1688 | } else { | ||
1689 | Reg left = asm_fuseload(as, lref, RSET_FPR); | ||
1690 | if (LJ_64 && irt_isu32(ir->t)) | ||
1691 | emit_rr(as, XO_MOV, dest, dest); /* Zero upper 32 bits. */ | ||
1692 | emit_mrm(as, op, | ||
1693 | dest|((LJ_64 && | ||
1694 | (irt_is64(ir->t) || irt_isu32(ir->t))) ? REX_64 : 0), | ||
1695 | left); | ||
1696 | } | ||
1678 | } | 1697 | } |
1679 | } else if (st >= IRT_I8 && st <= IRT_U16) { /* Extend to 32 bit integer. */ | 1698 | } else if (st >= IRT_I8 && st <= IRT_U16) { /* Extend to 32 bit integer. */ |
1680 | Reg left, dest = ra_dest(as, ir, RSET_GPR); | 1699 | Reg left, dest = ra_dest(as, ir, RSET_GPR); |
@@ -1690,7 +1709,7 @@ static void asm_conv(ASMState *as, IRIns *ir) | |||
1690 | } else { | 1709 | } else { |
1691 | op = XO_MOVZXw; | 1710 | op = XO_MOVZXw; |
1692 | } | 1711 | } |
1693 | left = asm_fuseload(as, ir->op1, allow); | 1712 | left = asm_fuseload(as, lref, allow); |
1694 | /* Add extra MOV if source is already in wrong register. */ | 1713 | /* Add extra MOV if source is already in wrong register. */ |
1695 | if (!LJ_64 && left != RID_MRM && !rset_test(allow, left)) { | 1714 | if (!LJ_64 && left != RID_MRM && !rset_test(allow, left)) { |
1696 | Reg tmp = ra_scratch(as, allow); | 1715 | Reg tmp = ra_scratch(as, allow); |
diff --git a/src/lj_obj.h b/src/lj_obj.h index 456aef0b..342ebafb 100644 --- a/src/lj_obj.h +++ b/src/lj_obj.h | |||
@@ -767,8 +767,7 @@ static LJ_AINLINE uint64_t lj_num2u64(lua_Number n) | |||
767 | { | 767 | { |
768 | #ifdef _MSC_VER | 768 | #ifdef _MSC_VER |
769 | if (n >= 9223372036854775808.0) /* They think it's a feature. */ | 769 | if (n >= 9223372036854775808.0) /* They think it's a feature. */ |
770 | return (uint64_t)(int64_t)(n - 9223372036854775808.0) + | 770 | return (uint64_t)(int64_t)(n - 18446744073709551616.0); |
771 | U64x(80000000,00000000); | ||
772 | else | 771 | else |
773 | #endif | 772 | #endif |
774 | return (uint64_t)n; | 773 | return (uint64_t)n; |