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