Index: src/compiler/arm/code-generator-arm.cc |
diff --git a/src/compiler/arm/code-generator-arm.cc b/src/compiler/arm/code-generator-arm.cc |
index 7ae9ded68b5ea5a1d3ad629f8c0d81a86c2c972e..bc3356f2fe4aa33dfe97b27d567899bcec4aa1b6 100644 |
--- a/src/compiler/arm/code-generator-arm.cc |
+++ b/src/compiler/arm/code-generator-arm.cc |
@@ -433,6 +433,27 @@ Condition FlagsConditionToCondition(FlagsCondition condition) { |
__ dmb(ISH); \ |
} while (0) |
+#define ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(load_instr, store_instr, \ |
+ mask) \ |
+ do { \ |
+ Label compareExchange; \ |
+ Label exit; \ |
+ __ dmb(ISH); \ |
binji
2017/02/28 23:28:53
The optimized code is a bit hard to follow, but th
|
+ __ bind(&compareExchange); \ |
+ __ add(i.TempRegister(0), i.InputRegister(0), i.InputRegister(1)); \ |
+ __ load_instr(i.OutputRegister(0), i.TempRegister(0)); \ |
+ __ eor(i.TempRegister(1), i.OutputRegister(0), \ |
+ Operand(i.InputRegister(2))); \ |
+ __ And(i.TempRegister(1), i.TempRegister(1), Operand(mask)); \ |
+ __ teq(i.TempRegister(1), Operand(0)); \ |
+ __ b(ne, &exit); \ |
+ __ store_instr(i.TempRegister(0), i.InputRegister(3), i.TempRegister(0)); \ |
+ __ teq(i.TempRegister(0), Operand(0)); \ |
+ __ b(ne, &compareExchange); \ |
+ __ bind(&exit); \ |
+ __ dmb(ISH); \ |
+ } while (0) |
+ |
#define ASSEMBLE_IEEE754_BINOP(name) \ |
do { \ |
/* TODO(bmeurer): We should really get rid of this special instruction, */ \ |
@@ -2039,6 +2060,25 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction( |
case kAtomicExchangeWord32: |
ASSEMBLE_ATOMIC_EXCHANGE_INTEGER(ldrex, strex); |
break; |
+ case kAtomicCompareExchangeInt8: |
+ ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexb, strexb, 0x000000ff); |
+ __ sxtb(i.OutputRegister(0), i.OutputRegister(0)); |
+ break; |
+ case kAtomicCompareExchangeUint8: |
+ ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexb, strexb, 0x000000ff); |
+ __ uxtb(i.OutputRegister(0), i.OutputRegister(0)); |
+ break; |
+ case kAtomicCompareExchangeInt16: |
+ ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexh, strexh, 0x0000ffff); |
+ __ sxth(i.OutputRegister(0), i.OutputRegister(0)); |
+ break; |
+ case kAtomicCompareExchangeUint16: |
+ ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrexh, strexh, 0x0000ffff); |
+ __ uxth(i.OutputRegister(0), i.OutputRegister(0)); |
+ break; |
+ case kAtomicCompareExchangeWord32: |
+ ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_INTEGER(ldrex, strex, 0xffffffff); |
+ break; |
} |
return kSuccess; |
} // NOLINT(readability/fn_size) |