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

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

Issue 268673021: Adds assert to mips assembler macros. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 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 | « runtime/vm/assembler_mips.h ('k') | no next file » | 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) 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 #include "vm/globals.h" 5 #include "vm/globals.h"
6 #if defined(TARGET_ARCH_MIPS) 6 #if defined(TARGET_ARCH_MIPS)
7 7
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/longjump.h" 9 #include "vm/longjump.h"
10 #include "vm/runtime_entry.h" 10 #include "vm/runtime_entry.h"
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 // If the offset loading instructions aren't there, we must have replaced 105 // If the offset loading instructions aren't there, we must have replaced
106 // the far branch with a near one, and so these instructions should be NOPs. 106 // the far branch with a near one, and so these instructions should be NOPs.
107 ASSERT((high == Instr::kNopInstruction) && (low == Instr::kNopInstruction)); 107 ASSERT((high == Instr::kNopInstruction) && (low == Instr::kNopInstruction));
108 } 108 }
109 109
110 virtual bool IsPointerOffset() const { return false; } 110 virtual bool IsPointerOffset() const { return false; }
111 }; 111 };
112 112
113 113
114 void Assembler::EmitFarJump(int32_t offset, bool link) { 114 void Assembler::EmitFarJump(int32_t offset, bool link) {
115 ASSERT(!in_delay_slot_);
115 ASSERT(use_far_branches()); 116 ASSERT(use_far_branches());
116 const uint16_t low = Utils::Low16Bits(offset); 117 const uint16_t low = Utils::Low16Bits(offset);
117 const uint16_t high = Utils::High16Bits(offset); 118 const uint16_t high = Utils::High16Bits(offset);
118 buffer_.EmitFixup(new PatchFarJump()); 119 buffer_.EmitFixup(new PatchFarJump());
119 lui(T9, Immediate(high)); 120 lui(T9, Immediate(high));
120 ori(T9, T9, Immediate(low)); 121 ori(T9, T9, Immediate(low));
121 if (link) { 122 if (link) {
122 EmitRType(SPECIAL, T9, R0, RA, 0, JALR); 123 EmitRType(SPECIAL, T9, R0, RA, 0, JALR);
123 } else { 124 } else {
124 EmitRType(SPECIAL, T9, R0, R0, 0, JR); 125 EmitRType(SPECIAL, T9, R0, R0, 0, JR);
(...skipping 14 matching lines...) Expand all
139 default: 140 default:
140 UNREACHABLE(); 141 UNREACHABLE();
141 break; 142 break;
142 } 143 }
143 return BNE; 144 return BNE;
144 } 145 }
145 146
146 147
147 void Assembler::EmitFarBranch(Opcode b, Register rs, Register rt, 148 void Assembler::EmitFarBranch(Opcode b, Register rs, Register rt,
148 int32_t offset) { 149 int32_t offset) {
150 ASSERT(!in_delay_slot_);
149 EmitIType(b, rs, rt, 4); 151 EmitIType(b, rs, rt, 4);
150 nop(); 152 nop();
151 EmitFarJump(offset, false); 153 EmitFarJump(offset, false);
152 } 154 }
153 155
154 156
155 static RtRegImm OppositeBranchNoLink(RtRegImm b) { 157 static RtRegImm OppositeBranchNoLink(RtRegImm b) {
156 switch (b) { 158 switch (b) {
157 case BLTZ: return BGEZ; 159 case BLTZ: return BGEZ;
158 case BGEZ: return BLTZ; 160 case BGEZ: return BLTZ;
159 case BLTZAL: return BGEZ; 161 case BLTZAL: return BGEZ;
160 case BGEZAL: return BLTZ; 162 case BGEZAL: return BLTZ;
161 default: 163 default:
162 UNREACHABLE(); 164 UNREACHABLE();
163 break; 165 break;
164 } 166 }
165 return BLTZ; 167 return BLTZ;
166 } 168 }
167 169
168 170
169 void Assembler::EmitFarRegImmBranch(RtRegImm b, Register rs, int32_t offset) { 171 void Assembler::EmitFarRegImmBranch(RtRegImm b, Register rs, int32_t offset) {
172 ASSERT(!in_delay_slot_);
170 EmitRegImmType(REGIMM, rs, b, 4); 173 EmitRegImmType(REGIMM, rs, b, 4);
171 nop(); 174 nop();
172 EmitFarJump(offset, (b == BLTZAL) || (b == BGEZAL)); 175 EmitFarJump(offset, (b == BLTZAL) || (b == BGEZAL));
173 } 176 }
174 177
175 178
176 void Assembler::EmitFarFpuBranch(bool kind, int32_t offset) { 179 void Assembler::EmitFarFpuBranch(bool kind, int32_t offset) {
180 ASSERT(!in_delay_slot_);
177 const uint32_t b16 = kind ? (1 << 16) : 0; 181 const uint32_t b16 = kind ? (1 << 16) : 0;
178 Emit(COP1 << kOpcodeShift | COP1_BC << kCop1SubShift | b16 | 4); 182 Emit(COP1 << kOpcodeShift | COP1_BC << kCop1SubShift | b16 | 4);
179 nop(); 183 nop();
180 EmitFarJump(offset, false); 184 EmitFarJump(offset, false);
181 } 185 }
182 186
183 187
184 void Assembler::EmitBranch(Opcode b, Register rs, Register rt, Label* label) { 188 void Assembler::EmitBranch(Opcode b, Register rs, Register rt, Label* label) {
189 ASSERT(!in_delay_slot_);
185 if (label->IsBound()) { 190 if (label->IsBound()) {
186 // Relative destination from an instruction after the branch. 191 // Relative destination from an instruction after the branch.
187 const int32_t dest = 192 const int32_t dest =
188 label->Position() - (buffer_.Size() + Instr::kInstrSize); 193 label->Position() - (buffer_.Size() + Instr::kInstrSize);
189 if (use_far_branches() && !CanEncodeBranchOffset(dest)) { 194 if (use_far_branches() && !CanEncodeBranchOffset(dest)) {
190 EmitFarBranch(OppositeBranchOpcode(b), rs, rt, label->Position()); 195 EmitFarBranch(OppositeBranchOpcode(b), rs, rt, label->Position());
191 } else { 196 } else {
192 const uint16_t dest_off = EncodeBranchOffset(dest, 0); 197 const uint16_t dest_off = EncodeBranchOffset(dest, 0);
193 EmitIType(b, rs, rt, dest_off); 198 EmitIType(b, rs, rt, dest_off);
194 } 199 }
195 } else { 200 } else {
196 const intptr_t position = buffer_.Size(); 201 const intptr_t position = buffer_.Size();
197 if (use_far_branches()) { 202 if (use_far_branches()) {
198 const uint32_t dest_off = label->position_; 203 const uint32_t dest_off = label->position_;
199 EmitFarBranch(b, rs, rt, dest_off); 204 EmitFarBranch(b, rs, rt, dest_off);
200 } else { 205 } else {
201 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); 206 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0);
202 EmitIType(b, rs, rt, dest_off); 207 EmitIType(b, rs, rt, dest_off);
203 } 208 }
204 label->LinkTo(position); 209 label->LinkTo(position);
205 } 210 }
206 } 211 }
207 212
208 213
209 void Assembler::EmitRegImmBranch(RtRegImm b, Register rs, Label* label) { 214 void Assembler::EmitRegImmBranch(RtRegImm b, Register rs, Label* label) {
215 ASSERT(!in_delay_slot_);
210 if (label->IsBound()) { 216 if (label->IsBound()) {
211 // Relative destination from an instruction after the branch. 217 // Relative destination from an instruction after the branch.
212 const int32_t dest = 218 const int32_t dest =
213 label->Position() - (buffer_.Size() + Instr::kInstrSize); 219 label->Position() - (buffer_.Size() + Instr::kInstrSize);
214 if (use_far_branches() && !CanEncodeBranchOffset(dest)) { 220 if (use_far_branches() && !CanEncodeBranchOffset(dest)) {
215 EmitFarRegImmBranch(OppositeBranchNoLink(b), rs, label->Position()); 221 EmitFarRegImmBranch(OppositeBranchNoLink(b), rs, label->Position());
216 } else { 222 } else {
217 const uint16_t dest_off = EncodeBranchOffset(dest, 0); 223 const uint16_t dest_off = EncodeBranchOffset(dest, 0);
218 EmitRegImmType(REGIMM, rs, b, dest_off); 224 EmitRegImmType(REGIMM, rs, b, dest_off);
219 } 225 }
220 } else { 226 } else {
221 const intptr_t position = buffer_.Size(); 227 const intptr_t position = buffer_.Size();
222 if (use_far_branches()) { 228 if (use_far_branches()) {
223 const uint32_t dest_off = label->position_; 229 const uint32_t dest_off = label->position_;
224 EmitFarRegImmBranch(b, rs, dest_off); 230 EmitFarRegImmBranch(b, rs, dest_off);
225 } else { 231 } else {
226 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); 232 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0);
227 EmitRegImmType(REGIMM, rs, b, dest_off); 233 EmitRegImmType(REGIMM, rs, b, dest_off);
228 } 234 }
229 label->LinkTo(position); 235 label->LinkTo(position);
230 } 236 }
231 } 237 }
232 238
233 239
234 void Assembler::EmitFpuBranch(bool kind, Label *label) { 240 void Assembler::EmitFpuBranch(bool kind, Label *label) {
241 ASSERT(!in_delay_slot_);
235 const int32_t b16 = kind ? (1 << 16) : 0; // Bit 16 set for branch on true. 242 const int32_t b16 = kind ? (1 << 16) : 0; // Bit 16 set for branch on true.
236 if (label->IsBound()) { 243 if (label->IsBound()) {
237 // Relative destination from an instruction after the branch. 244 // Relative destination from an instruction after the branch.
238 const int32_t dest = 245 const int32_t dest =
239 label->Position() - (buffer_.Size() + Instr::kInstrSize); 246 label->Position() - (buffer_.Size() + Instr::kInstrSize);
240 if (use_far_branches() && !CanEncodeBranchOffset(dest)) { 247 if (use_far_branches() && !CanEncodeBranchOffset(dest)) {
241 EmitFarFpuBranch(kind, label->Position()); 248 EmitFarFpuBranch(kind, label->Position());
242 } else { 249 } else {
243 const uint16_t dest_off = EncodeBranchOffset(dest, 0); 250 const uint16_t dest_off = EncodeBranchOffset(dest, 0);
244 Emit(COP1 << kOpcodeShift | 251 Emit(COP1 << kOpcodeShift |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 buffer_.Store<int32_t>(position, encoded); 348 buffer_.Store<int32_t>(position, encoded);
342 label->position_ = DecodeBranchOffset(next); 349 label->position_ = DecodeBranchOffset(next);
343 } 350 }
344 } 351 }
345 label->BindTo(bound_pc); 352 label->BindTo(bound_pc);
346 delay_slot_available_ = false; 353 delay_slot_available_ = false;
347 } 354 }
348 355
349 356
350 void Assembler::LoadWordFromPoolOffset(Register rd, int32_t offset) { 357 void Assembler::LoadWordFromPoolOffset(Register rd, int32_t offset) {
358 ASSERT(!in_delay_slot_);
351 ASSERT(rd != PP); 359 ASSERT(rd != PP);
352 if (Address::CanHoldOffset(offset)) { 360 if (Address::CanHoldOffset(offset)) {
353 lw(rd, Address(PP, offset)); 361 lw(rd, Address(PP, offset));
354 } else { 362 } else {
355 const int16_t offset_low = Utils::Low16Bits(offset); // Signed. 363 const int16_t offset_low = Utils::Low16Bits(offset); // Signed.
356 offset -= offset_low; 364 offset -= offset_low;
357 const uint16_t offset_high = Utils::High16Bits(offset); // Unsigned. 365 const uint16_t offset_high = Utils::High16Bits(offset); // Unsigned.
358 if (offset_high != 0) { 366 if (offset_high != 0) {
359 lui(rd, Immediate(offset_high)); 367 lui(rd, Immediate(offset_high));
360 addu(rd, rd, PP); 368 addu(rd, rd, PP);
361 lw(rd, Address(rd, offset_low)); 369 lw(rd, Address(rd, offset_low));
362 } else { 370 } else {
363 lw(rd, Address(PP, offset_low)); 371 lw(rd, Address(PP, offset_low));
364 } 372 }
365 } 373 }
366 } 374 }
367 375
368 376
369 void Assembler::AdduDetectOverflow(Register rd, Register rs, Register rt, 377 void Assembler::AdduDetectOverflow(Register rd, Register rs, Register rt,
370 Register ro, Register scratch) { 378 Register ro, Register scratch) {
379 ASSERT(!in_delay_slot_);
371 ASSERT(rd != ro); 380 ASSERT(rd != ro);
372 ASSERT(rd != TMP); 381 ASSERT(rd != TMP);
373 ASSERT(ro != TMP); 382 ASSERT(ro != TMP);
374 ASSERT(ro != rs); 383 ASSERT(ro != rs);
375 ASSERT(ro != rt); 384 ASSERT(ro != rt);
376 385
377 if ((rs == rt) && (rd == rs)) { 386 if ((rs == rt) && (rd == rs)) {
378 ASSERT(scratch != kNoRegister); 387 ASSERT(scratch != kNoRegister);
379 ASSERT(scratch != TMP); 388 ASSERT(scratch != TMP);
380 ASSERT(rd != scratch); 389 ASSERT(rd != scratch);
(...skipping 20 matching lines...) Expand all
401 addu(rd, rs, rt); 410 addu(rd, rs, rt);
402 xor_(ro, rd, rs); 411 xor_(ro, rd, rs);
403 xor_(TMP, rd, rt); 412 xor_(TMP, rd, rt);
404 and_(ro, TMP, ro); 413 and_(ro, TMP, ro);
405 } 414 }
406 } 415 }
407 416
408 417
409 void Assembler::SubuDetectOverflow(Register rd, Register rs, Register rt, 418 void Assembler::SubuDetectOverflow(Register rd, Register rs, Register rt,
410 Register ro) { 419 Register ro) {
420 ASSERT(!in_delay_slot_);
411 ASSERT(rd != ro); 421 ASSERT(rd != ro);
412 ASSERT(rd != TMP); 422 ASSERT(rd != TMP);
413 ASSERT(ro != TMP); 423 ASSERT(ro != TMP);
414 ASSERT(ro != rs); 424 ASSERT(ro != rs);
415 ASSERT(ro != rt); 425 ASSERT(ro != rt);
416 ASSERT(rs != TMP); 426 ASSERT(rs != TMP);
417 ASSERT(rt != TMP); 427 ASSERT(rt != TMP);
418 428
419 // This happens with some crankshaft code. Since Subu works fine if 429 // This happens with some crankshaft code. Since Subu works fine if
420 // left == right, let's not make that restriction here. 430 // left == right, let's not make that restriction here.
(...skipping 18 matching lines...) Expand all
439 } else { 449 } else {
440 subu(rd, rs, rt); 450 subu(rd, rs, rt);
441 xor_(ro, rd, rs); 451 xor_(ro, rd, rs);
442 xor_(TMP, rs, rt); 452 xor_(TMP, rs, rt);
443 and_(ro, TMP, ro); 453 and_(ro, TMP, ro);
444 } 454 }
445 } 455 }
446 456
447 457
448 void Assembler::LoadObject(Register rd, const Object& object) { 458 void Assembler::LoadObject(Register rd, const Object& object) {
459 ASSERT(!in_delay_slot_);
449 // Smis and VM heap objects are never relocated; do not use object pool. 460 // Smis and VM heap objects are never relocated; do not use object pool.
450 if (object.IsSmi()) { 461 if (object.IsSmi()) {
451 LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw())); 462 LoadImmediate(rd, reinterpret_cast<int32_t>(object.raw()));
452 } else if (object.InVMHeap()) { 463 } else if (object.InVMHeap()) {
453 // Make sure that class CallPattern is able to decode this load immediate. 464 // Make sure that class CallPattern is able to decode this load immediate.
454 int32_t object_raw = reinterpret_cast<int32_t>(object.raw()); 465 int32_t object_raw = reinterpret_cast<int32_t>(object.raw());
455 const uint16_t object_low = Utils::Low16Bits(object_raw); 466 const uint16_t object_low = Utils::Low16Bits(object_raw);
456 const uint16_t object_high = Utils::High16Bits(object_raw); 467 const uint16_t object_high = Utils::High16Bits(object_raw);
457 lui(rd, Immediate(object_high)); 468 lui(rd, Immediate(object_high));
458 ori(rd, rd, Immediate(object_low)); 469 ori(rd, rd, Immediate(object_low));
(...skipping 19 matching lines...) Expand all
478 if (object_pool_.At(i) == obj.raw()) { 489 if (object_pool_.At(i) == obj.raw()) {
479 return i; 490 return i;
480 } 491 }
481 } 492 }
482 object_pool_.Add(obj, Heap::kOld); 493 object_pool_.Add(obj, Heap::kOld);
483 return object_pool_.Length() - 1; 494 return object_pool_.Length() - 1;
484 } 495 }
485 496
486 497
487 void Assembler::PushObject(const Object& object) { 498 void Assembler::PushObject(const Object& object) {
499 ASSERT(!in_delay_slot_);
488 LoadObject(TMP, object); 500 LoadObject(TMP, object);
489 Push(TMP); 501 Push(TMP);
490 } 502 }
491 503
492 504
493 void Assembler::CompareObject(Register rd1, Register rd2, 505 void Assembler::CompareObject(Register rd1, Register rd2,
494 Register rn, const Object& object) { 506 Register rn, const Object& object) {
507 ASSERT(!in_delay_slot_);
495 ASSERT(rn != TMP); 508 ASSERT(rn != TMP);
496 ASSERT(rd1 != TMP); 509 ASSERT(rd1 != TMP);
497 ASSERT(rd1 != rd2); 510 ASSERT(rd1 != rd2);
498 LoadObject(TMP, object); 511 LoadObject(TMP, object);
499 slt(rd1, rn, TMP); 512 slt(rd1, rn, TMP);
500 slt(rd2, TMP, rn); 513 slt(rd2, TMP, rn);
501 } 514 }
502 515
503 516
504 // Preserves object and value registers. 517 // Preserves object and value registers.
505 void Assembler::StoreIntoObjectFilterNoSmi(Register object, 518 void Assembler::StoreIntoObjectFilterNoSmi(Register object,
506 Register value, 519 Register value,
507 Label* no_update) { 520 Label* no_update) {
521 ASSERT(!in_delay_slot_);
508 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) && 522 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) &&
509 (kOldObjectAlignmentOffset == 0), young_alignment); 523 (kOldObjectAlignmentOffset == 0), young_alignment);
510 524
511 // Write-barrier triggers if the value is in the new space (has bit set) and 525 // Write-barrier triggers if the value is in the new space (has bit set) and
512 // the object is in the old space (has bit cleared). 526 // the object is in the old space (has bit cleared).
513 // To check that, we compute value & ~object and skip the write barrier 527 // To check that, we compute value & ~object and skip the write barrier
514 // if the bit is not set. We can't destroy the object. 528 // if the bit is not set. We can't destroy the object.
515 nor(TMP, ZR, object); 529 nor(TMP, ZR, object);
516 and_(TMP, value, TMP); 530 and_(TMP, value, TMP);
517 andi(CMPRES1, TMP, Immediate(kNewObjectAlignmentOffset)); 531 andi(CMPRES1, TMP, Immediate(kNewObjectAlignmentOffset));
518 beq(CMPRES1, ZR, no_update); 532 beq(CMPRES1, ZR, no_update);
519 } 533 }
520 534
521 535
522 // Preserves object and value registers. 536 // Preserves object and value registers.
523 void Assembler::StoreIntoObjectFilter(Register object, 537 void Assembler::StoreIntoObjectFilter(Register object,
524 Register value, 538 Register value,
525 Label* no_update) { 539 Label* no_update) {
540 ASSERT(!in_delay_slot_);
526 // For the value we are only interested in the new/old bit and the tag bit. 541 // For the value we are only interested in the new/old bit and the tag bit.
527 // And the new bit with the tag bit. The resulting bit will be 0 for a Smi. 542 // And the new bit with the tag bit. The resulting bit will be 0 for a Smi.
528 sll(TMP, value, kObjectAlignmentLog2 - 1); 543 sll(TMP, value, kObjectAlignmentLog2 - 1);
529 and_(TMP, value, TMP); 544 and_(TMP, value, TMP);
530 // And the result with the negated space bit of the object. 545 // And the result with the negated space bit of the object.
531 nor(CMPRES1, ZR, object); 546 nor(CMPRES1, ZR, object);
532 and_(TMP, TMP, CMPRES1); 547 and_(TMP, TMP, CMPRES1);
533 andi(CMPRES1, TMP, Immediate(kNewObjectAlignmentOffset)); 548 andi(CMPRES1, TMP, Immediate(kNewObjectAlignmentOffset));
534 beq(CMPRES1, ZR, no_update); 549 beq(CMPRES1, ZR, no_update);
535 } 550 }
536 551
537 552
538 void Assembler::StoreIntoObject(Register object, 553 void Assembler::StoreIntoObject(Register object,
539 const Address& dest, 554 const Address& dest,
540 Register value, 555 Register value,
541 bool can_value_be_smi) { 556 bool can_value_be_smi) {
557 ASSERT(!in_delay_slot_);
542 ASSERT(object != value); 558 ASSERT(object != value);
543 sw(value, dest); 559 sw(value, dest);
544 Label done; 560 Label done;
545 if (can_value_be_smi) { 561 if (can_value_be_smi) {
546 StoreIntoObjectFilter(object, value, &done); 562 StoreIntoObjectFilter(object, value, &done);
547 } else { 563 } else {
548 StoreIntoObjectFilterNoSmi(object, value, &done); 564 StoreIntoObjectFilterNoSmi(object, value, &done);
549 } 565 }
550 // A store buffer update is required. 566 // A store buffer update is required.
551 if (value != T0) { 567 if (value != T0) {
(...skipping 16 matching lines...) Expand all
568 } else { 584 } else {
569 addiu(SP, SP, Immediate(1 * kWordSize)); 585 addiu(SP, SP, Immediate(1 * kWordSize));
570 } 586 }
571 Bind(&done); 587 Bind(&done);
572 } 588 }
573 589
574 590
575 void Assembler::StoreIntoObjectNoBarrier(Register object, 591 void Assembler::StoreIntoObjectNoBarrier(Register object,
576 const Address& dest, 592 const Address& dest,
577 Register value) { 593 Register value) {
594 ASSERT(!in_delay_slot_);
578 sw(value, dest); 595 sw(value, dest);
579 #if defined(DEBUG) 596 #if defined(DEBUG)
580 Label done; 597 Label done;
581 StoreIntoObjectFilter(object, value, &done); 598 StoreIntoObjectFilter(object, value, &done);
582 Stop("Store buffer update is required"); 599 Stop("Store buffer update is required");
583 Bind(&done); 600 Bind(&done);
584 #endif // defined(DEBUG) 601 #endif // defined(DEBUG)
585 // No store buffer update. 602 // No store buffer update.
586 } 603 }
587 604
588 605
589 void Assembler::StoreIntoObjectNoBarrier(Register object, 606 void Assembler::StoreIntoObjectNoBarrier(Register object,
590 const Address& dest, 607 const Address& dest,
591 const Object& value) { 608 const Object& value) {
609 ASSERT(!in_delay_slot_);
592 ASSERT(value.IsSmi() || value.InVMHeap() || 610 ASSERT(value.IsSmi() || value.InVMHeap() ||
593 (value.IsOld() && value.IsNotTemporaryScopedHandle())); 611 (value.IsOld() && value.IsNotTemporaryScopedHandle()));
594 // No store buffer update. 612 // No store buffer update.
595 LoadObject(TMP, value); 613 LoadObject(TMP, value);
596 sw(TMP, dest); 614 sw(TMP, dest);
597 } 615 }
598 616
599 617
600 void Assembler::LoadClassId(Register result, Register object) { 618 void Assembler::LoadClassId(Register result, Register object) {
601 ASSERT(RawObject::kClassIdTagPos == 16); 619 ASSERT(RawObject::kClassIdTagPos == 16);
602 ASSERT(RawObject::kClassIdTagSize == 16); 620 ASSERT(RawObject::kClassIdTagSize == 16);
603 const intptr_t class_id_offset = Object::tags_offset() + 621 const intptr_t class_id_offset = Object::tags_offset() +
604 RawObject::kClassIdTagPos / kBitsPerByte; 622 RawObject::kClassIdTagPos / kBitsPerByte;
605 lhu(result, FieldAddress(object, class_id_offset)); 623 lhu(result, FieldAddress(object, class_id_offset));
606 } 624 }
607 625
608 626
609 void Assembler::LoadClassById(Register result, Register class_id) { 627 void Assembler::LoadClassById(Register result, Register class_id) {
628 ASSERT(!in_delay_slot_);
610 ASSERT(result != class_id); 629 ASSERT(result != class_id);
611 lw(result, FieldAddress(CTX, Context::isolate_offset())); 630 lw(result, FieldAddress(CTX, Context::isolate_offset()));
612 const intptr_t table_offset_in_isolate = 631 const intptr_t table_offset_in_isolate =
613 Isolate::class_table_offset() + ClassTable::table_offset(); 632 Isolate::class_table_offset() + ClassTable::table_offset();
614 lw(result, Address(result, table_offset_in_isolate)); 633 lw(result, Address(result, table_offset_in_isolate));
615 sll(TMP, class_id, 2); 634 sll(TMP, class_id, 2);
616 addu(result, result, TMP); 635 addu(result, result, TMP);
617 lw(result, Address(result)); 636 lw(result, Address(result));
618 } 637 }
619 638
620 639
621 void Assembler::LoadClass(Register result, Register object) { 640 void Assembler::LoadClass(Register result, Register object) {
641 ASSERT(!in_delay_slot_);
622 ASSERT(TMP != result); 642 ASSERT(TMP != result);
623 LoadClassId(TMP, object); 643 LoadClassId(TMP, object);
624 644
625 lw(result, FieldAddress(CTX, Context::isolate_offset())); 645 lw(result, FieldAddress(CTX, Context::isolate_offset()));
626 const intptr_t table_offset_in_isolate = 646 const intptr_t table_offset_in_isolate =
627 Isolate::class_table_offset() + ClassTable::table_offset(); 647 Isolate::class_table_offset() + ClassTable::table_offset();
628 lw(result, Address(result, table_offset_in_isolate)); 648 lw(result, Address(result, table_offset_in_isolate));
629 sll(TMP, TMP, 2); 649 sll(TMP, TMP, 2);
630 addu(result, result, TMP); 650 addu(result, result, TMP);
631 lw(result, Address(result)); 651 lw(result, Address(result));
632 } 652 }
633 653
634 654
635 void Assembler::EnterFrame() { 655 void Assembler::EnterFrame() {
656 ASSERT(!in_delay_slot_);
636 addiu(SP, SP, Immediate(-2 * kWordSize)); 657 addiu(SP, SP, Immediate(-2 * kWordSize));
637 sw(RA, Address(SP, 1 * kWordSize)); 658 sw(RA, Address(SP, 1 * kWordSize));
638 sw(FP, Address(SP, 0 * kWordSize)); 659 sw(FP, Address(SP, 0 * kWordSize));
639 mov(FP, SP); 660 mov(FP, SP);
640 } 661 }
641 662
642 663
643 void Assembler::LeaveFrameAndReturn() { 664 void Assembler::LeaveFrameAndReturn() {
665 ASSERT(!in_delay_slot_);
644 mov(SP, FP); 666 mov(SP, FP);
645 lw(RA, Address(SP, 1 * kWordSize)); 667 lw(RA, Address(SP, 1 * kWordSize));
646 lw(FP, Address(SP, 0 * kWordSize)); 668 lw(FP, Address(SP, 0 * kWordSize));
647 Ret(); 669 Ret();
648 delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); 670 delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize));
649 } 671 }
650 672
651 673
652 void Assembler::EnterStubFrame(bool load_pp) { 674 void Assembler::EnterStubFrame(bool load_pp) {
675 ASSERT(!in_delay_slot_);
653 SetPrologueOffset(); 676 SetPrologueOffset();
654 addiu(SP, SP, Immediate(-4 * kWordSize)); 677 addiu(SP, SP, Immediate(-4 * kWordSize));
655 sw(ZR, Address(SP, 3 * kWordSize)); // PC marker is 0 in stubs. 678 sw(ZR, Address(SP, 3 * kWordSize)); // PC marker is 0 in stubs.
656 sw(RA, Address(SP, 2 * kWordSize)); 679 sw(RA, Address(SP, 2 * kWordSize));
657 sw(FP, Address(SP, 1 * kWordSize)); 680 sw(FP, Address(SP, 1 * kWordSize));
658 sw(PP, Address(SP, 0 * kWordSize)); 681 sw(PP, Address(SP, 0 * kWordSize));
659 addiu(FP, SP, Immediate(1 * kWordSize)); 682 addiu(FP, SP, Immediate(1 * kWordSize));
660 if (load_pp) { 683 if (load_pp) {
661 // Setup pool pointer for this stub. 684 // Setup pool pointer for this stub.
662 LoadPoolPointer(); 685 LoadPoolPointer();
663 } 686 }
664 } 687 }
665 688
666 689
667 void Assembler::LeaveStubFrame() { 690 void Assembler::LeaveStubFrame() {
691 ASSERT(!in_delay_slot_);
668 addiu(SP, FP, Immediate(-1 * kWordSize)); 692 addiu(SP, FP, Immediate(-1 * kWordSize));
669 lw(RA, Address(SP, 2 * kWordSize)); 693 lw(RA, Address(SP, 2 * kWordSize));
670 lw(FP, Address(SP, 1 * kWordSize)); 694 lw(FP, Address(SP, 1 * kWordSize));
671 lw(PP, Address(SP, 0 * kWordSize)); 695 lw(PP, Address(SP, 0 * kWordSize));
672 addiu(SP, SP, Immediate(4 * kWordSize)); 696 addiu(SP, SP, Immediate(4 * kWordSize));
673 } 697 }
674 698
675 699
676 void Assembler::LeaveStubFrameAndReturn(Register ra) { 700 void Assembler::LeaveStubFrameAndReturn(Register ra) {
701 ASSERT(!in_delay_slot_);
677 addiu(SP, FP, Immediate(-1 * kWordSize)); 702 addiu(SP, FP, Immediate(-1 * kWordSize));
678 lw(RA, Address(SP, 2 * kWordSize)); 703 lw(RA, Address(SP, 2 * kWordSize));
679 lw(FP, Address(SP, 1 * kWordSize)); 704 lw(FP, Address(SP, 1 * kWordSize));
680 lw(PP, Address(SP, 0 * kWordSize)); 705 lw(PP, Address(SP, 0 * kWordSize));
681 jr(ra); 706 jr(ra);
682 delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); 707 delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize));
683 } 708 }
684 709
685 710
686 void Assembler::UpdateAllocationStats(intptr_t cid, 711 void Assembler::UpdateAllocationStats(intptr_t cid,
687 Register temp_reg, 712 Register temp_reg,
688 Heap::Space space) { 713 Heap::Space space) {
714 ASSERT(!in_delay_slot_);
689 ASSERT(temp_reg != kNoRegister); 715 ASSERT(temp_reg != kNoRegister);
690 ASSERT(temp_reg != TMP); 716 ASSERT(temp_reg != TMP);
691 ASSERT(cid > 0); 717 ASSERT(cid > 0);
692 Isolate* isolate = Isolate::Current(); 718 Isolate* isolate = Isolate::Current();
693 ClassTable* class_table = isolate->class_table(); 719 ClassTable* class_table = isolate->class_table();
694 if (cid < kNumPredefinedCids) { 720 if (cid < kNumPredefinedCids) {
695 const uword class_heap_stats_table_address = 721 const uword class_heap_stats_table_address =
696 class_table->PredefinedClassHeapStatsTableAddress(); 722 class_table->PredefinedClassHeapStatsTableAddress();
697 const uword class_offset = cid * sizeof(ClassHeapStats); // NOLINT 723 const uword class_offset = cid * sizeof(ClassHeapStats); // NOLINT
698 const uword count_field_offset = (space == Heap::kNew) ? 724 const uword count_field_offset = (space == Heap::kNew) ?
(...skipping 17 matching lines...) Expand all
716 AddImmediate(TMP, 1); 742 AddImmediate(TMP, 1);
717 sw(TMP, Address(temp_reg, count_field_offset)); 743 sw(TMP, Address(temp_reg, count_field_offset));
718 } 744 }
719 } 745 }
720 746
721 747
722 void Assembler::UpdateAllocationStatsWithSize(intptr_t cid, 748 void Assembler::UpdateAllocationStatsWithSize(intptr_t cid,
723 Register size_reg, 749 Register size_reg,
724 Register temp_reg, 750 Register temp_reg,
725 Heap::Space space) { 751 Heap::Space space) {
752 ASSERT(!in_delay_slot_);
726 ASSERT(temp_reg != kNoRegister); 753 ASSERT(temp_reg != kNoRegister);
727 ASSERT(cid > 0); 754 ASSERT(cid > 0);
728 ASSERT(temp_reg != TMP); 755 ASSERT(temp_reg != TMP);
729 Isolate* isolate = Isolate::Current(); 756 Isolate* isolate = Isolate::Current();
730 ClassTable* class_table = isolate->class_table(); 757 ClassTable* class_table = isolate->class_table();
731 if (cid < kNumPredefinedCids) { 758 if (cid < kNumPredefinedCids) {
732 const uword class_heap_stats_table_address = 759 const uword class_heap_stats_table_address =
733 class_table->PredefinedClassHeapStatsTableAddress(); 760 class_table->PredefinedClassHeapStatsTableAddress();
734 const uword class_offset = cid * sizeof(ClassHeapStats); // NOLINT 761 const uword class_offset = cid * sizeof(ClassHeapStats); // NOLINT
735 const uword count_field_offset = (space == Heap::kNew) ? 762 const uword count_field_offset = (space == Heap::kNew) ?
(...skipping 30 matching lines...) Expand all
766 addu(TMP, TMP, size_reg); 793 addu(TMP, TMP, size_reg);
767 sw(TMP, Address(temp_reg, size_field_offset)); 794 sw(TMP, Address(temp_reg, size_field_offset));
768 } 795 }
769 } 796 }
770 797
771 798
772 void Assembler::TryAllocate(const Class& cls, 799 void Assembler::TryAllocate(const Class& cls,
773 Label* failure, 800 Label* failure,
774 Register instance_reg, 801 Register instance_reg,
775 Register temp_reg) { 802 Register temp_reg) {
803 ASSERT(!in_delay_slot_);
776 ASSERT(failure != NULL); 804 ASSERT(failure != NULL);
777 if (FLAG_inline_alloc) { 805 if (FLAG_inline_alloc) {
778 Heap* heap = Isolate::Current()->heap(); 806 Heap* heap = Isolate::Current()->heap();
779 const intptr_t instance_size = cls.instance_size(); 807 const intptr_t instance_size = cls.instance_size();
780 LoadImmediate(instance_reg, heap->TopAddress()); 808 LoadImmediate(instance_reg, heap->TopAddress());
781 lw(instance_reg, Address(instance_reg, 0)); 809 lw(instance_reg, Address(instance_reg, 0));
782 AddImmediate(instance_reg, instance_size); 810 AddImmediate(instance_reg, instance_size);
783 811
784 // instance_reg: potential next object start. 812 // instance_reg: potential next object start.
785 LoadImmediate(TMP, heap->EndAddress()); 813 LoadImmediate(TMP, heap->EndAddress());
(...skipping 21 matching lines...) Expand all
807 } 835 }
808 836
809 837
810 void Assembler::CallRuntime(const RuntimeEntry& entry, 838 void Assembler::CallRuntime(const RuntimeEntry& entry,
811 intptr_t argument_count) { 839 intptr_t argument_count) {
812 entry.Call(this, argument_count); 840 entry.Call(this, argument_count);
813 } 841 }
814 842
815 843
816 void Assembler::EnterDartFrame(intptr_t frame_size) { 844 void Assembler::EnterDartFrame(intptr_t frame_size) {
845 ASSERT(!in_delay_slot_);
817 const intptr_t offset = CodeSize(); 846 const intptr_t offset = CodeSize();
818 847
819 SetPrologueOffset(); 848 SetPrologueOffset();
820 849
821 addiu(SP, SP, Immediate(-4 * kWordSize)); 850 addiu(SP, SP, Immediate(-4 * kWordSize));
822 sw(RA, Address(SP, 2 * kWordSize)); 851 sw(RA, Address(SP, 2 * kWordSize));
823 sw(FP, Address(SP, 1 * kWordSize)); 852 sw(FP, Address(SP, 1 * kWordSize));
824 sw(PP, Address(SP, 0 * kWordSize)); 853 sw(PP, Address(SP, 0 * kWordSize));
825 854
826 GetNextPC(TMP); // TMP gets the address of the next instruction. 855 GetNextPC(TMP); // TMP gets the address of the next instruction.
(...skipping 17 matching lines...) Expand all
844 AddImmediate(SP, -frame_size); 873 AddImmediate(SP, -frame_size);
845 } 874 }
846 875
847 876
848 // On entry to a function compiled for OSR, the caller's frame pointer, the 877 // On entry to a function compiled for OSR, the caller's frame pointer, the
849 // stack locals, and any copied parameters are already in place. The frame 878 // stack locals, and any copied parameters are already in place. The frame
850 // pointer is already set up. The PC marker is not correct for the 879 // pointer is already set up. The PC marker is not correct for the
851 // optimized function and there may be extra space for spill slots to 880 // optimized function and there may be extra space for spill slots to
852 // allocate. We must also set up the pool pointer for the function. 881 // allocate. We must also set up the pool pointer for the function.
853 void Assembler::EnterOsrFrame(intptr_t extra_size) { 882 void Assembler::EnterOsrFrame(intptr_t extra_size) {
883 ASSERT(!in_delay_slot_);
854 Comment("EnterOsrFrame"); 884 Comment("EnterOsrFrame");
855 885
856 GetNextPC(TMP); // TMP gets the address of the next instruction. 886 GetNextPC(TMP); // TMP gets the address of the next instruction.
857 887
858 // The runtime system assumes that the code marker address is 888 // The runtime system assumes that the code marker address is
859 // kEntryPointToPcMarkerOffset bytes from the entry. Since there is no 889 // kEntryPointToPcMarkerOffset bytes from the entry. Since there is no
860 // code to set up the frame pointer, etc., the address needs to be adjusted. 890 // code to set up the frame pointer, etc., the address needs to be adjusted.
861 const intptr_t offset = kEntryPointToPcMarkerOffset - CodeSize(); 891 const intptr_t offset = kEntryPointToPcMarkerOffset - CodeSize();
862 // Calculate the offset of the pool pointer from the PC. 892 // Calculate the offset of the pool pointer from the PC.
863 const intptr_t object_pool_pc_dist = 893 const intptr_t object_pool_pc_dist =
864 Instructions::HeaderSize() - Instructions::object_pool_offset() + 894 Instructions::HeaderSize() - Instructions::object_pool_offset() +
865 CodeSize(); 895 CodeSize();
866 896
867 // Adjust PC by the offset, and store it in the stack frame. 897 // Adjust PC by the offset, and store it in the stack frame.
868 AddImmediate(TMP, TMP, offset); 898 AddImmediate(TMP, TMP, offset);
869 sw(TMP, Address(FP, kPcMarkerSlotFromFp * kWordSize)); 899 sw(TMP, Address(FP, kPcMarkerSlotFromFp * kWordSize));
870 900
871 // Restore return address. 901 // Restore return address.
872 lw(RA, Address(FP, 1 * kWordSize)); 902 lw(RA, Address(FP, 1 * kWordSize));
873 903
874 // Load the pool pointer. offset has already been subtracted from temp. 904 // Load the pool pointer. offset has already been subtracted from temp.
875 lw(PP, Address(TMP, -object_pool_pc_dist - offset)); 905 lw(PP, Address(TMP, -object_pool_pc_dist - offset));
876 906
877 // Reserve space for locals. 907 // Reserve space for locals.
878 AddImmediate(SP, -extra_size); 908 AddImmediate(SP, -extra_size);
879 } 909 }
880 910
881 911
882 void Assembler::LeaveDartFrame() { 912 void Assembler::LeaveDartFrame() {
913 ASSERT(!in_delay_slot_);
883 addiu(SP, FP, Immediate(-kWordSize)); 914 addiu(SP, FP, Immediate(-kWordSize));
884 915
885 lw(RA, Address(SP, 2 * kWordSize)); 916 lw(RA, Address(SP, 2 * kWordSize));
886 lw(FP, Address(SP, 1 * kWordSize)); 917 lw(FP, Address(SP, 1 * kWordSize));
887 lw(PP, Address(SP, 0 * kWordSize)); 918 lw(PP, Address(SP, 0 * kWordSize));
888 919
889 // Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame. 920 // Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame.
890 addiu(SP, SP, Immediate(4 * kWordSize)); 921 addiu(SP, SP, Immediate(4 * kWordSize));
891 } 922 }
892 923
893 924
894 void Assembler::LeaveDartFrameAndReturn() { 925 void Assembler::LeaveDartFrameAndReturn() {
926 ASSERT(!in_delay_slot_);
895 addiu(SP, FP, Immediate(-kWordSize)); 927 addiu(SP, FP, Immediate(-kWordSize));
896 928
897 lw(RA, Address(SP, 2 * kWordSize)); 929 lw(RA, Address(SP, 2 * kWordSize));
898 lw(FP, Address(SP, 1 * kWordSize)); 930 lw(FP, Address(SP, 1 * kWordSize));
899 lw(PP, Address(SP, 0 * kWordSize)); 931 lw(PP, Address(SP, 0 * kWordSize));
900 932
901 // Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame, and return. 933 // Adjust SP for PC, RA, FP, PP pushed in EnterDartFrame, and return.
902 Ret(); 934 Ret();
903 delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); 935 delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize));
904 } 936 }
905 937
906 938
907 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { 939 void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) {
940 ASSERT(!in_delay_slot_);
908 // Reserve space for arguments and align frame before entering 941 // Reserve space for arguments and align frame before entering
909 // the C++ world. 942 // the C++ world.
910 AddImmediate(SP, -frame_space); 943 AddImmediate(SP, -frame_space);
911 if (OS::ActivationFrameAlignment() > 1) { 944 if (OS::ActivationFrameAlignment() > 1) {
912 LoadImmediate(TMP, ~(OS::ActivationFrameAlignment() - 1)); 945 LoadImmediate(TMP, ~(OS::ActivationFrameAlignment() - 1));
913 and_(SP, SP, TMP); 946 and_(SP, SP, TMP);
914 } 947 }
915 } 948 }
916 949
917 950
918 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) { 951 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) {
952 ASSERT(!in_delay_slot_);
919 const intptr_t kPushedRegistersSize = 953 const intptr_t kPushedRegistersSize =
920 kDartVolatileCpuRegCount * kWordSize + 954 kDartVolatileCpuRegCount * kWordSize +
921 2 * kWordSize + // FP and RA. 955 2 * kWordSize + // FP and RA.
922 kDartVolatileFpuRegCount * kWordSize; 956 kDartVolatileFpuRegCount * kWordSize;
923 957
924 SetPrologueOffset(); 958 SetPrologueOffset();
925 959
926 TraceSimMsg("EnterCallRuntimeFrame"); 960 TraceSimMsg("EnterCallRuntimeFrame");
927 961
928 // Save volatile CPU and FPU registers on the stack: 962 // Save volatile CPU and FPU registers on the stack:
(...skipping 22 matching lines...) Expand all
951 } 985 }
952 sw(RA, Address(SP, 1 * kWordSize)); 986 sw(RA, Address(SP, 1 * kWordSize));
953 sw(FP, Address(SP, 0 * kWordSize)); 987 sw(FP, Address(SP, 0 * kWordSize));
954 mov(FP, SP); 988 mov(FP, SP);
955 989
956 ReserveAlignedFrameSpace(frame_space); 990 ReserveAlignedFrameSpace(frame_space);
957 } 991 }
958 992
959 993
960 void Assembler::LeaveCallRuntimeFrame() { 994 void Assembler::LeaveCallRuntimeFrame() {
995 ASSERT(!in_delay_slot_);
961 const intptr_t kPushedRegistersSize = 996 const intptr_t kPushedRegistersSize =
962 kDartVolatileCpuRegCount * kWordSize + 997 kDartVolatileCpuRegCount * kWordSize +
963 2 * kWordSize + // FP and RA. 998 2 * kWordSize + // FP and RA.
964 kDartVolatileFpuRegCount * kWordSize; 999 kDartVolatileFpuRegCount * kWordSize;
965 1000
966 TraceSimMsg("LeaveCallRuntimeFrame"); 1001 TraceSimMsg("LeaveCallRuntimeFrame");
967 1002
968 // SP might have been modified to reserve space for arguments 1003 // SP might have been modified to reserve space for arguments
969 // and ensure proper alignment of the stack frame. 1004 // and ensure proper alignment of the stack frame.
970 // We need to restore it before restoring registers. 1005 // We need to restore it before restoring registers.
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1055 Emit(reinterpret_cast<int32_t>(message)); 1090 Emit(reinterpret_cast<int32_t>(message));
1056 Bind(&msg); 1091 Bind(&msg);
1057 break_(Instr::kMsgMessageCode); 1092 break_(Instr::kMsgMessageCode);
1058 } 1093 }
1059 #endif 1094 #endif
1060 } 1095 }
1061 1096
1062 } // namespace dart 1097 } // namespace dart
1063 1098
1064 #endif // defined TARGET_ARCH_MIPS 1099 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/assembler_mips.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698