diff options
Diffstat (limited to 'deps/v8/src/x64/assembler-x64.h')
-rw-r--r-- | deps/v8/src/x64/assembler-x64.h | 142 |
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; }; |