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
This commit is contained in:
parent
503bbeb8c4
commit
96127b68e5
@ -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,56 +993,22 @@ 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) {
|
||||
// NOP
|
||||
if (operand_size_ == 0x66) {
|
||||
// 0x66 0x0F prefix.
|
||||
int mod, regop, rm;
|
||||
get_modrm(*current, &mod, ®op, &rm);
|
||||
current++;
|
||||
if (regop == 4) { // SIB byte present.
|
||||
current++;
|
||||
}
|
||||
if (mod == 1) { // Byte displacement.
|
||||
current += 1;
|
||||
} else if (mod == 2) { // 32-bit displacement.
|
||||
current += 4;
|
||||
} // else no immediate displacement.
|
||||
AppendToBuffer("nop");
|
||||
|
||||
} else if (opcode == 0xA2 || opcode == 0x31) {
|
||||
// RDTSC or CPUID
|
||||
AppendToBuffer("%s", mnemonic);
|
||||
|
||||
} else if ((opcode & 0xF0) == 0x40) {
|
||||
// CMOVcc: conditional move.
|
||||
int condition = opcode & 0x0F;
|
||||
const InstructionDesc& idesc = cmov_instructions[condition];
|
||||
byte_size_operand_ = idesc.byte_size_operation;
|
||||
current += PrintOperands(idesc.mnem, idesc.op_order_, current);
|
||||
|
||||
} else if ((opcode & 0xF0) == 0x80) {
|
||||
// Jcc: Conditional jump (branch).
|
||||
current = data + JumpConditional(data);
|
||||
|
||||
} else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 ||
|
||||
opcode == 0xB7 || opcode == 0xAF) {
|
||||
// Size-extending moves, IMUL.
|
||||
current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current);
|
||||
|
||||
} else if ((opcode & 0xF0) == 0x90) {
|
||||
// SETcc: Set byte on condition. Needs pointer to beginning of instruction.
|
||||
current = data + SetCC(data);
|
||||
|
||||
} else if (opcode == 0xAB || opcode == 0xA5 || opcode == 0xAD) {
|
||||
// SHLD, SHRD (double-precision shift), BTS (bit set).
|
||||
AppendToBuffer("%s ", mnemonic);
|
||||
int mod, regop, rm;
|
||||
get_modrm(*current, &mod, ®op, &rm);
|
||||
current += PrintRightOperand(current);
|
||||
if (opcode == 0xAB) {
|
||||
AppendToBuffer(",%s", NameOfCPURegister(regop));
|
||||
const char* mnemonic = "?";
|
||||
if (opcode == 0x57) {
|
||||
mnemonic = "xorpd";
|
||||
} else if (opcode == 0x2E) {
|
||||
mnemonic = "comisd";
|
||||
} else if (opcode == 0x2F) {
|
||||
mnemonic = "ucomisd";
|
||||
} else {
|
||||
AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
|
||||
UnimplementedInstruction();
|
||||
}
|
||||
AppendToBuffer("%s %s,", mnemonic, NameOfXMMRegister(regop));
|
||||
current += PrintRightXMMOperand(current);
|
||||
} else if (group_1_prefix_ == 0xF2) {
|
||||
// Beginning of instructions with prefix 0xF2.
|
||||
|
||||
@ -1080,6 +1046,55 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
|
||||
// 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, ®op, &rm);
|
||||
current++;
|
||||
if (regop == 4) { // SIB byte present.
|
||||
current++;
|
||||
}
|
||||
if (mod == 1) { // Byte displacement.
|
||||
current += 1;
|
||||
} else if (mod == 2) { // 32-bit displacement.
|
||||
current += 4;
|
||||
} // else no immediate displacement.
|
||||
AppendToBuffer("nop");
|
||||
} else if (opcode == 0xA2 || opcode == 0x31) {
|
||||
// RDTSC or CPUID
|
||||
AppendToBuffer("%s", mnemonic);
|
||||
|
||||
} else if ((opcode & 0xF0) == 0x40) {
|
||||
// CMOVcc: conditional move.
|
||||
int condition = opcode & 0x0F;
|
||||
const InstructionDesc& idesc = cmov_instructions[condition];
|
||||
byte_size_operand_ = idesc.byte_size_operation;
|
||||
current += PrintOperands(idesc.mnem, idesc.op_order_, current);
|
||||
|
||||
} else if ((opcode & 0xF0) == 0x80) {
|
||||
// Jcc: Conditional jump (branch).
|
||||
current = data + JumpConditional(data);
|
||||
|
||||
} else if (opcode == 0xBE || opcode == 0xBF || opcode == 0xB6 ||
|
||||
opcode == 0xB7 || opcode == 0xAF) {
|
||||
// Size-extending moves, IMUL.
|
||||
current += PrintOperands(mnemonic, REG_OPER_OP_ORDER, current);
|
||||
|
||||
} else if ((opcode & 0xF0) == 0x90) {
|
||||
// SETcc: Set byte on condition. Needs pointer to beginning of instruction.
|
||||
current = data + SetCC(data);
|
||||
|
||||
} else if (opcode == 0xAB || opcode == 0xA5 || opcode == 0xAD) {
|
||||
// SHLD, SHRD (double-precision shift), BTS (bit set).
|
||||
AppendToBuffer("%s ", mnemonic);
|
||||
int mod, regop, rm;
|
||||
get_modrm(*current, &mod, ®op, &rm);
|
||||
current += PrintRightOperand(current);
|
||||
if (opcode == 0xAB) {
|
||||
AppendToBuffer(",%s", NameOfCPURegister(regop));
|
||||
} else {
|
||||
AppendToBuffer(",%s,cl", NameOfCPURegister(regop));
|
||||
}
|
||||
} else {
|
||||
UnimplementedInstruction();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user