• 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_CODEGEN_PPC_ASSEMBLER_PPC_H_
41 #define V8_CODEGEN_PPC_ASSEMBLER_PPC_H_
42 
43 #include <stdio.h>
44 #include <memory>
45 #include <vector>
46 
47 #include "src/codegen/assembler.h"
48 #include "src/codegen/constant-pool.h"
49 #include "src/codegen/external-reference.h"
50 #include "src/codegen/label.h"
51 #include "src/codegen/ppc/constants-ppc.h"
52 #include "src/codegen/ppc/register-ppc.h"
53 #include "src/numbers/double.h"
54 #include "src/objects/smi.h"
55 
56 namespace v8 {
57 namespace internal {
58 
59 class SafepointTableBuilder;
60 
61 // -----------------------------------------------------------------------------
62 // Machine instruction Operands
63 
64 // Class Operand represents a shifter operand in data processing instructions
65 class V8_EXPORT_PRIVATE Operand {
66  public:
67   // immediate
68   V8_INLINE explicit Operand(intptr_t immediate,
69                              RelocInfo::Mode rmode = RelocInfo::NONE)
rmode_(rmode)70       : rmode_(rmode) {
71     value_.immediate = immediate;
72   }
Zero()73   V8_INLINE static Operand Zero() { return Operand(static_cast<intptr_t>(0)); }
Operand(const ExternalReference & f)74   V8_INLINE explicit Operand(const ExternalReference& f)
75       : rmode_(RelocInfo::EXTERNAL_REFERENCE) {
76     value_.immediate = static_cast<intptr_t>(f.address());
77   }
78   explicit Operand(Handle<HeapObject> handle);
Operand(Smi value)79   V8_INLINE explicit Operand(Smi value) : rmode_(RelocInfo::NONE) {
80     value_.immediate = static_cast<intptr_t>(value.ptr());
81   }
82   // rm
83   V8_INLINE explicit Operand(Register rm);
84 
85   static Operand EmbeddedNumber(double number);  // Smi or HeapNumber.
86   static Operand EmbeddedStringConstant(const StringConstantBase* str);
87 
88   // Return true if this is a register operand.
is_reg()89   V8_INLINE bool is_reg() const { return rm_.is_valid(); }
90 
91   bool must_output_reloc_info(const Assembler* assembler) const;
92 
immediate()93   inline intptr_t immediate() const {
94     DCHECK(IsImmediate());
95     DCHECK(!IsHeapObjectRequest());
96     return value_.immediate;
97   }
IsImmediate()98   bool IsImmediate() const { return !rm_.is_valid(); }
99 
heap_object_request()100   HeapObjectRequest heap_object_request() const {
101     DCHECK(IsHeapObjectRequest());
102     return value_.heap_object_request;
103   }
104 
rm()105   Register rm() const { return rm_; }
106 
IsHeapObjectRequest()107   bool IsHeapObjectRequest() const {
108     DCHECK_IMPLIES(is_heap_object_request_, IsImmediate());
109     DCHECK_IMPLIES(is_heap_object_request_,
110                    rmode_ == RelocInfo::FULL_EMBEDDED_OBJECT ||
111                        rmode_ == RelocInfo::CODE_TARGET);
112     return is_heap_object_request_;
113   }
114 
115  private:
116   Register rm_ = no_reg;
117   union Value {
Value()118     Value() {}
119     HeapObjectRequest heap_object_request;  // if is_heap_object_request_
120     intptr_t immediate;                     // otherwise
121   } value_;                                 // valid if rm_ == no_reg
122   bool is_heap_object_request_ = false;
123 
124   RelocInfo::Mode rmode_;
125 
126   friend class Assembler;
127   friend class MacroAssembler;
128 };
129 
130 // Class MemOperand represents a memory operand in load and store instructions
131 // On PowerPC we have base register + 16bit signed value
132 // Alternatively we can have a 16bit signed value immediate
133 class V8_EXPORT_PRIVATE MemOperand {
134  public:
135   explicit MemOperand(Register rn, int32_t offset = 0);
136 
137   explicit MemOperand(Register ra, Register rb);
138 
offset()139   int32_t offset() const { return offset_; }
140 
141   // PowerPC - base register
ra()142   Register ra() const { return ra_; }
143 
rb()144   Register rb() const { return rb_; }
145 
146  private:
147   Register ra_;     // base
148   int32_t offset_;  // offset
149   Register rb_;     // index
150 
151   friend class Assembler;
152 };
153 
154 class DeferredRelocInfo {
155  public:
DeferredRelocInfo()156   DeferredRelocInfo() {}
DeferredRelocInfo(int position,RelocInfo::Mode rmode,intptr_t data)157   DeferredRelocInfo(int position, RelocInfo::Mode rmode, intptr_t data)
158       : position_(position), rmode_(rmode), data_(data) {}
159 
position()160   int position() const { return position_; }
rmode()161   RelocInfo::Mode rmode() const { return rmode_; }
data()162   intptr_t data() const { return data_; }
163 
164  private:
165   int position_;
166   RelocInfo::Mode rmode_;
167   intptr_t data_;
168 };
169 
170 class Assembler : public AssemblerBase {
171  public:
172   // Create an assembler. Instructions and relocation information are emitted
173   // into a buffer, with the instructions starting from the beginning and the
174   // relocation information starting from the end of the buffer. See CodeDesc
175   // for a detailed comment on the layout (globals.h).
176   //
177   // If the provided buffer is nullptr, the assembler allocates and grows its
178   // own buffer. Otherwise it takes ownership of the provided buffer.
179   explicit Assembler(const AssemblerOptions&,
180                      std::unique_ptr<AssemblerBuffer> = {});
181 
~Assembler()182   virtual ~Assembler() {}
183 
184   // GetCode emits any pending (non-emitted) code and fills the descriptor desc.
185   static constexpr int kNoHandlerTable = 0;
186   static constexpr SafepointTableBuilder* kNoSafepointTable = nullptr;
187   void GetCode(Isolate* isolate, CodeDesc* desc,
188                SafepointTableBuilder* safepoint_table_builder,
189                int handler_table_offset);
190 
191   // Convenience wrapper for code without safepoint or handler tables.
GetCode(Isolate * isolate,CodeDesc * desc)192   void GetCode(Isolate* isolate, CodeDesc* desc) {
193     GetCode(isolate, desc, kNoSafepointTable, kNoHandlerTable);
194   }
195 
MaybeEmitOutOfLineConstantPool()196   void MaybeEmitOutOfLineConstantPool() { EmitConstantPool(); }
197 
198   // Label operations & relative jumps (PPUM Appendix D)
199   //
200   // Takes a branch opcode (cc) and a label (L) and generates
201   // either a backward branch or a forward branch and links it
202   // to the label fixup chain. Usage:
203   //
204   // Label L;    // unbound label
205   // j(cc, &L);  // forward branch to unbound label
206   // bind(&L);   // bind label to the current pc
207   // j(cc, &L);  // backward branch to bound label
208   // bind(&L);   // illegal: a label may be bound only once
209   //
210   // Note: The same Label can be used for forward and backward branches
211   // but it may be bound only once.
212 
213   void bind(Label* L);  // binds an unbound label L to the current code position
214 
215   // Links a label at the current pc_offset().  If already bound, returns the
216   // bound position.  If already linked, returns the position of the prior link.
217   // Otherwise, returns the current pc_offset().
218   int link(Label* L);
219 
220   // Determines if Label is bound and near enough so that a single
221   // branch instruction can be used to reach it.
222   bool is_near(Label* L, Condition cond);
223 
224   // Returns the branch offset to the given label from the current code position
225   // Links the label to the current position if it is still unbound
branch_offset(Label * L)226   int branch_offset(Label* L) {
227     if (L->is_unused() && !trampoline_emitted_) {
228       TrackBranch();
229     }
230     return link(L) - pc_offset();
231   }
232 
233   V8_INLINE static bool IsConstantPoolLoadStart(
234       Address pc, ConstantPoolEntry::Access* access = nullptr);
235   V8_INLINE static bool IsConstantPoolLoadEnd(
236       Address pc, ConstantPoolEntry::Access* access = nullptr);
237   V8_INLINE static int GetConstantPoolOffset(Address pc,
238                                              ConstantPoolEntry::Access access,
239                                              ConstantPoolEntry::Type type);
240   V8_INLINE void PatchConstantPoolAccessInstruction(
241       int pc_offset, int offset, ConstantPoolEntry::Access access,
242       ConstantPoolEntry::Type type);
243 
244   // Return the address in the constant pool of the code target address used by
245   // the branch/call instruction at pc, or the object in a mov.
246   V8_INLINE static Address target_constant_pool_address_at(
247       Address pc, Address constant_pool, ConstantPoolEntry::Access access,
248       ConstantPoolEntry::Type type);
249 
250   // Read/Modify the code target address in the branch/call instruction at pc.
251   // The isolate argument is unused (and may be nullptr) when skipping flushing.
252   V8_INLINE static Address target_address_at(Address pc, Address constant_pool);
253   V8_INLINE static void set_target_address_at(
254       Address pc, Address constant_pool, Address target,
255       ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
256 
257   // Read/Modify the code target address in the branch/call instruction at pc.
258   inline static Tagged_t target_compressed_address_at(Address pc,
259                                                       Address constant_pool);
260   inline static void set_target_compressed_address_at(
261       Address pc, Address constant_pool, Tagged_t target,
262       ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
263 
264   inline Handle<Object> code_target_object_handle_at(Address pc,
265                                                      Address constant_pool);
266   inline Handle<HeapObject> compressed_embedded_object_handle_at(
267       Address pc, Address constant_pool);
268 
269   // This sets the branch destination.
270   // This is for calls and branches within generated code.
271   inline static void deserialization_set_special_target_at(
272       Address instruction_payload, Code code, Address target);
273 
274   // Get the size of the special target encoded at 'instruction_payload'.
275   inline static int deserialization_special_target_size(
276       Address instruction_payload);
277 
278   // This sets the internal reference at the pc.
279   inline static void deserialization_set_target_internal_reference_at(
280       Address pc, Address target,
281       RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
282 
283   // Here we are patching the address in the LUI/ORI instruction pair.
284   // These values are used in the serialization process and must be zero for
285   // PPC platform, as Code, Embedded Object or External-reference pointers
286   // are split across two consecutive instructions and don't exist separately
287   // in the code, so the serializer should not step forwards in memory after
288   // a target is resolved and written.
289   static constexpr int kSpecialTargetSize = 0;
290 
291 // Number of instructions to load an address via a mov sequence.
292 #if V8_TARGET_ARCH_PPC64
293   static constexpr int kMovInstructionsConstantPool = 1;
294   static constexpr int kMovInstructionsNoConstantPool = 5;
295 #if defined(V8_PPC_TAGGING_OPT)
296   static constexpr int kTaggedLoadInstructions = 1;
297 #else
298   static constexpr int kTaggedLoadInstructions = 2;
299 #endif
300 #else
301   static constexpr int kMovInstructionsConstantPool = 1;
302   static constexpr int kMovInstructionsNoConstantPool = 2;
303   static constexpr int kTaggedLoadInstructions = 1;
304 #endif
305   static constexpr int kMovInstructions = FLAG_enable_embedded_constant_pool
306                                               ? kMovInstructionsConstantPool
307                                               : kMovInstructionsNoConstantPool;
308 
encode_crbit(const CRegister & cr,enum CRBit crbit)309   static inline int encode_crbit(const CRegister& cr, enum CRBit crbit) {
310     return ((cr.code() * CRWIDTH) + crbit);
311   }
312 
313 #define DECLARE_PPC_X_INSTRUCTIONS_A_FORM(name, instr_name, instr_value)    \
314   inline void name(const Register rt, const Register ra, const Register rb, \
315                    const RCBit rc = LeaveRC) {                              \
316     x_form(instr_name, rt, ra, rb, rc);                                     \
317   }
318 
319 #define DECLARE_PPC_X_INSTRUCTIONS_B_FORM(name, instr_name, instr_value)    \
320   inline void name(const Register ra, const Register rs, const Register rb, \
321                    const RCBit rc = LeaveRC) {                              \
322     x_form(instr_name, rs, ra, rb, rc);                                     \
323   }
324 
325 #define DECLARE_PPC_X_INSTRUCTIONS_C_FORM(name, instr_name, instr_value) \
326   inline void name(const Register dst, const Register src,               \
327                    const RCBit rc = LeaveRC) {                           \
328     x_form(instr_name, src, dst, r0, rc);                                \
329   }
330 
331 #define DECLARE_PPC_X_INSTRUCTIONS_D_FORM(name, instr_name, instr_value) \
332   template <class R>                                                     \
333   inline void name(const R rt, const Register ra, const Register rb,     \
334                    const RCBit rc = LeaveRC) {                           \
335     x_form(instr_name, rt.code(), ra.code(), rb.code(), rc);             \
336   }                                                                      \
337   template <class R>                                                     \
338   inline void name(const R dst, const MemOperand& src) {                 \
339     name(dst, src.ra(), src.rb());                                       \
340   }
341 
342 #define DECLARE_PPC_X_INSTRUCTIONS_E_FORM(name, instr_name, instr_value) \
343   inline void name(const Register dst, const Register src, const int sh, \
344                    const RCBit rc = LeaveRC) {                           \
345     x_form(instr_name, src.code(), dst.code(), sh, rc);                  \
346   }
347 
348 #define DECLARE_PPC_X_INSTRUCTIONS_F_FORM(name, instr_name, instr_value)    \
349   inline void name(const Register src1, const Register src2,                \
350                    const CRegister cr = cr7, const RCBit rc = LeaveRC) {    \
351     x_form(instr_name, cr, src1, src2, rc);                                 \
352   }                                                                         \
353   inline void name##w(const Register src1, const Register src2,             \
354                       const CRegister cr = cr7, const RCBit rc = LeaveRC) { \
355     x_form(instr_name, cr.code() * B2, src1.code(), src2.code(), LeaveRC);  \
356   }
357 
358 #define DECLARE_PPC_X_INSTRUCTIONS_EH_S_FORM(name, instr_name, instr_value) \
359   inline void name(const Register dst, const MemOperand& src) {             \
360     x_form(instr_name, src.ra(), dst, src.rb(), SetEH);                     \
361   }
362 #define DECLARE_PPC_X_INSTRUCTIONS_EH_L_FORM(name, instr_name, instr_value) \
363   inline void name(const Register dst, const MemOperand& src) {             \
364     DCHECK(src.ra_ != r0);                                                  \
365     x_form(instr_name, src.ra(), dst, src.rb(), SetEH);                     \
366   }
367 
x_form(Instr instr,int f1,int f2,int f3,int rc)368   inline void x_form(Instr instr, int f1, int f2, int f3, int rc) {
369     emit(instr | f1 * B21 | f2 * B16 | f3 * B11 | rc);
370   }
x_form(Instr instr,Register rs,Register ra,Register rb,RCBit rc)371   inline void x_form(Instr instr, Register rs, Register ra, Register rb,
372                      RCBit rc) {
373     emit(instr | rs.code() * B21 | ra.code() * B16 | rb.code() * B11 | rc);
374   }
375   inline void x_form(Instr instr, Register ra, Register rs, Register rb,
376                      EHBit eh = SetEH) {
377     emit(instr | rs.code() * B21 | ra.code() * B16 | rb.code() * B11 | eh);
378   }
x_form(Instr instr,CRegister cr,Register s1,Register s2,RCBit rc)379   inline void x_form(Instr instr, CRegister cr, Register s1, Register s2,
380                      RCBit rc) {
381 #if V8_TARGET_ARCH_PPC64
382     int L = 1;
383 #else
384     int L = 0;
385 #endif
386     emit(instr | cr.code() * B23 | L * B21 | s1.code() * B16 | s2.code() * B11 |
387          rc);
388   }
389 
390   PPC_X_OPCODE_A_FORM_LIST(DECLARE_PPC_X_INSTRUCTIONS_A_FORM)
PPC_X_OPCODE_B_FORM_LIST(DECLARE_PPC_X_INSTRUCTIONS_B_FORM)391   PPC_X_OPCODE_B_FORM_LIST(DECLARE_PPC_X_INSTRUCTIONS_B_FORM)
392   PPC_X_OPCODE_C_FORM_LIST(DECLARE_PPC_X_INSTRUCTIONS_C_FORM)
393   PPC_X_OPCODE_D_FORM_LIST(DECLARE_PPC_X_INSTRUCTIONS_D_FORM)
394   PPC_X_OPCODE_E_FORM_LIST(DECLARE_PPC_X_INSTRUCTIONS_E_FORM)
395   PPC_X_OPCODE_F_FORM_LIST(DECLARE_PPC_X_INSTRUCTIONS_F_FORM)
396   PPC_X_OPCODE_EH_S_FORM_LIST(DECLARE_PPC_X_INSTRUCTIONS_EH_S_FORM)
397   PPC_X_OPCODE_EH_L_FORM_LIST(DECLARE_PPC_X_INSTRUCTIONS_EH_L_FORM)
398 
399   inline void notx(Register dst, Register src, RCBit rc = LeaveRC) {
400     nor(dst, src, src, rc);
401   }
lwax(Register rt,const MemOperand & src)402   inline void lwax(Register rt, const MemOperand& src) {
403 #if V8_TARGET_ARCH_PPC64
404     Register ra = src.ra();
405     Register rb = src.rb();
406     DCHECK(ra != r0);
407     x_form(LWAX, rt, ra, rb, LeaveRC);
408 #else
409     lwzx(rt, src);
410 #endif
411   }
412   inline void extsw(Register rs, Register ra, RCBit rc = LeaveRC) {
413 #if V8_TARGET_ARCH_PPC64
414     emit(EXT2 | EXTSW | ra.code() * B21 | rs.code() * B16 | rc);
415 #else
416     // nop on 32-bit
417     DCHECK(rs == ra && rc == LeaveRC);
418 #endif
419   }
420 
421 #undef DECLARE_PPC_X_INSTRUCTIONS_A_FORM
422 #undef DECLARE_PPC_X_INSTRUCTIONS_B_FORM
423 #undef DECLARE_PPC_X_INSTRUCTIONS_C_FORM
424 #undef DECLARE_PPC_X_INSTRUCTIONS_D_FORM
425 #undef DECLARE_PPC_X_INSTRUCTIONS_E_FORM
426 #undef DECLARE_PPC_X_INSTRUCTIONS_F_FORM
427 #undef DECLARE_PPC_X_INSTRUCTIONS_EH_S_FORM
428 #undef DECLARE_PPC_X_INSTRUCTIONS_EH_L_FORM
429 
430 #define DECLARE_PPC_XX2_INSTRUCTIONS(name, instr_name, instr_value)      \
431   inline void name(const Simd128Register rt, const Simd128Register rb) { \
432     xx2_form(instr_name, rt, rb);                                        \
433   }
434 
xx2_form(Instr instr,Simd128Register t,Simd128Register b)435   inline void xx2_form(Instr instr, Simd128Register t, Simd128Register b) {
436     // Using VR (high VSR) registers.
437     int BX = 1;
438     int TX = 1;
439 
440     emit(instr | (t.code() & 0x1F) * B21 | (b.code() & 0x1F) * B11 | BX * B1 |
441          TX);
442   }
443 
PPC_XX2_OPCODE_A_FORM_LIST(DECLARE_PPC_XX2_INSTRUCTIONS)444   PPC_XX2_OPCODE_A_FORM_LIST(DECLARE_PPC_XX2_INSTRUCTIONS)
445 #undef DECLARE_PPC_XX2_INSTRUCTIONS
446 
447 #define DECLARE_PPC_XX3_INSTRUCTIONS(name, instr_name, instr_value)  \
448   inline void name(const DoubleRegister rt, const DoubleRegister ra, \
449                    const DoubleRegister rb) {                        \
450     xx3_form(instr_name, rt, ra, rb);                                \
451   }
452 
453   inline void xx3_form(Instr instr, DoubleRegister t, DoubleRegister a,
454                        DoubleRegister b) {
455     // Using VR (high VSR) registers.
456     int AX = 1;
457     int BX = 1;
458     int TX = 1;
459 
460     emit(instr | (t.code() & 0x1F) * B21 | (a.code() & 0x1F) * B16 |
461          (b.code() & 0x1F) * B11 | AX * B2 | BX * B1 | TX);
462   }
463 
PPC_XX3_OPCODE_LIST(DECLARE_PPC_XX3_INSTRUCTIONS)464   PPC_XX3_OPCODE_LIST(DECLARE_PPC_XX3_INSTRUCTIONS)
465 #undef DECLARE_PPC_XX3_INSTRUCTIONS
466 
467 #define DECLARE_PPC_VX_INSTRUCTIONS_A_FORM(name, instr_name, instr_value) \
468   inline void name(const Simd128Register rt, const Simd128Register rb,    \
469                    const Operand& imm) {                                  \
470     vx_form(instr_name, rt, rb, imm);                                     \
471   }
472 #define DECLARE_PPC_VX_INSTRUCTIONS_B_FORM(name, instr_name, instr_value) \
473   inline void name(const Simd128Register rt, const Simd128Register ra,    \
474                    const Simd128Register rb) {                            \
475     vx_form(instr_name, rt, ra, rb);                                      \
476   }
477 #define DECLARE_PPC_VX_INSTRUCTIONS_C_FORM(name, instr_name, instr_value) \
478   inline void name(const Simd128Register rt, const Simd128Register rb) {  \
479     vx_form(instr_name, rt, rb);                                          \
480   }
481 
482   inline void vx_form(Instr instr, Simd128Register rt, Simd128Register rb,
483                       const Operand& imm) {
484     emit(instr | rt.code() * B21 | imm.immediate() * B16 | rb.code() * B11);
485   }
vx_form(Instr instr,Simd128Register rt,Simd128Register ra,Simd128Register rb)486   inline void vx_form(Instr instr, Simd128Register rt, Simd128Register ra,
487                       Simd128Register rb) {
488     emit(instr | rt.code() * B21 | ra.code() * B16 | rb.code() * B11);
489   }
vx_form(Instr instr,Simd128Register rt,Simd128Register rb)490   inline void vx_form(Instr instr, Simd128Register rt, Simd128Register rb) {
491     emit(instr | rt.code() * B21 | rb.code() * B11);
492   }
493 
494   PPC_VX_OPCODE_A_FORM_LIST(DECLARE_PPC_VX_INSTRUCTIONS_A_FORM)
PPC_VX_OPCODE_B_FORM_LIST(DECLARE_PPC_VX_INSTRUCTIONS_B_FORM)495   PPC_VX_OPCODE_B_FORM_LIST(DECLARE_PPC_VX_INSTRUCTIONS_B_FORM)
496   PPC_VX_OPCODE_C_FORM_LIST(DECLARE_PPC_VX_INSTRUCTIONS_C_FORM)
497 #undef DECLARE_PPC_VX_INSTRUCTIONS_A_FORM
498 #undef DECLARE_PPC_VX_INSTRUCTIONS_B_FORM
499 #undef DECLARE_PPC_VX_INSTRUCTIONS_C_FORM
500 
501 #define DECLARE_PPC_VA_INSTRUCTIONS_A_FORM(name, instr_name, instr_value) \
502   inline void name(const Simd128Register rt, const Simd128Register ra,    \
503                    const Simd128Register rb, const Simd128Register rc) {  \
504     va_form(instr_name, rt, ra, rb, rc);                                  \
505   }
506 
507   inline void va_form(Instr instr, Simd128Register rt, Simd128Register ra,
508                       Simd128Register rb, Simd128Register rc) {
509     emit(instr | rt.code() * B21 | ra.code() * B16 | rb.code() * B11 |
510          rc.code() * B6);
511   }
512 
PPC_VA_OPCODE_A_FORM_LIST(DECLARE_PPC_VA_INSTRUCTIONS_A_FORM)513   PPC_VA_OPCODE_A_FORM_LIST(DECLARE_PPC_VA_INSTRUCTIONS_A_FORM)
514 #undef DECLARE_PPC_VA_INSTRUCTIONS_A_FORM
515 
516 #define DECLARE_PPC_VC_INSTRUCTIONS(name, instr_name, instr_value)       \
517   inline void name(const Simd128Register rt, const Simd128Register ra,   \
518                    const Simd128Register rb, const RCBit rc = LeaveRC) { \
519     vc_form(instr_name, rt, ra, rb, rc);                                 \
520   }
521 
522   inline void vc_form(Instr instr, Simd128Register rt, Simd128Register ra,
523                       Simd128Register rb, int rc) {
524     emit(instr | rt.code() * B21 | ra.code() * B16 | rb.code() * B11 |
525          rc * B10);
526   }
527 
PPC_VC_OPCODE_LIST(DECLARE_PPC_VC_INSTRUCTIONS)528   PPC_VC_OPCODE_LIST(DECLARE_PPC_VC_INSTRUCTIONS)
529 #undef DECLARE_PPC_VC_INSTRUCTIONS
530 
531   RegList* GetScratchRegisterList() { return &scratch_register_list_; }
532   // ---------------------------------------------------------------------------
533   // Code generation
534 
535   // Insert the smallest number of nop instructions
536   // possible to align the pc offset to a multiple
537   // of m. m must be a power of 2 (>= 4).
538   void Align(int m);
539   // Insert the smallest number of zero bytes possible to align the pc offset
540   // to a mulitple of m. m must be a power of 2 (>= 2).
541   void DataAlign(int m);
542   // Aligns code to something that's optimal for a jump target for the platform.
543   void CodeTargetAlign();
544 
545   // Branch instructions
546   void bclr(BOfield bo, int condition_bit, LKBit lk);
547   void blr();
548   void bc(int branch_offset, BOfield bo, int condition_bit, LKBit lk = LeaveLK);
549   void b(int branch_offset, LKBit lk);
550 
551   void bcctr(BOfield bo, int condition_bit, LKBit lk);
552   void bctr();
553   void bctrl();
554 
555   // Convenience branch instructions using labels
556   void b(Label* L, LKBit lk = LeaveLK) { b(branch_offset(L), lk); }
557 
cmpi_optimization(CRegister cr)558   inline CRegister cmpi_optimization(CRegister cr) {
559     // Check whether the branch is preceded by an optimizable cmpi against 0.
560     // The cmpi can be deleted if it is also preceded by an instruction that
561     // sets the register used by the compare and supports a dot form.
562     unsigned int sradi_mask = kOpcodeMask | kExt2OpcodeVariant2Mask;
563     unsigned int srawi_mask = kOpcodeMask | kExt2OpcodeMask;
564     int pos = pc_offset();
565     int cmpi_pos = pc_offset() - kInstrSize;
566 
567     if (cmpi_pos > 0 && optimizable_cmpi_pos_ == cmpi_pos &&
568         cmpi_cr_.code() == cr.code() && last_bound_pos_ != pos) {
569       int xpos = cmpi_pos - kInstrSize;
570       int xinstr = instr_at(xpos);
571       int cmpi_ra = (instr_at(cmpi_pos) & 0x1f0000) >> 16;
572       // ra is at the same bit position for the three cases below.
573       int ra = (xinstr & 0x1f0000) >> 16;
574       if (cmpi_ra == ra) {
575         if ((xinstr & sradi_mask) == (EXT2 | SRADIX)) {
576           cr = cr0;
577           instr_at_put(xpos, xinstr | SetRC);
578           pc_ -= kInstrSize;
579         } else if ((xinstr & srawi_mask) == (EXT2 | SRAWIX)) {
580           cr = cr0;
581           instr_at_put(xpos, xinstr | SetRC);
582           pc_ -= kInstrSize;
583         } else if ((xinstr & kOpcodeMask) == ANDIx) {
584           cr = cr0;
585           pc_ -= kInstrSize;
586           // nothing to do here since andi. records.
587         }
588         // didn't match one of the above, must keep cmpwi.
589       }
590     }
591     return cr;
592   }
593 
594   void bc_short(Condition cond, Label* L, CRegister cr = cr7,
595                 LKBit lk = LeaveLK) {
596     DCHECK(cond != al);
597     DCHECK(cr.code() >= 0 && cr.code() <= 7);
598 
599     cr = cmpi_optimization(cr);
600 
601     int b_offset = branch_offset(L);
602 
603     switch (cond) {
604       case eq:
605         bc(b_offset, BT, encode_crbit(cr, CR_EQ), lk);
606         break;
607       case ne:
608         bc(b_offset, BF, encode_crbit(cr, CR_EQ), lk);
609         break;
610       case gt:
611         bc(b_offset, BT, encode_crbit(cr, CR_GT), lk);
612         break;
613       case le:
614         bc(b_offset, BF, encode_crbit(cr, CR_GT), lk);
615         break;
616       case lt:
617         bc(b_offset, BT, encode_crbit(cr, CR_LT), lk);
618         break;
619       case ge:
620         bc(b_offset, BF, encode_crbit(cr, CR_LT), lk);
621         break;
622       case unordered:
623         bc(b_offset, BT, encode_crbit(cr, CR_FU), lk);
624         break;
625       case ordered:
626         bc(b_offset, BF, encode_crbit(cr, CR_FU), lk);
627         break;
628       case overflow:
629         bc(b_offset, BT, encode_crbit(cr, CR_SO), lk);
630         break;
631       case nooverflow:
632         bc(b_offset, BF, encode_crbit(cr, CR_SO), lk);
633         break;
634       default:
635         UNIMPLEMENTED();
636     }
637   }
638 
639   void bclr(Condition cond, CRegister cr = cr7, LKBit lk = LeaveLK) {
640     DCHECK(cond != al);
641     DCHECK(cr.code() >= 0 && cr.code() <= 7);
642 
643     cr = cmpi_optimization(cr);
644 
645     switch (cond) {
646       case eq:
647         bclr(BT, encode_crbit(cr, CR_EQ), lk);
648         break;
649       case ne:
650         bclr(BF, encode_crbit(cr, CR_EQ), lk);
651         break;
652       case gt:
653         bclr(BT, encode_crbit(cr, CR_GT), lk);
654         break;
655       case le:
656         bclr(BF, encode_crbit(cr, CR_GT), lk);
657         break;
658       case lt:
659         bclr(BT, encode_crbit(cr, CR_LT), lk);
660         break;
661       case ge:
662         bclr(BF, encode_crbit(cr, CR_LT), lk);
663         break;
664       case unordered:
665         bclr(BT, encode_crbit(cr, CR_FU), lk);
666         break;
667       case ordered:
668         bclr(BF, encode_crbit(cr, CR_FU), lk);
669         break;
670       case overflow:
671         bclr(BT, encode_crbit(cr, CR_SO), lk);
672         break;
673       case nooverflow:
674         bclr(BF, encode_crbit(cr, CR_SO), lk);
675         break;
676       default:
677         UNIMPLEMENTED();
678     }
679   }
680 
681   void isel(Register rt, Register ra, Register rb, int cb);
682   void isel(Condition cond, Register rt, Register ra, Register rb,
683             CRegister cr = cr7) {
684     DCHECK(cond != al);
685     DCHECK(cr.code() >= 0 && cr.code() <= 7);
686 
687     cr = cmpi_optimization(cr);
688 
689     switch (cond) {
690       case eq:
691         isel(rt, ra, rb, encode_crbit(cr, CR_EQ));
692         break;
693       case ne:
694         isel(rt, rb, ra, encode_crbit(cr, CR_EQ));
695         break;
696       case gt:
697         isel(rt, ra, rb, encode_crbit(cr, CR_GT));
698         break;
699       case le:
700         isel(rt, rb, ra, encode_crbit(cr, CR_GT));
701         break;
702       case lt:
703         isel(rt, ra, rb, encode_crbit(cr, CR_LT));
704         break;
705       case ge:
706         isel(rt, rb, ra, encode_crbit(cr, CR_LT));
707         break;
708       case unordered:
709         isel(rt, ra, rb, encode_crbit(cr, CR_FU));
710         break;
711       case ordered:
712         isel(rt, rb, ra, encode_crbit(cr, CR_FU));
713         break;
714       case overflow:
715         isel(rt, ra, rb, encode_crbit(cr, CR_SO));
716         break;
717       case nooverflow:
718         isel(rt, rb, ra, encode_crbit(cr, CR_SO));
719         break;
720       default:
721         UNIMPLEMENTED();
722     }
723   }
724 
725   void b(Condition cond, Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
726     if (cond == al) {
727       b(L, lk);
728       return;
729     }
730 
731     if ((L->is_bound() && is_near(L, cond)) || !is_trampoline_emitted()) {
732       bc_short(cond, L, cr, lk);
733       return;
734     }
735 
736     Label skip;
737     Condition neg_cond = NegateCondition(cond);
738     bc_short(neg_cond, &skip, cr);
739     b(L, lk);
740     bind(&skip);
741   }
742 
743   void bne(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
744     b(ne, L, cr, lk);
745   }
746   void beq(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
747     b(eq, L, cr, lk);
748   }
749   void blt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
750     b(lt, L, cr, lk);
751   }
752   void bge(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
753     b(ge, L, cr, lk);
754   }
755   void ble(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
756     b(le, L, cr, lk);
757   }
758   void bgt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
759     b(gt, L, cr, lk);
760   }
761   void bunordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
762     b(unordered, L, cr, lk);
763   }
764   void bordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
765     b(ordered, L, cr, lk);
766   }
767   void boverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
768     b(overflow, L, cr, lk);
769   }
770   void bnooverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
771     b(nooverflow, L, cr, lk);
772   }
773 
774   // Decrement CTR; branch if CTR != 0
775   void bdnz(Label* L, LKBit lk = LeaveLK) {
776     bc(branch_offset(L), DCBNZ, 0, lk);
777   }
778 
779   // Data-processing instructions
780 
781   void sub(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
782            RCBit r = LeaveRC);
783 
784   void subc(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
785             RCBit r = LeaveRC);
786   void sube(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
787             RCBit r = LeaveRC);
788 
789   void subfic(Register dst, Register src, const Operand& imm);
790 
791   void add(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
792            RCBit r = LeaveRC);
793 
794   void addc(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
795             RCBit r = LeaveRC);
796   void adde(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
797             RCBit r = LeaveRC);
798   void addze(Register dst, Register src1, OEBit o = LeaveOE, RCBit r = LeaveRC);
799 
800   void mullw(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
801              RCBit r = LeaveRC);
802 
803   void mulhw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
804   void mulhwu(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
805 
806   void divw(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
807             RCBit r = LeaveRC);
808   void divwu(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
809              RCBit r = LeaveRC);
810 
811   void addi(Register dst, Register src, const Operand& imm);
812   void addis(Register dst, Register src, const Operand& imm);
813   void addic(Register dst, Register src, const Operand& imm);
814 
815   void andi(Register ra, Register rs, const Operand& imm);
816   void andis(Register ra, Register rs, const Operand& imm);
817   void ori(Register dst, Register src, const Operand& imm);
818   void oris(Register dst, Register src, const Operand& imm);
819   void xori(Register dst, Register src, const Operand& imm);
820   void xoris(Register ra, Register rs, const Operand& imm);
821   void cmpi(Register src1, const Operand& src2, CRegister cr = cr7);
822   void cmpli(Register src1, const Operand& src2, CRegister cr = cr7);
823   void cmpwi(Register src1, const Operand& src2, CRegister cr = cr7);
824   void cmplwi(Register src1, const Operand& src2, CRegister cr = cr7);
825   void li(Register dst, const Operand& src);
826   void lis(Register dst, const Operand& imm);
827   void mr(Register dst, Register src);
828 
829   void lbz(Register dst, const MemOperand& src);
830   void lhz(Register dst, const MemOperand& src);
831   void lha(Register dst, const MemOperand& src);
832   void lwz(Register dst, const MemOperand& src);
833   void lwzu(Register dst, const MemOperand& src);
834   void lwa(Register dst, const MemOperand& src);
835   void stb(Register dst, const MemOperand& src);
836   void sth(Register dst, const MemOperand& src);
837   void stw(Register dst, const MemOperand& src);
838   void stwu(Register dst, const MemOperand& src);
839   void neg(Register rt, Register ra, OEBit o = LeaveOE, RCBit c = LeaveRC);
840 
841 #if V8_TARGET_ARCH_PPC64
842   void ld(Register rd, const MemOperand& src);
843   void ldu(Register rd, const MemOperand& src);
844   void std(Register rs, const MemOperand& src);
845   void stdu(Register rs, const MemOperand& src);
846   void rldic(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
847   void rldicl(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
848   void rldcl(Register ra, Register rs, Register rb, int mb, RCBit r = LeaveRC);
849   void rldicr(Register dst, Register src, int sh, int me, RCBit r = LeaveRC);
850   void rldimi(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
851   void sldi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
852   void srdi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
853   void clrrdi(Register dst, Register src, const Operand& val,
854               RCBit rc = LeaveRC);
855   void clrldi(Register dst, Register src, const Operand& val,
856               RCBit rc = LeaveRC);
857   void sradi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
858   void rotld(Register ra, Register rs, Register rb, RCBit r = LeaveRC);
859   void rotldi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
860   void rotrdi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
861   void mulld(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
862              RCBit r = LeaveRC);
863   void divd(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
864             RCBit r = LeaveRC);
865   void divdu(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
866              RCBit r = LeaveRC);
867 #endif
868 
869   void rlwinm(Register ra, Register rs, int sh, int mb, int me,
870               RCBit rc = LeaveRC);
871   void rlwimi(Register ra, Register rs, int sh, int mb, int me,
872               RCBit rc = LeaveRC);
873   void rlwnm(Register ra, Register rs, Register rb, int mb, int me,
874              RCBit rc = LeaveRC);
875   void slwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
876   void srwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
877   void clrrwi(Register dst, Register src, const Operand& val,
878               RCBit rc = LeaveRC);
879   void clrlwi(Register dst, Register src, const Operand& val,
880               RCBit rc = LeaveRC);
881   void rotlw(Register ra, Register rs, Register rb, RCBit r = LeaveRC);
882   void rotlwi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
883   void rotrwi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
884 
885   void subi(Register dst, Register src1, const Operand& src2);
886 
887   void mov(Register dst, const Operand& src);
888   void bitwise_mov(Register dst, intptr_t value);
889   void bitwise_mov32(Register dst, int32_t value);
890   void bitwise_add32(Register dst, Register src, int32_t value);
891 
892   // Load the position of the label relative to the generated code object
893   // pointer in a register.
894   void mov_label_offset(Register dst, Label* label);
895 
896   // dst = base + label position + delta
897   void add_label_offset(Register dst, Register base, Label* label,
898                         int delta = 0);
899 
900   // Load the address of the label in a register and associate with an
901   // internal reference relocation.
902   void mov_label_addr(Register dst, Label* label);
903 
904   // Emit the address of the label (i.e. a jump table entry) and associate with
905   // an internal reference relocation.
906   void emit_label_addr(Label* label);
907 
908   // Multiply instructions
909   void mul(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
910            RCBit r = LeaveRC);
911 
912   // Miscellaneous arithmetic instructions
913 
914   // Special register access
915   void crxor(int bt, int ba, int bb);
crclr(int bt)916   void crclr(int bt) { crxor(bt, bt, bt); }
917   void creqv(int bt, int ba, int bb);
crset(int bt)918   void crset(int bt) { creqv(bt, bt, bt); }
919   void mflr(Register dst);
920   void mtlr(Register src);
921   void mtctr(Register src);
922   void mtxer(Register src);
923   void mcrfs(CRegister cr, FPSCRBit bit);
924   void mfcr(Register dst);
925 #if V8_TARGET_ARCH_PPC64
926   void mffprd(Register dst, DoubleRegister src);
927   void mffprwz(Register dst, DoubleRegister src);
928   void mtfprd(DoubleRegister dst, Register src);
929   void mtfprwz(DoubleRegister dst, Register src);
930   void mtfprwa(DoubleRegister dst, Register src);
931 #endif
932 
933   // Exception-generating instructions and debugging support
934   void stop(Condition cond = al, int32_t code = kDefaultStopCode,
935             CRegister cr = cr7);
936 
937   void bkpt(uint32_t imm16);  // v5 and above
938 
939   void dcbf(Register ra, Register rb);
940   void sync();
941   void lwsync();
942   void icbi(Register ra, Register rb);
943   void isync();
944 
945   // Support for floating point
946   void lfd(const DoubleRegister frt, const MemOperand& src);
947   void lfdu(const DoubleRegister frt, const MemOperand& src);
948   void lfs(const DoubleRegister frt, const MemOperand& src);
949   void lfsu(const DoubleRegister frt, const MemOperand& src);
950   void stfd(const DoubleRegister frs, const MemOperand& src);
951   void stfdu(const DoubleRegister frs, const MemOperand& src);
952   void stfs(const DoubleRegister frs, const MemOperand& src);
953   void stfsu(const DoubleRegister frs, const MemOperand& src);
954 
955   void fadd(const DoubleRegister frt, const DoubleRegister fra,
956             const DoubleRegister frb, RCBit rc = LeaveRC);
957   void fsub(const DoubleRegister frt, const DoubleRegister fra,
958             const DoubleRegister frb, RCBit rc = LeaveRC);
959   void fdiv(const DoubleRegister frt, const DoubleRegister fra,
960             const DoubleRegister frb, RCBit rc = LeaveRC);
961   void fmul(const DoubleRegister frt, const DoubleRegister fra,
962             const DoubleRegister frc, RCBit rc = LeaveRC);
963   void fcmpu(const DoubleRegister fra, const DoubleRegister frb,
964              CRegister cr = cr7);
965   void fmr(const DoubleRegister frt, const DoubleRegister frb,
966            RCBit rc = LeaveRC);
967   void fctiwz(const DoubleRegister frt, const DoubleRegister frb);
968   void fctiw(const DoubleRegister frt, const DoubleRegister frb);
969   void fctiwuz(const DoubleRegister frt, const DoubleRegister frb);
970   void frin(const DoubleRegister frt, const DoubleRegister frb,
971             RCBit rc = LeaveRC);
972   void friz(const DoubleRegister frt, const DoubleRegister frb,
973             RCBit rc = LeaveRC);
974   void frip(const DoubleRegister frt, const DoubleRegister frb,
975             RCBit rc = LeaveRC);
976   void frim(const DoubleRegister frt, const DoubleRegister frb,
977             RCBit rc = LeaveRC);
978   void frsp(const DoubleRegister frt, const DoubleRegister frb,
979             RCBit rc = LeaveRC);
980   void fcfid(const DoubleRegister frt, const DoubleRegister frb,
981              RCBit rc = LeaveRC);
982   void fcfidu(const DoubleRegister frt, const DoubleRegister frb,
983               RCBit rc = LeaveRC);
984   void fcfidus(const DoubleRegister frt, const DoubleRegister frb,
985                RCBit rc = LeaveRC);
986   void fcfids(const DoubleRegister frt, const DoubleRegister frb,
987               RCBit rc = LeaveRC);
988   void fctid(const DoubleRegister frt, const DoubleRegister frb,
989              RCBit rc = LeaveRC);
990   void fctidz(const DoubleRegister frt, const DoubleRegister frb,
991               RCBit rc = LeaveRC);
992   void fctidu(const DoubleRegister frt, const DoubleRegister frb,
993               RCBit rc = LeaveRC);
994   void fctiduz(const DoubleRegister frt, const DoubleRegister frb,
995                RCBit rc = LeaveRC);
996   void fsel(const DoubleRegister frt, const DoubleRegister fra,
997             const DoubleRegister frc, const DoubleRegister frb,
998             RCBit rc = LeaveRC);
999   void fneg(const DoubleRegister frt, const DoubleRegister frb,
1000             RCBit rc = LeaveRC);
1001   void mtfsb0(FPSCRBit bit, RCBit rc = LeaveRC);
1002   void mtfsb1(FPSCRBit bit, RCBit rc = LeaveRC);
1003   void mtfsfi(int bf, int immediate, RCBit rc = LeaveRC);
1004   void mffs(const DoubleRegister frt, RCBit rc = LeaveRC);
1005   void mtfsf(const DoubleRegister frb, bool L = 1, int FLM = 0, bool W = 0,
1006              RCBit rc = LeaveRC);
1007   void fsqrt(const DoubleRegister frt, const DoubleRegister frb,
1008              RCBit rc = LeaveRC);
1009   void fabs(const DoubleRegister frt, const DoubleRegister frb,
1010             RCBit rc = LeaveRC);
1011   void fmadd(const DoubleRegister frt, const DoubleRegister fra,
1012              const DoubleRegister frc, const DoubleRegister frb,
1013              RCBit rc = LeaveRC);
1014   void fmsub(const DoubleRegister frt, const DoubleRegister fra,
1015              const DoubleRegister frc, const DoubleRegister frb,
1016              RCBit rc = LeaveRC);
1017 
1018   // Vector instructions
1019   void mfvsrd(const Register ra, const Simd128Register r);
1020   void mfvsrwz(const Register ra, const Simd128Register r);
1021   void mtvsrd(const Simd128Register rt, const Register ra);
1022   void mtvsrdd(const Simd128Register rt, const Register ra, const Register rb);
1023   void lxvd(const Simd128Register rt, const MemOperand& src);
1024   void stxvd(const Simd128Register rt, const MemOperand& src);
1025   void xxspltib(const Simd128Register rt, const Operand& imm);
1026 
1027   // Pseudo instructions
1028 
1029   // Different nop operations are used by the code generator to detect certain
1030   // states of the generated code.
1031   enum NopMarkerTypes {
1032     NON_MARKING_NOP = 0,
1033     GROUP_ENDING_NOP,
1034     DEBUG_BREAK_NOP,
1035     // IC markers.
1036     PROPERTY_ACCESS_INLINED,
1037     PROPERTY_ACCESS_INLINED_CONTEXT,
1038     PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1039     // Helper values.
1040     LAST_CODE_MARKER,
1041     FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1042   };
1043 
1044   void nop(int type = 0);  // 0 is the default non-marking type.
1045 
push(Register src)1046   void push(Register src) {
1047 #if V8_TARGET_ARCH_PPC64
1048     stdu(src, MemOperand(sp, -kSystemPointerSize));
1049 #else
1050     stwu(src, MemOperand(sp, -kSystemPointerSize));
1051 #endif
1052   }
1053 
pop(Register dst)1054   void pop(Register dst) {
1055 #if V8_TARGET_ARCH_PPC64
1056     ld(dst, MemOperand(sp));
1057 #else
1058     lwz(dst, MemOperand(sp));
1059 #endif
1060     addi(sp, sp, Operand(kSystemPointerSize));
1061   }
1062 
pop()1063   void pop() { addi(sp, sp, Operand(kSystemPointerSize)); }
1064 
1065   // Jump unconditionally to given label.
jmp(Label * L)1066   void jmp(Label* L) { b(L); }
1067 
1068   // Check the code size generated from label to here.
SizeOfCodeGeneratedSince(Label * label)1069   int SizeOfCodeGeneratedSince(Label* label) {
1070     return pc_offset() - label->pos();
1071   }
1072 
1073   // Check the number of instructions generated from label to here.
InstructionsGeneratedSince(Label * label)1074   int InstructionsGeneratedSince(Label* label) {
1075     return SizeOfCodeGeneratedSince(label) / kInstrSize;
1076   }
1077 
1078   // Class for scoping postponing the trampoline pool generation.
1079   class BlockTrampolinePoolScope {
1080    public:
BlockTrampolinePoolScope(Assembler * assem)1081     explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) {
1082       assem_->StartBlockTrampolinePool();
1083     }
~BlockTrampolinePoolScope()1084     ~BlockTrampolinePoolScope() { assem_->EndBlockTrampolinePool(); }
1085 
1086    private:
1087     Assembler* assem_;
1088 
1089     DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope);
1090   };
1091 
1092   // Class for scoping disabling constant pool entry merging
1093   class BlockConstantPoolEntrySharingScope {
1094    public:
BlockConstantPoolEntrySharingScope(Assembler * assem)1095     explicit BlockConstantPoolEntrySharingScope(Assembler* assem)
1096         : assem_(assem) {
1097       assem_->StartBlockConstantPoolEntrySharing();
1098     }
~BlockConstantPoolEntrySharingScope()1099     ~BlockConstantPoolEntrySharingScope() {
1100       assem_->EndBlockConstantPoolEntrySharing();
1101     }
1102 
1103    private:
1104     Assembler* assem_;
1105 
1106     DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstantPoolEntrySharingScope);
1107   };
1108 
1109   // Record a deoptimization reason that can be used by a log or cpu profiler.
1110   // Use --trace-deopt to enable.
1111   void RecordDeoptReason(DeoptimizeReason reason, SourcePosition position,
1112                          int id);
1113 
1114   // Writes a single byte or word of data in the code stream.  Used
1115   // for inline tables, e.g., jump-tables.
1116   void db(uint8_t data);
1117   void dd(uint32_t data);
1118   void dq(uint64_t data);
1119   void dp(uintptr_t data);
1120 
1121   // Read/patch instructions
instr_at(int pos)1122   Instr instr_at(int pos) {
1123     return *reinterpret_cast<Instr*>(buffer_start_ + pos);
1124   }
instr_at_put(int pos,Instr instr)1125   void instr_at_put(int pos, Instr instr) {
1126     *reinterpret_cast<Instr*>(buffer_start_ + pos) = instr;
1127   }
instr_at(Address pc)1128   static Instr instr_at(Address pc) { return *reinterpret_cast<Instr*>(pc); }
instr_at_put(Address pc,Instr instr)1129   static void instr_at_put(Address pc, Instr instr) {
1130     *reinterpret_cast<Instr*>(pc) = instr;
1131   }
1132   static Condition GetCondition(Instr instr);
1133 
1134   static bool IsLis(Instr instr);
1135   static bool IsLi(Instr instr);
1136   static bool IsAddic(Instr instr);
1137   static bool IsOri(Instr instr);
1138 
1139   static bool IsBranch(Instr instr);
1140   static Register GetRA(Instr instr);
1141   static Register GetRB(Instr instr);
1142 #if V8_TARGET_ARCH_PPC64
1143   static bool Is64BitLoadIntoR12(Instr instr1, Instr instr2, Instr instr3,
1144                                  Instr instr4, Instr instr5);
1145 #else
1146   static bool Is32BitLoadIntoR12(Instr instr1, Instr instr2);
1147 #endif
1148 
1149   static bool IsCmpRegister(Instr instr);
1150   static bool IsCmpImmediate(Instr instr);
1151   static bool IsRlwinm(Instr instr);
1152   static bool IsAndi(Instr instr);
1153 #if V8_TARGET_ARCH_PPC64
1154   static bool IsRldicl(Instr instr);
1155 #endif
1156   static bool IsCrSet(Instr instr);
1157   static Register GetCmpImmediateRegister(Instr instr);
1158   static int GetCmpImmediateRawImmediate(Instr instr);
1159   static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
1160 
1161   // Postpone the generation of the trampoline pool for the specified number of
1162   // instructions.
1163   void BlockTrampolinePoolFor(int instructions);
1164   void CheckTrampolinePool();
1165 
1166   // For mov.  Return the number of actual instructions required to
1167   // load the operand into a register.  This can be anywhere from
1168   // one (constant pool small section) to five instructions (full
1169   // 64-bit sequence).
1170   //
1171   // The value returned is only valid as long as no entries are added to the
1172   // constant pool between this call and the actual instruction being emitted.
1173   int instructions_required_for_mov(Register dst, const Operand& src) const;
1174 
1175   // Decide between using the constant pool vs. a mov immediate sequence.
1176   bool use_constant_pool_for_mov(Register dst, const Operand& src,
1177                                  bool canOptimize) const;
1178 
1179   // The code currently calls CheckBuffer() too often. This has the side
1180   // effect of randomly growing the buffer in the middle of multi-instruction
1181   // sequences.
1182   //
1183   // This function allows outside callers to check and grow the buffer
1184   void EnsureSpaceFor(int space_needed);
1185 
EmitConstantPool()1186   int EmitConstantPool() { return constant_pool_builder_.Emit(this); }
1187 
ConstantPoolAccessIsInOverflow()1188   bool ConstantPoolAccessIsInOverflow() const {
1189     return constant_pool_builder_.NextAccess(ConstantPoolEntry::INTPTR) ==
1190            ConstantPoolEntry::OVERFLOWED;
1191   }
1192 
ConstantPoolPosition()1193   Label* ConstantPoolPosition() {
1194     return constant_pool_builder_.EmittedPosition();
1195   }
1196 
1197   void EmitRelocations();
1198 
1199  protected:
buffer_space()1200   int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1201 
1202   // Decode instruction(s) at pos and return backchain to previous
1203   // label reference or kEndOfChain.
1204   int target_at(int pos);
1205 
1206   // Patch instruction(s) at pos to target target_pos (e.g. branch)
1207   void target_at_put(int pos, int target_pos, bool* is_branch = nullptr);
1208 
1209   // Record reloc info for current pc_
1210   void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
ConstantPoolAddEntry(RelocInfo::Mode rmode,intptr_t value)1211   ConstantPoolEntry::Access ConstantPoolAddEntry(RelocInfo::Mode rmode,
1212                                                  intptr_t value) {
1213     bool sharing_ok =
1214         RelocInfo::IsNone(rmode) ||
1215         (!options().record_reloc_info_for_serialization &&
1216          RelocInfo::IsShareableRelocMode(rmode) &&
1217          !is_constant_pool_entry_sharing_blocked() &&
1218          // TODO(johnyan): make the following rmode shareable
1219          !RelocInfo::IsWasmCall(rmode) && !RelocInfo::IsWasmStubCall(rmode));
1220     return constant_pool_builder_.AddEntry(pc_offset(), value, sharing_ok);
1221   }
ConstantPoolAddEntry(Double value)1222   ConstantPoolEntry::Access ConstantPoolAddEntry(Double value) {
1223     return constant_pool_builder_.AddEntry(pc_offset(), value);
1224   }
1225 
1226   // Block the emission of the trampoline pool before pc_offset.
BlockTrampolinePoolBefore(int pc_offset)1227   void BlockTrampolinePoolBefore(int pc_offset) {
1228     if (no_trampoline_pool_before_ < pc_offset)
1229       no_trampoline_pool_before_ = pc_offset;
1230   }
1231 
StartBlockTrampolinePool()1232   void StartBlockTrampolinePool() { trampoline_pool_blocked_nesting_++; }
EndBlockTrampolinePool()1233   void EndBlockTrampolinePool() {
1234     int count = --trampoline_pool_blocked_nesting_;
1235     if (count == 0) CheckTrampolinePoolQuick();
1236   }
is_trampoline_pool_blocked()1237   bool is_trampoline_pool_blocked() const {
1238     return trampoline_pool_blocked_nesting_ > 0;
1239   }
1240 
StartBlockConstantPoolEntrySharing()1241   void StartBlockConstantPoolEntrySharing() {
1242     constant_pool_entry_sharing_blocked_nesting_++;
1243   }
EndBlockConstantPoolEntrySharing()1244   void EndBlockConstantPoolEntrySharing() {
1245     constant_pool_entry_sharing_blocked_nesting_--;
1246   }
is_constant_pool_entry_sharing_blocked()1247   bool is_constant_pool_entry_sharing_blocked() const {
1248     return constant_pool_entry_sharing_blocked_nesting_ > 0;
1249   }
1250 
has_exception()1251   bool has_exception() const { return internal_trampoline_exception_; }
1252 
is_trampoline_emitted()1253   bool is_trampoline_emitted() const { return trampoline_emitted_; }
1254 
1255   // Code generation
1256   // The relocation writer's position is at least kGap bytes below the end of
1257   // the generated instructions. This is so that multi-instruction sequences do
1258   // not have to check for overflow. The same is true for writes of large
1259   // relocation info entries.
1260   static constexpr int kGap = 32;
1261   STATIC_ASSERT(AssemblerBase::kMinimalBufferSize >= 2 * kGap);
1262 
1263   RelocInfoWriter reloc_info_writer;
1264 
1265  private:
1266   // Avoid overflows for displacements etc.
1267   static const int kMaximalBufferSize = 512 * MB;
1268 
1269   // Repeated checking whether the trampoline pool should be emitted is rather
1270   // expensive. By default we only check again once a number of instructions
1271   // has been generated.
1272   int next_trampoline_check_;  // pc offset of next buffer check.
1273 
1274   // Emission of the trampoline pool may be blocked in some code sequences.
1275   int trampoline_pool_blocked_nesting_;  // Block emission if this is not zero.
1276   int no_trampoline_pool_before_;  // Block emission before this pc offset.
1277 
1278   // Do not share constant pool entries.
1279   int constant_pool_entry_sharing_blocked_nesting_;
1280 
1281   // Relocation info generation
1282   // Each relocation is encoded as a variable size value
1283   static constexpr int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1284   std::vector<DeferredRelocInfo> relocations_;
1285 
1286   // Scratch registers available for use by the Assembler.
1287   RegList scratch_register_list_;
1288 
1289   // The bound position, before this we cannot do instruction elimination.
1290   int last_bound_pos_;
1291   // Optimizable cmpi information.
1292   int optimizable_cmpi_pos_;
1293   CRegister cmpi_cr_ = CRegister::no_reg();
1294 
1295   ConstantPoolBuilder constant_pool_builder_;
1296 
CheckBuffer()1297   void CheckBuffer() {
1298     if (buffer_space() <= kGap) {
1299       GrowBuffer();
1300     }
1301   }
1302 
1303   void GrowBuffer(int needed = 0);
1304   // Code emission
emit(Instr x)1305   void emit(Instr x) {
1306     CheckBuffer();
1307     *reinterpret_cast<Instr*>(pc_) = x;
1308     pc_ += kInstrSize;
1309     CheckTrampolinePoolQuick();
1310   }
TrackBranch()1311   void TrackBranch() {
1312     DCHECK(!trampoline_emitted_);
1313     int count = tracked_branch_count_++;
1314     if (count == 0) {
1315       // We leave space (kMaxBlockTrampolineSectionSize)
1316       // for BlockTrampolinePoolScope buffer.
1317       next_trampoline_check_ =
1318           pc_offset() + kMaxCondBranchReach - kMaxBlockTrampolineSectionSize;
1319     } else {
1320       next_trampoline_check_ -= kTrampolineSlotsSize;
1321     }
1322   }
1323 
1324   inline void UntrackBranch();
CheckTrampolinePoolQuick()1325   void CheckTrampolinePoolQuick() {
1326     if (pc_offset() >= next_trampoline_check_) {
1327       CheckTrampolinePool();
1328     }
1329   }
1330 
1331   // Instruction generation
1332   void a_form(Instr instr, DoubleRegister frt, DoubleRegister fra,
1333               DoubleRegister frb, RCBit r);
1334   void d_form(Instr instr, Register rt, Register ra, const intptr_t val,
1335               bool signed_disp);
1336   void xo_form(Instr instr, Register rt, Register ra, Register rb, OEBit o,
1337                RCBit r);
1338   void md_form(Instr instr, Register ra, Register rs, int shift, int maskbit,
1339                RCBit r);
1340   void mds_form(Instr instr, Register ra, Register rs, Register rb, int maskbit,
1341                 RCBit r);
1342 
1343   // Labels
1344   void print(Label* L);
1345   int max_reach_from(int pos);
1346   void bind_to(Label* L, int pos);
1347   void next(Label* L);
1348 
1349   class Trampoline {
1350    public:
Trampoline()1351     Trampoline() {
1352       next_slot_ = 0;
1353       free_slot_count_ = 0;
1354     }
Trampoline(int start,int slot_count)1355     Trampoline(int start, int slot_count) {
1356       next_slot_ = start;
1357       free_slot_count_ = slot_count;
1358     }
take_slot()1359     int take_slot() {
1360       int trampoline_slot = kInvalidSlotPos;
1361       if (free_slot_count_ <= 0) {
1362         // We have run out of space on trampolines.
1363         // Make sure we fail in debug mode, so we become aware of each case
1364         // when this happens.
1365         DCHECK(0);
1366         // Internal exception will be caught.
1367       } else {
1368         trampoline_slot = next_slot_;
1369         free_slot_count_--;
1370         next_slot_ += kTrampolineSlotsSize;
1371       }
1372       return trampoline_slot;
1373     }
1374 
1375    private:
1376     int next_slot_;
1377     int free_slot_count_;
1378   };
1379 
1380   int32_t get_trampoline_entry();
1381   int tracked_branch_count_;
1382   // If trampoline is emitted, generated code is becoming large. As
1383   // this is already a slow case which can possibly break our code
1384   // generation for the extreme case, we use this information to
1385   // trigger different mode of branch instruction generation, where we
1386   // no longer use a single branch instruction.
1387   bool trampoline_emitted_;
1388   static constexpr int kTrampolineSlotsSize = kInstrSize;
1389   static constexpr int kMaxCondBranchReach = (1 << (16 - 1)) - 1;
1390   static constexpr int kMaxBlockTrampolineSectionSize = 64 * kInstrSize;
1391   static constexpr int kInvalidSlotPos = -1;
1392 
1393   Trampoline trampoline_;
1394   bool internal_trampoline_exception_;
1395 
1396   void AllocateAndInstallRequestedHeapObjects(Isolate* isolate);
1397 
1398   int WriteCodeComments();
1399 
1400   friend class RegExpMacroAssemblerPPC;
1401   friend class RelocInfo;
1402   friend class BlockTrampolinePoolScope;
1403   friend class EnsureSpace;
1404   friend class UseScratchRegisterScope;
1405 };
1406 
1407 class EnsureSpace {
1408  public:
EnsureSpace(Assembler * assembler)1409   explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); }
1410 };
1411 
1412 class PatchingAssembler : public Assembler {
1413  public:
1414   PatchingAssembler(const AssemblerOptions& options, byte* address,
1415                     int instructions);
1416   ~PatchingAssembler();
1417 };
1418 
1419 class V8_EXPORT_PRIVATE UseScratchRegisterScope {
1420  public:
1421   explicit UseScratchRegisterScope(Assembler* assembler);
1422   ~UseScratchRegisterScope();
1423 
1424   Register Acquire();
1425 
1426   // Check if we have registers available to acquire.
CanAcquire()1427   bool CanAcquire() const { return *assembler_->GetScratchRegisterList() != 0; }
1428 
1429  private:
1430   friend class Assembler;
1431   friend class TurboAssembler;
1432 
1433   Assembler* assembler_;
1434   RegList old_available_;
1435 };
1436 
1437 }  // namespace internal
1438 }  // namespace v8
1439 
1440 #endif  // V8_CODEGEN_PPC_ASSEMBLER_PPC_H_
1441