mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	dyncom: Migrate exclusive memory access control into armstate
This commit is contained in:
		
							parent
							
								
									db4e99c186
								
							
						
					
					
						commit
						a507ea23c1
					
				
					 2 changed files with 35 additions and 50 deletions
				
			
		|  | @ -47,27 +47,6 @@ enum { | ||||||
| 
 | 
 | ||||||
| typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper); | typedef unsigned int (*shtop_fp_t)(ARMul_State* cpu, unsigned int sht_oper); | ||||||
| 
 | 
 | ||||||
| // Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag.
 |  | ||||||
| // This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to
 |  | ||||||
| // support LDR/STREXD.
 |  | ||||||
| static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8; |  | ||||||
| 
 |  | ||||||
| // Exclusive memory access
 |  | ||||||
| static int exclusive_detect(ARMul_State* state, u32 addr) { |  | ||||||
|     if(state->exclusive_tag == (addr & RESERVATION_GRANULE_MASK)) |  | ||||||
|         return 0; |  | ||||||
|     else |  | ||||||
|         return -1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void add_exclusive_addr(ARMul_State* state, u32 addr){ |  | ||||||
|     state->exclusive_tag = addr & RESERVATION_GRANULE_MASK; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void remove_exclusive(ARMul_State* state, u32 addr){ |  | ||||||
|     state->exclusive_tag = 0xFFFFFFFF; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int CondPassed(ARMul_State* cpu, unsigned int cond) { | static int CondPassed(ARMul_State* cpu, unsigned int cond) { | ||||||
|     const u32 NFLAG = cpu->NFlag; |     const u32 NFLAG = cpu->NFlag; | ||||||
|     const u32 ZFLAG = cpu->ZFlag; |     const u32 ZFLAG = cpu->ZFlag; | ||||||
|  | @ -4170,9 +4149,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||||
| 
 | 
 | ||||||
|     CLREX_INST: |     CLREX_INST: | ||||||
|     { |     { | ||||||
|         remove_exclusive(cpu, 0); |         cpu->UnsetExclusiveMemoryAddress(); | ||||||
|         cpu->exclusive_state = 0; |  | ||||||
| 
 |  | ||||||
|         cpu->Reg[15] += cpu->GetInstructionSize(); |         cpu->Reg[15] += cpu->GetInstructionSize(); | ||||||
|         INC_PC(sizeof(clrex_inst)); |         INC_PC(sizeof(clrex_inst)); | ||||||
|         FETCH_INST; |         FETCH_INST; | ||||||
|  | @ -4539,8 +4516,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||||
|             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||||||
|             unsigned int read_addr = RN; |             unsigned int read_addr = RN; | ||||||
| 
 | 
 | ||||||
|             add_exclusive_addr(cpu, read_addr); |             cpu->SetExclusiveMemoryAddress(read_addr); | ||||||
|             cpu->exclusive_state = 1; |  | ||||||
| 
 | 
 | ||||||
|             RD = cpu->ReadMemory32(read_addr); |             RD = cpu->ReadMemory32(read_addr); | ||||||
|             if (inst_cream->Rd == 15) { |             if (inst_cream->Rd == 15) { | ||||||
|  | @ -4559,8 +4535,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||||
|             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||||||
|             unsigned int read_addr = RN; |             unsigned int read_addr = RN; | ||||||
| 
 | 
 | ||||||
|             add_exclusive_addr(cpu, read_addr); |             cpu->SetExclusiveMemoryAddress(read_addr); | ||||||
|             cpu->exclusive_state = 1; |  | ||||||
| 
 | 
 | ||||||
|             RD = Memory::Read8(read_addr); |             RD = Memory::Read8(read_addr); | ||||||
|             if (inst_cream->Rd == 15) { |             if (inst_cream->Rd == 15) { | ||||||
|  | @ -4579,8 +4554,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||||
|             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||||||
|             unsigned int read_addr = RN; |             unsigned int read_addr = RN; | ||||||
| 
 | 
 | ||||||
|             add_exclusive_addr(cpu, read_addr); |             cpu->SetExclusiveMemoryAddress(read_addr); | ||||||
|             cpu->exclusive_state = 1; |  | ||||||
| 
 | 
 | ||||||
|             RD = cpu->ReadMemory16(read_addr); |             RD = cpu->ReadMemory16(read_addr); | ||||||
|             if (inst_cream->Rd == 15) { |             if (inst_cream->Rd == 15) { | ||||||
|  | @ -4599,8 +4573,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||||
|             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||||||
|             unsigned int read_addr = RN; |             unsigned int read_addr = RN; | ||||||
| 
 | 
 | ||||||
|             add_exclusive_addr(cpu, read_addr); |             cpu->SetExclusiveMemoryAddress(read_addr); | ||||||
|             cpu->exclusive_state = 1; |  | ||||||
| 
 | 
 | ||||||
|             RD  = cpu->ReadMemory32(read_addr); |             RD  = cpu->ReadMemory32(read_addr); | ||||||
|             RD2 = cpu->ReadMemory32(read_addr + 4); |             RD2 = cpu->ReadMemory32(read_addr + 4); | ||||||
|  | @ -6085,10 +6058,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||||
|             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||||||
|             unsigned int write_addr = cpu->Reg[inst_cream->Rn]; |             unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | ||||||
| 
 | 
 | ||||||
|             if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { |             if (cpu->IsExclusiveMemoryAccess(write_addr)) { | ||||||
|                 remove_exclusive(cpu, write_addr); |                 cpu->UnsetExclusiveMemoryAddress(); | ||||||
|                 cpu->exclusive_state = 0; |  | ||||||
| 
 |  | ||||||
|                 cpu->WriteMemory32(write_addr, RM); |                 cpu->WriteMemory32(write_addr, RM); | ||||||
|                 RD = 0; |                 RD = 0; | ||||||
|             } else { |             } else { | ||||||
|  | @ -6107,10 +6078,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||||
|             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||||||
|             unsigned int write_addr = cpu->Reg[inst_cream->Rn]; |             unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | ||||||
| 
 | 
 | ||||||
|             if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { |             if (cpu->IsExclusiveMemoryAccess(write_addr)) { | ||||||
|                 remove_exclusive(cpu, write_addr); |                 cpu->UnsetExclusiveMemoryAddress(); | ||||||
|                 cpu->exclusive_state = 0; |  | ||||||
| 
 |  | ||||||
|                 Memory::Write8(write_addr, cpu->Reg[inst_cream->Rm]); |                 Memory::Write8(write_addr, cpu->Reg[inst_cream->Rm]); | ||||||
|                 RD = 0; |                 RD = 0; | ||||||
|             } else { |             } else { | ||||||
|  | @ -6129,9 +6098,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||||
|             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||||||
|             unsigned int write_addr = cpu->Reg[inst_cream->Rn]; |             unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | ||||||
| 
 | 
 | ||||||
|             if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { |             if (cpu->IsExclusiveMemoryAccess(write_addr)) { | ||||||
|                 remove_exclusive(cpu, write_addr); |                 cpu->UnsetExclusiveMemoryAddress(); | ||||||
|                 cpu->exclusive_state = 0; |  | ||||||
| 
 | 
 | ||||||
|                 const u32 rt  = cpu->Reg[inst_cream->Rm + 0]; |                 const u32 rt  = cpu->Reg[inst_cream->Rm + 0]; | ||||||
|                 const u32 rt2 = cpu->Reg[inst_cream->Rm + 1]; |                 const u32 rt2 = cpu->Reg[inst_cream->Rm + 1]; | ||||||
|  | @ -6161,10 +6129,8 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) { | ||||||
|             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; |             generic_arm_inst* inst_cream = (generic_arm_inst*)inst_base->component; | ||||||
|             unsigned int write_addr = cpu->Reg[inst_cream->Rn]; |             unsigned int write_addr = cpu->Reg[inst_cream->Rn]; | ||||||
| 
 | 
 | ||||||
|             if ((exclusive_detect(cpu, write_addr) == 0) && (cpu->exclusive_state == 1)) { |             if (cpu->IsExclusiveMemoryAccess(write_addr)) { | ||||||
|                 remove_exclusive(cpu, write_addr); |                 cpu->UnsetExclusiveMemoryAddress(); | ||||||
|                 cpu->exclusive_state = 0; |  | ||||||
| 
 |  | ||||||
|                 cpu->WriteMemory16(write_addr, RM); |                 cpu->WriteMemory16(write_addr, RM); | ||||||
|                 RD = 0; |                 RD = 0; | ||||||
|             } else { |             } else { | ||||||
|  |  | ||||||
|  | @ -163,6 +163,19 @@ public: | ||||||
|     u32 ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const; |     u32 ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const; | ||||||
|     void WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2); |     void WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2); | ||||||
| 
 | 
 | ||||||
|  |     // Exclusive memory access functions
 | ||||||
|  |     bool IsExclusiveMemoryAccess(u32 address) const { | ||||||
|  |         return exclusive_state && exclusive_tag == (address & RESERVATION_GRANULE_MASK); | ||||||
|  |     } | ||||||
|  |     void SetExclusiveMemoryAddress(u32 address) { | ||||||
|  |         exclusive_tag = address & RESERVATION_GRANULE_MASK; | ||||||
|  |         exclusive_state = true; | ||||||
|  |     } | ||||||
|  |     void UnsetExclusiveMemoryAddress() { | ||||||
|  |         exclusive_tag = 0xFFFFFFFF; | ||||||
|  |         exclusive_state = false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     // Whether or not the given CPU is in big endian mode (E bit is set)
 |     // Whether or not the given CPU is in big endian mode (E bit is set)
 | ||||||
|     bool InBigEndianMode() const { |     bool InBigEndianMode() const { | ||||||
|         return (Cpsr & (1 << 9)) != 0; |         return (Cpsr & (1 << 9)) != 0; | ||||||
|  | @ -203,9 +216,6 @@ public: | ||||||
| 
 | 
 | ||||||
|     u32 Mode;          // The current mode
 |     u32 Mode;          // The current mode
 | ||||||
|     u32 Bank;          // The current register bank
 |     u32 Bank;          // The current register bank
 | ||||||
|     u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode
 |  | ||||||
|     u32 exclusive_state; |  | ||||||
|     u32 exclusive_result; |  | ||||||
| 
 | 
 | ||||||
|     u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed
 |     u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed
 | ||||||
|     unsigned int shifter_carry_out; |     unsigned int shifter_carry_out; | ||||||
|  | @ -230,4 +240,13 @@ public: | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     void ResetMPCoreCP15Registers(); |     void ResetMPCoreCP15Registers(); | ||||||
|  | 
 | ||||||
|  |     // Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag.
 | ||||||
|  |     // This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to
 | ||||||
|  |     // support LDR/STREXD.
 | ||||||
|  |     static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8; | ||||||
|  | 
 | ||||||
|  |     u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode
 | ||||||
|  |     u32 exclusive_result; | ||||||
|  |     bool exclusive_state; | ||||||
| }; | }; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue