Commit 7260f62b authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[wasm][ia32][liftoff] Implement AtomicAdd except AtomicAddU64

This CL
* Adds the xadd instruction to the ia32 assembler and disassembler;
* Implements the AtomicAdd instructions, except AtomicAddU64, on ia32;

R=clemensb@chromium.org

Bug: v8:10108
Change-Id: Ic8653a9f96148282951104fefb4185c4c0db89a3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2232719Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68247}
parent 17f8f12b
......@@ -691,6 +691,29 @@ void Assembler::stos() {
EMIT(0xAB);
}
void Assembler::xadd(Operand dst, Register src) {
EnsureSpace ensure_space(this);
EMIT(0x0F);
EMIT(0xC1);
emit_operand(src, dst);
}
void Assembler::xadd_b(Operand dst, Register src) {
DCHECK(src.is_byte_register());
EnsureSpace ensure_space(this);
EMIT(0x0F);
EMIT(0xC0);
emit_operand(src, dst);
}
void Assembler::xadd_w(Operand dst, Register src) {
EnsureSpace ensure_space(this);
EMIT(0x66);
EMIT(0x0F);
EMIT(0xC1);
emit_operand(src, dst);
}
void Assembler::xchg(Register dst, Register src) {
EnsureSpace ensure_space(this);
if (src == eax || dst == eax) { // Single-byte encoding.
......
......@@ -528,6 +528,10 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
void rep_stos();
void stos();
void xadd(Operand dst, Register src);
void xadd_b(Operand dst, Register src);
void xadd_w(Operand dst, Register src);
// Exchange
void xchg(Register dst, Register src);
void xchg(Register dst, Operand src);
......
......@@ -1847,6 +1847,12 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
AppendToBuffer("movmskps %s,%s", NameOfCPURegister(regop),
NameOfXMMRegister(rm));
data++;
} else if (f0byte == 0xC0) {
data += 2;
data += PrintOperands("xadd_b", OPER_REG_OP_ORDER, data);
} else if (f0byte == 0xC1) {
data += 2;
data += PrintOperands("xadd", OPER_REG_OP_ORDER, data);
} else if (f0byte == 0xC2) {
data += 2;
int mod, regop, rm;
......@@ -2318,6 +2324,9 @@ int DisassemblerIA32::InstructionDecode(v8::internal::Vector<char> out_buffer,
AppendToBuffer("movd ");
data += PrintRightOperand(data);
AppendToBuffer(",%s", NameOfXMMRegister(regop));
} else if (*data == 0xC1) {
data += 2;
data += PrintOperands("xadd_w", OPER_REG_OP_ORDER, data);
} else if (*data == 0xC2) {
data++;
int mod, regop, rm;
......
......@@ -490,7 +490,56 @@ void LiftoffAssembler::AtomicStore(Register dst_addr, Register offset_reg,
void LiftoffAssembler::AtomicAdd(Register dst_addr, Register offset_reg,
uint32_t offset_imm, LiftoffRegister value,
LiftoffRegister result, StoreType type) {
bailout(kAtomics, "AtomicAdd");
if (type.value() == StoreType::kI64Store) {
bailout(kAtomics, "AtomicAdd");
return;
}
DCHECK_EQ(value, result);
DCHECK(!cache_state()->is_used(result));
bool is_64_bit_op = type.value_type() == kWasmI64;
Register value_reg = is_64_bit_op ? value.low_gp() : value.gp();
Register result_reg = is_64_bit_op ? result.low_gp() : result.gp();
bool is_byte_store = type.size() == 1;
LiftoffRegList pinned =
LiftoffRegList::ForRegs(dst_addr, value_reg, offset_reg);
// Ensure that {value_reg} is a valid register.
if (is_byte_store && !liftoff::kByteRegs.has(value_reg)) {
Register safe_value_reg =
GetUnusedRegister(liftoff::kByteRegs, pinned).gp();
mov(safe_value_reg, value_reg);
value_reg = safe_value_reg;
}
Operand dst_op = Operand(dst_addr, offset_reg, times_1, offset_imm);
lock();
switch (type.value()) {
case StoreType::kI64Store8:
case StoreType::kI32Store8:
xadd_b(dst_op, value_reg);
movzx_b(result_reg, value_reg);
break;
case StoreType::kI64Store16:
case StoreType::kI32Store16:
xadd_w(dst_op, value_reg);
movzx_w(result_reg, value_reg);
break;
case StoreType::kI64Store32:
case StoreType::kI32Store:
xadd(dst_op, value_reg);
if (value_reg != result_reg) {
mov(result_reg, value_reg);
}
break;
default:
UNREACHABLE();
}
if (is_64_bit_op) {
xor_(result.high_gp(), result.high_gp());
}
}
void LiftoffAssembler::AtomicSub(Register dst_addr, Register offset_reg,
......
......@@ -938,6 +938,12 @@ TEST(DisasmIa320) {
}
}
// xadd.
{
__ xadd(Operand(eax, 8), eax);
__ xadd_w(Operand(ebx, 8), eax);
__ xadd_b(Operand(ebx, 8), eax);
}
// xchg.
{
__ xchg_b(eax, Operand(eax, 8));
......
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