summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Lioncash2015-07-27 21:40:48 -0400
committerGravatar Lioncash2015-07-27 22:06:59 -0400
commita507ea23c157abfc490cbb0c85154b23c4b079b9 (patch)
tree910750e7ce0cca0da06820b992175d3bf12ad872
parentdyncom: Remove duplicated typedef and extern (diff)
downloadyuzu-a507ea23c157abfc490cbb0c85154b23c4b079b9.tar.gz
yuzu-a507ea23c157abfc490cbb0c85154b23c4b079b9.tar.xz
yuzu-a507ea23c157abfc490cbb0c85154b23c4b079b9.zip
dyncom: Migrate exclusive memory access control into armstate
Diffstat (limited to '')
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp60
-rw-r--r--src/core/arm/skyeye_common/armstate.h25
2 files changed, 35 insertions, 50 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index e855a4487..69228180e 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -47,27 +47,6 @@ enum {
47 47
48typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper); 48typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper);
49 49
50// Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag.
51// This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to
52// support LDR/STREXD.
53static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8;
54
55// Exclusive memory access
56static int exclusive_detect(ARMul_State* state, u32 addr) {
57 if(state->exclusive_tag == (addr & RESERVATION_GRANULE_MASK))
58 return 0;
59 else
60 return -1;
61}
62
63static void add_exclusive_addr(ARMul_State* state, u32 addr){
64 state->exclusive_tag = addr & RESERVATION_GRANULE_MASK;
65}
66
67static void remove_exclusive(ARMul_State* state, u32 addr){
68 state->exclusive_tag = 0xFFFFFFFF;
69}
70
71static int CondPassed(ARMul_State* cpu, unsigned int cond) { 50static int CondPassed(ARMul_State* cpu, unsigned int cond) {
72 const u32 NFLAG = cpu->NFlag; 51 const u32 NFLAG = cpu->NFlag;
73 const u32 ZFLAG = cpu->ZFlag; 52 const u32 ZFLAG = cpu->ZFlag;
@@ -4170,9 +4149,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
4170 4149
4171 CLREX_INST: 4150 CLREX_INST:
4172 { 4151 {
4173 remove_exclusive(cpu, 0); 4152 cpu->UnsetExclusiveMemoryAddress();
4174 cpu->exclusive_state = 0;
4175
4176 cpu->Reg[15] += cpu->GetInstructionSize(); 4153 cpu->Reg[15] += cpu->GetInstructionSize();
4177 INC_PC(sizeof(clrex_inst)); 4154 INC_PC(sizeof(clrex_inst));
4178 FETCH_INST; 4155 FETCH_INST;
@@ -4539,8 +4516,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
4539 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 4516 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4540 unsigned int read_addr = RN; 4517 unsigned int read_addr = RN;
4541 4518
4542 add_exclusive_addr(cpu, read_addr); 4519 cpu->SetExclusiveMemoryAddress(read_addr);
4543 cpu->exclusive_state = 1;
4544 4520
4545 RD = cpu->ReadMemory32(read_addr); 4521 RD = cpu->ReadMemory32(read_addr);
4546 if (inst_cream->Rd == 15) { 4522 if (inst_cream->Rd == 15) {
@@ -4559,8 +4535,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
4559 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 4535 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4560 unsigned int read_addr = RN; 4536 unsigned int read_addr = RN;
4561 4537
4562 add_exclusive_addr(cpu, read_addr); 4538 cpu->SetExclusiveMemoryAddress(read_addr);
4563 cpu->exclusive_state = 1;
4564 4539
4565 RD = Memory::Read8(read_addr); 4540 RD = Memory::Read8(read_addr);
4566 if (inst_cream->Rd == 15) { 4541 if (inst_cream->Rd == 15) {
@@ -4579,8 +4554,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
4579 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 4554 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4580 unsigned int read_addr = RN; 4555 unsigned int read_addr = RN;
4581 4556
4582 add_exclusive_addr(cpu, read_addr); 4557 cpu->SetExclusiveMemoryAddress(read_addr);
4583 cpu->exclusive_state = 1;
4584 4558
4585 RD = cpu->ReadMemory16(read_addr); 4559 RD = cpu->ReadMemory16(read_addr);
4586 if (inst_cream->Rd == 15) { 4560 if (inst_cream->Rd == 15) {
@@ -4599,8 +4573,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
4599 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 4573 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
4600 unsigned int read_addr = RN; 4574 unsigned int read_addr = RN;
4601 4575
4602 add_exclusive_addr(cpu, read_addr); 4576 cpu->SetExclusiveMemoryAddress(read_addr);
4603 cpu->exclusive_state = 1;
4604 4577
4605 RD = cpu->ReadMemory32(read_addr); 4578 RD = cpu->ReadMemory32(read_addr);
4606 RD2 = cpu->ReadMemory32(read_addr + 4); 4579 RD2 = cpu->ReadMemory32(read_addr + 4);
@@ -6085,10 +6058,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
6085 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 6058 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
6086 unsigned int write_addr = cpu->Reg[inst_cream->Rn]; 6059 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
6087 6060
6088 if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { 6061 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
6089 remove_exclusive(cpu, write_addr); 6062 cpu->UnsetExclusiveMemoryAddress();
6090 cpu->exclusive_state = 0;
6091
6092 cpu->WriteMemory32(write_addr, RM); 6063 cpu->WriteMemory32(write_addr, RM);
6093 RD = 0; 6064 RD = 0;
6094 } else { 6065 } else {
@@ -6107,10 +6078,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
6107 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 6078 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
6108 unsigned int write_addr = cpu->Reg[inst_cream->Rn]; 6079 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
6109 6080
6110 if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { 6081 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
6111 remove_exclusive(cpu, write_addr); 6082 cpu->UnsetExclusiveMemoryAddress();
6112 cpu->exclusive_state = 0;
6113
6114 Memory::Write8(write_addr, cpu->Reg[inst_cream->Rm]); 6083 Memory::Write8(write_addr, cpu->Reg[inst_cream->Rm]);
6115 RD = 0; 6084 RD = 0;
6116 } else { 6085 } else {
@@ -6129,9 +6098,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
6129 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 6098 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
6130 unsigned int write_addr = cpu->Reg[inst_cream->Rn]; 6099 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
6131 6100
6132 if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { 6101 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
6133 remove_exclusive(cpu, write_addr); 6102 cpu->UnsetExclusiveMemoryAddress();
6134 cpu->exclusive_state = 0;
6135 6103
6136 const u32 rt = cpu->Reg[inst_cream->Rm + 0]; 6104 const u32 rt = cpu->Reg[inst_cream->Rm + 0];
6137 const u32 rt2 = cpu->Reg[inst_cream->Rm + 1]; 6105 const u32 rt2 = cpu->Reg[inst_cream->Rm + 1];
@@ -6161,10 +6129,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
6161 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; 6129 generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component;
6162 unsigned int write_addr = cpu->Reg[inst_cream->Rn]; 6130 unsigned int write_addr = cpu->Reg[inst_cream->Rn];
6163 6131
6164 if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { 6132 if (cpu->IsExclusiveMemoryAccess(write_addr)) {
6165 remove_exclusive(cpu, write_addr); 6133 cpu->UnsetExclusiveMemoryAddress();
6166 cpu->exclusive_state = 0;
6167
6168 cpu->WriteMemory16(write_addr, RM); 6134 cpu->WriteMemory16(write_addr, RM);
6169 RD = 0; 6135 RD = 0;
6170 } else { 6136 } else {
diff --git a/src/core/arm/skyeye_common/armstate.h b/src/core/arm/skyeye_common/armstate.h
index 88c1dab9d..b364e2621 100644
--- a/src/core/arm/skyeye_common/armstate.h
+++ b/src/core/arm/skyeye_common/armstate.h
@@ -163,6 +163,19 @@ public:
163 u32 ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const; 163 u32 ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const;
164 void WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2); 164 void WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2);
165 165
166 // Exclusive memory access functions
167 bool IsExclusiveMemoryAccess(u32 address) const {
168 return exclusive_state && exclusive_tag == (address & RESERVATION_GRANULE_MASK);
169 }
170 void SetExclusiveMemoryAddress(u32 address) {
171 exclusive_tag = address & RESERVATION_GRANULE_MASK;
172 exclusive_state = true;
173 }
174 void UnsetExclusiveMemoryAddress() {
175 exclusive_tag = 0xFFFFFFFF;
176 exclusive_state = false;
177 }
178
166 // Whether or not the given CPU is in big endian mode (E bit is set) 179 // Whether or not the given CPU is in big endian mode (E bit is set)
167 bool InBigEndianMode() const { 180 bool InBigEndianMode() const {
168 return (Cpsr & (1 << 9)) != 0; 181 return (Cpsr & (1 << 9)) != 0;
@@ -203,9 +216,6 @@ public:
203 216
204 u32 Mode; // The current mode 217 u32 Mode; // The current mode
205 u32 Bank; // The current register bank 218 u32 Bank; // The current register bank
206 u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode
207 u32 exclusive_state;
208 u32 exclusive_result;
209 219
210 u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed 220 u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed
211 unsigned int shifter_carry_out; 221 unsigned int shifter_carry_out;
@@ -230,4 +240,13 @@ public:
230 240
231private: 241private:
232 void ResetMPCoreCP15Registers(); 242 void ResetMPCoreCP15Registers();
243
244 // Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag.
245 // This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to
246 // support LDR/STREXD.
247 static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8;
248
249 u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode
250 u32 exclusive_result;
251 bool exclusive_state;
233}; 252};