Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/ia32/code-generator-ia32.cc')
-rw-r--r--deps/v8/src/compiler/ia32/code-generator-ia32.cc208
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