// -----------------------------------------------------------------------------
// Implementation of Assembler
-// Emit a single byte. Must always be inlined.
-#define EMIT(x) \
- *pc_++ = (x)
-
#ifdef GENERATED_CODE_COVERAGE
static void InitCoverageLog();
#endif
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_rex_64(reg, op);
- EMIT(opcode);
+ emit(opcode);
emit_operand(reg, op);
}
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_rex_64(dst, src);
- EMIT(opcode);
- EMIT(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7));
+ emit(opcode);
+ emit(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7));
}
void Assembler::immediate_arithmetic_op(byte subcode,
last_pc_ = pc_;
emit_rex_64(rax, dst);
if (is_int8(src.value_)) {
- EMIT(0x83);
- EMIT(0xC0 | (subcode << 3) | (dst.code() & 0x7));
- EMIT(src.value_);
+ emit(0x83);
+ emit(0xC0 | (subcode << 3) | (dst.code() & 0x7));
+ emit(src.value_);
} else {
- EMIT(0x81);
- EMIT(0xC0 | (subcode << 3) | (dst.code() & 0x7));
+ emit(0x81);
+ emit(0xC0 | (subcode << 3) | (dst.code() & 0x7));
emitl(src.value_);
}
}
last_pc_ = pc_;
emit_rex_64(rax, dst);
if (is_int8(src.value_)) {
- EMIT(0x83);
+ emit(0x83);
emit_operand(Register::toRegister(subcode), dst);
- EMIT(src.value_);
+ emit(src.value_);
} else {
- EMIT(0x81);
+ emit(0x81);
emit_operand(Register::toRegister(subcode), dst);
emitl(src.value_);
}
EnsureSpace ensure_space(this);
last_pc_ = pc_;
// 1110 1000 #32-bit disp
- EMIT(0xE8);
+ emit(0xE8);
if (L->is_bound()) {
int offset = L->pos() - pc_offset() - sizeof(int32_t);
ASSERT(offset <= 0);
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_rex_64(rcx, dst);
- EMIT(0xFF);
- EMIT(0xC8 | (dst.code() & 0x7));
+ emit(0xFF);
+ emit(0xC8 | (dst.code() & 0x7));
}
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_rex_64(rax, dst);
- EMIT(0xFF);
+ emit(0xFF);
emit_operand(rcx, dst);
}
void Assembler::hlt() {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- EMIT(0xF4);
+ emit(0xF4);
}
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_rex_64(rax, dst);
- EMIT(0xFF);
- EMIT(0xC0 | (dst.code() & 0x7));
+ emit(0xFF);
+ emit(0xC0 | (dst.code() & 0x7));
}
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_rex_64(rax, dst);
- EMIT(0xFF);
+ emit(0xFF);
emit_operand(rax, dst);
}
void Assembler::int3() {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- EMIT(0xCC);
+ emit(0xCC);
}
ASSERT(offs <= 0);
if (is_int8(offs - short_size)) {
// 0111 tttn #8-bit disp
- EMIT(0x70 | cc);
- EMIT((offs - short_size) & 0xFF);
+ emit(0x70 | cc);
+ emit((offs - short_size) & 0xFF);
} else {
// 0000 1111 1000 tttn #32-bit disp
- EMIT(0x0F);
- EMIT(0x80 | cc);
+ emit(0x0F);
+ emit(0x80 | cc);
emitl(offs - long_size);
}
} else if (L->is_linked()) {
// 0000 1111 1000 tttn #32-bit disp
- EMIT(0x0F);
- EMIT(0x80 | cc);
+ emit(0x0F);
+ emit(0x80 | cc);
emitl(L->pos());
L->link_to(pc_offset() - sizeof(int32_t));
} else {
ASSERT(L->is_unused());
- EMIT(0x0F);
- EMIT(0x80 | cc);
+ emit(0x0F);
+ emit(0x80 | cc);
int32_t current = pc_offset();
emitl(current);
L->link_to(current);
ASSERT(offs <= 0);
if (is_int8(offs - sizeof(int8_t))) {
// 1110 1011 #8-bit disp
- EMIT(0xEB);
- EMIT((offs - sizeof(int8_t)) & 0xFF);
+ emit(0xEB);
+ emit((offs - sizeof(int8_t)) & 0xFF);
} else {
// 1110 1001 #32-bit disp
- EMIT(0xE9);
+ emit(0xE9);
emitl(offs - sizeof(int32_t));
}
} else if (L->is_linked()) {
// 1110 1001 #32-bit disp
- EMIT(0xE9);
+ emit(0xE9);
emitl(L->pos());
L->link_to(pc_offset() - sizeof(int32_t));
} else {
// 1110 1001 #32-bit disp
ASSERT(L->is_unused());
- EMIT(0xE9);
+ emit(0xE9);
int32_t current = pc_offset();
emitl(current);
L->link_to(current);
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_rex_64(dst, src);
- EMIT(0x8B);
+ emit(0x8B);
emit_operand(dst, src);
}
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_rex_64(dst, src);
- EMIT(0x8B);
- EMIT(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7));
+ emit(0x8B);
+ emit(0xC0 | (dst.code() & 0x7) << 3 | (src.code() & 0x7));
}
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_rex_64(rax, dst);
- EMIT(0xC7);
- EMIT(0xC0 | (dst.code() & 0x7));
+ emit(0xC7);
+ emit(0xC0 | (dst.code() & 0x7));
emit(value); // Only 32-bit immediates are possible, not 8-bit immediates.
}
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_rex_64(rax, dst);
- EMIT(0xB8 | (dst.code() & 0x7));
+ emit(0xB8 | (dst.code() & 0x7));
emitq(value, rmode);
}
void Assembler::nop() {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- EMIT(0x90);
+ emit(0x90);
}
if (dst.code() & 0x8) {
emit_rex_64(rax, dst);
}
- EMIT(0x58 | (dst.code() & 0x7));
+ emit(0x58 | (dst.code() & 0x7));
}
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_rex_64(rax, dst); // Could be omitted in some cases.
- EMIT(0x8F);
+ emit(0x8F);
emit_operand(rax, dst);
}
if (src.code() & 0x8) {
emit_rex_64(rax, src);
}
- EMIT(0x50 | (src.code() & 0x7));
+ emit(0x50 | (src.code() & 0x7));
}
EnsureSpace ensure_space(this);
last_pc_ = pc_;
emit_rex_64(rsi, src); // Could be omitted in some cases.
- EMIT(0xFF);
+ emit(0xFF);
emit_operand(rsi, src);
}
last_pc_ = pc_;
ASSERT(is_uint16(imm16));
if (imm16 == 0) {
- EMIT(0xC3);
+ emit(0xC3);
} else {
- EMIT(0xC2);
- EMIT(imm16 & 0xFF);
- EMIT((imm16 >> 8) & 0xFF);
+ emit(0xC2);
+ emit(imm16 & 0xFF);
+ emit((imm16 >> 8) & 0xFF);
}
}
arithmetic_op(0x03, dst, src);
}
+
void add(const Operand& dst, Register src) {
arithmetic_op(0x01, src, dst);
}
immediate_arithmetic_op(0x7, dst, src);
}
+ void and_(Register dst, Register src) {
+ arithmetic_op(0x23, dst, src);
+ }
+
+ void and_(Register dst, const Operand& src) {
+ arithmetic_op(0x23, dst, src);
+ }
+
+ void and_(const Operand& dst, Register src) {
+ arithmetic_op(0x21, src, dst);
+ }
+
+ void and_(Register dst, Immediate src) {
+ immediate_arithmetic_op(0x4, dst, src);
+ }
- void and_(Register dst, int32_t imm32);
- void and_(Register dst, const Operand& src);
- void and_(const Operand& src, Register dst);
- void and_(const Operand& dst, const Immediate& x);
+ void and_(const Operand& dst, Immediate src) {
+ immediate_arithmetic_op(0x4, dst, src);
+ }
void cmpb(const Operand& op, int8_t imm8);
void cmpb_al(const Operand& op);
void not_(Register dst);
- void or_(Register dst, int32_t imm32);
- void or_(Register dst, const Operand& src);
- void or_(const Operand& dst, Register src);
- void or_(const Operand& dst, const Immediate& x);
+ void or_(Register dst, Register src) {
+ arithmetic_op(0x0B, dst, src);
+ }
+
+ void or_(Register dst, const Operand& src) {
+ arithmetic_op(0x0B, dst, src);
+ }
+
+ void or_(const Operand& dst, Register src) {
+ arithmetic_op(0x09, src, dst);
+ }
+
+ void or_(Register dst, Immediate src) {
+ immediate_arithmetic_op(0x1, dst, src);
+ }
+
+ void or_(const Operand& dst, Immediate src) {
+ immediate_arithmetic_op(0x1, dst, src);
+ }
+
void rcl(Register dst, uint8_t imm8);
void shr(Register dst);
void shr_cl(Register dst);
- void sub(const Operand& dst, const Immediate& x);
- void sub(Register dst, const Operand& src);
- void sub(const Operand& dst, Register src);
+ void sub(Register dst, Register src) {
+ arithmetic_op(0x2B, dst, src);
+ }
+
+ void sub(Register dst, const Operand& src) {
+ arithmetic_op(0x2B, dst, src);
+ }
+
+ void sub(const Operand& dst, Register src) {
+ arithmetic_op(0x29, src, dst);
+ }
+
+ void sub(Register dst, Immediate src) {
+ immediate_arithmetic_op(0x5, dst, src);
+ }
+
+ void sub(const Operand& dst, Immediate src) {
+ immediate_arithmetic_op(0x5, dst, src);
+ }
+
void test(Register reg, const Immediate& imm);
void test(Register reg, const Operand& op);
void test(const Operand& op, const Immediate& imm);
- void xor_(Register dst, int32_t imm32);
- void xor_(Register dst, const Operand& src);
- void xor_(const Operand& src, Register dst);
- void xor_(const Operand& dst, const Immediate& x);
+ void xor_(Register dst, Register src) {
+ arithmetic_op(0x33, dst, src);
+ }
+
+ void xor_(Register dst, const Operand& src) {
+ arithmetic_op(0x33, dst, src);
+ }
+
+ void xor_(const Operand& dst, Register src) {
+ arithmetic_op(0x31, src, dst);
+ }
+
+ void xor_(Register dst, Immediate src) {
+ immediate_arithmetic_op(0x6, dst, src);
+ }
+
+ void xor_(const Operand& dst, Immediate src) {
+ immediate_arithmetic_op(0x6, dst, src);
+ }
+
// Bit operations.
void bt(const Operand& dst, Register src);
// code emission
void GrowBuffer();
+
+ void emit(byte x) { *pc_++ = x; }
inline void emitl(uint32_t x);
inline void emit(Handle<Object> handle);
inline void emitq(uint64_t x, RelocInfo::Mode rmode);
// is used for REX.X. REX.W is set.
inline void emit_rex_64(Register reg, const Operand& op);
+ // Emit the Mod/RM byte, and optionally the SIB byte and
+ // 1- or 4-byte offset for a memory operand. Also encodes
+ // the second operand of the operation, a register, into the Mod/RM byte.
+ void emit_operand(Register reg, const Operand& adr);
+
// Emit the code-object-relative offset of the label's position
inline void emit_code_relative_offset(Label* label);
- // instruction generation
- void emit_arith_b(int op1, int op2, Register dst, int imm8);
-
- // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81)
- // with a given destination expression and an immediate operand. It attempts
- // to use the shortest encoding possible.
- // sel specifies the /n in the modrm byte (see the Intel PRM).
+ // Emit machine code for one of the operations ADD, ADC, SUB, SBC,
+ // AND, OR, XOR, or CMP. The encodings of these operations are all
+ // similar, differing just in the opcode or in the reg field of the
+ // Mod/RM byte.
void arithmetic_op(byte opcode, Register dst, Register src);
void arithmetic_op(byte opcode, Register reg, const Operand& op);
void immediate_arithmetic_op(byte subcode, Register dst, Immediate src);
void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src);
- void emit_arith(int sel, Operand dst, const Immediate& x);
-
- void emit_operand(Register reg, const Operand& adr);
-
void emit_farith(int b1, int b2, int i);
// labels