1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
2 // All Rights Reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions
8 // - Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
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
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.
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.
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.
37 // A light-weight PPC Assembler
38 // Generates user mode instructions for the PPC architecture up
40 #ifndef V8_PPC_ASSEMBLER_PPC_H_
41 #define V8_PPC_ASSEMBLER_PPC_H_
46 #include "src/assembler.h"
47 #include "src/compiler.h"
48 #include "src/ppc/constants-ppc.h"
50 #define ABI_USES_FUNCTION_DESCRIPTORS \
51 (V8_HOST_ARCH_PPC && (V8_OS_AIX || \
52 (V8_TARGET_ARCH_PPC64 && V8_TARGET_BIG_ENDIAN)))
54 #define ABI_PASSES_HANDLES_IN_REGS \
55 (!V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64)
57 #define ABI_RETURNS_OBJECT_PAIRS_IN_REGS \
58 (!V8_HOST_ARCH_PPC || !V8_TARGET_ARCH_PPC64 || V8_TARGET_LITTLE_ENDIAN)
60 #define ABI_TOC_ADDRESSABILITY_VIA_IP \
61 (V8_HOST_ARCH_PPC && V8_TARGET_ARCH_PPC64 && V8_TARGET_LITTLE_ENDIAN)
63 #if !V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64
64 #define ABI_TOC_REGISTER kRegister_r2_Code
66 #define ABI_TOC_REGISTER kRegister_r13_Code
69 #define INSTR_AND_DATA_CACHE_COHERENCY LWSYNC
76 // 1) We would prefer to use an enum, but enum values are assignment-
77 // compatible with int, which has caused code-generation bugs.
79 // 2) We would prefer to use a class instead of a struct but we don't like
80 // the register initialization to depend on the particular initialization
81 // order (which appears to be different on OS X, Linux, and Windows for the
82 // installed versions of C++ we tried). Using a struct permits C-style
83 // "initialization". Also, the Register objects cannot be const as this
84 // forces initialization stubs in MSVC, making us dependent on initialization
87 // 3) By not using an enum, we are possibly preventing the compiler from
88 // doing certain constant folds, which may significantly reduce the
89 // code generated for some assembly instructions (because they boil down
90 // to a few constants). If this is a problem, we could change the code
91 // such that we use an enum in optimized mode, and the struct in debug
92 // mode. This way we get the compile-time error checking in debug mode
93 // and best performance in optimized code.
97 static const int kNumRegisters = 32;
98 static const int kSizeInBytes = kPointerSize;
100 #if V8_TARGET_LITTLE_ENDIAN
101 static const int kMantissaOffset = 0;
102 static const int kExponentOffset = 4;
104 static const int kMantissaOffset = 4;
105 static const int kExponentOffset = 0;
108 static const int kAllocatableLowRangeBegin = 3;
109 static const int kAllocatableLowRangeEnd = 10;
110 static const int kAllocatableHighRangeBegin = 14;
111 static const int kAllocatableHighRangeEnd =
112 FLAG_enable_embedded_constant_pool ? 27 : 28;
113 static const int kAllocatableContext = 30;
115 static const int kNumAllocatableLow =
116 kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1;
117 static const int kNumAllocatableHigh =
118 kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1;
119 static const int kMaxNumAllocatableRegisters =
120 kNumAllocatableLow + kNumAllocatableHigh + 1; // cp
122 static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; }
124 static int ToAllocationIndex(Register reg) {
126 int code = reg.code();
127 if (code == kAllocatableContext) {
128 // Context is the last index
129 index = NumAllocatableRegisters() - 1;
130 } else if (code <= kAllocatableLowRangeEnd) {
132 index = code - kAllocatableLowRangeBegin;
135 index = code - kAllocatableHighRangeBegin + kNumAllocatableLow;
137 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
141 static Register FromAllocationIndex(int index) {
142 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
143 // Last index is always the 'cp' register.
144 if (index == kMaxNumAllocatableRegisters - 1) {
145 return from_code(kAllocatableContext);
147 return (index < kNumAllocatableLow)
148 ? from_code(index + kAllocatableLowRangeBegin)
149 : from_code(index - kNumAllocatableLow +
150 kAllocatableHighRangeBegin);
153 static const char* AllocationIndexToString(int index) {
154 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
155 const char* const names[] = {
181 if (FLAG_enable_embedded_constant_pool &&
182 (index == kMaxNumAllocatableRegisters - 2)) {
183 return names[index + 1];
188 static const RegList kAllocatable =
189 1 << 3 | 1 << 4 | 1 << 5 | 1 << 6 | 1 << 7 | 1 << 8 | 1 << 9 | 1 << 10 |
190 1 << 14 | 1 << 15 | 1 << 16 | 1 << 17 | 1 << 18 | 1 << 19 | 1 << 20 |
191 1 << 21 | 1 << 22 | 1 << 23 | 1 << 24 | 1 << 25 | 1 << 26 | 1 << 27 |
192 (FLAG_enable_embedded_constant_pool ? 0 : 1 << 28) | 1 << 30;
194 static Register from_code(int code) {
199 bool is_valid() const { return 0 <= code_ && code_ < kNumRegisters; }
200 bool is(Register reg) const { return code_ == reg.code_; }
210 void set_code(int code) {
215 // Unfortunately we can't make this private in a struct.
219 // These constants are used in several locations, including static initializers
220 const int kRegister_no_reg_Code = -1;
221 const int kRegister_r0_Code = 0; // general scratch
222 const int kRegister_sp_Code = 1; // stack pointer
223 const int kRegister_r2_Code = 2; // special on PowerPC
224 const int kRegister_r3_Code = 3;
225 const int kRegister_r4_Code = 4;
226 const int kRegister_r5_Code = 5;
227 const int kRegister_r6_Code = 6;
228 const int kRegister_r7_Code = 7;
229 const int kRegister_r8_Code = 8;
230 const int kRegister_r9_Code = 9;
231 const int kRegister_r10_Code = 10;
232 const int kRegister_r11_Code = 11; // lithium scratch
233 const int kRegister_ip_Code = 12; // ip (general scratch)
234 const int kRegister_r13_Code = 13; // special on PowerPC
235 const int kRegister_r14_Code = 14;
236 const int kRegister_r15_Code = 15;
238 const int kRegister_r16_Code = 16;
239 const int kRegister_r17_Code = 17;
240 const int kRegister_r18_Code = 18;
241 const int kRegister_r19_Code = 19;
242 const int kRegister_r20_Code = 20;
243 const int kRegister_r21_Code = 21;
244 const int kRegister_r22_Code = 22;
245 const int kRegister_r23_Code = 23;
246 const int kRegister_r24_Code = 24;
247 const int kRegister_r25_Code = 25;
248 const int kRegister_r26_Code = 26;
249 const int kRegister_r27_Code = 27;
250 const int kRegister_r28_Code = 28; // constant pool pointer
251 const int kRegister_r29_Code = 29; // roots array pointer
252 const int kRegister_r30_Code = 30; // context pointer
253 const int kRegister_fp_Code = 31; // frame pointer
255 const Register no_reg = {kRegister_no_reg_Code};
257 const Register r0 = {kRegister_r0_Code};
258 const Register sp = {kRegister_sp_Code};
259 const Register r2 = {kRegister_r2_Code};
260 const Register r3 = {kRegister_r3_Code};
261 const Register r4 = {kRegister_r4_Code};
262 const Register r5 = {kRegister_r5_Code};
263 const Register r6 = {kRegister_r6_Code};
264 const Register r7 = {kRegister_r7_Code};
265 const Register r8 = {kRegister_r8_Code};
266 const Register r9 = {kRegister_r9_Code};
267 const Register r10 = {kRegister_r10_Code};
268 const Register r11 = {kRegister_r11_Code};
269 const Register ip = {kRegister_ip_Code};
270 const Register r13 = {kRegister_r13_Code};
271 const Register r14 = {kRegister_r14_Code};
272 const Register r15 = {kRegister_r15_Code};
274 const Register r16 = {kRegister_r16_Code};
275 const Register r17 = {kRegister_r17_Code};
276 const Register r18 = {kRegister_r18_Code};
277 const Register r19 = {kRegister_r19_Code};
278 const Register r20 = {kRegister_r20_Code};
279 const Register r21 = {kRegister_r21_Code};
280 const Register r22 = {kRegister_r22_Code};
281 const Register r23 = {kRegister_r23_Code};
282 const Register r24 = {kRegister_r24_Code};
283 const Register r25 = {kRegister_r25_Code};
284 const Register r26 = {kRegister_r26_Code};
285 const Register r27 = {kRegister_r27_Code};
286 const Register r28 = {kRegister_r28_Code};
287 const Register r29 = {kRegister_r29_Code};
288 const Register r30 = {kRegister_r30_Code};
289 const Register fp = {kRegister_fp_Code};
291 // Give alias names to registers
292 const Register cp = {kRegister_r30_Code}; // JavaScript context pointer
293 const Register kRootRegister = {kRegister_r29_Code}; // Roots array pointer.
294 const Register kConstantPoolRegister = {kRegister_r28_Code}; // Constant pool
296 // Double word FP register.
297 struct DoubleRegister {
298 static const int kNumRegisters = 32;
299 static const int kMaxNumRegisters = kNumRegisters;
300 static const int kNumVolatileRegisters = 14; // d0-d13
301 static const int kSizeInBytes = 8;
303 static const int kAllocatableLowRangeBegin = 1;
304 static const int kAllocatableLowRangeEnd = 12;
305 static const int kAllocatableHighRangeBegin = 15;
306 static const int kAllocatableHighRangeEnd = 31;
308 static const int kNumAllocatableLow =
309 kAllocatableLowRangeEnd - kAllocatableLowRangeBegin + 1;
310 static const int kNumAllocatableHigh =
311 kAllocatableHighRangeEnd - kAllocatableHighRangeBegin + 1;
312 static const int kMaxNumAllocatableRegisters =
313 kNumAllocatableLow + kNumAllocatableHigh;
314 static int NumAllocatableRegisters() { return kMaxNumAllocatableRegisters; }
317 inline static int NumAllocatableAliasedRegisters() {
318 return NumAllocatableRegisters();
321 static int ToAllocationIndex(DoubleRegister reg) {
322 int code = reg.code();
323 int index = (code <= kAllocatableLowRangeEnd)
324 ? code - kAllocatableLowRangeBegin
325 : code - kAllocatableHighRangeBegin + kNumAllocatableLow;
326 DCHECK(index < kMaxNumAllocatableRegisters);
330 static DoubleRegister FromAllocationIndex(int index) {
331 DCHECK(index >= 0 && index < kMaxNumAllocatableRegisters);
332 return (index < kNumAllocatableLow)
333 ? from_code(index + kAllocatableLowRangeBegin)
334 : from_code(index - kNumAllocatableLow +
335 kAllocatableHighRangeBegin);
338 static const char* AllocationIndexToString(int index);
340 static DoubleRegister from_code(int code) {
341 DoubleRegister r = {code};
345 bool is_valid() const { return 0 <= code_ && code_ < kMaxNumRegisters; }
346 bool is(DoubleRegister reg) const { return code_ == reg.code_; }
356 void split_code(int* vm, int* m) const {
358 *m = (code_ & 0x10) >> 4;
366 const DoubleRegister no_dreg = {-1};
367 const DoubleRegister d0 = {0};
368 const DoubleRegister d1 = {1};
369 const DoubleRegister d2 = {2};
370 const DoubleRegister d3 = {3};
371 const DoubleRegister d4 = {4};
372 const DoubleRegister d5 = {5};
373 const DoubleRegister d6 = {6};
374 const DoubleRegister d7 = {7};
375 const DoubleRegister d8 = {8};
376 const DoubleRegister d9 = {9};
377 const DoubleRegister d10 = {10};
378 const DoubleRegister d11 = {11};
379 const DoubleRegister d12 = {12};
380 const DoubleRegister d13 = {13};
381 const DoubleRegister d14 = {14};
382 const DoubleRegister d15 = {15};
383 const DoubleRegister d16 = {16};
384 const DoubleRegister d17 = {17};
385 const DoubleRegister d18 = {18};
386 const DoubleRegister d19 = {19};
387 const DoubleRegister d20 = {20};
388 const DoubleRegister d21 = {21};
389 const DoubleRegister d22 = {22};
390 const DoubleRegister d23 = {23};
391 const DoubleRegister d24 = {24};
392 const DoubleRegister d25 = {25};
393 const DoubleRegister d26 = {26};
394 const DoubleRegister d27 = {27};
395 const DoubleRegister d28 = {28};
396 const DoubleRegister d29 = {29};
397 const DoubleRegister d30 = {30};
398 const DoubleRegister d31 = {31};
400 // Aliases for double registers. Defined using #define instead of
401 // "static const DoubleRegister&" because Clang complains otherwise when a
402 // compilation unit that includes this header doesn't use the variables.
403 #define kFirstCalleeSavedDoubleReg d14
404 #define kLastCalleeSavedDoubleReg d31
405 #define kDoubleRegZero d14
406 #define kScratchDoubleReg d13
408 Register ToRegister(int num);
410 // Coprocessor register
412 bool is_valid() const { return 0 <= code_ && code_ < 16; }
413 bool is(CRegister creg) const { return code_ == creg.code_; }
423 // Unfortunately we can't make this private in a struct.
428 const CRegister no_creg = {-1};
430 const CRegister cr0 = {0};
431 const CRegister cr1 = {1};
432 const CRegister cr2 = {2};
433 const CRegister cr3 = {3};
434 const CRegister cr4 = {4};
435 const CRegister cr5 = {5};
436 const CRegister cr6 = {6};
437 const CRegister cr7 = {7};
438 const CRegister cr8 = {8};
439 const CRegister cr9 = {9};
440 const CRegister cr10 = {10};
441 const CRegister cr11 = {11};
442 const CRegister cr12 = {12};
443 const CRegister cr13 = {13};
444 const CRegister cr14 = {14};
445 const CRegister cr15 = {15};
447 // -----------------------------------------------------------------------------
448 // Machine instruction Operands
450 #if V8_TARGET_ARCH_PPC64
451 const RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE64;
453 const RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE32;
456 // Class Operand represents a shifter operand in data processing instructions
457 class Operand BASE_EMBEDDED {
460 INLINE(explicit Operand(intptr_t immediate,
461 RelocInfo::Mode rmode = kRelocInfo_NONEPTR));
462 INLINE(static Operand Zero()) { return Operand(static_cast<intptr_t>(0)); }
463 INLINE(explicit Operand(const ExternalReference& f));
464 explicit Operand(Handle<Object> handle);
465 INLINE(explicit Operand(Smi* value));
468 INLINE(explicit Operand(Register rm));
470 // Return true if this is a register operand.
471 INLINE(bool is_reg() const);
473 bool must_output_reloc_info(const Assembler* assembler) const;
475 inline intptr_t immediate() const {
476 DCHECK(!rm_.is_valid());
480 Register rm() const { return rm_; }
484 intptr_t imm_; // valid if rm_ == no_reg
485 RelocInfo::Mode rmode_;
487 friend class Assembler;
488 friend class MacroAssembler;
492 // Class MemOperand represents a memory operand in load and store instructions
493 // On PowerPC we have base register + 16bit signed value
494 // Alternatively we can have a 16bit signed value immediate
495 class MemOperand BASE_EMBEDDED {
497 explicit MemOperand(Register rn, int32_t offset = 0);
499 explicit MemOperand(Register ra, Register rb);
501 int32_t offset() const {
502 DCHECK(rb_.is(no_reg));
506 // PowerPC - base register
507 Register ra() const {
508 DCHECK(!ra_.is(no_reg));
512 Register rb() const {
513 DCHECK(offset_ == 0 && !rb_.is(no_reg));
518 Register ra_; // base
519 int32_t offset_; // offset
520 Register rb_; // index
522 friend class Assembler;
526 class DeferredRelocInfo {
528 DeferredRelocInfo() {}
529 DeferredRelocInfo(int position, RelocInfo::Mode rmode, intptr_t data)
530 : position_(position), rmode_(rmode), data_(data) {}
532 int position() const { return position_; }
533 RelocInfo::Mode rmode() const { return rmode_; }
534 intptr_t data() const { return data_; }
538 RelocInfo::Mode rmode_;
543 class Assembler : public AssemblerBase {
545 // Create an assembler. Instructions and relocation information are emitted
546 // into a buffer, with the instructions starting from the beginning and the
547 // relocation information starting from the end of the buffer. See CodeDesc
548 // for a detailed comment on the layout (globals.h).
550 // If the provided buffer is NULL, the assembler allocates and grows its own
551 // buffer, and buffer_size determines the initial buffer size. The buffer is
552 // owned by the assembler and deallocated upon destruction of the assembler.
554 // If the provided buffer is not NULL, the assembler uses the provided buffer
555 // for code generation and assumes its size to be buffer_size. If the buffer
556 // is too small, a fatal error occurs. No deallocation of the buffer is done
557 // upon destruction of the assembler.
558 Assembler(Isolate* isolate, void* buffer, int buffer_size);
559 virtual ~Assembler() {}
561 // GetCode emits any pending (non-emitted) code and fills the descriptor
562 // desc. GetCode() is idempotent; it returns the same result if no other
563 // Assembler functions are invoked in between GetCode() calls.
564 void GetCode(CodeDesc* desc);
566 // Label operations & relative jumps (PPUM Appendix D)
568 // Takes a branch opcode (cc) and a label (L) and generates
569 // either a backward branch or a forward branch and links it
570 // to the label fixup chain. Usage:
572 // Label L; // unbound label
573 // j(cc, &L); // forward branch to unbound label
574 // bind(&L); // bind label to the current pc
575 // j(cc, &L); // backward branch to bound label
576 // bind(&L); // illegal: a label may be bound only once
578 // Note: The same Label can be used for forward and backward branches
579 // but it may be bound only once.
581 void bind(Label* L); // binds an unbound label L to the current code position
583 // Links a label at the current pc_offset(). If already bound, returns the
584 // bound position. If already linked, returns the position of the prior link.
585 // Otherwise, returns the current pc_offset().
588 // Determines if Label is bound and near enough so that a single
589 // branch instruction can be used to reach it.
590 bool is_near(Label* L, Condition cond);
592 // Returns the branch offset to the given label from the current code position
593 // Links the label to the current position if it is still unbound
594 int branch_offset(Label* L) {
595 if (L->is_unused() && !trampoline_emitted_) {
598 return link(L) - pc_offset();
601 // Puts a labels target address at the given position.
602 // The high 8 bits are set to zero.
603 void label_at_put(Label* L, int at_offset);
605 INLINE(static bool IsConstantPoolLoadStart(
606 Address pc, ConstantPoolEntry::Access* access = nullptr));
607 INLINE(static bool IsConstantPoolLoadEnd(
608 Address pc, ConstantPoolEntry::Access* access = nullptr));
609 INLINE(static int GetConstantPoolOffset(Address pc,
610 ConstantPoolEntry::Access access,
611 ConstantPoolEntry::Type type));
612 INLINE(void PatchConstantPoolAccessInstruction(
613 int pc_offset, int offset, ConstantPoolEntry::Access access,
614 ConstantPoolEntry::Type type));
616 // Return the address in the constant pool of the code target address used by
617 // the branch/call instruction at pc, or the object in a mov.
618 INLINE(static Address target_constant_pool_address_at(
619 Address pc, Address constant_pool, ConstantPoolEntry::Access access,
620 ConstantPoolEntry::Type type));
622 // Read/Modify the code target address in the branch/call instruction at pc.
623 INLINE(static Address target_address_at(Address pc, Address constant_pool));
624 INLINE(static void set_target_address_at(
625 Address pc, Address constant_pool, Address target,
626 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
627 INLINE(static Address target_address_at(Address pc, Code* code)) {
628 Address constant_pool = code ? code->constant_pool() : NULL;
629 return target_address_at(pc, constant_pool);
631 INLINE(static void set_target_address_at(
632 Address pc, Code* code, Address target,
633 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)) {
634 Address constant_pool = code ? code->constant_pool() : NULL;
635 set_target_address_at(pc, constant_pool, target, icache_flush_mode);
638 // Return the code target address at a call site from the return address
639 // of that call in the instruction stream.
640 inline static Address target_address_from_return_address(Address pc);
642 // Given the address of the beginning of a call, return the address
643 // in the instruction stream that the call will return to.
644 INLINE(static Address return_address_from_call_start(Address pc));
646 // This sets the branch destination.
647 // This is for calls and branches within generated code.
648 inline static void deserialization_set_special_target_at(
649 Address instruction_payload, Code* code, Address target);
651 // This sets the internal reference at the pc.
652 inline static void deserialization_set_target_internal_reference_at(
653 Address pc, Address target,
654 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
656 // Size of an instruction.
657 static const int kInstrSize = sizeof(Instr);
659 // Here we are patching the address in the LUI/ORI instruction pair.
660 // These values are used in the serialization process and must be zero for
661 // PPC platform, as Code, Embedded Object or External-reference pointers
662 // are split across two consecutive instructions and don't exist separately
663 // in the code, so the serializer should not step forwards in memory after
664 // a target is resolved and written.
665 static const int kSpecialTargetSize = 0;
667 // Number of instructions to load an address via a mov sequence.
668 #if V8_TARGET_ARCH_PPC64
669 static const int kMovInstructionsConstantPool = 1;
670 static const int kMovInstructionsNoConstantPool = 5;
671 #if defined(V8_PPC_TAGGING_OPT)
672 static const int kTaggedLoadInstructions = 1;
674 static const int kTaggedLoadInstructions = 2;
677 static const int kMovInstructionsConstantPool = 1;
678 static const int kMovInstructionsNoConstantPool = 2;
679 static const int kTaggedLoadInstructions = 1;
681 static const int kMovInstructions = FLAG_enable_embedded_constant_pool
682 ? kMovInstructionsConstantPool
683 : kMovInstructionsNoConstantPool;
685 // Distance between the instruction referring to the address of the call
686 // target and the return address.
688 // Call sequence is a FIXED_SEQUENCE:
689 // mov r8, @ call address
693 static const int kCallTargetAddressOffset =
694 (kMovInstructions + 2) * kInstrSize;
696 // Distance between start of patched debug break slot and the emitted address
698 // Patched debug break slot code is a FIXED_SEQUENCE:
702 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize;
704 // This is the length of the code sequence from SetDebugBreakAtSlot()
706 static const int kDebugBreakSlotInstructions =
707 kMovInstructionsNoConstantPool + 2;
708 static const int kDebugBreakSlotLength =
709 kDebugBreakSlotInstructions * kInstrSize;
711 static inline int encode_crbit(const CRegister& cr, enum CRBit crbit) {
712 return ((cr.code() * CRWIDTH) + crbit);
715 // ---------------------------------------------------------------------------
718 // Insert the smallest number of nop instructions
719 // possible to align the pc offset to a multiple
720 // of m. m must be a power of 2 (>= 4).
722 // Insert the smallest number of zero bytes possible to align the pc offset
723 // to a mulitple of m. m must be a power of 2 (>= 2).
724 void DataAlign(int m);
725 // Aligns code to something that's optimal for a jump target for the platform.
726 void CodeTargetAlign();
728 // Branch instructions
729 void bclr(BOfield bo, int condition_bit, LKBit lk);
731 void bc(int branch_offset, BOfield bo, int condition_bit, LKBit lk = LeaveLK);
732 void b(int branch_offset, LKBit lk);
734 void bcctr(BOfield bo, int condition_bit, LKBit lk);
738 // Convenience branch instructions using labels
739 void b(Label* L, LKBit lk = LeaveLK) { b(branch_offset(L), lk); }
741 inline CRegister cmpi_optimization(CRegister cr) {
742 // Check whether the branch is preceeded by an optimizable cmpi against 0.
743 // The cmpi can be deleted if it is also preceeded by an instruction that
744 // sets the register used by the compare and supports a dot form.
745 unsigned int sradi_mask = kOpcodeMask | kExt2OpcodeVariant2Mask;
746 unsigned int srawi_mask = kOpcodeMask | kExt2OpcodeMask;
747 int pos = pc_offset();
748 int cmpi_pos = pc_offset() - kInstrSize;
750 if (cmpi_pos > 0 && optimizable_cmpi_pos_ == cmpi_pos &&
751 cmpi_cr_.code() == cr.code() && last_bound_pos_ != pos) {
752 int xpos = cmpi_pos - kInstrSize;
753 int xinstr = instr_at(xpos);
754 int cmpi_ra = (instr_at(cmpi_pos) & 0x1f0000) >> 16;
755 // ra is at the same bit position for the three cases below.
756 int ra = (xinstr & 0x1f0000) >> 16;
758 if ((xinstr & sradi_mask) == (EXT2 | SRADIX)) {
760 instr_at_put(xpos, xinstr | SetRC);
762 } else if ((xinstr & srawi_mask) == (EXT2 | SRAWIX)) {
764 instr_at_put(xpos, xinstr | SetRC);
766 } else if ((xinstr & kOpcodeMask) == ANDIx) {
769 // nothing to do here since andi. records.
771 // didn't match one of the above, must keep cmpwi.
777 void bc_short(Condition cond, Label* L, CRegister cr = cr7,
778 LKBit lk = LeaveLK) {
780 DCHECK(cr.code() >= 0 && cr.code() <= 7);
782 cr = cmpi_optimization(cr);
784 int b_offset = branch_offset(L);
788 bc(b_offset, BT, encode_crbit(cr, CR_EQ), lk);
791 bc(b_offset, BF, encode_crbit(cr, CR_EQ), lk);
794 bc(b_offset, BT, encode_crbit(cr, CR_GT), lk);
797 bc(b_offset, BF, encode_crbit(cr, CR_GT), lk);
800 bc(b_offset, BT, encode_crbit(cr, CR_LT), lk);
803 bc(b_offset, BF, encode_crbit(cr, CR_LT), lk);
806 bc(b_offset, BT, encode_crbit(cr, CR_FU), lk);
809 bc(b_offset, BF, encode_crbit(cr, CR_FU), lk);
812 bc(b_offset, BT, encode_crbit(cr, CR_SO), lk);
815 bc(b_offset, BF, encode_crbit(cr, CR_SO), lk);
822 void bclr(Condition cond, CRegister cr = cr7, LKBit lk = LeaveLK) {
824 DCHECK(cr.code() >= 0 && cr.code() <= 7);
826 cr = cmpi_optimization(cr);
830 bclr(BT, encode_crbit(cr, CR_EQ), lk);
833 bclr(BF, encode_crbit(cr, CR_EQ), lk);
836 bclr(BT, encode_crbit(cr, CR_GT), lk);
839 bclr(BF, encode_crbit(cr, CR_GT), lk);
842 bclr(BT, encode_crbit(cr, CR_LT), lk);
845 bclr(BF, encode_crbit(cr, CR_LT), lk);
848 bclr(BT, encode_crbit(cr, CR_FU), lk);
851 bclr(BF, encode_crbit(cr, CR_FU), lk);
854 bclr(BT, encode_crbit(cr, CR_SO), lk);
857 bclr(BF, encode_crbit(cr, CR_SO), lk);
864 void isel(Register rt, Register ra, Register rb, int cb);
865 void isel(Condition cond, Register rt, Register ra, Register rb,
866 CRegister cr = cr7) {
868 DCHECK(cr.code() >= 0 && cr.code() <= 7);
870 cr = cmpi_optimization(cr);
874 isel(rt, ra, rb, encode_crbit(cr, CR_EQ));
877 isel(rt, rb, ra, encode_crbit(cr, CR_EQ));
880 isel(rt, ra, rb, encode_crbit(cr, CR_GT));
883 isel(rt, rb, ra, encode_crbit(cr, CR_GT));
886 isel(rt, ra, rb, encode_crbit(cr, CR_LT));
889 isel(rt, rb, ra, encode_crbit(cr, CR_LT));
892 isel(rt, ra, rb, encode_crbit(cr, CR_FU));
895 isel(rt, rb, ra, encode_crbit(cr, CR_FU));
898 isel(rt, ra, rb, encode_crbit(cr, CR_SO));
901 isel(rt, rb, ra, encode_crbit(cr, CR_SO));
908 void b(Condition cond, Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
914 if ((L->is_bound() && is_near(L, cond)) || !is_trampoline_emitted()) {
915 bc_short(cond, L, cr, lk);
920 Condition neg_cond = NegateCondition(cond);
921 bc_short(neg_cond, &skip, cr);
926 void bne(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
929 void beq(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
932 void blt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
935 void bge(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
938 void ble(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
941 void bgt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
944 void bunordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
945 b(unordered, L, cr, lk);
947 void bordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
948 b(ordered, L, cr, lk);
950 void boverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
951 b(overflow, L, cr, lk);
953 void bnooverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
954 b(nooverflow, L, cr, lk);
957 // Decrement CTR; branch if CTR != 0
958 void bdnz(Label* L, LKBit lk = LeaveLK) {
959 bc(branch_offset(L), DCBNZ, 0, lk);
962 // Data-processing instructions
964 void sub(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
967 void subfic(Register dst, Register src, const Operand& imm);
969 void subfc(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
972 void add(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
975 void addc(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
978 void addze(Register dst, Register src1, OEBit o, RCBit r);
980 void mullw(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
983 void mulhw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
984 void mulhwu(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
986 void divw(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
988 void divwu(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
991 void addi(Register dst, Register src, const Operand& imm);
992 void addis(Register dst, Register src, const Operand& imm);
993 void addic(Register dst, Register src, const Operand& imm);
995 void and_(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
996 void andc(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
997 void andi(Register ra, Register rs, const Operand& imm);
998 void andis(Register ra, Register rs, const Operand& imm);
999 void nor(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
1000 void notx(Register dst, Register src, RCBit r = LeaveRC);
1001 void ori(Register dst, Register src, const Operand& imm);
1002 void oris(Register dst, Register src, const Operand& imm);
1003 void orx(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
1004 void orc(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
1005 void xori(Register dst, Register src, const Operand& imm);
1006 void xoris(Register ra, Register rs, const Operand& imm);
1007 void xor_(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
1008 void cmpi(Register src1, const Operand& src2, CRegister cr = cr7);
1009 void cmpli(Register src1, const Operand& src2, CRegister cr = cr7);
1010 void cmpwi(Register src1, const Operand& src2, CRegister cr = cr7);
1011 void cmplwi(Register src1, const Operand& src2, CRegister cr = cr7);
1012 void li(Register dst, const Operand& src);
1013 void lis(Register dst, const Operand& imm);
1014 void mr(Register dst, Register src);
1016 void lbz(Register dst, const MemOperand& src);
1017 void lbzx(Register dst, const MemOperand& src);
1018 void lbzux(Register dst, const MemOperand& src);
1019 void lhz(Register dst, const MemOperand& src);
1020 void lhzx(Register dst, const MemOperand& src);
1021 void lhzux(Register dst, const MemOperand& src);
1022 void lha(Register dst, const MemOperand& src);
1023 void lhax(Register dst, const MemOperand& src);
1024 void lwz(Register dst, const MemOperand& src);
1025 void lwzu(Register dst, const MemOperand& src);
1026 void lwzx(Register dst, const MemOperand& src);
1027 void lwzux(Register dst, const MemOperand& src);
1028 void lwa(Register dst, const MemOperand& src);
1029 void lwax(Register dst, const MemOperand& src);
1030 void stb(Register dst, const MemOperand& src);
1031 void stbx(Register dst, const MemOperand& src);
1032 void stbux(Register dst, const MemOperand& src);
1033 void sth(Register dst, const MemOperand& src);
1034 void sthx(Register dst, const MemOperand& src);
1035 void sthux(Register dst, const MemOperand& src);
1036 void stw(Register dst, const MemOperand& src);
1037 void stwu(Register dst, const MemOperand& src);
1038 void stwx(Register rs, const MemOperand& src);
1039 void stwux(Register rs, const MemOperand& src);
1041 void extsb(Register rs, Register ra, RCBit r = LeaveRC);
1042 void extsh(Register rs, Register ra, RCBit r = LeaveRC);
1043 void extsw(Register rs, Register ra, RCBit r = LeaveRC);
1045 void neg(Register rt, Register ra, OEBit o = LeaveOE, RCBit c = LeaveRC);
1047 #if V8_TARGET_ARCH_PPC64
1048 void ld(Register rd, const MemOperand& src);
1049 void ldx(Register rd, const MemOperand& src);
1050 void ldu(Register rd, const MemOperand& src);
1051 void ldux(Register rd, const MemOperand& src);
1052 void std(Register rs, const MemOperand& src);
1053 void stdx(Register rs, const MemOperand& src);
1054 void stdu(Register rs, const MemOperand& src);
1055 void stdux(Register rs, const MemOperand& src);
1056 void rldic(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
1057 void rldicl(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
1058 void rldcl(Register ra, Register rs, Register rb, int mb, RCBit r = LeaveRC);
1059 void rldicr(Register dst, Register src, int sh, int me, RCBit r = LeaveRC);
1060 void rldimi(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
1061 void sldi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
1062 void srdi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
1063 void clrrdi(Register dst, Register src, const Operand& val,
1064 RCBit rc = LeaveRC);
1065 void clrldi(Register dst, Register src, const Operand& val,
1066 RCBit rc = LeaveRC);
1067 void sradi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
1068 void srd(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
1069 void sld(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
1070 void srad(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
1071 void rotld(Register ra, Register rs, Register rb, RCBit r = LeaveRC);
1072 void rotldi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
1073 void rotrdi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
1074 void cntlzd_(Register dst, Register src, RCBit rc = LeaveRC);
1075 void mulld(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
1077 void divd(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
1079 void divdu(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
1083 void rlwinm(Register ra, Register rs, int sh, int mb, int me,
1084 RCBit rc = LeaveRC);
1085 void rlwimi(Register ra, Register rs, int sh, int mb, int me,
1086 RCBit rc = LeaveRC);
1087 void rlwnm(Register ra, Register rs, Register rb, int mb, int me,
1088 RCBit rc = LeaveRC);
1089 void slwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
1090 void srwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
1091 void clrrwi(Register dst, Register src, const Operand& val,
1092 RCBit rc = LeaveRC);
1093 void clrlwi(Register dst, Register src, const Operand& val,
1094 RCBit rc = LeaveRC);
1095 void srawi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
1096 void srw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
1097 void slw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
1098 void sraw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
1099 void rotlw(Register ra, Register rs, Register rb, RCBit r = LeaveRC);
1100 void rotlwi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
1101 void rotrwi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
1103 void cntlzw_(Register dst, Register src, RCBit rc = LeaveRC);
1105 void subi(Register dst, Register src1, const Operand& src2);
1107 void cmp(Register src1, Register src2, CRegister cr = cr7);
1108 void cmpl(Register src1, Register src2, CRegister cr = cr7);
1109 void cmpw(Register src1, Register src2, CRegister cr = cr7);
1110 void cmplw(Register src1, Register src2, CRegister cr = cr7);
1112 void mov(Register dst, const Operand& src);
1113 void bitwise_mov(Register dst, intptr_t value);
1114 void bitwise_mov32(Register dst, int32_t value);
1115 void bitwise_add32(Register dst, Register src, int32_t value);
1117 // Load the position of the label relative to the generated code object
1118 // pointer in a register.
1119 void mov_label_offset(Register dst, Label* label);
1121 // dst = base + label position + delta
1122 void add_label_offset(Register dst, Register base, Label* label,
1125 // Load the address of the label in a register and associate with an
1126 // internal reference relocation.
1127 void mov_label_addr(Register dst, Label* label);
1129 // Emit the address of the label (i.e. a jump table entry) and associate with
1130 // an internal reference relocation.
1131 void emit_label_addr(Label* label);
1133 // Multiply instructions
1134 void mul(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
1137 // Miscellaneous arithmetic instructions
1139 // Special register access
1140 void crxor(int bt, int ba, int bb);
1141 void crclr(int bt) { crxor(bt, bt, bt); }
1142 void creqv(int bt, int ba, int bb);
1143 void crset(int bt) { creqv(bt, bt, bt); }
1144 void mflr(Register dst);
1145 void mtlr(Register src);
1146 void mtctr(Register src);
1147 void mtxer(Register src);
1148 void mcrfs(int bf, int bfa);
1149 void mfcr(Register dst);
1150 #if V8_TARGET_ARCH_PPC64
1151 void mffprd(Register dst, DoubleRegister src);
1152 void mffprwz(Register dst, DoubleRegister src);
1153 void mtfprd(DoubleRegister dst, Register src);
1154 void mtfprwz(DoubleRegister dst, Register src);
1155 void mtfprwa(DoubleRegister dst, Register src);
1158 void function_descriptor();
1160 // Exception-generating instructions and debugging support
1161 void stop(const char* msg, Condition cond = al,
1162 int32_t code = kDefaultStopCode, CRegister cr = cr7);
1164 void bkpt(uint32_t imm16); // v5 and above
1166 void dcbf(Register ra, Register rb);
1169 void icbi(Register ra, Register rb);
1172 // Support for floating point
1173 void lfd(const DoubleRegister frt, const MemOperand& src);
1174 void lfdu(const DoubleRegister frt, const MemOperand& src);
1175 void lfdx(const DoubleRegister frt, const MemOperand& src);
1176 void lfdux(const DoubleRegister frt, const MemOperand& src);
1177 void lfs(const DoubleRegister frt, const MemOperand& src);
1178 void lfsu(const DoubleRegister frt, const MemOperand& src);
1179 void lfsx(const DoubleRegister frt, const MemOperand& src);
1180 void lfsux(const DoubleRegister frt, const MemOperand& src);
1181 void stfd(const DoubleRegister frs, const MemOperand& src);
1182 void stfdu(const DoubleRegister frs, const MemOperand& src);
1183 void stfdx(const DoubleRegister frs, const MemOperand& src);
1184 void stfdux(const DoubleRegister frs, const MemOperand& src);
1185 void stfs(const DoubleRegister frs, const MemOperand& src);
1186 void stfsu(const DoubleRegister frs, const MemOperand& src);
1187 void stfsx(const DoubleRegister frs, const MemOperand& src);
1188 void stfsux(const DoubleRegister frs, const MemOperand& src);
1190 void fadd(const DoubleRegister frt, const DoubleRegister fra,
1191 const DoubleRegister frb, RCBit rc = LeaveRC);
1192 void fsub(const DoubleRegister frt, const DoubleRegister fra,
1193 const DoubleRegister frb, RCBit rc = LeaveRC);
1194 void fdiv(const DoubleRegister frt, const DoubleRegister fra,
1195 const DoubleRegister frb, RCBit rc = LeaveRC);
1196 void fmul(const DoubleRegister frt, const DoubleRegister fra,
1197 const DoubleRegister frc, RCBit rc = LeaveRC);
1198 void fcmpu(const DoubleRegister fra, const DoubleRegister frb,
1199 CRegister cr = cr7);
1200 void fmr(const DoubleRegister frt, const DoubleRegister frb,
1201 RCBit rc = LeaveRC);
1202 void fctiwz(const DoubleRegister frt, const DoubleRegister frb);
1203 void fctiw(const DoubleRegister frt, const DoubleRegister frb);
1204 void frin(const DoubleRegister frt, const DoubleRegister frb,
1205 RCBit rc = LeaveRC);
1206 void friz(const DoubleRegister frt, const DoubleRegister frb,
1207 RCBit rc = LeaveRC);
1208 void frip(const DoubleRegister frt, const DoubleRegister frb,
1209 RCBit rc = LeaveRC);
1210 void frim(const DoubleRegister frt, const DoubleRegister frb,
1211 RCBit rc = LeaveRC);
1212 void frsp(const DoubleRegister frt, const DoubleRegister frb,
1213 RCBit rc = LeaveRC);
1214 void fcfid(const DoubleRegister frt, const DoubleRegister frb,
1215 RCBit rc = LeaveRC);
1216 void fctid(const DoubleRegister frt, const DoubleRegister frb,
1217 RCBit rc = LeaveRC);
1218 void fctidz(const DoubleRegister frt, const DoubleRegister frb,
1219 RCBit rc = LeaveRC);
1220 void fsel(const DoubleRegister frt, const DoubleRegister fra,
1221 const DoubleRegister frc, const DoubleRegister frb,
1222 RCBit rc = LeaveRC);
1223 void fneg(const DoubleRegister frt, const DoubleRegister frb,
1224 RCBit rc = LeaveRC);
1225 void mtfsfi(int bf, int immediate, RCBit rc = LeaveRC);
1226 void mffs(const DoubleRegister frt, RCBit rc = LeaveRC);
1227 void mtfsf(const DoubleRegister frb, bool L = 1, int FLM = 0, bool W = 0,
1228 RCBit rc = LeaveRC);
1229 void fsqrt(const DoubleRegister frt, const DoubleRegister frb,
1230 RCBit rc = LeaveRC);
1231 void fabs(const DoubleRegister frt, const DoubleRegister frb,
1232 RCBit rc = LeaveRC);
1233 void fmadd(const DoubleRegister frt, const DoubleRegister fra,
1234 const DoubleRegister frc, const DoubleRegister frb,
1235 RCBit rc = LeaveRC);
1236 void fmsub(const DoubleRegister frt, const DoubleRegister fra,
1237 const DoubleRegister frc, const DoubleRegister frb,
1238 RCBit rc = LeaveRC);
1240 // Pseudo instructions
1242 // Different nop operations are used by the code generator to detect certain
1243 // states of the generated code.
1244 enum NopMarkerTypes {
1245 NON_MARKING_NOP = 0,
1249 PROPERTY_ACCESS_INLINED,
1250 PROPERTY_ACCESS_INLINED_CONTEXT,
1251 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1254 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1257 void nop(int type = 0); // 0 is the default non-marking type.
1259 void push(Register src) {
1260 #if V8_TARGET_ARCH_PPC64
1261 stdu(src, MemOperand(sp, -kPointerSize));
1263 stwu(src, MemOperand(sp, -kPointerSize));
1267 void pop(Register dst) {
1268 #if V8_TARGET_ARCH_PPC64
1269 ld(dst, MemOperand(sp));
1271 lwz(dst, MemOperand(sp));
1273 addi(sp, sp, Operand(kPointerSize));
1276 void pop() { addi(sp, sp, Operand(kPointerSize)); }
1278 // Jump unconditionally to given label.
1279 void jmp(Label* L) { b(L); }
1281 // Check the code size generated from label to here.
1282 int SizeOfCodeGeneratedSince(Label* label) {
1283 return pc_offset() - label->pos();
1286 // Check the number of instructions generated from label to here.
1287 int InstructionsGeneratedSince(Label* label) {
1288 return SizeOfCodeGeneratedSince(label) / kInstrSize;
1291 // Class for scoping postponing the trampoline pool generation.
1292 class BlockTrampolinePoolScope {
1294 explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) {
1295 assem_->StartBlockTrampolinePool();
1297 ~BlockTrampolinePoolScope() { assem_->EndBlockTrampolinePool(); }
1302 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope);
1305 // Class for scoping disabling constant pool entry merging
1306 class BlockConstantPoolEntrySharingScope {
1308 explicit BlockConstantPoolEntrySharingScope(Assembler* assem)
1310 assem_->StartBlockConstantPoolEntrySharing();
1312 ~BlockConstantPoolEntrySharingScope() {
1313 assem_->EndBlockConstantPoolEntrySharing();
1319 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstantPoolEntrySharingScope);
1324 // Mark generator continuation.
1325 void RecordGeneratorContinuation();
1327 // Mark address of a debug break slot.
1328 void RecordDebugBreakSlot(RelocInfo::Mode mode, int argc = 0);
1330 // Record the AST id of the CallIC being compiled, so that it can be placed
1331 // in the relocation information.
1332 void SetRecordedAstId(TypeFeedbackId ast_id) {
1333 // Causes compiler to fail
1334 // DCHECK(recorded_ast_id_.IsNone());
1335 recorded_ast_id_ = ast_id;
1338 TypeFeedbackId RecordedAstId() {
1339 // Causes compiler to fail
1340 // DCHECK(!recorded_ast_id_.IsNone());
1341 return recorded_ast_id_;
1344 void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
1346 // Record a comment relocation entry that can be used by a disassembler.
1347 // Use --code-comments to enable.
1348 void RecordComment(const char* msg);
1350 // Record a deoptimization reason that can be used by a log or cpu profiler.
1351 // Use --trace-deopt to enable.
1352 void RecordDeoptReason(const int reason, const SourcePosition position);
1354 // Writes a single byte or word of data in the code stream. Used
1355 // for inline tables, e.g., jump-tables.
1356 void db(uint8_t data);
1357 void dd(uint32_t data);
1358 void dq(uint64_t data);
1359 void dp(uintptr_t data);
1361 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
1363 // Read/patch instructions
1364 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1365 void instr_at_put(int pos, Instr instr) {
1366 *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1368 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1369 static void instr_at_put(byte* pc, Instr instr) {
1370 *reinterpret_cast<Instr*>(pc) = instr;
1372 static Condition GetCondition(Instr instr);
1374 static bool IsLis(Instr instr);
1375 static bool IsLi(Instr instr);
1376 static bool IsAddic(Instr instr);
1377 static bool IsOri(Instr instr);
1379 static bool IsBranch(Instr instr);
1380 static Register GetRA(Instr instr);
1381 static Register GetRB(Instr instr);
1382 #if V8_TARGET_ARCH_PPC64
1383 static bool Is64BitLoadIntoR12(Instr instr1, Instr instr2, Instr instr3,
1384 Instr instr4, Instr instr5);
1386 static bool Is32BitLoadIntoR12(Instr instr1, Instr instr2);
1389 static bool IsCmpRegister(Instr instr);
1390 static bool IsCmpImmediate(Instr instr);
1391 static bool IsRlwinm(Instr instr);
1392 static bool IsAndi(Instr instr);
1393 #if V8_TARGET_ARCH_PPC64
1394 static bool IsRldicl(Instr instr);
1396 static bool IsCrSet(Instr instr);
1397 static Register GetCmpImmediateRegister(Instr instr);
1398 static int GetCmpImmediateRawImmediate(Instr instr);
1399 static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
1401 // Postpone the generation of the trampoline pool for the specified number of
1403 void BlockTrampolinePoolFor(int instructions);
1404 void CheckTrampolinePool();
1406 // For mov. Return the number of actual instructions required to
1407 // load the operand into a register. This can be anywhere from
1408 // one (constant pool small section) to five instructions (full
1409 // 64-bit sequence).
1411 // The value returned is only valid as long as no entries are added to the
1412 // constant pool between this call and the actual instruction being emitted.
1413 int instructions_required_for_mov(Register dst, const Operand& src) const;
1415 // Decide between using the constant pool vs. a mov immediate sequence.
1416 bool use_constant_pool_for_mov(Register dst, const Operand& src,
1417 bool canOptimize) const;
1419 // The code currently calls CheckBuffer() too often. This has the side
1420 // effect of randomly growing the buffer in the middle of multi-instruction
1423 // This function allows outside callers to check and grow the buffer
1424 void EnsureSpaceFor(int space_needed);
1426 int EmitConstantPool() { return constant_pool_builder_.Emit(this); }
1428 bool ConstantPoolAccessIsInOverflow() const {
1429 return constant_pool_builder_.NextAccess(ConstantPoolEntry::INTPTR) ==
1430 ConstantPoolEntry::OVERFLOWED;
1433 Label* ConstantPoolPosition() {
1434 return constant_pool_builder_.EmittedPosition();
1437 void EmitRelocations();
1440 // Relocation for a type-recording IC has the AST id added to it. This
1441 // member variable is a way to pass the information from the call site to
1442 // the relocation info.
1443 TypeFeedbackId recorded_ast_id_;
1445 int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1447 // Decode instruction(s) at pos and return backchain to previous
1448 // label reference or kEndOfChain.
1449 int target_at(int pos);
1451 // Patch instruction(s) at pos to target target_pos (e.g. branch)
1452 void target_at_put(int pos, int target_pos, bool* is_branch = nullptr);
1454 // Record reloc info for current pc_
1455 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
1456 ConstantPoolEntry::Access ConstantPoolAddEntry(RelocInfo::Mode rmode,
1458 bool sharing_ok = RelocInfo::IsNone(rmode) ||
1459 !(serializer_enabled() || rmode < RelocInfo::CELL ||
1460 is_constant_pool_entry_sharing_blocked());
1461 return constant_pool_builder_.AddEntry(pc_offset(), value, sharing_ok);
1463 ConstantPoolEntry::Access ConstantPoolAddEntry(double value) {
1464 return constant_pool_builder_.AddEntry(pc_offset(), value);
1467 // Block the emission of the trampoline pool before pc_offset.
1468 void BlockTrampolinePoolBefore(int pc_offset) {
1469 if (no_trampoline_pool_before_ < pc_offset)
1470 no_trampoline_pool_before_ = pc_offset;
1473 void StartBlockTrampolinePool() { trampoline_pool_blocked_nesting_++; }
1474 void EndBlockTrampolinePool() { trampoline_pool_blocked_nesting_--; }
1475 bool is_trampoline_pool_blocked() const {
1476 return trampoline_pool_blocked_nesting_ > 0;
1479 void StartBlockConstantPoolEntrySharing() {
1480 constant_pool_entry_sharing_blocked_nesting_++;
1482 void EndBlockConstantPoolEntrySharing() {
1483 constant_pool_entry_sharing_blocked_nesting_--;
1485 bool is_constant_pool_entry_sharing_blocked() const {
1486 return constant_pool_entry_sharing_blocked_nesting_ > 0;
1489 bool has_exception() const { return internal_trampoline_exception_; }
1491 bool is_trampoline_emitted() const { return trampoline_emitted_; }
1495 // The relocation writer's position is at least kGap bytes below the end of
1496 // the generated instructions. This is so that multi-instruction sequences do
1497 // not have to check for overflow. The same is true for writes of large
1498 // relocation info entries.
1499 static const int kGap = 32;
1501 // Repeated checking whether the trampoline pool should be emitted is rather
1502 // expensive. By default we only check again once a number of instructions
1503 // has been generated.
1504 int next_trampoline_check_; // pc offset of next buffer check.
1506 // Emission of the trampoline pool may be blocked in some code sequences.
1507 int trampoline_pool_blocked_nesting_; // Block emission if this is not zero.
1508 int no_trampoline_pool_before_; // Block emission before this pc offset.
1510 // Do not share constant pool entries.
1511 int constant_pool_entry_sharing_blocked_nesting_;
1513 // Relocation info generation
1514 // Each relocation is encoded as a variable size value
1515 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1516 RelocInfoWriter reloc_info_writer;
1517 std::vector<DeferredRelocInfo> relocations_;
1519 // The bound position, before this we cannot do instruction elimination.
1520 int last_bound_pos_;
1521 // Optimizable cmpi information.
1522 int optimizable_cmpi_pos_;
1525 ConstantPoolBuilder constant_pool_builder_;
1528 inline void CheckBuffer();
1529 void GrowBuffer(int needed = 0);
1530 inline void emit(Instr x);
1531 inline void TrackBranch();
1532 inline void UntrackBranch();
1533 inline void CheckTrampolinePoolQuick();
1535 // Instruction generation
1536 void a_form(Instr instr, DoubleRegister frt, DoubleRegister fra,
1537 DoubleRegister frb, RCBit r);
1538 void d_form(Instr instr, Register rt, Register ra, const intptr_t val,
1540 void x_form(Instr instr, Register ra, Register rs, Register rb, RCBit r);
1541 void xo_form(Instr instr, Register rt, Register ra, Register rb, OEBit o,
1543 void md_form(Instr instr, Register ra, Register rs, int shift, int maskbit,
1545 void mds_form(Instr instr, Register ra, Register rs, Register rb, int maskbit,
1549 void print(Label* L);
1550 int max_reach_from(int pos);
1551 void bind_to(Label* L, int pos);
1552 void next(Label* L);
1558 free_slot_count_ = 0;
1560 Trampoline(int start, int slot_count) {
1562 free_slot_count_ = slot_count;
1565 int trampoline_slot = kInvalidSlotPos;
1566 if (free_slot_count_ <= 0) {
1567 // We have run out of space on trampolines.
1568 // Make sure we fail in debug mode, so we become aware of each case
1569 // when this happens.
1571 // Internal exception will be caught.
1573 trampoline_slot = next_slot_;
1575 next_slot_ += kTrampolineSlotsSize;
1577 return trampoline_slot;
1582 int free_slot_count_;
1585 int32_t get_trampoline_entry();
1586 int tracked_branch_count_;
1587 // If trampoline is emitted, generated code is becoming large. As
1588 // this is already a slow case which can possibly break our code
1589 // generation for the extreme case, we use this information to
1590 // trigger different mode of branch instruction generation, where we
1591 // no longer use a single branch instruction.
1592 bool trampoline_emitted_;
1593 static const int kTrampolineSlotsSize = kInstrSize;
1594 static const int kMaxCondBranchReach = (1 << (16 - 1)) - 1;
1595 static const int kMaxBlockTrampolineSectionSize = 64 * kInstrSize;
1596 static const int kInvalidSlotPos = -1;
1598 Trampoline trampoline_;
1599 bool internal_trampoline_exception_;
1601 friend class RegExpMacroAssemblerPPC;
1602 friend class RelocInfo;
1603 friend class CodePatcher;
1604 friend class BlockTrampolinePoolScope;
1605 PositionsRecorder positions_recorder_;
1606 friend class PositionsRecorder;
1607 friend class EnsureSpace;
1611 class EnsureSpace BASE_EMBEDDED {
1613 explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); }
1615 } // namespace internal
1618 #endif // V8_PPC_ASSEMBLER_PPC_H_