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

Side by Side Diff: runtime/vm/assembler_arm64.h

Issue 239303008: Adds object pool, LoadImmediate, and LoadObject to ARM64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 8 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 | runtime/vm/assembler_arm64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #ifndef VM_ASSEMBLER_ARM64_H_ 5 #ifndef VM_ASSEMBLER_ARM64_H_
6 #define VM_ASSEMBLER_ARM64_H_ 6 #define VM_ASSEMBLER_ARM64_H_
7 7
8 #ifndef VM_ASSEMBLER_H_ 8 #ifndef VM_ASSEMBLER_H_
9 #error Do not include assembler_arm64.h directly; use assembler.h instead. 9 #error Do not include assembler_arm64.h directly; use assembler.h instead.
10 #endif 10 #endif
11 11
12 #include "platform/assert.h" 12 #include "platform/assert.h"
13 #include "platform/utils.h" 13 #include "platform/utils.h"
14 #include "vm/constants_arm64.h" 14 #include "vm/constants_arm64.h"
15 #include "vm/hash_map.h"
15 #include "vm/object.h" 16 #include "vm/object.h"
16 #include "vm/simulator.h" 17 #include "vm/simulator.h"
17 18
18 namespace dart { 19 namespace dart {
19 20
20 // Forward declarations. 21 // Forward declarations.
21 class RuntimeEntry; 22 class RuntimeEntry;
22 23
23 // TODO(zra): Label, Address, and FieldAddress are copied from ARM, 24 // TODO(zra): Label, Address, and FieldAddress are copied from ARM,
24 // they must be adapted to ARM64. 25 // they must be adapted to ARM64.
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
80 type_ = other.type_; 81 type_ = other.type_;
81 base_ = other.base_; 82 base_ = other.base_;
82 return *this; 83 return *this;
83 } 84 }
84 85
85 enum AddressType { 86 enum AddressType {
86 Offset, 87 Offset,
87 PreIndex, 88 PreIndex,
88 PostIndex, 89 PostIndex,
89 Reg, 90 Reg,
91 PCOffset,
92 Unknown,
90 }; 93 };
91 94
92 // Offset is in bytes. For the unsigned imm12 case, we unscale based on the 95 // Offset is in bytes. For the unsigned imm12 case, we unscale based on the
93 // operand size, and assert that offset is aligned accordingly. 96 // operand size, and assert that offset is aligned accordingly.
94 // For the smaller signed imm9 case, the offset is the number of bytes, but 97 // For the smaller signed imm9 case, the offset is the number of bytes, but
95 // is unscaled. 98 // is unscaled.
96 Address(Register rn, int32_t offset = 0, AddressType at = Offset, 99 Address(Register rn, int32_t offset = 0, AddressType at = Offset,
97 OperandSize sz = kDoubleWord) { 100 OperandSize sz = kDoubleWord) {
98 ASSERT((rn != R31) && (rn != ZR)); 101 ASSERT((rn != R31) && (rn != ZR));
99 const Register crn = ConcreteRegister(rn); 102 const Register crn = ConcreteRegister(rn);
(...skipping 10 matching lines...) Expand all
110 int32_t idx = (at == PostIndex) ? B10 : (B11 | B10); 113 int32_t idx = (at == PostIndex) ? B10 : (B11 | B10);
111 encoding_ = 114 encoding_ =
112 idx | 115 idx |
113 ((offset & 0x1ff) << kImm9Shift) | 116 ((offset & 0x1ff) << kImm9Shift) |
114 (static_cast<int32_t>(crn) << kRnShift); 117 (static_cast<int32_t>(crn) << kRnShift);
115 } 118 }
116 type_ = at; 119 type_ = at;
117 base_ = crn; 120 base_ = crn;
118 } 121 }
119 122
120 // TODO(zra): Write CanHoldOffset(int32_t off, AddressType, OperandSize). 123 static bool CanHoldOffset(int32_t offset, AddressType at = Offset,
121 // TODO(zra): Write constructor for PC-relative load address. 124 OperandSize sz = kDoubleWord) {
125 if (at == Offset) {
126 // Fits in 12 bit unsigned and right alignment for sz.
127 const int32_t scale = Log2OperandSizeBytes(sz);
128 return Utils::IsUint(12 + scale, offset) &&
129 (offset == ((offset >> scale) << scale));
130 } else if (at == PCOffset) {
131 return Utils::IsInt(21, offset) &&
132 (offset == ((offset >> 2) << 2));
133 } else {
134 ASSERT((at == PreIndex) || (at == PostIndex));
135 return Utils::IsInt(9, offset);
136 }
137 }
138
139 // PC-relative load address.
140 static Address PC(int32_t pc_off) {
141 ASSERT(CanHoldOffset(pc_off, PCOffset));
142 Address addr;
143 addr.encoding_ = (((pc_off >> 2) & kImm19Mask) << kImm19Shift);
144 addr.base_ = kNoRegister;
145 addr.type_ = PCOffset;
146 return addr;
147 }
122 148
123 // Base register rn with offset rm. rm is sign-extended according to ext. 149 // Base register rn with offset rm. rm is sign-extended according to ext.
124 // If ext is UXTX, rm may be optionally scaled by the 150 // If ext is UXTX, rm may be optionally scaled by the
125 // Log2OperandSize (specified by the instruction). 151 // Log2OperandSize (specified by the instruction).
126 Address(Register rn, Register rm, Extend ext = UXTX, bool scaled = false) { 152 Address(Register rn, Register rm, Extend ext = UXTX, bool scaled = false) {
127 ASSERT((rn != R31) && (rn != ZR)); 153 ASSERT((rn != R31) && (rn != ZR));
128 ASSERT((rm != R31) && (rm != SP)); 154 ASSERT((rm != R31) && (rm != SP));
129 ASSERT(!scaled || (ext == UXTX)); // Can only scale when ext = UXTX. 155 ASSERT(!scaled || (ext == UXTX)); // Can only scale when ext = UXTX.
130 ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX)); 156 ASSERT((ext == UXTW) || (ext == UXTX) || (ext == SXTW) || (ext == SXTX));
131 const Register crn = ConcreteRegister(rn); 157 const Register crn = ConcreteRegister(rn);
132 const Register crm = ConcreteRegister(rm); 158 const Register crm = ConcreteRegister(rm);
133 const int32_t s = scaled ? B12 : 0; 159 const int32_t s = scaled ? B12 : 0;
134 encoding_ = 160 encoding_ =
135 B21 | B11 | s | 161 B21 | B11 | s |
136 (static_cast<int32_t>(crn) << kRnShift) | 162 (static_cast<int32_t>(crn) << kRnShift) |
137 (static_cast<int32_t>(crm) << kRmShift) | 163 (static_cast<int32_t>(crm) << kRmShift) |
138 (static_cast<int32_t>(ext) << kExtendTypeShift); 164 (static_cast<int32_t>(ext) << kExtendTypeShift);
139 type_ = Reg; 165 type_ = Reg;
140 base_ = crn; 166 base_ = crn;
141 } 167 }
142 168
143 private: 169 private:
144 uint32_t encoding() const { return encoding_; } 170 uint32_t encoding() const { return encoding_; }
145 AddressType type() const { return type_; } 171 AddressType type() const { return type_; }
146 Register base() const { return base_; } 172 Register base() const { return base_; }
147 173
174 Address() : encoding_(0), type_(Unknown), base_(kNoRegister) {}
175
148 uint32_t encoding_; 176 uint32_t encoding_;
149 AddressType type_; 177 AddressType type_;
150 Register base_; 178 Register base_;
151 179
152 friend class Assembler; 180 friend class Assembler;
153 }; 181 };
154 182
155 183
156 class FieldAddress : public Address { 184 class FieldAddress : public Address {
157 public: 185 public:
158 FieldAddress(Register base, int32_t disp) 186 FieldAddress(Register base, int32_t disp)
159 : Address(base, disp - kHeapObjectTag) { } 187 : Address(base, disp - kHeapObjectTag) { }
160 188
161 FieldAddress(const FieldAddress& other) : Address(other) { } 189 FieldAddress(const FieldAddress& other) : Address(other) { }
162 190
163 FieldAddress& operator=(const FieldAddress& other) { 191 FieldAddress& operator=(const FieldAddress& other) {
164 Address::operator=(other); 192 Address::operator=(other);
165 return *this; 193 return *this;
166 } 194 }
167 }; 195 };
168 196
169 197
170 class Operand : public ValueObject { 198 class Operand : public ValueObject {
171 public: 199 public:
200 enum OperandType {
201 Shifted,
202 Extended,
203 Immediate,
204 BitfieldImm,
205 Unknown,
206 };
207
172 // Data-processing operand - Uninitialized. 208 // Data-processing operand - Uninitialized.
173 Operand() : encoding_(-1), type_(Unknown) { } 209 Operand() : encoding_(-1), type_(Unknown) { }
174 210
175 // Data-processing operands - Copy constructor. 211 // Data-processing operands - Copy constructor.
176 Operand(const Operand& other) 212 Operand(const Operand& other)
177 : ValueObject(), encoding_(other.encoding_), type_(other.type_) { } 213 : ValueObject(), encoding_(other.encoding_), type_(other.type_) { }
178 214
179 Operand& operator=(const Operand& other) { 215 Operand& operator=(const Operand& other) {
180 type_ = other.type_; 216 type_ = other.type_;
181 encoding_ = other.encoding_; 217 encoding_ = other.encoding_;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 } else { 254 } else {
219 // imm only has bits in [12, 24) set. 255 // imm only has bits in [12, 24) set.
220 ASSERT(((imm & 0xfff) == 0) && (Utils::IsUint(12, imm >> 12))); 256 ASSERT(((imm & 0xfff) == 0) && (Utils::IsUint(12, imm >> 12)));
221 encoding_ = B22 | ((imm >> 12) << kImm12Shift); 257 encoding_ = B22 | ((imm >> 12) << kImm12Shift);
222 } 258 }
223 type_ = Immediate; 259 type_ = Immediate;
224 } 260 }
225 261
226 // Encodes the value of an immediate for a logical operation. 262 // Encodes the value of an immediate for a logical operation.
227 // Since these values are difficult to craft by hand, instead pass the 263 // Since these values are difficult to craft by hand, instead pass the
228 // logical mask to the function Assembler::IsImmLogical to get n, imm_s, and 264 // logical mask to the function IsImmLogical to get n, imm_s, and
229 // imm_r. 265 // imm_r.
230 Operand(uint8_t n, int8_t imm_s, int8_t imm_r) { 266 Operand(uint8_t n, int8_t imm_s, int8_t imm_r) {
231 ASSERT((n == 1) || (n == 0)); 267 ASSERT((n == 1) || (n == 0));
232 ASSERT(Utils::IsUint(6, imm_s) && Utils::IsUint(6, imm_r)); 268 ASSERT(Utils::IsUint(6, imm_s) && Utils::IsUint(6, imm_r));
233 type_ = BitfieldImm; 269 type_ = BitfieldImm;
234 encoding_ = 270 encoding_ =
235 (static_cast<int32_t>(n) << kNShift) | 271 (static_cast<int32_t>(n) << kNShift) |
236 (static_cast<int32_t>(imm_s) << kImmSShift) | 272 (static_cast<int32_t>(imm_s) << kImmSShift) |
237 (static_cast<int32_t>(imm_r) << kImmRShift); 273 (static_cast<int32_t>(imm_r) << kImmRShift);
238 } 274 }
239 275
240 enum OperandType { 276 // Test if a given value can be encoded in the immediate field of a logical
241 Shifted, 277 // instruction.
242 Extended, 278 // If it can be encoded, the function returns true, and values pointed to by
243 Immediate, 279 // n, imm_s and imm_r are updated with immediates encoded in the format
244 BitfieldImm, 280 // required by the corresponding fields in the logical instruction.
245 Unknown, 281 // If it can't be encoded, the function returns false, and the operand is
246 }; 282 // undefined.
283 static bool IsImmLogical(uint64_t value, uint8_t width, Operand* imm_op);
284
285 // An immediate imm can be an operand to add/sub when the return value is
286 // Immediate, or a logical operation over sz bits when the return value is
287 // BitfieldImm. If the return value is Unknown, then the immediate can't be
288 // used as an operand in either instruction. The encoded operand is written
289 // to op.
290 static OperandType CanHold(int64_t imm, uint8_t sz, Operand* op) {
291 ASSERT(op != NULL);
292 ASSERT((sz == kXRegSizeInBits) || (sz == kWRegSizeInBits));
293 if (Utils::IsUint(12, imm)) {
294 op->encoding_ = imm << kImm12Shift;
295 op->type_ = Immediate;
296 } else if (((imm & 0xfff) == 0) && (Utils::IsUint(12, imm >> 12))) {
297 op->encoding_ = B22 | ((imm >> 12) << kImm12Shift);
298 op->type_ = Immediate;
299 } else if (IsImmLogical(imm, sz, op)) {
300 op->type_ = BitfieldImm;
301 } else {
302 op->encoding_ = 0;
303 op->type_ = Unknown;
304 }
305 return op->type_;
306 }
247 307
248 private: 308 private:
249 uint32_t encoding() const { 309 uint32_t encoding() const {
250 return encoding_; 310 return encoding_;
251 } 311 }
252 OperandType type() const { 312 OperandType type() const {
253 return type_; 313 return type_;
254 } 314 }
255 315
256 uint32_t encoding_; 316 uint32_t encoding_;
257 OperandType type_; 317 OperandType type_;
258 318
259 friend class Assembler; 319 friend class Assembler;
260 }; 320 };
261 321
262 322
263 class Assembler : public ValueObject { 323 class Assembler : public ValueObject {
264 public: 324 public:
265 explicit Assembler(bool use_far_branches = false) 325 explicit Assembler(bool use_far_branches = false);
266 : buffer_(),
267 object_pool_(GrowableObjectArray::Handle()),
268 prologue_offset_(-1),
269 use_far_branches_(use_far_branches),
270 comments_() { }
271 ~Assembler() { } 326 ~Assembler() { }
272 327
273 void PopRegister(Register r) { 328 void PopRegister(Register r) {
274 UNIMPLEMENTED(); 329 UNIMPLEMENTED();
275 } 330 }
276 331
277 void Drop(intptr_t stack_elements) { 332 void Drop(intptr_t stack_elements) {
278 UNIMPLEMENTED(); 333 UNIMPLEMENTED();
279 } 334 }
280 335
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 // PC relative immediate add. imm is in bytes. 412 // PC relative immediate add. imm is in bytes.
358 void adr(Register rd, int64_t imm) { 413 void adr(Register rd, int64_t imm) {
359 EmitPCRelOp(ADR, rd, imm); 414 EmitPCRelOp(ADR, rd, imm);
360 } 415 }
361 416
362 // Logical immediate operations. 417 // Logical immediate operations.
363 // TODO(zra): Add macros that check IsImmLogical, and fall back on a longer 418 // TODO(zra): Add macros that check IsImmLogical, and fall back on a longer
364 // sequence on failure. 419 // sequence on failure.
365 void andi(Register rd, Register rn, uint64_t imm) { 420 void andi(Register rd, Register rn, uint64_t imm) {
366 Operand imm_op; 421 Operand imm_op;
367 const bool immok = IsImmLogical(imm, kXRegSizeInBits, &imm_op); 422 const bool immok = Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op);
368 ASSERT(immok); 423 ASSERT(immok);
369 EmitLogicalImmOp(ANDI, rd, rn, imm_op, kDoubleWord); 424 EmitLogicalImmOp(ANDI, rd, rn, imm_op, kDoubleWord);
370 } 425 }
371 void orri(Register rd, Register rn, uint64_t imm) { 426 void orri(Register rd, Register rn, uint64_t imm) {
372 Operand imm_op; 427 Operand imm_op;
373 const bool immok = IsImmLogical(imm, kXRegSizeInBits, &imm_op); 428 const bool immok = Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op);
374 ASSERT(immok); 429 ASSERT(immok);
375 EmitLogicalImmOp(ORRI, rd, rn, imm_op, kDoubleWord); 430 EmitLogicalImmOp(ORRI, rd, rn, imm_op, kDoubleWord);
376 } 431 }
377 void eori(Register rd, Register rn, uint64_t imm) { 432 void eori(Register rd, Register rn, uint64_t imm) {
378 Operand imm_op; 433 Operand imm_op;
379 const bool immok = IsImmLogical(imm, kXRegSizeInBits, &imm_op); 434 const bool immok = Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op);
380 ASSERT(immok); 435 ASSERT(immok);
381 EmitLogicalImmOp(EORI, rd, rn, imm_op, kDoubleWord); 436 EmitLogicalImmOp(EORI, rd, rn, imm_op, kDoubleWord);
382 } 437 }
383 void andis(Register rd, Register rn, uint64_t imm) { 438 void andis(Register rd, Register rn, uint64_t imm) {
384 Operand imm_op; 439 Operand imm_op;
385 const bool immok = IsImmLogical(imm, kXRegSizeInBits, &imm_op); 440 const bool immok = Operand::IsImmLogical(imm, kXRegSizeInBits, &imm_op);
386 ASSERT(immok); 441 ASSERT(immok);
387 EmitLogicalImmOp(ANDIS, rd, rn, imm_op, kDoubleWord); 442 EmitLogicalImmOp(ANDIS, rd, rn, imm_op, kDoubleWord);
388 } 443 }
389 444
390 // Logical (shifted) register operations. 445 // Logical (shifted) register operations.
391 void and_(Register rd, Register rn, Operand o) { 446 void and_(Register rd, Register rn, Operand o) {
392 EmitLogicalShiftOp(AND, rd, rn, o, kDoubleWord); 447 EmitLogicalShiftOp(AND, rd, rn, o, kDoubleWord);
393 } 448 }
394 void bic(Register rd, Register rn, Operand o) { 449 void bic(Register rd, Register rn, Operand o) {
395 EmitLogicalShiftOp(BIC, rd, rn, o, kDoubleWord); 450 EmitLogicalShiftOp(BIC, rd, rn, o, kDoubleWord);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 EmitMiscDP2Source(LSRV, rd, rn, rm, kDoubleWord); 482 EmitMiscDP2Source(LSRV, rd, rn, rm, kDoubleWord);
428 } 483 }
429 void asrv(Register rd, Register rn, Register rm) { 484 void asrv(Register rd, Register rn, Register rm) {
430 EmitMiscDP2Source(ASRV, rd, rn, rm, kDoubleWord); 485 EmitMiscDP2Source(ASRV, rd, rn, rm, kDoubleWord);
431 } 486 }
432 void madd(Register rd, Register rn, Register rm, Register ra) { 487 void madd(Register rd, Register rn, Register rm, Register ra) {
433 EmitMiscDP3Source(MADD, rd, rn, rm, ra, kDoubleWord); 488 EmitMiscDP3Source(MADD, rd, rn, rm, ra, kDoubleWord);
434 } 489 }
435 490
436 // Move wide immediate. 491 // Move wide immediate.
437 void movk(Register rd, int32_t imm, int32_t hw_idx) { 492 void movk(Register rd, uint16_t imm, int hw_idx) {
438 ASSERT(rd != SP); 493 ASSERT(rd != SP);
439 const Register crd = ConcreteRegister(rd); 494 const Register crd = ConcreteRegister(rd);
440 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord); 495 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord);
441 } 496 }
442 void movn(Register rd, int32_t imm, int32_t hw_idx) { 497 void movn(Register rd, uint16_t imm, int hw_idx) {
443 ASSERT(rd != SP); 498 ASSERT(rd != SP);
444 const Register crd = ConcreteRegister(rd); 499 const Register crd = ConcreteRegister(rd);
445 EmitMoveWideOp(MOVN, crd, imm, hw_idx, kDoubleWord); 500 EmitMoveWideOp(MOVN, crd, imm, hw_idx, kDoubleWord);
446 } 501 }
447 void movz(Register rd, int32_t imm, int32_t hw_idx) { 502 void movz(Register rd, uint16_t imm, int hw_idx) {
448 ASSERT(rd != SP); 503 ASSERT(rd != SP);
449 const Register crd = ConcreteRegister(rd); 504 const Register crd = ConcreteRegister(rd);
450 EmitMoveWideOp(MOVZ, crd, imm, hw_idx, kDoubleWord); 505 EmitMoveWideOp(MOVZ, crd, imm, hw_idx, kDoubleWord);
451 } 506 }
452 507
453 // Loads and Stores. 508 // Loads and Stores.
454 void ldr(Register rt, Address a) { 509 void ldr(Register rt, Address a) {
455 // If we are doing pre-/post-indexing, and the base and result registers 510 if (a.type() == Address::PCOffset) {
456 // are the same, then the result of the load will be clobbered by the 511 EmitLoadRegLiteral(LDRpc, rt, a, kDoubleWord);
457 // writeback, which is unlikely to be useful. 512 } else {
458 ASSERT(((a.type() != Address::PreIndex) && 513 // If we are doing pre-/post-indexing, and the base and result registers
459 (a.type() != Address::PostIndex)) || 514 // are the same, then the result of the load will be clobbered by the
460 (rt != a.base())); 515 // writeback, which is unlikely to be useful.
461 EmitLoadStoreReg(LDR, rt, a, kDoubleWord); 516 ASSERT(((a.type() != Address::PreIndex) &&
517 (a.type() != Address::PostIndex)) ||
518 (rt != a.base()));
519 EmitLoadStoreReg(LDR, rt, a, kDoubleWord);
520 }
462 } 521 }
463 void str(Register rt, Address a) { 522 void str(Register rt, Address a) {
464 EmitLoadStoreReg(STR, rt, a, kDoubleWord); 523 EmitLoadStoreReg(STR, rt, a, kDoubleWord);
465 } 524 }
466 525
467 // Comparison. 526 // Comparison.
468 // rn cmp o. 527 // rn cmp o.
469 void cmp(Register rn, Operand o) { 528 void cmp(Register rn, Operand o) {
470 subs(ZR, rn, o); 529 subs(ZR, rn, o);
471 } 530 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 } 565 }
507 void neg(Register rd, Register rm) { 566 void neg(Register rd, Register rm) {
508 sub(rd, ZR, Operand(rm)); 567 sub(rd, ZR, Operand(rm));
509 } 568 }
510 void negs(Register rd, Register rm) { 569 void negs(Register rd, Register rm) {
511 subs(rd, ZR, Operand(rm)); 570 subs(rd, ZR, Operand(rm));
512 } 571 }
513 void mul(Register rd, Register rn, Register rm) { 572 void mul(Register rd, Register rn, Register rm) {
514 madd(rd, rn, rm, ZR); 573 madd(rd, rn, rm, ZR);
515 } 574 }
575 void Push(Register reg) {
576 str(reg, Address(SP, -1 * kWordSize, Address::PreIndex));
577 }
578 void Pop(Register reg) {
579 ldr(reg, Address(SP, 1 * kWordSize, Address::PostIndex));
580 }
581
582 // Object pool, loading from pool, etc.
583 void LoadPoolPointer(Register pp) {
584 const intptr_t object_pool_pc_dist =
585 Instructions::HeaderSize() - Instructions::object_pool_offset() +
586 CodeSize();
587 // PP <- Read(PC - object_pool_pc_dist).
588 ldr(pp, Address::PC(-object_pool_pc_dist));
589 }
590
591 enum Patchability {
592 kPatchable,
593 kNotPatchable,
594 };
595
596 void LoadWordFromPoolOffset(Register dst, Register pp, uint32_t offset);
597 intptr_t FindObject(const Object& obj, Patchability patchable);
598 intptr_t FindImmediate(int64_t imm);
599 bool CanLoadObjectFromPool(const Object& object);
600 bool CanLoadImmediateFromPool(int64_t imm, Register pp);
601 void LoadObject(Register dst, const Object& obj, Register pp);
602 void LoadImmediate(Register reg, int64_t imm, Register pp);
516 603
517 private: 604 private:
518 AssemblerBuffer buffer_; // Contains position independent code. 605 AssemblerBuffer buffer_; // Contains position independent code.
519 GrowableObjectArray& object_pool_; // Objects and patchable jump targets. 606
607 // Objects and patchable jump targets.
608 GrowableObjectArray& object_pool_;
609
610 // Patchability of pool entries.
611 GrowableArray<Patchability> patchable_pool_entries_;
612
613 // Pair type parameter for DirectChainedHashMap.
614 class ObjIndexPair {
615 public:
616 // TODO(zra): A WeakTable should be used here instead, but then it would
617 // also have to be possible to register and de-register WeakTables with the
618 // heap. Also, the Assembler would need to become a StackResource.
619 // Issue 13305. In the meantime...
620 // CAUTION: the RawObject* below is only safe because:
621 // The HashMap that will use this pair type will not contain any RawObject*
622 // keys that are not in the object_pool_ array. Since the keys will be
623 // visited by the GC when it visits the object_pool_, and since all objects
624 // in the object_pool_ are Old (and so will not be moved) the GC does not
625 // also need to visit the keys here in the HashMap.
626
627 // Typedefs needed for the DirectChainedHashMap template.
628 typedef RawObject* Key;
629 typedef intptr_t Value;
630 typedef ObjIndexPair Pair;
631
632 ObjIndexPair(Key key, Value value) : key_(key), value_(value) { }
633
634 static Key KeyOf(Pair kv) { return kv.key_; }
635
636 static Value ValueOf(Pair kv) { return kv.value_; }
637
638 static intptr_t Hashcode(Key key) {
639 return reinterpret_cast<intptr_t>(key) >> kObjectAlignmentLog2;
640 }
641
642 static inline bool IsKeyEqual(Pair kv, Key key) {
643 return kv.key_ == key;
644 }
645
646 private:
647 Key key_;
648 Value value_;
649 };
650
651 // Hashmap for fast lookup in object pool.
652 DirectChainedHashMap<ObjIndexPair> object_pool_index_table_;
653
520 int32_t prologue_offset_; 654 int32_t prologue_offset_;
521 655
522 bool use_far_branches_; 656 bool use_far_branches_;
523 657
524 class CodeComment : public ZoneAllocated { 658 class CodeComment : public ZoneAllocated {
525 public: 659 public:
526 CodeComment(intptr_t pc_offset, const String& comment) 660 CodeComment(intptr_t pc_offset, const String& comment)
527 : pc_offset_(pc_offset), comment_(comment) { } 661 : pc_offset_(pc_offset), comment_(comment) { }
528 662
529 intptr_t pc_offset() const { return pc_offset_; } 663 intptr_t pc_offset() const { return pc_offset_; }
530 const String& comment() const { return comment_; } 664 const String& comment() const { return comment_; }
531 665
532 private: 666 private:
533 intptr_t pc_offset_; 667 intptr_t pc_offset_;
534 const String& comment_; 668 const String& comment_;
535 669
536 DISALLOW_COPY_AND_ASSIGN(CodeComment); 670 DISALLOW_COPY_AND_ASSIGN(CodeComment);
537 }; 671 };
538 672
539 GrowableArray<CodeComment*> comments_; 673 GrowableArray<CodeComment*> comments_;
540 674
541 bool IsImmLogical(uint64_t value, uint8_t width, Operand* imm_op);
542
543 void AddSubHelper(OperandSize os, bool set_flags, bool subtract, 675 void AddSubHelper(OperandSize os, bool set_flags, bool subtract,
544 Register rd, Register rn, Operand o) { 676 Register rd, Register rn, Operand o) {
545 ASSERT((rd != R31) && (rn != R31)); 677 ASSERT((rd != R31) && (rn != R31));
546 const Register crd = ConcreteRegister(rd); 678 const Register crd = ConcreteRegister(rd);
547 const Register crn = ConcreteRegister(rn); 679 const Register crn = ConcreteRegister(rn);
548 if (o.type() == Operand::Immediate) { 680 if (o.type() == Operand::Immediate) {
549 ASSERT(rn != ZR); 681 ASSERT(rn != ZR);
550 EmitAddSubImmOp(subtract ? SUBI : ADDI, crd, crn, o, os, set_flags); 682 EmitAddSubImmOp(subtract ? SUBI : ADDI, crd, crn, o, os, set_flags);
551 } else if (o.type() == Operand::Shifted) { 683 } else if (o.type() == Operand::Shifted) {
552 ASSERT((rd != SP) && (rn != SP)); 684 ASSERT((rd != SP) && (rn != SP));
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
673 label->LinkTo(position); 805 label->LinkTo(position);
674 } 806 }
675 } 807 }
676 808
677 void EmitUnconditionalBranchRegOp(UnconditionalBranchRegOp op, Register rn) { 809 void EmitUnconditionalBranchRegOp(UnconditionalBranchRegOp op, Register rn) {
678 const int32_t encoding = 810 const int32_t encoding =
679 op | (static_cast<int32_t>(rn) << kRnShift); 811 op | (static_cast<int32_t>(rn) << kRnShift);
680 Emit(encoding); 812 Emit(encoding);
681 } 813 }
682 814
683 void EmitMoveWideOp(MoveWideOp op, Register rd, int32_t imm, int32_t hw_idx, 815 void EmitMoveWideOp(MoveWideOp op, Register rd, uint16_t imm, int hw_idx,
684 OperandSize sz) { 816 OperandSize sz) {
685 ASSERT(Utils::IsUint(16, imm));
686 ASSERT((hw_idx >= 0) && (hw_idx <= 3)); 817 ASSERT((hw_idx >= 0) && (hw_idx <= 3));
687 ASSERT((sz == kDoubleWord) || (sz == kWord)); 818 ASSERT((sz == kDoubleWord) || (sz == kWord));
688 const int32_t size = (sz == kDoubleWord) ? B31 : 0; 819 const int32_t size = (sz == kDoubleWord) ? B31 : 0;
689 const int32_t encoding = 820 const int32_t encoding =
690 op | size | 821 op | size |
691 (static_cast<int32_t>(rd) << kRdShift) | 822 (static_cast<int32_t>(rd) << kRdShift) |
692 (hw_idx << kHWShift) | 823 (static_cast<int32_t>(hw_idx) << kHWShift) |
693 (imm << kImm16Shift); 824 (static_cast<int32_t>(imm) << kImm16Shift);
694 Emit(encoding); 825 Emit(encoding);
695 } 826 }
696 827
697 void EmitLoadStoreReg(LoadStoreRegOp op, Register rt, Address a, 828 void EmitLoadStoreReg(LoadStoreRegOp op, Register rt, Address a,
698 OperandSize sz) { 829 OperandSize sz) {
699 const int32_t size = Log2OperandSizeBytes(sz); 830 const int32_t size = Log2OperandSizeBytes(sz);
700 const int32_t encoding = 831 const int32_t encoding =
701 op | (size << kSzShift) | 832 op | (size << kSzShift) |
702 (static_cast<int32_t>(rt) << kRtShift) | 833 (static_cast<int32_t>(rt) << kRtShift) |
703 a.encoding(); 834 a.encoding();
704 Emit(encoding); 835 Emit(encoding);
705 } 836 }
706 837
838 void EmitLoadRegLiteral(LoadRegLiteralOp op, Register rt, Address a,
839 OperandSize sz) {
840 ASSERT((sz == kDoubleWord) || (sz == kWord));
841 const int32_t size = (sz == kDoubleWord) ? B30 : 0;
842 const int32_t encoding =
843 op | size |
844 (static_cast<int32_t>(rt) << kRtShift) |
845 a.encoding();
846 Emit(encoding);
847 }
848
707 void EmitPCRelOp(PCRelOp op, Register rd, int64_t imm) { 849 void EmitPCRelOp(PCRelOp op, Register rd, int64_t imm) {
708 ASSERT(Utils::IsInt(21, imm)); 850 ASSERT(Utils::IsInt(21, imm));
709 ASSERT((rd != R31) && (rd != SP)); 851 ASSERT((rd != R31) && (rd != SP));
710 const Register crd = ConcreteRegister(rd); 852 const Register crd = ConcreteRegister(rd);
711 const int32_t loimm = (imm & 0x3) << 29; 853 const int32_t loimm = (imm & 0x3) << 29;
712 const int32_t hiimm = ((imm >> 2) & kImm19Mask) << kImm19Shift; 854 const int32_t hiimm = ((imm >> 2) & kImm19Mask) << kImm19Shift;
713 const int32_t encoding = 855 const int32_t encoding =
714 op | loimm | hiimm | 856 op | loimm | hiimm |
715 (static_cast<int32_t>(crd) << kRdShift); 857 (static_cast<int32_t>(crd) << kRdShift);
716 Emit(encoding); 858 Emit(encoding);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 Emit(encoding); 892 Emit(encoding);
751 } 893 }
752 894
753 DISALLOW_ALLOCATION(); 895 DISALLOW_ALLOCATION();
754 DISALLOW_COPY_AND_ASSIGN(Assembler); 896 DISALLOW_COPY_AND_ASSIGN(Assembler);
755 }; 897 };
756 898
757 } // namespace dart 899 } // namespace dart
758 900
759 #endif // VM_ASSEMBLER_ARM64_H_ 901 #endif // VM_ASSEMBLER_ARM64_H_
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/assembler_arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698