summaryrefslogtreecommitdiff
path: root/src/jit/emitarm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/jit/emitarm.cpp')
-rw-r--r--src/jit/emitarm.cpp125
1 files changed, 42 insertions, 83 deletions
diff --git a/src/jit/emitarm.cpp b/src/jit/emitarm.cpp
index 53ee88b3a2..2b8eb25bc2 100644
--- a/src/jit/emitarm.cpp
+++ b/src/jit/emitarm.cpp
@@ -7568,9 +7568,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR
if (offset != 0)
{
- regMaskTP tmpRegMask = indir->gtRsvdRegs;
- regNumber tmpReg = genRegNumFromMask(tmpRegMask);
- noway_assert(tmpReg != REG_NA);
+ regNumber tmpReg = indir->GetSingleTempReg();
if (emitIns_valid_imm_for_add(offset, INS_FLAGS_DONT_CARE))
{
@@ -7632,9 +7630,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR
else
{
// We require a tmpReg to hold the offset
- regMaskTP tmpRegMask = indir->gtRsvdRegs;
- regNumber tmpReg = genRegNumFromMask(tmpRegMask);
- noway_assert(tmpReg != REG_NA);
+ regNumber tmpReg = indir->GetSingleTempReg();
// First load/store tmpReg with the large offset constant
codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
@@ -7684,8 +7680,6 @@ regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, G
regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
{
- regNumber result = REG_NA;
-
// dst can only be a reg
assert(!dst->isContained());
@@ -7732,120 +7726,85 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst,
assert(!src1->isContained());
}
}
- bool isMulOverflow = false;
- bool isUnsignedMul = false;
- regNumber extraReg = REG_NA;
+
+ insFlags flags = INS_FLAGS_DONT_CARE;
+ bool isMulOverflow = false;
if (dst->gtOverflowEx())
{
- NYI_ARM("emitInsTernary overflow");
-#if 0
- if (ins == INS_add)
- {
- ins = INS_adds;
- }
- else if (ins == INS_sub)
+ if ((ins == INS_add) || (ins == INS_adc) || (ins == INS_sub) || (ins == INS_sbc))
{
- ins = INS_subs;
+ flags = INS_FLAGS_SET;
}
else if (ins == INS_mul)
{
isMulOverflow = true;
- isUnsignedMul = ((dst->gtFlags & GTF_UNSIGNED) != 0);
assert(intConst == nullptr); // overflow format doesn't support an int constant operand
}
else
{
assert(!"Invalid ins for overflow check");
}
-#endif
}
if (intConst != nullptr)
{
- emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
+ emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue(), flags);
}
else
{
if (isMulOverflow)
{
- NYI_ARM("emitInsTernary overflow");
-#if 0
- // Make sure that we have an internal register
- assert(genCountBits(dst->gtRsvdRegs) == 2);
+ regNumber extraReg = dst->GetSingleTempReg();
+ assert(extraReg != dst->gtRegNum);
- // There will be two bits set in tmpRegsMask.
- // Remove the bit for 'dst->gtRegNum' from 'tmpRegsMask'
- regMaskTP tmpRegsMask = dst->gtRsvdRegs & ~genRegMask(dst->gtRegNum);
- assert(tmpRegsMask != RBM_NONE);
- regMaskTP tmpRegMask = genFindLowestBit(tmpRegsMask); // set tmpRegMsk to a one-bit mask
- extraReg = genRegNumFromMask(tmpRegMask); // set tmpReg from that mask
-
- if (isUnsignedMul)
+ if ((dst->gtFlags & GTF_UNSIGNED) != 0)
{
- if (attr == EA_4BYTE)
- {
- // Compute 8 byte results from 4 byte by 4 byte multiplication.
- emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
+ // Compute 8 byte result from 4 byte by 4 byte multiplication.
+ emitIns_R_R_R_R(INS_umull, EA_4BYTE, dst->gtRegNum, extraReg, src1->gtRegNum, src2->gtRegNum);
- // Get the high result by shifting dst.
- emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
- }
- else
- {
- assert(attr == EA_8BYTE);
- // Compute the high result.
- emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
-
- // Now multiply without skewing the high result.
- emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
- }
-
- // zero-sign bit comparision to detect overflow.
+ // Overflow exists if the result's high word is non-zero.
emitIns_R_I(INS_cmp, attr, extraReg, 0);
}
else
{
- int bitShift = 0;
- if (attr == EA_4BYTE)
- {
- // Compute 8 byte results from 4 byte by 4 byte multiplication.
- emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
-
- // Get the high result by shifting dst.
- emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
-
- bitShift = 31;
- }
- else
- {
- assert(attr == EA_8BYTE);
- // Save the high result in a temporary register.
- emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
-
- // Now multiply without skewing the high result.
- emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
-
- bitShift = 63;
- }
+ // Compute 8 byte result from 4 byte by 4 byte multiplication.
+ emitIns_R_R_R_R(INS_smull, EA_4BYTE, dst->gtRegNum, extraReg, src1->gtRegNum, src2->gtRegNum);
- // Sign bit comparision to detect overflow.
- emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
+ // Overflow exists if the result's high word is not merely a sign bit.
+ emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, 31, INS_FLAGS_DONT_CARE, INS_OPTS_ASR);
}
-#endif
}
else
{
- // We can just multiply.
- emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
+ // We can just do the arithmetic, setting the flags if needed.
+ emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum, flags);
}
}
if (dst->gtOverflowEx())
{
- NYI_ARM("emitInsTernary overflow");
-#if 0
assert(!varTypeIsFloating(dst));
- codeGen->genCheckOverflow(dst);
-#endif
+
+ emitJumpKind jumpKind;
+
+ if (dst->OperGet() == GT_MUL)
+ {
+ jumpKind = EJ_ne;
+ }
+ else
+ {
+ bool isUnsignedOverflow = ((dst->gtFlags & GTF_UNSIGNED) != 0);
+ jumpKind = isUnsignedOverflow ? EJ_lo : EJ_vs;
+ if (jumpKind == EJ_lo)
+ {
+ if ((dst->OperGet() != GT_SUB) && (dst->OperGet() != GT_ASG_SUB) && (dst->OperGet() != GT_SUB_HI))
+ {
+ jumpKind = EJ_hs;
+ }
+ }
+ }
+
+ // Jump to the block which will throw the exception.
+ codeGen->genJumpToThrowHlpBlk(jumpKind, SCK_OVERFLOW);
}
return dst->gtRegNum;