From 8fe01fea4e1d7591645f89fb155a6a6bd89ed3b4 Mon Sep 17 00:00:00 2001 From: Deepti Gandluri Date: Fri, 24 Aug 2018 18:32:25 -0700 Subject: [PATCH] [arm] Implement I64Atomic operations on Arm - Implement all the I64Atomic operations on ARM - Change assembler methods to use Registers instead of memory operands - Move atomics64 test up be tested on all archs, disable tests on MIPS BUG:v8:6532 Change-Id: I91bd42fa819f194be15c719266c36230f9c65db8 Reviewed-on: https://chromium-review.googlesource.com/1180211 Commit-Queue: Deepti Gandluri Reviewed-by: Bill Budge Reviewed-by: Ben Smith Cr-Commit-Position: refs/heads/master@{#55416} --- src/arm/assembler-arm.cc | 12 +- src/arm/assembler-arm.h | 5 +- src/compiler/arm/code-generator-arm.cc | 131 ++++- src/compiler/arm/instruction-codes-arm.h | 548 +++++++++--------- src/compiler/arm/instruction-scheduler-arm.cc | 30 + src/compiler/arm/instruction-selector-arm.cc | 224 +++++++ src/compiler/instruction-selector.cc | 4 +- test/cctest/BUILD.gn | 4 +- test/cctest/cctest.status | 6 + test/cctest/test-disasm-arm.cc | 4 +- 10 files changed, 691 insertions(+), 277 deletions(-) diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc index 2e2909f30e..163fa4c219 100644 --- a/src/arm/assembler-arm.cc +++ b/src/arm/assembler-arm.cc @@ -2240,29 +2240,27 @@ void Assembler::strexh(Register src1, Register src2, Register dst, 0xF9 * B4 | src2.code()); } -void Assembler::ldrexd(Register dst1, Register dst2, const MemOperand& src, +void Assembler::ldrexd(Register dst1, Register dst2, Register src, Condition cond) { // cond(31-28) | 00011011(27-20) | Rn(19-16) | Rt(15-12) | 111110011111(11-0) - DCHECK(src.rm() == no_reg); DCHECK(dst1 != lr); // r14. // The pair of destination registers is restricted to being an even-numbered // register and the odd-numbered register that immediately follows it. DCHECK_EQ(0, dst1.code() % 2); DCHECK_EQ(dst1.code() + 1, dst2.code()); - emit(cond | B24 | B23 | B21 | B20 | src.rn_.code() * B16 | dst1.code() * B12 | + emit(cond | B24 | B23 | B21 | B20 | src.code() * B16 | dst1.code() * B12 | 0xF9F); } -void Assembler::strexd(Register res, Register src1, Register src2, - const MemOperand& dst, Condition cond) { +void Assembler::strexd(Register res, Register src1, Register src2, Register dst, + Condition cond) { // cond(31-28) | 00011010(27-20) | Rn(19-16) | Rt(15-12) | 111110011111(11-0) - DCHECK(dst.rm() == no_reg); DCHECK(src1 != lr); // r14. // The pair of source registers is restricted to being an even-numbered // register and the odd-numbered register that immediately follows it. DCHECK_EQ(0, src1.code() % 2); DCHECK_EQ(src1.code() + 1, src2.code()); - emit(cond | B24 | B23 | B21 | dst.rn_.code() * B16 | res.code() * B12 | + emit(cond | B24 | B23 | B21 | dst.code() * B16 | res.code() * B12 | 0xF9 * B4 | src1.code()); } diff --git a/src/arm/assembler-arm.h b/src/arm/assembler-arm.h index 6e6da1e4c0..fb36702882 100644 --- a/src/arm/assembler-arm.h +++ b/src/arm/assembler-arm.h @@ -930,9 +930,8 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase { void strexb(Register src1, Register src2, Register dst, Condition cond = al); void ldrexh(Register dst, Register src, Condition cond = al); void strexh(Register src1, Register src2, Register dst, Condition cond = al); - void ldrexd(Register dst1, Register dst2, const MemOperand& src, - Condition cond = al); - void strexd(Register res, Register src1, Register src2, const MemOperand& dst, + void ldrexd(Register dst1, Register dst2, Register src, Condition cond = al); + void strexd(Register res, Register src1, Register src2, Register dst, Condition cond = al); // Preload instructions diff --git a/src/compiler/arm/code-generator-arm.cc b/src/compiler/arm/code-generator-arm.cc index ebcf503c96..8e1c1ab8f4 100644 --- a/src/compiler/arm/code-generator-arm.cc +++ b/src/compiler/arm/code-generator-arm.cc @@ -416,6 +416,48 @@ void ComputePoisonedAddressForLoad(CodeGenerator* codegen, __ dmb(ISH); \ } while (0) +#define ASSEMBLE_ATOMIC64_ARITH_BINOP(instr1, instr2) \ + do { \ + Label binop; \ + __ add(i.TempRegister(0), i.InputRegister(2), i.InputRegister(3)); \ + __ dmb(ISH); \ + __ bind(&binop); \ + __ ldrexd(i.OutputRegister(0), i.OutputRegister(1), i.TempRegister(0)); \ + __ instr1(i.TempRegister(1), i.OutputRegister(0), i.InputRegister(0), \ + SBit::SetCC); \ + __ instr2(i.TempRegister(2), i.OutputRegister(1), \ + Operand(i.InputRegister(1))); \ + DCHECK_EQ(LeaveCC, i.OutputSBit()); \ + __ strexd(i.TempRegister(3), i.TempRegister(1), i.TempRegister(2), \ + i.TempRegister(0)); \ + __ teq(i.TempRegister(3), Operand(0)); \ + __ b(ne, &binop); \ + __ dmb(ISH); \ + } while (0) + +#define ASSEMBLE_ATOMIC64_LOGIC_BINOP(instr) \ + do { \ + Label binop; \ + __ add(i.TempRegister(0), i.InputRegister(2), i.InputRegister(3)); \ + __ dmb(ISH); \ + __ bind(&binop); \ + __ ldrexd(i.OutputRegister(0), i.OutputRegister(1), i.TempRegister(0)); \ + __ instr(i.TempRegister(1), i.OutputRegister(0), \ + Operand(i.InputRegister(0))); \ + __ instr(i.TempRegister(2), i.OutputRegister(1), \ + Operand(i.InputRegister(1))); \ + __ strexd(i.TempRegister(3), i.TempRegister(1), i.TempRegister(2), \ + i.TempRegister(0)); \ + __ teq(i.TempRegister(3), Operand(0)); \ + __ b(ne, &binop); \ + __ dmb(ISH); \ + } while (0) + +#define ATOMIC_NARROW_OP_CLEAR_HIGH_WORD(op) \ + if (arch_opcode == kArmWord64AtomicNarrow##op) { \ + __ mov(i.OutputRegister(1), Operand(0)); \ + } + #define ASSEMBLE_IEEE754_BINOP(name) \ do { \ /* TODO(bmeurer): We should really get rid of this special instruction, */ \ @@ -2628,7 +2670,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( case kWord32AtomicLoadWord32: ASSEMBLE_ATOMIC_LOAD_INTEGER(ldr); break; - case kWord32AtomicStoreWord8: ASSEMBLE_ATOMIC_STORE_INTEGER(strb); break; @@ -2643,17 +2684,23 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( __ sxtb(i.OutputRegister(0), i.OutputRegister(0)); break; case kWord32AtomicExchangeUint8: + case kArmWord64AtomicNarrowExchangeUint8: ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(ldrexb, strexb); + ATOMIC_NARROW_OP_CLEAR_HIGH_WORD(ExchangeUint8); break; case kWord32AtomicExchangeInt16: ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(ldrexh, strexh); __ sxth(i.OutputRegister(0), i.OutputRegister(0)); break; case kWord32AtomicExchangeUint16: + case kArmWord64AtomicNarrowExchangeUint16: ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(ldrexh, strexh); + ATOMIC_NARROW_OP_CLEAR_HIGH_WORD(ExchangeUint16); break; case kWord32AtomicExchangeWord32: + case kArmWord64AtomicNarrowExchangeUint32: ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(ldrex, strex); + ATOMIC_NARROW_OP_CLEAR_HIGH_WORD(ExchangeUint32); break; case kWord32AtomicCompareExchangeInt8: __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); @@ -2663,10 +2710,12 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( __ sxtb(i.OutputRegister(0), i.OutputRegister(0)); break; case kWord32AtomicCompareExchangeUint8: + case kArmWord64AtomicNarrowCompareExchangeUint8: __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); __ uxtb(i.TempRegister(2), i.InputRegister(2)); ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexb, strexb, i.TempRegister(2)); + ATOMIC_NARROW_OP_CLEAR_HIGH_WORD(CompareExchangeUint8); break; case kWord32AtomicCompareExchangeInt16: __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); @@ -2676,15 +2725,19 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( __ sxth(i.OutputRegister(0), i.OutputRegister(0)); break; case kWord32AtomicCompareExchangeUint16: + case kArmWord64AtomicNarrowCompareExchangeUint16: __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); __ uxth(i.TempRegister(2), i.InputRegister(2)); ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexh, strexh, i.TempRegister(2)); + ATOMIC_NARROW_OP_CLEAR_HIGH_WORD(CompareExchangeUint16); break; case kWord32AtomicCompareExchangeWord32: + case kArmWord64AtomicNarrowCompareExchangeUint32: __ add(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1)); ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrex, strex, i.InputRegister(2)); + ATOMIC_NARROW_OP_CLEAR_HIGH_WORD(CompareExchangeUint32); break; #define ATOMIC_BINOP_CASE(op, inst) \ case kWord32Atomic##op##Int8: \ @@ -2692,17 +2745,23 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( __ sxtb(i.OutputRegister(0), i.OutputRegister(0)); \ break; \ case kWord32Atomic##op##Uint8: \ + case kArmWord64AtomicNarrow##op##Uint8: \ ASSEMBLE_ATOMIC_BINOP(ldrexb, strexb, inst); \ + ATOMIC_NARROW_OP_CLEAR_HIGH_WORD(op##Uint8); \ break; \ case kWord32Atomic##op##Int16: \ ASSEMBLE_ATOMIC_BINOP(ldrexh, strexh, inst); \ __ sxth(i.OutputRegister(0), i.OutputRegister(0)); \ break; \ case kWord32Atomic##op##Uint16: \ + case kArmWord64AtomicNarrow##op##Uint16: \ ASSEMBLE_ATOMIC_BINOP(ldrexh, strexh, inst); \ + ATOMIC_NARROW_OP_CLEAR_HIGH_WORD(op##Uint16); \ break; \ case kWord32Atomic##op##Word32: \ + case kArmWord64AtomicNarrow##op##Uint32: \ ASSEMBLE_ATOMIC_BINOP(ldrex, strex, inst); \ + ATOMIC_NARROW_OP_CLEAR_HIGH_WORD(op##Uint32); \ break; ATOMIC_BINOP_CASE(Add, add) ATOMIC_BINOP_CASE(Sub, sub) @@ -2710,11 +2769,81 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( ATOMIC_BINOP_CASE(Or, orr) ATOMIC_BINOP_CASE(Xor, eor) #undef ATOMIC_BINOP_CASE + case kArmWord32AtomicPairLoad: + __ add(i.TempRegister(0), i.InputRegister(0), i.InputRegister(1)); + __ ldrexd(i.OutputRegister(0), i.OutputRegister(1), i.TempRegister(0)); + __ dmb(ISH); + break; + case kArmWord32AtomicPairStore: { + Label store; + __ add(i.TempRegister(0), i.InputRegister(0), i.InputRegister(1)); + __ dmb(ISH); + __ bind(&store); + __ ldrexd(i.TempRegister(1), i.TempRegister(2), i.TempRegister(0)); + __ strexd(i.TempRegister(1), i.InputRegister(2), i.InputRegister(3), + i.TempRegister(0)); + __ teq(i.TempRegister(1), Operand(0)); + __ b(ne, &store); + __ dmb(ISH); + break; + } +#define ATOMIC_ARITH_BINOP_CASE(op, instr1, instr2) \ + case kArmWord32AtomicPair##op: { \ + ASSEMBLE_ATOMIC64_ARITH_BINOP(instr1, instr2); \ + break; \ + } + ATOMIC_ARITH_BINOP_CASE(Add, add, adc) + ATOMIC_ARITH_BINOP_CASE(Sub, sub, sbc) +#undef ATOMIC_ARITH_BINOP_CASE +#define ATOMIC_LOGIC_BINOP_CASE(op, instr) \ + case kArmWord32AtomicPair##op: { \ + ASSEMBLE_ATOMIC64_LOGIC_BINOP(instr); \ + break; \ + } + ATOMIC_LOGIC_BINOP_CASE(And, and_) + ATOMIC_LOGIC_BINOP_CASE(Or, orr) + ATOMIC_LOGIC_BINOP_CASE(Xor, eor) + case kArmWord32AtomicPairExchange: { + Label exchange; + __ add(i.TempRegister(0), i.InputRegister(2), i.InputRegister(3)); + __ dmb(ISH); + __ bind(&exchange); + __ ldrexd(i.OutputRegister(0), i.OutputRegister(1), i.TempRegister(0)); + __ strexd(i.TempRegister(1), i.InputRegister(0), i.InputRegister(1), + i.TempRegister(0)); + __ teq(i.TempRegister(1), Operand(0)); + __ b(ne, &exchange); + __ dmb(ISH); + break; + } + case kArmWord32AtomicPairCompareExchange: { + __ add(i.TempRegister(0), i.InputRegister(4), i.InputRegister(5)); + Label compareExchange; + Label exit; + __ dmb(ISH); + __ bind(&compareExchange); + __ ldrexd(i.OutputRegister(0), i.OutputRegister(1), i.TempRegister(0)); + __ teq(i.InputRegister(0), Operand(i.OutputRegister(0))); + __ b(ne, &exit); + __ teq(i.InputRegister(1), Operand(i.OutputRegister(1))); + __ b(ne, &exit); + __ strexd(i.TempRegister(1), i.InputRegister(2), i.InputRegister(3), + i.TempRegister(0)); + __ teq(i.TempRegister(1), Operand(0)); + __ b(ne, &compareExchange); + __ bind(&exit); + __ dmb(ISH); + break; + } +#undef ATOMIC_LOGIC_BINOP_CASE +#undef ATOMIC_NARROW_OP_CLEAR_HIGH_WORD #undef ASSEMBLE_ATOMIC_LOAD_INTEGER #undef ASSEMBLE_ATOMIC_STORE_INTEGER #undef ASSEMBLE_ATOMIC_EXCHANGE_INTEGER #undef ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER #undef ASSEMBLE_ATOMIC_BINOP +#undef ASSEMBLE_ATOMIC64_ARITH_BINOP +#undef ASSEMBLE_ATOMIC64_LOGIC_BINOP #undef ASSEMBLE_IEEE754_BINOP #undef ASSEMBLE_IEEE754_UNOP #undef ASSEMBLE_NEON_NARROWING_OP diff --git a/src/compiler/arm/instruction-codes-arm.h b/src/compiler/arm/instruction-codes-arm.h index 05b8ef6a8e..ca8684a375 100644 --- a/src/compiler/arm/instruction-codes-arm.h +++ b/src/compiler/arm/instruction-codes-arm.h @@ -11,265 +11,295 @@ namespace compiler { // ARM-specific opcodes that specify which assembly sequence to emit. // Most opcodes specify a single instruction. -#define TARGET_ARCH_OPCODE_LIST(V) \ - V(ArmAdd) \ - V(ArmAnd) \ - V(ArmBic) \ - V(ArmClz) \ - V(ArmCmp) \ - V(ArmCmn) \ - V(ArmTst) \ - V(ArmTeq) \ - V(ArmOrr) \ - V(ArmEor) \ - V(ArmSub) \ - V(ArmRsb) \ - V(ArmMul) \ - V(ArmMla) \ - V(ArmMls) \ - V(ArmSmull) \ - V(ArmSmmul) \ - V(ArmSmmla) \ - V(ArmUmull) \ - V(ArmSdiv) \ - V(ArmUdiv) \ - V(ArmMov) \ - V(ArmMvn) \ - V(ArmBfc) \ - V(ArmUbfx) \ - V(ArmSbfx) \ - V(ArmSxtb) \ - V(ArmSxth) \ - V(ArmSxtab) \ - V(ArmSxtah) \ - V(ArmUxtb) \ - V(ArmUxth) \ - V(ArmUxtab) \ - V(ArmRbit) \ - V(ArmRev) \ - V(ArmUxtah) \ - V(ArmAddPair) \ - V(ArmSubPair) \ - V(ArmMulPair) \ - V(ArmLslPair) \ - V(ArmLsrPair) \ - V(ArmAsrPair) \ - V(ArmVcmpF32) \ - V(ArmVaddF32) \ - V(ArmVsubF32) \ - V(ArmVmulF32) \ - V(ArmVmlaF32) \ - V(ArmVmlsF32) \ - V(ArmVdivF32) \ - V(ArmVabsF32) \ - V(ArmVnegF32) \ - V(ArmVsqrtF32) \ - V(ArmVcmpF64) \ - V(ArmVaddF64) \ - V(ArmVsubF64) \ - V(ArmVmulF64) \ - V(ArmVmlaF64) \ - V(ArmVmlsF64) \ - V(ArmVdivF64) \ - V(ArmVmodF64) \ - V(ArmVabsF64) \ - V(ArmVnegF64) \ - V(ArmVsqrtF64) \ - V(ArmVrintmF32) \ - V(ArmVrintmF64) \ - V(ArmVrintpF32) \ - V(ArmVrintpF64) \ - V(ArmVrintzF32) \ - V(ArmVrintzF64) \ - V(ArmVrintaF64) \ - V(ArmVrintnF32) \ - V(ArmVrintnF64) \ - V(ArmVcvtF32F64) \ - V(ArmVcvtF64F32) \ - V(ArmVcvtF32S32) \ - V(ArmVcvtF32U32) \ - V(ArmVcvtF64S32) \ - V(ArmVcvtF64U32) \ - V(ArmVcvtS32F32) \ - V(ArmVcvtU32F32) \ - V(ArmVcvtS32F64) \ - V(ArmVcvtU32F64) \ - V(ArmVmovU32F32) \ - V(ArmVmovF32U32) \ - V(ArmVmovLowU32F64) \ - V(ArmVmovLowF64U32) \ - V(ArmVmovHighU32F64) \ - V(ArmVmovHighF64U32) \ - V(ArmVmovF64U32U32) \ - V(ArmVmovU32U32F64) \ - V(ArmVldrF32) \ - V(ArmVstrF32) \ - V(ArmVldrF64) \ - V(ArmVld1F64) \ - V(ArmVstrF64) \ - V(ArmVst1F64) \ - V(ArmVld1S128) \ - V(ArmVst1S128) \ - V(ArmFloat32Max) \ - V(ArmFloat64Max) \ - V(ArmFloat32Min) \ - V(ArmFloat64Min) \ - V(ArmFloat64SilenceNaN) \ - V(ArmLdrb) \ - V(ArmLdrsb) \ - V(ArmStrb) \ - V(ArmLdrh) \ - V(ArmLdrsh) \ - V(ArmStrh) \ - V(ArmLdr) \ - V(ArmStr) \ - V(ArmPush) \ - V(ArmPoke) \ - V(ArmPeek) \ - V(ArmDsbIsb) \ - V(ArmF32x4Splat) \ - V(ArmF32x4ExtractLane) \ - V(ArmF32x4ReplaceLane) \ - V(ArmF32x4SConvertI32x4) \ - V(ArmF32x4UConvertI32x4) \ - V(ArmF32x4Abs) \ - V(ArmF32x4Neg) \ - V(ArmF32x4RecipApprox) \ - V(ArmF32x4RecipSqrtApprox) \ - V(ArmF32x4Add) \ - V(ArmF32x4AddHoriz) \ - V(ArmF32x4Sub) \ - V(ArmF32x4Mul) \ - V(ArmF32x4Min) \ - V(ArmF32x4Max) \ - V(ArmF32x4Eq) \ - V(ArmF32x4Ne) \ - V(ArmF32x4Lt) \ - V(ArmF32x4Le) \ - V(ArmI32x4Splat) \ - V(ArmI32x4ExtractLane) \ - V(ArmI32x4ReplaceLane) \ - V(ArmI32x4SConvertF32x4) \ - V(ArmI32x4SConvertI16x8Low) \ - V(ArmI32x4SConvertI16x8High) \ - V(ArmI32x4Neg) \ - V(ArmI32x4Shl) \ - V(ArmI32x4ShrS) \ - V(ArmI32x4Add) \ - V(ArmI32x4AddHoriz) \ - V(ArmI32x4Sub) \ - V(ArmI32x4Mul) \ - V(ArmI32x4MinS) \ - V(ArmI32x4MaxS) \ - V(ArmI32x4Eq) \ - V(ArmI32x4Ne) \ - V(ArmI32x4GtS) \ - V(ArmI32x4GeS) \ - V(ArmI32x4UConvertF32x4) \ - V(ArmI32x4UConvertI16x8Low) \ - V(ArmI32x4UConvertI16x8High) \ - V(ArmI32x4ShrU) \ - V(ArmI32x4MinU) \ - V(ArmI32x4MaxU) \ - V(ArmI32x4GtU) \ - V(ArmI32x4GeU) \ - V(ArmI16x8Splat) \ - V(ArmI16x8ExtractLane) \ - V(ArmI16x8ReplaceLane) \ - V(ArmI16x8SConvertI8x16Low) \ - V(ArmI16x8SConvertI8x16High) \ - V(ArmI16x8Neg) \ - V(ArmI16x8Shl) \ - V(ArmI16x8ShrS) \ - V(ArmI16x8SConvertI32x4) \ - V(ArmI16x8Add) \ - V(ArmI16x8AddSaturateS) \ - V(ArmI16x8AddHoriz) \ - V(ArmI16x8Sub) \ - V(ArmI16x8SubSaturateS) \ - V(ArmI16x8Mul) \ - V(ArmI16x8MinS) \ - V(ArmI16x8MaxS) \ - V(ArmI16x8Eq) \ - V(ArmI16x8Ne) \ - V(ArmI16x8GtS) \ - V(ArmI16x8GeS) \ - V(ArmI16x8UConvertI8x16Low) \ - V(ArmI16x8UConvertI8x16High) \ - V(ArmI16x8ShrU) \ - V(ArmI16x8UConvertI32x4) \ - V(ArmI16x8AddSaturateU) \ - V(ArmI16x8SubSaturateU) \ - V(ArmI16x8MinU) \ - V(ArmI16x8MaxU) \ - V(ArmI16x8GtU) \ - V(ArmI16x8GeU) \ - V(ArmI8x16Splat) \ - V(ArmI8x16ExtractLane) \ - V(ArmI8x16ReplaceLane) \ - V(ArmI8x16Neg) \ - V(ArmI8x16Shl) \ - V(ArmI8x16ShrS) \ - V(ArmI8x16SConvertI16x8) \ - V(ArmI8x16Add) \ - V(ArmI8x16AddSaturateS) \ - V(ArmI8x16Sub) \ - V(ArmI8x16SubSaturateS) \ - V(ArmI8x16Mul) \ - V(ArmI8x16MinS) \ - V(ArmI8x16MaxS) \ - V(ArmI8x16Eq) \ - V(ArmI8x16Ne) \ - V(ArmI8x16GtS) \ - V(ArmI8x16GeS) \ - V(ArmI8x16ShrU) \ - V(ArmI8x16UConvertI16x8) \ - V(ArmI8x16AddSaturateU) \ - V(ArmI8x16SubSaturateU) \ - V(ArmI8x16MinU) \ - V(ArmI8x16MaxU) \ - V(ArmI8x16GtU) \ - V(ArmI8x16GeU) \ - V(ArmS128Zero) \ - V(ArmS128Dup) \ - V(ArmS128And) \ - V(ArmS128Or) \ - V(ArmS128Xor) \ - V(ArmS128Not) \ - V(ArmS128Select) \ - V(ArmS32x4ZipLeft) \ - V(ArmS32x4ZipRight) \ - V(ArmS32x4UnzipLeft) \ - V(ArmS32x4UnzipRight) \ - V(ArmS32x4TransposeLeft) \ - V(ArmS32x4TransposeRight) \ - V(ArmS32x4Shuffle) \ - V(ArmS16x8ZipLeft) \ - V(ArmS16x8ZipRight) \ - V(ArmS16x8UnzipLeft) \ - V(ArmS16x8UnzipRight) \ - V(ArmS16x8TransposeLeft) \ - V(ArmS16x8TransposeRight) \ - V(ArmS8x16ZipLeft) \ - V(ArmS8x16ZipRight) \ - V(ArmS8x16UnzipLeft) \ - V(ArmS8x16UnzipRight) \ - V(ArmS8x16TransposeLeft) \ - V(ArmS8x16TransposeRight) \ - V(ArmS8x16Concat) \ - V(ArmS8x16Shuffle) \ - V(ArmS32x2Reverse) \ - V(ArmS16x4Reverse) \ - V(ArmS16x2Reverse) \ - V(ArmS8x8Reverse) \ - V(ArmS8x4Reverse) \ - V(ArmS8x2Reverse) \ - V(ArmS1x4AnyTrue) \ - V(ArmS1x4AllTrue) \ - V(ArmS1x8AnyTrue) \ - V(ArmS1x8AllTrue) \ - V(ArmS1x16AnyTrue) \ - V(ArmS1x16AllTrue) +#define TARGET_ARCH_OPCODE_LIST(V) \ + V(ArmAdd) \ + V(ArmAnd) \ + V(ArmBic) \ + V(ArmClz) \ + V(ArmCmp) \ + V(ArmCmn) \ + V(ArmTst) \ + V(ArmTeq) \ + V(ArmOrr) \ + V(ArmEor) \ + V(ArmSub) \ + V(ArmRsb) \ + V(ArmMul) \ + V(ArmMla) \ + V(ArmMls) \ + V(ArmSmull) \ + V(ArmSmmul) \ + V(ArmSmmla) \ + V(ArmUmull) \ + V(ArmSdiv) \ + V(ArmUdiv) \ + V(ArmMov) \ + V(ArmMvn) \ + V(ArmBfc) \ + V(ArmUbfx) \ + V(ArmSbfx) \ + V(ArmSxtb) \ + V(ArmSxth) \ + V(ArmSxtab) \ + V(ArmSxtah) \ + V(ArmUxtb) \ + V(ArmUxth) \ + V(ArmUxtab) \ + V(ArmRbit) \ + V(ArmRev) \ + V(ArmUxtah) \ + V(ArmAddPair) \ + V(ArmSubPair) \ + V(ArmMulPair) \ + V(ArmLslPair) \ + V(ArmLsrPair) \ + V(ArmAsrPair) \ + V(ArmVcmpF32) \ + V(ArmVaddF32) \ + V(ArmVsubF32) \ + V(ArmVmulF32) \ + V(ArmVmlaF32) \ + V(ArmVmlsF32) \ + V(ArmVdivF32) \ + V(ArmVabsF32) \ + V(ArmVnegF32) \ + V(ArmVsqrtF32) \ + V(ArmVcmpF64) \ + V(ArmVaddF64) \ + V(ArmVsubF64) \ + V(ArmVmulF64) \ + V(ArmVmlaF64) \ + V(ArmVmlsF64) \ + V(ArmVdivF64) \ + V(ArmVmodF64) \ + V(ArmVabsF64) \ + V(ArmVnegF64) \ + V(ArmVsqrtF64) \ + V(ArmVrintmF32) \ + V(ArmVrintmF64) \ + V(ArmVrintpF32) \ + V(ArmVrintpF64) \ + V(ArmVrintzF32) \ + V(ArmVrintzF64) \ + V(ArmVrintaF64) \ + V(ArmVrintnF32) \ + V(ArmVrintnF64) \ + V(ArmVcvtF32F64) \ + V(ArmVcvtF64F32) \ + V(ArmVcvtF32S32) \ + V(ArmVcvtF32U32) \ + V(ArmVcvtF64S32) \ + V(ArmVcvtF64U32) \ + V(ArmVcvtS32F32) \ + V(ArmVcvtU32F32) \ + V(ArmVcvtS32F64) \ + V(ArmVcvtU32F64) \ + V(ArmVmovU32F32) \ + V(ArmVmovF32U32) \ + V(ArmVmovLowU32F64) \ + V(ArmVmovLowF64U32) \ + V(ArmVmovHighU32F64) \ + V(ArmVmovHighF64U32) \ + V(ArmVmovF64U32U32) \ + V(ArmVmovU32U32F64) \ + V(ArmVldrF32) \ + V(ArmVstrF32) \ + V(ArmVldrF64) \ + V(ArmVld1F64) \ + V(ArmVstrF64) \ + V(ArmVst1F64) \ + V(ArmVld1S128) \ + V(ArmVst1S128) \ + V(ArmFloat32Max) \ + V(ArmFloat64Max) \ + V(ArmFloat32Min) \ + V(ArmFloat64Min) \ + V(ArmFloat64SilenceNaN) \ + V(ArmLdrb) \ + V(ArmLdrsb) \ + V(ArmStrb) \ + V(ArmLdrh) \ + V(ArmLdrsh) \ + V(ArmStrh) \ + V(ArmLdr) \ + V(ArmStr) \ + V(ArmPush) \ + V(ArmPoke) \ + V(ArmPeek) \ + V(ArmDsbIsb) \ + V(ArmF32x4Splat) \ + V(ArmF32x4ExtractLane) \ + V(ArmF32x4ReplaceLane) \ + V(ArmF32x4SConvertI32x4) \ + V(ArmF32x4UConvertI32x4) \ + V(ArmF32x4Abs) \ + V(ArmF32x4Neg) \ + V(ArmF32x4RecipApprox) \ + V(ArmF32x4RecipSqrtApprox) \ + V(ArmF32x4Add) \ + V(ArmF32x4AddHoriz) \ + V(ArmF32x4Sub) \ + V(ArmF32x4Mul) \ + V(ArmF32x4Min) \ + V(ArmF32x4Max) \ + V(ArmF32x4Eq) \ + V(ArmF32x4Ne) \ + V(ArmF32x4Lt) \ + V(ArmF32x4Le) \ + V(ArmI32x4Splat) \ + V(ArmI32x4ExtractLane) \ + V(ArmI32x4ReplaceLane) \ + V(ArmI32x4SConvertF32x4) \ + V(ArmI32x4SConvertI16x8Low) \ + V(ArmI32x4SConvertI16x8High) \ + V(ArmI32x4Neg) \ + V(ArmI32x4Shl) \ + V(ArmI32x4ShrS) \ + V(ArmI32x4Add) \ + V(ArmI32x4AddHoriz) \ + V(ArmI32x4Sub) \ + V(ArmI32x4Mul) \ + V(ArmI32x4MinS) \ + V(ArmI32x4MaxS) \ + V(ArmI32x4Eq) \ + V(ArmI32x4Ne) \ + V(ArmI32x4GtS) \ + V(ArmI32x4GeS) \ + V(ArmI32x4UConvertF32x4) \ + V(ArmI32x4UConvertI16x8Low) \ + V(ArmI32x4UConvertI16x8High) \ + V(ArmI32x4ShrU) \ + V(ArmI32x4MinU) \ + V(ArmI32x4MaxU) \ + V(ArmI32x4GtU) \ + V(ArmI32x4GeU) \ + V(ArmI16x8Splat) \ + V(ArmI16x8ExtractLane) \ + V(ArmI16x8ReplaceLane) \ + V(ArmI16x8SConvertI8x16Low) \ + V(ArmI16x8SConvertI8x16High) \ + V(ArmI16x8Neg) \ + V(ArmI16x8Shl) \ + V(ArmI16x8ShrS) \ + V(ArmI16x8SConvertI32x4) \ + V(ArmI16x8Add) \ + V(ArmI16x8AddSaturateS) \ + V(ArmI16x8AddHoriz) \ + V(ArmI16x8Sub) \ + V(ArmI16x8SubSaturateS) \ + V(ArmI16x8Mul) \ + V(ArmI16x8MinS) \ + V(ArmI16x8MaxS) \ + V(ArmI16x8Eq) \ + V(ArmI16x8Ne) \ + V(ArmI16x8GtS) \ + V(ArmI16x8GeS) \ + V(ArmI16x8UConvertI8x16Low) \ + V(ArmI16x8UConvertI8x16High) \ + V(ArmI16x8ShrU) \ + V(ArmI16x8UConvertI32x4) \ + V(ArmI16x8AddSaturateU) \ + V(ArmI16x8SubSaturateU) \ + V(ArmI16x8MinU) \ + V(ArmI16x8MaxU) \ + V(ArmI16x8GtU) \ + V(ArmI16x8GeU) \ + V(ArmI8x16Splat) \ + V(ArmI8x16ExtractLane) \ + V(ArmI8x16ReplaceLane) \ + V(ArmI8x16Neg) \ + V(ArmI8x16Shl) \ + V(ArmI8x16ShrS) \ + V(ArmI8x16SConvertI16x8) \ + V(ArmI8x16Add) \ + V(ArmI8x16AddSaturateS) \ + V(ArmI8x16Sub) \ + V(ArmI8x16SubSaturateS) \ + V(ArmI8x16Mul) \ + V(ArmI8x16MinS) \ + V(ArmI8x16MaxS) \ + V(ArmI8x16Eq) \ + V(ArmI8x16Ne) \ + V(ArmI8x16GtS) \ + V(ArmI8x16GeS) \ + V(ArmI8x16ShrU) \ + V(ArmI8x16UConvertI16x8) \ + V(ArmI8x16AddSaturateU) \ + V(ArmI8x16SubSaturateU) \ + V(ArmI8x16MinU) \ + V(ArmI8x16MaxU) \ + V(ArmI8x16GtU) \ + V(ArmI8x16GeU) \ + V(ArmS128Zero) \ + V(ArmS128Dup) \ + V(ArmS128And) \ + V(ArmS128Or) \ + V(ArmS128Xor) \ + V(ArmS128Not) \ + V(ArmS128Select) \ + V(ArmS32x4ZipLeft) \ + V(ArmS32x4ZipRight) \ + V(ArmS32x4UnzipLeft) \ + V(ArmS32x4UnzipRight) \ + V(ArmS32x4TransposeLeft) \ + V(ArmS32x4TransposeRight) \ + V(ArmS32x4Shuffle) \ + V(ArmS16x8ZipLeft) \ + V(ArmS16x8ZipRight) \ + V(ArmS16x8UnzipLeft) \ + V(ArmS16x8UnzipRight) \ + V(ArmS16x8TransposeLeft) \ + V(ArmS16x8TransposeRight) \ + V(ArmS8x16ZipLeft) \ + V(ArmS8x16ZipRight) \ + V(ArmS8x16UnzipLeft) \ + V(ArmS8x16UnzipRight) \ + V(ArmS8x16TransposeLeft) \ + V(ArmS8x16TransposeRight) \ + V(ArmS8x16Concat) \ + V(ArmS8x16Shuffle) \ + V(ArmS32x2Reverse) \ + V(ArmS16x4Reverse) \ + V(ArmS16x2Reverse) \ + V(ArmS8x8Reverse) \ + V(ArmS8x4Reverse) \ + V(ArmS8x2Reverse) \ + V(ArmS1x4AnyTrue) \ + V(ArmS1x4AllTrue) \ + V(ArmS1x8AnyTrue) \ + V(ArmS1x8AllTrue) \ + V(ArmS1x16AnyTrue) \ + V(ArmS1x16AllTrue) \ + V(ArmWord32AtomicPairLoad) \ + V(ArmWord32AtomicPairStore) \ + V(ArmWord32AtomicPairAdd) \ + V(ArmWord32AtomicPairSub) \ + V(ArmWord32AtomicPairAnd) \ + V(ArmWord32AtomicPairOr) \ + V(ArmWord32AtomicPairXor) \ + V(ArmWord32AtomicPairExchange) \ + V(ArmWord32AtomicPairCompareExchange) \ + V(ArmWord64AtomicNarrowAddUint8) \ + V(ArmWord64AtomicNarrowAddUint16) \ + V(ArmWord64AtomicNarrowAddUint32) \ + V(ArmWord64AtomicNarrowSubUint8) \ + V(ArmWord64AtomicNarrowSubUint16) \ + V(ArmWord64AtomicNarrowSubUint32) \ + V(ArmWord64AtomicNarrowAndUint8) \ + V(ArmWord64AtomicNarrowAndUint16) \ + V(ArmWord64AtomicNarrowAndUint32) \ + V(ArmWord64AtomicNarrowOrUint8) \ + V(ArmWord64AtomicNarrowOrUint16) \ + V(ArmWord64AtomicNarrowOrUint32) \ + V(ArmWord64AtomicNarrowXorUint8) \ + V(ArmWord64AtomicNarrowXorUint16) \ + V(ArmWord64AtomicNarrowXorUint32) \ + V(ArmWord64AtomicNarrowExchangeUint8) \ + V(ArmWord64AtomicNarrowExchangeUint16) \ + V(ArmWord64AtomicNarrowExchangeUint32) \ + V(ArmWord64AtomicNarrowCompareExchangeUint8) \ + V(ArmWord64AtomicNarrowCompareExchangeUint16) \ + V(ArmWord64AtomicNarrowCompareExchangeUint32) // Addressing modes represent the "shape" of inputs to an instruction. // Many instructions support multiple addressing modes. Addressing modes diff --git a/src/compiler/arm/instruction-scheduler-arm.cc b/src/compiler/arm/instruction-scheduler-arm.cc index b96f71b1da..56ff02689a 100644 --- a/src/compiler/arm/instruction-scheduler-arm.cc +++ b/src/compiler/arm/instruction-scheduler-arm.cc @@ -264,6 +264,7 @@ int InstructionScheduler::GetTargetInstructionFlags( case kArmLdrsh: case kArmLdr: case kArmPeek: + case kArmWord32AtomicPairLoad: return kIsLoadOperation; case kArmVstrF32: @@ -276,6 +277,35 @@ int InstructionScheduler::GetTargetInstructionFlags( case kArmPush: case kArmPoke: case kArmDsbIsb: + case kArmWord32AtomicPairStore: + case kArmWord32AtomicPairAdd: + case kArmWord32AtomicPairSub: + case kArmWord32AtomicPairAnd: + case kArmWord32AtomicPairOr: + case kArmWord32AtomicPairXor: + case kArmWord32AtomicPairExchange: + case kArmWord32AtomicPairCompareExchange: + case kArmWord64AtomicNarrowAddUint8: + case kArmWord64AtomicNarrowAddUint16: + case kArmWord64AtomicNarrowAddUint32: + case kArmWord64AtomicNarrowSubUint8: + case kArmWord64AtomicNarrowSubUint16: + case kArmWord64AtomicNarrowSubUint32: + case kArmWord64AtomicNarrowAndUint8: + case kArmWord64AtomicNarrowAndUint16: + case kArmWord64AtomicNarrowAndUint32: + case kArmWord64AtomicNarrowOrUint8: + case kArmWord64AtomicNarrowOrUint16: + case kArmWord64AtomicNarrowOrUint32: + case kArmWord64AtomicNarrowXorUint8: + case kArmWord64AtomicNarrowXorUint16: + case kArmWord64AtomicNarrowXorUint32: + case kArmWord64AtomicNarrowExchangeUint8: + case kArmWord64AtomicNarrowExchangeUint16: + case kArmWord64AtomicNarrowExchangeUint32: + case kArmWord64AtomicNarrowCompareExchangeUint8: + case kArmWord64AtomicNarrowCompareExchangeUint16: + case kArmWord64AtomicNarrowCompareExchangeUint32: return kHasSideEffect; #define CASE(Name) case k##Name: diff --git a/src/compiler/arm/instruction-selector-arm.cc b/src/compiler/arm/instruction-selector-arm.cc index 24dc256a11..277d9779c0 100644 --- a/src/compiler/arm/instruction-selector-arm.cc +++ b/src/compiler/arm/instruction-selector-arm.cc @@ -403,6 +403,46 @@ void EmitStore(InstructionSelector* selector, InstructionCode opcode, selector->Emit(opcode, 0, nullptr, input_count, inputs); } +void VisitPairAtomicBinOp(InstructionSelector* selector, Node* node, + ArchOpcode opcode) { + ArmOperandGenerator g(selector); + Node* base = node->InputAt(0); + Node* index = node->InputAt(1); + Node* value = node->InputAt(2); + Node* value_high = node->InputAt(3); + AddressingMode addressing_mode = kMode_Offset_RR; + InstructionOperand inputs[] = {g.UseUniqueRegister(value), + g.UseUniqueRegister(value_high), + g.UseRegister(base), g.UseRegister(index)}; + InstructionOperand outputs[] = { + g.DefineAsFixed(NodeProperties::FindProjection(node, 0), r2), + g.DefineAsFixed(NodeProperties::FindProjection(node, 1), r3)}; + InstructionOperand temps[] = {g.TempRegister(), g.TempRegister(r6), + g.TempRegister(r7), g.TempRegister()}; + InstructionCode code = opcode | AddressingModeField::encode(addressing_mode); + selector->Emit(code, arraysize(outputs), outputs, arraysize(inputs), inputs, + arraysize(temps), temps); +} + +void VisitNarrowAtomicBinOp(InstructionSelector* selector, Node* node, + ArchOpcode opcode) { + ArmOperandGenerator g(selector); + Node* base = node->InputAt(0); + Node* index = node->InputAt(1); + Node* value = node->InputAt(2); + AddressingMode addressing_mode = kMode_Offset_RR; + InstructionOperand inputs[3] = {g.UseRegister(base), g.UseRegister(index), + g.UseUniqueRegister(value)}; + InstructionOperand outputs[] = { + g.DefineAsFixed(NodeProperties::FindProjection(node, 0), r4), + g.DefineAsFixed(NodeProperties::FindProjection(node, 1), r5)}; + InstructionOperand temps[] = {g.TempRegister(), g.TempRegister(), + g.TempRegister()}; + InstructionCode code = opcode | AddressingModeField::encode(addressing_mode); + selector->Emit(code, arraysize(outputs), outputs, arraysize(inputs), inputs, + arraysize(temps), temps); +} + } // namespace void InstructionSelector::VisitStackSlot(Node* node) { @@ -2221,6 +2261,190 @@ VISIT_ATOMIC_BINOP(Or) VISIT_ATOMIC_BINOP(Xor) #undef VISIT_ATOMIC_BINOP +void InstructionSelector::VisitWord32AtomicPairLoad(Node* node) { + ArmOperandGenerator g(this); + Node* base = node->InputAt(0); + Node* index = node->InputAt(1); + InstructionOperand inputs[] = {g.UseRegister(base), g.UseRegister(index)}; + InstructionOperand outputs[] = { + g.DefineAsFixed(NodeProperties::FindProjection(node, 0), r0), + g.DefineAsFixed(NodeProperties::FindProjection(node, 1), r1)}; + InstructionOperand temps[] = {g.TempRegister()}; + AddressingMode addressing_mode = kMode_Offset_RR; + InstructionCode code = + kArmWord32AtomicPairLoad | AddressingModeField::encode(addressing_mode); + Emit(code, arraysize(outputs), outputs, arraysize(inputs), inputs, + arraysize(temps), temps); +} + +void InstructionSelector::VisitWord32AtomicPairStore(Node* node) { + ArmOperandGenerator g(this); + Node* base = node->InputAt(0); + Node* index = node->InputAt(1); + Node* value_low = node->InputAt(2); + Node* value_high = node->InputAt(3); + AddressingMode addressing_mode = kMode_Offset_RR; + InstructionOperand inputs[] = { + g.UseUniqueRegister(base), g.UseUniqueRegister(index), + g.UseFixed(value_low, r2), g.UseFixed(value_high, r3)}; + InstructionOperand temps[] = {g.TempRegister(), g.TempRegister(r0), + g.TempRegister(r1)}; + InstructionCode code = + kArmWord32AtomicPairStore | AddressingModeField::encode(addressing_mode); + Emit(code, 0, nullptr, arraysize(inputs), inputs, arraysize(temps), temps); +} + +void InstructionSelector::VisitWord32AtomicPairAdd(Node* node) { + VisitPairAtomicBinOp(this, node, kArmWord32AtomicPairAdd); +} + +void InstructionSelector::VisitWord32AtomicPairSub(Node* node) { + VisitPairAtomicBinOp(this, node, kArmWord32AtomicPairSub); +} + +void InstructionSelector::VisitWord32AtomicPairAnd(Node* node) { + VisitPairAtomicBinOp(this, node, kArmWord32AtomicPairAnd); +} + +void InstructionSelector::VisitWord32AtomicPairOr(Node* node) { + VisitPairAtomicBinOp(this, node, kArmWord32AtomicPairOr); +} + +void InstructionSelector::VisitWord32AtomicPairXor(Node* node) { + VisitPairAtomicBinOp(this, node, kArmWord32AtomicPairXor); +} + +void InstructionSelector::VisitWord64AtomicNarrowBinop(Node* node, + ArchOpcode uint8_op, + ArchOpcode uint16_op, + ArchOpcode uint32_op) { + MachineType type = AtomicOpType(node->op()); + DCHECK(type != MachineType::Uint64()); + ArchOpcode opcode = kArchNop; + if (type == MachineType::Uint32()) { + opcode = uint32_op; + } else if (type == MachineType::Uint16()) { + opcode = uint16_op; + } else if (type == MachineType::Uint8()) { + opcode = uint8_op; + } else { + UNREACHABLE(); + return; + } + VisitNarrowAtomicBinOp(this, node, opcode); +} + +#define VISIT_ATOMIC_BINOP(op) \ + void InstructionSelector::VisitWord64AtomicNarrow##op(Node* node) { \ + VisitWord64AtomicNarrowBinop(node, kArmWord64AtomicNarrow##op##Uint8, \ + kArmWord64AtomicNarrow##op##Uint16, \ + kArmWord64AtomicNarrow##op##Uint32); \ + } +VISIT_ATOMIC_BINOP(Add) +VISIT_ATOMIC_BINOP(Sub) +VISIT_ATOMIC_BINOP(And) +VISIT_ATOMIC_BINOP(Or) +VISIT_ATOMIC_BINOP(Xor) +#undef VISIT_ATOMIC_BINOP + +void InstructionSelector::VisitWord32AtomicPairExchange(Node* node) { + ArmOperandGenerator g(this); + Node* base = node->InputAt(0); + Node* index = node->InputAt(1); + Node* value = node->InputAt(2); + Node* value_high = node->InputAt(3); + AddressingMode addressing_mode = kMode_Offset_RR; + InstructionOperand inputs[] = {g.UseFixed(value, r0), + g.UseFixed(value_high, r1), + g.UseRegister(base), g.UseRegister(index)}; + InstructionOperand outputs[] = { + g.DefineAsFixed(NodeProperties::FindProjection(node, 0), r6), + g.DefineAsFixed(NodeProperties::FindProjection(node, 1), r7)}; + InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()}; + InstructionCode code = kArmWord32AtomicPairExchange | + AddressingModeField::encode(addressing_mode); + Emit(code, arraysize(outputs), outputs, arraysize(inputs), inputs, + arraysize(temps), temps); +} + +void InstructionSelector::VisitWord64AtomicNarrowExchange(Node* node) { + ArmOperandGenerator g(this); + Node* base = node->InputAt(0); + Node* index = node->InputAt(1); + Node* value = node->InputAt(2); + ArchOpcode opcode = kArchNop; + MachineType type = AtomicOpType(node->op()); + if (type == MachineType::Uint8()) { + opcode = kArmWord64AtomicNarrowExchangeUint8; + } else if (type == MachineType::Uint16()) { + opcode = kArmWord64AtomicNarrowExchangeUint16; + } else if (type == MachineType::Uint32()) { + opcode = kArmWord64AtomicNarrowExchangeUint32; + } else { + UNREACHABLE(); + return; + } + AddressingMode addressing_mode = kMode_Offset_RR; + InstructionOperand inputs[] = {g.UseRegister(base), g.UseRegister(index), + g.UseUniqueRegister(value)}; + InstructionOperand outputs[] = { + g.DefineAsRegister(NodeProperties::FindProjection(node, 0)), + g.DefineAsRegister(NodeProperties::FindProjection(node, 1))}; + InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()}; + InstructionCode code = opcode | AddressingModeField::encode(addressing_mode); + Emit(code, arraysize(outputs), outputs, arraysize(inputs), inputs, + arraysize(temps), temps); +} + +void InstructionSelector::VisitWord32AtomicPairCompareExchange(Node* node) { + ArmOperandGenerator g(this); + AddressingMode addressing_mode = kMode_Offset_RR; + InstructionOperand inputs[] = { + g.UseFixed(node->InputAt(2), r4), g.UseFixed(node->InputAt(3), r5), + g.UseFixed(node->InputAt(4), r8), g.UseFixed(node->InputAt(5), r9), + g.UseRegister(node->InputAt(0)), g.UseRegister(node->InputAt(1))}; + InstructionOperand outputs[] = { + g.DefineAsFixed(NodeProperties::FindProjection(node, 0), r2), + g.DefineAsFixed(NodeProperties::FindProjection(node, 1), r3)}; + InstructionOperand temps[] = {g.TempRegister(), g.TempRegister()}; + InstructionCode code = kArmWord32AtomicPairCompareExchange | + AddressingModeField::encode(addressing_mode); + Emit(code, arraysize(outputs), outputs, arraysize(inputs), inputs, + arraysize(temps), temps); +} + +void InstructionSelector::VisitWord64AtomicNarrowCompareExchange(Node* node) { + ArmOperandGenerator g(this); + Node* base = node->InputAt(0); + Node* index = node->InputAt(1); + Node* old_value = node->InputAt(2); + Node* new_value = node->InputAt(3); + ArchOpcode opcode = kArchNop; + MachineType type = AtomicOpType(node->op()); + if (type == MachineType::Uint8()) { + opcode = kArmWord64AtomicNarrowCompareExchangeUint8; + } else if (type == MachineType::Uint16()) { + opcode = kArmWord64AtomicNarrowCompareExchangeUint16; + } else if (type == MachineType::Uint32()) { + opcode = kArmWord64AtomicNarrowCompareExchangeUint32; + } else { + UNREACHABLE(); + return; + } + AddressingMode addressing_mode = kMode_Offset_RR; + InstructionOperand inputs[] = {g.UseRegister(base), g.UseRegister(index), + g.UseUniqueRegister(old_value), + g.UseUniqueRegister(new_value)}; + InstructionOperand outputs[] = { + g.DefineAsRegister(NodeProperties::FindProjection(node, 0)), + g.DefineAsRegister(NodeProperties::FindProjection(node, 1))}; + InstructionOperand temps[] = {g.TempRegister(), g.TempRegister(), + g.TempRegister()}; + InstructionCode code = opcode | AddressingModeField::encode(addressing_mode); + Emit(code, arraysize(outputs), outputs, arraysize(inputs), inputs, + arraysize(temps), temps); +} + #define SIMD_TYPE_LIST(V) \ V(F32x4) \ V(I32x4) \ diff --git a/src/compiler/instruction-selector.cc b/src/compiler/instruction-selector.cc index 62d4f597b2..d15a633257 100644 --- a/src/compiler/instruction-selector.cc +++ b/src/compiler/instruction-selector.cc @@ -2389,7 +2389,7 @@ void InstructionSelector::VisitWord32PairShr(Node* node) { UNIMPLEMENTED(); } void InstructionSelector::VisitWord32PairSar(Node* node) { UNIMPLEMENTED(); } #endif // V8_TARGET_ARCH_64_BIT -#if !V8_TARGET_ARCH_IA32 +#if !V8_TARGET_ARCH_IA32 && !V8_TARGET_ARCH_ARM void InstructionSelector::VisitWord32AtomicPairLoad(Node* node) { UNIMPLEMENTED(); } @@ -2453,7 +2453,7 @@ void InstructionSelector::VisitWord64AtomicNarrowExchange(Node* node) { void InstructionSelector::VisitWord64AtomicNarrowCompareExchange(Node* node) { UNIMPLEMENTED(); } -#endif // !V8_TARGET_ARCH_IA32 +#endif // !V8_TARGET_ARCH_IA32 && !V8_TARGET_ARCH_ARM #if !V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_MIPS && \ !V8_TARGET_ARCH_MIPS64 && !V8_TARGET_ARCH_IA32 diff --git a/test/cctest/BUILD.gn b/test/cctest/BUILD.gn index 20c2a594ec..c4aa51b818 100644 --- a/test/cctest/BUILD.gn +++ b/test/cctest/BUILD.gn @@ -243,6 +243,7 @@ v8_source_set("cctest_sources") { "wasm/test-run-wasm-64.cc", "wasm/test-run-wasm-asmjs.cc", "wasm/test-run-wasm-atomics.cc", + "wasm/test-run-wasm-atomics64.cc", "wasm/test-run-wasm-interpreter.cc", "wasm/test-run-wasm-js.cc", "wasm/test-run-wasm-module.cc", @@ -299,7 +300,6 @@ v8_source_set("cctest_sources") { "test-sync-primitives-arm64.cc", "test-utils-arm64.cc", "test-utils-arm64.h", - "wasm/test-run-wasm-atomics64.cc", ] } else if (v8_current_cpu == "x86") { sources += [ ### gcmole(arch:ia32) ### @@ -309,7 +309,6 @@ v8_source_set("cctest_sources") { "test-code-stubs.h", "test-disasm-ia32.cc", "test-log-stack-tracer.cc", - "wasm/test-run-wasm-atomics64.cc", ] } else if (v8_current_cpu == "mips") { sources += [ ### gcmole(arch:mips) ### @@ -356,7 +355,6 @@ v8_source_set("cctest_sources") { "test-disasm-x64.cc", "test-log-stack-tracer.cc", "test-macro-assembler-x64.cc", - "wasm/test-run-wasm-atomics64.cc", ] } else if (v8_current_cpu == "ppc" || v8_current_cpu == "ppc64") { sources += [ ### gcmole(arch:ppc) ### diff --git a/test/cctest/cctest.status b/test/cctest/cctest.status index 0e2b4e5b27..5d3b4de79d 100644 --- a/test/cctest/cctest.status +++ b/test/cctest/cctest.status @@ -344,6 +344,12 @@ 'test-run-wasm-simd/RunWasm_ReductionTest16_compiled': [SKIP], }], # '(arch == mipsel or arch == mips64el or arch == mips or arch == mips64) and not simd_mips' +############################################################################## +['arch == mipsel or arch == mips64el or arch == mips or arch == mips64', { + # TODO(mips-team): Implement I64Atomic operations on MIPS + 'test-run-wasm-atomics64/*': [SKIP], +}], # 'arch == mipsel or arch == mips64el or arch == mips or arch == mips64' + ############################################################################## ['mips_arch_variant == r6', { # For MIPS[64] architecture release 6, fusion multiply-accumulate instructions diff --git a/test/cctest/test-disasm-arm.cc b/test/cctest/test-disasm-arm.cc index 232e2799ab..877ae6665f 100644 --- a/test/cctest/test-disasm-arm.cc +++ b/test/cctest/test-disasm-arm.cc @@ -1615,8 +1615,8 @@ TEST(LoadStoreExclusive) { COMPARE(strexh(r0, r1, r2), "e1e20f91 strexh r0, r1, [r2]"); COMPARE(ldrex(r0, r1), "e1910f9f ldrex r0, [r1]"); COMPARE(strex(r0, r1, r2), "e1820f91 strex r0, r1, [r2]"); - COMPARE(ldrexd(r0, r1, MemOperand(r2)), "e1b20f9f ldrexd r0, [r2]"); - COMPARE(strexd(r0, r2, r3, MemOperand(r4)), + COMPARE(ldrexd(r0, r1, r2), "e1b20f9f ldrexd r0, [r2]"); + COMPARE(strexd(r0, r2, r3, r4), "e1a40f92 strexd r0, r2, [r4]"); VERIFY_RUN();