| 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 |