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

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

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