Commit 1c3b3e99 authored by Vasili Skurydzin's avatar Vasili Skurydzin Committed by Commit Bot

s390: Implement Word32 atomic binary operations using LAA/LAN/LAO/LAX

Change-Id: I97cdf61a15c2141d3c552a792ac08c9865f272ff
Reviewed-on: https://chromium-review.googlesource.com/1066307
Commit-Queue: Junliang Yan <jyan@ca.ibm.com>
Reviewed-by: 's avatarJoran Siu <joransiu@ca.ibm.com>
Cr-Commit-Position: refs/heads/master@{#53291}
parent f46c6037
......@@ -1019,26 +1019,16 @@ static inline int AssembleUnaryOp(Instruction* instr, _R _r, _M _m, _I _i) {
__ CmpAndSwap(output, new_val, MemOperand(addr)); \
} while (false)
// TODO(vasili.skurydzin): use immediate operand for value and
// SI-formatted instructions (i.e. ASI/AGSI for add) to update
// memory atomically
#define ASSEMBLE_ATOMIC_BINOP_WORD(bin_inst, load_and_ext) \
#define ASSEMBLE_ATOMIC_BINOP_WORD(load_and_op) \
do { \
Register value = i.InputRegister(2); \
Register result = i.OutputRegister(0); \
Register addr = r1; \
Register prev = r0; \
Register next = kScratchReg; \
AddressingMode mode = kMode_None; \
MemOperand op = i.MemoryOperand(&mode); \
Label do_cs; \
__ lay(addr, op); \
__ l(prev, MemOperand(addr)); \
__ bind(&do_cs); \
__ bin_inst(next, prev, value); \
__ CmpAndSwap(prev, next, MemOperand(addr)); \
__ bne(&do_cs, Label::kNear); \
__ load_and_ext(result, prev); \
__ load_and_op(result, value, MemOperand(addr)); \
__ LoadlW(result, result); \
} while (false)
#define ATOMIC_BIN_OP(bin_inst, offset, shift_amount, start, end) \
......@@ -2724,9 +2714,6 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ risbg(result, prev, Operand(48), Operand(63), \
Operand(static_cast<intptr_t>(rotate_left)), true); \
}); \
break; \
case kWord32Atomic##op##Word32: \
ASSEMBLE_ATOMIC_BINOP_WORD(inst, LoadlW); \
break;
ATOMIC_BINOP_CASE(Add, Add32)
ATOMIC_BINOP_CASE(Sub, Sub32)
......@@ -2734,7 +2721,21 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
ATOMIC_BINOP_CASE(Or, Or)
ATOMIC_BINOP_CASE(Xor, Xor)
#undef ATOMIC_BINOP_CASE
case kWord32AtomicAddWord32:
ASSEMBLE_ATOMIC_BINOP_WORD(laa);
break;
case kWord32AtomicSubWord32:
ASSEMBLE_ATOMIC_BINOP_WORD(LoadAndSub32);
break;
case kWord32AtomicAndWord32:
ASSEMBLE_ATOMIC_BINOP_WORD(lan);
break;
case kWord32AtomicOrWord32:
ASSEMBLE_ATOMIC_BINOP_WORD(lao);
break;
case kWord32AtomicXorWord32:
ASSEMBLE_ATOMIC_BINOP_WORD(lax);
break;
default:
UNREACHABLE();
break;
......
......@@ -2869,6 +2869,13 @@ void TurboAssembler::SubP_ExtendSrc(Register dst, const MemOperand& opnd) {
#endif
}
// Load And Subtract 32-bit (similar to laa/lan/lao/lax)
void TurboAssembler::LoadAndSub32(Register dst, Register src,
const MemOperand& opnd) {
lcr(dst, src);
laa(dst, dst, opnd);
}
//----------------------------------------------------------------------------
// Subtract Logical Instructions
//----------------------------------------------------------------------------
......
......@@ -333,6 +333,7 @@ class TurboAssembler : public Assembler {
void Sub32(Register dst, const MemOperand& opnd);
void SubP(Register dst, const MemOperand& opnd);
void SubP_ExtendSrc(Register dst, const MemOperand& opnd);
void LoadAndSub32(Register dst, Register src, const MemOperand& opnd);
// Subtract Logical (Register - Mem)
void SubLogical(Register dst, const MemOperand& opnd);
......
......@@ -9194,28 +9194,38 @@ EVALUATE(STOC) {
return 0;
}
#define ATOMIC_LOAD_AND_UPDATE_WORD32(op) \
DECODE_RSY_A_INSTRUCTION(r1, r3, b2, d2); \
int64_t b2_val = (b2 == 0) ? 0 : get_register(b2); \
intptr_t addr = static_cast<intptr_t>(b2_val) + d2; \
int32_t r3_val = get_low_register<int32_t>(r3); \
DCHECK_EQ(target_addr & 0x3, 0); \
int32_t r1_val = op(reinterpret_cast<int32_t*>(addr), \
r3_val, __ATOMIC_SEQ_CST); \
set_low_register(r1, r1_val);
EVALUATE(LAN) {
UNIMPLEMENTED();
USE(instr);
return 0;
DCHECK_OPCODE(LAN);
ATOMIC_LOAD_AND_UPDATE_WORD32(__atomic_fetch_and);
return length;
}
EVALUATE(LAO) {
UNIMPLEMENTED();
USE(instr);
return 0;
DCHECK_OPCODE(LAO);
ATOMIC_LOAD_AND_UPDATE_WORD32(__atomic_fetch_or);
return length;
}
EVALUATE(LAX) {
UNIMPLEMENTED();
USE(instr);
return 0;
DCHECK_OPCODE(LAX);
ATOMIC_LOAD_AND_UPDATE_WORD32(__atomic_fetch_xor);
return length;
}
EVALUATE(LAA) {
UNIMPLEMENTED();
USE(instr);
return 0;
DCHECK_OPCODE(LAA);
ATOMIC_LOAD_AND_UPDATE_WORD32(__atomic_fetch_add);
return length;
}
EVALUATE(LAAL) {
......@@ -9224,6 +9234,8 @@ EVALUATE(LAAL) {
return 0;
}
#undef ATOMIC_LOAD_AND_UPDATE_WORD32
EVALUATE(BRXHG) {
UNIMPLEMENTED();
USE(instr);
......
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