mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Merge pull request #1001 from lioncash/arm
dyncom: Centralize state-related functions.
This commit is contained in:
		
						commit
						62caa89f48
					
				
					 12 changed files with 1028 additions and 1109 deletions
				
			
		|  | @ -4,9 +4,8 @@ set(SRCS | |||
|             arm/dyncom/arm_dyncom.cpp | ||||
|             arm/dyncom/arm_dyncom_dec.cpp | ||||
|             arm/dyncom/arm_dyncom_interpreter.cpp | ||||
|             arm/dyncom/arm_dyncom_run.cpp | ||||
|             arm/dyncom/arm_dyncom_thumb.cpp | ||||
|             arm/skyeye_common/arminit.cpp | ||||
|             arm/skyeye_common/armstate.cpp | ||||
|             arm/skyeye_common/armsupp.cpp | ||||
|             arm/skyeye_common/vfp/vfp.cpp | ||||
|             arm/skyeye_common/vfp/vfpdouble.cpp | ||||
|  | @ -133,7 +132,6 @@ set(HEADERS | |||
|             arm/dyncom/arm_dyncom_thumb.h | ||||
|             arm/skyeye_common/arm_regformat.h | ||||
|             arm/skyeye_common/armstate.h | ||||
|             arm/skyeye_common/armmmu.h | ||||
|             arm/skyeye_common/armsupp.h | ||||
|             arm/skyeye_common/vfp/asm_vfp.h | ||||
|             arm/skyeye_common/vfp/vfp.h | ||||
|  |  | |||
|  | @ -18,16 +18,7 @@ | |||
| #include "core/core_timing.h" | ||||
| 
 | ||||
| ARM_DynCom::ARM_DynCom(PrivilegeMode initial_mode) { | ||||
|     state = Common::make_unique<ARMul_State>(); | ||||
| 
 | ||||
|     // Reset the core to initial state
 | ||||
|     ARMul_Reset(state.get()); | ||||
| 
 | ||||
|     // Switch to the desired privilege mode.
 | ||||
|     switch_mode(state.get(), initial_mode); | ||||
| 
 | ||||
|     state->Reg[13] = 0x10000000; // Set stack pointer to the top of the stack
 | ||||
|     state->Reg[15] = 0x00000000; | ||||
|     state = Common::make_unique<ARMul_State>(initial_mode); | ||||
| } | ||||
| 
 | ||||
| ARM_DynCom::~ARM_DynCom() { | ||||
|  | @ -91,8 +82,8 @@ void ARM_DynCom::ResetContext(Core::ThreadContext& context, u32 stack_top, u32 e | |||
| } | ||||
| 
 | ||||
| void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) { | ||||
|     memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers)); | ||||
|     memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers)); | ||||
|     memcpy(ctx.cpu_registers, state->Reg.data(), sizeof(ctx.cpu_registers)); | ||||
|     memcpy(ctx.fpu_registers, state->ExtReg.data(), sizeof(ctx.fpu_registers)); | ||||
| 
 | ||||
|     ctx.sp = state->Reg[13]; | ||||
|     ctx.lr = state->Reg[14]; | ||||
|  | @ -104,8 +95,8 @@ void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) { | |||
| } | ||||
| 
 | ||||
| void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) { | ||||
|     memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers)); | ||||
|     memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers)); | ||||
|     memcpy(state->Reg.data(), ctx.cpu_registers, sizeof(ctx.cpu_registers)); | ||||
|     memcpy(state->ExtReg.data(), ctx.fpu_registers, sizeof(ctx.fpu_registers)); | ||||
| 
 | ||||
|     state->Reg[13] = ctx.sp; | ||||
|     state->Reg[14] = ctx.lr; | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -1,93 +0,0 @@ | |||
| // Copyright 2012 Michael Kang, 2014 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "core/arm/dyncom/arm_dyncom_run.h" | ||||
| #include "core/arm/skyeye_common/armstate.h" | ||||
| 
 | ||||
| void switch_mode(ARMul_State* core, uint32_t mode) { | ||||
|     if (core->Mode == mode) | ||||
|         return; | ||||
| 
 | ||||
|     if (mode != USERBANK) { | ||||
|         switch (core->Mode) { | ||||
|         case SYSTEM32MODE: // Shares registers with user mode
 | ||||
|         case USER32MODE: | ||||
|             core->Reg_usr[0] = core->Reg[13]; | ||||
|             core->Reg_usr[1] = core->Reg[14]; | ||||
|             break; | ||||
|         case IRQ32MODE: | ||||
|             core->Reg_irq[0] = core->Reg[13]; | ||||
|             core->Reg_irq[1] = core->Reg[14]; | ||||
|             core->Spsr[IRQBANK] = core->Spsr_copy; | ||||
|             break; | ||||
|         case SVC32MODE: | ||||
|             core->Reg_svc[0] = core->Reg[13]; | ||||
|             core->Reg_svc[1] = core->Reg[14]; | ||||
|             core->Spsr[SVCBANK] = core->Spsr_copy; | ||||
|             break; | ||||
|         case ABORT32MODE: | ||||
|             core->Reg_abort[0] = core->Reg[13]; | ||||
|             core->Reg_abort[1] = core->Reg[14]; | ||||
|             core->Spsr[ABORTBANK] = core->Spsr_copy; | ||||
|             break; | ||||
|         case UNDEF32MODE: | ||||
|             core->Reg_undef[0] = core->Reg[13]; | ||||
|             core->Reg_undef[1] = core->Reg[14]; | ||||
|             core->Spsr[UNDEFBANK] = core->Spsr_copy; | ||||
|             break; | ||||
|         case FIQ32MODE: | ||||
|             core->Reg_firq[0] = core->Reg[13]; | ||||
|             core->Reg_firq[1] = core->Reg[14]; | ||||
|             core->Spsr[FIQBANK] = core->Spsr_copy; | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         switch (mode) { | ||||
|         case USER32MODE: | ||||
|             core->Reg[13] = core->Reg_usr[0]; | ||||
|             core->Reg[14] = core->Reg_usr[1]; | ||||
|             core->Bank = USERBANK; | ||||
|             break; | ||||
|         case IRQ32MODE: | ||||
|             core->Reg[13] = core->Reg_irq[0]; | ||||
|             core->Reg[14] = core->Reg_irq[1]; | ||||
|             core->Spsr_copy = core->Spsr[IRQBANK]; | ||||
|             core->Bank = IRQBANK; | ||||
|             break; | ||||
|         case SVC32MODE: | ||||
|             core->Reg[13] = core->Reg_svc[0]; | ||||
|             core->Reg[14] = core->Reg_svc[1]; | ||||
|             core->Spsr_copy = core->Spsr[SVCBANK]; | ||||
|             core->Bank = SVCBANK; | ||||
|             break; | ||||
|         case ABORT32MODE: | ||||
|             core->Reg[13] = core->Reg_abort[0]; | ||||
|             core->Reg[14] = core->Reg_abort[1]; | ||||
|             core->Spsr_copy = core->Spsr[ABORTBANK]; | ||||
|             core->Bank = ABORTBANK; | ||||
|             break; | ||||
|         case UNDEF32MODE: | ||||
|             core->Reg[13] = core->Reg_undef[0]; | ||||
|             core->Reg[14] = core->Reg_undef[1]; | ||||
|             core->Spsr_copy = core->Spsr[UNDEFBANK]; | ||||
|             core->Bank = UNDEFBANK; | ||||
|             break; | ||||
|         case FIQ32MODE: | ||||
|             core->Reg[13] = core->Reg_firq[0]; | ||||
|             core->Reg[14] = core->Reg_firq[1]; | ||||
|             core->Spsr_copy = core->Spsr[FIQBANK]; | ||||
|             core->Bank = FIQBANK; | ||||
|             break; | ||||
|         case SYSTEM32MODE: // Shares registers with user mode.
 | ||||
|             core->Reg[13] = core->Reg_usr[0]; | ||||
|             core->Reg[14] = core->Reg_usr[1]; | ||||
|             core->Bank = SYSTEMBANK; | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         // Set the mode bits in the APSR
 | ||||
|         core->Cpsr = (core->Cpsr & ~core->Mode) | mode; | ||||
|         core->Mode = mode; | ||||
|     } | ||||
| } | ||||
|  | @ -20,38 +20,29 @@ | |||
| 
 | ||||
| #include "core/arm/skyeye_common/armstate.h" | ||||
| 
 | ||||
| void switch_mode(ARMul_State* core, uint32_t mode); | ||||
| 
 | ||||
| // Note that for the 3DS, a Thumb instruction will only ever be
 | ||||
| // two bytes in size. Thus we don't need to worry about ThumbEE
 | ||||
| // or Thumb-2 where instructions can be 4 bytes in length.
 | ||||
| static inline u32 GET_INST_SIZE(ARMul_State* core) { | ||||
|     return core->TFlag? 2 : 4; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Checks if the PC is being read, and if so, word-aligns it. | ||||
|  * Used with address calculations. | ||||
|  * | ||||
|  * @param core The ARM CPU state instance. | ||||
|  * @param cpu The ARM CPU state instance. | ||||
|  * @param Rn   The register being read. | ||||
|  * | ||||
|  * @return If the PC is being read, then the word-aligned PC value is returned. | ||||
|  *         If the PC is not being read, then the value stored in the register is returned. | ||||
|  */ | ||||
| static inline u32 CHECK_READ_REG15_WA(ARMul_State* core, int Rn) { | ||||
|     return (Rn == 15) ? ((core->Reg[15] & ~0x3) + GET_INST_SIZE(core) * 2) : core->Reg[Rn]; | ||||
| static inline u32 CHECK_READ_REG15_WA(ARMul_State* cpu, int Rn) { | ||||
|     return (Rn == 15) ? ((cpu->Reg[15] & ~0x3) + cpu->GetInstructionSize() * 2) : cpu->Reg[Rn]; | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * Reads the PC. Used for data processing operations that use the PC. | ||||
|  * | ||||
|  * @param core The ARM CPU state instance. | ||||
|  * @param cpu The ARM CPU state instance. | ||||
|  * @param Rn   The register being read. | ||||
|  * | ||||
|  * @return If the PC is being read, then the incremented PC value is returned. | ||||
|  *         If the PC is not being read, then the values stored in the register is returned. | ||||
|  */ | ||||
| static inline u32 CHECK_READ_REG15(ARMul_State* core, int Rn) { | ||||
|     return (Rn == 15) ? ((core->Reg[15] & ~0x1) + GET_INST_SIZE(core) * 2) : core->Reg[Rn]; | ||||
| static inline u32 CHECK_READ_REG15(ARMul_State* cpu, int Rn) { | ||||
|     return (Rn == 15) ? ((cpu->Reg[15] & ~0x1) + cpu->GetInstructionSize() * 2) : cpu->Reg[Rn]; | ||||
| } | ||||
|  |  | |||
|  | @ -1,100 +0,0 @@ | |||
| /*  arminit.c -- ARMulator initialization:  ARM6 Instruction Emulator.
 | ||||
|     Copyright (C) 1994 Advanced RISC Machines Ltd. | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program; if not, write to the Free Software | ||||
|     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | ||||
| 
 | ||||
| #include <cstring> | ||||
| #include "core/arm/skyeye_common/armstate.h" | ||||
| #include "core/arm/skyeye_common/vfp/vfp.h" | ||||
| 
 | ||||
| // Resets certain MPCore CP15 values to their ARM-defined reset values.
 | ||||
| static void ResetMPCoreCP15Registers(ARMul_State* cpu) | ||||
| { | ||||
|     // c0
 | ||||
|     cpu->CP15[CP15_MAIN_ID]  = 0x410FB024; | ||||
|     cpu->CP15[CP15_TLB_TYPE] = 0x00000800; | ||||
|     cpu->CP15[CP15_PROCESSOR_FEATURE_0] = 0x00000111; | ||||
|     cpu->CP15[CP15_PROCESSOR_FEATURE_1] = 0x00000001; | ||||
|     cpu->CP15[CP15_DEBUG_FEATURE_0] = 0x00000002; | ||||
|     cpu->CP15[CP15_MEMORY_MODEL_FEATURE_0] = 0x01100103; | ||||
|     cpu->CP15[CP15_MEMORY_MODEL_FEATURE_1] = 0x10020302; | ||||
|     cpu->CP15[CP15_MEMORY_MODEL_FEATURE_2] = 0x01222000; | ||||
|     cpu->CP15[CP15_MEMORY_MODEL_FEATURE_3] = 0x00000000; | ||||
|     cpu->CP15[CP15_ISA_FEATURE_0] = 0x00100011; | ||||
|     cpu->CP15[CP15_ISA_FEATURE_1] = 0x12002111; | ||||
|     cpu->CP15[CP15_ISA_FEATURE_2] = 0x11221011; | ||||
|     cpu->CP15[CP15_ISA_FEATURE_3] = 0x01102131; | ||||
|     cpu->CP15[CP15_ISA_FEATURE_4] = 0x00000141; | ||||
| 
 | ||||
|     // c1
 | ||||
|     cpu->CP15[CP15_CONTROL] = 0x00054078; | ||||
|     cpu->CP15[CP15_AUXILIARY_CONTROL] = 0x0000000F; | ||||
|     cpu->CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = 0x00000000; | ||||
| 
 | ||||
|     // c2
 | ||||
|     cpu->CP15[CP15_TRANSLATION_BASE_TABLE_0] = 0x00000000; | ||||
|     cpu->CP15[CP15_TRANSLATION_BASE_TABLE_1] = 0x00000000; | ||||
|     cpu->CP15[CP15_TRANSLATION_BASE_CONTROL] = 0x00000000; | ||||
| 
 | ||||
|     // c3
 | ||||
|     cpu->CP15[CP15_DOMAIN_ACCESS_CONTROL] = 0x00000000; | ||||
| 
 | ||||
|     // c7
 | ||||
|     cpu->CP15[CP15_PHYS_ADDRESS] = 0x00000000; | ||||
| 
 | ||||
|     // c9
 | ||||
|     cpu->CP15[CP15_DATA_CACHE_LOCKDOWN] = 0xFFFFFFF0; | ||||
| 
 | ||||
|     // c10
 | ||||
|     cpu->CP15[CP15_TLB_LOCKDOWN] = 0x00000000; | ||||
|     cpu->CP15[CP15_PRIMARY_REGION_REMAP] = 0x00098AA4; | ||||
|     cpu->CP15[CP15_NORMAL_REGION_REMAP]  = 0x44E048E0; | ||||
| 
 | ||||
|     // c13
 | ||||
|     cpu->CP15[CP15_PID] = 0x00000000; | ||||
|     cpu->CP15[CP15_CONTEXT_ID]  = 0x00000000; | ||||
|     cpu->CP15[CP15_THREAD_UPRW] = 0x00000000; | ||||
|     cpu->CP15[CP15_THREAD_URO]  = 0x00000000; | ||||
|     cpu->CP15[CP15_THREAD_PRW]  = 0x00000000; | ||||
| 
 | ||||
|     // c15
 | ||||
|     cpu->CP15[CP15_PERFORMANCE_MONITOR_CONTROL]    = 0x00000000; | ||||
|     cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = 0x00000000; | ||||
|     cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = 0x00000000; | ||||
|     cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE]    = 0x00000000; | ||||
|     cpu->CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000; | ||||
| } | ||||
| 
 | ||||
| // Performs a reset
 | ||||
| void ARMul_Reset(ARMul_State* state) | ||||
| { | ||||
|     VFPInit(state); | ||||
| 
 | ||||
|     state->Reg[15] = 0; | ||||
|     state->Cpsr = INTBITS | SVC32MODE; | ||||
|     state->Mode = SVC32MODE; | ||||
|     state->Bank = SVCBANK; | ||||
| 
 | ||||
|     ResetMPCoreCP15Registers(state); | ||||
| 
 | ||||
|     state->NresetSig = HIGH; | ||||
|     state->NfiqSig = HIGH; | ||||
|     state->NirqSig = HIGH; | ||||
|     state->NtransSig = (state->Mode & 3) ? HIGH : LOW; | ||||
|     state->abortSig = LOW; | ||||
| 
 | ||||
|     state->NumInstrs = 0; | ||||
|     state->Emulate = RUN; | ||||
| } | ||||
|  | @ -1,104 +0,0 @@ | |||
| /*
 | ||||
|     armmmu.c - Memory Management Unit emulation. | ||||
|     ARMulator extensions for the ARM7100 family. | ||||
|     Copyright (C) 1999  Ben Williamson | ||||
| 
 | ||||
|     This program is free software; you can redistribute it and/or modify | ||||
|     it under the terms of the GNU General Public License as published by | ||||
|     the Free Software Foundation; either version 2 of the License, or | ||||
|     (at your option) any later version. | ||||
| 
 | ||||
|     This program is distributed in the hope that it will be useful, | ||||
|     but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|     GNU General Public License for more details. | ||||
| 
 | ||||
|     You should have received a copy of the GNU General Public License | ||||
|     along with this program; if not, write to the Free Software | ||||
|     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
| */ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "common/swap.h" | ||||
| 
 | ||||
| #include "core/memory.h" | ||||
| #include "core/arm/skyeye_common/armstate.h" | ||||
| #include "core/arm/skyeye_common/armsupp.h" | ||||
| 
 | ||||
| // Register numbers in the MMU
 | ||||
| enum | ||||
| { | ||||
|     MMU_ID = 0, | ||||
|     MMU_CONTROL = 1, | ||||
|     MMU_TRANSLATION_TABLE_BASE = 2, | ||||
|     MMU_DOMAIN_ACCESS_CONTROL = 3, | ||||
|     MMU_FAULT_STATUS = 5, | ||||
|     MMU_FAULT_ADDRESS = 6, | ||||
|     MMU_CACHE_OPS = 7, | ||||
|     MMU_TLB_OPS = 8, | ||||
|     MMU_CACHE_LOCKDOWN = 9, | ||||
|     MMU_TLB_LOCKDOWN = 10, | ||||
|     MMU_PID = 13, | ||||
| 
 | ||||
|     // MMU_V4
 | ||||
|     MMU_V4_CACHE_OPS = 7, | ||||
|     MMU_V4_TLB_OPS = 8, | ||||
| 
 | ||||
|     // MMU_V3
 | ||||
|     MMU_V3_FLUSH_TLB = 5, | ||||
|     MMU_V3_FLUSH_TLB_ENTRY = 6, | ||||
|     MMU_V3_FLUSH_CACHE = 7, | ||||
| }; | ||||
| 
 | ||||
| // 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); | ||||
| } | ||||
							
								
								
									
										657
									
								
								src/core/arm/skyeye_common/armstate.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										657
									
								
								src/core/arm/skyeye_common/armstate.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,657 @@ | |||
| // Copyright 2015 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include "common/swap.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "core/mem_map.h" | ||||
| #include "core/memory.h" | ||||
| #include "core/arm/skyeye_common/armstate.h" | ||||
| #include "core/arm/skyeye_common/vfp/vfp.h" | ||||
| 
 | ||||
| ARMul_State::ARMul_State(PrivilegeMode initial_mode) | ||||
| { | ||||
|     Reset(); | ||||
|     ChangePrivilegeMode(initial_mode); | ||||
| } | ||||
| 
 | ||||
| void ARMul_State::ChangePrivilegeMode(u32 new_mode) | ||||
| { | ||||
|     if (Mode == new_mode) | ||||
|         return; | ||||
| 
 | ||||
|     if (new_mode != USERBANK) { | ||||
|         switch (Mode) { | ||||
|         case SYSTEM32MODE: // Shares registers with user mode
 | ||||
|         case USER32MODE: | ||||
|             Reg_usr[0] = Reg[13]; | ||||
|             Reg_usr[1] = Reg[14]; | ||||
|             break; | ||||
|         case IRQ32MODE: | ||||
|             Reg_irq[0] = Reg[13]; | ||||
|             Reg_irq[1] = Reg[14]; | ||||
|             Spsr[IRQBANK] = Spsr_copy; | ||||
|             break; | ||||
|         case SVC32MODE: | ||||
|             Reg_svc[0] = Reg[13]; | ||||
|             Reg_svc[1] = Reg[14]; | ||||
|             Spsr[SVCBANK] = Spsr_copy; | ||||
|             break; | ||||
|         case ABORT32MODE: | ||||
|             Reg_abort[0] = Reg[13]; | ||||
|             Reg_abort[1] = Reg[14]; | ||||
|             Spsr[ABORTBANK] = Spsr_copy; | ||||
|             break; | ||||
|         case UNDEF32MODE: | ||||
|             Reg_undef[0] = Reg[13]; | ||||
|             Reg_undef[1] = Reg[14]; | ||||
|             Spsr[UNDEFBANK] = Spsr_copy; | ||||
|             break; | ||||
|         case FIQ32MODE: | ||||
|             Reg_firq[0] = Reg[13]; | ||||
|             Reg_firq[1] = Reg[14]; | ||||
|             Spsr[FIQBANK] = Spsr_copy; | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         switch (new_mode) { | ||||
|         case USER32MODE: | ||||
|             Reg[13] = Reg_usr[0]; | ||||
|             Reg[14] = Reg_usr[1]; | ||||
|             Bank = USERBANK; | ||||
|             break; | ||||
|         case IRQ32MODE: | ||||
|             Reg[13] = Reg_irq[0]; | ||||
|             Reg[14] = Reg_irq[1]; | ||||
|             Spsr_copy = Spsr[IRQBANK]; | ||||
|             Bank = IRQBANK; | ||||
|             break; | ||||
|         case SVC32MODE: | ||||
|             Reg[13] = Reg_svc[0]; | ||||
|             Reg[14] = Reg_svc[1]; | ||||
|             Spsr_copy = Spsr[SVCBANK]; | ||||
|             Bank = SVCBANK; | ||||
|             break; | ||||
|         case ABORT32MODE: | ||||
|             Reg[13] = Reg_abort[0]; | ||||
|             Reg[14] = Reg_abort[1]; | ||||
|             Spsr_copy = Spsr[ABORTBANK]; | ||||
|             Bank = ABORTBANK; | ||||
|             break; | ||||
|         case UNDEF32MODE: | ||||
|             Reg[13] = Reg_undef[0]; | ||||
|             Reg[14] = Reg_undef[1]; | ||||
|             Spsr_copy = Spsr[UNDEFBANK]; | ||||
|             Bank = UNDEFBANK; | ||||
|             break; | ||||
|         case FIQ32MODE: | ||||
|             Reg[13] = Reg_firq[0]; | ||||
|             Reg[14] = Reg_firq[1]; | ||||
|             Spsr_copy = Spsr[FIQBANK]; | ||||
|             Bank = FIQBANK; | ||||
|             break; | ||||
|         case SYSTEM32MODE: // Shares registers with user mode.
 | ||||
|             Reg[13] = Reg_usr[0]; | ||||
|             Reg[14] = Reg_usr[1]; | ||||
|             Bank = SYSTEMBANK; | ||||
|             break; | ||||
|         } | ||||
| 
 | ||||
|         // Set the mode bits in the APSR
 | ||||
|         Cpsr = (Cpsr & ~Mode) | new_mode; | ||||
|         Mode = new_mode; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // Performs a reset
 | ||||
| void ARMul_State::Reset() | ||||
| { | ||||
|     VFPInit(this); | ||||
| 
 | ||||
|     // Set stack pointer to the top of the stack
 | ||||
|     Reg[13] = 0x10000000; | ||||
|     Reg[15] = 0; | ||||
| 
 | ||||
|     Cpsr = INTBITS | SVC32MODE; | ||||
|     Mode = SVC32MODE; | ||||
|     Bank = SVCBANK; | ||||
| 
 | ||||
|     ResetMPCoreCP15Registers(); | ||||
| 
 | ||||
|     NresetSig = HIGH; | ||||
|     NfiqSig = HIGH; | ||||
|     NirqSig = HIGH; | ||||
|     NtransSig = (Mode & 3) ? HIGH : LOW; | ||||
|     abortSig = LOW; | ||||
| 
 | ||||
|     NumInstrs = 0; | ||||
|     Emulate = RUN; | ||||
| } | ||||
| 
 | ||||
| // Resets certain MPCore CP15 values to their ARM-defined reset values.
 | ||||
| void ARMul_State::ResetMPCoreCP15Registers() | ||||
| { | ||||
|     // c0
 | ||||
|     CP15[CP15_MAIN_ID] = 0x410FB024; | ||||
|     CP15[CP15_TLB_TYPE] = 0x00000800; | ||||
|     CP15[CP15_PROCESSOR_FEATURE_0] = 0x00000111; | ||||
|     CP15[CP15_PROCESSOR_FEATURE_1] = 0x00000001; | ||||
|     CP15[CP15_DEBUG_FEATURE_0] = 0x00000002; | ||||
|     CP15[CP15_MEMORY_MODEL_FEATURE_0] = 0x01100103; | ||||
|     CP15[CP15_MEMORY_MODEL_FEATURE_1] = 0x10020302; | ||||
|     CP15[CP15_MEMORY_MODEL_FEATURE_2] = 0x01222000; | ||||
|     CP15[CP15_MEMORY_MODEL_FEATURE_3] = 0x00000000; | ||||
|     CP15[CP15_ISA_FEATURE_0] = 0x00100011; | ||||
|     CP15[CP15_ISA_FEATURE_1] = 0x12002111; | ||||
|     CP15[CP15_ISA_FEATURE_2] = 0x11221011; | ||||
|     CP15[CP15_ISA_FEATURE_3] = 0x01102131; | ||||
|     CP15[CP15_ISA_FEATURE_4] = 0x00000141; | ||||
| 
 | ||||
|     // c1
 | ||||
|     CP15[CP15_CONTROL] = 0x00054078; | ||||
|     CP15[CP15_AUXILIARY_CONTROL] = 0x0000000F; | ||||
|     CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = 0x00000000; | ||||
| 
 | ||||
|     // c2
 | ||||
|     CP15[CP15_TRANSLATION_BASE_TABLE_0] = 0x00000000; | ||||
|     CP15[CP15_TRANSLATION_BASE_TABLE_1] = 0x00000000; | ||||
|     CP15[CP15_TRANSLATION_BASE_CONTROL] = 0x00000000; | ||||
| 
 | ||||
|     // c3
 | ||||
|     CP15[CP15_DOMAIN_ACCESS_CONTROL] = 0x00000000; | ||||
| 
 | ||||
|     // c7
 | ||||
|     CP15[CP15_PHYS_ADDRESS] = 0x00000000; | ||||
| 
 | ||||
|     // c9
 | ||||
|     CP15[CP15_DATA_CACHE_LOCKDOWN] = 0xFFFFFFF0; | ||||
| 
 | ||||
|     // c10
 | ||||
|     CP15[CP15_TLB_LOCKDOWN] = 0x00000000; | ||||
|     CP15[CP15_PRIMARY_REGION_REMAP] = 0x00098AA4; | ||||
|     CP15[CP15_NORMAL_REGION_REMAP] = 0x44E048E0; | ||||
| 
 | ||||
|     // c13
 | ||||
|     CP15[CP15_PID] = 0x00000000; | ||||
|     CP15[CP15_CONTEXT_ID] = 0x00000000; | ||||
|     CP15[CP15_THREAD_UPRW] = 0x00000000; | ||||
|     CP15[CP15_THREAD_URO] = 0x00000000; | ||||
|     CP15[CP15_THREAD_PRW] = 0x00000000; | ||||
| 
 | ||||
|     // c15
 | ||||
|     CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = 0x00000000; | ||||
|     CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = 0x00000000; | ||||
|     CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = 0x00000000; | ||||
|     CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = 0x00000000; | ||||
|     CP15[CP15_TLB_DEBUG_CONTROL] = 0x00000000; | ||||
| } | ||||
| 
 | ||||
| u16 ARMul_State::ReadMemory16(u32 address) const | ||||
| { | ||||
|     u16 data = Memory::Read16(address); | ||||
| 
 | ||||
|     if (InBigEndianMode()) | ||||
|         data = Common::swap16(data); | ||||
| 
 | ||||
|     return data; | ||||
| } | ||||
| 
 | ||||
| u32 ARMul_State::ReadMemory32(u32 address) const | ||||
| { | ||||
|     u32 data = Memory::Read32(address); | ||||
| 
 | ||||
|     if (InBigEndianMode()) | ||||
|         data = Common::swap32(data); | ||||
| 
 | ||||
|     return data; | ||||
| } | ||||
| 
 | ||||
| u64 ARMul_State::ReadMemory64(u32 address) const | ||||
| { | ||||
|     u64 data = Memory::Read64(address); | ||||
| 
 | ||||
|     if (InBigEndianMode()) | ||||
|         data = Common::swap64(data); | ||||
| 
 | ||||
|     return data; | ||||
| } | ||||
| 
 | ||||
| void ARMul_State::WriteMemory16(u32 address, u16 data) | ||||
| { | ||||
|     if (InBigEndianMode()) | ||||
|         data = Common::swap16(data); | ||||
| 
 | ||||
|     Memory::Write16(address, data); | ||||
| } | ||||
| 
 | ||||
| void ARMul_State::WriteMemory32(u32 address, u32 data) | ||||
| { | ||||
|     if (InBigEndianMode()) | ||||
|         data = Common::swap32(data); | ||||
| 
 | ||||
|     Memory::Write32(address, data); | ||||
| } | ||||
| 
 | ||||
| void ARMul_State::WriteMemory64(u32 address, u64 data) | ||||
| { | ||||
|     if (InBigEndianMode()) | ||||
|         data = Common::swap64(data); | ||||
| 
 | ||||
|     Memory::Write64(address, data); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // Reads from the CP15 registers. Used with implementation of the MRC instruction.
 | ||||
| // Note that since the 3DS does not have the hypervisor extensions, these registers
 | ||||
| // are not implemented.
 | ||||
| u32 ARMul_State::ReadCP15Register(u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) const | ||||
| { | ||||
|     // Unprivileged registers
 | ||||
|     if (crn == 13 && opcode_1 == 0 && crm == 0) | ||||
|     { | ||||
|         if (opcode_2 == 2) | ||||
|             return CP15[CP15_THREAD_UPRW]; | ||||
| 
 | ||||
|         if (opcode_2 == 3) | ||||
|             return CP15[CP15_THREAD_URO]; | ||||
|     } | ||||
| 
 | ||||
|     if (InAPrivilegedMode()) | ||||
|     { | ||||
|         if (crn == 0 && opcode_1 == 0) | ||||
|         { | ||||
|             if (crm == 0) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     return CP15[CP15_MAIN_ID]; | ||||
| 
 | ||||
|                 if (opcode_2 == 1) | ||||
|                     return CP15[CP15_CACHE_TYPE]; | ||||
| 
 | ||||
|                 if (opcode_2 == 3) | ||||
|                     return CP15[CP15_TLB_TYPE]; | ||||
| 
 | ||||
|                 if (opcode_2 == 5) | ||||
|                     return CP15[CP15_CPU_ID]; | ||||
|             } | ||||
|             else if (crm == 1) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     return CP15[CP15_PROCESSOR_FEATURE_0]; | ||||
| 
 | ||||
|                 if (opcode_2 == 1) | ||||
|                     return CP15[CP15_PROCESSOR_FEATURE_1]; | ||||
| 
 | ||||
|                 if (opcode_2 == 2) | ||||
|                     return CP15[CP15_DEBUG_FEATURE_0]; | ||||
| 
 | ||||
|                 if (opcode_2 == 4) | ||||
|                     return CP15[CP15_MEMORY_MODEL_FEATURE_0]; | ||||
| 
 | ||||
|                 if (opcode_2 == 5) | ||||
|                     return CP15[CP15_MEMORY_MODEL_FEATURE_1]; | ||||
| 
 | ||||
|                 if (opcode_2 == 6) | ||||
|                     return CP15[CP15_MEMORY_MODEL_FEATURE_2]; | ||||
| 
 | ||||
|                 if (opcode_2 == 7) | ||||
|                     return CP15[CP15_MEMORY_MODEL_FEATURE_3]; | ||||
|             } | ||||
|             else if (crm == 2) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     return CP15[CP15_ISA_FEATURE_0]; | ||||
| 
 | ||||
|                 if (opcode_2 == 1) | ||||
|                     return CP15[CP15_ISA_FEATURE_1]; | ||||
| 
 | ||||
|                 if (opcode_2 == 2) | ||||
|                     return CP15[CP15_ISA_FEATURE_2]; | ||||
| 
 | ||||
|                 if (opcode_2 == 3) | ||||
|                     return CP15[CP15_ISA_FEATURE_3]; | ||||
| 
 | ||||
|                 if (opcode_2 == 4) | ||||
|                     return CP15[CP15_ISA_FEATURE_4]; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (crn == 1 && opcode_1 == 0 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 return CP15[CP15_CONTROL]; | ||||
| 
 | ||||
|             if (opcode_2 == 1) | ||||
|                 return CP15[CP15_AUXILIARY_CONTROL]; | ||||
| 
 | ||||
|             if (opcode_2 == 2) | ||||
|                 return CP15[CP15_COPROCESSOR_ACCESS_CONTROL]; | ||||
|         } | ||||
| 
 | ||||
|         if (crn == 2 && opcode_1 == 0 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 return CP15[CP15_TRANSLATION_BASE_TABLE_0]; | ||||
| 
 | ||||
|             if (opcode_2 == 1) | ||||
|                 return CP15[CP15_TRANSLATION_BASE_TABLE_1]; | ||||
| 
 | ||||
|             if (opcode_2 == 2) | ||||
|                 return CP15[CP15_TRANSLATION_BASE_CONTROL]; | ||||
|         } | ||||
| 
 | ||||
|         if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | ||||
|             return CP15[CP15_DOMAIN_ACCESS_CONTROL]; | ||||
| 
 | ||||
|         if (crn == 5 && opcode_1 == 0 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 return CP15[CP15_FAULT_STATUS]; | ||||
| 
 | ||||
|             if (opcode_2 == 1) | ||||
|                 return CP15[CP15_INSTR_FAULT_STATUS]; | ||||
|         } | ||||
| 
 | ||||
|         if (crn == 6 && opcode_1 == 0 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 return CP15[CP15_FAULT_ADDRESS]; | ||||
| 
 | ||||
|             if (opcode_2 == 1) | ||||
|                 return CP15[CP15_WFAR]; | ||||
|         } | ||||
| 
 | ||||
|         if (crn == 7 && opcode_1 == 0 && crm == 4 && opcode_2 == 0) | ||||
|             return CP15[CP15_PHYS_ADDRESS]; | ||||
| 
 | ||||
|         if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | ||||
|             return CP15[CP15_DATA_CACHE_LOCKDOWN]; | ||||
| 
 | ||||
|         if (crn == 10 && opcode_1 == 0) | ||||
|         { | ||||
|             if (crm == 0 && opcode_2 == 0) | ||||
|                 return CP15[CP15_TLB_LOCKDOWN]; | ||||
| 
 | ||||
|             if (crm == 2) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     return CP15[CP15_PRIMARY_REGION_REMAP]; | ||||
| 
 | ||||
|                 if (opcode_2 == 1) | ||||
|                     return CP15[CP15_NORMAL_REGION_REMAP]; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (crn == 13 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 return CP15[CP15_PID]; | ||||
| 
 | ||||
|             if (opcode_2 == 1) | ||||
|                 return CP15[CP15_CONTEXT_ID]; | ||||
| 
 | ||||
|             if (opcode_2 == 4) | ||||
|                 return CP15[CP15_THREAD_PRW]; | ||||
|         } | ||||
| 
 | ||||
|         if (crn == 15) | ||||
|         { | ||||
|             if (opcode_1 == 0 && crm == 12) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     return CP15[CP15_PERFORMANCE_MONITOR_CONTROL]; | ||||
| 
 | ||||
|                 if (opcode_2 == 1) | ||||
|                     return CP15[CP15_CYCLE_COUNTER]; | ||||
| 
 | ||||
|                 if (opcode_2 == 2) | ||||
|                     return CP15[CP15_COUNT_0]; | ||||
| 
 | ||||
|                 if (opcode_2 == 3) | ||||
|                     return CP15[CP15_COUNT_1]; | ||||
|             } | ||||
| 
 | ||||
|             if (opcode_1 == 5 && opcode_2 == 2) | ||||
|             { | ||||
|                 if (crm == 5) | ||||
|                     return CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS]; | ||||
| 
 | ||||
|                 if (crm == 6) | ||||
|                     return CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS]; | ||||
| 
 | ||||
|                 if (crm == 7) | ||||
|                     return CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE]; | ||||
|             } | ||||
| 
 | ||||
|             if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) | ||||
|                 return CP15[CP15_TLB_DEBUG_CONTROL]; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     LOG_ERROR(Core_ARM11, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.", crn, crm, opcode_1, opcode_2); | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| // Write to the CP15 registers. Used with implementation of the MCR instruction.
 | ||||
| // Note that since the 3DS does not have the hypervisor extensions, these registers
 | ||||
| // are not implemented.
 | ||||
| void ARMul_State::WriteCP15Register(u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | ||||
| { | ||||
|     if (InAPrivilegedMode()) | ||||
|     { | ||||
|         if (crn == 1 && opcode_1 == 0 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 CP15[CP15_CONTROL] = value; | ||||
|             else if (opcode_2 == 1) | ||||
|                 CP15[CP15_AUXILIARY_CONTROL] = value; | ||||
|             else if (opcode_2 == 2) | ||||
|                 CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = value; | ||||
|         } | ||||
|         else if (crn == 2 && opcode_1 == 0 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 CP15[CP15_TRANSLATION_BASE_TABLE_0] = value; | ||||
|             else if (opcode_2 == 1) | ||||
|                 CP15[CP15_TRANSLATION_BASE_TABLE_1] = value; | ||||
|             else if (opcode_2 == 2) | ||||
|                 CP15[CP15_TRANSLATION_BASE_CONTROL] = value; | ||||
|         } | ||||
|         else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | ||||
|         { | ||||
|             CP15[CP15_DOMAIN_ACCESS_CONTROL] = value; | ||||
|         } | ||||
|         else if (crn == 5 && opcode_1 == 0 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 CP15[CP15_FAULT_STATUS] = value; | ||||
|             else if (opcode_2 == 1) | ||||
|                 CP15[CP15_INSTR_FAULT_STATUS] = value; | ||||
|         } | ||||
|         else if (crn == 6 && opcode_1 == 0 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 CP15[CP15_FAULT_ADDRESS] = value; | ||||
|             else if (opcode_2 == 1) | ||||
|                 CP15[CP15_WFAR] = value; | ||||
|         } | ||||
|         else if (crn == 7 && opcode_1 == 0) | ||||
|         { | ||||
|             if (crm == 0 && opcode_2 == 4) | ||||
|             { | ||||
|                 CP15[CP15_WAIT_FOR_INTERRUPT] = value; | ||||
|             } | ||||
|             else if (crm == 4 && opcode_2 == 0) | ||||
|             { | ||||
|                 // NOTE: Not entirely accurate. This should do permission checks.
 | ||||
|                 CP15[CP15_PHYS_ADDRESS] = Memory::VirtualToPhysicalAddress(value); | ||||
|             } | ||||
|             else if (crm == 5) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     CP15[CP15_INVALIDATE_INSTR_CACHE] = value; | ||||
|                 else if (opcode_2 == 1) | ||||
|                     CP15[CP15_INVALIDATE_INSTR_CACHE_USING_MVA] = value; | ||||
|                 else if (opcode_2 == 2) | ||||
|                     CP15[CP15_INVALIDATE_INSTR_CACHE_USING_INDEX] = value; | ||||
|                 else if (opcode_2 == 6) | ||||
|                     CP15[CP15_FLUSH_BRANCH_TARGET_CACHE] = value; | ||||
|                 else if (opcode_2 == 7) | ||||
|                     CP15[CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY] = value; | ||||
|             } | ||||
|             else if (crm == 6) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     CP15[CP15_INVALIDATE_DATA_CACHE] = value; | ||||
|                 else if (opcode_2 == 1) | ||||
|                     CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value; | ||||
|                 else if (opcode_2 == 2) | ||||
|                     CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; | ||||
|             } | ||||
|             else if (crm == 7 && opcode_2 == 0) | ||||
|             { | ||||
|                 CP15[CP15_INVALIDATE_DATA_AND_INSTR_CACHE] = value; | ||||
|             } | ||||
|             else if (crm == 10) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     CP15[CP15_CLEAN_DATA_CACHE] = value; | ||||
|                 else if (opcode_2 == 1) | ||||
|                     CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_MVA] = value; | ||||
|                 else if (opcode_2 == 2) | ||||
|                     CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX] = value; | ||||
|             } | ||||
|             else if (crm == 14) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE] = value; | ||||
|                 else if (opcode_2 == 1) | ||||
|                     CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value; | ||||
|                 else if (opcode_2 == 2) | ||||
|                     CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; | ||||
|             } | ||||
|         } | ||||
|         else if (crn == 8 && opcode_1 == 0) | ||||
|         { | ||||
|             if (crm == 5) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     CP15[CP15_INVALIDATE_ITLB] = value; | ||||
|                 else if (opcode_2 == 1) | ||||
|                     CP15[CP15_INVALIDATE_ITLB_SINGLE_ENTRY] = value; | ||||
|                 else if (opcode_2 == 2) | ||||
|                     CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH] = value; | ||||
|                 else if (opcode_2 == 3) | ||||
|                     CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_MVA] = value; | ||||
|             } | ||||
|             else if (crm == 6) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     CP15[CP15_INVALIDATE_DTLB] = value; | ||||
|                 else if (opcode_2 == 1) | ||||
|                     CP15[CP15_INVALIDATE_DTLB_SINGLE_ENTRY] = value; | ||||
|                 else if (opcode_2 == 2) | ||||
|                     CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH] = value; | ||||
|                 else if (opcode_2 == 3) | ||||
|                     CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_MVA] = value; | ||||
|             } | ||||
|             else if (crm == 7) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     CP15[CP15_INVALIDATE_UTLB] = value; | ||||
|                 else if (opcode_2 == 1) | ||||
|                     CP15[CP15_INVALIDATE_UTLB_SINGLE_ENTRY] = value; | ||||
|                 else if (opcode_2 == 2) | ||||
|                     CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH] = value; | ||||
|                 else if (opcode_2 == 3) | ||||
|                     CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_MVA] = value; | ||||
|             } | ||||
|         } | ||||
|         else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | ||||
|         { | ||||
|             CP15[CP15_DATA_CACHE_LOCKDOWN] = value; | ||||
|         } | ||||
|         else if (crn == 10 && opcode_1 == 0) | ||||
|         { | ||||
|             if (crm == 0 && opcode_2 == 0) | ||||
|             { | ||||
|                 CP15[CP15_TLB_LOCKDOWN] = value; | ||||
|             } | ||||
|             else if (crm == 2) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     CP15[CP15_PRIMARY_REGION_REMAP] = value; | ||||
|                 else if (opcode_2 == 1) | ||||
|                     CP15[CP15_NORMAL_REGION_REMAP] = value; | ||||
|             } | ||||
|         } | ||||
|         else if (crn == 13 && opcode_1 == 0 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 CP15[CP15_PID] = value; | ||||
|             else if (opcode_2 == 1) | ||||
|                 CP15[CP15_CONTEXT_ID] = value; | ||||
|             else if (opcode_2 == 3) | ||||
|                 CP15[CP15_THREAD_URO] = value; | ||||
|             else if (opcode_2 == 4) | ||||
|                 CP15[CP15_THREAD_PRW] = value; | ||||
|         } | ||||
|         else if (crn == 15) | ||||
|         { | ||||
|             if (opcode_1 == 0 && crm == 12) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = value; | ||||
|                 else if (opcode_2 == 1) | ||||
|                     CP15[CP15_CYCLE_COUNTER] = value; | ||||
|                 else if (opcode_2 == 2) | ||||
|                     CP15[CP15_COUNT_0] = value; | ||||
|                 else if (opcode_2 == 3) | ||||
|                     CP15[CP15_COUNT_1] = value; | ||||
|             } | ||||
|             else if (opcode_1 == 5) | ||||
|             { | ||||
|                 if (crm == 4) | ||||
|                 { | ||||
|                     if (opcode_2 == 2) | ||||
|                         CP15[CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY] = value; | ||||
|                     else if (opcode_2 == 4) | ||||
|                         CP15[CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY] = value; | ||||
|                 } | ||||
|                 else if (crm == 5 && opcode_2 == 2) | ||||
|                 { | ||||
|                     CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = value; | ||||
|                 } | ||||
|                 else if (crm == 6 && opcode_2 == 2) | ||||
|                 { | ||||
|                     CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = value; | ||||
|                 } | ||||
|                 else if (crm == 7 && opcode_2 == 2) | ||||
|                 { | ||||
|                     CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = value; | ||||
|                 } | ||||
|             } | ||||
|             else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) | ||||
|             { | ||||
|                 CP15[CP15_TLB_DEBUG_CONTROL] = value; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Unprivileged registers
 | ||||
|     if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4) | ||||
|     { | ||||
|         CP15[CP15_FLUSH_PREFETCH_BUFFER] = value; | ||||
|     } | ||||
|     else if (crn == 7 && opcode_1 == 0 && crm == 10) | ||||
|     { | ||||
|         if (opcode_2 == 4) | ||||
|             CP15[CP15_DATA_SYNC_BARRIER] = value; | ||||
|         else if (opcode_2 == 5) | ||||
|             CP15[CP15_DATA_MEMORY_BARRIER] = value; | ||||
|     } | ||||
|     else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2) | ||||
|     { | ||||
|         CP15[CP15_THREAD_UPRW] = value; | ||||
|     } | ||||
| } | ||||
|  | @ -17,6 +17,7 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <array> | ||||
| #include <unordered_map> | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
|  | @ -37,67 +38,30 @@ enum { | |||
|     INSTCACHE = 2, | ||||
| }; | ||||
| 
 | ||||
| #define VFP_REG_NUM 64 | ||||
| struct ARMul_State | ||||
| { | ||||
|     u32 Emulate;       // To start and stop emulation
 | ||||
| 
 | ||||
|     // Order of the following register should not be modified
 | ||||
|     u32 Reg[16];            // The current register file
 | ||||
|     u32 Cpsr;               // The current PSR
 | ||||
|     u32 Spsr_copy; | ||||
|     u32 phys_pc; | ||||
|     u32 Reg_usr[2]; | ||||
|     u32 Reg_svc[2];         // R13_SVC R14_SVC
 | ||||
|     u32 Reg_abort[2];       // R13_ABORT R14_ABORT
 | ||||
|     u32 Reg_undef[2];       // R13 UNDEF R14 UNDEF
 | ||||
|     u32 Reg_irq[2];         // R13_IRQ R14_IRQ
 | ||||
|     u32 Reg_firq[7];        // R8---R14 FIRQ
 | ||||
|     u32 Spsr[7];            // The exception psr's
 | ||||
|     u32 Mode;               // The current mode
 | ||||
|     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 CP15[CP15_REGISTER_COUNT]; | ||||
| 
 | ||||
|     // FPSID, FPSCR, and FPEXC
 | ||||
|     u32 VFP[VFP_SYSTEM_REGISTER_COUNT]; | ||||
|     // VFPv2 and VFPv3-D16 has 16 doubleword registers (D0-D16 or S0-S31).
 | ||||
|     // VFPv3-D32/ASIMD may have up to 32 doubleword registers (D0-D31),
 | ||||
|     // and only 32 singleword registers are accessible (S0-S31).
 | ||||
|     u32 ExtReg[VFP_REG_NUM]; | ||||
|     /* ---- End of the ordered registers ---- */ | ||||
| 
 | ||||
|     u32 NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed
 | ||||
|     unsigned int shifter_carry_out; | ||||
| 
 | ||||
|     // Add armv6 flags dyf:2010-08-09
 | ||||
|     u32 GEFlag, EFlag, AFlag, QFlag; | ||||
| 
 | ||||
|     u32 TFlag; // Thumb state
 | ||||
| 
 | ||||
|     unsigned long long NumInstrs; // The number of instructions executed
 | ||||
|     unsigned NumInstrsToExecute; | ||||
| 
 | ||||
|     unsigned NresetSig; // Reset the processor
 | ||||
|     unsigned NfiqSig; | ||||
|     unsigned NirqSig; | ||||
| 
 | ||||
|     unsigned abortSig; | ||||
|     unsigned NtransSig; | ||||
|     unsigned bigendSig; | ||||
|     unsigned syscallSig; | ||||
| 
 | ||||
|     // TODO(bunnei): Move this cache to a better place - it should be per codeset (likely per
 | ||||
|     // process for our purposes), not per ARMul_State (which tracks CPU core state).
 | ||||
|     std::unordered_map<u32, int> instruction_cache; | ||||
| // ARM privilege modes
 | ||||
| enum PrivilegeMode { | ||||
|     USER32MODE   = 16, | ||||
|     FIQ32MODE    = 17, | ||||
|     IRQ32MODE    = 18, | ||||
|     SVC32MODE    = 19, | ||||
|     ABORT32MODE  = 23, | ||||
|     UNDEF32MODE  = 27, | ||||
|     SYSTEM32MODE = 31 | ||||
| }; | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                      The hardware vector addresses                        * | ||||
| \***************************************************************************/ | ||||
| // ARM privilege mode register banks
 | ||||
| enum { | ||||
|     USERBANK   = 0, | ||||
|     FIQBANK    = 1, | ||||
|     IRQBANK    = 2, | ||||
|     SVCBANK    = 3, | ||||
|     ABORTBANK  = 4, | ||||
|     UNDEFBANK  = 5, | ||||
|     DUMMYBANK  = 6, | ||||
|     SYSTEMBANK = 7 | ||||
| }; | ||||
| 
 | ||||
| // Hardware vector addresses
 | ||||
| enum { | ||||
|     ARMResetV          = 0, | ||||
|     ARMUndefinedInstrV = 4, | ||||
|  | @ -119,40 +83,7 @@ enum { | |||
|     ARMul_FIQV            = ARMFIQV | ||||
| }; | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                          Mode and Bank Constants                          * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| enum PrivilegeMode { | ||||
|     USER32MODE   = 16, | ||||
|     FIQ32MODE    = 17, | ||||
|     IRQ32MODE    = 18, | ||||
|     SVC32MODE    = 19, | ||||
|     ABORT32MODE  = 23, | ||||
|     UNDEF32MODE  = 27, | ||||
|     SYSTEM32MODE = 31 | ||||
| }; | ||||
| 
 | ||||
| enum { | ||||
|     USERBANK   = 0, | ||||
|     FIQBANK    = 1, | ||||
|     IRQBANK    = 2, | ||||
|     SVCBANK    = 3, | ||||
|     ABORTBANK  = 4, | ||||
|     UNDEFBANK  = 5, | ||||
|     DUMMYBANK  = 6, | ||||
|     SYSTEMBANK = 7 | ||||
| }; | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *                  Definitions of things in the emulator                     * | ||||
| \***************************************************************************/ | ||||
| void ARMul_Reset(ARMul_State* state); | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *            Definitions of things in the co-processor interface             * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| // Coprocessor status values
 | ||||
| enum { | ||||
|     ARMul_FIRST     = 0, | ||||
|     ARMul_TRANSFER  = 1, | ||||
|  | @ -164,10 +95,7 @@ enum { | |||
|     ARMul_INC       = 3 | ||||
| }; | ||||
| 
 | ||||
| /***************************************************************************\
 | ||||
| *               Definitions of things in the host environment                * | ||||
| \***************************************************************************/ | ||||
| 
 | ||||
| // Instruction condition codes
 | ||||
| enum ConditionCode { | ||||
|     EQ = 0, | ||||
|     NE = 1, | ||||
|  | @ -213,3 +141,93 @@ enum { | |||
|     ONCE       = 2, // Execute just one iteration
 | ||||
|     RUN        = 3  // Continuous execution
 | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| struct ARMul_State final | ||||
| { | ||||
| public: | ||||
|     explicit ARMul_State(PrivilegeMode initial_mode); | ||||
| 
 | ||||
|     void ChangePrivilegeMode(u32 new_mode); | ||||
|     void Reset(); | ||||
| 
 | ||||
|     // Reads/writes data in big/little endian format based on the
 | ||||
|     // state of the E (endian) bit in the APSR.
 | ||||
|     u16 ReadMemory16(u32 address) const; | ||||
|     u32 ReadMemory32(u32 address) const; | ||||
|     u64 ReadMemory64(u32 address) const; | ||||
|     void WriteMemory16(u32 address, u16 data); | ||||
|     void WriteMemory32(u32 address, u32 data); | ||||
|     void WriteMemory64(u32 address, u64 data); | ||||
| 
 | ||||
|     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); | ||||
| 
 | ||||
|     // Whether or not the given CPU is in big endian mode (E bit is set)
 | ||||
|     bool InBigEndianMode() const { | ||||
|         return (Cpsr & (1 << 9)) != 0; | ||||
|     } | ||||
|     // Whether or not the given CPU is in a mode other than user mode.
 | ||||
|     bool InAPrivilegedMode() const { | ||||
|         return (Mode != USER32MODE); | ||||
|     } | ||||
|     // Note that for the 3DS, a Thumb instruction will only ever be
 | ||||
|     // two bytes in size. Thus we don't need to worry about ThumbEE
 | ||||
|     // or Thumb-2 where instructions can be 4 bytes in length.
 | ||||
|     u32 GetInstructionSize() const { | ||||
|         return TFlag ? 2 : 4; | ||||
|     } | ||||
| 
 | ||||
|     std::array<u32, 16> Reg;      // The current register file
 | ||||
|     std::array<u32, 2> Reg_usr; | ||||
|     std::array<u32, 2> Reg_svc;   // R13_SVC R14_SVC
 | ||||
|     std::array<u32, 2> Reg_abort; // R13_ABORT R14_ABORT
 | ||||
|     std::array<u32, 2> Reg_undef; // R13 UNDEF R14 UNDEF
 | ||||
|     std::array<u32, 2> Reg_irq;   // R13_IRQ R14_IRQ
 | ||||
|     std::array<u32, 7> Reg_firq;  // R8---R14 FIRQ
 | ||||
|     std::array<u32, 7> Spsr;      // The exception psr's
 | ||||
|     std::array<u32, CP15_REGISTER_COUNT> CP15; | ||||
| 
 | ||||
|     // FPSID, FPSCR, and FPEXC
 | ||||
|     std::array<u32, VFP_SYSTEM_REGISTER_COUNT> VFP; | ||||
| 
 | ||||
|     // VFPv2 and VFPv3-D16 has 16 doubleword registers (D0-D16 or S0-S31).
 | ||||
|     // VFPv3-D32/ASIMD may have up to 32 doubleword registers (D0-D31),
 | ||||
|     // and only 32 singleword registers are accessible (S0-S31).
 | ||||
|     std::array<u32, 64> ExtReg; | ||||
| 
 | ||||
|     u32 Emulate; // To start and stop emulation
 | ||||
|     u32 Cpsr;    // The current PSR
 | ||||
|     u32 Spsr_copy; | ||||
|     u32 phys_pc; | ||||
| 
 | ||||
|     u32 Mode;          // The current mode
 | ||||
|     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
 | ||||
|     unsigned int shifter_carry_out; | ||||
| 
 | ||||
|     u32 TFlag; // Thumb state
 | ||||
| 
 | ||||
|     unsigned long long NumInstrs; // The number of instructions executed
 | ||||
|     unsigned NumInstrsToExecute; | ||||
| 
 | ||||
|     unsigned NresetSig; // Reset the processor
 | ||||
|     unsigned NfiqSig; | ||||
|     unsigned NirqSig; | ||||
| 
 | ||||
|     unsigned abortSig; | ||||
|     unsigned NtransSig; | ||||
|     unsigned bigendSig; | ||||
|     unsigned syscallSig; | ||||
| 
 | ||||
|     // TODO(bunnei): Move this cache to a better place - it should be per codeset (likely per
 | ||||
|     // process for our purposes), not per ARMul_State (which tracks CPU core state).
 | ||||
|     std::unordered_map<u32, int> instruction_cache; | ||||
| 
 | ||||
| private: | ||||
|     void ResetMPCoreCP15Registers(); | ||||
| }; | ||||
|  |  | |||
|  | @ -206,433 +206,3 @@ u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred) | |||
|     *saturation_occurred = false; | ||||
|     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; | ||||
| } | ||||
| 
 | ||||
| // Whether or not the given CPU is in a mode other than user mode.
 | ||||
| bool InAPrivilegedMode(ARMul_State* cpu) | ||||
| { | ||||
|     return (cpu->Mode != USER32MODE); | ||||
| } | ||||
| 
 | ||||
| // Reads from the CP15 registers. Used with implementation of the MRC instruction.
 | ||||
| // Note that since the 3DS does not have the hypervisor extensions, these registers
 | ||||
| // are not implemented.
 | ||||
| u32 ReadCP15Register(ARMul_State* cpu, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | ||||
| { | ||||
|     // Unprivileged registers
 | ||||
|     if (crn == 13 && opcode_1 == 0 && crm == 0) | ||||
|     { | ||||
|         if (opcode_2 == 2) | ||||
|             return cpu->CP15[CP15_THREAD_UPRW]; | ||||
| 
 | ||||
|         if (opcode_2 == 3) | ||||
|             return cpu->CP15[CP15_THREAD_URO]; | ||||
|     } | ||||
| 
 | ||||
|     if (InAPrivilegedMode(cpu)) | ||||
|     { | ||||
|         if (crn == 0 && opcode_1 == 0) | ||||
|         { | ||||
|             if (crm == 0) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     return cpu->CP15[CP15_MAIN_ID]; | ||||
| 
 | ||||
|                 if (opcode_2 == 1) | ||||
|                     return cpu->CP15[CP15_CACHE_TYPE]; | ||||
| 
 | ||||
|                 if (opcode_2 == 3) | ||||
|                     return cpu->CP15[CP15_TLB_TYPE]; | ||||
| 
 | ||||
|                 if (opcode_2 == 5) | ||||
|                     return cpu->CP15[CP15_CPU_ID]; | ||||
|             } | ||||
|             else if (crm == 1) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     return cpu->CP15[CP15_PROCESSOR_FEATURE_0]; | ||||
| 
 | ||||
|                 if (opcode_2 == 1) | ||||
|                     return cpu->CP15[CP15_PROCESSOR_FEATURE_1]; | ||||
| 
 | ||||
|                 if (opcode_2 == 2) | ||||
|                     return cpu->CP15[CP15_DEBUG_FEATURE_0]; | ||||
| 
 | ||||
|                 if (opcode_2 == 4) | ||||
|                     return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_0]; | ||||
| 
 | ||||
|                 if (opcode_2 == 5) | ||||
|                     return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_1]; | ||||
| 
 | ||||
|                 if (opcode_2 == 6) | ||||
|                     return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_2]; | ||||
| 
 | ||||
|                 if (opcode_2 == 7) | ||||
|                     return cpu->CP15[CP15_MEMORY_MODEL_FEATURE_3]; | ||||
|             } | ||||
|             else if (crm == 2) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     return cpu->CP15[CP15_ISA_FEATURE_0]; | ||||
| 
 | ||||
|                 if (opcode_2 == 1) | ||||
|                     return cpu->CP15[CP15_ISA_FEATURE_1]; | ||||
| 
 | ||||
|                 if (opcode_2 == 2) | ||||
|                     return cpu->CP15[CP15_ISA_FEATURE_2]; | ||||
| 
 | ||||
|                 if (opcode_2 == 3) | ||||
|                     return cpu->CP15[CP15_ISA_FEATURE_3]; | ||||
| 
 | ||||
|                 if (opcode_2 == 4) | ||||
|                     return cpu->CP15[CP15_ISA_FEATURE_4]; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (crn == 1 && opcode_1 == 0 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 return cpu->CP15[CP15_CONTROL]; | ||||
| 
 | ||||
|             if (opcode_2 == 1) | ||||
|                 return cpu->CP15[CP15_AUXILIARY_CONTROL]; | ||||
| 
 | ||||
|             if (opcode_2 == 2) | ||||
|                 return cpu->CP15[CP15_COPROCESSOR_ACCESS_CONTROL]; | ||||
|         } | ||||
| 
 | ||||
|         if (crn == 2 && opcode_1 == 0 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 return cpu->CP15[CP15_TRANSLATION_BASE_TABLE_0]; | ||||
| 
 | ||||
|             if (opcode_2 == 1) | ||||
|                 return cpu->CP15[CP15_TRANSLATION_BASE_TABLE_1]; | ||||
| 
 | ||||
|             if (opcode_2 == 2) | ||||
|                 return cpu->CP15[CP15_TRANSLATION_BASE_CONTROL]; | ||||
|         } | ||||
| 
 | ||||
|         if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | ||||
|             return cpu->CP15[CP15_DOMAIN_ACCESS_CONTROL]; | ||||
| 
 | ||||
|         if (crn == 5 && opcode_1 == 0 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 return cpu->CP15[CP15_FAULT_STATUS]; | ||||
| 
 | ||||
|             if (opcode_2 == 1) | ||||
|                 return cpu->CP15[CP15_INSTR_FAULT_STATUS]; | ||||
|         } | ||||
| 
 | ||||
|         if (crn == 6 && opcode_1 == 0 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 return cpu->CP15[CP15_FAULT_ADDRESS]; | ||||
| 
 | ||||
|             if (opcode_2 == 1) | ||||
|                 return cpu->CP15[CP15_WFAR]; | ||||
|         } | ||||
| 
 | ||||
|         if (crn == 7 && opcode_1 == 0 && crm == 4 && opcode_2 == 0) | ||||
|             return cpu->CP15[CP15_PHYS_ADDRESS]; | ||||
| 
 | ||||
|         if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | ||||
|             return cpu->CP15[CP15_DATA_CACHE_LOCKDOWN]; | ||||
| 
 | ||||
|         if (crn == 10 && opcode_1 == 0) | ||||
|         { | ||||
|             if (crm == 0 && opcode_2 == 0) | ||||
|                 return cpu->CP15[CP15_TLB_LOCKDOWN]; | ||||
| 
 | ||||
|             if (crm == 2) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     return cpu->CP15[CP15_PRIMARY_REGION_REMAP]; | ||||
| 
 | ||||
|                 if (opcode_2 == 1) | ||||
|                     return cpu->CP15[CP15_NORMAL_REGION_REMAP]; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (crn == 13 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 return cpu->CP15[CP15_PID]; | ||||
| 
 | ||||
|             if (opcode_2 == 1) | ||||
|                 return cpu->CP15[CP15_CONTEXT_ID]; | ||||
| 
 | ||||
|             if (opcode_2 == 4) | ||||
|                 return cpu->CP15[CP15_THREAD_PRW]; | ||||
|         } | ||||
| 
 | ||||
|         if (crn == 15) | ||||
|         { | ||||
|             if (opcode_1 == 0 && crm == 12) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     return cpu->CP15[CP15_PERFORMANCE_MONITOR_CONTROL]; | ||||
| 
 | ||||
|                 if (opcode_2 == 1) | ||||
|                     return cpu->CP15[CP15_CYCLE_COUNTER]; | ||||
| 
 | ||||
|                 if (opcode_2 == 2) | ||||
|                     return cpu->CP15[CP15_COUNT_0]; | ||||
| 
 | ||||
|                 if (opcode_2 == 3) | ||||
|                     return cpu->CP15[CP15_COUNT_1]; | ||||
|             } | ||||
| 
 | ||||
|             if (opcode_1 == 5 && opcode_2 == 2) | ||||
|             { | ||||
|                 if (crm == 5) | ||||
|                     return cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS]; | ||||
| 
 | ||||
|                 if (crm == 6) | ||||
|                     return cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS]; | ||||
| 
 | ||||
|                 if (crm == 7) | ||||
|                     return cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE]; | ||||
|             } | ||||
| 
 | ||||
|             if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) | ||||
|                 return cpu->CP15[CP15_TLB_DEBUG_CONTROL]; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     LOG_ERROR(Core_ARM11, "MRC CRn=%u, CRm=%u, OP1=%u OP2=%u is not implemented. Returning zero.", crn, crm, opcode_1, opcode_2); | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| // Write to the CP15 registers. Used with implementation of the MCR instruction.
 | ||||
| // Note that since the 3DS does not have the hypervisor extensions, these registers
 | ||||
| // are not implemented.
 | ||||
| void WriteCP15Register(ARMul_State* cpu, u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2) | ||||
| { | ||||
|     if (InAPrivilegedMode(cpu)) | ||||
|     { | ||||
|         if (crn == 1 && opcode_1 == 0 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 cpu->CP15[CP15_CONTROL] = value; | ||||
|             else if (opcode_2 == 1) | ||||
|                 cpu->CP15[CP15_AUXILIARY_CONTROL] = value; | ||||
|             else if (opcode_2 == 2) | ||||
|                 cpu->CP15[CP15_COPROCESSOR_ACCESS_CONTROL] = value; | ||||
|         } | ||||
|         else if (crn == 2 && opcode_1 == 0 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 cpu->CP15[CP15_TRANSLATION_BASE_TABLE_0] = value; | ||||
|             else if (opcode_2 == 1) | ||||
|                 cpu->CP15[CP15_TRANSLATION_BASE_TABLE_1] = value; | ||||
|             else if (opcode_2 == 2) | ||||
|                 cpu->CP15[CP15_TRANSLATION_BASE_CONTROL] = value; | ||||
|         } | ||||
|         else if (crn == 3 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | ||||
|         { | ||||
|             cpu->CP15[CP15_DOMAIN_ACCESS_CONTROL] = value; | ||||
|         } | ||||
|         else if (crn == 5 && opcode_1 == 0 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 cpu->CP15[CP15_FAULT_STATUS] = value; | ||||
|             else if (opcode_2 == 1) | ||||
|                 cpu->CP15[CP15_INSTR_FAULT_STATUS] = value; | ||||
|         } | ||||
|         else if (crn == 6 && opcode_1 == 0 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 cpu->CP15[CP15_FAULT_ADDRESS] = value; | ||||
|             else if (opcode_2 == 1) | ||||
|                 cpu->CP15[CP15_WFAR] = value; | ||||
|         } | ||||
|         else if (crn == 7 && opcode_1 == 0) | ||||
|         { | ||||
|             if (crm == 0 && opcode_2 == 4) | ||||
|             { | ||||
|                 cpu->CP15[CP15_WAIT_FOR_INTERRUPT] = value; | ||||
|             } | ||||
|             else if (crm == 4 && opcode_2 == 0) | ||||
|             { | ||||
|                 // NOTE: Not entirely accurate. This should do permission checks.
 | ||||
|                 cpu->CP15[CP15_PHYS_ADDRESS] = Memory::VirtualToPhysicalAddress(value); | ||||
|             } | ||||
|             else if (crm == 5) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     cpu->CP15[CP15_INVALIDATE_INSTR_CACHE] = value; | ||||
|                 else if (opcode_2 == 1) | ||||
|                     cpu->CP15[CP15_INVALIDATE_INSTR_CACHE_USING_MVA] = value; | ||||
|                 else if (opcode_2 == 2) | ||||
|                     cpu->CP15[CP15_INVALIDATE_INSTR_CACHE_USING_INDEX] = value; | ||||
|                 else if (opcode_2 == 6) | ||||
|                     cpu->CP15[CP15_FLUSH_BRANCH_TARGET_CACHE] = value; | ||||
|                 else if (opcode_2 == 7) | ||||
|                     cpu->CP15[CP15_FLUSH_BRANCH_TARGET_CACHE_ENTRY] = value; | ||||
|             } | ||||
|             else if (crm == 6) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     cpu->CP15[CP15_INVALIDATE_DATA_CACHE] = value; | ||||
|                 else if (opcode_2 == 1) | ||||
|                     cpu->CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value; | ||||
|                 else if (opcode_2 == 2) | ||||
|                     cpu->CP15[CP15_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; | ||||
|             } | ||||
|             else if (crm == 7 && opcode_2 == 0) | ||||
|             { | ||||
|                 cpu->CP15[CP15_INVALIDATE_DATA_AND_INSTR_CACHE] = value; | ||||
|             } | ||||
|             else if (crm == 10) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     cpu->CP15[CP15_CLEAN_DATA_CACHE] = value; | ||||
|                 else if (opcode_2 == 1) | ||||
|                     cpu->CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_MVA] = value; | ||||
|                 else if (opcode_2 == 2) | ||||
|                     cpu->CP15[CP15_CLEAN_DATA_CACHE_LINE_USING_INDEX] = value; | ||||
|             } | ||||
|             else if (crm == 14) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     cpu->CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE] = value; | ||||
|                 else if (opcode_2 == 1) | ||||
|                     cpu->CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_MVA] = value; | ||||
|                 else if (opcode_2 == 2) | ||||
|                     cpu->CP15[CP15_CLEAN_AND_INVALIDATE_DATA_CACHE_LINE_USING_INDEX] = value; | ||||
|             } | ||||
|         } | ||||
|         else if (crn == 8 && opcode_1 == 0) | ||||
|         { | ||||
|             LOG_WARNING(Core_ARM11, "TLB operations not fully implemented."); | ||||
| 
 | ||||
|             if (crm == 5) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     cpu->CP15[CP15_INVALIDATE_ITLB] = value; | ||||
|                 else if (opcode_2 == 1) | ||||
|                     cpu->CP15[CP15_INVALIDATE_ITLB_SINGLE_ENTRY] = value; | ||||
|                 else if (opcode_2 == 2) | ||||
|                     cpu->CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_ASID_MATCH] = value; | ||||
|                 else if (opcode_2 == 3) | ||||
|                     cpu->CP15[CP15_INVALIDATE_ITLB_ENTRY_ON_MVA] = value; | ||||
|             } | ||||
|             else if (crm == 6) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     cpu->CP15[CP15_INVALIDATE_DTLB] = value; | ||||
|                 else if (opcode_2 == 1) | ||||
|                     cpu->CP15[CP15_INVALIDATE_DTLB_SINGLE_ENTRY] = value; | ||||
|                 else if (opcode_2 == 2) | ||||
|                     cpu->CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_ASID_MATCH] = value; | ||||
|                 else if (opcode_2 == 3) | ||||
|                     cpu->CP15[CP15_INVALIDATE_DTLB_ENTRY_ON_MVA] = value; | ||||
|             } | ||||
|             else if (crm == 7) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     cpu->CP15[CP15_INVALIDATE_UTLB] = value; | ||||
|                 else if (opcode_2 == 1) | ||||
|                     cpu->CP15[CP15_INVALIDATE_UTLB_SINGLE_ENTRY] = value; | ||||
|                 else if (opcode_2 == 2) | ||||
|                     cpu->CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_ASID_MATCH] = value; | ||||
|                 else if (opcode_2 == 3) | ||||
|                     cpu->CP15[CP15_INVALIDATE_UTLB_ENTRY_ON_MVA] = value; | ||||
|             } | ||||
|         } | ||||
|         else if (crn == 9 && opcode_1 == 0 && crm == 0 && opcode_2 == 0) | ||||
|         { | ||||
|             cpu->CP15[CP15_DATA_CACHE_LOCKDOWN] = value; | ||||
|         } | ||||
|         else if (crn == 10 && opcode_1 == 0) | ||||
|         { | ||||
|             if (crm == 0 && opcode_2 == 0) | ||||
|             { | ||||
|                 cpu->CP15[CP15_TLB_LOCKDOWN] = value; | ||||
|             } | ||||
|             else if (crm == 2) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     cpu->CP15[CP15_PRIMARY_REGION_REMAP] = value; | ||||
|                 else if (opcode_2 == 1) | ||||
|                     cpu->CP15[CP15_NORMAL_REGION_REMAP] = value; | ||||
|             } | ||||
|         } | ||||
|         else if (crn == 13 && opcode_1 == 0 && crm == 0) | ||||
|         { | ||||
|             if (opcode_2 == 0) | ||||
|                 cpu->CP15[CP15_PID] = value; | ||||
|             else if (opcode_2 == 1) | ||||
|                 cpu->CP15[CP15_CONTEXT_ID] = value; | ||||
|             else if (opcode_2 == 3) | ||||
|                 cpu->CP15[CP15_THREAD_URO] = value; | ||||
|             else if (opcode_2 == 4) | ||||
|                 cpu->CP15[CP15_THREAD_PRW] = value; | ||||
|         } | ||||
|         else if (crn == 15) | ||||
|         { | ||||
|             if (opcode_1 == 0 && crm == 12) | ||||
|             { | ||||
|                 if (opcode_2 == 0) | ||||
|                     cpu->CP15[CP15_PERFORMANCE_MONITOR_CONTROL] = value; | ||||
|                 else if (opcode_2 == 1) | ||||
|                     cpu->CP15[CP15_CYCLE_COUNTER] = value; | ||||
|                 else if (opcode_2 == 2) | ||||
|                     cpu->CP15[CP15_COUNT_0] = value; | ||||
|                 else if (opcode_2 == 3) | ||||
|                     cpu->CP15[CP15_COUNT_1] = value; | ||||
|             } | ||||
|             else if (opcode_1 == 5) | ||||
|             { | ||||
|                 if (crm == 4) | ||||
|                 { | ||||
|                     if (opcode_2 == 2) | ||||
|                         cpu->CP15[CP15_READ_MAIN_TLB_LOCKDOWN_ENTRY] = value; | ||||
|                     else if (opcode_2 == 4) | ||||
|                         cpu->CP15[CP15_WRITE_MAIN_TLB_LOCKDOWN_ENTRY] = value; | ||||
|                 } | ||||
|                 else if (crm == 5 && opcode_2 == 2) | ||||
|                 { | ||||
|                     cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_VIRT_ADDRESS] = value; | ||||
|                 } | ||||
|                 else if (crm == 6 && opcode_2 == 2) | ||||
|                 { | ||||
|                     cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_PHYS_ADDRESS] = value; | ||||
|                 } | ||||
|                 else if (crm == 7 && opcode_2 == 2) | ||||
|                 { | ||||
|                     cpu->CP15[CP15_MAIN_TLB_LOCKDOWN_ATTRIBUTE] = value; | ||||
|                 } | ||||
|             } | ||||
|             else if (opcode_1 == 7 && crm == 1 && opcode_2 == 0) | ||||
|             { | ||||
|                 cpu->CP15[CP15_TLB_DEBUG_CONTROL] = value; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Unprivileged registers
 | ||||
|     if (crn == 7 && opcode_1 == 0 && crm == 5 && opcode_2 == 4) | ||||
|     { | ||||
|         cpu->CP15[CP15_FLUSH_PREFETCH_BUFFER] = value; | ||||
|     } | ||||
|     else if (crn == 7 && opcode_1 == 0 && crm == 10) | ||||
|     { | ||||
|        if (opcode_2 == 4) | ||||
|            cpu->CP15[CP15_DATA_SYNC_BARRIER] = value; | ||||
|        else if (opcode_2 == 5) | ||||
|            cpu->CP15[CP15_DATA_MEMORY_BARRIER] = value; | ||||
| 
 | ||||
|     } | ||||
|     else if (crn == 13 && opcode_1 == 0 && crm == 0 && opcode_2 == 2) | ||||
|     { | ||||
|         cpu->CP15[CP15_THREAD_UPRW] = value; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -6,8 +6,6 @@ | |||
| 
 | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| struct ARMul_State; | ||||
| 
 | ||||
| #define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1)) | ||||
| #define BIT(s, n) ((s >> (n)) & 1) | ||||
| 
 | ||||
|  | @ -32,9 +30,3 @@ u16 ARMul_UnsignedSaturatedSub16(u16, u16); | |||
| u8 ARMul_UnsignedAbsoluteDifference(u8, u8); | ||||
| u32 ARMul_SignedSatQ(s32, u8, bool*); | ||||
| u32 ARMul_UnsignedSatQ(s32, u8, bool*); | ||||
| 
 | ||||
| bool InBigEndianMode(ARMul_State*); | ||||
| bool InAPrivilegedMode(ARMul_State*); | ||||
| 
 | ||||
| u32 ReadCP15Register(ARMul_State* cpu, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2); | ||||
| void WriteCP15Register(ARMul_State* cpu, u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2); | ||||
|  |  | |||
|  | @ -51,7 +51,7 @@ VMLA_INST: | |||
| 
 | ||||
|         CHECK_VFP_CDP_RET; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vmla_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -100,7 +100,7 @@ VMLS_INST: | |||
| 
 | ||||
|         CHECK_VFP_CDP_RET; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vmls_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -149,7 +149,7 @@ VNMLA_INST: | |||
| 
 | ||||
|         CHECK_VFP_CDP_RET; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vnmla_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -199,7 +199,7 @@ VNMLS_INST: | |||
| 
 | ||||
|         CHECK_VFP_CDP_RET; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vnmls_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -248,7 +248,7 @@ VNMUL_INST: | |||
| 
 | ||||
|         CHECK_VFP_CDP_RET; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vnmul_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -297,7 +297,7 @@ VMUL_INST: | |||
| 
 | ||||
|         CHECK_VFP_CDP_RET; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vmul_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -346,7 +346,7 @@ VADD_INST: | |||
| 
 | ||||
|         CHECK_VFP_CDP_RET; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vadd_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -395,7 +395,7 @@ VSUB_INST: | |||
| 
 | ||||
|         CHECK_VFP_CDP_RET; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vsub_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -444,7 +444,7 @@ VDIV_INST: | |||
| 
 | ||||
|         CHECK_VFP_CDP_RET; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vdiv_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -492,7 +492,7 @@ VMOVI_INST: | |||
| 
 | ||||
|         VMOVI(cpu, inst_cream->single, inst_cream->d, inst_cream->imm); | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vmovi_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -536,7 +536,7 @@ VMOVR_INST: | |||
| 
 | ||||
|         VMOVR(cpu, inst_cream->single, inst_cream->d, inst_cream->m); | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vmovr_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -585,7 +585,7 @@ VABS_INST: | |||
| 
 | ||||
|         CHECK_VFP_CDP_RET; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vabs_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -635,7 +635,7 @@ VNEG_INST: | |||
| 
 | ||||
|         CHECK_VFP_CDP_RET; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vneg_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -684,7 +684,7 @@ VSQRT_INST: | |||
| 
 | ||||
|         CHECK_VFP_CDP_RET; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vsqrt_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -733,7 +733,7 @@ VCMP_INST: | |||
| 
 | ||||
|         CHECK_VFP_CDP_RET; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vcmp_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -782,7 +782,7 @@ VCMP2_INST: | |||
| 
 | ||||
|         CHECK_VFP_CDP_RET; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vcmp2_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -831,7 +831,7 @@ VCVTBDS_INST: | |||
| 
 | ||||
|         CHECK_VFP_CDP_RET; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vcvtbds_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -882,7 +882,7 @@ VCVTBFF_INST: | |||
| 
 | ||||
|         CHECK_VFP_CDP_RET; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vcvtbff_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -931,7 +931,7 @@ VCVTBFI_INST: | |||
| 
 | ||||
|         CHECK_VFP_CDP_RET; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vcvtbfi_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -981,7 +981,7 @@ VMOVBRS_INST: | |||
| 
 | ||||
|         VMOVBRS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->n, &(cpu->Reg[inst_cream->t])); | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vmovbrs_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -1032,7 +1032,7 @@ VMSR_INST: | |||
|         { | ||||
|             cpu->VFP[VFP_FPSCR] = cpu->Reg[rt]; | ||||
|         } | ||||
|         else if (InAPrivilegedMode(cpu)) | ||||
|         else if (cpu->InAPrivilegedMode()) | ||||
|         { | ||||
|             if (reg == 8) | ||||
|                 cpu->VFP[VFP_FPEXC] = cpu->Reg[rt]; | ||||
|  | @ -1042,7 +1042,7 @@ VMSR_INST: | |||
|                 cpu->VFP[VFP_FPINST2] = cpu->Reg[rt]; | ||||
|         } | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vmsr_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -1090,7 +1090,7 @@ VMOVBRC_INST: | |||
| 
 | ||||
|         cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index] = cpu->Reg[inst_cream->t]; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vmovbrc_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -1163,7 +1163,7 @@ VMRS_INST: | |||
|         { | ||||
|             cpu->Reg[rt] = cpu->VFP[VFP_MVFR0]; | ||||
|         } | ||||
|         else if (InAPrivilegedMode(cpu)) | ||||
|         else if (cpu->InAPrivilegedMode()) | ||||
|         { | ||||
|             if (reg == 8) | ||||
|                 cpu->Reg[rt] = cpu->VFP[VFP_FPEXC]; | ||||
|  | @ -1173,7 +1173,7 @@ VMRS_INST: | |||
|                 cpu->Reg[rt] = cpu->VFP[VFP_FPINST2]; | ||||
|         } | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vmrs_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -1221,7 +1221,7 @@ VMOVBCR_INST: | |||
| 
 | ||||
|         cpu->Reg[inst_cream->t] = cpu->ExtReg[(2 * inst_cream->d) + inst_cream->index]; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vmovbcr_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -1274,7 +1274,7 @@ VMOVBRRSS_INST: | |||
|         VMOVBRRSS(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m, | ||||
|             &cpu->Reg[inst_cream->t], &cpu->Reg[inst_cream->t2]); | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vmovbrrss_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -1322,7 +1322,7 @@ VMOVBRRD_INST: | |||
|         VMOVBRRD(cpu, inst_cream->to_arm, inst_cream->t, inst_cream->t2, inst_cream->m, | ||||
|             &(cpu->Reg[inst_cream->t]), &(cpu->Reg[inst_cream->t2])); | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vmovbrrd_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -1378,23 +1378,23 @@ VSTR_INST: | |||
| 
 | ||||
|         if (inst_cream->single) | ||||
|         { | ||||
|             WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d]); | ||||
|             cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d]); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             const u32 word1 = cpu->ExtReg[inst_cream->d*2+0]; | ||||
|             const u32 word2 = cpu->ExtReg[inst_cream->d*2+1]; | ||||
| 
 | ||||
|             if (InBigEndianMode(cpu)) { | ||||
|                 WriteMemory32(cpu, addr + 0, word2); | ||||
|                 WriteMemory32(cpu, addr + 4, word1); | ||||
|             if (cpu->InBigEndianMode()) { | ||||
|                 cpu->WriteMemory32(addr + 0, word2); | ||||
|                 cpu->WriteMemory32(addr + 4, word1); | ||||
|             } else { | ||||
|                 WriteMemory32(cpu, addr + 0, word1); | ||||
|                 WriteMemory32(cpu, addr + 4, word2); | ||||
|                 cpu->WriteMemory32(addr + 0, word1); | ||||
|                 cpu->WriteMemory32(addr + 4, word2); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vstr_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -1444,7 +1444,7 @@ VPUSH_INST: | |||
|         { | ||||
|             if (inst_cream->single) | ||||
|             { | ||||
|                 WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]); | ||||
|                 cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d+i]); | ||||
|                 addr += 4; | ||||
|             } | ||||
|             else | ||||
|  | @ -1452,12 +1452,12 @@ VPUSH_INST: | |||
|                 const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0]; | ||||
|                 const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1]; | ||||
| 
 | ||||
|                 if (InBigEndianMode(cpu)) { | ||||
|                     WriteMemory32(cpu, addr + 0, word2); | ||||
|                     WriteMemory32(cpu, addr + 4, word1); | ||||
|                 if (cpu->InBigEndianMode()) { | ||||
|                     cpu->WriteMemory32(addr + 0, word2); | ||||
|                     cpu->WriteMemory32(addr + 4, word1); | ||||
|                 } else { | ||||
|                     WriteMemory32(cpu, addr + 0, word1); | ||||
|                     WriteMemory32(cpu, addr + 4, word2); | ||||
|                     cpu->WriteMemory32(addr + 0, word1); | ||||
|                     cpu->WriteMemory32(addr + 4, word2); | ||||
|                 } | ||||
| 
 | ||||
|                 addr += 8; | ||||
|  | @ -1466,7 +1466,7 @@ VPUSH_INST: | |||
| 
 | ||||
|         cpu->Reg[R13] -= inst_cream->imm32; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vpush_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -1522,7 +1522,7 @@ VSTM_INST: /* encoding 1 */ | |||
|         { | ||||
|             if (inst_cream->single) | ||||
|             { | ||||
|                 WriteMemory32(cpu, addr, cpu->ExtReg[inst_cream->d+i]); | ||||
|                 cpu->WriteMemory32(addr, cpu->ExtReg[inst_cream->d+i]); | ||||
|                 addr += 4; | ||||
|             } | ||||
|             else | ||||
|  | @ -1530,12 +1530,12 @@ VSTM_INST: /* encoding 1 */ | |||
|                 const u32 word1 = cpu->ExtReg[(inst_cream->d+i)*2+0]; | ||||
|                 const u32 word2 = cpu->ExtReg[(inst_cream->d+i)*2+1]; | ||||
| 
 | ||||
|                 if (InBigEndianMode(cpu)) { | ||||
|                     WriteMemory32(cpu, addr + 0, word2); | ||||
|                     WriteMemory32(cpu, addr + 4, word1); | ||||
|                 if (cpu->InBigEndianMode()) { | ||||
|                     cpu->WriteMemory32(addr + 0, word2); | ||||
|                     cpu->WriteMemory32(addr + 4, word1); | ||||
|                 } else { | ||||
|                     WriteMemory32(cpu, addr + 0, word1); | ||||
|                     WriteMemory32(cpu, addr + 4, word2); | ||||
|                     cpu->WriteMemory32(addr + 0, word1); | ||||
|                     cpu->WriteMemory32(addr + 4, word2); | ||||
|                 } | ||||
| 
 | ||||
|                 addr += 8; | ||||
|  | @ -1597,15 +1597,15 @@ VPOP_INST: | |||
|         { | ||||
|             if (inst_cream->single) | ||||
|             { | ||||
|                 cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr); | ||||
|                 cpu->ExtReg[inst_cream->d+i] = cpu->ReadMemory32(addr); | ||||
|                 addr += 4; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 const u32 word1 = ReadMemory32(cpu, addr + 0); | ||||
|                 const u32 word2 = ReadMemory32(cpu, addr + 4); | ||||
|                 const u32 word1 = cpu->ReadMemory32(addr + 0); | ||||
|                 const u32 word2 = cpu->ReadMemory32(addr + 4); | ||||
| 
 | ||||
|                 if (InBigEndianMode(cpu)) { | ||||
|                 if (cpu->InBigEndianMode()) { | ||||
|                     cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; | ||||
|                     cpu->ExtReg[(inst_cream->d+i)*2+1] = word1; | ||||
|                 } else { | ||||
|  | @ -1618,7 +1618,7 @@ VPOP_INST: | |||
|         } | ||||
|         cpu->Reg[R13] += inst_cream->imm32; | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vpop_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -1670,14 +1670,14 @@ VLDR_INST: | |||
| 
 | ||||
|         if (inst_cream->single) | ||||
|         { | ||||
|             cpu->ExtReg[inst_cream->d] = ReadMemory32(cpu, addr); | ||||
|             cpu->ExtReg[inst_cream->d] = cpu->ReadMemory32(addr); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             const u32 word1 = ReadMemory32(cpu, addr + 0); | ||||
|             const u32 word2 = ReadMemory32(cpu, addr + 4); | ||||
|             const u32 word1 = cpu->ReadMemory32(addr + 0); | ||||
|             const u32 word2 = cpu->ReadMemory32(addr + 4); | ||||
| 
 | ||||
|             if (InBigEndianMode(cpu)) { | ||||
|             if (cpu->InBigEndianMode()) { | ||||
|                 cpu->ExtReg[inst_cream->d*2+0] = word2; | ||||
|                 cpu->ExtReg[inst_cream->d*2+1] = word1; | ||||
|             } else { | ||||
|  | @ -1686,7 +1686,7 @@ VLDR_INST: | |||
|             } | ||||
|         } | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vldr_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  | @ -1742,15 +1742,15 @@ VLDM_INST: | |||
|         { | ||||
|             if (inst_cream->single) | ||||
|             { | ||||
|                 cpu->ExtReg[inst_cream->d+i] = ReadMemory32(cpu, addr); | ||||
|                 cpu->ExtReg[inst_cream->d+i] = cpu->ReadMemory32(addr); | ||||
|                 addr += 4; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 const u32 word1 = ReadMemory32(cpu, addr + 0); | ||||
|                 const u32 word2 = ReadMemory32(cpu, addr + 4); | ||||
|                 const u32 word1 = cpu->ReadMemory32(addr + 0); | ||||
|                 const u32 word2 = cpu->ReadMemory32(addr + 4); | ||||
| 
 | ||||
|                 if (InBigEndianMode(cpu)) { | ||||
|                 if (cpu->InBigEndianMode()) { | ||||
|                     cpu->ExtReg[(inst_cream->d+i)*2+0] = word2; | ||||
|                     cpu->ExtReg[(inst_cream->d+i)*2+1] = word1; | ||||
|                 } else { | ||||
|  | @ -1766,7 +1766,7 @@ VLDM_INST: | |||
|                 cpu->Reg[inst_cream->n] - inst_cream->imm32); | ||||
|         } | ||||
|     } | ||||
|     cpu->Reg[15] += GET_INST_SIZE(cpu); | ||||
|     cpu->Reg[15] += cpu->GetInstructionSize(); | ||||
|     INC_PC(sizeof(vldm_inst)); | ||||
|     FETCH_INST; | ||||
|     GOTO_NEXT_INST; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue