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