assembler-ppc.h revision c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7a
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
6// are 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
14// distribution.
15//
16// - Neither the name of Sun Microsystems or the names of contributors may
17// be used to endorse or promote products derived from this software without
18// specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31// OF THE POSSIBILITY OF SUCH DAMAGE.
32
33// The original source code covered by the above license above has been
34// modified significantly by Google Inc.
35// Copyright 2014 the V8 project authors. All rights reserved.
36
37// A light-weight PPC Assembler
38// Generates user mode instructions for the PPC architecture up
39
40#ifndef V8_PPC_ASSEMBLER_PPC_H_
41#define V8_PPC_ASSEMBLER_PPC_H_
42
43#include <stdio.h>
44#include <vector>
45
46#include "src/assembler.h"
47#include "src/ppc/constants-ppc.h"
48
49#if V8_HOST_ARCH_PPC && \
50    (V8_OS_AIX || (V8_TARGET_ARCH_PPC64 && V8_TARGET_BIG_ENDIAN))
51#define ABI_USES_FUNCTION_DESCRIPTORS 1
52#else
53#define ABI_USES_FUNCTION_DESCRIPTORS 0
54#endif
55
56#if !V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64
57#define ABI_PASSES_HANDLES_IN_REGS 1
58#else
59#define ABI_PASSES_HANDLES_IN_REGS 0
60#endif
61
62#if !V8_HOST_ARCH_PPC || !V8_TARGET_ARCH_PPC64 || V8_TARGET_LITTLE_ENDIAN
63#define ABI_RETURNS_OBJECT_PAIRS_IN_REGS 1
64#else
65#define ABI_RETURNS_OBJECT_PAIRS_IN_REGS 0
66#endif
67
68#if !V8_HOST_ARCH_PPC || (V8_TARGET_ARCH_PPC64 && V8_TARGET_LITTLE_ENDIAN)
69#define ABI_CALL_VIA_IP 1
70#else
71#define ABI_CALL_VIA_IP 0
72#endif
73
74#if !V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64
75#define ABI_TOC_REGISTER 2
76#else
77#define ABI_TOC_REGISTER 13
78#endif
79
80#define INSTR_AND_DATA_CACHE_COHERENCY LWSYNC
81
82namespace v8 {
83namespace internal {
84
85// clang-format off
86#define GENERAL_REGISTERS(V)                              \
87  V(r0)  V(sp)  V(r2)  V(r3)  V(r4)  V(r5)  V(r6)  V(r7)  \
88  V(r8)  V(r9)  V(r10) V(r11) V(ip) V(r13) V(r14) V(r15)  \
89  V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \
90  V(r24) V(r25) V(r26) V(r27) V(r28) V(r29) V(r30) V(fp)
91
92#if V8_EMBEDDED_CONSTANT_POOL
93#define ALLOCATABLE_GENERAL_REGISTERS(V)                  \
94  V(r3)  V(r4)  V(r5)  V(r6)  V(r7)                       \
95  V(r8)  V(r9)  V(r10) V(r14) V(r15)                      \
96  V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \
97  V(r24) V(r25) V(r26) V(r27) V(r30)
98#else
99#define ALLOCATABLE_GENERAL_REGISTERS(V)                  \
100  V(r3)  V(r4)  V(r5)  V(r6)  V(r7)                       \
101  V(r8)  V(r9)  V(r10) V(r14) V(r15)                      \
102  V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \
103  V(r24) V(r25) V(r26) V(r27) V(r28) V(r30)
104#endif
105
106#define DOUBLE_REGISTERS(V)                               \
107  V(d0)  V(d1)  V(d2)  V(d3)  V(d4)  V(d5)  V(d6)  V(d7)  \
108  V(d8)  V(d9)  V(d10) V(d11) V(d12) V(d13) V(d14) V(d15) \
109  V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
110  V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
111
112#define FLOAT_REGISTERS DOUBLE_REGISTERS
113#define SIMD128_REGISTERS DOUBLE_REGISTERS
114
115#define ALLOCATABLE_DOUBLE_REGISTERS(V)                   \
116  V(d1)  V(d2)  V(d3)  V(d4)  V(d5)  V(d6)  V(d7)         \
117  V(d8)  V(d9)  V(d10) V(d11) V(d12) V(d15)               \
118  V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
119  V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
120// clang-format on
121
122// CPU Registers.
123//
124// 1) We would prefer to use an enum, but enum values are assignment-
125// compatible with int, which has caused code-generation bugs.
126//
127// 2) We would prefer to use a class instead of a struct but we don't like
128// the register initialization to depend on the particular initialization
129// order (which appears to be different on OS X, Linux, and Windows for the
130// installed versions of C++ we tried). Using a struct permits C-style
131// "initialization". Also, the Register objects cannot be const as this
132// forces initialization stubs in MSVC, making us dependent on initialization
133// order.
134//
135// 3) By not using an enum, we are possibly preventing the compiler from
136// doing certain constant folds, which may significantly reduce the
137// code generated for some assembly instructions (because they boil down
138// to a few constants). If this is a problem, we could change the code
139// such that we use an enum in optimized mode, and the struct in debug
140// mode. This way we get the compile-time error checking in debug mode
141// and best performance in optimized code.
142
143struct Register {
144  enum Code {
145#define REGISTER_CODE(R) kCode_##R,
146    GENERAL_REGISTERS(REGISTER_CODE)
147#undef REGISTER_CODE
148        kAfterLast,
149    kCode_no_reg = -1
150  };
151
152  static const int kNumRegisters = Code::kAfterLast;
153
154#define REGISTER_COUNT(R) 1 +
155  static const int kNumAllocatable =
156      ALLOCATABLE_GENERAL_REGISTERS(REGISTER_COUNT)0;
157#undef REGISTER_COUNT
158
159#define REGISTER_BIT(R) 1 << kCode_##R |
160  static const RegList kAllocatable =
161      ALLOCATABLE_GENERAL_REGISTERS(REGISTER_BIT)0;
162#undef REGISTER_BIT
163
164  static Register from_code(int code) {
165    DCHECK(code >= 0);
166    DCHECK(code < kNumRegisters);
167    Register r = {code};
168    return r;
169  }
170  bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
171  bool is(Register reg) const { return reg_code == reg.reg_code; }
172  int code() const {
173    DCHECK(is_valid());
174    return reg_code;
175  }
176  int bit() const {
177    DCHECK(is_valid());
178    return 1 << reg_code;
179  }
180  void set_code(int code) {
181    reg_code = code;
182    DCHECK(is_valid());
183  }
184
185#if V8_TARGET_LITTLE_ENDIAN
186  static const int kMantissaOffset = 0;
187  static const int kExponentOffset = 4;
188#else
189  static const int kMantissaOffset = 4;
190  static const int kExponentOffset = 0;
191#endif
192
193  // Unfortunately we can't make this private in a struct.
194  int reg_code;
195};
196
197#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
198GENERAL_REGISTERS(DECLARE_REGISTER)
199#undef DECLARE_REGISTER
200const Register no_reg = {Register::kCode_no_reg};
201
202// Aliases
203const Register kLithiumScratch = r11;        // lithium scratch.
204const Register kConstantPoolRegister = r28;  // Constant pool.
205const Register kRootRegister = r29;          // Roots array pointer.
206const Register cp = r30;                     // JavaScript context pointer.
207
208static const bool kSimpleFPAliasing = true;
209
210// Double word FP register.
211struct DoubleRegister {
212  enum Code {
213#define REGISTER_CODE(R) kCode_##R,
214    DOUBLE_REGISTERS(REGISTER_CODE)
215#undef REGISTER_CODE
216        kAfterLast,
217    kCode_no_reg = -1
218  };
219
220  static const int kNumRegisters = Code::kAfterLast;
221  static const int kMaxNumRegisters = kNumRegisters;
222
223  bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
224  bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
225  int code() const {
226    DCHECK(is_valid());
227    return reg_code;
228  }
229  int bit() const {
230    DCHECK(is_valid());
231    return 1 << reg_code;
232  }
233
234  static DoubleRegister from_code(int code) {
235    DoubleRegister r = {code};
236    return r;
237  }
238
239  int reg_code;
240};
241
242typedef DoubleRegister FloatRegister;
243
244// TODO(ppc) Define SIMD registers.
245typedef DoubleRegister Simd128Register;
246
247#define DECLARE_REGISTER(R) \
248  const DoubleRegister R = {DoubleRegister::kCode_##R};
249DOUBLE_REGISTERS(DECLARE_REGISTER)
250#undef DECLARE_REGISTER
251const Register no_dreg = {Register::kCode_no_reg};
252
253// Aliases for double registers.  Defined using #define instead of
254// "static const DoubleRegister&" because Clang complains otherwise when a
255// compilation unit that includes this header doesn't use the variables.
256#define kFirstCalleeSavedDoubleReg d14
257#define kLastCalleeSavedDoubleReg d31
258#define kDoubleRegZero d14
259#define kScratchDoubleReg d13
260
261Register ToRegister(int num);
262
263// Coprocessor register
264struct CRegister {
265  bool is_valid() const { return 0 <= reg_code && reg_code < 8; }
266  bool is(CRegister creg) const { return reg_code == creg.reg_code; }
267  int code() const {
268    DCHECK(is_valid());
269    return reg_code;
270  }
271  int bit() const {
272    DCHECK(is_valid());
273    return 1 << reg_code;
274  }
275
276  // Unfortunately we can't make this private in a struct.
277  int reg_code;
278};
279
280
281const CRegister no_creg = {-1};
282
283const CRegister cr0 = {0};
284const CRegister cr1 = {1};
285const CRegister cr2 = {2};
286const CRegister cr3 = {3};
287const CRegister cr4 = {4};
288const CRegister cr5 = {5};
289const CRegister cr6 = {6};
290const CRegister cr7 = {7};
291
292// -----------------------------------------------------------------------------
293// Machine instruction Operands
294
295#if V8_TARGET_ARCH_PPC64
296const RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE64;
297#else
298const RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE32;
299#endif
300
301// Class Operand represents a shifter operand in data processing instructions
302class Operand BASE_EMBEDDED {
303 public:
304  // immediate
305  INLINE(explicit Operand(intptr_t immediate,
306                          RelocInfo::Mode rmode = kRelocInfo_NONEPTR));
307  INLINE(static Operand Zero()) { return Operand(static_cast<intptr_t>(0)); }
308  INLINE(explicit Operand(const ExternalReference& f));
309  explicit Operand(Handle<Object> handle);
310  INLINE(explicit Operand(Smi* value));
311
312  // rm
313  INLINE(explicit Operand(Register rm));
314
315  // Return true if this is a register operand.
316  INLINE(bool is_reg() const);
317
318  bool must_output_reloc_info(const Assembler* assembler) const;
319
320  inline intptr_t immediate() const {
321    DCHECK(!rm_.is_valid());
322    return imm_;
323  }
324
325  Register rm() const { return rm_; }
326
327 private:
328  Register rm_;
329  intptr_t imm_;  // valid if rm_ == no_reg
330  RelocInfo::Mode rmode_;
331
332  friend class Assembler;
333  friend class MacroAssembler;
334};
335
336
337// Class MemOperand represents a memory operand in load and store instructions
338// On PowerPC we have base register + 16bit signed value
339// Alternatively we can have a 16bit signed value immediate
340class MemOperand BASE_EMBEDDED {
341 public:
342  explicit MemOperand(Register rn, int32_t offset = 0);
343
344  explicit MemOperand(Register ra, Register rb);
345
346  int32_t offset() const {
347    DCHECK(rb_.is(no_reg));
348    return offset_;
349  }
350
351  // PowerPC - base register
352  Register ra() const {
353    DCHECK(!ra_.is(no_reg));
354    return ra_;
355  }
356
357  Register rb() const {
358    DCHECK(offset_ == 0 && !rb_.is(no_reg));
359    return rb_;
360  }
361
362 private:
363  Register ra_;     // base
364  int32_t offset_;  // offset
365  Register rb_;     // index
366
367  friend class Assembler;
368};
369
370
371class DeferredRelocInfo {
372 public:
373  DeferredRelocInfo() {}
374  DeferredRelocInfo(int position, RelocInfo::Mode rmode, intptr_t data)
375      : position_(position), rmode_(rmode), data_(data) {}
376
377  int position() const { return position_; }
378  RelocInfo::Mode rmode() const { return rmode_; }
379  intptr_t data() const { return data_; }
380
381 private:
382  int position_;
383  RelocInfo::Mode rmode_;
384  intptr_t data_;
385};
386
387
388class Assembler : public AssemblerBase {
389 public:
390  // Create an assembler. Instructions and relocation information are emitted
391  // into a buffer, with the instructions starting from the beginning and the
392  // relocation information starting from the end of the buffer. See CodeDesc
393  // for a detailed comment on the layout (globals.h).
394  //
395  // If the provided buffer is NULL, the assembler allocates and grows its own
396  // buffer, and buffer_size determines the initial buffer size. The buffer is
397  // owned by the assembler and deallocated upon destruction of the assembler.
398  //
399  // If the provided buffer is not NULL, the assembler uses the provided buffer
400  // for code generation and assumes its size to be buffer_size. If the buffer
401  // is too small, a fatal error occurs. No deallocation of the buffer is done
402  // upon destruction of the assembler.
403  Assembler(Isolate* isolate, void* buffer, int buffer_size);
404  virtual ~Assembler() {}
405
406  // GetCode emits any pending (non-emitted) code and fills the descriptor
407  // desc. GetCode() is idempotent; it returns the same result if no other
408  // Assembler functions are invoked in between GetCode() calls.
409  void GetCode(CodeDesc* desc);
410
411  // Label operations & relative jumps (PPUM Appendix D)
412  //
413  // Takes a branch opcode (cc) and a label (L) and generates
414  // either a backward branch or a forward branch and links it
415  // to the label fixup chain. Usage:
416  //
417  // Label L;    // unbound label
418  // j(cc, &L);  // forward branch to unbound label
419  // bind(&L);   // bind label to the current pc
420  // j(cc, &L);  // backward branch to bound label
421  // bind(&L);   // illegal: a label may be bound only once
422  //
423  // Note: The same Label can be used for forward and backward branches
424  // but it may be bound only once.
425
426  void bind(Label* L);  // binds an unbound label L to the current code position
427
428  // Links a label at the current pc_offset().  If already bound, returns the
429  // bound position.  If already linked, returns the position of the prior link.
430  // Otherwise, returns the current pc_offset().
431  int link(Label* L);
432
433  // Determines if Label is bound and near enough so that a single
434  // branch instruction can be used to reach it.
435  bool is_near(Label* L, Condition cond);
436
437  // Returns the branch offset to the given label from the current code position
438  // Links the label to the current position if it is still unbound
439  int branch_offset(Label* L) {
440    if (L->is_unused() && !trampoline_emitted_) {
441      TrackBranch();
442    }
443    return link(L) - pc_offset();
444  }
445
446  // Puts a labels target address at the given position.
447  // The high 8 bits are set to zero.
448  void label_at_put(Label* L, int at_offset);
449
450  INLINE(static bool IsConstantPoolLoadStart(
451      Address pc, ConstantPoolEntry::Access* access = nullptr));
452  INLINE(static bool IsConstantPoolLoadEnd(
453      Address pc, ConstantPoolEntry::Access* access = nullptr));
454  INLINE(static int GetConstantPoolOffset(Address pc,
455                                          ConstantPoolEntry::Access access,
456                                          ConstantPoolEntry::Type type));
457  INLINE(void PatchConstantPoolAccessInstruction(
458      int pc_offset, int offset, ConstantPoolEntry::Access access,
459      ConstantPoolEntry::Type type));
460
461  // Return the address in the constant pool of the code target address used by
462  // the branch/call instruction at pc, or the object in a mov.
463  INLINE(static Address target_constant_pool_address_at(
464      Address pc, Address constant_pool, ConstantPoolEntry::Access access,
465      ConstantPoolEntry::Type type));
466
467  // Read/Modify the code target address in the branch/call instruction at pc.
468  INLINE(static Address target_address_at(Address pc, Address constant_pool));
469  INLINE(static void set_target_address_at(
470      Isolate* isolate, Address pc, Address constant_pool, Address target,
471      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
472  INLINE(static Address target_address_at(Address pc, Code* code)) {
473    Address constant_pool = code ? code->constant_pool() : NULL;
474    return target_address_at(pc, constant_pool);
475  }
476  INLINE(static void set_target_address_at(
477      Isolate* isolate, Address pc, Code* code, Address target,
478      ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)) {
479    Address constant_pool = code ? code->constant_pool() : NULL;
480    set_target_address_at(isolate, pc, constant_pool, target,
481                          icache_flush_mode);
482  }
483
484  // Return the code target address at a call site from the return address
485  // of that call in the instruction stream.
486  inline static Address target_address_from_return_address(Address pc);
487
488  // Given the address of the beginning of a call, return the address
489  // in the instruction stream that the call will return to.
490  INLINE(static Address return_address_from_call_start(Address pc));
491
492  // This sets the branch destination.
493  // This is for calls and branches within generated code.
494  inline static void deserialization_set_special_target_at(
495      Isolate* isolate, Address instruction_payload, Code* code,
496      Address target);
497
498  // This sets the internal reference at the pc.
499  inline static void deserialization_set_target_internal_reference_at(
500      Isolate* isolate, Address pc, Address target,
501      RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
502
503  // Size of an instruction.
504  static const int kInstrSize = sizeof(Instr);
505
506  // Here we are patching the address in the LUI/ORI instruction pair.
507  // These values are used in the serialization process and must be zero for
508  // PPC platform, as Code, Embedded Object or External-reference pointers
509  // are split across two consecutive instructions and don't exist separately
510  // in the code, so the serializer should not step forwards in memory after
511  // a target is resolved and written.
512  static const int kSpecialTargetSize = 0;
513
514// Number of instructions to load an address via a mov sequence.
515#if V8_TARGET_ARCH_PPC64
516  static const int kMovInstructionsConstantPool = 1;
517  static const int kMovInstructionsNoConstantPool = 5;
518#if defined(V8_PPC_TAGGING_OPT)
519  static const int kTaggedLoadInstructions = 1;
520#else
521  static const int kTaggedLoadInstructions = 2;
522#endif
523#else
524  static const int kMovInstructionsConstantPool = 1;
525  static const int kMovInstructionsNoConstantPool = 2;
526  static const int kTaggedLoadInstructions = 1;
527#endif
528  static const int kMovInstructions = FLAG_enable_embedded_constant_pool
529                                          ? kMovInstructionsConstantPool
530                                          : kMovInstructionsNoConstantPool;
531
532  // Distance between the instruction referring to the address of the call
533  // target and the return address.
534
535  // Call sequence is a FIXED_SEQUENCE:
536  // mov     r8, @ call address
537  // mtlr    r8
538  // blrl
539  //                      @ return address
540  static const int kCallTargetAddressOffset =
541      (kMovInstructions + 2) * kInstrSize;
542
543  // Distance between start of patched debug break slot and the emitted address
544  // to jump to.
545  // Patched debug break slot code is a FIXED_SEQUENCE:
546  //   mov r0, <address>
547  //   mtlr r0
548  //   blrl
549  static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize;
550
551  // This is the length of the code sequence from SetDebugBreakAtSlot()
552  // FIXED_SEQUENCE
553  static const int kDebugBreakSlotInstructions =
554      kMovInstructionsNoConstantPool + 2;
555  static const int kDebugBreakSlotLength =
556      kDebugBreakSlotInstructions * kInstrSize;
557
558  static inline int encode_crbit(const CRegister& cr, enum CRBit crbit) {
559    return ((cr.code() * CRWIDTH) + crbit);
560  }
561
562  // ---------------------------------------------------------------------------
563  // Code generation
564
565  // Insert the smallest number of nop instructions
566  // possible to align the pc offset to a multiple
567  // of m. m must be a power of 2 (>= 4).
568  void Align(int m);
569  // Insert the smallest number of zero bytes possible to align the pc offset
570  // to a mulitple of m. m must be a power of 2 (>= 2).
571  void DataAlign(int m);
572  // Aligns code to something that's optimal for a jump target for the platform.
573  void CodeTargetAlign();
574
575  // Branch instructions
576  void bclr(BOfield bo, int condition_bit, LKBit lk);
577  void blr();
578  void bc(int branch_offset, BOfield bo, int condition_bit, LKBit lk = LeaveLK);
579  void b(int branch_offset, LKBit lk);
580
581  void bcctr(BOfield bo, int condition_bit, LKBit lk);
582  void bctr();
583  void bctrl();
584
585  // Convenience branch instructions using labels
586  void b(Label* L, LKBit lk = LeaveLK) { b(branch_offset(L), lk); }
587
588  inline CRegister cmpi_optimization(CRegister cr) {
589    // Check whether the branch is preceeded by an optimizable cmpi against 0.
590    // The cmpi can be deleted if it is also preceeded by an instruction that
591    // sets the register used by the compare and supports a dot form.
592    unsigned int sradi_mask = kOpcodeMask | kExt2OpcodeVariant2Mask;
593    unsigned int srawi_mask = kOpcodeMask | kExt2OpcodeMask;
594    int pos = pc_offset();
595    int cmpi_pos = pc_offset() - kInstrSize;
596
597    if (cmpi_pos > 0 && optimizable_cmpi_pos_ == cmpi_pos &&
598        cmpi_cr_.code() == cr.code() && last_bound_pos_ != pos) {
599      int xpos = cmpi_pos - kInstrSize;
600      int xinstr = instr_at(xpos);
601      int cmpi_ra = (instr_at(cmpi_pos) & 0x1f0000) >> 16;
602      // ra is at the same bit position for the three cases below.
603      int ra = (xinstr & 0x1f0000) >> 16;
604      if (cmpi_ra == ra) {
605        if ((xinstr & sradi_mask) == (EXT2 | SRADIX)) {
606          cr = cr0;
607          instr_at_put(xpos, xinstr | SetRC);
608          pc_ -= kInstrSize;
609        } else if ((xinstr & srawi_mask) == (EXT2 | SRAWIX)) {
610          cr = cr0;
611          instr_at_put(xpos, xinstr | SetRC);
612          pc_ -= kInstrSize;
613        } else if ((xinstr & kOpcodeMask) == ANDIx) {
614          cr = cr0;
615          pc_ -= kInstrSize;
616          // nothing to do here since andi. records.
617        }
618        // didn't match one of the above, must keep cmpwi.
619      }
620    }
621    return cr;
622  }
623
624  void bc_short(Condition cond, Label* L, CRegister cr = cr7,
625                LKBit lk = LeaveLK) {
626    DCHECK(cond != al);
627    DCHECK(cr.code() >= 0 && cr.code() <= 7);
628
629    cr = cmpi_optimization(cr);
630
631    int b_offset = branch_offset(L);
632
633    switch (cond) {
634      case eq:
635        bc(b_offset, BT, encode_crbit(cr, CR_EQ), lk);
636        break;
637      case ne:
638        bc(b_offset, BF, encode_crbit(cr, CR_EQ), lk);
639        break;
640      case gt:
641        bc(b_offset, BT, encode_crbit(cr, CR_GT), lk);
642        break;
643      case le:
644        bc(b_offset, BF, encode_crbit(cr, CR_GT), lk);
645        break;
646      case lt:
647        bc(b_offset, BT, encode_crbit(cr, CR_LT), lk);
648        break;
649      case ge:
650        bc(b_offset, BF, encode_crbit(cr, CR_LT), lk);
651        break;
652      case unordered:
653        bc(b_offset, BT, encode_crbit(cr, CR_FU), lk);
654        break;
655      case ordered:
656        bc(b_offset, BF, encode_crbit(cr, CR_FU), lk);
657        break;
658      case overflow:
659        bc(b_offset, BT, encode_crbit(cr, CR_SO), lk);
660        break;
661      case nooverflow:
662        bc(b_offset, BF, encode_crbit(cr, CR_SO), lk);
663        break;
664      default:
665        UNIMPLEMENTED();
666    }
667  }
668
669  void bclr(Condition cond, CRegister cr = cr7, LKBit lk = LeaveLK) {
670    DCHECK(cond != al);
671    DCHECK(cr.code() >= 0 && cr.code() <= 7);
672
673    cr = cmpi_optimization(cr);
674
675    switch (cond) {
676      case eq:
677        bclr(BT, encode_crbit(cr, CR_EQ), lk);
678        break;
679      case ne:
680        bclr(BF, encode_crbit(cr, CR_EQ), lk);
681        break;
682      case gt:
683        bclr(BT, encode_crbit(cr, CR_GT), lk);
684        break;
685      case le:
686        bclr(BF, encode_crbit(cr, CR_GT), lk);
687        break;
688      case lt:
689        bclr(BT, encode_crbit(cr, CR_LT), lk);
690        break;
691      case ge:
692        bclr(BF, encode_crbit(cr, CR_LT), lk);
693        break;
694      case unordered:
695        bclr(BT, encode_crbit(cr, CR_FU), lk);
696        break;
697      case ordered:
698        bclr(BF, encode_crbit(cr, CR_FU), lk);
699        break;
700      case overflow:
701        bclr(BT, encode_crbit(cr, CR_SO), lk);
702        break;
703      case nooverflow:
704        bclr(BF, encode_crbit(cr, CR_SO), lk);
705        break;
706      default:
707        UNIMPLEMENTED();
708    }
709  }
710
711  void isel(Register rt, Register ra, Register rb, int cb);
712  void isel(Condition cond, Register rt, Register ra, Register rb,
713            CRegister cr = cr7) {
714    DCHECK(cond != al);
715    DCHECK(cr.code() >= 0 && cr.code() <= 7);
716
717    cr = cmpi_optimization(cr);
718
719    switch (cond) {
720      case eq:
721        isel(rt, ra, rb, encode_crbit(cr, CR_EQ));
722        break;
723      case ne:
724        isel(rt, rb, ra, encode_crbit(cr, CR_EQ));
725        break;
726      case gt:
727        isel(rt, ra, rb, encode_crbit(cr, CR_GT));
728        break;
729      case le:
730        isel(rt, rb, ra, encode_crbit(cr, CR_GT));
731        break;
732      case lt:
733        isel(rt, ra, rb, encode_crbit(cr, CR_LT));
734        break;
735      case ge:
736        isel(rt, rb, ra, encode_crbit(cr, CR_LT));
737        break;
738      case unordered:
739        isel(rt, ra, rb, encode_crbit(cr, CR_FU));
740        break;
741      case ordered:
742        isel(rt, rb, ra, encode_crbit(cr, CR_FU));
743        break;
744      case overflow:
745        isel(rt, ra, rb, encode_crbit(cr, CR_SO));
746        break;
747      case nooverflow:
748        isel(rt, rb, ra, encode_crbit(cr, CR_SO));
749        break;
750      default:
751        UNIMPLEMENTED();
752    }
753  }
754
755  void b(Condition cond, Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
756    if (cond == al) {
757      b(L, lk);
758      return;
759    }
760
761    if ((L->is_bound() && is_near(L, cond)) || !is_trampoline_emitted()) {
762      bc_short(cond, L, cr, lk);
763      return;
764    }
765
766    Label skip;
767    Condition neg_cond = NegateCondition(cond);
768    bc_short(neg_cond, &skip, cr);
769    b(L, lk);
770    bind(&skip);
771  }
772
773  void bne(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
774    b(ne, L, cr, lk);
775  }
776  void beq(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
777    b(eq, L, cr, lk);
778  }
779  void blt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
780    b(lt, L, cr, lk);
781  }
782  void bge(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
783    b(ge, L, cr, lk);
784  }
785  void ble(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
786    b(le, L, cr, lk);
787  }
788  void bgt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
789    b(gt, L, cr, lk);
790  }
791  void bunordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
792    b(unordered, L, cr, lk);
793  }
794  void bordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
795    b(ordered, L, cr, lk);
796  }
797  void boverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
798    b(overflow, L, cr, lk);
799  }
800  void bnooverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
801    b(nooverflow, L, cr, lk);
802  }
803
804  // Decrement CTR; branch if CTR != 0
805  void bdnz(Label* L, LKBit lk = LeaveLK) {
806    bc(branch_offset(L), DCBNZ, 0, lk);
807  }
808
809  // Data-processing instructions
810
811  void sub(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
812           RCBit r = LeaveRC);
813
814  void subc(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
815            RCBit r = LeaveRC);
816  void sube(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
817            RCBit r = LeaveRC);
818
819  void subfic(Register dst, Register src, const Operand& imm);
820
821  void add(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
822           RCBit r = LeaveRC);
823
824  void addc(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
825            RCBit r = LeaveRC);
826  void adde(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
827            RCBit r = LeaveRC);
828  void addze(Register dst, Register src1, OEBit o = LeaveOE, RCBit r = LeaveRC);
829
830  void mullw(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
831             RCBit r = LeaveRC);
832
833  void mulhw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
834  void mulhwu(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
835
836  void divw(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
837            RCBit r = LeaveRC);
838  void divwu(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
839             RCBit r = LeaveRC);
840
841  void addi(Register dst, Register src, const Operand& imm);
842  void addis(Register dst, Register src, const Operand& imm);
843  void addic(Register dst, Register src, const Operand& imm);
844
845  void and_(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
846  void andc(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
847  void andi(Register ra, Register rs, const Operand& imm);
848  void andis(Register ra, Register rs, const Operand& imm);
849  void nor(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
850  void notx(Register dst, Register src, RCBit r = LeaveRC);
851  void ori(Register dst, Register src, const Operand& imm);
852  void oris(Register dst, Register src, const Operand& imm);
853  void orx(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
854  void orc(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
855  void xori(Register dst, Register src, const Operand& imm);
856  void xoris(Register ra, Register rs, const Operand& imm);
857  void xor_(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
858  void cmpi(Register src1, const Operand& src2, CRegister cr = cr7);
859  void cmpli(Register src1, const Operand& src2, CRegister cr = cr7);
860  void cmpwi(Register src1, const Operand& src2, CRegister cr = cr7);
861  void cmplwi(Register src1, const Operand& src2, CRegister cr = cr7);
862  void li(Register dst, const Operand& src);
863  void lis(Register dst, const Operand& imm);
864  void mr(Register dst, Register src);
865
866  void lbz(Register dst, const MemOperand& src);
867  void lbzx(Register dst, const MemOperand& src);
868  void lbzux(Register dst, const MemOperand& src);
869  void lhz(Register dst, const MemOperand& src);
870  void lhzx(Register dst, const MemOperand& src);
871  void lhzux(Register dst, const MemOperand& src);
872  void lha(Register dst, const MemOperand& src);
873  void lhax(Register dst, const MemOperand& src);
874  void lwz(Register dst, const MemOperand& src);
875  void lwzu(Register dst, const MemOperand& src);
876  void lwzx(Register dst, const MemOperand& src);
877  void lwzux(Register dst, const MemOperand& src);
878  void lwa(Register dst, const MemOperand& src);
879  void lwax(Register dst, const MemOperand& src);
880  void ldbrx(Register dst, const MemOperand& src);
881  void lwbrx(Register dst, const MemOperand& src);
882  void lhbrx(Register dst, const MemOperand& src);
883  void stb(Register dst, const MemOperand& src);
884  void stbx(Register dst, const MemOperand& src);
885  void stbux(Register dst, const MemOperand& src);
886  void sth(Register dst, const MemOperand& src);
887  void sthx(Register dst, const MemOperand& src);
888  void sthux(Register dst, const MemOperand& src);
889  void stw(Register dst, const MemOperand& src);
890  void stwu(Register dst, const MemOperand& src);
891  void stwx(Register rs, const MemOperand& src);
892  void stwux(Register rs, const MemOperand& src);
893
894  void extsb(Register rs, Register ra, RCBit r = LeaveRC);
895  void extsh(Register rs, Register ra, RCBit r = LeaveRC);
896  void extsw(Register rs, Register ra, RCBit r = LeaveRC);
897
898  void neg(Register rt, Register ra, OEBit o = LeaveOE, RCBit c = LeaveRC);
899
900#if V8_TARGET_ARCH_PPC64
901  void ld(Register rd, const MemOperand& src);
902  void ldx(Register rd, const MemOperand& src);
903  void ldu(Register rd, const MemOperand& src);
904  void ldux(Register rd, const MemOperand& src);
905  void std(Register rs, const MemOperand& src);
906  void stdx(Register rs, const MemOperand& src);
907  void stdu(Register rs, const MemOperand& src);
908  void stdux(Register rs, const MemOperand& src);
909  void rldic(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
910  void rldicl(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
911  void rldcl(Register ra, Register rs, Register rb, int mb, RCBit r = LeaveRC);
912  void rldicr(Register dst, Register src, int sh, int me, RCBit r = LeaveRC);
913  void rldimi(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
914  void sldi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
915  void srdi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
916  void clrrdi(Register dst, Register src, const Operand& val,
917              RCBit rc = LeaveRC);
918  void clrldi(Register dst, Register src, const Operand& val,
919              RCBit rc = LeaveRC);
920  void sradi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
921  void srd(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
922  void sld(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
923  void srad(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
924  void rotld(Register ra, Register rs, Register rb, RCBit r = LeaveRC);
925  void rotldi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
926  void rotrdi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
927  void cntlzd_(Register dst, Register src, RCBit rc = LeaveRC);
928  void popcntd(Register dst, Register src);
929  void mulld(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
930             RCBit r = LeaveRC);
931  void divd(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
932            RCBit r = LeaveRC);
933  void divdu(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
934             RCBit r = LeaveRC);
935#endif
936
937  void rlwinm(Register ra, Register rs, int sh, int mb, int me,
938              RCBit rc = LeaveRC);
939  void rlwimi(Register ra, Register rs, int sh, int mb, int me,
940              RCBit rc = LeaveRC);
941  void rlwnm(Register ra, Register rs, Register rb, int mb, int me,
942             RCBit rc = LeaveRC);
943  void slwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
944  void srwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
945  void clrrwi(Register dst, Register src, const Operand& val,
946              RCBit rc = LeaveRC);
947  void clrlwi(Register dst, Register src, const Operand& val,
948              RCBit rc = LeaveRC);
949  void srawi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
950  void srw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
951  void slw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
952  void sraw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
953  void rotlw(Register ra, Register rs, Register rb, RCBit r = LeaveRC);
954  void rotlwi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
955  void rotrwi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
956
957  void cntlzw_(Register dst, Register src, RCBit rc = LeaveRC);
958  void popcntw(Register dst, Register src);
959
960  void subi(Register dst, Register src1, const Operand& src2);
961
962  void cmp(Register src1, Register src2, CRegister cr = cr7);
963  void cmpl(Register src1, Register src2, CRegister cr = cr7);
964  void cmpw(Register src1, Register src2, CRegister cr = cr7);
965  void cmplw(Register src1, Register src2, CRegister cr = cr7);
966
967  void mov(Register dst, const Operand& src);
968  void bitwise_mov(Register dst, intptr_t value);
969  void bitwise_mov32(Register dst, int32_t value);
970  void bitwise_add32(Register dst, Register src, int32_t value);
971
972  // Load the position of the label relative to the generated code object
973  // pointer in a register.
974  void mov_label_offset(Register dst, Label* label);
975
976  // dst = base + label position + delta
977  void add_label_offset(Register dst, Register base, Label* label,
978                        int delta = 0);
979
980  // Load the address of the label in a register and associate with an
981  // internal reference relocation.
982  void mov_label_addr(Register dst, Label* label);
983
984  // Emit the address of the label (i.e. a jump table entry) and associate with
985  // an internal reference relocation.
986  void emit_label_addr(Label* label);
987
988  // Multiply instructions
989  void mul(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
990           RCBit r = LeaveRC);
991
992  // Miscellaneous arithmetic instructions
993
994  // Special register access
995  void crxor(int bt, int ba, int bb);
996  void crclr(int bt) { crxor(bt, bt, bt); }
997  void creqv(int bt, int ba, int bb);
998  void crset(int bt) { creqv(bt, bt, bt); }
999  void mflr(Register dst);
1000  void mtlr(Register src);
1001  void mtctr(Register src);
1002  void mtxer(Register src);
1003  void mcrfs(CRegister cr, FPSCRBit bit);
1004  void mfcr(Register dst);
1005#if V8_TARGET_ARCH_PPC64
1006  void mffprd(Register dst, DoubleRegister src);
1007  void mffprwz(Register dst, DoubleRegister src);
1008  void mtfprd(DoubleRegister dst, Register src);
1009  void mtfprwz(DoubleRegister dst, Register src);
1010  void mtfprwa(DoubleRegister dst, Register src);
1011#endif
1012
1013  void function_descriptor();
1014
1015  // Exception-generating instructions and debugging support
1016  void stop(const char* msg, Condition cond = al,
1017            int32_t code = kDefaultStopCode, CRegister cr = cr7);
1018
1019  void bkpt(uint32_t imm16);  // v5 and above
1020
1021  void dcbf(Register ra, Register rb);
1022  void sync();
1023  void lwsync();
1024  void icbi(Register ra, Register rb);
1025  void isync();
1026
1027  // Support for floating point
1028  void lfd(const DoubleRegister frt, const MemOperand& src);
1029  void lfdu(const DoubleRegister frt, const MemOperand& src);
1030  void lfdx(const DoubleRegister frt, const MemOperand& src);
1031  void lfdux(const DoubleRegister frt, const MemOperand& src);
1032  void lfs(const DoubleRegister frt, const MemOperand& src);
1033  void lfsu(const DoubleRegister frt, const MemOperand& src);
1034  void lfsx(const DoubleRegister frt, const MemOperand& src);
1035  void lfsux(const DoubleRegister frt, const MemOperand& src);
1036  void stfd(const DoubleRegister frs, const MemOperand& src);
1037  void stfdu(const DoubleRegister frs, const MemOperand& src);
1038  void stfdx(const DoubleRegister frs, const MemOperand& src);
1039  void stfdux(const DoubleRegister frs, const MemOperand& src);
1040  void stfs(const DoubleRegister frs, const MemOperand& src);
1041  void stfsu(const DoubleRegister frs, const MemOperand& src);
1042  void stfsx(const DoubleRegister frs, const MemOperand& src);
1043  void stfsux(const DoubleRegister frs, const MemOperand& src);
1044
1045  void fadd(const DoubleRegister frt, const DoubleRegister fra,
1046            const DoubleRegister frb, RCBit rc = LeaveRC);
1047  void fsub(const DoubleRegister frt, const DoubleRegister fra,
1048            const DoubleRegister frb, RCBit rc = LeaveRC);
1049  void fdiv(const DoubleRegister frt, const DoubleRegister fra,
1050            const DoubleRegister frb, RCBit rc = LeaveRC);
1051  void fmul(const DoubleRegister frt, const DoubleRegister fra,
1052            const DoubleRegister frc, RCBit rc = LeaveRC);
1053  void fcmpu(const DoubleRegister fra, const DoubleRegister frb,
1054             CRegister cr = cr7);
1055  void fmr(const DoubleRegister frt, const DoubleRegister frb,
1056           RCBit rc = LeaveRC);
1057  void fctiwz(const DoubleRegister frt, const DoubleRegister frb);
1058  void fctiw(const DoubleRegister frt, const DoubleRegister frb);
1059  void frin(const DoubleRegister frt, const DoubleRegister frb,
1060            RCBit rc = LeaveRC);
1061  void friz(const DoubleRegister frt, const DoubleRegister frb,
1062            RCBit rc = LeaveRC);
1063  void frip(const DoubleRegister frt, const DoubleRegister frb,
1064            RCBit rc = LeaveRC);
1065  void frim(const DoubleRegister frt, const DoubleRegister frb,
1066            RCBit rc = LeaveRC);
1067  void frsp(const DoubleRegister frt, const DoubleRegister frb,
1068            RCBit rc = LeaveRC);
1069  void fcfid(const DoubleRegister frt, const DoubleRegister frb,
1070             RCBit rc = LeaveRC);
1071  void fcfidu(const DoubleRegister frt, const DoubleRegister frb,
1072              RCBit rc = LeaveRC);
1073  void fcfidus(const DoubleRegister frt, const DoubleRegister frb,
1074               RCBit rc = LeaveRC);
1075  void fcfids(const DoubleRegister frt, const DoubleRegister frb,
1076              RCBit rc = LeaveRC);
1077  void fctid(const DoubleRegister frt, const DoubleRegister frb,
1078             RCBit rc = LeaveRC);
1079  void fctidz(const DoubleRegister frt, const DoubleRegister frb,
1080              RCBit rc = LeaveRC);
1081  void fctidu(const DoubleRegister frt, const DoubleRegister frb,
1082              RCBit rc = LeaveRC);
1083  void fctiduz(const DoubleRegister frt, const DoubleRegister frb,
1084               RCBit rc = LeaveRC);
1085  void fsel(const DoubleRegister frt, const DoubleRegister fra,
1086            const DoubleRegister frc, const DoubleRegister frb,
1087            RCBit rc = LeaveRC);
1088  void fneg(const DoubleRegister frt, const DoubleRegister frb,
1089            RCBit rc = LeaveRC);
1090  void mtfsb0(FPSCRBit bit, RCBit rc = LeaveRC);
1091  void mtfsb1(FPSCRBit bit, RCBit rc = LeaveRC);
1092  void mtfsfi(int bf, int immediate, RCBit rc = LeaveRC);
1093  void mffs(const DoubleRegister frt, RCBit rc = LeaveRC);
1094  void mtfsf(const DoubleRegister frb, bool L = 1, int FLM = 0, bool W = 0,
1095             RCBit rc = LeaveRC);
1096  void fsqrt(const DoubleRegister frt, const DoubleRegister frb,
1097             RCBit rc = LeaveRC);
1098  void fabs(const DoubleRegister frt, const DoubleRegister frb,
1099            RCBit rc = LeaveRC);
1100  void fmadd(const DoubleRegister frt, const DoubleRegister fra,
1101             const DoubleRegister frc, const DoubleRegister frb,
1102             RCBit rc = LeaveRC);
1103  void fmsub(const DoubleRegister frt, const DoubleRegister fra,
1104             const DoubleRegister frc, const DoubleRegister frb,
1105             RCBit rc = LeaveRC);
1106
1107  // Pseudo instructions
1108
1109  // Different nop operations are used by the code generator to detect certain
1110  // states of the generated code.
1111  enum NopMarkerTypes {
1112    NON_MARKING_NOP = 0,
1113    GROUP_ENDING_NOP,
1114    DEBUG_BREAK_NOP,
1115    // IC markers.
1116    PROPERTY_ACCESS_INLINED,
1117    PROPERTY_ACCESS_INLINED_CONTEXT,
1118    PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1119    // Helper values.
1120    LAST_CODE_MARKER,
1121    FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1122  };
1123
1124  void nop(int type = 0);  // 0 is the default non-marking type.
1125
1126  void push(Register src) {
1127#if V8_TARGET_ARCH_PPC64
1128    stdu(src, MemOperand(sp, -kPointerSize));
1129#else
1130    stwu(src, MemOperand(sp, -kPointerSize));
1131#endif
1132  }
1133
1134  void pop(Register dst) {
1135#if V8_TARGET_ARCH_PPC64
1136    ld(dst, MemOperand(sp));
1137#else
1138    lwz(dst, MemOperand(sp));
1139#endif
1140    addi(sp, sp, Operand(kPointerSize));
1141  }
1142
1143  void pop() { addi(sp, sp, Operand(kPointerSize)); }
1144
1145  // Jump unconditionally to given label.
1146  void jmp(Label* L) { b(L); }
1147
1148  // Check the code size generated from label to here.
1149  int SizeOfCodeGeneratedSince(Label* label) {
1150    return pc_offset() - label->pos();
1151  }
1152
1153  // Check the number of instructions generated from label to here.
1154  int InstructionsGeneratedSince(Label* label) {
1155    return SizeOfCodeGeneratedSince(label) / kInstrSize;
1156  }
1157
1158  // Class for scoping postponing the trampoline pool generation.
1159  class BlockTrampolinePoolScope {
1160   public:
1161    explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) {
1162      assem_->StartBlockTrampolinePool();
1163    }
1164    ~BlockTrampolinePoolScope() { assem_->EndBlockTrampolinePool(); }
1165
1166   private:
1167    Assembler* assem_;
1168
1169    DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope);
1170  };
1171
1172  // Class for scoping disabling constant pool entry merging
1173  class BlockConstantPoolEntrySharingScope {
1174   public:
1175    explicit BlockConstantPoolEntrySharingScope(Assembler* assem)
1176        : assem_(assem) {
1177      assem_->StartBlockConstantPoolEntrySharing();
1178    }
1179    ~BlockConstantPoolEntrySharingScope() {
1180      assem_->EndBlockConstantPoolEntrySharing();
1181    }
1182
1183   private:
1184    Assembler* assem_;
1185
1186    DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstantPoolEntrySharingScope);
1187  };
1188
1189  // Debugging
1190
1191  // Mark generator continuation.
1192  void RecordGeneratorContinuation();
1193
1194  // Mark address of a debug break slot.
1195  void RecordDebugBreakSlot(RelocInfo::Mode mode);
1196
1197  // Record the AST id of the CallIC being compiled, so that it can be placed
1198  // in the relocation information.
1199  void SetRecordedAstId(TypeFeedbackId ast_id) {
1200    // Causes compiler to fail
1201    // DCHECK(recorded_ast_id_.IsNone());
1202    recorded_ast_id_ = ast_id;
1203  }
1204
1205  TypeFeedbackId RecordedAstId() {
1206    // Causes compiler to fail
1207    // DCHECK(!recorded_ast_id_.IsNone());
1208    return recorded_ast_id_;
1209  }
1210
1211  void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
1212
1213  // Record a comment relocation entry that can be used by a disassembler.
1214  // Use --code-comments to enable.
1215  void RecordComment(const char* msg);
1216
1217  // Record a deoptimization reason that can be used by a log or cpu profiler.
1218  // Use --trace-deopt to enable.
1219  void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
1220                         int id);
1221
1222  // Writes a single byte or word of data in the code stream.  Used
1223  // for inline tables, e.g., jump-tables.
1224  void db(uint8_t data);
1225  void dd(uint32_t data);
1226  void dq(uint64_t data);
1227  void dp(uintptr_t data);
1228
1229  // Read/patch instructions
1230  Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1231  void instr_at_put(int pos, Instr instr) {
1232    *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1233  }
1234  static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1235  static void instr_at_put(byte* pc, Instr instr) {
1236    *reinterpret_cast<Instr*>(pc) = instr;
1237  }
1238  static Condition GetCondition(Instr instr);
1239
1240  static bool IsLis(Instr instr);
1241  static bool IsLi(Instr instr);
1242  static bool IsAddic(Instr instr);
1243  static bool IsOri(Instr instr);
1244
1245  static bool IsBranch(Instr instr);
1246  static Register GetRA(Instr instr);
1247  static Register GetRB(Instr instr);
1248#if V8_TARGET_ARCH_PPC64
1249  static bool Is64BitLoadIntoR12(Instr instr1, Instr instr2, Instr instr3,
1250                                 Instr instr4, Instr instr5);
1251#else
1252  static bool Is32BitLoadIntoR12(Instr instr1, Instr instr2);
1253#endif
1254
1255  static bool IsCmpRegister(Instr instr);
1256  static bool IsCmpImmediate(Instr instr);
1257  static bool IsRlwinm(Instr instr);
1258  static bool IsAndi(Instr instr);
1259#if V8_TARGET_ARCH_PPC64
1260  static bool IsRldicl(Instr instr);
1261#endif
1262  static bool IsCrSet(Instr instr);
1263  static Register GetCmpImmediateRegister(Instr instr);
1264  static int GetCmpImmediateRawImmediate(Instr instr);
1265  static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
1266
1267  // Postpone the generation of the trampoline pool for the specified number of
1268  // instructions.
1269  void BlockTrampolinePoolFor(int instructions);
1270  void CheckTrampolinePool();
1271
1272  // For mov.  Return the number of actual instructions required to
1273  // load the operand into a register.  This can be anywhere from
1274  // one (constant pool small section) to five instructions (full
1275  // 64-bit sequence).
1276  //
1277  // The value returned is only valid as long as no entries are added to the
1278  // constant pool between this call and the actual instruction being emitted.
1279  int instructions_required_for_mov(Register dst, const Operand& src) const;
1280
1281  // Decide between using the constant pool vs. a mov immediate sequence.
1282  bool use_constant_pool_for_mov(Register dst, const Operand& src,
1283                                 bool canOptimize) const;
1284
1285  // The code currently calls CheckBuffer() too often. This has the side
1286  // effect of randomly growing the buffer in the middle of multi-instruction
1287  // sequences.
1288  //
1289  // This function allows outside callers to check and grow the buffer
1290  void EnsureSpaceFor(int space_needed);
1291
1292  int EmitConstantPool() { return constant_pool_builder_.Emit(this); }
1293
1294  bool ConstantPoolAccessIsInOverflow() const {
1295    return constant_pool_builder_.NextAccess(ConstantPoolEntry::INTPTR) ==
1296           ConstantPoolEntry::OVERFLOWED;
1297  }
1298
1299  Label* ConstantPoolPosition() {
1300    return constant_pool_builder_.EmittedPosition();
1301  }
1302
1303  void EmitRelocations();
1304
1305 protected:
1306  // Relocation for a type-recording IC has the AST id added to it.  This
1307  // member variable is a way to pass the information from the call site to
1308  // the relocation info.
1309  TypeFeedbackId recorded_ast_id_;
1310
1311  int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1312
1313  // Decode instruction(s) at pos and return backchain to previous
1314  // label reference or kEndOfChain.
1315  int target_at(int pos);
1316
1317  // Patch instruction(s) at pos to target target_pos (e.g. branch)
1318  void target_at_put(int pos, int target_pos, bool* is_branch = nullptr);
1319
1320  // Record reloc info for current pc_
1321  void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1322  ConstantPoolEntry::Access ConstantPoolAddEntry(RelocInfo::Mode rmode,
1323                                                 intptr_t value) {
1324    bool sharing_ok = RelocInfo::IsNone(rmode) ||
1325                      !(serializer_enabled() || rmode < RelocInfo::CELL ||
1326                        is_constant_pool_entry_sharing_blocked());
1327    return constant_pool_builder_.AddEntry(pc_offset(), value, sharing_ok);
1328  }
1329  ConstantPoolEntry::Access ConstantPoolAddEntry(double value) {
1330    return constant_pool_builder_.AddEntry(pc_offset(), value);
1331  }
1332
1333  // Block the emission of the trampoline pool before pc_offset.
1334  void BlockTrampolinePoolBefore(int pc_offset) {
1335    if (no_trampoline_pool_before_ < pc_offset)
1336      no_trampoline_pool_before_ = pc_offset;
1337  }
1338
1339  void StartBlockTrampolinePool() { trampoline_pool_blocked_nesting_++; }
1340  void EndBlockTrampolinePool() {
1341    int count = --trampoline_pool_blocked_nesting_;
1342    if (count == 0) CheckTrampolinePoolQuick();
1343  }
1344  bool is_trampoline_pool_blocked() const {
1345    return trampoline_pool_blocked_nesting_ > 0;
1346  }
1347
1348  void StartBlockConstantPoolEntrySharing() {
1349    constant_pool_entry_sharing_blocked_nesting_++;
1350  }
1351  void EndBlockConstantPoolEntrySharing() {
1352    constant_pool_entry_sharing_blocked_nesting_--;
1353  }
1354  bool is_constant_pool_entry_sharing_blocked() const {
1355    return constant_pool_entry_sharing_blocked_nesting_ > 0;
1356  }
1357
1358  bool has_exception() const { return internal_trampoline_exception_; }
1359
1360  bool is_trampoline_emitted() const { return trampoline_emitted_; }
1361
1362 private:
1363  // Code generation
1364  // The relocation writer's position is at least kGap bytes below the end of
1365  // the generated instructions. This is so that multi-instruction sequences do
1366  // not have to check for overflow. The same is true for writes of large
1367  // relocation info entries.
1368  static const int kGap = 32;
1369
1370  // Repeated checking whether the trampoline pool should be emitted is rather
1371  // expensive. By default we only check again once a number of instructions
1372  // has been generated.
1373  int next_trampoline_check_;  // pc offset of next buffer check.
1374
1375  // Emission of the trampoline pool may be blocked in some code sequences.
1376  int trampoline_pool_blocked_nesting_;  // Block emission if this is not zero.
1377  int no_trampoline_pool_before_;  // Block emission before this pc offset.
1378
1379  // Do not share constant pool entries.
1380  int constant_pool_entry_sharing_blocked_nesting_;
1381
1382  // Relocation info generation
1383  // Each relocation is encoded as a variable size value
1384  static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1385  RelocInfoWriter reloc_info_writer;
1386  std::vector<DeferredRelocInfo> relocations_;
1387
1388  // The bound position, before this we cannot do instruction elimination.
1389  int last_bound_pos_;
1390  // Optimizable cmpi information.
1391  int optimizable_cmpi_pos_;
1392  CRegister cmpi_cr_;
1393
1394  ConstantPoolBuilder constant_pool_builder_;
1395
1396  // Code emission
1397  inline void CheckBuffer();
1398  void GrowBuffer(int needed = 0);
1399  inline void emit(Instr x);
1400  inline void TrackBranch();
1401  inline void UntrackBranch();
1402  inline void CheckTrampolinePoolQuick();
1403
1404  // Instruction generation
1405  void a_form(Instr instr, DoubleRegister frt, DoubleRegister fra,
1406              DoubleRegister frb, RCBit r);
1407  void d_form(Instr instr, Register rt, Register ra, const intptr_t val,
1408              bool signed_disp);
1409  void x_form(Instr instr, Register ra, Register rs, Register rb, RCBit r);
1410  void xo_form(Instr instr, Register rt, Register ra, Register rb, OEBit o,
1411               RCBit r);
1412  void md_form(Instr instr, Register ra, Register rs, int shift, int maskbit,
1413               RCBit r);
1414  void mds_form(Instr instr, Register ra, Register rs, Register rb, int maskbit,
1415                RCBit r);
1416
1417  // Labels
1418  void print(Label* L);
1419  int max_reach_from(int pos);
1420  void bind_to(Label* L, int pos);
1421  void next(Label* L);
1422
1423  class Trampoline {
1424   public:
1425    Trampoline() {
1426      next_slot_ = 0;
1427      free_slot_count_ = 0;
1428    }
1429    Trampoline(int start, int slot_count) {
1430      next_slot_ = start;
1431      free_slot_count_ = slot_count;
1432    }
1433    int take_slot() {
1434      int trampoline_slot = kInvalidSlotPos;
1435      if (free_slot_count_ <= 0) {
1436        // We have run out of space on trampolines.
1437        // Make sure we fail in debug mode, so we become aware of each case
1438        // when this happens.
1439        DCHECK(0);
1440        // Internal exception will be caught.
1441      } else {
1442        trampoline_slot = next_slot_;
1443        free_slot_count_--;
1444        next_slot_ += kTrampolineSlotsSize;
1445      }
1446      return trampoline_slot;
1447    }
1448
1449   private:
1450    int next_slot_;
1451    int free_slot_count_;
1452  };
1453
1454  int32_t get_trampoline_entry();
1455  int tracked_branch_count_;
1456  // If trampoline is emitted, generated code is becoming large. As
1457  // this is already a slow case which can possibly break our code
1458  // generation for the extreme case, we use this information to
1459  // trigger different mode of branch instruction generation, where we
1460  // no longer use a single branch instruction.
1461  bool trampoline_emitted_;
1462  static const int kTrampolineSlotsSize = kInstrSize;
1463  static const int kMaxCondBranchReach = (1 << (16 - 1)) - 1;
1464  static const int kMaxBlockTrampolineSectionSize = 64 * kInstrSize;
1465  static const int kInvalidSlotPos = -1;
1466
1467  Trampoline trampoline_;
1468  bool internal_trampoline_exception_;
1469
1470  friend class RegExpMacroAssemblerPPC;
1471  friend class RelocInfo;
1472  friend class CodePatcher;
1473  friend class BlockTrampolinePoolScope;
1474  friend class EnsureSpace;
1475};
1476
1477
1478class EnsureSpace BASE_EMBEDDED {
1479 public:
1480  explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); }
1481};
1482}  // namespace internal
1483}  // namespace v8
1484
1485#endif  // V8_PPC_ASSEMBLER_PPC_H_
1486