• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 //
11 // - Redistribution in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the distribution.
14 //
15 // - Neither the name of Sun Microsystems or the names of contributors may
16 // be used to endorse or promote products derived from this software without
17 // specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // The original source code covered by the above license above has been
32 // modified significantly by Google Inc.
33 // Copyright 2011 the V8 project authors. All rights reserved.
34 
35 // A light-weight IA32 Assembler.
36 
37 #ifndef V8_X87_ASSEMBLER_X87_H_
38 #define V8_X87_ASSEMBLER_X87_H_
39 
40 #include <deque>
41 
42 #include "src/assembler.h"
43 #include "src/isolate.h"
44 #include "src/utils.h"
45 
46 namespace v8 {
47 namespace internal {
48 
49 #define GENERAL_REGISTERS(V) \
50   V(eax)                     \
51   V(ecx)                     \
52   V(edx)                     \
53   V(ebx)                     \
54   V(esp)                     \
55   V(ebp)                     \
56   V(esi)                     \
57   V(edi)
58 
59 #define ALLOCATABLE_GENERAL_REGISTERS(V) \
60   V(eax)                                 \
61   V(ecx)                                 \
62   V(edx)                                 \
63   V(ebx)                                 \
64   V(esi)                                 \
65   V(edi)
66 
67 #define DOUBLE_REGISTERS(V) \
68   V(stX_0)                  \
69   V(stX_1)                  \
70   V(stX_2)                  \
71   V(stX_3)                  \
72   V(stX_4)                  \
73   V(stX_5)                  \
74   V(stX_6)                  \
75   V(stX_7)
76 
77 #define FLOAT_REGISTERS DOUBLE_REGISTERS
78 #define SIMD128_REGISTERS DOUBLE_REGISTERS
79 
80 #define ALLOCATABLE_DOUBLE_REGISTERS(V) \
81   V(stX_0)                              \
82   V(stX_1)                              \
83   V(stX_2)                              \
84   V(stX_3)                              \
85   V(stX_4)                              \
86   V(stX_5)
87 
88 // CPU Registers.
89 //
90 // 1) We would prefer to use an enum, but enum values are assignment-
91 // compatible with int, which has caused code-generation bugs.
92 //
93 // 2) We would prefer to use a class instead of a struct but we don't like
94 // the register initialization to depend on the particular initialization
95 // order (which appears to be different on OS X, Linux, and Windows for the
96 // installed versions of C++ we tried). Using a struct permits C-style
97 // "initialization". Also, the Register objects cannot be const as this
98 // forces initialization stubs in MSVC, making us dependent on initialization
99 // order.
100 //
101 // 3) By not using an enum, we are possibly preventing the compiler from
102 // doing certain constant folds, which may significantly reduce the
103 // code generated for some assembly instructions (because they boil down
104 // to a few constants). If this is a problem, we could change the code
105 // such that we use an enum in optimized mode, and the struct in debug
106 // mode. This way we get the compile-time error checking in debug mode
107 // and best performance in optimized code.
108 //
109 struct Register {
110   enum Code {
111 #define REGISTER_CODE(R) kCode_##R,
112     GENERAL_REGISTERS(REGISTER_CODE)
113 #undef REGISTER_CODE
114         kAfterLast,
115     kCode_no_reg = -1
116   };
117 
118   static const int kNumRegisters = Code::kAfterLast;
119 
from_codeRegister120   static Register from_code(int code) {
121     DCHECK(code >= 0);
122     DCHECK(code < kNumRegisters);
123     Register r = {code};
124     return r;
125   }
is_validRegister126   bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
isRegister127   bool is(Register reg) const { return reg_code == reg.reg_code; }
codeRegister128   int code() const {
129     DCHECK(is_valid());
130     return reg_code;
131   }
bitRegister132   int bit() const {
133     DCHECK(is_valid());
134     return 1 << reg_code;
135   }
136 
is_byte_registerRegister137   bool is_byte_register() const { return reg_code <= 3; }
138 
139   // Unfortunately we can't make this private in a struct.
140   int reg_code;
141 };
142 
143 
144 #define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
145 GENERAL_REGISTERS(DECLARE_REGISTER)
146 #undef DECLARE_REGISTER
147 const Register no_reg = {Register::kCode_no_reg};
148 
149 static const bool kSimpleFPAliasing = true;
150 static const bool kSimdMaskRegisters = false;
151 
152 struct X87Register {
153   enum Code {
154 #define REGISTER_CODE(R) kCode_##R,
155     DOUBLE_REGISTERS(REGISTER_CODE)
156 #undef REGISTER_CODE
157         kAfterLast,
158     kCode_no_reg = -1
159   };
160 
161   static const int kMaxNumRegisters = Code::kAfterLast;
162   static const int kMaxNumAllocatableRegisters = 6;
163 
from_codeX87Register164   static X87Register from_code(int code) {
165     X87Register result = {code};
166     return result;
167   }
168 
is_validX87Register169   bool is_valid() const { return 0 <= reg_code && reg_code < kMaxNumRegisters; }
170 
codeX87Register171   int code() const {
172     DCHECK(is_valid());
173     return reg_code;
174   }
175 
isX87Register176   bool is(X87Register reg) const { return reg_code == reg.reg_code; }
177 
178   int reg_code;
179 };
180 
181 typedef X87Register FloatRegister;
182 
183 typedef X87Register DoubleRegister;
184 
185 // TODO(x87) Define SIMD registers.
186 typedef X87Register Simd128Register;
187 
188 #define DECLARE_REGISTER(R) \
189   const DoubleRegister R = {DoubleRegister::kCode_##R};
190 DOUBLE_REGISTERS(DECLARE_REGISTER)
191 #undef DECLARE_REGISTER
192 const DoubleRegister no_double_reg = {DoubleRegister::kCode_no_reg};
193 
194 enum Condition {
195   // any value < 0 is considered no_condition
196   no_condition  = -1,
197 
198   overflow      =  0,
199   no_overflow   =  1,
200   below         =  2,
201   above_equal   =  3,
202   equal         =  4,
203   not_equal     =  5,
204   below_equal   =  6,
205   above         =  7,
206   negative      =  8,
207   positive      =  9,
208   parity_even   = 10,
209   parity_odd    = 11,
210   less          = 12,
211   greater_equal = 13,
212   less_equal    = 14,
213   greater       = 15,
214 
215   // aliases
216   carry         = below,
217   not_carry     = above_equal,
218   zero          = equal,
219   not_zero      = not_equal,
220   sign          = negative,
221   not_sign      = positive
222 };
223 
224 
225 // Returns the equivalent of !cc.
226 // Negation of the default no_condition (-1) results in a non-default
227 // no_condition value (-2). As long as tests for no_condition check
228 // for condition < 0, this will work as expected.
NegateCondition(Condition cc)229 inline Condition NegateCondition(Condition cc) {
230   return static_cast<Condition>(cc ^ 1);
231 }
232 
233 
234 // Commute a condition such that {a cond b == b cond' a}.
CommuteCondition(Condition cc)235 inline Condition CommuteCondition(Condition cc) {
236   switch (cc) {
237     case below:
238       return above;
239     case above:
240       return below;
241     case above_equal:
242       return below_equal;
243     case below_equal:
244       return above_equal;
245     case less:
246       return greater;
247     case greater:
248       return less;
249     case greater_equal:
250       return less_equal;
251     case less_equal:
252       return greater_equal;
253     default:
254       return cc;
255   }
256 }
257 
258 
259 enum RoundingMode {
260   kRoundToNearest = 0x0,
261   kRoundDown = 0x1,
262   kRoundUp = 0x2,
263   kRoundToZero = 0x3
264 };
265 
266 
267 // -----------------------------------------------------------------------------
268 // Machine instruction Immediates
269 
270 class Immediate BASE_EMBEDDED {
271  public:
272   inline explicit Immediate(int x);
273   inline explicit Immediate(const ExternalReference& ext);
274   inline explicit Immediate(Handle<Object> handle);
275   inline explicit Immediate(Smi* value);
276   inline explicit Immediate(Address addr);
277   inline explicit Immediate(Address x, RelocInfo::Mode rmode);
278 
CodeRelativeOffset(Label * label)279   static Immediate CodeRelativeOffset(Label* label) {
280     return Immediate(label);
281   }
282 
is_zero()283   bool is_zero() const { return x_ == 0 && RelocInfo::IsNone(rmode_); }
is_int8()284   bool is_int8() const {
285     return -128 <= x_ && x_ < 128 && RelocInfo::IsNone(rmode_);
286   }
is_uint8()287   bool is_uint8() const {
288     return v8::internal::is_uint8(x_) && RelocInfo::IsNone(rmode_);
289   }
is_int16()290   bool is_int16() const {
291     return -32768 <= x_ && x_ < 32768 && RelocInfo::IsNone(rmode_);
292   }
is_uint16()293   bool is_uint16() const {
294     return v8::internal::is_uint16(x_) && RelocInfo::IsNone(rmode_);
295   }
296 
297  private:
298   inline explicit Immediate(Label* value);
299 
300   int x_;
301   RelocInfo::Mode rmode_;
302 
303   friend class Operand;
304   friend class Assembler;
305   friend class MacroAssembler;
306 };
307 
308 
309 // -----------------------------------------------------------------------------
310 // Machine instruction Operands
311 
312 enum ScaleFactor {
313   times_1 = 0,
314   times_2 = 1,
315   times_4 = 2,
316   times_8 = 3,
317   times_int_size = times_4,
318   times_half_pointer_size = times_2,
319   times_pointer_size = times_4,
320   times_twice_pointer_size = times_8
321 };
322 
323 
324 class Operand BASE_EMBEDDED {
325  public:
326   // reg
327   INLINE(explicit Operand(Register reg));
328 
329   // [disp/r]
330   INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode));
331 
332   // [disp/r]
333   INLINE(explicit Operand(Immediate imm));
334 
335   // [base + disp/r]
336   explicit Operand(Register base, int32_t disp,
337                    RelocInfo::Mode rmode = RelocInfo::NONE32);
338 
339   // [base + index*scale + disp/r]
340   explicit Operand(Register base,
341                    Register index,
342                    ScaleFactor scale,
343                    int32_t disp,
344                    RelocInfo::Mode rmode = RelocInfo::NONE32);
345 
346   // [index*scale + disp/r]
347   explicit Operand(Register index,
348                    ScaleFactor scale,
349                    int32_t disp,
350                    RelocInfo::Mode rmode = RelocInfo::NONE32);
351 
JumpTable(Register index,ScaleFactor scale,Label * table)352   static Operand JumpTable(Register index, ScaleFactor scale, Label* table) {
353     return Operand(index, scale, reinterpret_cast<int32_t>(table),
354                    RelocInfo::INTERNAL_REFERENCE);
355   }
356 
StaticVariable(const ExternalReference & ext)357   static Operand StaticVariable(const ExternalReference& ext) {
358     return Operand(reinterpret_cast<int32_t>(ext.address()),
359                    RelocInfo::EXTERNAL_REFERENCE);
360   }
361 
StaticArray(Register index,ScaleFactor scale,const ExternalReference & arr)362   static Operand StaticArray(Register index,
363                              ScaleFactor scale,
364                              const ExternalReference& arr) {
365     return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()),
366                    RelocInfo::EXTERNAL_REFERENCE);
367   }
368 
ForCell(Handle<Cell> cell)369   static Operand ForCell(Handle<Cell> cell) {
370     AllowDeferredHandleDereference embedding_raw_address;
371     return Operand(reinterpret_cast<int32_t>(cell.location()),
372                    RelocInfo::CELL);
373   }
374 
ForRegisterPlusImmediate(Register base,Immediate imm)375   static Operand ForRegisterPlusImmediate(Register base, Immediate imm) {
376     return Operand(base, imm.x_, imm.rmode_);
377   }
378 
379   // Returns true if this Operand is a wrapper for the specified register.
380   bool is_reg(Register reg) const;
381 
382   // Returns true if this Operand is a wrapper for one register.
383   bool is_reg_only() const;
384 
385   // Asserts that this Operand is a wrapper for one register and returns the
386   // register.
387   Register reg() const;
388 
389  private:
390   // Set the ModRM byte without an encoded 'reg' register. The
391   // register is encoded later as part of the emit_operand operation.
392   inline void set_modrm(int mod, Register rm);
393 
394   inline void set_sib(ScaleFactor scale, Register index, Register base);
395   inline void set_disp8(int8_t disp);
396   inline void set_dispr(int32_t disp, RelocInfo::Mode rmode);
397 
398   byte buf_[6];
399   // The number of bytes in buf_.
400   unsigned int len_;
401   // Only valid if len_ > 4.
402   RelocInfo::Mode rmode_;
403 
404   friend class Assembler;
405   friend class MacroAssembler;
406 };
407 
408 
409 // -----------------------------------------------------------------------------
410 // A Displacement describes the 32bit immediate field of an instruction which
411 // may be used together with a Label in order to refer to a yet unknown code
412 // position. Displacements stored in the instruction stream are used to describe
413 // the instruction and to chain a list of instructions using the same Label.
414 // A Displacement contains 2 different fields:
415 //
416 // next field: position of next displacement in the chain (0 = end of list)
417 // type field: instruction type
418 //
419 // A next value of null (0) indicates the end of a chain (note that there can
420 // be no displacement at position zero, because there is always at least one
421 // instruction byte before the displacement).
422 //
423 // Displacement _data field layout
424 //
425 // |31.....2|1......0|
426 // [  next  |  type  |
427 
428 class Displacement BASE_EMBEDDED {
429  public:
430   enum Type { UNCONDITIONAL_JUMP, CODE_RELATIVE, OTHER, CODE_ABSOLUTE };
431 
data()432   int data() const { return data_; }
type()433   Type type() const { return TypeField::decode(data_); }
next(Label * L)434   void next(Label* L) const {
435     int n = NextField::decode(data_);
436     n > 0 ? L->link_to(n) : L->Unuse();
437   }
link_to(Label * L)438   void link_to(Label* L) { init(L, type()); }
439 
Displacement(int data)440   explicit Displacement(int data) { data_ = data; }
441 
Displacement(Label * L,Type type)442   Displacement(Label* L, Type type) { init(L, type); }
443 
print()444   void print() {
445     PrintF("%s (%x) ", (type() == UNCONDITIONAL_JUMP ? "jmp" : "[other]"),
446                        NextField::decode(data_));
447   }
448 
449  private:
450   int data_;
451 
452   class TypeField: public BitField<Type, 0, 2> {};
453   class NextField: public BitField<int,  2, 32-2> {};
454 
455   void init(Label* L, Type type);
456 };
457 
458 
459 class Assembler : public AssemblerBase {
460  private:
461   // We check before assembling an instruction that there is sufficient
462   // space to write an instruction and its relocation information.
463   // The relocation writer's position must be kGap bytes above the end of
464   // the generated instructions. This leaves enough space for the
465   // longest possible ia32 instruction, 15 bytes, and the longest possible
466   // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
467   // (There is a 15 byte limit on ia32 instruction length that rules out some
468   // otherwise valid instructions.)
469   // This allows for a single, fast space check per instruction.
470   static const int kGap = 32;
471 
472  public:
473   // Create an assembler. Instructions and relocation information are emitted
474   // into a buffer, with the instructions starting from the beginning and the
475   // relocation information starting from the end of the buffer. See CodeDesc
476   // for a detailed comment on the layout (globals.h).
477   //
478   // If the provided buffer is NULL, the assembler allocates and grows its own
479   // buffer, and buffer_size determines the initial buffer size. The buffer is
480   // owned by the assembler and deallocated upon destruction of the assembler.
481   //
482   // If the provided buffer is not NULL, the assembler uses the provided buffer
483   // for code generation and assumes its size to be buffer_size. If the buffer
484   // is too small, a fatal error occurs. No deallocation of the buffer is done
485   // upon destruction of the assembler.
486   // TODO(vitalyr): the assembler does not need an isolate.
487   Assembler(Isolate* isolate, void* buffer, int buffer_size);
~Assembler()488   virtual ~Assembler() { }
489 
490   // GetCode emits any pending (non-emitted) code and fills the descriptor
491   // desc. GetCode() is idempotent; it returns the same result if no other
492   // Assembler functions are invoked in between GetCode() calls.
493   void GetCode(CodeDesc* desc);
494 
495   // Read/Modify the code target in the branch/call instruction at pc.
496   inline static Address target_address_at(Address pc, Address constant_pool);
497   inline static void set_target_address_at(
498       Isolate* isolate, Address pc, Address constant_pool, Address target,
499       ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
500   static inline Address target_address_at(Address pc, Code* code);
501   static inline void set_target_address_at(
502       Isolate* isolate, Address pc, Code* code, Address target,
503       ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
504 
505   // Return the code target address at a call site from the return address
506   // of that call in the instruction stream.
507   inline static Address target_address_from_return_address(Address pc);
508 
509   // This sets the branch destination (which is in the instruction on x86).
510   // This is for calls and branches within generated code.
deserialization_set_special_target_at(Isolate * isolate,Address instruction_payload,Code * code,Address target)511   inline static void deserialization_set_special_target_at(
512       Isolate* isolate, Address instruction_payload, Code* code,
513       Address target) {
514     set_target_address_at(isolate, instruction_payload, code, target);
515   }
516 
517   // This sets the internal reference at the pc.
518   inline static void deserialization_set_target_internal_reference_at(
519       Isolate* isolate, Address pc, Address target,
520       RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
521 
522   static const int kSpecialTargetSize = kPointerSize;
523 
524   // Distance between the address of the code target in the call instruction
525   // and the return address
526   static const int kCallTargetAddressOffset = kPointerSize;
527 
528   static const int kCallInstructionLength = 5;
529 
530   // The debug break slot must be able to contain a call instruction.
531   static const int kDebugBreakSlotLength = kCallInstructionLength;
532 
533   // Distance between start of patched debug break slot and the emitted address
534   // to jump to.
535   static const int kPatchDebugBreakSlotAddressOffset = 1;  // JMP imm32.
536 
537   // One byte opcode for test al, 0xXX.
538   static const byte kTestAlByte = 0xA8;
539   // One byte opcode for nop.
540   static const byte kNopByte = 0x90;
541 
542   // One byte opcode for a short unconditional jump.
543   static const byte kJmpShortOpcode = 0xEB;
544   // One byte prefix for a short conditional jump.
545   static const byte kJccShortPrefix = 0x70;
546   static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
547   static const byte kJcShortOpcode = kJccShortPrefix | carry;
548   static const byte kJnzShortOpcode = kJccShortPrefix | not_zero;
549   static const byte kJzShortOpcode = kJccShortPrefix | zero;
550 
551 
552   // ---------------------------------------------------------------------------
553   // Code generation
554   //
555   // - function names correspond one-to-one to ia32 instruction mnemonics
556   // - unless specified otherwise, instructions operate on 32bit operands
557   // - instructions on 8bit (byte) operands/registers have a trailing '_b'
558   // - instructions on 16bit (word) operands/registers have a trailing '_w'
559   // - naming conflicts with C++ keywords are resolved via a trailing '_'
560 
561   // NOTE ON INTERFACE: Currently, the interface is not very consistent
562   // in the sense that some operations (e.g. mov()) can be called in more
563   // the one way to generate the same instruction: The Register argument
564   // can in some cases be replaced with an Operand(Register) argument.
565   // This should be cleaned up and made more orthogonal. The questions
566   // is: should we always use Operands instead of Registers where an
567   // Operand is possible, or should we have a Register (overloaded) form
568   // instead? We must be careful to make sure that the selected instruction
569   // is obvious from the parameters to avoid hard-to-find code generation
570   // bugs.
571 
572   // Insert the smallest number of nop instructions
573   // possible to align the pc offset to a multiple
574   // of m. m must be a power of 2.
575   void Align(int m);
576   // Insert the smallest number of zero bytes possible to align the pc offset
577   // to a mulitple of m. m must be a power of 2 (>= 2).
578   void DataAlign(int m);
579   void Nop(int bytes = 1);
580   // Aligns code to something that's optimal for a jump target for the platform.
581   void CodeTargetAlign();
582 
583   // Stack
584   void pushad();
585   void popad();
586 
587   void pushfd();
588   void popfd();
589 
590   void push(const Immediate& x);
591   void push_imm32(int32_t imm32);
592   void push(Register src);
593   void push(const Operand& src);
594 
595   void pop(Register dst);
596   void pop(const Operand& dst);
597 
598   void enter(const Immediate& size);
599   void leave();
600 
601   // Moves
mov_b(Register dst,Register src)602   void mov_b(Register dst, Register src) { mov_b(dst, Operand(src)); }
603   void mov_b(Register dst, const Operand& src);
mov_b(Register dst,int8_t imm8)604   void mov_b(Register dst, int8_t imm8) { mov_b(Operand(dst), imm8); }
605   void mov_b(const Operand& dst, int8_t imm8);
606   void mov_b(const Operand& dst, const Immediate& src);
607   void mov_b(const Operand& dst, Register src);
608 
609   void mov_w(Register dst, const Operand& src);
610   void mov_w(const Operand& dst, Register src);
611   void mov_w(const Operand& dst, int16_t imm16);
612   void mov_w(const Operand& dst, const Immediate& src);
613 
614 
615   void mov(Register dst, int32_t imm32);
616   void mov(Register dst, const Immediate& x);
617   void mov(Register dst, Handle<Object> handle);
618   void mov(Register dst, const Operand& src);
619   void mov(Register dst, Register src);
620   void mov(const Operand& dst, const Immediate& x);
621   void mov(const Operand& dst, Handle<Object> handle);
622   void mov(const Operand& dst, Register src);
623 
movsx_b(Register dst,Register src)624   void movsx_b(Register dst, Register src) { movsx_b(dst, Operand(src)); }
625   void movsx_b(Register dst, const Operand& src);
626 
movsx_w(Register dst,Register src)627   void movsx_w(Register dst, Register src) { movsx_w(dst, Operand(src)); }
628   void movsx_w(Register dst, const Operand& src);
629 
movzx_b(Register dst,Register src)630   void movzx_b(Register dst, Register src) { movzx_b(dst, Operand(src)); }
631   void movzx_b(Register dst, const Operand& src);
632 
movzx_w(Register dst,Register src)633   void movzx_w(Register dst, Register src) { movzx_w(dst, Operand(src)); }
634   void movzx_w(Register dst, const Operand& src);
635 
636   // Flag management.
637   void cld();
638 
639   // Repetitive string instructions.
640   void rep_movs();
641   void rep_stos();
642   void stos();
643 
644   // Exchange
645   void xchg(Register dst, Register src);
646   void xchg(Register dst, const Operand& src);
647   void xchg_b(Register reg, const Operand& op);
648   void xchg_w(Register reg, const Operand& op);
649 
650   // Lock prefix
651   void lock();
652 
653   // CompareExchange
654   void cmpxchg(const Operand& dst, Register src);
655   void cmpxchg_b(const Operand& dst, Register src);
656   void cmpxchg_w(const Operand& dst, Register src);
657 
658   // Arithmetics
659   void adc(Register dst, int32_t imm32);
660   void adc(Register dst, const Operand& src);
661 
add(Register dst,Register src)662   void add(Register dst, Register src) { add(dst, Operand(src)); }
663   void add(Register dst, const Operand& src);
664   void add(const Operand& dst, Register src);
add(Register dst,const Immediate & imm)665   void add(Register dst, const Immediate& imm) { add(Operand(dst), imm); }
666   void add(const Operand& dst, const Immediate& x);
667 
668   void and_(Register dst, int32_t imm32);
669   void and_(Register dst, const Immediate& x);
and_(Register dst,Register src)670   void and_(Register dst, Register src) { and_(dst, Operand(src)); }
671   void and_(Register dst, const Operand& src);
672   void and_(const Operand& dst, Register src);
673   void and_(const Operand& dst, const Immediate& x);
674 
cmpb(Register reg,Immediate imm8)675   void cmpb(Register reg, Immediate imm8) { cmpb(Operand(reg), imm8); }
676   void cmpb(const Operand& op, Immediate imm8);
677   void cmpb(Register reg, const Operand& op);
678   void cmpb(const Operand& op, Register reg);
cmpb(Register dst,Register src)679   void cmpb(Register dst, Register src) { cmpb(Operand(dst), src); }
680   void cmpb_al(const Operand& op);
681   void cmpw_ax(const Operand& op);
682   void cmpw(const Operand& dst, Immediate src);
cmpw(Register dst,Immediate src)683   void cmpw(Register dst, Immediate src) { cmpw(Operand(dst), src); }
684   void cmpw(Register dst, const Operand& src);
cmpw(Register dst,Register src)685   void cmpw(Register dst, Register src) { cmpw(Operand(dst), src); }
686   void cmpw(const Operand& dst, Register src);
687   void cmp(Register reg, int32_t imm32);
688   void cmp(Register reg, Handle<Object> handle);
cmp(Register reg0,Register reg1)689   void cmp(Register reg0, Register reg1) { cmp(reg0, Operand(reg1)); }
690   void cmp(Register reg, const Operand& op);
cmp(Register reg,const Immediate & imm)691   void cmp(Register reg, const Immediate& imm) { cmp(Operand(reg), imm); }
692   void cmp(const Operand& op, Register reg);
693   void cmp(const Operand& op, const Immediate& imm);
694   void cmp(const Operand& op, Handle<Object> handle);
695 
696   void dec_b(Register dst);
697   void dec_b(const Operand& dst);
698 
699   void dec(Register dst);
700   void dec(const Operand& dst);
701 
702   void cdq();
703 
idiv(Register src)704   void idiv(Register src) { idiv(Operand(src)); }
705   void idiv(const Operand& src);
div(Register src)706   void div(Register src) { div(Operand(src)); }
707   void div(const Operand& src);
708 
709   // Signed multiply instructions.
710   void imul(Register src);                               // edx:eax = eax * src.
imul(Register dst,Register src)711   void imul(Register dst, Register src) { imul(dst, Operand(src)); }
712   void imul(Register dst, const Operand& src);           // dst = dst * src.
713   void imul(Register dst, Register src, int32_t imm32);  // dst = src * imm32.
714   void imul(Register dst, const Operand& src, int32_t imm32);
715 
716   void inc(Register dst);
717   void inc(const Operand& dst);
718 
719   void lea(Register dst, const Operand& src);
720 
721   // Unsigned multiply instruction.
722   void mul(Register src);                                // edx:eax = eax * reg.
723 
724   void neg(Register dst);
725   void neg(const Operand& dst);
726 
727   void not_(Register dst);
728   void not_(const Operand& dst);
729 
730   void or_(Register dst, int32_t imm32);
or_(Register dst,Register src)731   void or_(Register dst, Register src) { or_(dst, Operand(src)); }
732   void or_(Register dst, const Operand& src);
733   void or_(const Operand& dst, Register src);
or_(Register dst,const Immediate & imm)734   void or_(Register dst, const Immediate& imm) { or_(Operand(dst), imm); }
735   void or_(const Operand& dst, const Immediate& x);
736 
737   void rcl(Register dst, uint8_t imm8);
738   void rcr(Register dst, uint8_t imm8);
739 
ror(Register dst,uint8_t imm8)740   void ror(Register dst, uint8_t imm8) { ror(Operand(dst), imm8); }
741   void ror(const Operand& dst, uint8_t imm8);
ror_cl(Register dst)742   void ror_cl(Register dst) { ror_cl(Operand(dst)); }
743   void ror_cl(const Operand& dst);
744 
sar(Register dst,uint8_t imm8)745   void sar(Register dst, uint8_t imm8) { sar(Operand(dst), imm8); }
746   void sar(const Operand& dst, uint8_t imm8);
sar_cl(Register dst)747   void sar_cl(Register dst) { sar_cl(Operand(dst)); }
748   void sar_cl(const Operand& dst);
749 
750   void sbb(Register dst, const Operand& src);
751 
shl(Register dst,uint8_t imm8)752   void shl(Register dst, uint8_t imm8) { shl(Operand(dst), imm8); }
753   void shl(const Operand& dst, uint8_t imm8);
shl_cl(Register dst)754   void shl_cl(Register dst) { shl_cl(Operand(dst)); }
755   void shl_cl(const Operand& dst);
756   void shld(Register dst, Register src, uint8_t shift);
757   void shld_cl(Register dst, Register src);
758 
shr(Register dst,uint8_t imm8)759   void shr(Register dst, uint8_t imm8) { shr(Operand(dst), imm8); }
760   void shr(const Operand& dst, uint8_t imm8);
shr_cl(Register dst)761   void shr_cl(Register dst) { shr_cl(Operand(dst)); }
762   void shr_cl(const Operand& dst);
763   void shrd(Register dst, Register src, uint8_t shift);
shrd_cl(Register dst,Register src)764   void shrd_cl(Register dst, Register src) { shrd_cl(Operand(dst), src); }
765   void shrd_cl(const Operand& dst, Register src);
766 
sub(Register dst,const Immediate & imm)767   void sub(Register dst, const Immediate& imm) { sub(Operand(dst), imm); }
768   void sub(const Operand& dst, const Immediate& x);
sub(Register dst,Register src)769   void sub(Register dst, Register src) { sub(dst, Operand(src)); }
770   void sub(Register dst, const Operand& src);
771   void sub(const Operand& dst, Register src);
772 
773   void test(Register reg, const Immediate& imm);
test(Register reg0,Register reg1)774   void test(Register reg0, Register reg1) { test(reg0, Operand(reg1)); }
775   void test(Register reg, const Operand& op);
776   void test(const Operand& op, const Immediate& imm);
test(const Operand & op,Register reg)777   void test(const Operand& op, Register reg) { test(reg, op); }
778   void test_b(Register reg, const Operand& op);
779   void test_b(Register reg, Immediate imm8);
780   void test_b(const Operand& op, Immediate imm8);
test_b(const Operand & op,Register reg)781   void test_b(const Operand& op, Register reg) { test_b(reg, op); }
test_b(Register dst,Register src)782   void test_b(Register dst, Register src) { test_b(dst, Operand(src)); }
783   void test_w(Register reg, const Operand& op);
784   void test_w(Register reg, Immediate imm16);
785   void test_w(const Operand& op, Immediate imm16);
test_w(const Operand & op,Register reg)786   void test_w(const Operand& op, Register reg) { test_w(reg, op); }
test_w(Register dst,Register src)787   void test_w(Register dst, Register src) { test_w(dst, Operand(src)); }
788 
789   void xor_(Register dst, int32_t imm32);
xor_(Register dst,Register src)790   void xor_(Register dst, Register src) { xor_(dst, Operand(src)); }
791   void xor_(Register dst, const Operand& src);
792   void xor_(const Operand& dst, Register src);
xor_(Register dst,const Immediate & imm)793   void xor_(Register dst, const Immediate& imm) { xor_(Operand(dst), imm); }
794   void xor_(const Operand& dst, const Immediate& x);
795 
796   // Bit operations.
797   void bt(const Operand& dst, Register src);
bts(Register dst,Register src)798   void bts(Register dst, Register src) { bts(Operand(dst), src); }
799   void bts(const Operand& dst, Register src);
bsr(Register dst,Register src)800   void bsr(Register dst, Register src) { bsr(dst, Operand(src)); }
801   void bsr(Register dst, const Operand& src);
bsf(Register dst,Register src)802   void bsf(Register dst, Register src) { bsf(dst, Operand(src)); }
803   void bsf(Register dst, const Operand& src);
804 
805   // Miscellaneous
806   void hlt();
807   void int3();
808   void nop();
809   void ret(int imm16);
810   void ud2();
811 
812   // Label operations & relative jumps (PPUM Appendix D)
813   //
814   // Takes a branch opcode (cc) and a label (L) and generates
815   // either a backward branch or a forward branch and links it
816   // to the label fixup chain. Usage:
817   //
818   // Label L;    // unbound label
819   // j(cc, &L);  // forward branch to unbound label
820   // bind(&L);   // bind label to the current pc
821   // j(cc, &L);  // backward branch to bound label
822   // bind(&L);   // illegal: a label may be bound only once
823   //
824   // Note: The same Label can be used for forward and backward branches
825   // but it may be bound only once.
826 
827   void bind(Label* L);  // binds an unbound label L to the current code position
828 
829   // Calls
830   void call(Label* L);
831   void call(byte* entry, RelocInfo::Mode rmode);
832   int CallSize(const Operand& adr);
call(Register reg)833   void call(Register reg) { call(Operand(reg)); }
834   void call(const Operand& adr);
835   int CallSize(Handle<Code> code, RelocInfo::Mode mode);
836   void call(Handle<Code> code,
837             RelocInfo::Mode rmode,
838             TypeFeedbackId id = TypeFeedbackId::None());
839 
840   // Jumps
841   // unconditional jump to L
842   void jmp(Label* L, Label::Distance distance = Label::kFar);
843   void jmp(byte* entry, RelocInfo::Mode rmode);
jmp(Register reg)844   void jmp(Register reg) { jmp(Operand(reg)); }
845   void jmp(const Operand& adr);
846   void jmp(Handle<Code> code, RelocInfo::Mode rmode);
847 
848   // Conditional jumps
849   void j(Condition cc,
850          Label* L,
851          Label::Distance distance = Label::kFar);
852   void j(Condition cc, byte* entry, RelocInfo::Mode rmode);
853   void j(Condition cc, Handle<Code> code,
854          RelocInfo::Mode rmode = RelocInfo::CODE_TARGET);
855 
856   // Floating-point operations
857   void fld(int i);
858   void fstp(int i);
859 
860   void fld1();
861   void fldz();
862   void fldpi();
863   void fldln2();
864 
865   void fld_s(const Operand& adr);
866   void fld_d(const Operand& adr);
867 
868   void fstp_s(const Operand& adr);
869   void fst_s(const Operand& adr);
870   void fstp_d(const Operand& adr);
871   void fst_d(const Operand& adr);
872 
873   void fild_s(const Operand& adr);
874   void fild_d(const Operand& adr);
875 
876   void fist_s(const Operand& adr);
877 
878   void fistp_s(const Operand& adr);
879   void fistp_d(const Operand& adr);
880 
881   // The fisttp instructions require SSE3.
882   void fisttp_s(const Operand& adr);
883   void fisttp_d(const Operand& adr);
884 
885   void fabs();
886   void fchs();
887   void fsqrt();
888   void fcos();
889   void fsin();
890   void fptan();
891   void fyl2x();
892   void f2xm1();
893   void fscale();
894   void fninit();
895 
896   void fadd(int i);
897   void fadd_i(int i);
898   void fadd_d(const Operand& adr);
899   void fsub(int i);
900   void fsub_i(int i);
901   void fsub_d(const Operand& adr);
902   void fsubr_d(const Operand& adr);
903   void fmul(int i);
904   void fmul_d(const Operand& adr);
905   void fmul_i(int i);
906   void fdiv(int i);
907   void fdiv_d(const Operand& adr);
908   void fdivr_d(const Operand& adr);
909   void fdiv_i(int i);
910 
911   void fisub_s(const Operand& adr);
912 
913   void faddp(int i = 1);
914   void fsubp(int i = 1);
915   void fsubr(int i = 1);
916   void fsubrp(int i = 1);
917   void fmulp(int i = 1);
918   void fdivp(int i = 1);
919   void fprem();
920   void fprem1();
921 
922   void fxch(int i = 1);
923   void fincstp();
924   void ffree(int i = 0);
925 
926   void ftst();
927   void fxam();
928   void fucomp(int i);
929   void fucompp();
930   void fucomi(int i);
931   void fucomip();
932   void fcompp();
933   void fnstsw_ax();
934   void fldcw(const Operand& adr);
935   void fnstcw(const Operand& adr);
936   void fwait();
937   void fnclex();
938   void fnsave(const Operand& adr);
939   void frstor(const Operand& adr);
940 
941   void frndint();
942 
943   void sahf();
944   void setcc(Condition cc, Register reg);
945 
946   void cpuid();
947 
948   // TODO(lrn): Need SFENCE for movnt?
949 
950   // Check the code size generated from label to here.
SizeOfCodeGeneratedSince(Label * label)951   int SizeOfCodeGeneratedSince(Label* label) {
952     return pc_offset() - label->pos();
953   }
954 
955   // Mark address of a debug break slot.
956   void RecordDebugBreakSlot(RelocInfo::Mode mode);
957 
958   // Record a comment relocation entry that can be used by a disassembler.
959   // Use --code-comments to enable.
960   void RecordComment(const char* msg);
961 
962   // Record a deoptimization reason that can be used by a log or cpu profiler.
963   // Use --trace-deopt to enable.
964   void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
965                          int id);
966 
967   // Writes a single byte or word of data in the code stream.  Used for
968   // inline tables, e.g., jump-tables.
969   void db(uint8_t data);
970   void dd(uint32_t data);
971   void dq(uint64_t data);
dp(uintptr_t data)972   void dp(uintptr_t data) { dd(data); }
973   void dd(Label* label);
974 
975   // Check if there is less than kGap bytes available in the buffer.
976   // If this is the case, we need to grow the buffer before emitting
977   // an instruction or relocation information.
buffer_overflow()978   inline bool buffer_overflow() const {
979     return pc_ >= reloc_info_writer.pos() - kGap;
980   }
981 
982   // Get the number of bytes available in the buffer.
available_space()983   inline int available_space() const { return reloc_info_writer.pos() - pc_; }
984 
985   static bool IsNop(Address addr);
986 
relocation_writer_size()987   int relocation_writer_size() {
988     return (buffer_ + buffer_size_) - reloc_info_writer.pos();
989   }
990 
991   // Avoid overflows for displacements etc.
992   static const int kMaximalBufferSize = 512*MB;
993 
byte_at(int pos)994   byte byte_at(int pos) { return buffer_[pos]; }
set_byte_at(int pos,byte value)995   void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
996 
PatchConstantPoolAccessInstruction(int pc_offset,int offset,ConstantPoolEntry::Access access,ConstantPoolEntry::Type type)997   void PatchConstantPoolAccessInstruction(int pc_offset, int offset,
998                                           ConstantPoolEntry::Access access,
999                                           ConstantPoolEntry::Type type) {
1000     // No embedded constant pool support.
1001     UNREACHABLE();
1002   }
1003 
1004  protected:
addr_at(int pos)1005   byte* addr_at(int pos) { return buffer_ + pos; }
1006 
1007 
1008  private:
long_at(int pos)1009   uint32_t long_at(int pos)  {
1010     return *reinterpret_cast<uint32_t*>(addr_at(pos));
1011   }
long_at_put(int pos,uint32_t x)1012   void long_at_put(int pos, uint32_t x)  {
1013     *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
1014   }
1015 
1016   // code emission
1017   void GrowBuffer();
1018   inline void emit(uint32_t x);
1019   inline void emit(Handle<Object> handle);
1020   inline void emit(uint32_t x,
1021                    RelocInfo::Mode rmode,
1022                    TypeFeedbackId id = TypeFeedbackId::None());
1023   inline void emit(Handle<Code> code,
1024                    RelocInfo::Mode rmode,
1025                    TypeFeedbackId id = TypeFeedbackId::None());
1026   inline void emit(const Immediate& x);
1027   inline void emit_b(Immediate x);
1028   inline void emit_w(const Immediate& x);
1029   inline void emit_q(uint64_t x);
1030 
1031   // Emit the code-object-relative offset of the label's position
1032   inline void emit_code_relative_offset(Label* label);
1033 
1034   // instruction generation
1035   void emit_arith_b(int op1, int op2, Register dst, int imm8);
1036 
1037   // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81)
1038   // with a given destination expression and an immediate operand.  It attempts
1039   // to use the shortest encoding possible.
1040   // sel specifies the /n in the modrm byte (see the Intel PRM).
1041   void emit_arith(int sel, Operand dst, const Immediate& x);
1042 
1043   void emit_operand(Register reg, const Operand& adr);
1044 
1045   void emit_label(Label* label);
1046 
1047   void emit_farith(int b1, int b2, int i);
1048 
1049   // labels
1050   void print(Label* L);
1051   void bind_to(Label* L, int pos);
1052 
1053   // displacements
1054   inline Displacement disp_at(Label* L);
1055   inline void disp_at_put(Label* L, Displacement disp);
1056   inline void emit_disp(Label* L, Displacement::Type type);
1057   inline void emit_near_disp(Label* L);
1058 
1059   // record reloc info for current pc_
1060   void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1061 
1062   friend class CodePatcher;
1063   friend class EnsureSpace;
1064 
1065   // Internal reference positions, required for (potential) patching in
1066   // GrowBuffer(); contains only those internal references whose labels
1067   // are already bound.
1068   std::deque<int> internal_reference_positions_;
1069 
1070   // code generation
1071   RelocInfoWriter reloc_info_writer;
1072 };
1073 
1074 
1075 // Helper class that ensures that there is enough space for generating
1076 // instructions and relocation information.  The constructor makes
1077 // sure that there is enough space and (in debug mode) the destructor
1078 // checks that we did not generate too much.
1079 class EnsureSpace BASE_EMBEDDED {
1080  public:
EnsureSpace(Assembler * assembler)1081   explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
1082     if (assembler_->buffer_overflow()) assembler_->GrowBuffer();
1083 #ifdef DEBUG
1084     space_before_ = assembler_->available_space();
1085 #endif
1086   }
1087 
1088 #ifdef DEBUG
~EnsureSpace()1089   ~EnsureSpace() {
1090     int bytes_generated = space_before_ - assembler_->available_space();
1091     DCHECK(bytes_generated < assembler_->kGap);
1092   }
1093 #endif
1094 
1095  private:
1096   Assembler* assembler_;
1097 #ifdef DEBUG
1098   int space_before_;
1099 #endif
1100 };
1101 
1102 }  // namespace internal
1103 }  // namespace v8
1104 
1105 #endif  // V8_X87_ASSEMBLER_X87_H_
1106