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 
210 // Double word FP register.
211 struct 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 
is_validDoubleRegister223   bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
isDoubleRegister224   bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
codeDoubleRegister225   int code() const {
226     DCHECK(is_valid());
227     return reg_code;
228   }
bitDoubleRegister229   int bit() const {
230     DCHECK(is_valid());
231     return 1 << reg_code;
232   }
233 
from_codeDoubleRegister234   static DoubleRegister from_code(int code) {
235     DoubleRegister r = {code};
236     return r;
237   }
238 
239   int reg_code;
240 };
241 
242 typedef DoubleRegister FloatRegister;
243 
244 // TODO(ppc) Define SIMD registers.
245 typedef DoubleRegister Simd128Register;
246 
247 #define DECLARE_REGISTER(R) \
248   const DoubleRegister R = {DoubleRegister::kCode_##R};
249 DOUBLE_REGISTERS(DECLARE_REGISTER)
250 #undef DECLARE_REGISTER
251 const 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 
261 Register ToRegister(int num);
262 
263 // Coprocessor register
264 struct CRegister {
is_validCRegister265   bool is_valid() const { return 0 <= reg_code && reg_code < 8; }
isCRegister266   bool is(CRegister creg) const { return reg_code == creg.reg_code; }
codeCRegister267   int code() const {
268     DCHECK(is_valid());
269     return reg_code;
270   }
bitCRegister271   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 
281 const CRegister no_creg = {-1};
282 
283 const CRegister cr0 = {0};
284 const CRegister cr1 = {1};
285 const CRegister cr2 = {2};
286 const CRegister cr3 = {3};
287 const CRegister cr4 = {4};
288 const CRegister cr5 = {5};
289 const CRegister cr6 = {6};
290 const CRegister cr7 = {7};
291 
292 // -----------------------------------------------------------------------------
293 // Machine instruction Operands
294 
295 #if V8_TARGET_ARCH_PPC64
296 const RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE64;
297 #else
298 const RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE32;
299 #endif
300 
301 // Class Operand represents a shifter operand in data processing instructions
302 class Operand BASE_EMBEDDED {
303  public:
304   // immediate
305   INLINE(explicit Operand(intptr_t immediate,
306                           RelocInfo::Mode rmode = kRelocInfo_NONEPTR));
INLINE(static Operand Zero ())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 
immediate()320   inline intptr_t immediate() const {
321     DCHECK(!rm_.is_valid());
322     return imm_;
323   }
324 
rm()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
340 class MemOperand BASE_EMBEDDED {
341  public:
342   explicit MemOperand(Register rn, int32_t offset = 0);
343 
344   explicit MemOperand(Register ra, Register rb);
345 
offset()346   int32_t offset() const {
347     DCHECK(rb_.is(no_reg));
348     return offset_;
349   }
350 
351   // PowerPC - base register
ra()352   Register ra() const {
353     DCHECK(!ra_.is(no_reg));
354     return ra_;
355   }
356 
rb()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 
371 class DeferredRelocInfo {
372  public:
DeferredRelocInfo()373   DeferredRelocInfo() {}
DeferredRelocInfo(int position,RelocInfo::Mode rmode,intptr_t data)374   DeferredRelocInfo(int position, RelocInfo::Mode rmode, intptr_t data)
375       : position_(position), rmode_(rmode), data_(data) {}
376 
position()377   int position() const { return position_; }
rmode()378   RelocInfo::Mode rmode() const { return rmode_; }
data()379   intptr_t data() const { return data_; }
380 
381  private:
382   int position_;
383   RelocInfo::Mode rmode_;
384   intptr_t data_;
385 };
386 
387 
388 class 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);
~Assembler()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
branch_offset(Label * L)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));
INLINE(static Address target_address_at (Address pc,Code * code))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   }
INLINE(static void set_target_address_at (Isolate * isolate,Address pc,Code * code,Address target,ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED))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 
encode_crbit(const CRegister & cr,enum CRBit crbit)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 
cmpi_optimization(CRegister cr)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);
crclr(int bt)996   void crclr(int bt) { crxor(bt, bt, bt); }
997   void creqv(int bt, int ba, int bb);
crset(int bt)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 
push(Register src)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 
pop(Register dst)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 
pop()1143   void pop() { addi(sp, sp, Operand(kPointerSize)); }
1144 
1145   // Jump unconditionally to given label.
jmp(Label * L)1146   void jmp(Label* L) { b(L); }
1147 
1148   // Check the code size generated from label to here.
SizeOfCodeGeneratedSince(Label * label)1149   int SizeOfCodeGeneratedSince(Label* label) {
1150     return pc_offset() - label->pos();
1151   }
1152 
1153   // Check the number of instructions generated from label to here.
InstructionsGeneratedSince(Label * label)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:
BlockTrampolinePoolScope(Assembler * assem)1161     explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) {
1162       assem_->StartBlockTrampolinePool();
1163     }
~BlockTrampolinePoolScope()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:
BlockConstantPoolEntrySharingScope(Assembler * assem)1175     explicit BlockConstantPoolEntrySharingScope(Assembler* assem)
1176         : assem_(assem) {
1177       assem_->StartBlockConstantPoolEntrySharing();
1178     }
~BlockConstantPoolEntrySharingScope()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.
SetRecordedAstId(TypeFeedbackId ast_id)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 
RecordedAstId()1205   TypeFeedbackId RecordedAstId() {
1206     // Causes compiler to fail
1207     // DCHECK(!recorded_ast_id_.IsNone());
1208     return recorded_ast_id_;
1209   }
1210 
ClearRecordedAstId()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
instr_at(int pos)1230   Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
instr_at_put(int pos,Instr instr)1231   void instr_at_put(int pos, Instr instr) {
1232     *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1233   }
instr_at(byte * pc)1234   static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
instr_at_put(byte * pc,Instr instr)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 
EmitConstantPool()1292   int EmitConstantPool() { return constant_pool_builder_.Emit(this); }
1293 
ConstantPoolAccessIsInOverflow()1294   bool ConstantPoolAccessIsInOverflow() const {
1295     return constant_pool_builder_.NextAccess(ConstantPoolEntry::INTPTR) ==
1296            ConstantPoolEntry::OVERFLOWED;
1297   }
1298 
ConstantPoolPosition()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 
buffer_space()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);
ConstantPoolAddEntry(RelocInfo::Mode rmode,intptr_t value)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   }
ConstantPoolAddEntry(double value)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.
BlockTrampolinePoolBefore(int 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 
StartBlockTrampolinePool()1339   void StartBlockTrampolinePool() { trampoline_pool_blocked_nesting_++; }
EndBlockTrampolinePool()1340   void EndBlockTrampolinePool() {
1341     int count = --trampoline_pool_blocked_nesting_;
1342     if (count == 0) CheckTrampolinePoolQuick();
1343   }
is_trampoline_pool_blocked()1344   bool is_trampoline_pool_blocked() const {
1345     return trampoline_pool_blocked_nesting_ > 0;
1346   }
1347 
StartBlockConstantPoolEntrySharing()1348   void StartBlockConstantPoolEntrySharing() {
1349     constant_pool_entry_sharing_blocked_nesting_++;
1350   }
EndBlockConstantPoolEntrySharing()1351   void EndBlockConstantPoolEntrySharing() {
1352     constant_pool_entry_sharing_blocked_nesting_--;
1353   }
is_constant_pool_entry_sharing_blocked()1354   bool is_constant_pool_entry_sharing_blocked() const {
1355     return constant_pool_entry_sharing_blocked_nesting_ > 0;
1356   }
1357 
has_exception()1358   bool has_exception() const { return internal_trampoline_exception_; }
1359 
is_trampoline_emitted()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:
Trampoline()1425     Trampoline() {
1426       next_slot_ = 0;
1427       free_slot_count_ = 0;
1428     }
Trampoline(int start,int slot_count)1429     Trampoline(int start, int slot_count) {
1430       next_slot_ = start;
1431       free_slot_count_ = slot_count;
1432     }
take_slot()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 
1478 class EnsureSpace BASE_EMBEDDED {
1479  public:
EnsureSpace(Assembler * assembler)1480   explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); }
1481 };
1482 }  // namespace internal
1483 }  // namespace v8
1484 
1485 #endif  // V8_PPC_ASSEMBLER_PPC_H_
1486