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

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

Issue 12703028: Adds Stop to MIPS. Starts on MIPS call patcher. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 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
OLDNEW
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
51 offset_ = other.offset_; 51 offset_ = other.offset_;
52 return *this; 52 return *this;
53 } 53 }
54 54
55 uint32_t encoding() const { 55 uint32_t encoding() const {
56 ASSERT(Utils::IsInt(16, offset_)); 56 ASSERT(Utils::IsInt(16, offset_));
57 uint16_t imm_value = static_cast<uint16_t>(offset_); 57 uint16_t imm_value = static_cast<uint16_t>(offset_);
58 return (base_ << kRsShift) | imm_value; 58 return (base_ << kRsShift) | imm_value;
59 } 59 }
60 60
61 static bool CanHoldOffset(int32_t offset) {
62 return Utils::IsInt(16, offset);
63 }
64
61 private: 65 private:
62 Register base_; 66 Register base_;
63 int32_t offset_; 67 int32_t offset_;
64 }; 68 };
65 69
66 70
67 class FieldAddress : public Address { 71 class FieldAddress : public Address {
68 public: 72 public:
69 FieldAddress(Register base, int32_t disp) 73 FieldAddress(Register base, int32_t disp)
70 : Address(base, disp - kHeapObjectTag) { } 74 : Address(base, disp - kHeapObjectTag) { }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 public: 140 public:
137 Assembler() 141 Assembler()
138 : buffer_(), 142 : buffer_(),
139 object_pool_(GrowableObjectArray::Handle()), 143 object_pool_(GrowableObjectArray::Handle()),
140 prologue_offset_(-1), 144 prologue_offset_(-1),
141 delay_slot_available_(false), 145 delay_slot_available_(false),
142 in_delay_slot_(false), 146 in_delay_slot_(false),
143 comments_() { } 147 comments_() { }
144 ~Assembler() { } 148 ~Assembler() { }
145 149
146 void PopRegister(Register r) { 150 void PopRegister(Register r) { Pop(r); }
147 UNIMPLEMENTED();
148 }
149 151
150 void Bind(Label* label); 152 void Bind(Label* label);
151 153
152 // Misc. functionality 154 // Misc. functionality
153 int CodeSize() const { return buffer_.Size(); } 155 int CodeSize() const { return buffer_.Size(); }
154 int prologue_offset() const { return -1; } 156 int prologue_offset() const { return -1; }
155 const ZoneGrowableArray<int>& GetPointerOffsets() const { 157 const ZoneGrowableArray<int>& GetPointerOffsets() const {
156 return buffer_.pointer_offsets(); 158 return buffer_.pointer_offsets();
157 } 159 }
158 const GrowableObjectArray& object_pool() const { return object_pool_; } 160 const GrowableObjectArray& object_pool() const { return object_pool_; }
(...skipping 24 matching lines...) Expand all
183 // Allocated instance is returned in 'instance_reg'. 185 // Allocated instance is returned in 'instance_reg'.
184 // Only the tags field of the object is initialized. 186 // Only the tags field of the object is initialized.
185 void TryAllocate(const Class& cls, 187 void TryAllocate(const Class& cls,
186 Label* failure, 188 Label* failure,
187 bool near_jump, 189 bool near_jump,
188 Register instance_reg) { 190 Register instance_reg) {
189 UNIMPLEMENTED(); 191 UNIMPLEMENTED();
190 } 192 }
191 193
192 // Debugging and bringup support. 194 // Debugging and bringup support.
193 void Stop(const char* message) { UNIMPLEMENTED(); } 195 void Stop(const char* message);
194 void Unimplemented(const char* message); 196 void Unimplemented(const char* message);
195 void Untested(const char* message); 197 void Untested(const char* message);
196 void Unreachable(const char* message); 198 void Unreachable(const char* message);
197 199
198 static void InitializeMemoryWithBreakpoints(uword data, int length); 200 static void InitializeMemoryWithBreakpoints(uword data, int length);
199 201
200 void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); 202 void Comment(const char* format, ...) PRINTF_ATTRIBUTE(2, 3);
201 203
202 const Code::Comments& GetCodeComments() const; 204 const Code::Comments& GetCodeComments() const;
203 205
(...skipping 14 matching lines...) Expand all
218 Instr::kNopInstruction); 220 Instr::kNopInstruction);
219 buffer_.Remit<int32_t>(); 221 buffer_.Remit<int32_t>();
220 delay_slot_available_ = false; 222 delay_slot_available_ = false;
221 in_delay_slot_ = true; 223 in_delay_slot_ = true;
222 return this; 224 return this;
223 } 225 }
224 226
225 // CPU instructions in alphabetical order. 227 // CPU instructions in alphabetical order.
226 void addiu(Register rt, Register rs, const Immediate& imm) { 228 void addiu(Register rt, Register rs, const Immediate& imm) {
227 ASSERT(Utils::IsInt(16, imm.value())); 229 ASSERT(Utils::IsInt(16, imm.value()));
228 uint16_t imm_value = static_cast<uint16_t>(imm.value()); 230 const uint16_t imm_value = static_cast<uint16_t>(imm.value());
229 EmitIType(ADDIU, rs, rt, imm_value); 231 EmitIType(ADDIU, rs, rt, imm_value);
230 } 232 }
231 233
232 void addu(Register rd, Register rs, Register rt) { 234 void addu(Register rd, Register rs, Register rt) {
233 EmitRType(SPECIAL, rs, rt, rd, 0, ADDU); 235 EmitRType(SPECIAL, rs, rt, rd, 0, ADDU);
234 } 236 }
235 237
236 void and_(Register rd, Register rs, Register rt) { 238 void and_(Register rd, Register rs, Register rt) {
237 EmitRType(SPECIAL, rs, rt, rd, 0, AND); 239 EmitRType(SPECIAL, rs, rt, rd, 0, AND);
238 } 240 }
239 241
240 void andi(Register rt, Register rs, const Immediate& imm) { 242 void andi(Register rt, Register rs, const Immediate& imm) {
241 ASSERT(Utils::IsUint(16, imm.value())); 243 ASSERT(Utils::IsUint(16, imm.value()));
242 uint16_t imm_value = static_cast<uint16_t>(imm.value()); 244 const uint16_t imm_value = static_cast<uint16_t>(imm.value());
243 EmitIType(ANDI, rs, rt, imm_value); 245 EmitIType(ANDI, rs, rt, imm_value);
244 } 246 }
245 247
246 // Unconditional branch. 248 // Unconditional branch.
247 void b(Label* l) { 249 void b(Label* l) {
248 beq(R0, R0, l); 250 beq(R0, R0, l);
249 } 251 }
250 252
251 // Branch if equal. 253 // Branch if equal.
252 void beq(Register rs, Register rt, Label* l) { 254 void beq(Register rs, Register rt, Label* l) {
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 498
497 void sw(Register rt, const Address& addr) { 499 void sw(Register rt, const Address& addr) {
498 EmitLoadStore(SW, rt, addr); 500 EmitLoadStore(SW, rt, addr);
499 } 501 }
500 502
501 void xor_(Register rd, Register rs, Register rt) { 503 void xor_(Register rd, Register rs, Register rt) {
502 EmitRType(SPECIAL, rs, rt, rd, 0, XOR); 504 EmitRType(SPECIAL, rs, rt, rd, 0, XOR);
503 } 505 }
504 506
505 // Macros in alphabetical order. 507 // Macros in alphabetical order.
508
509 void Branch(const ExternalLabel* label) {
510 // Doesn't need to be patchable, so use the delay slot.
511 if (Utils::IsInt(16, label->address())) {
512 jr(TMP);
513 delay_slot()->addiu(TMP, ZR, Immediate(label->address()));
514 } else {
515 const uint16_t low = Utils::Low16Bits(label->address());
516 const uint16_t high = Utils::High16Bits(label->address());
517 lui(TMP, Immediate(high));
518 jr(TMP);
519 delay_slot()->ori(TMP, TMP, Immediate(low));
520 }
521 }
522
523 void BranchLink(const ExternalLabel* label) {
524 // Doesn't need to be patchable, so use the delay slot.
525 if (Utils::IsInt(16, label->address())) {
526 jalr(TMP);
527 delay_slot()->addiu(TMP, ZR, Immediate(label->address()));
528 } else {
529 const uint16_t low = Utils::Low16Bits(label->address());
530 const uint16_t high = Utils::High16Bits(label->address());
531 lui(TMP, Immediate(high));
532 jalr(TMP);
533 delay_slot()->ori(TMP, TMP, Immediate(low));
534 }
535 }
536
537 void BranchLinkPatchable(const ExternalLabel* label) {
538 const int32_t offset =
539 Array::data_offset() + 4*AddExternalLabel(label) - kHeapObjectTag;
540 LoadWordFromPoolOffset(TMP, offset);
541 jalr(TMP);
542 }
543
544 void BranchPatchable(const ExternalLabel* label) {
545 LoadImmediate(TMP, label->address());
546 jr(TMP);
547 }
548
549 void Drop(intptr_t stack_elements) {
550 ASSERT(stack_elements >= 0);
551 if (stack_elements > 0) {
552 addiu(SP, SP, Immediate(stack_elements * kWordSize));
553 }
554 }
555
506 void LoadImmediate(Register rd, int32_t value) { 556 void LoadImmediate(Register rd, int32_t value) {
507 if (Utils::IsInt(16, value)) { 557 if (Utils::IsInt(16, value)) {
508 addiu(rd, ZR, Immediate(value)); 558 addiu(rd, ZR, Immediate(value));
509 } else { 559 } else {
510 lui(rd, Immediate((value >> 16) & 0xffff)); 560 const uint16_t low = Utils::Low16Bits(value);
511 ori(rd, rd, Immediate(value & 0xffff)); 561 const uint16_t high = Utils::High16Bits(value);
562 lui(rd, Immediate(high));
563 ori(rd, rd, Immediate(low));
512 } 564 }
513 } 565 }
514 566
567 void Push(Register rt) {
568 addiu(SP, SP, Immediate(-kWordSize));
569 sw(rt, Address(SP));
570 }
571
572 void Pop(Register rt) {
573 lw(rt, Address(SP));
574 addiu(SP, SP, Immediate(kWordSize));
575 }
576
577 void Ret() {
578 jr(RA);
579 }
580
581 void LoadWordFromPoolOffset(Register rd, int32_t offset);
582 void LoadObject(Register rd, const Object& object);
583 void PushObject(const Object& object);
584
585 // Sets register rd to zero if the object is equal to register rn,
586 // set to non-zero otherwise.
587 void CompareObject(Register rd, Register rn, const Object& object);
588
515 private: 589 private:
516 AssemblerBuffer buffer_; 590 AssemblerBuffer buffer_;
517 GrowableObjectArray& object_pool_; // Objects and patchable jump targets. 591 GrowableObjectArray& object_pool_; // Objects and patchable jump targets.
518 int prologue_offset_; 592 int prologue_offset_;
519 593
520 bool delay_slot_available_; 594 bool delay_slot_available_;
521 bool in_delay_slot_; 595 bool in_delay_slot_;
522 596
597 int32_t AddObject(const Object& obj);
598 int32_t AddExternalLabel(const ExternalLabel* label);
599
523 class CodeComment : public ZoneAllocated { 600 class CodeComment : public ZoneAllocated {
524 public: 601 public:
525 CodeComment(intptr_t pc_offset, const String& comment) 602 CodeComment(intptr_t pc_offset, const String& comment)
526 : pc_offset_(pc_offset), comment_(comment) { } 603 : pc_offset_(pc_offset), comment_(comment) { }
527 604
528 intptr_t pc_offset() const { return pc_offset_; } 605 intptr_t pc_offset() const { return pc_offset_; }
529 const String& comment() const { return comment_; } 606 const String& comment() const { return comment_; }
530 607
531 private: 608 private:
532 intptr_t pc_offset_; 609 intptr_t pc_offset_;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 Emit(opcode << kOpcodeShift | 665 Emit(opcode << kOpcodeShift |
589 rs << kRsShift | 666 rs << kRsShift |
590 rt << kRtShift | 667 rt << kRtShift |
591 rd << kRdShift | 668 rd << kRdShift |
592 sa << kSaShift | 669 sa << kSaShift |
593 func << kFunctionShift); 670 func << kFunctionShift);
594 } 671 }
595 672
596 void EmitBranch(Opcode b, Register rs, Register rt, Label* label) { 673 void EmitBranch(Opcode b, Register rs, Register rt, Label* label) {
597 if (label->IsBound()) { 674 if (label->IsBound()) {
598 // Reletive destination from an instruction after the branch. 675 // Reletive destination from an instruction after the branch.
regis 2013/03/26 17:52:35 ditto
regis 2013/03/26 17:52:35 ditto
599 int32_t dest = label->Position() - (buffer_.Size() + Instr::kInstrSize); 676 const int32_t dest =
600 uint16_t dest_off = EncodeBranchOffset(dest, 0); 677 label->Position() - (buffer_.Size() + Instr::kInstrSize);
678 const uint16_t dest_off = EncodeBranchOffset(dest, 0);
601 EmitIType(b, rs, rt, dest_off); 679 EmitIType(b, rs, rt, dest_off);
602 } else { 680 } else {
603 int position = buffer_.Size(); 681 const int position = buffer_.Size();
604 EmitIType(b, rs, rt, label->position_); 682 EmitIType(b, rs, rt, label->position_);
605 label->LinkTo(position); 683 label->LinkTo(position);
606 } 684 }
607 } 685 }
608 686
609 void EmitRegImmBranch(RtRegImm b, Register rs, Label* label) { 687 void EmitRegImmBranch(RtRegImm b, Register rs, Label* label) {
610 if (label->IsBound()) { 688 if (label->IsBound()) {
611 // Reletive destination from an instruction after the branch. 689 // Reletive destination from an instruction after the branch.
regis 2013/03/26 17:52:35 ditto
612 int32_t dest = label->Position() - (buffer_.Size() + Instr::kInstrSize); 690 const int32_t dest =
613 uint16_t dest_off = EncodeBranchOffset(dest, 0); 691 label->Position() - (buffer_.Size() + Instr::kInstrSize);
692 const uint16_t dest_off = EncodeBranchOffset(dest, 0);
614 EmitRegImmType(REGIMM, rs, b, dest_off); 693 EmitRegImmType(REGIMM, rs, b, dest_off);
615 } else { 694 } else {
616 int position = buffer_.Size(); 695 const int position = buffer_.Size();
617 EmitRegImmType(REGIMM, rs, b, label->position_); 696 EmitRegImmType(REGIMM, rs, b, label->position_);
618 label->LinkTo(position); 697 label->LinkTo(position);
619 } 698 }
620 } 699 }
621 700
622 static int32_t EncodeBranchOffset(int32_t offset, int32_t instr); 701 static int32_t EncodeBranchOffset(int32_t offset, int32_t instr);
623 static int DecodeBranchOffset(int32_t instr); 702 static int DecodeBranchOffset(int32_t instr);
624 703
625 void EmitBranchDelayNop() { 704 void EmitBranchDelayNop() {
626 Emit(Instr::kNopInstruction); // Branch delay NOP. 705 Emit(Instr::kNopInstruction); // Branch delay NOP.
627 delay_slot_available_ = true; 706 delay_slot_available_ = true;
628 } 707 }
629 708
630 DISALLOW_ALLOCATION(); 709 DISALLOW_ALLOCATION();
631 DISALLOW_COPY_AND_ASSIGN(Assembler); 710 DISALLOW_COPY_AND_ASSIGN(Assembler);
632 }; 711 };
633 712
634 } // namespace dart 713 } // namespace dart
635 714
636 #endif // VM_ASSEMBLER_MIPS_H_ 715 #endif // VM_ASSEMBLER_MIPS_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698