Commit b4a21977 authored by whesse@chromium.org's avatar whesse@chromium.org

Add test, neg, and not instructions to x64 assembler

Review URL: http://codereview.chromium.org/112066

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2076 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent e1787e78
......@@ -56,7 +56,7 @@ void Assembler::emitq(uint64_t x, RelocInfo::Mode rmode) {
// 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);
}
......@@ -70,6 +70,39 @@ void Assembler::emit_rex_64(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 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();
}
......
......@@ -28,6 +28,7 @@
#include "v8.h"
#include "macro-assembler.h"
#include "serialize.h"
namespace v8 {
namespace internal {
......@@ -173,18 +174,6 @@ void Assembler::Align(int m) {
}
}
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.
......@@ -319,11 +308,14 @@ void Assembler::immediate_arithmetic_op(byte subcode,
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));
......@@ -336,7 +328,7 @@ void Assembler::immediate_arithmetic_op(byte subcode,
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);
......@@ -373,7 +365,7 @@ void Assembler::call(Label* L) {
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));
}
......@@ -382,9 +374,9 @@ void Assembler::dec(Register dst) {
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);
}
......@@ -398,7 +390,7 @@ void Assembler::hlt() {
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));
}
......@@ -407,9 +399,9 @@ void Assembler::inc(Register dst) {
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);
}
......@@ -508,7 +500,7 @@ void Assembler::movq(Register dst, Register src) {
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.
......@@ -518,12 +510,30 @@ void Assembler::movq(Register dst, Immediate value) {
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_;
......@@ -531,11 +541,29 @@ void Assembler::nop() {
}
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));
}
......@@ -544,9 +572,9 @@ void Assembler::pop(Register dst) {
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);
}
......@@ -554,7 +582,7 @@ void Assembler::push(Register src) {
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));
}
......@@ -563,9 +591,9 @@ void Assembler::push(Register src) {
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);
}
......@@ -582,6 +610,127 @@ void Assembler::ret(int imm16) {
}
}
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
......@@ -732,8 +881,6 @@ Object* LoadStubCompiler::CompileLoadInterceptor(JSObject* a,
return NULL;
}
const int RelocInfo::kApplyMask = -1;
StackFrame::Type StackFrame::ComputeType(StackFrame::State* a) {
UNIMPLEMENTED();
return NONE;
......
......@@ -528,8 +528,10 @@ class Assembler : public Malloced {
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);
......@@ -590,10 +592,10 @@ class Assembler : public Malloced {
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);
......@@ -752,9 +754,13 @@ class Assembler : public Malloced {
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
......@@ -809,6 +815,7 @@ class Assembler : public Malloced {
// 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.
......@@ -816,11 +823,35 @@ class Assembler : public Malloced {
// 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);
......@@ -842,9 +873,7 @@ class Assembler : public Malloced {
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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment