Commit f6496608 authored by ricow@chromium.org's avatar ricow@chromium.org

x64: Add MulI and DivI to lithium instructions.


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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6681 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 2f32f27e
......@@ -1306,10 +1306,10 @@ LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
// the generated code, which requires registers r0
// and r1 to be used. We should remove that
// when we provide a native implementation.
LOperand* value = UseFixed(instr->left(), r0);
LOperand* dividend = UseFixed(instr->left(), r0);
LOperand* divisor = UseFixed(instr->right(), r1);
return AssignEnvironment(AssignPointerMap(
DefineFixed(new LDivI(value, divisor), r0)));
DefineFixed(new LDivI(dividend, divisor), r0)));
} else {
return DoArithmeticT(Token::DIV, instr);
}
......
......@@ -1188,7 +1188,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
__ tst(left, Operand(left));
__ b(ne, &done);
if (instr->InputAt(1)->IsConstantOperand()) {
if (ToInteger32(LConstantOperand::cast(instr->InputAt(1))) < 0) {
if (ToInteger32(LConstantOperand::cast(instr->InputAt(1))) <= 0) {
DeoptimizeIf(kNoCondition, instr->environment());
}
} else {
......
......@@ -804,7 +804,7 @@ void LCodeGen::DoMulI(LMulI* instr) {
__ test(left, Operand(left));
__ j(not_zero, &done);
if (right->IsConstantOperand()) {
if (ToInteger32(LConstantOperand::cast(right)) < 0) {
if (ToInteger32(LConstantOperand::cast(right)) <= 0) {
DeoptimizeIf(no_condition, instr->environment());
}
} else {
......
......@@ -1322,9 +1322,9 @@ LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
// The temporary operand is necessary to ensure that right is not allocated
// into edx.
LOperand* temp = FixedTemp(edx);
LOperand* value = UseFixed(instr->left(), eax);
LOperand* dividend = UseFixed(instr->left(), eax);
LOperand* divisor = UseRegister(instr->right());
LDivI* result = new LDivI(value, divisor, temp);
LDivI* result = new LDivI(dividend, divisor, temp);
return AssignEnvironment(DefineFixed(result, eax));
} else {
ASSERT(instr->representation().IsTagged());
......
......@@ -1188,6 +1188,16 @@ void Assembler::imull(Register dst, Register src) {
}
void Assembler::imull(Register dst, const Operand& src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_optional_rex_32(dst, src);
emit(0x0F);
emit(0xAF);
emit_operand(dst, src);
}
void Assembler::imull(Register dst, Register src, Immediate imm) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
......
......@@ -865,6 +865,7 @@ class Assembler : public Malloced {
void imul(Register dst, Register src, Immediate imm); // dst = src * imm.
// Signed 32-bit multiply instructions.
void imull(Register dst, Register src); // dst = dst * src.
void imull(Register dst, const Operand& src); // dst = dst * src.
void imull(Register dst, Register src, Immediate imm); // dst = src * imm.
void incq(Register dst);
......
......@@ -657,11 +657,92 @@ void LCodeGen::DoModI(LModI* instr) {
void LCodeGen::DoDivI(LDivI* instr) {
Abort("Unimplemented: %s", "DoDivI");}
LOperand* right = instr->InputAt(1);
ASSERT(ToRegister(instr->result()).is(rax));
ASSERT(ToRegister(instr->InputAt(0)).is(rax));
ASSERT(!ToRegister(instr->InputAt(1)).is(rax));
ASSERT(!ToRegister(instr->InputAt(1)).is(rdx));
Register left_reg = rax;
// Check for x / 0.
Register right_reg = ToRegister(right);
if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
__ testl(right_reg, right_reg);
DeoptimizeIf(zero, instr->environment());
}
// Check for (0 / -x) that will produce negative zero.
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
NearLabel left_not_zero;
__ testl(left_reg, left_reg);
__ j(not_zero, &left_not_zero);
__ testl(right_reg, right_reg);
DeoptimizeIf(sign, instr->environment());
__ bind(&left_not_zero);
}
// Check for (-kMinInt / -1).
if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
NearLabel left_not_min_int;
__ cmpl(left_reg, Immediate(kMinInt));
__ j(not_zero, &left_not_min_int);
__ cmpl(right_reg, Immediate(-1));
DeoptimizeIf(zero, instr->environment());
__ bind(&left_not_min_int);
}
// Sign extend to rdx.
__ cdq();
__ idivl(right_reg);
// Deoptimize if remainder is not 0.
__ testl(rdx, rdx);
DeoptimizeIf(not_zero, instr->environment());
}
void LCodeGen::DoMulI(LMulI* instr) {
Abort("Unimplemented: %s", "DoMultI");}
Register left = ToRegister(instr->InputAt(0));
LOperand* right = instr->InputAt(1);
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
__ movl(kScratchRegister, left);
}
if (right->IsConstantOperand()) {
int right_value = ToInteger32(LConstantOperand::cast(right));
__ imull(left, left, Immediate(right_value));
} else if (right->IsStackSlot()) {
__ imull(left, ToOperand(right));
} else {
__ imull(left, ToRegister(right));
}
if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
DeoptimizeIf(overflow, instr->environment());
}
if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
// Bail out if the result is supposed to be negative zero.
NearLabel done;
__ testl(left, left);
__ j(not_zero, &done);
if (right->IsConstantOperand()) {
if (ToInteger32(LConstantOperand::cast(right)) <= 0) {
DeoptimizeIf(no_condition, instr->environment());
}
} else if (right->IsStackSlot()) {
__ or_(kScratchRegister, ToOperand(right));
DeoptimizeIf(sign, instr->environment());
} else {
// Test the non-zero operand for negative sign.
__ or_(kScratchRegister, ToRegister(right));
DeoptimizeIf(sign, instr->environment());
}
__ bind(&done);
}
}
void LCodeGen::DoBitI(LBitI* instr) {
......
......@@ -1264,8 +1264,20 @@ LInstruction* LChunkBuilder::DoBitXor(HBitXor* instr) {
LInstruction* LChunkBuilder::DoDiv(HDiv* instr) {
Abort("Unimplemented: %s", "DoDiv");
return NULL;
if (instr->representation().IsDouble()) {
return DoArithmeticD(Token::DIV, instr);
} else if (instr->representation().IsInteger32()) {
// The temporary operand is necessary to ensure that right is not allocated
// into rdx.
LOperand* temp = FixedTemp(rdx);
LOperand* dividend = UseFixed(instr->left(), rax);
LOperand* divisor = UseRegister(instr->right());
LDivI* result = new LDivI(dividend, divisor, temp);
return AssignEnvironment(DefineFixed(result, rax));
} else {
ASSERT(instr->representation().IsTagged());
return DoArithmeticT(Token::DIV, instr);
}
}
......@@ -1276,8 +1288,19 @@ LInstruction* LChunkBuilder::DoMod(HMod* instr) {
LInstruction* LChunkBuilder::DoMul(HMul* instr) {
Abort("Unimplemented: %s", "DoMul");
return NULL;
if (instr->representation().IsInteger32()) {
ASSERT(instr->left()->representation().IsInteger32());
ASSERT(instr->right()->representation().IsInteger32());
LOperand* left = UseRegisterAtStart(instr->LeastConstantOperand());
LOperand* right = UseOrConstant(instr->MostConstantOperand());
LMulI* mul = new LMulI(left, right);
return AssignEnvironment(DefineSameAsFirst(mul));
} else if (instr->representation().IsDouble()) {
return DoArithmeticD(Token::MUL, instr);
} else {
ASSERT(instr->representation().IsTagged());
return DoArithmeticT(Token::MUL, instr);
}
}
......
......@@ -539,12 +539,11 @@ class LDivI: public LTemplateInstruction<1, 2, 1> {
};
class LMulI: public LTemplateInstruction<1, 2, 1> {
class LMulI: public LTemplateInstruction<1, 2, 0> {
public:
LMulI(LOperand* left, LOperand* right, LOperand* temp) {
LMulI(LOperand* left, LOperand* right) {
inputs_[0] = left;
inputs_[1] = right;
temps_[0] = temp;
}
DECLARE_CONCRETE_INSTRUCTION(MulI, "mul-i")
......
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Test that we actually return the right value (-0) when we multiply
// constant 0 with a negative integer.
function foo(y) {return 0 * y; }
for( var i = 0; i< 1000000; i++){
foo(42);
}
assertEquals(1/foo(-42), -Infinity);
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