v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
assembler-ppc.h
Go to the documentation of this file.
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
51#include "src/codegen/label.h"
54#include "src/objects/smi.h"
55
56namespace v8 {
57namespace internal {
58
59class SafepointTableBuilder;
60
61// -----------------------------------------------------------------------------
62// Machine instruction Operands
63
64// Class Operand represents a shifter operand in data processing instructions
65class V8_EXPORT_PRIVATE Operand {
66 public:
67 // immediate
68 V8_INLINE explicit Operand(intptr_t immediate,
69 RelocInfo::Mode rmode = RelocInfo::NO_INFO)
70 : rmode_(rmode) {
71 value_.immediate = immediate;
72 }
73 V8_INLINE static Operand Zero() { return Operand(static_cast<intptr_t>(0)); }
75 : rmode_(RelocInfo::EXTERNAL_REFERENCE) {
76 value_.immediate = static_cast<intptr_t>(f.address());
77 }
78 explicit Operand(Handle<HeapObject> handle);
79 V8_INLINE explicit Operand(Tagged<Smi> value) : rmode_(RelocInfo::NO_INFO) {
80 value_.immediate = static_cast<intptr_t>(value.ptr());
81 }
82 // rm
84
85 static Operand EmbeddedNumber(double number); // Smi or HeapNumber.
86
87 // Return true if this is a register operand.
88 V8_INLINE bool is_reg() const { return rm_.is_valid(); }
89
90 bool must_output_reloc_info(const Assembler* assembler) const;
91
92 inline intptr_t immediate() const {
93 DCHECK(IsImmediate());
94 DCHECK(!IsHeapNumberRequest());
95 return value_.immediate;
96 }
97 bool IsImmediate() const { return !rm_.is_valid(); }
98
100 DCHECK(IsHeapNumberRequest());
101 return value_.heap_number_request;
102 }
103
104 Register rm() const { return rm_; }
105
106 bool IsHeapNumberRequest() const {
107 DCHECK_IMPLIES(is_heap_number_request_, IsImmediate());
108 DCHECK_IMPLIES(is_heap_number_request_,
109 rmode_ == RelocInfo::FULL_EMBEDDED_OBJECT ||
110 rmode_ == RelocInfo::CODE_TARGET);
111 return is_heap_number_request_;
112 }
113
114 private:
115 Register rm_ = no_reg;
116 union Value {
117 Value() {}
118 HeapNumberRequest heap_number_request; // if is_heap_number_request_
119 intptr_t immediate; // otherwise
120 } value_; // valid if rm_ == no_reg
121 bool is_heap_number_request_ = false;
122
123 RelocInfo::Mode rmode_;
124
125 friend class Assembler;
126 friend class MacroAssembler;
127};
128
129// Class MemOperand represents a memory operand in load and store instructions
130// On PowerPC we have base register + 16bit signed value
131// Alternatively we can have a 16bit signed value immediate
133 public:
134 explicit MemOperand(Register rn, int64_t offset = 0);
135
136 explicit MemOperand(Register ra, Register rb);
137
138 explicit MemOperand(Register ra, Register rb, int64_t offset);
139
140 int64_t offset() const { return offset_; }
141
142 // PowerPC - base register
143 Register ra() const { return ra_; }
144
145 Register rb() const { return rb_; }
146
147 private:
148 Register ra_; // base
149 int64_t offset_; // offset
150 Register rb_; // index
151
152 friend class Assembler;
153};
154
155class DeferredRelocInfo {
156 public:
160
161 int position() const { return position_; }
162 RelocInfo::Mode rmode() const { return rmode_; }
163 intptr_t data() const { return data_; }
164
165 private:
168 intptr_t data_;
169};
170
171class Assembler : public AssemblerBase {
172 public:
173 // Create an assembler. Instructions and relocation information are emitted
174 // into a buffer, with the instructions starting from the beginning and the
175 // relocation information starting from the end of the buffer. See CodeDesc
176 // for a detailed comment on the layout (globals.h).
177 //
178 // If the provided buffer is nullptr, the assembler allocates and grows its
179 // own buffer. Otherwise it takes ownership of the provided buffer.
181 std::unique_ptr<AssemblerBuffer> = {});
182 // For compatibility with assemblers that require a zone.
184 std::unique_ptr<AssemblerBuffer> buffer = {})
185 : Assembler(options, std::move(buffer)) {}
186
187 virtual ~Assembler() {}
188
189 // GetCode emits any pending (non-emitted) code and fills the descriptor desc.
190 static constexpr int kNoHandlerTable = 0;
191 static constexpr SafepointTableBuilderBase* kNoSafepointTable = nullptr;
192 void GetCode(LocalIsolate* isolate, CodeDesc* desc,
193 SafepointTableBuilderBase* safepoint_table_builder,
194 int handler_table_offset);
195
196 // Convenience wrapper for allocating with an Isolate.
197 void GetCode(Isolate* isolate, CodeDesc* desc);
198 // Convenience wrapper for code without safepoint or handler tables.
199 void GetCode(LocalIsolate* isolate, CodeDesc* desc) {
201 }
202
204
205 inline void CheckTrampolinePoolQuick(int extra_space = 0) {
206 if (pc_offset() >= next_trampoline_check_ - extra_space) {
208 }
209 }
210
211 // Label operations & relative jumps (PPUM Appendix D)
212 //
213 // Takes a branch opcode (cc) and a label (L) and generates
214 // either a backward branch or a forward branch and links it
215 // to the label fixup chain. Usage:
216 //
217 // Label L; // unbound label
218 // j(cc, &L); // forward branch to unbound label
219 // bind(&L); // bind label to the current pc
220 // j(cc, &L); // backward branch to bound label
221 // bind(&L); // illegal: a label may be bound only once
222 //
223 // Note: The same Label can be used for forward and backward branches
224 // but it may be bound only once.
225
226 void bind(Label* L); // binds an unbound label L to the current code position
227
228 // Links a label at the current pc_offset(). If already bound, returns the
229 // bound position. If already linked, returns the position of the prior link.
230 // Otherwise, returns the current pc_offset().
231 int link(Label* L);
232
233 // Determines if Label is bound and near enough so that a single
234 // branch instruction can be used to reach it.
235 bool is_near(Label* L, Condition cond);
236
237 // Returns the branch offset to the given label from the current code position
238 // Links the label to the current position if it is still unbound
240 if (L->is_unused() && !trampoline_emitted_) {
241 TrackBranch();
242 }
243 return link(L) - pc_offset();
244 }
245
247 Address pc, ConstantPoolEntry::Access* access = nullptr);
249 Address pc, ConstantPoolEntry::Access* access = nullptr);
256
257 // Return the address in the constant pool of the code target address used by
258 // the branch/call instruction at pc, or the object in a mov.
262
263 // Read/Modify the code target address in the branch/call instruction at pc.
264 // The isolate argument is unused (and may be nullptr) when skipping flushing.
268 WritableJitAllocation* jit_allocation,
269 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
270
271 // Read/Modify the code target address in the branch/call instruction at pc.
276 WritableJitAllocation* jit_allocation,
277 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
278
283
284 // Get the size of the special target encoded at 'instruction_payload'.
286 Address instruction_payload);
287
288 // This sets the internal reference at the pc.
290 Address pc, Address target, WritableJitAllocation& jit_allocation,
292
293 // Read/modify the uint32 constant used at pc.
295 static inline void set_uint32_constant_at(
296 Address pc, Address constant_pool, uint32_t new_constant,
297 WritableJitAllocation* jit_allocation,
298 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
299
300 // Here we are patching the address in the LUI/ORI instruction pair.
301 // These values are used in the serialization process and must be zero for
302 // PPC platform, as Code, Embedded Object or External-reference pointers
303 // are split across two consecutive instructions and don't exist separately
304 // in the code, so the serializer should not step forwards in memory after
305 // a target is resolved and written.
306 static constexpr int kSpecialTargetSize = 0;
307
308// Number of instructions to load an address via a mov sequence.
309 static constexpr int kMovInstructionsConstantPool = 1;
310 static constexpr int kMovInstructionsNoConstantPool = 5;
311#if defined(V8_PPC_TAGGING_OPT)
312 static constexpr int kTaggedLoadInstructions = 1;
313#else
314 static constexpr int kTaggedLoadInstructions = 2;
315#endif
319
320 static inline int encode_crbit(const CRegister& cr, enum CRBit crbit) {
321 return ((cr.code() * CRWIDTH) + crbit);
322 }
323
324#define DECLARE_PPC_X_INSTRUCTIONS_A_FORM(name, instr_name, instr_value) \
325 inline void name(const Register rt, const Register ra, const Register rb, \
326 const RCBit rc = LeaveRC) { \
327 x_form(instr_name, rt, ra, rb, rc); \
328 }
329
330#define DECLARE_PPC_X_INSTRUCTIONS_B_FORM(name, instr_name, instr_value) \
331 inline void name(const Register ra, const Register rs, const Register rb, \
332 const RCBit rc = LeaveRC) { \
333 x_form(instr_name, rs, ra, rb, rc); \
334 }
335
336#define DECLARE_PPC_X_INSTRUCTIONS_C_FORM(name, instr_name, instr_value) \
337 inline void name(const Register dst, const Register src, \
338 const RCBit rc = LeaveRC) { \
339 x_form(instr_name, src, dst, r0, rc); \
340 }
341
342#define DECLARE_PPC_X_INSTRUCTIONS_D_FORM(name, instr_name, instr_value) \
343 template <class R> \
344 inline void name(const R rt, const Register ra, const Register rb, \
345 const RCBit rc = LeaveRC) { \
346 x_form(instr_name, rt.code(), ra.code(), rb.code(), rc); \
347 } \
348 template <class R> \
349 inline void name(const R dst, const MemOperand& src) { \
350 name(dst, src.ra(), src.rb()); \
351 }
352
353#define DECLARE_PPC_X_INSTRUCTIONS_E_FORM(name, instr_name, instr_value) \
354 inline void name(const Register dst, const Register src, const int sh, \
355 const RCBit rc = LeaveRC) { \
356 x_form(instr_name, src.code(), dst.code(), sh, rc); \
357 }
358
359#define DECLARE_PPC_X_INSTRUCTIONS_F_FORM(name, instr_name, instr_value) \
360 inline void name(const Register src1, const Register src2, \
361 const CRegister cr = cr0, const RCBit rc = LeaveRC) { \
362 x_form(instr_name, cr, src1, src2, rc); \
363 } \
364 inline void name##w(const Register src1, const Register src2, \
365 const CRegister cr = cr0, const RCBit rc = LeaveRC) { \
366 x_form(instr_name, cr.code() * B2, src1.code(), src2.code(), LeaveRC); \
367 }
368
369#define DECLARE_PPC_X_INSTRUCTIONS_G_FORM(name, instr_name, instr_value) \
370 inline void name(const Register dst, const Register src) { \
371 x_form(instr_name, src, dst, r0, LeaveRC); \
372 }
373
374#define DECLARE_PPC_X_INSTRUCTIONS_EH_S_FORM(name, instr_name, instr_value) \
375 inline void name(const Register dst, const MemOperand& src) { \
376 x_form(instr_name, src.ra(), dst, src.rb(), SetEH); \
377 }
378#define DECLARE_PPC_X_INSTRUCTIONS_EH_L_FORM(name, instr_name, instr_value) \
379 inline void name(const Register dst, const MemOperand& src) { \
380 x_form(instr_name, src.ra(), dst, src.rb(), SetEH); \
381 }
382
383 inline void x_form(Instr instr, int f1, int f2, int f3, int rc) {
384 emit(instr | f1 * B21 | f2 * B16 | f3 * B11 | rc);
385 }
387 RCBit rc) {
388 emit(instr | rs.code() * B21 | ra.code() * B16 | rb.code() * B11 | rc);
389 }
391 EHBit eh = SetEH) {
392 emit(instr | rs.code() * B21 | ra.code() * B16 | rb.code() * B11 | eh);
393 }
394 inline void x_form(Instr instr, CRegister cr, Register s1, Register s2,
395 RCBit rc) {
396 int L = 1;
397 emit(instr | cr.code() * B23 | L * B21 | s1.code() * B16 | s2.code() * B11 |
398 rc);
399 }
400
410
411 inline void notx(Register dst, Register src, RCBit rc = LeaveRC) {
412 nor(dst, src, src, rc);
413 }
414 inline void lwax(Register rt, const MemOperand& src) {
415 Register ra = src.ra();
416 Register rb = src.rb();
417 DCHECK(ra != r0);
418 x_form(LWAX, rt, ra, rb, LeaveRC);
419 }
420 inline void extsw(Register rs, Register ra, RCBit rc = LeaveRC) {
421 emit(EXT2 | EXTSW | ra.code() * B21 | rs.code() * B16 | rc);
422 }
423
424#undef DECLARE_PPC_X_INSTRUCTIONS_A_FORM
425#undef DECLARE_PPC_X_INSTRUCTIONS_B_FORM
426#undef DECLARE_PPC_X_INSTRUCTIONS_C_FORM
427#undef DECLARE_PPC_X_INSTRUCTIONS_D_FORM
428#undef DECLARE_PPC_X_INSTRUCTIONS_E_FORM
429#undef DECLARE_PPC_X_INSTRUCTIONS_F_FORM
430#undef DECLARE_PPC_X_INSTRUCTIONS_G_FORM
431#undef DECLARE_PPC_X_INSTRUCTIONS_EH_S_FORM
432#undef DECLARE_PPC_X_INSTRUCTIONS_EH_L_FORM
433
434#define DECLARE_PPC_XX2_VECTOR_INSTRUCTIONS(name, instr_name, instr_value) \
435 inline void name(const Simd128Register rt, const Simd128Register rb) { \
436 xx2_form(instr_name, rt, rb); \
437 }
438#define DECLARE_PPC_XX2_SCALAR_INSTRUCTIONS(name, instr_name, instr_value) \
439 inline void name(const DoubleRegister rt, const DoubleRegister rb) { \
440 xx2_form(instr_name, rt, rb); \
441 }
442
443 template <typename T>
444 inline void xx2_form(Instr instr, T t, T b) {
445 static_assert(std::is_same<T, Simd128Register>::value ||
446 std::is_same<T, DoubleRegister>::value,
447 "VSX only uses FP or Vector registers.");
448 // Using FP (low VSR) registers.
449 int BX = 0, TX = 0;
450 // Using VR (high VSR) registers when Simd registers are used.
451 if (std::is_same<T, Simd128Register>::value) {
452 BX = TX = 1;
453 }
454
455 emit(instr | (t.code() & 0x1F) * B21 | (b.code() & 0x1F) * B11 | BX * B1 |
456 TX);
457 }
458
462#undef DECLARE_PPC_XX2_VECTOR_INSTRUCTIONS
463#undef DECLARE_PPC_XX2_SCALAR_INSTRUCTIONS
464
465#define DECLARE_PPC_XX3_VECTOR_INSTRUCTIONS_A_FORM(name, instr_name, \
466 instr_value) \
467 inline void name(const Simd128Register rt, const Simd128Register ra, \
468 const Simd128Register rb, const RCBit rc = LeaveRC) { \
469 xx3_form(instr_name, rt, ra, rb, rc); \
470 }
471#define DECLARE_PPC_XX3_VECTOR_INSTRUCTIONS_B_FORM(name, instr_name, \
472 instr_value) \
473 inline void name(const Simd128Register rt, const Simd128Register ra, \
474 const Simd128Register rb) { \
475 xx3_form(instr_name, rt, ra, rb); \
476 }
477#define DECLARE_PPC_XX3_SCALAR_INSTRUCTIONS(name, instr_name, instr_value) \
478 inline void name(const DoubleRegister rt, const DoubleRegister ra, \
479 const DoubleRegister rb) { \
480 xx3_form(instr_name, rt, ra, rb); \
481 }
482
484 Simd128Register b, int rc) {
485 // Using VR (high VSR) registers.
486 int AX = 1, BX = 1, TX = 1;
487
488 emit(instr | (t.code() & 0x1F) * B21 | (a.code() & 0x1F) * B16 |
489 (b.code() & 0x1F) * B11 | rc * B10 | AX * B2 | BX * B1 | TX);
490 }
491
492 template <typename T>
493 inline void xx3_form(Instr instr, T t, T a, T b) {
494 static_assert(std::is_same<T, Simd128Register>::value ||
495 std::is_same<T, DoubleRegister>::value,
496 "VSX only uses FP or Vector registers.");
497 // Using FP (low VSR) registers.
498 int AX = 0, BX = 0, TX = 0;
499 // Using VR (high VSR) registers when Simd registers are used.
500 if (std::is_same<T, Simd128Register>::value) {
501 AX = BX = TX = 1;
502 }
503
504 emit(instr | (t.code() & 0x1F) * B21 | (a.code() & 0x1F) * B16 |
505 (b.code() & 0x1F) * B11 | AX * B2 | BX * B1 | TX);
506 }
507
511#undef DECLARE_PPC_XX3_VECTOR_INSTRUCTIONS_A_FORM
512#undef DECLARE_PPC_XX3_VECTOR_INSTRUCTIONS_B_FORM
513#undef DECLARE_PPC_XX3_SCALAR_INSTRUCTIONS
514
515#define DECLARE_PPC_VX_INSTRUCTIONS_A_FORM(name, instr_name, instr_value) \
516 inline void name(const Simd128Register rt, const Simd128Register rb, \
517 const Operand& imm) { \
518 vx_form(instr_name, rt, rb, imm); \
519 }
520#define DECLARE_PPC_VX_INSTRUCTIONS_B_FORM(name, instr_name, instr_value) \
521 inline void name(const Simd128Register rt, const Simd128Register ra, \
522 const Simd128Register rb) { \
523 vx_form(instr_name, rt, ra, rb); \
524 }
525#define DECLARE_PPC_VX_INSTRUCTIONS_C_FORM(name, instr_name, instr_value) \
526 inline void name(const Simd128Register rt, const Simd128Register rb) { \
527 vx_form(instr_name, rt, rb); \
528 }
529#define DECLARE_PPC_VX_INSTRUCTIONS_E_FORM(name, instr_name, instr_value) \
530 inline void name(const Simd128Register rt, const Operand& imm) { \
531 vx_form(instr_name, rt, imm); \
532 }
533#define DECLARE_PPC_VX_INSTRUCTIONS_F_FORM(name, instr_name, instr_value) \
534 inline void name(const Register rt, const Simd128Register rb) { \
535 vx_form(instr_name, rt, rb); \
536 }
537#define DECLARE_PPC_VX_INSTRUCTIONS_G_FORM(name, instr_name, instr_value) \
538 inline void name(const Simd128Register rt, const Register rb, \
539 const Operand& imm) { \
540 vx_form(instr_name, rt, rb, imm); \
541 }
542
544 const Operand& imm) {
545 emit(instr | (rt.code() & 0x1F) * B21 | (imm.immediate() & 0x1F) * B16 |
546 (rb.code() & 0x1F) * B11);
547 }
550 emit(instr | (rt.code() & 0x1F) * B21 | ra.code() * B16 |
551 (rb.code() & 0x1F) * B11);
552 }
554 emit(instr | (rt.code() & 0x1F) * B21 | (rb.code() & 0x1F) * B11);
555 }
556 inline void vx_form(Instr instr, Simd128Register rt, const Operand& imm) {
557 emit(instr | (rt.code() & 0x1F) * B21 | (imm.immediate() & 0x1F) * B16);
558 }
560 emit(instr | (rt.code() & 0x1F) * B21 | (rb.code() & 0x1F) * B11);
561 }
563 const Operand& imm) {
564 emit(instr | (rt.code() & 0x1F) * B21 | (imm.immediate() & 0x1F) * B16 |
565 (rb.code() & 0x1F) * B11);
566 }
567
572 DECLARE_PPC_VX_INSTRUCTIONS_C_FORM) /* OPCODE_D_FORM can use
573 INSTRUCTIONS_C_FORM */
577#undef DECLARE_PPC_VX_INSTRUCTIONS_A_FORM
578#undef DECLARE_PPC_VX_INSTRUCTIONS_B_FORM
579#undef DECLARE_PPC_VX_INSTRUCTIONS_C_FORM
580#undef DECLARE_PPC_VX_INSTRUCTIONS_E_FORM
581#undef DECLARE_PPC_VX_INSTRUCTIONS_F_FORM
582#undef DECLARE_PPC_VX_INSTRUCTIONS_G_FORM
583
584#define DECLARE_PPC_VA_INSTRUCTIONS_A_FORM(name, instr_name, instr_value) \
585 inline void name(const Simd128Register rt, const Simd128Register ra, \
586 const Simd128Register rb, const Simd128Register rc) { \
587 va_form(instr_name, rt, ra, rb, rc); \
588 }
589
592 emit(instr | (rt.code() & 0x1F) * B21 | (ra.code() & 0x1F) * B16 |
593 (rb.code() & 0x1F) * B11 | (rc.code() & 0x1F) * B6);
594 }
595
597#undef DECLARE_PPC_VA_INSTRUCTIONS_A_FORM
598
599#define DECLARE_PPC_VC_INSTRUCTIONS(name, instr_name, instr_value) \
600 inline void name(const Simd128Register rt, const Simd128Register ra, \
601 const Simd128Register rb, const RCBit rc = LeaveRC) { \
602 vc_form(instr_name, rt, ra, rb, rc); \
603 }
604
606 Simd128Register rb, int rc) {
607 emit(instr | (rt.code() & 0x1F) * B21 | (ra.code() & 0x1F) * B16 |
608 (rb.code() & 0x1F) * B11 | rc * B10);
609 }
610
612#undef DECLARE_PPC_VC_INSTRUCTIONS
613
614#define DECLARE_PPC_PREFIX_INSTRUCTIONS_TYPE_00(name, instr_name, instr_value) \
615 inline void name(const Operand& imm, const PRBit pr = LeavePR) { \
616 prefix_form(instr_name, imm, pr); \
617 }
618#define DECLARE_PPC_PREFIX_INSTRUCTIONS_TYPE_10(name, instr_name, instr_value) \
619 inline void name(const Operand& imm, const PRBit pr = LeavePR) { \
620 prefix_form(instr_name, imm, pr); \
621 }
622 inline void prefix_form(Instr instr, const Operand& imm, int pr) {
623 emit_prefix(instr | pr * B20 | (imm.immediate() & kImm18Mask));
624 }
627#undef DECLARE_PPC_PREFIX_INSTRUCTIONS_TYPE_00
628#undef DECLARE_PPC_PREFIX_INSTRUCTIONS_TYPE_10
629
631 // ---------------------------------------------------------------------------
632 // InstructionStream generation
633
634 // Insert the smallest number of nop instructions
635 // possible to align the pc offset to a multiple
636 // of m. m must be a power of 2 (>= 4).
637 void Align(int m);
638 // Insert the smallest number of zero bytes possible to align the pc offset
639 // to a mulitple of m. m must be a power of 2 (>= 2).
640 void DataAlign(int m);
641 // Aligns code to something that's optimal for a jump target for the platform.
644
645 // Branch instructions
646 void bclr(BOfield bo, int condition_bit, LKBit lk);
647 void blr();
648 void bc(int branch_offset, BOfield bo, int condition_bit, LKBit lk = LeaveLK);
649 void b(int branch_offset, LKBit lk);
650
651 void bcctr(BOfield bo, int condition_bit, LKBit lk);
652 void bctr();
653 void bctrl();
654
655 // Convenience branch instructions using labels
656 void b(Label* L, LKBit lk = LeaveLK) { b(branch_offset(L), lk); }
657
659 // Check whether the branch is preceded by an optimizable cmpi against 0.
660 // The cmpi can be deleted if it is also preceded by an instruction that
661 // sets the register used by the compare and supports a dot form.
662 unsigned int sradi_mask = kOpcodeMask | kExt2OpcodeVariant2Mask;
663 unsigned int srawi_mask = kOpcodeMask | kExt2OpcodeMask;
664 int pos = pc_offset();
665 int cmpi_pos = pc_offset() - kInstrSize;
666
667 if (cmpi_pos > 0 && optimizable_cmpi_pos_ == cmpi_pos &&
668 cmpi_cr_.code() == cr.code() && last_bound_pos_ != pos) {
669 int xpos = cmpi_pos - kInstrSize;
670 int xinstr = instr_at(xpos);
671 int cmpi_ra = (instr_at(cmpi_pos) & 0x1f0000) >> 16;
672 // ra is at the same bit position for the three cases below.
673 int ra = (xinstr & 0x1f0000) >> 16;
674 if (cmpi_ra == ra) {
675 if ((xinstr & sradi_mask) == (EXT2 | SRADIX)) {
676 cr = cr0;
677 instr_at_put(xpos, xinstr | SetRC);
678 pc_ -= kInstrSize;
679 } else if ((xinstr & srawi_mask) == (EXT2 | SRAWIX)) {
680 cr = cr0;
681 instr_at_put(xpos, xinstr | SetRC);
682 pc_ -= kInstrSize;
683 } else if ((xinstr & kOpcodeMask) == ANDIx) {
684 cr = cr0;
685 pc_ -= kInstrSize;
686 // nothing to do here since andi. records.
687 }
688 // didn't match one of the above, must keep cmpwi.
689 }
690 }
691 return cr;
692 }
693
694 void bc_short(Condition cond, Label* L, CRegister cr = cr0,
695 LKBit lk = LeaveLK) {
696 DCHECK(cond != al);
697 DCHECK(cr.code() >= 0 && cr.code() <= 7);
698
699 cr = cmpi_optimization(cr);
700
701 int b_offset = branch_offset(L);
702
703 switch (cond) {
704 case eq:
705 bc(b_offset, BT, encode_crbit(cr, CR_EQ), lk);
706 break;
707 case ne:
708 bc(b_offset, BF, encode_crbit(cr, CR_EQ), lk);
709 break;
710 case gt:
711 bc(b_offset, BT, encode_crbit(cr, CR_GT), lk);
712 break;
713 case le:
714 bc(b_offset, BF, encode_crbit(cr, CR_GT), lk);
715 break;
716 case lt:
717 bc(b_offset, BT, encode_crbit(cr, CR_LT), lk);
718 break;
719 case ge:
720 bc(b_offset, BF, encode_crbit(cr, CR_LT), lk);
721 break;
722 case unordered:
723 bc(b_offset, BT, encode_crbit(cr, CR_FU), lk);
724 break;
725 case ordered:
726 bc(b_offset, BF, encode_crbit(cr, CR_FU), lk);
727 break;
728 case overflow:
729 bc(b_offset, BT, encode_crbit(cr, CR_SO), lk);
730 break;
731 case nooverflow:
732 bc(b_offset, BF, encode_crbit(cr, CR_SO), lk);
733 break;
734 default:
736 }
737 }
738
739 void bclr(Condition cond, CRegister cr = cr0, LKBit lk = LeaveLK) {
740 DCHECK(cond != al);
741 DCHECK(cr.code() >= 0 && cr.code() <= 7);
742
743 cr = cmpi_optimization(cr);
744
745 switch (cond) {
746 case eq:
747 bclr(BT, encode_crbit(cr, CR_EQ), lk);
748 break;
749 case ne:
750 bclr(BF, encode_crbit(cr, CR_EQ), lk);
751 break;
752 case gt:
753 bclr(BT, encode_crbit(cr, CR_GT), lk);
754 break;
755 case le:
756 bclr(BF, encode_crbit(cr, CR_GT), lk);
757 break;
758 case lt:
759 bclr(BT, encode_crbit(cr, CR_LT), lk);
760 break;
761 case ge:
762 bclr(BF, encode_crbit(cr, CR_LT), lk);
763 break;
764 case unordered:
765 bclr(BT, encode_crbit(cr, CR_FU), lk);
766 break;
767 case ordered:
768 bclr(BF, encode_crbit(cr, CR_FU), lk);
769 break;
770 case overflow:
771 bclr(BT, encode_crbit(cr, CR_SO), lk);
772 break;
773 case nooverflow:
774 bclr(BF, encode_crbit(cr, CR_SO), lk);
775 break;
776 default:
778 }
779 }
780
783 CRegister cr = cr0) {
784 DCHECK(cond != al);
785 DCHECK(cr.code() >= 0 && cr.code() <= 7);
786
787 cr = cmpi_optimization(cr);
788
789 switch (cond) {
790 case eq:
791 isel(rt, ra, rb, encode_crbit(cr, CR_EQ));
792 break;
793 case ne:
794 isel(rt, rb, ra, encode_crbit(cr, CR_EQ));
795 break;
796 case gt:
797 isel(rt, ra, rb, encode_crbit(cr, CR_GT));
798 break;
799 case le:
800 isel(rt, rb, ra, encode_crbit(cr, CR_GT));
801 break;
802 case lt:
803 isel(rt, ra, rb, encode_crbit(cr, CR_LT));
804 break;
805 case ge:
806 isel(rt, rb, ra, encode_crbit(cr, CR_LT));
807 break;
808 case unordered:
809 isel(rt, ra, rb, encode_crbit(cr, CR_FU));
810 break;
811 case ordered:
812 isel(rt, rb, ra, encode_crbit(cr, CR_FU));
813 break;
814 case overflow:
815 isel(rt, ra, rb, encode_crbit(cr, CR_SO));
816 break;
817 case nooverflow:
818 isel(rt, rb, ra, encode_crbit(cr, CR_SO));
819 break;
820 default:
822 }
823 }
824
825 void b(Condition cond, Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
826 if (cond == al) {
827 b(L, lk);
828 return;
829 }
830
831 if ((L->is_bound() && is_near(L, cond))) {
832 bc_short(cond, L, cr, lk);
833 return;
834 }
835
836 Label skip;
837 Condition neg_cond = NegateCondition(cond);
838 bc_short(neg_cond, &skip, cr);
839 b(L, lk);
840 bind(&skip);
841 }
842
843 void bne(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
844 b(ne, L, cr, lk);
845 }
846 void beq(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
847 b(eq, L, cr, lk);
848 }
849 void blt(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
850 b(lt, L, cr, lk);
851 }
852 void bge(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
853 b(ge, L, cr, lk);
854 }
855 void ble(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
856 b(le, L, cr, lk);
857 }
858 void bgt(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
859 b(gt, L, cr, lk);
860 }
861 void bunordered(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
862 b(unordered, L, cr, lk);
863 }
864 void bordered(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
865 b(ordered, L, cr, lk);
866 }
867 void boverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
868 b(overflow, L, cr, lk);
869 }
870 void bnooverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
871 b(nooverflow, L, cr, lk);
872 }
873
874 // Decrement CTR; branch if CTR != 0
875 void bdnz(Label* L, LKBit lk = LeaveLK) {
876 bc(branch_offset(L), DCBNZ, 0, lk);
877 }
878
879 // Data-processing instructions
880
881 void sub(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
882 RCBit r = LeaveRC);
883
884 void subc(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
885 RCBit r = LeaveRC);
886 void sube(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
887 RCBit r = LeaveRC);
888
889 void subfic(Register dst, Register src, const Operand& imm);
890
891 void add(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
892 RCBit r = LeaveRC);
893
894 void addc(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
895 RCBit r = LeaveRC);
896 void adde(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
897 RCBit r = LeaveRC);
899
900 void mullw(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
901 RCBit r = LeaveRC);
902
903 void mulhw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
904 void mulhwu(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
905 void mulhd(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
906 void mulhdu(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
907 void mulli(Register dst, Register src, const Operand& imm);
908
909 void divw(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
910 RCBit r = LeaveRC);
911 void divwu(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
912 RCBit r = LeaveRC);
913
914 void addi(Register dst, Register src, const Operand& imm);
915 void addis(Register dst, Register src, const Operand& imm);
916 void addic(Register dst, Register src, const Operand& imm);
917
918 void andi(Register ra, Register rs, const Operand& imm);
919 void andis(Register ra, Register rs, const Operand& imm);
920 void ori(Register dst, Register src, const Operand& imm);
921 void oris(Register dst, Register src, const Operand& imm);
922 void xori(Register dst, Register src, const Operand& imm);
923 void xoris(Register ra, Register rs, const Operand& imm);
924 void cmpi(Register src1, const Operand& src2, CRegister cr = cr0);
925 void cmpli(Register src1, const Operand& src2, CRegister cr = cr0);
926 void cmpwi(Register src1, const Operand& src2, CRegister cr = cr0);
927 void cmplwi(Register src1, const Operand& src2, CRegister cr = cr0);
928 void li(Register dst, const Operand& src);
929 void lis(Register dst, const Operand& imm);
930 void mr(Register dst, Register src);
931
932 void lbz(Register dst, const MemOperand& src);
933 void lhz(Register dst, const MemOperand& src);
934 void lha(Register dst, const MemOperand& src);
935 void lwz(Register dst, const MemOperand& src);
936 void lwzu(Register dst, const MemOperand& src);
937 void lwa(Register dst, const MemOperand& src);
938 void stb(Register dst, const MemOperand& src);
939 void sth(Register dst, const MemOperand& src);
940 void stw(Register dst, const MemOperand& src);
941 void stwu(Register dst, const MemOperand& src);
943
944 void ld(Register rd, const MemOperand& src);
945 void ldu(Register rd, const MemOperand& src);
946 void std(Register rs, const MemOperand& src);
947 void stdu(Register rs, const MemOperand& src);
948 void rldic(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
949 void rldicl(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
951 void rldicr(Register dst, Register src, int sh, int me, RCBit r = LeaveRC);
952 void rldimi(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
953 void sldi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
954 void srdi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
955 void clrrdi(Register dst, Register src, const Operand& val,
956 RCBit rc = LeaveRC);
957 void clrldi(Register dst, Register src, const Operand& val,
958 RCBit rc = LeaveRC);
963 void mulld(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
964 RCBit r = LeaveRC);
965 void divd(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
966 RCBit r = LeaveRC);
967 void divdu(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
968 RCBit r = LeaveRC);
969
970 void rlwinm(Register ra, Register rs, int sh, int mb, int me,
971 RCBit rc = LeaveRC);
972 void rlwimi(Register ra, Register rs, int sh, int mb, int me,
973 RCBit rc = LeaveRC);
974 void rlwnm(Register ra, Register rs, Register rb, int mb, int me,
975 RCBit rc = LeaveRC);
976 void slwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
977 void srwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
978 void clrrwi(Register dst, Register src, const Operand& val,
979 RCBit rc = LeaveRC);
980 void clrlwi(Register dst, Register src, const Operand& val,
981 RCBit rc = LeaveRC);
985
986 void subi(Register dst, Register src1, const Operand& src2);
987
988 void mov(Register dst, const Operand& src);
989 void bitwise_mov(Register dst, intptr_t value);
990 void bitwise_mov32(Register dst, int32_t value);
991 void bitwise_add32(Register dst, Register src, int32_t value);
992
993 // Patch the offset to the return address after Call.
994 void patch_pc_address(Register dst, int pc_offset, int return_address_offset);
995
996 // Load the position of the label relative to the generated code object
997 // pointer in a register.
999
1000 // dst = base + label position + delta
1002 int delta = 0);
1003
1004 // Load the address of the label in a register and associate with an
1005 // internal reference relocation.
1007
1008 // Emit the address of the label (i.e. a jump table entry) and associate with
1009 // an internal reference relocation.
1011
1012 // Multiply instructions
1013 void mul(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
1014 RCBit r = LeaveRC);
1015
1016 // Miscellaneous arithmetic instructions
1017
1018 // Special register access
1019 void crxor(int bt, int ba, int bb);
1020 void crclr(int bt) { crxor(bt, bt, bt); }
1021 void creqv(int bt, int ba, int bb);
1022 void crset(int bt) { creqv(bt, bt, bt); }
1023 void mflr(Register dst);
1024 void mtlr(Register src);
1025 void mtctr(Register src);
1026 void mtxer(Register src);
1028 void mfcr(Register dst);
1029 void mtcrf(Register src, uint8_t FXM);
1035
1036 // Exception-generating instructions and debugging support
1037 void stop(Condition cond = al, int32_t code = kDefaultStopCode,
1038 CRegister cr = cr0);
1039
1040 void bkpt(uint32_t imm16); // v5 and above
1041
1043 void sync();
1044 void lwsync();
1046 void isync();
1047
1048 // Support for floating point
1049 void lfd(const DoubleRegister frt, const MemOperand& src);
1050 void lfdu(const DoubleRegister frt, const MemOperand& src);
1051 void lfs(const DoubleRegister frt, const MemOperand& src);
1052 void lfsu(const DoubleRegister frt, const MemOperand& src);
1053 void stfd(const DoubleRegister frs, const MemOperand& src);
1054 void stfdu(const DoubleRegister frs, const MemOperand& src);
1055 void stfs(const DoubleRegister frs, const MemOperand& src);
1056 void stfsu(const DoubleRegister frs, const MemOperand& src);
1057
1058 void fadd(const DoubleRegister frt, const DoubleRegister fra,
1059 const DoubleRegister frb, RCBit rc = LeaveRC);
1060 void fsub(const DoubleRegister frt, const DoubleRegister fra,
1061 const DoubleRegister frb, RCBit rc = LeaveRC);
1062 void fdiv(const DoubleRegister frt, const DoubleRegister fra,
1063 const DoubleRegister frb, RCBit rc = LeaveRC);
1064 void fmul(const DoubleRegister frt, const DoubleRegister fra,
1065 const DoubleRegister frc, RCBit rc = LeaveRC);
1066 void fcmpu(const DoubleRegister fra, const DoubleRegister frb,
1067 CRegister cr = cr0);
1068 void fmr(const DoubleRegister frt, const DoubleRegister frb,
1069 RCBit rc = LeaveRC);
1070 void fctiwz(const DoubleRegister frt, const DoubleRegister frb);
1071 void fctiw(const DoubleRegister frt, const DoubleRegister frb);
1072 void fctiwuz(const DoubleRegister frt, const DoubleRegister frb);
1073 void frin(const DoubleRegister frt, const DoubleRegister frb,
1074 RCBit rc = LeaveRC);
1075 void friz(const DoubleRegister frt, const DoubleRegister frb,
1076 RCBit rc = LeaveRC);
1077 void frip(const DoubleRegister frt, const DoubleRegister frb,
1078 RCBit rc = LeaveRC);
1079 void frim(const DoubleRegister frt, const DoubleRegister frb,
1080 RCBit rc = LeaveRC);
1081 void frsp(const DoubleRegister frt, const DoubleRegister frb,
1082 RCBit rc = LeaveRC);
1083 void fcfid(const DoubleRegister frt, const DoubleRegister frb,
1084 RCBit rc = LeaveRC);
1085 void fcfidu(const DoubleRegister frt, const DoubleRegister frb,
1086 RCBit rc = LeaveRC);
1087 void fcfidus(const DoubleRegister frt, const DoubleRegister frb,
1088 RCBit rc = LeaveRC);
1089 void fcfids(const DoubleRegister frt, const DoubleRegister frb,
1090 RCBit rc = LeaveRC);
1091 void fctid(const DoubleRegister frt, const DoubleRegister frb,
1092 RCBit rc = LeaveRC);
1093 void fctidz(const DoubleRegister frt, const DoubleRegister frb,
1094 RCBit rc = LeaveRC);
1095 void fctidu(const DoubleRegister frt, const DoubleRegister frb,
1096 RCBit rc = LeaveRC);
1097 void fctiduz(const DoubleRegister frt, const DoubleRegister frb,
1098 RCBit rc = LeaveRC);
1099 void fsel(const DoubleRegister frt, const DoubleRegister fra,
1100 const DoubleRegister frc, const DoubleRegister frb,
1101 RCBit rc = LeaveRC);
1102 void fneg(const DoubleRegister frt, const DoubleRegister frb,
1103 RCBit rc = LeaveRC);
1106 void mtfsfi(int bf, int immediate, RCBit rc = LeaveRC);
1107 void mffs(const DoubleRegister frt, RCBit rc = LeaveRC);
1108 void mtfsf(const DoubleRegister frb, bool L = 1, int FLM = 0, bool W = 0,
1109 RCBit rc = LeaveRC);
1110 void fsqrt(const DoubleRegister frt, const DoubleRegister frb,
1111 RCBit rc = LeaveRC);
1112 void fabs(const DoubleRegister frt, const DoubleRegister frb,
1113 RCBit rc = LeaveRC);
1114 void fmadd(const DoubleRegister frt, const DoubleRegister fra,
1115 const DoubleRegister frc, const DoubleRegister frb,
1116 RCBit rc = LeaveRC);
1117 void fmsub(const DoubleRegister frt, const DoubleRegister fra,
1118 const DoubleRegister frc, const DoubleRegister frb,
1119 RCBit rc = LeaveRC);
1120 void fcpsgn(const DoubleRegister frt, const DoubleRegister fra,
1121 const DoubleRegister frc, RCBit rc = LeaveRC);
1122
1123 // Vector instructions
1124 void mfvsrd(const Register ra, const Simd128Register r);
1127 void mtvsrdd(const Simd128Register rt, const Register ra, const Register rb);
1128 void lxvd(const Simd128Register rt, const MemOperand& src);
1129 void lxvx(const Simd128Register rt, const MemOperand& src);
1130 void lxsdx(const Simd128Register rt, const MemOperand& src);
1131 void lxsibzx(const Simd128Register rt, const MemOperand& src);
1132 void lxsihzx(const Simd128Register rt, const MemOperand& src);
1133 void lxsiwzx(const Simd128Register rt, const MemOperand& src);
1134 void stxsdx(const Simd128Register rs, const MemOperand& dst);
1135 void stxsibx(const Simd128Register rs, const MemOperand& dst);
1136 void stxsihx(const Simd128Register rs, const MemOperand& dst);
1137 void stxsiwx(const Simd128Register rs, const MemOperand& dst);
1138 void stxvd(const Simd128Register rt, const MemOperand& dst);
1139 void stxvx(const Simd128Register rt, const MemOperand& dst);
1140 void xxspltib(const Simd128Register rt, const Operand& imm);
1141
1142 // Prefixed instructioons.
1143 void paddi(Register dst, Register src, const Operand& imm);
1144 void pli(Register dst, const Operand& imm);
1145 void psubi(Register dst, Register src, const Operand& imm);
1146 void plbz(Register dst, const MemOperand& src);
1147 void plhz(Register dst, const MemOperand& src);
1148 void plha(Register dst, const MemOperand& src);
1149 void plwz(Register dst, const MemOperand& src);
1150 void plwa(Register dst, const MemOperand& src);
1151 void pld(Register dst, const MemOperand& src);
1152 void plfs(DoubleRegister dst, const MemOperand& src);
1153 void plfd(DoubleRegister dst, const MemOperand& src);
1154 void pstb(Register src, const MemOperand& dst);
1155 void psth(Register src, const MemOperand& dst);
1156 void pstw(Register src, const MemOperand& dst);
1157 void pstd(Register src, const MemOperand& dst);
1158 void pstfs(const DoubleRegister src, const MemOperand& dst);
1159 void pstfd(const DoubleRegister src, const MemOperand& dst);
1160
1161 // Pseudo instructions
1162
1163 // Different nop operations are used by the code generator to detect certain
1164 // states of the generated code.
1177
1178 void nop(int type = 0); // 0 is the default non-marking type.
1179
1180 void push(Register src) {
1182 }
1183
1184 void pop(Register dst) {
1185 ld(dst, MemOperand(sp));
1187 }
1188
1189 void pop() { addi(sp, sp, Operand(kSystemPointerSize)); }
1190
1191 // Jump unconditionally to given label.
1192 void jmp(Label* L) { b(L); }
1193
1194 // Check the code size generated from label to here.
1196 return pc_offset() - label->pos();
1197 }
1198
1199 // Check the number of instructions generated from label to here.
1203
1204 // Class for scoping postponing the trampoline pool generation.
1206 public:
1207 explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) {
1208 assem_->StartBlockTrampolinePool();
1209 }
1210 ~BlockTrampolinePoolScope() { assem_->EndBlockTrampolinePool(); }
1211
1212 private:
1213 Assembler* assem_;
1214
1216 };
1217
1218 // Class for scoping disabling constant pool entry merging
1220 public:
1222 : assem_(assem) {
1223 assem_->StartBlockConstantPoolEntrySharing();
1224 }
1226 assem_->EndBlockConstantPoolEntrySharing();
1227 }
1228
1229 private:
1231
1233 };
1234
1235 // Record a deoptimization reason that can be used by a log or cpu profiler.
1236 // Use --trace-deopt to enable.
1237 void RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id,
1238 SourcePosition position, int id);
1239
1240 // Writes a single byte or word of data in the code stream. Used
1241 // for inline tables, e.g., jump-tables.
1242 void db(uint8_t data);
1243 void dd(uint32_t data);
1244 void dq(uint64_t data);
1245 void dp(uintptr_t data);
1246
1247 // Read/patch instructions
1249 return *reinterpret_cast<Instr*>(buffer_start_ + pos);
1250 }
1252 *reinterpret_cast<Instr*>(buffer_start_ + pos) = instr;
1253 }
1254 static Instr instr_at(Address pc) { return *reinterpret_cast<Instr*>(pc); }
1256 *reinterpret_cast<Instr*>(pc) = instr;
1257 }
1259
1260 static bool IsLis(Instr instr);
1261 static bool IsLi(Instr instr);
1262 static bool IsAddic(Instr instr);
1263 static bool IsOri(Instr instr);
1264
1265 static bool IsBranch(Instr instr);
1268 static bool Is64BitLoadIntoR12(Instr instr1, Instr instr2, Instr instr3,
1269 Instr instr4, Instr instr5);
1270
1273 static bool IsRlwinm(Instr instr);
1274 static bool IsAndi(Instr instr);
1275 static bool IsRldicl(Instr instr);
1276 static bool IsCrSet(Instr instr);
1279 static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
1280
1281 // Postpone the generation of the trampoline pool for the specified number of
1282 // instructions.
1283 void BlockTrampolinePoolFor(int instructions);
1285
1286 // For mov. Return the number of actual instructions required to
1287 // load the operand into a register. This can be anywhere from
1288 // one (constant pool small section) to five instructions (full
1289 // 64-bit sequence).
1290 //
1291 // The value returned is only valid as long as no entries are added to the
1292 // constant pool between this call and the actual instruction being emitted.
1294
1295 // Decide between using the constant pool vs. a mov immediate sequence.
1297 bool canOptimize) const;
1298
1299 // The code currently calls CheckBuffer() too often. This has the side
1300 // effect of randomly growing the buffer in the middle of multi-instruction
1301 // sequences.
1302 //
1303 // This function allows outside callers to check and grow the buffer
1304 void EnsureSpaceFor(int space_needed);
1305
1306 int EmitConstantPool() { return constant_pool_builder_.Emit(this); }
1307
1312
1314 return constant_pool_builder_.EmittedPosition();
1315 }
1316
1318
1319 protected:
1320 int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1321
1322 // Decode instruction(s) at pos and return backchain to previous
1323 // label reference or kEndOfChain.
1324 int target_at(int pos);
1325
1326 // Patch instruction(s) at pos to target target_pos (e.g. branch)
1327 void target_at_put(int pos, int target_pos, bool* is_branch = nullptr);
1328
1329 // Record reloc info for current pc_
1330 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1332 intptr_t value) {
1333 bool sharing_ok =
1334 RelocInfo::IsNoInfo(rmode) ||
1335 (!options().record_reloc_info_for_serialization &&
1338 // TODO(johnyan): make the following rmode shareable
1340 return constant_pool_builder_.AddEntry(pc_offset(), value, sharing_ok);
1341 }
1345
1346 // Block the emission of the trampoline pool before pc_offset.
1351
1359 }
1360
1370
1372
1374
1375 // InstructionStream generation
1376 // The relocation writer's position is at least kGap bytes below the end of
1377 // the generated instructions. This is so that multi-instruction sequences do
1378 // not have to check for overflow. The same is true for writes of large
1379 // relocation info entries.
1380 static constexpr int kGap = 32;
1381 static_assert(AssemblerBase::kMinimalBufferSize >= 2 * kGap);
1382
1384
1385 private:
1386 // Avoid overflows for displacements etc.
1387 static const int kMaximalBufferSize = 512 * MB;
1388
1389 // Repeated checking whether the trampoline pool should be emitted is rather
1390 // expensive. By default we only check again once a number of instructions
1391 // has been generated.
1392 int next_trampoline_check_; // pc offset of next buffer check.
1393
1394 // Emission of the trampoline pool may be blocked in some code sequences.
1395 int trampoline_pool_blocked_nesting_; // Block emission if this is not zero.
1396 int no_trampoline_pool_before_; // Block emission before this pc offset.
1397
1398 // Do not share constant pool entries.
1400
1401 // Relocation info generation
1402 // Each relocation is encoded as a variable size value
1403 static constexpr int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1404 std::vector<DeferredRelocInfo> relocations_;
1405
1406 // Scratch registers available for use by the Assembler.
1408
1409 // The bound position, before this we cannot do instruction elimination.
1410 int last_bound_pos_;
1411 // Optimizable cmpi information.
1414
1415 ConstantPoolBuilder constant_pool_builder_;
1416
1418 if (buffer_space() <= kGap) {
1419 GrowBuffer();
1420 }
1421 }
1422
1423 void GrowBuffer(int needed = 0);
1424 // Code emission
1425 void emit(Instr x) {
1426 CheckBuffer();
1427 *reinterpret_cast<Instr*>(pc_) = x;
1428 pc_ += kInstrSize;
1430 }
1431
1433 // Prefixed instructions cannot cross 64-byte boundaries. Add a nop if the
1434 // boundary will be crossed mid way.
1435 // Code is set to be 64-byte aligned on PPC64 after relocation (look for
1436 // kCodeAlignment). We use pc_offset() instead of pc_ as current pc_
1437 // alignment could be different after relocation.
1438 if (((pc_offset() + sizeof(Instr)) & 63) == 0) {
1439 nop();
1440 }
1441 // Do not emit trampoline pool in between prefix and suffix.
1443 emit(x);
1444 }
1445
1449 if (count == 0) {
1450 // We leave space (kMaxBlockTrampolineSectionSize)
1451 // for BlockTrampolinePoolScope buffer.
1454 } else {
1456 }
1457 }
1458
1459 inline void UntrackBranch();
1460 // Instruction generation
1462 DoubleRegister frb, RCBit r);
1463 void d_form(Instr instr, Register rt, Register ra, const intptr_t val,
1464 bool signed_disp);
1466 RCBit r);
1467 void md_form(Instr instr, Register ra, Register rs, int shift, int maskbit,
1468 RCBit r);
1470 RCBit r);
1471
1472 // Labels
1473 void print(Label* L);
1475 void bind_to(Label* L, int pos);
1476 void next(Label* L);
1477
1478 class Trampoline {
1479 public:
1481 next_slot_ = 0;
1482 free_slot_count_ = 0;
1483 }
1484 Trampoline(int start, int slot_count) {
1485 next_slot_ = start;
1486 free_slot_count_ = slot_count;
1487 }
1489 int trampoline_slot = kInvalidSlotPos;
1490 if (free_slot_count_ <= 0) {
1491 // We have run out of space on trampolines.
1492 // Make sure we fail in debug mode, so we become aware of each case
1493 // when this happens.
1494 DCHECK(0);
1495 // Internal exception will be caught.
1496 } else {
1497 trampoline_slot = next_slot_;
1500 }
1501 return trampoline_slot;
1502 }
1503
1504 private:
1505 int next_slot_;
1506 int free_slot_count_;
1507 };
1508
1511 // If trampoline is emitted, generated code is becoming large. As
1512 // this is already a slow case which can possibly break our code
1513 // generation for the extreme case, we use this information to
1514 // trigger different mode of branch instruction generation, where we
1515 // no longer use a single branch instruction.
1517 static constexpr int kTrampolineSlotsSize = kInstrSize;
1518 static constexpr int kMaxCondBranchReach = (1 << (16 - 1)) - 1;
1519 static constexpr int kMaxBlockTrampolineSectionSize = 64 * kInstrSize;
1520 static constexpr int kInvalidSlotPos = -1;
1521
1524
1526
1528
1530 friend class RelocInfo;
1531 friend class BlockTrampolinePoolScope;
1532 friend class EnsureSpace;
1533 friend class UseScratchRegisterScope;
1534};
1535
1536class EnsureSpace {
1537 public:
1538 explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); }
1539};
1540
1542 public:
1543 PatchingAssembler(const AssemblerOptions& options, uint8_t* address,
1544 int instructions);
1546};
1547
1549 public:
1551 : assembler_(assembler),
1552 old_available_(*assembler->GetScratchRegisterList()) {}
1553
1555 *assembler_->GetScratchRegisterList() = old_available_;
1556 }
1557
1559 return assembler_->GetScratchRegisterList()->PopFirst();
1560 }
1561
1562 // Check if we have registers available to acquire.
1563 bool CanAcquire() const {
1564 return !assembler_->GetScratchRegisterList()->is_empty();
1565 }
1566
1567 private:
1568 friend class Assembler;
1569 friend class MacroAssembler;
1570
1572 RegList old_available_;
1573};
1574
1575} // namespace internal
1576} // namespace v8
1577
1578#endif // V8_CODEGEN_PPC_ASSEMBLER_PPC_H_
#define DECLARE_PPC_XX2_VECTOR_INSTRUCTIONS(name, instr_name, instr_value)
#define DECLARE_PPC_VX_INSTRUCTIONS_E_FORM(name, instr_name, instr_value)
#define DECLARE_PPC_VX_INSTRUCTIONS_B_FORM(name, instr_name, instr_value)
#define DECLARE_PPC_XX3_VECTOR_INSTRUCTIONS_A_FORM(name, instr_name, instr_value)
#define DECLARE_PPC_X_INSTRUCTIONS_EH_L_FORM(name, instr_name, instr_value)
#define DECLARE_PPC_X_INSTRUCTIONS_C_FORM(name, instr_name, instr_value)
#define DECLARE_PPC_VX_INSTRUCTIONS_G_FORM(name, instr_name, instr_value)
#define DECLARE_PPC_X_INSTRUCTIONS_A_FORM(name, instr_name, instr_value)
#define DECLARE_PPC_VC_INSTRUCTIONS(name, instr_name, instr_value)
#define DECLARE_PPC_X_INSTRUCTIONS_F_FORM(name, instr_name, instr_value)
#define DECLARE_PPC_XX3_VECTOR_INSTRUCTIONS_B_FORM(name, instr_name, instr_value)
#define DECLARE_PPC_XX2_SCALAR_INSTRUCTIONS(name, instr_name, instr_value)
#define DECLARE_PPC_VA_INSTRUCTIONS_A_FORM(name, instr_name, instr_value)
#define DECLARE_PPC_XX3_SCALAR_INSTRUCTIONS(name, instr_name, instr_value)
#define DECLARE_PPC_VX_INSTRUCTIONS_A_FORM(name, instr_name, instr_value)
#define DECLARE_PPC_X_INSTRUCTIONS_EH_S_FORM(name, instr_name, instr_value)
#define DECLARE_PPC_X_INSTRUCTIONS_B_FORM(name, instr_name, instr_value)
#define DECLARE_PPC_VX_INSTRUCTIONS_F_FORM(name, instr_name, instr_value)
#define DECLARE_PPC_X_INSTRUCTIONS_E_FORM(name, instr_name, instr_value)
#define DECLARE_PPC_PREFIX_INSTRUCTIONS_TYPE_10(name, instr_name, instr_value)
#define DECLARE_PPC_PREFIX_INSTRUCTIONS_TYPE_00(name, instr_name, instr_value)
#define DECLARE_PPC_VX_INSTRUCTIONS_C_FORM(name, instr_name, instr_value)
#define DECLARE_PPC_X_INSTRUCTIONS_G_FORM(name, instr_name, instr_value)
#define DECLARE_PPC_X_INSTRUCTIONS_D_FORM(name, instr_name, instr_value)
SourcePosition pos
static constexpr int kMinimalBufferSize
Definition assembler.h:485
const AssemblerOptions & options() const
Definition assembler.h:339
DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstantPoolEntrySharingScope)
DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope)
Trampoline(int start, int slot_count)
void bind_to(Label *L, int pos)
void pstd(Register src, const MemOperand &dst)
void rotldi(Register ra, Register rs, int sh, RCBit r=LeaveRC)
static bool IsRldicl(Instr instr)
static const int kMaximalBufferSize
void xx2_form(Instr instr, T t, T b)
void mulhd(Register dst, Register src1, Register src2, RCBit r=LeaveRC)
void b(int branch_offset, LKBit lk)
void ld(Register rd, const MemOperand &rs)
static constexpr int kTaggedLoadInstructions
void GetCode(LocalIsolate *isolate, CodeDesc *desc)
RelocInfoWriter reloc_info_writer
void andis(Register ra, Register rs, const Operand &imm)
void stb(Register dst, const MemOperand &src)
void mtvsrdd(const Simd128Register rt, const Register ra, const Register rb)
void andi(Register ra, Register rs, const Operand &imm)
void divwu(Register dst, Register src1, Register src2, OEBit o=LeaveOE, RCBit r=LeaveRC)
void rotlw(Register ra, Register rs, Register rb, RCBit r=LeaveRC)
void CheckTrampolinePoolQuick(int extra_space=0)
bool is_near(Label *L, OffsetSize bits)
static constexpr int kSpecialTargetSize
void addi(Register dst, Register src, const Operand &imm)
void patch_pc_address(Register dst, int pc_offset, int return_address_offset)
void rldicr(Register dst, Register src, int sh, int me, RCBit r=LeaveRC)
void divw(Register dst, Register src1, Register src2, OEBit o=LeaveOE, RCBit r=LeaveRC)
void addze(Register dst, Register src1, OEBit o=LeaveOE, RCBit r=LeaveRC)
void lxsiwzx(const Simd128Register rt, const MemOperand &src)
void mtfsb0(FPSCRBit bit, RCBit rc=LeaveRC)
void lfsu(const DoubleRegister frt, const MemOperand &src)
void notx(Register dst, Register src, RCBit rc=LeaveRC)
int instructions_required_for_mov(Register dst, const Operand &src) const
static V8_INLINE Address target_constant_pool_address_at(Address pc, Address constant_pool, ConstantPoolEntry::Access access, ConstantPoolEntry::Type type)
void bit(const VRegister &vd, const VRegister &vn, const VRegister &vm)
void x_form(Instr instr, CRegister cr, Register s1, Register s2, RCBit rc)
void stfsu(const DoubleRegister frs, const MemOperand &src)
void icbi(Register ra, Register rb)
bool is_trampoline_emitted() const
static bool IsCmpRegister(Instr instr)
bool is_near(Label *L, Condition cond)
void lis(Register dst, const Operand &imm)
void fctidu(const DoubleRegister frt, const DoubleRegister frb, RCBit rc=LeaveRC)
void mds_form(Instr instr, Register ra, Register rs, Register rb, int maskbit, RCBit r)
void stxsiwx(const Simd128Register rs, const MemOperand &dst)
static int GetCmpImmediateRawImmediate(Instr instr)
void lxvx(const Simd128Register rt, const MemOperand &src)
void mov_label_offset(Register dst, Label *label)
void fmul(const DoubleRegister frt, const DoubleRegister fra, const DoubleRegister frc, RCBit rc=LeaveRC)
static constexpr int kTrampolineSlotsSize
void fcpsgn(const DoubleRegister frt, const DoubleRegister fra, const DoubleRegister frc, RCBit rc=LeaveRC)
void xx3_form(Instr instr, T t, T a, T b)
void frip(const DoubleRegister frt, const DoubleRegister frb, RCBit rc=LeaveRC)
void xxspltib(const Simd128Register rt, const Operand &imm)
V8_INLINE void PatchConstantPoolAccessInstruction(int pc_offset, int offset, ConstantPoolEntry::Access access, ConstantPoolEntry::Type type)
void stdu(Register rs, const MemOperand &src)
void mr(Register dst, Register src)
void plfd(DoubleRegister dst, const MemOperand &src)
static bool IsAddic(Instr instr)
static constexpr int kNoHandlerTable
void extsw(Register rs, Register ra, RCBit rc=LeaveRC)
void lxsdx(const Simd128Register rt, const MemOperand &src)
void b(int branch_offset, Condition cond=al, RelocInfo::Mode rmode=RelocInfo::NO_INFO)
Assembler(const MaybeAssemblerZone &, const AssemblerOptions &options, std::unique_ptr< AssemblerBuffer > buffer={})
int branch_offset(Label *L)
void mulhw(Register dst, Register src1, Register src2, RCBit r=LeaveRC)
static int deserialization_special_target_size(Address instruction_payload)
void mflr(Register dst)
void fdiv(const DoubleRegister frt, const DoubleRegister fra, const DoubleRegister frb, RCBit rc=LeaveRC)
void AllocateAndInstallRequestedHeapNumbers(LocalIsolate *isolate)
static V8_INLINE int GetConstantPoolOffset(Address pc, ConstantPoolEntry::Access access, ConstantPoolEntry::Type type)
void rldicl(Register dst, Register src, int sh, int mb, RCBit r=LeaveRC)
void sradi(Register ra, Register rs, int sh, RCBit r=LeaveRC)
void emit_label_addr(Label *label)
std::vector< DeferredRelocInfo > relocations_
void stop(Condition cond=al, int32_t code=kDefaultStopCode, CRegister cr=cr0)
void fctid(const DoubleRegister frt, const DoubleRegister frb, RCBit rc=LeaveRC)
void mtctr(Register src)
void frin(const DoubleRegister frt, const DoubleRegister frb, RCBit rc=LeaveRC)
void fctiduz(const DoubleRegister frt, const DoubleRegister frb, RCBit rc=LeaveRC)
int32_t get_trampoline_entry()
static constexpr int kMaxCondBranchReach
void subc(Register dst, Register src1, Register src2, OEBit s=LeaveOE, RCBit r=LeaveRC)
static bool IsCmpImmediate(Instr instr)
static void deserialization_set_target_internal_reference_at(Address pc, Address target, WritableJitAllocation &jit_allocation, RelocInfo::Mode mode=RelocInfo::INTERNAL_REFERENCE)
void c(FPUCondition cond, SecondaryField fmt, FPURegister ft, FPURegister fs, uint16_t cc=0)
void bc(int branch_offset, BOfield bo, int condition_bit, LKBit lk=LeaveLK)
bool is_trampoline_pool_blocked() const
void ld(Register rd, const MemOperand &src)
void std(Register rs, const MemOperand &src)
void md_form(Instr instr, Register ra, Register rs, int shift, int maskbit, RCBit r)
void plha(Register dst, const MemOperand &src)
void fmsub(const DoubleRegister frt, const DoubleRegister fra, const DoubleRegister frc, const DoubleRegister frb, RCBit rc=LeaveRC)
bool use_constant_pool_for_mov(Register dst, const Operand &src, bool canOptimize) const
bool is_constant_pool_entry_sharing_blocked() const
void isel(Register rt, Register ra, Register rb, int cb)
void stxsdx(const Simd128Register rs, const MemOperand &dst)
void srdi(Register dst, Register src, const Operand &val, RCBit rc=LeaveRC)
static bool IsNop(Instr instr, int type=NON_MARKING_NOP)
int InstructionsGeneratedSince(Label *label)
void db(uint8_t data)
void vx_form(Instr instr, Simd128Register rt, Simd128Register ra, Simd128Register rb)
void clrlwi(Register dst, Register src, const Operand &val, RCBit rc=LeaveRC)
void stxvx(const Simd128Register rt, const MemOperand &dst)
void mtfprwz(DoubleRegister dst, Register src)
static bool IsOri(Instr instr)
void frsp(const DoubleRegister frt, const DoubleRegister frb, RCBit rc=LeaveRC)
void lhz(Register dst, const MemOperand &src)
void instr_at_put(int pos, Instr instr)
void ble(Label *L, CRegister cr=cr0, LKBit lk=LeaveLK)
void clrldi(Register dst, Register src, const Operand &val, RCBit rc=LeaveRC)
void rotld(Register ra, Register rs, Register rb, RCBit r=LeaveRC)
void sub(Register dst, Register src1, Register src2, OEBit s=LeaveOE, RCBit r=LeaveRC)
void rlwnm(Register ra, Register rs, Register rb, int mb, int me, RCBit rc=LeaveRC)
void b(Condition cond, Label *L, CRegister cr=cr0, LKBit lk=LeaveLK)
static constexpr SafepointTableBuilderBase * kNoSafepointTable
void bitwise_add32(Register dst, Register src, int32_t value)
static bool IsCrSet(Instr instr)
void blt(Label *L, CRegister cr=cr0, LKBit lk=LeaveLK)
Simd128Register Simd128Register ra
void xori(Register dst, Register src, const Operand &imm)
static bool IsAndi(Instr instr)
static void set_uint32_constant_at(Address pc, Address constant_pool, uint32_t new_constant, WritableJitAllocation *jit_allocation, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
void pli(Register dst, const Operand &imm)
void mulhdu(Register dst, Register src1, Register src2, RCBit r=LeaveRC)
void ori(Register dst, Register src, const Operand &imm)
void mfcr(Register dst)
void fsub(const DoubleRegister frt, const DoubleRegister fra, const DoubleRegister frb, RCBit rc=LeaveRC)
ConstantPoolEntry::Access ConstantPoolAddEntry(base::Double value)
void rldimi(Register dst, Register src, int sh, int mb, RCBit r=LeaveRC)
void d_form(Instr instr, Register rt, Register ra, const intptr_t val, bool signed_disp)
Simd128Register Simd128Register Simd128Register Simd128Register rc
void creqv(int bt, int ba, int bb)
void print(Label *L)
void crxor(int bt, int ba, int bb)
void pop(Register dst)
void mul(Register dst, Register src1, Register src2, OEBit s=LeaveOE, RCBit r=LeaveRC)
void addis(Register dst, Register src, const Operand &imm)
static constexpr int kMaxRelocSize
void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data=0)
void srwi(Register dst, Register src, const Operand &val, RCBit rc=LeaveRC)
void fneg(const DoubleRegister frt, const DoubleRegister frb, RCBit rc=LeaveRC)
void add(Register dst, Register src1, Register src2, OEBit s=LeaveOE, RCBit r=LeaveRC)
void lwax(Register rt, const MemOperand &src)
void addic(Register dst, Register src, const Operand &imm)
static uint32_t uint32_constant_at(Address pc, Address constant_pool)
static V8_INLINE bool IsConstantPoolLoadStart(Address pc, ConstantPoolEntry::Access *access=nullptr)
void lwa(Register dst, const MemOperand &src)
void x_form(Instr instr, Register ra, Register rs, Register rb, EHBit eh=SetEH)
static V8_INLINE void set_target_address_at(Address pc, Address constant_pool, Address target, WritableJitAllocation *jit_allocation, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
void x_form(Instr instr, Register rs, Register ra, Register rb, RCBit rc)
RegList * GetScratchRegisterList()
void bc(int32_t offset)
void mov(Register dst, const Operand &src)
void xo_form(Instr instr, Register rt, Register ra, Register rb, OEBit o, RCBit r)
void lxvd(const Simd128Register rt, const MemOperand &src)
void mulld(Register dst, Register src1, Register src2, OEBit o=LeaveOE, RCBit r=LeaveRC)
void nor(Register rd, Register rj, Register rk)
static Tagged_t target_compressed_address_at(Address pc, Address constant_pool)
void cmpwi(Register src1, const Operand &src2, CRegister cr=cr0)
static bool IsLis(Instr instr)
void mffprd(Register dst, DoubleRegister src)
static constexpr int kMaxBlockTrampolineSectionSize
void mtlr(Register src)
void push(Register src)
void shift(Operand dst, Immediate shift_amount, int subcode, int size)
void fcfidu(const DoubleRegister frt, const DoubleRegister frb, RCBit rc=LeaveRC)
Handle< Object > code_target_object_handle_at(Address pc, Address constant_pool)
void sldi(Register dst, Register src, const Operand &val, RCBit rc=LeaveRC)
void rldic(Register dst, Register src, int sh, int mb, RCBit r=LeaveRC)
void plwa(Register dst, const MemOperand &src)
void mtfprwa(DoubleRegister dst, Register src)
static bool Is64BitLoadIntoR12(Instr instr1, Instr instr2, Instr instr3, Instr instr4, Instr instr5)
void a_form(Instr instr, DoubleRegister frt, DoubleRegister fra, DoubleRegister frb, RCBit r)
void rotrwi(Register ra, Register rs, int sh, RCBit r=LeaveRC)
void vx_form(Instr instr, Simd128Register rt, Simd128Register rb, const Operand &imm)
void bne(Label *L, CRegister cr=cr0, LKBit lk=LeaveLK)
void lfd(const DoubleRegister frt, const MemOperand &src)
void rlwimi(Register ra, Register rs, int sh, int mb, int me, RCBit rc=LeaveRC)
static constexpr int kGap
void mcrfs(CRegister cr, FPSCRBit bit)
void fcmpu(const DoubleRegister fra, const DoubleRegister frb, CRegister cr=cr0)
void stxsibx(const Simd128Register rs, const MemOperand &dst)
static bool IsBranch(Instr instr)
void fctiwz(const DoubleRegister frt, const DoubleRegister frb)
void fctiwuz(const DoubleRegister frt, const DoubleRegister frb)
void dcbf(Register ra, Register rb)
void pstb(Register src, const MemOperand &dst)
void stfd(const DoubleRegister frs, const MemOperand &src)
void cmpi(Register src1, const Operand &src2, CRegister cr=cr0)
void mtfsf(const DoubleRegister frb, bool L=1, int FLM=0, bool W=0, RCBit rc=LeaveRC)
static void instr_at_put(Address pc, Instr instr)
void BlockTrampolinePoolFor(int instructions)
void EnsureSpaceFor(int space_needed)
void cmpli(Register src1, const Operand &src2, CRegister cr=cr0)
void lwz(Register dst, const MemOperand &src)
static Register GetCmpImmediateRegister(Instr instr)
void friz(const DoubleRegister frt, const DoubleRegister frb, RCBit rc=LeaveRC)
void GetCode(Isolate *isolate, CodeDesc *desc)
static constexpr int kMovInstructionsNoConstantPool
void lwzu(Register dst, const MemOperand &src)
void add_label_offset(Register dst, Register base, Label *label, int delta=0)
void b(Label *L, LKBit lk=LeaveLK)
void addc(Register dst, Register src1, Register src2, OEBit o=LeaveOE, RCBit r=LeaveRC)
void lha(Register dst, const MemOperand &src)
Simd128Register Simd128Register Simd128Register rb
void lfs(const DoubleRegister frt, const MemOperand &src)
void mfvsrd(const Register ra, const Simd128Register r)
void vx_form(Instr instr, Simd128Register rt, Register rb, const Operand &imm)
void psth(Register src, const MemOperand &dst)
Handle< HeapObject > compressed_embedded_object_handle_at(Address pc, Address constant_pool)
void fctidz(const DoubleRegister frt, const DoubleRegister frb, RCBit rc=LeaveRC)
void fcfid(const DoubleRegister frt, const DoubleRegister frb, RCBit rc=LeaveRC)
void xoris(Register ra, Register rs, const Operand &imm)
void target_at_put(int pos, int target_pos, bool *is_branch=nullptr)
void mffs(const DoubleRegister frt, RCBit rc=LeaveRC)
static constexpr int kInvalidSlotPos
void rldcl(Register ra, Register rs, Register rb, int mb, RCBit r=LeaveRC)
void cmplwi(Register src1, const Operand &src2, CRegister cr=cr0)
void dq(uint64_t data)
void beq(Label *L, CRegister cr=cr0, LKBit lk=LeaveLK)
void plfs(DoubleRegister dst, const MemOperand &src)
static bool IsRlwinm(Instr instr)
void fcfids(const DoubleRegister frt, const DoubleRegister frb, RCBit rc=LeaveRC)
ConstantPoolEntry::Access ConstantPoolAddEntry(RelocInfo::Mode rmode, intptr_t value)
void clrrwi(Register dst, Register src, const Operand &val, RCBit rc=LeaveRC)
void fabs(const DoubleRegister frt, const DoubleRegister frb, RCBit rc=LeaveRC)
static V8_INLINE Address target_address_at(Address pc, Address constant_pool)
void fsel(const DoubleRegister frt, const DoubleRegister fra, const DoubleRegister frc, const DoubleRegister frb, RCBit rc=LeaveRC)
static Instr instr_at(Address pc)
static int encode_crbit(const CRegister &cr, enum CRBit crbit)
void mov_label_addr(Register dst, Label *label)
void mtvsrd(const Simd128Register rt, const Register ra)
void subfic(Register dst, Register src, const Operand &imm)
static V8_INLINE bool IsConstantPoolLoadEnd(Address pc, ConstantPoolEntry::Access *access=nullptr)
static constexpr int kMovInstructionsConstantPool
void divd(Register dst, Register src1, Register src2, OEBit o=LeaveOE, RCBit r=LeaveRC)
void frim(const DoubleRegister frt, const DoubleRegister frb, RCBit rc=LeaveRC)
void plbz(Register dst, const MemOperand &src)
void mtfprd(DoubleRegister dst, Register src)
void oris(Register dst, Register src, const Operand &imm)
void bclr(Condition cond, CRegister cr=cr0, LKBit lk=LeaveLK)
void stwu(Register dst, const MemOperand &src)
void bunordered(Label *L, CRegister cr=cr0, LKBit lk=LeaveLK)
void fadd(const DoubleRegister frt, const DoubleRegister fra, const DoubleRegister frb, RCBit rc=LeaveRC)
void rlwinm(Register ra, Register rs, int sh, int mb, int me, RCBit rc=LeaveRC)
void bcctr(BOfield bo, int condition_bit, LKBit lk)
void plhz(Register dst, const MemOperand &src)
void pstfd(const DoubleRegister src, const MemOperand &dst)
void bc_short(Condition cond, Label *L, CRegister cr=cr0, LKBit lk=LeaveLK)
void pstw(Register src, const MemOperand &dst)
void fmr(const DoubleRegister frt, const DoubleRegister frb, RCBit rc=LeaveRC)
void xx3_form(Instr instr, Simd128Register t, Simd128Register a, Simd128Register b, int rc)
void mulli(Register dst, Register src, const Operand &imm)
void fmadd(const DoubleRegister frt, const DoubleRegister fra, const DoubleRegister frc, const DoubleRegister frb, RCBit rc=LeaveRC)
void GetCode(LocalIsolate *isolate, CodeDesc *desc, SafepointTableBuilderBase *safepoint_table_builder, int handler_table_offset)
void stxsihx(const Simd128Register rs, const MemOperand &dst)
void ldu(Register rd, const MemOperand &src)
void bordered(Label *L, CRegister cr=cr0, LKBit lk=LeaveLK)
void isel(Condition cond, Register rt, Register ra, Register rb, CRegister cr=cr0)
void pstfs(const DoubleRegister src, const MemOperand &dst)
static Register GetRB(Instr instr)
void dp(uintptr_t data)
void bt(Operand dst, Register src)
void stxvd(const Simd128Register rt, const MemOperand &dst)
void vc_form(Instr instr, Simd128Register rt, Simd128Register ra, Simd128Register rb, int rc)
static Register GetRA(Instr instr)
void bitwise_mov32(Register dst, int32_t value)
void li(Register dst, const Operand &src)
static bool IsLi(Instr instr)
void mulhwu(Register dst, Register src1, Register src2, RCBit r=LeaveRC)
void mtxer(Register src)
void mffprwz(Register dst, DoubleRegister src)
void plwz(Register dst, const MemOperand &src)
static Condition GetCondition(Instr instr)
void lbz(Register dst, const MemOperand &src)
void bclr(BOfield bo, int condition_bit, LKBit lk)
void sube(Register dst, Register src1, Register src2, OEBit s=LeaveOE, RCBit r=LeaveRC)
void bitwise_mov(Register dst, intptr_t value)
void nop(int type=0)
void bkpt(uint32_t imm16)
void vx_form(Instr instr, Simd128Register rt, const Operand &imm)
void dd(uint32_t data)
void mtcrf(Register src, uint8_t FXM)
void divdu(Register dst, Register src1, Register src2, OEBit o=LeaveOE, RCBit r=LeaveRC)
void prefix_form(Instr instr, const Operand &imm, int pr)
CRegister cmpi_optimization(CRegister cr)
void rotlwi(Register ra, Register rs, int sh, RCBit r=LeaveRC)
void stfs(const DoubleRegister frs, const MemOperand &src)
void stw(Register dst, const MemOperand &src)
void psubi(Register dst, Register src, const Operand &imm)
Assembler(const AssemblerOptions &, std::unique_ptr< AssemblerBuffer >={})
void bnooverflow(Label *L, CRegister cr=cr0, LKBit lk=LeaveLK)
void sh(Register rd, const MemOperand &rs)
void lfdu(const DoubleRegister frt, const MemOperand &src)
void clrrdi(Register dst, Register src, const Operand &val, RCBit rc=LeaveRC)
void subi(Register dst, Register src1, const Operand &src2)
void sth(Register dst, const MemOperand &src)
void fcfidus(const DoubleRegister frt, const DoubleRegister frb, RCBit rc=LeaveRC)
void bgt(Label *L, CRegister cr=cr0, LKBit lk=LeaveLK)
void mullw(Register dst, Register src1, Register src2, OEBit o=LeaveOE, RCBit r=LeaveRC)
void stfdu(const DoubleRegister frs, const MemOperand &src)
void lxsihzx(const Simd128Register rt, const MemOperand &src)
void boverflow(Label *L, CRegister cr=cr0, LKBit lk=LeaveLK)
void mtfsfi(int bf, int immediate, RCBit rc=LeaveRC)
bool ConstantPoolAccessIsInOverflow() const
void neg(Register rt, Register ra, OEBit o=LeaveOE, RCBit c=LeaveRC)
void fsqrt(const DoubleRegister frt, const DoubleRegister frb, RCBit rc=LeaveRC)
void CheckTrampolinePoolQuick(int extra_instructions=0)
int SizeOfCodeGeneratedSince(Label *label)
Instruction * pc() const
static constexpr int kMovInstructions
void mtfsb1(FPSCRBit bit, RCBit rc=LeaveRC)
void fctiw(const DoubleRegister frt, const DoubleRegister frb)
void RecordDeoptReason(DeoptimizeReason reason, uint32_t node_id, SourcePosition position, int id)
void lxsibzx(const Simd128Register rt, const MemOperand &src)
void BlockTrampolinePoolBefore(int pc_offset)
void paddi(Register dst, Register src, const Operand &imm)
void bge(Label *L, CRegister cr=cr0, LKBit lk=LeaveLK)
void pld(Register dst, const MemOperand &src)
void vx_form(Instr instr, Register rt, Simd128Register rb)
void bdnz(Label *L, LKBit lk=LeaveLK)
void vx_form(Instr instr, Simd128Register rt, Simd128Register rb)
void x_form(Instr instr, int f1, int f2, int f3, int rc)
void adde(Register dst, Register src1, Register src2, OEBit o=LeaveOE, RCBit r=LeaveRC)
static void set_target_compressed_address_at(Address pc, Address constant_pool, Tagged_t target, WritableJitAllocation *jit_allocation, ICacheFlushMode icache_flush_mode=FLUSH_ICACHE_IF_NEEDED)
ConstantPoolBuilder constant_pool_builder_
void rotrdi(Register ra, Register rs, int sh, RCBit r=LeaveRC)
int max_reach_from(int pos)
void slwi(Register dst, Register src, const Operand &val, RCBit rc=LeaveRC)
void mfvsrwz(const Register ra, const Simd128Register r)
void GrowBuffer(int needed=0)
RelocInfo::Mode rmode() const
DeferredRelocInfo(int position, RelocInfo::Mode rmode, intptr_t data)
EnsureSpace(Assembler *assembler)
V8_EXPORT_PRIVATE Address address() const
MemOperand(Register rn, int64_t offset=0)
MemOperand(Register ra, Register rb)
MemOperand(Register ra, Register rb, int64_t offset)
intptr_t immediate() const
V8_INLINE Operand(Tagged< Smi > value)
V8_INLINE Operand(const ExternalReference &f)
bool must_output_reloc_info(const Assembler *assembler) const
Operand(Handle< HeapObject > handle)
bool IsImmediate() const
HeapNumberRequest heap_number_request() const
bool IsHeapNumberRequest() const
V8_INLINE bool is_reg() const
static Operand EmbeddedNumber(double number)
Register rm() const
V8_INLINE Operand(intptr_t immediate, RelocInfo::Mode rmode=RelocInfo::NO_INFO)
static V8_INLINE Operand Zero()
int32_t immediate() const
V8_INLINE Operand(Register rm)
PatchingAssembler(const AssemblerOptions &options, uint8_t *address, int instructions)
constexpr int8_t code() const
static constexpr int kMaxSize
Definition reloc-info.h:488
static constexpr bool IsShareableRelocMode(Mode mode)
Definition reloc-info.h:192
static constexpr bool IsWasmCall(Mode mode)
Definition reloc-info.h:213
static constexpr bool IsWasmStubCall(Mode mode)
Definition reloc-info.h:214
static constexpr bool IsNoInfo(Mode mode)
Definition reloc-info.h:257
UseScratchRegisterScope(Assembler *assembler)
Operand const offset_
Register const value_
#define V8_EMBEDDED_CONSTANT_POOL_BOOL
Definition globals.h:81
#define PPC_VX_OPCODE_A_FORM_LIST(V)
#define PPC_PREFIX_OPCODE_TYPE_00_LIST(V)
#define PPC_X_OPCODE_EH_L_FORM_LIST(V)
#define PPC_VX_OPCODE_G_FORM_LIST(V)
#define PPC_VA_OPCODE_A_FORM_LIST(V)
#define PPC_VX_OPCODE_C_FORM_LIST(V)
#define PPC_X_OPCODE_D_FORM_LIST(V)
#define PPC_VX_OPCODE_B_FORM_LIST(V)
#define PPC_VX_OPCODE_D_FORM_LIST(V)
#define CRWIDTH
#define PPC_XX3_OPCODE_SCALAR_LIST(V)
#define PPC_X_OPCODE_F_FORM_LIST(V)
#define PPC_XX2_OPCODE_VECTOR_A_FORM_LIST(V)
#define PPC_X_OPCODE_C_FORM_LIST(V)
#define PPC_X_OPCODE_B_FORM_LIST(V)
#define PPC_XX3_OPCODE_VECTOR_B_FORM_LIST(V)
#define PPC_X_OPCODE_G_FORM_LIST(V)
#define PPC_X_OPCODE_A_FORM_LIST(V)
#define PPC_XX3_OPCODE_VECTOR_A_FORM_LIST(V)
#define PPC_VX_OPCODE_E_FORM_LIST(V)
#define PPC_VC_OPCODE_LIST(V)
#define PPC_X_OPCODE_EH_S_FORM_LIST(V)
#define PPC_VX_OPCODE_F_FORM_LIST(V)
#define PPC_X_OPCODE_E_FORM_LIST(V)
#define PPC_XX2_OPCODE_B_FORM_LIST(V)
#define PPC_XX2_OPCODE_SCALAR_A_FORM_LIST(V)
#define PPC_PREFIX_OPCODE_TYPE_10_LIST(V)
Label label
BytecodeAssembler & assembler_
int32_t offset
Instruction * instr
int x
int position
Definition liveedit.cc:290
int m
Definition mul-fft.cc:294
int r
Definition mul-fft.cc:298
STL namespace.
constexpr Register no_reg
constexpr int B6
constexpr int W
constexpr int32_t kDefaultStopCode
constexpr int B21
constexpr int B10
constexpr int B16
std::variant< Zone *, AccountingAllocator * > MaybeAssemblerZone
Definition assembler.h:262
const int kImm18Mask
Address Tagged_t
Definition globals.h:547
constexpr int L
constexpr int kSystemPointerSize
Definition globals.h:410
Condition NegateCondition(Condition cond)
@ FLUSH_ICACHE_IF_NEEDED
Definition reloc-info.h:25
constexpr int B23
constexpr uint8_t kInstrSize
const int kOpcodeMask
constexpr MiscInstructionsBits74 BX
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in allocation gc speed threshold for starting incremental marking via a task in percent of available threshold for starting incremental marking immediately in percent of available Use a single schedule for determining a marking schedule between JS and C objects schedules the minor GC task with kUserVisible priority max worker number of concurrent for NumberOfWorkerThreads start background threads that allocate memory concurrent_array_buffer_sweeping use parallel threads to clear weak refs in the atomic pause trace progress of the incremental marking trace object counts and memory usage * MB
Definition flags.cc:2197
constexpr int B20
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_IMPLIES(v1, v2)
Definition logging.h:493
#define DCHECK(condition)
Definition logging.h:482
#define V8_EXPORT_PRIVATE
Definition macros.h:460
#define V8_INLINE
Definition v8config.h:500
#define V8_NODISCARD
Definition v8config.h:693