Commit f506c609 authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[x64] Implement xadd in the assembler

This CL introduces the xadd instruction to the x64 assembler so it can
be used to implement WebAssembly's AtomicAdd. This is done in a
separate CL though.

R=clemensb@chromium.org

Bug: v8:10108
Change-Id: I36dcb900ed4c39b23c4996328774780afd8b816a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2011105
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65879}
parent 99641cb4
......@@ -1202,6 +1202,39 @@ void Assembler::lock() {
emit(0xF0);
}
void Assembler::xaddb(Operand dst, Register src) {
EnsureSpace ensure_space(this);
emit_optional_rex_32(src, dst);
emit(0x0F);
emit(0xC0);
emit_operand(src, dst);
}
void Assembler::xaddw(Operand dst, Register src) {
EnsureSpace ensure_space(this);
emit(0x66);
emit_optional_rex_32(src, dst);
emit(0x0F);
emit(0xC1);
emit_operand(src, dst);
}
void Assembler::xaddl(Operand dst, Register src) {
EnsureSpace ensure_space(this);
emit_optional_rex_32(src, dst);
emit(0x0F);
emit(0xC1);
emit_operand(src, dst);
}
void Assembler::xaddq(Operand dst, Register src) {
EnsureSpace ensure_space(this);
emit_rex(src, dst, kInt64Size);
emit(0x0F);
emit(0xC1);
emit_operand(src, dst);
}
void Assembler::cmpxchgb(Operand dst, Register src) {
EnsureSpace ensure_space(this);
if (!src.is_byte_register()) {
......
......@@ -607,6 +607,11 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
void xchgb(Register reg, Operand op);
void xchgw(Register reg, Operand op);
void xaddb(Operand dst, Register src);
void xaddw(Operand dst, Register src);
void xaddl(Operand dst, Register src);
void xaddq(Operand dst, Register src);
void cmpxchgb(Operand dst, Register src);
void cmpxchgw(Operand dst, Register src);
......
......@@ -1890,6 +1890,8 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
} else {
UnimplementedInstruction();
}
} else if (opcode == 0xC1) {
current += PrintOperands("xadd", OPER_REG_OP_ORDER, current);
} else {
get_modrm(*current, &mod, &regop, &rm);
if (opcode == 0x1F) {
......@@ -2030,6 +2032,8 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
mnemonic = "pcmpeqw";
} else if (opcode == 0x76) {
mnemonic = "pcmpeqd";
} else if (opcode == 0xC2) {
mnemonic = "cmppd";
} else if (opcode == 0xD1) {
mnemonic = "psrlw";
} else if (opcode == 0xD2) {
......@@ -2102,8 +2106,6 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
mnemonic = "paddw";
} else if (opcode == 0xFE) {
mnemonic = "paddd";
} else if (opcode == 0xC2) {
mnemonic = "cmppd";
} else {
UnimplementedInstruction();
}
......@@ -2366,6 +2368,11 @@ int DisassemblerX64::TwoByteOpcodeInstruction(byte* data) {
NameOfXMMRegister(regop));
current += PrintRightXMMOperand(current);
} else if (opcode == 0xC0) {
byte_size_operand_ = true;
current += PrintOperands("xadd", OPER_REG_OP_ORDER, current);
} else if (opcode == 0xC1) {
current += PrintOperands("xadd", OPER_REG_OP_ORDER, current);
} else if (opcode == 0xC2) {
// cmpps xmm, xmm/m128, imm8
int mod, regop, rm;
......
......@@ -919,6 +919,18 @@ TEST(DisasmX64) {
__ cmpxchgq(Operand(rbx, rcx, times_4, 10000), rax);
}
// xadd.
{
__ xaddb(Operand(rsp, 12), rax);
__ xaddw(Operand(rsp, 12), rax);
__ xaddl(Operand(rsp, 12), rax);
__ xaddq(Operand(rsp, 12), rax);
__ xaddb(Operand(rbx, rcx, times_4, 10000), rax);
__ xaddw(Operand(rbx, rcx, times_4, 10000), rax);
__ xaddl(Operand(rbx, rcx, times_4, 10000), rax);
__ xaddq(Operand(rbx, rcx, times_4, 10000), rax);
}
// lock prefix.
{
__ lock();
......
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