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

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

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

Powered by Google App Engine
This is Rietveld 408576698