diff options
| author | 2015-03-11 16:10:14 -0400 | |
|---|---|---|
| committer | 2015-03-17 15:13:32 -0400 | |
| commit | 9fdb311d6e2d636c4599ddc3d4cb9adad6cec540 (patch) | |
| tree | 358501f8f2e31c7c27ee17c62996ef01e21354c7 /src/core/arm/skyeye_common | |
| parent | dyncom: Implement SETEND (diff) | |
| download | yuzu-9fdb311d6e2d636c4599ddc3d4cb9adad6cec540.tar.gz yuzu-9fdb311d6e2d636c4599ddc3d4cb9adad6cec540.tar.xz yuzu-9fdb311d6e2d636c4599ddc3d4cb9adad6cec540.zip | |
dyncom: Make Load/Store instructions support big endian
Diffstat (limited to 'src/core/arm/skyeye_common')
| -rw-r--r-- | src/core/arm/skyeye_common/armdefs.h | 3 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/armmmu.h | 55 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/vfp/vfpinstr.cpp | 102 |
3 files changed, 130 insertions, 30 deletions
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h index 16f3ac86c..c1a19fecc 100644 --- a/src/core/arm/skyeye_common/armdefs.h +++ b/src/core/arm/skyeye_common/armdefs.h | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | #pragma once | 18 | #pragma once |
| 19 | 19 | ||
| 20 | #include "common/common_types.h" | 20 | #include "common/common_types.h" |
| 21 | #include "core/arm/skyeye_common/armmmu.h" | ||
| 22 | #include "core/arm/skyeye_common/arm_regformat.h" | 21 | #include "core/arm/skyeye_common/arm_regformat.h" |
| 23 | #include "core/arm/skyeye_common/skyeye_defs.h" | 22 | #include "core/arm/skyeye_common/skyeye_defs.h" |
| 24 | 23 | ||
| @@ -356,3 +355,5 @@ extern u16 ARMul_UnsignedSaturatedSub16(u16, u16); | |||
| 356 | extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8); | 355 | extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8); |
| 357 | extern u32 ARMul_SignedSatQ(s32, u8, bool*); | 356 | extern u32 ARMul_SignedSatQ(s32, u8, bool*); |
| 358 | extern u32 ARMul_UnsignedSatQ(s32, u8, bool*); | 357 | extern u32 ARMul_UnsignedSatQ(s32, u8, bool*); |
| 358 | |||
| 359 | extern bool InBigEndianMode(ARMul_State*); | ||
diff --git a/src/core/arm/skyeye_common/armmmu.h b/src/core/arm/skyeye_common/armmmu.h index 6e54142ee..0f9eadafa 100644 --- a/src/core/arm/skyeye_common/armmmu.h +++ b/src/core/arm/skyeye_common/armmmu.h | |||
| @@ -20,6 +20,9 @@ | |||
| 20 | 20 | ||
| 21 | #pragma once | 21 | #pragma once |
| 22 | 22 | ||
| 23 | #include "core/mem_map.h" | ||
| 24 | #include "core/arm/skyeye_common/armdefs.h" | ||
| 25 | |||
| 23 | // Register numbers in the MMU | 26 | // Register numbers in the MMU |
| 24 | enum | 27 | enum |
| 25 | { | 28 | { |
| @@ -54,3 +57,55 @@ enum | |||
| 54 | XSCALE_CP15_AUX_CONTROL = 1, | 57 | XSCALE_CP15_AUX_CONTROL = 1, |
| 55 | XSCALE_CP15_COPRO_ACCESS = 15, | 58 | XSCALE_CP15_COPRO_ACCESS = 15, |
| 56 | }; | 59 | }; |
| 60 | |||
| 61 | // Reads data in big/little endian format based on the | ||
| 62 | // state of the E (endian) bit in the emulated CPU's APSR. | ||
| 63 | inline u16 ReadMemory16(ARMul_State* cpu, u32 address) { | ||
| 64 | u16 data = Memory::Read16(address); | ||
| 65 | |||
| 66 | if (InBigEndianMode(cpu)) | ||
| 67 | data = Common::swap16(data); | ||
| 68 | |||
| 69 | return data; | ||
| 70 | } | ||
| 71 | |||
| 72 | inline u32 ReadMemory32(ARMul_State* cpu, u32 address) { | ||
| 73 | u32 data = Memory::Read32(address); | ||
| 74 | |||
| 75 | if (InBigEndianMode(cpu)) | ||
| 76 | data = Common::swap32(data); | ||
| 77 | |||
| 78 | return data; | ||
| 79 | } | ||
| 80 | |||
| 81 | inline u64 ReadMemory64(ARMul_State* cpu, u32 address) { | ||
| 82 | u64 data = Memory::Read64(address); | ||
| 83 | |||
| 84 | if (InBigEndianMode(cpu)) | ||
| 85 | data = Common::swap64(data); | ||
| 86 | |||
| 87 | return data; | ||
| 88 | } | ||
| 89 | |||
| 90 | // Writes data in big/little endian format based on the | ||
| 91 | // state of the E (endian) bit in the emulated CPU's APSR. | ||
| 92 | inline void WriteMemory16(ARMul_State* cpu, u32 address, u16 data) { | ||
| 93 | if (InBigEndianMode(cpu)) | ||
| 94 | data = Common::swap16(data); | ||
| 95 | |||
| 96 | Memory::Write16(address, data); | ||
| 97 | } | ||
| 98 | |||
| 99 | inline void WriteMemory32(ARMul_State* cpu, u32 address, u32 data) { | ||
| 100 | if (InBigEndianMode(cpu)) | ||
| 101 | data = Common::swap32(data); | ||
| 102 | |||
| 103 | Memory::Write32(address, data); | ||
| 104 | } | ||
| 105 | |||
| 106 | inline void WriteMemory64(ARMul_State* cpu, u32 address, u64 data) { | ||
| 107 | if (InBigEndianMode(cpu)) | ||
| 108 | data = Common::swap64(data); | ||
| 109 | |||
| 110 | Memory::Write64(address, data); | ||
| 111 | } | ||
diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp index b9b96c388..368b5a25d 100644 --- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp | |||
| @@ -1388,12 +1388,20 @@ VSTR_INST: | |||
| 1388 | 1388 | ||
| 1389 | if (inst_cream->single) | 1389 | if (inst_cream->single) |
| 1390 | { | 1390 | { |
| 1391 | Memory::Write32(addr, cpu->ExtReg[inst_cream->d]); | 1391 | WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d]); |
| 1392 | } | 1392 | } |
| 1393 | else | 1393 | else |
| 1394 | { | 1394 | { |
| 1395 | Memory::Write32(addr, cpu->ExtReg[inst_cream->d*2]); | 1395 | const u32 word1 = cpu->ExtReg[inst_cream->d*2+0]; |
| 1396 | Memory::Write32(addr + 4, cpu->ExtReg[inst_cream->d*2+1]); | 1396 | const u32 word2 = cpu->ExtReg[inst_cream->d*2+1]; |
| 1397 | |||
| 1398 | if (InBigEndianMode(cpu)) { | ||
| 1399 | WriteMemory32(cpu, addr + 0, word2); | ||
| 1400 | WriteMemory32(cpu, addr + 4, word1); | ||
| 1401 | } else { | ||
| 1402 | WriteMemory32(cpu, addr + 0, word1); | ||
| 1403 | WriteMemory32(cpu, addr + 4, word2); | ||
| 1404 | } | ||
| 1397 | } | 1405 | } |
| 1398 | } | 1406 | } |
| 1399 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1407 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -1447,17 +1455,27 @@ VPUSH_INST: | |||
| 1447 | { | 1455 | { |
| 1448 | if (inst_cream->single) | 1456 | if (inst_cream->single) |
| 1449 | { | 1457 | { |
| 1450 | Memory::Write32(addr, cpu->ExtReg[inst_cream->d+i]); | 1458 | WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]); |
| 1451 | addr += 4; | 1459 | addr += 4; |
| 1452 | } | 1460 | } |
| 1453 | else | 1461 | else |
| 1454 | { | 1462 | { |
| 1455 | Memory::Write32(addr, cpu->ExtReg[(inst_cream->d+i)*2]); | 1463 | const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0]; |
| 1456 | Memory::Write32(addr + 4, cpu->ExtReg[(inst_cream->d+i)*2 + 1]); | 1464 | const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1]; |
| 1465 | |||
| 1466 | if (InBigEndianMode(cpu)) { | ||
| 1467 | WriteMemory32(cpu, addr + 0, word2); | ||
| 1468 | WriteMemory32(cpu, addr + 4, word1); | ||
| 1469 | } else { | ||
| 1470 | WriteMemory32(cpu, addr + 0, word1); | ||
| 1471 | WriteMemory32(cpu, addr + 4, word2); | ||
| 1472 | } | ||
| 1473 | |||
| 1457 | addr += 8; | 1474 | addr += 8; |
| 1458 | } | 1475 | } |
| 1459 | } | 1476 | } |
| 1460 | cpu->Reg[R13] = cpu->Reg[R13] - inst_cream->imm32; | 1477 | |
| 1478 | cpu->Reg[R13] -= inst_cream->imm32; | ||
| 1461 | } | 1479 | } |
| 1462 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1480 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| 1463 | INC_PC(sizeof(vpush_inst)); | 1481 | INC_PC(sizeof(vpush_inst)); |
| @@ -1516,13 +1534,22 @@ VSTM_INST: /* encoding 1 */ | |||
| 1516 | { | 1534 | { |
| 1517 | if (inst_cream->single) | 1535 | if (inst_cream->single) |
| 1518 | { | 1536 | { |
| 1519 | Memory::Write32(addr, cpu->ExtReg[inst_cream->d+i]); | 1537 | WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]); |
| 1520 | addr += 4; | 1538 | addr += 4; |
| 1521 | } | 1539 | } |
| 1522 | else | 1540 | else |
| 1523 | { | 1541 | { |
| 1524 | Memory::Write32(addr, cpu->ExtReg[(inst_cream->d+i)*2]); | 1542 | const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0]; |
| 1525 | Memory::Write32(addr + 4, cpu->ExtReg[(inst_cream->d+i)*2 + 1]); | 1543 | const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1]; |
| 1544 | |||
| 1545 | if (InBigEndianMode(cpu)) { | ||
| 1546 | WriteMemory32(cpu, addr + 0, word2); | ||
| 1547 | WriteMemory32(cpu, addr + 4, word1); | ||
| 1548 | } else { | ||
| 1549 | WriteMemory32(cpu, addr + 0, word1); | ||
| 1550 | WriteMemory32(cpu, addr + 4, word2); | ||
| 1551 | } | ||
| 1552 | |||
| 1526 | addr += 8; | 1553 | addr += 8; |
| 1527 | } | 1554 | } |
| 1528 | } | 1555 | } |
| @@ -1575,8 +1602,6 @@ VPOP_INST: | |||
| 1575 | if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { | 1602 | if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { |
| 1576 | CHECK_VFP_ENABLED; | 1603 | CHECK_VFP_ENABLED; |
| 1577 | 1604 | ||
| 1578 | unsigned int value1, value2; | ||
| 1579 | |||
| 1580 | vpop_inst *inst_cream = (vpop_inst *)inst_base->component; | 1605 | vpop_inst *inst_cream = (vpop_inst *)inst_base->component; |
| 1581 | 1606 | ||
| 1582 | addr = cpu->Reg[R13]; | 1607 | addr = cpu->Reg[R13]; |
| @@ -1585,20 +1610,26 @@ VPOP_INST: | |||
| 1585 | { | 1610 | { |
| 1586 | if (inst_cream->single) | 1611 | if (inst_cream->single) |
| 1587 | { | 1612 | { |
| 1588 | value1 = Memory::Read32(addr); | 1613 | cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr); |
| 1589 | cpu->ExtReg[inst_cream->d+i] = value1; | ||
| 1590 | addr += 4; | 1614 | addr += 4; |
| 1591 | } | 1615 | } |
| 1592 | else | 1616 | else |
| 1593 | { | 1617 | { |
| 1594 | value1 = Memory::Read32(addr); | 1618 | const u32 word1 = ReadMemory32(cpu, addr + 0); |
| 1595 | value2 = Memory::Read32(addr + 4); | 1619 | const u32 word2 = ReadMemory32(cpu, addr + 4); |
| 1596 | cpu->ExtReg[(inst_cream->d+i)*2] = value1; | 1620 | |
| 1597 | cpu->ExtReg[(inst_cream->d+i)*2 + 1] = value2; | 1621 | if (InBigEndianMode(cpu)) { |
| 1622 | cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; | ||
| 1623 | cpu->ExtReg[(inst_cream->d+i)*2+1] = word1; | ||
| 1624 | } else { | ||
| 1625 | cpu->ExtReg[(inst_cream->d+i)*2+0] = word1; | ||
| 1626 | cpu->ExtReg[(inst_cream->d+i)*2+1] = word2; | ||
| 1627 | } | ||
| 1628 | |||
| 1598 | addr += 8; | 1629 | addr += 8; |
| 1599 | } | 1630 | } |
| 1600 | } | 1631 | } |
| 1601 | cpu->Reg[R13] = cpu->Reg[R13] + inst_cream->imm32; | 1632 | cpu->Reg[R13] += inst_cream->imm32; |
| 1602 | } | 1633 | } |
| 1603 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1634 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| 1604 | INC_PC(sizeof(vpop_inst)); | 1635 | INC_PC(sizeof(vpop_inst)); |
| @@ -1653,16 +1684,20 @@ VLDR_INST: | |||
| 1653 | 1684 | ||
| 1654 | if (inst_cream->single) | 1685 | if (inst_cream->single) |
| 1655 | { | 1686 | { |
| 1656 | cpu->ExtReg[inst_cream->d] = Memory::Read32(addr); | 1687 | cpu->ExtReg[inst_cream->d] = ReadMemory32(cpu, addr); |
| 1657 | } | 1688 | } |
| 1658 | else | 1689 | else |
| 1659 | { | 1690 | { |
| 1660 | unsigned int word1, word2; | 1691 | const u32 word1 = ReadMemory32(cpu, addr + 0); |
| 1661 | word1 = Memory::Read32(addr); | 1692 | const u32 word2 = ReadMemory32(cpu, addr + 4); |
| 1662 | word2 = Memory::Read32(addr + 4); | 1693 | |
| 1663 | 1694 | if (InBigEndianMode(cpu)) { | |
| 1664 | cpu->ExtReg[inst_cream->d*2] = word1; | 1695 | cpu->ExtReg[inst_cream->d*2+0] = word2; |
| 1665 | cpu->ExtReg[inst_cream->d*2+1] = word2; | 1696 | cpu->ExtReg[inst_cream->d*2+1] = word1; |
| 1697 | } else { | ||
| 1698 | cpu->ExtReg[inst_cream->d*2+0] = word1; | ||
| 1699 | cpu->ExtReg[inst_cream->d*2+1] = word2; | ||
| 1700 | } | ||
| 1666 | } | 1701 | } |
| 1667 | } | 1702 | } |
| 1668 | cpu->Reg[15] += GET_INST_SIZE(cpu); | 1703 | cpu->Reg[15] += GET_INST_SIZE(cpu); |
| @@ -1722,13 +1757,22 @@ VLDM_INST: | |||
| 1722 | { | 1757 | { |
| 1723 | if (inst_cream->single) | 1758 | if (inst_cream->single) |
| 1724 | { | 1759 | { |
| 1725 | cpu->ExtReg[inst_cream->d+i] = Memory::Read32(addr); | 1760 | cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr); |
| 1726 | addr += 4; | 1761 | addr += 4; |
| 1727 | } | 1762 | } |
| 1728 | else | 1763 | else |
| 1729 | { | 1764 | { |
| 1730 | cpu->ExtReg[(inst_cream->d+i)*2] = Memory::Read32(addr); | 1765 | const u32 word1 = ReadMemory32(cpu, addr + 0); |
| 1731 | cpu->ExtReg[(inst_cream->d+i)*2 + 1] = Memory::Read32(addr + 4); | 1766 | const u32 word2 = ReadMemory32(cpu, addr + 4); |
| 1767 | |||
| 1768 | if (InBigEndianMode(cpu)) { | ||
| 1769 | cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; | ||
| 1770 | cpu->ExtReg[(inst_cream->d+i)*2+1] = word1; | ||
| 1771 | } else { | ||
| 1772 | cpu->ExtReg[(inst_cream->d+i)*2+0] = word1; | ||
| 1773 | cpu->ExtReg[(inst_cream->d+i)*2+1] = word2; | ||
| 1774 | } | ||
| 1775 | |||
| 1732 | addr += 8; | 1776 | addr += 8; |
| 1733 | } | 1777 | } |
| 1734 | } | 1778 | } |