blob: a9cf730af4eb04e177b8e47d56c7f074f00f12eb [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 }
169 const char* ToString();
170 bool IsAllocatable() const;
171 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
172 bool is(Register reg) const { return reg_code == reg.reg_code; }
173 int code() const {
174 DCHECK(is_valid());
175 return reg_code;
176 }
177 int bit() const {
178 DCHECK(is_valid());
179 return 1 << reg_code;
180 }
181 void set_code(int code) {
182 reg_code = code;
183 DCHECK(is_valid());
184 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400185
186#if V8_TARGET_LITTLE_ENDIAN
187 static const int kMantissaOffset = 0;
188 static const int kExponentOffset = 4;
189#else
190 static const int kMantissaOffset = 4;
191 static const int kExponentOffset = 0;
192#endif
193
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400194 // Unfortunately we can't make this private in a struct.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195 int reg_code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400196};
197
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198#define DECLARE_REGISTER(R) const Register R = {Register::kCode_##R};
199GENERAL_REGISTERS(DECLARE_REGISTER)
200#undef DECLARE_REGISTER
201const Register no_reg = {Register::kCode_no_reg};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400202
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203// Aliases
204const Register kLithiumScratch = r11; // lithium scratch.
205const Register kConstantPoolRegister = r28; // Constant pool.
206const Register kRootRegister = r29; // Roots array pointer.
207const Register cp = r30; // JavaScript context pointer.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400208
209// 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 const char* ToString();
223 bool IsAllocatable() const;
224 bool is_valid() const { return 0 <= reg_code && reg_code < kNumRegisters; }
225 bool is(DoubleRegister reg) const { return reg_code == reg.reg_code; }
226 int code() const {
227 DCHECK(is_valid());
228 return reg_code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400229 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000230 int bit() const {
231 DCHECK(is_valid());
232 return 1 << reg_code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400233 }
234
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400235 static DoubleRegister from_code(int code) {
236 DoubleRegister r = {code};
237 return r;
238 }
239
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 int reg_code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400241};
242
Ben Murdochc5610432016-08-08 18:44:38 +0100243typedef DoubleRegister FloatRegister;
244
245// TODO(ppc) Define SIMD registers.
246typedef DoubleRegister Simd128Register;
247
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000248#define DECLARE_REGISTER(R) \
249 const DoubleRegister R = {DoubleRegister::kCode_##R};
250DOUBLE_REGISTERS(DECLARE_REGISTER)
251#undef DECLARE_REGISTER
252const Register no_dreg = {Register::kCode_no_reg};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400253
254// Aliases for double registers. Defined using #define instead of
255// "static const DoubleRegister&" because Clang complains otherwise when a
256// compilation unit that includes this header doesn't use the variables.
257#define kFirstCalleeSavedDoubleReg d14
258#define kLastCalleeSavedDoubleReg d31
259#define kDoubleRegZero d14
260#define kScratchDoubleReg d13
261
262Register ToRegister(int num);
263
264// Coprocessor register
265struct CRegister {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100266 bool is_valid() const { return 0 <= reg_code && reg_code < 8; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000267 bool is(CRegister creg) const { return reg_code == creg.reg_code; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400268 int code() const {
269 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000270 return reg_code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400271 }
272 int bit() const {
273 DCHECK(is_valid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000274 return 1 << reg_code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400275 }
276
277 // Unfortunately we can't make this private in a struct.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000278 int reg_code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400279};
280
281
282const CRegister no_creg = {-1};
283
284const CRegister cr0 = {0};
285const CRegister cr1 = {1};
286const CRegister cr2 = {2};
287const CRegister cr3 = {3};
288const CRegister cr4 = {4};
289const CRegister cr5 = {5};
290const CRegister cr6 = {6};
291const CRegister cr7 = {7};
Ben Murdoch097c5b22016-05-18 11:27:45 +0100292
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400293// -----------------------------------------------------------------------------
294// Machine instruction Operands
295
296#if V8_TARGET_ARCH_PPC64
297const RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE64;
298#else
299const RelocInfo::Mode kRelocInfo_NONEPTR = RelocInfo::NONE32;
300#endif
301
302// Class Operand represents a shifter operand in data processing instructions
303class Operand BASE_EMBEDDED {
304 public:
305 // immediate
306 INLINE(explicit Operand(intptr_t immediate,
307 RelocInfo::Mode rmode = kRelocInfo_NONEPTR));
308 INLINE(static Operand Zero()) { return Operand(static_cast<intptr_t>(0)); }
309 INLINE(explicit Operand(const ExternalReference& f));
310 explicit Operand(Handle<Object> handle);
311 INLINE(explicit Operand(Smi* value));
312
313 // rm
314 INLINE(explicit Operand(Register rm));
315
316 // Return true if this is a register operand.
317 INLINE(bool is_reg() const);
318
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400319 bool must_output_reloc_info(const Assembler* assembler) const;
320
321 inline intptr_t immediate() const {
322 DCHECK(!rm_.is_valid());
323 return imm_;
324 }
325
326 Register rm() const { return rm_; }
327
328 private:
329 Register rm_;
330 intptr_t imm_; // valid if rm_ == no_reg
331 RelocInfo::Mode rmode_;
332
333 friend class Assembler;
334 friend class MacroAssembler;
335};
336
337
338// Class MemOperand represents a memory operand in load and store instructions
339// On PowerPC we have base register + 16bit signed value
340// Alternatively we can have a 16bit signed value immediate
341class MemOperand BASE_EMBEDDED {
342 public:
343 explicit MemOperand(Register rn, int32_t offset = 0);
344
345 explicit MemOperand(Register ra, Register rb);
346
347 int32_t offset() const {
348 DCHECK(rb_.is(no_reg));
349 return offset_;
350 }
351
352 // PowerPC - base register
353 Register ra() const {
354 DCHECK(!ra_.is(no_reg));
355 return ra_;
356 }
357
358 Register rb() const {
359 DCHECK(offset_ == 0 && !rb_.is(no_reg));
360 return rb_;
361 }
362
363 private:
364 Register ra_; // base
365 int32_t offset_; // offset
366 Register rb_; // index
367
368 friend class Assembler;
369};
370
371
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000372class DeferredRelocInfo {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400373 public:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000374 DeferredRelocInfo() {}
375 DeferredRelocInfo(int position, RelocInfo::Mode rmode, intptr_t data)
376 : position_(position), rmode_(rmode), data_(data) {}
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400377
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000378 int position() const { return position_; }
379 RelocInfo::Mode rmode() const { return rmode_; }
380 intptr_t data() const { return data_; }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400381
382 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000383 int position_;
384 RelocInfo::Mode rmode_;
385 intptr_t data_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400386};
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400387
388
389class Assembler : public AssemblerBase {
390 public:
391 // Create an assembler. Instructions and relocation information are emitted
392 // into a buffer, with the instructions starting from the beginning and the
393 // relocation information starting from the end of the buffer. See CodeDesc
394 // for a detailed comment on the layout (globals.h).
395 //
396 // If the provided buffer is NULL, the assembler allocates and grows its own
397 // buffer, and buffer_size determines the initial buffer size. The buffer is
398 // owned by the assembler and deallocated upon destruction of the assembler.
399 //
400 // If the provided buffer is not NULL, the assembler uses the provided buffer
401 // for code generation and assumes its size to be buffer_size. If the buffer
402 // is too small, a fatal error occurs. No deallocation of the buffer is done
403 // upon destruction of the assembler.
404 Assembler(Isolate* isolate, void* buffer, int buffer_size);
405 virtual ~Assembler() {}
406
407 // GetCode emits any pending (non-emitted) code and fills the descriptor
408 // desc. GetCode() is idempotent; it returns the same result if no other
409 // Assembler functions are invoked in between GetCode() calls.
410 void GetCode(CodeDesc* desc);
411
412 // Label operations & relative jumps (PPUM Appendix D)
413 //
414 // Takes a branch opcode (cc) and a label (L) and generates
415 // either a backward branch or a forward branch and links it
416 // to the label fixup chain. Usage:
417 //
418 // Label L; // unbound label
419 // j(cc, &L); // forward branch to unbound label
420 // bind(&L); // bind label to the current pc
421 // j(cc, &L); // backward branch to bound label
422 // bind(&L); // illegal: a label may be bound only once
423 //
424 // Note: The same Label can be used for forward and backward branches
425 // but it may be bound only once.
426
427 void bind(Label* L); // binds an unbound label L to the current code position
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000428
429 // Links a label at the current pc_offset(). If already bound, returns the
430 // bound position. If already linked, returns the position of the prior link.
431 // Otherwise, returns the current pc_offset().
432 int link(Label* L);
433
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400434 // Determines if Label is bound and near enough so that a single
435 // branch instruction can be used to reach it.
436 bool is_near(Label* L, Condition cond);
437
438 // Returns the branch offset to the given label from the current code position
439 // Links the label to the current position if it is still unbound
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000440 int branch_offset(Label* L) {
441 if (L->is_unused() && !trampoline_emitted_) {
442 TrackBranch();
443 }
444 return link(L) - pc_offset();
445 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400446
447 // Puts a labels target address at the given position.
448 // The high 8 bits are set to zero.
449 void label_at_put(Label* L, int at_offset);
450
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000451 INLINE(static bool IsConstantPoolLoadStart(
452 Address pc, ConstantPoolEntry::Access* access = nullptr));
453 INLINE(static bool IsConstantPoolLoadEnd(
454 Address pc, ConstantPoolEntry::Access* access = nullptr));
455 INLINE(static int GetConstantPoolOffset(Address pc,
456 ConstantPoolEntry::Access access,
457 ConstantPoolEntry::Type type));
458 INLINE(void PatchConstantPoolAccessInstruction(
459 int pc_offset, int offset, ConstantPoolEntry::Access access,
460 ConstantPoolEntry::Type type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400461
462 // Return the address in the constant pool of the code target address used by
463 // the branch/call instruction at pc, or the object in a mov.
464 INLINE(static Address target_constant_pool_address_at(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000465 Address pc, Address constant_pool, ConstantPoolEntry::Access access,
466 ConstantPoolEntry::Type type));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400467
468 // Read/Modify the code target address in the branch/call instruction at pc.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000469 INLINE(static Address target_address_at(Address pc, Address constant_pool));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400470 INLINE(static void set_target_address_at(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000471 Isolate* isolate, Address pc, Address constant_pool, Address target,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400472 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
473 INLINE(static Address target_address_at(Address pc, Code* code)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000474 Address constant_pool = code ? code->constant_pool() : NULL;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400475 return target_address_at(pc, constant_pool);
476 }
477 INLINE(static void set_target_address_at(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000478 Isolate* isolate, Address pc, Code* code, Address target,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400479 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000480 Address constant_pool = code ? code->constant_pool() : NULL;
481 set_target_address_at(isolate, pc, constant_pool, target,
482 icache_flush_mode);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400483 }
484
485 // Return the code target address at a call site from the return address
486 // of that call in the instruction stream.
487 inline static Address target_address_from_return_address(Address pc);
488
489 // Given the address of the beginning of a call, return the address
490 // in the instruction stream that the call will return to.
491 INLINE(static Address return_address_from_call_start(Address pc));
492
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400493 // This sets the branch destination.
494 // This is for calls and branches within generated code.
495 inline static void deserialization_set_special_target_at(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000496 Isolate* isolate, Address instruction_payload, Code* code,
497 Address target);
498
499 // This sets the internal reference at the pc.
500 inline static void deserialization_set_target_internal_reference_at(
501 Isolate* isolate, Address pc, Address target,
502 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400503
504 // Size of an instruction.
505 static const int kInstrSize = sizeof(Instr);
506
507 // Here we are patching the address in the LUI/ORI instruction pair.
508 // These values are used in the serialization process and must be zero for
509 // PPC platform, as Code, Embedded Object or External-reference pointers
510 // are split across two consecutive instructions and don't exist separately
511 // in the code, so the serializer should not step forwards in memory after
512 // a target is resolved and written.
513 static const int kSpecialTargetSize = 0;
514
515// Number of instructions to load an address via a mov sequence.
516#if V8_TARGET_ARCH_PPC64
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000517 static const int kMovInstructionsConstantPool = 1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400518 static const int kMovInstructionsNoConstantPool = 5;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000519#if defined(V8_PPC_TAGGING_OPT)
520 static const int kTaggedLoadInstructions = 1;
521#else
522 static const int kTaggedLoadInstructions = 2;
523#endif
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400524#else
525 static const int kMovInstructionsConstantPool = 1;
526 static const int kMovInstructionsNoConstantPool = 2;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000527 static const int kTaggedLoadInstructions = 1;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400528#endif
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000529 static const int kMovInstructions = FLAG_enable_embedded_constant_pool
530 ? kMovInstructionsConstantPool
531 : kMovInstructionsNoConstantPool;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400532
533 // Distance between the instruction referring to the address of the call
534 // target and the return address.
535
536 // Call sequence is a FIXED_SEQUENCE:
537 // mov r8, @ call address
538 // mtlr r8
539 // blrl
540 // @ return address
541 static const int kCallTargetAddressOffset =
542 (kMovInstructions + 2) * kInstrSize;
543
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400544 // Distance between start of patched debug break slot and the emitted address
545 // to jump to.
546 // Patched debug break slot code is a FIXED_SEQUENCE:
547 // mov r0, <address>
548 // mtlr r0
549 // blrl
550 static const int kPatchDebugBreakSlotAddressOffset = 0 * kInstrSize;
551
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400552 // This is the length of the code sequence from SetDebugBreakAtSlot()
553 // FIXED_SEQUENCE
554 static const int kDebugBreakSlotInstructions =
555 kMovInstructionsNoConstantPool + 2;
556 static const int kDebugBreakSlotLength =
557 kDebugBreakSlotInstructions * kInstrSize;
558
559 static inline int encode_crbit(const CRegister& cr, enum CRBit crbit) {
560 return ((cr.code() * CRWIDTH) + crbit);
561 }
562
563 // ---------------------------------------------------------------------------
564 // Code generation
565
566 // Insert the smallest number of nop instructions
567 // possible to align the pc offset to a multiple
568 // of m. m must be a power of 2 (>= 4).
569 void Align(int m);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000570 // Insert the smallest number of zero bytes possible to align the pc offset
571 // to a mulitple of m. m must be a power of 2 (>= 2).
572 void DataAlign(int m);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400573 // Aligns code to something that's optimal for a jump target for the platform.
574 void CodeTargetAlign();
575
576 // Branch instructions
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000577 void bclr(BOfield bo, int condition_bit, LKBit lk);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400578 void blr();
579 void bc(int branch_offset, BOfield bo, int condition_bit, LKBit lk = LeaveLK);
580 void b(int branch_offset, LKBit lk);
581
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000582 void bcctr(BOfield bo, int condition_bit, LKBit lk);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400583 void bctr();
584 void bctrl();
585
586 // Convenience branch instructions using labels
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000587 void b(Label* L, LKBit lk = LeaveLK) { b(branch_offset(L), lk); }
588
589 inline CRegister cmpi_optimization(CRegister cr) {
590 // Check whether the branch is preceeded by an optimizable cmpi against 0.
591 // The cmpi can be deleted if it is also preceeded by an instruction that
592 // sets the register used by the compare and supports a dot form.
593 unsigned int sradi_mask = kOpcodeMask | kExt2OpcodeVariant2Mask;
594 unsigned int srawi_mask = kOpcodeMask | kExt2OpcodeMask;
595 int pos = pc_offset();
596 int cmpi_pos = pc_offset() - kInstrSize;
597
598 if (cmpi_pos > 0 && optimizable_cmpi_pos_ == cmpi_pos &&
599 cmpi_cr_.code() == cr.code() && last_bound_pos_ != pos) {
600 int xpos = cmpi_pos - kInstrSize;
601 int xinstr = instr_at(xpos);
602 int cmpi_ra = (instr_at(cmpi_pos) & 0x1f0000) >> 16;
603 // ra is at the same bit position for the three cases below.
604 int ra = (xinstr & 0x1f0000) >> 16;
605 if (cmpi_ra == ra) {
606 if ((xinstr & sradi_mask) == (EXT2 | SRADIX)) {
607 cr = cr0;
608 instr_at_put(xpos, xinstr | SetRC);
609 pc_ -= kInstrSize;
610 } else if ((xinstr & srawi_mask) == (EXT2 | SRAWIX)) {
611 cr = cr0;
612 instr_at_put(xpos, xinstr | SetRC);
613 pc_ -= kInstrSize;
614 } else if ((xinstr & kOpcodeMask) == ANDIx) {
615 cr = cr0;
616 pc_ -= kInstrSize;
617 // nothing to do here since andi. records.
618 }
619 // didn't match one of the above, must keep cmpwi.
620 }
621 }
622 return cr;
623 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400624
625 void bc_short(Condition cond, Label* L, CRegister cr = cr7,
626 LKBit lk = LeaveLK) {
627 DCHECK(cond != al);
628 DCHECK(cr.code() >= 0 && cr.code() <= 7);
629
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000630 cr = cmpi_optimization(cr);
631
632 int b_offset = branch_offset(L);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400633
634 switch (cond) {
635 case eq:
636 bc(b_offset, BT, encode_crbit(cr, CR_EQ), lk);
637 break;
638 case ne:
639 bc(b_offset, BF, encode_crbit(cr, CR_EQ), lk);
640 break;
641 case gt:
642 bc(b_offset, BT, encode_crbit(cr, CR_GT), lk);
643 break;
644 case le:
645 bc(b_offset, BF, encode_crbit(cr, CR_GT), lk);
646 break;
647 case lt:
648 bc(b_offset, BT, encode_crbit(cr, CR_LT), lk);
649 break;
650 case ge:
651 bc(b_offset, BF, encode_crbit(cr, CR_LT), lk);
652 break;
653 case unordered:
654 bc(b_offset, BT, encode_crbit(cr, CR_FU), lk);
655 break;
656 case ordered:
657 bc(b_offset, BF, encode_crbit(cr, CR_FU), lk);
658 break;
659 case overflow:
660 bc(b_offset, BT, encode_crbit(cr, CR_SO), lk);
661 break;
662 case nooverflow:
663 bc(b_offset, BF, encode_crbit(cr, CR_SO), lk);
664 break;
665 default:
666 UNIMPLEMENTED();
667 }
668 }
669
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000670 void bclr(Condition cond, CRegister cr = cr7, LKBit lk = LeaveLK) {
671 DCHECK(cond != al);
672 DCHECK(cr.code() >= 0 && cr.code() <= 7);
673
674 cr = cmpi_optimization(cr);
675
676 switch (cond) {
677 case eq:
678 bclr(BT, encode_crbit(cr, CR_EQ), lk);
679 break;
680 case ne:
681 bclr(BF, encode_crbit(cr, CR_EQ), lk);
682 break;
683 case gt:
684 bclr(BT, encode_crbit(cr, CR_GT), lk);
685 break;
686 case le:
687 bclr(BF, encode_crbit(cr, CR_GT), lk);
688 break;
689 case lt:
690 bclr(BT, encode_crbit(cr, CR_LT), lk);
691 break;
692 case ge:
693 bclr(BF, encode_crbit(cr, CR_LT), lk);
694 break;
695 case unordered:
696 bclr(BT, encode_crbit(cr, CR_FU), lk);
697 break;
698 case ordered:
699 bclr(BF, encode_crbit(cr, CR_FU), lk);
700 break;
701 case overflow:
702 bclr(BT, encode_crbit(cr, CR_SO), lk);
703 break;
704 case nooverflow:
705 bclr(BF, encode_crbit(cr, CR_SO), lk);
706 break;
707 default:
708 UNIMPLEMENTED();
709 }
710 }
711
712 void isel(Register rt, Register ra, Register rb, int cb);
713 void isel(Condition cond, Register rt, Register ra, Register rb,
714 CRegister cr = cr7) {
715 DCHECK(cond != al);
716 DCHECK(cr.code() >= 0 && cr.code() <= 7);
717
718 cr = cmpi_optimization(cr);
719
720 switch (cond) {
721 case eq:
722 isel(rt, ra, rb, encode_crbit(cr, CR_EQ));
723 break;
724 case ne:
725 isel(rt, rb, ra, encode_crbit(cr, CR_EQ));
726 break;
727 case gt:
728 isel(rt, ra, rb, encode_crbit(cr, CR_GT));
729 break;
730 case le:
731 isel(rt, rb, ra, encode_crbit(cr, CR_GT));
732 break;
733 case lt:
734 isel(rt, ra, rb, encode_crbit(cr, CR_LT));
735 break;
736 case ge:
737 isel(rt, rb, ra, encode_crbit(cr, CR_LT));
738 break;
739 case unordered:
740 isel(rt, ra, rb, encode_crbit(cr, CR_FU));
741 break;
742 case ordered:
743 isel(rt, rb, ra, encode_crbit(cr, CR_FU));
744 break;
745 case overflow:
746 isel(rt, ra, rb, encode_crbit(cr, CR_SO));
747 break;
748 case nooverflow:
749 isel(rt, rb, ra, encode_crbit(cr, CR_SO));
750 break;
751 default:
752 UNIMPLEMENTED();
753 }
754 }
755
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400756 void b(Condition cond, Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
757 if (cond == al) {
758 b(L, lk);
759 return;
760 }
761
762 if ((L->is_bound() && is_near(L, cond)) || !is_trampoline_emitted()) {
763 bc_short(cond, L, cr, lk);
764 return;
765 }
766
767 Label skip;
768 Condition neg_cond = NegateCondition(cond);
769 bc_short(neg_cond, &skip, cr);
770 b(L, lk);
771 bind(&skip);
772 }
773
774 void bne(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
775 b(ne, L, cr, lk);
776 }
777 void beq(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
778 b(eq, L, cr, lk);
779 }
780 void blt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
781 b(lt, L, cr, lk);
782 }
783 void bge(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
784 b(ge, L, cr, lk);
785 }
786 void ble(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
787 b(le, L, cr, lk);
788 }
789 void bgt(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
790 b(gt, L, cr, lk);
791 }
792 void bunordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
793 b(unordered, L, cr, lk);
794 }
795 void bordered(Label* L, CRegister cr = cr7, LKBit lk = LeaveLK) {
796 b(ordered, L, cr, lk);
797 }
798 void boverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
799 b(overflow, L, cr, lk);
800 }
801 void bnooverflow(Label* L, CRegister cr = cr0, LKBit lk = LeaveLK) {
802 b(nooverflow, L, cr, lk);
803 }
804
805 // Decrement CTR; branch if CTR != 0
806 void bdnz(Label* L, LKBit lk = LeaveLK) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000807 bc(branch_offset(L), DCBNZ, 0, lk);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400808 }
809
810 // Data-processing instructions
811
812 void sub(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
813 RCBit r = LeaveRC);
814
Ben Murdochda12d292016-06-02 14:46:10 +0100815 void subc(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
816 RCBit r = LeaveRC);
817 void sube(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
818 RCBit r = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400819
Ben Murdochda12d292016-06-02 14:46:10 +0100820 void subfic(Register dst, Register src, const Operand& imm);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400821
822 void add(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
823 RCBit r = LeaveRC);
824
825 void addc(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
826 RCBit r = LeaveRC);
Ben Murdochda12d292016-06-02 14:46:10 +0100827 void adde(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
828 RCBit r = LeaveRC);
829 void addze(Register dst, Register src1, OEBit o = LeaveOE, RCBit r = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400830
831 void mullw(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
832 RCBit r = LeaveRC);
833
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000834 void mulhw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
835 void mulhwu(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400836
837 void divw(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
838 RCBit r = LeaveRC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000839 void divwu(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
840 RCBit r = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400841
842 void addi(Register dst, Register src, const Operand& imm);
843 void addis(Register dst, Register src, const Operand& imm);
844 void addic(Register dst, Register src, const Operand& imm);
845
846 void and_(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
847 void andc(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
848 void andi(Register ra, Register rs, const Operand& imm);
849 void andis(Register ra, Register rs, const Operand& imm);
850 void nor(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
851 void notx(Register dst, Register src, RCBit r = LeaveRC);
852 void ori(Register dst, Register src, const Operand& imm);
853 void oris(Register dst, Register src, const Operand& imm);
854 void orx(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000855 void orc(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400856 void xori(Register dst, Register src, const Operand& imm);
857 void xoris(Register ra, Register rs, const Operand& imm);
858 void xor_(Register dst, Register src1, Register src2, RCBit rc = LeaveRC);
859 void cmpi(Register src1, const Operand& src2, CRegister cr = cr7);
860 void cmpli(Register src1, const Operand& src2, CRegister cr = cr7);
861 void cmpwi(Register src1, const Operand& src2, CRegister cr = cr7);
862 void cmplwi(Register src1, const Operand& src2, CRegister cr = cr7);
863 void li(Register dst, const Operand& src);
864 void lis(Register dst, const Operand& imm);
865 void mr(Register dst, Register src);
866
867 void lbz(Register dst, const MemOperand& src);
868 void lbzx(Register dst, const MemOperand& src);
869 void lbzux(Register dst, const MemOperand& src);
870 void lhz(Register dst, const MemOperand& src);
871 void lhzx(Register dst, const MemOperand& src);
872 void lhzux(Register dst, const MemOperand& src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000873 void lha(Register dst, const MemOperand& src);
874 void lhax(Register dst, const MemOperand& src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400875 void lwz(Register dst, const MemOperand& src);
876 void lwzu(Register dst, const MemOperand& src);
877 void lwzx(Register dst, const MemOperand& src);
878 void lwzux(Register dst, const MemOperand& src);
879 void lwa(Register dst, const MemOperand& src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000880 void lwax(Register dst, const MemOperand& src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400881 void stb(Register dst, const MemOperand& src);
882 void stbx(Register dst, const MemOperand& src);
883 void stbux(Register dst, const MemOperand& src);
884 void sth(Register dst, const MemOperand& src);
885 void sthx(Register dst, const MemOperand& src);
886 void sthux(Register dst, const MemOperand& src);
887 void stw(Register dst, const MemOperand& src);
888 void stwu(Register dst, const MemOperand& src);
889 void stwx(Register rs, const MemOperand& src);
890 void stwux(Register rs, const MemOperand& src);
891
892 void extsb(Register rs, Register ra, RCBit r = LeaveRC);
893 void extsh(Register rs, Register ra, RCBit r = LeaveRC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000894 void extsw(Register rs, Register ra, RCBit r = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400895
896 void neg(Register rt, Register ra, OEBit o = LeaveOE, RCBit c = LeaveRC);
897
898#if V8_TARGET_ARCH_PPC64
899 void ld(Register rd, const MemOperand& src);
900 void ldx(Register rd, const MemOperand& src);
901 void ldu(Register rd, const MemOperand& src);
902 void ldux(Register rd, const MemOperand& src);
903 void std(Register rs, const MemOperand& src);
904 void stdx(Register rs, const MemOperand& src);
905 void stdu(Register rs, const MemOperand& src);
906 void stdux(Register rs, const MemOperand& src);
907 void rldic(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
908 void rldicl(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
909 void rldcl(Register ra, Register rs, Register rb, int mb, RCBit r = LeaveRC);
910 void rldicr(Register dst, Register src, int sh, int me, RCBit r = LeaveRC);
911 void rldimi(Register dst, Register src, int sh, int mb, RCBit r = LeaveRC);
912 void sldi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
913 void srdi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
914 void clrrdi(Register dst, Register src, const Operand& val,
915 RCBit rc = LeaveRC);
916 void clrldi(Register dst, Register src, const Operand& val,
917 RCBit rc = LeaveRC);
918 void sradi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
919 void srd(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
920 void sld(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
921 void srad(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
922 void rotld(Register ra, Register rs, Register rb, RCBit r = LeaveRC);
923 void rotldi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
924 void rotrdi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
925 void cntlzd_(Register dst, Register src, RCBit rc = LeaveRC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000926 void popcntd(Register dst, Register src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400927 void mulld(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
928 RCBit r = LeaveRC);
929 void divd(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
930 RCBit r = LeaveRC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000931 void divdu(Register dst, Register src1, Register src2, OEBit o = LeaveOE,
932 RCBit r = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400933#endif
934
935 void rlwinm(Register ra, Register rs, int sh, int mb, int me,
936 RCBit rc = LeaveRC);
937 void rlwimi(Register ra, Register rs, int sh, int mb, int me,
938 RCBit rc = LeaveRC);
939 void rlwnm(Register ra, Register rs, Register rb, int mb, int me,
940 RCBit rc = LeaveRC);
941 void slwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
942 void srwi(Register dst, Register src, const Operand& val, RCBit rc = LeaveRC);
943 void clrrwi(Register dst, Register src, const Operand& val,
944 RCBit rc = LeaveRC);
945 void clrlwi(Register dst, Register src, const Operand& val,
946 RCBit rc = LeaveRC);
947 void srawi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
948 void srw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
949 void slw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
950 void sraw(Register dst, Register src1, Register src2, RCBit r = LeaveRC);
951 void rotlw(Register ra, Register rs, Register rb, RCBit r = LeaveRC);
952 void rotlwi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
953 void rotrwi(Register ra, Register rs, int sh, RCBit r = LeaveRC);
954
955 void cntlzw_(Register dst, Register src, RCBit rc = LeaveRC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000956 void popcntw(Register dst, Register src);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400957
958 void subi(Register dst, Register src1, const Operand& src2);
959
960 void cmp(Register src1, Register src2, CRegister cr = cr7);
961 void cmpl(Register src1, Register src2, CRegister cr = cr7);
962 void cmpw(Register src1, Register src2, CRegister cr = cr7);
963 void cmplw(Register src1, Register src2, CRegister cr = cr7);
964
965 void mov(Register dst, const Operand& src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000966 void bitwise_mov(Register dst, intptr_t value);
967 void bitwise_mov32(Register dst, int32_t value);
968 void bitwise_add32(Register dst, Register src, int32_t value);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400969
970 // Load the position of the label relative to the generated code object
971 // pointer in a register.
972 void mov_label_offset(Register dst, Label* label);
973
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000974 // dst = base + label position + delta
975 void add_label_offset(Register dst, Register base, Label* label,
976 int delta = 0);
977
978 // Load the address of the label in a register and associate with an
979 // internal reference relocation.
980 void mov_label_addr(Register dst, Label* label);
981
982 // Emit the address of the label (i.e. a jump table entry) and associate with
983 // an internal reference relocation.
984 void emit_label_addr(Label* label);
985
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400986 // Multiply instructions
987 void mul(Register dst, Register src1, Register src2, OEBit s = LeaveOE,
988 RCBit r = LeaveRC);
989
990 // Miscellaneous arithmetic instructions
991
992 // Special register access
993 void crxor(int bt, int ba, int bb);
994 void crclr(int bt) { crxor(bt, bt, bt); }
995 void creqv(int bt, int ba, int bb);
996 void crset(int bt) { creqv(bt, bt, bt); }
997 void mflr(Register dst);
998 void mtlr(Register src);
999 void mtctr(Register src);
1000 void mtxer(Register src);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001001 void mcrfs(CRegister cr, FPSCRBit bit);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001002 void mfcr(Register dst);
1003#if V8_TARGET_ARCH_PPC64
1004 void mffprd(Register dst, DoubleRegister src);
1005 void mffprwz(Register dst, DoubleRegister src);
1006 void mtfprd(DoubleRegister dst, Register src);
1007 void mtfprwz(DoubleRegister dst, Register src);
1008 void mtfprwa(DoubleRegister dst, Register src);
1009#endif
1010
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001011 void function_descriptor();
1012
1013 // Exception-generating instructions and debugging support
1014 void stop(const char* msg, Condition cond = al,
1015 int32_t code = kDefaultStopCode, CRegister cr = cr7);
1016
1017 void bkpt(uint32_t imm16); // v5 and above
1018
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001019 void dcbf(Register ra, Register rb);
1020 void sync();
1021 void lwsync();
1022 void icbi(Register ra, Register rb);
1023 void isync();
1024
1025 // Support for floating point
1026 void lfd(const DoubleRegister frt, const MemOperand& src);
1027 void lfdu(const DoubleRegister frt, const MemOperand& src);
1028 void lfdx(const DoubleRegister frt, const MemOperand& src);
1029 void lfdux(const DoubleRegister frt, const MemOperand& src);
1030 void lfs(const DoubleRegister frt, const MemOperand& src);
1031 void lfsu(const DoubleRegister frt, const MemOperand& src);
1032 void lfsx(const DoubleRegister frt, const MemOperand& src);
1033 void lfsux(const DoubleRegister frt, const MemOperand& src);
1034 void stfd(const DoubleRegister frs, const MemOperand& src);
1035 void stfdu(const DoubleRegister frs, const MemOperand& src);
1036 void stfdx(const DoubleRegister frs, const MemOperand& src);
1037 void stfdux(const DoubleRegister frs, const MemOperand& src);
1038 void stfs(const DoubleRegister frs, const MemOperand& src);
1039 void stfsu(const DoubleRegister frs, const MemOperand& src);
1040 void stfsx(const DoubleRegister frs, const MemOperand& src);
1041 void stfsux(const DoubleRegister frs, const MemOperand& src);
1042
1043 void fadd(const DoubleRegister frt, const DoubleRegister fra,
1044 const DoubleRegister frb, RCBit rc = LeaveRC);
1045 void fsub(const DoubleRegister frt, const DoubleRegister fra,
1046 const DoubleRegister frb, RCBit rc = LeaveRC);
1047 void fdiv(const DoubleRegister frt, const DoubleRegister fra,
1048 const DoubleRegister frb, RCBit rc = LeaveRC);
1049 void fmul(const DoubleRegister frt, const DoubleRegister fra,
1050 const DoubleRegister frc, RCBit rc = LeaveRC);
1051 void fcmpu(const DoubleRegister fra, const DoubleRegister frb,
1052 CRegister cr = cr7);
1053 void fmr(const DoubleRegister frt, const DoubleRegister frb,
1054 RCBit rc = LeaveRC);
1055 void fctiwz(const DoubleRegister frt, const DoubleRegister frb);
1056 void fctiw(const DoubleRegister frt, const DoubleRegister frb);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001057 void frin(const DoubleRegister frt, const DoubleRegister frb,
1058 RCBit rc = LeaveRC);
1059 void friz(const DoubleRegister frt, const DoubleRegister frb,
1060 RCBit rc = LeaveRC);
1061 void frip(const DoubleRegister frt, const DoubleRegister frb,
1062 RCBit rc = LeaveRC);
1063 void frim(const DoubleRegister frt, const DoubleRegister frb,
1064 RCBit rc = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001065 void frsp(const DoubleRegister frt, const DoubleRegister frb,
1066 RCBit rc = LeaveRC);
1067 void fcfid(const DoubleRegister frt, const DoubleRegister frb,
1068 RCBit rc = LeaveRC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001069 void fcfidu(const DoubleRegister frt, const DoubleRegister frb,
1070 RCBit rc = LeaveRC);
1071 void fcfidus(const DoubleRegister frt, const DoubleRegister frb,
1072 RCBit rc = LeaveRC);
1073 void fcfids(const DoubleRegister frt, const DoubleRegister frb,
1074 RCBit rc = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001075 void fctid(const DoubleRegister frt, const DoubleRegister frb,
1076 RCBit rc = LeaveRC);
1077 void fctidz(const DoubleRegister frt, const DoubleRegister frb,
1078 RCBit rc = LeaveRC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001079 void fctidu(const DoubleRegister frt, const DoubleRegister frb,
1080 RCBit rc = LeaveRC);
1081 void fctiduz(const DoubleRegister frt, const DoubleRegister frb,
1082 RCBit rc = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001083 void fsel(const DoubleRegister frt, const DoubleRegister fra,
1084 const DoubleRegister frc, const DoubleRegister frb,
1085 RCBit rc = LeaveRC);
1086 void fneg(const DoubleRegister frt, const DoubleRegister frb,
1087 RCBit rc = LeaveRC);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001088 void mtfsb0(FPSCRBit bit, RCBit rc = LeaveRC);
1089 void mtfsb1(FPSCRBit bit, RCBit rc = LeaveRC);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001090 void mtfsfi(int bf, int immediate, RCBit rc = LeaveRC);
1091 void mffs(const DoubleRegister frt, RCBit rc = LeaveRC);
1092 void mtfsf(const DoubleRegister frb, bool L = 1, int FLM = 0, bool W = 0,
1093 RCBit rc = LeaveRC);
1094 void fsqrt(const DoubleRegister frt, const DoubleRegister frb,
1095 RCBit rc = LeaveRC);
1096 void fabs(const DoubleRegister frt, const DoubleRegister frb,
1097 RCBit rc = LeaveRC);
1098 void fmadd(const DoubleRegister frt, const DoubleRegister fra,
1099 const DoubleRegister frc, const DoubleRegister frb,
1100 RCBit rc = LeaveRC);
1101 void fmsub(const DoubleRegister frt, const DoubleRegister fra,
1102 const DoubleRegister frc, const DoubleRegister frb,
1103 RCBit rc = LeaveRC);
1104
1105 // Pseudo instructions
1106
1107 // Different nop operations are used by the code generator to detect certain
1108 // states of the generated code.
1109 enum NopMarkerTypes {
1110 NON_MARKING_NOP = 0,
1111 GROUP_ENDING_NOP,
1112 DEBUG_BREAK_NOP,
1113 // IC markers.
1114 PROPERTY_ACCESS_INLINED,
1115 PROPERTY_ACCESS_INLINED_CONTEXT,
1116 PROPERTY_ACCESS_INLINED_CONTEXT_DONT_DELETE,
1117 // Helper values.
1118 LAST_CODE_MARKER,
1119 FIRST_IC_MARKER = PROPERTY_ACCESS_INLINED
1120 };
1121
1122 void nop(int type = 0); // 0 is the default non-marking type.
1123
1124 void push(Register src) {
1125#if V8_TARGET_ARCH_PPC64
1126 stdu(src, MemOperand(sp, -kPointerSize));
1127#else
1128 stwu(src, MemOperand(sp, -kPointerSize));
1129#endif
1130 }
1131
1132 void pop(Register dst) {
1133#if V8_TARGET_ARCH_PPC64
1134 ld(dst, MemOperand(sp));
1135#else
1136 lwz(dst, MemOperand(sp));
1137#endif
1138 addi(sp, sp, Operand(kPointerSize));
1139 }
1140
1141 void pop() { addi(sp, sp, Operand(kPointerSize)); }
1142
1143 // Jump unconditionally to given label.
1144 void jmp(Label* L) { b(L); }
1145
1146 // Check the code size generated from label to here.
1147 int SizeOfCodeGeneratedSince(Label* label) {
1148 return pc_offset() - label->pos();
1149 }
1150
1151 // Check the number of instructions generated from label to here.
1152 int InstructionsGeneratedSince(Label* label) {
1153 return SizeOfCodeGeneratedSince(label) / kInstrSize;
1154 }
1155
1156 // Class for scoping postponing the trampoline pool generation.
1157 class BlockTrampolinePoolScope {
1158 public:
1159 explicit BlockTrampolinePoolScope(Assembler* assem) : assem_(assem) {
1160 assem_->StartBlockTrampolinePool();
1161 }
1162 ~BlockTrampolinePoolScope() { assem_->EndBlockTrampolinePool(); }
1163
1164 private:
1165 Assembler* assem_;
1166
1167 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockTrampolinePoolScope);
1168 };
1169
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001170 // Class for scoping disabling constant pool entry merging
1171 class BlockConstantPoolEntrySharingScope {
1172 public:
1173 explicit BlockConstantPoolEntrySharingScope(Assembler* assem)
1174 : assem_(assem) {
1175 assem_->StartBlockConstantPoolEntrySharing();
1176 }
1177 ~BlockConstantPoolEntrySharingScope() {
1178 assem_->EndBlockConstantPoolEntrySharing();
1179 }
1180
1181 private:
1182 Assembler* assem_;
1183
1184 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstantPoolEntrySharingScope);
1185 };
1186
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001187 // Debugging
1188
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001189 // Mark generator continuation.
1190 void RecordGeneratorContinuation();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001191
1192 // Mark address of a debug break slot.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001193 void RecordDebugBreakSlot(RelocInfo::Mode mode);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001194
1195 // Record the AST id of the CallIC being compiled, so that it can be placed
1196 // in the relocation information.
1197 void SetRecordedAstId(TypeFeedbackId ast_id) {
1198 // Causes compiler to fail
1199 // DCHECK(recorded_ast_id_.IsNone());
1200 recorded_ast_id_ = ast_id;
1201 }
1202
1203 TypeFeedbackId RecordedAstId() {
1204 // Causes compiler to fail
1205 // DCHECK(!recorded_ast_id_.IsNone());
1206 return recorded_ast_id_;
1207 }
1208
1209 void ClearRecordedAstId() { recorded_ast_id_ = TypeFeedbackId::None(); }
1210
1211 // Record a comment relocation entry that can be used by a disassembler.
1212 // Use --code-comments to enable.
1213 void RecordComment(const char* msg);
1214
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001215 // Record a deoptimization reason that can be used by a log or cpu profiler.
1216 // Use --trace-deopt to enable.
Ben Murdochc5610432016-08-08 18:44:38 +01001217 void RecordDeoptReason(const int reason, int raw_position, int id);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001218
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001219 // Writes a single byte or word of data in the code stream. Used
1220 // for inline tables, e.g., jump-tables.
1221 void db(uint8_t data);
1222 void dd(uint32_t data);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001223 void dq(uint64_t data);
1224 void dp(uintptr_t data);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001225
Ben Murdochda12d292016-06-02 14:46:10 +01001226 AssemblerPositionsRecorder* positions_recorder() {
1227 return &positions_recorder_;
1228 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001229
1230 // Read/patch instructions
1231 Instr instr_at(int pos) { return *reinterpret_cast<Instr*>(buffer_ + pos); }
1232 void instr_at_put(int pos, Instr instr) {
1233 *reinterpret_cast<Instr*>(buffer_ + pos) = instr;
1234 }
1235 static Instr instr_at(byte* pc) { return *reinterpret_cast<Instr*>(pc); }
1236 static void instr_at_put(byte* pc, Instr instr) {
1237 *reinterpret_cast<Instr*>(pc) = instr;
1238 }
1239 static Condition GetCondition(Instr instr);
1240
1241 static bool IsLis(Instr instr);
1242 static bool IsLi(Instr instr);
1243 static bool IsAddic(Instr instr);
1244 static bool IsOri(Instr instr);
1245
1246 static bool IsBranch(Instr instr);
1247 static Register GetRA(Instr instr);
1248 static Register GetRB(Instr instr);
1249#if V8_TARGET_ARCH_PPC64
1250 static bool Is64BitLoadIntoR12(Instr instr1, Instr instr2, Instr instr3,
1251 Instr instr4, Instr instr5);
1252#else
1253 static bool Is32BitLoadIntoR12(Instr instr1, Instr instr2);
1254#endif
1255
1256 static bool IsCmpRegister(Instr instr);
1257 static bool IsCmpImmediate(Instr instr);
1258 static bool IsRlwinm(Instr instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001259 static bool IsAndi(Instr instr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001260#if V8_TARGET_ARCH_PPC64
1261 static bool IsRldicl(Instr instr);
1262#endif
1263 static bool IsCrSet(Instr instr);
1264 static Register GetCmpImmediateRegister(Instr instr);
1265 static int GetCmpImmediateRawImmediate(Instr instr);
1266 static bool IsNop(Instr instr, int type = NON_MARKING_NOP);
1267
1268 // Postpone the generation of the trampoline pool for the specified number of
1269 // instructions.
1270 void BlockTrampolinePoolFor(int instructions);
1271 void CheckTrampolinePool();
1272
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001273 // For mov. Return the number of actual instructions required to
1274 // load the operand into a register. This can be anywhere from
1275 // one (constant pool small section) to five instructions (full
1276 // 64-bit sequence).
1277 //
1278 // The value returned is only valid as long as no entries are added to the
1279 // constant pool between this call and the actual instruction being emitted.
1280 int instructions_required_for_mov(Register dst, const Operand& src) const;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001281
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001282 // Decide between using the constant pool vs. a mov immediate sequence.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001283 bool use_constant_pool_for_mov(Register dst, const Operand& src,
1284 bool canOptimize) const;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001285
1286 // The code currently calls CheckBuffer() too often. This has the side
1287 // effect of randomly growing the buffer in the middle of multi-instruction
1288 // sequences.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001289 //
1290 // This function allows outside callers to check and grow the buffer
1291 void EnsureSpaceFor(int space_needed);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001292
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001293 int EmitConstantPool() { return constant_pool_builder_.Emit(this); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001294
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001295 bool ConstantPoolAccessIsInOverflow() const {
1296 return constant_pool_builder_.NextAccess(ConstantPoolEntry::INTPTR) ==
1297 ConstantPoolEntry::OVERFLOWED;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001298 }
1299
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001300 Label* ConstantPoolPosition() {
1301 return constant_pool_builder_.EmittedPosition();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001302 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001303
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001304 void EmitRelocations();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001305
1306 protected:
1307 // Relocation for a type-recording IC has the AST id added to it. This
1308 // member variable is a way to pass the information from the call site to
1309 // the relocation info.
1310 TypeFeedbackId recorded_ast_id_;
1311
1312 int buffer_space() const { return reloc_info_writer.pos() - pc_; }
1313
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001314 // Decode instruction(s) at pos and return backchain to previous
1315 // label reference or kEndOfChain.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001316 int target_at(int pos);
1317
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001318 // Patch instruction(s) at pos to target target_pos (e.g. branch)
1319 void target_at_put(int pos, int target_pos, bool* is_branch = nullptr);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001320
1321 // Record reloc info for current pc_
1322 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001323 ConstantPoolEntry::Access ConstantPoolAddEntry(RelocInfo::Mode rmode,
1324 intptr_t value) {
1325 bool sharing_ok = RelocInfo::IsNone(rmode) ||
1326 !(serializer_enabled() || rmode < RelocInfo::CELL ||
1327 is_constant_pool_entry_sharing_blocked());
1328 return constant_pool_builder_.AddEntry(pc_offset(), value, sharing_ok);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001329 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001330 ConstantPoolEntry::Access ConstantPoolAddEntry(double value) {
1331 return constant_pool_builder_.AddEntry(pc_offset(), value);
1332 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001333
1334 // Block the emission of the trampoline pool before pc_offset.
1335 void BlockTrampolinePoolBefore(int pc_offset) {
1336 if (no_trampoline_pool_before_ < pc_offset)
1337 no_trampoline_pool_before_ = pc_offset;
1338 }
1339
1340 void StartBlockTrampolinePool() { trampoline_pool_blocked_nesting_++; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001341 void EndBlockTrampolinePool() {
1342 int count = --trampoline_pool_blocked_nesting_;
1343 if (count == 0) CheckTrampolinePoolQuick();
1344 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001345 bool is_trampoline_pool_blocked() const {
1346 return trampoline_pool_blocked_nesting_ > 0;
1347 }
1348
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001349 void StartBlockConstantPoolEntrySharing() {
1350 constant_pool_entry_sharing_blocked_nesting_++;
1351 }
1352 void EndBlockConstantPoolEntrySharing() {
1353 constant_pool_entry_sharing_blocked_nesting_--;
1354 }
1355 bool is_constant_pool_entry_sharing_blocked() const {
1356 return constant_pool_entry_sharing_blocked_nesting_ > 0;
1357 }
1358
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001359 bool has_exception() const { return internal_trampoline_exception_; }
1360
1361 bool is_trampoline_emitted() const { return trampoline_emitted_; }
1362
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001363 private:
1364 // Code generation
1365 // The relocation writer's position is at least kGap bytes below the end of
1366 // the generated instructions. This is so that multi-instruction sequences do
1367 // not have to check for overflow. The same is true for writes of large
1368 // relocation info entries.
1369 static const int kGap = 32;
1370
1371 // Repeated checking whether the trampoline pool should be emitted is rather
1372 // expensive. By default we only check again once a number of instructions
1373 // has been generated.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001374 int next_trampoline_check_; // pc offset of next buffer check.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001375
1376 // Emission of the trampoline pool may be blocked in some code sequences.
1377 int trampoline_pool_blocked_nesting_; // Block emission if this is not zero.
1378 int no_trampoline_pool_before_; // Block emission before this pc offset.
1379
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001380 // Do not share constant pool entries.
1381 int constant_pool_entry_sharing_blocked_nesting_;
1382
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001383 // Relocation info generation
1384 // Each relocation is encoded as a variable size value
1385 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
1386 RelocInfoWriter reloc_info_writer;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001387 std::vector<DeferredRelocInfo> relocations_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001388
1389 // The bound position, before this we cannot do instruction elimination.
1390 int last_bound_pos_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001391 // Optimizable cmpi information.
1392 int optimizable_cmpi_pos_;
1393 CRegister cmpi_cr_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001394
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001395 ConstantPoolBuilder constant_pool_builder_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001396
1397 // Code emission
1398 inline void CheckBuffer();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001399 void GrowBuffer(int needed = 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001400 inline void emit(Instr x);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001401 inline void TrackBranch();
1402 inline void UntrackBranch();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001403 inline void CheckTrampolinePoolQuick();
1404
1405 // Instruction generation
1406 void a_form(Instr instr, DoubleRegister frt, DoubleRegister fra,
1407 DoubleRegister frb, RCBit r);
1408 void d_form(Instr instr, Register rt, Register ra, const intptr_t val,
1409 bool signed_disp);
1410 void x_form(Instr instr, Register ra, Register rs, Register rb, RCBit r);
1411 void xo_form(Instr instr, Register rt, Register ra, Register rb, OEBit o,
1412 RCBit r);
1413 void md_form(Instr instr, Register ra, Register rs, int shift, int maskbit,
1414 RCBit r);
1415 void mds_form(Instr instr, Register ra, Register rs, Register rb, int maskbit,
1416 RCBit r);
1417
1418 // Labels
1419 void print(Label* L);
1420 int max_reach_from(int pos);
1421 void bind_to(Label* L, int pos);
1422 void next(Label* L);
1423
1424 class Trampoline {
1425 public:
1426 Trampoline() {
1427 next_slot_ = 0;
1428 free_slot_count_ = 0;
1429 }
1430 Trampoline(int start, int slot_count) {
1431 next_slot_ = start;
1432 free_slot_count_ = slot_count;
1433 }
1434 int take_slot() {
1435 int trampoline_slot = kInvalidSlotPos;
1436 if (free_slot_count_ <= 0) {
1437 // We have run out of space on trampolines.
1438 // Make sure we fail in debug mode, so we become aware of each case
1439 // when this happens.
1440 DCHECK(0);
1441 // Internal exception will be caught.
1442 } else {
1443 trampoline_slot = next_slot_;
1444 free_slot_count_--;
1445 next_slot_ += kTrampolineSlotsSize;
1446 }
1447 return trampoline_slot;
1448 }
1449
1450 private:
1451 int next_slot_;
1452 int free_slot_count_;
1453 };
1454
1455 int32_t get_trampoline_entry();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001456 int tracked_branch_count_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001457 // If trampoline is emitted, generated code is becoming large. As
1458 // this is already a slow case which can possibly break our code
1459 // generation for the extreme case, we use this information to
1460 // trigger different mode of branch instruction generation, where we
1461 // no longer use a single branch instruction.
1462 bool trampoline_emitted_;
1463 static const int kTrampolineSlotsSize = kInstrSize;
1464 static const int kMaxCondBranchReach = (1 << (16 - 1)) - 1;
1465 static const int kMaxBlockTrampolineSectionSize = 64 * kInstrSize;
1466 static const int kInvalidSlotPos = -1;
1467
1468 Trampoline trampoline_;
1469 bool internal_trampoline_exception_;
1470
1471 friend class RegExpMacroAssemblerPPC;
1472 friend class RelocInfo;
1473 friend class CodePatcher;
1474 friend class BlockTrampolinePoolScope;
Ben Murdochda12d292016-06-02 14:46:10 +01001475 AssemblerPositionsRecorder positions_recorder_;
1476 friend class AssemblerPositionsRecorder;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001477 friend class EnsureSpace;
1478};
1479
1480
1481class EnsureSpace BASE_EMBEDDED {
1482 public:
1483 explicit EnsureSpace(Assembler* assembler) { assembler->CheckBuffer(); }
1484};
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001485} // namespace internal
1486} // namespace v8
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001487
1488#endif // V8_PPC_ASSEMBLER_PPC_H_