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