void Assembler::arithmetic_op(byte opcode, Register reg, Register rm_reg) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- emit_rex_64(reg, rm_reg);
- emit(opcode);
- emit_modrm(reg, rm_reg);
+ ASSERT((opcode & 0xC6) == 2);
+ if (rm_reg.low_bits() == 4) { // Forces SIB byte.
+ // 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) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- emit(0x66);
- emit_optional_rex_32(reg, rm_reg);
- emit(opcode);
- emit_modrm(reg, rm_reg);
+ ASSERT((opcode & 0xC6) == 2);
+ if (rm_reg.low_bits() == 4) { // Forces SIB byte.
+ // Swap reg and rm_reg and change opcode operand order.
+ 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);
+ }
}
void Assembler::arithmetic_op_32(byte opcode, Register reg, Register rm_reg) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- emit_optional_rex_32(reg, rm_reg);
- emit(opcode);
- emit_modrm(reg, rm_reg);
+ ASSERT((opcode & 0xC6) == 2);
+ if (rm_reg.low_bits() == 4) { // Forces SIB byte.
+ // 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);
+ }
}
void Assembler::movl(Register dst, Register src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- emit_optional_rex_32(dst, src);
- emit(0x8B);
- emit_modrm(dst, src);
+ if (src.low_bits() == 4) {
+ emit_optional_rex_32(src, dst);
+ emit(0x89);
+ emit_modrm(src, dst);
+ } else {
+ emit_optional_rex_32(dst, src);
+ emit(0x8B);
+ emit_modrm(dst, src);
+ }
}
void Assembler::movq(Register dst, Register src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- emit_rex_64(dst, src);
- emit(0x8B);
- emit_modrm(dst, src);
+ if (src.low_bits() == 4) {
+ emit_rex_64(src, dst);
+ emit(0x89);
+ emit_modrm(src, dst);
+ } else {
+ emit_rex_64(dst, src);
+ emit(0x8B);
+ emit_modrm(dst, src);
+ }
}
Register other = src.is(rax) ? dst : src;
emit_rex_64(other);
emit(0x90 | other.low_bits());
+ } else if (dst.low_bits() == 4) {
+ emit_rex_64(dst, src);
+ emit(0x87);
+ emit_modrm(dst, src);
} else {
emit_rex_64(src, dst);
emit(0x87);
void Assembler::testb(Register dst, Register src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- 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);
+ if (src.low_bits() == 4) {
+ emit_rex_32(src, dst);
+ 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);
}
void Assembler::testl(Register dst, Register src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- emit_optional_rex_32(dst, src);
- emit(0x85);
- emit_modrm(dst, src);
+ if (src.low_bits() == 4) {
+ emit_optional_rex_32(src, dst);
+ emit(0x85);
+ emit_modrm(src, dst);
+ } else {
+ emit_optional_rex_32(dst, src);
+ emit(0x85);
+ emit_modrm(dst, src);
+ }
}
void Assembler::testq(Register dst, Register src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- emit_rex_64(dst, src);
- emit(0x85);
- emit_modrm(dst, src);
+ if (src.low_bits() == 4) {
+ emit_rex_64(src, dst);
+ emit(0x85);
+ emit_modrm(src, dst);
+ } else {
+ emit_rex_64(dst, src);
+ emit(0x85);
+ emit_modrm(dst, src);
+ }
}
// Arithmetics
void addl(Register dst, Register src) {
- if (dst.low_bits() == 4) { // Forces SIB byte.
- arithmetic_op_32(0x01, src, dst);
- } else {
- arithmetic_op_32(0x03, dst, src);
- }
+ arithmetic_op_32(0x03, dst, src);
}
void addl(Register dst, Immediate src) {
}
void sbbl(Register dst, Register src) {
- if (dst.low_bits() == 4) { // Forces SIB byte if dst is base register.
- arithmetic_op_32(0x19, src, dst);
- } else {
- arithmetic_op_32(0x1b, dst, src);
- }
+ arithmetic_op_32(0x1b, dst, src);
}
void cmpb(Register dst, Immediate src) {