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" // NOLINT | 5 #include "vm/globals.h" // NOLINT |
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 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
450 } else { | 450 } else { |
451 subu(rd, rs, rt); | 451 subu(rd, rs, rt); |
452 xor_(ro, rd, rs); | 452 xor_(ro, rd, rs); |
453 xor_(TMP, rs, rt); | 453 xor_(TMP, rs, rt); |
454 and_(ro, TMP, ro); | 454 and_(ro, TMP, ro); |
455 } | 455 } |
456 } | 456 } |
457 | 457 |
458 | 458 |
459 void Assembler::Branch(const StubEntry& stub_entry) { | 459 void Assembler::Branch(const StubEntry& stub_entry) { |
| 460 ASSERT(!in_delay_slot_); |
460 const ExternalLabel label(stub_entry.EntryPoint()); | 461 const ExternalLabel label(stub_entry.EntryPoint()); |
461 Branch(&label); | 462 LoadImmediate(TMP, label.address()); |
| 463 jr(TMP); |
462 } | 464 } |
463 | 465 |
464 | 466 |
465 void Assembler::BranchPatchable(const StubEntry& stub_entry) { | 467 void Assembler::BranchPatchable(const StubEntry& stub_entry) { |
| 468 ASSERT(!in_delay_slot_); |
466 const ExternalLabel label(stub_entry.EntryPoint()); | 469 const ExternalLabel label(stub_entry.EntryPoint()); |
467 BranchPatchable(&label); | 470 const uint16_t low = Utils::Low16Bits(label.address()); |
| 471 const uint16_t high = Utils::High16Bits(label.address()); |
| 472 lui(T9, Immediate(high)); |
| 473 ori(T9, T9, Immediate(low)); |
| 474 jr(T9); |
| 475 delay_slot_available_ = false; // CodePatcher expects a nop. |
468 } | 476 } |
469 | 477 |
470 | 478 |
471 void Assembler::BranchLink(const StubEntry& stub_entry) { | 479 void Assembler::BranchLink(const ExternalLabel* label) { |
472 const ExternalLabel label(stub_entry.EntryPoint()); | 480 ASSERT(!in_delay_slot_); |
473 BranchLink(&label); | 481 LoadImmediate(T9, label->address()); |
| 482 jalr(T9); |
474 } | 483 } |
475 | 484 |
476 | 485 |
| 486 void Assembler::BranchLink(const ExternalLabel* label, Patchability patchable) { |
| 487 ASSERT(!in_delay_slot_); |
| 488 const int32_t offset = ObjectPool::element_offset( |
| 489 object_pool_wrapper_.FindExternalLabel(label, patchable)); |
| 490 LoadWordFromPoolOffset(T9, offset - kHeapObjectTag); |
| 491 jalr(T9); |
| 492 if (patchable == kPatchable) { |
| 493 delay_slot_available_ = false; // CodePatcher expects a nop. |
| 494 } |
| 495 } |
| 496 |
| 497 |
477 void Assembler::BranchLink(const StubEntry& stub_entry, | 498 void Assembler::BranchLink(const StubEntry& stub_entry, |
478 Patchability patchable) { | 499 Patchability patchable) { |
479 const ExternalLabel label(stub_entry.EntryPoint()); | 500 const ExternalLabel label(stub_entry.EntryPoint()); |
480 BranchLink(&label, patchable); | 501 BranchLink(&label, patchable); |
481 } | 502 } |
482 | 503 |
483 | 504 |
484 void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) { | 505 void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) { |
485 const ExternalLabel label(stub_entry.EntryPoint()); | 506 const ExternalLabel label(stub_entry.EntryPoint()); |
486 BranchLink(&label, kPatchable); | 507 BranchLink(&label, kPatchable); |
(...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1146 LoadImmediate(TMP, ~(OS::ActivationFrameAlignment() - 1)); | 1167 LoadImmediate(TMP, ~(OS::ActivationFrameAlignment() - 1)); |
1147 and_(SP, SP, TMP); | 1168 and_(SP, SP, TMP); |
1148 } | 1169 } |
1149 } | 1170 } |
1150 | 1171 |
1151 | 1172 |
1152 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) { | 1173 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) { |
1153 ASSERT(!in_delay_slot_); | 1174 ASSERT(!in_delay_slot_); |
1154 const intptr_t kPushedRegistersSize = | 1175 const intptr_t kPushedRegistersSize = |
1155 kDartVolatileCpuRegCount * kWordSize + | 1176 kDartVolatileCpuRegCount * kWordSize + |
1156 2 * kWordSize + // FP and RA. | 1177 3 * kWordSize + // PP, FP and RA. |
1157 kDartVolatileFpuRegCount * kWordSize; | 1178 kDartVolatileFpuRegCount * kWordSize; |
1158 | 1179 |
1159 SetPrologueOffset(); | 1180 SetPrologueOffset(); |
1160 | 1181 |
1161 Comment("EnterCallRuntimeFrame"); | 1182 Comment("EnterCallRuntimeFrame"); |
1162 | 1183 |
1163 // Save volatile CPU and FPU registers on the stack: | 1184 // Save volatile CPU and FPU registers on the stack: |
1164 // ------------- | 1185 // ------------- |
1165 // FPU Registers | 1186 // FPU Registers |
1166 // CPU Registers | 1187 // CPU Registers |
1167 // RA | 1188 // RA |
1168 // FP | 1189 // FP |
1169 // ------------- | 1190 // ------------- |
1170 // TODO(zra): It may be a problem for walking the stack that FP is below | 1191 // TODO(zra): It may be a problem for walking the stack that FP is below |
1171 // the saved registers. If it turns out to be a problem in the | 1192 // the saved registers. If it turns out to be a problem in the |
1172 // future, try pushing RA and FP before the volatile registers. | 1193 // future, try pushing RA and FP before the volatile registers. |
1173 addiu(SP, SP, Immediate(-kPushedRegistersSize)); | 1194 addiu(SP, SP, Immediate(-kPushedRegistersSize)); |
1174 for (int i = kDartFirstVolatileFpuReg; i <= kDartLastVolatileFpuReg; i++) { | 1195 for (int i = kDartFirstVolatileFpuReg; i <= kDartLastVolatileFpuReg; i++) { |
1175 // These go above the volatile CPU registers. | 1196 // These go above the volatile CPU registers. |
1176 const int slot = | 1197 const int slot = |
1177 (i - kDartFirstVolatileFpuReg) + kDartVolatileCpuRegCount + 2; | 1198 (i - kDartFirstVolatileFpuReg) + kDartVolatileCpuRegCount + 3; |
1178 FRegister reg = static_cast<FRegister>(i); | 1199 FRegister reg = static_cast<FRegister>(i); |
1179 swc1(reg, Address(SP, slot * kWordSize)); | 1200 swc1(reg, Address(SP, slot * kWordSize)); |
1180 } | 1201 } |
1181 for (int i = kDartFirstVolatileCpuReg; i <= kDartLastVolatileCpuReg; i++) { | 1202 for (int i = kDartFirstVolatileCpuReg; i <= kDartLastVolatileCpuReg; i++) { |
1182 // + 2 because FP goes in slot 0. | 1203 // + 2 because FP goes in slot 0. |
1183 const int slot = (i - kDartFirstVolatileCpuReg) + 2; | 1204 const int slot = (i - kDartFirstVolatileCpuReg) + 3; |
1184 Register reg = static_cast<Register>(i); | 1205 Register reg = static_cast<Register>(i); |
1185 sw(reg, Address(SP, slot * kWordSize)); | 1206 sw(reg, Address(SP, slot * kWordSize)); |
1186 } | 1207 } |
1187 sw(RA, Address(SP, 1 * kWordSize)); | 1208 sw(RA, Address(SP, 2 * kWordSize)); |
1188 sw(FP, Address(SP, 0 * kWordSize)); | 1209 sw(FP, Address(SP, 1 * kWordSize)); |
| 1210 sw(PP, Address(SP, 0 * kWordSize)); |
| 1211 LoadPoolPointer(); |
| 1212 |
1189 mov(FP, SP); | 1213 mov(FP, SP); |
1190 | 1214 |
1191 ReserveAlignedFrameSpace(frame_space); | 1215 ReserveAlignedFrameSpace(frame_space); |
1192 } | 1216 } |
1193 | 1217 |
1194 | 1218 |
1195 void Assembler::LeaveCallRuntimeFrame() { | 1219 void Assembler::LeaveCallRuntimeFrame() { |
1196 ASSERT(!in_delay_slot_); | 1220 ASSERT(!in_delay_slot_); |
1197 const intptr_t kPushedRegistersSize = | 1221 const intptr_t kPushedRegistersSize = |
1198 kDartVolatileCpuRegCount * kWordSize + | 1222 kDartVolatileCpuRegCount * kWordSize + |
1199 2 * kWordSize + // FP and RA. | 1223 3 * kWordSize + // FP and RA. |
1200 kDartVolatileFpuRegCount * kWordSize; | 1224 kDartVolatileFpuRegCount * kWordSize; |
1201 | 1225 |
1202 Comment("LeaveCallRuntimeFrame"); | 1226 Comment("LeaveCallRuntimeFrame"); |
1203 | 1227 |
1204 // SP might have been modified to reserve space for arguments | 1228 // SP might have been modified to reserve space for arguments |
1205 // and ensure proper alignment of the stack frame. | 1229 // and ensure proper alignment of the stack frame. |
1206 // We need to restore it before restoring registers. | 1230 // We need to restore it before restoring registers. |
1207 mov(SP, FP); | 1231 mov(SP, FP); |
1208 | 1232 |
1209 // Restore volatile CPU and FPU registers from the stack. | 1233 // Restore volatile CPU and FPU registers from the stack. |
1210 lw(FP, Address(SP, 0 * kWordSize)); | 1234 lw(PP, Address(SP, 0 * kWordSize)); |
1211 lw(RA, Address(SP, 1 * kWordSize)); | 1235 lw(FP, Address(SP, 1 * kWordSize)); |
| 1236 lw(RA, Address(SP, 2 * kWordSize)); |
1212 for (int i = kDartFirstVolatileCpuReg; i <= kDartLastVolatileCpuReg; i++) { | 1237 for (int i = kDartFirstVolatileCpuReg; i <= kDartLastVolatileCpuReg; i++) { |
1213 // + 2 because FP goes in slot 0. | 1238 // + 2 because FP goes in slot 0. |
1214 const int slot = (i - kDartFirstVolatileCpuReg) + 2; | 1239 const int slot = (i - kDartFirstVolatileCpuReg) + 3; |
1215 Register reg = static_cast<Register>(i); | 1240 Register reg = static_cast<Register>(i); |
1216 lw(reg, Address(SP, slot * kWordSize)); | 1241 lw(reg, Address(SP, slot * kWordSize)); |
1217 } | 1242 } |
1218 for (int i = kDartFirstVolatileFpuReg; i <= kDartLastVolatileFpuReg; i++) { | 1243 for (int i = kDartFirstVolatileFpuReg; i <= kDartLastVolatileFpuReg; i++) { |
1219 // These go above the volatile CPU registers. | 1244 // These go above the volatile CPU registers. |
1220 const int slot = | 1245 const int slot = |
1221 (i - kDartFirstVolatileFpuReg) + kDartVolatileCpuRegCount + 2; | 1246 (i - kDartFirstVolatileFpuReg) + kDartVolatileCpuRegCount + 3; |
1222 FRegister reg = static_cast<FRegister>(i); | 1247 FRegister reg = static_cast<FRegister>(i); |
1223 lwc1(reg, Address(SP, slot * kWordSize)); | 1248 lwc1(reg, Address(SP, slot * kWordSize)); |
1224 } | 1249 } |
1225 addiu(SP, SP, Immediate(kPushedRegistersSize)); | 1250 addiu(SP, SP, Immediate(kPushedRegistersSize)); |
1226 } | 1251 } |
1227 | 1252 |
1228 | 1253 |
1229 Address Assembler::ElementAddressForIntIndex(bool is_external, | 1254 Address Assembler::ElementAddressForIntIndex(bool is_external, |
1230 intptr_t cid, | 1255 intptr_t cid, |
1231 intptr_t index_scale, | 1256 intptr_t index_scale, |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1300 Label stop; | 1325 Label stop; |
1301 b(&stop); | 1326 b(&stop); |
1302 Emit(reinterpret_cast<int32_t>(message)); | 1327 Emit(reinterpret_cast<int32_t>(message)); |
1303 Bind(&stop); | 1328 Bind(&stop); |
1304 break_(Instr::kStopMessageCode); | 1329 break_(Instr::kStopMessageCode); |
1305 } | 1330 } |
1306 | 1331 |
1307 } // namespace dart | 1332 } // namespace dart |
1308 | 1333 |
1309 #endif // defined TARGET_ARCH_MIPS | 1334 #endif // defined TARGET_ARCH_MIPS |
OLD | NEW |