mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	
						commit
						1981aa3d7e
					
				
					 7 changed files with 239 additions and 82 deletions
				
			
		|  | @ -1075,6 +1075,10 @@ typedef struct _swp_inst { | ||||||
|     unsigned int Rm; |     unsigned int Rm; | ||||||
| } swp_inst; | } swp_inst; | ||||||
| 
 | 
 | ||||||
|  | typedef struct setend_inst { | ||||||
|  |     unsigned int set_bigend; | ||||||
|  | } setend_inst; | ||||||
|  | 
 | ||||||
| typedef struct _b_2_thumb { | typedef struct _b_2_thumb { | ||||||
|     unsigned int imm; |     unsigned int imm; | ||||||
| }b_2_thumb; | }b_2_thumb; | ||||||
|  | @ -2283,7 +2287,20 @@ static ARM_INST_PTR INTERPRETER_TRANSLATE(sel)(unsigned int inst, int index) | ||||||
|     return inst_base; |     return inst_base; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index)    { UNIMPLEMENTED_INSTRUCTION("SETEND"); } | static ARM_INST_PTR INTERPRETER_TRANSLATE(setend)(unsigned int inst, int index) | ||||||
|  | { | ||||||
|  |     arm_inst* const inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(setend_inst)); | ||||||
|  |     setend_inst* const inst_cream = (setend_inst*)inst_base->component; | ||||||
|  | 
 | ||||||
|  |     inst_base->cond     = AL; | ||||||
|  |     inst_base->idx      = index; | ||||||
|  |     inst_base->br       = NON_BRANCH; | ||||||
|  |     inst_base->load_r15 = 0; | ||||||
|  | 
 | ||||||
|  |     inst_cream->set_bigend = BIT(inst, 9); | ||||||
|  | 
 | ||||||
|  |     return inst_base; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index) | static ARM_INST_PTR INTERPRETER_TRANSLATE(shadd8)(unsigned int inst, int index) | ||||||
| { | { | ||||||
|  | @ -4345,30 +4362,30 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|             if (BIT(inst, 22) && !BIT(inst, 15)) { |             if (BIT(inst, 22) && !BIT(inst, 15)) { | ||||||
|                 for (int i = 0; i < 13; i++) { |                 for (int i = 0; i < 13; i++) { | ||||||
|                     if(BIT(inst, i)) { |                     if(BIT(inst, i)) { | ||||||
|                         cpu->Reg[i] = Memory::Read32(addr); |                         cpu->Reg[i] = ReadMemory32(cpu, addr); | ||||||
|                         addr += 4; |                         addr += 4; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 if (BIT(inst, 13)) { |                 if (BIT(inst, 13)) { | ||||||
|                     if (cpu->Mode == USER32MODE)  |                     if (cpu->Mode == USER32MODE)  | ||||||
|                         cpu->Reg[13] = Memory::Read32(addr); |                         cpu->Reg[13] = ReadMemory32(cpu, addr); | ||||||
|                     else |                     else | ||||||
|                         cpu->Reg_usr[0] = Memory::Read32(addr); |                         cpu->Reg_usr[0] = ReadMemory32(cpu, addr); | ||||||
| 
 | 
 | ||||||
|                     addr += 4; |                     addr += 4; | ||||||
|                 } |                 } | ||||||
|                 if (BIT(inst, 14)) { |                 if (BIT(inst, 14)) { | ||||||
|                     if (cpu->Mode == USER32MODE)  |                     if (cpu->Mode == USER32MODE)  | ||||||
|                         cpu->Reg[14] = Memory::Read32(addr); |                         cpu->Reg[14] = ReadMemory32(cpu, addr); | ||||||
|                     else |                     else | ||||||
|                         cpu->Reg_usr[1] = Memory::Read32(addr); |                         cpu->Reg_usr[1] = ReadMemory32(cpu, addr); | ||||||
| 
 | 
 | ||||||
|                     addr += 4; |                     addr += 4; | ||||||
|                 } |                 } | ||||||
|             } else if (!BIT(inst, 22)) { |             } else if (!BIT(inst, 22)) { | ||||||
|                 for(int i = 0; i < 16; i++ ){ |                 for(int i = 0; i < 16; i++ ){ | ||||||
|                     if(BIT(inst, i)){ |                     if(BIT(inst, i)){ | ||||||
|                         unsigned int ret = Memory::Read32(addr); |                         unsigned int ret = ReadMemory32(cpu, addr); | ||||||
| 
 | 
 | ||||||
|                         // For armv5t, should enter thumb when bits[0] is non-zero.
 |                         // For armv5t, should enter thumb when bits[0] is non-zero.
 | ||||||
|                         if(i == 15){ |                         if(i == 15){ | ||||||
|  | @ -4383,7 +4400,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|             } else if (BIT(inst, 22) && BIT(inst, 15)) { |             } else if (BIT(inst, 22) && BIT(inst, 15)) { | ||||||
|                 for(int i = 0; i < 15; i++ ){ |                 for(int i = 0; i < 15; i++ ){ | ||||||
|                     if(BIT(inst, i)){ |                     if(BIT(inst, i)){ | ||||||
|                         cpu->Reg[i] = Memory::Read32(addr); |                         cpu->Reg[i] = ReadMemory32(cpu, addr); | ||||||
|                         addr += 4; |                         addr += 4; | ||||||
|                      } |                      } | ||||||
|                  } |                  } | ||||||
|  | @ -4394,7 +4411,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|                     LOAD_NZCVT; |                     LOAD_NZCVT; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 cpu->Reg[15] = Memory::Read32(addr); |                 cpu->Reg[15] = ReadMemory32(cpu, addr); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             if (BIT(inst, 15)) { |             if (BIT(inst, 15)) { | ||||||
|  | @ -4428,20 +4445,18 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|     LDR_INST: |     LDR_INST: | ||||||
|     { |     { | ||||||
|         ldst_inst *inst_cream = (ldst_inst *)inst_base->component; |         ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | ||||||
|         //if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
 |         inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); | ||||||
|             inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); |  | ||||||
| 
 | 
 | ||||||
|             unsigned int value = Memory::Read32(addr); |         unsigned int value = ReadMemory32(cpu, addr); | ||||||
|             cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; |         cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; | ||||||
| 
 | 
 | ||||||
|             if (BITS(inst_cream->inst, 12, 15) == 15) { |         if (BITS(inst_cream->inst, 12, 15) == 15) { | ||||||
|                 // For armv5t, should enter thumb when bits[0] is non-zero.
 |             // For armv5t, should enter thumb when bits[0] is non-zero.
 | ||||||
|                 cpu->TFlag = value & 0x1; |             cpu->TFlag = value & 0x1; | ||||||
|                 cpu->Reg[15] &= 0xFFFFFFFE; |             cpu->Reg[15] &= 0xFFFFFFFE; | ||||||
|                 INC_PC(sizeof(ldst_inst)); |             INC_PC(sizeof(ldst_inst)); | ||||||
|                 goto DISPATCH; |             goto DISPATCH; | ||||||
|             } |         } | ||||||
|         //}
 |  | ||||||
| 
 | 
 | ||||||
|         cpu->Reg[15] += GET_INST_SIZE(cpu); |         cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||||
|         INC_PC(sizeof(ldst_inst)); |         INC_PC(sizeof(ldst_inst)); | ||||||
|  | @ -4454,7 +4469,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|             ldst_inst *inst_cream = (ldst_inst *)inst_base->component; |             ldst_inst *inst_cream = (ldst_inst *)inst_base->component; | ||||||
|             inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); |             inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); | ||||||
| 
 | 
 | ||||||
|             unsigned int value = Memory::Read32(addr); |             unsigned int value = ReadMemory32(cpu, addr); | ||||||
|             cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; |             cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; | ||||||
| 
 | 
 | ||||||
|             if (BITS(inst_cream->inst, 12, 15) == 15) { |             if (BITS(inst_cream->inst, 12, 15) == 15) { | ||||||
|  | @ -4537,8 +4552,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|             // Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 || addr[2] == 0)
 |             // Should check if RD is even-numbered, Rd != 14, addr[0:1] == 0, (CP15_reg1_U == 1 || addr[2] == 0)
 | ||||||
|             inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); |             inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); | ||||||
| 
 | 
 | ||||||
|             cpu->Reg[BITS(inst_cream->inst, 12, 15)] = Memory::Read32(addr); |             // The 3DS doesn't have LPAE (Large Physical Access Extension), so it
 | ||||||
|             cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = Memory::Read32(addr + 4); |             // wouldn't do this as a single read.
 | ||||||
|  |             cpu->Reg[BITS(inst_cream->inst, 12, 15) + 0] = ReadMemory32(cpu, addr); | ||||||
|  |             cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1] = ReadMemory32(cpu, addr + 4); | ||||||
| 
 | 
 | ||||||
|             // No dispatch since this operation should not modify R15
 |             // No dispatch since this operation should not modify R15
 | ||||||
|         } |         } | ||||||
|  | @ -4557,7 +4574,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|             add_exclusive_addr(cpu, read_addr); |             add_exclusive_addr(cpu, read_addr); | ||||||
|             cpu->exclusive_state = 1; |             cpu->exclusive_state = 1; | ||||||
| 
 | 
 | ||||||
|             RD = Memory::Read32(read_addr); |             RD = ReadMemory32(cpu, read_addr); | ||||||
|             if (inst_cream->Rd == 15) { |             if (inst_cream->Rd == 15) { | ||||||
|                 INC_PC(sizeof(generic_arm_inst)); |                 INC_PC(sizeof(generic_arm_inst)); | ||||||
|                 goto DISPATCH; |                 goto DISPATCH; | ||||||
|  | @ -4597,7 +4614,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|             add_exclusive_addr(cpu, read_addr); |             add_exclusive_addr(cpu, read_addr); | ||||||
|             cpu->exclusive_state = 1; |             cpu->exclusive_state = 1; | ||||||
| 
 | 
 | ||||||
|             RD = Memory::Read16(read_addr); |             RD = ReadMemory16(cpu, read_addr); | ||||||
|             if (inst_cream->Rd == 15) { |             if (inst_cream->Rd == 15) { | ||||||
|                 INC_PC(sizeof(generic_arm_inst)); |                 INC_PC(sizeof(generic_arm_inst)); | ||||||
|                 goto DISPATCH; |                 goto DISPATCH; | ||||||
|  | @ -4617,8 +4634,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|             add_exclusive_addr(cpu, read_addr); |             add_exclusive_addr(cpu, read_addr); | ||||||
|             cpu->exclusive_state = 1; |             cpu->exclusive_state = 1; | ||||||
| 
 | 
 | ||||||
|             RD = Memory::Read32(read_addr); |             RD  = ReadMemory32(cpu, read_addr); | ||||||
|             RD2 = Memory::Read32(read_addr + 4); |             RD2 = ReadMemory32(cpu, read_addr + 4); | ||||||
| 
 | 
 | ||||||
|             if (inst_cream->Rd == 15) { |             if (inst_cream->Rd == 15) { | ||||||
|                 INC_PC(sizeof(generic_arm_inst)); |                 INC_PC(sizeof(generic_arm_inst)); | ||||||
|  | @ -4635,7 +4652,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|         if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |         if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | ||||||
|             ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |             ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||||||
|             inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); |             inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); | ||||||
|             cpu->Reg[BITS(inst_cream->inst, 12, 15)] = Memory::Read16(addr); | 
 | ||||||
|  |             cpu->Reg[BITS(inst_cream->inst, 12, 15)] = ReadMemory16(cpu, addr); | ||||||
|             if (BITS(inst_cream->inst, 12, 15) == 15) { |             if (BITS(inst_cream->inst, 12, 15) == 15) { | ||||||
|                 INC_PC(sizeof(ldst_inst)); |                 INC_PC(sizeof(ldst_inst)); | ||||||
|                 goto DISPATCH; |                 goto DISPATCH; | ||||||
|  | @ -4671,7 +4689,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|         if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |         if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { | ||||||
|             ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |             ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||||||
|             inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); |             inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); | ||||||
|             unsigned int value = Memory::Read16(addr); | 
 | ||||||
|  |             unsigned int value = ReadMemory16(cpu, addr); | ||||||
|             if (BIT(value, 15)) { |             if (BIT(value, 15)) { | ||||||
|                 value |= 0xffff0000; |                 value |= 0xffff0000; | ||||||
|             } |             } | ||||||
|  | @ -4692,7 +4711,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|             ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |             ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||||||
|             inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); |             inst_cream->get_addr(cpu, inst_cream->inst, addr, 1); | ||||||
| 
 | 
 | ||||||
|             unsigned int value = Memory::Read32(addr); |             unsigned int value = ReadMemory32(cpu, addr); | ||||||
|             cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; |             cpu->Reg[BITS(inst_cream->inst, 12, 15)] = value; | ||||||
| 
 | 
 | ||||||
|             if (BITS(inst_cream->inst, 12, 15) == 15) { |             if (BITS(inst_cream->inst, 12, 15) == 15) { | ||||||
|  | @ -5521,6 +5540,23 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     SETEND_INST: |     SETEND_INST: | ||||||
|  |     { | ||||||
|  |         // SETEND is unconditional
 | ||||||
|  |         setend_inst* const inst_cream = (setend_inst*)inst_base->component; | ||||||
|  |         const bool big_endian = (inst_cream->set_bigend == 1); | ||||||
|  | 
 | ||||||
|  |         if (big_endian) | ||||||
|  |             cpu->Cpsr |= (1 << 9); | ||||||
|  |         else | ||||||
|  |             cpu->Cpsr &= ~(1 << 9); | ||||||
|  | 
 | ||||||
|  |         LOG_WARNING(Core_ARM11, "SETEND %s executed", big_endian ? "BE" : "LE"); | ||||||
|  | 
 | ||||||
|  |         cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||||
|  |         INC_PC(sizeof(setend_inst)); | ||||||
|  |         FETCH_INST; | ||||||
|  |         GOTO_NEXT_INST; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     SHADD8_INST: |     SHADD8_INST: | ||||||
|     SHADD16_INST: |     SHADD16_INST: | ||||||
|  | @ -5976,36 +6012,36 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|             if (BIT(inst_cream->inst, 22) == 1) { |             if (BIT(inst_cream->inst, 22) == 1) { | ||||||
|                 for (int i = 0; i < 13; i++) { |                 for (int i = 0; i < 13; i++) { | ||||||
|                     if (BIT(inst_cream->inst, i)) { |                     if (BIT(inst_cream->inst, i)) { | ||||||
|                         Memory::Write32(addr, cpu->Reg[i]); |                         WriteMemory32(cpu, addr, cpu->Reg[i]); | ||||||
|                         addr += 4; |                         addr += 4; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 if (BIT(inst_cream->inst, 13)) { |                 if (BIT(inst_cream->inst, 13)) { | ||||||
|                     if (cpu->Mode == USER32MODE) |                     if (cpu->Mode == USER32MODE) | ||||||
|                         Memory::Write32(addr, cpu->Reg[13]); |                         WriteMemory32(cpu, addr, cpu->Reg[13]); | ||||||
|                     else |                     else | ||||||
|                         Memory::Write32(addr, cpu->Reg_usr[0]); |                         WriteMemory32(cpu, addr, cpu->Reg_usr[0]); | ||||||
| 
 | 
 | ||||||
|                     addr += 4; |                     addr += 4; | ||||||
|                 } |                 } | ||||||
|                 if (BIT(inst_cream->inst, 14)) { |                 if (BIT(inst_cream->inst, 14)) { | ||||||
|                     if (cpu->Mode == USER32MODE) |                     if (cpu->Mode == USER32MODE) | ||||||
|                         Memory::Write32(addr, cpu->Reg[14]); |                         WriteMemory32(cpu, addr, cpu->Reg[14]); | ||||||
|                     else |                     else | ||||||
|                         Memory::Write32(addr, cpu->Reg_usr[1]); |                         WriteMemory32(cpu, addr, cpu->Reg_usr[1]); | ||||||
| 
 | 
 | ||||||
|                     addr += 4; |                     addr += 4; | ||||||
|                 } |                 } | ||||||
|                 if (BIT(inst_cream->inst, 15)) { |                 if (BIT(inst_cream->inst, 15)) { | ||||||
|                     Memory::Write32(addr, cpu->Reg_usr[1] + 8); |                     WriteMemory32(cpu, addr, cpu->Reg_usr[1] + 8); | ||||||
|                 } |                 } | ||||||
|             } else { |             } else { | ||||||
|                 for (int i = 0; i < 15; i++) { |                 for (int i = 0; i < 15; i++) { | ||||||
|                     if (BIT(inst_cream->inst, i)) { |                     if (BIT(inst_cream->inst, i)) { | ||||||
|                         if (i == Rn) |                         if (i == Rn) | ||||||
|                             Memory::Write32(addr, old_RN); |                             WriteMemory32(cpu, addr, old_RN); | ||||||
|                         else |                         else | ||||||
|                             Memory::Write32(addr, cpu->Reg[i]); |                             WriteMemory32(cpu, addr, cpu->Reg[i]); | ||||||
| 
 | 
 | ||||||
|                         addr += 4; |                         addr += 4; | ||||||
|                     } |                     } | ||||||
|  | @ -6013,7 +6049,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
| 
 | 
 | ||||||
|                 // Check PC reg
 |                 // Check PC reg
 | ||||||
|                 if (BIT(inst_cream->inst, 15)) |                 if (BIT(inst_cream->inst, 15)) | ||||||
|                     Memory::Write32(addr, cpu->Reg_usr[1] + 8); |                     WriteMemory32(cpu, addr, cpu->Reg_usr[1] + 8); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         cpu->Reg[15] += GET_INST_SIZE(cpu); |         cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||||
|  | @ -6046,7 +6082,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|             inst_cream->get_addr(cpu, inst_cream->inst, addr, 0); |             inst_cream->get_addr(cpu, inst_cream->inst, addr, 0); | ||||||
| 
 | 
 | ||||||
|             unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; |             unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; | ||||||
|             Memory::Write32(addr, value); |             WriteMemory32(cpu, addr, value); | ||||||
|         } |         } | ||||||
|         cpu->Reg[15] += GET_INST_SIZE(cpu); |         cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||||
|         INC_PC(sizeof(ldst_inst)); |         INC_PC(sizeof(ldst_inst)); | ||||||
|  | @ -6109,10 +6145,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|             ldst_inst* inst_cream = (ldst_inst*)inst_base->component; |             ldst_inst* inst_cream = (ldst_inst*)inst_base->component; | ||||||
|             inst_cream->get_addr(cpu, inst_cream->inst, addr, 0); |             inst_cream->get_addr(cpu, inst_cream->inst, addr, 0); | ||||||
| 
 | 
 | ||||||
|             unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; |             // The 3DS doesn't have the Large Physical Access Extension (LPAE)
 | ||||||
|             Memory::Write32(addr, value); |             // so STRD wouldn't store these as a single write.
 | ||||||
|             value = cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]; |             WriteMemory32(cpu, addr + 0, cpu->Reg[BITS(inst_cream->inst, 12, 15)]); | ||||||
|             Memory::Write32(addr + 4, value); |             WriteMemory32(cpu, addr + 4, cpu->Reg[BITS(inst_cream->inst, 12, 15) + 1]); | ||||||
|         } |         } | ||||||
|         cpu->Reg[15] += GET_INST_SIZE(cpu); |         cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||||
|         INC_PC(sizeof(ldst_inst)); |         INC_PC(sizeof(ldst_inst)); | ||||||
|  | @ -6129,7 +6165,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|                 remove_exclusive(cpu, write_addr); |                 remove_exclusive(cpu, write_addr); | ||||||
|                 cpu->exclusive_state = 0; |                 cpu->exclusive_state = 0; | ||||||
| 
 | 
 | ||||||
|                 Memory::Write32(write_addr, cpu->Reg[inst_cream->Rm]); |                 WriteMemory32(cpu, write_addr, RM); | ||||||
|                 RD = 0; |                 RD = 0; | ||||||
|             } else { |             } else { | ||||||
|                 // Failed to write due to mutex access
 |                 // Failed to write due to mutex access
 | ||||||
|  | @ -6173,8 +6209,16 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|                 remove_exclusive(cpu, write_addr); |                 remove_exclusive(cpu, write_addr); | ||||||
|                 cpu->exclusive_state = 0; |                 cpu->exclusive_state = 0; | ||||||
| 
 | 
 | ||||||
|                 Memory::Write32(write_addr, cpu->Reg[inst_cream->Rm]); |                 const u32 rt  = cpu->Reg[inst_cream->Rm + 0]; | ||||||
|                 Memory::Write32(write_addr + 4, cpu->Reg[inst_cream->Rm + 1]); |                 const u32 rt2 = cpu->Reg[inst_cream->Rm + 1]; | ||||||
|  |                 u64 value; | ||||||
|  | 
 | ||||||
|  |                 if (InBigEndianMode(cpu)) | ||||||
|  |                     value = (((u64)rt << 32) | rt2); | ||||||
|  |                 else | ||||||
|  |                     value = (((u64)rt2 << 32) | rt); | ||||||
|  | 
 | ||||||
|  |                 WriteMemory64(cpu, write_addr, value); | ||||||
|                 RD = 0; |                 RD = 0; | ||||||
|             } |             } | ||||||
|             else { |             else { | ||||||
|  | @ -6197,7 +6241,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|                 remove_exclusive(cpu, write_addr); |                 remove_exclusive(cpu, write_addr); | ||||||
|                 cpu->exclusive_state = 0; |                 cpu->exclusive_state = 0; | ||||||
| 
 | 
 | ||||||
|                 Memory::Write16(write_addr, cpu->Reg[inst_cream->Rm]); |                 WriteMemory16(cpu, write_addr, RM); | ||||||
|                 RD = 0; |                 RD = 0; | ||||||
|             } else { |             } else { | ||||||
|                 // Failed to write due to mutex access
 |                 // Failed to write due to mutex access
 | ||||||
|  | @ -6216,7 +6260,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|             inst_cream->get_addr(cpu, inst_cream->inst, addr, 0); |             inst_cream->get_addr(cpu, inst_cream->inst, addr, 0); | ||||||
| 
 | 
 | ||||||
|             unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff; |             unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)] & 0xffff; | ||||||
|             Memory::Write16(addr, value); |             WriteMemory16(cpu, addr, value); | ||||||
|         } |         } | ||||||
|         cpu->Reg[15] += GET_INST_SIZE(cpu); |         cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||||
|         INC_PC(sizeof(ldst_inst)); |         INC_PC(sizeof(ldst_inst)); | ||||||
|  | @ -6230,7 +6274,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|             inst_cream->get_addr(cpu, inst_cream->inst, addr, 0); |             inst_cream->get_addr(cpu, inst_cream->inst, addr, 0); | ||||||
| 
 | 
 | ||||||
|             unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; |             unsigned int value = cpu->Reg[BITS(inst_cream->inst, 12, 15)]; | ||||||
|             Memory::Write32(addr, value); |             WriteMemory32(cpu, addr, value); | ||||||
|         } |         } | ||||||
|         cpu->Reg[15] += GET_INST_SIZE(cpu); |         cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||||
|         INC_PC(sizeof(ldst_inst)); |         INC_PC(sizeof(ldst_inst)); | ||||||
|  | @ -6289,8 +6333,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | ||||||
|             swp_inst* inst_cream = (swp_inst*)inst_base->component; |             swp_inst* inst_cream = (swp_inst*)inst_base->component; | ||||||
| 
 | 
 | ||||||
|             addr = RN; |             addr = RN; | ||||||
|             unsigned int value = Memory::Read32(addr); |             unsigned int value = ReadMemory32(cpu, addr); | ||||||
|             Memory::Write32(addr, RM); |             WriteMemory32(cpu, addr, RM); | ||||||
| 
 | 
 | ||||||
|             RD = value; |             RD = value; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -201,3 +201,9 @@ u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred) | ||||||
|     *saturation_occurred = false; |     *saturation_occurred = false; | ||||||
|     return (u32)value; |     return (u32)value; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // Whether or not the given CPU is in big endian mode (E bit is set)
 | ||||||
|  | bool InBigEndianMode(ARMul_State* cpu) | ||||||
|  | { | ||||||
|  |     return (cpu->Cpsr & (1 << 9)) != 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -18,7 +18,6 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "core/arm/skyeye_common/armmmu.h" |  | ||||||
| #include "core/arm/skyeye_common/arm_regformat.h" | #include "core/arm/skyeye_common/arm_regformat.h" | ||||||
| #include "core/arm/skyeye_common/skyeye_defs.h" | #include "core/arm/skyeye_common/skyeye_defs.h" | ||||||
| 
 | 
 | ||||||
|  | @ -356,3 +355,5 @@ extern u16 ARMul_UnsignedSaturatedSub16(u16, u16); | ||||||
| extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8); | extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8); | ||||||
| extern u32 ARMul_SignedSatQ(s32, u8, bool*); | extern u32 ARMul_SignedSatQ(s32, u8, bool*); | ||||||
| extern u32 ARMul_UnsignedSatQ(s32, u8, bool*); | extern u32 ARMul_UnsignedSatQ(s32, u8, bool*); | ||||||
|  | 
 | ||||||
|  | extern bool InBigEndianMode(ARMul_State*); | ||||||
|  |  | ||||||
|  | @ -20,6 +20,9 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include "core/mem_map.h" | ||||||
|  | #include "core/arm/skyeye_common/armdefs.h" | ||||||
|  | 
 | ||||||
| // Register numbers in the MMU
 | // Register numbers in the MMU
 | ||||||
| enum | enum | ||||||
| { | { | ||||||
|  | @ -54,3 +57,55 @@ enum | ||||||
| 	XSCALE_CP15_AUX_CONTROL = 1, | 	XSCALE_CP15_AUX_CONTROL = 1, | ||||||
| 	XSCALE_CP15_COPRO_ACCESS = 15, | 	XSCALE_CP15_COPRO_ACCESS = 15, | ||||||
| }; | }; | ||||||
|  | 
 | ||||||
|  | // Reads data in big/little endian format based on the
 | ||||||
|  | // state of the E (endian) bit in the emulated CPU's APSR.
 | ||||||
|  | inline u16 ReadMemory16(ARMul_State* cpu, u32 address) { | ||||||
|  |     u16 data = Memory::Read16(address); | ||||||
|  | 
 | ||||||
|  |     if (InBigEndianMode(cpu)) | ||||||
|  |         data = Common::swap16(data); | ||||||
|  | 
 | ||||||
|  |     return data; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | inline u32 ReadMemory32(ARMul_State* cpu, u32 address) { | ||||||
|  |     u32 data = Memory::Read32(address); | ||||||
|  | 
 | ||||||
|  |     if (InBigEndianMode(cpu)) | ||||||
|  |         data = Common::swap32(data); | ||||||
|  | 
 | ||||||
|  |     return data; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | inline u64 ReadMemory64(ARMul_State* cpu, u32 address) { | ||||||
|  |     u64 data = Memory::Read64(address); | ||||||
|  | 
 | ||||||
|  |     if (InBigEndianMode(cpu)) | ||||||
|  |         data = Common::swap64(data); | ||||||
|  | 
 | ||||||
|  |     return data; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Writes data in big/little endian format based on the
 | ||||||
|  | // state of the E (endian) bit in the emulated CPU's APSR.
 | ||||||
|  | inline void WriteMemory16(ARMul_State* cpu, u32 address, u16 data) { | ||||||
|  |     if (InBigEndianMode(cpu)) | ||||||
|  |         data = Common::swap16(data); | ||||||
|  | 
 | ||||||
|  |     Memory::Write16(address, data); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | inline void WriteMemory32(ARMul_State* cpu, u32 address, u32 data) { | ||||||
|  |     if (InBigEndianMode(cpu)) | ||||||
|  |         data = Common::swap32(data); | ||||||
|  | 
 | ||||||
|  |     Memory::Write32(address, data); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | inline void WriteMemory64(ARMul_State* cpu, u32 address, u64 data) { | ||||||
|  |     if (InBigEndianMode(cpu)) | ||||||
|  |         data = Common::swap64(data); | ||||||
|  | 
 | ||||||
|  |     Memory::Write64(address, data); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -1388,12 +1388,20 @@ VSTR_INST: | ||||||
| 
 | 
 | ||||||
|         if (inst_cream->single) |         if (inst_cream->single) | ||||||
|         { |         { | ||||||
|             Memory::Write32(addr, cpu->ExtReg[inst_cream->d]); |             WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d]); | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             Memory::Write32(addr, cpu->ExtReg[inst_cream->d*2]); |             const u32 word1 = cpu->ExtReg[inst_cream->d*2+0]; | ||||||
|             Memory::Write32(addr + 4, cpu->ExtReg[inst_cream->d*2+1]); |             const u32 word2 = cpu->ExtReg[inst_cream->d*2+1]; | ||||||
|  | 
 | ||||||
|  |             if (InBigEndianMode(cpu)) { | ||||||
|  |                 WriteMemory32(cpu, addr + 0, word2); | ||||||
|  |                 WriteMemory32(cpu, addr + 4, word1); | ||||||
|  |             } else { | ||||||
|  |                 WriteMemory32(cpu, addr + 0, word1); | ||||||
|  |                 WriteMemory32(cpu, addr + 4, word2); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); |     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||||
|  | @ -1447,17 +1455,27 @@ VPUSH_INST: | ||||||
|         { |         { | ||||||
|             if (inst_cream->single) |             if (inst_cream->single) | ||||||
|             { |             { | ||||||
|                 Memory::Write32(addr, cpu->ExtReg[inst_cream->d+i]); |                 WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]); | ||||||
|                 addr += 4; |                 addr += 4; | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 Memory::Write32(addr, cpu->ExtReg[(inst_cream->d+i)*2]); |                 const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0]; | ||||||
|                 Memory::Write32(addr + 4, cpu->ExtReg[(inst_cream->d+i)*2 + 1]); |                 const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1]; | ||||||
|  | 
 | ||||||
|  |                 if (InBigEndianMode(cpu)) { | ||||||
|  |                     WriteMemory32(cpu, addr + 0, word2); | ||||||
|  |                     WriteMemory32(cpu, addr + 4, word1); | ||||||
|  |                 } else { | ||||||
|  |                     WriteMemory32(cpu, addr + 0, word1); | ||||||
|  |                     WriteMemory32(cpu, addr + 4, word2); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|                 addr += 8; |                 addr += 8; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         cpu->Reg[R13] = cpu->Reg[R13] - inst_cream->imm32; | 
 | ||||||
|  |         cpu->Reg[R13] -= inst_cream->imm32; | ||||||
|     } |     } | ||||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); |     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||||
|     INC_PC(sizeof(vpush_inst)); |     INC_PC(sizeof(vpush_inst)); | ||||||
|  | @ -1516,13 +1534,22 @@ VSTM_INST: /* encoding 1 */ | ||||||
|         { |         { | ||||||
|             if (inst_cream->single) |             if (inst_cream->single) | ||||||
|             { |             { | ||||||
|                 Memory::Write32(addr, cpu->ExtReg[inst_cream->d+i]); |                 WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]); | ||||||
|                 addr += 4; |                 addr += 4; | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 Memory::Write32(addr, cpu->ExtReg[(inst_cream->d+i)*2]); |                 const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0]; | ||||||
|                 Memory::Write32(addr + 4, cpu->ExtReg[(inst_cream->d+i)*2 + 1]); |                 const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1]; | ||||||
|  | 
 | ||||||
|  |                 if (InBigEndianMode(cpu)) { | ||||||
|  |                     WriteMemory32(cpu, addr + 0, word2); | ||||||
|  |                     WriteMemory32(cpu, addr + 4, word1); | ||||||
|  |                 } else { | ||||||
|  |                     WriteMemory32(cpu, addr + 0, word1); | ||||||
|  |                     WriteMemory32(cpu, addr + 4, word2); | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|                 addr += 8; |                 addr += 8; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -1575,8 +1602,6 @@ VPOP_INST: | ||||||
|     if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { |     if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { | ||||||
|         CHECK_VFP_ENABLED; |         CHECK_VFP_ENABLED; | ||||||
| 
 | 
 | ||||||
|         unsigned int value1, value2; |  | ||||||
| 
 |  | ||||||
|         vpop_inst *inst_cream = (vpop_inst *)inst_base->component; |         vpop_inst *inst_cream = (vpop_inst *)inst_base->component; | ||||||
| 
 | 
 | ||||||
|         addr = cpu->Reg[R13]; |         addr = cpu->Reg[R13]; | ||||||
|  | @ -1585,20 +1610,26 @@ VPOP_INST: | ||||||
|         { |         { | ||||||
|             if (inst_cream->single) |             if (inst_cream->single) | ||||||
|             { |             { | ||||||
|                 value1 = Memory::Read32(addr); |                 cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr); | ||||||
|                 cpu->ExtReg[inst_cream->d+i] = value1; |  | ||||||
|                 addr += 4; |                 addr += 4; | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 value1 = Memory::Read32(addr); |                 const u32 word1 = ReadMemory32(cpu, addr + 0); | ||||||
|                 value2 = Memory::Read32(addr + 4); |                 const u32 word2 = ReadMemory32(cpu, addr + 4); | ||||||
|                 cpu->ExtReg[(inst_cream->d+i)*2] = value1; | 
 | ||||||
|                 cpu->ExtReg[(inst_cream->d+i)*2 + 1] = value2; |                 if (InBigEndianMode(cpu)) { | ||||||
|  |                     cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; | ||||||
|  |                     cpu->ExtReg[(inst_cream->d+i)*2+1] = word1; | ||||||
|  |                 } else { | ||||||
|  |                     cpu->ExtReg[(inst_cream->d+i)*2+0] = word1; | ||||||
|  |                     cpu->ExtReg[(inst_cream->d+i)*2+1] = word2; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|                 addr += 8; |                 addr += 8; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         cpu->Reg[R13] = cpu->Reg[R13] + inst_cream->imm32; |         cpu->Reg[R13] += inst_cream->imm32; | ||||||
|     } |     } | ||||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); |     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||||
|     INC_PC(sizeof(vpop_inst)); |     INC_PC(sizeof(vpop_inst)); | ||||||
|  | @ -1653,16 +1684,20 @@ VLDR_INST: | ||||||
| 
 | 
 | ||||||
|         if (inst_cream->single) |         if (inst_cream->single) | ||||||
|         { |         { | ||||||
|             cpu->ExtReg[inst_cream->d] = Memory::Read32(addr); |             cpu->ExtReg[inst_cream->d] = ReadMemory32(cpu, addr); | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             unsigned int word1, word2; |             const u32 word1 = ReadMemory32(cpu, addr + 0); | ||||||
|             word1 = Memory::Read32(addr); |             const u32 word2 = ReadMemory32(cpu, addr + 4); | ||||||
|             word2 = Memory::Read32(addr + 4); |  | ||||||
| 
 | 
 | ||||||
|             cpu->ExtReg[inst_cream->d*2] = word1; |             if (InBigEndianMode(cpu)) { | ||||||
|             cpu->ExtReg[inst_cream->d*2+1] = word2; |                 cpu->ExtReg[inst_cream->d*2+0] = word2; | ||||||
|  |                 cpu->ExtReg[inst_cream->d*2+1] = word1; | ||||||
|  |             } else { | ||||||
|  |                 cpu->ExtReg[inst_cream->d*2+0] = word1; | ||||||
|  |                 cpu->ExtReg[inst_cream->d*2+1] = word2; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); |     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||||
|  | @ -1722,13 +1757,22 @@ VLDM_INST: | ||||||
|         { |         { | ||||||
|             if (inst_cream->single) |             if (inst_cream->single) | ||||||
|             { |             { | ||||||
|                 cpu->ExtReg[inst_cream->d+i] = Memory::Read32(addr); |                 cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr); | ||||||
|                 addr += 4; |                 addr += 4; | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 cpu->ExtReg[(inst_cream->d+i)*2] = Memory::Read32(addr); |                 const u32 word1 = ReadMemory32(cpu, addr + 0); | ||||||
|                 cpu->ExtReg[(inst_cream->d+i)*2 + 1] = Memory::Read32(addr + 4); |                 const u32 word2 = ReadMemory32(cpu, addr + 4); | ||||||
|  | 
 | ||||||
|  |                 if (InBigEndianMode(cpu)) { | ||||||
|  |                     cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; | ||||||
|  |                     cpu->ExtReg[(inst_cream->d+i)*2+1] = word1; | ||||||
|  |                 } else { | ||||||
|  |                     cpu->ExtReg[(inst_cream->d+i)*2+0] = word1; | ||||||
|  |                     cpu->ExtReg[(inst_cream->d+i)*2+1] = word2; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|                 addr += 8; |                 addr += 8; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -147,6 +147,7 @@ inline void Write(VAddr addr, T data); | ||||||
| u8 Read8(VAddr addr); | u8 Read8(VAddr addr); | ||||||
| u16 Read16(VAddr addr); | u16 Read16(VAddr addr); | ||||||
| u32 Read32(VAddr addr); | u32 Read32(VAddr addr); | ||||||
|  | u64 Read64(VAddr addr); | ||||||
| 
 | 
 | ||||||
| u32 Read8_ZX(VAddr addr); | u32 Read8_ZX(VAddr addr); | ||||||
| u32 Read16_ZX(VAddr addr); | u32 Read16_ZX(VAddr addr); | ||||||
|  |  | ||||||
|  | @ -245,6 +245,12 @@ u32 Read32(const VAddr addr) { | ||||||
|     return (u32)data; |     return (u32)data; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | u64 Read64(const VAddr addr) { | ||||||
|  |     u64_le data = 0; | ||||||
|  |     Read<u64_le>(data, addr); | ||||||
|  |     return (u64)data; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| u32 Read8_ZX(const VAddr addr) { | u32 Read8_ZX(const VAddr addr) { | ||||||
|     return (u32)Read8(addr); |     return (u32)Read8(addr); | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue