blob: 5854704b6825c8ae824d5f26cfe712cd4452e9e7 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2013 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_ARM64_ASSEMBLER_ARM64_H_
6#define V8_ARM64_ASSEMBLER_ARM64_H_
7
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00008#include <deque>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00009#include <list>
10#include <map>
11#include <vector>
12
13#include "src/arm64/instructions-arm64.h"
14#include "src/assembler.h"
15#include "src/globals.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000016#include "src/utils.h"
17
18
19namespace v8 {
20namespace internal {
21
22
23// -----------------------------------------------------------------------------
24// Registers.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000025// clang-format off
26#define GENERAL_REGISTER_CODE_LIST(R) \
27 R(0) R(1) R(2) R(3) R(4) R(5) R(6) R(7) \
28 R(8) R(9) R(10) R(11) R(12) R(13) R(14) R(15) \
29 R(16) R(17) R(18) R(19) R(20) R(21) R(22) R(23) \
30 R(24) R(25) R(26) R(27) R(28) R(29) R(30) R(31)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000032#define GENERAL_REGISTERS(R) \
33 R(x0) R(x1) R(x2) R(x3) R(x4) R(x5) R(x6) R(x7) \
34 R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \
35 R(x16) R(x17) R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) \
36 R(x24) R(x25) R(x26) R(x27) R(x28) R(x29) R(x30) R(x31)
37
38#define ALLOCATABLE_GENERAL_REGISTERS(R) \
39 R(x0) R(x1) R(x2) R(x3) R(x4) R(x5) R(x6) R(x7) \
40 R(x8) R(x9) R(x10) R(x11) R(x12) R(x13) R(x14) R(x15) \
41 R(x18) R(x19) R(x20) R(x21) R(x22) R(x23) R(x24) R(x27)
42
43#define DOUBLE_REGISTERS(R) \
44 R(d0) R(d1) R(d2) R(d3) R(d4) R(d5) R(d6) R(d7) \
45 R(d8) R(d9) R(d10) R(d11) R(d12) R(d13) R(d14) R(d15) \
46 R(d16) R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) \
47 R(d24) R(d25) R(d26) R(d27) R(d28) R(d29) R(d30) R(d31)
48
49#define ALLOCATABLE_DOUBLE_REGISTERS(R) \
50 R(d0) R(d1) R(d2) R(d3) R(d4) R(d5) R(d6) R(d7) \
51 R(d8) R(d9) R(d10) R(d11) R(d12) R(d13) R(d14) R(d16) \
52 R(d17) R(d18) R(d19) R(d20) R(d21) R(d22) R(d23) R(d24) \
53 R(d25) R(d26) R(d27) R(d28)
54// clang-format on
Ben Murdochb8a8cc12014-11-26 15:28:44 +000055
56static const int kRegListSizeInBits = sizeof(RegList) * kBitsPerByte;
57
58
59// Some CPURegister methods can return Register and FPRegister types, so we
60// need to declare them in advance.
61struct Register;
62struct FPRegister;
63
64
65struct CPURegister {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000066 enum Code {
67#define REGISTER_CODE(R) kCode_##R,
68 GENERAL_REGISTERS(REGISTER_CODE)
69#undef REGISTER_CODE
70 kAfterLast,
71 kCode_no_reg = -1
72 };
73
Ben Murdochb8a8cc12014-11-26 15:28:44 +000074 enum RegisterType {
75 // The kInvalid value is used to detect uninitialized static instances,
76 // which are always zero-initialized before any constructors are called.
77 kInvalid = 0,
78 kRegister,
79 kFPRegister,
80 kNoRegister
81 };
82
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000083 static CPURegister Create(int code, int size, RegisterType type) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000084 CPURegister r = {code, size, type};
85 return r;
86 }
87
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088 int code() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000089 RegisterType type() const;
90 RegList Bit() const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000091 int SizeInBits() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000092 int SizeInBytes() const;
93 bool Is32Bits() const;
94 bool Is64Bits() const;
95 bool IsValid() const;
96 bool IsValidOrNone() const;
97 bool IsValidRegister() const;
98 bool IsValidFPRegister() const;
99 bool IsNone() const;
100 bool Is(const CPURegister& other) const;
101 bool Aliases(const CPURegister& other) const;
102
103 bool IsZero() const;
104 bool IsSP() const;
105
106 bool IsRegister() const;
107 bool IsFPRegister() const;
108
109 Register X() const;
110 Register W() const;
111 FPRegister D() const;
112 FPRegister S() const;
113
114 bool IsSameSizeAndType(const CPURegister& other) const;
115
116 // V8 compatibility.
117 bool is(const CPURegister& other) const { return Is(other); }
118 bool is_valid() const { return IsValid(); }
119
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000120 int reg_code;
121 int reg_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000122 RegisterType reg_type;
123};
124
125
126struct Register : public CPURegister {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000127 static Register Create(int code, int size) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000128 return Register(CPURegister::Create(code, size, CPURegister::kRegister));
129 }
130
131 Register() {
132 reg_code = 0;
133 reg_size = 0;
134 reg_type = CPURegister::kNoRegister;
135 }
136
137 explicit Register(const CPURegister& r) {
138 reg_code = r.reg_code;
139 reg_size = r.reg_size;
140 reg_type = r.reg_type;
141 DCHECK(IsValidOrNone());
142 }
143
144 Register(const Register& r) { // NOLINT(runtime/explicit)
145 reg_code = r.reg_code;
146 reg_size = r.reg_size;
147 reg_type = r.reg_type;
148 DCHECK(IsValidOrNone());
149 }
150
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000151 const char* ToString();
152 bool IsAllocatable() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000153 bool IsValid() const {
154 DCHECK(IsRegister() || IsNone());
155 return IsValidRegister();
156 }
157
158 static Register XRegFromCode(unsigned code);
159 static Register WRegFromCode(unsigned code);
160
161 // Start of V8 compatibility section ---------------------
162 // These memebers are necessary for compilation.
163 // A few of them may be unused for now.
164
165 static const int kNumRegisters = kNumberOfRegisters;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000166 STATIC_ASSERT(kNumRegisters == Code::kAfterLast);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000167 static int NumRegisters() { return kNumRegisters; }
168
169 // We allow crankshaft to use the following registers:
170 // - x0 to x15
171 // - x18 to x24
172 // - x27 (also context)
173 //
174 // TODO(all): Register x25 is currently free and could be available for
175 // crankshaft, but we don't use it as we might use it as a per function
176 // literal pool pointer in the future.
177 //
178 // TODO(all): Consider storing cp in x25 to have only two ranges.
179 // We split allocatable registers in three ranges called
180 // - "low range"
181 // - "high range"
182 // - "context"
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000183
184 static Register from_code(int code) {
185 // Always return an X register.
186 return Register::Create(code, kXRegSizeInBits);
187 }
188
189 // End of V8 compatibility section -----------------------
190};
191
192
193struct FPRegister : public CPURegister {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000194 enum Code {
195#define REGISTER_CODE(R) kCode_##R,
196 DOUBLE_REGISTERS(REGISTER_CODE)
197#undef REGISTER_CODE
198 kAfterLast,
199 kCode_no_reg = -1
200 };
201
202 static FPRegister Create(int code, int size) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000203 return FPRegister(
204 CPURegister::Create(code, size, CPURegister::kFPRegister));
205 }
206
207 FPRegister() {
208 reg_code = 0;
209 reg_size = 0;
210 reg_type = CPURegister::kNoRegister;
211 }
212
213 explicit FPRegister(const CPURegister& r) {
214 reg_code = r.reg_code;
215 reg_size = r.reg_size;
216 reg_type = r.reg_type;
217 DCHECK(IsValidOrNone());
218 }
219
220 FPRegister(const FPRegister& r) { // NOLINT(runtime/explicit)
221 reg_code = r.reg_code;
222 reg_size = r.reg_size;
223 reg_type = r.reg_type;
224 DCHECK(IsValidOrNone());
225 }
226
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000227 const char* ToString();
228 bool IsAllocatable() const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000229 bool IsValid() const {
230 DCHECK(IsFPRegister() || IsNone());
231 return IsValidFPRegister();
232 }
233
234 static FPRegister SRegFromCode(unsigned code);
235 static FPRegister DRegFromCode(unsigned code);
236
237 // Start of V8 compatibility section ---------------------
238 static const int kMaxNumRegisters = kNumberOfFPRegisters;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000239 STATIC_ASSERT(kMaxNumRegisters == Code::kAfterLast);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000240
241 // Crankshaft can use all the FP registers except:
242 // - d15 which is used to keep the 0 double value
243 // - d30 which is used in crankshaft as a double scratch register
244 // - d31 which is used in the MacroAssembler as a double scratch register
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000245 static FPRegister from_code(int code) {
246 // Always return a D register.
247 return FPRegister::Create(code, kDRegSizeInBits);
248 }
249 // End of V8 compatibility section -----------------------
250};
251
252
253STATIC_ASSERT(sizeof(CPURegister) == sizeof(Register));
254STATIC_ASSERT(sizeof(CPURegister) == sizeof(FPRegister));
255
256
257#if defined(ARM64_DEFINE_REG_STATICS)
258#define INITIALIZE_REGISTER(register_class, name, code, size, type) \
259 const CPURegister init_##register_class##_##name = {code, size, type}; \
260 const register_class& name = *reinterpret_cast<const register_class*>( \
261 &init_##register_class##_##name)
262#define ALIAS_REGISTER(register_class, alias, name) \
263 const register_class& alias = *reinterpret_cast<const register_class*>( \
264 &init_##register_class##_##name)
265#else
266#define INITIALIZE_REGISTER(register_class, name, code, size, type) \
267 extern const register_class& name
268#define ALIAS_REGISTER(register_class, alias, name) \
269 extern const register_class& alias
270#endif // defined(ARM64_DEFINE_REG_STATICS)
271
272// No*Reg is used to indicate an unused argument, or an error case. Note that
273// these all compare equal (using the Is() method). The Register and FPRegister
274// variants are provided for convenience.
275INITIALIZE_REGISTER(Register, NoReg, 0, 0, CPURegister::kNoRegister);
276INITIALIZE_REGISTER(FPRegister, NoFPReg, 0, 0, CPURegister::kNoRegister);
277INITIALIZE_REGISTER(CPURegister, NoCPUReg, 0, 0, CPURegister::kNoRegister);
278
279// v8 compatibility.
280INITIALIZE_REGISTER(Register, no_reg, 0, 0, CPURegister::kNoRegister);
281
282#define DEFINE_REGISTERS(N) \
283 INITIALIZE_REGISTER(Register, w##N, N, \
284 kWRegSizeInBits, CPURegister::kRegister); \
285 INITIALIZE_REGISTER(Register, x##N, N, \
286 kXRegSizeInBits, CPURegister::kRegister);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000287GENERAL_REGISTER_CODE_LIST(DEFINE_REGISTERS)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000288#undef DEFINE_REGISTERS
289
290INITIALIZE_REGISTER(Register, wcsp, kSPRegInternalCode, kWRegSizeInBits,
291 CPURegister::kRegister);
292INITIALIZE_REGISTER(Register, csp, kSPRegInternalCode, kXRegSizeInBits,
293 CPURegister::kRegister);
294
295#define DEFINE_FPREGISTERS(N) \
296 INITIALIZE_REGISTER(FPRegister, s##N, N, \
297 kSRegSizeInBits, CPURegister::kFPRegister); \
298 INITIALIZE_REGISTER(FPRegister, d##N, N, \
299 kDRegSizeInBits, CPURegister::kFPRegister);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000300GENERAL_REGISTER_CODE_LIST(DEFINE_FPREGISTERS)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000301#undef DEFINE_FPREGISTERS
302
303#undef INITIALIZE_REGISTER
304
305// Registers aliases.
306ALIAS_REGISTER(Register, ip0, x16);
307ALIAS_REGISTER(Register, ip1, x17);
308ALIAS_REGISTER(Register, wip0, w16);
309ALIAS_REGISTER(Register, wip1, w17);
310// Root register.
311ALIAS_REGISTER(Register, root, x26);
312ALIAS_REGISTER(Register, rr, x26);
313// Context pointer register.
314ALIAS_REGISTER(Register, cp, x27);
315// We use a register as a JS stack pointer to overcome the restriction on the
316// architectural SP alignment.
317// We chose x28 because it is contiguous with the other specific purpose
318// registers.
319STATIC_ASSERT(kJSSPCode == 28);
320ALIAS_REGISTER(Register, jssp, x28);
321ALIAS_REGISTER(Register, wjssp, w28);
322ALIAS_REGISTER(Register, fp, x29);
323ALIAS_REGISTER(Register, lr, x30);
324ALIAS_REGISTER(Register, xzr, x31);
325ALIAS_REGISTER(Register, wzr, w31);
326
327// Keeps the 0 double value.
328ALIAS_REGISTER(FPRegister, fp_zero, d15);
329// Crankshaft double scratch register.
330ALIAS_REGISTER(FPRegister, crankshaft_fp_scratch, d29);
331// MacroAssembler double scratch registers.
332ALIAS_REGISTER(FPRegister, fp_scratch, d30);
333ALIAS_REGISTER(FPRegister, fp_scratch1, d30);
334ALIAS_REGISTER(FPRegister, fp_scratch2, d31);
335
336#undef ALIAS_REGISTER
337
338
339Register GetAllocatableRegisterThatIsNotOneOf(Register reg1,
340 Register reg2 = NoReg,
341 Register reg3 = NoReg,
342 Register reg4 = NoReg);
343
344
345// AreAliased returns true if any of the named registers overlap. Arguments set
346// to NoReg are ignored. The system stack pointer may be specified.
347bool AreAliased(const CPURegister& reg1,
348 const CPURegister& reg2,
349 const CPURegister& reg3 = NoReg,
350 const CPURegister& reg4 = NoReg,
351 const CPURegister& reg5 = NoReg,
352 const CPURegister& reg6 = NoReg,
353 const CPURegister& reg7 = NoReg,
354 const CPURegister& reg8 = NoReg);
355
356// AreSameSizeAndType returns true if all of the specified registers have the
357// same size, and are of the same type. The system stack pointer may be
358// specified. Arguments set to NoReg are ignored, as are any subsequent
359// arguments. At least one argument (reg1) must be valid (not NoCPUReg).
360bool AreSameSizeAndType(const CPURegister& reg1,
361 const CPURegister& reg2,
362 const CPURegister& reg3 = NoCPUReg,
363 const CPURegister& reg4 = NoCPUReg,
364 const CPURegister& reg5 = NoCPUReg,
365 const CPURegister& reg6 = NoCPUReg,
366 const CPURegister& reg7 = NoCPUReg,
367 const CPURegister& reg8 = NoCPUReg);
368
369
370typedef FPRegister DoubleRegister;
371
372
373// -----------------------------------------------------------------------------
374// Lists of registers.
375class CPURegList {
376 public:
377 explicit CPURegList(CPURegister reg1,
378 CPURegister reg2 = NoCPUReg,
379 CPURegister reg3 = NoCPUReg,
380 CPURegister reg4 = NoCPUReg)
381 : list_(reg1.Bit() | reg2.Bit() | reg3.Bit() | reg4.Bit()),
382 size_(reg1.SizeInBits()), type_(reg1.type()) {
383 DCHECK(AreSameSizeAndType(reg1, reg2, reg3, reg4));
384 DCHECK(IsValid());
385 }
386
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000387 CPURegList(CPURegister::RegisterType type, int size, RegList list)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000388 : list_(list), size_(size), type_(type) {
389 DCHECK(IsValid());
390 }
391
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000392 CPURegList(CPURegister::RegisterType type, int size, int first_reg,
393 int last_reg)
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000394 : size_(size), type_(type) {
395 DCHECK(((type == CPURegister::kRegister) &&
396 (last_reg < kNumberOfRegisters)) ||
397 ((type == CPURegister::kFPRegister) &&
398 (last_reg < kNumberOfFPRegisters)));
399 DCHECK(last_reg >= first_reg);
400 list_ = (1UL << (last_reg + 1)) - 1;
401 list_ &= ~((1UL << first_reg) - 1);
402 DCHECK(IsValid());
403 }
404
405 CPURegister::RegisterType type() const {
406 DCHECK(IsValid());
407 return type_;
408 }
409
410 RegList list() const {
411 DCHECK(IsValid());
412 return list_;
413 }
414
415 inline void set_list(RegList new_list) {
416 DCHECK(IsValid());
417 list_ = new_list;
418 }
419
420 // Combine another CPURegList into this one. Registers that already exist in
421 // this list are left unchanged. The type and size of the registers in the
422 // 'other' list must match those in this list.
423 void Combine(const CPURegList& other);
424
425 // Remove every register in the other CPURegList from this one. Registers that
426 // do not exist in this list are ignored. The type of the registers in the
427 // 'other' list must match those in this list.
428 void Remove(const CPURegList& other);
429
430 // Variants of Combine and Remove which take CPURegisters.
431 void Combine(const CPURegister& other);
432 void Remove(const CPURegister& other1,
433 const CPURegister& other2 = NoCPUReg,
434 const CPURegister& other3 = NoCPUReg,
435 const CPURegister& other4 = NoCPUReg);
436
437 // Variants of Combine and Remove which take a single register by its code;
438 // the type and size of the register is inferred from this list.
439 void Combine(int code);
440 void Remove(int code);
441
442 // Remove all callee-saved registers from the list. This can be useful when
443 // preparing registers for an AAPCS64 function call, for example.
444 void RemoveCalleeSaved();
445
446 CPURegister PopLowestIndex();
447 CPURegister PopHighestIndex();
448
449 // AAPCS64 callee-saved registers.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000450 static CPURegList GetCalleeSaved(int size = kXRegSizeInBits);
451 static CPURegList GetCalleeSavedFP(int size = kDRegSizeInBits);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000452
453 // AAPCS64 caller-saved registers. Note that this includes lr.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000454 static CPURegList GetCallerSaved(int size = kXRegSizeInBits);
455 static CPURegList GetCallerSavedFP(int size = kDRegSizeInBits);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000456
457 // Registers saved as safepoints.
458 static CPURegList GetSafepointSavedRegisters();
459
460 bool IsEmpty() const {
461 DCHECK(IsValid());
462 return list_ == 0;
463 }
464
465 bool IncludesAliasOf(const CPURegister& other1,
466 const CPURegister& other2 = NoCPUReg,
467 const CPURegister& other3 = NoCPUReg,
468 const CPURegister& other4 = NoCPUReg) const {
469 DCHECK(IsValid());
470 RegList list = 0;
471 if (!other1.IsNone() && (other1.type() == type_)) list |= other1.Bit();
472 if (!other2.IsNone() && (other2.type() == type_)) list |= other2.Bit();
473 if (!other3.IsNone() && (other3.type() == type_)) list |= other3.Bit();
474 if (!other4.IsNone() && (other4.type() == type_)) list |= other4.Bit();
475 return (list_ & list) != 0;
476 }
477
478 int Count() const {
479 DCHECK(IsValid());
480 return CountSetBits(list_, kRegListSizeInBits);
481 }
482
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000483 int RegisterSizeInBits() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000484 DCHECK(IsValid());
485 return size_;
486 }
487
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000488 int RegisterSizeInBytes() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000489 int size_in_bits = RegisterSizeInBits();
490 DCHECK((size_in_bits % kBitsPerByte) == 0);
491 return size_in_bits / kBitsPerByte;
492 }
493
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000494 int TotalSizeInBytes() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000495 DCHECK(IsValid());
496 return RegisterSizeInBytes() * Count();
497 }
498
499 private:
500 RegList list_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000501 int size_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000502 CPURegister::RegisterType type_;
503
504 bool IsValid() const {
505 const RegList kValidRegisters = 0x8000000ffffffff;
506 const RegList kValidFPRegisters = 0x0000000ffffffff;
507 switch (type_) {
508 case CPURegister::kRegister:
509 return (list_ & kValidRegisters) == list_;
510 case CPURegister::kFPRegister:
511 return (list_ & kValidFPRegisters) == list_;
512 case CPURegister::kNoRegister:
513 return list_ == 0;
514 default:
515 UNREACHABLE();
516 return false;
517 }
518 }
519};
520
521
522// AAPCS64 callee-saved registers.
523#define kCalleeSaved CPURegList::GetCalleeSaved()
524#define kCalleeSavedFP CPURegList::GetCalleeSavedFP()
525
526
527// AAPCS64 caller-saved registers. Note that this includes lr.
528#define kCallerSaved CPURegList::GetCallerSaved()
529#define kCallerSavedFP CPURegList::GetCallerSavedFP()
530
531// -----------------------------------------------------------------------------
532// Immediates.
533class Immediate {
534 public:
535 template<typename T>
536 inline explicit Immediate(Handle<T> handle);
537
538 // This is allowed to be an implicit constructor because Immediate is
539 // a wrapper class that doesn't normally perform any type conversion.
540 template<typename T>
541 inline Immediate(T value); // NOLINT(runtime/explicit)
542
543 template<typename T>
544 inline Immediate(T value, RelocInfo::Mode rmode);
545
546 int64_t value() const { return value_; }
547 RelocInfo::Mode rmode() const { return rmode_; }
548
549 private:
550 void InitializeHandle(Handle<Object> value);
551
552 int64_t value_;
553 RelocInfo::Mode rmode_;
554};
555
556
557// -----------------------------------------------------------------------------
558// Operands.
559const int kSmiShift = kSmiTagSize + kSmiShiftSize;
560const uint64_t kSmiShiftMask = (1UL << kSmiShift) - 1;
561
562// Represents an operand in a machine instruction.
563class Operand {
564 // TODO(all): If necessary, study more in details which methods
565 // TODO(all): should be inlined or not.
566 public:
567 // rm, {<shift> {#<shift_amount>}}
568 // where <shift> is one of {LSL, LSR, ASR, ROR}.
569 // <shift_amount> is uint6_t.
570 // This is allowed to be an implicit constructor because Operand is
571 // a wrapper class that doesn't normally perform any type conversion.
572 inline Operand(Register reg,
573 Shift shift = LSL,
574 unsigned shift_amount = 0); // NOLINT(runtime/explicit)
575
576 // rm, <extend> {#<shift_amount>}
577 // where <extend> is one of {UXTB, UXTH, UXTW, UXTX, SXTB, SXTH, SXTW, SXTX}.
578 // <shift_amount> is uint2_t.
579 inline Operand(Register reg,
580 Extend extend,
581 unsigned shift_amount = 0);
582
583 template<typename T>
584 inline explicit Operand(Handle<T> handle);
585
586 // Implicit constructor for all int types, ExternalReference, and Smi.
587 template<typename T>
588 inline Operand(T t); // NOLINT(runtime/explicit)
589
590 // Implicit constructor for int types.
591 template<typename T>
592 inline Operand(T t, RelocInfo::Mode rmode);
593
594 inline bool IsImmediate() const;
595 inline bool IsShiftedRegister() const;
596 inline bool IsExtendedRegister() const;
597 inline bool IsZero() const;
598
599 // This returns an LSL shift (<= 4) operand as an equivalent extend operand,
600 // which helps in the encoding of instructions that use the stack pointer.
601 inline Operand ToExtendedRegister() const;
602
603 inline Immediate immediate() const;
604 inline int64_t ImmediateValue() const;
605 inline Register reg() const;
606 inline Shift shift() const;
607 inline Extend extend() const;
608 inline unsigned shift_amount() const;
609
610 // Relocation information.
611 bool NeedsRelocation(const Assembler* assembler) const;
612
613 // Helpers
614 inline static Operand UntagSmi(Register smi);
615 inline static Operand UntagSmiAndScale(Register smi, int scale);
616
617 private:
618 Immediate immediate_;
619 Register reg_;
620 Shift shift_;
621 Extend extend_;
622 unsigned shift_amount_;
623};
624
625
626// MemOperand represents a memory operand in a load or store instruction.
627class MemOperand {
628 public:
629 inline MemOperand();
630 inline explicit MemOperand(Register base,
631 int64_t offset = 0,
632 AddrMode addrmode = Offset);
633 inline explicit MemOperand(Register base,
634 Register regoffset,
635 Shift shift = LSL,
636 unsigned shift_amount = 0);
637 inline explicit MemOperand(Register base,
638 Register regoffset,
639 Extend extend,
640 unsigned shift_amount = 0);
641 inline explicit MemOperand(Register base,
642 const Operand& offset,
643 AddrMode addrmode = Offset);
644
645 const Register& base() const { return base_; }
646 const Register& regoffset() const { return regoffset_; }
647 int64_t offset() const { return offset_; }
648 AddrMode addrmode() const { return addrmode_; }
649 Shift shift() const { return shift_; }
650 Extend extend() const { return extend_; }
651 unsigned shift_amount() const { return shift_amount_; }
652 inline bool IsImmediateOffset() const;
653 inline bool IsRegisterOffset() const;
654 inline bool IsPreIndex() const;
655 inline bool IsPostIndex() const;
656
657 // For offset modes, return the offset as an Operand. This helper cannot
658 // handle indexed modes.
659 inline Operand OffsetAsOperand() const;
660
661 enum PairResult {
662 kNotPair, // Can't use a pair instruction.
663 kPairAB, // Can use a pair instruction (operandA has lower address).
664 kPairBA // Can use a pair instruction (operandB has lower address).
665 };
666 // Check if two MemOperand are consistent for stp/ldp use.
667 static PairResult AreConsistentForPair(const MemOperand& operandA,
668 const MemOperand& operandB,
669 int access_size_log2 = kXRegSizeLog2);
670
671 private:
672 Register base_;
673 Register regoffset_;
674 int64_t offset_;
675 AddrMode addrmode_;
676 Shift shift_;
677 Extend extend_;
678 unsigned shift_amount_;
679};
680
681
682class ConstPool {
683 public:
684 explicit ConstPool(Assembler* assm)
685 : assm_(assm),
686 first_use_(-1),
687 shared_entries_count(0) {}
688 void RecordEntry(intptr_t data, RelocInfo::Mode mode);
689 int EntryCount() const {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000690 return shared_entries_count + static_cast<int>(unique_entries_.size());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000691 }
692 bool IsEmpty() const {
693 return shared_entries_.empty() && unique_entries_.empty();
694 }
695 // Distance in bytes between the current pc and the first instruction
696 // using the pool. If there are no pending entries return kMaxInt.
697 int DistanceToFirstUse();
698 // Offset after which instructions using the pool will be out of range.
699 int MaxPcOffset();
700 // Maximum size the constant pool can be with current entries. It always
701 // includes alignment padding and branch over.
702 int WorstCaseSize();
703 // Size in bytes of the literal pool *if* it is emitted at the current
704 // pc. The size will include the branch over the pool if it was requested.
705 int SizeIfEmittedAtCurrentPc(bool require_jump);
706 // Emit the literal pool at the current pc with a branch over the pool if
707 // requested.
708 void Emit(bool require_jump);
709 // Discard any pending pool entries.
710 void Clear();
711
712 private:
713 bool CanBeShared(RelocInfo::Mode mode);
714 void EmitMarker();
715 void EmitGuard();
716 void EmitEntries();
717
718 Assembler* assm_;
719 // Keep track of the first instruction requiring a constant pool entry
720 // since the previous constant pool was emitted.
721 int first_use_;
722 // values, pc offset(s) of entries which can be shared.
723 std::multimap<uint64_t, int> shared_entries_;
724 // Number of distinct literal in shared entries.
725 int shared_entries_count;
726 // values, pc offset of entries which cannot be shared.
727 std::vector<std::pair<uint64_t, int> > unique_entries_;
728};
729
730
731// -----------------------------------------------------------------------------
732// Assembler.
733
734class Assembler : public AssemblerBase {
735 public:
736 // Create an assembler. Instructions and relocation information are emitted
737 // into a buffer, with the instructions starting from the beginning and the
738 // relocation information starting from the end of the buffer. See CodeDesc
739 // for a detailed comment on the layout (globals.h).
740 //
741 // If the provided buffer is NULL, the assembler allocates and grows its own
742 // buffer, and buffer_size determines the initial buffer size. The buffer is
743 // owned by the assembler and deallocated upon destruction of the assembler.
744 //
745 // If the provided buffer is not NULL, the assembler uses the provided buffer
746 // for code generation and assumes its size to be buffer_size. If the buffer
747 // is too small, a fatal error occurs. No deallocation of the buffer is done
748 // upon destruction of the assembler.
749 Assembler(Isolate* arg_isolate, void* buffer, int buffer_size);
750
751 virtual ~Assembler();
752
753 virtual void AbortedCodeGeneration() {
754 constpool_.Clear();
755 }
756
757 // System functions ---------------------------------------------------------
758 // Start generating code from the beginning of the buffer, discarding any code
759 // and data that has already been emitted into the buffer.
760 //
761 // In order to avoid any accidental transfer of state, Reset DCHECKs that the
762 // constant pool is not blocked.
763 void Reset();
764
765 // GetCode emits any pending (non-emitted) code and fills the descriptor
766 // desc. GetCode() is idempotent; it returns the same result if no other
767 // Assembler functions are invoked in between GetCode() calls.
768 //
769 // The descriptor (desc) can be NULL. In that case, the code is finalized as
770 // usual, but the descriptor is not populated.
771 void GetCode(CodeDesc* desc);
772
773 // Insert the smallest number of nop instructions
774 // possible to align the pc offset to a multiple
775 // of m. m must be a power of 2 (>= 4).
776 void Align(int m);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000777 // Insert the smallest number of zero bytes possible to align the pc offset
778 // to a mulitple of m. m must be a power of 2 (>= 2).
779 void DataAlign(int m);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000780
781 inline void Unreachable();
782
783 // Label --------------------------------------------------------------------
784 // Bind a label to the current pc. Note that labels can only be bound once,
785 // and if labels are linked to other instructions, they _must_ be bound
786 // before they go out of scope.
787 void bind(Label* label);
788
789
790 // RelocInfo and pools ------------------------------------------------------
791
792 // Record relocation information for current pc_.
793 void RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data = 0);
794
795 // Return the address in the constant pool of the code target address used by
796 // the branch/call instruction at pc.
797 inline static Address target_pointer_address_at(Address pc);
798
799 // Read/Modify the code target address in the branch/call instruction at pc.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000800 inline static Address target_address_at(Address pc, Address constant_pool);
801 inline static void set_target_address_at(
802 Isolate* isolate, Address pc, Address constant_pool, Address target,
803 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000804 static inline Address target_address_at(Address pc, Code* code);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000805 static inline void set_target_address_at(
806 Isolate* isolate, Address pc, Code* code, Address target,
807 ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000808
809 // Return the code target address at a call site from the return address of
810 // that call in the instruction stream.
811 inline static Address target_address_from_return_address(Address pc);
812
813 // Given the address of the beginning of a call, return the address in the
814 // instruction stream that call will return from.
815 inline static Address return_address_from_call_start(Address pc);
816
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000817 // This sets the branch destination (which is in the constant pool on ARM).
818 // This is for calls and branches within generated code.
819 inline static void deserialization_set_special_target_at(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000820 Isolate* isolate, Address constant_pool_entry, Code* code,
821 Address target);
822
823 // This sets the internal reference at the pc.
824 inline static void deserialization_set_target_internal_reference_at(
825 Isolate* isolate, Address pc, Address target,
826 RelocInfo::Mode mode = RelocInfo::INTERNAL_REFERENCE);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000827
828 // All addresses in the constant pool are the same size as pointers.
829 static const int kSpecialTargetSize = kPointerSize;
830
831 // The sizes of the call sequences emitted by MacroAssembler::Call.
832 // Wherever possible, use MacroAssembler::CallSize instead of these constants,
833 // as it will choose the correct value for a given relocation mode.
834 //
835 // Without relocation:
836 // movz temp, #(target & 0x000000000000ffff)
837 // movk temp, #(target & 0x00000000ffff0000)
838 // movk temp, #(target & 0x0000ffff00000000)
839 // blr temp
840 //
841 // With relocation:
842 // ldr temp, =target
843 // blr temp
844 static const int kCallSizeWithoutRelocation = 4 * kInstructionSize;
845 static const int kCallSizeWithRelocation = 2 * kInstructionSize;
846
847 // Size of the generated code in bytes
848 uint64_t SizeOfGeneratedCode() const {
849 DCHECK((pc_ >= buffer_) && (pc_ < (buffer_ + buffer_size_)));
850 return pc_ - buffer_;
851 }
852
853 // Return the code size generated from label to the current position.
854 uint64_t SizeOfCodeGeneratedSince(const Label* label) {
855 DCHECK(label->is_bound());
856 DCHECK(pc_offset() >= label->pos());
857 DCHECK(pc_offset() < buffer_size_);
858 return pc_offset() - label->pos();
859 }
860
861 // Check the size of the code generated since the given label. This function
862 // is used primarily to work around comparisons between signed and unsigned
863 // quantities, since V8 uses both.
864 // TODO(jbramley): Work out what sign to use for these things and if possible,
865 // change things to be consistent.
866 void AssertSizeOfCodeGeneratedSince(const Label* label, ptrdiff_t size) {
867 DCHECK(size >= 0);
868 DCHECK(static_cast<uint64_t>(size) == SizeOfCodeGeneratedSince(label));
869 }
870
871 // Return the number of instructions generated from label to the
872 // current position.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000873 uint64_t InstructionsGeneratedSince(const Label* label) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000874 return SizeOfCodeGeneratedSince(label) / kInstructionSize;
875 }
876
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000877 static const int kPatchDebugBreakSlotAddressOffset = 0;
878
879 // Number of instructions necessary to be able to later patch it to a call.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000880 static const int kDebugBreakSlotInstructions = 5;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000881 static const int kDebugBreakSlotLength =
882 kDebugBreakSlotInstructions * kInstructionSize;
883
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000884 // Prevent contant pool emission until EndBlockConstPool is called.
885 // Call to this function can be nested but must be followed by an equal
886 // number of call to EndBlockConstpool.
887 void StartBlockConstPool();
888
889 // Resume constant pool emission. Need to be called as many time as
890 // StartBlockConstPool to have an effect.
891 void EndBlockConstPool();
892
893 bool is_const_pool_blocked() const;
894 static bool IsConstantPoolAt(Instruction* instr);
895 static int ConstantPoolSizeAt(Instruction* instr);
896 // See Assembler::CheckConstPool for more info.
897 void EmitPoolGuard();
898
899 // Prevent veneer pool emission until EndBlockVeneerPool is called.
900 // Call to this function can be nested but must be followed by an equal
901 // number of call to EndBlockConstpool.
902 void StartBlockVeneerPool();
903
904 // Resume constant pool emission. Need to be called as many time as
905 // StartBlockVeneerPool to have an effect.
906 void EndBlockVeneerPool();
907
908 bool is_veneer_pool_blocked() const {
909 return veneer_pool_blocked_nesting_ > 0;
910 }
911
912 // Block/resume emission of constant pools and veneer pools.
913 void StartBlockPools() {
914 StartBlockConstPool();
915 StartBlockVeneerPool();
916 }
917 void EndBlockPools() {
918 EndBlockConstPool();
919 EndBlockVeneerPool();
920 }
921
922 // Debugging ----------------------------------------------------------------
923 PositionsRecorder* positions_recorder() { return &positions_recorder_; }
924 void RecordComment(const char* msg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000925
926 // Record a deoptimization reason that can be used by a log or cpu profiler.
927 // Use --trace-deopt to enable.
928 void RecordDeoptReason(const int reason, const SourcePosition position);
929
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000930 int buffer_space() const;
931
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000932 // Mark generator continuation.
933 void RecordGeneratorContinuation();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000934
935 // Mark address of a debug break slot.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000936 void RecordDebugBreakSlot(RelocInfo::Mode mode);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000937
938 // Record the emission of a constant pool.
939 //
940 // The emission of constant and veneer pools depends on the size of the code
941 // generated and the number of RelocInfo recorded.
942 // The Debug mechanism needs to map code offsets between two versions of a
943 // function, compiled with and without debugger support (see for example
944 // Debug::PrepareForBreakPoints()).
945 // Compiling functions with debugger support generates additional code
946 // (DebugCodegen::GenerateSlot()). This may affect the emission of the pools
947 // and cause the version of the code with debugger support to have pools
948 // generated in different places.
949 // Recording the position and size of emitted pools allows to correctly
950 // compute the offset mappings between the different versions of a function in
951 // all situations.
952 //
953 // The parameter indicates the size of the pool (in bytes), including
954 // the marker and branch over the data.
955 void RecordConstPool(int size);
956
957
958 // Instruction set functions ------------------------------------------------
959
960 // Branch / Jump instructions.
961 // For branches offsets are scaled, i.e. they in instrcutions not in bytes.
962 // Branch to register.
963 void br(const Register& xn);
964
965 // Branch-link to register.
966 void blr(const Register& xn);
967
968 // Branch to register with return hint.
969 void ret(const Register& xn = lr);
970
971 // Unconditional branch to label.
972 void b(Label* label);
973
974 // Conditional branch to label.
975 void b(Label* label, Condition cond);
976
977 // Unconditional branch to PC offset.
978 void b(int imm26);
979
980 // Conditional branch to PC offset.
981 void b(int imm19, Condition cond);
982
983 // Branch-link to label / pc offset.
984 void bl(Label* label);
985 void bl(int imm26);
986
987 // Compare and branch to label / pc offset if zero.
988 void cbz(const Register& rt, Label* label);
989 void cbz(const Register& rt, int imm19);
990
991 // Compare and branch to label / pc offset if not zero.
992 void cbnz(const Register& rt, Label* label);
993 void cbnz(const Register& rt, int imm19);
994
995 // Test bit and branch to label / pc offset if zero.
996 void tbz(const Register& rt, unsigned bit_pos, Label* label);
997 void tbz(const Register& rt, unsigned bit_pos, int imm14);
998
999 // Test bit and branch to label / pc offset if not zero.
1000 void tbnz(const Register& rt, unsigned bit_pos, Label* label);
1001 void tbnz(const Register& rt, unsigned bit_pos, int imm14);
1002
1003 // Address calculation instructions.
1004 // Calculate a PC-relative address. Unlike for branches the offset in adr is
1005 // unscaled (i.e. the result can be unaligned).
1006 void adr(const Register& rd, Label* label);
1007 void adr(const Register& rd, int imm21);
1008
1009 // Data Processing instructions.
1010 // Add.
1011 void add(const Register& rd,
1012 const Register& rn,
1013 const Operand& operand);
1014
1015 // Add and update status flags.
1016 void adds(const Register& rd,
1017 const Register& rn,
1018 const Operand& operand);
1019
1020 // Compare negative.
1021 void cmn(const Register& rn, const Operand& operand);
1022
1023 // Subtract.
1024 void sub(const Register& rd,
1025 const Register& rn,
1026 const Operand& operand);
1027
1028 // Subtract and update status flags.
1029 void subs(const Register& rd,
1030 const Register& rn,
1031 const Operand& operand);
1032
1033 // Compare.
1034 void cmp(const Register& rn, const Operand& operand);
1035
1036 // Negate.
1037 void neg(const Register& rd,
1038 const Operand& operand);
1039
1040 // Negate and update status flags.
1041 void negs(const Register& rd,
1042 const Operand& operand);
1043
1044 // Add with carry bit.
1045 void adc(const Register& rd,
1046 const Register& rn,
1047 const Operand& operand);
1048
1049 // Add with carry bit and update status flags.
1050 void adcs(const Register& rd,
1051 const Register& rn,
1052 const Operand& operand);
1053
1054 // Subtract with carry bit.
1055 void sbc(const Register& rd,
1056 const Register& rn,
1057 const Operand& operand);
1058
1059 // Subtract with carry bit and update status flags.
1060 void sbcs(const Register& rd,
1061 const Register& rn,
1062 const Operand& operand);
1063
1064 // Negate with carry bit.
1065 void ngc(const Register& rd,
1066 const Operand& operand);
1067
1068 // Negate with carry bit and update status flags.
1069 void ngcs(const Register& rd,
1070 const Operand& operand);
1071
1072 // Logical instructions.
1073 // Bitwise and (A & B).
1074 void and_(const Register& rd,
1075 const Register& rn,
1076 const Operand& operand);
1077
1078 // Bitwise and (A & B) and update status flags.
1079 void ands(const Register& rd,
1080 const Register& rn,
1081 const Operand& operand);
1082
1083 // Bit test, and set flags.
1084 void tst(const Register& rn, const Operand& operand);
1085
1086 // Bit clear (A & ~B).
1087 void bic(const Register& rd,
1088 const Register& rn,
1089 const Operand& operand);
1090
1091 // Bit clear (A & ~B) and update status flags.
1092 void bics(const Register& rd,
1093 const Register& rn,
1094 const Operand& operand);
1095
1096 // Bitwise or (A | B).
1097 void orr(const Register& rd, const Register& rn, const Operand& operand);
1098
1099 // Bitwise nor (A | ~B).
1100 void orn(const Register& rd, const Register& rn, const Operand& operand);
1101
1102 // Bitwise eor/xor (A ^ B).
1103 void eor(const Register& rd, const Register& rn, const Operand& operand);
1104
1105 // Bitwise enor/xnor (A ^ ~B).
1106 void eon(const Register& rd, const Register& rn, const Operand& operand);
1107
1108 // Logical shift left variable.
1109 void lslv(const Register& rd, const Register& rn, const Register& rm);
1110
1111 // Logical shift right variable.
1112 void lsrv(const Register& rd, const Register& rn, const Register& rm);
1113
1114 // Arithmetic shift right variable.
1115 void asrv(const Register& rd, const Register& rn, const Register& rm);
1116
1117 // Rotate right variable.
1118 void rorv(const Register& rd, const Register& rn, const Register& rm);
1119
1120 // Bitfield instructions.
1121 // Bitfield move.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001122 void bfm(const Register& rd, const Register& rn, int immr, int imms);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001123
1124 // Signed bitfield move.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001125 void sbfm(const Register& rd, const Register& rn, int immr, int imms);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001126
1127 // Unsigned bitfield move.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001128 void ubfm(const Register& rd, const Register& rn, int immr, int imms);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001129
1130 // Bfm aliases.
1131 // Bitfield insert.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001132 void bfi(const Register& rd, const Register& rn, int lsb, int width) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001133 DCHECK(width >= 1);
1134 DCHECK(lsb + width <= rn.SizeInBits());
1135 bfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1);
1136 }
1137
1138 // Bitfield extract and insert low.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001139 void bfxil(const Register& rd, const Register& rn, int lsb, int width) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001140 DCHECK(width >= 1);
1141 DCHECK(lsb + width <= rn.SizeInBits());
1142 bfm(rd, rn, lsb, lsb + width - 1);
1143 }
1144
1145 // Sbfm aliases.
1146 // Arithmetic shift right.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001147 void asr(const Register& rd, const Register& rn, int shift) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001148 DCHECK(shift < rd.SizeInBits());
1149 sbfm(rd, rn, shift, rd.SizeInBits() - 1);
1150 }
1151
1152 // Signed bitfield insert in zero.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001153 void sbfiz(const Register& rd, const Register& rn, int lsb, int width) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001154 DCHECK(width >= 1);
1155 DCHECK(lsb + width <= rn.SizeInBits());
1156 sbfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1);
1157 }
1158
1159 // Signed bitfield extract.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001160 void sbfx(const Register& rd, const Register& rn, int lsb, int width) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001161 DCHECK(width >= 1);
1162 DCHECK(lsb + width <= rn.SizeInBits());
1163 sbfm(rd, rn, lsb, lsb + width - 1);
1164 }
1165
1166 // Signed extend byte.
1167 void sxtb(const Register& rd, const Register& rn) {
1168 sbfm(rd, rn, 0, 7);
1169 }
1170
1171 // Signed extend halfword.
1172 void sxth(const Register& rd, const Register& rn) {
1173 sbfm(rd, rn, 0, 15);
1174 }
1175
1176 // Signed extend word.
1177 void sxtw(const Register& rd, const Register& rn) {
1178 sbfm(rd, rn, 0, 31);
1179 }
1180
1181 // Ubfm aliases.
1182 // Logical shift left.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001183 void lsl(const Register& rd, const Register& rn, int shift) {
1184 int reg_size = rd.SizeInBits();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001185 DCHECK(shift < reg_size);
1186 ubfm(rd, rn, (reg_size - shift) % reg_size, reg_size - shift - 1);
1187 }
1188
1189 // Logical shift right.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001190 void lsr(const Register& rd, const Register& rn, int shift) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001191 DCHECK(shift < rd.SizeInBits());
1192 ubfm(rd, rn, shift, rd.SizeInBits() - 1);
1193 }
1194
1195 // Unsigned bitfield insert in zero.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001196 void ubfiz(const Register& rd, const Register& rn, int lsb, int width) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001197 DCHECK(width >= 1);
1198 DCHECK(lsb + width <= rn.SizeInBits());
1199 ubfm(rd, rn, (rd.SizeInBits() - lsb) & (rd.SizeInBits() - 1), width - 1);
1200 }
1201
1202 // Unsigned bitfield extract.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001203 void ubfx(const Register& rd, const Register& rn, int lsb, int width) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001204 DCHECK(width >= 1);
1205 DCHECK(lsb + width <= rn.SizeInBits());
1206 ubfm(rd, rn, lsb, lsb + width - 1);
1207 }
1208
1209 // Unsigned extend byte.
1210 void uxtb(const Register& rd, const Register& rn) {
1211 ubfm(rd, rn, 0, 7);
1212 }
1213
1214 // Unsigned extend halfword.
1215 void uxth(const Register& rd, const Register& rn) {
1216 ubfm(rd, rn, 0, 15);
1217 }
1218
1219 // Unsigned extend word.
1220 void uxtw(const Register& rd, const Register& rn) {
1221 ubfm(rd, rn, 0, 31);
1222 }
1223
1224 // Extract.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001225 void extr(const Register& rd, const Register& rn, const Register& rm,
1226 int lsb);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001227
1228 // Conditional select: rd = cond ? rn : rm.
1229 void csel(const Register& rd,
1230 const Register& rn,
1231 const Register& rm,
1232 Condition cond);
1233
1234 // Conditional select increment: rd = cond ? rn : rm + 1.
1235 void csinc(const Register& rd,
1236 const Register& rn,
1237 const Register& rm,
1238 Condition cond);
1239
1240 // Conditional select inversion: rd = cond ? rn : ~rm.
1241 void csinv(const Register& rd,
1242 const Register& rn,
1243 const Register& rm,
1244 Condition cond);
1245
1246 // Conditional select negation: rd = cond ? rn : -rm.
1247 void csneg(const Register& rd,
1248 const Register& rn,
1249 const Register& rm,
1250 Condition cond);
1251
1252 // Conditional set: rd = cond ? 1 : 0.
1253 void cset(const Register& rd, Condition cond);
1254
1255 // Conditional set minus: rd = cond ? -1 : 0.
1256 void csetm(const Register& rd, Condition cond);
1257
1258 // Conditional increment: rd = cond ? rn + 1 : rn.
1259 void cinc(const Register& rd, const Register& rn, Condition cond);
1260
1261 // Conditional invert: rd = cond ? ~rn : rn.
1262 void cinv(const Register& rd, const Register& rn, Condition cond);
1263
1264 // Conditional negate: rd = cond ? -rn : rn.
1265 void cneg(const Register& rd, const Register& rn, Condition cond);
1266
1267 // Extr aliases.
1268 void ror(const Register& rd, const Register& rs, unsigned shift) {
1269 extr(rd, rs, rs, shift);
1270 }
1271
1272 // Conditional comparison.
1273 // Conditional compare negative.
1274 void ccmn(const Register& rn,
1275 const Operand& operand,
1276 StatusFlags nzcv,
1277 Condition cond);
1278
1279 // Conditional compare.
1280 void ccmp(const Register& rn,
1281 const Operand& operand,
1282 StatusFlags nzcv,
1283 Condition cond);
1284
1285 // Multiplication.
1286 // 32 x 32 -> 32-bit and 64 x 64 -> 64-bit multiply.
1287 void mul(const Register& rd, const Register& rn, const Register& rm);
1288
1289 // 32 + 32 x 32 -> 32-bit and 64 + 64 x 64 -> 64-bit multiply accumulate.
1290 void madd(const Register& rd,
1291 const Register& rn,
1292 const Register& rm,
1293 const Register& ra);
1294
1295 // -(32 x 32) -> 32-bit and -(64 x 64) -> 64-bit multiply.
1296 void mneg(const Register& rd, const Register& rn, const Register& rm);
1297
1298 // 32 - 32 x 32 -> 32-bit and 64 - 64 x 64 -> 64-bit multiply subtract.
1299 void msub(const Register& rd,
1300 const Register& rn,
1301 const Register& rm,
1302 const Register& ra);
1303
1304 // 32 x 32 -> 64-bit multiply.
1305 void smull(const Register& rd, const Register& rn, const Register& rm);
1306
1307 // Xd = bits<127:64> of Xn * Xm.
1308 void smulh(const Register& rd, const Register& rn, const Register& rm);
1309
1310 // Signed 32 x 32 -> 64-bit multiply and accumulate.
1311 void smaddl(const Register& rd,
1312 const Register& rn,
1313 const Register& rm,
1314 const Register& ra);
1315
1316 // Unsigned 32 x 32 -> 64-bit multiply and accumulate.
1317 void umaddl(const Register& rd,
1318 const Register& rn,
1319 const Register& rm,
1320 const Register& ra);
1321
1322 // Signed 32 x 32 -> 64-bit multiply and subtract.
1323 void smsubl(const Register& rd,
1324 const Register& rn,
1325 const Register& rm,
1326 const Register& ra);
1327
1328 // Unsigned 32 x 32 -> 64-bit multiply and subtract.
1329 void umsubl(const Register& rd,
1330 const Register& rn,
1331 const Register& rm,
1332 const Register& ra);
1333
1334 // Signed integer divide.
1335 void sdiv(const Register& rd, const Register& rn, const Register& rm);
1336
1337 // Unsigned integer divide.
1338 void udiv(const Register& rd, const Register& rn, const Register& rm);
1339
1340 // Bit count, bit reverse and endian reverse.
1341 void rbit(const Register& rd, const Register& rn);
1342 void rev16(const Register& rd, const Register& rn);
1343 void rev32(const Register& rd, const Register& rn);
1344 void rev(const Register& rd, const Register& rn);
1345 void clz(const Register& rd, const Register& rn);
1346 void cls(const Register& rd, const Register& rn);
1347
1348 // Memory instructions.
1349
1350 // Load integer or FP register.
1351 void ldr(const CPURegister& rt, const MemOperand& src);
1352
1353 // Store integer or FP register.
1354 void str(const CPURegister& rt, const MemOperand& dst);
1355
1356 // Load word with sign extension.
1357 void ldrsw(const Register& rt, const MemOperand& src);
1358
1359 // Load byte.
1360 void ldrb(const Register& rt, const MemOperand& src);
1361
1362 // Store byte.
1363 void strb(const Register& rt, const MemOperand& dst);
1364
1365 // Load byte with sign extension.
1366 void ldrsb(const Register& rt, const MemOperand& src);
1367
1368 // Load half-word.
1369 void ldrh(const Register& rt, const MemOperand& src);
1370
1371 // Store half-word.
1372 void strh(const Register& rt, const MemOperand& dst);
1373
1374 // Load half-word with sign extension.
1375 void ldrsh(const Register& rt, const MemOperand& src);
1376
1377 // Load integer or FP register pair.
1378 void ldp(const CPURegister& rt, const CPURegister& rt2,
1379 const MemOperand& src);
1380
1381 // Store integer or FP register pair.
1382 void stp(const CPURegister& rt, const CPURegister& rt2,
1383 const MemOperand& dst);
1384
1385 // Load word pair with sign extension.
1386 void ldpsw(const Register& rt, const Register& rt2, const MemOperand& src);
1387
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001388 // Load literal to register from a pc relative address.
1389 void ldr_pcrel(const CPURegister& rt, int imm19);
1390
1391 // Load literal to register.
1392 void ldr(const CPURegister& rt, const Immediate& imm);
1393
1394 // Move instructions. The default shift of -1 indicates that the move
1395 // instruction will calculate an appropriate 16-bit immediate and left shift
1396 // that is equal to the 64-bit immediate argument. If an explicit left shift
1397 // is specified (0, 16, 32 or 48), the immediate must be a 16-bit value.
1398 //
1399 // For movk, an explicit shift can be used to indicate which half word should
1400 // be overwritten, eg. movk(x0, 0, 0) will overwrite the least-significant
1401 // half word with zero, whereas movk(x0, 0, 48) will overwrite the
1402 // most-significant.
1403
1404 // Move and keep.
1405 void movk(const Register& rd, uint64_t imm, int shift = -1) {
1406 MoveWide(rd, imm, shift, MOVK);
1407 }
1408
1409 // Move with non-zero.
1410 void movn(const Register& rd, uint64_t imm, int shift = -1) {
1411 MoveWide(rd, imm, shift, MOVN);
1412 }
1413
1414 // Move with zero.
1415 void movz(const Register& rd, uint64_t imm, int shift = -1) {
1416 MoveWide(rd, imm, shift, MOVZ);
1417 }
1418
1419 // Misc instructions.
1420 // Monitor debug-mode breakpoint.
1421 void brk(int code);
1422
1423 // Halting debug-mode breakpoint.
1424 void hlt(int code);
1425
1426 // Move register to register.
1427 void mov(const Register& rd, const Register& rn);
1428
1429 // Move NOT(operand) to register.
1430 void mvn(const Register& rd, const Operand& operand);
1431
1432 // System instructions.
1433 // Move to register from system register.
1434 void mrs(const Register& rt, SystemRegister sysreg);
1435
1436 // Move from register to system register.
1437 void msr(SystemRegister sysreg, const Register& rt);
1438
1439 // System hint.
1440 void hint(SystemHint code);
1441
1442 // Data memory barrier
1443 void dmb(BarrierDomain domain, BarrierType type);
1444
1445 // Data synchronization barrier
1446 void dsb(BarrierDomain domain, BarrierType type);
1447
1448 // Instruction synchronization barrier
1449 void isb();
1450
1451 // Alias for system instructions.
1452 void nop() { hint(NOP); }
1453
1454 // Different nop operations are used by the code generator to detect certain
1455 // states of the generated code.
1456 enum NopMarkerTypes {
1457 DEBUG_BREAK_NOP,
1458 INTERRUPT_CODE_NOP,
1459 ADR_FAR_NOP,
1460 FIRST_NOP_MARKER = DEBUG_BREAK_NOP,
1461 LAST_NOP_MARKER = ADR_FAR_NOP
1462 };
1463
1464 void nop(NopMarkerTypes n) {
1465 DCHECK((FIRST_NOP_MARKER <= n) && (n <= LAST_NOP_MARKER));
1466 mov(Register::XRegFromCode(n), Register::XRegFromCode(n));
1467 }
1468
1469 // FP instructions.
1470 // Move immediate to FP register.
1471 void fmov(FPRegister fd, double imm);
1472 void fmov(FPRegister fd, float imm);
1473
1474 // Move FP register to register.
1475 void fmov(Register rd, FPRegister fn);
1476
1477 // Move register to FP register.
1478 void fmov(FPRegister fd, Register rn);
1479
1480 // Move FP register to FP register.
1481 void fmov(FPRegister fd, FPRegister fn);
1482
1483 // FP add.
1484 void fadd(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1485
1486 // FP subtract.
1487 void fsub(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1488
1489 // FP multiply.
1490 void fmul(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1491
1492 // FP fused multiply and add.
1493 void fmadd(const FPRegister& fd,
1494 const FPRegister& fn,
1495 const FPRegister& fm,
1496 const FPRegister& fa);
1497
1498 // FP fused multiply and subtract.
1499 void fmsub(const FPRegister& fd,
1500 const FPRegister& fn,
1501 const FPRegister& fm,
1502 const FPRegister& fa);
1503
1504 // FP fused multiply, add and negate.
1505 void fnmadd(const FPRegister& fd,
1506 const FPRegister& fn,
1507 const FPRegister& fm,
1508 const FPRegister& fa);
1509
1510 // FP fused multiply, subtract and negate.
1511 void fnmsub(const FPRegister& fd,
1512 const FPRegister& fn,
1513 const FPRegister& fm,
1514 const FPRegister& fa);
1515
1516 // FP divide.
1517 void fdiv(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1518
1519 // FP maximum.
1520 void fmax(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1521
1522 // FP minimum.
1523 void fmin(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1524
1525 // FP maximum.
1526 void fmaxnm(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1527
1528 // FP minimum.
1529 void fminnm(const FPRegister& fd, const FPRegister& fn, const FPRegister& fm);
1530
1531 // FP absolute.
1532 void fabs(const FPRegister& fd, const FPRegister& fn);
1533
1534 // FP negate.
1535 void fneg(const FPRegister& fd, const FPRegister& fn);
1536
1537 // FP square root.
1538 void fsqrt(const FPRegister& fd, const FPRegister& fn);
1539
1540 // FP round to integer (nearest with ties to away).
1541 void frinta(const FPRegister& fd, const FPRegister& fn);
1542
1543 // FP round to integer (toward minus infinity).
1544 void frintm(const FPRegister& fd, const FPRegister& fn);
1545
1546 // FP round to integer (nearest with ties to even).
1547 void frintn(const FPRegister& fd, const FPRegister& fn);
1548
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001549 // FP round to integer (towards plus infinity).
1550 void frintp(const FPRegister& fd, const FPRegister& fn);
1551
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001552 // FP round to integer (towards zero.)
1553 void frintz(const FPRegister& fd, const FPRegister& fn);
1554
1555 // FP compare registers.
1556 void fcmp(const FPRegister& fn, const FPRegister& fm);
1557
1558 // FP compare immediate.
1559 void fcmp(const FPRegister& fn, double value);
1560
1561 // FP conditional compare.
1562 void fccmp(const FPRegister& fn,
1563 const FPRegister& fm,
1564 StatusFlags nzcv,
1565 Condition cond);
1566
1567 // FP conditional select.
1568 void fcsel(const FPRegister& fd,
1569 const FPRegister& fn,
1570 const FPRegister& fm,
1571 Condition cond);
1572
1573 // Common FP Convert function
1574 void FPConvertToInt(const Register& rd,
1575 const FPRegister& fn,
1576 FPIntegerConvertOp op);
1577
1578 // FP convert between single and double precision.
1579 void fcvt(const FPRegister& fd, const FPRegister& fn);
1580
1581 // Convert FP to unsigned integer (nearest with ties to away).
1582 void fcvtau(const Register& rd, const FPRegister& fn);
1583
1584 // Convert FP to signed integer (nearest with ties to away).
1585 void fcvtas(const Register& rd, const FPRegister& fn);
1586
1587 // Convert FP to unsigned integer (round towards -infinity).
1588 void fcvtmu(const Register& rd, const FPRegister& fn);
1589
1590 // Convert FP to signed integer (round towards -infinity).
1591 void fcvtms(const Register& rd, const FPRegister& fn);
1592
1593 // Convert FP to unsigned integer (nearest with ties to even).
1594 void fcvtnu(const Register& rd, const FPRegister& fn);
1595
1596 // Convert FP to signed integer (nearest with ties to even).
1597 void fcvtns(const Register& rd, const FPRegister& fn);
1598
1599 // Convert FP to unsigned integer (round towards zero).
1600 void fcvtzu(const Register& rd, const FPRegister& fn);
1601
1602 // Convert FP to signed integer (rounf towards zero).
1603 void fcvtzs(const Register& rd, const FPRegister& fn);
1604
1605 // Convert signed integer or fixed point to FP.
1606 void scvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0);
1607
1608 // Convert unsigned integer or fixed point to FP.
1609 void ucvtf(const FPRegister& fd, const Register& rn, unsigned fbits = 0);
1610
1611 // Instruction functions used only for test, debug, and patching.
1612 // Emit raw instructions in the instruction stream.
1613 void dci(Instr raw_inst) { Emit(raw_inst); }
1614
1615 // Emit 8 bits of data in the instruction stream.
1616 void dc8(uint8_t data) { EmitData(&data, sizeof(data)); }
1617
1618 // Emit 32 bits of data in the instruction stream.
1619 void dc32(uint32_t data) { EmitData(&data, sizeof(data)); }
1620
1621 // Emit 64 bits of data in the instruction stream.
1622 void dc64(uint64_t data) { EmitData(&data, sizeof(data)); }
1623
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001624 // Emit an address in the instruction stream.
1625 void dcptr(Label* label);
1626
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001627 // Copy a string into the instruction stream, including the terminating NULL
1628 // character. The instruction pointer (pc_) is then aligned correctly for
1629 // subsequent instructions.
1630 void EmitStringData(const char* string);
1631
1632 // Pseudo-instructions ------------------------------------------------------
1633
1634 // Parameters are described in arm64/instructions-arm64.h.
1635 void debug(const char* message, uint32_t code, Instr params = BREAK);
1636
1637 // Required by V8.
1638 void dd(uint32_t data) { dc32(data); }
1639 void db(uint8_t data) { dc8(data); }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001640 void dq(uint64_t data) { dc64(data); }
1641 void dp(uintptr_t data) { dc64(data); }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001642
1643 // Code generation helpers --------------------------------------------------
1644
1645 bool IsConstPoolEmpty() const { return constpool_.IsEmpty(); }
1646
1647 Instruction* pc() const { return Instruction::Cast(pc_); }
1648
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001649 Instruction* InstructionAt(ptrdiff_t offset) const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001650 return reinterpret_cast<Instruction*>(buffer_ + offset);
1651 }
1652
1653 ptrdiff_t InstructionOffset(Instruction* instr) const {
1654 return reinterpret_cast<byte*>(instr) - buffer_;
1655 }
1656
1657 // Register encoding.
1658 static Instr Rd(CPURegister rd) {
1659 DCHECK(rd.code() != kSPRegInternalCode);
1660 return rd.code() << Rd_offset;
1661 }
1662
1663 static Instr Rn(CPURegister rn) {
1664 DCHECK(rn.code() != kSPRegInternalCode);
1665 return rn.code() << Rn_offset;
1666 }
1667
1668 static Instr Rm(CPURegister rm) {
1669 DCHECK(rm.code() != kSPRegInternalCode);
1670 return rm.code() << Rm_offset;
1671 }
1672
1673 static Instr Ra(CPURegister ra) {
1674 DCHECK(ra.code() != kSPRegInternalCode);
1675 return ra.code() << Ra_offset;
1676 }
1677
1678 static Instr Rt(CPURegister rt) {
1679 DCHECK(rt.code() != kSPRegInternalCode);
1680 return rt.code() << Rt_offset;
1681 }
1682
1683 static Instr Rt2(CPURegister rt2) {
1684 DCHECK(rt2.code() != kSPRegInternalCode);
1685 return rt2.code() << Rt2_offset;
1686 }
1687
1688 // These encoding functions allow the stack pointer to be encoded, and
1689 // disallow the zero register.
1690 static Instr RdSP(Register rd) {
1691 DCHECK(!rd.IsZero());
1692 return (rd.code() & kRegCodeMask) << Rd_offset;
1693 }
1694
1695 static Instr RnSP(Register rn) {
1696 DCHECK(!rn.IsZero());
1697 return (rn.code() & kRegCodeMask) << Rn_offset;
1698 }
1699
1700 // Flags encoding.
1701 inline static Instr Flags(FlagsUpdate S);
1702 inline static Instr Cond(Condition cond);
1703
1704 // PC-relative address encoding.
1705 inline static Instr ImmPCRelAddress(int imm21);
1706
1707 // Branch encoding.
1708 inline static Instr ImmUncondBranch(int imm26);
1709 inline static Instr ImmCondBranch(int imm19);
1710 inline static Instr ImmCmpBranch(int imm19);
1711 inline static Instr ImmTestBranch(int imm14);
1712 inline static Instr ImmTestBranchBit(unsigned bit_pos);
1713
1714 // Data Processing encoding.
1715 inline static Instr SF(Register rd);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001716 inline static Instr ImmAddSub(int imm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001717 inline static Instr ImmS(unsigned imms, unsigned reg_size);
1718 inline static Instr ImmR(unsigned immr, unsigned reg_size);
1719 inline static Instr ImmSetBits(unsigned imms, unsigned reg_size);
1720 inline static Instr ImmRotate(unsigned immr, unsigned reg_size);
1721 inline static Instr ImmLLiteral(int imm19);
1722 inline static Instr BitN(unsigned bitn, unsigned reg_size);
1723 inline static Instr ShiftDP(Shift shift);
1724 inline static Instr ImmDPShift(unsigned amount);
1725 inline static Instr ExtendMode(Extend extend);
1726 inline static Instr ImmExtendShift(unsigned left_shift);
1727 inline static Instr ImmCondCmp(unsigned imm);
1728 inline static Instr Nzcv(StatusFlags nzcv);
1729
1730 static bool IsImmAddSub(int64_t immediate);
1731 static bool IsImmLogical(uint64_t value,
1732 unsigned width,
1733 unsigned* n,
1734 unsigned* imm_s,
1735 unsigned* imm_r);
1736
1737 // MemOperand offset encoding.
1738 inline static Instr ImmLSUnsigned(int imm12);
1739 inline static Instr ImmLS(int imm9);
1740 inline static Instr ImmLSPair(int imm7, LSDataSize size);
1741 inline static Instr ImmShiftLS(unsigned shift_amount);
1742 inline static Instr ImmException(int imm16);
1743 inline static Instr ImmSystemRegister(int imm15);
1744 inline static Instr ImmHint(int imm7);
1745 inline static Instr ImmBarrierDomain(int imm2);
1746 inline static Instr ImmBarrierType(int imm2);
1747 inline static LSDataSize CalcLSDataSize(LoadStoreOp op);
1748
1749 static bool IsImmLSUnscaled(int64_t offset);
1750 static bool IsImmLSScaled(int64_t offset, LSDataSize size);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001751 static bool IsImmLLiteral(int64_t offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001752
1753 // Move immediates encoding.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001754 inline static Instr ImmMoveWide(int imm);
1755 inline static Instr ShiftMoveWide(int shift);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001756
1757 // FP Immediates.
1758 static Instr ImmFP32(float imm);
1759 static Instr ImmFP64(double imm);
1760 inline static Instr FPScale(unsigned scale);
1761
1762 // FP register type.
1763 inline static Instr FPType(FPRegister fd);
1764
1765 // Class for scoping postponing the constant pool generation.
1766 class BlockConstPoolScope {
1767 public:
1768 explicit BlockConstPoolScope(Assembler* assem) : assem_(assem) {
1769 assem_->StartBlockConstPool();
1770 }
1771 ~BlockConstPoolScope() {
1772 assem_->EndBlockConstPool();
1773 }
1774
1775 private:
1776 Assembler* assem_;
1777
1778 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockConstPoolScope);
1779 };
1780
1781 // Check if is time to emit a constant pool.
1782 void CheckConstPool(bool force_emit, bool require_jump);
1783
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001784 void PatchConstantPoolAccessInstruction(int pc_offset, int offset,
1785 ConstantPoolEntry::Access access,
1786 ConstantPoolEntry::Type type) {
1787 // No embedded constant pool support.
1788 UNREACHABLE();
1789 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001790
1791 // Returns true if we should emit a veneer as soon as possible for a branch
1792 // which can at most reach to specified pc.
1793 bool ShouldEmitVeneer(int max_reachable_pc,
1794 int margin = kVeneerDistanceMargin);
1795 bool ShouldEmitVeneers(int margin = kVeneerDistanceMargin) {
1796 return ShouldEmitVeneer(unresolved_branches_first_limit(), margin);
1797 }
1798
1799 // The maximum code size generated for a veneer. Currently one branch
1800 // instruction. This is for code size checking purposes, and can be extended
1801 // in the future for example if we decide to add nops between the veneers.
1802 static const int kMaxVeneerCodeSize = 1 * kInstructionSize;
1803
1804 void RecordVeneerPool(int location_offset, int size);
1805 // Emits veneers for branches that are approaching their maximum range.
1806 // If need_protection is true, the veneers are protected by a branch jumping
1807 // over the code.
1808 void EmitVeneers(bool force_emit, bool need_protection,
1809 int margin = kVeneerDistanceMargin);
1810 void EmitVeneersGuard() { EmitPoolGuard(); }
1811 // Checks whether veneers need to be emitted at this point.
1812 // If force_emit is set, a veneer is generated for *all* unresolved branches.
1813 void CheckVeneerPool(bool force_emit, bool require_jump,
1814 int margin = kVeneerDistanceMargin);
1815
1816 class BlockPoolsScope {
1817 public:
1818 explicit BlockPoolsScope(Assembler* assem) : assem_(assem) {
1819 assem_->StartBlockPools();
1820 }
1821 ~BlockPoolsScope() {
1822 assem_->EndBlockPools();
1823 }
1824
1825 private:
1826 Assembler* assem_;
1827
1828 DISALLOW_IMPLICIT_CONSTRUCTORS(BlockPoolsScope);
1829 };
1830
1831 protected:
1832 inline const Register& AppropriateZeroRegFor(const CPURegister& reg) const;
1833
1834 void LoadStore(const CPURegister& rt,
1835 const MemOperand& addr,
1836 LoadStoreOp op);
1837
1838 void LoadStorePair(const CPURegister& rt, const CPURegister& rt2,
1839 const MemOperand& addr, LoadStorePairOp op);
1840 static bool IsImmLSPair(int64_t offset, LSDataSize size);
1841
1842 void Logical(const Register& rd,
1843 const Register& rn,
1844 const Operand& operand,
1845 LogicalOp op);
1846 void LogicalImmediate(const Register& rd,
1847 const Register& rn,
1848 unsigned n,
1849 unsigned imm_s,
1850 unsigned imm_r,
1851 LogicalOp op);
1852
1853 void ConditionalCompare(const Register& rn,
1854 const Operand& operand,
1855 StatusFlags nzcv,
1856 Condition cond,
1857 ConditionalCompareOp op);
1858 static bool IsImmConditionalCompare(int64_t immediate);
1859
1860 void AddSubWithCarry(const Register& rd,
1861 const Register& rn,
1862 const Operand& operand,
1863 FlagsUpdate S,
1864 AddSubWithCarryOp op);
1865
1866 // Functions for emulating operands not directly supported by the instruction
1867 // set.
1868 void EmitShift(const Register& rd,
1869 const Register& rn,
1870 Shift shift,
1871 unsigned amount);
1872 void EmitExtendShift(const Register& rd,
1873 const Register& rn,
1874 Extend extend,
1875 unsigned left_shift);
1876
1877 void AddSub(const Register& rd,
1878 const Register& rn,
1879 const Operand& operand,
1880 FlagsUpdate S,
1881 AddSubOp op);
1882
1883 static bool IsImmFP32(float imm);
1884 static bool IsImmFP64(double imm);
1885
1886 // Find an appropriate LoadStoreOp or LoadStorePairOp for the specified
1887 // registers. Only simple loads are supported; sign- and zero-extension (such
1888 // as in LDPSW_x or LDRB_w) are not supported.
1889 static inline LoadStoreOp LoadOpFor(const CPURegister& rt);
1890 static inline LoadStorePairOp LoadPairOpFor(const CPURegister& rt,
1891 const CPURegister& rt2);
1892 static inline LoadStoreOp StoreOpFor(const CPURegister& rt);
1893 static inline LoadStorePairOp StorePairOpFor(const CPURegister& rt,
1894 const CPURegister& rt2);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001895 static inline LoadLiteralOp LoadLiteralOpFor(const CPURegister& rt);
1896
1897 // Remove the specified branch from the unbound label link chain.
1898 // If available, a veneer for this label can be used for other branches in the
1899 // chain if the link chain cannot be fixed up without this branch.
1900 void RemoveBranchFromLabelLinkChain(Instruction* branch,
1901 Label* label,
1902 Instruction* label_veneer = NULL);
1903
1904 private:
1905 // Instruction helpers.
1906 void MoveWide(const Register& rd,
1907 uint64_t imm,
1908 int shift,
1909 MoveWideImmediateOp mov_op);
1910 void DataProcShiftedRegister(const Register& rd,
1911 const Register& rn,
1912 const Operand& operand,
1913 FlagsUpdate S,
1914 Instr op);
1915 void DataProcExtendedRegister(const Register& rd,
1916 const Register& rn,
1917 const Operand& operand,
1918 FlagsUpdate S,
1919 Instr op);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001920 void ConditionalSelect(const Register& rd,
1921 const Register& rn,
1922 const Register& rm,
1923 Condition cond,
1924 ConditionalSelectOp op);
1925 void DataProcessing1Source(const Register& rd,
1926 const Register& rn,
1927 DataProcessing1SourceOp op);
1928 void DataProcessing3Source(const Register& rd,
1929 const Register& rn,
1930 const Register& rm,
1931 const Register& ra,
1932 DataProcessing3SourceOp op);
1933 void FPDataProcessing1Source(const FPRegister& fd,
1934 const FPRegister& fn,
1935 FPDataProcessing1SourceOp op);
1936 void FPDataProcessing2Source(const FPRegister& fd,
1937 const FPRegister& fn,
1938 const FPRegister& fm,
1939 FPDataProcessing2SourceOp op);
1940 void FPDataProcessing3Source(const FPRegister& fd,
1941 const FPRegister& fn,
1942 const FPRegister& fm,
1943 const FPRegister& fa,
1944 FPDataProcessing3SourceOp op);
1945
1946 // Label helpers.
1947
1948 // Return an offset for a label-referencing instruction, typically a branch.
1949 int LinkAndGetByteOffsetTo(Label* label);
1950
1951 // This is the same as LinkAndGetByteOffsetTo, but return an offset
1952 // suitable for fields that take instruction offsets.
1953 inline int LinkAndGetInstructionOffsetTo(Label* label);
1954
1955 static const int kStartOfLabelLinkChain = 0;
1956
1957 // Verify that a label's link chain is intact.
1958 void CheckLabelLinkChain(Label const * label);
1959
1960 void RecordLiteral(int64_t imm, unsigned size);
1961
1962 // Postpone the generation of the constant pool for the specified number of
1963 // instructions.
1964 void BlockConstPoolFor(int instructions);
1965
1966 // Set how far from current pc the next constant pool check will be.
1967 void SetNextConstPoolCheckIn(int instructions) {
1968 next_constant_pool_check_ = pc_offset() + instructions * kInstructionSize;
1969 }
1970
1971 // Emit the instruction at pc_.
1972 void Emit(Instr instruction) {
1973 STATIC_ASSERT(sizeof(*pc_) == 1);
1974 STATIC_ASSERT(sizeof(instruction) == kInstructionSize);
1975 DCHECK((pc_ + sizeof(instruction)) <= (buffer_ + buffer_size_));
1976
1977 memcpy(pc_, &instruction, sizeof(instruction));
1978 pc_ += sizeof(instruction);
1979 CheckBuffer();
1980 }
1981
1982 // Emit data inline in the instruction stream.
1983 void EmitData(void const * data, unsigned size) {
1984 DCHECK(sizeof(*pc_) == 1);
1985 DCHECK((pc_ + size) <= (buffer_ + buffer_size_));
1986
1987 // TODO(all): Somehow register we have some data here. Then we can
1988 // disassemble it correctly.
1989 memcpy(pc_, data, size);
1990 pc_ += size;
1991 CheckBuffer();
1992 }
1993
1994 void GrowBuffer();
1995 void CheckBufferSpace();
1996 void CheckBuffer();
1997
1998 // Pc offset of the next constant pool check.
1999 int next_constant_pool_check_;
2000
2001 // Constant pool generation
2002 // Pools are emitted in the instruction stream. They are emitted when:
2003 // * the distance to the first use is above a pre-defined distance or
2004 // * the numbers of entries in the pool is above a pre-defined size or
2005 // * code generation is finished
2006 // If a pool needs to be emitted before code generation is finished a branch
2007 // over the emitted pool will be inserted.
2008
2009 // Constants in the pool may be addresses of functions that gets relocated;
2010 // if so, a relocation info entry is associated to the constant pool entry.
2011
2012 // Repeated checking whether the constant pool should be emitted is rather
2013 // expensive. By default we only check again once a number of instructions
2014 // has been generated. That also means that the sizing of the buffers is not
2015 // an exact science, and that we rely on some slop to not overrun buffers.
2016 static const int kCheckConstPoolInterval = 128;
2017
2018 // Distance to first use after a which a pool will be emitted. Pool entries
2019 // are accessed with pc relative load therefore this cannot be more than
2020 // 1 * MB. Since constant pool emission checks are interval based this value
2021 // is an approximation.
2022 static const int kApproxMaxDistToConstPool = 64 * KB;
2023
2024 // Number of pool entries after which a pool will be emitted. Since constant
2025 // pool emission checks are interval based this value is an approximation.
2026 static const int kApproxMaxPoolEntryCount = 512;
2027
2028 // Emission of the constant pool may be blocked in some code sequences.
2029 int const_pool_blocked_nesting_; // Block emission if this is not zero.
2030 int no_const_pool_before_; // Block emission before this pc offset.
2031
2032 // Emission of the veneer pools may be blocked in some code sequences.
2033 int veneer_pool_blocked_nesting_; // Block emission if this is not zero.
2034
2035 // Relocation info generation
2036 // Each relocation is encoded as a variable size value
2037 static const int kMaxRelocSize = RelocInfoWriter::kMaxSize;
2038 RelocInfoWriter reloc_info_writer;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002039 // Internal reference positions, required for (potential) patching in
2040 // GrowBuffer(); contains only those internal references whose labels
2041 // are already bound.
2042 std::deque<int> internal_reference_positions_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002043
2044 // Relocation info records are also used during code generation as temporary
2045 // containers for constants and code target addresses until they are emitted
2046 // to the constant pool. These pending relocation info records are temporarily
2047 // stored in a separate buffer until a constant pool is emitted.
2048 // If every instruction in a long sequence is accessing the pool, we need one
2049 // pending relocation entry per instruction.
2050
2051 // The pending constant pool.
2052 ConstPool constpool_;
2053
2054 // Relocation for a type-recording IC has the AST id added to it. This
2055 // member variable is a way to pass the information from the call site to
2056 // the relocation info.
2057 TypeFeedbackId recorded_ast_id_;
2058
2059 inline TypeFeedbackId RecordedAstId();
2060 inline void ClearRecordedAstId();
2061
2062 protected:
2063 // Record the AST id of the CallIC being compiled, so that it can be placed
2064 // in the relocation information.
2065 void SetRecordedAstId(TypeFeedbackId ast_id) {
2066 DCHECK(recorded_ast_id_.IsNone());
2067 recorded_ast_id_ = ast_id;
2068 }
2069
2070 // Code generation
2071 // The relocation writer's position is at least kGap bytes below the end of
2072 // the generated instructions. This is so that multi-instruction sequences do
2073 // not have to check for overflow. The same is true for writes of large
2074 // relocation info entries, and debug strings encoded in the instruction
2075 // stream.
2076 static const int kGap = 128;
2077
2078 public:
2079 class FarBranchInfo {
2080 public:
2081 FarBranchInfo(int offset, Label* label)
2082 : pc_offset_(offset), label_(label) {}
2083 // Offset of the branch in the code generation buffer.
2084 int pc_offset_;
2085 // The label branched to.
2086 Label* label_;
2087 };
2088
2089 protected:
2090 // Information about unresolved (forward) branches.
2091 // The Assembler is only allowed to delete out-of-date information from here
2092 // after a label is bound. The MacroAssembler uses this information to
2093 // generate veneers.
2094 //
2095 // The second member gives information about the unresolved branch. The first
2096 // member of the pair is the maximum offset that the branch can reach in the
2097 // buffer. The map is sorted according to this reachable offset, allowing to
2098 // easily check when veneers need to be emitted.
2099 // Note that the maximum reachable offset (first member of the pairs) should
2100 // always be positive but has the same type as the return value for
2101 // pc_offset() for convenience.
2102 std::multimap<int, FarBranchInfo> unresolved_branches_;
2103
2104 // We generate a veneer for a branch if we reach within this distance of the
2105 // limit of the range.
2106 static const int kVeneerDistanceMargin = 1 * KB;
2107 // The factor of 2 is a finger in the air guess. With a default margin of
2108 // 1KB, that leaves us an addional 256 instructions to avoid generating a
2109 // protective branch.
2110 static const int kVeneerNoProtectionFactor = 2;
2111 static const int kVeneerDistanceCheckMargin =
2112 kVeneerNoProtectionFactor * kVeneerDistanceMargin;
2113 int unresolved_branches_first_limit() const {
2114 DCHECK(!unresolved_branches_.empty());
2115 return unresolved_branches_.begin()->first;
2116 }
2117 // This is similar to next_constant_pool_check_ and helps reduce the overhead
2118 // of checking for veneer pools.
2119 // It is maintained to the closest unresolved branch limit minus the maximum
2120 // veneer margin (or kMaxInt if there are no unresolved branches).
2121 int next_veneer_pool_check_;
2122
2123 private:
2124 // If a veneer is emitted for a branch instruction, that instruction must be
2125 // removed from the associated label's link chain so that the assembler does
2126 // not later attempt (likely unsuccessfully) to patch it to branch directly to
2127 // the label.
2128 void DeleteUnresolvedBranchInfoForLabel(Label* label);
2129 // This function deletes the information related to the label by traversing
2130 // the label chain, and for each PC-relative instruction in the chain checking
2131 // if pending unresolved information exists. Its complexity is proportional to
2132 // the length of the label chain.
2133 void DeleteUnresolvedBranchInfoForLabelTraverse(Label* label);
2134
2135 private:
2136 PositionsRecorder positions_recorder_;
2137 friend class PositionsRecorder;
2138 friend class EnsureSpace;
2139 friend class ConstPool;
2140};
2141
2142class PatchingAssembler : public Assembler {
2143 public:
2144 // Create an Assembler with a buffer starting at 'start'.
2145 // The buffer size is
2146 // size of instructions to patch + kGap
2147 // Where kGap is the distance from which the Assembler tries to grow the
2148 // buffer.
2149 // If more or fewer instructions than expected are generated or if some
2150 // relocation information takes space in the buffer, the PatchingAssembler
2151 // will crash trying to grow the buffer.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002152 PatchingAssembler(Isolate* isolate, Instruction* start, unsigned count)
2153 : Assembler(isolate, reinterpret_cast<byte*>(start),
2154 count * kInstructionSize + kGap) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002155 StartBlockPools();
2156 }
2157
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002158 PatchingAssembler(Isolate* isolate, byte* start, unsigned count)
2159 : Assembler(isolate, start, count * kInstructionSize + kGap) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002160 // Block constant pool emission.
2161 StartBlockPools();
2162 }
2163
2164 ~PatchingAssembler() {
2165 // Const pool should still be blocked.
2166 DCHECK(is_const_pool_blocked());
2167 EndBlockPools();
2168 // Verify we have generated the number of instruction we expected.
2169 DCHECK((pc_offset() + kGap) == buffer_size_);
2170 // Verify no relocation information has been emitted.
2171 DCHECK(IsConstPoolEmpty());
2172 // Flush the Instruction cache.
2173 size_t length = buffer_size_ - kGap;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002174 Assembler::FlushICache(isolate(), buffer_, length);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002175 }
2176
2177 // See definition of PatchAdrFar() for details.
2178 static const int kAdrFarPatchableNNops = 2;
2179 static const int kAdrFarPatchableNInstrs = kAdrFarPatchableNNops + 2;
2180 void PatchAdrFar(int64_t target_offset);
2181};
2182
2183
2184class EnsureSpace BASE_EMBEDDED {
2185 public:
2186 explicit EnsureSpace(Assembler* assembler) {
2187 assembler->CheckBufferSpace();
2188 }
2189};
2190
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002191} // namespace internal
2192} // namespace v8
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002193
2194#endif // V8_ARM64_ASSEMBLER_ARM64_H_