Commit e1448ebd authored by whesse@chromium.org's avatar whesse@chromium.org

X64 Crankshaft: Add ModI and ModT to x64 optimizing compiler.

Review URL: http://codereview.chromium.org/6548005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6863 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ea0dda89
......@@ -683,7 +683,42 @@ void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
void LCodeGen::DoModI(LModI* instr) {
Abort("Unimplemented: %s", "DoModI");
LOperand* right = instr->InputAt(1);
ASSERT(ToRegister(instr->result()).is(rdx));
ASSERT(ToRegister(instr->InputAt(0)).is(rax));
ASSERT(!ToRegister(instr->InputAt(1)).is(rax));
ASSERT(!ToRegister(instr->InputAt(1)).is(rdx));
Register right_reg = ToRegister(right);
// Check for x % 0.
if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
__ testl(right_reg, right_reg);
DeoptimizeIf(zero, instr->environment());
}
// Sign extend eax to edx. (We are using only the low 32 bits of the values.)
__ cdq();
// Check for (0 % -x) that will produce negative zero.
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
NearLabel positive_left;
NearLabel done;
__ testl(rax, rax);
__ j(not_sign, &positive_left);
__ idivl(right_reg);
// Test the remainder for 0, because then the result would be -0.
__ testl(rdx, rdx);
__ j(not_zero, &done);
DeoptimizeIf(no_condition, instr->environment());
__ bind(&positive_left);
__ idivl(right_reg);
__ bind(&done);
} else {
__ idivl(right_reg);
}
}
......
......@@ -1318,8 +1318,32 @@ LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
LInstruction* LChunkBuilder::DoMod(HMod* instr) {
Abort("Unimplemented: %s", "DoMod");
return NULL;
if (instr->representation().IsInteger32()) {
ASSERT(instr->left()->representation().IsInteger32());
ASSERT(instr->right()->representation().IsInteger32());
// The temporary operand is necessary to ensure that right is not allocated
// into edx.
LOperand* temp = FixedTemp(rdx);
LOperand* value = UseFixed(instr->left(), rax);
LOperand* divisor = UseRegister(instr->right());
LModI* mod = new LModI(value, divisor, temp);
LInstruction* result = DefineFixed(mod, rdx);
return (instr->CheckFlag(HValue::kBailoutOnMinusZero) ||
instr->CheckFlag(HValue::kCanBeDivByZero))
? AssignEnvironment(result)
: result;
} else if (instr->representation().IsTagged()) {
return DoArithmeticT(Token::MOD, instr);
} else {
ASSERT(instr->representation().IsDouble());
// We call a C function for double modulo. It can't trigger a GC.
// We need to use fixed result register for the call.
// TODO(fschneider): Allow any register as input registers.
LOperand* left = UseFixedDouble(instr->left(), xmm1);
LOperand* right = UseFixedDouble(instr->right(), xmm2);
LArithmeticD* result = new LArithmeticD(Token::MOD, left, right);
return MarkAsCall(DefineFixedDouble(result, xmm1), instr);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment