summaryrefslogtreecommitdiff
path: root/src/core/arm/skyeye_common
diff options
context:
space:
mode:
authorGravatar Lioncash2015-03-11 16:10:14 -0400
committerGravatar Lioncash2015-03-17 15:13:32 -0400
commit9fdb311d6e2d636c4599ddc3d4cb9adad6cec540 (patch)
tree358501f8f2e31c7c27ee17c62996ef01e21354c7 /src/core/arm/skyeye_common
parentdyncom: Implement SETEND (diff)
downloadyuzu-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.h3
-rw-r--r--src/core/arm/skyeye_common/armmmu.h55
-rw-r--r--src/core/arm/skyeye_common/vfp/vfpinstr.cpp102
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);
356extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8); 355extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8);
357extern u32 ARMul_SignedSatQ(s32, u8, bool*); 356extern u32 ARMul_SignedSatQ(s32, u8, bool*);
358extern u32 ARMul_UnsignedSatQ(s32, u8, bool*); 357extern u32 ARMul_UnsignedSatQ(s32, u8, bool*);
358
359extern 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
24enum 27enum
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.
63inline 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
72inline 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
81inline 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.
92inline 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
99inline 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
106inline 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 }