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