| Index: src/compiler/s390/code-generator-s390.cc
|
| diff --git a/src/compiler/s390/code-generator-s390.cc b/src/compiler/s390/code-generator-s390.cc
|
| index 377feada5161927317c87535018c95c2e8a8f5ec..916323b22c74066b7445fc0beda43ec9de0f55a2 100644
|
| --- a/src/compiler/s390/code-generator-s390.cc
|
| +++ b/src/compiler/s390/code-generator-s390.cc
|
| @@ -2260,13 +2260,138 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
|
| case kAtomicStoreWord32:
|
| __ StoreW(i.InputRegister(0), i.MemoryOperand(NULL, 1));
|
| break;
|
| +// 0x aa bb cc dd
|
| +// index = 3..2..1..0
|
| +#define ATOMIC_EXCHANGE(start, end, shift_amount, offset) \
|
| + { \
|
| + Label do_cs; \
|
| + __ LoadlW(output, MemOperand(r1)); \
|
| + __ bind(&do_cs); \
|
| + __ llgfr(r0, output); \
|
| + __ risbg(r0, value, Operand(start), Operand(end), Operand(shift_amount), \
|
| + false); \
|
| + __ csy(output, r0, MemOperand(r1, offset)); \
|
| + __ bne(&do_cs, Label::kNear); \
|
| + __ srl(output, Operand(shift_amount)); \
|
| + }
|
| +#ifdef V8_TARGET_BIG_ENDIAN
|
| +#define ATOMIC_EXCHANGE_BYTE(i) \
|
| + { \
|
| + constexpr int idx = (i); \
|
| + static_assert(idx <= 3 && idx >= 0, "idx is out of range!"); \
|
| + constexpr int start = 32 + 8 * idx; \
|
| + constexpr int end = start + 7; \
|
| + constexpr int shift_amount = (3 - idx) * 8; \
|
| + ATOMIC_EXCHANGE(start, end, shift_amount, -idx); \
|
| + }
|
| +#define ATOMIC_EXCHANGE_HALFWORD(i) \
|
| + { \
|
| + constexpr int idx = (i); \
|
| + static_assert(idx <= 1 && idx >= 0, "idx is out of range!"); \
|
| + constexpr int start = 32 + 16 * idx; \
|
| + constexpr int end = start + 15; \
|
| + constexpr int shift_amount = (1 - idx) * 16; \
|
| + ATOMIC_EXCHANGE(start, end, shift_amount, -idx * 2); \
|
| + }
|
| +#else
|
| +#define ATOMIC_EXCHANGE_BYTE(i) \
|
| + { \
|
| + constexpr int idx = (i); \
|
| + static_assert(idx <= 3 && idx >= 0, "idx is out of range!"); \
|
| + constexpr int start = 32 + 8 * (3 - idx); \
|
| + constexpr int end = start + 7; \
|
| + constexpr int shift_amount = idx * 8; \
|
| + ATOMIC_EXCHANGE(start, end, shift_amount, -idx); \
|
| + }
|
| +#define ATOMIC_EXCHANGE_HALFWORD(i) \
|
| + { \
|
| + constexpr int idx = (i); \
|
| + static_assert(idx <= 1 && idx >= 0, "idx is out of range!"); \
|
| + constexpr int start = 32 + 16 * (1 - idx); \
|
| + constexpr int end = start + 15; \
|
| + constexpr int shift_amount = idx * 16; \
|
| + ATOMIC_EXCHANGE(start, end, shift_amount, -idx * 2); \
|
| + }
|
| +#endif
|
| case kAtomicExchangeInt8:
|
| - case kAtomicExchangeUint8:
|
| + case kAtomicExchangeUint8: {
|
| + Register base = i.InputRegister(0);
|
| + Register index = i.InputRegister(1);
|
| + Register value = i.InputRegister(2);
|
| + Register output = i.OutputRegister();
|
| + Label three, two, one, done;
|
| + __ la(r1, MemOperand(base, index));
|
| + __ tmll(r1, Operand(3));
|
| + __ b(Condition(1), &three);
|
| + __ b(Condition(2), &two);
|
| + __ b(Condition(4), &one);
|
| +
|
| + // end with 0b00
|
| + ATOMIC_EXCHANGE_BYTE(0);
|
| + __ b(&done);
|
| +
|
| + // ending with 0b01
|
| + __ bind(&one);
|
| + ATOMIC_EXCHANGE_BYTE(1);
|
| + __ b(&done);
|
| +
|
| + // ending with 0b10
|
| + __ bind(&two);
|
| + ATOMIC_EXCHANGE_BYTE(2);
|
| + __ b(&done);
|
| +
|
| + // ending with 0b11
|
| + __ bind(&three);
|
| + ATOMIC_EXCHANGE_BYTE(3);
|
| +
|
| + __ bind(&done);
|
| + if (opcode == kAtomicExchangeInt8) {
|
| + __ lbr(output, output);
|
| + } else {
|
| + __ llcr(output, output);
|
| + }
|
| + break;
|
| + }
|
| case kAtomicExchangeInt16:
|
| - case kAtomicExchangeUint16:
|
| - case kAtomicExchangeWord32:
|
| - UNREACHABLE();
|
| + case kAtomicExchangeUint16: {
|
| + Register base = i.InputRegister(0);
|
| + Register index = i.InputRegister(1);
|
| + Register value = i.InputRegister(2);
|
| + Register output = i.OutputRegister();
|
| + Label two, unaligned, done;
|
| + __ la(r1, MemOperand(base, index));
|
| + __ tmll(r1, Operand(3));
|
| + __ b(Condition(2), &two);
|
| +
|
| + // end with 0b00
|
| + ATOMIC_EXCHANGE_HALFWORD(0);
|
| + __ b(&done);
|
| +
|
| + // ending with 0b10
|
| + __ bind(&two);
|
| + ATOMIC_EXCHANGE_HALFWORD(1);
|
| +
|
| + __ bind(&done);
|
| + if (opcode == kAtomicExchangeInt8) {
|
| + __ lhr(output, output);
|
| + } else {
|
| + __ llhr(output, output);
|
| + }
|
| break;
|
| + }
|
| + case kAtomicExchangeWord32: {
|
| + Register base = i.InputRegister(0);
|
| + Register index = i.InputRegister(1);
|
| + Register value = i.InputRegister(2);
|
| + Register output = i.OutputRegister();
|
| + Label do_cs;
|
| + __ lay(r1, MemOperand(base, index));
|
| + __ LoadlW(output, MemOperand(r1));
|
| + __ bind(&do_cs);
|
| + __ cs(output, value, MemOperand(r1));
|
| + __ bne(&do_cs, Label::kNear);
|
| + break;
|
| + }
|
| default:
|
| UNREACHABLE();
|
| break;
|
|
|