Commit 96127b68 authored by lrn@chromium.org's avatar lrn@chromium.org

Ported ia32 optimization of revision 3487 to x64.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3821 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 503bbeb8
......@@ -2508,6 +2508,38 @@ void Assembler::divsd(XMMRegister dst, XMMRegister src) {
}
void Assembler::xorpd(XMMRegister dst, XMMRegister src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit(0x66);
emit_optional_rex_32(dst, src);
emit(0x0f);
emit(0x57);
emit_sse_operand(dst, src);
}
void Assembler::comisd(XMMRegister dst, XMMRegister src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit(0x66);
emit_optional_rex_32(dst, src);
emit(0x0f);
emit(0x2f);
emit_sse_operand(dst, src);
}
void Assembler::ucomisd(XMMRegister dst, XMMRegister src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit(0x66);
emit_optional_rex_32(dst, src);
emit(0x0f);
emit(0x2e);
emit_sse_operand(dst, src);
}
void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
Register ireg = { reg.code() };
......
......@@ -1122,6 +1122,10 @@ class Assembler : public Malloced {
void mulsd(XMMRegister dst, XMMRegister src);
void divsd(XMMRegister dst, XMMRegister src);
void xorpd(XMMRegister dst, XMMRegister src);
void comisd(XMMRegister dst, XMMRegister src);
void ucomisd(XMMRegister dst, XMMRegister src);
void emit_sse_operand(XMMRegister dst, XMMRegister src);
void emit_sse_operand(XMMRegister reg, const Operand& adr);
......@@ -1168,14 +1172,6 @@ class Assembler : public Malloced {
static const int kMaximalBufferSize = 512*MB;
static const int kMinimalBufferSize = 4*KB;
protected:
// void movsd(XMMRegister dst, const Operand& src);
// void movsd(const Operand& dst, XMMRegister src);
// void emit_sse_operand(XMMRegister reg, const Operand& adr);
// void emit_sse_operand(XMMRegister dst, XMMRegister src);
private:
byte* addr_at(int pos) { return buffer_ + pos; }
byte byte_at(int pos) { return buffer_[pos]; }
......
......@@ -1221,7 +1221,7 @@ void CodeGenerator::VisitSwitchStatement(SwitchStatement* node) {
// Compare and branch to the body if true or the next test if
// false. Prefer the next test as a fall through.
ControlDestination dest(clause->body_target(), &next_test, false);
Comparison(equal, true, &dest);
Comparison(node, equal, true, &dest);
// If the comparison fell through to the true target, jump to the
// actual body.
......@@ -3585,7 +3585,7 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
}
Load(left);
Load(right);
Comparison(cc, strict, destination());
Comparison(node, cc, strict, destination());
}
......@@ -4867,7 +4867,8 @@ void CodeGenerator::LoadTypeofExpression(Expression* expr) {
}
void CodeGenerator::Comparison(Condition cc,
void CodeGenerator::Comparison(AstNode* node,
Condition cc,
bool strict,
ControlDestination* dest) {
// Strict only makes sense for equality comparisons.
......@@ -4914,7 +4915,8 @@ void CodeGenerator::Comparison(Condition cc,
default:
UNREACHABLE();
}
} else { // Only one side is a constant Smi.
} else {
// Only one side is a constant Smi.
// If left side is a constant Smi, reverse the operands.
// Since one side is a constant Smi, conversion order does not matter.
if (left_side_constant_smi) {
......@@ -4928,6 +4930,8 @@ void CodeGenerator::Comparison(Condition cc,
// Implement comparison against a constant Smi, inlining the case
// where both sides are Smis.
left_side.ToRegister();
Register left_reg = left_side.reg();
Handle<Object> right_val = right_side.handle();
// Here we split control flow to the stub call and inlined cases
// before finally splitting it to the control destination. We use
......@@ -4935,12 +4939,48 @@ void CodeGenerator::Comparison(Condition cc,
// the first split. We manually handle the off-frame references
// by reconstituting them on the non-fall-through path.
JumpTarget is_smi;
Register left_reg = left_side.reg();
Handle<Object> right_val = right_side.handle();
Condition left_is_smi = masm_->CheckSmi(left_side.reg());
is_smi.Branch(left_is_smi);
bool is_for_loop_compare = (node->AsCompareOperation() != NULL)
&& node->AsCompareOperation()->is_for_loop_condition();
if (!is_for_loop_compare && right_val->IsSmi()) {
// Right side is a constant smi and left side has been checked
// not to be a smi.
JumpTarget not_number;
__ Cmp(FieldOperand(left_reg, HeapObject::kMapOffset),
Factory::heap_number_map());
not_number.Branch(not_equal, &left_side);
__ movsd(xmm1,
FieldOperand(left_reg, HeapNumber::kValueOffset));
int value = Smi::cast(*right_val)->value();
if (value == 0) {
__ xorpd(xmm0, xmm0);
} else {
Result temp = allocator()->Allocate();
__ movl(temp.reg(), Immediate(value));
__ cvtlsi2sd(xmm0, temp.reg());
temp.Unuse();
}
__ ucomisd(xmm1, xmm0);
// Jump to builtin for NaN.
not_number.Branch(parity_even, &left_side);
left_side.Unuse();
Condition double_cc = cc;
switch (cc) {
case less: double_cc = below; break;
case equal: double_cc = equal; break;
case less_equal: double_cc = below_equal; break;
case greater: double_cc = above; break;
case greater_equal: double_cc = above_equal; break;
default: UNREACHABLE();
}
dest->true_target()->Branch(double_cc);
dest->false_target()->Jump();
not_number.Bind(&left_side);
}
// Setup and call the compare stub.
CompareStub stub(cc, strict);
Result result = frame_->CallStub(&stub, &left_side, &right_side);
......
......@@ -484,7 +484,8 @@ class CodeGenerator: public AstVisitor {
Result* right,
OverwriteMode overwrite_mode);
void Comparison(Condition cc,
void Comparison(AstNode* node,
Condition cc,
bool strict,
ControlDestination* destination);
......
......@@ -993,7 +993,60 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
byte* current = data + 2;
// At return, "current" points to the start of the next instruction.
const char* mnemonic = TwoByteMnemonic(opcode);
if (opcode == 0x1F) {
if (operand_size_ == 0x66) {
// 0x66 0x0F prefix.
int mod, regop, rm;
get_modrm(*current, &mod, &regop, &rm);
const char* mnemonic = "?";
if (opcode == 0x57) {
mnemonic = "xorpd";
} else if (opcode == 0x2E) {
mnemonic = "comisd";
} else if (opcode == 0x2F) {
mnemonic = "ucomisd";
} else {
UnimplementedInstruction();
}
AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
current += PrintRightXMMOperand(current);
} else if (group_1_prefix_ == 0xF2) {
// Beginning of instructions with prefix 0xF2.
if (opcode == 0x11 || opcode == 0x10) {
// MOVSD: Move scalar double-precision fp to/from/between XMM registers.
AppendToBuffer("movsd ");
int mod, regop, rm;
get_modrm(*current, &mod, &regop, &rm);
if (opcode == 0x11) {
current += PrintRightOperand(current);
AppendToBuffer(",%s", NameOfXMMRegister(regop));
} else {
AppendToBuffer("%s,", NameOfXMMRegister(regop));
current += PrintRightOperand(current);
}
} else if (opcode == 0x2A) {
// CVTSI2SD: integer to XMM double conversion.
int mod, regop, rm;
get_modrm(*current, &mod, &regop, &rm);
AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
current += PrintRightOperand(current);
} else if ((opcode & 0xF8) == 0x58) {
// XMM arithmetic. Mnemonic was retrieved at the start of this function.
int mod, regop, rm;
get_modrm(*current, &mod, &regop, &rm);
AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
current += PrintRightXMMOperand(current);
} else {
UnimplementedInstruction();
}
} else if (opcode == 0x2C && group_1_prefix_ == 0xF3) {
// Instruction with prefix 0xF3.
// CVTTSS2SI: Convert scalar single-precision FP to dword integer.
// Assert that mod is not 3, so source is memory, not an XMM register.
ASSERT_NE(0xC0, *current & 0xC0);
current += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, current);
} else if (opcode == 0x1F) {
// NOP
int mod, regop, rm;
get_modrm(*current, &mod, &regop, &rm);
......@@ -1007,8 +1060,7 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
current += 4;
} // else no immediate displacement.
AppendToBuffer("nop");
} else if (opcode == 0xA2 || opcode == 0x31) {
} else if (opcode == 0xA2 || opcode == 0x31) {
// RDTSC or CPUID
AppendToBuffer("%s", mnemonic);
......@@ -1043,43 +1095,6 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
} else {
AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
}
} else if (group_1_prefix_ == 0xF2) {
// Beginning of instructions with prefix 0xF2.
if (opcode == 0x11 || opcode == 0x10) {
// MOVSD: Move scalar double-precision fp to/from/between XMM registers.
AppendToBuffer("movsd ");
int mod, regop, rm;
get_modrm(*current, &mod, &regop, &rm);
if (opcode == 0x11) {
current += PrintRightOperand(current);
AppendToBuffer(",%s", NameOfXMMRegister(regop));
} else {
AppendToBuffer("%s,", NameOfXMMRegister(regop));
current += PrintRightOperand(current);
}
} else if (opcode == 0x2A) {
// CVTSI2SD: integer to XMM double conversion.
int mod, regop, rm;
get_modrm(*current, &mod, &regop, &rm);
AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
current += PrintRightOperand(current);
} else if ((opcode & 0xF8) == 0x58) {
// XMM arithmetic. Mnemonic was retrieved at the start of this function.
int mod, regop, rm;
get_modrm(*current, &mod, &regop, &rm);
AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
current += PrintRightXMMOperand(current);
} else {
UnimplementedInstruction();
}
} else if (opcode == 0x2C && group_1_prefix_ == 0xF3) {
// Instruction with prefix 0xF3.
// CVTTSS2SI: Convert scalar single-precision FP to dword integer.
// Assert that mod is not 3, so source is memory, not an XMM register.
ASSERT_NE(0xC0, *current & 0xC0);
current += PrintOperands("cvttss2si", REG_OPER_OP_ORDER, current);
} else {
UnimplementedInstruction();
}
......
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