summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Wilbert Pol <wilbert@jdg.info>2010-07-25 13:42:34 +0000
committer Wilbert Pol <wilbert@jdg.info>2010-07-25 13:42:34 +0000
commit18785817cb4995b99ea73f8c39857a49840bb07c (patch)
treeba7bac6c05bf0a8db94998b84b5a760ab437c41b /src
parent4607ee58e90d63db78e94f979bec46e710ee1959 (diff)
arm.c: Added a big endian version of the arm2/3/6 cpu core and cleaned up the little/big endian handling. [Wilbert Pol]
Diffstat (limited to 'src')
-rw-r--r--src/emu/cpu/arm/arm.c90
-rw-r--r--src/emu/cpu/arm/arm.h3
-rw-r--r--src/emu/cpu/arm/armdasm.c7
3 files changed, 74 insertions, 26 deletions
diff --git a/src/emu/cpu/arm/arm.c b/src/emu/cpu/arm/arm.c
index 385f5feb587..7797cde7d02 100644
--- a/src/emu/cpu/arm/arm.c
+++ b/src/emu/cpu/arm/arm.c
@@ -20,6 +20,7 @@
#include "arm.h"
CPU_DISASSEMBLE( arm );
+CPU_DISASSEMBLE( arm_be );
#define READ8(addr) cpu_read8(cpustate,addr)
#define WRITE8(addr,data) cpu_write8(cpustate,addr,data)
@@ -254,25 +255,36 @@ static void arm_check_irq_state(ARM_REGS* cpustate);
INLINE ARM_REGS *get_safe_token(running_device *device)
{
assert(device != NULL);
- assert(device->type() == ARM);
+ assert(device->type() == ARM || device->type() == ARM_BE);
return (ARM_REGS *)downcast<legacy_cpu_device *>(device)->token();
}
INLINE void cpu_write32( ARM_REGS* cpustate, int addr, UINT32 data )
{
/* Unaligned writes are treated as normal writes */
- memory_write_dword_32le(cpustate->program, addr&ADDRESS_MASK,data);
+ if ( cpustate->endian == ENDIANNESS_BIG )
+ memory_write_dword_32be(cpustate->program, addr&ADDRESS_MASK,data);
+ else
+ memory_write_dword_32le(cpustate->program, addr&ADDRESS_MASK,data);
if (ARM_DEBUG_CORE && addr&3) logerror("%08x: Unaligned write %08x\n",R15,addr);
}
INLINE void cpu_write8( ARM_REGS* cpustate, int addr, UINT8 data )
{
- memory_write_byte_32le(cpustate->program,addr,data);
+ if ( cpustate->endian == ENDIANNESS_BIG )
+ memory_write_byte_32be(cpustate->program,addr,data);
+ else
+ memory_write_byte_32le(cpustate->program,addr,data);
}
INLINE UINT32 cpu_read32( ARM_REGS* cpustate, int addr )
{
- UINT32 result = memory_read_dword_32le(cpustate->program,addr&ADDRESS_MASK);
+ UINT32 result;
+
+ if ( cpustate->endian == ENDIANNESS_BIG )
+ result = memory_read_dword_32be(cpustate->program,addr&ADDRESS_MASK);
+ else
+ result = memory_read_dword_32le(cpustate->program,addr&ADDRESS_MASK);
/* Unaligned reads rotate the word, they never combine words */
if (addr&3) {
@@ -292,7 +304,10 @@ INLINE UINT32 cpu_read32( ARM_REGS* cpustate, int addr )
INLINE UINT8 cpu_read8( ARM_REGS* cpustate, int addr )
{
- return memory_read_byte_32le(cpustate->program, addr);
+ if ( cpustate->endian == ENDIANNESS_BIG )
+ return memory_read_byte_32be(cpustate->program, addr);
+ else
+ return memory_read_byte_32le(cpustate->program, addr);
}
INLINE UINT32 GetRegister( ARM_REGS* cpustate, int rIndex )
@@ -312,8 +327,11 @@ static CPU_RESET( arm )
ARM_REGS *cpustate = get_safe_token(device);
device_irq_callback save_irqcallback = cpustate->irq_callback;
+ endianness_t save_endian = cpustate->endian;
+
memset(cpustate, 0, sizeof(ARM_REGS));
cpustate->irq_callback = save_irqcallback;
+ cpustate->endian = save_endian;
cpustate->device = device;
cpustate->program = device->space(AS_PROGRAM);
@@ -507,6 +525,24 @@ static CPU_INIT( arm )
state_save_register_device_item(device, 0, cpustate->endian);
}
+
+static CPU_INIT( arm_be )
+{
+ ARM_REGS *cpustate = get_safe_token(device);
+
+ cpustate->irq_callback = irqcallback;
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->endian = ENDIANNESS_BIG;
+
+ state_save_register_device_item_array(device, 0, cpustate->sArmRegister);
+ state_save_register_device_item_array(device, 0, cpustate->coproRegister);
+ state_save_register_device_item(device, 0, cpustate->pendingIrq);
+ state_save_register_device_item(device, 0, cpustate->pendingFiq);
+ state_save_register_device_item(device, 0, cpustate->endian);
+}
+
+
/***************************************************************************/
static void HandleBranch( ARM_REGS* cpustate, UINT32 insn )
@@ -596,7 +632,7 @@ static void HandleMemSingle( ARM_REGS* cpustate, UINT32 insn )
{
if (ARM_DEBUG_CORE && rd == eR15)
logerror("read byte R15 %08x\n", R15);
- SetRegister(cpustate, rd,(UINT32) READ8( ( cpustate->endian == ENDIANNESS_LITTLE ? rnv : (rnv ^ 0x03) ) ) );
+ SetRegister(cpustate, rd,(UINT32) READ8(rnv) );
}
else
{
@@ -619,16 +655,7 @@ static void HandleMemSingle( ARM_REGS* cpustate, UINT32 insn )
}
else
{
- UINT32 data = READ32(rnv);
-
- if ( cpustate->endian == ENDIANNESS_BIG )
- {
- if ( rnv & 0x02 )
- data = ( data >> 16 ) | ( data << 16 );
- if ( rnv & 0x01 )
- data = ( data >> 24 ) | ( data << 8 );
- }
- SetRegister(cpustate, rd, data);
+ SetRegister(cpustate, rd, READ32(rnv));
}
}
}
@@ -641,7 +668,7 @@ static void HandleMemSingle( ARM_REGS* cpustate, UINT32 insn )
if (ARM_DEBUG_CORE && rd==eR15)
logerror("Wrote R15 in byte mode\n");
- WRITE8( ( cpustate->endian == ENDIANNESS_LITTLE ? rnv : (rnv ^ 0x03) ), (UINT8) GetRegister(cpustate, rd) & 0xffu);
+ WRITE8(rnv, (UINT8) GetRegister(cpustate, rd) & 0xffu);
}
else
{
@@ -1388,13 +1415,6 @@ static void HandleCoPro( ARM_REGS* cpustate, UINT32 insn )
}
-void arm_set_endianness( legacy_cpu_device *device, endianness_t endianness )
-{
- ARM_REGS *cpustate = get_safe_token(device);
-
- cpustate->endian = endianness;
-}
-
/**************************************************************************
* Generic set_info
**************************************************************************/
@@ -1587,4 +1607,26 @@ CPU_GET_INFO( arm )
}
}
+
+CPU_GET_INFO( arm_be )
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(arm_be); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(arm_be); break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case DEVINFO_STR_NAME: strcpy(info->s, "ARM (big endian)"); break;
+
+ default: CPU_GET_INFO_CALL(arm); break;
+ }
+}
+
+
DEFINE_LEGACY_CPU_DEVICE(ARM, arm);
+DEFINE_LEGACY_CPU_DEVICE(ARM_BE, arm_be);
+
diff --git a/src/emu/cpu/arm/arm.h b/src/emu/cpu/arm/arm.h
index 7b9d62c1414..19297096a68 100644
--- a/src/emu/cpu/arm/arm.h
+++ b/src/emu/cpu/arm/arm.h
@@ -15,6 +15,7 @@
***************************************************************************************************/
DECLARE_LEGACY_CPU_DEVICE(ARM, arm);
+DECLARE_LEGACY_CPU_DEVICE(ARM_BE, arm_be);
enum
{
@@ -25,6 +26,4 @@ enum
ARM32_IR13, ARM32_IR14, ARM32_SR13, ARM32_SR14
};
-void arm_set_endianness( legacy_cpu_device *device, endianness_t endianness );
-
#endif /* __ARM_H__ */
diff --git a/src/emu/cpu/arm/armdasm.c b/src/emu/cpu/arm/armdasm.c
index fe1f4132502..0d596fb5597 100644
--- a/src/emu/cpu/arm/armdasm.c
+++ b/src/emu/cpu/arm/armdasm.c
@@ -398,3 +398,10 @@ CPU_DISASSEMBLE( arm )
UINT32 opcode = oprom[0] | (oprom[1] << 8) | (oprom[2] << 16) | (oprom[3] << 24);
return 4 | arm_disasm(buffer, pc, opcode);
}
+
+CPU_DISASSEMBLE( arm_be )
+{
+ UINT32 opcode = oprom[3] | (oprom[2] << 8) | (oprom[1] << 16) | (oprom[0] << 24);
+ return 4 | arm_disasm(buffer, pc, opcode);
+}
+