v8  3.11.10(node0.8.26)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
assembler-x64.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 2012 the V8 project authors. All rights reserved.
34 
35 // A lightweight X64 Assembler.
36 
37 #ifndef V8_X64_ASSEMBLER_X64_H_
38 #define V8_X64_ASSEMBLER_X64_H_
39 
40 #include "serialize.h"
41 
42 namespace v8 {
43 namespace internal {
44 
45 // Utility functions
46 
47 // Test whether a 64-bit value is in a specific range.
48 inline bool is_uint32(int64_t x) {
49  static const uint64_t kMaxUInt32 = V8_UINT64_C(0xffffffff);
50  return static_cast<uint64_t>(x) <= kMaxUInt32;
51 }
52 
53 inline bool is_int32(int64_t x) {
54  static const int64_t kMinInt32 = -V8_INT64_C(0x80000000);
55  return is_uint32(x - kMinInt32);
56 }
57 
58 inline bool uint_is_int32(uint64_t x) {
59  static const uint64_t kMaxInt32 = V8_UINT64_C(0x7fffffff);
60  return x <= kMaxInt32;
61 }
62 
63 inline bool is_uint32(uint64_t x) {
64  static const uint64_t kMaxUInt32 = V8_UINT64_C(0xffffffff);
65  return x <= kMaxUInt32;
66 }
67 
68 // CPU Registers.
69 //
70 // 1) We would prefer to use an enum, but enum values are assignment-
71 // compatible with int, which has caused code-generation bugs.
72 //
73 // 2) We would prefer to use a class instead of a struct but we don't like
74 // the register initialization to depend on the particular initialization
75 // order (which appears to be different on OS X, Linux, and Windows for the
76 // installed versions of C++ we tried). Using a struct permits C-style
77 // "initialization". Also, the Register objects cannot be const as this
78 // forces initialization stubs in MSVC, making us dependent on initialization
79 // order.
80 //
81 // 3) By not using an enum, we are possibly preventing the compiler from
82 // doing certain constant folds, which may significantly reduce the
83 // code generated for some assembly instructions (because they boil down
84 // to a few constants). If this is a problem, we could change the code
85 // such that we use an enum in optimized mode, and the struct in debug
86 // mode. This way we get the compile-time error checking in debug mode
87 // and best performance in optimized code.
88 //
89 
90 struct Register {
91  // The non-allocatable registers are:
92  // rsp - stack pointer
93  // rbp - frame pointer
94  // rsi - context register
95  // r10 - fixed scratch register
96  // r12 - smi constant register
97  // r13 - root register
98  static const int kNumRegisters = 16;
99  static const int kNumAllocatableRegisters = 10;
100 
101  static int ToAllocationIndex(Register reg) {
102  return kAllocationIndexByRegisterCode[reg.code()];
103  }
104 
105  static Register FromAllocationIndex(int index) {
106  ASSERT(index >= 0 && index < kNumAllocatableRegisters);
107  Register result = { kRegisterCodeByAllocationIndex[index] };
108  return result;
109  }
110 
111  static const char* AllocationIndexToString(int index) {
112  ASSERT(index >= 0 && index < kNumAllocatableRegisters);
113  const char* const names[] = {
114  "rax",
115  "rbx",
116  "rdx",
117  "rcx",
118  "rdi",
119  "r8",
120  "r9",
121  "r11",
122  "r14",
123  "r15"
124  };
125  return names[index];
126  }
127 
128  static Register from_code(int code) {
129  Register r = { code };
130  return r;
131  }
132  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
133  bool is(Register reg) const { return code_ == reg.code_; }
134  // rax, rbx, rcx and rdx are byte registers, the rest are not.
135  bool is_byte_register() const { return code_ <= 3; }
136  int code() const {
137  ASSERT(is_valid());
138  return code_;
139  }
140  int bit() const {
141  return 1 << code_;
142  }
143 
144  // Return the high bit of the register code as a 0 or 1. Used often
145  // when constructing the REX prefix byte.
146  int high_bit() const {
147  return code_ >> 3;
148  }
149  // Return the 3 low bits of the register code. Used when encoding registers
150  // in modR/M, SIB, and opcode bytes.
151  int low_bits() const {
152  return code_ & 0x7;
153  }
154 
155  // Unfortunately we can't make this private in a struct when initializing
156  // by assignment.
157  int code_;
158 
159  private:
160  static const int kRegisterCodeByAllocationIndex[kNumAllocatableRegisters];
161  static const int kAllocationIndexByRegisterCode[kNumRegisters];
162 };
163 
164 const int kRegister_rax_Code = 0;
165 const int kRegister_rcx_Code = 1;
166 const int kRegister_rdx_Code = 2;
167 const int kRegister_rbx_Code = 3;
168 const int kRegister_rsp_Code = 4;
169 const int kRegister_rbp_Code = 5;
170 const int kRegister_rsi_Code = 6;
171 const int kRegister_rdi_Code = 7;
172 const int kRegister_r8_Code = 8;
173 const int kRegister_r9_Code = 9;
174 const int kRegister_r10_Code = 10;
175 const int kRegister_r11_Code = 11;
176 const int kRegister_r12_Code = 12;
177 const int kRegister_r13_Code = 13;
178 const int kRegister_r14_Code = 14;
179 const int kRegister_r15_Code = 15;
180 const int kRegister_no_reg_Code = -1;
181 
190 const Register r8 = { kRegister_r8_Code };
191 const Register r9 = { kRegister_r9_Code };
192 const Register r10 = { kRegister_r10_Code };
198 const Register no_reg = { kRegister_no_reg_Code };
199 
200 
201 struct XMMRegister {
202  static const int kNumRegisters = 16;
203  static const int kNumAllocatableRegisters = 15;
204 
205  static int ToAllocationIndex(XMMRegister reg) {
206  ASSERT(reg.code() != 0);
207  return reg.code() - 1;
208  }
209 
210  static XMMRegister FromAllocationIndex(int index) {
211  ASSERT(0 <= index && index < kNumAllocatableRegisters);
212  XMMRegister result = { index + 1 };
213  return result;
214  }
215 
216  static const char* AllocationIndexToString(int index) {
217  ASSERT(index >= 0 && index < kNumAllocatableRegisters);
218  const char* const names[] = {
219  "xmm1",
220  "xmm2",
221  "xmm3",
222  "xmm4",
223  "xmm5",
224  "xmm6",
225  "xmm7",
226  "xmm8",
227  "xmm9",
228  "xmm10",
229  "xmm11",
230  "xmm12",
231  "xmm13",
232  "xmm14",
233  "xmm15"
234  };
235  return names[index];
236  }
237 
238  static XMMRegister from_code(int code) {
239  ASSERT(code >= 0);
240  ASSERT(code < kNumRegisters);
241  XMMRegister r = { code };
242  return r;
243  }
244  bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
245  bool is(XMMRegister reg) const { return code_ == reg.code_; }
246  int code() const {
247  ASSERT(is_valid());
248  return code_;
249  }
250 
251  // Return the high bit of the register code as a 0 or 1. Used often
252  // when constructing the REX prefix byte.
253  int high_bit() const {
254  return code_ >> 3;
255  }
256  // Return the 3 low bits of the register code. Used when encoding registers
257  // in modR/M, SIB, and opcode bytes.
258  int low_bits() const {
259  return code_ & 0x7;
260  }
261 
262  int code_;
263 };
264 
265 const XMMRegister xmm0 = { 0 };
266 const XMMRegister xmm1 = { 1 };
267 const XMMRegister xmm2 = { 2 };
268 const XMMRegister xmm3 = { 3 };
269 const XMMRegister xmm4 = { 4 };
270 const XMMRegister xmm5 = { 5 };
271 const XMMRegister xmm6 = { 6 };
272 const XMMRegister xmm7 = { 7 };
273 const XMMRegister xmm8 = { 8 };
274 const XMMRegister xmm9 = { 9 };
275 const XMMRegister xmm10 = { 10 };
276 const XMMRegister xmm11 = { 11 };
277 const XMMRegister xmm12 = { 12 };
278 const XMMRegister xmm13 = { 13 };
279 const XMMRegister xmm14 = { 14 };
280 const XMMRegister xmm15 = { 15 };
281 
282 
283 typedef XMMRegister DoubleRegister;
284 
285 
286 enum Condition {
287  // any value < 0 is considered no_condition
288  no_condition = -1,
289 
290  overflow = 0,
291  no_overflow = 1,
292  below = 2,
293  above_equal = 3,
294  equal = 4,
295  not_equal = 5,
296  below_equal = 6,
297  above = 7,
298  negative = 8,
299  positive = 9,
300  parity_even = 10,
301  parity_odd = 11,
302  less = 12,
303  greater_equal = 13,
304  less_equal = 14,
305  greater = 15,
306 
307  // Fake conditions that are handled by the
308  // opcodes using them.
309  always = 16,
310  never = 17,
311  // aliases
312  carry = below,
314  zero = equal,
316  sign = negative,
317  not_sign = positive,
319 };
320 
321 
322 // Returns the equivalent of !cc.
323 // Negation of the default no_condition (-1) results in a non-default
324 // no_condition value (-2). As long as tests for no_condition check
325 // for condition < 0, this will work as expected.
327  return static_cast<Condition>(cc ^ 1);
328 }
329 
330 
331 // Corresponds to transposing the operands of a comparison.
333  switch (cc) {
334  case below:
335  return above;
336  case above:
337  return below;
338  case above_equal:
339  return below_equal;
340  case below_equal:
341  return above_equal;
342  case less:
343  return greater;
344  case greater:
345  return less;
346  case greater_equal:
347  return less_equal;
348  case less_equal:
349  return greater_equal;
350  default:
351  return cc;
352  };
353 }
354 
355 
356 // -----------------------------------------------------------------------------
357 // Machine instruction Immediates
358 
359 class Immediate BASE_EMBEDDED {
360  public:
361  explicit Immediate(int32_t value) : value_(value) {}
362 
363  private:
364  int32_t value_;
365 
366  friend class Assembler;
367 };
368 
369 
370 // -----------------------------------------------------------------------------
371 // Machine instruction Operands
372 
374  times_1 = 0,
375  times_2 = 1,
376  times_4 = 2,
377  times_8 = 3,
380 };
381 
382 
383 class Operand BASE_EMBEDDED {
384  public:
385  // [base + disp/r]
386  Operand(Register base, int32_t disp);
387 
388  // [base + index*scale + disp/r]
389  Operand(Register base,
390  Register index,
391  ScaleFactor scale,
392  int32_t disp);
393 
394  // [index*scale + disp/r]
395  Operand(Register index,
396  ScaleFactor scale,
397  int32_t disp);
398 
399  // Offset from existing memory operand.
400  // Offset is added to existing displacement as 32-bit signed values and
401  // this must not overflow.
402  Operand(const Operand& base, int32_t offset);
403 
404  // Checks whether either base or index register is the given register.
405  // Does not check the "reg" part of the Operand.
406  bool AddressUsesRegister(Register reg) const;
407 
408  // Queries related to the size of the generated instruction.
409  // Whether the generated instruction will have a REX prefix.
410  bool requires_rex() const { return rex_ != 0; }
411  // Size of the ModR/M, SIB and displacement parts of the generated
412  // instruction.
413  int operand_size() const { return len_; }
414 
415  private:
416  byte rex_;
417  byte buf_[6];
418  // The number of bytes of buf_ in use.
419  byte len_;
420 
421  // Set the ModR/M byte without an encoded 'reg' register. The
422  // register is encoded later as part of the emit_operand operation.
423  // set_modrm can be called before or after set_sib and set_disp*.
424  inline void set_modrm(int mod, Register rm);
425 
426  // Set the SIB byte if one is needed. Sets the length to 2 rather than 1.
427  inline void set_sib(ScaleFactor scale, Register index, Register base);
428 
429  // Adds operand displacement fields (offsets added to the memory address).
430  // Needs to be called after set_sib, not before it.
431  inline void set_disp8(int disp);
432  inline void set_disp32(int disp);
433 
434  friend class Assembler;
435 };
436 
437 
438 // CpuFeatures keeps track of which features are supported by the target CPU.
439 // Supported features must be enabled by a Scope before use.
440 // Example:
441 // if (CpuFeatures::IsSupported(SSE3)) {
442 // CpuFeatures::Scope fscope(SSE3);
443 // // Generate SSE3 floating point code.
444 // } else {
445 // // Generate standard x87 or SSE2 floating point code.
446 // }
447 class CpuFeatures : public AllStatic {
448  public:
449  // Detect features of the target CPU. Set safe defaults if the serializer
450  // is enabled (snapshots must be portable).
451  static void Probe();
452 
453  // Check whether a feature is supported by the target CPU.
454  static bool IsSupported(CpuFeature f) {
455  ASSERT(initialized_);
456  if (f == SSE2 && !FLAG_enable_sse2) return false;
457  if (f == SSE3 && !FLAG_enable_sse3) return false;
458  if (f == CMOV && !FLAG_enable_cmov) return false;
459  if (f == RDTSC && !FLAG_enable_rdtsc) return false;
460  if (f == SAHF && !FLAG_enable_sahf) return false;
461  return (supported_ & (V8_UINT64_C(1) << f)) != 0;
462  }
463 
464 #ifdef DEBUG
465  // Check whether a feature is currently enabled.
466  static bool IsEnabled(CpuFeature f) {
467  ASSERT(initialized_);
468  Isolate* isolate = Isolate::UncheckedCurrent();
469  if (isolate == NULL) {
470  // When no isolate is available, work as if we're running in
471  // release mode.
472  return IsSupported(f);
473  }
474  uint64_t enabled = isolate->enabled_cpu_features();
475  return (enabled & (V8_UINT64_C(1) << f)) != 0;
476  }
477 #endif
478 
479  // Enable a specified feature within a scope.
480  class Scope BASE_EMBEDDED {
481 #ifdef DEBUG
482 
483  public:
484  explicit Scope(CpuFeature f) {
485  uint64_t mask = V8_UINT64_C(1) << f;
488  (CpuFeatures::found_by_runtime_probing_ & mask) == 0);
489  isolate_ = Isolate::UncheckedCurrent();
490  old_enabled_ = 0;
491  if (isolate_ != NULL) {
492  old_enabled_ = isolate_->enabled_cpu_features();
493  isolate_->set_enabled_cpu_features(old_enabled_ | mask);
494  }
495  }
496  ~Scope() {
497  ASSERT_EQ(Isolate::UncheckedCurrent(), isolate_);
498  if (isolate_ != NULL) {
499  isolate_->set_enabled_cpu_features(old_enabled_);
500  }
501  }
502 
503  private:
504  Isolate* isolate_;
505  uint64_t old_enabled_;
506 #else
507 
508  public:
509  explicit Scope(CpuFeature f) {}
510 #endif
511  };
512 
513  private:
514  // Safe defaults include SSE2 and CMOV for X64. It is always available, if
515  // anyone checks, but they shouldn't need to check.
516  // The required user mode extensions in X64 are (from AMD64 ABI Table A.1):
517  // fpu, tsc, cx8, cmov, mmx, sse, sse2, fxsr, syscall
518  static const uint64_t kDefaultCpuFeatures = (1 << SSE2 | 1 << CMOV);
519 
520 #ifdef DEBUG
521  static bool initialized_;
522 #endif
523  static uint64_t supported_;
524  static uint64_t found_by_runtime_probing_;
525 
526  DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
527 };
528 
529 
530 class Assembler : public AssemblerBase {
531  private:
532  // We check before assembling an instruction that there is sufficient
533  // space to write an instruction and its relocation information.
534  // The relocation writer's position must be kGap bytes above the end of
535  // the generated instructions. This leaves enough space for the
536  // longest possible x64 instruction, 15 bytes, and the longest possible
537  // relocation information encoding, RelocInfoWriter::kMaxLength == 16.
538  // (There is a 15 byte limit on x64 instruction length that rules out some
539  // otherwise valid instructions.)
540  // This allows for a single, fast space check per instruction.
541  static const int kGap = 32;
542 
543  public:
544  // Create an assembler. Instructions and relocation information are emitted
545  // into a buffer, with the instructions starting from the beginning and the
546  // relocation information starting from the end of the buffer. See CodeDesc
547  // for a detailed comment on the layout (globals.h).
548  //
549  // If the provided buffer is NULL, the assembler allocates and grows its own
550  // buffer, and buffer_size determines the initial buffer size. The buffer is
551  // owned by the assembler and deallocated upon destruction of the assembler.
552  //
553  // If the provided buffer is not NULL, the assembler uses the provided buffer
554  // for code generation and assumes its size to be buffer_size. If the buffer
555  // is too small, a fatal error occurs. No deallocation of the buffer is done
556  // upon destruction of the assembler.
557  Assembler(Isolate* isolate, void* buffer, int buffer_size);
558  ~Assembler();
559 
560  // Overrides the default provided by FLAG_debug_code.
561  void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
562 
563  // GetCode emits any pending (non-emitted) code and fills the descriptor
564  // desc. GetCode() is idempotent; it returns the same result if no other
565  // Assembler functions are invoked in between GetCode() calls.
566  void GetCode(CodeDesc* desc);
567 
568  // Read/Modify the code target in the relative branch/call instruction at pc.
569  // On the x64 architecture, we use relative jumps with a 32-bit displacement
570  // to jump to other Code objects in the Code space in the heap.
571  // Jumps to C functions are done indirectly through a 64-bit register holding
572  // the absolute address of the target.
573  // These functions convert between absolute Addresses of Code objects and
574  // the relative displacements stored in the code.
575  static inline Address target_address_at(Address pc);
576  static inline void set_target_address_at(Address pc, Address target);
577 
578  // This sets the branch destination (which is in the instruction on x64).
579  // This is for calls and branches within generated code.
581  Address instruction_payload, Address target) {
582  set_target_address_at(instruction_payload, target);
583  }
584 
585  // This sets the branch destination (which is a load instruction on x64).
586  // This is for calls and branches to runtime code.
587  inline static void set_external_target_at(Address instruction_payload,
588  Address target) {
589  *reinterpret_cast<Address*>(instruction_payload) = target;
590  }
591 
593  // Number of bytes taken up by the branch target in the code.
594  static const int kSpecialTargetSize = 4; // Use 32-bit displacement.
595  // Distance between the address of the code target in the call instruction
596  // and the return address pushed on the stack.
597  static const int kCallTargetAddressOffset = 4; // Use 32-bit displacement.
598  // Distance between the start of the JS return sequence and where the
599  // 32-bit displacement of a near call would be, relative to the pushed
600  // return address. TODO: Use return sequence length instead.
601  // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
602  static const int kPatchReturnSequenceAddressOffset = 13 - 4;
603  // Distance between start of patched debug break slot and where the
604  // 32-bit displacement of a near call would be, relative to the pushed
605  // return address. TODO: Use return sequence length instead.
606  // Should equal Debug::kX64JSReturnSequenceLength - kCallTargetAddressOffset;
607  static const int kPatchDebugBreakSlotAddressOffset = 13 - 4;
608  // TODO(X64): Rename this, removing the "Real", after changing the above.
610 
611  // Some x64 JS code is padded with int3 to make it large
612  // enough to hold an instruction when the debugger patches it.
613  static const int kJumpInstructionLength = 13;
614  static const int kCallInstructionLength = 13;
615  static const int kJSReturnSequenceLength = 13;
616  static const int kShortCallInstructionLength = 5;
617 
618  // The debug break slot must be able to contain a call instruction.
620 
621  // One byte opcode for test eax,0xXXXXXXXX.
622  static const byte kTestEaxByte = 0xA9;
623  // One byte opcode for test al, 0xXX.
624  static const byte kTestAlByte = 0xA8;
625  // One byte opcode for nop.
626  static const byte kNopByte = 0x90;
627 
628  // One byte prefix for a short conditional jump.
629  static const byte kJccShortPrefix = 0x70;
631  static const byte kJcShortOpcode = kJccShortPrefix | carry;
632  static const byte kJnzShortOpcode = kJccShortPrefix | not_zero;
633  static const byte kJzShortOpcode = kJccShortPrefix | zero;
634 
635 
636  // ---------------------------------------------------------------------------
637  // Code generation
638  //
639  // Function names correspond one-to-one to x64 instruction mnemonics.
640  // Unless specified otherwise, instructions operate on 64-bit operands.
641  //
642  // If we need versions of an assembly instruction that operate on different
643  // width arguments, we add a single-letter suffix specifying the width.
644  // This is done for the following instructions: mov, cmp, inc, dec,
645  // add, sub, and test.
646  // There are no versions of these instructions without the suffix.
647  // - Instructions on 8-bit (byte) operands/registers have a trailing 'b'.
648  // - Instructions on 16-bit (word) operands/registers have a trailing 'w'.
649  // - Instructions on 32-bit (doubleword) operands/registers use 'l'.
650  // - Instructions on 64-bit (quadword) operands/registers use 'q'.
651  //
652  // Some mnemonics, such as "and", are the same as C++ keywords.
653  // Naming conflicts with C++ keywords are resolved by adding a trailing '_'.
654 
655  // Insert the smallest number of nop instructions
656  // possible to align the pc offset to a multiple
657  // of m, where m must be a power of 2.
658  void Align(int m);
659  void Nop(int bytes = 1);
660  // Aligns code to something that's optimal for a jump target for the platform.
661  void CodeTargetAlign();
662 
663  // Stack
664  void pushfq();
665  void popfq();
666 
667  void push(Immediate value);
668  // Push a 32 bit integer, and guarantee that it is actually pushed as a
669  // 32 bit value, the normal push will optimize the 8 bit case.
670  void push_imm32(int32_t imm32);
671  void push(Register src);
672  void push(const Operand& src);
673 
674  void pop(Register dst);
675  void pop(const Operand& dst);
676 
677  void enter(Immediate size);
678  void leave();
679 
680  // Moves
681  void movb(Register dst, const Operand& src);
682  void movb(Register dst, Immediate imm);
683  void movb(const Operand& dst, Register src);
684 
685  // Move the low 16 bits of a 64-bit register value to a 16-bit
686  // memory location.
687  void movw(const Operand& dst, Register src);
688 
689  void movl(Register dst, Register src);
690  void movl(Register dst, const Operand& src);
691  void movl(const Operand& dst, Register src);
692  void movl(const Operand& dst, Immediate imm);
693  // Load a 32-bit immediate value, zero-extended to 64 bits.
694  void movl(Register dst, Immediate imm32);
695 
696  // Move 64 bit register value to 64-bit memory location.
697  void movq(const Operand& dst, Register src);
698  // Move 64 bit memory location to 64-bit register value.
699  void movq(Register dst, const Operand& src);
700  void movq(Register dst, Register src);
701  // Sign extends immediate 32-bit value to 64 bits.
702  void movq(Register dst, Immediate x);
703  // Move the offset of the label location relative to the current
704  // position (after the move) to the destination.
705  void movl(const Operand& dst, Label* src);
706 
707  // Move sign extended immediate to memory location.
708  void movq(const Operand& dst, Immediate value);
709  // Instructions to load a 64-bit immediate into a register.
710  // All 64-bit immediates must have a relocation mode.
711  void movq(Register dst, void* ptr, RelocInfo::Mode rmode);
712  void movq(Register dst, int64_t value, RelocInfo::Mode rmode);
713  void movq(Register dst, const char* s, RelocInfo::Mode rmode);
714  // Moves the address of the external reference into the register.
715  void movq(Register dst, ExternalReference ext);
716  void movq(Register dst, Handle<Object> handle, RelocInfo::Mode rmode);
717 
718  void movsxbq(Register dst, const Operand& src);
719  void movsxwq(Register dst, const Operand& src);
720  void movsxlq(Register dst, Register src);
721  void movsxlq(Register dst, const Operand& src);
722  void movzxbq(Register dst, const Operand& src);
723  void movzxbl(Register dst, const Operand& src);
724  void movzxwq(Register dst, const Operand& src);
725  void movzxwl(Register dst, const Operand& src);
726 
727  // Repeated moves.
728 
729  void repmovsb();
730  void repmovsw();
731  void repmovsl();
732  void repmovsq();
733 
734  // Instruction to load from an immediate 64-bit pointer into RAX.
735  void load_rax(void* ptr, RelocInfo::Mode rmode);
736  void load_rax(ExternalReference ext);
737 
738  // Conditional moves.
739  void cmovq(Condition cc, Register dst, Register src);
740  void cmovq(Condition cc, Register dst, const Operand& src);
741  void cmovl(Condition cc, Register dst, Register src);
742  void cmovl(Condition cc, Register dst, const Operand& src);
743 
744  // Exchange two registers
745  void xchg(Register dst, Register src);
746 
747  // Arithmetics
748  void addl(Register dst, Register src) {
749  arithmetic_op_32(0x03, dst, src);
750  }
751 
752  void addl(Register dst, Immediate src) {
753  immediate_arithmetic_op_32(0x0, dst, src);
754  }
755 
756  void addl(Register dst, const Operand& src) {
757  arithmetic_op_32(0x03, dst, src);
758  }
759 
760  void addl(const Operand& dst, Immediate src) {
761  immediate_arithmetic_op_32(0x0, dst, src);
762  }
763 
764  void addl(const Operand& dst, Register src) {
765  arithmetic_op_32(0x01, src, dst);
766  }
767 
768  void addq(Register dst, Register src) {
769  arithmetic_op(0x03, dst, src);
770  }
771 
772  void addq(Register dst, const Operand& src) {
773  arithmetic_op(0x03, dst, src);
774  }
775 
776  void addq(const Operand& dst, Register src) {
777  arithmetic_op(0x01, src, dst);
778  }
779 
780  void addq(Register dst, Immediate src) {
781  immediate_arithmetic_op(0x0, dst, src);
782  }
783 
784  void addq(const Operand& dst, Immediate src) {
785  immediate_arithmetic_op(0x0, dst, src);
786  }
787 
788  void sbbl(Register dst, Register src) {
789  arithmetic_op_32(0x1b, dst, src);
790  }
791 
792  void sbbq(Register dst, Register src) {
793  arithmetic_op(0x1b, dst, src);
794  }
795 
796  void cmpb(Register dst, Immediate src) {
797  immediate_arithmetic_op_8(0x7, dst, src);
798  }
799 
800  void cmpb_al(Immediate src);
801 
802  void cmpb(Register dst, Register src) {
803  arithmetic_op(0x3A, dst, src);
804  }
805 
806  void cmpb(Register dst, const Operand& src) {
807  arithmetic_op(0x3A, dst, src);
808  }
809 
810  void cmpb(const Operand& dst, Register src) {
811  arithmetic_op(0x38, src, dst);
812  }
813 
814  void cmpb(const Operand& dst, Immediate src) {
815  immediate_arithmetic_op_8(0x7, dst, src);
816  }
817 
818  void cmpw(const Operand& dst, Immediate src) {
819  immediate_arithmetic_op_16(0x7, dst, src);
820  }
821 
822  void cmpw(Register dst, Immediate src) {
823  immediate_arithmetic_op_16(0x7, dst, src);
824  }
825 
826  void cmpw(Register dst, const Operand& src) {
827  arithmetic_op_16(0x3B, dst, src);
828  }
829 
830  void cmpw(Register dst, Register src) {
831  arithmetic_op_16(0x3B, dst, src);
832  }
833 
834  void cmpw(const Operand& dst, Register src) {
835  arithmetic_op_16(0x39, src, dst);
836  }
837 
838  void cmpl(Register dst, Register src) {
839  arithmetic_op_32(0x3B, dst, src);
840  }
841 
842  void cmpl(Register dst, const Operand& src) {
843  arithmetic_op_32(0x3B, dst, src);
844  }
845 
846  void cmpl(const Operand& dst, Register src) {
847  arithmetic_op_32(0x39, src, dst);
848  }
849 
850  void cmpl(Register dst, Immediate src) {
851  immediate_arithmetic_op_32(0x7, dst, src);
852  }
853 
854  void cmpl(const Operand& dst, Immediate src) {
855  immediate_arithmetic_op_32(0x7, dst, src);
856  }
857 
858  void cmpq(Register dst, Register src) {
859  arithmetic_op(0x3B, dst, src);
860  }
861 
862  void cmpq(Register dst, const Operand& src) {
863  arithmetic_op(0x3B, dst, src);
864  }
865 
866  void cmpq(const Operand& dst, Register src) {
867  arithmetic_op(0x39, src, dst);
868  }
869 
870  void cmpq(Register dst, Immediate src) {
871  immediate_arithmetic_op(0x7, dst, src);
872  }
873 
874  void cmpq(const Operand& dst, Immediate src) {
875  immediate_arithmetic_op(0x7, dst, src);
876  }
877 
878  void and_(Register dst, Register src) {
879  arithmetic_op(0x23, dst, src);
880  }
881 
882  void and_(Register dst, const Operand& src) {
883  arithmetic_op(0x23, dst, src);
884  }
885 
886  void and_(const Operand& dst, Register src) {
887  arithmetic_op(0x21, src, dst);
888  }
889 
890  void and_(Register dst, Immediate src) {
891  immediate_arithmetic_op(0x4, dst, src);
892  }
893 
894  void and_(const Operand& dst, Immediate src) {
895  immediate_arithmetic_op(0x4, dst, src);
896  }
897 
898  void andl(Register dst, Immediate src) {
899  immediate_arithmetic_op_32(0x4, dst, src);
900  }
901 
902  void andl(Register dst, Register src) {
903  arithmetic_op_32(0x23, dst, src);
904  }
905 
906  void andl(Register dst, const Operand& src) {
907  arithmetic_op_32(0x23, dst, src);
908  }
909 
910  void andb(Register dst, Immediate src) {
911  immediate_arithmetic_op_8(0x4, dst, src);
912  }
913 
914  void decq(Register dst);
915  void decq(const Operand& dst);
916  void decl(Register dst);
917  void decl(const Operand& dst);
918  void decb(Register dst);
919  void decb(const Operand& dst);
920 
921  // Sign-extends rax into rdx:rax.
922  void cqo();
923  // Sign-extends eax into edx:eax.
924  void cdq();
925 
926  // Divide rdx:rax by src. Quotient in rax, remainder in rdx.
927  void idivq(Register src);
928  // Divide edx:eax by lower 32 bits of src. Quotient in eax, rem. in edx.
929  void idivl(Register src);
930 
931  // Signed multiply instructions.
932  void imul(Register src); // rdx:rax = rax * src.
933  void imul(Register dst, Register src); // dst = dst * src.
934  void imul(Register dst, const Operand& src); // dst = dst * src.
935  void imul(Register dst, Register src, Immediate imm); // dst = src * imm.
936  // Signed 32-bit multiply instructions.
937  void imull(Register dst, Register src); // dst = dst * src.
938  void imull(Register dst, const Operand& src); // dst = dst * src.
939  void imull(Register dst, Register src, Immediate imm); // dst = src * imm.
940 
941  void incq(Register dst);
942  void incq(const Operand& dst);
943  void incl(Register dst);
944  void incl(const Operand& dst);
945 
946  void lea(Register dst, const Operand& src);
947  void leal(Register dst, const Operand& src);
948 
949  // Multiply rax by src, put the result in rdx:rax.
950  void mul(Register src);
951 
952  void neg(Register dst);
953  void neg(const Operand& dst);
954  void negl(Register dst);
955 
956  void not_(Register dst);
957  void not_(const Operand& dst);
958  void notl(Register dst);
959 
960  void or_(Register dst, Register src) {
961  arithmetic_op(0x0B, dst, src);
962  }
963 
964  void orl(Register dst, Register src) {
965  arithmetic_op_32(0x0B, dst, src);
966  }
967 
968  void or_(Register dst, const Operand& src) {
969  arithmetic_op(0x0B, dst, src);
970  }
971 
972  void orl(Register dst, const Operand& src) {
973  arithmetic_op_32(0x0B, dst, src);
974  }
975 
976  void or_(const Operand& dst, Register src) {
977  arithmetic_op(0x09, src, dst);
978  }
979 
980  void or_(Register dst, Immediate src) {
981  immediate_arithmetic_op(0x1, dst, src);
982  }
983 
984  void orl(Register dst, Immediate src) {
985  immediate_arithmetic_op_32(0x1, dst, src);
986  }
987 
988  void or_(const Operand& dst, Immediate src) {
989  immediate_arithmetic_op(0x1, dst, src);
990  }
991 
992  void orl(const Operand& dst, Immediate src) {
993  immediate_arithmetic_op_32(0x1, dst, src);
994  }
995 
996 
997  void rcl(Register dst, Immediate imm8) {
998  shift(dst, imm8, 0x2);
999  }
1000 
1001  void rol(Register dst, Immediate imm8) {
1002  shift(dst, imm8, 0x0);
1003  }
1004 
1005  void rcr(Register dst, Immediate imm8) {
1006  shift(dst, imm8, 0x3);
1007  }
1008 
1009  void ror(Register dst, Immediate imm8) {
1010  shift(dst, imm8, 0x1);
1011  }
1012 
1013  // Shifts dst:src left by cl bits, affecting only dst.
1014  void shld(Register dst, Register src);
1015 
1016  // Shifts src:dst right by cl bits, affecting only dst.
1017  void shrd(Register dst, Register src);
1018 
1019  // Shifts dst right, duplicating sign bit, by shift_amount bits.
1020  // Shifting by 1 is handled efficiently.
1021  void sar(Register dst, Immediate shift_amount) {
1022  shift(dst, shift_amount, 0x7);
1023  }
1024 
1025  // Shifts dst right, duplicating sign bit, by shift_amount bits.
1026  // Shifting by 1 is handled efficiently.
1027  void sarl(Register dst, Immediate shift_amount) {
1028  shift_32(dst, shift_amount, 0x7);
1029  }
1030 
1031  // Shifts dst right, duplicating sign bit, by cl % 64 bits.
1032  void sar_cl(Register dst) {
1033  shift(dst, 0x7);
1034  }
1035 
1036  // Shifts dst right, duplicating sign bit, by cl % 64 bits.
1037  void sarl_cl(Register dst) {
1038  shift_32(dst, 0x7);
1039  }
1040 
1041  void shl(Register dst, Immediate shift_amount) {
1042  shift(dst, shift_amount, 0x4);
1043  }
1044 
1045  void shl_cl(Register dst) {
1046  shift(dst, 0x4);
1047  }
1048 
1049  void shll_cl(Register dst) {
1050  shift_32(dst, 0x4);
1051  }
1052 
1053  void shll(Register dst, Immediate shift_amount) {
1054  shift_32(dst, shift_amount, 0x4);
1055  }
1056 
1057  void shr(Register dst, Immediate shift_amount) {
1058  shift(dst, shift_amount, 0x5);
1059  }
1060 
1061  void shr_cl(Register dst) {
1062  shift(dst, 0x5);
1063  }
1064 
1065  void shrl_cl(Register dst) {
1066  shift_32(dst, 0x5);
1067  }
1068 
1069  void shrl(Register dst, Immediate shift_amount) {
1070  shift_32(dst, shift_amount, 0x5);
1071  }
1072 
1073  void store_rax(void* dst, RelocInfo::Mode mode);
1074  void store_rax(ExternalReference ref);
1075 
1076  void subq(Register dst, Register src) {
1077  arithmetic_op(0x2B, dst, src);
1078  }
1079 
1080  void subq(Register dst, const Operand& src) {
1081  arithmetic_op(0x2B, dst, src);
1082  }
1083 
1084  void subq(const Operand& dst, Register src) {
1085  arithmetic_op(0x29, src, dst);
1086  }
1087 
1088  void subq(Register dst, Immediate src) {
1089  immediate_arithmetic_op(0x5, dst, src);
1090  }
1091 
1092  void subq(const Operand& dst, Immediate src) {
1093  immediate_arithmetic_op(0x5, dst, src);
1094  }
1095 
1096  void subl(Register dst, Register src) {
1097  arithmetic_op_32(0x2B, dst, src);
1098  }
1099 
1100  void subl(Register dst, const Operand& src) {
1101  arithmetic_op_32(0x2B, dst, src);
1102  }
1103 
1104  void subl(const Operand& dst, Immediate src) {
1105  immediate_arithmetic_op_32(0x5, dst, src);
1106  }
1107 
1108  void subl(Register dst, Immediate src) {
1109  immediate_arithmetic_op_32(0x5, dst, src);
1110  }
1111 
1112  void subb(Register dst, Immediate src) {
1113  immediate_arithmetic_op_8(0x5, dst, src);
1114  }
1115 
1116  void testb(Register dst, Register src);
1117  void testb(Register reg, Immediate mask);
1118  void testb(const Operand& op, Immediate mask);
1119  void testb(const Operand& op, Register reg);
1120  void testl(Register dst, Register src);
1121  void testl(Register reg, Immediate mask);
1122  void testl(const Operand& op, Immediate mask);
1123  void testq(const Operand& op, Register reg);
1124  void testq(Register dst, Register src);
1125  void testq(Register dst, Immediate mask);
1126 
1127  void xor_(Register dst, Register src) {
1128  if (dst.code() == src.code()) {
1129  arithmetic_op_32(0x33, dst, src);
1130  } else {
1131  arithmetic_op(0x33, dst, src);
1132  }
1133  }
1134 
1135  void xorl(Register dst, Register src) {
1136  arithmetic_op_32(0x33, dst, src);
1137  }
1138 
1139  void xorl(Register dst, const Operand& src) {
1140  arithmetic_op_32(0x33, dst, src);
1141  }
1142 
1143  void xorl(Register dst, Immediate src) {
1144  immediate_arithmetic_op_32(0x6, dst, src);
1145  }
1146 
1147  void xorl(const Operand& dst, Immediate src) {
1148  immediate_arithmetic_op_32(0x6, dst, src);
1149  }
1150 
1151  void xor_(Register dst, const Operand& src) {
1152  arithmetic_op(0x33, dst, src);
1153  }
1154 
1155  void xor_(const Operand& dst, Register src) {
1156  arithmetic_op(0x31, src, dst);
1157  }
1158 
1159  void xor_(Register dst, Immediate src) {
1160  immediate_arithmetic_op(0x6, dst, src);
1161  }
1162 
1163  void xor_(const Operand& dst, Immediate src) {
1164  immediate_arithmetic_op(0x6, dst, src);
1165  }
1166 
1167  // Bit operations.
1168  void bt(const Operand& dst, Register src);
1169  void bts(const Operand& dst, Register src);
1170 
1171  // Miscellaneous
1172  void clc();
1173  void cld();
1174  void cpuid();
1175  void hlt();
1176  void int3();
1177  void nop();
1178  void rdtsc();
1179  void ret(int imm16);
1180  void setcc(Condition cc, Register reg);
1181 
1182  // Label operations & relative jumps (PPUM Appendix D)
1183  //
1184  // Takes a branch opcode (cc) and a label (L) and generates
1185  // either a backward branch or a forward branch and links it
1186  // to the label fixup chain. Usage:
1187  //
1188  // Label L; // unbound label
1189  // j(cc, &L); // forward branch to unbound label
1190  // bind(&L); // bind label to the current pc
1191  // j(cc, &L); // backward branch to bound label
1192  // bind(&L); // illegal: a label may be bound only once
1193  //
1194  // Note: The same Label can be used for forward and backward branches
1195  // but it may be bound only once.
1196 
1197  void bind(Label* L); // binds an unbound label L to the current code position
1198 
1199  // Calls
1200  // Call near relative 32-bit displacement, relative to next instruction.
1201  void call(Label* L);
1202  void call(Handle<Code> target,
1203  RelocInfo::Mode rmode = RelocInfo::CODE_TARGET,
1204  unsigned ast_id = kNoASTId);
1205 
1206  // Calls directly to the given address using a relative offset.
1207  // Should only ever be used in Code objects for calls within the
1208  // same Code object. Should not be used when generating new code (use labels),
1209  // but only when patching existing code.
1210  void call(Address target);
1211 
1212  // Call near absolute indirect, address in register
1213  void call(Register adr);
1214 
1215  // Call near indirect
1216  void call(const Operand& operand);
1217 
1218  // Jumps
1219  // Jump short or near relative.
1220  // Use a 32-bit signed displacement.
1221  // Unconditional jump to L
1222  void jmp(Label* L, Label::Distance distance = Label::kFar);
1223  void jmp(Handle<Code> target, RelocInfo::Mode rmode);
1224 
1225  // Jump near absolute indirect (r64)
1226  void jmp(Register adr);
1227 
1228  // Jump near absolute indirect (m64)
1229  void jmp(const Operand& src);
1230 
1231  // Conditional jumps
1232  void j(Condition cc,
1233  Label* L,
1234  Label::Distance distance = Label::kFar);
1235  void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);
1236 
1237  // Floating-point operations
1238  void fld(int i);
1239 
1240  void fld1();
1241  void fldz();
1242  void fldpi();
1243  void fldln2();
1244 
1245  void fld_s(const Operand& adr);
1246  void fld_d(const Operand& adr);
1247 
1248  void fstp_s(const Operand& adr);
1249  void fstp_d(const Operand& adr);
1250  void fstp(int index);
1251 
1252  void fild_s(const Operand& adr);
1253  void fild_d(const Operand& adr);
1254 
1255  void fist_s(const Operand& adr);
1256 
1257  void fistp_s(const Operand& adr);
1258  void fistp_d(const Operand& adr);
1259 
1260  void fisttp_s(const Operand& adr);
1261  void fisttp_d(const Operand& adr);
1262 
1263  void fabs();
1264  void fchs();
1265 
1266  void fadd(int i);
1267  void fsub(int i);
1268  void fmul(int i);
1269  void fdiv(int i);
1270 
1271  void fisub_s(const Operand& adr);
1272 
1273  void faddp(int i = 1);
1274  void fsubp(int i = 1);
1275  void fsubrp(int i = 1);
1276  void fmulp(int i = 1);
1277  void fdivp(int i = 1);
1278  void fprem();
1279  void fprem1();
1280 
1281  void fxch(int i = 1);
1282  void fincstp();
1283  void ffree(int i = 0);
1284 
1285  void ftst();
1286  void fucomp(int i);
1287  void fucompp();
1288  void fucomi(int i);
1289  void fucomip();
1290 
1291  void fcompp();
1292  void fnstsw_ax();
1293  void fwait();
1294  void fnclex();
1295 
1296  void fsin();
1297  void fcos();
1298  void fptan();
1299  void fyl2x();
1300  void f2xm1();
1301  void fscale();
1302  void fninit();
1303 
1304  void frndint();
1305 
1306  void sahf();
1307 
1308  // SSE2 instructions
1309  void movd(XMMRegister dst, Register src);
1310  void movd(Register dst, XMMRegister src);
1311  void movq(XMMRegister dst, Register src);
1312  void movq(Register dst, XMMRegister src);
1313  void movq(XMMRegister dst, XMMRegister src);
1314  void extractps(Register dst, XMMRegister src, byte imm8);
1315 
1316  // Don't use this unless it's important to keep the
1317  // top half of the destination register unchanged.
1318  // Used movaps when moving double values and movq for integer
1319  // values in xmm registers.
1320  void movsd(XMMRegister dst, XMMRegister src);
1321 
1322  void movsd(const Operand& dst, XMMRegister src);
1323  void movsd(XMMRegister dst, const Operand& src);
1324 
1325  void movdqa(const Operand& dst, XMMRegister src);
1326  void movdqa(XMMRegister dst, const Operand& src);
1327 
1328  void movapd(XMMRegister dst, XMMRegister src);
1329  void movaps(XMMRegister dst, XMMRegister src);
1330 
1331  void movss(XMMRegister dst, const Operand& src);
1332  void movss(const Operand& dst, XMMRegister src);
1333 
1334  void cvttss2si(Register dst, const Operand& src);
1335  void cvttss2si(Register dst, XMMRegister src);
1336  void cvttsd2si(Register dst, const Operand& src);
1337  void cvttsd2si(Register dst, XMMRegister src);
1338  void cvttsd2siq(Register dst, XMMRegister src);
1339 
1340  void cvtlsi2sd(XMMRegister dst, const Operand& src);
1341  void cvtlsi2sd(XMMRegister dst, Register src);
1342  void cvtqsi2sd(XMMRegister dst, const Operand& src);
1343  void cvtqsi2sd(XMMRegister dst, Register src);
1344 
1345  void cvtlsi2ss(XMMRegister dst, Register src);
1346 
1347  void cvtss2sd(XMMRegister dst, XMMRegister src);
1348  void cvtss2sd(XMMRegister dst, const Operand& src);
1349  void cvtsd2ss(XMMRegister dst, XMMRegister src);
1350 
1351  void cvtsd2si(Register dst, XMMRegister src);
1352  void cvtsd2siq(Register dst, XMMRegister src);
1353 
1354  void addsd(XMMRegister dst, XMMRegister src);
1355  void subsd(XMMRegister dst, XMMRegister src);
1356  void mulsd(XMMRegister dst, XMMRegister src);
1357  void divsd(XMMRegister dst, XMMRegister src);
1358 
1359  void andpd(XMMRegister dst, XMMRegister src);
1360  void orpd(XMMRegister dst, XMMRegister src);
1361  void xorpd(XMMRegister dst, XMMRegister src);
1362  void xorps(XMMRegister dst, XMMRegister src);
1363  void sqrtsd(XMMRegister dst, XMMRegister src);
1364 
1365  void ucomisd(XMMRegister dst, XMMRegister src);
1366  void ucomisd(XMMRegister dst, const Operand& src);
1367 
1369  kRoundToNearest = 0x0,
1370  kRoundDown = 0x1,
1371  kRoundUp = 0x2,
1372  kRoundToZero = 0x3
1373  };
1374 
1375  void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode);
1376 
1377  void movmskpd(Register dst, XMMRegister src);
1378 
1379  // The first argument is the reg field, the second argument is the r/m field.
1380  void emit_sse_operand(XMMRegister dst, XMMRegister src);
1381  void emit_sse_operand(XMMRegister reg, const Operand& adr);
1382  void emit_sse_operand(XMMRegister dst, Register src);
1383  void emit_sse_operand(Register dst, XMMRegister src);
1384 
1385  // Debugging
1386  void Print();
1387 
1388  // Check the code size generated from label to here.
1389  int SizeOfCodeGeneratedSince(Label* label) {
1390  return pc_offset() - label->pos();
1391  }
1392 
1393  // Mark address of the ExitJSFrame code.
1394  void RecordJSReturn();
1395 
1396  // Mark address of a debug break slot.
1397  void RecordDebugBreakSlot();
1398 
1399  // Record a comment relocation entry that can be used by a disassembler.
1400  // Use --code-comments to enable.
1401  void RecordComment(const char* msg, bool force = false);
1402 
1403  // Writes a single word of data in the code stream.
1404  // Used for inline tables, e.g., jump-tables.
1405  void db(uint8_t data);
1406  void dd(uint32_t data);
1407 
1408  int pc_offset() const { return static_cast<int>(pc_ - buffer_); }
1409 
1410  PositionsRecorder* positions_recorder() { return &positions_recorder_; }
1411 
1412  // Check if there is less than kGap bytes available in the buffer.
1413  // If this is the case, we need to grow the buffer before emitting
1414  // an instruction or relocation information.
1415  inline bool buffer_overflow() const {
1416  return pc_ >= reloc_info_writer.pos() - kGap;
1417  }
1418 
1419  // Get the number of bytes available in the buffer.
1420  inline int available_space() const {
1421  return static_cast<int>(reloc_info_writer.pos() - pc_);
1422  }
1423 
1424  static bool IsNop(Address addr);
1425 
1426  // Avoid overflows for displacements etc.
1427  static const int kMaximalBufferSize = 512*MB;
1428  static const int kMinimalBufferSize = 4*KB;
1429 
1430  byte byte_at(int pos) { return buffer_[pos]; }
1431  void set_byte_at(int pos, byte value) { buffer_[pos] = value; }
1432 
1433  protected:
1434  bool emit_debug_code() const { return emit_debug_code_; }
1435 
1436  private:
1437  byte* addr_at(int pos) { return buffer_ + pos; }
1438  uint32_t long_at(int pos) {
1439  return *reinterpret_cast<uint32_t*>(addr_at(pos));
1440  }
1441  void long_at_put(int pos, uint32_t x) {
1442  *reinterpret_cast<uint32_t*>(addr_at(pos)) = x;
1443  }
1444 
1445  // code emission
1446  void GrowBuffer();
1447 
1448  void emit(byte x) { *pc_++ = x; }
1449  inline void emitl(uint32_t x);
1450  inline void emitq(uint64_t x, RelocInfo::Mode rmode);
1451  inline void emitw(uint16_t x);
1452  inline void emit_code_target(Handle<Code> target,
1453  RelocInfo::Mode rmode,
1454  unsigned ast_id = kNoASTId);
1455  void emit(Immediate x) { emitl(x.value_); }
1456 
1457  // Emits a REX prefix that encodes a 64-bit operand size and
1458  // the top bit of both register codes.
1459  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1460  // REX.W is set.
1461  inline void emit_rex_64(XMMRegister reg, Register rm_reg);
1462  inline void emit_rex_64(Register reg, XMMRegister rm_reg);
1463  inline void emit_rex_64(Register reg, Register rm_reg);
1464 
1465  // Emits a REX prefix that encodes a 64-bit operand size and
1466  // the top bit of the destination, index, and base register codes.
1467  // The high bit of reg is used for REX.R, the high bit of op's base
1468  // register is used for REX.B, and the high bit of op's index register
1469  // is used for REX.X. REX.W is set.
1470  inline void emit_rex_64(Register reg, const Operand& op);
1471  inline void emit_rex_64(XMMRegister reg, const Operand& op);
1472 
1473  // Emits a REX prefix that encodes a 64-bit operand size and
1474  // the top bit of the register code.
1475  // The high bit of register is used for REX.B.
1476  // REX.W is set and REX.R and REX.X are clear.
1477  inline void emit_rex_64(Register rm_reg);
1478 
1479  // Emits a REX prefix that encodes a 64-bit operand size and
1480  // the top bit of the index and base register codes.
1481  // The high bit of op's base register is used for REX.B, and the high
1482  // bit of op's index register is used for REX.X.
1483  // REX.W is set and REX.R clear.
1484  inline void emit_rex_64(const Operand& op);
1485 
1486  // Emit a REX prefix that only sets REX.W to choose a 64-bit operand size.
1487  void emit_rex_64() { emit(0x48); }
1488 
1489  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1490  // REX.W is clear.
1491  inline void emit_rex_32(Register reg, Register rm_reg);
1492 
1493  // The high bit of reg is used for REX.R, the high bit of op's base
1494  // register is used for REX.B, and the high bit of op's index register
1495  // is used for REX.X. REX.W is cleared.
1496  inline void emit_rex_32(Register reg, const Operand& op);
1497 
1498  // High bit of rm_reg goes to REX.B.
1499  // REX.W, REX.R and REX.X are clear.
1500  inline void emit_rex_32(Register rm_reg);
1501 
1502  // High bit of base goes to REX.B and high bit of index to REX.X.
1503  // REX.W and REX.R are clear.
1504  inline void emit_rex_32(const Operand& op);
1505 
1506  // High bit of reg goes to REX.R, high bit of rm_reg goes to REX.B.
1507  // REX.W is cleared. If no REX bits are set, no byte is emitted.
1508  inline void emit_optional_rex_32(Register reg, Register rm_reg);
1509 
1510  // The high bit of reg is used for REX.R, the high bit of op's base
1511  // register is used for REX.B, and the high bit of op's index register
1512  // is used for REX.X. REX.W is cleared. If no REX bits are set, nothing
1513  // is emitted.
1514  inline void emit_optional_rex_32(Register reg, const Operand& op);
1515 
1516  // As for emit_optional_rex_32(Register, Register), except that
1517  // the registers are XMM registers.
1518  inline void emit_optional_rex_32(XMMRegister reg, XMMRegister base);
1519 
1520  // As for emit_optional_rex_32(Register, Register), except that
1521  // one of the registers is an XMM registers.
1522  inline void emit_optional_rex_32(XMMRegister reg, Register base);
1523 
1524  // As for emit_optional_rex_32(Register, Register), except that
1525  // one of the registers is an XMM registers.
1526  inline void emit_optional_rex_32(Register reg, XMMRegister base);
1527 
1528  // As for emit_optional_rex_32(Register, const Operand&), except that
1529  // the register is an XMM register.
1530  inline void emit_optional_rex_32(XMMRegister reg, const Operand& op);
1531 
1532  // Optionally do as emit_rex_32(Register) if the register number has
1533  // the high bit set.
1534  inline void emit_optional_rex_32(Register rm_reg);
1535 
1536  // Optionally do as emit_rex_32(const Operand&) if the operand register
1537  // numbers have a high bit set.
1538  inline void emit_optional_rex_32(const Operand& op);
1539 
1540 
1541  // Emit the ModR/M byte, and optionally the SIB byte and
1542  // 1- or 4-byte offset for a memory operand. Also encodes
1543  // the second operand of the operation, a register or operation
1544  // subcode, into the reg field of the ModR/M byte.
1545  void emit_operand(Register reg, const Operand& adr) {
1546  emit_operand(reg.low_bits(), adr);
1547  }
1548 
1549  // Emit the ModR/M byte, and optionally the SIB byte and
1550  // 1- or 4-byte offset for a memory operand. Also used to encode
1551  // a three-bit opcode extension into the ModR/M byte.
1552  void emit_operand(int rm, const Operand& adr);
1553 
1554  // Emit a ModR/M byte with registers coded in the reg and rm_reg fields.
1555  void emit_modrm(Register reg, Register rm_reg) {
1556  emit(0xC0 | reg.low_bits() << 3 | rm_reg.low_bits());
1557  }
1558 
1559  // Emit a ModR/M byte with an operation subcode in the reg field and
1560  // a register in the rm_reg field.
1561  void emit_modrm(int code, Register rm_reg) {
1562  ASSERT(is_uint3(code));
1563  emit(0xC0 | code << 3 | rm_reg.low_bits());
1564  }
1565 
1566  // Emit the code-object-relative offset of the label's position
1567  inline void emit_code_relative_offset(Label* label);
1568 
1569  // Emit machine code for one of the operations ADD, ADC, SUB, SBC,
1570  // AND, OR, XOR, or CMP. The encodings of these operations are all
1571  // similar, differing just in the opcode or in the reg field of the
1572  // ModR/M byte.
1573  void arithmetic_op_16(byte opcode, Register reg, Register rm_reg);
1574  void arithmetic_op_16(byte opcode, Register reg, const Operand& rm_reg);
1575  void arithmetic_op_32(byte opcode, Register reg, Register rm_reg);
1576  void arithmetic_op_32(byte opcode, Register reg, const Operand& rm_reg);
1577  void arithmetic_op(byte opcode, Register reg, Register rm_reg);
1578  void arithmetic_op(byte opcode, Register reg, const Operand& rm_reg);
1579  void immediate_arithmetic_op(byte subcode, Register dst, Immediate src);
1580  void immediate_arithmetic_op(byte subcode, const Operand& dst, Immediate src);
1581  // Operate on a byte in memory or register.
1582  void immediate_arithmetic_op_8(byte subcode,
1583  Register dst,
1584  Immediate src);
1585  void immediate_arithmetic_op_8(byte subcode,
1586  const Operand& dst,
1587  Immediate src);
1588  // Operate on a word in memory or register.
1589  void immediate_arithmetic_op_16(byte subcode,
1590  Register dst,
1591  Immediate src);
1592  void immediate_arithmetic_op_16(byte subcode,
1593  const Operand& dst,
1594  Immediate src);
1595  // Operate on a 32-bit word in memory or register.
1596  void immediate_arithmetic_op_32(byte subcode,
1597  Register dst,
1598  Immediate src);
1599  void immediate_arithmetic_op_32(byte subcode,
1600  const Operand& dst,
1601  Immediate src);
1602 
1603  // Emit machine code for a shift operation.
1604  void shift(Register dst, Immediate shift_amount, int subcode);
1605  void shift_32(Register dst, Immediate shift_amount, int subcode);
1606  // Shift dst by cl % 64 bits.
1607  void shift(Register dst, int subcode);
1608  void shift_32(Register dst, int subcode);
1609 
1610  void emit_farith(int b1, int b2, int i);
1611 
1612  // labels
1613  // void print(Label* L);
1614  void bind_to(Label* L, int pos);
1615 
1616  // record reloc info for current pc_
1617  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1618 
1619  friend class CodePatcher;
1620  friend class EnsureSpace;
1622 
1623  // Code buffer:
1624  // The buffer into which code and relocation info are generated.
1625  byte* buffer_;
1626  int buffer_size_;
1627  // True if the assembler owns the buffer, false if buffer is external.
1628  bool own_buffer_;
1629 
1630  // code generation
1631  byte* pc_; // the program counter; moves forward
1632  RelocInfoWriter reloc_info_writer;
1633 
1634  List< Handle<Code> > code_targets_;
1635 
1636  PositionsRecorder positions_recorder_;
1637 
1638  bool emit_debug_code_;
1639 
1640  friend class PositionsRecorder;
1641 };
1642 
1643 
1644 // Helper class that ensures that there is enough space for generating
1645 // instructions and relocation information. The constructor makes
1646 // sure that there is enough space and (in debug mode) the destructor
1647 // checks that we did not generate too much.
1648 class EnsureSpace BASE_EMBEDDED {
1649  public:
1650  explicit EnsureSpace(Assembler* assembler) : assembler_(assembler) {
1651  if (assembler_->buffer_overflow()) assembler_->GrowBuffer();
1652 #ifdef DEBUG
1653  space_before_ = assembler_->available_space();
1654 #endif
1655  }
1656 
1657 #ifdef DEBUG
1658  ~EnsureSpace() {
1659  int bytes_generated = space_before_ - assembler_->available_space();
1660  ASSERT(bytes_generated < assembler_->kGap);
1661  }
1662 #endif
1663 
1664  private:
1665  Assembler* assembler_;
1666 #ifdef DEBUG
1667  int space_before_;
1668 #endif
1669 };
1670 
1671 } } // namespace v8::internal
1672 
1673 #endif // V8_X64_ASSEMBLER_X64_H_
byte * Address
Definition: globals.h:172
const Register rdx
void shl(Register dst, Immediate shift_amount)
void xor_(Register dst, Immediate src)
void cvtlsi2ss(XMMRegister dst, Register src)
const XMMRegister xmm13
void movapd(XMMRegister dst, XMMRegister src)
static const int kMaximalBufferSize
void cmpb(const Operand &dst, Register src)
void xorl(Register dst, const Operand &src)
void or_(Register dst, Immediate src)
const Register r14
void db(uint8_t data)
void addq(Register dst, Immediate src)
void load_rax(void *ptr, RelocInfo::Mode rmode)
const int kRegister_r14_Code
const int kRegister_rsp_Code
void addq(const Operand &dst, Register src)
static const byte kJccShortPrefix
void ucomisd(XMMRegister dst, XMMRegister src)
void cvttss2si(Register dst, const Operand &src)
void movzxbl(Register dst, const Operand &src)
void cmpw(Register dst, const Operand &src)
void or_(Register dst, Register src)
void ror(Register dst, Immediate imm8)
void roundsd(XMMRegister dst, XMMRegister src, RoundingMode mode)
const Register r11
void or_(const Operand &dst, Register src)
const XMMRegister xmm4
void addq(Register dst, const Operand &src)
bool buffer_overflow() const
void mulsd(XMMRegister dst, XMMRegister src)
const Register rbp
bool is_byte_register() const
const int KB
Definition: globals.h:221
void cvtsd2si(Register dst, XMMRegister src)
void cmpl(Register dst, Register src)
const int kRegister_r13_Code
void idivq(Register src)
void andl(Register dst, const Operand &src)
void and_(Register dst, const Operand &src)
const int kRegister_rbp_Code
void orpd(XMMRegister dst, XMMRegister src)
int SizeOfCodeGeneratedSince(Label *label)
void cmpw(const Operand &dst, Immediate src)
const Register rsi
void addq(Register dst, Register src)
void dd(uint32_t data)
void push(Register src, Condition cond=al)
void subl(Register dst, Register src)
void xorl(const Operand &dst, Immediate src)
void cvtss2sd(XMMRegister dst, XMMRegister src)
void orl(Register dst, Immediate src)
void sqrtsd(XMMRegister dst, XMMRegister src)
int int32_t
Definition: unicode.cc:47
static XMMRegister FromAllocationIndex(int index)
void xorl(Register dst, Immediate src)
static bool IsSupported(CpuFeature f)
static bool enabled()
Definition: serialize.h:480
bool is_uint3(int x)
Definition: assembler.h:840
void andpd(XMMRegister dst, XMMRegister src)
static const int kCallInstructionLength
void subq(const Operand &dst, Register src)
void xor_(Register dst, const Operand &src)
void j(Condition cc, Label *L, Label::Distance distance=Label::kFar)
static Register FromAllocationIndex(int index)
static const int kMinimalBufferSize
void cmpq(Register dst, const Operand &src)
#define ASSERT(condition)
Definition: checks.h:270
static const int kPatchReturnSequenceAddressOffset
void subq(Register dst, Register src)
void cvtlsi2sd(XMMRegister dst, const Operand &src)
static const int kShortCallInstructionLength
unsigned short uint16_t
Definition: unicode.cc:46
void and_(const Operand &dst, Register src)
void addl(Register dst, Register src)
static const char * AllocationIndexToString(int index)
const XMMRegister xmm6
void movsxlq(Register dst, Register src)
void xorpd(XMMRegister dst, XMMRegister src)
void cmpl(Register dst, Immediate src)
StringInputBuffer *const buffer_
void ret(int imm16)
void bt(const Operand &dst, Register src)
bool is_uint32(int64_t x)
Definition: assembler-x64.h:48
void sarl_cl(Register dst)
void orl(Register dst, const Operand &src)
const XMMRegister xmm12
void incl(Register dst)
static const byte kTestAlByte
void shll(Register dst, Immediate shift_amount)
void cmovl(Condition cc, Register dst, Register src)
void testb(Register dst, Register src)
const XMMRegister xmm5
const int kRegister_rcx_Code
void cmpb(Register dst, Register src)
void fistp_s(const Operand &adr)
void imul(Register src)
void addsd(XMMRegister dst, XMMRegister src)
const int kRegister_r12_Code
void shr_cl(Register dst)
void fld_d(const Operand &adr)
void addq(const Operand &dst, Immediate src)
static const int kNumRegisters
Definition: assembler-arm.h:73
void imull(Register dst, Register src)
void cmpb_al(const Operand &op)
void xchg(Register dst, Register src)
void fild_s(const Operand &adr)
EnsureSpace(Assembler *assembler)
void orl(Register dst, Register src)
void decl(Register dst)
void cmpl(const Operand &dst, Immediate src)
void shr(Register dst, Immediate shift_amount)
static const char * AllocationIndexToString(int index)
void idivl(Register src)
uint8_t byte
Definition: globals.h:171
const XMMRegister xmm14
void enter(const Immediate &size)
Condition ReverseCondition(Condition cond)
static const int kJumpInstructionLength
static const byte kJcShortOpcode
const unsigned kNoASTId
Definition: assembler.h:54
void testl(Register dst, Register src)
void movzxbq(Register dst, const Operand &src)
void shld(Register dst, Register src)
const XMMRegister xmm15
void subl(Register dst, const Operand &src)
void sbbl(Register dst, Register src)
DwVfpRegister DoubleRegister
void fisttp_d(const Operand &adr)
static const int kRealPatchReturnSequenceAddressOffset
void movss(XMMRegister dst, const Operand &src)
void movb(Register dst, const Operand &src)
void set_byte_at(int pos, byte value)
void cvtsd2ss(XMMRegister dst, XMMRegister src)
void negl(Register dst)
static const int kSpecialTargetSize
const XMMRegister xmm1
void cmpl(Register dst, const Operand &src)
const int kRegister_r11_Code
void or_(const Operand &dst, Immediate src)
void movsd(XMMRegister dst, XMMRegister src)
void GetCode(CodeDesc *desc)
const Register r9
void movdqa(XMMRegister dst, const Operand &src)
void andl(Register dst, Register src)
void rol(Register dst, Immediate imm8)
static const int kJSReturnSequenceLength
void sar(Register dst, Immediate shift_amount)
static const byte kNopByte
int available_space() const
void movsxbq(Register dst, const Operand &src)
static void set_target_address_at(Address pc, Address target)
static const byte kJzShortOpcode
void movmskpd(Register dst, XMMRegister src)
void subq(const Operand &dst, Immediate src)
void fisttp_s(const Operand &adr)
void subq(Register dst, Immediate src)
void addl(const Operand &dst, Register src)
void movzxwq(Register dst, const Operand &src)
const Register rbx
void subb(Register dst, Immediate src)
void cmpb(const Operand &dst, Immediate src)
static void set_external_target_at(Address instruction_payload, Address target)
void cmpq(Register dst, Immediate src)
const Register rsp
void movzxwl(Register dst, const Operand &src)
const XMMRegister xmm10
const Register pc
void addl(Register dst, Immediate src)
const Register r12
void not_(Register dst)
static Register from_code(int code)
void set_emit_debug_code(bool value)
const int kRegister_r8_Code
void cmpb(Register dst, Immediate src)
const Register rax
void emit_sse_operand(XMMRegister reg, const Operand &adr)
const Register r13
const Register rdi
void cvtqsi2sd(XMMRegister dst, const Operand &src)
const int kRegister_r15_Code
void xorps(XMMRegister dst, XMMRegister src)
static const int kCallTargetAddressOffset
#define BASE_EMBEDDED
Definition: allocation.h:68
const int kRegister_rsi_Code
void subl(const Operand &dst, Immediate src)
void andb(Register dst, Immediate src)
static const int kDebugBreakSlotLength
void Nop(int bytes=1)
void neg(Register dst)
void setcc(Condition cc, Register reg)
const int kRegister_rbx_Code
void fld_s(const Operand &adr)
static bool IsNop(Instr instr, int type=NON_MARKING_NOP)
const int kRegister_r10_Code
bool is_int32(int64_t x)
Definition: assembler-x64.h:53
void decq(Register dst)
const XMMRegister xmm3
void fstp_d(const Operand &adr)
void movw(Register reg, uint32_t immediate, Condition cond=al)
static const int kNumAllocatableRegisters
static int ToAllocationIndex(XMMRegister reg)
bool is_valid() const
void store_rax(void *dst, RelocInfo::Mode mode)
void cmpq(const Operand &dst, Immediate src)
void push_imm32(int32_t imm32)
void fistp_d(const Operand &adr)
bool is(Register reg) const
static Address target_address_at(Address pc)
void cvtsd2siq(Register dst, XMMRegister src)
static const byte kTestEaxByte
void orl(const Operand &dst, Immediate src)
static const byte kJncShortOpcode
void shrd(Register dst, Register src)
void movaps(XMMRegister dst, XMMRegister src)
void rcr(Register dst, Immediate imm8)
void RecordComment(const char *msg)
static void deserialization_set_special_target_at(Address instruction_payload, Address target)
const XMMRegister xmm11
void fstp_s(const Operand &adr)
void divsd(XMMRegister dst, XMMRegister src)
void shrl_cl(Register dst)
void lea(Register dst, const Operand &src)
void fild_d(const Operand &adr)
void shll_cl(Register dst)
friend class PositionsRecorder
void shrl(Register dst, Immediate shift_amount)
const Register r8
static const int kNumAllocatableRegisters
Definition: assembler-arm.h:74
void andl(Register dst, Immediate src)
const Register rcx
Assembler(Isolate *isolate, void *buffer, int buffer_size)
void xorl(Register dst, Register src)
void movl(Register dst, Register src)
Condition NegateCondition(Condition cond)
#define ASSERT_EQ(v1, v2)
Definition: checks.h:271
void decb(Register dst)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination trace on stack replacement optimize closures functions with arguments object optimize functions containing for in loops profiler considers IC stability primitive functions trigger their own optimization re try self optimization if it failed insert an interrupt check at function exit execution budget before interrupt is triggered call count before self optimization self_optimization count_based_interrupts weighted_back_edges trace_opt emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 enable use of ARMv7 instructions if enable use of MIPS FPU instructions if NULL
Definition: flags.cc:274
const int kRegister_rdx_Code
static XMMRegister from_code(int code)
void cmpw(const Operand &dst, Register src)
const XMMRegister xmm9
void cmpq(Register dst, Register src)
void xor_(const Operand &dst, Register src)
void and_(Register dst, Immediate src)
void notl(Register dst)
void testq(const Operand &op, Register reg)
void sar_cl(Register dst)
void movd(XMMRegister dst, Register src)
void sbbq(Register dst, Register src)
PositionsRecorder * positions_recorder()
const uint32_t kMaxUInt32
Definition: globals.h:227
void fisub_s(const Operand &adr)
void or_(Register dst, const Operand &src)
const Register r10
void extractps(Register dst, XMMRegister src, byte imm8)
static const byte kJnzShortOpcode
void cmpw(Register dst, Immediate src)
Handle< Object > code_target_object_handle_at(Address pc)
void subl(Register dst, Immediate src)
void cmpb(Register dst, const Operand &src)
const Register no_reg
void xor_(const Operand &dst, Immediate src)
void subq(Register dst, const Operand &src)
static int ToAllocationIndex(Register reg)
const XMMRegister xmm8
void fist_s(const Operand &adr)
void cmpw(Register dst, Register src)
const XMMRegister xmm7
void rcl(Register dst, Immediate imm8)
bool is(XMMRegister reg) const
void and_(const Operand &dst, Immediate src)
const int kRegister_r9_Code
void movsxwq(Register dst, const Operand &src)
static const int kNumRegisters
const XMMRegister xmm2
void bts(Register dst, Register src)
void cmpq(const Operand &dst, Register src)
void sarl(Register dst, Immediate shift_amount)
void addl(Register dst, const Operand &src)
void cmovq(Condition cc, Register dst, Register src)
const int kRegister_rax_Code
static const int kPatchDebugBreakSlotAddressOffset
bool emit_debug_code() const
void subsd(XMMRegister dst, XMMRegister src)
const Register r15
bool uint_is_int32(uint64_t x)
Definition: assembler-x64.h:58
const int kRegister_rdi_Code
const int kRegister_no_reg_Code
void cvttsd2siq(Register dst, XMMRegister src)
void xor_(Register dst, Register src)
void movq(const Operand &dst, Register src)
void cmpl(const Operand &dst, Register src)
void addl(const Operand &dst, Immediate src)
void mul(Register dst, Register src1, Register src2, SBit s=LeaveCC, Condition cond=al)
void cvttsd2si(Register dst, const Operand &src)
void and_(Register dst, Register src)
void incq(Register dst)
void shl_cl(Register dst)
void leal(Register dst, const Operand &src)
const XMMRegister xmm0
const int MB
Definition: globals.h:222