summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/arm/arm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/arm/arm.cpp')
-rw-r--r--src/devices/cpu/arm/arm.cpp79
1 files changed, 26 insertions, 53 deletions
diff --git a/src/devices/cpu/arm/arm.cpp b/src/devices/cpu/arm/arm.cpp
index 13a6cf7c64b..03b610e86dc 100644
--- a/src/devices/cpu/arm/arm.cpp
+++ b/src/devices/cpu/arm/arm.cpp
@@ -1,7 +1,7 @@
// license:BSD-3-Clause
// copyright-holders:Bryan McPhail, Phil Stroffolino
/*
- ARM 2/3/6 Emulation (26 bit address bus)
+ ARM 2/3 Emulation (26 bit address bus, no separate PSRs)
Todo:
- Timing - Currently very approximated, nothing relies on proper timing so far.
@@ -18,7 +18,6 @@
#include "emu.h"
#include "arm.h"
-#include "debugger.h"
#include "armdasm.h"
#define ARM_DEBUG_CORE 0
@@ -213,16 +212,10 @@ enum
COND_NV /* never */
};
-#define LSL(v,s) ((v) << (s))
-#define LSR(v,s) ((v) >> (s))
-#define ROL(v,s) (LSL((v),(s)) | (LSR((v),32u - (s))))
-#define ROR(v,s) (LSR((v),(s)) | (LSL((v),32u - (s))))
-
/***************************************************************************/
-DEFINE_DEVICE_TYPE(ARM, arm_cpu_device, "arm_le", "ARM (little)")
-DEFINE_DEVICE_TYPE(ARM_BE, arm_be_cpu_device, "arm_be", "ARM (big)")
+DEFINE_DEVICE_TYPE(ARM, arm_cpu_device, "arm_cpu", "ARM")
device_memory_interface::space_config_vector arm_cpu_device::memory_space_config() const
@@ -233,27 +226,20 @@ device_memory_interface::space_config_vector arm_cpu_device::memory_space_config
}
arm_cpu_device::arm_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : arm_cpu_device(mconfig, ARM, tag, owner, clock, ENDIANNESS_LITTLE)
+ : arm_cpu_device(mconfig, ARM, tag, owner, clock)
{
}
-arm_cpu_device::arm_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, endianness_t endianness)
+arm_cpu_device::arm_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: cpu_device(mconfig, type, tag, owner, clock)
- , m_program_config("program", endianness, 32, 26, 0)
- , m_endian(endianness)
+ , m_program_config("program", ENDIANNESS_LITTLE, 32, 26, 0)
, m_copro_type(copro_type::UNKNOWN_CP15)
{
std::fill(std::begin(m_sArmRegister), std::end(m_sArmRegister), 0);
}
-arm_be_cpu_device::arm_be_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : arm_cpu_device(mconfig, ARM_BE, tag, owner, clock, ENDIANNESS_BIG)
-{
-}
-
-
void arm_cpu_device::cpu_write32( int addr, uint32_t data )
{
@@ -278,11 +264,11 @@ uint32_t arm_cpu_device::cpu_read32( int addr )
logerror("%08x: Unaligned byte read %08x\n",R15,addr);
if ((addr&3)==1)
- return ((result&0x000000ff)<<24)|((result&0xffffff00)>> 8);
+ return rotr_32(result, 8);
if ((addr&3)==2)
- return ((result&0x0000ffff)<<16)|((result&0xffff0000)>>16);
+ return rotr_32(result, 16);
if ((addr&3)==3)
- return ((result&0x00ffffff)<< 8)|((result&0xff000000)>>24);
+ return rotr_32(result, 24);
}
return result;
@@ -343,7 +329,7 @@ void arm_cpu_device::execute_run()
/* load instruction */
uint32_t pc = R15;
- uint32_t insn = m_pr32( pc & ADDRESS_MASK );
+ uint32_t insn = m_cache.read_dword( pc & ADDRESS_MASK );
switch (insn >> INSN_COND_SHIFT)
{
@@ -448,10 +434,10 @@ void arm_cpu_device::arm_check_irq_state()
{
uint32_t pc = R15+4; /* save old pc (already incremented in pipeline) */;
- /* Exception priorities (from ARM6, not specifically ARM2/3):
+ /* Exception priorities for ARM2/3:
Reset
- Data abort
+ Data abort or address exception
FIRQ
IRQ
Prefetch abort
@@ -460,19 +446,19 @@ void arm_cpu_device::arm_check_irq_state()
if (m_pendingFiq && (pc&F_MASK)==0)
{
+ standard_irq_callback(ARM_FIRQ_LINE, R15 & ADDRESS_MASK);
R15 = eARM_MODE_FIQ; /* Set FIQ mode so PC is saved to correct R14 bank */
SetRegister( 14, pc ); /* save PC */
R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x1c|eARM_MODE_FIQ|I_MASK|F_MASK; /* Mask both IRQ & FIRQ, set PC=0x1c */
- standard_irq_callback(ARM_FIRQ_LINE);
return;
}
if (m_pendingIrq && (pc&I_MASK)==0)
{
+ standard_irq_callback(ARM_IRQ_LINE, R15 & ADDRESS_MASK);
R15 = eARM_MODE_IRQ; /* Set IRQ mode so PC is saved to correct R14 bank */
SetRegister( 14, pc ); /* save PC */
R15 = (pc&PSR_MASK)|(pc&IRQ_MASK)|0x18|eARM_MODE_IRQ|I_MASK|(pc&F_MASK); /* Mask only IRQ, set PC=0x18 */
- standard_irq_callback(ARM_IRQ_LINE);
return;
}
}
@@ -497,13 +483,7 @@ void arm_cpu_device::device_start()
{
m_program = &space(AS_PROGRAM);
- if(m_program->endianness() == ENDIANNESS_LITTLE) {
- m_program->cache(m_cachele);
- m_pr32 = [this](offs_t address) -> u32 { return m_cachele.read_dword(address); };
- } else {
- m_program->cache(m_cachebe);
- m_pr32 = [this](offs_t address) -> u32 { return m_cachebe.read_dword(address); };
- }
+ m_program->cache(m_cache);
save_item(NAME(m_sArmRegister));
save_item(NAME(m_coproRegister));
@@ -539,8 +519,8 @@ void arm_cpu_device::device_start()
state_add( ARM32_SR13, "SR13", m_sArmRegister[eR13_SVC] ).formatstr("%08X");
state_add( ARM32_SR14, "SR14", m_sArmRegister[eR14_SVC] ).formatstr("%08X");
- state_add(STATE_GENPC, "GENPC", m_sArmRegister[15]).mask(ADDRESS_MASK).formatstr("%8s").noshow();
- state_add(STATE_GENPCBASE, "CURPC", m_sArmRegister[15]).mask(ADDRESS_MASK).formatstr("%8s").noshow();
+ state_add(STATE_GENPC, "GENPC", m_sArmRegister[15]).mask(ADDRESS_MASK).noshow();
+ state_add(STATE_GENPCBASE, "CURPC", m_sArmRegister[15]).mask(ADDRESS_MASK).noshow();
state_add(STATE_GENFLAGS, "GENFLAGS", m_sArmRegister[15]).formatstr("%11s").noshow();
set_icountptr(m_icount);
@@ -580,14 +560,7 @@ void arm_cpu_device::HandleBranch( uint32_t insn )
}
/* Sign-extend the 24-bit offset in our calculations */
- if (off & 0x2000000u)
- {
- R15 = ((R15 - (((~(off | 0xfc000000u)) + 1) - 8)) & ADDRESS_MASK) | (R15 & ~ADDRESS_MASK);
- }
- else
- {
- R15 = ((R15 + (off + 8)) & ADDRESS_MASK) | (R15 & ~ADDRESS_MASK);
- }
+ R15 = ((R15 + (util::sext(off, 26) + 8)) & ADDRESS_MASK) | (R15 & ~ADDRESS_MASK);
m_icount -= 2 * S_CYCLE + N_CYCLE;
}
@@ -765,7 +738,7 @@ void arm_cpu_device::HandleMemSingle( uint32_t insn )
((R15 &~ (N_MASK | Z_MASK | V_MASK | C_MASK)) \
| (((!SIGN_BITS_DIFFER(rn, op2)) && SIGN_BITS_DIFFER(rn, rd)) \
<< V_BIT) \
- | (((~(rn)) < (op2)) << C_BIT) \
+ | (((IsNeg(rn) & IsNeg(op2)) | (IsNeg(rn) & IsPos(rd)) | (IsNeg(op2) & IsPos(rd))) ? C_MASK : 0) \
| HandleALUNZFlags(rd)) \
+ 4; \
else R15 += 4;
@@ -811,7 +784,7 @@ void arm_cpu_device::HandleALU( uint32_t insn )
by = (insn & INSN_OP2_ROTATE) >> INSN_OP2_ROTATE_SHIFT;
if (by)
{
- op2 = ROR(insn & INSN_OP2_IMM, by << 1);
+ op2 = rotr_32(insn & INSN_OP2_IMM, by << 1);
sc = op2 & SIGN_BIT;
}
else
@@ -824,7 +797,7 @@ void arm_cpu_device::HandleALU( uint32_t insn )
{
op2 = decodeShift(insn, (insn & INSN_S) ? &sc : nullptr);
- if (!(insn & INSN_S))
+ if (!(insn & INSN_S))
sc=0;
}
@@ -1327,7 +1300,7 @@ uint32_t arm_cpu_device::decodeShift(uint32_t insn, uint32_t *pCarry)
{
*pCarry = k ? (rm & (1 << (32 - k))) : (R15 & C_MASK);
}
- return k ? LSL(rm, k) : rm;
+ return rm << k;
case 1: /* LSR */
if (k == 0 || k == 32)
@@ -1343,7 +1316,7 @@ uint32_t arm_cpu_device::decodeShift(uint32_t insn, uint32_t *pCarry)
else
{
if (pCarry) *pCarry = (rm & (1 << (k - 1)));
- return LSR(rm, k);
+ return rm >> k;
}
case 2: /* ASR */
@@ -1355,9 +1328,9 @@ uint32_t arm_cpu_device::decodeShift(uint32_t insn, uint32_t *pCarry)
else
{
if (rm & SIGN_BIT)
- return LSR(rm, k) | (0xffffffffu << (32 - k));
+ return (rm >> k) | (0xffffffffu << (32 - k));
else
- return LSR(rm, k);
+ return (rm >> k);
}
case 3: /* ROR and RRX */
@@ -1365,12 +1338,12 @@ uint32_t arm_cpu_device::decodeShift(uint32_t insn, uint32_t *pCarry)
{
while (k > 32) k -= 32;
if (pCarry) *pCarry = rm & (1 << (k - 1));
- return ROR(rm, k);
+ return rotr_32(rm, k);
}
else
{
if (pCarry) *pCarry = (rm & 1);
- return LSR(rm, 1) | ((R15 & C_MASK) << 2);
+ return (rm >> 1) | ((R15 & C_MASK) << 2);
}
}