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