[x64] Introduce negb and negw instructions
This CL introduces the negb and negw instructions (8-bit and 16-bit versions of neg) in the x64 assembler. These instructions are needed to implement I32AtomicSub8U and similar WebAssembly instructions efficiently. The existing implementation was embedded in a generic macro, and it was difficult to change it without introducing also the 8-bit and 16-bit versions of many other instructions. This would have introduced a lot of dead code. Instead this CL extracted the neg instructions from the macro and implements them directly. This should be fine because the assembler does not change much, and approachability of the code is improved. R=clemensb@chromium.org Bug: v8:10108 Change-Id: I46099bbebd47f864311a67da3ba8ddc4fe4cd35d Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2019165 Commit-Queue: Andreas Haas <ahaas@chromium.org> Reviewed-by: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/master@{#65989}
This commit is contained in:
parent
261a22e258
commit
911f38c411
@ -142,6 +142,22 @@ void Assembler::emit_optional_rex_32(Operand op) {
|
||||
if (op.data().rex != 0) emit(0x40 | op.data().rex);
|
||||
}
|
||||
|
||||
void Assembler::emit_optional_rex_8(Register reg) {
|
||||
if (!reg.is_byte_register()) {
|
||||
// Register is not one of al, bl, cl, dl. Its encoding needs REX.
|
||||
emit_rex_32(reg);
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::emit_optional_rex_8(Register reg, Operand op) {
|
||||
if (!reg.is_byte_register()) {
|
||||
// Register is not one of al, bl, cl, dl. Its encoding needs REX.
|
||||
emit_rex_32(reg, op);
|
||||
} else {
|
||||
emit_optional_rex_32(reg, op);
|
||||
}
|
||||
}
|
||||
|
||||
// byte 1 of 3-byte VEX
|
||||
void Assembler::emit_vex3_byte1(XMMRegister reg, XMMRegister rm,
|
||||
LeadingOpcode m) {
|
||||
|
@ -1204,12 +1204,7 @@ void Assembler::lock() {
|
||||
|
||||
void Assembler::xaddb(Operand dst, Register src) {
|
||||
EnsureSpace ensure_space(this);
|
||||
if (!src.is_byte_register()) {
|
||||
// Register is not one of al, bl, cl, dl. Its encoding needs REX.
|
||||
emit_rex_32(src, dst);
|
||||
} else {
|
||||
emit_optional_rex_32(src, dst);
|
||||
}
|
||||
emit_optional_rex_8(src, dst);
|
||||
emit(0x0F);
|
||||
emit(0xC0);
|
||||
emit_operand(src, dst);
|
||||
@ -2012,18 +2007,62 @@ void Assembler::mulq(Register src) {
|
||||
emit_modrm(0x4, src);
|
||||
}
|
||||
|
||||
void Assembler::emit_neg(Register dst, int size) {
|
||||
void Assembler::negb(Register reg) {
|
||||
EnsureSpace ensure_space(this);
|
||||
emit_rex(dst, size);
|
||||
emit(0xF7);
|
||||
emit_modrm(0x3, dst);
|
||||
emit_optional_rex_8(reg);
|
||||
emit(0xF6);
|
||||
emit_modrm(0x3, reg);
|
||||
}
|
||||
|
||||
void Assembler::emit_neg(Operand dst, int size) {
|
||||
void Assembler::negw(Register reg) {
|
||||
EnsureSpace ensure_space(this);
|
||||
emit_rex_64(dst);
|
||||
emit(0x66);
|
||||
emit_optional_rex_32(reg);
|
||||
emit(0xF7);
|
||||
emit_operand(3, dst);
|
||||
emit_modrm(0x3, reg);
|
||||
}
|
||||
|
||||
void Assembler::negl(Register reg) {
|
||||
EnsureSpace ensure_space(this);
|
||||
emit_optional_rex_32(reg);
|
||||
emit(0xF7);
|
||||
emit_modrm(0x3, reg);
|
||||
}
|
||||
|
||||
void Assembler::negq(Register reg) {
|
||||
EnsureSpace ensure_space(this);
|
||||
emit_rex_64(reg);
|
||||
emit(0xF7);
|
||||
emit_modrm(0x3, reg);
|
||||
}
|
||||
|
||||
void Assembler::negb(Operand op) {
|
||||
EnsureSpace ensure_space(this);
|
||||
emit_optional_rex_32(op);
|
||||
emit(0xF6);
|
||||
emit_operand(0x3, op);
|
||||
}
|
||||
|
||||
void Assembler::negw(Operand op) {
|
||||
EnsureSpace ensure_space(this);
|
||||
emit(0x66);
|
||||
emit_optional_rex_32(op);
|
||||
emit(0xF7);
|
||||
emit_operand(0x3, op);
|
||||
}
|
||||
|
||||
void Assembler::negl(Operand op) {
|
||||
EnsureSpace ensure_space(this);
|
||||
emit_optional_rex_32(op);
|
||||
emit(0xF7);
|
||||
emit_operand(0x3, op);
|
||||
}
|
||||
|
||||
void Assembler::negq(Operand op) {
|
||||
EnsureSpace ensure_space(this);
|
||||
emit_rex_64(op);
|
||||
emit(0xF7);
|
||||
emit_operand(0x3, op);
|
||||
}
|
||||
|
||||
void Assembler::nop() {
|
||||
|
@ -225,7 +225,6 @@ static_assert(sizeof(Operand) <= 2 * kSystemPointerSize,
|
||||
V(mov) \
|
||||
V(movzxb) \
|
||||
V(movzxw) \
|
||||
V(neg) \
|
||||
V(not) \
|
||||
V(or) \
|
||||
V(repmovs) \
|
||||
@ -612,6 +611,15 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
void xaddl(Operand dst, Register src);
|
||||
void xaddq(Operand dst, Register src);
|
||||
|
||||
void negb(Register reg);
|
||||
void negw(Register reg);
|
||||
void negl(Register reg);
|
||||
void negq(Register reg);
|
||||
void negb(Operand op);
|
||||
void negw(Operand op);
|
||||
void negl(Operand op);
|
||||
void negq(Operand op);
|
||||
|
||||
void cmpxchgb(Operand dst, Register src);
|
||||
void cmpxchgw(Operand dst, Register src);
|
||||
|
||||
@ -1836,6 +1844,13 @@ class V8_EXPORT_PRIVATE Assembler : public AssemblerBase {
|
||||
// numbers have a high bit set.
|
||||
inline void emit_optional_rex_32(Operand op);
|
||||
|
||||
// Calls emit_rex_32(Register) for all non-byte registers.
|
||||
inline void emit_optional_rex_8(Register reg);
|
||||
|
||||
// Calls emit_rex_32(Register, Operand) for all non-byte registers, and
|
||||
// emit_optional_rex_32(Register, Operand) for byte registers.
|
||||
inline void emit_optional_rex_8(Register reg, Operand op);
|
||||
|
||||
void emit_rex(int size) {
|
||||
if (size == kInt64Size) {
|
||||
emit_rex_64();
|
||||
|
@ -679,7 +679,7 @@ int DisassemblerX64::F6F7Instruction(byte* data) {
|
||||
byte modrm = *(data + 1);
|
||||
int mod, regop, rm;
|
||||
get_modrm(modrm, &mod, ®op, &rm);
|
||||
if (mod == 3 && regop != 0) {
|
||||
if (regop != 0) {
|
||||
const char* mnem = nullptr;
|
||||
switch (regop) {
|
||||
case 2:
|
||||
@ -703,8 +703,18 @@ int DisassemblerX64::F6F7Instruction(byte* data) {
|
||||
default:
|
||||
UnimplementedInstruction();
|
||||
}
|
||||
AppendToBuffer("%s%c %s", mnem, operand_size_code(), NameOfCPURegister(rm));
|
||||
return 2;
|
||||
if (mod == 3) {
|
||||
AppendToBuffer("%s%c %s", mnem, operand_size_code(),
|
||||
NameOfCPURegister(rm));
|
||||
return 2;
|
||||
} else if (mod == 1) {
|
||||
AppendToBuffer("%s%c ", mnem, operand_size_code());
|
||||
int count = PrintRightOperand(data + 1); // Use name of 64-bit register.
|
||||
return 1 + count;
|
||||
} else {
|
||||
UnimplementedInstruction();
|
||||
return 2;
|
||||
}
|
||||
} else if (regop == 0) {
|
||||
AppendToBuffer("test%c ", operand_size_code());
|
||||
int count = PrintRightOperand(data + 1); // Use name of 64-bit register.
|
||||
|
@ -189,7 +189,17 @@ TEST(DisasmX64) {
|
||||
__ idivq(rdx);
|
||||
__ mull(rdx);
|
||||
__ mulq(rdx);
|
||||
|
||||
__ negb(rdx);
|
||||
__ negb(r10);
|
||||
__ negw(rdx);
|
||||
__ negl(rdx);
|
||||
__ negq(rdx);
|
||||
__ negb(Operand(rsp, 12));
|
||||
__ negw(Operand(rsp, 12));
|
||||
__ negl(Operand(rsp, 12));
|
||||
__ negb(Operand(rsp, 12));
|
||||
|
||||
__ notq(rdx);
|
||||
__ testq(Operand(rbx, rcx, times_4, 10000), rdx);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user