summaryrefslogtreecommitdiff
path: root/deps/v8/src/x64/assembler-x64.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/x64/assembler-x64.h')
-rw-r--r--deps/v8/src/x64/assembler-x64.h142
1 files changed, 96 insertions, 46 deletions
diff --git a/deps/v8/src/x64/assembler-x64.h b/deps/v8/src/x64/assembler-x64.h
index f6cd570936..2971db845e 100644
--- a/deps/v8/src/x64/assembler-x64.h
+++ b/deps/v8/src/x64/assembler-x64.h
@@ -93,8 +93,8 @@ struct Register {
// rbp - frame pointer
// rsi - context register
// r10 - fixed scratch register
+ // r12 - smi constant register
// r13 - root register
- // r15 - smi constant register
static const int kNumRegisters = 16;
static const int kNumAllocatableRegisters = 10;
@@ -120,7 +120,7 @@ struct Register {
"r9",
"r11",
"r14",
- "r12"
+ "r15"
};
return names[index];
}
@@ -327,22 +327,6 @@ inline Condition ReverseCondition(Condition cc) {
}
-enum Hint {
- no_hint = 0,
- not_taken = 0x2e,
- taken = 0x3e
-};
-
-// The result of negating a hint is as if the corresponding condition
-// were negated by NegateCondition. That is, no_hint is mapped to
-// itself and not_taken and taken are mapped to each other.
-inline Hint NegateHint(Hint hint) {
- return (hint == no_hint)
- ? no_hint
- : ((hint == not_taken) ? taken : not_taken);
-}
-
-
// -----------------------------------------------------------------------------
// Machine instruction Immediates
@@ -395,6 +379,13 @@ class Operand BASE_EMBEDDED {
// Does not check the "reg" part of the Operand.
bool AddressUsesRegister(Register reg) const;
+ // Queries related to the size of the generated instruction.
+ // Whether the generated instruction will have a REX prefix.
+ bool requires_rex() const { return rex_ != 0; }
+ // Size of the ModR/M, SIB and displacement parts of the generated
+ // instruction.
+ int operand_size() const { return len_; }
+
private:
byte rex_;
byte buf_[6];
@@ -431,9 +422,11 @@ 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(bool portable);
+ static void Probe();
+
// 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;
@@ -441,40 +434,71 @@ class CpuFeatures : public AllStatic {
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) {
- return (enabled_ & (V8_UINT64_C(1) << f)) != 0;
+ 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);
+ uint64_t mask = V8_UINT64_C(1) << f;
ASSERT(CpuFeatures::IsSupported(f));
- ASSERT(!Serializer::enabled() || (found_by_runtime_probing_ & mask) == 0);
- old_enabled_ = CpuFeatures::enabled_;
- CpuFeatures::enabled_ |= mask;
+ 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_);
+ }
}
- ~Scope() { CpuFeatures::enabled_ = 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 enabled_;
static uint64_t found_by_runtime_probing_;
+
+ DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
};
-class Assembler : public Malloced {
+class Assembler : public AssemblerBase {
private:
// We check before assembling an instruction that there is sufficient
// space to write an instruction and its relocation information.
@@ -501,9 +525,12 @@ class Assembler : public Malloced {
// for code generation and assumes its size to be buffer_size. If the buffer
// is too small, a fatal error occurs. No deallocation of the buffer is done
// upon destruction of the assembler.
- Assembler(void* buffer, int buffer_size);
+ 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; }
+
// GetCode emits any pending (non-emitted) code and fills the descriptor
// desc. GetCode() is idempotent; it returns the same result if no other
// Assembler functions are invoked in between GetCode() calls.
@@ -613,6 +640,7 @@ class Assembler : public Malloced {
void push_imm32(int32_t imm32);
void push(Register src);
void push(const Operand& src);
+ void push(Handle<Object> handle);
void pop(Register dst);
void pop(const Operand& dst);
@@ -649,7 +677,7 @@ class Assembler : public Malloced {
// Move sign extended immediate to memory location.
void movq(const Operand& dst, Immediate value);
- // New x64 instructions to load a 64-bit immediate into a register.
+ // 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);
@@ -674,7 +702,7 @@ class Assembler : public Malloced {
void repmovsl();
void repmovsq();
- // New x64 instruction to load from an immediate 64-bit pointer into RAX.
+ // Instruction to load from an immediate 64-bit pointer into RAX.
void load_rax(void* ptr, RelocInfo::Mode rmode);
void load_rax(ExternalReference ext);
@@ -1109,6 +1137,7 @@ class Assembler : public Malloced {
// Miscellaneous
void clc();
+ void cld();
void cpuid();
void hlt();
void int3();
@@ -1134,12 +1163,13 @@ class Assembler : public Malloced {
// but it may be bound only once.
void bind(Label* L); // binds an unbound label L to the current code position
- void bind(NearLabel* L);
// Calls
// Call near relative 32-bit displacement, relative to next instruction.
void call(Label* L);
- void call(Handle<Code> target, RelocInfo::Mode rmode);
+ void call(Handle<Code> target,
+ RelocInfo::Mode rmode,
+ unsigned ast_id = kNoASTId);
// Calls directly to the given address using a relative offset.
// Should only ever be used in Code objects for calls within the
@@ -1156,7 +1186,8 @@ class Assembler : public Malloced {
// Jumps
// Jump short or near relative.
// Use a 32-bit signed displacement.
- void jmp(Label* L); // unconditional jump to L
+ // Unconditional jump to L
+ void jmp(Label* L, Label::Distance distance = Label::kFar);
void jmp(Handle<Code> target, RelocInfo::Mode rmode);
// Jump near absolute indirect (r64)
@@ -1165,16 +1196,12 @@ class Assembler : public Malloced {
// Jump near absolute indirect (m64)
void jmp(const Operand& src);
- // Short jump
- void jmp(NearLabel* L);
-
// Conditional jumps
- void j(Condition cc, Label* L);
+ void j(Condition cc,
+ Label* L,
+ Label::Distance distance = Label::kFar);
void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);
- // Conditional short jump
- void j(Condition cc, NearLabel* L, Hint hint = no_hint);
-
// Floating-point operations
void fld(int i);
@@ -1247,15 +1274,24 @@ class Assembler : public Malloced {
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);
- void movsd(const Operand& dst, XMMRegister src);
+ // Don't use this unless it's important to keep the
+ // top half of the destination register unchanged.
+ // Used movaps when moving double values and movq for integer
+ // values in xmm registers.
void movsd(XMMRegister dst, XMMRegister src);
+
+ void movsd(const Operand& dst, XMMRegister src);
void movsd(XMMRegister dst, const Operand& src);
void movdqa(const Operand& dst, XMMRegister src);
void movdqa(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);
@@ -1287,11 +1323,21 @@ class Assembler : public Malloced {
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 ucomisd(XMMRegister dst, XMMRegister src);
void ucomisd(XMMRegister dst, const Operand& src);
+ enum RoundingMode {
+ kRoundToNearest = 0x0,
+ kRoundDown = 0x1,
+ kRoundUp = 0x2,
+ kRoundToZero = 0x3
+ };
+
+ 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.
@@ -1343,6 +1389,9 @@ class Assembler : public Malloced {
static const int kMaximalBufferSize = 512*MB;
static const int kMinimalBufferSize = 4*KB;
+ protected:
+ bool emit_debug_code() const { return emit_debug_code_; }
+
private:
byte* addr_at(int pos) { return buffer_ + pos; }
byte byte_at(int pos) { return buffer_[pos]; }
@@ -1361,7 +1410,9 @@ class Assembler : public Malloced {
inline void emitl(uint32_t x);
inline void emitq(uint64_t x, RelocInfo::Mode rmode);
inline void emitw(uint16_t x);
- inline void emit_code_target(Handle<Code> target, RelocInfo::Mode rmode);
+ inline void emit_code_target(Handle<Code> target,
+ RelocInfo::Mode rmode,
+ unsigned ast_id = kNoASTId);
void emit(Immediate x) { emitl(x.value_); }
// Emits a REX prefix that encodes a 64-bit operand size and
@@ -1536,18 +1587,17 @@ class Assembler : public Malloced {
int buffer_size_;
// True if the assembler owns the buffer, false if buffer is external.
bool own_buffer_;
- // A previously allocated buffer of kMinimalBufferSize bytes, or NULL.
- static byte* spare_buffer_;
// code generation
byte* pc_; // the program counter; moves forward
RelocInfoWriter reloc_info_writer;
List< Handle<Code> > code_targets_;
- // push-pop elimination
- byte* last_pc_;
PositionsRecorder positions_recorder_;
+
+ bool emit_debug_code_;
+
friend class PositionsRecorder;
};