diff options
Diffstat (limited to 'deps/v8/src/ia32/assembler-ia32.cc')
-rw-r--r-- | deps/v8/src/ia32/assembler-ia32.cc | 258 |
1 files changed, 187 insertions, 71 deletions
diff --git a/deps/v8/src/ia32/assembler-ia32.cc b/deps/v8/src/ia32/assembler-ia32.cc index 999647487e..bb050b63f9 100644 --- a/deps/v8/src/ia32/assembler-ia32.cc +++ b/deps/v8/src/ia32/assembler-ia32.cc @@ -55,6 +55,8 @@ uint64_t CpuFeatures::supported_ = 0; uint64_t CpuFeatures::found_by_runtime_probing_ = 0; +// The Probe method needs executable memory, so it uses Heap::CreateCode. +// Allocation failure is silent and leads to safe default. void CpuFeatures::Probe() { ASSERT(!initialized_); ASSERT(supported_ == 0); @@ -86,23 +88,23 @@ void CpuFeatures::Probe() { __ pushfd(); __ push(ecx); __ push(ebx); - __ mov(ebp, Operand(esp)); + __ mov(ebp, esp); // If we can modify bit 21 of the EFLAGS register, then CPUID is supported. __ pushfd(); __ pop(eax); - __ mov(edx, Operand(eax)); + __ mov(edx, eax); __ xor_(eax, 0x200000); // Flip bit 21. __ push(eax); __ popfd(); __ pushfd(); __ pop(eax); - __ xor_(eax, Operand(edx)); // Different if CPUID is supported. + __ xor_(eax, edx); // Different if CPUID is supported. __ j(not_zero, &cpuid); // CPUID not supported. Clear the supported features in edx:eax. - __ xor_(eax, Operand(eax)); - __ xor_(edx, Operand(edx)); + __ xor_(eax, eax); + __ xor_(edx, edx); __ jmp(&done); // Invoke CPUID with 1 in eax to get feature information in @@ -118,13 +120,13 @@ void CpuFeatures::Probe() { // Move the result from ecx:edx to edx:eax and make sure to mark the // CPUID feature as supported. - __ mov(eax, Operand(edx)); + __ mov(eax, edx); __ or_(eax, 1 << CPUID); - __ mov(edx, Operand(ecx)); + __ mov(edx, ecx); // Done. __ bind(&done); - __ mov(esp, Operand(ebp)); + __ mov(esp, ebp); __ pop(ebx); __ pop(ecx); __ popfd(); @@ -286,6 +288,18 @@ bool Operand::is_reg(Register reg) const { && ((buf_[0] & 0x07) == reg.code()); // register codes match. } + +bool Operand::is_reg_only() const { + return (buf_[0] & 0xF8) == 0xC0; // Addressing mode is register only. +} + + +Register Operand::reg() const { + ASSERT(is_reg_only()); + return Register::from_code(buf_[0] & 0x07); +} + + // ----------------------------------------------------------------------------- // Implementation of Assembler. @@ -336,7 +350,7 @@ Assembler::Assembler(Isolate* arg_isolate, void* buffer, int buffer_size) } #endif - // Setup buffer pointers. + // Set up buffer pointers. ASSERT(buffer_ != NULL); pc_ = buffer_; reloc_info_writer.Reposition(buffer_ + buffer_size, pc_); @@ -363,7 +377,7 @@ void Assembler::GetCode(CodeDesc* desc) { // Finalize code (at this point overflow() may be true, but the gap ensures // that we are still not overlapping instructions and relocation info). ASSERT(pc_ <= reloc_info_writer.pos()); // No overlap. - // Setup code descriptor. + // Set up code descriptor. desc->buffer = buffer_; desc->buffer_size = buffer_size_; desc->instr_size = pc_offset(); @@ -374,8 +388,91 @@ void Assembler::GetCode(CodeDesc* desc) { void Assembler::Align(int m) { ASSERT(IsPowerOf2(m)); - while ((pc_offset() & (m - 1)) != 0) { - nop(); + int mask = m - 1; + int addr = pc_offset(); + Nop((m - (addr & mask)) & mask); +} + + +bool Assembler::IsNop(Address addr) { + Address a = addr; + while (*a == 0x66) a++; + if (*a == 0x90) return true; + if (a[0] == 0xf && a[1] == 0x1f) return true; + return false; +} + + +void Assembler::Nop(int bytes) { + EnsureSpace ensure_space(this); + + if (!CpuFeatures::IsSupported(SSE2)) { + // Older CPUs that do not support SSE2 may not support multibyte NOP + // instructions. + for (; bytes > 0; bytes--) { + EMIT(0x90); + } + return; + } + + // Multi byte nops from http://support.amd.com/us/Processor_TechDocs/40546.pdf + while (bytes > 0) { + switch (bytes) { + case 2: + EMIT(0x66); + case 1: + EMIT(0x90); + return; + case 3: + EMIT(0xf); + EMIT(0x1f); + EMIT(0); + return; + case 4: + EMIT(0xf); + EMIT(0x1f); + EMIT(0x40); + EMIT(0); + return; + case 6: + EMIT(0x66); + case 5: + EMIT(0xf); + EMIT(0x1f); + EMIT(0x44); + EMIT(0); + EMIT(0); + return; + case 7: + EMIT(0xf); + EMIT(0x1f); + EMIT(0x80); + EMIT(0); + EMIT(0); + EMIT(0); + EMIT(0); + return; + default: + case 11: + EMIT(0x66); + bytes--; + case 10: + EMIT(0x66); + bytes--; + case 9: + EMIT(0x66); + bytes--; + case 8: + EMIT(0xf); + EMIT(0x1f); + EMIT(0x84); + EMIT(0); + EMIT(0); + EMIT(0); + EMIT(0); + EMIT(0); + bytes -= 8; + } } } @@ -449,13 +546,6 @@ void Assembler::push(const Operand& src) { } -void Assembler::push(Handle<Object> handle) { - EnsureSpace ensure_space(this); - EMIT(0x68); - emit(handle); -} - - void Assembler::pop(Register dst) { ASSERT(reloc_info_writer.last_pc() != NULL); EnsureSpace ensure_space(this); @@ -614,26 +704,6 @@ void Assembler::movzx_w(Register dst, const Operand& src) { } -void Assembler::cmov(Condition cc, Register dst, int32_t imm32) { - ASSERT(CpuFeatures::IsEnabled(CMOV)); - EnsureSpace ensure_space(this); - UNIMPLEMENTED(); - USE(cc); - USE(dst); - USE(imm32); -} - - -void Assembler::cmov(Condition cc, Register dst, Handle<Object> handle) { - ASSERT(CpuFeatures::IsEnabled(CMOV)); - EnsureSpace ensure_space(this); - UNIMPLEMENTED(); - USE(cc); - USE(dst); - USE(handle); -} - - void Assembler::cmov(Condition cc, Register dst, const Operand& src) { ASSERT(CpuFeatures::IsEnabled(CMOV)); EnsureSpace ensure_space(this); @@ -701,6 +771,13 @@ void Assembler::add(Register dst, const Operand& src) { } +void Assembler::add(const Operand& dst, Register src) { + EnsureSpace ensure_space(this); + EMIT(0x01); + emit_operand(src, dst); +} + + void Assembler::add(const Operand& dst, const Immediate& x) { ASSERT(reloc_info_writer.last_pc() != NULL); EnsureSpace ensure_space(this); @@ -741,25 +818,29 @@ void Assembler::and_(const Operand& dst, Register src) { void Assembler::cmpb(const Operand& op, int8_t imm8) { EnsureSpace ensure_space(this); - EMIT(0x80); - emit_operand(edi, op); // edi == 7 + if (op.is_reg(eax)) { + EMIT(0x3C); + } else { + EMIT(0x80); + emit_operand(edi, op); // edi == 7 + } EMIT(imm8); } -void Assembler::cmpb(const Operand& dst, Register src) { - ASSERT(src.is_byte_register()); +void Assembler::cmpb(const Operand& op, Register reg) { + ASSERT(reg.is_byte_register()); EnsureSpace ensure_space(this); EMIT(0x38); - emit_operand(src, dst); + emit_operand(reg, op); } -void Assembler::cmpb(Register dst, const Operand& src) { - ASSERT(dst.is_byte_register()); +void Assembler::cmpb(Register reg, const Operand& op) { + ASSERT(reg.is_byte_register()); EnsureSpace ensure_space(this); EMIT(0x3A); - emit_operand(dst, src); + emit_operand(reg, op); } @@ -1069,18 +1150,6 @@ void Assembler::shr_cl(Register dst) { } -void Assembler::subb(const Operand& op, int8_t imm8) { - EnsureSpace ensure_space(this); - if (op.is_reg(eax)) { - EMIT(0x2c); - } else { - EMIT(0x80); - emit_operand(ebp, op); // ebp == 5 - } - EMIT(imm8); -} - - void Assembler::sub(const Operand& dst, const Immediate& x) { EnsureSpace ensure_space(this); emit_arith(5, dst, x); @@ -1094,14 +1163,6 @@ void Assembler::sub(Register dst, const Operand& src) { } -void Assembler::subb(Register dst, const Operand& src) { - ASSERT(dst.code() < 4); - EnsureSpace ensure_space(this); - EMIT(0x2A); - emit_operand(dst, src); -} - - void Assembler::sub(const Operand& dst, Register src) { EnsureSpace ensure_space(this); EMIT(0x29); @@ -1158,6 +1219,10 @@ void Assembler::test(const Operand& op, const Immediate& imm) { void Assembler::test_b(const Operand& op, uint8_t imm8) { + if (op.is_reg_only() && op.reg().code() >= 4) { + test(op, Immediate(imm8)); + return; + } EnsureSpace ensure_space(this); EMIT(0xF6); emit_operand(eax, op); @@ -1178,10 +1243,10 @@ void Assembler::xor_(Register dst, const Operand& src) { } -void Assembler::xor_(const Operand& src, Register dst) { +void Assembler::xor_(const Operand& dst, Register src) { EnsureSpace ensure_space(this); EMIT(0x31); - emit_operand(dst, src); + emit_operand(src, dst); } @@ -1637,6 +1702,13 @@ void Assembler::fsin() { } +void Assembler::fptan() { + EnsureSpace ensure_space(this); + EMIT(0xD9); + EMIT(0xF2); +} + + void Assembler::fyl2x() { EnsureSpace ensure_space(this); EMIT(0xD9); @@ -1644,6 +1716,27 @@ void Assembler::fyl2x() { } +void Assembler::f2xm1() { + EnsureSpace ensure_space(this); + EMIT(0xD9); + EMIT(0xF0); +} + + +void Assembler::fscale() { + EnsureSpace ensure_space(this); + EMIT(0xD9); + EMIT(0xFD); +} + + +void Assembler::fninit() { + EnsureSpace ensure_space(this); + EMIT(0xDB); + EMIT(0xE3); +} + + void Assembler::fadd(int i) { EnsureSpace ensure_space(this); emit_farith(0xDC, 0xC0, i); @@ -1957,6 +2050,16 @@ void Assembler::ucomisd(XMMRegister dst, XMMRegister src) { } +void Assembler::ucomisd(XMMRegister dst, const Operand& src) { + ASSERT(CpuFeatures::IsEnabled(SSE2)); + EnsureSpace ensure_space(this); + EMIT(0x66); + EMIT(0x0F); + EMIT(0x2E); + emit_sse_operand(dst, src); +} + + void Assembler::roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode) { ASSERT(CpuFeatures::IsEnabled(SSE4_1)); EnsureSpace ensure_space(this); @@ -2162,6 +2265,19 @@ void Assembler::movd(const Operand& dst, XMMRegister src) { } +void Assembler::extractps(Register dst, XMMRegister src, byte imm8) { + ASSERT(CpuFeatures::IsSupported(SSE4_1)); + ASSERT(is_uint8(imm8)); + EnsureSpace ensure_space(this); + EMIT(0x66); + EMIT(0x0F); + EMIT(0x3A); + EMIT(0x17); + emit_sse_operand(dst, src); + EMIT(imm8); +} + + void Assembler::pand(XMMRegister dst, XMMRegister src) { ASSERT(CpuFeatures::IsEnabled(SSE2)); EnsureSpace ensure_space(this); @@ -2341,7 +2457,7 @@ void Assembler::GrowBuffer() { V8::FatalProcessOutOfMemory("Assembler::GrowBuffer"); } - // Setup new buffer. + // Set up new buffer. desc.buffer = NewArray<byte>(desc.buffer_size); desc.instr_size = pc_offset(); desc.reloc_size = (buffer_ + buffer_size_) - (reloc_info_writer.pos()); @@ -2471,7 +2587,7 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { return; } } - RelocInfo rinfo(pc_, rmode, data); + RelocInfo rinfo(pc_, rmode, data, NULL); reloc_info_writer.Write(&rinfo); } |