| 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 #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/runtime_entry.h" | 9 #include "vm/runtime_entry.h" |
| 10 #include "vm/simulator.h" | 10 #include "vm/simulator.h" |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 const intptr_t table_offset_in_isolate = | 328 const intptr_t table_offset_in_isolate = |
| 329 Isolate::class_table_offset() + ClassTable::table_offset(); | 329 Isolate::class_table_offset() + ClassTable::table_offset(); |
| 330 lw(result, Address(result, table_offset_in_isolate)); | 330 lw(result, Address(result, table_offset_in_isolate)); |
| 331 sll(TMP1, TMP1, 2); | 331 sll(TMP1, TMP1, 2); |
| 332 addu(result, result, TMP1); | 332 addu(result, result, TMP1); |
| 333 lw(result, Address(result)); | 333 lw(result, Address(result)); |
| 334 } | 334 } |
| 335 | 335 |
| 336 | 336 |
| 337 void Assembler::EnterStubFrame(bool uses_pp) { | 337 void Assembler::EnterStubFrame(bool uses_pp) { |
| 338 SetPrologueOffset(); |
| 338 if (uses_pp) { | 339 if (uses_pp) { |
| 339 addiu(SP, SP, Immediate(-4 * kWordSize)); | 340 addiu(SP, SP, Immediate(-4 * kWordSize)); |
| 340 sw(ZR, Address(SP, 3 * kWordSize)); // PC marker is 0 in stubs. | 341 sw(ZR, Address(SP, 3 * kWordSize)); // PC marker is 0 in stubs. |
| 341 sw(RA, Address(SP, 2 * kWordSize)); | 342 sw(RA, Address(SP, 2 * kWordSize)); |
| 342 sw(FP, Address(SP, 1 * kWordSize)); | 343 sw(FP, Address(SP, 1 * kWordSize)); |
| 343 sw(PP, Address(SP, 0 * kWordSize)); | 344 sw(PP, Address(SP, 0 * kWordSize)); |
| 344 addiu(FP, SP, Immediate(1 * kWordSize)); | 345 addiu(FP, SP, Immediate(1 * kWordSize)); |
| 345 // Setup pool pointer for this stub. | 346 // Setup pool pointer for this stub. |
| 346 Label next; | 347 Label next; |
| 347 bal(&next); | 348 bal(&next); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 | 436 |
| 436 | 437 |
| 437 void Assembler::CallRuntime(const RuntimeEntry& entry) { | 438 void Assembler::CallRuntime(const RuntimeEntry& entry) { |
| 438 entry.Call(this); | 439 entry.Call(this); |
| 439 } | 440 } |
| 440 | 441 |
| 441 | 442 |
| 442 void Assembler::EnterDartFrame(intptr_t frame_size) { | 443 void Assembler::EnterDartFrame(intptr_t frame_size) { |
| 443 const intptr_t offset = CodeSize(); | 444 const intptr_t offset = CodeSize(); |
| 444 | 445 |
| 446 SetPrologueOffset(); |
| 447 |
| 445 addiu(SP, SP, Immediate(-4 * kWordSize)); | 448 addiu(SP, SP, Immediate(-4 * kWordSize)); |
| 446 sw(RA, Address(SP, 2 * kWordSize)); | 449 sw(RA, Address(SP, 2 * kWordSize)); |
| 447 sw(FP, Address(SP, 1 * kWordSize)); | 450 sw(FP, Address(SP, 1 * kWordSize)); |
| 448 sw(PP, Address(SP, 0 * kWordSize)); | 451 sw(PP, Address(SP, 0 * kWordSize)); |
| 449 | 452 |
| 450 Label next; | 453 Label next; |
| 451 // Branch and link to the instruction after the delay slot to get the PC. | 454 // Branch and link to the instruction after the delay slot to get the PC. |
| 452 bal(&next); | 455 bal(&next); |
| 453 // RA is the address of the sw instruction below. Save it in T0. | 456 // RA is the address of the sw instruction below. Save it in T0. |
| 454 delay_slot()->mov(T0, RA); | 457 delay_slot()->mov(TMP1, RA); |
| 455 | 458 |
| 456 // Calculate the offset of the pool pointer from the PC. | 459 // Calculate the offset of the pool pointer from the PC. |
| 457 const intptr_t object_pool_pc_dist = | 460 const intptr_t object_pool_pc_dist = |
| 458 Instructions::HeaderSize() - Instructions::object_pool_offset() + | 461 Instructions::HeaderSize() - Instructions::object_pool_offset() + |
| 459 CodeSize(); | 462 CodeSize(); |
| 460 | 463 |
| 461 // This sw instruction is the return address for the bal, so T0 holds | 464 // This sw instruction is the return address for the bal, so T0 holds |
| 462 // the PC at this sw instruction. | 465 // the PC at this sw instruction. |
| 463 Bind(&next); | 466 Bind(&next); |
| 464 | 467 |
| 465 // Save PC in frame for fast identification of corresponding code. | 468 // Save PC in frame for fast identification of corresponding code. |
| 466 if (offset == 0) { | 469 if (offset == 0) { |
| 467 sw(T0, Address(SP, 3 * kWordSize)); | 470 sw(TMP1, Address(SP, 3 * kWordSize)); |
| 468 } else { | 471 } else { |
| 469 // Adjust saved PC for any intrinsic code that could have been generated | 472 // Adjust saved PC for any intrinsic code that could have been generated |
| 470 // before a frame is created. | 473 // before a frame is created. |
| 471 AddImmediate(T1, T0, -offset); | 474 addiu(TMP1, TMP1, Immediate(-offset)); |
| 472 sw(T1, Address(SP, 3 * kWordSize)); | 475 sw(TMP1, Address(SP, 3 * kWordSize)); |
| 473 } | 476 } |
| 474 | 477 |
| 475 // Set FP to the saved previous FP. | 478 // Set FP to the saved previous FP. |
| 476 addiu(FP, SP, Immediate(kWordSize)); | 479 addiu(FP, SP, Immediate(kWordSize)); |
| 477 | 480 |
| 478 // Load the pool pointer. | 481 // Load the pool pointer. offset has already been subtracted from TMP1. |
| 479 lw(PP, Address(T0, -object_pool_pc_dist)); | 482 lw(PP, Address(TMP1, -object_pool_pc_dist + offset)); |
| 480 | 483 |
| 481 // Reserve space for locals. | 484 // Reserve space for locals. |
| 482 AddImmediate(SP, -frame_size); | 485 AddImmediate(SP, -frame_size); |
| 483 } | 486 } |
| 484 | 487 |
| 485 | 488 |
| 486 void Assembler::LeaveDartFrameAndReturn() { | 489 void Assembler::LeaveDartFrameAndReturn() { |
| 487 addiu(SP, FP, Immediate(-kWordSize)); | 490 addiu(SP, FP, Immediate(-kWordSize)); |
| 488 | 491 |
| 489 lw(RA, Address(SP, 2 * kWordSize)); | 492 lw(RA, Address(SP, 2 * kWordSize)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 506 } | 509 } |
| 507 } | 510 } |
| 508 | 511 |
| 509 | 512 |
| 510 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) { | 513 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) { |
| 511 const intptr_t kPushedRegistersSize = | 514 const intptr_t kPushedRegistersSize = |
| 512 kDartVolatileCpuRegCount * kWordSize + | 515 kDartVolatileCpuRegCount * kWordSize + |
| 513 2 * kWordSize + // FP and RA. | 516 2 * kWordSize + // FP and RA. |
| 514 kDartVolatileFpuRegCount * kWordSize; | 517 kDartVolatileFpuRegCount * kWordSize; |
| 515 | 518 |
| 519 SetPrologueOffset(); |
| 520 |
| 516 TraceSimMsg("EnterCallRuntimeFrame"); | 521 TraceSimMsg("EnterCallRuntimeFrame"); |
| 517 | 522 |
| 518 if (prologue_offset_ == -1) { | |
| 519 prologue_offset_ = CodeSize(); | |
| 520 } | |
| 521 | |
| 522 // Save volatile CPU and FPU registers on the stack: | 523 // Save volatile CPU and FPU registers on the stack: |
| 523 // ------------- | 524 // ------------- |
| 524 // FPU Registers | 525 // FPU Registers |
| 525 // CPU Registers | 526 // CPU Registers |
| 526 // RA | 527 // RA |
| 527 // FP | 528 // FP |
| 528 // ------------- | 529 // ------------- |
| 529 // TODO(zra): It may be a problem for walking the stack that FP is below | 530 // TODO(zra): It may be a problem for walking the stack that FP is below |
| 530 // the saved registers. If it turns out to be a problem in the | 531 // the saved registers. If it turns out to be a problem in the |
| 531 // future, try pushing RA and FP before the volatile registers. | 532 // future, try pushing RA and FP before the volatile registers. |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 594 ASSERT(Utils::IsAligned(address, 4)); | 595 ASSERT(Utils::IsAligned(address, 4)); |
| 595 // The address is stored in the object array as a RawSmi. | 596 // The address is stored in the object array as a RawSmi. |
| 596 const Smi& smi = Smi::Handle(Smi::New(address >> kSmiTagShift)); | 597 const Smi& smi = Smi::Handle(Smi::New(address >> kSmiTagShift)); |
| 597 // Do not reuse an existing entry, since each reference may be patched | 598 // Do not reuse an existing entry, since each reference may be patched |
| 598 // independently. | 599 // independently. |
| 599 object_pool_.Add(smi, Heap::kOld); | 600 object_pool_.Add(smi, Heap::kOld); |
| 600 return object_pool_.Length() - 1; | 601 return object_pool_.Length() - 1; |
| 601 } | 602 } |
| 602 | 603 |
| 603 | 604 |
| 605 static const char* cpu_reg_names[kNumberOfCpuRegisters] = { |
| 606 "zr", "tmp", "v0", "v1", "a0", "a1", "a2", "a3", |
| 607 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", |
| 608 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", |
| 609 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra", |
| 610 }; |
| 611 |
| 612 |
| 613 const char* Assembler::RegisterName(Register reg) { |
| 614 ASSERT((0 <= reg) && (reg < kNumberOfCpuRegisters)); |
| 615 return cpu_reg_names[reg]; |
| 616 } |
| 617 |
| 618 |
| 619 static const char* fpu_reg_names[kNumberOfFpuRegisters] = { |
| 620 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", |
| 621 "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15", |
| 622 }; |
| 623 |
| 624 |
| 625 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
| 626 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); |
| 627 return fpu_reg_names[reg]; |
| 628 } |
| 629 |
| 630 |
| 604 void Assembler::Stop(const char* message) { | 631 void Assembler::Stop(const char* message) { |
| 605 if (FLAG_print_stop_message) { | 632 if (FLAG_print_stop_message) { |
| 606 UNIMPLEMENTED(); | 633 UNIMPLEMENTED(); |
| 607 } | 634 } |
| 608 Label stop; | 635 Label stop; |
| 609 b(&stop); | 636 b(&stop); |
| 610 Emit(reinterpret_cast<int32_t>(message)); | 637 Emit(reinterpret_cast<int32_t>(message)); |
| 611 Bind(&stop); | 638 Bind(&stop); |
| 612 break_(Instr::kStopMessageCode); | 639 break_(Instr::kStopMessageCode); |
| 613 } | 640 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 624 Bind(&msg); | 651 Bind(&msg); |
| 625 break_(Instr::kMsgMessageCode); | 652 break_(Instr::kMsgMessageCode); |
| 626 } | 653 } |
| 627 #endif | 654 #endif |
| 628 } | 655 } |
| 629 | 656 |
| 630 } // namespace dart | 657 } // namespace dart |
| 631 | 658 |
| 632 #endif // defined TARGET_ARCH_MIPS | 659 #endif // defined TARGET_ARCH_MIPS |
| 633 | 660 |
| OLD | NEW |