summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author arbee <rb6502@users.noreply.github.com>2017-11-15 23:55:09 -0500
committer arbee <rb6502@users.noreply.github.com>2017-11-15 23:55:09 -0500
commit78ceb48177b77fc27438a344b5a44959127dacf0 (patch)
tree67e317acda894e0e69b4fbe7192e56a42b55f9f0
parentb503e9c8c223e2e3cdd55ecd386b5a5d01ae8339 (diff)
arm7: add support for high vector option, fixed v5 BLX to save the return address in R14 [R. Belmont]
-rw-r--r--src/devices/cpu/arm7/arm7.cpp3
-rw-r--r--src/devices/cpu/arm7/arm7.h11
-rw-r--r--src/devices/cpu/arm7/arm7core.hxx7
-rw-r--r--src/devices/cpu/arm7/arm7ops.cpp4
-rw-r--r--src/mame/drivers/nds.cpp10
5 files changed, 27 insertions, 8 deletions
diff --git a/src/devices/cpu/arm7/arm7.cpp b/src/devices/cpu/arm7/arm7.cpp
index d6b324fc31a..6c745cec5f9 100644
--- a/src/devices/cpu/arm7/arm7.cpp
+++ b/src/devices/cpu/arm7/arm7.cpp
@@ -68,6 +68,7 @@ arm7_cpu_device::arm7_cpu_device(const machine_config &mconfig, device_type type
, m_endian(endianness)
, m_archRev(archRev)
, m_archFlags(archFlags)
+ , m_vectorbase(0)
, m_pc(0)
{
memset(m_r, 0x00, sizeof(m_r));
@@ -662,7 +663,7 @@ void arm7_cpu_device::device_reset()
/* start up in SVC mode with interrupts disabled. */
m_r[eCPSR] = I_MASK | F_MASK | 0x10;
SwitchMode(eARM7_MODE_SVC);
- m_r[eR15] = 0;
+ m_r[eR15] = 0 | m_vectorbase;
m_impstate.cache_dirty = true;
}
diff --git a/src/devices/cpu/arm7/arm7.h b/src/devices/cpu/arm7/arm7.h
index 1a9681232bb..38b7d185b63 100644
--- a/src/devices/cpu/arm7/arm7.h
+++ b/src/devices/cpu/arm7/arm7.h
@@ -31,6 +31,9 @@
#define ARM7_MAX_FASTRAM 4
#define ARM7_MAX_HOTSPOTS 16
+#define MCFG_ARM_HIGH_VECTORS() \
+ arm7_cpu_device::set_high_vectors(*device);
+
/***************************************************************************
COMPILER-SPECIFIC OPTIONS
@@ -52,6 +55,12 @@ public:
// construction/destruction
arm7_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ static void set_high_vectors(device_t &device)
+ {
+ arm7_cpu_device &dev = downcast<arm7_cpu_device &>(device);
+ dev.m_vectorbase = 0xffff0000;
+ }
+
protected:
enum
{
@@ -168,6 +177,8 @@ protected:
uint8_t m_archRev; // ARM architecture revision (3, 4, and 5 are valid)
uint8_t m_archFlags; // architecture flags
+ uint32_t m_vectorbase;
+
//#if ARM7_MMU_ENABLE_HACK
// uint32_t mmu_enable_addr; // workaround for "MMU is enabled when PA != VA" problem
//#endif
diff --git a/src/devices/cpu/arm7/arm7core.hxx b/src/devices/cpu/arm7/arm7core.hxx
index 0e418209e73..0fbe5f00868 100644
--- a/src/devices/cpu/arm7/arm7core.hxx
+++ b/src/devices/cpu/arm7/arm7core.hxx
@@ -136,6 +136,7 @@ void arm7_cpu_device::arm7_check_irq_state()
set_cpsr(GET_CPSR | I_MASK | F_MASK); /* Mask both IRQ & FIQ */
set_cpsr(GET_CPSR & ~T_MASK);
R15 = 0x1c; /* IRQ Vector address */
+ R15 |= m_vectorbase;
if ((COPRO_CTRL & COPRO_CTRL_MMU_EN) && (COPRO_CTRL & COPRO_CTRL_INTVEC_ADJUST)) R15 |= 0xFFFF0000;
return;
}
@@ -159,6 +160,7 @@ void arm7_cpu_device::arm7_check_irq_state()
temp = (GET_CPSR & 0x0FFFFF3F) /* N Z C V I F */ | (R15 & 0xF0000000) /* N Z C V */ | ((R15 & 0x0C000000) >> (26 - 6)) /* I F */;
set_cpsr(temp); /* Mask IRQ */
}
+ R15 |= m_vectorbase;
if ((COPRO_CTRL & COPRO_CTRL_MMU_EN) && (COPRO_CTRL & COPRO_CTRL_INTVEC_ADJUST)) R15 |= 0xFFFF0000;
return;
}
@@ -172,7 +174,7 @@ void arm7_cpu_device::arm7_check_irq_state()
SetRegister(SPSR, cpsr); /* Save current CPSR */
set_cpsr(GET_CPSR | I_MASK); /* Mask IRQ */
set_cpsr(GET_CPSR & ~T_MASK);
- R15 = 0x0c; /* IRQ Vector address */
+ R15 = 0x0c | m_vectorbase; /* IRQ Vector address */
if ((COPRO_CTRL & COPRO_CTRL_MMU_EN) && (COPRO_CTRL & COPRO_CTRL_INTVEC_ADJUST)) R15 |= 0xFFFF0000;
m_pendingAbtP = false;
update_irq_state();
@@ -196,7 +198,7 @@ void arm7_cpu_device::arm7_check_irq_state()
SetRegister(SPSR, cpsr); /* Save current CPSR */
set_cpsr(GET_CPSR | I_MASK); /* Mask IRQ */
set_cpsr(GET_CPSR & ~T_MASK);
- R15 = 0x04; /* IRQ Vector address */
+ R15 = 0x04 | m_vectorbase; /* IRQ Vector address */
if ((COPRO_CTRL & COPRO_CTRL_MMU_EN) && (COPRO_CTRL & COPRO_CTRL_INTVEC_ADJUST)) R15 |= 0xFFFF0000;
m_pendingUnd = false;
update_irq_state();
@@ -230,6 +232,7 @@ void arm7_cpu_device::arm7_check_irq_state()
temp = (GET_CPSR & 0x0FFFFF3F) /* N Z C V I F */ | (R15 & 0xF0000000) /* N Z C V */ | ((R15 & 0x0C000000) >> (26 - 6)) /* I F */;
set_cpsr(temp); /* Mask IRQ */
}
+ R15 |= m_vectorbase;
if ((COPRO_CTRL & COPRO_CTRL_MMU_EN) && (COPRO_CTRL & COPRO_CTRL_INTVEC_ADJUST)) R15 |= 0xFFFF0000;
m_pendingSwi = false;
update_irq_state();
diff --git a/src/devices/cpu/arm7/arm7ops.cpp b/src/devices/cpu/arm7/arm7ops.cpp
index dd65d8ae765..5b71b7e8d9f 100644
--- a/src/devices/cpu/arm7/arm7ops.cpp
+++ b/src/devices/cpu/arm7/arm7ops.cpp
@@ -380,8 +380,8 @@ void arm7_cpu_device::HandleBranch(uint32_t insn, bool h_bit)
off |= (insn & 0x01000000) >> 23;
}
- /* Save PC into LR if this is a branch with link */
- if (insn & INSN_BL)
+ /* Save PC into LR if this is a branch with link or a BLX */
+ if ((insn & INSN_BL) || ((m_archRev >= 5) && ((insn & 0xfe000000) == 0xfa000000)))
{
SetRegister(14, R15 + 4);
}
diff --git a/src/mame/drivers/nds.cpp b/src/mame/drivers/nds.cpp
index 485d7c45a42..c9844a0702b 100644
--- a/src/mame/drivers/nds.cpp
+++ b/src/mame/drivers/nds.cpp
@@ -105,16 +105,17 @@ WRITE32_MEMBER(nds_state::arm9_io_w)
}
static ADDRESS_MAP_START( nds_arm7_map, AS_PROGRAM, 32, nds_state )
- AM_RANGE(0x00000000, 0x00003fff) AM_ROM
- AM_RANGE(0x02000000, 0x023fffff) AM_RAM AM_SHARE("mainram")
+ AM_RANGE(0x00000000, 0x00003fff) AM_ROM AM_REGION("arm7", 0)
+ AM_RANGE(0x02000000, 0x023fffff) AM_RAM AM_MIRROR(0x00400000) AM_SHARE("mainram")
AM_RANGE(0x03800000, 0x0380ffff) AM_RAM
AM_RANGE(0x04000000, 0x0400ffff) AM_READWRITE(arm7_io_r, arm7_io_w)
ADDRESS_MAP_END
static ADDRESS_MAP_START( nds_arm9_map, AS_PROGRAM, 32, nds_state )
- AM_RANGE(0x00000000, 0x00000fff) AM_ROM
+ AM_RANGE(0x00000000, 0x00007fff) AM_RAM // Instruction TCM
AM_RANGE(0x02000000, 0x023fffff) AM_RAM AM_SHARE("mainram")
AM_RANGE(0x04000000, 0x0400ffff) AM_READWRITE(arm9_io_r, arm9_io_w)
+ AM_RANGE(0xffff0000, 0xffff0fff) AM_ROM AM_MIRROR(0x1000) AM_REGION("arm9", 0)
ADDRESS_MAP_END
static INPUT_PORTS_START( nds )
@@ -134,9 +135,12 @@ void nds_state::machine_start()
static MACHINE_CONFIG_START( nds )
MCFG_CPU_ADD("arm7", ARM7, XTAL_33_333MHz)
MCFG_CPU_PROGRAM_MAP(nds_arm7_map)
+ MCFG_DEVICE_DISABLE()
MCFG_CPU_ADD("arm9", ARM946ES, XTAL_66_6667MHz)
+ MCFG_ARM_HIGH_VECTORS()
MCFG_CPU_PROGRAM_MAP(nds_arm9_map)
+
MACHINE_CONFIG_END
/* Help identifying the region and revisions of the set would be greatly appreciated! */