diff --git a/src/x64/assembler-x64.cc b/src/x64/assembler-x64.cc index 1b6874e9a5..8078a94c3a 100644 --- a/src/x64/assembler-x64.cc +++ b/src/x64/assembler-x64.cc @@ -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() }; diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h index 64fbd8887f..c455a26807 100644 --- a/src/x64/assembler-x64.h +++ b/src/x64/assembler-x64.h @@ -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]; } diff --git a/src/x64/codegen-x64.cc b/src/x64/codegen-x64.cc index ef9e493ba6..90a92cc8e4 100644 --- a/src/x64/codegen-x64.cc +++ b/src/x64/codegen-x64.cc @@ -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 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 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); diff --git a/src/x64/codegen-x64.h b/src/x64/codegen-x64.h index 8fbbe5a650..d82682fbf4 100644 --- a/src/x64/codegen-x64.h +++ b/src/x64/codegen-x64.h @@ -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); diff --git a/src/x64/disasm-x64.cc b/src/x64/disasm-x64.cc index ce3aae8a2c..547daeeb17 100644 --- a/src/x64/disasm-x64.cc +++ b/src/x64/disasm-x64.cc @@ -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(); }