Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1171)

Side by Side Diff: src/a64/assembler-a64.h

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

Powered by Google App Engine
This is Rietveld 408576698