ARM7 updates:

- Preliminary PXA255 support, including Intel-specific CP14
- Hooked up TLB
This commit is contained in:
R. Belmont 2009-07-21 01:18:50 +00:00
parent 5c79939388
commit 3b09e634ac
6 changed files with 249 additions and 57 deletions

View File

@ -38,8 +38,11 @@
#include "debugger.h"
#include "arm7core.h" //include arm7 core
/* Example for showing how Co-Proc functions work */
#define TEST_COPROC_FUNCS 1
#if 0
#define LOG(x) mame_printf_debug x
#else
#define LOG(x) logerror x
#endif
/* prototypes of coprocessor functions */
static WRITE32_DEVICE_HANDLER(arm7_do_callback);
@ -69,7 +72,7 @@ INLINE arm_state *get_safe_token(const device_config *device)
assert(device != NULL);
assert(device->token != NULL);
assert(device->type == CPU);
assert(cpu_get_type(device) == CPU_ARM7 || cpu_get_type(device) == CPU_ARM9);
assert(cpu_get_type(device) == CPU_ARM7 || cpu_get_type(device) == CPU_ARM9 || cpu_get_type(device) == CPU_PXA255);
return (arm_state *)device->token;
}
@ -89,6 +92,115 @@ INLINE INT64 saturate_qbit_overflow(arm_state *cpustate, INT64 res)
return res;
}
/**************************************************************************
* ARM TLB IMPLEMENTATION
**************************************************************************/
enum
{
TLB_COARSE = 0,
TLB_FINE,
};
INLINE UINT32 arm7_tlb_get_first_level_descriptor( arm_state *cpustate, UINT32 vaddr )
{
UINT32 entry_paddr = ( COPRO_TLB_BASE & COPRO_TLB_BASE_MASK ) | ( ( vaddr & COPRO_TLB_VADDR_FLTI_MASK ) >> COPRO_TLB_VADDR_FLTI_MASK_SHIFT );
return memory_read_dword_32le( cpustate->program, entry_paddr );
}
INLINE UINT32 arm7_tlb_get_second_level_descriptor( arm_state *cpustate, UINT32 granularity, UINT32 first_desc, UINT32 vaddr )
{
UINT32 desc_lvl2 = vaddr;
switch( granularity )
{
case TLB_COARSE:
desc_lvl2 = ( first_desc & COPRO_TLB_CFLD_ADDR_MASK ) | ( ( vaddr & COPRO_TLB_VADDR_CSLTI_MASK ) >> COPRO_TLB_VADDR_CSLTI_MASK_SHIFT );
break;
case TLB_FINE:
LOG( ( "ARM7: Attempting to get second-level TLB descriptor of fine granularity\n" ) );
break;
default:
// We shouldn't be here
LOG( ( "ARM7: Attempting to get second-level TLB descriptor of invalid granularity (%d)\n", granularity ) );
break;
}
return memory_read_dword_32le( cpustate->program, desc_lvl2 );
}
INLINE UINT32 arm7_tlb_translate(arm_state *cpustate, UINT32 vaddr)
{
UINT32 desc_lvl1 = arm7_tlb_get_first_level_descriptor( cpustate, vaddr );
UINT32 desc_lvl2 = 0;
UINT32 paddr = vaddr;
switch( desc_lvl1 & 3 )
{
case COPRO_TLB_UNMAPPED:
// Unmapped, generate a translation fault
LOG( ( "ARM7: Not Yet Implemented: Translation fault on unmapped virtual address, PC = %08x, vaddr = %08x\n", R15, vaddr ) );
break;
case COPRO_TLB_COARSE_TABLE:
// Entry is the physical address of a coarse second-level table
desc_lvl2 = arm7_tlb_get_second_level_descriptor( cpustate, TLB_COARSE, desc_lvl1, vaddr );
break;
case COPRO_TLB_SECTION_TABLE:
// Entry is a section
paddr = ( desc_lvl1 & COPRO_TLB_SECTION_PAGE_MASK ) | ( vaddr & ~COPRO_TLB_SECTION_PAGE_MASK );
break;
case COPRO_TLB_FINE_TABLE:
// Entry is the physical address of a fine second-level table
LOG( ( "ARM7: Not Yet Implemented: fine second-level TLB lookup, PC = %08x, vaddr = %08x\n", R15, vaddr ) );
break;
default:
// Entry is the physical address of a three-legged termite-eaten table
break;
}
if( ( desc_lvl1 & 3 ) == COPRO_TLB_COARSE_TABLE || ( desc_lvl1 & 3 ) == COPRO_TLB_FINE_TABLE )
{
switch( desc_lvl2 & 3 )
{
case COPRO_TLB_UNMAPPED:
// Unmapped, generate a translation fault
LOG( ( "ARM7: Not Yet Implemented: Translation fault on unmapped virtual address, vaddr = %08x\n", vaddr ) );
break;
case COPRO_TLB_LARGE_PAGE:
// Large page descriptor
paddr = ( desc_lvl2 & COPRO_TLB_LARGE_PAGE_MASK ) | ( vaddr & ~COPRO_TLB_LARGE_PAGE_MASK );
break;
case COPRO_TLB_SMALL_PAGE:
// Small page descriptor
paddr = ( desc_lvl2 & COPRO_TLB_SMALL_PAGE_MASK ) | ( vaddr & ~COPRO_TLB_SMALL_PAGE_MASK );
break;
case COPRO_TLB_TINY_PAGE:
// Tiny page descriptor
if( ( desc_lvl1 & 3 ) == 1 )
{
LOG( ( "ARM7: It would appear that we're looking up a tiny page from a coarse TLB lookup. This is bad. vaddr = %08x\n", vaddr ) );
}
paddr = ( desc_lvl2 & COPRO_TLB_TINY_PAGE_MASK ) | ( vaddr & ~COPRO_TLB_TINY_PAGE_MASK );
break;
}
}
return paddr;
}
static CPU_TRANSLATE( arm7 )
{
arm_state *cpustate = (device != NULL) ? device->token : NULL;
/* only applies to the program address space and only does something if the MMU's enabled */
if( space == ADDRESS_SPACE_PROGRAM && ( COPRO_CTRL & COPRO_CTRL_MMU_EN ) )
{
*address = arm7_tlb_translate(cpustate, *address);
}
return TRUE;
}
/* include the arm7 core */
#include "arm7core.c"
@ -130,10 +242,21 @@ static CPU_RESET( arm9 )
arm_state *cpustate = device->token;
// must call core reset
cpustate->archRev = 5; // ARMv5
cpustate->archFlags = eARM_ARCHFLAGS_T; // has Thumb
arm7_core_reset(device);
cpustate->archRev = 5; // ARMv5
cpustate->archFlags = eARM_ARCHFLAGS_T | eARM_ARCHFLAGS_E; // has TE extensions
}
static CPU_RESET( pxa255 )
{
arm_state *cpustate = device->token;
// must call core reset
arm7_core_reset(device);
cpustate->archRev = 5; // ARMv5
cpustate->archFlags = eARM_ARCHFLAGS_T | eARM_ARCHFLAGS_E | eARM_ARCHFLAGS_XSCALE; // has TE and XScale extensions
}
static CPU_EXIT( arm7 )
@ -348,6 +471,7 @@ CPU_GET_INFO( arm7 )
case CPUINFO_FCT_BURN: info->burn = NULL; break;
case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(arm7); break;
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &ARM7_ICOUNT; break;
case CPUINFO_FCT_TRANSLATE: info->translate = CPU_TRANSLATE_NAME(arm7); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case DEVINFO_STR_NAME: strcpy(info->s, "ARM7"); break;
@ -431,9 +555,18 @@ CPU_GET_INFO( arm9 )
}
}
/* ARM system coprocessor support */
CPU_GET_INFO( pxa255 )
{
switch (state)
{
case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(pxa255); break;
case DEVINFO_STR_NAME: strcpy(info->s, "PXA255"); break;
default: CPU_GET_INFO_CALL(arm7);
break;
}
}
#define LOG(x) logerror x
/* ARM system coprocessor support */
static WRITE32_DEVICE_HANDLER( arm7_do_callback )
{
@ -446,8 +579,42 @@ static READ32_DEVICE_HANDLER( arm7_rt_r_callback )
UINT8 cReg = ( opcode & INSN_COPRO_CREG ) >> INSN_COPRO_CREG_SHIFT;
UINT8 op2 = ( opcode & INSN_COPRO_OP2 ) >> INSN_COPRO_OP2_SHIFT;
UINT8 op3 = opcode & INSN_COPRO_OP3;
UINT8 cpnum = (opcode & INSN_COPRO_CPNUM) >> INSN_COPRO_CPNUM_SHIFT;
UINT32 data = 0;
// printf("cpnum %d cReg %d op2 %d op3 %d (%x)\n", cpnum, cReg, op2, op3, GET_REGISTER(cpustate, 15));
// we only handle system copro here
if (cpnum != 15)
{
if (cpustate->archFlags & eARM_ARCHFLAGS_XSCALE)
{
// handle XScale specific CP14
if (cpnum == 14)
{
switch( cReg )
{
case 1: // clock counter
data = (UINT32)cpu_get_total_cycles(device);
break;
default:
break;
}
}
else
{
fatalerror("XScale: Unhandled coprocessor %d (archFlags %x)\n", cpnum, cpustate->archFlags);
}
return data;
}
else
{
fatalerror("ARM7: Unhandled coprocessor %d (archFlags %x)\n", cpnum, cpustate->archFlags);
}
}
switch( cReg )
{
case 4:
@ -517,11 +684,9 @@ static READ32_DEVICE_HANDLER( arm7_rt_r_callback )
LOG( ( "arm7_rt_r_callback, ID\n" ) );
break;
case 1: // Control
LOG( ( "arm7_rt_r_callback, Control\n" ) );
data = COPRO_CTRL;
data = COPRO_CTRL | 0x70; // bits 4-6 always read back as "1" (bit 3 too in XScale)
break;
case 2: // Translation Table Base
LOG( ( "arm7_rt_r_callback, TLB Base\n" ) );
data = COPRO_TLB_BASE;
break;
case 3: // Domain Access Control
@ -557,7 +722,22 @@ static WRITE32_DEVICE_HANDLER( arm7_rt_w_callback )
UINT8 cReg = ( opcode & INSN_COPRO_CREG ) >> INSN_COPRO_CREG_SHIFT;
UINT8 op2 = ( opcode & INSN_COPRO_OP2 ) >> INSN_COPRO_OP2_SHIFT;
UINT8 op3 = opcode & INSN_COPRO_OP3;
UINT8 cpnum = (opcode & INSN_COPRO_CPNUM) >> INSN_COPRO_CPNUM_SHIFT;
// handle XScale specific CP14 - just eat writes for now
if (cpnum != 15)
{
if (cpnum == 14)
{
LOG( ("arm7_rt_w_callback: write %x to XScale CP14 reg %d\n", data, cReg) );
return;
}
else
{
fatalerror("ARM7: Unhandled coprocessor %d\n", cpnum);
}
}
switch( cReg )
{
case 0:
@ -581,10 +761,6 @@ static WRITE32_DEVICE_HANDLER( arm7_rt_w_callback )
( data & COPRO_CTRL_ICACHE_EN ) >> COPRO_CTRL_ICACHE_EN_SHIFT ) );
LOG( ( " Int Vector Adjust:%d\n", ( data & COPRO_CTRL_INTVEC_ADJUST ) >> COPRO_CTRL_INTVEC_ADJUST_SHIFT ) );
COPRO_CTRL = data & COPRO_CTRL_MASK;
if( COPRO_CTRL & COPRO_CTRL_MMU_EN )
{
// change_pc(arm7_tlb_translate(R15));
}
break;
case 2: // Translation Table Base
LOG( ( "arm7_rt_w_callback TLB Base = %08x (%d) (%d)\n", data, op2, op3 ) );
@ -600,7 +776,7 @@ static WRITE32_DEVICE_HANDLER( arm7_rt_w_callback )
LOG( ( "arm7_rt_w_callback Fault Address = %08x (%d) (%d)\n", data, op2, op3 ) );
break;
case 7: // Cache Operations
LOG( ( "arm7_rt_w_callback Cache Ops = %08x (%d) (%d)\n", data, op2, op3 ) );
// LOG( ( "arm7_rt_w_callback Cache Ops = %08x (%d) (%d)\n", data, op2, op3 ) );
break;
case 8: // TLB Operations
LOG( ( "arm7_rt_w_callback TLB Ops = %08x (%d) (%d)\n", data, op2, op3 ) );

View File

@ -44,4 +44,7 @@ extern CPU_GET_INFO( arm7 );
extern CPU_GET_INFO( arm9 );
#define CPU_ARM9 CPU_GET_INFO_NAME( arm9 )
extern CPU_GET_INFO( pxa255 );
#define CPU_PXA255 CPU_GET_INFO_NAME( pxa255 )
#endif /* __ARM7_H__ */

View File

@ -81,12 +81,6 @@
#define ARM7_DEBUG_CORE 0
#if 0
#define LOG(x) mame_printf_debug x
#else
#define LOG(x) logerror x
#endif
/* Prototypes */
// SJE: should these be inline? or are they too big to see any benefit?
@ -137,6 +131,11 @@ char *(*arm7_dasm_cop_do_callback)(arm_state *cpustate, char *pBuf, UINT32 opcod
***************************************************************************/
INLINE void arm7_cpu_write32(arm_state *cpustate, UINT32 addr, UINT32 data)
{
if( COPRO_CTRL & COPRO_CTRL_MMU_EN )
{
addr = arm7_tlb_translate( cpustate, addr );
}
addr &= ~3;
memory_write_dword_32le(cpustate->program, addr, data);
}
@ -144,12 +143,22 @@ INLINE void arm7_cpu_write32(arm_state *cpustate, UINT32 addr, UINT32 data)
INLINE void arm7_cpu_write16(arm_state *cpustate, UINT32 addr, UINT16 data)
{
if( COPRO_CTRL & COPRO_CTRL_MMU_EN )
{
addr = arm7_tlb_translate( cpustate, addr );
}
addr &= ~1;
memory_write_word_32le(cpustate->program, addr, data);
}
INLINE void arm7_cpu_write8(arm_state *cpustate, UINT32 addr, UINT8 data)
{
if( COPRO_CTRL & COPRO_CTRL_MMU_EN )
{
addr = arm7_tlb_translate( cpustate, addr );
}
memory_write_byte_32le(cpustate->program, addr, data);
}
@ -157,6 +166,11 @@ INLINE UINT32 arm7_cpu_read32(arm_state *cpustate, offs_t addr)
{
UINT32 result;
if( COPRO_CTRL & COPRO_CTRL_MMU_EN )
{
addr = arm7_tlb_translate( cpustate, addr );
}
if (addr & 3)
{
result = memory_read_dword_32le(cpustate->program, addr & ~3);
@ -174,6 +188,11 @@ INLINE UINT16 arm7_cpu_read16(arm_state *cpustate, offs_t addr)
{
UINT16 result;
if( COPRO_CTRL & COPRO_CTRL_MMU_EN )
{
addr = arm7_tlb_translate( cpustate, addr );
}
result = memory_read_word_32le(cpustate->program, addr & ~1);
if (addr & 1)
@ -186,6 +205,11 @@ INLINE UINT16 arm7_cpu_read16(arm_state *cpustate, offs_t addr)
INLINE UINT8 arm7_cpu_read8(arm_state *cpustate, offs_t addr)
{
if( COPRO_CTRL & COPRO_CTRL_MMU_EN )
{
addr = arm7_tlb_translate( cpustate, addr );
}
// Handle through normal 8 bit handler (for 32 bit cpu)
return memory_read_byte_32le(cpustate->program, addr);
}

View File

@ -148,6 +148,8 @@ enum
eARM_ARCHFLAGS_E = 2, // extended DSP operations present (only for v5+)
eARM_ARCHFLAGS_J = 4, // "Jazelle" (direct execution of Java bytecode)
eARM_ARCHFLAGS_MMU = 8, // has on-board MMU (traditional ARM style like the SA1110)
eARM_ARCHFLAGS_SA = 16, // StrongARM extensions (enhanced TLB)
eARM_ARCHFLAGS_XSCALE = 32, // XScale extensions (CP14, enhanced TLB)
};
#define ARM7CORE_REGS \
@ -350,11 +352,13 @@ static const int sRegisterTable[ARM7_NUM_MODES][18] =
#define INSN_COPRO_N ((UINT32) 0x00100000u)
#define INSN_COPRO_CREG ((UINT32) 0x000f0000u)
#define INSN_COPRO_AREG ((UINT32) 0x0000f000u)
#define INSN_COPRO_CPNUM ((UINT32) 0x00000f00u)
#define INSN_COPRO_OP2 ((UINT32) 0x000000e0u)
#define INSN_COPRO_OP3 ((UINT32) 0x0000000fu)
#define INSN_COPRO_N_SHIFT 20
#define INSN_COPRO_CREG_SHIFT 16
#define INSN_COPRO_AREG_SHIFT 12
#define INSN_COPRO_CPNUM_SHIFT 8
#define INSN_COPRO_OP2_SHIFT 5
#define THUMB_INSN_TYPE ((UINT16)0xf000)

View File

@ -53,13 +53,17 @@
/* handle Thumb instructions if active */
if (T_IS_SET(GET_CPSR))
{
UINT32 readword;
UINT32 addr;
UINT32 readword, addr, raddr;
UINT32 rm, rn, rs, rd, op2, imm, rrs, rrd;
INT32 offs;
pc = R15;
insn = memory_decrypted_read_word(cpustate->program, pc & (~1));
raddr = pc & (~1);
if ( COPRO_CTRL & COPRO_CTRL_MMU_EN )
{
raddr = arm7_tlb_translate(cpustate, raddr);
}
insn = memory_decrypted_read_word(cpustate->program, raddr);
ARM7_ICOUNT -= (3 - thumbCycles[insn >> 8]);
switch ((insn & THUMB_INSN_TYPE) >> THUMB_INSN_TYPE_SHIFT)
{
@ -1165,6 +1169,10 @@
/* load 32 bit instruction */
pc = R15;
if ( COPRO_CTRL & COPRO_CTRL_MMU_EN )
{
pc = arm7_tlb_translate(cpustate, pc);
}
insn = memory_decrypted_read_dword(cpustate->program, pc);
/* process condition codes for this instruction */

View File

@ -15,8 +15,7 @@
* PCB also contains a custom ASIC, probably used for the decryption
*
* TODO:
* Figure out weird memory test subroutine at 1c8
* PXA255 MMU and peripherals
* PXA255 peripherals
*
**************************************************************************/
@ -37,9 +36,16 @@ static READ32_HANDLER( os_timer_counter_r )
return ret;
}
// intel docs says nothing's here, but code at e4010 begs to differ
static READ32_HANDLER( unknown_r )
{
return 2; // TST #$2
}
static ADDRESS_MAP_START( 39in1_map, ADDRESS_SPACE_PROGRAM, 32 )
AM_RANGE(0x00000000, 0x0007ffff) AM_ROM
AM_RANGE(0x40a00010, 0x40a00013) AM_READ( os_timer_counter_r )
AM_RANGE(0x40e00000, 0x40e00003) AM_READ( unknown_r )
AM_RANGE(0xa0000000, 0xa3ffffff) AM_RAM
ADDRESS_MAP_END
@ -65,7 +71,7 @@ static MACHINE_START(39in1)
}
static MACHINE_DRIVER_START( 39in1 )
MDRV_CPU_ADD("maincpu", ARM9, 200000000) // actually Xscale PXA255, but ARM9 is a compatible subset
MDRV_CPU_ADD("maincpu", PXA255, 200000000)
MDRV_CPU_PROGRAM_MAP(39in1_map)
MDRV_PALETTE_LENGTH(32768)
@ -92,32 +98,3 @@ ROM_START( 39in1 )
ROM_END
GAME(2004, 39in1, 0, 39in1, 39in1, 0, ROT0, "????", "39 in 1 MAME bootleg", GAME_NOT_WORKING|GAME_NO_SOUND)
/*
cpu #0 (PC=00000010): unmapped program memory dword write to 40E00024 = FFFFFFFF & FFFFFFFF GPIO pin output clear 31:0
cpu #0 (PC=00000014): unmapped program memory dword write to 40E00028 = FFFFFFFF & FFFFFFFF 63:32
cpu #0 (PC=00000018): unmapped program memory dword write to 40E0002C = FFFFFFFF & FFFFFFFF 80:64
cpu #0 (PC=00000028): unmapped program memory dword write to 40E00018 = 01008000 & FFFFFFFF GPIO pin direction register 63:32
cpu #0 (PC=0000002C): unmapped program memory dword write to 40E0001C = 00020802 & FFFFFFFF pin output set 63:32
cpu #0 (PC=00000030): unmapped program memory dword write to 40E00020 = 0001CC00 & FFFFFFFF 80:64
cpu #0 (PC=00000040): unmapped program memory dword write to 40E0000C = DFE3FFDC & FFFFFFFF GPIO pin direction 31:0
cpu #0 (PC=00000044): unmapped program memory dword write to 40E00010 = FC9FAF83 & FFFFFFFF 63:32
cpu #0 (PC=00000048): unmapped program memory dword write to 40E00014 = 0001FFFF & FFFFFFFF
cpu #0 (PC=00000064): unmapped program memory dword write to 40E00054 = 80000000 & FFFFFFFF GPIO alternate function
cpu #0 (PC=00000068): unmapped program memory dword write to 40E00058 = 59000110 & FFFFFFFF
cpu #0 (PC=0000006C): unmapped program memory dword write to 40E0005C = 600A9559 & FFFFFFFF
cpu #0 (PC=00000070): unmapped program memory dword write to 40E00060 = AAA00008 & FFFFFFFF
cpu #0 (PC=00000074): unmapped program memory dword write to 40E00064 = AAAAAAAA & FFFFFFFF
cpu #0 (PC=00000078): unmapped program memory dword write to 40E00068 = 00000002 & FFFFFFFF
cpu #0 (PC=00000084): unmapped program memory dword write to 40F00004 = 00000020 & FFFFFFFF power manager sleep status
test_rt_r_callback opcode=ee160e10
test_rt_w_callback opcode=ee060e10, data from ARM7 register=2
cpu #0 (PC=0000009C): unmapped program memory dword write to 41300000 = 00000141 & FFFFFFFF core clock configure (multiplier=27, RAM is 99.53 MHz + multiplier = 2 * memory + turbo = 1x)
test_rt_w_callback opcode=ee060e10, data from ARM7 register=3
test_rt_w_callback opcode=ee060e10, data from ARM7 register=1
cpu #0 (PC=000000B4): unmapped program memory dword read from 40A00010 & FFFFFFFF OS timer/counter
cpu #0 (PC=000000B8): unmapped program memory dword read from 40A00010 & FFFFFFFF
cpu #0 (PC=000000B8): unmapped program memory dword read from 40A00010 & FFFFFFFF
*/