Merge pull request #2057 from trap15/pgm2-work

arm7/pgm2 improvements
This commit is contained in:
R. Belmont 2017-02-11 13:36:20 -05:00 committed by GitHub
commit 85803cee20
6 changed files with 162 additions and 38 deletions

View File

@ -655,6 +655,7 @@ void arm7_cpu_device::execute_run()
insn = m_direct->read_dword(raddr); insn = m_direct->read_dword(raddr);
int op_offset = 0;
/* process condition codes for this instruction */ /* process condition codes for this instruction */
if ((insn >> INSN_COND_SHIFT) != COND_AL) if ((insn >> INSN_COND_SHIFT) != COND_AL)
{ {
@ -717,13 +718,17 @@ void arm7_cpu_device::execute_run()
{ UNEXECUTED(); goto skip_exec; } { UNEXECUTED(); goto skip_exec; }
break; break;
case COND_NV: case COND_NV:
if (m_archRev < 5)
{ UNEXECUTED(); goto skip_exec; } { UNEXECUTED(); goto skip_exec; }
else
op_offset = 0x10;
break;
} }
} }
/*******************************************************************/ /*******************************************************************/
/* If we got here - condition satisfied, so decode the instruction */ /* If we got here - condition satisfied, so decode the instruction */
/*******************************************************************/ /*******************************************************************/
(this->*ops_handler[((insn & 0xF000000) >> 24)])(insn); (this->*ops_handler[((insn & 0xF000000) >> 24) + op_offset])(insn);
} }
skip_exec: skip_exec:

View File

@ -126,7 +126,7 @@ protected:
void HandleCoProcDO(uint32_t insn); void HandleCoProcDO(uint32_t insn);
void HandleCoProcRT(uint32_t insn); void HandleCoProcRT(uint32_t insn);
void HandleCoProcDT(uint32_t insn); void HandleCoProcDT(uint32_t insn);
void HandleBranch(uint32_t insn); void HandleBranch(uint32_t insn, bool h_bit);
void HandleMemSingle(uint32_t insn); void HandleMemSingle(uint32_t insn);
void HandleHalfWordDT(uint32_t insn); void HandleHalfWordDT(uint32_t insn);
void HandleSwap(uint32_t insn); void HandleSwap(uint32_t insn);
@ -136,6 +136,7 @@ protected:
void HandleSMulLong(uint32_t insn); void HandleSMulLong(uint32_t insn);
void HandleUMulLong(uint32_t insn); void HandleUMulLong(uint32_t insn);
void HandleMemBlock(uint32_t insn); void HandleMemBlock(uint32_t insn);
void arm7ops_0123(uint32_t insn); void arm7ops_0123(uint32_t insn);
void arm7ops_4567(uint32_t insn); void arm7ops_4567(uint32_t insn);
void arm7ops_89(uint32_t insn); void arm7ops_89(uint32_t insn);
@ -143,6 +144,15 @@ protected:
void arm7ops_cd(uint32_t insn); void arm7ops_cd(uint32_t insn);
void arm7ops_e(uint32_t insn); void arm7ops_e(uint32_t insn);
void arm7ops_f(uint32_t insn); void arm7ops_f(uint32_t insn);
void arm9ops_undef(uint32_t insn);
void arm9ops_1(uint32_t insn);
void arm9ops_57(uint32_t insn);
void arm9ops_89(uint32_t insn);
void arm9ops_ab(uint32_t insn);
void arm9ops_c(uint32_t insn);
void arm9ops_e(uint32_t insn);
void set_cpsr(uint32_t val); void set_cpsr(uint32_t val);
bool arm7_tlb_translate(offs_t &addr, int flags); bool arm7_tlb_translate(offs_t &addr, int flags);
uint32_t arm7_tlb_get_second_level_descriptor( uint32_t granularity, uint32_t first_desc, uint32_t vaddr ); uint32_t arm7_tlb_get_second_level_descriptor( uint32_t granularity, uint32_t first_desc, uint32_t vaddr );
@ -268,7 +278,7 @@ protected:
static const arm7thumb_ophandler thumb_handler[0x40*0x10]; static const arm7thumb_ophandler thumb_handler[0x40*0x10];
typedef void ( arm7_cpu_device::*arm7ops_ophandler )(uint32_t); typedef void ( arm7_cpu_device::*arm7ops_ophandler )(uint32_t);
static const arm7ops_ophandler ops_handler[0x10]; static const arm7ops_ophandler ops_handler[0x20];
// //
// DRC // DRC

View File

@ -172,14 +172,19 @@ static void WriteRegisterOperand1( std::ostream &stream, uint32_t opcode )
} /* WriteRegisterOperand */ } /* WriteRegisterOperand */
static void WriteBranchAddress( std::ostream &stream, uint32_t pc, uint32_t opcode ) static void WriteBranchAddress( std::ostream &stream, uint32_t pc, uint32_t opcode, bool h_bit )
{ {
opcode &= 0x00ffffff; opcode <<= 2;
if( opcode&0x00800000 ) if (h_bit && (opcode & 0x04000000))
{ {
opcode |= 0xff000000; /* sign-extend */ opcode |= 2;
} }
pc += 8+4*opcode; opcode &= 0x03fffffe;
if( opcode & 0x02000000 )
{
opcode |= 0xfc000000; /* sign-extend */
}
pc += 8+opcode;
util::stream_format( stream, "$%x", pc ); util::stream_format( stream, "$%x", pc );
} /* WriteBranchAddress */ } /* WriteBranchAddress */
@ -205,7 +210,18 @@ static uint32_t arm7_disasm( std::ostream &stream, uint32_t pc, uint32_t opcode
pConditionCode= pConditionCodeTable[opcode>>28]; pConditionCode= pConditionCodeTable[opcode>>28];
if( (opcode&0x0ffffff0)==0x012fff10 ) { //bits 27-4 == 000100101111111111110001 if( (opcode&0xfe000000)==0xfa000000 ) //bits 31-25 == 1111 101 (BLX - v5)
{
/* BLX */
util::stream_format( stream, "BLX" );
dasmflags = DASMFLAG_STEP_OVER;
WritePadding(stream, start_position);
WriteBranchAddress( stream, pc, opcode, true );
}
else if( (opcode&0x0ffffff0)==0x012fff10 ) //bits 27-4 == 000100101111111111110001
{
/* Branch and Exchange (BX) */ /* Branch and Exchange (BX) */
util::stream_format( stream, "B"); util::stream_format( stream, "B");
util::stream_format( stream, "%sX", pConditionCode ); util::stream_format( stream, "%sX", pConditionCode );
@ -636,7 +652,7 @@ static uint32_t arm7_disasm( std::ostream &stream, uint32_t pc, uint32_t opcode
WritePadding(stream, start_position); WritePadding(stream, start_position);
WriteBranchAddress( stream, pc, opcode ); WriteBranchAddress( stream, pc, opcode, false );
} }
else if( (opcode&0x0e000000)==0x0c000000 ) //bits 27-25 == 110 else if( (opcode&0x0e000000)==0x0c000000 ) //bits 27-25 == 110
{ {

View File

@ -378,9 +378,14 @@ void arm7_cpu_device::HandleCoProcDT(uint32_t insn)
SetRegister(rn, ornv); SetRegister(rn, ornv);
} }
void arm7_cpu_device::HandleBranch(uint32_t insn) void arm7_cpu_device::HandleBranch(uint32_t insn, bool h_bit)
{ {
uint32_t off = (insn & INSN_BRANCH) << 2; uint32_t off = (insn & INSN_BRANCH) << 2;
if (h_bit)
{
// H goes to bit1
off |= (insn & 0x01000000) >> 23;
}
/* Save PC into LR if this is a branch with link */ /* Save PC into LR if this is a branch with link */
if (insn & INSN_BL) if (insn & INSN_BL)
@ -1519,14 +1524,105 @@ void arm7_cpu_device::HandleMemBlock(uint32_t insn)
} /* HandleMemBlock */ } /* HandleMemBlock */
const arm7_cpu_device::arm7ops_ophandler arm7_cpu_device::ops_handler[0x10] = const arm7_cpu_device::arm7ops_ophandler arm7_cpu_device::ops_handler[0x20] =
{ {
&arm7_cpu_device::arm7ops_0123, &arm7_cpu_device::arm7ops_0123, &arm7_cpu_device::arm7ops_0123, &arm7_cpu_device::arm7ops_0123, &arm7_cpu_device::arm7ops_0123, &arm7_cpu_device::arm7ops_0123, &arm7_cpu_device::arm7ops_0123, &arm7_cpu_device::arm7ops_0123,
&arm7_cpu_device::arm7ops_4567, &arm7_cpu_device::arm7ops_4567, &arm7_cpu_device::arm7ops_4567, &arm7_cpu_device::arm7ops_4567, &arm7_cpu_device::arm7ops_4567, &arm7_cpu_device::arm7ops_4567, &arm7_cpu_device::arm7ops_4567, &arm7_cpu_device::arm7ops_4567,
&arm7_cpu_device::arm7ops_89, &arm7_cpu_device::arm7ops_89, &arm7_cpu_device::arm7ops_ab, &arm7_cpu_device::arm7ops_ab, &arm7_cpu_device::arm7ops_89, &arm7_cpu_device::arm7ops_89, &arm7_cpu_device::arm7ops_ab, &arm7_cpu_device::arm7ops_ab,
&arm7_cpu_device::arm7ops_cd, &arm7_cpu_device::arm7ops_cd, &arm7_cpu_device::arm7ops_e, &arm7_cpu_device::arm7ops_f, &arm7_cpu_device::arm7ops_cd, &arm7_cpu_device::arm7ops_cd, &arm7_cpu_device::arm7ops_e, &arm7_cpu_device::arm7ops_f,
&arm7_cpu_device::arm9ops_undef,&arm7_cpu_device::arm9ops_1, &arm7_cpu_device::arm9ops_undef,&arm7_cpu_device::arm9ops_undef,
&arm7_cpu_device::arm9ops_undef,&arm7_cpu_device::arm9ops_57, &arm7_cpu_device::arm9ops_undef,&arm7_cpu_device::arm9ops_57,
&arm7_cpu_device::arm9ops_89, &arm7_cpu_device::arm9ops_89, &arm7_cpu_device::arm9ops_ab, &arm7_cpu_device::arm9ops_ab,
&arm7_cpu_device::arm9ops_c, &arm7_cpu_device::arm9ops_undef,&arm7_cpu_device::arm9ops_e, &arm7_cpu_device::arm9ops_undef,
}; };
void arm7_cpu_device::arm9ops_undef(uint32_t insn)
{
// unsupported instruction
LOG(("ARM7: Instruction %08X unsupported\n", insn));
}
void arm7_cpu_device::arm9ops_1(uint32_t insn)
{
/* Change processor state (CPS) */
if ((insn & 0x00f10020) == 0x00000000)
{
// unsupported (armv6 onwards only)
arm9ops_undef(insn);
}
else if ((insn & 0x00ff00f0) == 0x00010000) /* set endianness (SETEND) */
{
// unsupported (armv6 onwards only)
arm9ops_undef(insn);
}
else
{
arm9ops_undef(insn);
}
}
void arm7_cpu_device::arm9ops_57(uint32_t insn)
{
/* Cache Preload (PLD) */
if ((insn & 0x0070f000) == 0x0050f000)
{
// unsupported (armv6 onwards only)
arm9ops_undef(insn);
}
else
{
arm9ops_undef(insn);
}
}
void arm7_cpu_device::arm9ops_89(uint32_t insn)
{
/* Save Return State (SRS) */
if ((insn & 0x005f0f00) == 0x004d0500)
{
// unsupported (armv6 onwards only)
arm9ops_undef(insn);
}
else if ((insn & 0x00500f00) == 0x00100a00) /* Return From Exception (RFE) */
{
// unsupported (armv6 onwards only)
arm9ops_undef(insn);
}
else
{
arm9ops_undef(insn);
}
}
void arm7_cpu_device::arm9ops_ab(uint32_t insn)
{
// BLX
HandleBranch(insn, true);
set_cpsr(GET_CPSR|T_MASK);
}
void arm7_cpu_device::arm9ops_c(uint32_t insn)
{
/* Additional coprocessor double register transfer */
if ((insn & 0x00e00000) == 0x00400000)
{
// unsupported
arm9ops_undef(insn);
}
else
{
arm9ops_undef(insn);
}
}
void arm7_cpu_device::arm9ops_e(uint32_t insn)
{
/* Additional coprocessor register transfer */
// unsupported
arm9ops_undef(insn);
}
void arm7_cpu_device::arm7ops_0123(uint32_t insn) void arm7_cpu_device::arm7ops_0123(uint32_t insn)
{ {
//case 0: //case 0:
@ -1824,7 +1920,7 @@ void arm7_cpu_device::arm7ops_ab(uint32_t insn) /* Branch or Branch & Link */
{ {
//case 0xa: //case 0xa:
//case 0xb: //case 0xb:
HandleBranch(insn); HandleBranch(insn, false);
// break; // break;
} }

View File

@ -1562,6 +1562,7 @@ void arm7_cpu_device::tg0e_1(uint32_t pc, uint32_t op)
addr &= 0xfffffffc; addr &= 0xfffffffc;
SetRegister(14, (R15 + 4) | 1); SetRegister(14, (R15 + 4) | 1);
R15 = addr; R15 = addr;
set_cpsr(GET_CPSR & ~T_MASK);
} }
/* BL */ /* BL */

View File

@ -4,22 +4,15 @@
Motherboard is bare bones stuff, and does not contain any ROMs. Motherboard is bare bones stuff, and does not contain any ROMs.
The IGS036 used by the games is an ARM based CPU, like IGS027A used on PGM1 it has internal ROM. The IGS036 used by the games is an ARM based CPU, like IGS027A used on PGM1 it has internal ROM.
Decryption should be correct in most cases, but the ARM mode code at the start of the external Decryption should be correct in most cases.
ROMs is a bit weird, with many BNV instructions rather than jumps. Maybe the ARM is customized, The ARM appears to be ARMv5T, probably an ARM9.
the code has been 'NOPPED' out this way (BNV is Branch Never) or it's a different type of ARM?
- Some of the THUMB code looks like THUMB2 code
eg
f004 BL (HI) 00004000
e51f B #fffffa3e
0434 LSL R4, R6, 16
0000 LSL R0, R0, 0
should be a 32-bit branch instruction with the 2nd dword used as data.
We need to determine where VRAM etc. map in order to attempt tests on the PCBs. We need to determine where VRAM etc. map in order to attempt tests on the PCBs.
We will also need to try to attack the internal ROM, as there are many many calls made into it.
Chances are it'll be possible to get it to copy itself out, or black-box the behavior.
All calls to the IROM are done through small shims, so it should also be possible to hack around
the IROM if we can't get the dump out.
PGM2 Motherboard Components: PGM2 Motherboard Components:
@ -80,14 +73,16 @@ public:
void screen_eof_pgm2(screen_device &screen, bool state); void screen_eof_pgm2(screen_device &screen, bool state);
required_device<cpu_device> m_maincpu; required_device<cpu_device> m_maincpu;
void pgm_create_dummy_internal_arm_region(int addr); void pgm_create_dummy_internal_arm_region();
}; };
static ADDRESS_MAP_START( pgm2_map, AS_PROGRAM, 32, pgm2_state ) static ADDRESS_MAP_START( pgm2_map, AS_PROGRAM, 32, pgm2_state )
AM_RANGE(0x00000000, 0x00003fff) AM_ROM //AM_REGION("user1", 0x00000) // internal ROM AM_RANGE(0x00000000, 0x00003fff) AM_ROM //AM_REGION("user1", 0x00000) // internal ROM
AM_RANGE(0x08000000, 0x087fffff) AM_ROM AM_REGION("user1", 0) // not 100% sure it maps here.
AM_RANGE(0xffff0000, 0xffffffff) AM_RAM
AM_RANGE(0x10000000, 0x107fffff) AM_ROM AM_MIRROR(0x0f800000) AM_REGION("user1", 0) // external ROM
AM_RANGE(0x20000000, 0x2007ffff) AM_RAM // main SRAM?
// This doesn't exist, it's just necessary because our stub IPL doesn't set SP
AM_RANGE(0xfff00000, 0xffffffff) AM_RAM
ADDRESS_MAP_END ADDRESS_MAP_END
static INPUT_PORTS_START( pgm2 ) static INPUT_PORTS_START( pgm2 )
@ -169,7 +164,7 @@ static GFXDECODE_START( pgm2 )
GFXDECODE_END GFXDECODE_END
void pgm2_state::pgm_create_dummy_internal_arm_region(int addr) void pgm2_state::pgm_create_dummy_internal_arm_region()
{ {
uint16_t *temp16 = (uint16_t *)memregion("maincpu")->base(); uint16_t *temp16 = (uint16_t *)memregion("maincpu")->base();
int i; int i;
@ -180,9 +175,11 @@ void pgm2_state::pgm_create_dummy_internal_arm_region(int addr)
} }
int base = 0; int base = 0;
int addr = 0x10000000;
// just do a jump to 0x080003c9 because there is some valid thumb code there with the current hookup.. // just do a jump to 0x10000000 because that looks possibly correct.
// i'd expect valid non-thumb code at 0x08000000 tho? // we probably should be setting up stack and other things too, but we
// don't really know that info yet.
temp16[(base) / 2] = 0x0004; base += 2; temp16[(base) / 2] = 0x0004; base += 2;
temp16[(base) / 2] = 0xe59f; base += 2; temp16[(base) / 2] = 0xe59f; base += 2;
@ -204,7 +201,6 @@ static MACHINE_CONFIG_START( pgm2, pgm2_state )
/* basic machine hardware */ /* basic machine hardware */
MCFG_CPU_ADD("maincpu", ARM9, 20000000) // ?? ARM baesd CPU, has internal ROM. MCFG_CPU_ADD("maincpu", ARM9, 20000000) // ?? ARM baesd CPU, has internal ROM.
MCFG_CPU_PROGRAM_MAP(pgm2_map) MCFG_CPU_PROGRAM_MAP(pgm2_map)
// MCFG_DEVICE_DISABLE()
@ -503,7 +499,7 @@ DRIVER_INIT_MEMBER(pgm2_state,orleg2)
igs036_decryptor decrypter(orleg2_key); igs036_decryptor decrypter(orleg2_key);
decrypter.decrypter_rom(memregion("user1")); decrypter.decrypter_rom(memregion("user1"));
pgm_create_dummy_internal_arm_region(0x80003c9); pgm_create_dummy_internal_arm_region();
} }
DRIVER_INIT_MEMBER(pgm2_state,kov2nl) DRIVER_INIT_MEMBER(pgm2_state,kov2nl)
@ -516,7 +512,7 @@ DRIVER_INIT_MEMBER(pgm2_state,kov2nl)
igs036_decryptor decrypter(kov2_key); igs036_decryptor decrypter(kov2_key);
decrypter.decrypter_rom(memregion("user1")); decrypter.decrypter_rom(memregion("user1"));
pgm_create_dummy_internal_arm_region(0x8000069); pgm_create_dummy_internal_arm_region();
} }
DRIVER_INIT_MEMBER(pgm2_state,ddpdojh) DRIVER_INIT_MEMBER(pgm2_state,ddpdojh)
@ -529,7 +525,7 @@ DRIVER_INIT_MEMBER(pgm2_state,ddpdojh)
igs036_decryptor decrypter(ddpdoj_key); igs036_decryptor decrypter(ddpdoj_key);
decrypter.decrypter_rom(memregion("user1")); decrypter.decrypter_rom(memregion("user1"));
pgm_create_dummy_internal_arm_region(0x80003c9); pgm_create_dummy_internal_arm_region();
} }
DRIVER_INIT_MEMBER(pgm2_state,kov3) DRIVER_INIT_MEMBER(pgm2_state,kov3)
@ -542,7 +538,7 @@ DRIVER_INIT_MEMBER(pgm2_state,kov3)
igs036_decryptor decrypter(kov3_key); igs036_decryptor decrypter(kov3_key);
decrypter.decrypter_rom(memregion("user1")); decrypter.decrypter_rom(memregion("user1"));
pgm_create_dummy_internal_arm_region(0x80003c9); pgm_create_dummy_internal_arm_region();
} }