ARM: Fix register allocation when rematerializing FPRs.

This commit is contained in:
Mike Pall 2013-07-31 01:48:21 +02:00
parent 6dc02450d3
commit 6a878b0441

View File

@ -521,10 +521,10 @@ static void asm_tointg(ASMState *as, IRIns *ir, Reg left)
static void asm_tobit(ASMState *as, IRIns *ir) static void asm_tobit(ASMState *as, IRIns *ir)
{ {
RegSet allow = RSET_FPR; RegSet allow = RSET_FPR;
Reg dest = ra_dest(as, ir, RSET_GPR);
Reg left = ra_alloc1(as, ir->op1, allow); Reg left = ra_alloc1(as, ir->op1, allow);
Reg right = ra_alloc1(as, ir->op2, rset_clear(allow, left)); Reg right = ra_alloc1(as, ir->op2, rset_clear(allow, left));
Reg tmp = ra_scratch(as, rset_clear(allow, right)); Reg tmp = ra_scratch(as, rset_clear(allow, right));
Reg dest = ra_dest(as, ir, RSET_GPR);
emit_dn(as, ARMI_VMOV_R_S, dest, (tmp & 15)); emit_dn(as, ARMI_VMOV_R_S, dest, (tmp & 15));
emit_dnm(as, ARMI_VADD_D, (tmp & 15), (left & 15), (right & 15)); emit_dnm(as, ARMI_VADD_D, (tmp & 15), (left & 15), (right & 15));
} }
@ -564,9 +564,9 @@ static void asm_conv(ASMState *as, IRIns *ir)
lua_assert(irt_isint(ir->t) && st == IRT_NUM); lua_assert(irt_isint(ir->t) && st == IRT_NUM);
asm_tointg(as, ir, ra_alloc1(as, lref, RSET_FPR)); asm_tointg(as, ir, ra_alloc1(as, lref, RSET_FPR));
} else { } else {
Reg dest = ra_dest(as, ir, RSET_GPR);
Reg left = ra_alloc1(as, lref, RSET_FPR); Reg left = ra_alloc1(as, lref, RSET_FPR);
Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, left)); Reg tmp = ra_scratch(as, rset_exclude(RSET_FPR, left));
Reg dest = ra_dest(as, ir, RSET_GPR);
ARMIns ai; ARMIns ai;
emit_dn(as, ARMI_VMOV_R_S, dest, (tmp & 15)); emit_dn(as, ARMI_VMOV_R_S, dest, (tmp & 15));
ai = irt_isint(ir->t) ? ai = irt_isint(ir->t) ?
@ -1210,6 +1210,9 @@ static void asm_sload(ASMState *as, IRIns *ir)
} else } else
#endif #endif
if (ra_used(ir)) { if (ra_used(ir)) {
Reg tmp = RID_NONE;
if ((ir->op2 & IRSLOAD_CONVERT))
tmp = ra_scratch(as, t == IRT_INT ? RSET_FPR : RSET_GPR);
lua_assert((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) || lua_assert((LJ_SOFTFP ? 0 : irt_isnum(ir->t)) ||
irt_isint(ir->t) || irt_isaddr(ir->t)); irt_isint(ir->t) || irt_isaddr(ir->t));
dest = ra_dest(as, ir, (!LJ_SOFTFP && t == IRT_NUM) ? RSET_FPR : allow); dest = ra_dest(as, ir, (!LJ_SOFTFP && t == IRT_NUM) ? RSET_FPR : allow);
@ -1217,18 +1220,15 @@ static void asm_sload(ASMState *as, IRIns *ir)
base = ra_alloc1(as, REF_BASE, allow); base = ra_alloc1(as, REF_BASE, allow);
if ((ir->op2 & IRSLOAD_CONVERT)) { if ((ir->op2 & IRSLOAD_CONVERT)) {
if (t == IRT_INT) { if (t == IRT_INT) {
Reg tmp = ra_scratch(as, RSET_FPR);
emit_dn(as, ARMI_VMOV_R_S, dest, (tmp & 15)); emit_dn(as, ARMI_VMOV_R_S, dest, (tmp & 15));
emit_dm(as, ARMI_VCVT_S32_F64, (tmp & 15), (tmp & 15)); emit_dm(as, ARMI_VCVT_S32_F64, (tmp & 15), (tmp & 15));
dest = tmp;
t = IRT_NUM; /* Check for original type. */ t = IRT_NUM; /* Check for original type. */
} else { } else {
Reg tmp = ra_scratch(as, RSET_GPR);
emit_dm(as, ARMI_VCVT_F64_S32, (dest & 15), (dest & 15)); emit_dm(as, ARMI_VCVT_F64_S32, (dest & 15), (dest & 15));
emit_dn(as, ARMI_VMOV_S_R, tmp, (dest & 15)); emit_dn(as, ARMI_VMOV_S_R, tmp, (dest & 15));
dest = tmp;
t = IRT_INT; /* Check for original type. */ t = IRT_INT; /* Check for original type. */
} }
dest = tmp;
} }
goto dotypecheck; goto dotypecheck;
} }
@ -1503,7 +1503,7 @@ static void asm_intmul(ASMState *as, IRIns *ir)
if (dest == left && left != right) { left = right; right = dest; } if (dest == left && left != right) { left = right; right = dest; }
if (irt_isguard(ir->t)) { /* IR_MULOV */ if (irt_isguard(ir->t)) { /* IR_MULOV */
if (!(as->flags & JIT_F_ARMV6) && dest == left) if (!(as->flags & JIT_F_ARMV6) && dest == left)
tmp = left = ra_scratch(as, rset_exclude(RSET_FPR, left)); tmp = left = ra_scratch(as, rset_exclude(RSET_GPR, left));
asm_guardcc(as, CC_NE); asm_guardcc(as, CC_NE);
emit_nm(as, ARMI_TEQ|ARMF_SH(ARMSH_ASR, 31), RID_TMP, dest); emit_nm(as, ARMI_TEQ|ARMF_SH(ARMSH_ASR, 31), RID_TMP, dest);
emit_dnm(as, ARMI_SMULL|ARMF_S(right), dest, RID_TMP, left); emit_dnm(as, ARMI_SMULL|ARMF_S(right), dest, RID_TMP, left);