diff options
| author | 2015-07-27 21:40:48 -0400 | |
|---|---|---|
| committer | 2015-07-27 22:06:59 -0400 | |
| commit | a507ea23c157abfc490cbb0c85154b23c4b079b9 (patch) | |
| tree | 910750e7ce0cca0da06820b992175d3bf12ad872 | |
| parent | dyncom: Remove duplicated typedef and extern (diff) | |
| download | yuzu-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.cpp | 60 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/armstate.h | 25 |
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 | ||
| 48 | typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper); | 48 | typedef 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. | ||
| 53 | static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8; | ||
| 54 | |||
| 55 | // Exclusive memory access | ||
| 56 | static 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 | |||
| 63 | static void add_exclusive_addr(ARMul_State* state, u32 addr){ | ||
| 64 | state->exclusive_tag = addr & RESERVATION_GRANULE_MASK; | ||
| 65 | } | ||
| 66 | |||
| 67 | static void remove_exclusive(ARMul_State* state, u32 addr){ | ||
| 68 | state->exclusive_tag = 0xFFFFFFFF; | ||
| 69 | } | ||
| 70 | |||
| 71 | static int CondPassed(ARMul_State* cpu, unsigned int cond) { | 50 | static 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 | ||
| 231 | private: | 241 | private: |
| 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 | }; |