| 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 <math.h> // for isnan. | 5 #include <math.h> // for isnan. |
| 6 #include <setjmp.h> | 6 #include <setjmp.h> |
| 7 #include <stdlib.h> | 7 #include <stdlib.h> |
| 8 | 8 |
| 9 #include "vm/globals.h" | 9 #include "vm/globals.h" |
| 10 #if defined(TARGET_ARCH_MIPS) | 10 #if defined(TARGET_ARCH_MIPS) |
| (...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 Simulator* Simulator::Current() { | 635 Simulator* Simulator::Current() { |
| 636 Simulator* simulator = Isolate::Current()->simulator(); | 636 Simulator* simulator = Isolate::Current()->simulator(); |
| 637 if (simulator == NULL) { | 637 if (simulator == NULL) { |
| 638 simulator = new Simulator(); | 638 simulator = new Simulator(); |
| 639 Isolate::Current()->set_simulator(simulator); | 639 Isolate::Current()->set_simulator(simulator); |
| 640 } | 640 } |
| 641 return simulator; | 641 return simulator; |
| 642 } | 642 } |
| 643 | 643 |
| 644 | 644 |
| 645 // Sets the register in the architecture state. It will also deal with updating | 645 // Sets the register in the architecture state. |
| 646 // Simulator internal state for special registers such as PC. | |
| 647 void Simulator::set_register(Register reg, int32_t value) { | 646 void Simulator::set_register(Register reg, int32_t value) { |
| 648 if (reg != R0) { | 647 if (reg != R0) { |
| 649 registers_[reg] = value; | 648 registers_[reg] = value; |
| 650 } | 649 } |
| 651 } | 650 } |
| 652 | 651 |
| 653 | 652 |
| 654 // Get the register from the architecture state. This function does handle | 653 void Simulator::set_fregister(FRegister reg, int32_t value) { |
| 655 // the special case of accessing the PC register. | 654 ASSERT(reg >= 0); |
| 655 ASSERT(reg < kNumberOfFRegisters); |
| 656 fregisters_[reg] = value; |
| 657 } |
| 658 |
| 659 |
| 660 void Simulator::set_fregister_float(FRegister reg, float value) { |
| 661 ASSERT(reg >= 0); |
| 662 ASSERT(reg < kNumberOfFRegisters); |
| 663 fregisters_[reg] = bit_cast<int32_t, float>(value); |
| 664 } |
| 665 |
| 666 |
| 667 void Simulator::set_fregister_long(FRegister reg, int64_t value) { |
| 668 ASSERT(reg >= 0); |
| 669 ASSERT(reg < kNumberOfFRegisters); |
| 670 ASSERT((reg & 1) == 0); |
| 671 fregisters_[reg] = Utils::Low32Bits(value); |
| 672 fregisters_[reg + 1] = Utils::High32Bits(value); |
| 673 } |
| 674 |
| 675 |
| 676 void Simulator::set_fregister_double(FRegister reg, double value) { |
| 677 const int64_t ival = bit_cast<int64_t, double>(value); |
| 678 set_fregister_long(reg, ival); |
| 679 } |
| 680 |
| 681 |
| 682 // Get the register from the architecture state. |
| 656 int32_t Simulator::get_register(Register reg) const { | 683 int32_t Simulator::get_register(Register reg) const { |
| 657 if (reg == R0) { | 684 if (reg == R0) { |
| 658 return 0; | 685 return 0; |
| 659 } | 686 } |
| 660 return registers_[reg]; | 687 return registers_[reg]; |
| 661 } | 688 } |
| 662 | 689 |
| 663 | 690 |
| 664 void Simulator::set_fregister(FRegister reg, double value) { | 691 int32_t Simulator::get_fregister(FRegister reg) const { |
| 665 ASSERT((reg >= 0) && (reg < kNumberOfFRegisters)); | 692 ASSERT((reg >= 0) && (reg < kNumberOfFRegisters)); |
| 666 fregisters_[reg] = value; | 693 return fregisters_[reg]; |
| 667 } | 694 } |
| 668 | 695 |
| 669 | 696 |
| 670 double Simulator::get_fregister(FRegister reg) const { | 697 float Simulator::get_fregister_float(FRegister reg) const { |
| 671 ASSERT((reg >= 0) && (reg < kNumberOfFRegisters)); | 698 ASSERT(reg >= 0); |
| 672 return fregisters_[reg]; | 699 ASSERT(reg < kNumberOfFRegisters); |
| 700 return bit_cast<float, int32_t>(fregisters_[reg]); |
| 701 } |
| 702 |
| 703 |
| 704 int64_t Simulator::get_fregister_long(FRegister reg) const { |
| 705 ASSERT(reg >= 0); |
| 706 ASSERT(reg < kNumberOfFRegisters); |
| 707 ASSERT((reg & 1) == 0); |
| 708 const int32_t low = fregisters_[reg]; |
| 709 const int32_t high = fregisters_[reg + 1]; |
| 710 const int64_t value = Utils::LowHighTo64Bits(low, high); |
| 711 return value; |
| 712 } |
| 713 |
| 714 |
| 715 double Simulator::get_fregister_double(FRegister reg) const { |
| 716 ASSERT(reg >= 0); |
| 717 ASSERT(reg < kNumberOfFRegisters); |
| 718 ASSERT((reg & 1) == 0); |
| 719 const int64_t value = get_fregister_long(reg); |
| 720 return bit_cast<double, int64_t>(value); |
| 673 } | 721 } |
| 674 | 722 |
| 675 | 723 |
| 676 void Simulator::UnimplementedInstruction(Instr* instr) { | 724 void Simulator::UnimplementedInstruction(Instr* instr) { |
| 677 char buffer[64]; | 725 char buffer[64]; |
| 678 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr); | 726 snprintf(buffer, sizeof(buffer), "Unimplemented instruction: pc=%p\n", instr); |
| 679 SimulatorDebugger dbg(this); | 727 SimulatorDebugger dbg(this); |
| 680 dbg.Stop(instr, buffer); | 728 dbg.Stop(instr, buffer); |
| 681 FATAL("Cannot continue execution after unimplemented instruction."); | 729 FATAL("Cannot continue execution after unimplemented instruction."); |
| 682 } | 730 } |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 787 void Simulator::WriteW(uword addr, int value, Instr* instr) { | 835 void Simulator::WriteW(uword addr, int value, Instr* instr) { |
| 788 if ((addr & 3) == 0) { | 836 if ((addr & 3) == 0) { |
| 789 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); | 837 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); |
| 790 *ptr = value; | 838 *ptr = value; |
| 791 return; | 839 return; |
| 792 } | 840 } |
| 793 UnalignedAccess("write", addr, instr); | 841 UnalignedAccess("write", addr, instr); |
| 794 } | 842 } |
| 795 | 843 |
| 796 | 844 |
| 845 double Simulator::ReadD(uword addr, Instr* instr) { |
| 846 if ((addr & 7) == 0) { |
| 847 double* ptr = reinterpret_cast<double*>(addr); |
| 848 return *ptr; |
| 849 } |
| 850 UnalignedAccess("double-precision floating point read", addr, instr); |
| 851 return 0.0; |
| 852 } |
| 853 |
| 854 |
| 855 void Simulator::WriteD(uword addr, double value, Instr* instr) { |
| 856 if ((addr & 7) == 0) { |
| 857 double* ptr = reinterpret_cast<double*>(addr); |
| 858 *ptr = value; |
| 859 return; |
| 860 } |
| 861 UnalignedAccess("double-precision floating point write", addr, instr); |
| 862 } |
| 863 |
| 864 |
| 797 bool Simulator::OverflowFrom(int32_t alu_out, | 865 bool Simulator::OverflowFrom(int32_t alu_out, |
| 798 int32_t left, int32_t right, bool addition) { | 866 int32_t left, int32_t right, bool addition) { |
| 799 bool overflow; | 867 bool overflow; |
| 800 if (addition) { | 868 if (addition) { |
| 801 // Operands have the same sign. | 869 // Operands have the same sign. |
| 802 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0)) | 870 overflow = ((left >= 0 && right >= 0) || (left < 0 && right < 0)) |
| 803 // And operands and result have different sign. | 871 // And operands and result have different sign. |
| 804 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); | 872 && ((left < 0 && alu_out >= 0) || (left >= 0 && alu_out < 0)); |
| 805 } else { | 873 } else { |
| 806 // Operands have different signs. | 874 // Operands have different signs. |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 898 set_register(T9, icount_); | 966 set_register(T9, icount_); |
| 899 | 967 |
| 900 set_register(A0, icount_); | 968 set_register(A0, icount_); |
| 901 set_register(A1, icount_); | 969 set_register(A1, icount_); |
| 902 set_register(A2, icount_); | 970 set_register(A2, icount_); |
| 903 set_register(A3, icount_); | 971 set_register(A3, icount_); |
| 904 set_register(TMP, icount_); | 972 set_register(TMP, icount_); |
| 905 set_register(RA, icount_); | 973 set_register(RA, icount_); |
| 906 | 974 |
| 907 // Zap floating point registers. | 975 // Zap floating point registers. |
| 908 double zap_dvalue = static_cast<double>(icount_); | 976 int32_t zap_dvalue = icount_; |
| 909 for (int i = F0; i <= F31; i++) { | 977 for (int i = F0; i <= F31; i++) { |
| 910 set_fregister(static_cast<FRegister>(i), zap_dvalue); | 978 set_fregister(static_cast<FRegister>(i), zap_dvalue); |
| 911 } | 979 } |
| 912 | 980 |
| 913 // Return. Subtract to account for pc_ increment after return. | 981 // Return. Subtract to account for pc_ increment after return. |
| 914 set_pc(saved_ra - Instr::kInstrSize); | 982 set_pc(saved_ra - Instr::kInstrSize); |
| 915 } | 983 } |
| 916 } else { | 984 } else { |
| 917 SimulatorDebugger dbg(this); | 985 SimulatorDebugger dbg(this); |
| 918 dbg.Stop(instr, "breakpoint"); | 986 dbg.Stop(instr, "breakpoint"); |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1279 } | 1347 } |
| 1280 default: { | 1348 default: { |
| 1281 OS::PrintErr("DecodeRegImm: 0x%x\n", instr->InstructionBits()); | 1349 OS::PrintErr("DecodeRegImm: 0x%x\n", instr->InstructionBits()); |
| 1282 UnimplementedInstruction(instr); | 1350 UnimplementedInstruction(instr); |
| 1283 break; | 1351 break; |
| 1284 } | 1352 } |
| 1285 } | 1353 } |
| 1286 } | 1354 } |
| 1287 | 1355 |
| 1288 | 1356 |
| 1357 void Simulator::DecodeCop1(Instr* instr) { |
| 1358 ASSERT(instr->OpcodeField() == COP1); |
| 1359 if (instr->HasFormat()) { |
| 1360 // If the rs field is a valid format, then the function field identifies the |
| 1361 // instruction. |
| 1362 switch (instr->Cop1FunctionField()) { |
| 1363 case COP1_ADD: { |
| 1364 // Format(instr, "add.'fmt 'fd, 'fs, 'ft"); |
| 1365 if (instr->FormatField() == FMT_S) { |
| 1366 float fs_val = get_fregister_float(instr->FsField()); |
| 1367 float ft_val = get_fregister_float(instr->FtField()); |
| 1368 set_fregister_float(instr->FdField(), fs_val + ft_val); |
| 1369 } else { |
| 1370 ASSERT(instr->FormatField() == FMT_D); // Only S and D supported. |
| 1371 double fs_val = get_fregister_double(instr->FsField()); |
| 1372 double ft_val = get_fregister_double(instr->FtField()); |
| 1373 set_fregister_double(instr->FdField(), fs_val + ft_val); |
| 1374 } |
| 1375 break; |
| 1376 } |
| 1377 case COP1_MOV: { |
| 1378 // Format(instr, "mov.'fmt 'fd, 'fs"); |
| 1379 ASSERT(instr->FtField() == F0); |
| 1380 if (instr->FormatField() == FMT_S) { |
| 1381 float fs_val = get_fregister_float(instr->FsField()); |
| 1382 set_fregister_float(instr->FdField(), fs_val); |
| 1383 } else { |
| 1384 ASSERT(instr->FormatField() == FMT_D); |
| 1385 double fs_val = get_fregister_double(instr->FsField()); |
| 1386 set_fregister_double(instr->FdField(), fs_val); |
| 1387 } |
| 1388 break; |
| 1389 } |
| 1390 default: { |
| 1391 OS::PrintErr("DecodeCop1: 0x%x\n", instr->InstructionBits()); |
| 1392 UnimplementedInstruction(instr); |
| 1393 break; |
| 1394 } |
| 1395 } |
| 1396 } else { |
| 1397 // If the rs field isn't a valid format, then it must be a sub-op. |
| 1398 switch (instr->Cop1SubField()) { |
| 1399 case COP1_MF: { |
| 1400 // Format(instr, "mfc1 'rt, 'fs"); |
| 1401 ASSERT(instr->Bits(0, 11) == 0); |
| 1402 int32_t fs_val = get_fregister(instr->FsField()); |
| 1403 set_register(instr->RtField(), fs_val); |
| 1404 break; |
| 1405 } |
| 1406 case COP1_MT: { |
| 1407 // Format(instr, "mtc1 'rt, 'fs"); |
| 1408 ASSERT(instr->Bits(0, 11) == 0); |
| 1409 int32_t rt_val = get_register(instr->RtField()); |
| 1410 set_fregister(instr->FsField(), rt_val); |
| 1411 break; |
| 1412 } |
| 1413 default: { |
| 1414 OS::PrintErr("DecodeCop1: 0x%x\n", instr->InstructionBits()); |
| 1415 UnimplementedInstruction(instr); |
| 1416 break; |
| 1417 } |
| 1418 } |
| 1419 } |
| 1420 } |
| 1421 |
| 1422 |
| 1289 void Simulator::InstructionDecode(Instr* instr) { | 1423 void Simulator::InstructionDecode(Instr* instr) { |
| 1290 if (FLAG_trace_sim) { | 1424 if (FLAG_trace_sim) { |
| 1291 const uword start = reinterpret_cast<uword>(instr); | 1425 const uword start = reinterpret_cast<uword>(instr); |
| 1292 const uword end = start + Instr::kInstrSize; | 1426 const uword end = start + Instr::kInstrSize; |
| 1293 Disassembler::Disassemble(start, end); | 1427 Disassembler::Disassemble(start, end); |
| 1294 } | 1428 } |
| 1295 | 1429 |
| 1296 switch (instr->OpcodeField()) { | 1430 switch (instr->OpcodeField()) { |
| 1297 case SPECIAL: { | 1431 case SPECIAL: { |
| 1298 DecodeSpecial(instr); | 1432 DecodeSpecial(instr); |
| 1299 break; | 1433 break; |
| 1300 } | 1434 } |
| 1301 case SPECIAL2: { | 1435 case SPECIAL2: { |
| 1302 DecodeSpecial2(instr); | 1436 DecodeSpecial2(instr); |
| 1303 break; | 1437 break; |
| 1304 } | 1438 } |
| 1305 case REGIMM: { | 1439 case REGIMM: { |
| 1306 DecodeRegImm(instr); | 1440 DecodeRegImm(instr); |
| 1307 break; | 1441 break; |
| 1308 } | 1442 } |
| 1443 case COP1: { |
| 1444 DecodeCop1(instr); |
| 1445 break; |
| 1446 } |
| 1309 case ADDIU: { | 1447 case ADDIU: { |
| 1310 // Format(instr, "addiu 'rt, 'rs, 'imms"); | 1448 // Format(instr, "addiu 'rt, 'rs, 'imms"); |
| 1311 int32_t rs_val = get_register(instr->RsField()); | 1449 int32_t rs_val = get_register(instr->RsField()); |
| 1312 int32_t imm_val = instr->SImmField(); | 1450 int32_t imm_val = instr->SImmField(); |
| 1313 int32_t res = rs_val + imm_val; | 1451 int32_t res = rs_val + imm_val; |
| 1314 // Rt is set even on overflow. | 1452 // Rt is set even on overflow. |
| 1315 set_register(instr->RtField(), res); | 1453 set_register(instr->RtField(), res); |
| 1316 break; | 1454 break; |
| 1317 } | 1455 } |
| 1318 case ANDI: { | 1456 case ANDI: { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1396 int32_t imm_val = instr->SImmField(); | 1534 int32_t imm_val = instr->SImmField(); |
| 1397 uword addr = base_val + imm_val; | 1535 uword addr = base_val + imm_val; |
| 1398 if (Simulator::IsIllegalAddress(addr)) { | 1536 if (Simulator::IsIllegalAddress(addr)) { |
| 1399 HandleIllegalAccess(addr, instr); | 1537 HandleIllegalAccess(addr, instr); |
| 1400 } else { | 1538 } else { |
| 1401 int32_t res = ReadBU(addr); | 1539 int32_t res = ReadBU(addr); |
| 1402 set_register(instr->RtField(), res); | 1540 set_register(instr->RtField(), res); |
| 1403 } | 1541 } |
| 1404 break; | 1542 break; |
| 1405 } | 1543 } |
| 1544 case LDC1: { |
| 1545 // Format(instr, "ldc1 'ft, 'imms('rs)"); |
| 1546 int32_t base_val = get_register(instr->RsField()); |
| 1547 int32_t imm_val = instr->SImmField(); |
| 1548 uword addr = base_val + imm_val; |
| 1549 if (Simulator::IsIllegalAddress(addr)) { |
| 1550 HandleIllegalAccess(addr, instr); |
| 1551 } else { |
| 1552 double value = ReadD(addr, instr); |
| 1553 set_fregister_double(instr->FtField(), value); |
| 1554 } |
| 1555 break; |
| 1556 } |
| 1406 case LH: { | 1557 case LH: { |
| 1407 // Format(instr, "lh 'rt, 'imms('rs)"); | 1558 // Format(instr, "lh 'rt, 'imms('rs)"); |
| 1408 int32_t base_val = get_register(instr->RsField()); | 1559 int32_t base_val = get_register(instr->RsField()); |
| 1409 int32_t imm_val = instr->SImmField(); | 1560 int32_t imm_val = instr->SImmField(); |
| 1410 uword addr = base_val + imm_val; | 1561 uword addr = base_val + imm_val; |
| 1411 if (Simulator::IsIllegalAddress(addr)) { | 1562 if (Simulator::IsIllegalAddress(addr)) { |
| 1412 HandleIllegalAccess(addr, instr); | 1563 HandleIllegalAccess(addr, instr); |
| 1413 } else { | 1564 } else { |
| 1414 int32_t res = ReadH(addr, instr); | 1565 int32_t res = ReadH(addr, instr); |
| 1415 set_register(instr->RtField(), res); | 1566 set_register(instr->RtField(), res); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1440 int32_t imm_val = instr->SImmField(); | 1591 int32_t imm_val = instr->SImmField(); |
| 1441 uword addr = base_val + imm_val; | 1592 uword addr = base_val + imm_val; |
| 1442 if (Simulator::IsIllegalAddress(addr)) { | 1593 if (Simulator::IsIllegalAddress(addr)) { |
| 1443 HandleIllegalAccess(addr, instr); | 1594 HandleIllegalAccess(addr, instr); |
| 1444 } else { | 1595 } else { |
| 1445 int32_t res = ReadW(addr, instr); | 1596 int32_t res = ReadW(addr, instr); |
| 1446 set_register(instr->RtField(), res); | 1597 set_register(instr->RtField(), res); |
| 1447 } | 1598 } |
| 1448 break; | 1599 break; |
| 1449 } | 1600 } |
| 1601 case LWC1: { |
| 1602 // Format(instr, "lwc1 'ft, 'imms('rs)"); |
| 1603 int32_t base_val = get_register(instr->RsField()); |
| 1604 int32_t imm_val = instr->SImmField(); |
| 1605 uword addr = base_val + imm_val; |
| 1606 if (Simulator::IsIllegalAddress(addr)) { |
| 1607 HandleIllegalAccess(addr, instr); |
| 1608 } else { |
| 1609 int32_t value = ReadW(addr, instr); |
| 1610 set_fregister(instr->FtField(), value); |
| 1611 } |
| 1612 break; |
| 1613 } |
| 1450 case ORI: { | 1614 case ORI: { |
| 1451 // Format(instr, "ori 'rt, 'rs, 'immu"); | 1615 // Format(instr, "ori 'rt, 'rs, 'immu"); |
| 1452 int32_t rs_val = get_register(instr->RsField()); | 1616 int32_t rs_val = get_register(instr->RsField()); |
| 1453 set_register(instr->RtField(), rs_val | instr->UImmField()); | 1617 set_register(instr->RtField(), rs_val | instr->UImmField()); |
| 1454 break; | 1618 break; |
| 1455 } | 1619 } |
| 1456 case SB: { | 1620 case SB: { |
| 1457 // Format(instr, "sb 'rt, 'imms('rs)"); | 1621 // Format(instr, "sb 'rt, 'imms('rs)"); |
| 1458 int32_t rt_val = get_register(instr->RtField()); | 1622 int32_t rt_val = get_register(instr->RtField()); |
| 1459 int32_t base_val = get_register(instr->RsField()); | 1623 int32_t base_val = get_register(instr->RsField()); |
| 1460 int32_t imm_val = instr->SImmField(); | 1624 int32_t imm_val = instr->SImmField(); |
| 1461 uword addr = base_val + imm_val; | 1625 uword addr = base_val + imm_val; |
| 1462 if (Simulator::IsIllegalAddress(addr)) { | 1626 if (Simulator::IsIllegalAddress(addr)) { |
| 1463 HandleIllegalAccess(addr, instr); | 1627 HandleIllegalAccess(addr, instr); |
| 1464 } else { | 1628 } else { |
| 1465 WriteB(addr, rt_val & 0xff); | 1629 WriteB(addr, rt_val & 0xff); |
| 1466 } | 1630 } |
| 1467 break; | 1631 break; |
| 1468 } | 1632 } |
| 1633 case SDC1: { |
| 1634 // Format(instr, "sdc1 'ft, 'imms('rs)"); |
| 1635 int32_t base_val = get_register(instr->RsField()); |
| 1636 int32_t imm_val = instr->SImmField(); |
| 1637 uword addr = base_val + imm_val; |
| 1638 if (Simulator::IsIllegalAddress(addr)) { |
| 1639 HandleIllegalAccess(addr, instr); |
| 1640 } else { |
| 1641 double value = get_fregister_double(instr->FtField()); |
| 1642 WriteD(addr, value, instr); |
| 1643 } |
| 1644 break; |
| 1645 } |
| 1469 case SH: { | 1646 case SH: { |
| 1470 // Format(instr, "sh 'rt, 'imms('rs)"); | 1647 // Format(instr, "sh 'rt, 'imms('rs)"); |
| 1471 int32_t rt_val = get_register(instr->RtField()); | 1648 int32_t rt_val = get_register(instr->RtField()); |
| 1472 int32_t base_val = get_register(instr->RsField()); | 1649 int32_t base_val = get_register(instr->RsField()); |
| 1473 int32_t imm_val = instr->SImmField(); | 1650 int32_t imm_val = instr->SImmField(); |
| 1474 uword addr = base_val + imm_val; | 1651 uword addr = base_val + imm_val; |
| 1475 if (Simulator::IsIllegalAddress(addr)) { | 1652 if (Simulator::IsIllegalAddress(addr)) { |
| 1476 HandleIllegalAccess(addr, instr); | 1653 HandleIllegalAccess(addr, instr); |
| 1477 } else { | 1654 } else { |
| 1478 WriteH(addr, rt_val & 0xffff, instr); | 1655 WriteH(addr, rt_val & 0xffff, instr); |
| 1479 } | 1656 } |
| 1480 break; | 1657 break; |
| 1481 } | 1658 } |
| 1482 case SW: { | 1659 case SW: { |
| 1483 // Format(instr, "sw 'rt, 'imms('rs)"); | 1660 // Format(instr, "sw 'rt, 'imms('rs)"); |
| 1484 int32_t rt_val = get_register(instr->RtField()); | 1661 int32_t rt_val = get_register(instr->RtField()); |
| 1485 int32_t base_val = get_register(instr->RsField()); | 1662 int32_t base_val = get_register(instr->RsField()); |
| 1486 int32_t imm_val = instr->SImmField(); | 1663 int32_t imm_val = instr->SImmField(); |
| 1487 uword addr = base_val + imm_val; | 1664 uword addr = base_val + imm_val; |
| 1488 if (Simulator::IsIllegalAddress(addr)) { | 1665 if (Simulator::IsIllegalAddress(addr)) { |
| 1489 HandleIllegalAccess(addr, instr); | 1666 HandleIllegalAccess(addr, instr); |
| 1490 } else { | 1667 } else { |
| 1491 WriteW(addr, rt_val, instr); | 1668 WriteW(addr, rt_val, instr); |
| 1492 } | 1669 } |
| 1493 break; | 1670 break; |
| 1494 } | 1671 } |
| 1672 case SWC1: { |
| 1673 // Format(instr, "swc1 'ft, 'imms('rs)"); |
| 1674 int32_t base_val = get_register(instr->RsField()); |
| 1675 int32_t imm_val = instr->SImmField(); |
| 1676 uword addr = base_val + imm_val; |
| 1677 if (Simulator::IsIllegalAddress(addr)) { |
| 1678 HandleIllegalAccess(addr, instr); |
| 1679 } else { |
| 1680 int32_t value = get_fregister(instr->FtField()); |
| 1681 WriteW(addr, value, instr); |
| 1682 } |
| 1683 break; |
| 1684 } |
| 1495 default: { | 1685 default: { |
| 1496 OS::PrintErr("Undecoded instruction: 0x%x at %p\n", | 1686 OS::PrintErr("Undecoded instruction: 0x%x at %p\n", |
| 1497 instr->InstructionBits(), instr); | 1687 instr->InstructionBits(), instr); |
| 1498 UnimplementedInstruction(instr); | 1688 UnimplementedInstruction(instr); |
| 1499 break; | 1689 break; |
| 1500 } | 1690 } |
| 1501 } | 1691 } |
| 1502 pc_ += Instr::kInstrSize; | 1692 pc_ += Instr::kInstrSize; |
| 1503 } | 1693 } |
| 1504 | 1694 |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1630 // Restore the SP register and return R1:R0. | 1820 // Restore the SP register and return R1:R0. |
| 1631 set_register(SP, sp_before_call); | 1821 set_register(SP, sp_before_call); |
| 1632 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1)); | 1822 return Utils::LowHighTo64Bits(get_register(V0), get_register(V1)); |
| 1633 } | 1823 } |
| 1634 | 1824 |
| 1635 } // namespace dart | 1825 } // namespace dart |
| 1636 | 1826 |
| 1637 #endif // !defined(HOST_ARCH_MIPS) | 1827 #endif // !defined(HOST_ARCH_MIPS) |
| 1638 | 1828 |
| 1639 #endif // defined TARGET_ARCH_MIPS | 1829 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |