• 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     DCHECK(code >= 0);
82     DCHECK(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     DCHECK(is_valid());
92     return code_;
93   }
bitRegister94   int bit() const {
95     DCHECK(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   DCHECK(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   DCHECK(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   DCHECK(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 = 6;
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     DCHECK(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     DCHECK(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     DCHECK(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 Operand;
296   friend class Assembler;
297   friend class MacroAssembler;
298 };
299 
300 
301 // -----------------------------------------------------------------------------
302 // Machine instruction Operands
303 
304 enum ScaleFactor {
305   times_1 = 0,
306   times_2 = 1,
307   times_4 = 2,
308   times_8 = 3,
309   times_int_size = times_4,
310   times_half_pointer_size = times_2,
311   times_pointer_size = times_4,
312   times_twice_pointer_size = times_8
313 };
314 
315 
316 class Operand BASE_EMBEDDED {
317  public:
318   // reg
319   INLINE(explicit Operand(Register reg));
320 
321   // [disp/r]
322   INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode));
323 
324   // [disp/r]
325   INLINE(explicit Operand(Immediate imm));
326 
327   // [base + disp/r]
328   explicit Operand(Register base, int32_t disp,
329                    RelocInfo::Mode rmode = RelocInfo::NONE32);
330 
331   // [base + index*scale + disp/r]
332   explicit Operand(Register base,
333                    Register index,
334                    ScaleFactor scale,
335                    int32_t disp,
336                    RelocInfo::Mode rmode = RelocInfo::NONE32);
337 
338   // [index*scale + disp/r]
339   explicit Operand(Register index,
340                    ScaleFactor scale,
341                    int32_t disp,
342                    RelocInfo::Mode rmode = RelocInfo::NONE32);
343 
StaticVariable(const ExternalReference & ext)344   static Operand StaticVariable(const ExternalReference& ext) {
345     return Operand(reinterpret_cast<int32_t>(ext.address()),
346                    RelocInfo::EXTERNAL_REFERENCE);
347   }
348 
StaticArray(Register index,ScaleFactor scale,const ExternalReference & arr)349   static Operand StaticArray(Register index,
350                              ScaleFactor scale,
351                              const ExternalReference& arr) {
352     return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()),
353                    RelocInfo::EXTERNAL_REFERENCE);
354   }
355 
ForCell(Handle<Cell> cell)356   static Operand ForCell(Handle<Cell> cell) {
357     AllowDeferredHandleDereference embedding_raw_address;
358     return Operand(reinterpret_cast<int32_t>(cell.location()),
359                    RelocInfo::CELL);
360   }
361 
ForRegisterPlusImmediate(Register base,Immediate imm)362   static Operand ForRegisterPlusImmediate(Register base, Immediate imm) {
363     return Operand(base, imm.x_, imm.rmode_);
364   }
365 
366   // Returns true if this Operand is a wrapper for the specified register.
367   bool is_reg(Register reg) const;
368 
369   // Returns true if this Operand is a wrapper for one register.
370   bool is_reg_only() const;
371 
372   // Asserts that this Operand is a wrapper for one register and returns the
373   // register.
374   Register reg() const;
375 
376  private:
377   // Set the ModRM byte without an encoded 'reg' register. The
378   // register is encoded later as part of the emit_operand operation.
379   inline void set_modrm(int mod, Register rm);
380 
381   inline void set_sib(ScaleFactor scale, Register index, Register base);
382   inline void set_disp8(int8_t disp);
383   inline void set_dispr(int32_t disp, RelocInfo::Mode rmode);
384 
385   byte buf_[6];
386   // The number of bytes in buf_.
387   unsigned int len_;
388   // Only valid if len_ > 4.
389   RelocInfo::Mode rmode_;
390 
391   friend class Assembler;
392   friend class MacroAssembler;
393 };
394 
395 
396 // -----------------------------------------------------------------------------
397 // A Displacement describes the 32bit immediate field of an instruction which
398 // may be used together with a Label in order to refer to a yet unknown code
399 // position. Displacements stored in the instruction stream are used to describe
400 // the instruction and to chain a list of instructions using the same Label.
401 // A Displacement contains 2 different fields:
402 //
403 // next field: position of next displacement in the chain (0 = end of list)
404 // type field: instruction type
405 //
406 // A next value of null (0) indicates the end of a chain (note that there can
407 // be no displacement at position zero, because there is always at least one
408 // instruction byte before the displacement).
409 //
410 // Displacement _data field layout
411 //
412 // |31.....2|1......0|
413 // [  next  |  type  |
414 
415 class Displacement BASE_EMBEDDED {
416  public:
417   enum Type {
418     UNCONDITIONAL_JUMP,
419     CODE_RELATIVE,
420     OTHER
421   };
422 
data()423   int data() const { return data_; }
type()424   Type type() const { return TypeField::decode(data_); }
next(Label * L)425   void next(Label* L) const {
426     int n = NextField::decode(data_);
427     n > 0 ? L->link_to(n) : L->Unuse();
428   }
link_to(Label * L)429   void link_to(Label* L) { init(L, type()); }
430 
Displacement(int data)431   explicit Displacement(int data) { data_ = data; }
432 
Displacement(Label * L,Type type)433   Displacement(Label* L, Type type) { init(L, type); }
434 
print()435   void print() {
436     PrintF("%s (%x) ", (type() == UNCONDITIONAL_JUMP ? "jmp" : "[other]"),
437                        NextField::decode(data_));
438   }
439 
440  private:
441   int data_;
442 
443   class TypeField: public BitField<Type, 0, 2> {};
444   class NextField: public BitField<int,  2, 32-2> {};
445 
446   void init(Label* L, Type type);
447 };
448 
449 
450 class Assembler : public AssemblerBase {
451  private:
452   // We check before assembling an instruction that there is sufficient
453   // space to write an instruction and its relocation information.
454   // The relocation writer's position must be kGap bytes above the end of
455   // the generated instructions. This leaves enough space for the
456   // longest possible ia32 instruction, 15 bytes, and the longest possible
457   // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
458   // (There is a 15 byte limit on ia32 instruction length that rules out some
459   // otherwise valid instructions.)
460   // This allows for a single, fast space check per instruction.
461   static const int kGap = 32;
462 
463  public:
464   // Create an assembler. Instructions and relocation information are emitted
465   // into a buffer, with the instructions starting from the beginning and the
466   // relocation information starting from the end of the buffer. See CodeDesc
467   // for a detailed comment on the layout (globals.h).
468   //
469   // If the provided buffer is NULL, the assembler allocates and grows its own
470   // buffer, and buffer_size determines the initial buffer size. The buffer is
471   // owned by the assembler and deallocated upon destruction of the assembler.
472   //
473   // If the provided buffer is not NULL, the assembler uses the provided buffer
474   // for code generation and assumes its size to be buffer_size. If the buffer
475   // is too small, a fatal error occurs. No deallocation of the buffer is done
476   // upon destruction of the assembler.
477   // TODO(vitalyr): the assembler does not need an isolate.
478   Assembler(Isolate* isolate, void* buffer, int buffer_size);
~Assembler()479   virtual ~Assembler() { }
480 
481   // GetCode emits any pending (non-emitted) code and fills the descriptor
482   // desc. GetCode() is idempotent; it returns the same result if no other
483   // Assembler functions are invoked in between GetCode() calls.
484   void GetCode(CodeDesc* desc);
485 
486   // Read/Modify the code target in the branch/call instruction at pc.
487   inline static Address target_address_at(Address pc,
488                                           ConstantPoolArray* constant_pool);
489   inline static void set_target_address_at(Address pc,
490                                            ConstantPoolArray* constant_pool,
491                                            Address target,
492                                            ICacheFlushMode icache_flush_mode =
493                                                FLUSH_ICACHE_IF_NEEDED);
target_address_at(Address pc,Code * code)494   static inline Address target_address_at(Address pc, Code* code) {
495     ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
496     return target_address_at(pc, constant_pool);
497   }
498   static inline void set_target_address_at(Address pc,
499                                            Code* code,
500                                            Address target,
501                                            ICacheFlushMode icache_flush_mode =
502                                                FLUSH_ICACHE_IF_NEEDED) {
503     ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
504     set_target_address_at(pc, constant_pool, target);
505   }
506 
507   // Return the code target address at a call site from the return address
508   // of that call in the instruction stream.
509   inline static Address target_address_from_return_address(Address pc);
510 
511   // Return the code target address of the patch debug break slot
512   inline static Address break_address_from_return_address(Address pc);
513 
514   // This sets the branch destination (which is in the instruction on x86).
515   // This is for calls and branches within generated code.
deserialization_set_special_target_at(Address instruction_payload,Code * code,Address target)516   inline static void deserialization_set_special_target_at(
517       Address instruction_payload, Code* code, Address target) {
518     set_target_address_at(instruction_payload, code, target);
519   }
520 
521   static const int kSpecialTargetSize = kPointerSize;
522 
523   // Distance between the address of the code target in the call instruction
524   // and the return address
525   static const int kCallTargetAddressOffset = kPointerSize;
526   // Distance between start of patched return sequence and the emitted address
527   // to jump to.
528   static const int kPatchReturnSequenceAddressOffset = 1;  // JMP imm32.
529 
530   // Distance between start of patched debug break slot and the emitted address
531   // to jump to.
532   static const int kPatchDebugBreakSlotAddressOffset = 1;  // JMP imm32.
533 
534   static const int kCallInstructionLength = 5;
535   static const int kPatchDebugBreakSlotReturnOffset = kPointerSize;
536   static const int kJSReturnSequenceLength = 6;
537 
538   // The debug break slot must be able to contain a call instruction.
539   static const int kDebugBreakSlotLength = kCallInstructionLength;
540 
541   // One byte opcode for test al, 0xXX.
542   static const byte kTestAlByte = 0xA8;
543   // One byte opcode for nop.
544   static const byte kNopByte = 0x90;
545 
546   // One byte opcode for a short unconditional jump.
547   static const byte kJmpShortOpcode = 0xEB;
548   // One byte prefix for a short conditional jump.
549   static const byte kJccShortPrefix = 0x70;
550   static const byte kJncShortOpcode = kJccShortPrefix | not_carry;
551   static const byte kJcShortOpcode = kJccShortPrefix | carry;
552   static const byte kJnzShortOpcode = kJccShortPrefix | not_zero;
553   static const byte kJzShortOpcode = kJccShortPrefix | zero;
554 
555 
556   // ---------------------------------------------------------------------------
557   // Code generation
558   //
559   // - function names correspond one-to-one to ia32 instruction mnemonics
560   // - unless specified otherwise, instructions operate on 32bit operands
561   // - instructions on 8bit (byte) operands/registers have a trailing '_b'
562   // - instructions on 16bit (word) operands/registers have a trailing '_w'
563   // - naming conflicts with C++ keywords are resolved via a trailing '_'
564 
565   // NOTE ON INTERFACE: Currently, the interface is not very consistent
566   // in the sense that some operations (e.g. mov()) can be called in more
567   // the one way to generate the same instruction: The Register argument
568   // can in some cases be replaced with an Operand(Register) argument.
569   // This should be cleaned up and made more orthogonal. The questions
570   // is: should we always use Operands instead of Registers where an
571   // Operand is possible, or should we have a Register (overloaded) form
572   // instead? We must be careful to make sure that the selected instruction
573   // is obvious from the parameters to avoid hard-to-find code generation
574   // bugs.
575 
576   // Insert the smallest number of nop instructions
577   // possible to align the pc offset to a multiple
578   // of m. m must be a power of 2.
579   void Align(int m);
580   void Nop(int bytes = 1);
581   // Aligns code to something that's optimal for a jump target for the platform.
582   void CodeTargetAlign();
583 
584   // Stack
585   void pushad();
586   void popad();
587 
588   void pushfd();
589   void popfd();
590 
591   void push(const Immediate& x);
592   void push_imm32(int32_t imm32);
593   void push(Register src);
594   void push(const Operand& src);
595 
596   void pop(Register dst);
597   void pop(const Operand& dst);
598 
599   void enter(const Immediate& size);
600   void leave();
601 
602   // Moves
mov_b(Register dst,Register src)603   void mov_b(Register dst, Register src) { mov_b(dst, Operand(src)); }
604   void mov_b(Register dst, const Operand& src);
mov_b(Register dst,int8_t imm8)605   void mov_b(Register dst, int8_t imm8) { mov_b(Operand(dst), imm8); }
606   void mov_b(const Operand& dst, int8_t imm8);
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 
613   void mov(Register dst, int32_t imm32);
614   void mov(Register dst, const Immediate& x);
615   void mov(Register dst, Handle<Object> handle);
616   void mov(Register dst, const Operand& src);
617   void mov(Register dst, Register src);
618   void mov(const Operand& dst, const Immediate& x);
619   void mov(const Operand& dst, Handle<Object> handle);
620   void mov(const Operand& dst, Register src);
621 
movsx_b(Register dst,Register src)622   void movsx_b(Register dst, Register src) { movsx_b(dst, Operand(src)); }
623   void movsx_b(Register dst, const Operand& src);
624 
movsx_w(Register dst,Register src)625   void movsx_w(Register dst, Register src) { movsx_w(dst, Operand(src)); }
626   void movsx_w(Register dst, const Operand& src);
627 
movzx_b(Register dst,Register src)628   void movzx_b(Register dst, Register src) { movzx_b(dst, Operand(src)); }
629   void movzx_b(Register dst, const Operand& src);
630 
movzx_w(Register dst,Register src)631   void movzx_w(Register dst, Register src) { movzx_w(dst, Operand(src)); }
632   void movzx_w(Register dst, const Operand& src);
633 
634   // Flag management.
635   void cld();
636 
637   // Repetitive string instructions.
638   void rep_movs();
639   void rep_stos();
640   void stos();
641 
642   // Exchange
643   void xchg(Register dst, Register src);
644   void xchg(Register dst, const Operand& src);
645 
646   // Arithmetics
647   void adc(Register dst, int32_t imm32);
648   void adc(Register dst, const Operand& src);
649 
add(Register dst,Register src)650   void add(Register dst, Register src) { add(dst, Operand(src)); }
651   void add(Register dst, const Operand& src);
652   void add(const Operand& dst, Register src);
add(Register dst,const Immediate & imm)653   void add(Register dst, const Immediate& imm) { add(Operand(dst), imm); }
654   void add(const Operand& dst, const Immediate& x);
655 
656   void and_(Register dst, int32_t imm32);
657   void and_(Register dst, const Immediate& x);
and_(Register dst,Register src)658   void and_(Register dst, Register src) { and_(dst, Operand(src)); }
659   void and_(Register dst, const Operand& src);
660   void and_(const Operand& dst, Register src);
661   void and_(const Operand& dst, const Immediate& x);
662 
cmpb(Register reg,int8_t imm8)663   void cmpb(Register reg, int8_t imm8) { cmpb(Operand(reg), imm8); }
664   void cmpb(const Operand& op, int8_t imm8);
665   void cmpb(Register reg, const Operand& op);
666   void cmpb(const Operand& op, Register reg);
667   void cmpb_al(const Operand& op);
668   void cmpw_ax(const Operand& op);
669   void cmpw(const Operand& op, Immediate imm16);
670   void cmp(Register reg, int32_t imm32);
671   void cmp(Register reg, Handle<Object> handle);
cmp(Register reg0,Register reg1)672   void cmp(Register reg0, Register reg1) { cmp(reg0, Operand(reg1)); }
673   void cmp(Register reg, const Operand& op);
cmp(Register reg,const Immediate & imm)674   void cmp(Register reg, const Immediate& imm) { cmp(Operand(reg), imm); }
675   void cmp(const Operand& op, const Immediate& imm);
676   void cmp(const Operand& op, Handle<Object> handle);
677 
678   void dec_b(Register dst);
679   void dec_b(const Operand& dst);
680 
681   void dec(Register dst);
682   void dec(const Operand& dst);
683 
684   void cdq();
685 
idiv(Register src)686   void idiv(Register src) { idiv(Operand(src)); }
687   void idiv(const Operand& src);
div(Register src)688   void div(Register src) { div(Operand(src)); }
689   void div(const Operand& src);
690 
691   // Signed multiply instructions.
692   void imul(Register src);                               // edx:eax = eax * src.
imul(Register dst,Register src)693   void imul(Register dst, Register src) { imul(dst, Operand(src)); }
694   void imul(Register dst, const Operand& src);           // dst = dst * src.
695   void imul(Register dst, Register src, int32_t imm32);  // dst = src * imm32.
696   void imul(Register dst, const Operand& src, int32_t imm32);
697 
698   void inc(Register dst);
699   void inc(const Operand& dst);
700 
701   void lea(Register dst, const Operand& src);
702 
703   // Unsigned multiply instruction.
704   void mul(Register src);                                // edx:eax = eax * reg.
705 
706   void neg(Register dst);
707   void neg(const Operand& dst);
708 
709   void not_(Register dst);
710   void not_(const Operand& dst);
711 
712   void or_(Register dst, int32_t imm32);
or_(Register dst,Register src)713   void or_(Register dst, Register src) { or_(dst, Operand(src)); }
714   void or_(Register dst, const Operand& src);
715   void or_(const Operand& dst, Register src);
or_(Register dst,const Immediate & imm)716   void or_(Register dst, const Immediate& imm) { or_(Operand(dst), imm); }
717   void or_(const Operand& dst, const Immediate& x);
718 
719   void rcl(Register dst, uint8_t imm8);
720   void rcr(Register dst, uint8_t imm8);
721   void ror(Register dst, uint8_t imm8);
722   void ror_cl(Register dst);
723 
sar(Register dst,uint8_t imm8)724   void sar(Register dst, uint8_t imm8) { sar(Operand(dst), imm8); }
725   void sar(const Operand& dst, uint8_t imm8);
sar_cl(Register dst)726   void sar_cl(Register dst) { sar_cl(Operand(dst)); }
727   void sar_cl(const Operand& dst);
728 
729   void sbb(Register dst, const Operand& src);
730 
shld(Register dst,Register src)731   void shld(Register dst, Register src) { shld(dst, Operand(src)); }
732   void shld(Register dst, const Operand& src);
733 
shl(Register dst,uint8_t imm8)734   void shl(Register dst, uint8_t imm8) { shl(Operand(dst), imm8); }
735   void shl(const Operand& dst, uint8_t imm8);
shl_cl(Register dst)736   void shl_cl(Register dst) { shl_cl(Operand(dst)); }
737   void shl_cl(const Operand& dst);
738 
shrd(Register dst,Register src)739   void shrd(Register dst, Register src) { shrd(dst, Operand(src)); }
740   void shrd(Register dst, const Operand& src);
741 
shr(Register dst,uint8_t imm8)742   void shr(Register dst, uint8_t imm8) { shr(Operand(dst), imm8); }
743   void shr(const Operand& dst, uint8_t imm8);
shr_cl(Register dst)744   void shr_cl(Register dst) { shr_cl(Operand(dst)); }
745   void shr_cl(const Operand& dst);
746 
sub(Register dst,const Immediate & imm)747   void sub(Register dst, const Immediate& imm) { sub(Operand(dst), imm); }
748   void sub(const Operand& dst, const Immediate& x);
sub(Register dst,Register src)749   void sub(Register dst, Register src) { sub(dst, Operand(src)); }
750   void sub(Register dst, const Operand& src);
751   void sub(const Operand& dst, Register src);
752 
753   void test(Register reg, const Immediate& imm);
test(Register reg0,Register reg1)754   void test(Register reg0, Register reg1) { test(reg0, Operand(reg1)); }
755   void test(Register reg, const Operand& op);
756   void test_b(Register reg, const Operand& op);
757   void test(const Operand& op, const Immediate& imm);
758   void test_b(Register reg, uint8_t imm8);
759   void test_b(const Operand& op, uint8_t imm8);
760 
761   void xor_(Register dst, int32_t imm32);
xor_(Register dst,Register src)762   void xor_(Register dst, Register src) { xor_(dst, Operand(src)); }
763   void xor_(Register dst, const Operand& src);
764   void xor_(const Operand& dst, Register src);
xor_(Register dst,const Immediate & imm)765   void xor_(Register dst, const Immediate& imm) { xor_(Operand(dst), imm); }
766   void xor_(const Operand& dst, const Immediate& x);
767 
768   // Bit operations.
769   void bt(const Operand& dst, Register src);
bts(Register dst,Register src)770   void bts(Register dst, Register src) { bts(Operand(dst), src); }
771   void bts(const Operand& dst, Register src);
bsr(Register dst,Register src)772   void bsr(Register dst, Register src) { bsr(dst, Operand(src)); }
773   void bsr(Register dst, const Operand& src);
774 
775   // Miscellaneous
776   void hlt();
777   void int3();
778   void nop();
779   void ret(int imm16);
780 
781   // Label operations & relative jumps (PPUM Appendix D)
782   //
783   // Takes a branch opcode (cc) and a label (L) and generates
784   // either a backward branch or a forward branch and links it
785   // to the label fixup chain. Usage:
786   //
787   // Label L;    // unbound label
788   // j(cc, &L);  // forward branch to unbound label
789   // bind(&L);   // bind label to the current pc
790   // j(cc, &L);  // backward branch to bound label
791   // bind(&L);   // illegal: a label may be bound only once
792   //
793   // Note: The same Label can be used for forward and backward branches
794   // but it may be bound only once.
795 
796   void bind(Label* L);  // binds an unbound label L to the current code position
797 
798   // Calls
799   void call(Label* L);
800   void call(byte* entry, RelocInfo::Mode rmode);
801   int CallSize(const Operand& adr);
call(Register reg)802   void call(Register reg) { call(Operand(reg)); }
803   void call(const Operand& adr);
804   int CallSize(Handle<Code> code, RelocInfo::Mode mode);
805   void call(Handle<Code> code,
806             RelocInfo::Mode rmode,
807             TypeFeedbackId id = TypeFeedbackId::None());
808 
809   // Jumps
810   // unconditional jump to L
811   void jmp(Label* L, Label::Distance distance = Label::kFar);
812   void jmp(byte* entry, RelocInfo::Mode rmode);
jmp(Register reg)813   void jmp(Register reg) { jmp(Operand(reg)); }
814   void jmp(const Operand& adr);
815   void jmp(Handle<Code> code, RelocInfo::Mode rmode);
816 
817   // Conditional jumps
818   void j(Condition cc,
819          Label* L,
820          Label::Distance distance = Label::kFar);
821   void j(Condition cc, byte* entry, RelocInfo::Mode rmode);
822   void j(Condition cc, Handle<Code> code);
823 
824   // Floating-point operations
825   void fld(int i);
826   void fstp(int i);
827 
828   void fld1();
829   void fldz();
830   void fldpi();
831   void fldln2();
832 
833   void fld_s(const Operand& adr);
834   void fld_d(const Operand& adr);
835 
836   void fstp_s(const Operand& adr);
837   void fst_s(const Operand& adr);
838   void fstp_d(const Operand& adr);
839   void fst_d(const Operand& adr);
840 
841   void fild_s(const Operand& adr);
842   void fild_d(const Operand& adr);
843 
844   void fist_s(const Operand& adr);
845 
846   void fistp_s(const Operand& adr);
847   void fistp_d(const Operand& adr);
848 
849   // The fisttp instructions require SSE3.
850   void fisttp_s(const Operand& adr);
851   void fisttp_d(const Operand& adr);
852 
853   void fabs();
854   void fchs();
855   void fsqrt();
856   void fcos();
857   void fsin();
858   void fptan();
859   void fyl2x();
860   void f2xm1();
861   void fscale();
862   void fninit();
863 
864   void fadd(int i);
865   void fadd_i(int i);
866   void fadd_d(const Operand& adr);
867   void fsub(int i);
868   void fsub_i(int i);
869   void fmul(int i);
870   void fmul_i(int i);
871   void fdiv(int i);
872   void fdiv_i(int i);
873 
874   void fisub_s(const Operand& adr);
875 
876   void faddp(int i = 1);
877   void fsubp(int i = 1);
878   void fsubrp(int i = 1);
879   void fmulp(int i = 1);
880   void fdivp(int i = 1);
881   void fprem();
882   void fprem1();
883 
884   void fxch(int i = 1);
885   void fincstp();
886   void ffree(int i = 0);
887 
888   void ftst();
889   void fxam();
890   void fucomp(int i);
891   void fucompp();
892   void fucomi(int i);
893   void fucomip();
894   void fcompp();
895   void fnstsw_ax();
896   void fldcw(const Operand& adr);
897   void fnstcw(const Operand& adr);
898   void fwait();
899   void fnclex();
900   void fnsave(const Operand& adr);
901   void frstor(const Operand& adr);
902 
903   void frndint();
904 
905   void sahf();
906   void setcc(Condition cc, Register reg);
907 
908   void cpuid();
909 
910   // TODO(lrn): Need SFENCE for movnt?
911 
912   // Debugging
913   void Print();
914 
915   // Check the code size generated from label to here.
SizeOfCodeGeneratedSince(Label * label)916   int SizeOfCodeGeneratedSince(Label* label) {
917     return pc_offset() - label->pos();
918   }
919 
920   // Mark address of the ExitJSFrame code.
921   void RecordJSReturn();
922 
923   // Mark address of a debug break slot.
924   void RecordDebugBreakSlot();
925 
926   // Record a comment relocation entry that can be used by a disassembler.
927   // Use --code-comments to enable, or provide "force = true" flag to always
928   // write a comment.
929   void RecordComment(const char* msg, bool force = false);
930 
931   // Writes a single byte or word of data in the code stream.  Used for
932   // inline tables, e.g., jump-tables.
933   void db(uint8_t data);
934   void dd(uint32_t data);
935 
936   // Check if there is less than kGap bytes available in the buffer.
937   // If this is the case, we need to grow the buffer before emitting
938   // an instruction or relocation information.
buffer_overflow()939   inline bool buffer_overflow() const {
940     return pc_ >= reloc_info_writer.pos() - kGap;
941   }
942 
943   // Get the number of bytes available in the buffer.
available_space()944   inline int available_space() const { return reloc_info_writer.pos() - pc_; }
945 
946   static bool IsNop(Address addr);
947 
positions_recorder()948   PositionsRecorder* positions_recorder() { return &positions_recorder_; }
949 
relocation_writer_size()950   int relocation_writer_size() {
951     return (buffer_ + buffer_size_) - reloc_info_writer.pos();
952   }
953 
954   // Avoid overflows for displacements etc.
955   static const int kMaximalBufferSize = 512*MB;
956 
byte_at(int pos)957   byte byte_at(int pos) { return buffer_[pos]; }
set_byte_at(int pos,byte value)958   void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
959 
960   // Allocate a constant pool of the correct size for the generated code.
961   Handle<ConstantPoolArray> NewConstantPool(Isolate* isolate);
962 
963   // Generate the constant pool for the generated code.
964   void PopulateConstantPool(ConstantPoolArray* constant_pool);
965 
966  protected:
addr_at(int pos)967   byte* addr_at(int pos) { return buffer_ + pos; }
968 
969 
970  private:
long_at(int pos)971   uint32_t long_at(int pos)  {
972     return *reinterpret_cast<uint32_t*>(addr_at(pos));
973   }
long_at_put(int pos,uint32_t x)974   void long_at_put(int pos, uint32_t x)  {
975     *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
976   }
977 
978   // code emission
979   void GrowBuffer();
980   inline void emit(uint32_t x);
981   inline void emit(Handle<Object> handle);
982   inline void emit(uint32_t x,
983                    RelocInfo::Mode rmode,
984                    TypeFeedbackId id = TypeFeedbackId::None());
985   inline void emit(Handle<Code> code,
986                    RelocInfo::Mode rmode,
987                    TypeFeedbackId id = TypeFeedbackId::None());
988   inline void emit(const Immediate& x);
989   inline void emit_w(const Immediate& x);
990 
991   // Emit the code-object-relative offset of the label's position
992   inline void emit_code_relative_offset(Label* label);
993 
994   // instruction generation
995   void emit_arith_b(int op1, int op2, Register dst, int imm8);
996 
997   // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81)
998   // with a given destination expression and an immediate operand.  It attempts
999   // to use the shortest encoding possible.
1000   // sel specifies the /n in the modrm byte (see the Intel PRM).
1001   void emit_arith(int sel, Operand dst, const Immediate& x);
1002 
1003   void emit_operand(Register reg, const Operand& adr);
1004 
1005   void emit_farith(int b1, int b2, int i);
1006 
1007   // labels
1008   void print(Label* L);
1009   void bind_to(Label* L, int pos);
1010 
1011   // displacements
1012   inline Displacement disp_at(Label* L);
1013   inline void disp_at_put(Label* L, Displacement disp);
1014   inline void emit_disp(Label* L, Displacement::Type type);
1015   inline void emit_near_disp(Label* L);
1016 
1017   // record reloc info for current pc_
1018   void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1019 
1020   friend class CodePatcher;
1021   friend class EnsureSpace;
1022 
1023   // code generation
1024   RelocInfoWriter reloc_info_writer;
1025 
1026   PositionsRecorder positions_recorder_;
1027   friend class PositionsRecorder;
1028 };
1029 
1030 
1031 // Helper class that ensures that there is enough space for generating
1032 // instructions and relocation information.  The constructor makes
1033 // sure that there is enough space and (in debug mode) the destructor
1034 // checks that we did not generate too much.
1035 class EnsureSpace BASE_EMBEDDED {
1036  public:
EnsureSpace(Assembler * assembler)1037   explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
1038     if (assembler_->buffer_overflow()) assembler_->GrowBuffer();
1039 #ifdef DEBUG
1040     space_before_ = assembler_->available_space();
1041 #endif
1042   }
1043 
1044 #ifdef DEBUG
~EnsureSpace()1045   ~EnsureSpace() {
1046     int bytes_generated = space_before_ - assembler_->available_space();
1047     DCHECK(bytes_generated < assembler_->kGap);
1048   }
1049 #endif
1050 
1051  private:
1052   Assembler* assembler_;
1053 #ifdef DEBUG
1054   int space_before_;
1055 #endif
1056 };
1057 
1058 } }  // namespace v8::internal
1059 
1060 #endif  // V8_X87_ASSEMBLER_X87_H_
1061