diff options
Diffstat (limited to 'src/core/arm/skyeye_common')
-rw-r--r-- | src/core/arm/skyeye_common/armdefs.h | 318 | ||||
-rw-r--r-- | src/core/arm/skyeye_common/armmmu.h | 103 | ||||
-rw-r--r-- | src/core/arm/skyeye_common/armstate.cpp | 657 | ||||
-rw-r--r-- | src/core/arm/skyeye_common/armstate.h | 252 | ||||
-rw-r--r-- | src/core/arm/skyeye_common/armsupp.cpp | 208 | ||||
-rw-r--r-- | src/core/arm/skyeye_common/armsupp.h | 32 | ||||
-rw-r--r-- | src/core/arm/skyeye_common/vfp/vfp.cpp | 12 | ||||
-rw-r--r-- | src/core/arm/skyeye_common/vfp/vfp.h | 10 | ||||
-rw-r--r-- | src/core/arm/skyeye_common/vfp/vfp_helper.h | 4 | ||||
-rw-r--r-- | src/core/arm/skyeye_common/vfp/vfpdouble.cpp | 12 | ||||
-rw-r--r-- | src/core/arm/skyeye_common/vfp/vfpinstr.cpp | 126 |
11 files changed, 1231 insertions, 503 deletions
diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h deleted file mode 100644 index d2c901100..000000000 --- a/src/core/arm/skyeye_common/armdefs.h +++ /dev/null @@ -1,318 +0,0 @@ -/* armdefs.h -- ARMulator common definitions: 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. */ - -#pragma once - -#include <unordered_map> - -#include "common/common_types.h" -#include "core/arm/skyeye_common/arm_regformat.h" - -#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1)) -#define BIT(s, n) ((s >> (n)) & 1) - -// Signal levels -enum { - LOW = 0, - HIGH = 1, - LOWHIGH = 1, - HIGHLOW = 2 -}; - -// Cache types -enum { - NONCACHE = 0, - DATACACHE = 1, - INSTCACHE = 2, -}; - -// Abort models -enum { - ABORT_BASE_RESTORED = 0, - ABORT_EARLY = 1, - ABORT_BASE_UPDATED = 2 -}; - -#define POS(i) ( (~(i)) >> 31 ) -#define NEG(i) ( (i) >> 31 ) - -typedef u64 ARMdword; // must be 64 bits wide -typedef u32 ARMword; // must be 32 bits wide -typedef u16 ARMhword; // must be 16 bits wide -typedef u8 ARMbyte; // must be 8 bits wide - -#define VFP_REG_NUM 64 -struct ARMul_State -{ - ARMword Emulate; // To start and stop emulation - - // Order of the following register should not be modified - ARMword Reg[16]; // The current register file - ARMword Cpsr; // The current PSR - ARMword Spsr_copy; - ARMword phys_pc; - ARMword Reg_usr[2]; - ARMword Reg_svc[2]; // R13_SVC R14_SVC - ARMword Reg_abort[2]; // R13_ABORT R14_ABORT - ARMword Reg_undef[2]; // R13 UNDEF R14 UNDEF - ARMword Reg_irq[2]; // R13_IRQ R14_IRQ - ARMword Reg_firq[7]; // R8---R14 FIRQ - ARMword Spsr[7]; // The exception psr's - ARMword Mode; // The current mode - ARMword Bank; // The current register bank - ARMword exclusive_tag; // The address for which the local monitor is in exclusive access mode - ARMword exclusive_state; - ARMword exclusive_result; - ARMword CP15[CP15_REGISTER_COUNT]; - - // FPSID, FPSCR, and FPEXC - ARMword 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). - ARMword ExtReg[VFP_REG_NUM]; - /* ---- End of the ordered registers ---- */ - - ARMword NFlag, ZFlag, CFlag, VFlag, IFFlags; // Dummy flags for speed - unsigned int shifter_carry_out; - - // Add armv6 flags dyf:2010-08-09 - ARMword GEFlag, EFlag, AFlag, QFlag; - - ARMword 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; - -/* 2004-05-09 chy ----------------------------------------------------------- -read ARM Architecture Reference Manual -2.6.5 Data Abort -There are three Abort Model in ARM arch. - -Early Abort Model: used in some ARMv3 and earlier implementations. In this -model, base register wirteback occurred for LDC,LDM,STC,STM instructions, and -the base register was unchanged for all other instructions. (oldest) - -Base Restored Abort Model: If a Data Abort occurs in an instruction which -specifies base register writeback, the value in the base register is -unchanged. (strongarm, xscale) - -Base Updated Abort Model: If a Data Abort occurs in an instruction which -specifies base register writeback, the base register writeback still occurs. -(arm720T) - -read PART B -chap2 The System Control Coprocessor CP15 -2.4 Register1:control register -L(bit 6): in some ARMv3 and earlier implementations, the abort model of the -processor could be configured: -0=early Abort Model Selected(now obsolete) -1=Late Abort Model selceted(same as Base Updated Abort Model) - -on later processors, this bit reads as 1 and ignores writes. -------------------------------------------------------------- -So, if lateabtSig=1, then it means Late Abort Model(Base Updated Abort Model) - if lateabtSig=0, then it means Base Restored Abort Model -*/ - unsigned lateabtSig; - - // For differentiating ARM core emulaiton. - bool is_v4; // Are we emulating a v4 architecture (or higher)? - bool is_v5; // Are we emulating a v5 architecture? - bool is_v5e; // Are we emulating a v5e architecture? - bool is_v6; // Are we emulating a v6 architecture? - bool is_v7; // Are we emulating a v7 architecture? - - // ARM_ARM A2-18 - // 0 Base Restored Abort Model, 1 the Early Abort Model, 2 Base Updated Abort Model - int abort_model; - - // 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; -}; - -/***************************************************************************\ -* Types of ARM we know about * -\***************************************************************************/ - -enum { - ARM_v4_Prop = 0x01, - ARM_v5_Prop = 0x02, - ARM_v5e_Prop = 0x04, - ARM_v6_Prop = 0x08, - ARM_v7_Prop = 0x10, -}; - -/***************************************************************************\ -* The hardware vector addresses * -\***************************************************************************/ - -enum { - ARMResetV = 0, - ARMUndefinedInstrV = 4, - ARMSWIV = 8, - ARMPrefetchAbortV = 12, - ARMDataAbortV = 16, - ARMAddrExceptnV = 20, - ARMIRQV = 24, - ARMFIQV = 28, - ARMErrorV = 32, // This is an offset, not an address! - - ARMul_ResetV = ARMResetV, - ARMul_UndefinedInstrV = ARMUndefinedInstrV, - ARMul_SWIV = ARMSWIV, - ARMul_PrefetchAbortV = ARMPrefetchAbortV, - ARMul_DataAbortV = ARMDataAbortV, - ARMul_AddrExceptnV = ARMAddrExceptnV, - ARMul_IRQV = ARMIRQV, - 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 -}; - -/***************************************************************************\ -* Definitons of things in the emulator * -\***************************************************************************/ -extern void ARMul_Reset(ARMul_State* state); -extern ARMul_State* ARMul_NewState(ARMul_State* state); - -/***************************************************************************\ -* Definitons of things in the co-processor interface * -\***************************************************************************/ - -enum { - ARMul_FIRST = 0, - ARMul_TRANSFER = 1, - ARMul_BUSY = 2, - ARMul_DATA = 3, - ARMul_INTERRUPT = 4, - ARMul_DONE = 0, - ARMul_CANT = 1, - ARMul_INC = 3 -}; - -/***************************************************************************\ -* Definitons of things in the host environment * -\***************************************************************************/ - -enum ConditionCode { - EQ = 0, - NE = 1, - CS = 2, - CC = 3, - MI = 4, - PL = 5, - VS = 6, - VC = 7, - HI = 8, - LS = 9, - GE = 10, - LT = 11, - GT = 12, - LE = 13, - AL = 14, - NV = 15, -}; - -// Flags for use with the APSR. -enum : u32 { - NBIT = (1U << 31U), - ZBIT = (1 << 30), - CBIT = (1 << 29), - VBIT = (1 << 28), - QBIT = (1 << 27), - JBIT = (1 << 24), - EBIT = (1 << 9), - ABIT = (1 << 8), - IBIT = (1 << 7), - FBIT = (1 << 6), - TBIT = (1 << 5), - - // Masks for groups of bits in the APSR. - MODEBITS = 0x1F, - INTBITS = 0x1C0, -}; - -// Values for Emulate. -enum { - STOP = 0, // Stop - CHANGEMODE = 1, // Change mode - ONCE = 2, // Execute just one iteration - RUN = 3 // Continuous execution -}; - - -extern bool AddOverflow(ARMword, ARMword, ARMword); -extern bool SubOverflow(ARMword, ARMword, ARMword); - -extern void ARMul_SelectProcessor(ARMul_State*, unsigned); - -extern u32 AddWithCarry(u32, u32, u32, bool*, bool*); -extern bool ARMul_AddOverflowQ(ARMword, ARMword); - -extern u8 ARMul_SignedSaturatedAdd8(u8, u8); -extern u8 ARMul_SignedSaturatedSub8(u8, u8); -extern u16 ARMul_SignedSaturatedAdd16(u16, u16); -extern u16 ARMul_SignedSaturatedSub16(u16, u16); - -extern u8 ARMul_UnsignedSaturatedAdd8(u8, u8); -extern u16 ARMul_UnsignedSaturatedAdd16(u16, u16); -extern u8 ARMul_UnsignedSaturatedSub8(u8, u8); -extern u16 ARMul_UnsignedSaturatedSub16(u16, u16); -extern u8 ARMul_UnsignedAbsoluteDifference(u8, u8); -extern u32 ARMul_SignedSatQ(s32, u8, bool*); -extern u32 ARMul_UnsignedSatQ(s32, u8, bool*); - -extern bool InBigEndianMode(ARMul_State*); -extern bool InAPrivilegedMode(ARMul_State*); - -extern u32 ReadCP15Register(ARMul_State* cpu, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2); -extern void WriteCP15Register(ARMul_State* cpu, u32 value, u32 crn, u32 opcode_1, u32 crm, u32 opcode_2); diff --git a/src/core/arm/skyeye_common/armmmu.h b/src/core/arm/skyeye_common/armmmu.h deleted file mode 100644 index c67d7209b..000000000 --- a/src/core/arm/skyeye_common/armmmu.h +++ /dev/null @@ -1,103 +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/armdefs.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); -} diff --git a/src/core/arm/skyeye_common/armstate.cpp b/src/core/arm/skyeye_common/armstate.cpp new file mode 100644 index 000000000..ccb2eb0eb --- /dev/null +++ b/src/core/arm/skyeye_common/armstate.cpp @@ -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; + } +} diff --git a/src/core/arm/skyeye_common/armstate.h b/src/core/arm/skyeye_common/armstate.h new file mode 100644 index 000000000..b364e2621 --- /dev/null +++ b/src/core/arm/skyeye_common/armstate.h @@ -0,0 +1,252 @@ +/* armdefs.h -- ARMulator common definitions: 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. */ + +#pragma once + +#include <array> +#include <unordered_map> + +#include "common/common_types.h" +#include "core/arm/skyeye_common/arm_regformat.h" + +// Signal levels +enum { + LOW = 0, + HIGH = 1, + LOWHIGH = 1, + HIGHLOW = 2 +}; + +// Cache types +enum { + NONCACHE = 0, + DATACACHE = 1, + INSTCACHE = 2, +}; + +// ARM privilege modes +enum PrivilegeMode { + USER32MODE = 16, + FIQ32MODE = 17, + IRQ32MODE = 18, + SVC32MODE = 19, + ABORT32MODE = 23, + UNDEF32MODE = 27, + SYSTEM32MODE = 31 +}; + +// 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, + ARMSWIV = 8, + ARMPrefetchAbortV = 12, + ARMDataAbortV = 16, + ARMAddrExceptnV = 20, + ARMIRQV = 24, + ARMFIQV = 28, + ARMErrorV = 32, // This is an offset, not an address! + + ARMul_ResetV = ARMResetV, + ARMul_UndefinedInstrV = ARMUndefinedInstrV, + ARMul_SWIV = ARMSWIV, + ARMul_PrefetchAbortV = ARMPrefetchAbortV, + ARMul_DataAbortV = ARMDataAbortV, + ARMul_AddrExceptnV = ARMAddrExceptnV, + ARMul_IRQV = ARMIRQV, + ARMul_FIQV = ARMFIQV +}; + +// Coprocessor status values +enum { + ARMul_FIRST = 0, + ARMul_TRANSFER = 1, + ARMul_BUSY = 2, + ARMul_DATA = 3, + ARMul_INTERRUPT = 4, + ARMul_DONE = 0, + ARMul_CANT = 1, + ARMul_INC = 3 +}; + +// Instruction condition codes +enum ConditionCode { + EQ = 0, + NE = 1, + CS = 2, + CC = 3, + MI = 4, + PL = 5, + VS = 6, + VC = 7, + HI = 8, + LS = 9, + GE = 10, + LT = 11, + GT = 12, + LE = 13, + AL = 14, + NV = 15, +}; + +// Flags for use with the APSR. +enum : u32 { + NBIT = (1U << 31U), + ZBIT = (1 << 30), + CBIT = (1 << 29), + VBIT = (1 << 28), + QBIT = (1 << 27), + JBIT = (1 << 24), + EBIT = (1 << 9), + ABIT = (1 << 8), + IBIT = (1 << 7), + FBIT = (1 << 6), + TBIT = (1 << 5), + + // Masks for groups of bits in the APSR. + MODEBITS = 0x1F, + INTBITS = 0x1C0, +}; + +// Values for Emulate. +enum { + STOP = 0, // Stop + CHANGEMODE = 1, // Change mode + 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); + + // Exclusive memory access functions + bool IsExclusiveMemoryAccess(u32 address) const { + return exclusive_state && exclusive_tag == (address & RESERVATION_GRANULE_MASK); + } + void SetExclusiveMemoryAddress(u32 address) { + exclusive_tag = address & RESERVATION_GRANULE_MASK; + exclusive_state = true; + } + void UnsetExclusiveMemoryAddress() { + exclusive_tag = 0xFFFFFFFF; + exclusive_state = false; + } + + // Whether or not the given CPU is in big endian mode (E bit is set) + 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 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(); + + // Defines a reservation granule of 2 words, which protects the first 2 words starting at the tag. + // This is the smallest granule allowed by the v7 spec, and is coincidentally just large enough to + // support LDR/STREXD. + static const u32 RESERVATION_GRANULE_MASK = 0xFFFFFFF8; + + u32 exclusive_tag; // The address for which the local monitor is in exclusive access mode + u32 exclusive_result; + bool exclusive_state; +}; diff --git a/src/core/arm/skyeye_common/armsupp.cpp b/src/core/arm/skyeye_common/armsupp.cpp new file mode 100644 index 000000000..d31fb9449 --- /dev/null +++ b/src/core/arm/skyeye_common/armsupp.cpp @@ -0,0 +1,208 @@ +/* armsupp.c -- ARMulator support code: 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 "common/logging/log.h" + +#include "core/mem_map.h" +#include "core/arm/skyeye_common/arm_regformat.h" +#include "core/arm/skyeye_common/armstate.h" +#include "core/arm/skyeye_common/armsupp.h" + +// Unsigned sum of absolute difference +u8 ARMul_UnsignedAbsoluteDifference(u8 left, u8 right) +{ + if (left > right) + return left - right; + + return right - left; +} + +// Add with carry, indicates if a carry-out or signed overflow occurred. +u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bool* overflow_occurred) +{ + u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in; + s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in; + u64 result = (unsigned_sum & 0xFFFFFFFF); + + if (carry_out_occurred) + *carry_out_occurred = (result != unsigned_sum); + + if (overflow_occurred) + *overflow_occurred = ((s64)(s32)result != signed_sum); + + return (u32)result; +} + +// Compute whether an addition of A and B, giving RESULT, overflowed. +bool AddOverflow(u32 a, u32 b, u32 result) +{ + return ((NEG(a) && NEG(b) && POS(result)) || + (POS(a) && POS(b) && NEG(result))); +} + +// Compute whether a subtraction of A and B, giving RESULT, overflowed. +bool SubOverflow(u32 a, u32 b, u32 result) +{ + return ((NEG(a) && POS(b) && POS(result)) || + (POS(a) && NEG(b) && NEG(result))); +} + +// Returns true if the Q flag should be set as a result of overflow. +bool ARMul_AddOverflowQ(u32 a, u32 b) +{ + u32 result = a + b; + if (((result ^ a) & (u32)0x80000000) && ((a ^ b) & (u32)0x80000000) == 0) + return true; + + return false; +} + +// 8-bit signed saturated addition +u8 ARMul_SignedSaturatedAdd8(u8 left, u8 right) +{ + u8 result = left + right; + + if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) == 0) { + if (left & 0x80) + result = 0x80; + else + result = 0x7F; + } + + return result; +} + +// 8-bit signed saturated subtraction +u8 ARMul_SignedSaturatedSub8(u8 left, u8 right) +{ + u8 result = left - right; + + if (((result ^ left) & 0x80) && ((left ^ right) & 0x80) != 0) { + if (left & 0x80) + result = 0x80; + else + result = 0x7F; + } + + return result; +} + +// 16-bit signed saturated addition +u16 ARMul_SignedSaturatedAdd16(u16 left, u16 right) +{ + u16 result = left + right; + + if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) == 0) { + if (left & 0x8000) + result = 0x8000; + else + result = 0x7FFF; + } + + return result; +} + +// 16-bit signed saturated subtraction +u16 ARMul_SignedSaturatedSub16(u16 left, u16 right) +{ + u16 result = left - right; + + if (((result ^ left) & 0x8000) && ((left ^ right) & 0x8000) != 0) { + if (left & 0x8000) + result = 0x8000; + else + result = 0x7FFF; + } + + return result; +} + +// 8-bit unsigned saturated addition +u8 ARMul_UnsignedSaturatedAdd8(u8 left, u8 right) +{ + u8 result = left + right; + + if (result < left) + result = 0xFF; + + return result; +} + +// 16-bit unsigned saturated addition +u16 ARMul_UnsignedSaturatedAdd16(u16 left, u16 right) +{ + u16 result = left + right; + + if (result < left) + result = 0xFFFF; + + return result; +} + +// 8-bit unsigned saturated subtraction +u8 ARMul_UnsignedSaturatedSub8(u8 left, u8 right) +{ + if (left <= right) + return 0; + + return left - right; +} + +// 16-bit unsigned saturated subtraction +u16 ARMul_UnsignedSaturatedSub16(u16 left, u16 right) +{ + if (left <= right) + return 0; + + return left - right; +} + +// Signed saturation. +u32 ARMul_SignedSatQ(s32 value, u8 shift, bool* saturation_occurred) +{ + const u32 max = (1 << shift) - 1; + const s32 top = (value >> shift); + + if (top > 0) { + *saturation_occurred = true; + return max; + } + else if (top < -1) { + *saturation_occurred = true; + return ~max; + } + + *saturation_occurred = false; + return (u32)value; +} + +// Unsigned saturation +u32 ARMul_UnsignedSatQ(s32 value, u8 shift, bool* saturation_occurred) +{ + const u32 max = (1 << shift) - 1; + + if (value < 0) { + *saturation_occurred = true; + return 0; + } else if ((u32)value > max) { + *saturation_occurred = true; + return max; + } + + *saturation_occurred = false; + return (u32)value; +} diff --git a/src/core/arm/skyeye_common/armsupp.h b/src/core/arm/skyeye_common/armsupp.h new file mode 100644 index 000000000..391309fa8 --- /dev/null +++ b/src/core/arm/skyeye_common/armsupp.h @@ -0,0 +1,32 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "common/common_types.h" + +#define BITS(s, a, b) ((s << ((sizeof(s) * 8 - 1) - b)) >> (sizeof(s) * 8 - b + a - 1)) +#define BIT(s, n) ((s >> (n)) & 1) + +#define POS(i) ( (~(i)) >> 31 ) +#define NEG(i) ( (i) >> 31 ) + +bool AddOverflow(u32, u32, u32); +bool SubOverflow(u32, u32, u32); + +u32 AddWithCarry(u32, u32, u32, bool*, bool*); +bool ARMul_AddOverflowQ(u32, u32); + +u8 ARMul_SignedSaturatedAdd8(u8, u8); +u8 ARMul_SignedSaturatedSub8(u8, u8); +u16 ARMul_SignedSaturatedAdd16(u16, u16); +u16 ARMul_SignedSaturatedSub16(u16, u16); + +u8 ARMul_UnsignedSaturatedAdd8(u8, u8); +u16 ARMul_UnsignedSaturatedAdd16(u16, u16); +u8 ARMul_UnsignedSaturatedSub8(u8, u8); +u16 ARMul_UnsignedSaturatedSub16(u16, u16); +u8 ARMul_UnsignedAbsoluteDifference(u8, u8); +u32 ARMul_SignedSatQ(s32, u8, bool*); +u32 ARMul_UnsignedSatQ(s32, u8, bool*); diff --git a/src/core/arm/skyeye_common/vfp/vfp.cpp b/src/core/arm/skyeye_common/vfp/vfp.cpp index 1ffc1f9af..26f303de4 100644 --- a/src/core/arm/skyeye_common/vfp/vfp.cpp +++ b/src/core/arm/skyeye_common/vfp/vfp.cpp @@ -23,7 +23,7 @@ #include "common/common_funcs.h" #include "common/logging/log.h" -#include "core/arm/skyeye_common/armdefs.h" +#include "core/arm/skyeye_common/armstate.h" #include "core/arm/skyeye_common/vfp/asm_vfp.h" #include "core/arm/skyeye_common/vfp/vfp.h" @@ -43,7 +43,7 @@ void VFPInit(ARMul_State* state) state->VFP[VFP_MVFR1] = 0; } -void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value) +void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value) { if (to_arm) { @@ -55,7 +55,7 @@ void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* } } -void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2) +void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) { if (to_arm) { @@ -68,7 +68,7 @@ void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword state->ExtReg[n*2] = *value1; } } -void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2) +void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2) { if (to_arm) { @@ -82,7 +82,7 @@ void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMwor } } -void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm) +void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm) { if (single) { @@ -95,7 +95,7 @@ void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm) state->ExtReg[d*2] = 0; } } -void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword m) +void VMOVR(ARMul_State* state, u32 single, u32 d, u32 m) { if (single) { diff --git a/src/core/arm/skyeye_common/vfp/vfp.h b/src/core/arm/skyeye_common/vfp/vfp.h index 80ca93ccd..88908da9f 100644 --- a/src/core/arm/skyeye_common/vfp/vfp.h +++ b/src/core/arm/skyeye_common/vfp/vfp.h @@ -36,8 +36,8 @@ void vfp_raise_exceptions(ARMul_State* state, u32 exceptions, u32 inst, u32 fpsc u32 vfp_single_cpdo(ARMul_State* state, u32 inst, u32 fpscr); u32 vfp_double_cpdo(ARMul_State* state, u32 inst, u32 fpscr); -void VMOVBRS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword n, ARMword* value); -void VMOVBRRD(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2); -void VMOVBRRSS(ARMul_State* state, ARMword to_arm, ARMword t, ARMword t2, ARMword n, ARMword* value1, ARMword* value2); -void VMOVI(ARMul_State* state, ARMword single, ARMword d, ARMword imm); -void VMOVR(ARMul_State* state, ARMword single, ARMword d, ARMword imm); +void VMOVBRS(ARMul_State* state, u32 to_arm, u32 t, u32 n, u32* value); +void VMOVBRRD(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2); +void VMOVBRRSS(ARMul_State* state, u32 to_arm, u32 t, u32 t2, u32 n, u32* value1, u32* value2); +void VMOVI(ARMul_State* state, u32 single, u32 d, u32 imm); +void VMOVR(ARMul_State* state, u32 single, u32 d, u32 imm); diff --git a/src/core/arm/skyeye_common/vfp/vfp_helper.h b/src/core/arm/skyeye_common/vfp/vfp_helper.h index 2007d6dc4..91a8d4d57 100644 --- a/src/core/arm/skyeye_common/vfp/vfp_helper.h +++ b/src/core/arm/skyeye_common/vfp/vfp_helper.h @@ -34,7 +34,7 @@ #include <cstdio> #include "common/common_types.h" -#include "core/arm/skyeye_common/armdefs.h" +#include "core/arm/skyeye_common/armstate.h" #include "core/arm/skyeye_common/vfp/asm_vfp.h" #define do_div(n, base) {n/=base;} @@ -415,7 +415,7 @@ struct op { u32 flags; }; -static inline u32 fls(ARMword x) +static inline u32 fls(u32 x) { int r = 32; diff --git a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp index f91049585..1d844a66e 100644 --- a/src/core/arm/skyeye_common/vfp/vfpdouble.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpdouble.cpp @@ -70,9 +70,9 @@ static void vfp_double_dump(const char *str, struct vfp_double *d) static void vfp_double_normalise_denormal(struct vfp_double *vd) { - int bits = 31 - fls((ARMword)(vd->significand >> 32)); + int bits = 31 - fls((u32)(vd->significand >> 32)); if (bits == 31) - bits = 63 - fls((ARMword)vd->significand); + bits = 63 - fls((u32)vd->significand); vfp_double_dump("normalise_denormal: in", vd); @@ -109,9 +109,9 @@ u32 vfp_double_normaliseround(ARMul_State* state, int dd, struct vfp_double *vd, exponent = vd->exponent; significand = vd->significand; - shift = 32 - fls((ARMword)(significand >> 32)); + shift = 32 - fls((u32)(significand >> 32)); if (shift == 32) - shift = 64 - fls((ARMword)significand); + shift = 64 - fls((u32)significand); if (shift) { exponent -= shift; significand <<= shift; @@ -566,7 +566,7 @@ static u32 vfp_double_ftoui(ARMul_State* state, int sd, int unused, int dm, u32 /* * 2^0 <= m < 2^32-2^8 */ - d = (ARMword)((vdm.significand << 1) >> shift); + d = (u32)((vdm.significand << 1) >> shift); rem = vdm.significand << (65 - shift); if (rmode == FPSCR_ROUND_NEAREST) { @@ -647,7 +647,7 @@ static u32 vfp_double_ftosi(ARMul_State* state, int sd, int unused, int dm, u32 int shift = 1023 + 63 - vdm.exponent; /* 58 */ u64 rem, incr = 0; - d = (ARMword)((vdm.significand << 1) >> shift); + d = (u32)((vdm.significand << 1) >> shift); rem = vdm.significand << (65 - shift); if (rmode == FPSCR_ROUND_NEAREST) { diff --git a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp index 8efcbab1c..9b99fc5bc 100644 --- a/src/core/arm/skyeye_common/vfp/vfpinstr.cpp +++ b/src/core/arm/skyeye_common/vfp/vfpinstr.cpp @@ -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; |