V8 Project
assembler-ia32.h
Go to the documentation of this file.
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_IA32_ASSEMBLER_IA32_H_
38 #define V8_IA32_ASSEMBLER_IA32_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;
69  static int NumAllocatableRegisters() {
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 
80  static Register from_code(int code) {
81  DCHECK(code >= 0);
83  Register r = { code };
84  return r;
85  }
86  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
87  bool is(Register reg) const { return code_ == reg.code_; }
88  // eax, ebx, ecx and edx are byte registers, the rest are not.
89  bool is_byte_register() const { return code_ <= 3; }
90  int code() const {
91  DCHECK(is_valid());
92  return code_;
93  }
94  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 
121 const Register no_reg = { kRegister_no_reg_Code };
122 
123 
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 
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 
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 XMMRegister {
145  static const int kMaxNumAllocatableRegisters = 7;
146  static const int kMaxNumRegisters = 8;
147  static int NumAllocatableRegisters() {
149  }
150 
151  // TODO(turbofan): Proper support for float32.
153  return NumAllocatableRegisters();
154  }
155 
156  static int ToAllocationIndex(XMMRegister reg) {
157  DCHECK(reg.code() != 0);
158  return reg.code() - 1;
159  }
160 
161  static XMMRegister FromAllocationIndex(int index) {
162  DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
163  return from_code(index + 1);
164  }
165 
166  static XMMRegister from_code(int code) {
167  XMMRegister result = { code };
168  return result;
169  }
170 
171  bool is_valid() const {
172  return 0 <= code_ && code_ < kMaxNumRegisters;
173  }
174 
175  int code() const {
176  DCHECK(is_valid());
177  return code_;
178  }
179 
180  bool is(XMMRegister reg) const { return code_ == reg.code_; }
181 
182  static const char* AllocationIndexToString(int index) {
183  DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
184  const char* const names[] = {
185  "xmm1",
186  "xmm2",
187  "xmm3",
188  "xmm4",
189  "xmm5",
190  "xmm6",
191  "xmm7"
192  };
193  return names[index];
194  }
195 
196  int code_;
197 };
198 
199 
201 
202 
203 const XMMRegister xmm0 = { 0 };
204 const XMMRegister xmm1 = { 1 };
205 const XMMRegister xmm2 = { 2 };
206 const XMMRegister xmm3 = { 3 };
207 const XMMRegister xmm4 = { 4 };
208 const XMMRegister xmm5 = { 5 };
209 const XMMRegister xmm6 = { 6 };
210 const XMMRegister xmm7 = { 7 };
211 const XMMRegister no_xmm_reg = { -1 };
212 
213 
214 enum Condition {
215  // any value < 0 is considered no_condition
217 
218  overflow = 0,
220  below = 2,
222  equal = 4,
225  above = 7,
226  negative = 8,
227  positive = 9,
230  less = 12,
233  greater = 15,
234 
235  // aliases
242 };
243 
244 
245 // Returns the equivalent of !cc.
246 // Negation of the default no_condition (-1) results in a non-default
247 // no_condition value (-2). As long as tests for no_condition check
248 // for condition < 0, this will work as expected.
250  return static_cast<Condition>(cc ^ 1);
251 }
252 
253 
254 // Commute a condition such that {a cond b == b cond' a}.
256  switch (cc) {
257  case below:
258  return above;
259  case above:
260  return below;
261  case above_equal:
262  return below_equal;
263  case below_equal:
264  return above_equal;
265  case less:
266  return greater;
267  case greater:
268  return less;
269  case greater_equal:
270  return less_equal;
271  case less_equal:
272  return greater_equal;
273  default:
274  return cc;
275  }
276 }
277 
278 
279 // -----------------------------------------------------------------------------
280 // Machine instruction Immediates
281 
282 class Immediate BASE_EMBEDDED {
283  public:
284  inline explicit Immediate(int x);
285  inline explicit Immediate(const ExternalReference& ext);
286  inline explicit Immediate(Handle<Object> handle);
287  inline explicit Immediate(Smi* value);
288  inline explicit Immediate(Address addr);
289 
290  static Immediate CodeRelativeOffset(Label* label) {
291  return Immediate(label);
292  }
293 
294  bool is_zero() const { return x_ == 0 && RelocInfo::IsNone(rmode_); }
295  bool is_int8() const {
296  return -128 <= x_ && x_ < 128 && RelocInfo::IsNone(rmode_);
297  }
298  bool is_int16() const {
299  return -32768 <= x_ && x_ < 32768 && RelocInfo::IsNone(rmode_);
300  }
301 
302  private:
303  inline explicit Immediate(Label* value);
304 
305  int x_;
307 
308  friend class Operand;
309  friend class Assembler;
310  friend class MacroAssembler;
311 };
312 
313 
314 // -----------------------------------------------------------------------------
315 // Machine instruction Operands
316 
318  times_1 = 0,
319  times_2 = 1,
320  times_4 = 2,
321  times_8 = 3,
326 };
327 
328 
329 class Operand BASE_EMBEDDED {
330  public:
331  // reg
333 
334  // XMM reg
335  INLINE(explicit Operand(XMMRegister xmm_reg));
336 
337  // [disp/r]
338  INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode));
339 
340  // [disp/r]
341  INLINE(explicit Operand(Immediate imm));
342 
343  // [base + disp/r]
344  explicit Operand(Register base, int32_t disp,
346 
347  // [base + index*scale + disp/r]
348  explicit Operand(Register base,
349  Register index,
350  ScaleFactor scale,
351  int32_t disp,
353 
354  // [index*scale + disp/r]
355  explicit Operand(Register index,
356  ScaleFactor scale,
357  int32_t disp,
359 
360  static Operand StaticVariable(const ExternalReference& ext) {
361  return Operand(reinterpret_cast<int32_t>(ext.address()),
363  }
364 
366  ScaleFactor scale,
367  const ExternalReference& arr) {
368  return Operand(index, scale, reinterpret_cast<int32_t>(arr.address()),
370  }
371 
372  static Operand ForCell(Handle<Cell> cell) {
373  AllowDeferredHandleDereference embedding_raw_address;
374  return Operand(reinterpret_cast<int32_t>(cell.location()),
376  }
377 
379  return Operand(base, imm.x_, imm.rmode_);
380  }
381 
382  // Returns true if this Operand is a wrapper for the specified register.
383  bool is_reg(Register reg) const;
384 
385  // Returns true if this Operand is a wrapper for one register.
386  bool is_reg_only() const;
387 
388  // Asserts that this Operand is a wrapper for one register and returns the
389  // register.
390  Register reg() const;
391 
392  private:
393  // Set the ModRM byte without an encoded 'reg' register. The
394  // register is encoded later as part of the emit_operand operation.
395  inline void set_modrm(int mod, Register rm);
396 
397  inline void set_sib(ScaleFactor scale, Register index, Register base);
398  inline void set_disp8(int8_t disp);
399  inline void set_dispr(int32_t disp, RelocInfo::Mode rmode);
400 
401  byte buf_[6];
402  // The number of bytes in buf_.
403  unsigned int len_;
404  // Only valid if len_ > 4.
405  RelocInfo::Mode rmode_;
406 
407  friend class Assembler;
408  friend class MacroAssembler;
409 };
410 
411 
412 // -----------------------------------------------------------------------------
413 // A Displacement describes the 32bit immediate field of an instruction which
414 // may be used together with a Label in order to refer to a yet unknown code
415 // position. Displacements stored in the instruction stream are used to describe
416 // the instruction and to chain a list of instructions using the same Label.
417 // A Displacement contains 2 different fields:
418 //
419 // next field: position of next displacement in the chain (0 = end of list)
420 // type field: instruction type
421 //
422 // A next value of null (0) indicates the end of a chain (note that there can
423 // be no displacement at position zero, because there is always at least one
424 // instruction byte before the displacement).
425 //
426 // Displacement _data field layout
427 //
428 // |31.....2|1......0|
429 // [ next | type |
430 
431 class Displacement BASE_EMBEDDED {
432  public:
433  enum Type {
436  OTHER
437  };
438 
439  int data() const { return data_; }
440  Type type() const { return TypeField::decode(data_); }
441  void next(Label* L) const {
442  int n = NextField::decode(data_);
443  n > 0 ? L->link_to(n) : L->Unuse();
444  }
445  void link_to(Label* L) { init(L, type()); }
446 
447  explicit Displacement(int data) { data_ = data; }
448 
449  Displacement(Label* L, Type type) { init(L, type); }
450 
451  void print() {
452  PrintF("%s (%x) ", (type() == UNCONDITIONAL_JUMP ? "jmp" : "[other]"),
453  NextField::decode(data_));
454  }
455 
456  private:
457  int data_;
458 
459  class TypeField: public BitField<Type, 0, 2> {};
460  class NextField: public BitField<int, 2, 32-2> {};
461 
462  void init(Label* L, Type type);
463 };
464 
465 
466 class Assembler : public AssemblerBase {
467  private:
468  // We check before assembling an instruction that there is sufficient
469  // space to write an instruction and its relocation information.
470  // The relocation writer's position must be kGap bytes above the end of
471  // the generated instructions. This leaves enough space for the
472  // longest possible ia32 instruction, 15 bytes, and the longest possible
473  // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
474  // (There is a 15 byte limit on ia32 instruction length that rules out some
475  // otherwise valid instructions.)
476  // This allows for a single, fast space check per instruction.
477  static const int kGap = 32;
478 
479  public:
480  // Create an assembler. Instructions and relocation information are emitted
481  // into a buffer, with the instructions starting from the beginning and the
482  // relocation information starting from the end of the buffer. See CodeDesc
483  // for a detailed comment on the layout (globals.h).
484  //
485  // If the provided buffer is NULL, the assembler allocates and grows its own
486  // buffer, and buffer_size determines the initial buffer size. The buffer is
487  // owned by the assembler and deallocated upon destruction of the assembler.
488  //
489  // If the provided buffer is not NULL, the assembler uses the provided buffer
490  // for code generation and assumes its size to be buffer_size. If the buffer
491  // is too small, a fatal error occurs. No deallocation of the buffer is done
492  // upon destruction of the assembler.
493  // TODO(vitalyr): the assembler does not need an isolate.
494  Assembler(Isolate* isolate, void* buffer, int buffer_size);
495  virtual ~Assembler() { }
496 
497  // GetCode emits any pending (non-emitted) code and fills the descriptor
498  // desc. GetCode() is idempotent; it returns the same result if no other
499  // Assembler functions are invoked in between GetCode() calls.
500  void GetCode(CodeDesc* desc);
501 
502  // Read/Modify the code target in the branch/call instruction at pc.
504  ConstantPoolArray* constant_pool);
505  inline static void set_target_address_at(Address pc,
506  ConstantPoolArray* constant_pool,
507  Address target,
508  ICacheFlushMode icache_flush_mode =
510  static inline Address target_address_at(Address pc, Code* code) {
511  ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
512  return target_address_at(pc, constant_pool);
513  }
514  static inline void set_target_address_at(Address pc,
515  Code* code,
516  Address target,
517  ICacheFlushMode icache_flush_mode =
519  ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
520  set_target_address_at(pc, constant_pool, target);
521  }
522 
523  // Return the code target address at a call site from the return address
524  // of that call in the instruction stream.
526 
527  // Return the code target address of the patch debug break slot
529 
530  // This sets the branch destination (which is in the instruction on x86).
531  // This is for calls and branches within generated code.
533  Address instruction_payload, Code* code, Address target) {
534  set_target_address_at(instruction_payload, code, target);
535  }
536 
537  static const int kSpecialTargetSize = kPointerSize;
538 
539  // Distance between the address of the code target in the call instruction
540  // and the return address
542  // Distance between start of patched return sequence and the emitted address
543  // to jump to.
544  static const int kPatchReturnSequenceAddressOffset = 1; // JMP imm32.
545 
546  // Distance between start of patched debug break slot and the emitted address
547  // to jump to.
548  static const int kPatchDebugBreakSlotAddressOffset = 1; // JMP imm32.
549 
550  static const int kCallInstructionLength = 5;
552  static const int kJSReturnSequenceLength = 6;
553 
554  // The debug break slot must be able to contain a call instruction.
556 
557  // One byte opcode for test al, 0xXX.
558  static const byte kTestAlByte = 0xA8;
559  // One byte opcode for nop.
560  static const byte kNopByte = 0x90;
561 
562  // One byte opcode for a short unconditional jump.
563  static const byte kJmpShortOpcode = 0xEB;
564  // One byte prefix for a short conditional jump.
565  static const byte kJccShortPrefix = 0x70;
567  static const byte kJcShortOpcode = kJccShortPrefix | carry;
568  static const byte kJnzShortOpcode = kJccShortPrefix | not_zero;
569  static const byte kJzShortOpcode = kJccShortPrefix | zero;
570 
571 
572  // ---------------------------------------------------------------------------
573  // Code generation
574  //
575  // - function names correspond one-to-one to ia32 instruction mnemonics
576  // - unless specified otherwise, instructions operate on 32bit operands
577  // - instructions on 8bit (byte) operands/registers have a trailing '_b'
578  // - instructions on 16bit (word) operands/registers have a trailing '_w'
579  // - naming conflicts with C++ keywords are resolved via a trailing '_'
580 
581  // NOTE ON INTERFACE: Currently, the interface is not very consistent
582  // in the sense that some operations (e.g. mov()) can be called in more
583  // the one way to generate the same instruction: The Register argument
584  // can in some cases be replaced with an Operand(Register) argument.
585  // This should be cleaned up and made more orthogonal. The questions
586  // is: should we always use Operands instead of Registers where an
587  // Operand is possible, or should we have a Register (overloaded) form
588  // instead? We must be careful to make sure that the selected instruction
589  // is obvious from the parameters to avoid hard-to-find code generation
590  // bugs.
591 
592  // Insert the smallest number of nop instructions
593  // possible to align the pc offset to a multiple
594  // of m. m must be a power of 2.
595  void Align(int m);
596  void Nop(int bytes = 1);
597  // Aligns code to something that's optimal for a jump target for the platform.
599 
600  // Stack
601  void pushad();
602  void popad();
603 
604  void pushfd();
605  void popfd();
606 
607  void push(const Immediate& x);
608  void push_imm32(int32_t imm32);
609  void push(Register src);
610  void push(const Operand& src);
611 
612  void pop(Register dst);
613  void pop(const Operand& dst);
614 
615  void enter(const Immediate& size);
616  void leave();
617 
618  // Moves
619  void mov_b(Register dst, Register src) { mov_b(dst, Operand(src)); }
620  void mov_b(Register dst, const Operand& src);
621  void mov_b(Register dst, int8_t imm8) { mov_b(Operand(dst), imm8); }
622  void mov_b(const Operand& dst, int8_t imm8);
623  void mov_b(const Operand& dst, Register src);
624 
625  void mov_w(Register dst, const Operand& src);
626  void mov_w(const Operand& dst, Register src);
627  void mov_w(const Operand& dst, int16_t imm16);
628 
629  void mov(Register dst, int32_t imm32);
630  void mov(Register dst, const Immediate& x);
632  void mov(Register dst, const Operand& src);
633  void mov(Register dst, Register src);
634  void mov(const Operand& dst, const Immediate& x);
635  void mov(const Operand& dst, Handle<Object> handle);
636  void mov(const Operand& dst, Register src);
637 
638  void movsx_b(Register dst, Register src) { movsx_b(dst, Operand(src)); }
639  void movsx_b(Register dst, const Operand& src);
640 
641  void movsx_w(Register dst, Register src) { movsx_w(dst, Operand(src)); }
642  void movsx_w(Register dst, const Operand& src);
643 
644  void movzx_b(Register dst, Register src) { movzx_b(dst, Operand(src)); }
645  void movzx_b(Register dst, const Operand& src);
646 
647  void movzx_w(Register dst, Register src) { movzx_w(dst, Operand(src)); }
648  void movzx_w(Register dst, const Operand& src);
649 
650  // Conditional moves
651  void cmov(Condition cc, Register dst, Register src) {
652  cmov(cc, dst, Operand(src));
653  }
654  void cmov(Condition cc, Register dst, const Operand& src);
655 
656  // Flag management.
657  void cld();
658 
659  // Repetitive string instructions.
660  void rep_movs();
661  void rep_stos();
662  void stos();
663 
664  // Exchange
665  void xchg(Register dst, Register src);
666  void xchg(Register dst, const Operand& src);
667 
668  // Arithmetics
669  void adc(Register dst, int32_t imm32);
670  void adc(Register dst, const Operand& src);
671 
672  void add(Register dst, Register src) { add(dst, Operand(src)); }
673  void add(Register dst, const Operand& src);
674  void add(const Operand& dst, Register src);
675  void add(Register dst, const Immediate& imm) { add(Operand(dst), imm); }
676  void add(const Operand& dst, const Immediate& x);
677 
678  void and_(Register dst, int32_t imm32);
679  void and_(Register dst, const Immediate& x);
680  void and_(Register dst, Register src) { and_(dst, Operand(src)); }
681  void and_(Register dst, const Operand& src);
682  void and_(const Operand& dst, Register src);
683  void and_(const Operand& dst, const Immediate& x);
684 
685  void cmpb(Register reg, int8_t imm8) { cmpb(Operand(reg), imm8); }
686  void cmpb(const Operand& op, int8_t imm8);
687  void cmpb(Register reg, const Operand& op);
688  void cmpb(const Operand& op, Register reg);
689  void cmpb_al(const Operand& op);
690  void cmpw_ax(const Operand& op);
691  void cmpw(const Operand& op, Immediate imm16);
692  void cmp(Register reg, int32_t imm32);
694  void cmp(Register reg0, Register reg1) { cmp(reg0, Operand(reg1)); }
695  void cmp(Register reg, const Operand& op);
696  void cmp(Register reg, const Immediate& imm) { cmp(Operand(reg), imm); }
697  void cmp(const Operand& op, const Immediate& imm);
698  void cmp(const Operand& op, Handle<Object> handle);
699 
700  void dec_b(Register dst);
701  void dec_b(const Operand& dst);
702 
703  void dec(Register dst);
704  void dec(const Operand& dst);
705 
706  void cdq();
707 
708  void idiv(Register src) { idiv(Operand(src)); }
709  void idiv(const Operand& src);
710  void div(Register src) { div(Operand(src)); }
711  void div(const Operand& src);
712 
713  // Signed multiply instructions.
714  void imul(Register src); // edx:eax = eax * src.
715  void imul(Register dst, Register src) { imul(dst, Operand(src)); }
716  void imul(Register dst, const Operand& src); // dst = dst * src.
717  void imul(Register dst, Register src, int32_t imm32); // dst = src * imm32.
718  void imul(Register dst, const Operand& src, int32_t imm32);
719 
720  void inc(Register dst);
721  void inc(const Operand& dst);
722 
723  void lea(Register dst, const Operand& src);
724 
725  // Unsigned multiply instruction.
726  void mul(Register src); // edx:eax = eax * reg.
727 
728  void neg(Register dst);
729  void neg(const Operand& dst);
730 
731  void not_(Register dst);
732  void not_(const Operand& dst);
733 
734  void or_(Register dst, int32_t imm32);
735  void or_(Register dst, Register src) { or_(dst, Operand(src)); }
736  void or_(Register dst, const Operand& src);
737  void or_(const Operand& dst, Register src);
738  void or_(Register dst, const Immediate& imm) { or_(Operand(dst), imm); }
739  void or_(const Operand& dst, const Immediate& x);
740 
741  void rcl(Register dst, uint8_t imm8);
742  void rcr(Register dst, uint8_t imm8);
743  void ror(Register dst, uint8_t imm8);
744  void ror_cl(Register dst);
745 
746  void sar(Register dst, uint8_t imm8) { sar(Operand(dst), imm8); }
747  void sar(const Operand& dst, uint8_t imm8);
748  void sar_cl(Register dst) { sar_cl(Operand(dst)); }
749  void sar_cl(const Operand& dst);
750 
751  void sbb(Register dst, const Operand& src);
752 
753  void shld(Register dst, Register src) { shld(dst, Operand(src)); }
754  void shld(Register dst, const Operand& src);
755 
756  void shl(Register dst, uint8_t imm8) { shl(Operand(dst), imm8); }
757  void shl(const Operand& dst, uint8_t imm8);
758  void shl_cl(Register dst) { shl_cl(Operand(dst)); }
759  void shl_cl(const Operand& dst);
760 
761  void shrd(Register dst, Register src) { shrd(dst, Operand(src)); }
762  void shrd(Register dst, const Operand& src);
763 
764  void shr(Register dst, uint8_t imm8) { shr(Operand(dst), imm8); }
765  void shr(const Operand& dst, uint8_t imm8);
766  void shr_cl(Register dst) { shr_cl(Operand(dst)); }
767  void shr_cl(const Operand& dst);
768 
769  void sub(Register dst, const Immediate& imm) { sub(Operand(dst), imm); }
770  void sub(const Operand& dst, const Immediate& x);
771  void sub(Register dst, Register src) { sub(dst, Operand(src)); }
772  void sub(Register dst, const Operand& src);
773  void sub(const Operand& dst, Register src);
774 
775  void test(Register reg, const Immediate& imm);
776  void test(Register reg0, Register reg1) { test(reg0, Operand(reg1)); }
777  void test(Register reg, const Operand& op);
778  void test_b(Register reg, const Operand& op);
779  void test(const Operand& op, const Immediate& imm);
780  void test_b(Register reg, uint8_t imm8);
781  void test_b(const Operand& op, uint8_t imm8);
782 
783  void xor_(Register dst, int32_t imm32);
784  void xor_(Register dst, Register src) { xor_(dst, Operand(src)); }
785  void xor_(Register dst, const Operand& src);
786  void xor_(const Operand& dst, Register src);
787  void xor_(Register dst, const Immediate& imm) { xor_(Operand(dst), imm); }
788  void xor_(const Operand& dst, const Immediate& x);
789 
790  // Bit operations.
791  void bt(const Operand& dst, Register src);
792  void bts(Register dst, Register src) { bts(Operand(dst), src); }
793  void bts(const Operand& dst, Register src);
794  void bsr(Register dst, Register src) { bsr(dst, Operand(src)); }
795  void bsr(Register dst, const Operand& src);
796 
797  // Miscellaneous
798  void hlt();
799  void int3();
800  void nop();
801  void ret(int imm16);
802 
803  // Label operations & relative jumps (PPUM Appendix D)
804  //
805  // Takes a branch opcode (cc) and a label (L) and generates
806  // either a backward branch or a forward branch and links it
807  // to the label fixup chain. Usage:
808  //
809  // Label L; // unbound label
810  // j(cc, &L); // forward branch to unbound label
811  // bind(&L); // bind label to the current pc
812  // j(cc, &L); // backward branch to bound label
813  // bind(&L); // illegal: a label may be bound only once
814  //
815  // Note: The same Label can be used for forward and backward branches
816  // but it may be bound only once.
817 
818  void bind(Label* L); // binds an unbound label L to the current code position
819 
820  // Calls
821  void call(Label* L);
822  void call(byte* entry, RelocInfo::Mode rmode);
823  int CallSize(const Operand& adr);
824  void call(Register reg) { call(Operand(reg)); }
825  void call(const Operand& adr);
827  void call(Handle<Code> code,
828  RelocInfo::Mode rmode,
830 
831  // Jumps
832  // unconditional jump to L
833  void jmp(Label* L, Label::Distance distance = Label::kFar);
834  void jmp(byte* entry, RelocInfo::Mode rmode);
835  void jmp(Register reg) { jmp(Operand(reg)); }
836  void jmp(const Operand& adr);
837  void jmp(Handle<Code> code, RelocInfo::Mode rmode);
838 
839  // Conditional jumps
840  void j(Condition cc,
841  Label* L,
842  Label::Distance distance = Label::kFar);
843  void j(Condition cc, byte* entry, RelocInfo::Mode rmode);
844  void j(Condition cc, Handle<Code> code);
845 
846  // Floating-point operations
847  void fld(int i);
848  void fstp(int i);
849 
850  void fld1();
851  void fldz();
852  void fldpi();
853  void fldln2();
854 
855  void fld_s(const Operand& adr);
856  void fld_d(const Operand& adr);
857 
858  void fstp_s(const Operand& adr);
859  void fst_s(const Operand& adr);
860  void fstp_d(const Operand& adr);
861  void fst_d(const Operand& adr);
862 
863  void fild_s(const Operand& adr);
864  void fild_d(const Operand& adr);
865 
866  void fist_s(const Operand& adr);
867 
868  void fistp_s(const Operand& adr);
869  void fistp_d(const Operand& adr);
870 
871  // The fisttp instructions require SSE3.
872  void fisttp_s(const Operand& adr);
873  void fisttp_d(const Operand& adr);
874 
875  void fabs();
876  void fchs();
877  void fcos();
878  void fsin();
879  void fptan();
880  void fyl2x();
881  void f2xm1();
882  void fscale();
883  void fninit();
884 
885  void fadd(int i);
886  void fadd_i(int i);
887  void fsub(int i);
888  void fsub_i(int i);
889  void fmul(int i);
890  void fmul_i(int i);
891  void fdiv(int i);
892  void fdiv_i(int i);
893 
894  void fisub_s(const Operand& adr);
895 
896  void faddp(int i = 1);
897  void fsubp(int i = 1);
898  void fsubrp(int i = 1);
899  void fmulp(int i = 1);
900  void fdivp(int i = 1);
901  void fprem();
902  void fprem1();
903 
904  void fxch(int i = 1);
905  void fincstp();
906  void ffree(int i = 0);
907 
908  void ftst();
909  void fucomp(int i);
910  void fucompp();
911  void fucomi(int i);
912  void fucomip();
913  void fcompp();
914  void fnstsw_ax();
915  void fwait();
916  void fnclex();
917 
918  void frndint();
919 
920  void sahf();
922 
923  void cpuid();
924 
925  // SSE instructions
927  void shufps(XMMRegister dst, XMMRegister src, byte imm8);
928 
929  void andps(XMMRegister dst, const Operand& src);
930  void andps(XMMRegister dst, XMMRegister src) { andps(dst, Operand(src)); }
931  void xorps(XMMRegister dst, const Operand& src);
932  void xorps(XMMRegister dst, XMMRegister src) { xorps(dst, Operand(src)); }
933  void orps(XMMRegister dst, const Operand& src);
934  void orps(XMMRegister dst, XMMRegister src) { orps(dst, Operand(src)); }
935 
936  void addps(XMMRegister dst, const Operand& src);
937  void addps(XMMRegister dst, XMMRegister src) { addps(dst, Operand(src)); }
938  void subps(XMMRegister dst, const Operand& src);
939  void subps(XMMRegister dst, XMMRegister src) { subps(dst, Operand(src)); }
940  void mulps(XMMRegister dst, const Operand& src);
941  void mulps(XMMRegister dst, XMMRegister src) { mulps(dst, Operand(src)); }
942  void divps(XMMRegister dst, const Operand& src);
943  void divps(XMMRegister dst, XMMRegister src) { divps(dst, Operand(src)); }
944 
945  // SSE2 instructions
946  void cvttss2si(Register dst, const Operand& src);
947  void cvttss2si(Register dst, XMMRegister src) {
948  cvttss2si(dst, Operand(src));
949  }
950  void cvttsd2si(Register dst, const Operand& src);
951  void cvttsd2si(Register dst, XMMRegister src) {
952  cvttsd2si(dst, Operand(src));
953  }
954  void cvtsd2si(Register dst, XMMRegister src);
955 
956  void cvtsi2sd(XMMRegister dst, Register src) { cvtsi2sd(dst, Operand(src)); }
957  void cvtsi2sd(XMMRegister dst, const Operand& src);
960 
961  void addsd(XMMRegister dst, XMMRegister src);
962  void addsd(XMMRegister dst, const Operand& src);
963  void subsd(XMMRegister dst, XMMRegister src);
964  void subsd(XMMRegister dst, const Operand& src);
965  void mulsd(XMMRegister dst, XMMRegister src);
966  void mulsd(XMMRegister dst, const Operand& src);
967  void divsd(XMMRegister dst, XMMRegister src);
968  void xorpd(XMMRegister dst, XMMRegister src);
970  void sqrtsd(XMMRegister dst, const Operand& src);
971 
972  void andpd(XMMRegister dst, XMMRegister src);
973  void orpd(XMMRegister dst, XMMRegister src);
974 
975  void ucomisd(XMMRegister dst, XMMRegister src) { ucomisd(dst, Operand(src)); }
976  void ucomisd(XMMRegister dst, const Operand& src);
977 
980  kRoundDown = 0x1,
981  kRoundUp = 0x2,
982  kRoundToZero = 0x3
983  };
984 
986 
987  void movmskpd(Register dst, XMMRegister src);
988  void movmskps(Register dst, XMMRegister src);
989 
992 
993  void movdqa(XMMRegister dst, const Operand& src);
994  void movdqa(const Operand& dst, XMMRegister src);
995  void movdqu(XMMRegister dst, const Operand& src);
996  void movdqu(const Operand& dst, XMMRegister src);
997  void movdq(bool aligned, XMMRegister dst, const Operand& src) {
998  if (aligned) {
999  movdqa(dst, src);
1000  } else {
1001  movdqu(dst, src);
1002  }
1003  }
1004 
1005  void movd(XMMRegister dst, Register src) { movd(dst, Operand(src)); }
1006  void movd(XMMRegister dst, const Operand& src);
1007  void movd(Register dst, XMMRegister src) { movd(Operand(dst), src); }
1008  void movd(const Operand& dst, XMMRegister src);
1009  void movsd(XMMRegister dst, XMMRegister src) { movsd(dst, Operand(src)); }
1010  void movsd(XMMRegister dst, const Operand& src);
1011  void movsd(const Operand& dst, XMMRegister src);
1012 
1013 
1014  void movss(XMMRegister dst, const Operand& src);
1015  void movss(const Operand& dst, XMMRegister src);
1016  void movss(XMMRegister dst, XMMRegister src) { movss(dst, Operand(src)); }
1017  void extractps(Register dst, XMMRegister src, byte imm8);
1018 
1019  void pand(XMMRegister dst, XMMRegister src);
1020  void pxor(XMMRegister dst, XMMRegister src);
1021  void por(XMMRegister dst, XMMRegister src);
1023 
1024  void psllq(XMMRegister reg, int8_t shift);
1026  void psrlq(XMMRegister reg, int8_t shift);
1028  void pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle);
1029  void pextrd(Register dst, XMMRegister src, int8_t offset) {
1030  pextrd(Operand(dst), src, offset);
1031  }
1032  void pextrd(const Operand& dst, XMMRegister src, int8_t offset);
1033  void pinsrd(XMMRegister dst, Register src, int8_t offset) {
1034  pinsrd(dst, Operand(src), offset);
1035  }
1036  void pinsrd(XMMRegister dst, const Operand& src, int8_t offset);
1037 
1038  // Parallel XMM operations.
1039  void movntdqa(XMMRegister dst, const Operand& src);
1040  void movntdq(const Operand& dst, XMMRegister src);
1041  // Prefetch src position into cache level.
1042  // Level 1, 2 or 3 specifies CPU cache level. Level 0 specifies a
1043  // non-temporal
1044  void prefetch(const Operand& src, int level);
1045  // TODO(lrn): Need SFENCE for movnt?
1046 
1047  // Check the code size generated from label to here.
1048  int SizeOfCodeGeneratedSince(Label* label) {
1049  return pc_offset() - label->pos();
1050  }
1051 
1052  // Mark address of the ExitJSFrame code.
1054 
1055  // Mark address of a debug break slot.
1057 
1058  // Record a comment relocation entry that can be used by a disassembler.
1059  // Use --code-comments to enable, or provide "force = true" flag to always
1060  // write a comment.
1061  void RecordComment(const char* msg, bool force = false);
1062 
1063  // Writes a single byte or word of data in the code stream. Used for
1064  // inline tables, e.g., jump-tables.
1065  void db(uint8_t data);
1066  void dd(uint32_t data);
1067 
1068  // Check if there is less than kGap bytes available in the buffer.
1069  // If this is the case, we need to grow the buffer before emitting
1070  // an instruction or relocation information.
1071  inline bool buffer_overflow() const {
1072  return pc_ >= reloc_info_writer.pos() - kGap;
1073  }
1074 
1075  // Get the number of bytes available in the buffer.
1076  inline int available_space() const { return reloc_info_writer.pos() - pc_; }
1077 
1078  static bool IsNop(Address addr);
1079 
1081 
1083  return (buffer_ + buffer_size_) - reloc_info_writer.pos();
1084  }
1085 
1086  // Avoid overflows for displacements etc.
1087  static const int kMaximalBufferSize = 512*MB;
1088 
1089  byte byte_at(int pos) { return buffer_[pos]; }
1090  void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
1091 
1092  // Allocate a constant pool of the correct size for the generated code.
1094 
1095  // Generate the constant pool for the generated code.
1097 
1098  protected:
1103 
1104  byte* addr_at(int pos) { return buffer_ + pos; }
1105 
1106 
1107  private:
1108  uint32_t long_at(int pos) {
1109  return *reinterpret_cast<uint32_t*>(addr_at(pos));
1110  }
1111  void long_at_put(int pos, uint32_t x) {
1112  *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
1113  }
1114 
1115  // code emission
1116  void GrowBuffer();
1117  inline void emit(uint32_t x);
1118  inline void emit(Handle<Object> handle);
1119  inline void emit(uint32_t x,
1120  RelocInfo::Mode rmode,
1122  inline void emit(Handle<Code> code,
1123  RelocInfo::Mode rmode,
1125  inline void emit(const Immediate& x);
1126  inline void emit_w(const Immediate& x);
1127 
1128  // Emit the code-object-relative offset of the label's position
1129  inline void emit_code_relative_offset(Label* label);
1130 
1131  // instruction generation
1132  void emit_arith_b(int op1, int op2, Register dst, int imm8);
1133 
1134  // Emit a basic arithmetic instruction (i.e. first byte of the family is 0x81)
1135  // with a given destination expression and an immediate operand. It attempts
1136  // to use the shortest encoding possible.
1137  // sel specifies the /n in the modrm byte (see the Intel PRM).
1138  void emit_arith(int sel, Operand dst, const Immediate& x);
1139 
1140  void emit_operand(Register reg, const Operand& adr);
1141 
1142  void emit_farith(int b1, int b2, int i);
1143 
1144  // labels
1145  void print(Label* L);
1146  void bind_to(Label* L, int pos);
1147 
1148  // displacements
1149  inline Displacement disp_at(Label* L);
1150  inline void disp_at_put(Label* L, Displacement disp);
1151  inline void emit_disp(Label* L, Displacement::Type type);
1152  inline void emit_near_disp(Label* L);
1153 
1154  // record reloc info for current pc_
1155  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1156 
1157  friend class CodePatcher;
1158  friend class EnsureSpace;
1159 
1160  // code generation
1161  RelocInfoWriter reloc_info_writer;
1162 
1164  friend class PositionsRecorder;
1165 };
1166 
1167 
1168 // Helper class that ensures that there is enough space for generating
1169 // instructions and relocation information. The constructor makes
1170 // sure that there is enough space and (in debug mode) the destructor
1171 // checks that we did not generate too much.
1172 class EnsureSpace BASE_EMBEDDED {
1173  public:
1174  explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
1175  if (assembler_->buffer_overflow()) assembler_->GrowBuffer();
1176 #ifdef DEBUG
1177  space_before_ = assembler_->available_space();
1178 #endif
1179  }
1180 
1181 #ifdef DEBUG
1182  ~EnsureSpace() {
1183  int bytes_generated = space_before_ - assembler_->available_space();
1184  DCHECK(bytes_generated < assembler_->kGap);
1185  }
1186 #endif
1187 
1188  private:
1189  Assembler* assembler_;
1190 #ifdef DEBUG
1191  int space_before_;
1192 #endif
1193 };
1194 
1195 } } // namespace v8::internal
1196 
1197 #endif // V8_IA32_ASSEMBLER_IA32_H_
#define BASE_EMBEDDED
Definition: allocation.h:45
Isolate * isolate() const
Definition: assembler.h:62
static const int kSpecialTargetSize
void bind_to(Label *L, int pos)
void neg(Register dst)
static Address target_address_at(Address pc, Code *code)
void sar_cl(const Operand &dst)
void movsx_w(Register dst, const Operand &src)
void cmp(const Operand &op, const Immediate &imm)
void cmov(Condition cc, Register dst, Register src)
static const int kCallInstructionLength
void pxor(XMMRegister dst, XMMRegister src)
int CallSize(const Operand &adr)
RelocInfoWriter reloc_info_writer
void shufps(XMMRegister dst, XMMRegister src, byte imm8)
void cvttsd2si(Register dst, const Operand &src)
void shrd(Register dst, Register src)
void subsd(XMMRegister dst, XMMRegister src)
void emit_sse_operand(XMMRegister dst, XMMRegister src)
void and_(const Operand &dst, const Immediate &x)
void j(Condition cc, Handle< Code > code)
void fst_s(const Operand &adr)
void Nop(int bytes=1)
void div(const Operand &src)
void shld(Register dst, const Operand &src)
void adc(Register dst, int32_t imm32)
void cvttss2si(Register dst, XMMRegister src)
void cmpb(const Operand &op, int8_t imm8)
void emit_w(const Immediate &x)
void or_(Register dst, Register src)
void sub(Register dst, Register src)
Instruction * pc() const
void sub(const Operand &dst, Register src)
void subps(XMMRegister dst, const Operand &src)
void shr_cl(const Operand &dst)
void movdqu(XMMRegister dst, const Operand &src)
void mov(Register dst, Handle< Object > handle)
void test_b(Register reg, uint8_t imm8)
void ror_cl(Register dst)
void imul(Register dst, const Operand &src)
void rcr(Register dst, uint8_t imm8)
void j(Condition cc, byte *entry, RelocInfo::Mode rmode)
void and_(Register dst, const Immediate &x)
void fst_d(const Operand &adr)
void sub(Register dst, const Immediate &imm)
static const byte kJnzShortOpcode
void movsd(const Operand &dst, XMMRegister src)
void sqrtsd(XMMRegister dst, const Operand &src)
void cmov(Condition cc, Register dst, const Operand &src)
static Address target_address_at(Address pc, ConstantPoolArray *constant_pool)
void enter(const Immediate &size)
static void set_target_address_at(Address pc, ConstantPoolArray *constant_pool, Address target, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
void fisttp_d(const Operand &adr)
void emit_sse_operand(XMMRegister dst, Register src)
void add(Register dst, const Operand &src)
void not_(Register dst)
void sar(Register dst, uint8_t imm8)
void adc(Register dst, const Operand &src)
void jmp(const Operand &adr)
static void deserialization_set_special_target_at(Address instruction_payload, Code *code, Address target)
void movdqa(XMMRegister dst, const Operand &src)
static const byte kNopByte
void ucomisd(XMMRegister dst, XMMRegister src)
void imul(Register dst, Register src, int32_t imm32)
void pinsrd(XMMRegister dst, Register src, int8_t offset)
void RecordComment(const char *msg, bool force=false)
void xor_(const Operand &dst, const Immediate &x)
void sqrtsd(XMMRegister dst, XMMRegister src)
void orpd(XMMRegister dst, XMMRegister src)
void disp_at_put(Label *L, Displacement disp)
void movmskps(Register dst, XMMRegister src)
void fild_s(const Operand &adr)
void emit_code_relative_offset(Label *label)
static const byte kJmpShortOpcode
void andps(XMMRegister dst, const Operand &src)
void div(Register src)
void mov_b(Register dst, int8_t imm8)
void addsd(XMMRegister dst, XMMRegister src)
void cmpw_ax(const Operand &op)
void j(Condition cc, Label *L, Label::Distance distance=Label::kFar)
void sar(const Operand &dst, uint8_t imm8)
void mulsd(XMMRegister dst, const Operand &src)
void mul(Register src)
void pop(const Operand &dst)
void movd(XMMRegister dst, Register src)
void sbb(Register dst, const Operand &src)
void emit_disp(Label *L, Displacement::Type type)
void movss(const Operand &dst, XMMRegister src)
void idiv(Register src)
void GetCode(CodeDesc *desc)
void test_b(Register reg, const Operand &op)
void add(const Operand &dst, Register src)
void ror(Register dst, uint8_t imm8)
void jmp(Handle< Code > code, RelocInfo::Mode rmode)
void db(uint8_t data)
void or_(const Operand &dst, const Immediate &x)
static const int kPatchDebugBreakSlotAddressOffset
void lea(Register dst, const Operand &src)
void and_(Register dst, int32_t imm32)
void xorpd(XMMRegister dst, XMMRegister src)
void jmp(Register reg)
static const byte kJccShortPrefix
void emit_sse_operand(XMMRegister reg, const Operand &adr)
void dec(Register dst)
void long_at_put(int pos, uint32_t x)
void xorps(XMMRegister dst, XMMRegister src)
void shr(Register dst, uint8_t imm8)
void ucomisd(XMMRegister dst, const Operand &src)
void add(Register dst, const Immediate &imm)
void shl_cl(Register dst)
static const int kPatchDebugBreakSlotReturnOffset
void and_(const Operand &dst, Register src)
void or_(Register dst, const Operand &src)
static void set_target_address_at(Address pc, Code *code, Address target, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
void cmp(const Operand &op, Handle< Object > handle)
void print(Label *L)
static const int kGap
void movntdq(const Operand &dst, XMMRegister src)
void dec_b(const Operand &dst)
void pop(Register dst)
void movsd(XMMRegister dst, const Operand &src)
Displacement disp_at(Label *L)
void psllq(XMMRegister dst, XMMRegister src)
void divsd(XMMRegister dst, XMMRegister src)
void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data=0)
void shl(const Operand &dst, uint8_t imm8)
void shr(const Operand &dst, uint8_t imm8)
void psllq(XMMRegister reg, int8_t shift)
void shl(Register dst, uint8_t imm8)
void mov_b(Register dst, const Operand &src)
void shift(Register dst, Immediate shift_amount, int subcode, int size)
void cvttss2si(Register dst, const Operand &src)
void setcc(Condition cc, Register reg)
void cmpw(const Operand &op, Immediate imm16)
void fld_d(const Operand &adr)
static const int kMaximalBufferSize
static Address break_address_from_return_address(Address pc)
void movsx_b(Register dst, const Operand &src)
void add(Register dst, Register src)
void mov(Register dst, const Operand &src)
void psrlq(XMMRegister reg, int8_t shift)
void mov_b(Register dst, Register src)
void test(const Operand &op, const Immediate &imm)
void movdq(bool aligned, XMMRegister dst, const Operand &src)
void movss(XMMRegister dst, XMMRegister src)
void fld_s(const Operand &adr)
void inc(Register dst)
void fist_s(const Operand &adr)
uint32_t long_at(int pos)
void push(Register src)
void fisttp_s(const Operand &adr)
void call(Register reg)
void or_(Register dst, int32_t imm32)
void pinsrd(XMMRegister dst, const Operand &src, int8_t offset)
void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode)
void test(Register reg, const Immediate &imm)
void movzx_w(Register dst, Register src)
void cmpb(Register reg, int8_t imm8)
void mov(const Operand &dst, const Immediate &x)
void cmp(Register reg, int32_t imm32)
Handle< ConstantPoolArray > NewConstantPool(Isolate *isolate)
void jmp(byte *entry, RelocInfo::Mode rmode)
void movzx_b(Register dst, Register src)
void mov(Register dst, const Immediate &x)
void xor_(Register dst, int32_t imm32)
void fistp_d(const Operand &adr)
void sub(const Operand &dst, const Immediate &x)
void pcmpeqd(XMMRegister dst, XMMRegister src)
void cmpltsd(XMMRegister dst, XMMRegister src)
void cmp(Register reg, Handle< Object > handle)
void movntdqa(XMMRegister dst, const Operand &src)
void subsd(XMMRegister dst, const Operand &src)
void call(byte *entry, RelocInfo::Mode rmode)
void fstp_d(const Operand &adr)
void mov_b(const Operand &dst, int8_t imm8)
void extractps(Register dst, XMMRegister src, byte imm8)
void andps(XMMRegister dst, XMMRegister src)
void cmp(Register reg, const Immediate &imm)
void adr(const Register &rd, Label *label)
void imul(Register dst, Register src)
void movsd(XMMRegister dst, XMMRegister src)
friend class PositionsRecorder
void and_(Register dst, Register src)
void movaps(XMMRegister dst, XMMRegister src)
void emit_operand(Register reg, const Operand &adr)
void test_b(const Operand &op, uint8_t imm8)
void cvtsi2sd(XMMRegister dst, Register src)
void jmp(Label *L, Label::Distance distance=Label::kFar)
void test(Register reg, const Operand &op)
void movd(const Operand &dst, XMMRegister src)
void emit_sse_operand(Register dst, XMMRegister src)
static Address target_address_at(Address pc, ConstantPoolArray *constant_pool)
void movsx_w(Register dst, Register src)
void divps(XMMRegister dst, const Operand &src)
void sub(Register dst, const Operand &src)
void xchg(Register dst, Register src)
void cvttsd2si(Register dst, XMMRegister src)
void psrlq(XMMRegister dst, XMMRegister src)
void movdqa(const Operand &dst, XMMRegister src)
void por(XMMRegister dst, XMMRegister src)
static void set_target_address_at(Address pc, ConstantPoolArray *constant_pool, Address target, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
void shld(Register dst, Register src)
void ret(int imm16)
void movss(XMMRegister dst, const Operand &src)
void divps(XMMRegister dst, XMMRegister src)
void addsd(XMMRegister dst, const Operand &src)
void test(Register reg0, Register reg1)
void movd(XMMRegister dst, const Operand &src)
void fisub_s(const Operand &adr)
static bool IsNop(Address addr)
void ptest(XMMRegister dst, XMMRegister src)
void cvtsd2si(Register dst, XMMRegister src)
static const int kJSReturnSequenceLength
void mov_w(const Operand &dst, int16_t imm16)
void cmpb_al(const Operand &op)
void call(const Operand &adr)
void bsr(Register dst, const Operand &src)
void inc(const Operand &dst)
static const int kDebugBreakSlotLength
static const byte kJncShortOpcode
void mov(const Operand &dst, Handle< Object > handle)
void and_(Register dst, const Operand &src)
void andpd(XMMRegister dst, XMMRegister src)
void xchg(Register dst, const Operand &src)
void sel(SecondaryField fmt, FPURegister fd, FPURegister ft, FPURegister fs, uint8_t sel)
void pextrd(const Operand &dst, XMMRegister src, int8_t offset)
void emit_farith(int b1, int b2, int i)
void shr_cl(Register dst)
void set_byte_at(int pos, byte value)
void bts(const Operand &dst, Register src)
static const byte kTestAlByte
void or_(Register dst, const Immediate &imm)
void mulsd(XMMRegister dst, XMMRegister src)
void push(const Immediate &x)
void xor_(const Operand &dst, Register src)
void mov_w(const Operand &dst, Register src)
void rcl(Register dst, uint8_t imm8)
void cmpb(const Operand &op, Register reg)
void emit_arith_b(int op1, int op2, Register dst, int imm8)
int CallSize(Handle< Code > code, RelocInfo::Mode mode)
void orps(XMMRegister dst, XMMRegister src)
void movzx_w(Register dst, const Operand &src)
void mulps(XMMRegister dst, XMMRegister src)
void movdqu(const Operand &dst, XMMRegister src)
void fstp_s(const Operand &adr)
void mulps(XMMRegister dst, const Operand &src)
static const int kCallTargetAddressOffset
void call(Handle< Code > code, RelocInfo::Mode rmode, TypeFeedbackId id=TypeFeedbackId::None())
static const int kPatchReturnSequenceAddressOffset
void fistp_s(const Operand &adr)
void bt(const Operand &dst, Register src)
void mov_b(const Operand &dst, Register src)
void cmpb(Register reg, const Operand &op)
void bsr(Register dst, Register src)
void shrd(Register dst, const Operand &src)
void prefetch(const Operand &src, int level)
void neg(const Operand &dst)
void xor_(Register dst, const Immediate &imm)
void idiv(const Operand &src)
void movsx_b(Register dst, Register src)
void cmp(Register reg0, Register reg1)
void movmskpd(Register dst, XMMRegister src)
void bts(Register dst, Register src)
void movd(Register dst, XMMRegister src)
void sar_cl(Register dst)
void cvtsd2ss(XMMRegister dst, XMMRegister src)
void push_imm32(int32_t imm32)
void dd(uint32_t data)
static const byte kJcShortOpcode
void mov(const Operand &dst, Register src)
void xor_(Register dst, const Operand &src)
void addps(XMMRegister dst, XMMRegister src)
void imul(Register src)
void pshufd(XMMRegister dst, XMMRegister src, uint8_t shuffle)
void xor_(Register dst, Register src)
void subps(XMMRegister dst, XMMRegister src)
void dec(const Operand &dst)
void fild_d(const Operand &adr)
void cmp(Register reg, const Operand &op)
void imul(Register dst, const Operand &src, int32_t imm32)
void pand(XMMRegister dst, XMMRegister src)
void movzx_b(Register dst, const Operand &src)
PositionsRecorder positions_recorder_
Assembler(Isolate *isolate, void *buffer, int buffer_size)
void mov(Register dst, int32_t imm32)
void add(const Operand &dst, const Immediate &x)
PositionsRecorder * positions_recorder()
void mov(Register dst, Register src)
static Address target_address_from_return_address(Address pc)
void or_(const Operand &dst, Register src)
void mov_w(Register dst, const Operand &src)
void addps(XMMRegister dst, const Operand &src)
int SizeOfCodeGeneratedSince(Label *label)
void not_(const Operand &dst)
void xorps(XMMRegister dst, const Operand &src)
void shl_cl(const Operand &dst)
void pextrd(Register dst, XMMRegister src, int8_t offset)
void emit_arith(int sel, Operand dst, const Immediate &x)
void cvtsi2sd(XMMRegister dst, const Operand &src)
static const byte kJzShortOpcode
void PopulateConstantPool(ConstantPoolArray *constant_pool)
void cvtss2sd(XMMRegister dst, XMMRegister src)
void dec_b(Register dst)
void push(const Operand &src)
void orps(XMMRegister dst, const Operand &src)
Displacement(Label *L, Type type)
Operand(Register base, int32_t disp, RelocInfo::Mode rmode=RelocInfo::NONE32)
static Operand ForCell(Handle< Cell > cell)
void set_modrm(int mod, Register rm)
static Operand ForRegisterPlusImmediate(Register base, Immediate imm)
INLINE(explicit Operand(Register reg))
INLINE(explicit Operand(XMMRegister xmm_reg))
INLINE(explicit Operand(Immediate imm))
void set_sib(ScaleFactor scale, Register index, Register base)
void set_disp8(int8_t disp)
INLINE(explicit Operand(int32_t disp, RelocInfo::Mode rmode))
EnsureSpace(Assembler *assembler)
bool is_reg(Register reg) const
static Operand StaticVariable(const ExternalReference &ext)
void set_dispr(int32_t disp, RelocInfo::Mode rmode)
Operand(Register index, ScaleFactor scale, int32_t disp, RelocInfo::Mode rmode=RelocInfo::NONE32)
void next(Label *L) const
Operand(Register base, Register index, ScaleFactor scale, int32_t disp, RelocInfo::Mode rmode=RelocInfo::NONE32)
void init(Label *L, Type type)
static Operand StaticArray(Register index, ScaleFactor scale, const ExternalReference &arr)
Immediate(const ExternalReference &ext)
static Immediate CodeRelativeOffset(Label *label)
Immediate(Handle< Object > handle)
ConstantPoolArray * constant_pool()
Definition: objects-inl.h:4942
Immediate(Handle< T > handle)
Operand(Register reg, Shift shift=LSL, unsigned shift_amount=0)
static bool IsNone(Mode mode)
Definition: assembler.h:439
static TypeFeedbackId None()
Definition: utils.h:945
enable harmony numeric enable harmony object literal extensions Optimize object size
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be aligned(ARM64 only)") DEFINE_STRING(expose_gc_as
#define DCHECK(condition)
Definition: logging.h:205
signed short int16_t
Definition: unicode.cc:22
int int32_t
Definition: unicode.cc:24
const XMMRegister xmm6
const int kPointerSize
Definition: globals.h:129
const Register edx
const Register edi
const int kRegister_ebx_Code
const int kRegister_ecx_Code
const int kRegister_edx_Code
Condition CommuteCondition(Condition cond)
Definition: constants-arm.h:93
const XMMRegister xmm1
const Register esp
TypeImpl< ZoneTypeConfig > Type
const int kRegister_esi_Code
const XMMRegister xmm2
const int kRegister_edi_Code
DwVfpRegister DoubleRegister
const int kRegister_esp_Code
const XMMRegister xmm3
Handle< T > handle(T *t, Isolate *isolate)
Definition: handles.h:146
const Register esi
const Register eax
const Register ebx
const XMMRegister xmm0
Condition NegateCondition(Condition cond)
Definition: constants-arm.h:86
const XMMRegister no_xmm_reg
const int kRegister_ebp_Code
const XMMRegister xmm7
byte * Address
Definition: globals.h:101
void PrintF(const char *format,...)
Definition: utils.cc:80
const XMMRegister xmm4
const Register no_reg
@ FLUSH_ICACHE_IF_NEEDED
Definition: assembler.h:293
const Register ebp
const int MB
Definition: globals.h:107
const int kRegister_no_reg_Code
Definition: assembler-arm.h:75
const XMMRegister xmm5
const int kRegister_eax_Code
const Register ecx
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
static const int kNumRegisters
Definition: assembler-arm.h:95
static int NumAllocatableRegisters()
static Register from_code(int code)
static int ToAllocationIndex(Register reg)
static Register FromAllocationIndex(int index)
bool is(Register reg) const
static const char * AllocationIndexToString(int index)
static int ToAllocationIndex(Register reg)
bool is_byte_register() const
static const char * AllocationIndexToString(int index)
static const int kMaxNumAllocatableRegisters
Definition: assembler-arm.h:96
static Register FromAllocationIndex(int index)
static XMMRegister FromAllocationIndex(int index)
static const int kMaxNumRegisters
static XMMRegister from_code(int code)
static const int kMaxNumAllocatableRegisters
static int NumAllocatableRegisters()
static int ToAllocationIndex(XMMRegister reg)
static const char * AllocationIndexToString(int index)
bool is(XMMRegister reg) const
static int NumAllocatableAliasedRegisters()