Index: src/x64/assembler-x64.cc |
=================================================================== |
--- src/x64/assembler-x64.cc (revision 2097) |
+++ src/x64/assembler-x64.cc (working copy) |
@@ -342,7 +342,7 @@ |
const unsigned length = adr.len_; |
ASSERT(length > 0); |
- // Emit updated ModRM byte containing the given register. |
+ // Emit updated ModR/M byte containing the given register. |
pc_[0] = (adr.buf_[0] & ~0x38) | (rm << 3); |
// Emit the rest of the encoded operand. |
@@ -367,7 +367,7 @@ |
last_pc_ = pc_; |
emit_rex_64(dst, src); |
emit(opcode); |
- emit(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7)); |
+ emit_modrm(dst, src); |
} |
void Assembler::immediate_arithmetic_op(byte subcode, |
@@ -378,14 +378,14 @@ |
emit_rex_64(dst); |
if (is_int8(src.value_)) { |
emit(0x83); |
- emit(0xC0 | (subcode << 3) | (dst.code() & 0x7)); |
+ emit_modrm(subcode, dst); |
emit(src.value_); |
} else if (dst.is(rax)) { |
emit(0x05 | (subcode << 3)); |
emitl(src.value_); |
} else { |
emit(0x81); |
- emit(0xC0 | (subcode << 3) | (dst.code() & 0x7)); |
+ emit_modrm(subcode, dst); |
emitl(src.value_); |
} |
} |
@@ -415,11 +415,11 @@ |
if (shift_amount.value_ == 1) { |
emit_rex_64(dst); |
emit(0xD1); |
- emit(0xC0 | (subcode << 3) | (dst.code() & 0x7)); |
+ emit_modrm(subcode, dst); |
} else { |
emit_rex_64(dst); |
emit(0xC1); |
- emit(0xC0 | (subcode << 3) | (dst.code() & 0x7)); |
+ emit_modrm(subcode, dst); |
emit(shift_amount.value_); |
} |
} |
@@ -430,7 +430,7 @@ |
last_pc_ = pc_; |
emit_rex_64(dst); |
emit(0xD3); |
- emit(0xC0 | (subcode << 3) | (dst.code() & 0x7)); |
+ emit_modrm(subcode, dst); |
} |
@@ -479,11 +479,11 @@ |
EnsureSpace ensure_space(this); |
last_pc_ = pc_; |
// Opcode: FF /2 r64 |
- if (!is_uint3(adr.code())) { |
+ if (adr.code() > 7) { |
emit_rex_64(adr); |
} |
emit(0xFF); |
- emit(0xD0 | (adr.code() & 0x07)); |
+ emit_modrm(0x2, adr); |
} |
@@ -509,7 +509,7 @@ |
last_pc_ = pc_; |
emit_rex_64(dst); |
emit(0xFF); |
- emit(0xC8 | (dst.code() & 0x7)); |
+ emit_modrm(0x1, dst); |
} |
@@ -538,12 +538,47 @@ |
} |
+void Assembler::idiv(Register src) { |
+ EnsureSpace ensure_space(this); |
+ last_pc_ = pc_; |
+ emit_rex_64(src); |
+ emit(0xF7); |
+ emit_modrm(0x7, src); |
+} |
+ |
+ |
+void Assembler::imul(Register dst, const Operand& src) { |
+ EnsureSpace ensure_space(this); |
+ last_pc_ = pc_; |
+ emit_rex_64(dst, src); |
+ emit(0x0F); |
+ emit(0xAF); |
+ emit_operand(dst, src); |
+} |
+ |
+ |
+void Assembler::imul(Register dst, Register src, Immediate imm) { |
+ EnsureSpace ensure_space(this); |
+ last_pc_ = pc_; |
+ emit_rex_64(dst, src); |
+ if (is_int8(imm.value_)) { |
+ emit(0x6B); |
+ emit_modrm(dst, src); |
+ emit(imm.value_); |
+ } else { |
+ emit(0x69); |
+ emit_modrm(dst, src); |
+ emitl(imm.value_); |
+ } |
+} |
+ |
+ |
void Assembler::inc(Register dst) { |
EnsureSpace ensure_space(this); |
last_pc_ = pc_; |
emit_rex_64(dst); |
emit(0xFF); |
- emit(0xC0 | (dst.code() & 0x7)); |
+ emit_modrm(0x0, dst); |
} |
@@ -634,11 +669,11 @@ |
EnsureSpace ensure_space(this); |
last_pc_ = pc_; |
// Opcode FF/4 r64 |
- if (!is_uint3(target.code())) { |
+ if (target.code() > 7) { |
emit_rex_64(target); |
} |
emit(0xFF); |
- emit(0xE0 | target.code() & 0x07); |
+ emit_modrm(0x4, target); |
} |
@@ -658,6 +693,31 @@ |
} |
+void Assembler::movb(Register dst, const Operand& src) { |
+ EnsureSpace ensure_space(this); |
+ last_pc_ = pc_; |
+ emit_rex_32(dst, src); |
+ emit(0x8A); |
+ emit_operand(dst, src); |
+} |
+ |
+void Assembler::movb(Register dst, Immediate imm) { |
+ EnsureSpace ensure_space(this); |
+ last_pc_ = pc_; |
+ emit_rex_32(dst); |
+ emit(0xC6); |
+ emit_modrm(0x0, dst); |
+ emit(imm.value_); |
+} |
+ |
+void Assembler::movb(const Operand& dst, Register src) { |
+ EnsureSpace ensure_space(this); |
+ last_pc_ = pc_; |
+ emit_rex_32(src, dst); |
+ emit(0x88); |
+ emit_operand(src, dst); |
+} |
+ |
void Assembler::movl(Register dst, const Operand& src) { |
EnsureSpace ensure_space(this); |
last_pc_ = pc_; |
@@ -672,7 +732,7 @@ |
last_pc_ = pc_; |
emit_optional_rex_32(dst, src); |
emit(0x8B); |
- emit(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7)); |
+ emit_modrm(dst, src); |
} |
@@ -690,7 +750,7 @@ |
last_pc_ = pc_; |
emit_optional_rex_32(dst); |
emit(0xC7); |
- emit(0xC0 | (dst.code() & 0x7)); |
+ emit_modrm(0x0, dst); |
emit(value); // Only 32-bit immediates are possible, not 8-bit immediates. |
} |
@@ -709,7 +769,7 @@ |
last_pc_ = pc_; |
emit_rex_64(dst, src); |
emit(0x8B); |
- emit(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7)); |
+ emit_modrm(dst, src); |
} |
@@ -718,7 +778,7 @@ |
last_pc_ = pc_; |
emit_rex_64(dst); |
emit(0xC7); |
- emit(0xC0 | (dst.code() & 0x7)); |
+ emit_modrm(0x0, dst); |
emit(value); // Only 32-bit immediates are possible, not 8-bit immediates. |
} |
@@ -727,7 +787,7 @@ |
EnsureSpace ensure_space(this); |
last_pc_ = pc_; |
emit_rex_64(dst); |
- emit(0xB8 | (dst.code() & 0x7)); |
+ emit(0xB8 | (dst.code() & 0x7)); // Not a ModR/M byte. |
emitq(value, rmode); |
} |
@@ -741,12 +801,21 @@ |
} |
+void Assembler::mul(Register src) { |
+ EnsureSpace ensure_space(this); |
+ last_pc_ = pc_; |
+ emit_rex_64(src); |
+ emit(0xF7); |
+ emit_modrm(0x4, src); |
+} |
+ |
+ |
void Assembler::neg(Register dst) { |
EnsureSpace ensure_space(this); |
last_pc_ = pc_; |
emit_rex_64(dst); |
emit(0xF7); |
- emit(0xC0 | (0x3 << 3) | (dst.code() & 0x7)); |
+ emit_modrm(0x3, dst); |
} |
@@ -771,7 +840,7 @@ |
last_pc_ = pc_; |
emit_rex_64(dst); |
emit(0xF7); |
- emit(0xC0 | (0x2 << 3) | (dst.code() & 0x7)); |
+ emit_modrm(0x2, dst); |
} |
@@ -874,7 +943,7 @@ |
void Assembler::pop(Register dst) { |
EnsureSpace ensure_space(this); |
last_pc_ = pc_; |
- if (dst.code() & 0x8) { |
+ if (dst.code() > 7) { |
emit_rex_64(dst); |
} |
emit(0x58 | (dst.code() & 0x7)); |
@@ -900,7 +969,7 @@ |
void Assembler::push(Register src) { |
EnsureSpace ensure_space(this); |
last_pc_ = pc_; |
- if (src.code() & 0x8) { |
+ if (src.code() > 7) { |
emit_rex_64(src); |
} |
emit(0x50 | (src.code() & 0x7)); |
@@ -943,11 +1012,11 @@ |
if (imm8 == 1) { |
emit_rex_64(dst); |
emit(0xD1); |
- emit(0xD0 | (dst.code() & 0x7)); |
+ emit_modrm(0x2, dst); |
} else { |
emit_rex_64(dst); |
emit(0xC1); |
- emit(0xD0 | (dst.code() & 0x7)); |
+ emit_modrm(0x2, dst); |
emit(imm8); |
} |
} |
@@ -967,6 +1036,26 @@ |
} |
+void Assembler::shld(Register dst, Register src) { |
+ EnsureSpace ensure_space(this); |
+ last_pc_ = pc_; |
+ emit_rex_64(src, dst); |
+ emit(0x0F); |
+ emit(0xA5); |
+ emit_modrm(src, dst); |
+} |
+ |
+ |
+void Assembler::shrd(Register dst, Register src) { |
+ EnsureSpace ensure_space(this); |
+ last_pc_ = pc_; |
+ emit_rex_64(src, dst); |
+ emit(0x0F); |
+ emit(0xAD); |
+ emit_modrm(src, dst); |
+} |
+ |
+ |
void Assembler::xchg(Register dst, Register src) { |
EnsureSpace ensure_space(this); |
last_pc_ = pc_; |
@@ -977,7 +1066,7 @@ |
} else { |
emit_rex_64(src, dst); |
emit(0x87); |
- emit(0xC0 | (src.code() & 0x7) << 3 | (dst.code() & 0x7)); |
+ emit_modrm(src, dst); |
} |
} |
@@ -989,11 +1078,12 @@ |
emit(0xA8); |
emit(mask); |
} else { |
- if (reg.code() & 0x8) { |
- emit_rex_32(rax, reg); |
+ if (reg.code() > 3) { |
+ // Register is not one of al, bl, cl, dl. Its encoding needs REX. |
+ emit_rex_32(reg); |
} |
emit(0xF6); |
- emit(0xC0 | (reg.code() & 0x3)); |
+ emit_modrm(0x0, reg); |
emit(mask.value_); // Low byte emitted. |
} |
} |
@@ -1018,7 +1108,7 @@ |
} else { |
emit_optional_rex_32(rax, reg); |
emit(0xF7); |
- emit(0xC0 | (reg.code() & 0x3)); |
+ emit_modrm(0x0, reg); |
emit(mask); |
} |
} |
@@ -1034,6 +1124,24 @@ |
} |
+void Assembler::testq(const Operand& op, Register reg) { |
+ EnsureSpace ensure_space(this); |
+ last_pc_ = pc_; |
+ emit_rex_64(reg, op); |
+ emit(0x85); |
+ emit_operand(reg, op); |
+} |
+ |
+ |
+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); |
+} |
+ |
+ |
// Relocation information implementations |
void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { |