| Index: src/x64/assembler-x64.cc
|
| ===================================================================
|
| --- src/x64/assembler-x64.cc (revision 6800)
|
| +++ src/x64/assembler-x64.cc (working copy)
|
| @@ -186,7 +186,21 @@
|
| CPU::FlushICache(pc_, instruction_count);
|
| }
|
|
|
| +
|
| // -----------------------------------------------------------------------------
|
| +// Register constants.
|
| +
|
| +const int Register::registerCodeByAllocationIndex[kNumAllocatableRegisters] = {
|
| + // rax, rbx, rdx, rcx, rdi, r8, r9, r11, r14, r12
|
| + 0, 3, 2, 1, 7, 8, 9, 11, 14, 12
|
| +};
|
| +
|
| +const int Register::allocationIndexByRegisterCode[kNumRegisters] = {
|
| + 0, 3, 2, 1, -1, -1, -1, 4, 5, 6, -1, 7, 9, -1, 8, -1
|
| +};
|
| +
|
| +
|
| +// -----------------------------------------------------------------------------
|
| // Implementation of Operand
|
|
|
| Operand::Operand(Register base, int32_t disp) : rex_(0) {
|
| @@ -286,6 +300,34 @@
|
| }
|
| }
|
|
|
| +
|
| +bool Operand::AddressUsesRegister(Register reg) const {
|
| + int code = reg.code();
|
| + ASSERT((buf_[0] & 0xC0) != 0xC0); // Always a memory operand.
|
| + // Start with only low three bits of base register. Initial decoding doesn't
|
| + // distinguish on the REX.B bit.
|
| + int base_code = buf_[0] & 0x07;
|
| + if (base_code == rsp.code()) {
|
| + // SIB byte present in buf_[1].
|
| + // Check the index register from the SIB byte + REX.X prefix.
|
| + int index_code = ((buf_[1] >> 3) & 0x07) | ((rex_ & 0x02) << 2);
|
| + // Index code (including REX.X) of 0x04 (rsp) means no index register.
|
| + if (index_code != rsp.code() && index_code == code) return true;
|
| + // Add REX.B to get the full base register code.
|
| + base_code = (buf_[1] & 0x07) | ((rex_ & 0x01) << 3);
|
| + // A base register of 0x05 (rbp) with mod = 0 means no base register.
|
| + if (base_code == rbp.code() && ((buf_[0] & 0xC0) == 0)) return false;
|
| + return code == base_code;
|
| + } else {
|
| + // A base register with low bits of 0x05 (rbp or r13) and mod = 0 means
|
| + // no base register.
|
| + if (base_code == rbp.code() && ((buf_[0] & 0xC0) == 0)) return false;
|
| + base_code |= ((rex_ & 0x01) << 3);
|
| + return code == base_code;
|
| + }
|
| +}
|
| +
|
| +
|
| // -----------------------------------------------------------------------------
|
| // Implementation of Assembler.
|
|
|
| @@ -874,6 +916,23 @@
|
| }
|
|
|
|
|
| +// Calls directly to the given address using a relative offset.
|
| +// Should only ever be used in Code objects for calls within the
|
| +// same Code object. Should not be used when generating new code (use labels),
|
| +// but only when patching existing code.
|
| +void Assembler::call(Address target) {
|
| + positions_recorder()->WriteRecordedPositions();
|
| + EnsureSpace ensure_space(this);
|
| + last_pc_ = pc_;
|
| + // 1110 1000 #32-bit disp.
|
| + emit(0xE8);
|
| + Address source = pc_ + 4;
|
| + intptr_t displacement = target - source;
|
| + ASSERT(is_int32(displacement));
|
| + emitl(static_cast<int32_t>(displacement));
|
| +}
|
| +
|
| +
|
| void Assembler::clc() {
|
| EnsureSpace ensure_space(this);
|
| last_pc_ = pc_;
|
| @@ -1129,6 +1188,16 @@
|
| }
|
|
|
|
|
| +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_;
|
| @@ -1935,6 +2004,14 @@
|
| }
|
|
|
|
|
| +void Assembler::push_imm32(int32_t imm32) {
|
| + EnsureSpace ensure_space(this);
|
| + last_pc_ = pc_;
|
| + emit(0x68);
|
| + emitl(imm32);
|
| +}
|
| +
|
| +
|
| void Assembler::pushfq() {
|
| EnsureSpace ensure_space(this);
|
| last_pc_ = pc_;
|
| @@ -2627,6 +2704,30 @@
|
| }
|
|
|
|
|
| +void Assembler::movdqa(const Operand& dst, XMMRegister src) {
|
| + ASSERT(CpuFeatures::IsEnabled(SSE2));
|
| + EnsureSpace ensure_space(this);
|
| + last_pc_ = pc_;
|
| + emit(0x66);
|
| + emit_rex_64(src, dst);
|
| + emit(0x0F);
|
| + emit(0x7F);
|
| + emit_sse_operand(src, dst);
|
| +}
|
| +
|
| +
|
| +void Assembler::movdqa(XMMRegister dst, const Operand& src) {
|
| + ASSERT(CpuFeatures::IsEnabled(SSE2));
|
| + EnsureSpace ensure_space(this);
|
| + last_pc_ = pc_;
|
| + emit(0x66);
|
| + emit_rex_64(dst, src);
|
| + emit(0x0F);
|
| + emit(0x6F);
|
| + emit_sse_operand(dst, src);
|
| +}
|
| +
|
| +
|
| void Assembler::extractps(Register dst, XMMRegister src, byte imm8) {
|
| ASSERT(is_uint2(imm8));
|
| EnsureSpace ensure_space(this);
|
| @@ -2707,6 +2808,17 @@
|
| }
|
|
|
|
|
| +void Assembler::cvttss2si(Register dst, XMMRegister src) {
|
| + EnsureSpace ensure_space(this);
|
| + last_pc_ = pc_;
|
| + emit(0xF3);
|
| + emit_optional_rex_32(dst, src);
|
| + emit(0x0F);
|
| + emit(0x2C);
|
| + emit_sse_operand(dst, src);
|
| +}
|
| +
|
| +
|
| void Assembler::cvttsd2si(Register dst, const Operand& src) {
|
| EnsureSpace ensure_space(this);
|
| last_pc_ = pc_;
|
| @@ -2718,6 +2830,17 @@
|
| }
|
|
|
|
|
| +void Assembler::cvttsd2si(Register dst, XMMRegister src) {
|
| + EnsureSpace ensure_space(this);
|
| + last_pc_ = pc_;
|
| + emit(0xF2);
|
| + emit_optional_rex_32(dst, src);
|
| + emit(0x0F);
|
| + emit(0x2C);
|
| + emit_sse_operand(dst, src);
|
| +}
|
| +
|
| +
|
| void Assembler::cvttsd2siq(Register dst, XMMRegister src) {
|
| EnsureSpace ensure_space(this);
|
| last_pc_ = pc_;
|
| @@ -2916,7 +3039,17 @@
|
| }
|
|
|
|
|
| +void Assembler::movmskpd(Register dst, XMMRegister src) {
|
| + EnsureSpace ensure_space(this);
|
| + last_pc_ = pc_;
|
| + emit(0x66);
|
| + emit_optional_rex_32(dst, src);
|
| + emit(0x0f);
|
| + emit(0x50);
|
| + emit_sse_operand(dst, src);
|
| +}
|
|
|
| +
|
| void Assembler::emit_sse_operand(XMMRegister reg, const Operand& adr) {
|
| Register ireg = { reg.code() };
|
| emit_operand(ireg, adr);
|
| @@ -2936,6 +3069,12 @@
|
| }
|
|
|
|
|
| +void Assembler::db(uint8_t data) {
|
| + EnsureSpace ensure_space(this);
|
| + emit(data);
|
| +}
|
| +
|
| +
|
| void Assembler::dd(uint32_t data) {
|
| EnsureSpace ensure_space(this);
|
| emitl(data);
|
| @@ -2947,10 +3086,15 @@
|
| void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
|
| ASSERT(rmode != RelocInfo::NONE);
|
| // Don't record external references unless the heap will be serialized.
|
| - if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
|
| - !Serializer::enabled() &&
|
| - !FLAG_debug_code) {
|
| - return;
|
| + if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
|
| +#ifdef DEBUG
|
| + if (!Serializer::enabled()) {
|
| + Serializer::TooLateToEnableNow();
|
| + }
|
| +#endif
|
| + if (!Serializer::enabled() && !FLAG_debug_code) {
|
| + return;
|
| + }
|
| }
|
| RelocInfo rinfo(pc_, rmode, data);
|
| reloc_info_writer.Write(&rinfo);
|
|
|