// High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
-// REX.W is set.
+// REX.W is set. REX.X is cleared.
void Assembler::emit_rex_64(Register reg, Register rm_reg) {
emit(0x48 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
}
}
+// High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
+// REX.W is set. REX.X is cleared.
+void Assembler::emit_rex_32(Register reg, Register rm_reg) {
+ emit(0x40 | (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3);
+}
+
+
+// The high bit of reg is used for REX.R, the high bit of op's base
+// register is used for REX.B, and the high bit of op's index register
+// is used for REX.X. REX.W is cleared.
+void Assembler::emit_rex_32(Register reg, const Operand& op) {
+ emit(0x40 | (reg.code() & 0x8) >> 1 | op.rex_);
+}
+
+
+// High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
+// REX.W and REX.X are cleared. If no REX bits are set, no byte is emitted.
+void Assembler::emit_optional_rex_32(Register reg, Register rm_reg) {
+ byte rex_bits = (reg.code() & 0x8) >> 1 | rm_reg.code() >> 3;
+ if (rex_bits) emit(0x40 | rex_bits);
+}
+
+
+// The high bit of reg is used for REX.R, the high bit of op's base
+// register is used for REX.B, and the high bit of op's index register
+// is used for REX.X. REX.W is cleared. If no REX bits are set, nothing
+// is emitted.
+void Assembler::emit_optional_rex_32(Register reg, const Operand& op) {
+ byte rex_bits = (reg.code() & 0x8) >> 1 | op.rex_;
+ if (rex_bits) emit(0x40 | rex_bits);
+}
+
+
void Assembler::set_target_address_at(byte* location, byte* value) {
UNIMPLEMENTED();
}
#include "v8.h"
#include "macro-assembler.h"
+#include "serialize.h"
namespace v8 {
namespace internal {
}
}
-void Assembler::RecordComment(char const* a) {
- UNIMPLEMENTED();
-}
-
-void Assembler::RecordPosition(int a) {
- UNIMPLEMENTED();
-}
-
-void Assembler::RecordStatementPosition(int a) {
- UNIMPLEMENTED();
-}
-
void Assembler::bind_to(Label* L, int pos) {
ASSERT(!L->is_bound()); // Label may only be bound once.
Immediate src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- emit_rex_64(rax, dst);
+ emit_rex_64(dst);
if (is_int8(src.value_)) {
emit(0x83);
emit(0xC0 | (subcode << 3) | (dst.code() & 0x7));
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));
Immediate src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- emit_rex_64(rax, dst);
+ emit_rex_64(dst);
if (is_int8(src.value_)) {
emit(0x83);
emit_operand(Register::toRegister(subcode), dst);
void Assembler::dec(Register dst) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- emit_rex_64(rcx, dst);
+ emit_rex_64(dst);
emit(0xFF);
emit(0xC8 | (dst.code() & 0x7));
}
void Assembler::dec(const Operand& dst) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- emit_rex_64(rax, dst);
+ emit_rex_64(dst);
emit(0xFF);
- emit_operand(rcx, dst);
+ emit_operand(1, dst);
}
void Assembler::inc(Register dst) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- emit_rex_64(rax, dst);
+ emit_rex_64(dst);
emit(0xFF);
emit(0xC0 | (dst.code() & 0x7));
}
void Assembler::inc(const Operand& dst) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- emit_rex_64(rax, dst);
+ emit_rex_64(dst);
emit(0xFF);
- emit_operand(rax, dst);
+ emit_operand(0, dst);
}
void Assembler::movq(Register dst, Immediate value) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- emit_rex_64(rax, dst);
+ emit_rex_64(dst);
emit(0xC7);
emit(0xC0 | (dst.code() & 0x7));
emit(value); // Only 32-bit immediates are possible, not 8-bit immediates.
void Assembler::movq(Register dst, int64_t value, RelocInfo::Mode rmode) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- emit_rex_64(rax, dst);
+ emit_rex_64(dst);
emit(0xB8 | (dst.code() & 0x7));
emitq(value, rmode);
}
+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));
+}
+
+
+void Assembler::neg(const Operand& dst) {
+ EnsureSpace ensure_space(this);
+ last_pc_ = pc_;
+ emit_rex_64(dst);
+ emit(0xF7);
+ emit_operand(3, dst);
+}
+
+
void Assembler::nop() {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
}
+void Assembler::not_(Register dst) {
+ EnsureSpace ensure_space(this);
+ last_pc_ = pc_;
+ emit_rex_64(dst);
+ emit(0xF7);
+ emit(0xC0 | (0x2 << 3) | (dst.code() & 0x7));
+}
+
+
+void Assembler::not_(const Operand& dst) {
+ EnsureSpace ensure_space(this);
+ last_pc_ = pc_;
+ emit_rex_64(dst);
+ emit(0xF7);
+ emit_operand(2, dst);
+}
+
+
void Assembler::pop(Register dst) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
if (dst.code() & 0x8) {
- emit_rex_64(rax, dst);
+ emit_rex_64(dst);
}
emit(0x58 | (dst.code() & 0x7));
}
void Assembler::pop(const Operand& dst) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- emit_rex_64(rax, dst); // Could be omitted in some cases.
+ emit_rex_64(dst); // Could be omitted in some cases.
emit(0x8F);
- emit_operand(rax, dst);
+ emit_operand(0, dst);
}
EnsureSpace ensure_space(this);
last_pc_ = pc_;
if (src.code() & 0x8) {
- emit_rex_64(rax, src);
+ emit_rex_64(src);
}
emit(0x50 | (src.code() & 0x7));
}
void Assembler::push(const Operand& src) {
EnsureSpace ensure_space(this);
last_pc_ = pc_;
- emit_rex_64(rsi, src); // Could be omitted in some cases.
+ emit_rex_64(src); // Could be omitted in some cases.
emit(0xFF);
- emit_operand(rsi, src);
+ emit_operand(6, src);
}
}
}
+
+void Assembler::testb(Register reg, Immediate mask) {
+ EnsureSpace ensure_space(this);
+ last_pc_ = pc_;
+ if (reg.is(rax)) {
+ emit(0xA8);
+ emit(mask);
+ } else {
+ if (reg.code() & 0x8) {
+ emit_rex_32(rax, reg);
+ }
+ emit(0xF6);
+ emit(0xC0 | (reg.code() & 0x3));
+ emit(mask.value_); // Low byte emitted.
+ }
+}
+
+
+void Assembler::testb(const Operand& op, Immediate mask) {
+ EnsureSpace ensure_space(this);
+ last_pc_ = pc_;
+ emit_optional_rex_32(rax, op);
+ emit(0xF6);
+ emit_operand(rax, op); // Operation code 0
+ emit(mask.value_); // Low byte emitted.
+}
+
+
+void Assembler::testl(Register reg, Immediate mask) {
+ EnsureSpace ensure_space(this);
+ last_pc_ = pc_;
+ if (reg.is(rax)) {
+ emit(0xA9);
+ emit(mask);
+ } else {
+ emit_optional_rex_32(rax, reg);
+ emit(0xF7);
+ emit(0xC0 | (reg.code() & 0x3));
+ emit(mask);
+ }
+}
+
+
+void Assembler::testl(const Operand& op, Immediate mask) {
+ EnsureSpace ensure_space(this);
+ last_pc_ = pc_;
+ emit_optional_rex_32(rax, op);
+ emit(0xF7);
+ emit_operand(rax, op); // Operation code 0
+ emit(mask);
+}
+
+
+// Relocation information implementations
+
+void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
+ ASSERT(rmode != RelocInfo::NONE);
+ // Don't record external references unless the heap will be serialized.
+ if (rmode == RelocInfo::EXTERNAL_REFERENCE &&
+ !Serializer::enabled() &&
+ !FLAG_debug_code) {
+ return;
+ }
+ RelocInfo rinfo(pc_, rmode, data);
+ reloc_info_writer.Write(&rinfo);
+}
+
+void Assembler::RecordJSReturn() {
+ WriteRecordedPositions();
+ EnsureSpace ensure_space(this);
+ RecordRelocInfo(RelocInfo::JS_RETURN);
+}
+
+
+void Assembler::RecordComment(const char* msg) {
+ if (FLAG_debug_code) {
+ EnsureSpace ensure_space(this);
+ RecordRelocInfo(RelocInfo::COMMENT, reinterpret_cast<intptr_t>(msg));
+ }
+}
+
+
+void Assembler::RecordPosition(int pos) {
+ ASSERT(pos != RelocInfo::kNoPosition);
+ ASSERT(pos >= 0);
+ current_position_ = pos;
+}
+
+
+void Assembler::RecordStatementPosition(int pos) {
+ ASSERT(pos != RelocInfo::kNoPosition);
+ ASSERT(pos >= 0);
+ current_statement_position_ = pos;
+}
+
+
+void Assembler::WriteRecordedPositions() {
+ // Write the statement position if it is different from what was written last
+ // time.
+ if (current_statement_position_ != written_statement_position_) {
+ EnsureSpace ensure_space(this);
+ RecordRelocInfo(RelocInfo::STATEMENT_POSITION, current_statement_position_);
+ written_statement_position_ = current_statement_position_;
+ }
+
+ // Write the position if it is different from what was written last time and
+ // also different from the written statement position.
+ if (current_position_ != written_position_ &&
+ current_position_ != written_statement_position_) {
+ EnsureSpace ensure_space(this);
+ RecordRelocInfo(RelocInfo::POSITION, current_position_);
+ written_position_ = current_position_;
+ }
+}
+
+
+const int RelocInfo::kApplyMask =
+ RelocInfo::kCodeTargetMask | 1 << RelocInfo::RUNTIME_ENTRY |
+ 1 << RelocInfo::JS_RETURN | 1 << RelocInfo::INTERNAL_REFERENCE;
+
+
} } // namespace v8::internal
return NULL;
}
-const int RelocInfo::kApplyMask = -1;
-
StackFrame::Type StackFrame::ComputeType(StackFrame::State* a) {
UNIMPLEMENTED();
return NONE;
void mul(Register src);
void neg(Register dst);
+ void neg(const Operand& dst);
void not_(Register dst);
+ void not_(const Operand& dst);
void or_(Register dst, Register src) {
arithmetic_op(0x0B, dst, 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 testb(Register reg, Immediate mask);
+ void testb(const Operand& op, Immediate mask);
+ void testl(Register reg, Immediate mask);
+ void testl(const Operand& op, Immediate mask);
void xor_(Register dst, Register src) {
arithmetic_op(0x33, dst, src);
void RecordStatementPosition(int pos);
void WriteRecordedPositions();
- // Writes a single word of data in the code stream.
+ // Writes a doubleword of data in the code stream.
+ // Used for inline tables, e.g., jump-tables.
+ void dd(uint32_t data);
+
+ // Writes a quadword of data in the code stream.
// Used for inline tables, e.g., jump-tables.
- void dd(uint32_t data, RelocInfo::Mode reloc_info);
+ void dd(uint64_t data, RelocInfo::Mode reloc_info);
// Writes the absolute address of a bound label at the given position in
// the generated code. That positions should have the relocation mode
// High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
// REX.W is set.
inline void emit_rex_64(Register reg, Register rm_reg);
+ void emit_rex_64(Register rm_reg) { emit_rex_64(rax, rm_reg); }
// Emits a REX prefix that encodes a 64-bit operand size and
// the top bit of the destination, index, and base register codes.
// register is used for REX.B, and the high bit of op's index register
// is used for REX.X. REX.W is set.
inline void emit_rex_64(Register reg, const Operand& op);
+ void emit_rex_64(const Operand& op) { emit_rex_64(rax, op); }
+
+ // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
+ // REX.W is set.
+ inline void emit_rex_32(Register reg, Register rm_reg);
+
+ // The high bit of reg is used for REX.R, the high bit of op's base
+ // register is used for REX.B, and the high bit of op's index register
+ // is used for REX.X. REX.W is cleared.
+ inline void emit_rex_32(Register reg, const Operand& op);
+
+ // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
+ // REX.W is cleared. If no REX bits are set, no byte is emitted.
+ inline void emit_optional_rex_32(Register reg, Register rm_reg);
+
+ // The high bit of reg is used for REX.R, the high bit of op's base
+ // register is used for REX.B, and the high bit of op's index register
+ // is used for REX.X. REX.W is cleared. If no REX bits are set, nothing
+ // is emitted.
+ inline void emit_optional_rex_32(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.
+ // the second operand of the operation, a register or operation
+ // subcode, into the Mod/RM byte.
void emit_operand(Register reg, const Operand& adr);
+ void emit_operand(int op_subcode, const Operand& adr) {
+ emit_operand(Register::toRegister(op_subcode), adr);
+ }
// Emit the code-object-relative offset of the label's position
inline void emit_code_relative_offset(Label* label);
void link_to(Label* L, Label* appendix);
// record reloc info for current pc_
- void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0) {
- UNIMPLEMENTED();
- }
+ void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
friend class CodePatcher;
friend class EnsureSpace;