OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_MIPS_H_ | 5 #ifndef VM_ASSEMBLER_MIPS_H_ |
6 #define VM_ASSEMBLER_MIPS_H_ | 6 #define VM_ASSEMBLER_MIPS_H_ |
7 | 7 |
8 #ifndef VM_ASSEMBLER_H_ | 8 #ifndef VM_ASSEMBLER_H_ |
9 #error Do not include assembler_mips.h directly; use assembler.h instead. | 9 #error Do not include assembler_mips.h directly; use assembler.h instead. |
10 #endif | 10 #endif |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 | 51 |
52 Address(const Address& other) | 52 Address(const Address& other) |
53 : ValueObject(), base_(other.base_), offset_(other.offset_) { } | 53 : ValueObject(), base_(other.base_), offset_(other.offset_) { } |
54 Address& operator=(const Address& other) { | 54 Address& operator=(const Address& other) { |
55 base_ = other.base_; | 55 base_ = other.base_; |
56 offset_ = other.offset_; | 56 offset_ = other.offset_; |
57 return *this; | 57 return *this; |
58 } | 58 } |
59 | 59 |
60 uint32_t encoding() const { | 60 uint32_t encoding() const { |
61 ASSERT(Utils::IsInt(16, offset_)); | 61 ASSERT(Utils::IsInt(kImmBits, offset_)); |
62 uint16_t imm_value = static_cast<uint16_t>(offset_); | 62 uint16_t imm_value = static_cast<uint16_t>(offset_); |
63 return (base_ << kRsShift) | imm_value; | 63 return (base_ << kRsShift) | imm_value; |
64 } | 64 } |
65 | 65 |
66 static bool CanHoldOffset(int32_t offset) { | 66 static bool CanHoldOffset(int32_t offset) { |
67 return Utils::IsInt(16, offset); | 67 return Utils::IsInt(kImmBits, offset); |
68 } | 68 } |
69 | 69 |
70 private: | 70 private: |
71 Register base_; | 71 Register base_; |
72 int32_t offset_; | 72 int32_t offset_; |
73 }; | 73 }; |
74 | 74 |
75 | 75 |
76 class FieldAddress : public Address { | 76 class FieldAddress : public Address { |
77 public: | 77 public: |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
217 ASSERT(buffer_.Load<int32_t>(buffer_.GetPosition() - sizeof(int32_t)) == | 217 ASSERT(buffer_.Load<int32_t>(buffer_.GetPosition() - sizeof(int32_t)) == |
218 Instr::kNopInstruction); | 218 Instr::kNopInstruction); |
219 buffer_.Remit<int32_t>(); | 219 buffer_.Remit<int32_t>(); |
220 delay_slot_available_ = false; | 220 delay_slot_available_ = false; |
221 in_delay_slot_ = true; | 221 in_delay_slot_ = true; |
222 return this; | 222 return this; |
223 } | 223 } |
224 | 224 |
225 // CPU instructions in alphabetical order. | 225 // CPU instructions in alphabetical order. |
226 void addiu(Register rt, Register rs, const Immediate& imm) { | 226 void addiu(Register rt, Register rs, const Immediate& imm) { |
227 ASSERT(Utils::IsInt(16, imm.value())); | 227 ASSERT(Utils::IsInt(kImmBits, imm.value())); |
228 const uint16_t imm_value = static_cast<uint16_t>(imm.value()); | 228 const uint16_t imm_value = static_cast<uint16_t>(imm.value()); |
229 EmitIType(ADDIU, rs, rt, imm_value); | 229 EmitIType(ADDIU, rs, rt, imm_value); |
230 } | 230 } |
231 | 231 |
232 void addu(Register rd, Register rs, Register rt) { | 232 void addu(Register rd, Register rs, Register rt) { |
233 EmitRType(SPECIAL, rs, rt, rd, 0, ADDU); | 233 EmitRType(SPECIAL, rs, rt, rd, 0, ADDU); |
234 } | 234 } |
235 | 235 |
236 void and_(Register rd, Register rs, Register rt) { | 236 void and_(Register rd, Register rs, Register rt) { |
237 EmitRType(SPECIAL, rs, rt, rd, 0, AND); | 237 EmitRType(SPECIAL, rs, rt, rd, 0, AND); |
238 } | 238 } |
239 | 239 |
240 void andi(Register rt, Register rs, const Immediate& imm) { | 240 void andi(Register rt, Register rs, const Immediate& imm) { |
241 ASSERT(Utils::IsUint(16, imm.value())); | 241 ASSERT(Utils::IsUint(kImmBits, imm.value())); |
242 const uint16_t imm_value = static_cast<uint16_t>(imm.value()); | 242 const uint16_t imm_value = static_cast<uint16_t>(imm.value()); |
243 EmitIType(ANDI, rs, rt, imm_value); | 243 EmitIType(ANDI, rs, rt, imm_value); |
244 } | 244 } |
245 | 245 |
246 // Unconditional branch. | 246 // Unconditional branch. |
247 void b(Label* l) { | 247 void b(Label* l) { |
248 beq(R0, R0, l); | 248 beq(R0, R0, l); |
249 } | 249 } |
250 | 250 |
251 void bal(Label *l) { | 251 void bal(Label *l) { |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 | 390 |
391 void lh(Register rt, const Address& addr) { | 391 void lh(Register rt, const Address& addr) { |
392 EmitLoadStore(LH, rt, addr); | 392 EmitLoadStore(LH, rt, addr); |
393 } | 393 } |
394 | 394 |
395 void lhu(Register rt, const Address& addr) { | 395 void lhu(Register rt, const Address& addr) { |
396 EmitLoadStore(LHU, rt, addr); | 396 EmitLoadStore(LHU, rt, addr); |
397 } | 397 } |
398 | 398 |
399 void lui(Register rt, const Immediate& imm) { | 399 void lui(Register rt, const Immediate& imm) { |
400 ASSERT(Utils::IsUint(16, imm.value())); | 400 ASSERT(Utils::IsUint(kImmBits, imm.value())); |
401 uint16_t imm_value = static_cast<uint16_t>(imm.value()); | 401 uint16_t imm_value = static_cast<uint16_t>(imm.value()); |
402 EmitIType(LUI, R0, rt, imm_value); | 402 EmitIType(LUI, R0, rt, imm_value); |
403 } | 403 } |
404 | 404 |
405 void lw(Register rt, const Address& addr) { | 405 void lw(Register rt, const Address& addr) { |
406 EmitLoadStore(LW, rt, addr); | 406 EmitLoadStore(LW, rt, addr); |
407 } | 407 } |
408 | 408 |
409 void mfhi(Register rd) { | 409 void mfhi(Register rd) { |
410 EmitRType(SPECIAL, R0, R0, rd, 0, MFHI); | 410 EmitRType(SPECIAL, R0, R0, rd, 0, MFHI); |
(...skipping 29 matching lines...) Expand all Loading... |
440 | 440 |
441 void nor(Register rd, Register rs, Register rt) { | 441 void nor(Register rd, Register rs, Register rt) { |
442 EmitRType(SPECIAL, rs, rt, rd, 0, NOR); | 442 EmitRType(SPECIAL, rs, rt, rd, 0, NOR); |
443 } | 443 } |
444 | 444 |
445 void or_(Register rd, Register rs, Register rt) { | 445 void or_(Register rd, Register rs, Register rt) { |
446 EmitRType(SPECIAL, rs, rt, rd, 0, OR); | 446 EmitRType(SPECIAL, rs, rt, rd, 0, OR); |
447 } | 447 } |
448 | 448 |
449 void ori(Register rt, Register rs, const Immediate& imm) { | 449 void ori(Register rt, Register rs, const Immediate& imm) { |
450 ASSERT(Utils::IsUint(16, imm.value())); | 450 ASSERT(Utils::IsUint(kImmBits, imm.value())); |
451 uint16_t imm_value = static_cast<uint16_t>(imm.value()); | 451 uint16_t imm_value = static_cast<uint16_t>(imm.value()); |
452 EmitIType(ORI, rs, rt, imm_value); | 452 EmitIType(ORI, rs, rt, imm_value); |
453 } | 453 } |
454 | 454 |
455 void sb(Register rt, const Address& addr) { | 455 void sb(Register rt, const Address& addr) { |
456 EmitLoadStore(SB, rt, addr); | 456 EmitLoadStore(SB, rt, addr); |
457 } | 457 } |
458 | 458 |
459 void sh(Register rt, const Address& addr) { | 459 void sh(Register rt, const Address& addr) { |
460 EmitLoadStore(SH, rt, addr); | 460 EmitLoadStore(SH, rt, addr); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 } | 501 } |
502 | 502 |
503 void xor_(Register rd, Register rs, Register rt) { | 503 void xor_(Register rd, Register rs, Register rt) { |
504 EmitRType(SPECIAL, rs, rt, rd, 0, XOR); | 504 EmitRType(SPECIAL, rs, rt, rd, 0, XOR); |
505 } | 505 } |
506 | 506 |
507 // Macros in alphabetical order. | 507 // Macros in alphabetical order. |
508 | 508 |
509 // Addition of rs and rt with the result placed in rd. | 509 // Addition of rs and rt with the result placed in rd. |
510 // After, ro < 0 if there was signed overflow, ro >= 0 otherwise. | 510 // After, ro < 0 if there was signed overflow, ro >= 0 otherwise. |
511 // A scratch register is needed when rd, rs, and rt are the same | 511 // rd and ro must not be TMP1 or TMP2. |
512 // register. The scratch register may not be TMP. | |
513 // ro must be different from all the other registers. | 512 // ro must be different from all the other registers. |
514 void AdduDetectOverflow(Register rd, Register rs, Register rt, Register ro, | 513 void AdduDetectOverflow(Register rd, Register rs, Register rt, Register ro); |
515 Register scratch = kNoRegister); | 514 |
| 515 // ro must be different from rd and rs. |
| 516 // rd and ro must not be TMP1 or TMP2 |
| 517 void AddImmediateDetectOverflow(Register rd, Register rs, int32_t imm, |
| 518 Register ro) { |
| 519 LoadImmediate(rd, imm); |
| 520 AdduDetectOverflow(rd, rs, rd, ro); |
| 521 } |
516 | 522 |
517 void Branch(const ExternalLabel* label) { | 523 void Branch(const ExternalLabel* label) { |
518 LoadImmediate(TMP, label->address()); | 524 LoadImmediate(TMP1, label->address()); |
519 jr(TMP); | 525 jr(TMP1); |
520 } | 526 } |
521 | 527 |
522 void BranchPatchable(const ExternalLabel* label) { | 528 void BranchPatchable(const ExternalLabel* label) { |
523 const uint16_t low = Utils::Low16Bits(label->address()); | 529 const uint16_t low = Utils::Low16Bits(label->address()); |
524 const uint16_t high = Utils::High16Bits(label->address()); | 530 const uint16_t high = Utils::High16Bits(label->address()); |
525 lui(TMP, Immediate(high)); | 531 lui(TMP1, Immediate(high)); |
526 ori(TMP, TMP, Immediate(low)); | 532 ori(TMP1, TMP1, Immediate(low)); |
527 jr(TMP); | 533 jr(TMP1); |
528 delay_slot_available_ = false; // CodePatcher expects a nop. | 534 delay_slot_available_ = false; // CodePatcher expects a nop. |
529 } | 535 } |
530 | 536 |
531 void BranchLink(const ExternalLabel* label) { | 537 void BranchLink(const ExternalLabel* label) { |
532 LoadImmediate(TMP, label->address()); | 538 LoadImmediate(TMP1, label->address()); |
533 jalr(TMP); | 539 jalr(TMP1); |
534 } | 540 } |
535 | 541 |
536 void BranchLinkPatchable(const ExternalLabel* label) { | 542 void BranchLinkPatchable(const ExternalLabel* label) { |
537 const int32_t offset = | 543 const int32_t offset = |
538 Array::data_offset() + 4*AddExternalLabel(label) - kHeapObjectTag; | 544 Array::data_offset() + 4*AddExternalLabel(label) - kHeapObjectTag; |
539 LoadWordFromPoolOffset(TMP, offset); | 545 LoadWordFromPoolOffset(TMP1, offset); |
540 jalr(TMP); | 546 jalr(TMP1); |
541 delay_slot_available_ = false; // CodePatcher expects a nop. | 547 delay_slot_available_ = false; // CodePatcher expects a nop. |
542 } | 548 } |
543 | 549 |
544 // If the signed value in rs is less than value, rd is 1, and 0 otherwise. | |
545 void LessThanSImmediate(Register rd, Register rs, int32_t value) { | |
546 LoadImmediate(TMP, value); | |
547 slt(rd, rs, TMP); | |
548 } | |
549 | |
550 // If the unsigned value in rs is less than value, rd is 1, and 0 otherwise. | |
551 void LessThanUImmediate(Register rd, Register rs, uint32_t value) { | |
552 LoadImmediate(TMP, value); | |
553 sltu(rd, rs, TMP); | |
554 } | |
555 | |
556 void Drop(intptr_t stack_elements) { | 550 void Drop(intptr_t stack_elements) { |
557 ASSERT(stack_elements >= 0); | 551 ASSERT(stack_elements >= 0); |
558 if (stack_elements > 0) { | 552 if (stack_elements > 0) { |
559 addiu(SP, SP, Immediate(stack_elements * kWordSize)); | 553 addiu(SP, SP, Immediate(stack_elements * kWordSize)); |
560 } | 554 } |
561 } | 555 } |
562 | 556 |
563 void LoadImmediate(Register rd, int32_t value) { | 557 void LoadImmediate(Register rd, int32_t value) { |
564 if (Utils::IsInt(16, value)) { | 558 if (Utils::IsInt(kImmBits, value)) { |
565 addiu(rd, ZR, Immediate(value)); | 559 addiu(rd, ZR, Immediate(value)); |
566 } else { | 560 } else { |
567 const uint16_t low = Utils::Low16Bits(value); | 561 const uint16_t low = Utils::Low16Bits(value); |
568 const uint16_t high = Utils::High16Bits(value); | 562 const uint16_t high = Utils::High16Bits(value); |
569 lui(rd, Immediate(high)); | 563 lui(rd, Immediate(high)); |
570 ori(rd, rd, Immediate(low)); | 564 ori(rd, rd, Immediate(low)); |
571 } | 565 } |
572 } | 566 } |
573 | 567 |
| 568 void BranchEqual(Register rd, int32_t value, Label* l) { |
| 569 LoadImmediate(TMP1, value); |
| 570 beq(rd, TMP1, l); |
| 571 } |
| 572 |
| 573 void BranchEqual(Register rd, const Object& object, Label* l) { |
| 574 LoadObject(TMP1, object); |
| 575 beq(rd, TMP1, l); |
| 576 } |
| 577 |
| 578 void BranchNotEqual(Register rd, int32_t value, Label* l) { |
| 579 LoadImmediate(TMP1, value); |
| 580 bne(rd, TMP1, l); |
| 581 } |
| 582 |
| 583 void BranchNotEqual(Register rd, const Object& object, Label* l) { |
| 584 LoadObject(TMP1, object); |
| 585 bne(rd, TMP1, l); |
| 586 } |
| 587 |
| 588 void BranchGreater(Register rd, int32_t value, Label* l) { |
| 589 if (Utils::IsInt(kImmBits, -value)) { |
| 590 addiu(TMP1, rd, Immediate(-value)); |
| 591 bgtz(TMP1, l); |
| 592 } else { |
| 593 LoadImmediate(TMP1, value); |
| 594 subu(TMP1, rd, TMP1); |
| 595 bgtz(TMP1, l); |
| 596 } |
| 597 } |
| 598 |
| 599 void BranchGreater(Register rd, Register rs, Label* l) { |
| 600 subu(TMP1, rd, rs); |
| 601 bgtz(TMP1, l); |
| 602 } |
| 603 |
| 604 void BranchGreaterEqual(Register rd, int32_t value, Label* l) { |
| 605 if (Utils::IsInt(kImmBits, -value)) { |
| 606 addiu(TMP1, rd, Immediate(-value)); |
| 607 bgez(TMP1, l); |
| 608 } else { |
| 609 LoadImmediate(TMP1, value); |
| 610 subu(TMP1, rd, TMP1); |
| 611 bgez(TMP1, l); |
| 612 } |
| 613 } |
| 614 |
| 615 void BranchGreaterEqual(Register rd, Register rs, Label* l) { |
| 616 subu(TMP1, rd, rs); |
| 617 bgez(TMP1, l); |
| 618 } |
| 619 |
| 620 void BranchLess(Register rd, int32_t value, Label* l) { |
| 621 if (Utils::IsInt(kImmBits, -value)) { |
| 622 addiu(TMP1, rd, Immediate(-value)); |
| 623 bltz(TMP1, l); |
| 624 } else { |
| 625 LoadImmediate(TMP1, value); |
| 626 subu(TMP1, rd, TMP1); |
| 627 bltz(TMP1, l); |
| 628 } |
| 629 } |
| 630 |
| 631 void BranchLess(Register rd, Register rs, Label* l) { |
| 632 subu(TMP1, rd, rs); |
| 633 bltz(TMP1, l); |
| 634 } |
| 635 |
| 636 void BranchLessEqual(Register rd, int32_t value, Label* l) { |
| 637 if (Utils::IsInt(kImmBits, -value)) { |
| 638 addiu(TMP1, rd, Immediate(-value)); |
| 639 blez(TMP1, l); |
| 640 } else { |
| 641 LoadImmediate(TMP1, value); |
| 642 subu(TMP1, rd, TMP1); |
| 643 blez(TMP1, l); |
| 644 } |
| 645 } |
| 646 |
| 647 void BranchLessEqual(Register rd, Register rs, Label* l) { |
| 648 subu(TMP1, rd, rs); |
| 649 blez(TMP1, l); |
| 650 } |
| 651 |
574 void Push(Register rt) { | 652 void Push(Register rt) { |
575 addiu(SP, SP, Immediate(-kWordSize)); | 653 addiu(SP, SP, Immediate(-kWordSize)); |
576 sw(rt, Address(SP)); | 654 sw(rt, Address(SP)); |
577 } | 655 } |
578 | 656 |
579 void Pop(Register rt) { | 657 void Pop(Register rt) { |
580 lw(rt, Address(SP)); | 658 lw(rt, Address(SP)); |
581 addiu(SP, SP, Immediate(kWordSize)); | 659 addiu(SP, SP, Immediate(kWordSize)); |
582 } | 660 } |
583 | 661 |
(...skipping 14 matching lines...) Expand all Loading... |
598 void LoadWordFromPoolOffset(Register rd, int32_t offset); | 676 void LoadWordFromPoolOffset(Register rd, int32_t offset); |
599 void LoadObject(Register rd, const Object& object); | 677 void LoadObject(Register rd, const Object& object); |
600 void PushObject(const Object& object); | 678 void PushObject(const Object& object); |
601 | 679 |
602 // Sets register rd to zero if the object is equal to register rn, | 680 // Sets register rd to zero if the object is equal to register rn, |
603 // set to non-zero otherwise. | 681 // set to non-zero otherwise. |
604 void CompareObject(Register rd, Register rn, const Object& object); | 682 void CompareObject(Register rd, Register rn, const Object& object); |
605 | 683 |
606 void LoadClassId(Register result, Register object); | 684 void LoadClassId(Register result, Register object); |
607 void LoadClassById(Register result, Register class_id); | 685 void LoadClassById(Register result, Register class_id); |
608 void LoadClass(Register result, Register object, Register scratch); | 686 void LoadClass(Register result, Register object); |
609 | 687 |
610 void CallRuntime(const RuntimeEntry& entry); | 688 void CallRuntime(const RuntimeEntry& entry); |
611 | 689 |
612 // Set up a Dart frame on entry with a frame pointer and PC information to | 690 // Set up a Dart frame on entry with a frame pointer and PC information to |
613 // enable easy access to the RawInstruction object of code corresponding | 691 // enable easy access to the RawInstruction object of code corresponding |
614 // to this frame. | 692 // to this frame. |
615 void EnterDartFrame(intptr_t frame_size); | 693 void EnterDartFrame(intptr_t frame_size); |
616 void LeaveDartFrame(); | 694 void LeaveDartFrame(); |
617 | 695 |
618 private: | 696 private: |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 delay_slot_available_ = true; | 815 delay_slot_available_ = true; |
738 } | 816 } |
739 | 817 |
740 DISALLOW_ALLOCATION(); | 818 DISALLOW_ALLOCATION(); |
741 DISALLOW_COPY_AND_ASSIGN(Assembler); | 819 DISALLOW_COPY_AND_ASSIGN(Assembler); |
742 }; | 820 }; |
743 | 821 |
744 } // namespace dart | 822 } // namespace dart |
745 | 823 |
746 #endif // VM_ASSEMBLER_MIPS_H_ | 824 #endif // VM_ASSEMBLER_MIPS_H_ |
OLD | NEW |