Commit 7cbb7db7 authored by Junliang Yan's avatar Junliang Yan Committed by Commit Bot

s390x: Refactor compare swap to turbo assembler

Change-Id: Ic1c0b725e810468938f2ac6b990cade8fd4204cc
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2794430Reviewed-by: 's avatarMilad Fa <mfarazma@redhat.com>
Commit-Queue: Junliang Yan <junyan@redhat.com>
Cr-Commit-Position: refs/heads/master@{#73730}
parent 34802532
......@@ -4761,6 +4761,110 @@ void TurboAssembler::CountTrailingZerosU64(Register dst, Register src,
bind(&done);
}
void TurboAssembler::AtomicCmpExchangeHelper(Register addr, Register output,
Register old_value,
Register new_value, int start,
int end, int shift_amount,
int offset, Register temp0,
Register temp1) {
LoadU32(temp0, MemOperand(addr, offset));
llgfr(temp1, temp0);
RotateInsertSelectBits(temp0, old_value, Operand(start), Operand(end),
Operand(shift_amount), false);
RotateInsertSelectBits(temp1, new_value, Operand(start), Operand(end),
Operand(shift_amount), false);
CmpAndSwap(temp0, temp1, MemOperand(addr, offset));
RotateInsertSelectBits(output, temp0, Operand(start + shift_amount),
Operand(end + shift_amount),
Operand(64 - shift_amount), true);
}
void TurboAssembler::AtomicCmpExchangeU8(Register addr, Register output,
Register old_value, Register new_value,
Register temp0, Register temp1) {
#ifdef V8_TARGET_BIG_ENDIAN
#define ATOMIC_COMP_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; \
AtomicCmpExchangeHelper(addr, output, old_value, new_value, start, end, \
shift_amount, -idx, temp0, temp1); \
}
#else
#define ATOMIC_COMP_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; \
AtomicCmpExchangeHelper(addr, output, old_value, new_value, start, end, \
shift_amount, -idx, temp0, temp1); \
}
#endif
Label one, two, three, done;
tmll(addr, Operand(3));
b(Condition(1), &three);
b(Condition(2), &two);
b(Condition(4), &one);
/* ending with 0b00 */
ATOMIC_COMP_EXCHANGE_BYTE(0);
b(&done);
/* ending with 0b01 */
bind(&one);
ATOMIC_COMP_EXCHANGE_BYTE(1);
b(&done);
/* ending with 0b10 */
bind(&two);
ATOMIC_COMP_EXCHANGE_BYTE(2);
b(&done);
/* ending with 0b11 */
bind(&three);
ATOMIC_COMP_EXCHANGE_BYTE(3);
bind(&done);
}
void TurboAssembler::AtomicCmpExchangeU16(Register addr, Register output,
Register old_value,
Register new_value, Register temp0,
Register temp1) {
#ifdef V8_TARGET_BIG_ENDIAN
#define ATOMIC_COMP_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; \
AtomicCmpExchangeHelper(addr, output, old_value, new_value, start, end, \
shift_amount, -idx * 2, temp0, temp1); \
}
#else
#define ATOMIC_COMP_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; \
AtomicCmpExchangeHelper(addr, output, old_value, new_value, start, end, \
shift_amount, -idx * 2, temp0, temp1); \
}
#endif
Label two, done;
tmll(addr, Operand(3));
b(Condition(2), &two);
ATOMIC_COMP_EXCHANGE_HALFWORD(0);
b(&done);
bind(&two);
ATOMIC_COMP_EXCHANGE_HALFWORD(1);
bind(&done);
}
} // namespace internal
} // namespace v8
......
......@@ -46,6 +46,15 @@ class V8_EXPORT_PRIVATE TurboAssembler : public TurboAssemblerBase {
public:
using TurboAssemblerBase::TurboAssemblerBase;
void AtomicCmpExchangeHelper(Register addr, Register output,
Register old_value, Register new_value,
int start, int end, int shift_amount, int offset,
Register temp0, Register temp1);
void AtomicCmpExchangeU8(Register addr, Register output, Register old_value,
Register new_value, Register temp0, Register temp1);
void AtomicCmpExchangeU16(Register addr, Register output, Register old_value,
Register new_value, Register temp0, Register temp1);
void DoubleMax(DoubleRegister result_reg, DoubleRegister left_reg,
DoubleRegister right_reg);
void DoubleMin(DoubleRegister result_reg, DoubleRegister left_reg,
......
......@@ -730,116 +730,37 @@ static inline int AssembleUnaryOp(Instruction* instr, _R _r, _M _m, _I _i) {
__ asm_instr(value, operand); \
} while (0)
#define ATOMIC_COMP_EXCHANGE(start, end, shift_amount, offset) \
{ \
__ LoadU32(temp0, MemOperand(addr, offset)); \
__ llgfr(temp1, temp0); \
__ RotateInsertSelectBits(temp0, old_val, Operand(start), Operand(end), \
Operand(shift_amount), false); \
__ RotateInsertSelectBits(temp1, new_val, Operand(start), Operand(end), \
Operand(shift_amount), false); \
__ CmpAndSwap(temp0, temp1, MemOperand(addr, offset)); \
__ RotateInsertSelectBits(output, temp0, Operand(start + shift_amount), \
Operand(end + shift_amount), \
Operand(64 - shift_amount), true); \
}
#ifdef V8_TARGET_BIG_ENDIAN
#define ATOMIC_COMP_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_COMP_EXCHANGE(start, end, shift_amount, -idx); \
}
#define ATOMIC_COMP_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_COMP_EXCHANGE(start, end, shift_amount, -idx * 2); \
}
#else
#define ATOMIC_COMP_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_COMP_EXCHANGE(start, end, shift_amount, -idx); \
}
#define ATOMIC_COMP_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_COMP_EXCHANGE(start, end, shift_amount, -idx * 2); \
}
#endif
#define ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_BYTE(load_and_ext) \
do { \
Register old_val = i.InputRegister(0); \
Register new_val = i.InputRegister(1); \
Register output = i.OutputRegister(); \
Register addr = kScratchReg; \
Register temp0 = r0; \
Register temp1 = r1; \
size_t index = 2; \
AddressingMode mode = kMode_None; \
MemOperand op = i.MemoryOperand(&mode, &index); \
Label three, two, one, done; \
__ lay(addr, op); \
__ tmll(addr, Operand(3)); \
__ b(Condition(1), &three); \
__ b(Condition(2), &two); \
__ b(Condition(4), &one); \
/* ending with 0b00 */ \
ATOMIC_COMP_EXCHANGE_BYTE(0); \
__ b(&done); \
/* ending with 0b01 */ \
__ bind(&one); \
ATOMIC_COMP_EXCHANGE_BYTE(1); \
__ b(&done); \
/* ending with 0b10 */ \
__ bind(&two); \
ATOMIC_COMP_EXCHANGE_BYTE(2); \
__ b(&done); \
/* ending with 0b11 */ \
__ bind(&three); \
ATOMIC_COMP_EXCHANGE_BYTE(3); \
__ bind(&done); \
__ load_and_ext(output, output); \
#define ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_BYTE(load_and_ext) \
do { \
Register old_value = i.InputRegister(0); \
Register new_value = i.InputRegister(1); \
Register output = i.OutputRegister(); \
Register addr = kScratchReg; \
Register temp0 = r0; \
Register temp1 = r1; \
size_t index = 2; \
AddressingMode mode = kMode_None; \
MemOperand op = i.MemoryOperand(&mode, &index); \
__ lay(addr, op); \
__ AtomicCmpExchangeU8(addr, output, old_value, new_value, temp0, temp1); \
__ load_and_ext(output, output); \
} while (false)
#define ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_HALFWORD(load_and_ext) \
do { \
Register old_val = i.InputRegister(0); \
Register new_val = i.InputRegister(1); \
Register output = i.OutputRegister(); \
Register addr = kScratchReg; \
Register temp0 = r0; \
Register temp1 = r1; \
size_t index = 2; \
AddressingMode mode = kMode_None; \
MemOperand op = i.MemoryOperand(&mode, &index); \
Label two, done; \
__ lay(addr, op); \
__ tmll(addr, Operand(3)); \
__ b(Condition(2), &two); \
ATOMIC_COMP_EXCHANGE_HALFWORD(0); \
__ b(&done); \
__ bind(&two); \
ATOMIC_COMP_EXCHANGE_HALFWORD(1); \
__ bind(&done); \
__ load_and_ext(output, output); \
#define ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_HALFWORD(load_and_ext) \
do { \
Register old_value = i.InputRegister(0); \
Register new_value = i.InputRegister(1); \
Register output = i.OutputRegister(); \
Register addr = kScratchReg; \
Register temp0 = r0; \
Register temp1 = r1; \
size_t index = 2; \
AddressingMode mode = kMode_None; \
MemOperand op = i.MemoryOperand(&mode, &index); \
Label two, done; \
__ lay(addr, op); \
__ AtomicCmpExchangeU16(addr, output, old_value, new_value, temp0, temp1); \
__ load_and_ext(output, output); \
} while (false)
#define ASSEMBLE_ATOMIC_COMPARE_EXCHANGE_WORD() \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment