Upgrade to 3.29
Update V8 to 3.29.88.17 and update makefiles to support building on
all the relevant platforms.
Bug: 17370214
Change-Id: Ia3407c157fd8d72a93e23d8318ccaf6ecf77fa4e
diff --git a/src/x64/assembler-x64.h b/src/x64/assembler-x64.h
index 60b29e6..b2a97cc 100644
--- a/src/x64/assembler-x64.h
+++ b/src/x64/assembler-x64.h
@@ -37,34 +37,13 @@
#ifndef V8_X64_ASSEMBLER_X64_H_
#define V8_X64_ASSEMBLER_X64_H_
-#include "serialize.h"
+#include "src/serialize.h"
namespace v8 {
namespace internal {
// Utility functions
-// Test whether a 64-bit value is in a specific range.
-inline bool is_uint32(int64_t x) {
- static const uint64_t kMaxUInt32 = V8_UINT64_C(0xffffffff);
- return static_cast<uint64_t>(x) <= kMaxUInt32;
-}
-
-inline bool is_int32(int64_t x) {
- static const int64_t kMinInt32 = -V8_INT64_C(0x80000000);
- return is_uint32(x - kMinInt32);
-}
-
-inline bool uint_is_int32(uint64_t x) {
- static const uint64_t kMaxInt32 = V8_UINT64_C(0x7fffffff);
- return x <= kMaxInt32;
-}
-
-inline bool is_uint32(uint64_t x) {
- static const uint64_t kMaxUInt32 = V8_UINT64_C(0xffffffff);
- return x <= kMaxUInt32;
-}
-
// CPU Registers.
//
// 1) We would prefer to use an enum, but enum values are assignment-
@@ -91,30 +70,33 @@
// The non-allocatable registers are:
// rsp - stack pointer
// rbp - frame pointer
- // rsi - context register
// r10 - fixed scratch register
// r12 - smi constant register
// r13 - root register
+ static const int kMaxNumAllocatableRegisters = 11;
+ static int NumAllocatableRegisters() {
+ return kMaxNumAllocatableRegisters;
+ }
static const int kNumRegisters = 16;
- static const int kNumAllocatableRegisters = 10;
static int ToAllocationIndex(Register reg) {
return kAllocationIndexByRegisterCode[reg.code()];
}
static Register FromAllocationIndex(int index) {
- ASSERT(index >= 0 && index < kNumAllocatableRegisters);
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
Register result = { kRegisterCodeByAllocationIndex[index] };
return result;
}
static const char* AllocationIndexToString(int index) {
- ASSERT(index >= 0 && index < kNumAllocatableRegisters);
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
const char* const names[] = {
"rax",
"rbx",
"rdx",
"rcx",
+ "rsi",
"rdi",
"r8",
"r9",
@@ -134,7 +116,7 @@
// rax, rbx, rcx and rdx are byte registers, the rest are not.
bool is_byte_register() const { return code_ <= 3; }
int code() const {
- ASSERT(is_valid());
+ DCHECK(is_valid());
return code_;
}
int bit() const {
@@ -157,7 +139,7 @@
int code_;
private:
- static const int kRegisterCodeByAllocationIndex[kNumAllocatableRegisters];
+ static const int kRegisterCodeByAllocationIndex[kMaxNumAllocatableRegisters];
static const int kAllocationIndexByRegisterCode[kNumRegisters];
};
@@ -197,24 +179,40 @@
const Register r15 = { kRegister_r15_Code };
const Register no_reg = { kRegister_no_reg_Code };
+#ifdef _WIN64
+ // Windows calling convention
+ const Register arg_reg_1 = { kRegister_rcx_Code };
+ const Register arg_reg_2 = { kRegister_rdx_Code };
+ const Register arg_reg_3 = { kRegister_r8_Code };
+ const Register arg_reg_4 = { kRegister_r9_Code };
+#else
+ // AMD64 calling convention
+ const Register arg_reg_1 = { kRegister_rdi_Code };
+ const Register arg_reg_2 = { kRegister_rsi_Code };
+ const Register arg_reg_3 = { kRegister_rdx_Code };
+ const Register arg_reg_4 = { kRegister_rcx_Code };
+#endif // _WIN64
struct XMMRegister {
- static const int kNumRegisters = 16;
- static const int kNumAllocatableRegisters = 15;
+ static const int kMaxNumRegisters = 16;
+ static const int kMaxNumAllocatableRegisters = 15;
+ static int NumAllocatableRegisters() {
+ return kMaxNumAllocatableRegisters;
+ }
static int ToAllocationIndex(XMMRegister reg) {
- ASSERT(reg.code() != 0);
+ DCHECK(reg.code() != 0);
return reg.code() - 1;
}
static XMMRegister FromAllocationIndex(int index) {
- ASSERT(0 <= index && index < kNumAllocatableRegisters);
+ DCHECK(0 <= index && index < kMaxNumAllocatableRegisters);
XMMRegister result = { index + 1 };
return result;
}
static const char* AllocationIndexToString(int index) {
- ASSERT(index >= 0 && index < kNumAllocatableRegisters);
+ DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
const char* const names[] = {
"xmm1",
"xmm2",
@@ -236,15 +234,15 @@
}
static XMMRegister from_code(int code) {
- ASSERT(code >= 0);
- ASSERT(code < kNumRegisters);
+ DCHECK(code >= 0);
+ DCHECK(code < kMaxNumRegisters);
XMMRegister r = { code };
return r;
}
- bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
+ bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters; }
bool is(XMMRegister reg) const { return code_ == reg.code_; }
int code() const {
- ASSERT(is_valid());
+ DCHECK(is_valid());
return code_;
}
@@ -328,8 +326,8 @@
}
-// Corresponds to transposing the operands of a comparison.
-inline Condition ReverseCondition(Condition cc) {
+// Commute a condition such that {a cond b == b cond' a}.
+inline Condition CommuteCondition(Condition cc) {
switch (cc) {
case below:
return above;
@@ -349,7 +347,7 @@
return greater_equal;
default:
return cc;
- };
+ }
}
@@ -359,6 +357,10 @@
class Immediate BASE_EMBEDDED {
public:
explicit Immediate(int32_t value) : value_(value) {}
+ explicit Immediate(Smi* value) {
+ DCHECK(SmiValuesAre31Bits()); // Only available for 31-bit SMI.
+ value_ = static_cast<int32_t>(reinterpret_cast<intptr_t>(value));
+ }
private:
int32_t value_;
@@ -376,7 +378,7 @@
times_4 = 2,
times_8 = 3,
times_int_size = times_4,
- times_pointer_size = times_8
+ times_pointer_size = (kPointerSize == 8) ? times_8 : times_4
};
@@ -435,96 +437,40 @@
};
-// CpuFeatures keeps track of which features are supported by the target CPU.
-// Supported features must be enabled by a Scope before use.
-// Example:
-// if (CpuFeatures::IsSupported(SSE3)) {
-// CpuFeatures::Scope fscope(SSE3);
-// // Generate SSE3 floating point code.
-// } else {
-// // Generate standard x87 or SSE2 floating point code.
-// }
-class CpuFeatures : public AllStatic {
- public:
- // Detect features of the target CPU. Set safe defaults if the serializer
- // is enabled (snapshots must be portable).
- static void Probe();
+#define ASSEMBLER_INSTRUCTION_LIST(V) \
+ V(add) \
+ V(and) \
+ V(cmp) \
+ V(dec) \
+ V(idiv) \
+ V(div) \
+ V(imul) \
+ V(inc) \
+ V(lea) \
+ V(mov) \
+ V(movzxb) \
+ V(movzxw) \
+ V(neg) \
+ V(not) \
+ V(or) \
+ V(repmovs) \
+ V(sbb) \
+ V(sub) \
+ V(test) \
+ V(xchg) \
+ V(xor)
- // Check whether a feature is supported by the target CPU.
- static bool IsSupported(CpuFeature f) {
- ASSERT(initialized_);
- if (f == SSE2 && !FLAG_enable_sse2) return false;
- if (f == SSE3 && !FLAG_enable_sse3) return false;
- if (f == CMOV && !FLAG_enable_cmov) return false;
- if (f == RDTSC && !FLAG_enable_rdtsc) return false;
- if (f == SAHF && !FLAG_enable_sahf) return false;
- return (supported_ & (V8_UINT64_C(1) << f)) != 0;
- }
-#ifdef DEBUG
- // Check whether a feature is currently enabled.
- static bool IsEnabled(CpuFeature f) {
- ASSERT(initialized_);
- Isolate* isolate = Isolate::UncheckedCurrent();
- if (isolate == NULL) {
- // When no isolate is available, work as if we're running in
- // release mode.
- return IsSupported(f);
- }
- uint64_t enabled = isolate->enabled_cpu_features();
- return (enabled & (V8_UINT64_C(1) << f)) != 0;
- }
-#endif
-
- // Enable a specified feature within a scope.
- class Scope BASE_EMBEDDED {
-#ifdef DEBUG
-
- public:
- explicit Scope(CpuFeature f) {
- uint64_t mask = V8_UINT64_C(1) << f;
- ASSERT(CpuFeatures::IsSupported(f));
- ASSERT(!Serializer::enabled() ||
- (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
- isolate_ = Isolate::UncheckedCurrent();
- old_enabled_ = 0;
- if (isolate_ != NULL) {
- old_enabled_ = isolate_->enabled_cpu_features();
- isolate_->set_enabled_cpu_features(old_enabled_ | mask);
- }
- }
- ~Scope() {
- ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
- if (isolate_ != NULL) {
- isolate_->set_enabled_cpu_features(old_enabled_);
- }
- }
-
- private:
- Isolate* isolate_;
- uint64_t old_enabled_;
-#else
-
- public:
- explicit Scope(CpuFeature f) {}
-#endif
- };
-
- private:
- // Safe defaults include SSE2 and CMOV for X64. It is always available, if
- // anyone checks, but they shouldn't need to check.
- // The required user mode extensions in X64 are (from AMD64 ABI Table A.1):
- // fpu, tsc, cx8, cmov, mmx, sse, sse2, fxsr, syscall
- static const uint64_t kDefaultCpuFeatures = (1 << SSE2 | 1 << CMOV);
-
-#ifdef DEBUG
- static bool initialized_;
-#endif
- static uint64_t supported_;
- static uint64_t found_by_runtime_probing_;
-
- DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
-};
+// Shift instructions on operands/registers with kPointerSize, kInt32Size and
+// kInt64Size.
+#define SHIFT_INSTRUCTION_LIST(V) \
+ V(rol, 0x0) \
+ V(ror, 0x1) \
+ V(rcl, 0x2) \
+ V(rcr, 0x3) \
+ V(shl, 0x4) \
+ V(shr, 0x5) \
+ V(sar, 0x7) \
class Assembler : public AssemblerBase {
@@ -555,10 +501,7 @@
// is too small, a fatal error occurs. No deallocation of the buffer is done
// upon destruction of the assembler.
Assembler(Isolate* isolate, void* buffer, int buffer_size);
- ~Assembler();
-
- // Overrides the default provided by FLAG_debug_code.
- void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
+ virtual ~Assembler() { }
// GetCode emits any pending (non-emitted) code and fills the descriptor
// desc. GetCode() is idempotent; it returns the same result if no other
@@ -572,51 +515,86 @@
// the absolute address of the target.
// These functions convert between absolute Addresses of Code objects and
// the relative displacements stored in the code.
- static inline Address target_address_at(Address pc);
- static inline void set_target_address_at(Address pc, Address target);
+ static inline Address target_address_at(Address pc,
+ ConstantPoolArray* constant_pool);
+ static inline void set_target_address_at(Address pc,
+ ConstantPoolArray* constant_pool,
+ Address target,
+ ICacheFlushMode icache_flush_mode =
+ FLUSH_ICACHE_IF_NEEDED) ;
+ static inline Address target_address_at(Address pc, Code* code) {
+ ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
+ return target_address_at(pc, constant_pool);
+ }
+ static inline void set_target_address_at(Address pc,
+ Code* code,
+ Address target,
+ ICacheFlushMode icache_flush_mode =
+ FLUSH_ICACHE_IF_NEEDED) {
+ ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
+ set_target_address_at(pc, constant_pool, target, icache_flush_mode);
+ }
+
+ // Return the code target address at a call site from the return address
+ // of that call in the instruction stream.
+ static inline Address target_address_from_return_address(Address pc);
+
+ // Return the code target address of the patch debug break slot
+ inline static Address break_address_from_return_address(Address pc);
// This sets the branch destination (which is in the instruction on x64).
// This is for calls and branches within generated code.
inline static void deserialization_set_special_target_at(
- Address instruction_payload, Address target) {
- set_target_address_at(instruction_payload, target);
+ Address instruction_payload, Code* code, Address target) {
+ set_target_address_at(instruction_payload, code, target);
}
- // This sets the branch destination (which is a load instruction on x64).
- // This is for calls and branches to runtime code.
- inline static void set_external_target_at(Address instruction_payload,
- Address target) {
- *reinterpret_cast<Address*>(instruction_payload) = target;
+ static inline RelocInfo::Mode RelocInfoNone() {
+ if (kPointerSize == kInt64Size) {
+ return RelocInfo::NONE64;
+ } else {
+ DCHECK(kPointerSize == kInt32Size);
+ return RelocInfo::NONE32;
+ }
}
inline Handle<Object> code_target_object_handle_at(Address pc);
+ inline Address runtime_entry_at(Address pc);
// Number of bytes taken up by the branch target in the code.
static const int kSpecialTargetSize = 4; // Use 32-bit displacement.
// Distance between the address of the code target in the call instruction
// and the return address pushed on the stack.
static const int kCallTargetAddressOffset = 4; // Use 32-bit displacement.
- // Distance between the start of the JS return sequence and where the
- // 32-bit displacement of a near call would be, relative to the pushed
- // return address. TODO: Use return sequence length instead.
- // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
- static const int kPatchReturnSequenceAddressOffset = 13 - 4;
- // Distance between start of patched debug break slot and where the
- // 32-bit displacement of a near call would be, relative to the pushed
- // return address. TODO: Use return sequence length instead.
- // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
- static const int kPatchDebugBreakSlotAddressOffset = 13 - 4;
- // TODO(X64): Rename this, removing the "Real", after changing the above.
- static const int kRealPatchReturnSequenceAddressOffset = 2;
-
- // Some x64 JS code is padded with int3 to make it large
- // enough to hold an instruction when the debugger patches it.
- static const int kJumpInstructionLength = 13;
- static const int kCallInstructionLength = 13;
- static const int kJSReturnSequenceLength = 13;
+ // The length of call(kScratchRegister).
+ static const int kCallScratchRegisterInstructionLength = 3;
+ // The length of call(Immediate32).
static const int kShortCallInstructionLength = 5;
+ // The length of movq(kScratchRegister, address).
+ static const int kMoveAddressIntoScratchRegisterInstructionLength =
+ 2 + kPointerSize;
+ // The length of movq(kScratchRegister, address) and call(kScratchRegister).
+ static const int kCallSequenceLength =
+ kMoveAddressIntoScratchRegisterInstructionLength +
+ kCallScratchRegisterInstructionLength;
- // The debug break slot must be able to contain a call instruction.
- static const int kDebugBreakSlotLength = kCallInstructionLength;
+ // The js return and debug break slot must be able to contain an indirect
+ // call sequence, some x64 JS code is padded with int3 to make it large
+ // enough to hold an instruction when the debugger patches it.
+ static const int kJSReturnSequenceLength = kCallSequenceLength;
+ static const int kDebugBreakSlotLength = kCallSequenceLength;
+ static const int kPatchDebugBreakSlotReturnOffset = kCallTargetAddressOffset;
+ // Distance between the start of the JS return sequence and where the
+ // 32-bit displacement of a short call would be. The short call is from
+ // SetDebugBreakAtIC from debug-x64.cc.
+ static const int kPatchReturnSequenceAddressOffset =
+ kJSReturnSequenceLength - kPatchDebugBreakSlotReturnOffset;
+ // Distance between the start of the JS return sequence and where the
+ // 32-bit displacement of a short call would be. The short call is from
+ // SetDebugBreakAtIC from debug-x64.cc.
+ static const int kPatchDebugBreakSlotAddressOffset =
+ kDebugBreakSlotLength - kPatchDebugBreakSlotReturnOffset;
+ static const int kRealPatchReturnSequenceAddressOffset =
+ kMoveAddressIntoScratchRegisterInstructionLength - kPointerSize;
// One byte opcode for test eax,0xXXXXXXXX.
static const byte kTestEaxByte = 0xA9;
@@ -629,7 +607,8 @@
static const byte kJccShortPrefix = 0x70;
static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
static const byte kJcShortOpcode = kJccShortPrefix | carry;
-
+ static const byte kJnzShortOpcode = kJccShortPrefix | not_zero;
+ static const byte kJzShortOpcode = kJccShortPrefix | zero;
// ---------------------------------------------------------------------------
@@ -647,9 +626,57 @@
// - Instructions on 16-bit (word) operands/registers have a trailing 'w'.
// - Instructions on 32-bit (doubleword) operands/registers use 'l'.
// - Instructions on 64-bit (quadword) operands/registers use 'q'.
- //
- // Some mnemonics, such as "and", are the same as C++ keywords.
- // Naming conflicts with C++ keywords are resolved by adding a trailing '_'.
+ // - Instructions on operands/registers with pointer size use 'p'.
+
+ STATIC_ASSERT(kPointerSize == kInt64Size || kPointerSize == kInt32Size);
+
+#define DECLARE_INSTRUCTION(instruction) \
+ template<class P1> \
+ void instruction##p(P1 p1) { \
+ emit_##instruction(p1, kPointerSize); \
+ } \
+ \
+ template<class P1> \
+ void instruction##l(P1 p1) { \
+ emit_##instruction(p1, kInt32Size); \
+ } \
+ \
+ template<class P1> \
+ void instruction##q(P1 p1) { \
+ emit_##instruction(p1, kInt64Size); \
+ } \
+ \
+ template<class P1, class P2> \
+ void instruction##p(P1 p1, P2 p2) { \
+ emit_##instruction(p1, p2, kPointerSize); \
+ } \
+ \
+ template<class P1, class P2> \
+ void instruction##l(P1 p1, P2 p2) { \
+ emit_##instruction(p1, p2, kInt32Size); \
+ } \
+ \
+ template<class P1, class P2> \
+ void instruction##q(P1 p1, P2 p2) { \
+ emit_##instruction(p1, p2, kInt64Size); \
+ } \
+ \
+ template<class P1, class P2, class P3> \
+ void instruction##p(P1 p1, P2 p2, P3 p3) { \
+ emit_##instruction(p1, p2, p3, kPointerSize); \
+ } \
+ \
+ template<class P1, class P2, class P3> \
+ void instruction##l(P1 p1, P2 p2, P3 p3) { \
+ emit_##instruction(p1, p2, p3, kInt32Size); \
+ } \
+ \
+ template<class P1, class P2, class P3> \
+ void instruction##q(P1 p1, P2 p2, P3 p3) { \
+ emit_##instruction(p1, p2, p3, kInt64Size); \
+ }
+ ASSEMBLER_INSTRUCTION_LIST(DECLARE_INSTRUCTION)
+#undef DECLARE_INSTRUCTION
// Insert the smallest number of nop instructions
// possible to align the pc offset to a multiple
@@ -663,15 +690,15 @@
void pushfq();
void popfq();
- void push(Immediate value);
+ void pushq(Immediate value);
// Push a 32 bit integer, and guarantee that it is actually pushed as a
// 32 bit value, the normal push will optimize the 8 bit case.
- void push_imm32(int32_t imm32);
- void push(Register src);
- void push(const Operand& src);
+ void pushq_imm32(int32_t imm32);
+ void pushq(Register src);
+ void pushq(const Operand& src);
- void pop(Register dst);
- void pop(const Operand& dst);
+ void popq(Register dst);
+ void popq(const Operand& dst);
void enter(Immediate size);
void leave();
@@ -680,55 +707,39 @@
void movb(Register dst, const Operand& src);
void movb(Register dst, Immediate imm);
void movb(const Operand& dst, Register src);
+ void movb(const Operand& dst, Immediate imm);
// Move the low 16 bits of a 64-bit register value to a 16-bit
// memory location.
+ void movw(Register dst, const Operand& src);
void movw(const Operand& dst, Register src);
+ void movw(const Operand& dst, Immediate imm);
- void movl(Register dst, Register src);
- void movl(Register dst, const Operand& src);
- void movl(const Operand& dst, Register src);
- void movl(const Operand& dst, Immediate imm);
- // Load a 32-bit immediate value, zero-extended to 64 bits.
- void movl(Register dst, Immediate imm32);
-
- // Move 64 bit register value to 64-bit memory location.
- void movq(const Operand& dst, Register src);
- // Move 64 bit memory location to 64-bit register value.
- void movq(Register dst, const Operand& src);
- void movq(Register dst, Register src);
- // Sign extends immediate 32-bit value to 64 bits.
- void movq(Register dst, Immediate x);
// Move the offset of the label location relative to the current
// position (after the move) to the destination.
void movl(const Operand& dst, Label* src);
- // Move sign extended immediate to memory location.
- void movq(const Operand& dst, Immediate value);
- // Instructions to load a 64-bit immediate into a register.
- // All 64-bit immediates must have a relocation mode.
- void movq(Register dst, void* ptr, RelocInfo::Mode rmode);
- void movq(Register dst, int64_t value, RelocInfo::Mode rmode);
- void movq(Register dst, const char* s, RelocInfo::Mode rmode);
- // Moves the address of the external reference into the register.
- void movq(Register dst, ExternalReference ext);
- void movq(Register dst, Handle<Object> handle, RelocInfo::Mode rmode);
+ // Loads a pointer into a register with a relocation mode.
+ void movp(Register dst, void* ptr, RelocInfo::Mode rmode);
+ // Loads a 64-bit immediate into a register.
+ void movq(Register dst, int64_t value);
+ void movq(Register dst, uint64_t value);
+
+ void movsxbl(Register dst, const Operand& src);
void movsxbq(Register dst, const Operand& src);
+ void movsxwl(Register dst, const Operand& src);
void movsxwq(Register dst, const Operand& src);
void movsxlq(Register dst, Register src);
void movsxlq(Register dst, const Operand& src);
- void movzxbq(Register dst, const Operand& src);
- void movzxbl(Register dst, const Operand& src);
- void movzxwq(Register dst, const Operand& src);
- void movzxwl(Register dst, const Operand& src);
// Repeated moves.
void repmovsb();
void repmovsw();
- void repmovsl();
- void repmovsq();
+ void repmovsp() { emit_repmovs(kPointerSize); }
+ void repmovsl() { emit_repmovs(kInt32Size); }
+ void repmovsq() { emit_repmovs(kInt64Size); }
// Instruction to load from an immediate 64-bit pointer into RAX.
void load_rax(void* ptr, RelocInfo::Mode rmode);
@@ -740,58 +751,6 @@
void cmovl(Condition cc, Register dst, Register src);
void cmovl(Condition cc, Register dst, const Operand& src);
- // Exchange two registers
- void xchg(Register dst, Register src);
-
- // Arithmetics
- void addl(Register dst, Register src) {
- arithmetic_op_32(0x03, dst, src);
- }
-
- void addl(Register dst, Immediate src) {
- immediate_arithmetic_op_32(0x0, dst, src);
- }
-
- void addl(Register dst, const Operand& src) {
- arithmetic_op_32(0x03, dst, src);
- }
-
- void addl(const Operand& dst, Immediate src) {
- immediate_arithmetic_op_32(0x0, dst, src);
- }
-
- void addl(const Operand& dst, Register src) {
- arithmetic_op_32(0x01, src, dst);
- }
-
- void addq(Register dst, Register src) {
- arithmetic_op(0x03, dst, src);
- }
-
- void addq(Register dst, const Operand& src) {
- arithmetic_op(0x03, dst, src);
- }
-
- void addq(const Operand& dst, Register src) {
- arithmetic_op(0x01, src, dst);
- }
-
- void addq(Register dst, Immediate src) {
- immediate_arithmetic_op(0x0, dst, src);
- }
-
- void addq(const Operand& dst, Immediate src) {
- immediate_arithmetic_op(0x0, dst, src);
- }
-
- void sbbl(Register dst, Register src) {
- arithmetic_op_32(0x1b, dst, src);
- }
-
- void sbbq(Register dst, Register src) {
- arithmetic_op(0x1b, dst, src);
- }
-
void cmpb(Register dst, Immediate src) {
immediate_arithmetic_op_8(0x7, dst, src);
}
@@ -799,15 +758,15 @@
void cmpb_al(Immediate src);
void cmpb(Register dst, Register src) {
- arithmetic_op(0x3A, dst, src);
+ arithmetic_op_8(0x3A, dst, src);
}
void cmpb(Register dst, const Operand& src) {
- arithmetic_op(0x3A, dst, src);
+ arithmetic_op_8(0x3A, dst, src);
}
void cmpb(const Operand& dst, Register src) {
- arithmetic_op(0x38, src, dst);
+ arithmetic_op_8(0x38, src, dst);
}
void cmpb(const Operand& dst, Immediate src) {
@@ -834,86 +793,10 @@
arithmetic_op_16(0x39, src, dst);
}
- void cmpl(Register dst, Register src) {
- arithmetic_op_32(0x3B, dst, src);
- }
-
- void cmpl(Register dst, const Operand& src) {
- arithmetic_op_32(0x3B, dst, src);
- }
-
- void cmpl(const Operand& dst, Register src) {
- arithmetic_op_32(0x39, src, dst);
- }
-
- void cmpl(Register dst, Immediate src) {
- immediate_arithmetic_op_32(0x7, dst, src);
- }
-
- void cmpl(const Operand& dst, Immediate src) {
- immediate_arithmetic_op_32(0x7, dst, src);
- }
-
- void cmpq(Register dst, Register src) {
- arithmetic_op(0x3B, dst, src);
- }
-
- void cmpq(Register dst, const Operand& src) {
- arithmetic_op(0x3B, dst, src);
- }
-
- void cmpq(const Operand& dst, Register src) {
- arithmetic_op(0x39, src, dst);
- }
-
- void cmpq(Register dst, Immediate src) {
- immediate_arithmetic_op(0x7, dst, src);
- }
-
- void cmpq(const Operand& dst, Immediate src) {
- 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_(const Operand& dst, Immediate src) {
- immediate_arithmetic_op(0x4, dst, src);
- }
-
- void andl(Register dst, Immediate src) {
- immediate_arithmetic_op_32(0x4, dst, src);
- }
-
- void andl(Register dst, Register src) {
- arithmetic_op_32(0x23, dst, src);
- }
-
- void andl(Register dst, const Operand& src) {
- arithmetic_op_32(0x23, dst, src);
- }
-
void andb(Register dst, Immediate src) {
immediate_arithmetic_op_8(0x4, dst, src);
}
- void decq(Register dst);
- void decq(const Operand& dst);
- void decl(Register dst);
- void decl(const Operand& dst);
void decb(Register dst);
void decb(const Operand& dst);
@@ -922,92 +805,35 @@
// Sign-extends eax into edx:eax.
void cdq();
- // Divide rdx:rax by src. Quotient in rax, remainder in rdx.
- void idivq(Register src);
- // Divide edx:eax by lower 32 bits of src. Quotient in eax, rem. in edx.
- void idivl(Register src);
-
- // Signed multiply instructions.
- void imul(Register src); // rdx:rax = rax * src.
- void imul(Register dst, Register src); // dst = dst * src.
- void imul(Register dst, const Operand& src); // dst = dst * src.
- void imul(Register dst, Register src, Immediate imm); // dst = src * imm.
- // Signed 32-bit multiply instructions.
- void imull(Register dst, Register src); // dst = dst * src.
- void imull(Register dst, const Operand& src); // dst = dst * src.
- void imull(Register dst, Register src, Immediate imm); // dst = src * imm.
-
- void incq(Register dst);
- void incq(const Operand& dst);
- void incl(Register dst);
- void incl(const Operand& dst);
-
- void lea(Register dst, const Operand& src);
- void leal(Register dst, const Operand& src);
-
// Multiply rax by src, put the result in rdx:rax.
void mul(Register src);
- void neg(Register dst);
- void neg(const Operand& dst);
- void negl(Register dst);
-
- void not_(Register dst);
- void not_(const Operand& dst);
- void notl(Register dst);
-
- void or_(Register dst, Register src) {
- arithmetic_op(0x0B, dst, src);
+#define DECLARE_SHIFT_INSTRUCTION(instruction, subcode) \
+ void instruction##p(Register dst, Immediate imm8) { \
+ shift(dst, imm8, subcode, kPointerSize); \
+ } \
+ \
+ void instruction##l(Register dst, Immediate imm8) { \
+ shift(dst, imm8, subcode, kInt32Size); \
+ } \
+ \
+ void instruction##q(Register dst, Immediate imm8) { \
+ shift(dst, imm8, subcode, kInt64Size); \
+ } \
+ \
+ void instruction##p_cl(Register dst) { \
+ shift(dst, subcode, kPointerSize); \
+ } \
+ \
+ void instruction##l_cl(Register dst) { \
+ shift(dst, subcode, kInt32Size); \
+ } \
+ \
+ void instruction##q_cl(Register dst) { \
+ shift(dst, subcode, kInt64Size); \
}
-
- void orl(Register dst, Register src) {
- arithmetic_op_32(0x0B, dst, src);
- }
-
- void or_(Register dst, const Operand& src) {
- arithmetic_op(0x0B, dst, src);
- }
-
- void orl(Register dst, const Operand& src) {
- arithmetic_op_32(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 orl(Register dst, Immediate src) {
- immediate_arithmetic_op_32(0x1, dst, src);
- }
-
- void or_(const Operand& dst, Immediate src) {
- immediate_arithmetic_op(0x1, dst, src);
- }
-
- void orl(const Operand& dst, Immediate src) {
- immediate_arithmetic_op_32(0x1, dst, src);
- }
-
-
- void rcl(Register dst, Immediate imm8) {
- shift(dst, imm8, 0x2);
- }
-
- void rol(Register dst, Immediate imm8) {
- shift(dst, imm8, 0x0);
- }
-
- void rcr(Register dst, Immediate imm8) {
- shift(dst, imm8, 0x3);
- }
-
- void ror(Register dst, Immediate imm8) {
- shift(dst, imm8, 0x1);
- }
+ SHIFT_INSTRUCTION_LIST(DECLARE_SHIFT_INSTRUCTION)
+#undef DECLARE_SHIFT_INSTRUCTION
// Shifts dst:src left by cl bits, affecting only dst.
void shld(Register dst, Register src);
@@ -1015,99 +841,9 @@
// Shifts src:dst right by cl bits, affecting only dst.
void shrd(Register dst, Register src);
- // Shifts dst right, duplicating sign bit, by shift_amount bits.
- // Shifting by 1 is handled efficiently.
- void sar(Register dst, Immediate shift_amount) {
- shift(dst, shift_amount, 0x7);
- }
-
- // Shifts dst right, duplicating sign bit, by shift_amount bits.
- // Shifting by 1 is handled efficiently.
- void sarl(Register dst, Immediate shift_amount) {
- shift_32(dst, shift_amount, 0x7);
- }
-
- // Shifts dst right, duplicating sign bit, by cl % 64 bits.
- void sar_cl(Register dst) {
- shift(dst, 0x7);
- }
-
- // Shifts dst right, duplicating sign bit, by cl % 64 bits.
- void sarl_cl(Register dst) {
- shift_32(dst, 0x7);
- }
-
- void shl(Register dst, Immediate shift_amount) {
- shift(dst, shift_amount, 0x4);
- }
-
- void shl_cl(Register dst) {
- shift(dst, 0x4);
- }
-
- void shll_cl(Register dst) {
- shift_32(dst, 0x4);
- }
-
- void shll(Register dst, Immediate shift_amount) {
- shift_32(dst, shift_amount, 0x4);
- }
-
- void shr(Register dst, Immediate shift_amount) {
- shift(dst, shift_amount, 0x5);
- }
-
- void shr_cl(Register dst) {
- shift(dst, 0x5);
- }
-
- void shrl_cl(Register dst) {
- shift_32(dst, 0x5);
- }
-
- void shrl(Register dst, Immediate shift_amount) {
- shift_32(dst, shift_amount, 0x5);
- }
-
void store_rax(void* dst, RelocInfo::Mode mode);
void store_rax(ExternalReference ref);
- void subq(Register dst, Register src) {
- arithmetic_op(0x2B, dst, src);
- }
-
- void subq(Register dst, const Operand& src) {
- arithmetic_op(0x2B, dst, src);
- }
-
- void subq(const Operand& dst, Register src) {
- arithmetic_op(0x29, src, dst);
- }
-
- void subq(Register dst, Immediate src) {
- immediate_arithmetic_op(0x5, dst, src);
- }
-
- void subq(const Operand& dst, Immediate src) {
- immediate_arithmetic_op(0x5, dst, src);
- }
-
- void subl(Register dst, Register src) {
- arithmetic_op_32(0x2B, dst, src);
- }
-
- void subl(Register dst, const Operand& src) {
- arithmetic_op_32(0x2B, dst, src);
- }
-
- void subl(const Operand& dst, Immediate src) {
- immediate_arithmetic_op_32(0x5, dst, src);
- }
-
- void subl(Register dst, Immediate src) {
- immediate_arithmetic_op_32(0x5, dst, src);
- }
-
void subb(Register dst, Immediate src) {
immediate_arithmetic_op_8(0x5, dst, src);
}
@@ -1116,56 +852,11 @@
void testb(Register reg, Immediate mask);
void testb(const Operand& op, Immediate mask);
void testb(const Operand& op, Register reg);
- void testl(Register dst, Register src);
- void testl(Register reg, Immediate mask);
- void testl(const Operand& op, Immediate mask);
- void testq(const Operand& op, Register reg);
- void testq(Register dst, Register src);
- void testq(Register dst, Immediate mask);
-
- void xor_(Register dst, Register src) {
- if (dst.code() == src.code()) {
- arithmetic_op_32(0x33, dst, src);
- } else {
- arithmetic_op(0x33, dst, src);
- }
- }
-
- void xorl(Register dst, Register src) {
- arithmetic_op_32(0x33, dst, src);
- }
-
- void xorl(Register dst, const Operand& src) {
- arithmetic_op_32(0x33, dst, src);
- }
-
- void xorl(Register dst, Immediate src) {
- immediate_arithmetic_op_32(0x6, dst, src);
- }
-
- void xorl(const Operand& dst, Immediate src) {
- immediate_arithmetic_op_32(0x6, 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);
void bts(const Operand& dst, Register src);
+ void bsrl(Register dst, Register src);
// Miscellaneous
void clc();
@@ -1174,7 +865,6 @@
void hlt();
void int3();
void nop();
- void rdtsc();
void ret(int imm16);
void setcc(Condition cc, Register reg);
@@ -1198,9 +888,10 @@
// Calls
// Call near relative 32-bit displacement, relative to next instruction.
void call(Label* L);
+ void call(Address entry, RelocInfo::Mode rmode);
void call(Handle<Code> target,
RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
- unsigned ast_id = kNoASTId);
+ TypeFeedbackId ast_id = TypeFeedbackId::None());
// Calls directly to the given address using a relative offset.
// Should only ever be used in Code objects for calls within the
@@ -1211,26 +902,22 @@
// Call near absolute indirect, address in register
void call(Register adr);
- // Call near indirect
- void call(const Operand& operand);
-
// Jumps
// Jump short or near relative.
// Use a 32-bit signed displacement.
// Unconditional jump to L
void jmp(Label* L, Label::Distance distance = Label::kFar);
+ void jmp(Address entry, RelocInfo::Mode rmode);
void jmp(Handle<Code> target, RelocInfo::Mode rmode);
// Jump near absolute indirect (r64)
void jmp(Register adr);
- // Jump near absolute indirect (m64)
- void jmp(const Operand& src);
-
// Conditional jumps
void j(Condition cc,
Label* L,
Label::Distance distance = Label::kFar);
+ void j(Condition cc, Address entry, RelocInfo::Mode rmode);
void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);
// Floating-point operations
@@ -1304,13 +991,40 @@
void sahf();
+ // SSE instructions
+ void movaps(XMMRegister dst, XMMRegister src);
+ void movss(XMMRegister dst, const Operand& src);
+ void movss(const Operand& dst, XMMRegister src);
+ void shufps(XMMRegister dst, XMMRegister src, byte imm8);
+
+ void cvttss2si(Register dst, const Operand& src);
+ void cvttss2si(Register dst, XMMRegister src);
+ void cvtlsi2ss(XMMRegister dst, Register src);
+
+ void andps(XMMRegister dst, XMMRegister src);
+ void andps(XMMRegister dst, const Operand& src);
+ void orps(XMMRegister dst, XMMRegister src);
+ void orps(XMMRegister dst, const Operand& src);
+ void xorps(XMMRegister dst, XMMRegister src);
+ void xorps(XMMRegister dst, const Operand& src);
+
+ void addps(XMMRegister dst, XMMRegister src);
+ void addps(XMMRegister dst, const Operand& src);
+ void subps(XMMRegister dst, XMMRegister src);
+ void subps(XMMRegister dst, const Operand& src);
+ void mulps(XMMRegister dst, XMMRegister src);
+ void mulps(XMMRegister dst, const Operand& src);
+ void divps(XMMRegister dst, XMMRegister src);
+ void divps(XMMRegister dst, const Operand& src);
+
+ void movmskps(Register dst, XMMRegister src);
+
// SSE2 instructions
void movd(XMMRegister dst, Register src);
void movd(Register dst, XMMRegister src);
void movq(XMMRegister dst, Register src);
void movq(Register dst, XMMRegister src);
void movq(XMMRegister dst, XMMRegister src);
- void extractps(Register dst, XMMRegister src, byte imm8);
// Don't use this unless it's important to keep the
// top half of the destination register unchanged.
@@ -1324,24 +1038,23 @@
void movdqa(const Operand& dst, XMMRegister src);
void movdqa(XMMRegister dst, const Operand& src);
+ void movdqu(const Operand& dst, XMMRegister src);
+ void movdqu(XMMRegister dst, const Operand& src);
+
void movapd(XMMRegister dst, XMMRegister src);
- void movaps(XMMRegister dst, XMMRegister src);
- void movss(XMMRegister dst, const Operand& src);
- void movss(const Operand& dst, XMMRegister src);
+ void psllq(XMMRegister reg, byte imm8);
- void cvttss2si(Register dst, const Operand& src);
- void cvttss2si(Register dst, XMMRegister src);
void cvttsd2si(Register dst, const Operand& src);
void cvttsd2si(Register dst, XMMRegister src);
void cvttsd2siq(Register dst, XMMRegister src);
+ void cvttsd2siq(Register dst, const Operand& src);
void cvtlsi2sd(XMMRegister dst, const Operand& src);
void cvtlsi2sd(XMMRegister dst, Register src);
void cvtqsi2sd(XMMRegister dst, const Operand& src);
void cvtqsi2sd(XMMRegister dst, Register src);
- void cvtlsi2ss(XMMRegister dst, Register src);
void cvtss2sd(XMMRegister dst, XMMRegister src);
void cvtss2sd(XMMRegister dst, const Operand& src);
@@ -1351,18 +1064,26 @@
void cvtsd2siq(Register dst, XMMRegister src);
void addsd(XMMRegister dst, XMMRegister src);
+ void addsd(XMMRegister dst, const Operand& src);
void subsd(XMMRegister dst, XMMRegister src);
void mulsd(XMMRegister dst, XMMRegister src);
+ void mulsd(XMMRegister dst, const Operand& src);
void divsd(XMMRegister dst, XMMRegister src);
void andpd(XMMRegister dst, XMMRegister src);
void orpd(XMMRegister dst, XMMRegister src);
void xorpd(XMMRegister dst, XMMRegister src);
- void xorps(XMMRegister dst, XMMRegister src);
void sqrtsd(XMMRegister dst, XMMRegister src);
+ void sqrtsd(XMMRegister dst, const Operand& src);
void ucomisd(XMMRegister dst, XMMRegister src);
void ucomisd(XMMRegister dst, const Operand& src);
+ void cmpltsd(XMMRegister dst, XMMRegister src);
+
+ void movmskpd(Register dst, XMMRegister src);
+
+ // SSE 4.1 instruction
+ void extractps(Register dst, XMMRegister src, byte imm8);
enum RoundingMode {
kRoundToNearest = 0x0,
@@ -1373,14 +1094,6 @@
void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);
- void movmskpd(Register dst, XMMRegister src);
-
- // The first argument is the reg field, the second argument is the r/m field.
- void emit_sse_operand(XMMRegister dst, XMMRegister src);
- void emit_sse_operand(XMMRegister reg, const Operand& adr);
- void emit_sse_operand(XMMRegister dst, Register src);
- void emit_sse_operand(Register dst, XMMRegister src);
-
// Debugging
void Print();
@@ -1399,13 +1112,17 @@
// Use --code-comments to enable.
void RecordComment(const char* msg, bool force = false);
+ // Allocate a constant pool of the correct size for the generated code.
+ Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate);
+
+ // Generate the constant pool for the generated code.
+ void PopulateConstantPool(ConstantPoolArray* constant_pool);
+
// Writes a single word of data in the code stream.
// Used for inline tables, e.g., jump-tables.
void db(uint8_t data);
void dd(uint32_t data);
- int pc_offset() const { return static_cast<int>(pc_ - buffer_); }
-
PositionsRecorder* positions_recorder() { return &positions_recorder_; }
// Check if there is less than kGap bytes available in the buffer.
@@ -1424,13 +1141,16 @@
// Avoid overflows for displacements etc.
static const int kMaximalBufferSize = 512*MB;
- static const int kMinimalBufferSize = 4*KB;
byte byte_at(int pos) { return buffer_[pos]; }
void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
protected:
- bool emit_debug_code() const { return emit_debug_code_; }
+ // Call near indirect
+ void call(const Operand& operand);
+
+ // Jump near absolute indirect (m64)
+ void jmp(const Operand& src);
private:
byte* addr_at(int pos) { return buffer_ + pos; }
@@ -1446,11 +1166,13 @@
void emit(byte x) { *pc_++ = x; }
inline void emitl(uint32_t x);
- inline void emitq(uint64_t x, RelocInfo::Mode rmode);
+ inline void emitp(void* x, RelocInfo::Mode rmode);
+ inline void emitq(uint64_t x);
inline void emitw(uint16_t x);
inline void emit_code_target(Handle<Code> target,
RelocInfo::Mode rmode,
- unsigned ast_id = kNoASTId);
+ TypeFeedbackId ast_id = TypeFeedbackId::None());
+ inline void emit_runtime_entry(Address entry, RelocInfo::Mode rmode);
void emit(Immediate x) { emitl(x.value_); }
// Emits a REX prefix that encodes a 64-bit operand size and
@@ -1536,6 +1258,33 @@
// numbers have a high bit set.
inline void emit_optional_rex_32(const Operand& op);
+ void emit_rex(int size) {
+ if (size == kInt64Size) {
+ emit_rex_64();
+ } else {
+ DCHECK(size == kInt32Size);
+ }
+ }
+
+ template<class P1>
+ void emit_rex(P1 p1, int size) {
+ if (size == kInt64Size) {
+ emit_rex_64(p1);
+ } else {
+ DCHECK(size == kInt32Size);
+ emit_optional_rex_32(p1);
+ }
+ }
+
+ template<class P1, class P2>
+ void emit_rex(P1 p1, P2 p2, int size) {
+ if (size == kInt64Size) {
+ emit_rex_64(p1, p2);
+ } else {
+ DCHECK(size == kInt32Size);
+ emit_optional_rex_32(p1, p2);
+ }
+ }
// Emit the ModR/M byte, and optionally the SIB byte and
// 1- or 4-byte offset for a memory operand. Also encodes
@@ -1558,25 +1307,34 @@
// Emit a ModR/M byte with an operation subcode in the reg field and
// a register in the rm_reg field.
void emit_modrm(int code, Register rm_reg) {
- ASSERT(is_uint3(code));
+ DCHECK(is_uint3(code));
emit(0xC0 | code << 3 | rm_reg.low_bits());
}
// Emit the code-object-relative offset of the label's position
inline void emit_code_relative_offset(Label* label);
+ // The first argument is the reg field, the second argument is the r/m field.
+ void emit_sse_operand(XMMRegister dst, XMMRegister src);
+ void emit_sse_operand(XMMRegister reg, const Operand& adr);
+ void emit_sse_operand(Register reg, const Operand& adr);
+ void emit_sse_operand(XMMRegister dst, Register src);
+ void emit_sse_operand(Register dst, XMMRegister src);
+
// 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
// ModR/M byte.
+ void arithmetic_op_8(byte opcode, Register reg, Register rm_reg);
+ void arithmetic_op_8(byte opcode, Register reg, const Operand& rm_reg);
void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
- void arithmetic_op_32(byte opcode, Register reg, Register rm_reg);
- void arithmetic_op_32(byte opcode, Register reg, const Operand& rm_reg);
- void arithmetic_op(byte opcode, Register reg, Register rm_reg);
- void arithmetic_op(byte opcode, Register reg, const Operand& rm_reg);
- void immediate_arithmetic_op(byte subcode, Register dst, Immediate src);
- void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src);
+ // Operate on operands/registers with pointer size, 32-bit or 64-bit size.
+ void arithmetic_op(byte opcode, Register reg, Register rm_reg, int size);
+ void arithmetic_op(byte opcode,
+ Register reg,
+ const Operand& rm_reg,
+ int size);
// Operate on a byte in memory or register.
void immediate_arithmetic_op_8(byte subcode,
Register dst,
@@ -1591,20 +1349,20 @@
void immediate_arithmetic_op_16(byte subcode,
const Operand& dst,
Immediate src);
- // Operate on a 32-bit word in memory or register.
- void immediate_arithmetic_op_32(byte subcode,
- Register dst,
- Immediate src);
- void immediate_arithmetic_op_32(byte subcode,
- const Operand& dst,
- Immediate src);
+ // Operate on operands/registers with pointer size, 32-bit or 64-bit size.
+ void immediate_arithmetic_op(byte subcode,
+ Register dst,
+ Immediate src,
+ int size);
+ void immediate_arithmetic_op(byte subcode,
+ const Operand& dst,
+ Immediate src,
+ int size);
// Emit machine code for a shift operation.
- void shift(Register dst, Immediate shift_amount, int subcode);
- void shift_32(Register dst, Immediate shift_amount, int subcode);
+ void shift(Register dst, Immediate shift_amount, int subcode, int size);
// Shift dst by cl % 64 bits.
- void shift(Register dst, int subcode);
- void shift_32(Register dst, int subcode);
+ void shift(Register dst, int subcode, int size);
void emit_farith(int b1, int b2, int i);
@@ -1615,27 +1373,198 @@
// record reloc info for current pc_
void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
+ // Arithmetics
+ void emit_add(Register dst, Register src, int size) {
+ arithmetic_op(0x03, dst, src, size);
+ }
+
+ void emit_add(Register dst, Immediate src, int size) {
+ immediate_arithmetic_op(0x0, dst, src, size);
+ }
+
+ void emit_add(Register dst, const Operand& src, int size) {
+ arithmetic_op(0x03, dst, src, size);
+ }
+
+ void emit_add(const Operand& dst, Register src, int size) {
+ arithmetic_op(0x1, src, dst, size);
+ }
+
+ void emit_add(const Operand& dst, Immediate src, int size) {
+ immediate_arithmetic_op(0x0, dst, src, size);
+ }
+
+ void emit_and(Register dst, Register src, int size) {
+ arithmetic_op(0x23, dst, src, size);
+ }
+
+ void emit_and(Register dst, const Operand& src, int size) {
+ arithmetic_op(0x23, dst, src, size);
+ }
+
+ void emit_and(const Operand& dst, Register src, int size) {
+ arithmetic_op(0x21, src, dst, size);
+ }
+
+ void emit_and(Register dst, Immediate src, int size) {
+ immediate_arithmetic_op(0x4, dst, src, size);
+ }
+
+ void emit_and(const Operand& dst, Immediate src, int size) {
+ immediate_arithmetic_op(0x4, dst, src, size);
+ }
+
+ void emit_cmp(Register dst, Register src, int size) {
+ arithmetic_op(0x3B, dst, src, size);
+ }
+
+ void emit_cmp(Register dst, const Operand& src, int size) {
+ arithmetic_op(0x3B, dst, src, size);
+ }
+
+ void emit_cmp(const Operand& dst, Register src, int size) {
+ arithmetic_op(0x39, src, dst, size);
+ }
+
+ void emit_cmp(Register dst, Immediate src, int size) {
+ immediate_arithmetic_op(0x7, dst, src, size);
+ }
+
+ void emit_cmp(const Operand& dst, Immediate src, int size) {
+ immediate_arithmetic_op(0x7, dst, src, size);
+ }
+
+ void emit_dec(Register dst, int size);
+ void emit_dec(const Operand& dst, int size);
+
+ // Divide rdx:rax by src. Quotient in rax, remainder in rdx when size is 64.
+ // Divide edx:eax by lower 32 bits of src. Quotient in eax, remainder in edx
+ // when size is 32.
+ void emit_idiv(Register src, int size);
+ void emit_div(Register src, int size);
+
+ // Signed multiply instructions.
+ // rdx:rax = rax * src when size is 64 or edx:eax = eax * src when size is 32.
+ void emit_imul(Register src, int size);
+ void emit_imul(Register dst, Register src, int size);
+ void emit_imul(Register dst, const Operand& src, int size);
+ void emit_imul(Register dst, Register src, Immediate imm, int size);
+
+ void emit_inc(Register dst, int size);
+ void emit_inc(const Operand& dst, int size);
+
+ void emit_lea(Register dst, const Operand& src, int size);
+
+ void emit_mov(Register dst, const Operand& src, int size);
+ void emit_mov(Register dst, Register src, int size);
+ void emit_mov(const Operand& dst, Register src, int size);
+ void emit_mov(Register dst, Immediate value, int size);
+ void emit_mov(const Operand& dst, Immediate value, int size);
+
+ void emit_movzxb(Register dst, const Operand& src, int size);
+ void emit_movzxb(Register dst, Register src, int size);
+ void emit_movzxw(Register dst, const Operand& src, int size);
+ void emit_movzxw(Register dst, Register src, int size);
+
+ void emit_neg(Register dst, int size);
+ void emit_neg(const Operand& dst, int size);
+
+ void emit_not(Register dst, int size);
+ void emit_not(const Operand& dst, int size);
+
+ void emit_or(Register dst, Register src, int size) {
+ arithmetic_op(0x0B, dst, src, size);
+ }
+
+ void emit_or(Register dst, const Operand& src, int size) {
+ arithmetic_op(0x0B, dst, src, size);
+ }
+
+ void emit_or(const Operand& dst, Register src, int size) {
+ arithmetic_op(0x9, src, dst, size);
+ }
+
+ void emit_or(Register dst, Immediate src, int size) {
+ immediate_arithmetic_op(0x1, dst, src, size);
+ }
+
+ void emit_or(const Operand& dst, Immediate src, int size) {
+ immediate_arithmetic_op(0x1, dst, src, size);
+ }
+
+ void emit_repmovs(int size);
+
+ void emit_sbb(Register dst, Register src, int size) {
+ arithmetic_op(0x1b, dst, src, size);
+ }
+
+ void emit_sub(Register dst, Register src, int size) {
+ arithmetic_op(0x2B, dst, src, size);
+ }
+
+ void emit_sub(Register dst, Immediate src, int size) {
+ immediate_arithmetic_op(0x5, dst, src, size);
+ }
+
+ void emit_sub(Register dst, const Operand& src, int size) {
+ arithmetic_op(0x2B, dst, src, size);
+ }
+
+ void emit_sub(const Operand& dst, Register src, int size) {
+ arithmetic_op(0x29, src, dst, size);
+ }
+
+ void emit_sub(const Operand& dst, Immediate src, int size) {
+ immediate_arithmetic_op(0x5, dst, src, size);
+ }
+
+ void emit_test(Register dst, Register src, int size);
+ void emit_test(Register reg, Immediate mask, int size);
+ void emit_test(const Operand& op, Register reg, int size);
+ void emit_test(const Operand& op, Immediate mask, int size);
+ void emit_test(Register reg, const Operand& op, int size) {
+ return emit_test(op, reg, size);
+ }
+
+ void emit_xchg(Register dst, Register src, int size);
+ void emit_xchg(Register dst, const Operand& src, int size);
+
+ void emit_xor(Register dst, Register src, int size) {
+ if (size == kInt64Size && dst.code() == src.code()) {
+ // 32 bit operations zero the top 32 bits of 64 bit registers. Therefore
+ // there is no need to make this a 64 bit operation.
+ arithmetic_op(0x33, dst, src, kInt32Size);
+ } else {
+ arithmetic_op(0x33, dst, src, size);
+ }
+ }
+
+ void emit_xor(Register dst, const Operand& src, int size) {
+ arithmetic_op(0x33, dst, src, size);
+ }
+
+ void emit_xor(Register dst, Immediate src, int size) {
+ immediate_arithmetic_op(0x6, dst, src, size);
+ }
+
+ void emit_xor(const Operand& dst, Immediate src, int size) {
+ immediate_arithmetic_op(0x6, dst, src, size);
+ }
+
+ void emit_xor(const Operand& dst, Register src, int size) {
+ arithmetic_op(0x31, src, dst, size);
+ }
+
friend class CodePatcher;
friend class EnsureSpace;
friend class RegExpMacroAssemblerX64;
- // Code buffer:
- // The buffer into which code and relocation info are generated.
- byte* buffer_;
- int buffer_size_;
- // True if the assembler owns the buffer, false if buffer is external.
- bool own_buffer_;
-
// code generation
- byte* pc_; // the program counter; moves forward
RelocInfoWriter reloc_info_writer;
List< Handle<Code> > code_targets_;
PositionsRecorder positions_recorder_;
-
- bool emit_debug_code_;
-
friend class PositionsRecorder;
};
@@ -1656,7 +1585,7 @@
#ifdef DEBUG
~EnsureSpace() {
int bytes_generated = space_before_ - assembler_->available_space();
- ASSERT(bytes_generated < assembler_->kGap);
+ DCHECK(bytes_generated < assembler_->kGap);
}
#endif