blob: 24166e3c6e989ef6ada53426234f9ba53e7472be [file] [log] [blame]
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001// Copyright (c) 1994-2006 Sun Microsystems Inc.
2// All Rights Reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions
6// are met:
7//
8// - Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10//
11// - Redistribution in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the
14// distribution.
15//
16// - Neither the name of Sun Microsystems or the names of contributors may
17// be used to endorse or promote products derived from this software without
18// specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31// OF THE POSSIBILITY OF SUCH DAMAGE.
32
33// The original source code covered by the above license above has been
34// modified significantly by Google Inc.
35// Copyright 2014 the V8 project authors. All rights reserved.
36
37// A light-weight PPC Assembler
38// Generates user mode instructions for the PPC architecture up
39
40#ifndef V8_PPC_ASSEMBLER_PPC_H_
41#define V8_PPC_ASSEMBLER_PPC_H_
42
43#include <stdio.h>
44#include <vector>
45
46#include "src/assembler.h"
47#include "src/ppc/constants-ppc.h"
Emily Bernierd0a1eb72015-03-24 16:35:39 -040048
Ben Murdoch097c5b22016-05-18 11:27:45 +010049#if V8_HOST_ARCH_PPC && \
50 (V8_OS_AIX || (V8_TARGET_ARCH_PPC64 && V8_TARGET_BIG_ENDIAN))
51#define ABI_USES_FUNCTION_DESCRIPTORS 1
52#else
53#define ABI_USES_FUNCTION_DESCRIPTORS 0
54#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -040055
Ben Murdoch097c5b22016-05-18 11:27:45 +010056#if !V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64
57#define ABI_PASSES_HANDLES_IN_REGS 1
58#else
59#define ABI_PASSES_HANDLES_IN_REGS 0
60#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -040061
Ben Murdoch097c5b22016-05-18 11:27:45 +010062#if !V8_HOST_ARCH_PPC || !V8_TARGET_ARCH_PPC64 || V8_TARGET_LITTLE_ENDIAN
63#define ABI_RETURNS_OBJECT_PAIRS_IN_REGS 1
64#else
65#define ABI_RETURNS_OBJECT_PAIRS_IN_REGS 0
66#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -040067
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000068#if !V8_HOST_ARCH_PPC || (V8_TARGET_ARCH_PPC64 && V8_TARGET_LITTLE_ENDIAN)
69#define ABI_CALL_VIA_IP 1
70#else
71#define ABI_CALL_VIA_IP 0
72#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -040073
74#if !V8_HOST_ARCH_PPC || V8_OS_AIX || V8_TARGET_ARCH_PPC64
Ben Murdoch097c5b22016-05-18 11:27:45 +010075#define ABI_TOC_REGISTER 2
Emily Bernierd0a1eb72015-03-24 16:35:39 -040076#else
Ben Murdoch097c5b22016-05-18 11:27:45 +010077#define ABI_TOC_REGISTER 13
Emily Bernierd0a1eb72015-03-24 16:35:39 -040078#endif
79
80#define INSTR_AND_DATA_CACHE_COHERENCY LWSYNC
81
82namespace v8 {
83namespace internal {
84
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000085// clang-format off
86#define GENERAL_REGISTERS(V) \
87 V(r0) V(sp) V(r2) V(r3) V(r4) V(r5) V(r6) V(r7) \
88 V(r8) V(r9) V(r10) V(r11) V(ip) V(r13) V(r14) V(r15) \
89 V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \
90 V(r24) V(r25) V(r26) V(r27) V(r28) V(r29) V(r30) V(fp)
91
92#if V8_EMBEDDED_CONSTANT_POOL
93#define ALLOCATABLE_GENERAL_REGISTERS(V) \
94 V(r3) V(r4) V(r5) V(r6) V(r7) \
95 V(r8) V(r9) V(r10) V(r14) V(r15) \
96 V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \
97 V(r24) V(r25) V(r26) V(r27) V(r30)
98#else
99#define ALLOCATABLE_GENERAL_REGISTERS(V) \
100 V(r3) V(r4) V(r5) V(r6) V(r7) \
101 V(r8) V(r9) V(r10) V(r14) V(r15) \
102 V(r16) V(r17) V(r18) V(r19) V(r20) V(r21) V(r22) V(r23) \
103 V(r24) V(r25) V(r26) V(r27) V(r28) V(r30)
104#endif
105
106#define DOUBLE_REGISTERS(V) \
107 V(d0) V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
108 V(d8) V(d9) V(d10) V(d11) V(d12) V(d13) V(d14) V(d15) \
109 V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
110 V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
111
Ben Murdochc5610432016-08-08 18:44:38 +0100112#define FLOAT_REGISTERS DOUBLE_REGISTERS
113
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000114#define ALLOCATABLE_DOUBLE_REGISTERS(V) \
115 V(d1) V(d2) V(d3) V(d4) V(d5) V(d6) V(d7) \
116 V(d8) V(d9) V(d10) V(d11) V(d12) V(d15) \
117 V(d16) V(d17) V(d18) V(d19) V(d20) V(d21) V(d22) V(d23) \
118 V(d24) V(d25) V(d26) V(d27) V(d28) V(d29) V(d30) V(d31)
119// clang-format on
120
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400121// CPU Registers.
122//
123// 1) We would prefer to use an enum, but enum values are assignment-
124// compatible with int, which has caused code-generation bugs.
125//
126// 2) We would prefer to use a class instead of a struct but we don't like
127// the register initialization to depend on the particular initialization
128// order (which appears to be different on OS X, Linux, and Windows for the
129// installed versions of C++ we tried). Using a struct permits C-style
130// "initialization". Also, the Register objects cannot be const as this
131// forces initialization stubs in MSVC, making us dependent on initialization
132// order.
133//
134// 3) By not using an enum, we are possibly preventing the compiler from
135// doing certain constant folds, which may significantly reduce the
136// code generated for some assembly instructions (because they boil down
137// to a few constants). If this is a problem, we could change the code
138// such that we use an enum in optimized mode, and the struct in debug
139// mode. This way we get the compile-time error checking in debug mode
140// and best performance in optimized code.
141
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400142struct Register {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000143 enum Code {
144#define REGISTER_CODE(R) kCode_##R,
145 GENERAL_REGISTERS(REGISTER_CODE)
146#undef REGISTER_CODE
147 kAfterLast,
148 kCode_no_reg = -1
149 };
150
151 static const int kNumRegisters = Code::kAfterLast;
152
153#define REGISTER_COUNT(R) 1 +
154 static const int kNumAllocatable =
155 ALLOCATABLE_GENERAL_REGISTERS(REGISTER_COUNT)0;
156#undef REGISTER_COUNT
157
158#define REGISTER_BIT(R) 1 << kCode_##R |
159 static const RegList kAllocatable =
160 ALLOCATABLE_GENERAL_REGISTERS(REGISTER_BIT)0;
161#undef REGISTER_BIT
162
163 static Register from_code(int code) {
164 DCHECK(code >= 0);
165 DCHECK(code < kNumRegisters);
166 Register r = {code};
167 return r;
168 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
170 bool is(Register reg) const { return reg_code == reg.reg_code; }
171 int code() const {
172 DCHECK(is_valid());
173 return reg_code;
174 }
175 int bit() const {
176 DCHECK(is_valid());
177 return 1 << reg_code;
178 }
179 void set_code(int code) {
180 reg_code = code;
181 DCHECK(is_valid());
182 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400183
184#if V8_TARGET_LITTLE_ENDIAN
185 static const int kMantissaOffset = 0;
186 static const int kExponentOffset = 4;
187#else
188 static const int kMantissaOffset = 4;
189 static const int kExponentOffset = 0;
190#endif
191
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400192 // Unfortunately we can't make this private in a struct.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 int reg_code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400194};
195
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000196#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
197GENERAL_REGISTERS(DECLARE_REGISTER)
198#undef DECLARE_REGISTER
199const Register no_reg = {Register::kCode_no_reg};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400200
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000201// Aliases
202const Register kLithiumScratch = r11; // lithium scratch.
203const Register kConstantPoolRegister = r28; // Constant pool.
204const Register kRootRegister = r29; // Roots array pointer.
205const Register cp = r30; // JavaScript context pointer.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400206
Ben Murdoch61f157c2016-09-16 13:49:30 +0100207static const bool kSimpleFPAliasing = true;
208
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400209// Double word FP register.
210struct DoubleRegister {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211 enum Code {
212#define REGISTER_CODE(R) kCode_##R,
213 DOUBLE_REGISTERS(REGISTER_CODE)
214#undef REGISTER_CODE
215 kAfterLast,
216 kCode_no_reg = -1
217 };
218
219 static const int kNumRegisters = Code::kAfterLast;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400220 static const int kMaxNumRegisters = kNumRegisters;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400221
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000222 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
223 bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
224 int code() const {
225 DCHECK(is_valid());
226 return reg_code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400227 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000228 int bit() const {
229 DCHECK(is_valid());
230 return 1 << reg_code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400231 }
232
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400233 static DoubleRegister from_code(int code) {
234 DoubleRegister r = {code};
235 return r;
236 }
237
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000238 int reg_code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400239};
240
Ben Murdochc5610432016-08-08 18:44:38 +0100241typedef DoubleRegister FloatRegister;
242
243// TODO(ppc) Define SIMD registers.
244typedef DoubleRegister Simd128Register;
245
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000246#define DECLARE_REGISTER(R) \
247 const DoubleRegister R = {DoubleRegister::kCode_##R};
248DOUBLE_REGISTERS(DECLARE_REGISTER)
249#undef DECLARE_REGISTER
250const Register no_dreg = {Register::kCode_no_reg};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400251
252// Aliases for double registers. Defined using #define instead of
253// "static const DoubleRegister&" because Clang complains otherwise when a
254// compilation unit that includes this header doesn't use the variables.
255#define kFirstCalleeSavedDoubleReg d14
256#define kLastCalleeSavedDoubleReg d31
257#define kDoubleRegZero d14
258#define kScratchDoubleReg d13
259
260Register ToRegister(int num);
261
262// Coprocessor register
263struct CRegister {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100264 bool is_valid() const { return 0 <= reg_code && reg_code < 8; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000265 bool is(CRegister creg) const { return reg_code == creg.reg_code; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400266 int code() const {
267 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000268 return reg_code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400269 }
270 int bit() const {
271 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000272 return 1 << reg_code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400273 }
274
275 // Unfortunately we can't make this private in a struct.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000276 int reg_code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400277};
278
279
280const CRegister no_creg = {-1};
281
282const CRegister cr0 = {0};
283const CRegister cr1 = {1};
284const CRegister cr2 = {2};
285const CRegister cr3 = {3};
286const CRegister cr4 = {4};
287const CRegister cr5 = {5};
288const CRegister cr6 = {6};
289const CRegister cr7 = {7};
Ben Murdoch097c5b22016-05-18 11:27:45 +0100290
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400291// -----------------------------------------------------------------------------
292// Machine instruction Operands
293
294#if V8_TARGET_ARCH_PPC64
295const RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE64;
296#else
297const RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE32;
298#endif
299
300// Class Operand represents a shifter operand in data processing instructions
301class Operand BASE_EMBEDDED {
302 public:
303 // immediate
304 INLINE(explicit Operand(intptr_t immediate,
305 RelocInfo::Mode rmode = kRelocInfo_NONEPTR));
306 INLINE(static Operand Zero()) { return Operand(static_cast<intptr_t>(0)); }
307 INLINE(explicit Operand(const ExternalReference& f));
308 explicit Operand(Handle<Object> handle);
309 INLINE(explicit Operand(Smi* value));
310
311 // rm
312 INLINE(explicit Operand(Register rm));
313
314 // Return true if this is a register operand.
315 INLINE(bool is_reg() const);
316
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400317 bool must_output_reloc_info(const Assembler* assembler) const;
318
319 inline intptr_t immediate() const {
320 DCHECK(!rm_.is_valid());
321 return imm_;
322 }
323
324 Register rm() const { return rm_; }
325
326 private:
327 Register rm_;
328 intptr_t imm_; // valid if rm_ == no_reg
329 RelocInfo::Mode rmode_;
330
331 friend class Assembler;
332 friend class MacroAssembler;
333};
334
335
336// Class MemOperand represents a memory operand in load and store instructions
337// On PowerPC we have base register + 16bit signed value
338// Alternatively we can have a 16bit signed value immediate
339class MemOperand BASE_EMBEDDED {
340 public:
341 explicit MemOperand(Register rn, int32_t offset = 0);
342
343 explicit MemOperand(Register ra, Register rb);
344
345 int32_t offset() const {
346 DCHECK(rb_.is(no_reg));
347 return offset_;
348 }
349
350 // PowerPC - base register
351 Register ra() const {
352 DCHECK(!ra_.is(no_reg));
353 return ra_;
354 }
355
356 Register rb() const {
357 DCHECK(offset_ == 0 && !rb_.is(no_reg));
358 return rb_;
359 }
360
361 private:
362 Register ra_; // base
363 int32_t offset_; // offset
364 Register rb_; // index
365
366 friend class Assembler;
367};
368
369
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000370class DeferredRelocInfo {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400371 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000372 DeferredRelocInfo() {}
373 DeferredRelocInfo(int position, RelocInfo::Mode rmode, intptr_t data)
374 : position_(position), rmode_(rmode), data_(data) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400375
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000376 int position() const { return position_; }
377 RelocInfo::Mode rmode() const { return rmode_; }
378 intptr_t data() const { return data_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400379
380 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000381 int position_;
382 RelocInfo::Mode rmode_;
383 intptr_t data_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400384};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400385
386
387class Assembler : public AssemblerBase {
388 public:
389 // Create an assembler. Instructions and relocation information are emitted
390 // into a buffer, with the instructions starting from the beginning and the
391 // relocation information starting from the end of the buffer. See CodeDesc
392 // for a detailed comment on the layout (globals.h).
393 //
394 // If the provided buffer is NULL, the assembler allocates and grows its own
395 // buffer, and buffer_size determines the initial buffer size. The buffer is
396 // owned by the assembler and deallocated upon destruction of the assembler.
397 //
398 // If the provided buffer is not NULL, the assembler uses the provided buffer
399 // for code generation and assumes its size to be buffer_size. If the buffer
400 // is too small, a fatal error occurs. No deallocation of the buffer is done
401 // upon destruction of the assembler.
402 Assembler(Isolate* isolate, void* buffer, int buffer_size);
403 virtual ~Assembler() {}
404
405 // GetCode emits any pending (non-emitted) code and fills the descriptor
406 // desc. GetCode() is idempotent; it returns the same result if no other
407 // Assembler functions are invoked in between GetCode() calls.
408 void GetCode(CodeDesc* desc);
409
410 // Label operations & relative jumps (PPUM Appendix D)
411 //
412 // Takes a branch opcode (cc) and a label (L) and generates
413 // either a backward branch or a forward branch and links it
414 // to the label fixup chain. Usage:
415 //
416 // Label L; // unbound label
417 // j(cc, &L); // forward branch to unbound label
418 // bind(&L); // bind label to the current pc
419 // j(cc, &L); // backward branch to bound label
420 // bind(&L); // illegal: a label may be bound only once
421 //
422 // Note: The same Label can be used for forward and backward branches
423 // but it may be bound only once.
424
425 void bind(Label* L); // binds an unbound label L to the current code position
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000426
427 // Links a label at the current pc_offset(). If already bound, returns the
428 // bound position. If already linked, returns the position of the prior link.
429 // Otherwise, returns the current pc_offset().
430 int link(Label* L);
431
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400432 // Determines if Label is bound and near enough so that a single
433 // branch instruction can be used to reach it.
434 bool is_near(Label* L, Condition cond);
435
436 // Returns the branch offset to the given label from the current code position
437 // Links the label to the current position if it is still unbound
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000438 int branch_offset(Label* L) {
439 if (L->is_unused() && !trampoline_emitted_) {
440 TrackBranch();
441 }
442 return link(L) - pc_offset();
443 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400444
445 // Puts a labels target address at the given position.
446 // The high 8 bits are set to zero.
447 void label_at_put(Label* L, int at_offset);
448
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000449 INLINE(static bool IsConstantPoolLoadStart(
450 Address pc, ConstantPoolEntry::Access* access = nullptr));
451 INLINE(static bool IsConstantPoolLoadEnd(
452 Address pc, ConstantPoolEntry::Access* access = nullptr));
453 INLINE(static int GetConstantPoolOffset(Address pc,
454 ConstantPoolEntry::Access access,
455 ConstantPoolEntry::Type type));
456 INLINE(void PatchConstantPoolAccessInstruction(
457 int pc_offset, int offset, ConstantPoolEntry::Access access,
458 ConstantPoolEntry::Type type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400459
460 // Return the address in the constant pool of the code target address used by
461 // the branch/call instruction at pc, or the object in a mov.
462 INLINE(static Address target_constant_pool_address_at(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000463 Address pc, Address constant_pool, ConstantPoolEntry::Access access,
464 ConstantPoolEntry::Type type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400465
466 // Read/Modify the code target address in the branch/call instruction at pc.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000467 INLINE(static Address target_address_at(Address pc, Address constant_pool));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400468 INLINE(static void set_target_address_at(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000469 Isolate* isolate, Address pc, Address constant_pool, Address target,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400470 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
471 INLINE(static Address target_address_at(Address pc, Code* code)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000472 Address constant_pool = code ? code->constant_pool() : NULL;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400473 return target_address_at(pc, constant_pool);
474 }
475 INLINE(static void set_target_address_at(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000476 Isolate* isolate, Address pc, Code* code, Address target,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400477 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000478 Address constant_pool = code ? code->constant_pool() : NULL;
479 set_target_address_at(isolate, pc, constant_pool, target,
480 icache_flush_mode);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400481 }
482
483 // Return the code target address at a call site from the return address
484 // of that call in the instruction stream.
485 inline static Address target_address_from_return_address(Address pc);
486
487 // Given the address of the beginning of a call, return the address
488 // in the instruction stream that the call will return to.
489 INLINE(static Address return_address_from_call_start(Address pc));
490
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400491 // This sets the branch destination.
492 // This is for calls and branches within generated code.
493 inline static void deserialization_set_special_target_at(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000494 Isolate* isolate, Address instruction_payload, Code* code,
495 Address target);
496
497 // This sets the internal reference at the pc.
498 inline static void deserialization_set_target_internal_reference_at(
499 Isolate* isolate, Address pc, Address target,
500 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400501
502 // Size of an instruction.
503 static const int kInstrSize = sizeof(Instr);
504
505 // Here we are patching the address in the LUI/ORI instruction pair.
506 // These values are used in the serialization process and must be zero for
507 // PPC platform, as Code, Embedded Object or External-reference pointers
508 // are split across two consecutive instructions and don't exist separately
509 // in the code, so the serializer should not step forwards in memory after
510 // a target is resolved and written.
511 static const int kSpecialTargetSize = 0;
512
513// Number of instructions to load an address via a mov sequence.
514#if V8_TARGET_ARCH_PPC64
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000515 static const int kMovInstructionsConstantPool = 1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400516 static const int kMovInstructionsNoConstantPool = 5;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000517#if defined(V8_PPC_TAGGING_OPT)
518 static const int kTaggedLoadInstructions = 1;
519#else
520 static const int kTaggedLoadInstructions = 2;
521#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400522#else
523 static const int kMovInstructionsConstantPool = 1;
524 static const int kMovInstructionsNoConstantPool = 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000525 static const int kTaggedLoadInstructions = 1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400526#endif
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000527 static const int kMovInstructions = FLAG_enable_embedded_constant_pool
528 ? kMovInstructionsConstantPool
529 : kMovInstructionsNoConstantPool;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400530
531 // Distance between the instruction referring to the address of the call
532 // target and the return address.
533
534 // Call sequence is a FIXED_SEQUENCE:
535 // mov r8, @ call address
536 // mtlr r8
537 // blrl
538 // @ return address
539 static const int kCallTargetAddressOffset =
540 (kMovInstructions + 2) * kInstrSize;
541
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400542 // Distance between start of patched debug break slot and the emitted address
543 // to jump to.
544 // Patched debug break slot code is a FIXED_SEQUENCE:
545 // mov r0, <address>
546 // mtlr r0
547 // blrl
548 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize;
549
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400550 // This is the length of the code sequence from SetDebugBreakAtSlot()
551 // FIXED_SEQUENCE
552 static const int kDebugBreakSlotInstructions =
553 kMovInstructionsNoConstantPool + 2;
554 static const int kDebugBreakSlotLength =
555 kDebugBreakSlotInstructions * kInstrSize;
556
557 static inline int encode_crbit(const CRegister& cr, enum CRBit crbit) {
558 return ((cr.code() * CRWIDTH) + crbit);
559 }
560
561 // ---------------------------------------------------------------------------
562 // Code generation
563
564 // Insert the smallest number of nop instructions
565 // possible to align the pc offset to a multiple
566 // of m. m must be a power of 2 (>= 4).
567 void Align(int m);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000568 // Insert the smallest number of zero bytes possible to align the pc offset
569 // to a mulitple of m. m must be a power of 2 (>= 2).
570 void DataAlign(int m);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400571 // Aligns code to something that's optimal for a jump target for the platform.
572 void CodeTargetAlign();
573
574 // Branch instructions
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000575 void bclr(BOfield bo, int condition_bit, LKBit lk);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400576 void blr();
577 void bc(int branch_offset, BOfield bo, int condition_bit, LKBit lk = LeaveLK);
578 void b(int branch_offset, LKBit lk);
579
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000580 void bcctr(BOfield bo, int condition_bit, LKBit lk);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400581 void bctr();
582 void bctrl();
583
584 // Convenience branch instructions using labels
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000585 void b(Label* L, LKBit lk = LeaveLK) { b(branch_offset(L), lk); }
586
587 inline CRegister cmpi_optimization(CRegister cr) {
588 // Check whether the branch is preceeded by an optimizable cmpi against 0.
589 // The cmpi can be deleted if it is also preceeded by an instruction that
590 // sets the register used by the compare and supports a dot form.
591 unsigned int sradi_mask = kOpcodeMask | kExt2OpcodeVariant2Mask;
592 unsigned int srawi_mask = kOpcodeMask | kExt2OpcodeMask;
593 int pos = pc_offset();
594 int cmpi_pos = pc_offset() - kInstrSize;
595
596 if (cmpi_pos > 0 && optimizable_cmpi_pos_ == cmpi_pos &&
597 cmpi_cr_.code() == cr.code() && last_bound_pos_ != pos) {
598 int xpos = cmpi_pos - kInstrSize;
599 int xinstr = instr_at(xpos);
600 int cmpi_ra = (instr_at(cmpi_pos) & 0x1f0000) >> 16;
601 // ra is at the same bit position for the three cases below.
602 int ra = (xinstr & 0x1f0000) >> 16;
603 if (cmpi_ra == ra) {
604 if ((xinstr & sradi_mask) == (EXT2 | SRADIX)) {
605 cr = cr0;
606 instr_at_put(xpos, xinstr | SetRC);
607 pc_ -= kInstrSize;
608 } else if ((xinstr & srawi_mask) == (EXT2 | SRAWIX)) {
609 cr = cr0;
610 instr_at_put(xpos, xinstr | SetRC);
611 pc_ -= kInstrSize;
612 } else if ((xinstr & kOpcodeMask) == ANDIx) {
613 cr = cr0;
614 pc_ -= kInstrSize;
615 // nothing to do here since andi. records.
616 }
617 // didn't match one of the above, must keep cmpwi.
618 }
619 }
620 return cr;
621 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400622
623 void bc_short(Condition cond, Label* L, CRegister cr = cr7,
624 LKBit lk = LeaveLK) {
625 DCHECK(cond != al);
626 DCHECK(cr.code() >= 0 && cr.code() <= 7);
627
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000628 cr = cmpi_optimization(cr);
629
630 int b_offset = branch_offset(L);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400631
632 switch (cond) {
633 case eq:
634 bc(b_offset, BT, encode_crbit(cr, CR_EQ), lk);
635 break;
636 case ne:
637 bc(b_offset, BF, encode_crbit(cr, CR_EQ), lk);
638 break;
639 case gt:
640 bc(b_offset, BT, encode_crbit(cr, CR_GT), lk);
641 break;
642 case le:
643 bc(b_offset, BF, encode_crbit(cr, CR_GT), lk);
644 break;
645 case lt:
646 bc(b_offset, BT, encode_crbit(cr, CR_LT), lk);
647 break;
648 case ge:
649 bc(b_offset, BF, encode_crbit(cr, CR_LT), lk);
650 break;
651 case unordered:
652 bc(b_offset, BT, encode_crbit(cr, CR_FU), lk);
653 break;
654 case ordered:
655 bc(b_offset, BF, encode_crbit(cr, CR_FU), lk);
656 break;
657 case overflow:
658 bc(b_offset, BT, encode_crbit(cr, CR_SO), lk);
659 break;
660 case nooverflow:
661 bc(b_offset, BF, encode_crbit(cr, CR_SO), lk);
662 break;
663 default:
664 UNIMPLEMENTED();
665 }
666 }
667
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000668 void bclr(Condition cond, CRegister cr = cr7, LKBit lk = LeaveLK) {
669 DCHECK(cond != al);
670 DCHECK(cr.code() >= 0 && cr.code() <= 7);
671
672 cr = cmpi_optimization(cr);
673
674 switch (cond) {
675 case eq:
676 bclr(BT, encode_crbit(cr, CR_EQ), lk);
677 break;
678 case ne:
679 bclr(BF, encode_crbit(cr, CR_EQ), lk);
680 break;
681 case gt:
682 bclr(BT, encode_crbit(cr, CR_GT), lk);
683 break;
684 case le:
685 bclr(BF, encode_crbit(cr, CR_GT), lk);
686 break;
687 case lt:
688 bclr(BT, encode_crbit(cr, CR_LT), lk);
689 break;
690 case ge:
691 bclr(BF, encode_crbit(cr, CR_LT), lk);
692 break;
693 case unordered:
694 bclr(BT, encode_crbit(cr, CR_FU), lk);
695 break;
696 case ordered:
697 bclr(BF, encode_crbit(cr, CR_FU), lk);
698 break;
699 case overflow:
700 bclr(BT, encode_crbit(cr, CR_SO), lk);
701 break;
702 case nooverflow:
703 bclr(BF, encode_crbit(cr, CR_SO), lk);
704 break;
705 default:
706 UNIMPLEMENTED();
707 }
708 }
709
710 void isel(Register rt, Register ra, Register rb, int cb);
711 void isel(Condition cond, Register rt, Register ra, Register rb,
712 CRegister cr = cr7) {
713 DCHECK(cond != al);
714 DCHECK(cr.code() >= 0 && cr.code() <= 7);
715
716 cr = cmpi_optimization(cr);
717
718 switch (cond) {
719 case eq:
720 isel(rt, ra, rb, encode_crbit(cr, CR_EQ));
721 break;
722 case ne:
723 isel(rt, rb, ra, encode_crbit(cr, CR_EQ));
724 break;
725 case gt:
726 isel(rt, ra, rb, encode_crbit(cr, CR_GT));
727 break;
728 case le:
729 isel(rt, rb, ra, encode_crbit(cr, CR_GT));
730 break;
731 case lt:
732 isel(rt, ra, rb, encode_crbit(cr, CR_LT));
733 break;
734 case ge:
735 isel(rt, rb, ra, encode_crbit(cr, CR_LT));
736 break;
737 case unordered:
738 isel(rt, ra, rb, encode_crbit(cr, CR_FU));
739 break;
740 case ordered:
741 isel(rt, rb, ra, encode_crbit(cr, CR_FU));
742 break;
743 case overflow:
744 isel(rt, ra, rb, encode_crbit(cr, CR_SO));
745 break;
746 case nooverflow:
747 isel(rt, rb, ra, encode_crbit(cr, CR_SO));
748 break;
749 default:
750 UNIMPLEMENTED();
751 }
752 }
753
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400754 void b(Condition cond, Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
755 if (cond == al) {
756 b(L, lk);
757 return;
758 }
759
760 if ((L->is_bound() && is_near(L, cond)) || !is_trampoline_emitted()) {
761 bc_short(cond, L, cr, lk);
762 return;
763 }
764
765 Label skip;
766 Condition neg_cond = NegateCondition(cond);
767 bc_short(neg_cond, &skip, cr);
768 b(L, lk);
769 bind(&skip);
770 }
771
772 void bne(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
773 b(ne, L, cr, lk);
774 }
775 void beq(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
776 b(eq, L, cr, lk);
777 }
778 void blt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
779 b(lt, L, cr, lk);
780 }
781 void bge(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
782 b(ge, L, cr, lk);
783 }
784 void ble(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
785 b(le, L, cr, lk);
786 }
787 void bgt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
788 b(gt, L, cr, lk);
789 }
790 void bunordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
791 b(unordered, L, cr, lk);
792 }
793 void bordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
794 b(ordered, L, cr, lk);
795 }
796 void boverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
797 b(overflow, L, cr, lk);
798 }
799 void bnooverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
800 b(nooverflow, L, cr, lk);
801 }
802
803 // Decrement CTR; branch if CTR != 0
804 void bdnz(Label* L, LKBit lk = LeaveLK) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000805 bc(branch_offset(L), DCBNZ, 0, lk);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400806 }
807
808 // Data-processing instructions
809
810 void sub(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
811 RCBit r = LeaveRC);
812
Ben Murdochda12d292016-06-02 14:46:10 +0100813 void subc(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
814 RCBit r = LeaveRC);
815 void sube(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
816 RCBit r = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400817
Ben Murdochda12d292016-06-02 14:46:10 +0100818 void subfic(Register dst, Register src, const Operand& imm);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400819
820 void add(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
821 RCBit r = LeaveRC);
822
823 void addc(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
824 RCBit r = LeaveRC);
Ben Murdochda12d292016-06-02 14:46:10 +0100825 void adde(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
826 RCBit r = LeaveRC);
827 void addze(Register dst, Register src1, OEBit o = LeaveOE, RCBit r = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400828
829 void mullw(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
830 RCBit r = LeaveRC);
831
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000832 void mulhw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
833 void mulhwu(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400834
835 void divw(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
836 RCBit r = LeaveRC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000837 void divwu(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
838 RCBit r = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400839
840 void addi(Register dst, Register src, const Operand& imm);
841 void addis(Register dst, Register src, const Operand& imm);
842 void addic(Register dst, Register src, const Operand& imm);
843
844 void and_(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
845 void andc(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
846 void andi(Register ra, Register rs, const Operand& imm);
847 void andis(Register ra, Register rs, const Operand& imm);
848 void nor(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
849 void notx(Register dst, Register src, RCBit r = LeaveRC);
850 void ori(Register dst, Register src, const Operand& imm);
851 void oris(Register dst, Register src, const Operand& imm);
852 void orx(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000853 void orc(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400854 void xori(Register dst, Register src, const Operand& imm);
855 void xoris(Register ra, Register rs, const Operand& imm);
856 void xor_(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
857 void cmpi(Register src1, const Operand& src2, CRegister cr = cr7);
858 void cmpli(Register src1, const Operand& src2, CRegister cr = cr7);
859 void cmpwi(Register src1, const Operand& src2, CRegister cr = cr7);
860 void cmplwi(Register src1, const Operand& src2, CRegister cr = cr7);
861 void li(Register dst, const Operand& src);
862 void lis(Register dst, const Operand& imm);
863 void mr(Register dst, Register src);
864
865 void lbz(Register dst, const MemOperand& src);
866 void lbzx(Register dst, const MemOperand& src);
867 void lbzux(Register dst, const MemOperand& src);
868 void lhz(Register dst, const MemOperand& src);
869 void lhzx(Register dst, const MemOperand& src);
870 void lhzux(Register dst, const MemOperand& src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000871 void lha(Register dst, const MemOperand& src);
872 void lhax(Register dst, const MemOperand& src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400873 void lwz(Register dst, const MemOperand& src);
874 void lwzu(Register dst, const MemOperand& src);
875 void lwzx(Register dst, const MemOperand& src);
876 void lwzux(Register dst, const MemOperand& src);
877 void lwa(Register dst, const MemOperand& src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000878 void lwax(Register dst, const MemOperand& src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400879 void stb(Register dst, const MemOperand& src);
880 void stbx(Register dst, const MemOperand& src);
881 void stbux(Register dst, const MemOperand& src);
882 void sth(Register dst, const MemOperand& src);
883 void sthx(Register dst, const MemOperand& src);
884 void sthux(Register dst, const MemOperand& src);
885 void stw(Register dst, const MemOperand& src);
886 void stwu(Register dst, const MemOperand& src);
887 void stwx(Register rs, const MemOperand& src);
888 void stwux(Register rs, const MemOperand& src);
889
890 void extsb(Register rs, Register ra, RCBit r = LeaveRC);
891 void extsh(Register rs, Register ra, RCBit r = LeaveRC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000892 void extsw(Register rs, Register ra, RCBit r = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400893
894 void neg(Register rt, Register ra, OEBit o = LeaveOE, RCBit c = LeaveRC);
895
896#if V8_TARGET_ARCH_PPC64
897 void ld(Register rd, const MemOperand& src);
898 void ldx(Register rd, const MemOperand& src);
899 void ldu(Register rd, const MemOperand& src);
900 void ldux(Register rd, const MemOperand& src);
901 void std(Register rs, const MemOperand& src);
902 void stdx(Register rs, const MemOperand& src);
903 void stdu(Register rs, const MemOperand& src);
904 void stdux(Register rs, const MemOperand& src);
905 void rldic(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
906 void rldicl(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
907 void rldcl(Register ra, Register rs, Register rb, int mb, RCBit r = LeaveRC);
908 void rldicr(Register dst, Register src, int sh, int me, RCBit r = LeaveRC);
909 void rldimi(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
910 void sldi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
911 void srdi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
912 void clrrdi(Register dst, Register src, const Operand& val,
913 RCBit rc = LeaveRC);
914 void clrldi(Register dst, Register src, const Operand& val,
915 RCBit rc = LeaveRC);
916 void sradi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
917 void srd(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
918 void sld(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
919 void srad(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
920 void rotld(Register ra, Register rs, Register rb, RCBit r = LeaveRC);
921 void rotldi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
922 void rotrdi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
923 void cntlzd_(Register dst, Register src, RCBit rc = LeaveRC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000924 void popcntd(Register dst, Register src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400925 void mulld(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
926 RCBit r = LeaveRC);
927 void divd(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
928 RCBit r = LeaveRC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000929 void divdu(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
930 RCBit r = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400931#endif
932
933 void rlwinm(Register ra, Register rs, int sh, int mb, int me,
934 RCBit rc = LeaveRC);
935 void rlwimi(Register ra, Register rs, int sh, int mb, int me,
936 RCBit rc = LeaveRC);
937 void rlwnm(Register ra, Register rs, Register rb, int mb, int me,
938 RCBit rc = LeaveRC);
939 void slwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
940 void srwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
941 void clrrwi(Register dst, Register src, const Operand& val,
942 RCBit rc = LeaveRC);
943 void clrlwi(Register dst, Register src, const Operand& val,
944 RCBit rc = LeaveRC);
945 void srawi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
946 void srw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
947 void slw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
948 void sraw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
949 void rotlw(Register ra, Register rs, Register rb, RCBit r = LeaveRC);
950 void rotlwi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
951 void rotrwi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
952
953 void cntlzw_(Register dst, Register src, RCBit rc = LeaveRC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000954 void popcntw(Register dst, Register src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400955
956 void subi(Register dst, Register src1, const Operand& src2);
957
958 void cmp(Register src1, Register src2, CRegister cr = cr7);
959 void cmpl(Register src1, Register src2, CRegister cr = cr7);
960 void cmpw(Register src1, Register src2, CRegister cr = cr7);
961 void cmplw(Register src1, Register src2, CRegister cr = cr7);
962
963 void mov(Register dst, const Operand& src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000964 void bitwise_mov(Register dst, intptr_t value);
965 void bitwise_mov32(Register dst, int32_t value);
966 void bitwise_add32(Register dst, Register src, int32_t value);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400967
968 // Load the position of the label relative to the generated code object
969 // pointer in a register.
970 void mov_label_offset(Register dst, Label* label);
971
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000972 // dst = base + label position + delta
973 void add_label_offset(Register dst, Register base, Label* label,
974 int delta = 0);
975
976 // Load the address of the label in a register and associate with an
977 // internal reference relocation.
978 void mov_label_addr(Register dst, Label* label);
979
980 // Emit the address of the label (i.e. a jump table entry) and associate with
981 // an internal reference relocation.
982 void emit_label_addr(Label* label);
983
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400984 // Multiply instructions
985 void mul(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
986 RCBit r = LeaveRC);
987
988 // Miscellaneous arithmetic instructions
989
990 // Special register access
991 void crxor(int bt, int ba, int bb);
992 void crclr(int bt) { crxor(bt, bt, bt); }
993 void creqv(int bt, int ba, int bb);
994 void crset(int bt) { creqv(bt, bt, bt); }
995 void mflr(Register dst);
996 void mtlr(Register src);
997 void mtctr(Register src);
998 void mtxer(Register src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000999 void mcrfs(CRegister cr, FPSCRBit bit);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001000 void mfcr(Register dst);
1001#if V8_TARGET_ARCH_PPC64
1002 void mffprd(Register dst, DoubleRegister src);
1003 void mffprwz(Register dst, DoubleRegister src);
1004 void mtfprd(DoubleRegister dst, Register src);
1005 void mtfprwz(DoubleRegister dst, Register src);
1006 void mtfprwa(DoubleRegister dst, Register src);
1007#endif
1008
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001009 void function_descriptor();
1010
1011 // Exception-generating instructions and debugging support
1012 void stop(const char* msg, Condition cond = al,
1013 int32_t code = kDefaultStopCode, CRegister cr = cr7);
1014
1015 void bkpt(uint32_t imm16); // v5 and above
1016
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001017 void dcbf(Register ra, Register rb);
1018 void sync();
1019 void lwsync();
1020 void icbi(Register ra, Register rb);
1021 void isync();
1022
1023 // Support for floating point
1024 void lfd(const DoubleRegister frt, const MemOperand& src);
1025 void lfdu(const DoubleRegister frt, const MemOperand& src);
1026 void lfdx(const DoubleRegister frt, const MemOperand& src);
1027 void lfdux(const DoubleRegister frt, const MemOperand& src);
1028 void lfs(const DoubleRegister frt, const MemOperand& src);
1029 void lfsu(const DoubleRegister frt, const MemOperand& src);
1030 void lfsx(const DoubleRegister frt, const MemOperand& src);
1031 void lfsux(const DoubleRegister frt, const MemOperand& src);
1032 void stfd(const DoubleRegister frs, const MemOperand& src);
1033 void stfdu(const DoubleRegister frs, const MemOperand& src);
1034 void stfdx(const DoubleRegister frs, const MemOperand& src);
1035 void stfdux(const DoubleRegister frs, const MemOperand& src);
1036 void stfs(const DoubleRegister frs, const MemOperand& src);
1037 void stfsu(const DoubleRegister frs, const MemOperand& src);
1038 void stfsx(const DoubleRegister frs, const MemOperand& src);
1039 void stfsux(const DoubleRegister frs, const MemOperand& src);
1040
1041 void fadd(const DoubleRegister frt, const DoubleRegister fra,
1042 const DoubleRegister frb, RCBit rc = LeaveRC);
1043 void fsub(const DoubleRegister frt, const DoubleRegister fra,
1044 const DoubleRegister frb, RCBit rc = LeaveRC);
1045 void fdiv(const DoubleRegister frt, const DoubleRegister fra,
1046 const DoubleRegister frb, RCBit rc = LeaveRC);
1047 void fmul(const DoubleRegister frt, const DoubleRegister fra,
1048 const DoubleRegister frc, RCBit rc = LeaveRC);
1049 void fcmpu(const DoubleRegister fra, const DoubleRegister frb,
1050 CRegister cr = cr7);
1051 void fmr(const DoubleRegister frt, const DoubleRegister frb,
1052 RCBit rc = LeaveRC);
1053 void fctiwz(const DoubleRegister frt, const DoubleRegister frb);
1054 void fctiw(const DoubleRegister frt, const DoubleRegister frb);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001055 void frin(const DoubleRegister frt, const DoubleRegister frb,
1056 RCBit rc = LeaveRC);
1057 void friz(const DoubleRegister frt, const DoubleRegister frb,
1058 RCBit rc = LeaveRC);
1059 void frip(const DoubleRegister frt, const DoubleRegister frb,
1060 RCBit rc = LeaveRC);
1061 void frim(const DoubleRegister frt, const DoubleRegister frb,
1062 RCBit rc = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001063 void frsp(const DoubleRegister frt, const DoubleRegister frb,
1064 RCBit rc = LeaveRC);
1065 void fcfid(const DoubleRegister frt, const DoubleRegister frb,
1066 RCBit rc = LeaveRC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001067 void fcfidu(const DoubleRegister frt, const DoubleRegister frb,
1068 RCBit rc = LeaveRC);
1069 void fcfidus(const DoubleRegister frt, const DoubleRegister frb,
1070 RCBit rc = LeaveRC);
1071 void fcfids(const DoubleRegister frt, const DoubleRegister frb,
1072 RCBit rc = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001073 void fctid(const DoubleRegister frt, const DoubleRegister frb,
1074 RCBit rc = LeaveRC);
1075 void fctidz(const DoubleRegister frt, const DoubleRegister frb,
1076 RCBit rc = LeaveRC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001077 void fctidu(const DoubleRegister frt, const DoubleRegister frb,
1078 RCBit rc = LeaveRC);
1079 void fctiduz(const DoubleRegister frt, const DoubleRegister frb,
1080 RCBit rc = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001081 void fsel(const DoubleRegister frt, const DoubleRegister fra,
1082 const DoubleRegister frc, const DoubleRegister frb,
1083 RCBit rc = LeaveRC);
1084 void fneg(const DoubleRegister frt, const DoubleRegister frb,
1085 RCBit rc = LeaveRC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001086 void mtfsb0(FPSCRBit bit, RCBit rc = LeaveRC);
1087 void mtfsb1(FPSCRBit bit, RCBit rc = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001088 void mtfsfi(int bf, int immediate, RCBit rc = LeaveRC);
1089 void mffs(const DoubleRegister frt, RCBit rc = LeaveRC);
1090 void mtfsf(const DoubleRegister frb, bool L = 1, int FLM = 0, bool W = 0,
1091 RCBit rc = LeaveRC);
1092 void fsqrt(const DoubleRegister frt, const DoubleRegister frb,
1093 RCBit rc = LeaveRC);
1094 void fabs(const DoubleRegister frt, const DoubleRegister frb,
1095 RCBit rc = LeaveRC);
1096 void fmadd(const DoubleRegister frt, const DoubleRegister fra,
1097 const DoubleRegister frc, const DoubleRegister frb,
1098 RCBit rc = LeaveRC);
1099 void fmsub(const DoubleRegister frt, const DoubleRegister fra,
1100 const DoubleRegister frc, const DoubleRegister frb,
1101 RCBit rc = LeaveRC);
1102
1103 // Pseudo instructions
1104
1105 // Different nop operations are used by the code generator to detect certain
1106 // states of the generated code.
1107 enum NopMarkerTypes {
1108 NON_MARKING_NOP = 0,
1109 GROUP_ENDING_NOP,
1110 DEBUG_BREAK_NOP,
1111 // IC markers.
1112 PROPERTY_ACCESS_INLINED,
1113 PROPERTY_ACCESS_INLINED_CONTEXT,
1114 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1115 // Helper values.
1116 LAST_CODE_MARKER,
1117 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1118 };
1119
1120 void nop(int type = 0); // 0 is the default non-marking type.
1121
1122 void push(Register src) {
1123#if V8_TARGET_ARCH_PPC64
1124 stdu(src, MemOperand(sp, -kPointerSize));
1125#else
1126 stwu(src, MemOperand(sp, -kPointerSize));
1127#endif
1128 }
1129
1130 void pop(Register dst) {
1131#if V8_TARGET_ARCH_PPC64
1132 ld(dst, MemOperand(sp));
1133#else
1134 lwz(dst, MemOperand(sp));
1135#endif
1136 addi(sp, sp, Operand(kPointerSize));
1137 }
1138
1139 void pop() { addi(sp, sp, Operand(kPointerSize)); }
1140
1141 // Jump unconditionally to given label.
1142 void jmp(Label* L) { b(L); }
1143
1144 // Check the code size generated from label to here.
1145 int SizeOfCodeGeneratedSince(Label* label) {
1146 return pc_offset() - label->pos();
1147 }
1148
1149 // Check the number of instructions generated from label to here.
1150 int InstructionsGeneratedSince(Label* label) {
1151 return SizeOfCodeGeneratedSince(label) / kInstrSize;
1152 }
1153
1154 // Class for scoping postponing the trampoline pool generation.
1155 class BlockTrampolinePoolScope {
1156 public:
1157 explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) {
1158 assem_->StartBlockTrampolinePool();
1159 }
1160 ~BlockTrampolinePoolScope() { assem_->EndBlockTrampolinePool(); }
1161
1162 private:
1163 Assembler* assem_;
1164
1165 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope);
1166 };
1167
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001168 // Class for scoping disabling constant pool entry merging
1169 class BlockConstantPoolEntrySharingScope {
1170 public:
1171 explicit BlockConstantPoolEntrySharingScope(Assembler* assem)
1172 : assem_(assem) {
1173 assem_->StartBlockConstantPoolEntrySharing();
1174 }
1175 ~BlockConstantPoolEntrySharingScope() {
1176 assem_->EndBlockConstantPoolEntrySharing();
1177 }
1178
1179 private:
1180 Assembler* assem_;
1181
1182 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstantPoolEntrySharingScope);
1183 };
1184
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001185 // Debugging
1186
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001187 // Mark generator continuation.
1188 void RecordGeneratorContinuation();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001189
1190 // Mark address of a debug break slot.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001191 void RecordDebugBreakSlot(RelocInfo::Mode mode);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001192
1193 // Record the AST id of the CallIC being compiled, so that it can be placed
1194 // in the relocation information.
1195 void SetRecordedAstId(TypeFeedbackId ast_id) {
1196 // Causes compiler to fail
1197 // DCHECK(recorded_ast_id_.IsNone());
1198 recorded_ast_id_ = ast_id;
1199 }
1200
1201 TypeFeedbackId RecordedAstId() {
1202 // Causes compiler to fail
1203 // DCHECK(!recorded_ast_id_.IsNone());
1204 return recorded_ast_id_;
1205 }
1206
1207 void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
1208
1209 // Record a comment relocation entry that can be used by a disassembler.
1210 // Use --code-comments to enable.
1211 void RecordComment(const char* msg);
1212
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001213 // Record a deoptimization reason that can be used by a log or cpu profiler.
1214 // Use --trace-deopt to enable.
Ben Murdochc5610432016-08-08 18:44:38 +01001215 void RecordDeoptReason(const int reason, int raw_position, int id);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001216
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001217 // Writes a single byte or word of data in the code stream. Used
1218 // for inline tables, e.g., jump-tables.
1219 void db(uint8_t data);
1220 void dd(uint32_t data);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001221 void dq(uint64_t data);
1222 void dp(uintptr_t data);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001223
Ben Murdochda12d292016-06-02 14:46:10 +01001224 AssemblerPositionsRecorder* positions_recorder() {
1225 return &positions_recorder_;
1226 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001227
1228 // Read/patch instructions
1229 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1230 void instr_at_put(int pos, Instr instr) {
1231 *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1232 }
1233 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1234 static void instr_at_put(byte* pc, Instr instr) {
1235 *reinterpret_cast<Instr*>(pc) = instr;
1236 }
1237 static Condition GetCondition(Instr instr);
1238
1239 static bool IsLis(Instr instr);
1240 static bool IsLi(Instr instr);
1241 static bool IsAddic(Instr instr);
1242 static bool IsOri(Instr instr);
1243
1244 static bool IsBranch(Instr instr);
1245 static Register GetRA(Instr instr);
1246 static Register GetRB(Instr instr);
1247#if V8_TARGET_ARCH_PPC64
1248 static bool Is64BitLoadIntoR12(Instr instr1, Instr instr2, Instr instr3,
1249 Instr instr4, Instr instr5);
1250#else
1251 static bool Is32BitLoadIntoR12(Instr instr1, Instr instr2);
1252#endif
1253
1254 static bool IsCmpRegister(Instr instr);
1255 static bool IsCmpImmediate(Instr instr);
1256 static bool IsRlwinm(Instr instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001257 static bool IsAndi(Instr instr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001258#if V8_TARGET_ARCH_PPC64
1259 static bool IsRldicl(Instr instr);
1260#endif
1261 static bool IsCrSet(Instr instr);
1262 static Register GetCmpImmediateRegister(Instr instr);
1263 static int GetCmpImmediateRawImmediate(Instr instr);
1264 static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
1265
1266 // Postpone the generation of the trampoline pool for the specified number of
1267 // instructions.
1268 void BlockTrampolinePoolFor(int instructions);
1269 void CheckTrampolinePool();
1270
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001271 // For mov. Return the number of actual instructions required to
1272 // load the operand into a register. This can be anywhere from
1273 // one (constant pool small section) to five instructions (full
1274 // 64-bit sequence).
1275 //
1276 // The value returned is only valid as long as no entries are added to the
1277 // constant pool between this call and the actual instruction being emitted.
1278 int instructions_required_for_mov(Register dst, const Operand& src) const;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001279
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001280 // Decide between using the constant pool vs. a mov immediate sequence.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001281 bool use_constant_pool_for_mov(Register dst, const Operand& src,
1282 bool canOptimize) const;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001283
1284 // The code currently calls CheckBuffer() too often. This has the side
1285 // effect of randomly growing the buffer in the middle of multi-instruction
1286 // sequences.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001287 //
1288 // This function allows outside callers to check and grow the buffer
1289 void EnsureSpaceFor(int space_needed);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001290
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001291 int EmitConstantPool() { return constant_pool_builder_.Emit(this); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001292
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001293 bool ConstantPoolAccessIsInOverflow() const {
1294 return constant_pool_builder_.NextAccess(ConstantPoolEntry::INTPTR) ==
1295 ConstantPoolEntry::OVERFLOWED;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001296 }
1297
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001298 Label* ConstantPoolPosition() {
1299 return constant_pool_builder_.EmittedPosition();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001300 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001301
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001302 void EmitRelocations();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001303
1304 protected:
1305 // Relocation for a type-recording IC has the AST id added to it. This
1306 // member variable is a way to pass the information from the call site to
1307 // the relocation info.
1308 TypeFeedbackId recorded_ast_id_;
1309
1310 int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1311
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001312 // Decode instruction(s) at pos and return backchain to previous
1313 // label reference or kEndOfChain.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001314 int target_at(int pos);
1315
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001316 // Patch instruction(s) at pos to target target_pos (e.g. branch)
1317 void target_at_put(int pos, int target_pos, bool* is_branch = nullptr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001318
1319 // Record reloc info for current pc_
1320 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001321 ConstantPoolEntry::Access ConstantPoolAddEntry(RelocInfo::Mode rmode,
1322 intptr_t value) {
1323 bool sharing_ok = RelocInfo::IsNone(rmode) ||
1324 !(serializer_enabled() || rmode < RelocInfo::CELL ||
1325 is_constant_pool_entry_sharing_blocked());
1326 return constant_pool_builder_.AddEntry(pc_offset(), value, sharing_ok);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001327 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001328 ConstantPoolEntry::Access ConstantPoolAddEntry(double value) {
1329 return constant_pool_builder_.AddEntry(pc_offset(), value);
1330 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001331
1332 // Block the emission of the trampoline pool before pc_offset.
1333 void BlockTrampolinePoolBefore(int pc_offset) {
1334 if (no_trampoline_pool_before_ < pc_offset)
1335 no_trampoline_pool_before_ = pc_offset;
1336 }
1337
1338 void StartBlockTrampolinePool() { trampoline_pool_blocked_nesting_++; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001339 void EndBlockTrampolinePool() {
1340 int count = --trampoline_pool_blocked_nesting_;
1341 if (count == 0) CheckTrampolinePoolQuick();
1342 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001343 bool is_trampoline_pool_blocked() const {
1344 return trampoline_pool_blocked_nesting_ > 0;
1345 }
1346
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001347 void StartBlockConstantPoolEntrySharing() {
1348 constant_pool_entry_sharing_blocked_nesting_++;
1349 }
1350 void EndBlockConstantPoolEntrySharing() {
1351 constant_pool_entry_sharing_blocked_nesting_--;
1352 }
1353 bool is_constant_pool_entry_sharing_blocked() const {
1354 return constant_pool_entry_sharing_blocked_nesting_ > 0;
1355 }
1356
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001357 bool has_exception() const { return internal_trampoline_exception_; }
1358
1359 bool is_trampoline_emitted() const { return trampoline_emitted_; }
1360
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001361 private:
1362 // Code generation
1363 // The relocation writer's position is at least kGap bytes below the end of
1364 // the generated instructions. This is so that multi-instruction sequences do
1365 // not have to check for overflow. The same is true for writes of large
1366 // relocation info entries.
1367 static const int kGap = 32;
1368
1369 // Repeated checking whether the trampoline pool should be emitted is rather
1370 // expensive. By default we only check again once a number of instructions
1371 // has been generated.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001372 int next_trampoline_check_; // pc offset of next buffer check.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001373
1374 // Emission of the trampoline pool may be blocked in some code sequences.
1375 int trampoline_pool_blocked_nesting_; // Block emission if this is not zero.
1376 int no_trampoline_pool_before_; // Block emission before this pc offset.
1377
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001378 // Do not share constant pool entries.
1379 int constant_pool_entry_sharing_blocked_nesting_;
1380
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001381 // Relocation info generation
1382 // Each relocation is encoded as a variable size value
1383 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1384 RelocInfoWriter reloc_info_writer;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001385 std::vector<DeferredRelocInfo> relocations_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001386
1387 // The bound position, before this we cannot do instruction elimination.
1388 int last_bound_pos_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001389 // Optimizable cmpi information.
1390 int optimizable_cmpi_pos_;
1391 CRegister cmpi_cr_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001392
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001393 ConstantPoolBuilder constant_pool_builder_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001394
1395 // Code emission
1396 inline void CheckBuffer();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001397 void GrowBuffer(int needed = 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001398 inline void emit(Instr x);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001399 inline void TrackBranch();
1400 inline void UntrackBranch();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001401 inline void CheckTrampolinePoolQuick();
1402
1403 // Instruction generation
1404 void a_form(Instr instr, DoubleRegister frt, DoubleRegister fra,
1405 DoubleRegister frb, RCBit r);
1406 void d_form(Instr instr, Register rt, Register ra, const intptr_t val,
1407 bool signed_disp);
1408 void x_form(Instr instr, Register ra, Register rs, Register rb, RCBit r);
1409 void xo_form(Instr instr, Register rt, Register ra, Register rb, OEBit o,
1410 RCBit r);
1411 void md_form(Instr instr, Register ra, Register rs, int shift, int maskbit,
1412 RCBit r);
1413 void mds_form(Instr instr, Register ra, Register rs, Register rb, int maskbit,
1414 RCBit r);
1415
1416 // Labels
1417 void print(Label* L);
1418 int max_reach_from(int pos);
1419 void bind_to(Label* L, int pos);
1420 void next(Label* L);
1421
1422 class Trampoline {
1423 public:
1424 Trampoline() {
1425 next_slot_ = 0;
1426 free_slot_count_ = 0;
1427 }
1428 Trampoline(int start, int slot_count) {
1429 next_slot_ = start;
1430 free_slot_count_ = slot_count;
1431 }
1432 int take_slot() {
1433 int trampoline_slot = kInvalidSlotPos;
1434 if (free_slot_count_ <= 0) {
1435 // We have run out of space on trampolines.
1436 // Make sure we fail in debug mode, so we become aware of each case
1437 // when this happens.
1438 DCHECK(0);
1439 // Internal exception will be caught.
1440 } else {
1441 trampoline_slot = next_slot_;
1442 free_slot_count_--;
1443 next_slot_ += kTrampolineSlotsSize;
1444 }
1445 return trampoline_slot;
1446 }
1447
1448 private:
1449 int next_slot_;
1450 int free_slot_count_;
1451 };
1452
1453 int32_t get_trampoline_entry();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001454 int tracked_branch_count_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001455 // If trampoline is emitted, generated code is becoming large. As
1456 // this is already a slow case which can possibly break our code
1457 // generation for the extreme case, we use this information to
1458 // trigger different mode of branch instruction generation, where we
1459 // no longer use a single branch instruction.
1460 bool trampoline_emitted_;
1461 static const int kTrampolineSlotsSize = kInstrSize;
1462 static const int kMaxCondBranchReach = (1 << (16 - 1)) - 1;
1463 static const int kMaxBlockTrampolineSectionSize = 64 * kInstrSize;
1464 static const int kInvalidSlotPos = -1;
1465
1466 Trampoline trampoline_;
1467 bool internal_trampoline_exception_;
1468
1469 friend class RegExpMacroAssemblerPPC;
1470 friend class RelocInfo;
1471 friend class CodePatcher;
1472 friend class BlockTrampolinePoolScope;
Ben Murdochda12d292016-06-02 14:46:10 +01001473 AssemblerPositionsRecorder positions_recorder_;
1474 friend class AssemblerPositionsRecorder;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001475 friend class EnsureSpace;
1476};
1477
1478
1479class EnsureSpace BASE_EMBEDDED {
1480 public:
1481 explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); }
1482};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001483} // namespace internal
1484} // namespace v8
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001485
1486#endif // V8_PPC_ASSEMBLER_PPC_H_