| 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 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 485 } | 485 } |
| 486 | 486 |
| 487 void srl(Register rd, Register rt, int sa) { | 487 void srl(Register rd, Register rt, int sa) { |
| 488 EmitRType(SPECIAL, R0, rt, rd, sa, SRL); | 488 EmitRType(SPECIAL, R0, rt, rd, sa, SRL); |
| 489 } | 489 } |
| 490 | 490 |
| 491 void srlv(Register rd, Register rt, Register rs) { | 491 void srlv(Register rd, Register rt, Register rs) { |
| 492 EmitRType(SPECIAL, rs, rt, rd, 0, SRLV); | 492 EmitRType(SPECIAL, rs, rt, rd, 0, SRLV); |
| 493 } | 493 } |
| 494 | 494 |
| 495 void sub(Register rd, Register rs, Register rt) { | |
| 496 EmitRType(SPECIAL, rs, rt, rd, 0, SUB); | |
| 497 } | |
| 498 | |
| 499 void subu(Register rd, Register rs, Register rt) { | 495 void subu(Register rd, Register rs, Register rt) { |
| 500 EmitRType(SPECIAL, rs, rt, rd, 0, SUBU); | 496 EmitRType(SPECIAL, rs, rt, rd, 0, SUBU); |
| 501 } | 497 } |
| 502 | 498 |
| 503 void sw(Register rt, const Address& addr) { | 499 void sw(Register rt, const Address& addr) { |
| 504 EmitLoadStore(SW, rt, addr); | 500 EmitLoadStore(SW, rt, addr); |
| 505 } | 501 } |
| 506 | 502 |
| 507 void xor_(Register rd, Register rs, Register rt) { | 503 void xor_(Register rd, Register rs, Register rt) { |
| 508 EmitRType(SPECIAL, rs, rt, rd, 0, XOR); | 504 EmitRType(SPECIAL, rs, rt, rd, 0, XOR); |
| 509 } | 505 } |
| 510 | 506 |
| 511 // Macros in alphabetical order. | 507 // Macros in alphabetical order. |
| 512 | 508 |
| 513 void Branch(const ExternalLabel* label) { | 509 void Branch(const ExternalLabel* label) { |
| 514 LoadImmediate(TMP, label->address()); | 510 LoadImmediate(TMP, label->address()); |
| 515 jr(TMP); | 511 jr(TMP); |
| 516 } | 512 } |
| 517 | 513 |
| 518 void BranchPatchable(const ExternalLabel* label) { | 514 void BranchPatchable(const ExternalLabel* label) { |
| 519 const uint16_t low = Utils::Low16Bits(label->address()); | 515 const uint16_t low = Utils::Low16Bits(label->address()); |
| 520 const uint16_t high = Utils::High16Bits(label->address()); | 516 const uint16_t high = Utils::High16Bits(label->address()); |
| 521 lui(TMP, Immediate(high)); | 517 lui(TMP, Immediate(high)); |
| 522 ori(TMP, TMP, Immediate(low)); | 518 ori(TMP, TMP, Immediate(low)); |
| 523 jr(TMP); | 519 jr(TMP); |
| 524 delay_slot()->nop(); | 520 delay_slot_available_ = false; // CodePatcher expects a nop. |
| 525 } | 521 } |
| 526 | 522 |
| 527 void BranchLink(const ExternalLabel* label) { | 523 void BranchLink(const ExternalLabel* label) { |
| 528 LoadImmediate(TMP, label->address()); | 524 LoadImmediate(TMP, label->address()); |
| 529 jalr(TMP); | 525 jalr(TMP); |
| 530 } | 526 } |
| 531 | 527 |
| 532 void BranchLinkPatchable(const ExternalLabel* label) { | 528 void BranchLinkPatchable(const ExternalLabel* label) { |
| 533 const int32_t offset = | 529 const int32_t offset = |
| 534 Array::data_offset() + 4*AddExternalLabel(label) - kHeapObjectTag; | 530 Array::data_offset() + 4*AddExternalLabel(label) - kHeapObjectTag; |
| 535 LoadWordFromPoolOffset(TMP, offset); | 531 LoadWordFromPoolOffset(TMP, offset); |
| 536 jalr(TMP); | 532 jalr(TMP); |
| 537 delay_slot()->nop(); | 533 delay_slot_available_ = false; // CodePatcher expects a nop. |
| 538 } | 534 } |
| 539 | 535 |
| 540 // If the signed value in rs is less than value, rd is 1, and 0 otherwise. | 536 // If the signed value in rs is less than value, rd is 1, and 0 otherwise. |
| 541 void LessThanSImmediate(Register rd, Register rs, int32_t value) { | 537 void LessThanSImmediate(Register rd, Register rs, int32_t value) { |
| 542 LoadImmediate(TMP, value); | 538 LoadImmediate(TMP, value); |
| 543 slt(rd, rs, TMP); | 539 slt(rd, rs, TMP); |
| 544 } | 540 } |
| 545 | 541 |
| 546 // If the unsigned value in rs is less than value, rd is 1, and 0 otherwise. | 542 // If the unsigned value in rs is less than value, rd is 1, and 0 otherwise. |
| 547 void LessThanUImmediate(Register rd, Register rs, uint32_t value) { | 543 void LessThanUImmediate(Register rd, Register rs, uint32_t value) { |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 void EmitRegImmType(Opcode opcode, | 661 void EmitRegImmType(Opcode opcode, |
| 666 Register rs, | 662 Register rs, |
| 667 RtRegImm code, | 663 RtRegImm code, |
| 668 uint16_t imm) { | 664 uint16_t imm) { |
| 669 Emit(opcode << kOpcodeShift | | 665 Emit(opcode << kOpcodeShift | |
| 670 rs << kRsShift | | 666 rs << kRsShift | |
| 671 code << kRtShift | | 667 code << kRtShift | |
| 672 imm); | 668 imm); |
| 673 } | 669 } |
| 674 | 670 |
| 675 void EmitJType(Opcode opcode, Label* label) { | 671 void EmitJType(Opcode opcode, uint32_t destination) { |
| 676 UNIMPLEMENTED(); | 672 UNIMPLEMENTED(); |
| 677 } | 673 } |
| 678 | 674 |
| 679 void EmitRType(Opcode opcode, | 675 void EmitRType(Opcode opcode, |
| 680 Register rs, | 676 Register rs, |
| 681 Register rt, | 677 Register rt, |
| 682 Register rd, | 678 Register rd, |
| 683 int sa, | 679 int sa, |
| 684 SpecialFunction func) { | 680 SpecialFunction func) { |
| 685 ASSERT(Utils::IsUint(5, sa)); | 681 ASSERT(Utils::IsUint(5, sa)); |
| 686 Emit(opcode << kOpcodeShift | | 682 Emit(opcode << kOpcodeShift | |
| 687 rs << kRsShift | | 683 rs << kRsShift | |
| 688 rt << kRtShift | | 684 rt << kRtShift | |
| 689 rd << kRdShift | | 685 rd << kRdShift | |
| 690 sa << kSaShift | | 686 sa << kSaShift | |
| 691 func << kFunctionShift); | 687 func << kFunctionShift); |
| 692 } | 688 } |
| 693 | 689 |
| 694 void EmitBranch(Opcode b, Register rs, Register rt, Label* label) { | 690 void EmitBranch(Opcode b, Register rs, Register rt, Label* label) { |
| 695 if (label->IsBound()) { | 691 if (label->IsBound()) { |
| 696 // Relative destination from an instruction after the branch. | 692 // Relative destination from an instruction after the branch. |
| 697 const int32_t dest = | 693 const int32_t dest = |
| 698 label->Position() - (buffer_.Size() + Instr::kInstrSize); | 694 label->Position() - (buffer_.Size() + Instr::kInstrSize); |
| 699 const uint16_t dest_off = EncodeBranchOffset(dest, 0); | 695 const uint16_t dest_off = EncodeBranchOffset(dest, 0); |
| 700 EmitIType(b, rs, rt, dest_off); | 696 EmitIType(b, rs, rt, dest_off); |
| 701 } else { | 697 } else { |
| 702 const int position = buffer_.Size(); | 698 const int position = buffer_.Size(); |
| 703 EmitIType(b, rs, rt, label->position_); | 699 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); |
| 700 EmitIType(b, rs, rt, dest_off); |
| 704 label->LinkTo(position); | 701 label->LinkTo(position); |
| 705 } | 702 } |
| 706 } | 703 } |
| 707 | 704 |
| 708 void EmitRegImmBranch(RtRegImm b, Register rs, Label* label) { | 705 void EmitRegImmBranch(RtRegImm b, Register rs, Label* label) { |
| 709 if (label->IsBound()) { | 706 if (label->IsBound()) { |
| 710 // Relative destination from an instruction after the branch. | 707 // Relative destination from an instruction after the branch. |
| 711 const int32_t dest = | 708 const int32_t dest = |
| 712 label->Position() - (buffer_.Size() + Instr::kInstrSize); | 709 label->Position() - (buffer_.Size() + Instr::kInstrSize); |
| 713 const uint16_t dest_off = EncodeBranchOffset(dest, 0); | 710 const uint16_t dest_off = EncodeBranchOffset(dest, 0); |
| 714 EmitRegImmType(REGIMM, rs, b, dest_off); | 711 EmitRegImmType(REGIMM, rs, b, dest_off); |
| 715 } else { | 712 } else { |
| 716 const int position = buffer_.Size(); | 713 const int position = buffer_.Size(); |
| 717 EmitRegImmType(REGIMM, rs, b, label->position_); | 714 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); |
| 715 EmitRegImmType(REGIMM, rs, b, dest_off); |
| 718 label->LinkTo(position); | 716 label->LinkTo(position); |
| 719 } | 717 } |
| 720 } | 718 } |
| 721 | 719 |
| 722 static int32_t EncodeBranchOffset(int32_t offset, int32_t instr); | 720 static int32_t EncodeBranchOffset(int32_t offset, int32_t instr); |
| 723 static int DecodeBranchOffset(int32_t instr); | 721 static int DecodeBranchOffset(int32_t instr); |
| 724 | 722 |
| 725 void EmitBranchDelayNop() { | 723 void EmitBranchDelayNop() { |
| 726 Emit(Instr::kNopInstruction); // Branch delay NOP. | 724 Emit(Instr::kNopInstruction); // Branch delay NOP. |
| 727 delay_slot_available_ = true; | 725 delay_slot_available_ = true; |
| 728 } | 726 } |
| 729 | 727 |
| 730 DISALLOW_ALLOCATION(); | 728 DISALLOW_ALLOCATION(); |
| 731 DISALLOW_COPY_AND_ASSIGN(Assembler); | 729 DISALLOW_COPY_AND_ASSIGN(Assembler); |
| 732 }; | 730 }; |
| 733 | 731 |
| 734 } // namespace dart | 732 } // namespace dart |
| 735 | 733 |
| 736 #endif // VM_ASSEMBLER_MIPS_H_ | 734 #endif // VM_ASSEMBLER_MIPS_H_ |
| OLD | NEW |