diff options
Diffstat (limited to 'deps/v8/src/compiler/ia32/code-generator-ia32.cc')
-rw-r--r-- | deps/v8/src/compiler/ia32/code-generator-ia32.cc | 208 |
1 files changed, 183 insertions, 25 deletions
diff --git a/deps/v8/src/compiler/ia32/code-generator-ia32.cc b/deps/v8/src/compiler/ia32/code-generator-ia32.cc index 9aef1388118..9d54eaeb909 100644 --- a/deps/v8/src/compiler/ia32/code-generator-ia32.cc +++ b/deps/v8/src/compiler/ia32/code-generator-ia32.cc @@ -16,6 +16,8 @@ #include "src/ia32/assembler-ia32.h" #include "src/ia32/macro-assembler-ia32.h" #include "src/optimized-compilation-info.h" +#include "src/wasm/wasm-code-manager.h" +#include "src/wasm/wasm-objects.h" namespace v8 { namespace internal { @@ -166,6 +168,22 @@ class IA32OperandConverter : public InstructionOperandConverter { Operand MemoryOperand(size_t first_input = 0) { return MemoryOperand(&first_input); } + + Operand NextMemoryOperand(size_t offset = 0) { + AddressingMode mode = AddressingModeField::decode(instr_->opcode()); + Register base = InputRegister(NextOffset(&offset)); + const int32_t disp = 4; + if (mode == kMode_MR1) { + Register index = InputRegister(NextOffset(&offset)); + ScaleFactor scale = ScaleFor(kMode_MR1, kMode_MR1); + return Operand(base, index, scale, disp); + } else if (mode == kMode_MRI) { + Constant ctant = ToConstant(instr_->InputAt(NextOffset(&offset))); + return Operand(base, ctant.ToInt32() + disp, ctant.rmode()); + } else { + UNREACHABLE(); + } + } }; @@ -409,6 +427,23 @@ void EmitWordLoadPoisoningIfNeeded(CodeGenerator* codegen, __ j(not_equal, &binop); \ } while (false) +#define ASSEMBLE_I64ATOMIC_BINOP(instr1, instr2) \ + do { \ + Label binop; \ + __ bind(&binop); \ + __ mov(i.OutputRegister(0), i.MemoryOperand(2)); \ + __ mov(i.OutputRegister(1), i.NextMemoryOperand(2)); \ + __ push(i.InputRegister(0)); \ + __ push(i.InputRegister(1)); \ + __ instr1(i.InputRegister(0), i.OutputRegister(0)); \ + __ instr2(i.InputRegister(1), i.OutputRegister(1)); \ + __ lock(); \ + __ cmpxchg8b(i.MemoryOperand(2)); \ + __ pop(i.InputRegister(1)); \ + __ pop(i.InputRegister(0)); \ + __ j(not_equal, &binop); \ + } while (false); + #define ASSEMBLE_MOVX(mov_instr) \ do { \ if (instr->addressing_mode() != kMode_None) { \ @@ -1152,6 +1187,9 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( case kIA32Popcnt: __ Popcnt(i.OutputRegister(), i.InputOperand(0)); break; + case kIA32Bswap: + __ bswap(i.OutputRegister()); + break; case kArchWordPoisonOnSpeculation: DCHECK_EQ(i.OutputRegister(), i.InputRegister(0)); __ and_(i.InputRegister(0), kSpeculationPoisonRegister); @@ -3594,7 +3632,22 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( case kIA32StackCheck: { ExternalReference const stack_limit = ExternalReference::address_of_stack_limit(__ isolate()); - __ cmp(esp, Operand::StaticVariable(stack_limit)); + __ VerifyRootRegister(); + __ cmp(esp, tasm()->StaticVariable(stack_limit)); + break; + } + case kIA32Word32AtomicPairLoad: { + XMMRegister tmp = i.ToDoubleRegister(instr->TempAt(0)); + __ movq(tmp, i.MemoryOperand()); + __ Pextrd(i.OutputRegister(0), tmp, 0); + __ Pextrd(i.OutputRegister(1), tmp, 1); + break; + } + case kIA32Word32AtomicPairStore: { + __ mov(i.TempRegister(0), i.MemoryOperand(2)); + __ mov(i.TempRegister(1), i.NextMemoryOperand(2)); + __ lock(); + __ cmpxchg8b(i.MemoryOperand(2)); break; } case kWord32AtomicExchangeInt8: { @@ -3621,6 +3674,34 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( __ xchg(i.InputRegister(0), i.MemoryOperand(1)); break; } + // For the narrow Word64 operations below, i.OutputRegister(1) contains + // the high-order 32 bits for the 64bit operation. As the data exchange + // fits in one register, the i.OutputRegister(1) needs to be cleared for + // the correct return value to be propagated back. + case kIA32Word64AtomicNarrowExchangeUint8: { + __ xchg_b(i.OutputRegister(0), i.MemoryOperand(1)); + __ movzx_b(i.OutputRegister(0), i.OutputRegister(0)); + __ xor_(i.OutputRegister(1), i.OutputRegister(1)); + break; + } + case kIA32Word64AtomicNarrowExchangeUint16: { + __ xchg_w(i.OutputRegister(0), i.MemoryOperand(1)); + __ movzx_w(i.OutputRegister(0), i.OutputRegister(0)); + __ xor_(i.OutputRegister(1), i.OutputRegister(1)); + break; + } + case kIA32Word64AtomicNarrowExchangeUint32: { + __ xchg(i.OutputRegister(0), i.MemoryOperand(1)); + __ xor_(i.OutputRegister(1), i.OutputRegister(1)); + break; + } + case kIA32Word32AtomicPairExchange: { + __ mov(i.OutputRegister(0), i.MemoryOperand(2)); + __ mov(i.OutputRegister(1), i.NextMemoryOperand(2)); + __ lock(); + __ cmpxchg8b(i.MemoryOperand(2)); + break; + } case kWord32AtomicCompareExchangeInt8: { __ lock(); __ cmpxchg_b(i.MemoryOperand(2), i.InputRegister(1)); @@ -3650,30 +3731,72 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( __ cmpxchg(i.MemoryOperand(2), i.InputRegister(1)); break; } -#define ATOMIC_BINOP_CASE(op, inst) \ - case kWord32Atomic##op##Int8: { \ - ASSEMBLE_ATOMIC_BINOP(inst, mov_b, cmpxchg_b); \ - __ movsx_b(eax, eax); \ - break; \ - } \ - case kWord32Atomic##op##Uint8: { \ - ASSEMBLE_ATOMIC_BINOP(inst, mov_b, cmpxchg_b); \ - __ movzx_b(eax, eax); \ - break; \ - } \ - case kWord32Atomic##op##Int16: { \ - ASSEMBLE_ATOMIC_BINOP(inst, mov_w, cmpxchg_w); \ - __ movsx_w(eax, eax); \ - break; \ - } \ - case kWord32Atomic##op##Uint16: { \ - ASSEMBLE_ATOMIC_BINOP(inst, mov_w, cmpxchg_w); \ - __ movzx_w(eax, eax); \ - break; \ - } \ - case kWord32Atomic##op##Word32: { \ - ASSEMBLE_ATOMIC_BINOP(inst, mov, cmpxchg); \ - break; \ + case kIA32Word64AtomicNarrowCompareExchangeUint8: { + __ lock(); + __ cmpxchg_b(i.MemoryOperand(2), i.InputRegister(1)); + __ movzx_b(i.OutputRegister(0), i.OutputRegister(0)); + __ xor_(i.OutputRegister(1), i.OutputRegister(1)); + break; + } + case kIA32Word64AtomicNarrowCompareExchangeUint16: { + __ lock(); + __ cmpxchg_w(i.MemoryOperand(2), i.InputRegister(1)); + __ movzx_w(i.OutputRegister(0), i.OutputRegister(0)); + __ xor_(i.OutputRegister(1), i.OutputRegister(1)); + break; + } + case kIA32Word64AtomicNarrowCompareExchangeUint32: { + __ lock(); + __ cmpxchg(i.MemoryOperand(2), i.InputRegister(1)); + __ xor_(i.OutputRegister(1), i.OutputRegister(1)); + break; + } + case kIA32Word32AtomicPairCompareExchange: { + __ lock(); + __ cmpxchg8b(i.MemoryOperand(4)); + break; + } +#define ATOMIC_BINOP_CASE(op, inst) \ + case kWord32Atomic##op##Int8: { \ + ASSEMBLE_ATOMIC_BINOP(inst, mov_b, cmpxchg_b); \ + __ movsx_b(eax, eax); \ + break; \ + } \ + case kIA32Word64AtomicNarrow##op##Uint8: { \ + ASSEMBLE_ATOMIC_BINOP(inst, mov_b, cmpxchg_b); \ + __ movzx_b(i.OutputRegister(0), i.OutputRegister(0)); \ + __ xor_(i.OutputRegister(1), i.OutputRegister(1)); \ + break; \ + } \ + case kWord32Atomic##op##Uint8: { \ + ASSEMBLE_ATOMIC_BINOP(inst, mov_b, cmpxchg_b); \ + __ movzx_b(eax, eax); \ + break; \ + } \ + case kWord32Atomic##op##Int16: { \ + ASSEMBLE_ATOMIC_BINOP(inst, mov_w, cmpxchg_w); \ + __ movsx_w(eax, eax); \ + break; \ + } \ + case kIA32Word64AtomicNarrow##op##Uint16: { \ + ASSEMBLE_ATOMIC_BINOP(inst, mov_w, cmpxchg_w); \ + __ movzx_w(i.OutputRegister(0), i.OutputRegister(0)); \ + __ xor_(i.OutputRegister(1), i.OutputRegister(1)); \ + break; \ + } \ + case kWord32Atomic##op##Uint16: { \ + ASSEMBLE_ATOMIC_BINOP(inst, mov_w, cmpxchg_w); \ + __ movzx_w(eax, eax); \ + break; \ + } \ + case kIA32Word64AtomicNarrow##op##Uint32: { \ + ASSEMBLE_ATOMIC_BINOP(inst, mov, cmpxchg); \ + __ xor_(i.OutputRegister(1), i.OutputRegister(1)); \ + break; \ + } \ + case kWord32Atomic##op##Word32: { \ + ASSEMBLE_ATOMIC_BINOP(inst, mov, cmpxchg); \ + break; \ } ATOMIC_BINOP_CASE(Add, add) ATOMIC_BINOP_CASE(Sub, sub) @@ -3681,6 +3804,40 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ATOMIC_BINOP_CASE(Or, or_) ATOMIC_BINOP_CASE(Xor, xor_) #undef ATOMIC_BINOP_CASE +#define ATOMIC_BINOP_CASE(op, instr1, instr2) \ + case kIA32Word32AtomicPair##op: { \ + ASSEMBLE_I64ATOMIC_BINOP(instr1, instr2) \ + break; \ + } + ATOMIC_BINOP_CASE(Add, add, adc) + ATOMIC_BINOP_CASE(And, and_, and_) + ATOMIC_BINOP_CASE(Or, or_, or_) + ATOMIC_BINOP_CASE(Xor, xor_, xor_) +#undef ATOMIC_BINOP_CASE + case kIA32Word32AtomicPairSub: { + Label binop; + __ bind(&binop); + // Move memory operand into edx:eax + __ mov(i.OutputRegister(0), i.MemoryOperand(2)); + __ mov(i.OutputRegister(1), i.NextMemoryOperand(2)); + // Save input registers temporarily on the stack. + __ push(i.InputRegister(0)); + __ push(i.InputRegister(1)); + // Negate input in place + __ neg(i.InputRegister(0)); + __ adc(i.InputRegister(1), 0); + __ neg(i.InputRegister(1)); + // Add memory operand, negated input. + __ add(i.InputRegister(0), i.OutputRegister(0)); + __ adc(i.InputRegister(1), i.OutputRegister(1)); + __ lock(); + __ cmpxchg8b(i.MemoryOperand(2)); + // Restore input registers + __ pop(i.InputRegister(1)); + __ pop(i.InputRegister(0)); + __ j(not_equal, &binop); + break; + } case kWord32AtomicLoadInt8: case kWord32AtomicLoadUint8: case kWord32AtomicLoadInt16: @@ -4450,6 +4607,7 @@ void CodeGenerator::AssembleJumpTable(Label** targets, size_t target_count) { #undef ASSEMBLE_IEEE754_UNOP #undef ASSEMBLE_BINOP #undef ASSEMBLE_ATOMIC_BINOP +#undef ASSEMBLE_I64ATOMIC_BINOP #undef ASSEMBLE_MOVX #undef ASSEMBLE_SIMD_PUNPCK_SHUFFLE #undef ASSEMBLE_SIMD_IMM_SHUFFLE |