diff --git a/src/emu/cpu/arm7/arm7.c b/src/emu/cpu/arm7/arm7.c index c3fb1761779..e7ffc5fc8e6 100644 --- a/src/emu/cpu/arm7/arm7.c +++ b/src/emu/cpu/arm7/arm7.c @@ -127,10 +127,10 @@ INLINE UINT32 arm7_tlb_get_second_level_descriptor( arm_state *arm, UINT32 granu 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 ); + 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" ) ); + desc_lvl2 = (first_desc & COPRO_TLB_FPTB_ADDR_MASK) | ((vaddr & COPRO_TLB_VADDR_FSLTI_MASK) >> COPRO_TLB_VADDR_FSLTI_MASK_SHIFT); break; default: // We shouldn't be here @@ -322,8 +322,15 @@ int arm7_tlb_translate(arm_state *arm, UINT32 *addr, int flags) } break; case COPRO_TLB_FINE_TABLE: - // Entry is the physical address of a fine second-level table - fatalerror("ARM7: Not Yet Implemented: fine second-level TLB lookup, PC = %08x, vaddr = %08x\n", R15, vaddr); + // Entry is the physical address of a coarse second-level table + if ((permission == 1) || (permission == 3)) + { + desc_lvl2 = arm7_tlb_get_second_level_descriptor( arm, TLB_FINE, desc_lvl1, vaddr ); + } + else + { + fatalerror("ARM7: Not Yet Implemented: Fine Table, Section Domain fault on virtual address, vaddr = %08x, domain = %08x, PC = %08x\n", vaddr, domain, R15); + } break; default: // Entry is the physical address of a three-legged termite-eaten table diff --git a/src/emu/cpu/arm7/arm7core.h b/src/emu/cpu/arm7/arm7core.h index d812e9a26ef..73dcd4d5593 100644 --- a/src/emu/cpu/arm7/arm7core.h +++ b/src/emu/cpu/arm7/arm7core.h @@ -103,6 +103,8 @@ enum #define COPRO_TLB_VADDR_FSLTI_MASK_SHIFT 8 #define COPRO_TLB_CFLD_ADDR_MASK 0xfffffc00 #define COPRO_TLB_CFLD_ADDR_MASK_SHIFT 10 +#define COPRO_TLB_FPTB_ADDR_MASK 0xfffff000 +#define COPRO_TLB_FPTB_ADDR_MASK_SHIFT 12 #define COPRO_TLB_SECTION_PAGE_MASK 0xfff00000 #define COPRO_TLB_LARGE_PAGE_MASK 0xffff0000 #define COPRO_TLB_SMALL_PAGE_MASK 0xfffff000 diff --git a/src/emu/cpu/arm7/arm7drc.c b/src/emu/cpu/arm7/arm7drc.c index 470cabda3da..177312718c9 100644 --- a/src/emu/cpu/arm7/arm7drc.c +++ b/src/emu/cpu/arm7/arm7drc.c @@ -2287,7 +2287,40 @@ static int generate_opcode(arm_state *arm, drcuml_block *block, compiler_state * if (T_IS_SET(GET_CPSR)) { + UINT32 raddr; + pc = R15; + + // "In Thumb state, bit [0] is undefined and must be ignored. Bits [31:1] contain the PC." + raddr = pc & (~1); + + if ( COPRO_CTRL & COPRO_CTRL_MMU_EN ) + { + if (!arm7_tlb_translate(arm, &raddr, ARM7_TLB_ABORT_P | ARM7_TLB_READ)) + { + goto skip_exec; + } + } + + UML_AND(block, I0, DRC_PC, ~1); + UML_TEST(block, mem(&COPRO_CTRL), COPRO_CTRL_MMU_EN); // test COPRO_CTRL, COPRO_CTRL_MMU_EN + UML_MOVc(block, COND_Z, I0, 0); // movz i0, 0 + UML_MOVc(block, COND_NZ, I0, ARM7_TLB_ABORT_P | ARM7_TLB_READ); // movnz i0, ARM7_TLB_ABORT_P | ARM7_TLB_READ + UML_CALLHc(block, COND_NZ, *arm->impstate->tlb_translate); // callhnz tlb_translate); + + insn = arm->direct->read_decrypted_word(raddr); + thumb_handler[(insn & 0xffc0) >> 6](arm, pc, insn); + UML_OR(block, I3, I3, ); // or i2, i2, i3 + UML_CALLHc(block, COND_NZ, *arm->impstate->tlb_translate); // callhnz tlb_translate + + } + else + { + UML_AND(block, I0, DRC_PC, ~1); + UML_TEST(block, mem(&COPRO_CTRL), COPRO_CTRL_MMU_EN); // test COPRO_CTRL, COPRO_CTRL_MMU_EN + UML_MOVc(block, COND_NZ, I3, ARM7_TLB_READ); // movnz i3, ARM7_TLB_READ + UML_OR(block, I3, I3, I3); // or i2, i2, i3 + UML_CALLHc(block, COND_NZ, *arm->impstate->tlb_translate); // callhnz tlb_translate } switch (opswitch)