diff options
Diffstat (limited to 'trunk/src/emu/cpu/arm7/arm7help.h')
-rw-r--r-- | trunk/src/emu/cpu/arm7/arm7help.h | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/arm7/arm7help.h b/trunk/src/emu/cpu/arm7/arm7help.h new file mode 100644 index 00000000000..cfd1e33cc3f --- /dev/null +++ b/trunk/src/emu/cpu/arm7/arm7help.h @@ -0,0 +1,242 @@ +/* ARM7 core helper Macros / Functions */ + +/* Macros that need to be defined according to the cpu implementation specific need */ +#define ARM7REG(reg) cpustate->sArmRegister[reg] +#define ARM7_ICOUNT cpustate->iCount + + +extern void SwitchMode(arm_state *cpustate, int cpsr_mode_val); + +#if 0 +#define LOG(x) mame_printf_debug x +#else +#define LOG(x) logerror x +#endif + +/*************** + * helper funcs + ***************/ + +// TODO LD: +// - SIGN_BITS_DIFFER = THUMB_SIGN_BITS_DIFFER +// - do while (0) +// - HandleALUAddFlags = HandleThumbALUAddFlags except for PC incr +// - HandleALUSubFlags = HandleThumbALUSubFlags except for PC incr + +#define IsNeg(i) ((i) >> 31) +#define IsPos(i) ((~(i)) >> 31) + +/* Set NZCV flags for ADDS / SUBS */ +#define HandleALUAddFlags(rd, rn, op2) \ + if (insn & INSN_S) \ + SET_CPSR(((GET_CPSR & ~(N_MASK | Z_MASK | V_MASK | C_MASK)) \ + | (((!SIGN_BITS_DIFFER(rn, op2)) && SIGN_BITS_DIFFER(rn, rd)) << V_BIT) \ + | (((IsNeg(rn) & IsNeg(op2)) | (IsNeg(rn) & IsPos(rd)) | (IsNeg(op2) & IsPos(rd))) ? C_MASK : 0) \ + | HandleALUNZFlags(rd))); \ + R15 += 4; + +#define HandleThumbALUAddFlags(rd, rn, op2) \ + SET_CPSR(((GET_CPSR & ~(N_MASK | Z_MASK | V_MASK | C_MASK)) \ + | (((!THUMB_SIGN_BITS_DIFFER(rn, op2)) && THUMB_SIGN_BITS_DIFFER(rn, rd)) << V_BIT) \ + | (((~(rn)) < (op2)) << C_BIT) \ + | HandleALUNZFlags(rd))); \ + R15 += 2; + +#define HandleALUSubFlags(rd, rn, op2) \ + if (insn & INSN_S) \ + SET_CPSR(((GET_CPSR & ~(N_MASK | Z_MASK | V_MASK | C_MASK)) \ + | ((SIGN_BITS_DIFFER(rn, op2) && SIGN_BITS_DIFFER(rn, rd)) << V_BIT) \ + | (((IsNeg(rn) & IsPos(op2)) | (IsNeg(rn) & IsPos(rd)) | (IsPos(op2) & IsPos(rd))) ? C_MASK : 0) \ + | HandleALUNZFlags(rd))); \ + R15 += 4; + +#define HandleThumbALUSubFlags(rd, rn, op2) \ + SET_CPSR(((GET_CPSR & ~(N_MASK | Z_MASK | V_MASK | C_MASK)) \ + | ((THUMB_SIGN_BITS_DIFFER(rn, op2) && THUMB_SIGN_BITS_DIFFER(rn, rd)) << V_BIT) \ + | (((IsNeg(rn) & IsPos(op2)) | (IsNeg(rn) & IsPos(rd)) | (IsPos(op2) & IsPos(rd))) ? C_MASK : 0) \ + | HandleALUNZFlags(rd))); \ + R15 += 2; + +/* Set NZC flags for logical operations. */ + +// This macro (which I didn't write) - doesn't make it obvious that the SIGN BIT = 31, just as the N Bit does, +// therefore, N is set by default +#define HandleALUNZFlags(rd) \ + (((rd) & SIGN_BIT) | ((!(rd)) << Z_BIT)) + + +// Long ALU Functions use bit 63 +#define HandleLongALUNZFlags(rd) \ + ((((rd) & ((UINT64)1 << 63)) >> 32) | ((!(rd)) << Z_BIT)) + +#define HandleALULogicalFlags(rd, sc) \ + if (insn & INSN_S) \ + SET_CPSR(((GET_CPSR & ~(N_MASK | Z_MASK | C_MASK)) \ + | HandleALUNZFlags(rd) \ + | (((sc) != 0) << C_BIT))); \ + R15 += 4; + +void set_cpsr( arm_state *cpustate, UINT32 val); + +// used to be functions, but no longer a need, so we'll use define for better speed. +#define GetRegister(cpustate, rIndex) ARM7REG(sRegisterTable[GET_MODE][rIndex]) +#define SetRegister(cpustate, rIndex, value) ARM7REG(sRegisterTable[GET_MODE][rIndex]) = value + +#define GetModeRegister(cpustate, mode, rIndex) ARM7REG(sRegisterTable[mode][rIndex]) +#define SetModeRegister(cpustate, mode, rIndex, value) ARM7REG(sRegisterTable[mode][rIndex]) = value + +int arm7_tlb_translate(arm_state *cpustate, UINT32 *addr, int flags); +void arm7_check_irq_state(arm_state *cpustate); + +typedef const void (*arm7thumb_ophandler)(arm_state*, UINT32, UINT32); + +extern arm7thumb_ophandler thumb_handler[0x40*0x10]; + +typedef const void (*arm7ops_ophandler)(arm_state*, UINT32); + +extern arm7ops_ophandler ops_handler[0x10]; + +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)); + + +/*************************************************************************** + * Default Memory Handlers + ***************************************************************************/ +INLINE void arm7_cpu_write32(arm_state *cpustate, UINT32 addr, UINT32 data) +{ + if( COPRO_CTRL & COPRO_CTRL_MMU_EN ) + { + if (!arm7_tlb_translate( cpustate, &addr, ARM7_TLB_ABORT_D | ARM7_TLB_WRITE )) + { + return; + } + } + + addr &= ~3; + if ( cpustate->endian == ENDIANNESS_BIG ) + cpustate->program->write_dword(addr, data); + else + cpustate->program->write_dword(addr, data); +} + + +INLINE void arm7_cpu_write16(arm_state *cpustate, UINT32 addr, UINT16 data) +{ + if( COPRO_CTRL & COPRO_CTRL_MMU_EN ) + { + if (!arm7_tlb_translate( cpustate, &addr, ARM7_TLB_ABORT_D | ARM7_TLB_WRITE )) + { + return; + } + } + + addr &= ~1; + if ( cpustate->endian == ENDIANNESS_BIG ) + cpustate->program->write_word(addr, data); + else + cpustate->program->write_word(addr, data); +} + +INLINE void arm7_cpu_write8(arm_state *cpustate, UINT32 addr, UINT8 data) +{ + if( COPRO_CTRL & COPRO_CTRL_MMU_EN ) + { + if (!arm7_tlb_translate( cpustate, &addr, ARM7_TLB_ABORT_D | ARM7_TLB_WRITE )) + { + return; + } + } + + if ( cpustate->endian == ENDIANNESS_BIG ) + cpustate->program->write_byte(addr, data); + else + cpustate->program->write_byte(addr, data); +} + +INLINE UINT32 arm7_cpu_read32(arm_state *cpustate, UINT32 addr) +{ + UINT32 result; + + if( COPRO_CTRL & COPRO_CTRL_MMU_EN ) + { + if (!arm7_tlb_translate( cpustate, &addr, ARM7_TLB_ABORT_D | ARM7_TLB_READ )) + { + return 0; + } + } + + if (addr & 3) + { + if ( cpustate->endian == ENDIANNESS_BIG ) + result = cpustate->program->read_dword(addr & ~3); + else + result = cpustate->program->read_dword(addr & ~3); + result = (result >> (8 * (addr & 3))) | (result << (32 - (8 * (addr & 3)))); + } + else + { + if ( cpustate->endian == ENDIANNESS_BIG ) + result = cpustate->program->read_dword(addr); + else + result = cpustate->program->read_dword(addr); + } + + return result; +} + +INLINE UINT16 arm7_cpu_read16(arm_state *cpustate, UINT32 addr) +{ + UINT16 result; + + if( COPRO_CTRL & COPRO_CTRL_MMU_EN ) + { + if (!arm7_tlb_translate( cpustate, &addr, ARM7_TLB_ABORT_D | ARM7_TLB_READ )) + { + return 0; + } + } + + if ( cpustate->endian == ENDIANNESS_BIG ) + result = cpustate->program->read_word(addr & ~1); + else + result = cpustate->program->read_word(addr & ~1); + + if (addr & 1) + { + result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); + } + + return result; +} + +INLINE UINT8 arm7_cpu_read8(arm_state *cpustate, UINT32 addr) +{ + if( COPRO_CTRL & COPRO_CTRL_MMU_EN ) + { + if (!arm7_tlb_translate( cpustate, &addr, ARM7_TLB_ABORT_D | ARM7_TLB_READ )) + { + return 0; + } + } + + // Handle through normal 8 bit handler (for 32 bit cpu) + if ( cpustate->endian == ENDIANNESS_BIG ) + return cpustate->program->read_byte(addr); + else + return cpustate->program->read_byte(addr); +} + + +/* 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(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 + |