ARM7 updates

- Pointer-ified ARM7 core
- Added disassembler and execution support for ARMv5 LDRD/STRD instructions.
  39in1 now makes it until it needs the MMU.
This commit is contained in:
R. Belmont 2008-11-29 02:59:53 +00:00
parent 86e9b479bd
commit cdd72b00bd
5 changed files with 527 additions and 496 deletions

View File

@ -46,35 +46,25 @@
static WRITE32_HANDLER(test_do_callback);
static READ32_HANDLER(test_rt_r_callback);
static WRITE32_HANDLER(test_rt_w_callback);
static void test_dt_r_callback(UINT32 insn, UINT32 *prn, UINT32 (*read32)(UINT32 addr));
static void test_dt_w_callback(UINT32 insn, UINT32 *prn, void (*write32)(UINT32 addr, UINT32 data));
static void test_dt_r_callback(arm_state *cpustate, UINT32 insn, UINT32 *prn, UINT32 (*read32)(arm_state *cpustate, UINT32 addr));
static void test_dt_w_callback(arm_state *cpustate, UINT32 insn, UINT32 *prn, void (*write32)(arm_state *cpustate, UINT32 addr, UINT32 data));
#endif
/* Macros that can be re-defined for custom cpu implementations - The core expects these to be defined */
/* In this case, we are using the default arm7 handlers (supplied by the core)
- but simply changes these and define your own if needed for cpu implementation specific needs */
#define READ8(addr) arm7_cpu_read8(addr)
#define WRITE8(addr,data) arm7_cpu_write8(addr,data)
#define READ16(addr) arm7_cpu_read16(addr)
#define WRITE16(addr,data) arm7_cpu_write16(addr,data)
#define READ32(addr) arm7_cpu_read32(addr)
#define WRITE32(addr,data) arm7_cpu_write32(addr,data)
#define READ8(addr) arm7_cpu_read8(cpustate, addr)
#define WRITE8(addr,data) arm7_cpu_write8(cpustate, addr,data)
#define READ16(addr) arm7_cpu_read16(cpustate, addr)
#define WRITE16(addr,data) arm7_cpu_write16(cpustate, addr,data)
#define READ32(addr) arm7_cpu_read32(cpustate, addr)
#define WRITE32(addr,data) arm7_cpu_write32(cpustate, addr,data)
#define PTR_READ32 &arm7_cpu_read32
#define PTR_WRITE32 &arm7_cpu_write32
/* Macros that need to be defined according to the cpu implementation specific need */
#define ARM7REG(reg) arm7.sArmRegister[reg]
#define ARM7 arm7
#define ARM7_ICOUNT arm7_icount
/* CPU Registers */
typedef struct
{
ARM7CORE_REGS // these must be included in your cpu specific register implementation
} ARM7_REGS;
static ARM7_REGS arm7;
static int ARM7_ICOUNT;
#define ARM7REG(reg) cpustate->sArmRegister[reg]
#define ARM7_ICOUNT cpustate->iCount
/* include the arm7 core */
#include "arm7core.c"
@ -84,32 +74,34 @@ static int ARM7_ICOUNT;
**************************************************************************/
static CPU_INIT( arm7 )
{
// must call core
arm7_core_init("arm7", device);
arm_state *cpustate = device->token;
ARM7.irq_callback = irqcallback;
ARM7.device = device;
ARM7.program = cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM);
// must call core
arm7_core_init("arm7", device);
cpustate->irq_callback = irqcallback;
cpustate->device = device;
cpustate->program = cpu_get_address_space(device, ADDRESS_SPACE_PROGRAM);
#if TEST_COPROC_FUNCS
// setup co-proc callbacks example
arm7_coproc_do_callback = test_do_callback;
arm7_coproc_rt_r_callback = test_rt_r_callback;
arm7_coproc_rt_w_callback = test_rt_w_callback;
arm7_coproc_dt_r_callback = test_dt_r_callback;
arm7_coproc_dt_w_callback = test_dt_w_callback;
// setup co-proc callbacks example
arm7_coproc_do_callback = test_do_callback;
arm7_coproc_rt_r_callback = test_rt_r_callback;
arm7_coproc_rt_w_callback = test_rt_w_callback;
arm7_coproc_dt_r_callback = test_dt_r_callback;
arm7_coproc_dt_w_callback = test_dt_w_callback;
#endif
}
static CPU_RESET( arm7 )
{
// must call core reset
arm7_core_reset(device);
// must call core reset
arm7_core_reset(device);
}
static CPU_EXIT( arm7 )
{
/* nothing to do here */
/* nothing to do here */
}
static CPU_EXECUTE( arm7 )
@ -119,30 +111,24 @@ static CPU_EXECUTE( arm7 )
}
static void set_irq_line(int irqline, int state)
static void set_irq_line(arm_state *cpustate, int irqline, int state)
{
// must call core
arm7_core_set_irq_line(irqline,state);
arm7_core_set_irq_line(cpustate, irqline, state);
}
static CPU_GET_CONTEXT( arm7 )
{
if (dst)
{
memcpy(dst, &ARM7, sizeof(ARM7));
}
}
static CPU_SET_CONTEXT( arm7 )
{
if (src)
{
memcpy(&ARM7, src, sizeof(ARM7));
}
}
static CPU_DISASSEMBLE( arm7 )
{
arm_state *cpustate = device->token;
if (T_IS_SET(GET_CPSR))
{
return thumb_disasm(buffer, pc, oprom[0] | (oprom[1] << 8)) | 2;
@ -160,16 +146,18 @@ static CPU_DISASSEMBLE( arm7 )
static CPU_SET_INFO( arm7 )
{
arm_state *cpustate = device->token;
switch (state)
{
/* --- the following bits of info are set as 64-bit signed integers --- */
/* interrupt lines/exceptions */
case CPUINFO_INT_INPUT_STATE + ARM7_IRQ_LINE: set_irq_line(ARM7_IRQ_LINE, info->i); break;
case CPUINFO_INT_INPUT_STATE + ARM7_FIRQ_LINE: set_irq_line(ARM7_FIRQ_LINE, info->i); break;
case CPUINFO_INT_INPUT_STATE + ARM7_ABORT_EXCEPTION: set_irq_line(ARM7_ABORT_EXCEPTION, info->i); break;
case CPUINFO_INT_INPUT_STATE + ARM7_ABORT_PREFETCH_EXCEPTION: set_irq_line(ARM7_ABORT_PREFETCH_EXCEPTION, info->i); break;
case CPUINFO_INT_INPUT_STATE + ARM7_UNDEFINE_EXCEPTION: set_irq_line(ARM7_UNDEFINE_EXCEPTION, info->i); break;
case CPUINFO_INT_INPUT_STATE + ARM7_IRQ_LINE: set_irq_line(cpustate, ARM7_IRQ_LINE, info->i); break;
case CPUINFO_INT_INPUT_STATE + ARM7_FIRQ_LINE: set_irq_line(cpustate, ARM7_FIRQ_LINE, info->i); break;
case CPUINFO_INT_INPUT_STATE + ARM7_ABORT_EXCEPTION: set_irq_line(cpustate, ARM7_ABORT_EXCEPTION, info->i); break;
case CPUINFO_INT_INPUT_STATE + ARM7_ABORT_PREFETCH_EXCEPTION: set_irq_line(cpustate, ARM7_ABORT_PREFETCH_EXCEPTION, info->i); break;
case CPUINFO_INT_INPUT_STATE + ARM7_UNDEFINE_EXCEPTION: set_irq_line(cpustate, ARM7_UNDEFINE_EXCEPTION, info->i); break;
/* registers shared by all operating modes */
case CPUINFO_INT_REGISTER + ARM7_R0: ARM7REG( 0) = info->i; break;
@ -192,7 +180,7 @@ static CPU_SET_INFO( arm7 )
case CPUINFO_INT_PC:
case CPUINFO_INT_REGISTER + ARM7_PC: R15 = info->i; break;
case CPUINFO_INT_SP: SetRegister(13,info->i); break;
case CPUINFO_INT_SP: SetRegister(cpustate, 13,info->i); break;
/* FIRQ Mode Shadowed Registers */
case CPUINFO_INT_REGISTER + ARM7_FR8: ARM7REG(eR8_FIQ) = info->i; break;
@ -234,12 +222,14 @@ static CPU_SET_INFO( arm7 )
CPU_GET_INFO( arm7 )
{
arm_state *cpustate = (device != NULL) ? device->token : NULL;
switch (state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
/* cpu implementation data */
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(ARM7); break;
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(arm_state); break;
case CPUINFO_INT_INPUT_LINES: info->i = ARM7_NUM_LINES; break;
case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_LE; break;
@ -261,11 +251,11 @@ CPU_GET_INFO( arm7 )
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break;
/* interrupt lines/exceptions */
case CPUINFO_INT_INPUT_STATE + ARM7_IRQ_LINE: info->i = ARM7.pendingIrq; break;
case CPUINFO_INT_INPUT_STATE + ARM7_FIRQ_LINE: info->i = ARM7.pendingFiq; break;
case CPUINFO_INT_INPUT_STATE + ARM7_ABORT_EXCEPTION: info->i = ARM7.pendingAbtD; break;
case CPUINFO_INT_INPUT_STATE + ARM7_ABORT_PREFETCH_EXCEPTION: info->i = ARM7.pendingAbtP; break;
case CPUINFO_INT_INPUT_STATE + ARM7_UNDEFINE_EXCEPTION: info->i = ARM7.pendingUnd; break;
case CPUINFO_INT_INPUT_STATE + ARM7_IRQ_LINE: info->i = cpustate->pendingIrq; break;
case CPUINFO_INT_INPUT_STATE + ARM7_FIRQ_LINE: info->i = cpustate->pendingFiq; break;
case CPUINFO_INT_INPUT_STATE + ARM7_ABORT_EXCEPTION: info->i = cpustate->pendingAbtD; break;
case CPUINFO_INT_INPUT_STATE + ARM7_ABORT_PREFETCH_EXCEPTION: info->i = cpustate->pendingAbtP; break;
case CPUINFO_INT_INPUT_STATE + ARM7_UNDEFINE_EXCEPTION: info->i = cpustate->pendingUnd; break;
/* registers shared by all operating modes */
case CPUINFO_INT_REGISTER + ARM7_R0: info->i = ARM7REG( 0); break;
@ -288,7 +278,7 @@ CPU_GET_INFO( arm7 )
case CPUINFO_INT_PREVIOUSPC: info->i = 0; /* not implemented */ break;
case CPUINFO_INT_PC:
case CPUINFO_INT_REGISTER + ARM7_PC: info->i = R15; break;
case CPUINFO_INT_SP: info->i = GetRegister(13); break;
case CPUINFO_INT_SP: info->i = GetRegister(cpustate, 13); break;
/* FIRQ Mode Shadowed Registers */
case CPUINFO_INT_REGISTER + ARM7_FR8: info->i = ARM7REG(eR8_FIQ); break;
@ -419,11 +409,11 @@ static WRITE32_HANDLER(test_rt_w_callback)
{
LOG(("test_rt_w_callback opcode=%x, data from ARM7 register=%x\n", offset, data));
}
static void test_dt_r_callback(UINT32 insn, UINT32 *prn, UINT32 (*read32)(UINT32 addr))
static void test_dt_r_callback(arm_state *cpustate, UINT32 insn, UINT32 *prn, UINT32 (*read32)(arm_state *cpustate, UINT32 addr))
{
LOG(("test_dt_r_callback: insn = %x\n", insn));
}
static void test_dt_w_callback(UINT32 insn, UINT32 *prn, void (*write32)(UINT32 addr, UINT32 data))
static void test_dt_w_callback(arm_state *cpustate, UINT32 insn, UINT32 *prn, void (*write32)(arm_state *cpustate, UINT32 addr, UINT32 data))
{
LOG(("test_dt_w_callback: opcode = %x\n", insn));
}

File diff suppressed because it is too large Load Diff

View File

@ -59,36 +59,6 @@ enum
ARM7_CPSR, ARM7_AR13, ARM7_AR14, ARM7_ASPSR, ARM7_UR13, ARM7_UR14, ARM7_USPSR
};
#define ARM7CORE_REGS \
UINT32 sArmRegister[kNumRegisters]; \
UINT8 pendingIrq; \
UINT8 pendingFiq; \
UINT8 pendingAbtD; \
UINT8 pendingAbtP; \
UINT8 pendingUnd; \
UINT8 pendingSwi; \
cpu_irq_callback irq_callback; \
const device_config *device; \
const address_space *program;
/****************************************************************************************************
* VARIOUS INTERNAL STRUCS/DEFINES/ETC..
***************************************************************************************************/
// Mode values come from bit 4-0 of CPSR, but we are ignoring bit 4 here, since bit 4 always = 1 for valid modes
enum
{
eARM7_MODE_USER = 0x0, // Bit: 4-0 = 10000
eARM7_MODE_FIQ = 0x1, // Bit: 4-0 = 10001
eARM7_MODE_IRQ = 0x2, // Bit: 4-0 = 10010
eARM7_MODE_SVC = 0x3, // Bit: 4-0 = 10011
eARM7_MODE_ABT = 0x7, // Bit: 4-0 = 10111
eARM7_MODE_UND = 0xb, // Bit: 4-0 = 11011
eARM7_MODE_SYS = 0xf // Bit: 4-0 = 11111
};
#define ARM7_NUM_MODES 0x10
/* There are 36 Unique - 32 bit processor registers */
/* Each mode has 17 registers (except user & system, which have 16) */
/* This is a list of each *unique* register */
@ -120,6 +90,43 @@ enum
kNumRegisters
};
#define ARM7CORE_REGS \
UINT32 sArmRegister[kNumRegisters]; \
UINT8 pendingIrq; \
UINT8 pendingFiq; \
UINT8 pendingAbtD; \
UINT8 pendingAbtP; \
UINT8 pendingUnd; \
UINT8 pendingSwi; \
INT32 iCount; \
cpu_irq_callback irq_callback; \
const device_config *device; \
const address_space *program;
/* CPU state struct */
typedef struct
{
ARM7CORE_REGS // these must be included in your cpu specific register implementation
} arm_state;
/****************************************************************************************************
* VARIOUS INTERNAL STRUCS/DEFINES/ETC..
***************************************************************************************************/
// Mode values come from bit 4-0 of CPSR, but we are ignoring bit 4 here, since bit 4 always = 1 for valid modes
enum
{
eARM7_MODE_USER = 0x0, // Bit: 4-0 = 10000
eARM7_MODE_FIQ = 0x1, // Bit: 4-0 = 10001
eARM7_MODE_IRQ = 0x2, // Bit: 4-0 = 10010
eARM7_MODE_SVC = 0x3, // Bit: 4-0 = 10011
eARM7_MODE_ABT = 0x7, // Bit: 4-0 = 10111
eARM7_MODE_UND = 0xb, // Bit: 4-0 = 11011
eARM7_MODE_SYS = 0xf // Bit: 4-0 = 11111
};
#define ARM7_NUM_MODES 0x10
static const int thumbCycles[256] =
{
// 0 1 2 3 4 5 6 7 8 9 a b c d e f
@ -392,23 +399,23 @@ enum
#define THUMB_SIGN_BITS_DIFFER(a, b) (((a)^(b)) >> 31)
/* At one point I thought these needed to be cpu implementation specific, but they don't.. */
#define GET_REGISTER(reg) GetRegister(reg)
#define SET_REGISTER(reg, val) SetRegister(reg, val)
#define ARM7_CHECKIRQ arm7_check_irq_state()
#define GET_REGISTER(state, reg) GetRegister(state, reg)
#define SET_REGISTER(state, reg, val) SetRegister(state, reg, val)
#define ARM7_CHECKIRQ arm7_check_irq_state(cpustate)
extern WRITE32_HANDLER((*arm7_coproc_do_callback));
extern READ32_HANDLER((*arm7_coproc_rt_r_callback));
extern WRITE32_HANDLER((*arm7_coproc_rt_w_callback));
extern void (*arm7_coproc_dt_r_callback)(UINT32 insn, UINT32* prn, UINT32 (*read32)(UINT32 addr));
extern void (*arm7_coproc_dt_w_callback)(UINT32 insn, UINT32* prn, void (*write32)(UINT32 addr, UINT32 data));
extern void (*arm7_coproc_dt_r_callback)(arm_state *cpustate, UINT32 insn, UINT32* prn, UINT32 (*read32)(arm_state *cpustate, UINT32 addr));
extern void (*arm7_coproc_dt_w_callback)(arm_state *cpustate, UINT32 insn, UINT32* prn, void (*write32)(arm_state *cpustate, UINT32 addr, UINT32 data));
extern UINT32 arm7_disasm(char *pBuf, UINT32 pc, UINT32 opcode);
extern UINT32 thumb_disasm(char *pBuf, UINT32 pc, UINT16 opcode);
#ifdef UNUSED_DEFINITION
extern char *(*arm7_dasm_cop_dt_callback)(char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0);
extern char *(*arm7_dasm_cop_rt_callback)(char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0);
extern char *(*arm7_dasm_cop_do_callback)(char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0);
extern char *(*arm7_dasm_cop_dt_callback)(arm_state *cpustate, char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0);
extern char *(*arm7_dasm_cop_rt_callback)(arm_state *cpustate, char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0);
extern char *(*arm7_dasm_cop_do_callback)(arm_state *cpustate, char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0);
#endif
#endif /* __ARM7CORE_H__ */

View File

@ -234,17 +234,31 @@ UINT32 arm7_disasm( char *pBuf, UINT32 pc, UINT32 opcode )
else if( (opcode&0x0e000000)==0 && (opcode&0x80) && (opcode&0x10) ) //bits 27-25 == 000, bit 7=1, bit 4=1
{
/* multiply or swap or half word data transfer */
if(opcode&0x60)
{ //bits = 6-5 != 00
/* half word data transfer */
pBuf += sprintf(pBuf, "%s%s",(opcode&0x00100000)?"LDR":"STR",pConditionCode); //Bit 20 = 1 for Load, 0 for Store
//Signed? (if not, always unsigned half word)
if(opcode&0x40)
pBuf += sprintf(pBuf, "%s",(opcode&0x20)?"SH":"SB"); //Bit 5 = 1 for Half Word, 0 for Byte
/* half word data transfer */
if (((opcode & 0x60) == 0x40) && !(opcode & 0x100000)) // bit 20 = 0, bits 5&6 = 10 is ARMv5 LDRD
{
pBuf += sprintf(pBuf, "LDRD%s", pConditionCode);
}
else if (((opcode & 0x60) == 0x60) && !(opcode & 0x100000)) // bit 20 = 0, bits 5&6 = 11 is ARMv5 STRD
{
pBuf += sprintf(pBuf, "STRD%s", pConditionCode);
}
else
pBuf += sprintf(pBuf, "H");
{
pBuf += sprintf(pBuf, "%s%s",(opcode&0x00100000)?"LDR":"STR",pConditionCode); //Bit 20 = 1 for Load, 0 for Store
//Signed? (if not, always unsigned half word)
if(opcode&0x40)
{
pBuf += sprintf(pBuf, "%s",(opcode&0x20)?"SH":"SB"); //Bit 5 = 1 for Half Word, 0 for Byte
}
else
{
pBuf += sprintf(pBuf, "H");
}
}
pBuf = WritePadding( pBuf, pBuf0 );

View File

@ -43,11 +43,12 @@
{
UINT32 pc;
UINT32 insn;
arm_state *cpustate = device->token;
ARM7_ICOUNT = cycles;
do
{
debugger_instruction_hook(arm7.device, R15);
debugger_instruction_hook(cpustate->device, R15);
/* handle Thumb instructions if active */
if (T_IS_SET(GET_CPSR))
@ -58,7 +59,7 @@
INT32 offs;
pc = R15;
insn = memory_decrypted_read_word(ARM7.program, pc & (~1));
insn = memory_decrypted_read_word(cpustate->program, pc & (~1));
ARM7_ICOUNT -= (3 - thumbCycles[insn >> 8]);
switch ((insn & THUMB_INSN_TYPE) >> THUMB_INSN_TYPE_SHIFT)
{
@ -68,11 +69,11 @@
{
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
rrs = GET_REGISTER(rs);
rrs = GET_REGISTER(cpustate, rs);
offs = (insn & THUMB_SHIFT_AMT) >> THUMB_SHIFT_AMT_SHIFT;
if (offs != 0)
{
SET_REGISTER(rd, rrs >> offs);
SET_REGISTER(cpustate, rd, rrs >> offs);
if (rrs & (1 << (offs - 1)))
{
SET_CPSR(GET_CPSR | C_MASK);
@ -84,7 +85,7 @@
}
else
{
SET_REGISTER(rd, 0);
SET_REGISTER(cpustate, rd, 0);
if (rrs & 0x80000000)
{
SET_CPSR(GET_CPSR | C_MASK);
@ -95,18 +96,18 @@
}
}
SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd)));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
R15 += 2;
}
else /* Shift left */
{
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
rrs = GET_REGISTER(rs);
rrs = GET_REGISTER(cpustate, rs);
offs = (insn & THUMB_SHIFT_AMT) >> THUMB_SHIFT_AMT_SHIFT;
if (offs != 0)
{
SET_REGISTER(rd, rrs << offs);
SET_REGISTER(cpustate, rd, rrs << offs);
if (rrs & (1 << (31 - (offs - 1))))
{
SET_CPSR(GET_CPSR | C_MASK);
@ -118,10 +119,10 @@
}
else
{
SET_REGISTER(rd, rrs);
SET_REGISTER(cpustate, rd, rrs);
}
SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd)));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
R15 += 2;
}
break;
@ -131,32 +132,32 @@
switch ((insn & THUMB_ADDSUB_TYPE) >> THUMB_ADDSUB_TYPE_SHIFT)
{
case 0x0: /* ADD Rd, Rs, Rn */
rn = GET_REGISTER((insn & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT);
rs = GET_REGISTER((insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT);
rn = GET_REGISTER(cpustate, (insn & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT);
rs = GET_REGISTER(cpustate, (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT);
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
SET_REGISTER(rd, rs + rn);
HandleThumbALUAddFlags(GET_REGISTER(rd), rs, rn);
SET_REGISTER(cpustate, rd, rs + rn);
HandleThumbALUAddFlags(GET_REGISTER(cpustate, rd), rs, rn);
break;
case 0x1: /* SUB Rd, Rs, Rn */
rn = GET_REGISTER((insn & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT);
rs = GET_REGISTER((insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT);
rn = GET_REGISTER(cpustate, (insn & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT);
rs = GET_REGISTER(cpustate, (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT);
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
SET_REGISTER(rd, rs - rn);
HandleThumbALUSubFlags(GET_REGISTER(rd), rs, rn);
SET_REGISTER(cpustate, rd, rs - rn);
HandleThumbALUSubFlags(GET_REGISTER(cpustate, rd), rs, rn);
break;
case 0x2: /* ADD Rd, Rs, #imm */
imm = (insn & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT;
rs = GET_REGISTER((insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT);
rs = GET_REGISTER(cpustate, (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT);
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
SET_REGISTER(rd, rs + imm);
HandleThumbALUAddFlags(GET_REGISTER(rd), rs, imm);
SET_REGISTER(cpustate, rd, rs + imm);
HandleThumbALUAddFlags(GET_REGISTER(cpustate, rd), rs, imm);
break;
case 0x3: /* SUB Rd, Rs, #imm */
imm = (insn & THUMB_ADDSUB_RNIMM) >> THUMB_ADDSUB_RNIMM_SHIFT;
rs = GET_REGISTER((insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT);
rs = GET_REGISTER(cpustate, (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT);
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
SET_REGISTER(rd, rs - imm);
HandleThumbALUSubFlags(GET_REGISTER(rd), rs,imm);
SET_REGISTER(cpustate, rd, rs - imm);
HandleThumbALUSubFlags(GET_REGISTER(cpustate, rd), rs,imm);
break;
default:
fatalerror("%08x: G1 Undefined Thumb instruction: %04x\n", pc, insn);
@ -171,7 +172,7 @@
{
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
rrs = GET_REGISTER(rs);
rrs = GET_REGISTER(cpustate, rs);
offs = (insn & THUMB_SHIFT_AMT) >> THUMB_SHIFT_AMT_SHIFT;
if (offs == 0)
{
@ -187,7 +188,7 @@
{
SET_CPSR(GET_CPSR & ~C_MASK);
}
SET_REGISTER(rd, (rrs & 0x80000000) ? 0xFFFFFFFF : 0x00000000);
SET_REGISTER(cpustate, rd, (rrs & 0x80000000) ? 0xFFFFFFFF : 0x00000000);
}
else
{
@ -199,13 +200,13 @@
{
SET_CPSR(GET_CPSR & ~C_MASK);
}
SET_REGISTER(rd,
SET_REGISTER(cpustate, rd,
(rrs & 0x80000000)
? ((0xFFFFFFFF << (32 - offs)) | (rrs >> offs))
: (rrs >> offs));
}
SET_CPSR(GET_CPSR & ~(N_MASK | Z_MASK));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd)));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
R15 += 2;
}
}
@ -213,39 +214,39 @@
case 0x2: /* CMP / MOV */
if (insn & THUMB_INSN_CMP)
{
rn = GET_REGISTER((insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT);
rn = GET_REGISTER(cpustate, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT);
op2 = insn & THUMB_INSN_IMM;
rd = rn - op2;
HandleThumbALUSubFlags(rd, rn, op2);
//mame_printf_debug("%08x: xxx Thumb instruction: CMP R%d (%08x), %02x (N=%d, Z=%d, C=%d, V=%d)\n", pc, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, GET_REGISTER((insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT), op2, N_IS_SET(GET_CPSR) ? 1 : 0, Z_IS_SET(GET_CPSR) ? 1 : 0, C_IS_SET(GET_CPSR) ? 1 : 0, V_IS_SET(GET_CPSR) ? 1 : 0);
//mame_printf_debug("%08x: xxx Thumb instruction: CMP R%d (%08x), %02x (N=%d, Z=%d, C=%d, V=%d)\n", pc, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, GET_REGISTER(cpustate, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT), op2, N_IS_SET(GET_CPSR) ? 1 : 0, Z_IS_SET(GET_CPSR) ? 1 : 0, C_IS_SET(GET_CPSR) ? 1 : 0, V_IS_SET(GET_CPSR) ? 1 : 0);
}
else
{
rd = (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT;
op2 = (insn & THUMB_INSN_IMM);
SET_REGISTER(rd, op2);
SET_REGISTER(cpustate, rd, op2);
SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd)));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
R15 += 2;
}
break;
case 0x3: /* ADD/SUB immediate */
if (insn & THUMB_INSN_SUB) /* SUB Rd, #Offset8 */
{
rn = GET_REGISTER((insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT);
rn = GET_REGISTER(cpustate, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT);
op2 = insn & THUMB_INSN_IMM;
//mame_printf_debug("%08x: Thumb instruction: SUB R%d, %02x\n", pc, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, op2);
rd = rn - op2;
SET_REGISTER((insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, rd);
SET_REGISTER(cpustate, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, rd);
HandleThumbALUSubFlags(rd, rn, op2);
}
else /* ADD Rd, #Offset8 */
{
rn = GET_REGISTER((insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT);
rn = GET_REGISTER(cpustate, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT);
op2 = insn & THUMB_INSN_IMM;
rd = rn + op2;
//mame_printf_debug("%08x: Thumb instruction: ADD R%d, %02x\n", pc, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, op2);
SET_REGISTER((insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, rd);
SET_REGISTER(cpustate, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, rd);
HandleThumbALUAddFlags(rd, rn, op2);
}
break;
@ -258,29 +259,29 @@
case 0x0: /* AND Rd, Rs */
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
SET_REGISTER(rd, GET_REGISTER(rd) & GET_REGISTER(rs));
SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, rd) & GET_REGISTER(cpustate, rs));
SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd)));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
R15 += 2;
break;
case 0x1: /* EOR Rd, Rs */
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
SET_REGISTER(rd, GET_REGISTER(rd) ^ GET_REGISTER(rs));
SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, rd) ^ GET_REGISTER(cpustate, rs));
SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd)));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
R15 += 2;
break;
case 0x2: /* LSL Rd, Rs */
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
rrd = GET_REGISTER(rd);
offs = GET_REGISTER(rs) & 0x000000ff;
rrd = GET_REGISTER(cpustate, rd);
offs = GET_REGISTER(cpustate, rs) & 0x000000ff;
if (offs > 0)
{
if (offs < 32)
{
SET_REGISTER(rd, rrd << offs);
SET_REGISTER(cpustate, rd, rrd << offs);
if (rrd & (1 << (31 - (offs - 1))))
{
SET_CPSR(GET_CPSR | C_MASK);
@ -292,7 +293,7 @@
}
else if (offs == 32)
{
SET_REGISTER(rd, 0);
SET_REGISTER(cpustate, rd, 0);
if (rrd & 1)
{
SET_CPSR(GET_CPSR | C_MASK);
@ -304,24 +305,24 @@
}
else
{
SET_REGISTER(rd, 0);
SET_REGISTER(cpustate, rd, 0);
SET_CPSR(GET_CPSR & ~C_MASK);
}
}
SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd)));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
R15 += 2;
break;
case 0x3: /* LSR Rd, Rs */
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
rrd = GET_REGISTER(rd);
offs = GET_REGISTER(rs) & 0x000000ff;
rrd = GET_REGISTER(cpustate, rd);
offs = GET_REGISTER(cpustate, rs) & 0x000000ff;
if (offs > 0)
{
if (offs < 32)
{
SET_REGISTER(rd, rrd >> offs);
SET_REGISTER(cpustate, rd, rrd >> offs);
if (rrd & (1 << (offs - 1)))
{
SET_CPSR(GET_CPSR | C_MASK);
@ -333,7 +334,7 @@
}
else if (offs == 32)
{
SET_REGISTER(rd, 0);
SET_REGISTER(cpustate, rd, 0);
if (rrd & 0x80000000)
{
SET_CPSR(GET_CPSR | C_MASK);
@ -345,19 +346,19 @@
}
else
{
SET_REGISTER(rd, 0);
SET_REGISTER(cpustate, rd, 0);
SET_CPSR(GET_CPSR & ~C_MASK);
}
}
SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd)));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
R15 += 2;
break;
case 0x4: /* ASR Rd, Rs */
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
rrs = GET_REGISTER(rs)&0xff;
rrd = GET_REGISTER(rd);
rrs = GET_REGISTER(cpustate, rs)&0xff;
rrd = GET_REGISTER(cpustate, rd);
if (rrs != 0)
{
if (rrs >= 32)
@ -370,7 +371,7 @@
{
SET_CPSR(GET_CPSR & ~C_MASK);
}
SET_REGISTER(rd, (GET_REGISTER(rd) & 0x80000000) ? 0xFFFFFFFF : 0x00000000);
SET_REGISTER(cpustate, rd, (GET_REGISTER(cpustate, rd) & 0x80000000) ? 0xFFFFFFFF : 0x00000000);
}
else
{
@ -382,37 +383,37 @@
{
SET_CPSR(GET_CPSR & ~C_MASK);
}
SET_REGISTER(rd, (rrd & 0x80000000)
SET_REGISTER(cpustate, rd, (rrd & 0x80000000)
? ((0xFFFFFFFF << (32 - rrs)) | (rrd >> rrs))
: (rrd >> rrs));
}
}
SET_CPSR(GET_CPSR & ~(N_MASK | Z_MASK));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd)));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
R15 += 2;
break;
case 0x5: /* ADC Rd, Rs */
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
op2=(GET_CPSR & C_MASK) ? 1 : 0;
rn=GET_REGISTER(rd) + GET_REGISTER(rs) + op2;
HandleThumbALUAddFlags(rn, GET_REGISTER(rd), (GET_REGISTER(rs))); // ?
SET_REGISTER(rd, rn);
rn=GET_REGISTER(cpustate, rd) + GET_REGISTER(cpustate, rs) + op2;
HandleThumbALUAddFlags(rn, GET_REGISTER(cpustate, rd), (GET_REGISTER(cpustate, rs))); // ?
SET_REGISTER(cpustate, rd, rn);
break;
case 0x6: /* SBC Rd, Rs */
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
op2=(GET_CPSR & C_MASK) ? 0 : 1;
rn=GET_REGISTER(rd) - GET_REGISTER(rs) - op2;
HandleThumbALUSubFlags(rn, GET_REGISTER(rd), (GET_REGISTER(rs))); //?
SET_REGISTER(rd, rn);
rn=GET_REGISTER(cpustate, rd) - GET_REGISTER(cpustate, rs) - op2;
HandleThumbALUSubFlags(rn, GET_REGISTER(cpustate, rd), (GET_REGISTER(cpustate, rs))); //?
SET_REGISTER(cpustate, rd, rn);
break;
case 0x7: /* ROR Rd, Rs */
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
rrd = GET_REGISTER(rd);
imm = GET_REGISTER(rs) & 0x0000001f;
SET_REGISTER(rd, (rrd >> imm) | (rrd << (32 - imm)));
rrd = GET_REGISTER(cpustate, rd);
imm = GET_REGISTER(cpustate, rs) & 0x0000001f;
SET_REGISTER(cpustate, rd, (rrd >> imm) | (rrd << (32 - imm)));
if (rrd & (1 << (imm - 1)))
{
SET_CPSR(GET_CPSR | C_MASK);
@ -422,68 +423,68 @@
SET_CPSR(GET_CPSR & ~C_MASK);
}
SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd)));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
R15 += 2;
break;
case 0x8: /* TST Rd, Rs */
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd) & GET_REGISTER(rs)));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd) & GET_REGISTER(cpustate, rs)));
R15 += 2;
break;
case 0x9: /* NEG Rd, Rs - todo: check me */
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
rrs = GET_REGISTER(rs);
rrs = GET_REGISTER(cpustate, rs);
rn = 0 - rrs;
SET_REGISTER(rd, rn);
HandleThumbALUSubFlags(GET_REGISTER(rd), 0, rrs);
SET_REGISTER(cpustate, rd, rn);
HandleThumbALUSubFlags(GET_REGISTER(cpustate, rd), 0, rrs);
break;
case 0xa: /* CMP Rd, Rs */
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
rn = GET_REGISTER(rd) - GET_REGISTER(rs);
HandleThumbALUSubFlags(rn, GET_REGISTER(rd), GET_REGISTER(rs));
rn = GET_REGISTER(cpustate, rd) - GET_REGISTER(cpustate, rs);
HandleThumbALUSubFlags(rn, GET_REGISTER(cpustate, rd), GET_REGISTER(cpustate, rs));
break;
case 0xb: /* CMN Rd, Rs - check flags, add dasm */
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
rn = GET_REGISTER(rd) + GET_REGISTER(rs);
HandleThumbALUAddFlags(rn, GET_REGISTER(rd), GET_REGISTER(rs));
rn = GET_REGISTER(cpustate, rd) + GET_REGISTER(cpustate, rs);
HandleThumbALUAddFlags(rn, GET_REGISTER(cpustate, rd), GET_REGISTER(cpustate, rs));
break;
case 0xc: /* ORR Rd, Rs */
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
SET_REGISTER(rd, GET_REGISTER(rd) | GET_REGISTER(rs));
SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, rd) | GET_REGISTER(cpustate, rs));
SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd)));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
R15 += 2;
break;
case 0xd: /* MUL Rd, Rs */
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
rn = GET_REGISTER(rd) * GET_REGISTER(rs);
rn = GET_REGISTER(cpustate, rd) * GET_REGISTER(cpustate, rs);
SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
SET_REGISTER(rd, rn);
SET_REGISTER(cpustate, rd, rn);
SET_CPSR(GET_CPSR | HandleALUNZFlags(rn));
R15 += 2;
break;
case 0xe: /* BIC Rd, Rs */
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
SET_REGISTER(rd, GET_REGISTER(rd) & (~GET_REGISTER(rs)));
SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, rd) & (~GET_REGISTER(cpustate, rs)));
SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd)));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
R15 += 2;
break;
case 0xf: /* MVN Rd, Rs */
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
op2 = GET_REGISTER(rs);
SET_REGISTER(rd, ~op2);
op2 = GET_REGISTER(cpustate, rs);
SET_REGISTER(cpustate, rd, ~op2);
SET_CPSR(GET_CPSR & ~(Z_MASK | N_MASK));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(rd)));
SET_CPSR(GET_CPSR | HandleALUNZFlags(GET_REGISTER(cpustate, rd)));
R15 += 2;
break;
default:
@ -501,26 +502,26 @@
switch ((insn & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT)
{
case 0x1: /* ADD Rd, HRs */
SET_REGISTER(rd, GET_REGISTER(rd) + GET_REGISTER(rs+8));
SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, rd) + GET_REGISTER(cpustate, rs+8));
// emulate the effects of pre-fetch
if (rs == 7)
{
SET_REGISTER(rd, GET_REGISTER(rd) + 4);
SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, rd) + 4);
}
break;
case 0x2: /* ADD HRd, Rs */
SET_REGISTER(rd+8, GET_REGISTER(rd+8) + GET_REGISTER(rs));
SET_REGISTER(cpustate, rd+8, GET_REGISTER(cpustate, rd+8) + GET_REGISTER(cpustate, rs));
if (rd == 7)
{
R15 += 2;
}
break;
case 0x3: /* Add HRd, HRs */
SET_REGISTER(rd+8, GET_REGISTER(rd+8) + GET_REGISTER(rs+8));
SET_REGISTER(cpustate, rd+8, GET_REGISTER(cpustate, rd+8) + GET_REGISTER(cpustate, rs+8));
// emulate the effects of pre-fetch
if (rs == 7)
{
SET_REGISTER(rd+8, GET_REGISTER(rd+8) + 4);
SET_REGISTER(cpustate, rd+8, GET_REGISTER(cpustate, rd+8) + 4);
}
if (rd == 7)
{
@ -537,26 +538,26 @@
switch ((insn & THUMB_HIREG_H) >> THUMB_HIREG_H_SHIFT)
{
case 0x0: /* CMP Rd, Rs */
rs = GET_REGISTER(((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT));
rd = GET_REGISTER(insn & THUMB_HIREG_RD);
rs = GET_REGISTER(cpustate, ((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT));
rd = GET_REGISTER(cpustate, insn & THUMB_HIREG_RD);
rn = rd - rs;
HandleThumbALUSubFlags(rn, rd, rs);
break;
case 0x1: /* CMP Rd, Hs */
rs = GET_REGISTER(((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8);
rd = GET_REGISTER(insn & THUMB_HIREG_RD);
rs = GET_REGISTER(cpustate, ((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8);
rd = GET_REGISTER(cpustate, insn & THUMB_HIREG_RD);
rn = rd - rs;
HandleThumbALUSubFlags(rn, rd, rs);
break;
case 0x2: /* CMP Hd, Rs */
rs = GET_REGISTER(((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT));
rd = GET_REGISTER((insn & THUMB_HIREG_RD) + 8);
rs = GET_REGISTER(cpustate, ((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT));
rd = GET_REGISTER(cpustate, (insn & THUMB_HIREG_RD) + 8);
rn = rd - rs;
HandleThumbALUSubFlags(rn, rd, rs);
break;
case 0x3: /* CMP Hd, Hs */
rs = GET_REGISTER(((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8);
rd = GET_REGISTER((insn & THUMB_HIREG_RD) + 8);
rs = GET_REGISTER(cpustate, ((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8);
rd = GET_REGISTER(cpustate, (insn & THUMB_HIREG_RD) + 8);
rn = rd - rs;
HandleThumbALUSubFlags(rn, rd, rs);
break;
@ -574,18 +575,18 @@
rd = insn & THUMB_HIREG_RD;
if (rs == 7)
{
SET_REGISTER(rd, GET_REGISTER(rs + 8) + 4);
SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, rs + 8) + 4);
}
else
{
SET_REGISTER(rd, GET_REGISTER(rs + 8));
SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, rs + 8));
}
R15 += 2;
break;
case 0x2: // MOV Hd, Rs
rs = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT;
rd = insn & THUMB_HIREG_RD;
SET_REGISTER(rd + 8, GET_REGISTER(rs));
SET_REGISTER(cpustate, rd + 8, GET_REGISTER(cpustate, rs));
if (rd != 7)
{
R15 += 2;
@ -600,11 +601,11 @@
rd = insn & THUMB_HIREG_RD;
if (rs == 7)
{
SET_REGISTER(rd + 8, GET_REGISTER(rs+8)+4);
SET_REGISTER(cpustate, rd + 8, GET_REGISTER(cpustate, rs+8)+4);
}
else
{
SET_REGISTER(rd + 8, GET_REGISTER(rs+8));
SET_REGISTER(cpustate, rd + 8, GET_REGISTER(cpustate, rs+8));
}
if (rd != 7)
{
@ -626,7 +627,7 @@
{
case 0x0:
rd = (insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT;
addr = GET_REGISTER(rd);
addr = GET_REGISTER(cpustate, rd);
if (addr & 1)
{
addr &= ~1;
@ -642,7 +643,7 @@
R15 = addr;
break;
case 0x1:
addr = GET_REGISTER(((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8);
addr = GET_REGISTER(cpustate, ((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8);
if ((((insn & THUMB_HIREG_RS) >> THUMB_HIREG_RS_SHIFT) + 8) == 15)
{
addr += 2;
@ -676,7 +677,7 @@
case 0x2:
case 0x3:
readword = READ32((R15 & ~2) + 4 + ((insn & THUMB_INSN_IMM) << 2));
SET_REGISTER((insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, readword);
SET_REGISTER(cpustate, (insn & THUMB_INSN_IMM_RD) >> THUMB_INSN_IMM_RD_SHIFT, readword);
R15 += 2;
break;
default:
@ -692,77 +693,77 @@
rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT;
rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
addr = GET_REGISTER(rn) + GET_REGISTER(rm);
WRITE32(addr, GET_REGISTER(rd));
addr = GET_REGISTER(cpustate, rn) + GET_REGISTER(cpustate, rm);
WRITE32(addr, GET_REGISTER(cpustate, rd));
R15 += 2;
break;
case 0x1: /* STRH Rd, [Rn, Rm] */
rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT;
rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
addr = GET_REGISTER(rn) + GET_REGISTER(rm);
WRITE16(addr, GET_REGISTER(rd));
addr = GET_REGISTER(cpustate, rn) + GET_REGISTER(cpustate, rm);
WRITE16(addr, GET_REGISTER(cpustate, rd));
R15 += 2;
break;
case 0x2: /* STRB Rd, [Rn, Rm] */
rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT;
rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
addr = GET_REGISTER(rn) + GET_REGISTER(rm);
WRITE8(addr, GET_REGISTER(rd));
addr = GET_REGISTER(cpustate, rn) + GET_REGISTER(cpustate, rm);
WRITE8(addr, GET_REGISTER(cpustate, rd));
R15 += 2;
break;
case 0x3: /* LDSB Rd, [Rn, Rm] todo, add dasm */
rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT;
rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
addr = GET_REGISTER(rn) + GET_REGISTER(rm);
addr = GET_REGISTER(cpustate, rn) + GET_REGISTER(cpustate, rm);
op2 = READ8(addr);
if (op2 & 0x00000080)
{
op2 |= 0xffffff00;
}
SET_REGISTER(rd, op2);
SET_REGISTER(cpustate, rd, op2);
R15 += 2;
break;
case 0x4: /* LDR Rd, [Rn, Rm] */
rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT;
rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
addr = GET_REGISTER(rn) + GET_REGISTER(rm);
addr = GET_REGISTER(cpustate, rn) + GET_REGISTER(cpustate, rm);
op2 = READ32(addr);
SET_REGISTER(rd, op2);
SET_REGISTER(cpustate, rd, op2);
R15 += 2;
break;
case 0x5: /* LDRH Rd, [Rn, Rm] */
rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT;
rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
addr = GET_REGISTER(rn) + GET_REGISTER(rm);
addr = GET_REGISTER(cpustate, rn) + GET_REGISTER(cpustate, rm);
op2 = READ16(addr);
SET_REGISTER(rd, op2);
SET_REGISTER(cpustate, rd, op2);
R15 += 2;
break;
case 0x6: /* LDRB Rd, [Rn, Rm] */
rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT;
rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
addr = GET_REGISTER(rn) + GET_REGISTER(rm);
addr = GET_REGISTER(cpustate, rn) + GET_REGISTER(cpustate, rm);
op2 = READ8(addr);
SET_REGISTER(rd, op2);
SET_REGISTER(cpustate, rd, op2);
R15 += 2;
break;
case 0x7: /* LDSH Rd, [Rn, Rm] */
rm = (insn & THUMB_GROUP5_RM) >> THUMB_GROUP5_RM_SHIFT;
rn = (insn & THUMB_GROUP5_RN) >> THUMB_GROUP5_RN_SHIFT;
rd = (insn & THUMB_GROUP5_RD) >> THUMB_GROUP5_RD_SHIFT;
addr = GET_REGISTER(rn) + GET_REGISTER(rm);
addr = GET_REGISTER(cpustate, rn) + GET_REGISTER(cpustate, rm);
op2 = READ16(addr);
if (op2 & 0x00008000)
{
op2 |= 0xffff0000;
}
SET_REGISTER(rd, op2);
SET_REGISTER(cpustate, rd, op2);
R15 += 2;
break;
default:
@ -777,7 +778,7 @@
rn = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = insn & THUMB_ADDSUB_RD;
offs = ((insn & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT) << 2;
SET_REGISTER(rd, READ32(GET_REGISTER(rn) + offs)); // fix
SET_REGISTER(cpustate, rd, READ32(GET_REGISTER(cpustate, rn) + offs)); // fix
R15 += 2;
}
else /* Store */
@ -785,7 +786,7 @@
rn = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = insn & THUMB_ADDSUB_RD;
offs = ((insn & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT) << 2;
WRITE32(GET_REGISTER(rn) + offs, GET_REGISTER(rd));
WRITE32(GET_REGISTER(cpustate, rn) + offs, GET_REGISTER(cpustate, rd));
R15 += 2;
}
break;
@ -795,7 +796,7 @@
rn = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = insn & THUMB_ADDSUB_RD;
offs = (insn & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT;
SET_REGISTER(rd, READ8(GET_REGISTER(rn) + offs));
SET_REGISTER(cpustate, rd, READ8(GET_REGISTER(cpustate, rn) + offs));
R15 += 2;
}
else /* Store */
@ -803,7 +804,7 @@
rn = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = insn & THUMB_ADDSUB_RD;
offs = (insn & THUMB_LSOP_OFFS) >> THUMB_LSOP_OFFS_SHIFT;
WRITE8(GET_REGISTER(rn) + offs, GET_REGISTER(rd));
WRITE8(GET_REGISTER(cpustate, rn) + offs, GET_REGISTER(cpustate, rd));
R15 += 2;
}
break;
@ -813,7 +814,7 @@
imm = (insn & THUMB_HALFOP_OFFS) >> THUMB_HALFOP_OFFS_SHIFT;
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
SET_REGISTER(rd, READ16(GET_REGISTER(rs) + (imm << 1)));
SET_REGISTER(cpustate, rd, READ16(GET_REGISTER(cpustate, rs) + (imm << 1)));
R15 += 2;
}
else /* Store */
@ -821,7 +822,7 @@
imm = (insn & THUMB_HALFOP_OFFS) >> THUMB_HALFOP_OFFS_SHIFT;
rs = (insn & THUMB_ADDSUB_RS) >> THUMB_ADDSUB_RS_SHIFT;
rd = (insn & THUMB_ADDSUB_RD) >> THUMB_ADDSUB_RD_SHIFT;
WRITE16(GET_REGISTER(rs) + (imm << 1), GET_REGISTER(rd));
WRITE16(GET_REGISTER(cpustate, rs) + (imm << 1), GET_REGISTER(cpustate, rd));
R15 += 2;
}
break;
@ -830,15 +831,15 @@
{
rd = (insn & THUMB_STACKOP_RD) >> THUMB_STACKOP_RD_SHIFT;
offs = (UINT8)(insn & THUMB_INSN_IMM);
readword = READ32(GET_REGISTER(13) + ((UINT32)offs << 2));
SET_REGISTER(rd, readword);
readword = READ32(GET_REGISTER(cpustate, 13) + ((UINT32)offs << 2));
SET_REGISTER(cpustate, rd, readword);
R15 += 2;
}
else
{
rd = (insn & THUMB_STACKOP_RD) >> THUMB_STACKOP_RD_SHIFT;
offs = (UINT8)(insn & THUMB_INSN_IMM);
WRITE32(GET_REGISTER(13) + ((UINT32)offs << 2), GET_REGISTER(rd));
WRITE32(GET_REGISTER(cpustate, 13) + ((UINT32)offs << 2), GET_REGISTER(cpustate, rd));
R15 += 2;
}
break;
@ -847,14 +848,14 @@
{
rd = (insn & THUMB_RELADDR_RD) >> THUMB_RELADDR_RD_SHIFT;
offs = (UINT8)(insn & THUMB_INSN_IMM) << 2;
SET_REGISTER(rd, GET_REGISTER(13) + offs);
SET_REGISTER(cpustate, rd, GET_REGISTER(cpustate, 13) + offs);
R15 += 2;
}
else /* ADD Rd, PC, #nn */
{
rd = (insn & THUMB_RELADDR_RD) >> THUMB_RELADDR_RD_SHIFT;
offs = (UINT8)(insn & THUMB_INSN_IMM) << 2;
SET_REGISTER(rd, ((R15 + 4) & ~2) + offs);
SET_REGISTER(cpustate, rd, ((R15 + 4) & ~2) + offs);
R15 += 2;
}
break;
@ -864,7 +865,7 @@
case 0x0: /* ADD SP, #imm */
addr = (insn & THUMB_INSN_IMM);
addr &= ~THUMB_INSN_IMM_S;
SET_REGISTER(13, GET_REGISTER(13) + ((insn & THUMB_INSN_IMM_S) ? -(addr << 2) : (addr << 2)));
SET_REGISTER(cpustate, 13, GET_REGISTER(cpustate, 13) + ((insn & THUMB_INSN_IMM_S) ? -(addr << 2) : (addr << 2)));
R15 += 2;
break;
case 0x4: /* PUSH {Rlist} */
@ -872,21 +873,21 @@
{
if (insn & (1 << offs))
{
SET_REGISTER(13, GET_REGISTER(13) - 4);
WRITE32(GET_REGISTER(13), GET_REGISTER(offs));
SET_REGISTER(cpustate, 13, GET_REGISTER(cpustate, 13) - 4);
WRITE32(GET_REGISTER(cpustate, 13), GET_REGISTER(cpustate, offs));
}
}
R15 += 2;
break;
case 0x5: /* PUSH {Rlist}{LR} */
SET_REGISTER(13, GET_REGISTER(13) - 4);
WRITE32(GET_REGISTER(13), GET_REGISTER(14));
SET_REGISTER(cpustate, 13, GET_REGISTER(cpustate, 13) - 4);
WRITE32(GET_REGISTER(cpustate, 13), GET_REGISTER(cpustate, 14));
for (offs = 7; offs >= 0; offs--)
{
if (insn & (1 << offs))
{
SET_REGISTER(13, GET_REGISTER(13) - 4);
WRITE32(GET_REGISTER(13), GET_REGISTER(offs));
SET_REGISTER(cpustate, 13, GET_REGISTER(cpustate, 13) - 4);
WRITE32(GET_REGISTER(cpustate, 13), GET_REGISTER(cpustate, offs));
}
}
R15 += 2;
@ -896,8 +897,8 @@
{
if (insn & (1 << offs))
{
SET_REGISTER(offs, READ32(GET_REGISTER(13)));
SET_REGISTER(13, GET_REGISTER(13) + 4);
SET_REGISTER(cpustate, offs, READ32(GET_REGISTER(cpustate, 13)));
SET_REGISTER(cpustate, 13, GET_REGISTER(cpustate, 13) + 4);
}
}
R15 += 2;
@ -907,12 +908,12 @@
{
if (insn & (1 << offs))
{
SET_REGISTER(offs, READ32(GET_REGISTER(13)));
SET_REGISTER(13, GET_REGISTER(13) + 4);
SET_REGISTER(cpustate, offs, READ32(GET_REGISTER(cpustate, 13)));
SET_REGISTER(cpustate, 13, GET_REGISTER(cpustate, 13) + 4);
}
}
R15 = READ32(GET_REGISTER(13)) & ~1;
SET_REGISTER(13, GET_REGISTER(13) + 4);
R15 = READ32(GET_REGISTER(cpustate, 13)) & ~1;
SET_REGISTER(cpustate, 13, GET_REGISTER(cpustate, 13) + 4);
break;
default:
fatalerror("%08x: Gb Undefined Thumb instruction: %04x\n", pc, insn);
@ -925,7 +926,7 @@
UINT32 ld_st_address;
rd = (insn & THUMB_MULTLS_BASE) >> THUMB_MULTLS_BASE_SHIFT;
ld_st_address = GET_REGISTER(rd) & 0xfffffffc;
ld_st_address = GET_REGISTER(cpustate, rd) & 0xfffffffc;
if (insn & THUMB_MULTLS) /* Load */
{
@ -936,12 +937,12 @@
{
if (insn & (1 << offs))
{
SET_REGISTER(offs, READ32(ld_st_address));
SET_REGISTER(cpustate, offs, READ32(ld_st_address));
ld_st_address += 4;
}
}
if (!rd_in_list)
SET_REGISTER(rd, ld_st_address);
SET_REGISTER(cpustate, rd, ld_st_address);
R15 += 2;
}
else /* Store */
@ -950,11 +951,11 @@
{
if (insn & (1 << offs))
{
WRITE32(ld_st_address, GET_REGISTER(offs));
WRITE32(ld_st_address, GET_REGISTER(cpustate, offs));
ld_st_address += 4;
}
}
SET_REGISTER(rd, ld_st_address);
SET_REGISTER(cpustate, rd, ld_st_address);
R15 += 2;
}
}
@ -1108,7 +1109,7 @@
R15 += 2;
break;
case COND_NV: // SWI (this is sort of a "hole" in the opcode encoding)
ARM7.pendingSwi = 1;
cpustate->pendingSwi = 1;
ARM7_CHECKIRQ;
break;
}
@ -1116,10 +1117,10 @@
case 0xe: /* B #offs */
if (insn & THUMB_BLOP_LO)
{
addr = GET_REGISTER(14);
addr = GET_REGISTER(cpustate, 14);
addr += (insn & THUMB_BLOP_OFFS) << 1;
addr &= 0xfffffffc;
SET_REGISTER(14, (R15 + 4) | 1);
SET_REGISTER(cpustate, 14, (R15 + 4) | 1);
R15 = addr;
}
else
@ -1135,9 +1136,9 @@
case 0xf: /* BL */
if (insn & THUMB_BLOP_LO)
{
addr = GET_REGISTER(14);
addr = GET_REGISTER(cpustate, 14);
addr += (insn & THUMB_BLOP_OFFS) << 1;
SET_REGISTER(14, (R15 + 2) | 1);
SET_REGISTER(cpustate, 14, (R15 + 2) | 1);
R15 = addr;
//R15 += 2;
}
@ -1149,7 +1150,7 @@
addr |= 0xff800000;
}
addr += R15 + 4;
SET_REGISTER(14, addr);
SET_REGISTER(cpustate, 14, addr);
R15 += 2;
}
break;
@ -1164,7 +1165,7 @@
/* load 32 bit instruction */
pc = R15;
insn = memory_decrypted_read_dword(ARM7.program, pc);
insn = memory_decrypted_read_dword(cpustate->program, pc);
/* process condition codes for this instruction */
switch (insn >> INSN_COND_SHIFT)
@ -1240,7 +1241,7 @@
/* Branch and Exchange (BX) */
if ((insn & 0x0ffffff0) == 0x012fff10) // bits 27-4 == 000100101111111111110001
{
R15 = GET_REGISTER(insn & 0x0f);
R15 = GET_REGISTER(cpustate, insn & 0x0f);
// If new PC address has A0 set, switch to Thumb mode
if (R15 & 1) {
SET_CPSR(GET_CPSR|T_MASK);
@ -1254,13 +1255,13 @@
/* Half Word Data Transfer */
if (insn & 0x60) // bits = 6-5 != 00
{
HandleHalfWordDT(insn);
HandleHalfWordDT(cpustate, insn);
}
else
/* Swap */
if (insn & 0x01000000) // bit 24 = 1
{
HandleSwap(insn);
HandleSwap(cpustate, insn);
}
/* Multiply Or Multiply Long */
else
@ -1270,14 +1271,14 @@
{
/* Signed? */
if (insn & 0x00400000)
HandleSMulLong(insn);
HandleSMulLong(cpustate, insn);
else
HandleUMulLong(insn);
HandleUMulLong(cpustate, insn);
}
/* multiply */
else
{
HandleMul(insn);
HandleMul(cpustate, insn);
}
R15 += 4;
}
@ -1289,14 +1290,14 @@
/* PSR Transfer (MRS & MSR) */
if (((insn & 0x00100000) == 0) && ((insn & 0x01800000) == 0x01000000)) // S bit must be clear, and bit 24,23 = 10
{
HandlePSRTransfer(insn);
HandlePSRTransfer(cpustate, insn);
ARM7_ICOUNT += 2; // PSR only takes 1 - S Cycle, so we add + 2, since at end, we -3..
R15 += 4;
}
/* Data Processing */
else
{
HandleALU(insn);
HandleALU(cpustate, insn);
}
}
break;
@ -1305,43 +1306,43 @@
case 5:
case 6:
case 7:
HandleMemSingle(insn);
HandleMemSingle(cpustate, insn);
R15 += 4;
break;
/* Block Data Transfer/Access */
case 8:
case 9:
HandleMemBlock(insn);
HandleMemBlock(cpustate, insn);
R15 += 4;
break;
/* Branch or Branch & Link */
case 0xa:
case 0xb:
HandleBranch(insn);
HandleBranch(cpustate, insn);
break;
/* Co-Processor Data Transfer */
case 0xc:
case 0xd:
HandleCoProcDT(insn);
HandleCoProcDT(cpustate, insn);
R15 += 4;
break;
/* Co-Processor Data Operation or Register Transfer */
case 0xe:
if (insn & 0x10)
HandleCoProcRT(insn);
HandleCoProcRT(cpustate, insn);
else
HandleCoProcDO(insn);
HandleCoProcDO(cpustate, insn);
R15 += 4;
break;
/* Software Interrupt */
case 0x0f:
ARM7.pendingSwi = 1;
cpustate->pendingSwi = 1;
ARM7_CHECKIRQ;
//couldn't find any cycle counts for SWI
break;
/* Undefined */
default:
ARM7.pendingSwi = 1;
cpustate->pendingSwi = 1;
ARM7_CHECKIRQ;
ARM7_ICOUNT -= 1; //undefined takes 4 cycles (page 77)
LOG(("%08x: Undefined instruction\n",pc-4));