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

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

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

Powered by Google App Engine
This is Rietveld 408576698