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

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

Issue 235363005: Adds comparisons, labels, branches 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
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 ~Assembler() { } 271 ~Assembler() { }
272 272
273 void PopRegister(Register r) { 273 void PopRegister(Register r) {
274 UNIMPLEMENTED(); 274 UNIMPLEMENTED();
275 } 275 }
276 276
277 void Drop(intptr_t stack_elements) { 277 void Drop(intptr_t stack_elements) {
278 UNIMPLEMENTED(); 278 UNIMPLEMENTED();
279 } 279 }
280 280
281 void Bind(Label* label) { 281 void Bind(Label* label);
282 UNIMPLEMENTED();
283 }
284 282
285 // Misc. functionality 283 // Misc. functionality
286 intptr_t CodeSize() const { return buffer_.Size(); } 284 intptr_t CodeSize() const { return buffer_.Size(); }
287 intptr_t prologue_offset() const { return prologue_offset_; } 285 intptr_t prologue_offset() const { return prologue_offset_; }
288 286
289 // Count the fixups that produce a pointer offset, without processing 287 // Count the fixups that produce a pointer offset, without processing
290 // the fixups. On ARM64 there are no pointers in code. 288 // the fixups. On ARM64 there are no pointers in code.
291 intptr_t CountPointerOffsets() const { return 0; } 289 intptr_t CountPointerOffsets() const { return 0; }
292 290
293 const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const { 291 const ZoneGrowableArray<intptr_t>& GetPointerOffsets() const {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 void addw(Register rd, Register rn, Operand o) { 347 void addw(Register rd, Register rn, Operand o) {
350 AddSubHelper(kWord, false, false, rd, rn, o); 348 AddSubHelper(kWord, false, false, rd, rn, o);
351 } 349 }
352 void sub(Register rd, Register rn, Operand o) { 350 void sub(Register rd, Register rn, Operand o) {
353 AddSubHelper(kDoubleWord, false, true, rd, rn, o); 351 AddSubHelper(kDoubleWord, false, true, rd, rn, o);
354 } 352 }
355 void subs(Register rd, Register rn, Operand o) { 353 void subs(Register rd, Register rn, Operand o) {
356 AddSubHelper(kDoubleWord, true, true, rd, rn, o); 354 AddSubHelper(kDoubleWord, true, true, rd, rn, o);
357 } 355 }
358 356
357 // PC relative immediate add. imm is in bytes.
358 void adr(Register rd, int64_t imm) {
359 EmitPCRelOp(ADR, rd, imm);
360 }
361
359 // Logical immediate operations. 362 // Logical immediate operations.
360 // TODO(zra): Add macros that check IsImmLogical, and fall back on a longer 363 // TODO(zra): Add macros that check IsImmLogical, and fall back on a longer
361 // sequence on failure. 364 // sequence on failure.
362 void andi(Register rd, Register rn, uint64_t imm) { 365 void andi(Register rd, Register rn, uint64_t imm) {
363 Operand imm_op; 366 Operand imm_op;
364 const bool immok = IsImmLogical(imm, kXRegSizeInBits, &imm_op); 367 const bool immok = IsImmLogical(imm, kXRegSizeInBits, &imm_op);
365 ASSERT(immok); 368 ASSERT(immok);
366 EmitLogicalImmOp(ANDI, rd, rn, imm_op, kDoubleWord); 369 EmitLogicalImmOp(ANDI, rd, rn, imm_op, kDoubleWord);
367 } 370 }
368 void orri(Register rd, Register rn, uint64_t imm) { 371 void orri(Register rd, Register rn, uint64_t imm) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 void eon(Register rd, Register rn, Operand o) { 406 void eon(Register rd, Register rn, Operand o) {
404 EmitLogicalShiftOp(EON, rd, rn, o, kDoubleWord); 407 EmitLogicalShiftOp(EON, rd, rn, o, kDoubleWord);
405 } 408 }
406 void ands(Register rd, Register rn, Operand o) { 409 void ands(Register rd, Register rn, Operand o) {
407 EmitLogicalShiftOp(ANDS, rd, rn, o, kDoubleWord); 410 EmitLogicalShiftOp(ANDS, rd, rn, o, kDoubleWord);
408 } 411 }
409 void bics(Register rd, Register rn, Operand o) { 412 void bics(Register rd, Register rn, Operand o) {
410 EmitLogicalShiftOp(BICS, rd, rn, o, kDoubleWord); 413 EmitLogicalShiftOp(BICS, rd, rn, o, kDoubleWord);
411 } 414 }
412 415
413 // Comparison.
414 // rn cmp o.
415 void cmp(Register rn, Operand o) {
416 subs(ZR, rn, o);
417 }
418 // rn cmp -o.
419 void cmn(Register rn, Operand o) {
420 adds(ZR, rn, o);
421 }
422
423 // Move wide immediate. 416 // Move wide immediate.
424 void movk(Register rd, int32_t imm, int32_t hw_idx) { 417 void movk(Register rd, int32_t imm, int32_t hw_idx) {
425 ASSERT(rd != SP); 418 ASSERT(rd != SP);
426 const Register crd = ConcreteRegister(rd); 419 const Register crd = ConcreteRegister(rd);
427 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord); 420 EmitMoveWideOp(MOVK, crd, imm, hw_idx, kDoubleWord);
428 } 421 }
429 void movn(Register rd, int32_t imm, int32_t hw_idx) { 422 void movn(Register rd, int32_t imm, int32_t hw_idx) {
430 ASSERT(rd != SP); 423 ASSERT(rd != SP);
431 const Register crd = ConcreteRegister(rd); 424 const Register crd = ConcreteRegister(rd);
432 EmitMoveWideOp(MOVN, crd, imm, hw_idx, kDoubleWord); 425 EmitMoveWideOp(MOVN, crd, imm, hw_idx, kDoubleWord);
(...skipping 11 matching lines...) Expand all
444 // writeback, which is unlikely to be useful. 437 // writeback, which is unlikely to be useful.
445 ASSERT(((a.type() != Address::PreIndex) && 438 ASSERT(((a.type() != Address::PreIndex) &&
446 (a.type() != Address::PostIndex)) || 439 (a.type() != Address::PostIndex)) ||
447 (rt != a.base())); 440 (rt != a.base()));
448 EmitLoadStoreReg(LDR, rt, a, kDoubleWord); 441 EmitLoadStoreReg(LDR, rt, a, kDoubleWord);
449 } 442 }
450 void str(Register rt, Address a) { 443 void str(Register rt, Address a) {
451 EmitLoadStoreReg(STR, rt, a, kDoubleWord); 444 EmitLoadStoreReg(STR, rt, a, kDoubleWord);
452 } 445 }
453 446
454 // Function return. 447 // Comparison.
448 // rn cmp o.
449 void cmp(Register rn, Operand o) {
450 subs(ZR, rn, o);
451 }
452 // rn cmp -o.
453 void cmn(Register rn, Operand o) {
454 adds(ZR, rn, o);
455 }
456
457 // Conditional branch.
458 void b(Label* label, Condition cond = AL) {
459 EmitBranch(BCOND, cond, label);
460 }
461
462 // TODO(zra): branch and link with imm26 offset.
463 // TODO(zra): cbz, cbnz.
464
465 // Branch, link, return.
466 void br(Register rn) {
467 EmitUnconditionalBranchRegOp(BR, rn);
468 }
469 void blr(Register rn) {
470 EmitUnconditionalBranchRegOp(BLR, rn);
471 }
455 void ret(Register rn = R30) { 472 void ret(Register rn = R30) {
456 EmitUnconditionalBranchRegOp(RET, rn); 473 EmitUnconditionalBranchRegOp(RET, rn);
457 } 474 }
458 475
459 private: 476 private:
460 AssemblerBuffer buffer_; // Contains position independent code. 477 AssemblerBuffer buffer_; // Contains position independent code.
461 GrowableObjectArray& object_pool_; // Objects and patchable jump targets. 478 GrowableObjectArray& object_pool_; // Objects and patchable jump targets.
462 int32_t prologue_offset_; 479 int32_t prologue_offset_;
463 480
464 bool use_far_branches_; 481 bool use_far_branches_;
(...skipping 16 matching lines...) Expand all
481 GrowableArray<CodeComment*> comments_; 498 GrowableArray<CodeComment*> comments_;
482 499
483 bool IsImmLogical(uint64_t value, uint8_t width, Operand* imm_op); 500 bool IsImmLogical(uint64_t value, uint8_t width, Operand* imm_op);
484 501
485 void AddSubHelper(OperandSize os, bool set_flags, bool subtract, 502 void AddSubHelper(OperandSize os, bool set_flags, bool subtract,
486 Register rd, Register rn, Operand o) { 503 Register rd, Register rn, Operand o) {
487 ASSERT((rd != R31) && (rn != R31)); 504 ASSERT((rd != R31) && (rn != R31));
488 const Register crd = ConcreteRegister(rd); 505 const Register crd = ConcreteRegister(rd);
489 const Register crn = ConcreteRegister(rn); 506 const Register crn = ConcreteRegister(rn);
490 if (o.type() == Operand::Immediate) { 507 if (o.type() == Operand::Immediate) {
491 ASSERT((rd != ZR) && (rn != ZR)); 508 ASSERT(rn != ZR);
492 EmitAddSubImmOp(subtract ? SUBI : ADDI, crd, crn, o, os, set_flags); 509 EmitAddSubImmOp(subtract ? SUBI : ADDI, crd, crn, o, os, set_flags);
493 } else if (o.type() == Operand::Shifted) { 510 } else if (o.type() == Operand::Shifted) {
494 ASSERT((rd != SP) && (rn != SP)); 511 ASSERT((rd != SP) && (rn != SP));
495 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags); 512 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags);
496 } else { 513 } else {
497 ASSERT(o.type() == Operand::Extended); 514 ASSERT(o.type() == Operand::Extended);
498 ASSERT((rd != SP) && (rn != ZR)); 515 ASSERT((rd != SP) && (rn != ZR));
499 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags); 516 EmitAddSubShiftExtOp(subtract ? SUB : ADD, crd, crn, o, os, set_flags);
500 } 517 }
501 } 518 }
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 const int32_t size = (sz == kDoubleWord) ? B31 : 0; 573 const int32_t size = (sz == kDoubleWord) ? B31 : 0;
557 const int32_t s = set_flags ? B29 : 0; 574 const int32_t s = set_flags ? B29 : 0;
558 const int32_t encoding = 575 const int32_t encoding =
559 op | size | s | 576 op | size | s |
560 (static_cast<int32_t>(rd) << kRdShift) | 577 (static_cast<int32_t>(rd) << kRdShift) |
561 (static_cast<int32_t>(rn) << kRnShift) | 578 (static_cast<int32_t>(rn) << kRnShift) |
562 o.encoding(); 579 o.encoding();
563 Emit(encoding); 580 Emit(encoding);
564 } 581 }
565 582
583 int32_t EncodeImm19BranchOffset(int64_t imm, int32_t instr) {
584 const int32_t imm32 = static_cast<int32_t>(imm);
585 const int32_t off = (((imm32 >> 2) & kImm19Mask) << kImm19Shift);
586 return (instr & ~(kImm19Mask << kImm19Shift)) | off;
587 }
588
589 int64_t DecodeImm19BranchOffset(int32_t instr) {
590 const int32_t off = (((instr >> kImm19Shift) & kImm19Shift) << 13) >> 13;
591 return static_cast<int64_t>(off);
592 }
593
594 void EmitCompareAndBranch(CompareAndBranchOp op, Register rt, int64_t imm,
595 OperandSize sz) {
596 ASSERT((sz == kDoubleWord) || (sz == kWord));
597 ASSERT(Utils::IsInt(21, imm) && ((imm & 0x3) == 0));
598 const int32_t size = (sz == kDoubleWord) ? B31 : 0;
599 const int32_t encoded_offset = EncodeImm19BranchOffset(imm, 0);
600 const int32_t encoding =
601 op | size |
602 (static_cast<int32_t>(rt) << kRtShift) |
603 encoded_offset;
604 Emit(encoding);
605 }
606
607 void EmitConditionalBranch(ConditionalBranchOp op, Condition cond,
608 int64_t imm) {
609 ASSERT(Utils::IsInt(21, imm) && ((imm & 0x3) == 0));
610 const int32_t encoding =
611 op |
612 (static_cast<int32_t>(cond) << kCondShift) |
613 (((imm >> 2) & kImm19Mask) << kImm19Shift);
614 Emit(encoding);
615 }
616
617 bool CanEncodeImm19BranchOffset(int64_t offset) {
618 ASSERT(Utils::IsAligned(offset, 4));
619 return Utils::IsInt(19, offset);
620 }
621
622 // TODO(zra): Implement far branches. Requires loading large immediates.
623 void EmitBranch(ConditionalBranchOp op, Condition cond, Label* label) {
624 if (label->IsBound()) {
625 const int64_t dest = label->Position() - buffer_.Size();
626 ASSERT(CanEncodeImm19BranchOffset(dest));
627 EmitConditionalBranch(op, cond, dest);
628 } else {
629 const int64_t position = buffer_.Size();
630 ASSERT(CanEncodeImm19BranchOffset(position));
631 EmitConditionalBranch(op, cond, label->position_);
632 label->LinkTo(position);
633 }
634 }
635
566 void EmitUnconditionalBranchRegOp(UnconditionalBranchRegOp op, Register rn) { 636 void EmitUnconditionalBranchRegOp(UnconditionalBranchRegOp op, Register rn) {
567 const int32_t encoding = 637 const int32_t encoding =
568 op | (static_cast<int32_t>(rn) << kRnShift); 638 op | (static_cast<int32_t>(rn) << kRnShift);
569 Emit(encoding); 639 Emit(encoding);
570 } 640 }
571 641
572 void EmitMoveWideOp(MoveWideOp op, Register rd, int32_t imm, int32_t hw_idx, 642 void EmitMoveWideOp(MoveWideOp op, Register rd, int32_t imm, int32_t hw_idx,
573 OperandSize sz) { 643 OperandSize sz) {
574 ASSERT(Utils::IsUint(16, imm)); 644 ASSERT(Utils::IsUint(16, imm));
575 ASSERT((hw_idx >= 0) && (hw_idx <= 3)); 645 ASSERT((hw_idx >= 0) && (hw_idx <= 3));
(...skipping 10 matching lines...) Expand all
586 void EmitLoadStoreReg(LoadStoreRegOp op, Register rt, Address a, 656 void EmitLoadStoreReg(LoadStoreRegOp op, Register rt, Address a,
587 OperandSize sz) { 657 OperandSize sz) {
588 const int32_t size = Log2OperandSizeBytes(sz); 658 const int32_t size = Log2OperandSizeBytes(sz);
589 const int32_t encoding = 659 const int32_t encoding =
590 op | (size << kSzShift) | 660 op | (size << kSzShift) |
591 (static_cast<int32_t>(rt) << kRtShift) | 661 (static_cast<int32_t>(rt) << kRtShift) |
592 a.encoding(); 662 a.encoding();
593 Emit(encoding); 663 Emit(encoding);
594 } 664 }
595 665
666 void EmitPCRelOp(PCRelOp op, Register rd, int64_t imm) {
667 ASSERT(Utils::IsInt(21, imm));
668 ASSERT((rd != R31) && (rd != SP));
669 const Register crd = ConcreteRegister(rd);
670 const int32_t loimm = (imm & 0x3) << 29;
671 const int32_t hiimm = ((imm & 0x1ffffc) >> 2) << kImm19Shift;
regis 2014/04/11 20:29:21 Instead of (imm & 0x1ffffc) >> 2 I would write (im
zra 2014/04/11 20:39:59 Done.
672 const int32_t encoding =
673 op | loimm | hiimm |
674 (static_cast<int32_t>(crd) << kRdShift);
675 Emit(encoding);
676 }
677
596 DISALLOW_ALLOCATION(); 678 DISALLOW_ALLOCATION();
597 DISALLOW_COPY_AND_ASSIGN(Assembler); 679 DISALLOW_COPY_AND_ASSIGN(Assembler);
598 }; 680 };
599 681
600 } // namespace dart 682 } // namespace dart
601 683
602 #endif // VM_ASSEMBLER_ARM64_H_ 684 #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