X64: Make all arithmetic ops, and a few other, try to avoid rsp and r12 as base register.
Using rsp or r12 as the "base" register of the ModR/M byte forces a SIB byte, even with no index register. Some operations can avoid this by using another, equivalent, encoding that swaps the meaning of the base and register parts. Review URL: http://codereview.chromium.org/2075010 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@4678 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
c5b8a2c9ec
commit
7410865adb
@ -460,19 +460,36 @@ void Assembler::arithmetic_op(byte opcode, Register reg, const Operand& op) {
|
|||||||
void Assembler::arithmetic_op(byte opcode, Register reg, Register rm_reg) {
|
void Assembler::arithmetic_op(byte opcode, Register reg, Register rm_reg) {
|
||||||
EnsureSpace ensure_space(this);
|
EnsureSpace ensure_space(this);
|
||||||
last_pc_ = pc_;
|
last_pc_ = pc_;
|
||||||
emit_rex_64(reg, rm_reg);
|
ASSERT((opcode & 0xC6) == 2);
|
||||||
emit(opcode);
|
if (rm_reg.low_bits() == 4) { // Forces SIB byte.
|
||||||
emit_modrm(reg, rm_reg);
|
// Swap reg and rm_reg and change opcode operand order.
|
||||||
|
emit_rex_64(rm_reg, reg);
|
||||||
|
emit(opcode ^ 0x02);
|
||||||
|
emit_modrm(rm_reg, reg);
|
||||||
|
} else {
|
||||||
|
emit_rex_64(reg, rm_reg);
|
||||||
|
emit(opcode);
|
||||||
|
emit_modrm(reg, rm_reg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Assembler::arithmetic_op_16(byte opcode, Register reg, Register rm_reg) {
|
void Assembler::arithmetic_op_16(byte opcode, Register reg, Register rm_reg) {
|
||||||
EnsureSpace ensure_space(this);
|
EnsureSpace ensure_space(this);
|
||||||
last_pc_ = pc_;
|
last_pc_ = pc_;
|
||||||
emit(0x66);
|
ASSERT((opcode & 0xC6) == 2);
|
||||||
emit_optional_rex_32(reg, rm_reg);
|
if (rm_reg.low_bits() == 4) { // Forces SIB byte.
|
||||||
emit(opcode);
|
// Swap reg and rm_reg and change opcode operand order.
|
||||||
emit_modrm(reg, rm_reg);
|
emit(0x66);
|
||||||
|
emit_optional_rex_32(rm_reg, reg);
|
||||||
|
emit(opcode ^ 0x02);
|
||||||
|
emit_modrm(rm_reg, reg);
|
||||||
|
} else {
|
||||||
|
emit(0x66);
|
||||||
|
emit_optional_rex_32(reg, rm_reg);
|
||||||
|
emit(opcode);
|
||||||
|
emit_modrm(reg, rm_reg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -491,9 +508,17 @@ void Assembler::arithmetic_op_16(byte opcode,
|
|||||||
void Assembler::arithmetic_op_32(byte opcode, Register reg, Register rm_reg) {
|
void Assembler::arithmetic_op_32(byte opcode, Register reg, Register rm_reg) {
|
||||||
EnsureSpace ensure_space(this);
|
EnsureSpace ensure_space(this);
|
||||||
last_pc_ = pc_;
|
last_pc_ = pc_;
|
||||||
emit_optional_rex_32(reg, rm_reg);
|
ASSERT((opcode & 0xC6) == 2);
|
||||||
emit(opcode);
|
if (rm_reg.low_bits() == 4) { // Forces SIB byte.
|
||||||
emit_modrm(reg, rm_reg);
|
// Swap reg and rm_reg and change opcode operand order.
|
||||||
|
emit_optional_rex_32(rm_reg, reg);
|
||||||
|
emit(opcode ^ 0x02); // E.g. 0x03 -> 0x01 for ADD.
|
||||||
|
emit_modrm(rm_reg, reg);
|
||||||
|
} else {
|
||||||
|
emit_optional_rex_32(reg, rm_reg);
|
||||||
|
emit(opcode);
|
||||||
|
emit_modrm(reg, rm_reg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1292,9 +1317,15 @@ void Assembler::movl(Register dst, const Operand& src) {
|
|||||||
void Assembler::movl(Register dst, Register src) {
|
void Assembler::movl(Register dst, Register src) {
|
||||||
EnsureSpace ensure_space(this);
|
EnsureSpace ensure_space(this);
|
||||||
last_pc_ = pc_;
|
last_pc_ = pc_;
|
||||||
emit_optional_rex_32(dst, src);
|
if (src.low_bits() == 4) {
|
||||||
emit(0x8B);
|
emit_optional_rex_32(src, dst);
|
||||||
emit_modrm(dst, src);
|
emit(0x89);
|
||||||
|
emit_modrm(src, dst);
|
||||||
|
} else {
|
||||||
|
emit_optional_rex_32(dst, src);
|
||||||
|
emit(0x8B);
|
||||||
|
emit_modrm(dst, src);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1339,9 +1370,15 @@ void Assembler::movq(Register dst, const Operand& src) {
|
|||||||
void Assembler::movq(Register dst, Register src) {
|
void Assembler::movq(Register dst, Register src) {
|
||||||
EnsureSpace ensure_space(this);
|
EnsureSpace ensure_space(this);
|
||||||
last_pc_ = pc_;
|
last_pc_ = pc_;
|
||||||
emit_rex_64(dst, src);
|
if (src.low_bits() == 4) {
|
||||||
emit(0x8B);
|
emit_rex_64(src, dst);
|
||||||
emit_modrm(dst, src);
|
emit(0x89);
|
||||||
|
emit_modrm(src, dst);
|
||||||
|
} else {
|
||||||
|
emit_rex_64(dst, src);
|
||||||
|
emit(0x8B);
|
||||||
|
emit_modrm(dst, src);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1862,6 +1899,10 @@ void Assembler::xchg(Register dst, Register src) {
|
|||||||
Register other = src.is(rax) ? dst : src;
|
Register other = src.is(rax) ? dst : src;
|
||||||
emit_rex_64(other);
|
emit_rex_64(other);
|
||||||
emit(0x90 | other.low_bits());
|
emit(0x90 | other.low_bits());
|
||||||
|
} else if (dst.low_bits() == 4) {
|
||||||
|
emit_rex_64(dst, src);
|
||||||
|
emit(0x87);
|
||||||
|
emit_modrm(dst, src);
|
||||||
} else {
|
} else {
|
||||||
emit_rex_64(src, dst);
|
emit_rex_64(src, dst);
|
||||||
emit(0x87);
|
emit(0x87);
|
||||||
@ -1887,12 +1928,18 @@ void Assembler::store_rax(ExternalReference ref) {
|
|||||||
void Assembler::testb(Register dst, Register src) {
|
void Assembler::testb(Register dst, Register src) {
|
||||||
EnsureSpace ensure_space(this);
|
EnsureSpace ensure_space(this);
|
||||||
last_pc_ = pc_;
|
last_pc_ = pc_;
|
||||||
if (dst.code() > 3 || src.code() > 3) {
|
if (src.low_bits() == 4) {
|
||||||
// Register is not one of al, bl, cl, dl. Its encoding needs REX.
|
emit_rex_32(src, dst);
|
||||||
emit_rex_32(dst, src);
|
emit(0x84);
|
||||||
|
emit_modrm(src, dst);
|
||||||
|
} else {
|
||||||
|
if (dst.code() > 3 || src.code() > 3) {
|
||||||
|
// Register is not one of al, bl, cl, dl. Its encoding needs REX.
|
||||||
|
emit_rex_32(dst, src);
|
||||||
|
}
|
||||||
|
emit(0x84);
|
||||||
|
emit_modrm(dst, src);
|
||||||
}
|
}
|
||||||
emit(0x84);
|
|
||||||
emit_modrm(dst, src);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1943,9 +1990,15 @@ void Assembler::testb(const Operand& op, Register reg) {
|
|||||||
void Assembler::testl(Register dst, Register src) {
|
void Assembler::testl(Register dst, Register src) {
|
||||||
EnsureSpace ensure_space(this);
|
EnsureSpace ensure_space(this);
|
||||||
last_pc_ = pc_;
|
last_pc_ = pc_;
|
||||||
emit_optional_rex_32(dst, src);
|
if (src.low_bits() == 4) {
|
||||||
emit(0x85);
|
emit_optional_rex_32(src, dst);
|
||||||
emit_modrm(dst, src);
|
emit(0x85);
|
||||||
|
emit_modrm(src, dst);
|
||||||
|
} else {
|
||||||
|
emit_optional_rex_32(dst, src);
|
||||||
|
emit(0x85);
|
||||||
|
emit_modrm(dst, src);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1996,9 +2049,15 @@ void Assembler::testq(const Operand& op, Register reg) {
|
|||||||
void Assembler::testq(Register dst, Register src) {
|
void Assembler::testq(Register dst, Register src) {
|
||||||
EnsureSpace ensure_space(this);
|
EnsureSpace ensure_space(this);
|
||||||
last_pc_ = pc_;
|
last_pc_ = pc_;
|
||||||
emit_rex_64(dst, src);
|
if (src.low_bits() == 4) {
|
||||||
emit(0x85);
|
emit_rex_64(src, dst);
|
||||||
emit_modrm(dst, src);
|
emit(0x85);
|
||||||
|
emit_modrm(src, dst);
|
||||||
|
} else {
|
||||||
|
emit_rex_64(dst, src);
|
||||||
|
emit(0x85);
|
||||||
|
emit_modrm(dst, src);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -567,11 +567,7 @@ class Assembler : public Malloced {
|
|||||||
|
|
||||||
// Arithmetics
|
// Arithmetics
|
||||||
void addl(Register dst, Register src) {
|
void addl(Register dst, Register src) {
|
||||||
if (dst.low_bits() == 4) { // Forces SIB byte.
|
arithmetic_op_32(0x03, dst, src);
|
||||||
arithmetic_op_32(0x01, src, dst);
|
|
||||||
} else {
|
|
||||||
arithmetic_op_32(0x03, dst, src);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void addl(Register dst, Immediate src) {
|
void addl(Register dst, Immediate src) {
|
||||||
@ -607,11 +603,7 @@ class Assembler : public Malloced {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sbbl(Register dst, Register src) {
|
void sbbl(Register dst, Register src) {
|
||||||
if (dst.low_bits() == 4) { // Forces SIB byte if dst is base register.
|
arithmetic_op_32(0x1b, dst, src);
|
||||||
arithmetic_op_32(0x19, src, dst);
|
|
||||||
} else {
|
|
||||||
arithmetic_op_32(0x1b, dst, src);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmpb(Register dst, Immediate src) {
|
void cmpb(Register dst, Immediate src) {
|
||||||
|
Loading…
Reference in New Issue
Block a user