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