From 976647a2925a4624daea51a572f604a6d38f924d Mon Sep 17 00:00:00 2001 From: trap15 Date: Fri, 10 Feb 2017 22:16:10 -0800 Subject: [PATCH 1/3] ARMv5 additions to ARM7 --- src/devices/cpu/arm7/arm7.cpp | 9 ++- src/devices/cpu/arm7/arm7.h | 14 ++++- src/devices/cpu/arm7/arm7dasm.cpp | 30 +++++++--- src/devices/cpu/arm7/arm7ops.cpp | 92 ++++++++++++++++++++++++++++++- 4 files changed, 131 insertions(+), 14 deletions(-) diff --git a/src/devices/cpu/arm7/arm7.cpp b/src/devices/cpu/arm7/arm7.cpp index 9ae2d06cb85..52e148a92ac 100644 --- a/src/devices/cpu/arm7/arm7.cpp +++ b/src/devices/cpu/arm7/arm7.cpp @@ -655,6 +655,7 @@ void arm7_cpu_device::execute_run() insn = m_direct->read_dword(raddr); + int op_offset = 0; /* process condition codes for this instruction */ if ((insn >> INSN_COND_SHIFT) != COND_AL) { @@ -717,13 +718,17 @@ void arm7_cpu_device::execute_run() { UNEXECUTED(); goto skip_exec; } break; case COND_NV: - { UNEXECUTED(); goto skip_exec; } + if (m_archRev < 5) + { UNEXECUTED(); goto skip_exec; } + else + op_offset = 0x10; + break; } } /*******************************************************************/ /* 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: diff --git a/src/devices/cpu/arm7/arm7.h b/src/devices/cpu/arm7/arm7.h index 7007f4b4be6..d243c788e00 100644 --- a/src/devices/cpu/arm7/arm7.h +++ b/src/devices/cpu/arm7/arm7.h @@ -126,7 +126,7 @@ protected: void HandleCoProcDO(uint32_t insn); void HandleCoProcRT(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 HandleHalfWordDT(uint32_t insn); void HandleSwap(uint32_t insn); @@ -136,6 +136,7 @@ protected: void HandleSMulLong(uint32_t insn); void HandleUMulLong(uint32_t insn); void HandleMemBlock(uint32_t insn); + void arm7ops_0123(uint32_t insn); void arm7ops_4567(uint32_t insn); void arm7ops_89(uint32_t insn); @@ -143,6 +144,15 @@ protected: void arm7ops_cd(uint32_t insn); void arm7ops_e(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); 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 ); @@ -268,7 +278,7 @@ protected: static const arm7thumb_ophandler thumb_handler[0x40*0x10]; typedef void ( arm7_cpu_device::*arm7ops_ophandler )(uint32_t); - static const arm7ops_ophandler ops_handler[0x10]; + static const arm7ops_ophandler ops_handler[0x20]; // // DRC diff --git a/src/devices/cpu/arm7/arm7dasm.cpp b/src/devices/cpu/arm7/arm7dasm.cpp index 5288f27e9b5..3d38ea29872 100644 --- a/src/devices/cpu/arm7/arm7dasm.cpp +++ b/src/devices/cpu/arm7/arm7dasm.cpp @@ -172,14 +172,19 @@ static void WriteRegisterOperand1( std::ostream &stream, uint32_t opcode ) } /* 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; - if( opcode&0x00800000 ) + opcode <<= 2; + 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 ); } /* WriteBranchAddress */ @@ -205,7 +210,18 @@ static uint32_t arm7_disasm( std::ostream &stream, uint32_t pc, uint32_t opcode 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) */ util::stream_format( stream, "B"); 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); - WriteBranchAddress( stream, pc, opcode ); + WriteBranchAddress( stream, pc, opcode, false ); } else if( (opcode&0x0e000000)==0x0c000000 ) //bits 27-25 == 110 { diff --git a/src/devices/cpu/arm7/arm7ops.cpp b/src/devices/cpu/arm7/arm7ops.cpp index b43fa89b60b..81e93079862 100644 --- a/src/devices/cpu/arm7/arm7ops.cpp +++ b/src/devices/cpu/arm7/arm7ops.cpp @@ -378,9 +378,14 @@ void arm7_cpu_device::HandleCoProcDT(uint32_t insn) 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; + if (h_bit) + { + // H goes to bit1 + off |= (insn & 0x01000000) >> 23; + } /* Save PC into LR if this is a branch with link */ if (insn & INSN_BL) @@ -1519,14 +1524,95 @@ void arm7_cpu_device::HandleMemBlock(uint32_t insn) } /* 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_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_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) +{ +} + +void arm7_cpu_device::arm9ops_1(uint32_t insn) +{ + /* Change processor state (CPS) */ + if ((insn & 0x00f10020) == 0x00000000) + { + // unsupported (armv6 onwards only) + } + else if ((insn & 0x00ff00f0) == 0x00010000) /* set endianness (SETEND) */ + { + // unsupported (armv6 onwards only) + } + else + { + arm9ops_undef(insn); + } +} + +void arm7_cpu_device::arm9ops_57(uint32_t insn) +{ + /* Cache Preload (PLD) */ + if ((insn & 0x0070f000) == 0x0050f000) + { + // unsupported (armv6 onwards only) + } + 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) + } + else if ((insn & 0x00500f00) == 0x00100a00) /* Return From Exception (RFE) */ + { + // unsupported (armv6 onwards only) + } + else + { + arm9ops_undef(insn); + } +} + +void arm7_cpu_device::arm9ops_ab(uint32_t insn) +{ + // blx + HandleBranch(insn, true); +} + +void arm7_cpu_device::arm9ops_c(uint32_t insn) +{ + /* Additional coprocessor double register transfer */ + if ((insn & 0x00e00000) == 0x00400000) + { + // unsupported + } + else + { + arm9ops_undef(insn); + } +} + +void arm7_cpu_device::arm9ops_e(uint32_t insn) +{ + /* Additional coprocessor register transfer */ + // unsupported +} + + void arm7_cpu_device::arm7ops_0123(uint32_t insn) { //case 0: @@ -1824,7 +1910,7 @@ void arm7_cpu_device::arm7ops_ab(uint32_t insn) /* Branch or Branch & Link */ { //case 0xa: //case 0xb: - HandleBranch(insn); + HandleBranch(insn, false); // break; } From 2672fb6f8ea40953d63aef5c272dae902b3c0080 Mon Sep 17 00:00:00 2001 From: trap15 Date: Sat, 11 Feb 2017 01:04:33 -0800 Subject: [PATCH 2/3] Further fixes for ARM --- src/devices/cpu/arm7/arm7ops.cpp | 12 +++++++++++- src/devices/cpu/arm7/arm7thmb.cpp | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/devices/cpu/arm7/arm7ops.cpp b/src/devices/cpu/arm7/arm7ops.cpp index 81e93079862..f93b5c4473a 100644 --- a/src/devices/cpu/arm7/arm7ops.cpp +++ b/src/devices/cpu/arm7/arm7ops.cpp @@ -1538,6 +1538,8 @@ const arm7_cpu_device::arm7ops_ophandler arm7_cpu_device::ops_handler[0x20] = 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) @@ -1546,10 +1548,12 @@ void arm7_cpu_device::arm9ops_1(uint32_t insn) 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 { @@ -1563,6 +1567,7 @@ void arm7_cpu_device::arm9ops_57(uint32_t insn) if ((insn & 0x0070f000) == 0x0050f000) { // unsupported (armv6 onwards only) + arm9ops_undef(insn); } else { @@ -1576,10 +1581,12 @@ void arm7_cpu_device::arm9ops_89(uint32_t insn) 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 { @@ -1589,8 +1596,9 @@ void arm7_cpu_device::arm9ops_89(uint32_t insn) void arm7_cpu_device::arm9ops_ab(uint32_t insn) { - // blx + // BLX HandleBranch(insn, true); + set_cpsr(GET_CPSR|T_MASK); } void arm7_cpu_device::arm9ops_c(uint32_t insn) @@ -1599,6 +1607,7 @@ void arm7_cpu_device::arm9ops_c(uint32_t insn) if ((insn & 0x00e00000) == 0x00400000) { // unsupported + arm9ops_undef(insn); } else { @@ -1610,6 +1619,7 @@ void arm7_cpu_device::arm9ops_e(uint32_t insn) { /* Additional coprocessor register transfer */ // unsupported + arm9ops_undef(insn); } diff --git a/src/devices/cpu/arm7/arm7thmb.cpp b/src/devices/cpu/arm7/arm7thmb.cpp index 56eb819cac7..251e5b16408 100644 --- a/src/devices/cpu/arm7/arm7thmb.cpp +++ b/src/devices/cpu/arm7/arm7thmb.cpp @@ -1562,6 +1562,7 @@ void arm7_cpu_device::tg0e_1(uint32_t pc, uint32_t op) addr &= 0xfffffffc; SetRegister(14, (R15 + 4) | 1); R15 = addr; + set_cpsr(GET_CPSR & ~T_MASK); } /* BL */ From a42197691116299755b921050af955d2e011cb91 Mon Sep 17 00:00:00 2001 From: trap15 Date: Sat, 11 Feb 2017 01:08:56 -0800 Subject: [PATCH 3/3] PGM2 driver work --- src/mame/drivers/pgm2.cpp | 44 ++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/src/mame/drivers/pgm2.cpp b/src/mame/drivers/pgm2.cpp index 813d01a1ee4..fb75f617863 100644 --- a/src/mame/drivers/pgm2.cpp +++ b/src/mame/drivers/pgm2.cpp @@ -4,22 +4,15 @@ 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. - Decryption should be correct in most cases, but the ARM mode code at the start of the external - ROMs is a bit weird, with many BNV instructions rather than jumps. Maybe the ARM is customized, - 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. - + Decryption should be correct in most cases. + The ARM appears to be ARMv5T, probably an ARM9. 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: @@ -80,14 +73,16 @@ public: void screen_eof_pgm2(screen_device &screen, bool state); required_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 ) 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 static INPUT_PORTS_START( pgm2 ) @@ -169,7 +164,7 @@ static GFXDECODE_START( pgm2 ) 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(); int i; @@ -180,9 +175,11 @@ void pgm2_state::pgm_create_dummy_internal_arm_region(int addr) } int base = 0; + int addr = 0x10000000; - // just do a jump to 0x080003c9 because there is some valid thumb code there with the current hookup.. - // i'd expect valid non-thumb code at 0x08000000 tho? + // just do a jump to 0x10000000 because that looks possibly correct. + // 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] = 0xe59f; base += 2; @@ -204,7 +201,6 @@ static MACHINE_CONFIG_START( pgm2, pgm2_state ) /* basic machine hardware */ MCFG_CPU_ADD("maincpu", ARM9, 20000000) // ?? ARM baesd CPU, has internal ROM. MCFG_CPU_PROGRAM_MAP(pgm2_map) -// MCFG_DEVICE_DISABLE() @@ -503,7 +499,7 @@ DRIVER_INIT_MEMBER(pgm2_state,orleg2) igs036_decryptor decrypter(orleg2_key); decrypter.decrypter_rom(memregion("user1")); - pgm_create_dummy_internal_arm_region(0x80003c9); + pgm_create_dummy_internal_arm_region(); } DRIVER_INIT_MEMBER(pgm2_state,kov2nl) @@ -516,7 +512,7 @@ DRIVER_INIT_MEMBER(pgm2_state,kov2nl) igs036_decryptor decrypter(kov2_key); decrypter.decrypter_rom(memregion("user1")); - pgm_create_dummy_internal_arm_region(0x8000069); + pgm_create_dummy_internal_arm_region(); } DRIVER_INIT_MEMBER(pgm2_state,ddpdojh) @@ -529,7 +525,7 @@ DRIVER_INIT_MEMBER(pgm2_state,ddpdojh) igs036_decryptor decrypter(ddpdoj_key); decrypter.decrypter_rom(memregion("user1")); - pgm_create_dummy_internal_arm_region(0x80003c9); + pgm_create_dummy_internal_arm_region(); } DRIVER_INIT_MEMBER(pgm2_state,kov3) @@ -542,7 +538,7 @@ DRIVER_INIT_MEMBER(pgm2_state,kov3) igs036_decryptor decrypter(kov3_key); decrypter.decrypter_rom(memregion("user1")); - pgm_create_dummy_internal_arm_region(0x80003c9); + pgm_create_dummy_internal_arm_region(); }