diff --git a/src/emu/cpu/drcbeut.c b/src/emu/cpu/drcbeut.c index 462ec118f11..3313dc7b476 100644 --- a/src/emu/cpu/drcbeut.c +++ b/src/emu/cpu/drcbeut.c @@ -13,6 +13,13 @@ #include "drcbeut.h" +/*************************************************************************** + DEBUGGING +***************************************************************************/ + +#define LOG_RECOVER (0) + + /*************************************************************************** TYPE DEFINITIONS ***************************************************************************/ @@ -308,6 +315,9 @@ void drcmap_block_begin(drcmap_state *drcmap, drcuml_block *block) /* reset the tailptr and count */ drcmap->tailptr = &drcmap->head; drcmap->numvalues = 0; + + /* reset the variable values */ + memset(drcmap->mapvalue, 0, sizeof(drcmap->mapvalue)); } @@ -317,8 +327,8 @@ void drcmap_block_begin(drcmap_state *drcmap, drcuml_block *block) void drcmap_block_end(drcmap_state *drcmap, drcuml_block *block) { - UINT32 curvalue[DRCUML_MAPVAR_END - DRCUML_MAPVAR_M0]; - UINT8 changed[DRCUML_MAPVAR_END - DRCUML_MAPVAR_M0]; + UINT32 curvalue[DRCUML_MAPVAR_END - DRCUML_MAPVAR_M0] = { 0 }; + UINT8 changed[DRCUML_MAPVAR_END - DRCUML_MAPVAR_M0] = { 0 }; drcmap_entry *entry; drccodeptr lastptr; drccodeptr *top; @@ -343,10 +353,6 @@ void drcmap_block_end(drcmap_state *drcmap, drcuml_block *block) *dest = (drccodeptr)dest - lastptr; dest++; - /* reset the current values */ - memset(curvalue, 0, sizeof(curvalue)); - memset(changed, 0, sizeof(changed)); - /* now iterate over entries and store them */ for (entry = drcmap->head; entry != NULL; entry = entry->next) { @@ -503,6 +509,8 @@ UINT32 drcmap_get_value(drcmap_state *drcmap, drccodeptr codebase, UINT32 mapvar /* low 4 bits contain the total number of words of data */ data += controlword & 0x0f; } + if (LOG_RECOVER) + printf("recover %d @ %p = %08X\n", mapvar, codebase, result); return result; } diff --git a/src/emu/cpu/drcfe.c b/src/emu/cpu/drcfe.c index b4d1fff5f2d..9cfd1091bd6 100644 --- a/src/emu/cpu/drcfe.c +++ b/src/emu/cpu/drcfe.c @@ -217,6 +217,10 @@ const opcode_desc *drcfe_describe_code(drcfe_state *drcfe, offs_t startpc) /* allocate a new description and describe this instruction */ drcfe->desc_array[curpc - minpc] = curdesc = describe_one(drcfe, curpc); + /* first instruction in a sequence is always a branch target */ + if (curpc == curstack->targetpc) + curdesc->flags |= OPFLAG_IS_BRANCH_TARGET; + /* stop if we hit a page fault */ if (curdesc->flags & OPFLAG_COMPILER_PAGE_FAULT) break; @@ -225,10 +229,6 @@ const opcode_desc *drcfe_describe_code(drcfe_state *drcfe, offs_t startpc) if (curpc == startpc && drcfe->pageshift != 0) curdesc->flags |= OPFLAG_VALIDATE_TLB | OPFLAG_CAN_CAUSE_EXCEPTION; - /* first instruction in a sequence is always a branch target */ - if (curpc == curstack->targetpc) - curdesc->flags |= OPFLAG_IS_BRANCH_TARGET; - /* if we are a branch within the block range, add the branch target to our stack */ if ((curdesc->flags & OPFLAG_IS_BRANCH) && curdesc->targetpc >= minpc && curdesc->targetpc < maxpc && pcstackptr < &pcstack[MAX_STACK_DEPTH]) { @@ -373,8 +373,12 @@ static opcode_desc **build_sequence(drcfe_state *drcfe, opcode_desc **tailptr, i } /* start a new sequence if we aren't already in the middle of one */ - if (seqstart == -1) + if (seqstart == -1 && skipsleft == 0) + { + /* tag all start-of-sequence instructions as needing TLB verification */ + curdesc->flags |= OPFLAG_VALIDATE_TLB | OPFLAG_CAN_CAUSE_EXCEPTION; seqstart = descnum; + } /* if we are the last instruction, indicate end-of-sequence and redispatch */ if (nextdesc == NULL) diff --git a/src/emu/cpu/mips/mips3com.c b/src/emu/cpu/mips/mips3com.c index dfbc777d3a2..82e9b383018 100644 --- a/src/emu/cpu/mips/mips3com.c +++ b/src/emu/cpu/mips/mips3com.c @@ -82,14 +82,14 @@ static const memory_accessors le_memory = size_t mips3com_init(mips3_state *mips, mips3_flavor flavor, int bigendian, int index, int clock, const struct mips3_config *config, int (*irqcallback)(int), void *memory) { + int tlbindex; + /* if no memory, return the amount needed */ if (memory == NULL) return config->icache + config->dcache + (sizeof(mips->tlb_table[0]) * (1 << (MIPS3_MAX_PADDR_SHIFT - MIPS3_MIN_PAGE_SHIFT))); - /* initialize the state */ - memset(mips, 0, sizeof(*mips)); - /* initialize based on the config */ + memset(mips, 0, sizeof(*mips)); mips->flavor = flavor; mips->bigendian = bigendian; mips->cpu_clock = clock; @@ -109,6 +109,16 @@ size_t mips3com_init(mips3_state *mips, mips3_flavor flavor, int bigendian, int mips->dcache = (void *)((UINT8 *)memory + config->icache); mips->tlb_table = (void *)((UINT8 *)memory + config->dcache); + /* initialize the TLB state */ + for (tlbindex = 0; tlbindex < ARRAY_LENGTH(mips->tlb); tlbindex++) + { + mips3_tlb_entry *tlbent = &mips->tlb[tlbindex]; + tlbent->page_mask = 0; + tlbent->entry_hi = 0xffffffff; + tlbent->entry_lo[0] = 0xfffffff8; + tlbent->entry_lo[1] = 0xfffffff8; + } + /* allocate a timer for the compare interrupt */ mips->compare_int_timer = timer_alloc(compare_int_callback, NULL); @@ -128,6 +138,7 @@ void mips3com_reset(mips3_state *mips) /* initialize the state */ mips->pc = 0xbfc00000; mips->cpr[0][COP0_Status] = SR_BEV | SR_ERL; + mips->cpr[0][COP0_Wired] = 0; mips->cpr[0][COP0_Compare] = 0xffffffff; mips->cpr[0][COP0_Count] = 0; mips->cpr[0][COP0_Config] = compute_config_register(mips); @@ -202,8 +213,8 @@ void mips3com_map_tlb_entries(mips3_state *mips) { mips3_tlb_entry *tlbent = &mips->tlb[index]; - /* only process if global or if the ASID matches */ - if ((tlbent->entry_hi & 0x1000) || valid_asid == (tlbent->entry_hi & 0xff)) + /* only process if the ASID matches or if global */ + if (valid_asid == (tlbent->entry_hi & 0xff) || ((tlbent->entry_lo[0] & tlbent->entry_lo[1]) & TLB_GLOBAL)) { UINT32 count = (tlbent->page_mask >> 13) & 0x00fff; UINT32 vpn = ((tlbent->entry_hi >> 13) & 0x07ffffff) << 1; @@ -216,21 +227,17 @@ void mips3com_map_tlb_entries(mips3_state *mips) for (which = 0; which < 2; which++) { UINT64 lo = tlbent->entry_lo[which]; + UINT32 pfn = (lo >> 6) & 0x00ffffff; + UINT32 wp = (lo & 7) | TLB_PRESENT; + + /* ensure that if the valid bit is clear, the dirty bit is as well */ + /* this way we can always test dirty for writes, and valid for reads */ + if (!(wp & TLB_VALID)) + wp &= ~TLB_DIRTY; - /* only map if the TLB entry is valid */ - if (lo & 2) - { - UINT32 pfn = (lo >> 6) & 0x00ffffff; - UINT32 wp = (~lo >> 2) & 1; - - for (i = 0; i <= count; i++, vpn++, pfn++) - if (vpn < 0x80000 || vpn >= 0xc0000) - mips->tlb_table[vpn] = (pfn << MIPS3_MIN_PAGE_SHIFT) | wp; - } - - /* otherwise, advance by the number of pages we would have mapped */ - else - vpn += count + 1; + for (i = 0; i <= count; i++, vpn++, pfn++) + if (vpn < 0x80000 || vpn >= 0xc0000) + mips->tlb_table[vpn] = (pfn << MIPS3_MIN_PAGE_SHIFT) | wp; } } } @@ -261,7 +268,7 @@ void mips3com_unmap_tlb_entries(mips3_state *mips) for (which = 0; which < 2; which++) for (i = 0; i <= count; i++, vpn++) if (vpn < 0x80000 || vpn >= 0xc0000) - mips->tlb_table[vpn] = 0xffffffff; + mips->tlb_table[vpn] = 0; } } @@ -277,11 +284,11 @@ void mips3com_recompute_tlb_table(mips3_state *mips) /* map in the hard-coded spaces */ for (addr = 0x80000000; addr < 0xc0000000; addr += MIPS3_MIN_PAGE_SIZE) - mips->tlb_table[addr >> MIPS3_MIN_PAGE_SHIFT] = addr & 0x1ffff000; + mips->tlb_table[addr >> MIPS3_MIN_PAGE_SHIFT] = (addr & 0x1ffff000) | TLB_PRESENT | TLB_DIRTY | TLB_VALID | TLB_GLOBAL; /* reset everything else to unmapped */ - memset(&mips->tlb_table[0x00000000 >> MIPS3_MIN_PAGE_SHIFT], 0xff, sizeof(mips->tlb_table[0]) * (0x80000000 >> MIPS3_MIN_PAGE_SHIFT)); - memset(&mips->tlb_table[0xc0000000 >> MIPS3_MIN_PAGE_SHIFT], 0xff, sizeof(mips->tlb_table[0]) * (0x40000000 >> MIPS3_MIN_PAGE_SHIFT)); + memset(&mips->tlb_table[0x00000000 >> MIPS3_MIN_PAGE_SHIFT], 0, sizeof(mips->tlb_table[0]) * (0x80000000 >> MIPS3_MIN_PAGE_SHIFT)); + memset(&mips->tlb_table[0xc0000000 >> MIPS3_MIN_PAGE_SHIFT], 0, sizeof(mips->tlb_table[0]) * (0x40000000 >> MIPS3_MIN_PAGE_SHIFT)); /* remap all the entries in the TLB */ mips3com_map_tlb_entries(mips); @@ -299,7 +306,7 @@ int mips3com_translate_address(mips3_state *mips, int space, offs_t *address) if (space == ADDRESS_SPACE_PROGRAM) { UINT32 result = mips->tlb_table[*address >> MIPS3_MIN_PAGE_SHIFT]; - if (result == 0xffffffff) + if (!(result & TLB_PRESENT) || !(result & TLB_VALID)) return FALSE; *address = (result & ~MIPS3_MIN_PAGE_MASK) | (*address & MIPS3_MIN_PAGE_MASK); } @@ -378,7 +385,7 @@ void mips3com_tlbp(mips3_state *mips) if ((tlbent->entry_hi & mask) == (mips->cpr[0][COP0_EntryHi] & mask)) /* and if we are either global or matching the current ASID, then stop */ - if ((tlbent->entry_hi & 0x1000) || (tlbent->entry_hi & 0xff) == (mips->cpr[0][COP0_EntryHi] & 0xff)) + if ((tlbent->entry_hi & 0xff) == (mips->cpr[0][COP0_EntryHi] & 0xff) || ((tlbent->entry_lo[0] & tlbent->entry_lo[1]) & TLB_GLOBAL)) break; } @@ -386,13 +393,12 @@ void mips3com_tlbp(mips3_state *mips) vpn = ((mips->cpr[0][COP0_EntryHi] >> 13) & 0x07ffffff) << 1; if (index != ARRAY_LENGTH(mips->tlb)) { - /* we can't assert this because the TLB entry may not be valid */ - /* assert(mips->tlb_table[vpn & 0xfffff] != 0xffffffff); */ + assert(mips->tlb_table[vpn & 0xfffff] & TLB_PRESENT); mips->cpr[0][COP0_Index] = index; } else { - assert(mips->tlb_table[vpn & 0xfffff] == 0xffffffff); + assert(!(mips->tlb_table[vpn & 0xfffff] & TLB_PRESENT)); mips->cpr[0][COP0_Index] = 0x80000000; } } @@ -920,6 +926,6 @@ static void tlb_entry_log_half(mips3_tlb_entry *tlbent, int index, int which) mame_printf_debug("index=%08X pagesize=%08X vaddr=%08X%08X paddr=%08X%08X asid=%02X r=%X c=%X dvg=%c%c%c\n", index, pagesize, (UINT32)(vaddr >> 32), (UINT32)vaddr, (UINT32)(paddr >> 32), (UINT32)paddr, - asid, r, c, (lo & 4) ? 'd' : '.', (lo & 2) ? 'v' : '.', (hi & 0x1000) ? 'g' : '.'); + asid, r, c, (lo & 4) ? 'd' : '.', (lo & 2) ? 'v' : '.', (lo & 1) ? 'g' : '.'); #endif } diff --git a/src/emu/cpu/mips/mips3com.h b/src/emu/cpu/mips/mips3com.h index af11bd7d874..335f87efbd3 100644 --- a/src/emu/cpu/mips/mips3com.h +++ b/src/emu/cpu/mips/mips3com.h @@ -44,72 +44,86 @@ enum _mips3_flavor }; typedef enum _mips3_flavor mips3_flavor; +/* TLB bits */ +#define TLB_GLOBAL 0x01 +#define TLB_VALID 0x02 +#define TLB_DIRTY 0x04 +#define TLB_PRESENT 0x08 + /* COP0 registers */ -#define COP0_Index 0 -#define COP0_Random 1 -#define COP0_EntryLo 2 -#define COP0_EntryLo0 2 -#define COP0_EntryLo1 3 -#define COP0_Context 4 -#define COP0_PageMask 5 -#define COP0_Wired 6 -#define COP0_BadVAddr 8 -#define COP0_Count 9 -#define COP0_EntryHi 10 -#define COP0_Compare 11 -#define COP0_Status 12 -#define COP0_Cause 13 -#define COP0_EPC 14 -#define COP0_PRId 15 -#define COP0_Config 16 -#define COP0_XContext 20 +#define COP0_Index 0 +#define COP0_Random 1 +#define COP0_EntryLo 2 +#define COP0_EntryLo0 2 +#define COP0_EntryLo1 3 +#define COP0_Context 4 +#define COP0_PageMask 5 +#define COP0_Wired 6 +#define COP0_BadVAddr 8 +#define COP0_Count 9 +#define COP0_EntryHi 10 +#define COP0_Compare 11 +#define COP0_Status 12 +#define COP0_Cause 13 +#define COP0_EPC 14 +#define COP0_PRId 15 +#define COP0_Config 16 +#define COP0_LLAddr 17 +#define COP0_XContext 20 +#define COP0_ECC 26 +#define COP0_CacheErr 27 +#define COP0_TagLo 28 +#define COP0_TagHi 29 +#define COP0_ErrorPC 30 /* Status register bits */ -#define SR_IE 0x00000001 -#define SR_EXL 0x00000002 -#define SR_ERL 0x00000004 -#define SR_KSU_MASK 0x00000018 -#define SR_KSU_KERNEL 0x00000000 -#define SR_KSU_SUPERVISOR 0x00000008 -#define SR_KSU_USER 0x00000010 -#define SR_IMSW0 0x00000100 -#define SR_IMSW1 0x00000200 -#define SR_IMEX0 0x00000400 -#define SR_IMEX1 0x00000800 -#define SR_IMEX2 0x00001000 -#define SR_IMEX3 0x00002000 -#define SR_IMEX4 0x00004000 -#define SR_IMEX5 0x00008000 -#define SR_DE 0x00010000 -#define SR_CE 0x00020000 -#define SR_CH 0x00040000 -#define SR_SR 0x00100000 -#define SR_TS 0x00200000 -#define SR_BEV 0x00400000 -#define SR_RE 0x02000000 -#define SR_FR 0x04000000 -#define SR_RP 0x08000000 -#define SR_COP0 0x10000000 -#define SR_COP1 0x20000000 -#define SR_COP2 0x40000000 -#define SR_COP3 0x80000000 +#define SR_IE 0x00000001 +#define SR_EXL 0x00000002 +#define SR_ERL 0x00000004 +#define SR_KSU_MASK 0x00000018 +#define SR_KSU_KERNEL 0x00000000 +#define SR_KSU_SUPERVISOR 0x00000008 +#define SR_KSU_USER 0x00000010 +#define SR_IMSW0 0x00000100 +#define SR_IMSW1 0x00000200 +#define SR_IMEX0 0x00000400 +#define SR_IMEX1 0x00000800 +#define SR_IMEX2 0x00001000 +#define SR_IMEX3 0x00002000 +#define SR_IMEX4 0x00004000 +#define SR_IMEX5 0x00008000 +#define SR_DE 0x00010000 +#define SR_CE 0x00020000 +#define SR_CH 0x00040000 +#define SR_SR 0x00100000 +#define SR_TS 0x00200000 +#define SR_BEV 0x00400000 +#define SR_RE 0x02000000 +#define SR_FR 0x04000000 +#define SR_RP 0x08000000 +#define SR_COP0 0x10000000 +#define SR_COP1 0x20000000 +#define SR_COP2 0x40000000 +#define SR_COP3 0x80000000 /* exception types */ -#define EXCEPTION_INTERRUPT 0 -#define EXCEPTION_TLBMOD 1 -#define EXCEPTION_TLBLOAD 2 -#define EXCEPTION_TLBSTORE 3 -#define EXCEPTION_ADDRLOAD 4 -#define EXCEPTION_ADDRSTORE 5 -#define EXCEPTION_BUSINST 6 -#define EXCEPTION_BUSDATA 7 -#define EXCEPTION_SYSCALL 8 -#define EXCEPTION_BREAK 9 -#define EXCEPTION_INVALIDOP 10 -#define EXCEPTION_BADCOP 11 -#define EXCEPTION_OVERFLOW 12 -#define EXCEPTION_TRAP 13 -#define EXCEPTION_COUNT 16 +#define EXCEPTION_INTERRUPT 0 +#define EXCEPTION_TLBMOD 1 +#define EXCEPTION_TLBLOAD 2 +#define EXCEPTION_TLBSTORE 3 +#define EXCEPTION_ADDRLOAD 4 +#define EXCEPTION_ADDRSTORE 5 +#define EXCEPTION_BUSINST 6 +#define EXCEPTION_BUSDATA 7 +#define EXCEPTION_SYSCALL 8 +#define EXCEPTION_BREAK 9 +#define EXCEPTION_INVALIDOP 10 +#define EXCEPTION_BADCOP 11 +#define EXCEPTION_OVERFLOW 12 +#define EXCEPTION_TRAP 13 +#define EXCEPTION_TLBLOAD_FILL 16 +#define EXCEPTION_TLBSTORE_FILL 17 +#define EXCEPTION_COUNT 18 diff --git a/src/emu/cpu/mips/mips3drc.c b/src/emu/cpu/mips/mips3drc.c index ade1da48810..3f335b008a4 100644 --- a/src/emu/cpu/mips/mips3drc.c +++ b/src/emu/cpu/mips/mips3drc.c @@ -55,7 +55,7 @@ extern unsigned dasmmips3(char *buffer, unsigned pc, UINT32 op); #define SINGLE_INSTRUCTION_MODE (0) #define PRINTF_EXCEPTIONS (0) -#define PRINTF_MMU (1) +#define PRINTF_MMU (0) #define PROBE_ADDRESS ~0 @@ -69,6 +69,11 @@ extern unsigned dasmmips3(char *buffer, unsigned pc, UINT32 op); #define MAPVAR_PC MVAR(0) #define MAPVAR_CYCLES MVAR(1) +/* modes */ +#define MODE_KERNEL 0 +#define MODE_SUPER 1 +#define MODE_USER 2 + /* size of the execution code cache */ #define CACHE_SIZE (32 * 1024 * 1024) @@ -199,18 +204,18 @@ struct _mips3_regs drcuml_codehandle * nocode; /* nocode exception handler */ drcuml_codehandle * out_of_cycles; /* out of cycles exception handler */ drcuml_codehandle * tlb_mismatch; /* tlb mismatch handler */ - drcuml_codehandle * read8; /* read byte */ - drcuml_codehandle * write8; /* write byte */ - drcuml_codehandle * read16; /* read half */ - drcuml_codehandle * write16; /* write half */ - drcuml_codehandle * read32; /* read word */ - drcuml_codehandle * read32mask; /* read word masked */ - drcuml_codehandle * write32; /* write word */ - drcuml_codehandle * write32mask; /* write word masked */ - drcuml_codehandle * read64; /* read double */ - drcuml_codehandle * read64mask; /* read double masked */ - drcuml_codehandle * write64; /* write double */ - drcuml_codehandle * write64mask; /* write double masked */ + drcuml_codehandle * read8[3]; /* read byte */ + drcuml_codehandle * write8[3]; /* write byte */ + drcuml_codehandle * read16[3]; /* read half */ + drcuml_codehandle * write16[3]; /* write half */ + drcuml_codehandle * read32[3]; /* read word */ + drcuml_codehandle * read32mask[3]; /* read word masked */ + drcuml_codehandle * write32[3]; /* write word */ + drcuml_codehandle * write32mask[3]; /* write word masked */ + drcuml_codehandle * read64[3]; /* read double */ + drcuml_codehandle * read64mask[3]; /* read double masked */ + drcuml_codehandle * write64[3]; /* write double */ + drcuml_codehandle * write64mask[3]; /* write double masked */ drcuml_codehandle * exception[EXCEPTION_COUNT]; /* array of exception handlers */ drcuml_codehandle * exception_norecover[EXCEPTION_COUNT]; /* array of no-recover exception handlers */ @@ -241,8 +246,9 @@ static void static_generate_nocode_handler(drcuml_state *drcuml); static void static_generate_out_of_cycles(drcuml_state *drcuml); static void static_generate_tlb_mismatch(drcuml_state *drcuml); static void static_generate_exception(drcuml_state *drcuml, UINT8 exception, int recover, const char *name); -static void static_generate_memory_accessor(drcuml_state *drcuml, int size, int iswrite, int ismasked, const char *name, drcuml_codehandle **handleptr); +static void static_generate_memory_accessor(drcuml_state *drcuml, int mode, int size, int iswrite, int ismasked, const char *name, drcuml_codehandle **handleptr); +static void generate_update_mode(drcuml_block *block); static void generate_update_cycles(drcuml_block *block, compiler_state *compiler, UINT32 nextpc, UINT32 *mempc, int allow_exception); static void generate_checksum_block(drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast); static void generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); @@ -703,7 +709,7 @@ static void mips3_init(mips3_flavor flavor, int bigendian, int index, int clock, flags |= DRCUML_OPTION_LOG_UML; if (LOG_NATIVE) flags |= DRCUML_OPTION_LOG_NATIVE; - mips3.drcuml = drcuml_alloc(mips3.cache, flags, 2, 32, 2); + mips3.drcuml = drcuml_alloc(mips3.cache, flags, 8, 32, 2); if (mips3.drcuml == NULL) fatalerror("Error initializing the UML"); @@ -725,6 +731,7 @@ static void mips3_reset(void) { /* reset the common code and mark the cache dirty */ mips3com_reset(mips3.core); + mips3.cstate->mode = (MODE_KERNEL << 1) | 0; mips3.cache_dirty = TRUE; } @@ -837,6 +844,8 @@ static offs_t mips3_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT static void code_flush_cache(drcuml_state *drcuml) { + int mode; + /* empty the transient cache contents */ drcuml_reset(drcuml); @@ -847,31 +856,38 @@ static void code_flush_cache(drcuml_state *drcuml) static_generate_tlb_mismatch(drcuml); /* append exception handlers for various types */ - static_generate_exception(drcuml, EXCEPTION_INTERRUPT, TRUE, "exception_interrupt"); - static_generate_exception(drcuml, EXCEPTION_INTERRUPT, FALSE, "exception_interrupt_norecover"); - static_generate_exception(drcuml, EXCEPTION_TLBMOD, TRUE, "exception_tlbmod"); - static_generate_exception(drcuml, EXCEPTION_TLBLOAD, TRUE, "exception_tlbload"); - static_generate_exception(drcuml, EXCEPTION_TLBSTORE, TRUE, "exception_tlbstore"); - static_generate_exception(drcuml, EXCEPTION_SYSCALL, TRUE, "exception_syscall"); - static_generate_exception(drcuml, EXCEPTION_BREAK, TRUE, "exception_break"); - static_generate_exception(drcuml, EXCEPTION_INVALIDOP, TRUE, "exception_invalidop"); - static_generate_exception(drcuml, EXCEPTION_BADCOP, TRUE, "exception_badcop"); - static_generate_exception(drcuml, EXCEPTION_OVERFLOW, TRUE, "exception_overflow"); - static_generate_exception(drcuml, EXCEPTION_TRAP, TRUE, "exception_trap"); + static_generate_exception(drcuml, EXCEPTION_INTERRUPT, TRUE, "exception_interrupt"); + static_generate_exception(drcuml, EXCEPTION_INTERRUPT, FALSE, "exception_interrupt_norecover"); + static_generate_exception(drcuml, EXCEPTION_TLBMOD, TRUE, "exception_tlbmod"); + static_generate_exception(drcuml, EXCEPTION_TLBLOAD, TRUE, "exception_tlbload"); + static_generate_exception(drcuml, EXCEPTION_TLBSTORE, TRUE, "exception_tlbstore"); + static_generate_exception(drcuml, EXCEPTION_TLBLOAD_FILL, TRUE, "exception_tlbload_fill"); + static_generate_exception(drcuml, EXCEPTION_TLBSTORE_FILL, TRUE, "exception_tlbstore_fill"); + static_generate_exception(drcuml, EXCEPTION_ADDRLOAD, TRUE, "exception_addrload"); + static_generate_exception(drcuml, EXCEPTION_ADDRSTORE, TRUE, "exception_addrstore"); + static_generate_exception(drcuml, EXCEPTION_SYSCALL, TRUE, "exception_syscall"); + static_generate_exception(drcuml, EXCEPTION_BREAK, TRUE, "exception_break"); + static_generate_exception(drcuml, EXCEPTION_INVALIDOP, TRUE, "exception_invalidop"); + static_generate_exception(drcuml, EXCEPTION_BADCOP, TRUE, "exception_badcop"); + static_generate_exception(drcuml, EXCEPTION_OVERFLOW, TRUE, "exception_overflow"); + static_generate_exception(drcuml, EXCEPTION_TRAP, TRUE, "exception_trap"); /* add subroutines for memory accesses */ - static_generate_memory_accessor(drcuml, 1, FALSE, FALSE, "read8", &mips3.read8); - static_generate_memory_accessor(drcuml, 1, TRUE, FALSE, "write8", &mips3.write8); - static_generate_memory_accessor(drcuml, 2, FALSE, FALSE, "read16", &mips3.read16); - static_generate_memory_accessor(drcuml, 2, TRUE, FALSE, "write16", &mips3.write16); - static_generate_memory_accessor(drcuml, 4, FALSE, FALSE, "read32", &mips3.read32); - static_generate_memory_accessor(drcuml, 4, FALSE, TRUE, "read32mask", &mips3.read32mask); - static_generate_memory_accessor(drcuml, 4, TRUE, FALSE, "write32", &mips3.write32); - static_generate_memory_accessor(drcuml, 4, TRUE, TRUE, "write32mask", &mips3.write32mask); - static_generate_memory_accessor(drcuml, 8, FALSE, FALSE, "read64", &mips3.read64); - static_generate_memory_accessor(drcuml, 8, FALSE, TRUE, "read64mask", &mips3.read64mask); - static_generate_memory_accessor(drcuml, 8, TRUE, FALSE, "write64", &mips3.write64); - static_generate_memory_accessor(drcuml, 8, TRUE, TRUE, "write64mask", &mips3.write64mask); + for (mode = 0; mode < 3; mode++) + { + static_generate_memory_accessor(drcuml, mode, 1, FALSE, FALSE, "read8", &mips3.read8[mode]); + static_generate_memory_accessor(drcuml, mode, 1, TRUE, FALSE, "write8", &mips3.write8[mode]); + static_generate_memory_accessor(drcuml, mode, 2, FALSE, FALSE, "read16", &mips3.read16[mode]); + static_generate_memory_accessor(drcuml, mode, 2, TRUE, FALSE, "write16", &mips3.write16[mode]); + static_generate_memory_accessor(drcuml, mode, 4, FALSE, FALSE, "read32", &mips3.read32[mode]); + static_generate_memory_accessor(drcuml, mode, 4, FALSE, TRUE, "read32mask", &mips3.read32mask[mode]); + static_generate_memory_accessor(drcuml, mode, 4, TRUE, FALSE, "write32", &mips3.write32[mode]); + static_generate_memory_accessor(drcuml, mode, 4, TRUE, TRUE, "write32mask", &mips3.write32mask[mode]); + static_generate_memory_accessor(drcuml, mode, 8, FALSE, FALSE, "read64", &mips3.read64[mode]); + static_generate_memory_accessor(drcuml, mode, 8, FALSE, TRUE, "read64mask", &mips3.read64mask[mode]); + static_generate_memory_accessor(drcuml, mode, 8, TRUE, FALSE, "write64", &mips3.write64[mode]); + static_generate_memory_accessor(drcuml, mode, 8, TRUE, TRUE, "write64mask", &mips3.write64mask[mode]); + } } @@ -1069,6 +1085,18 @@ static void cfunc_printf_probe(void *param) } +/*------------------------------------------------- + cfunc_unimplemented - handler for + unimplemented opcdes +-------------------------------------------------*/ + +static void cfunc_unimplemented(void *param) +{ + UINT32 opcode = (FPTR)param; + fatalerror("PC=%08X: Unimplemented op %08X (%02X,%02X)", mips3.core->pc, opcode, opcode >> 26, opcode & 0x3f); +} + + /*************************************************************************** STATIC CODEGEN @@ -1196,6 +1224,7 @@ static void static_generate_tlb_mismatch(drcuml_state *drcuml) /* forward references */ alloc_handle(drcuml, &mips3.exception[EXCEPTION_TLBLOAD], "exception_tlbload"); + alloc_handle(drcuml, &mips3.exception[EXCEPTION_TLBLOAD_FILL], "exception_tlbload_fill"); /* begin generating */ block = drcuml_block_begin(drcuml, 20, &errorbuf); @@ -1205,16 +1234,19 @@ static void static_generate_tlb_mismatch(drcuml_state *drcuml) UML_HANDLE(block, mips3.tlb_mismatch); // handle tlb_mismatch UML_RECOVER(block, IREG(0), MAPVAR_PC); // recover i0,PC UML_MOV(block, MEM(&mips3.core->pc), IREG(0)); // mov ,i0 + UML_SHR(block, IREG(1), IREG(0), IMM(12)); // shr i1,i0,12 + UML_LOAD4(block, IREG(1), mips3.core->tlb_table, IREG(1)); // load4 i1,[tlb_table],i1 if (PRINTF_MMU) { UML_MOV(block, MEM(&mips3.cstate->arg0), IREG(0)); // mov [arg0],i0 - UML_CALLC(block, cfunc_printf_debug, "TLB mismatch @ %08X\n"); // callc printf_debug + UML_MOV(block, MEM(&mips3.cstate->arg1), IREG(1)); // mov [arg1],i1 + UML_CALLC(block, cfunc_printf_debug, "TLB mismatch @ %08X (ent=%08X)\n"); // callc printf_debug } - UML_SHR(block, IREG(1), IREG(0), IMM(12)); // shr i1,i0,12 - UML_LOAD4(block, IREG(1), mips3.core->tlb_table, IREG(1)); // load4 i1,[tlb_table],i1 - UML_TEST(block, IREG(1), IMM(2)); // test i1,2 - UML_EXHc(block, IF_NZ, mips3.exception[EXCEPTION_TLBLOAD], IREG(0)); // exh exception[TLBLOAD],i0 - UML_EXIT(block, IMM(EXECUTE_MISSING_CODE)); // exit EXECUTE_MISSING_CODE + UML_TEST(block, IREG(1), IMM(TLB_VALID)); // test i1,TLB_VALID + UML_EXITc(block, IF_NZ, IMM(EXECUTE_MISSING_CODE)); // exit EXECUTE_MISSING_CODE,nz + UML_TEST(block, IREG(1), IMM(TLB_PRESENT)); // test i1,TLB_PRESENT + UML_EXHc(block, IF_NZ, mips3.exception[EXCEPTION_TLBLOAD], IREG(0)); // exh exception[TLBLOAD],i0,nz + UML_EXH(block, mips3.exception[EXCEPTION_TLBLOAD_FILL], IREG(0)); // exh exception[TLBLOAD_FILL],i0 drcuml_block_end(block); } @@ -1227,7 +1259,8 @@ static void static_generate_tlb_mismatch(drcuml_state *drcuml) static void static_generate_exception(drcuml_state *drcuml, UINT8 exception, int recover, const char *name) { - UINT32 offset = (exception >= EXCEPTION_TLBMOD && exception <= EXCEPTION_TLBSTORE) ? 0x00 : 0x180; + drcuml_codehandle **exception_handle = recover ? &mips3.exception[exception] : &mips3.exception_norecover[exception]; + UINT32 offset = 0x180; drcuml_codelabel next = 1; drcuml_block *block; jmp_buf errorbuf; @@ -1236,27 +1269,39 @@ static void static_generate_exception(drcuml_state *drcuml, UINT8 exception, int if (setjmp(errorbuf) != 0) fatalerror("Unrecoverable error in static_generate_exception"); + /* translate our fake fill exceptions into real exceptions */ + if (exception == EXCEPTION_TLBLOAD_FILL || exception == EXCEPTION_TLBSTORE_FILL) + { + offset = 0x000; + exception = (exception - EXCEPTION_TLBLOAD_FILL) + EXCEPTION_TLBLOAD; + } + /* begin generating */ block = drcuml_block_begin(drcuml, 1024, &errorbuf); /* add a global entry for this */ if (recover) { - alloc_handle(drcuml, &mips3.exception[exception], name); - UML_HANDLE(block, mips3.exception[exception]); // handle name + alloc_handle(drcuml, exception_handle, name); + UML_HANDLE(block, *exception_handle); // handle name } else { - alloc_handle(drcuml, &mips3.exception_norecover[exception], name); - UML_HANDLE(block, mips3.exception_norecover[exception]); // handle name + alloc_handle(drcuml, exception_handle, name); + UML_HANDLE(block, *exception_handle); // handle name } /* exception parameter is expected to be the fault address in this case */ - if (exception == EXCEPTION_TLBLOAD || exception == EXCEPTION_TLBSTORE) + if (exception == EXCEPTION_TLBLOAD || exception == EXCEPTION_TLBSTORE || exception == EXCEPTION_ADDRLOAD || exception == EXCEPTION_ADDRSTORE) { /* set BadVAddr to the fault address */ - UML_GETEXP(block, CPR032(COP0_BadVAddr)); // mov [BadVAddr],exp + UML_GETEXP(block, IREG(0)); // getexp i0 + UML_TEST(block, CPR032(COP0_Status), IMM(SR_EXL)); // test [Status],SR_EXL + UML_MOVc(block, IF_Z, CPR032(COP0_BadVAddr), IREG(0)); // mov [BadVAddr],i0,Z + } + if (exception == EXCEPTION_TLBLOAD || exception == EXCEPTION_TLBSTORE) + { /* set the upper bits of EntryHi to the fault page */ UML_AND(block, IREG(0), IREG(0), IMM(0xffffe000)); // and i0,i0,0xffffe000 UML_AND(block, IREG(1), CPR032(COP0_EntryHi), IMM(0x000000ff)); // and i1,[EntryHi],0x000000ff @@ -1281,11 +1326,14 @@ static void static_generate_exception(drcuml_state *drcuml, UINT8 exception, int UML_OR(block, IREG(2), IREG(2), IMM(0x80000000)); // or i2,i2,0x80000000 UML_SUB(block, IREG(0), IREG(0), IMM(1)); // sub i0,i0,1 UML_LABEL(block, next); // : - UML_MOV(block, CPR032(COP0_EPC), IREG(0)); // mov [EPC],i0 + UML_TEST(block, CPR032(COP0_Status), IMM(SR_EXL)); // test [Status],SR_EXL + UML_MOVc(block, IF_Z, CPR032(COP0_EPC), IREG(0)); // mov [EPC],i0,Z UML_OR(block, CPR032(COP0_Cause), IREG(2), IMM(exception << 2)); // or [Cause],i2,exception << 2 /* set EXL in the SR */ - UML_OR(block, CPR032(COP0_Status), CPR032(COP0_Status), IMM(SR_EXL)); // or [Status],[Status],SR_EXL + UML_OR(block, IREG(0), CPR032(COP0_Status), IMM(SR_EXL)); // or i0,[Status],SR_EXL + UML_MOV(block, CPR032(COP0_Status), IREG(0)); // mov [Status],i0 + generate_update_mode(block); /* optionally print exceptions */ if ((PRINTF_EXCEPTIONS && exception != EXCEPTION_INTERRUPT && exception != EXCEPTION_SYSCALL) || @@ -1294,7 +1342,7 @@ static void static_generate_exception(drcuml_state *drcuml, UINT8 exception, int /* choose our target PC */ UML_MOV(block, IREG(0), IMM(0xbfc00200 + offset)); // mov i0,0xbfc00200 + offset - UML_TEST(block, CPR032(COP0_Status), IMM(SR_BEV)); // test [Status],SR_BEV + UML_TEST(block, IREG(1), IMM(SR_BEV)); // test i1,SR_BEV UML_MOVc(block, IF_Z, IREG(0), IMM(0x80000000 + offset)); // mov i0,0x80000000 + offset,z /* adjust cycles */ @@ -1311,15 +1359,18 @@ static void static_generate_exception(drcuml_state *drcuml, UINT8 exception, int static_generate_memory_accessor ------------------------------------------------------------------*/ -static void static_generate_memory_accessor(drcuml_state *drcuml, int size, int iswrite, int ismasked, const char *name, drcuml_codehandle **handleptr) +static void static_generate_memory_accessor(drcuml_state *drcuml, int mode, int size, int iswrite, int ismasked, const char *name, drcuml_codehandle **handleptr) { /* on entry, address is in I0; data for writes is in I1; mask for accesses is in I2 */ /* on exit, read result is in I0 */ /* routine trashes I0-I3 */ - drcuml_codehandle *exception_target = mips3.exception[iswrite ? EXCEPTION_TLBSTORE : EXCEPTION_TLBLOAD]; + drcuml_codehandle *exception_tlb = mips3.exception[iswrite ? EXCEPTION_TLBSTORE : EXCEPTION_TLBLOAD]; + drcuml_codehandle *exception_tlbfill = mips3.exception[iswrite ? EXCEPTION_TLBSTORE_FILL : EXCEPTION_TLBLOAD_FILL]; + drcuml_codehandle *exception_addrerr = mips3.exception[iswrite ? EXCEPTION_ADDRSTORE : EXCEPTION_ADDRLOAD]; drcuml_block *block; jmp_buf errorbuf; - int label = 0; + int tlbmiss = 0; + int label = 1; int ramnum; /* if we get an error back, we're screwed */ @@ -1332,12 +1383,31 @@ static void static_generate_memory_accessor(drcuml_state *drcuml, int size, int /* add a global entry for this */ alloc_handle(drcuml, handleptr, name); UML_HANDLE(block, *handleptr); // handle *handleptr + + /* user mode? generate address exception if top bit is set */ + if (mode == MODE_USER) + { + UML_TEST(block, IREG(0), IMM(0x80000000)); // test i0,0x80000000 + UML_EXHc(block, IF_NZ, exception_addrerr, IREG(0)); // exh addrerr,i0,nz + } + + /* supervisor mode? generate address exception if not in user space or in $C0000000-DFFFFFFF */ + if (mode == MODE_SUPER) + { + int addrok; + UML_TEST(block, IREG(0), IMM(0x80000000)); // test i0,0x80000000 + UML_JMPc(block, IF_Z, addrok = label++); // jz addrok + UML_SHR(block, IREG(3), IREG(0), IMM(29)); // shr i3,i0,29 + UML_CMP(block, IREG(3), IMM(6)); // cmp i3,6 + UML_EXHc(block, IF_NE, exception_addrerr, IREG(0)); // exh addrerr,i0,ne + UML_LABEL(block, addrok); // addrok: + } /* general case: assume paging and perform a translation */ UML_SHR(block, IREG(3), IREG(0), IMM(12)); // shr i3,i0,12 UML_LOAD4(block, IREG(3), mips3.core->tlb_table, IREG(3)); // load4 i3,[tlb_table],i3 - UML_TEST(block, IREG(3), IMM(iswrite ? 1 : 2)); // test i3,iswrite ? 1 : 2 - UML_EXHc(block, IF_NZ, exception_target, IREG(0)); // exnz exception_target,i0 + UML_TEST(block, IREG(3), IMM(iswrite ? TLB_DIRTY : TLB_VALID)); // test i3,iswrite ? TLB_DIRTY : TLB_VALID + UML_JMPc(block, IF_Z, tlbmiss = label++); // jmp tlbmiss,z UML_AND(block, IREG(0), IREG(0), IMM(0xfff)); // and i0,i0,0xfff UML_AND(block, IREG(3), IREG(3), IMM(~0xfff)); // and i3,i3,~0xfff UML_OR(block, IREG(0), IREG(0), IREG(3)); // or i0,i0,i3 @@ -1491,6 +1561,19 @@ static void static_generate_memory_accessor(drcuml_state *drcuml, int size, int } UML_RET(block); // ret + if (tlbmiss != 0) + { + UML_LABEL(block, tlbmiss); // tlbmiss: + if (iswrite) + { + UML_TEST(block, IREG(3), IMM(TLB_VALID)); // test i3,TLB_VALID + UML_EXHc(block, IF_NZ, mips3.exception[EXCEPTION_TLBMOD], IREG(0)); // exh tlbmod,i0,nz + } + UML_TEST(block, IREG(3), IMM(TLB_PRESENT)); // test i3,TLB_PRESENT + UML_EXHc(block, IF_NZ, exception_tlb, IREG(0)); // exh tlb,i0,nz + UML_EXH(block, exception_tlbfill, IREG(0)); // exh tlbfill,i0 + } + drcuml_block_end(block); } @@ -1500,6 +1583,23 @@ static void static_generate_memory_accessor(drcuml_state *drcuml, int size, int CODE GENERATION ***************************************************************************/ +/*------------------------------------------------- + generate_update_mode - update the mode based + on a new SR (in i0); trashes i2 and i3 +-------------------------------------------------*/ + +static void generate_update_mode(drcuml_block *block) +{ + UML_AND(block, IREG(2), IREG(0), IMM(SR_KSU_MASK)); // and i2,i0,SR_KSU_MASK + UML_AND(block, IREG(3), IREG(0), IMM(SR_FR)); // and i3,i0,SR_FR + UML_SHR(block, IREG(2), IREG(2), IMM(2)); // shr i2,i2,2 + UML_SHR(block, IREG(3), IREG(3), IMM(26)); // shr i3,i3,26 + UML_TEST(block, IREG(0), IMM(SR_EXL | SR_ERL)); // test i0,SR_EXL | SR_ERL + UML_MOVc(block, IF_NZ, IREG(2), IMM(0)); // mov i2,0,nz + UML_OR(block, MEM(&mips3.cstate->mode), IREG(2), IREG(3)); // or [mode],i2,i3 +} + + /*------------------------------------------------- generate_update_cycles - generate code to subtract cycles from the icount and generate @@ -1580,25 +1680,39 @@ static void generate_checksum_block(drcuml_block *block, compiler_state *compile /* loose verify or single instruction: just compare and fail */ if (!(mips3.drcoptions & MIPS3DRC_STRICT_VERIFY) || seqhead->next == NULL) { - UML_LOAD4(block, IREG(0), seqhead->opptr.l, IMM(0)); // load4 i0,*opptr - UML_CMP(block, IREG(0), IMM(*seqhead->opptr.l)); // cmp i0,*opptr - UML_EXHc(block, IF_NE, mips3.nocode, IMM(epc(seqhead))); // exne nocode,seqhead->pc + if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP)) + { + UML_LOAD4(block, IREG(0), seqhead->opptr.l, IMM(0)); // load4 i0,*opptr + UML_CMP(block, IREG(0), IMM(*seqhead->opptr.l)); // cmp i0,*opptr + UML_EXHc(block, IF_NE, mips3.nocode, IMM(epc(seqhead))); // exne nocode,seqhead->pc + } } /* full verification; sum up everything */ else { +#if 0 + for (curdesc = seqhead->next; curdesc != seqlast->next; curdesc = curdesc->next) + if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) + { + UML_LOAD4(block, IREG(0), curdesc->opptr.l, IMM(0)); // load4 i0,*opptr + UML_CMP(block, IREG(0), IMM(*curdesc->opptr.l)); // cmp i0,*opptr + UML_EXHc(block, IF_NE, mips3.nocode, IMM(epc(seqhead))); // exne nocode,seqhead->pc + } +#else UINT32 sum = 0; UML_LOAD4(block, IREG(0), seqhead->opptr.l, IMM(0)); // load4 i0,*opptr sum += *seqhead->opptr.l; for (curdesc = seqhead->next; curdesc != seqlast->next; curdesc = curdesc->next) - { - UML_LOAD4(block, IREG(1), curdesc->opptr.l, IMM(0)); // load4 i1,*opptr - UML_ADD(block, IREG(0), IREG(0), IREG(1)); // add i0,i0,i1 - sum += *curdesc->opptr.l; - } + if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP)) + { + UML_LOAD4(block, IREG(1), curdesc->opptr.l, IMM(0)); // load4 i1,*opptr + UML_ADD(block, IREG(0), IREG(0), IREG(1)); // add i0,i0,i1 + sum += *curdesc->opptr.l; + } UML_CMP(block, IREG(0), IMM(sum)); // cmp i0,sum UML_EXHc(block, IF_NE, mips3.nocode, IMM(epc(seqhead))); // exne nocode,seqhead->pc +#endif } } @@ -1614,7 +1728,7 @@ static void generate_sequence_instruction(drcuml_block *block, compiler_state *c int hotnum; /* add an entry for the log */ - if (LOG_UML) + if (LOG_UML && !(desc->flags & OPFLAG_VIRTUAL_NOOP)) log_add_disasm_comment(block, desc->pc, *desc->opptr.l); /* set the PC map variable */ @@ -1626,7 +1740,7 @@ static void generate_sequence_instruction(drcuml_block *block, compiler_state *c /* is this a hotspot? */ for (hotnum = 0; hotnum < MIPS3_MAX_HOTSPOTS; hotnum++) - if (desc->pc == mips3.hotspot[hotnum].pc && *desc->opptr.l == mips3.hotspot[hotnum].opcode) + if (mips3.hotspot[hotnum].pc != 0 && desc->pc == mips3.hotspot[hotnum].pc && *desc->opptr.l == mips3.hotspot[hotnum].opcode) { compiler->cycles += mips3.hotspot[hotnum].cycles; break; @@ -1668,7 +1782,7 @@ static void generate_sequence_instruction(drcuml_block *block, compiler_state *c if ((desc->flags & OPFLAG_VALIDATE_TLB) && (desc->pc < 0x80000000 || desc->pc >= 0xc0000000)) { /* if we currently have a valid TLB read entry, we just verify */ - if (!(mips3.core->tlb_table[desc->pc >> 12] & 2)) + if (mips3.core->tlb_table[desc->pc >> 12] & TLB_VALID) { if (PRINTF_MMU) { @@ -1701,7 +1815,10 @@ static void generate_sequence_instruction(drcuml_block *block, compiler_state *c { /* compile the instruction */ if (!generate_opcode(block, compiler, desc)) - fatalerror("Unimplemented op %08X (%02X,%02X)", *desc->opptr.l, *desc->opptr.l >> 26, *desc->opptr.l & 0x3f); + { + UML_MOV(block, MEM(&mips3.core->pc), IMM(desc->pc)); // mov [pc],desc->pc + UML_CALLC(block, cfunc_unimplemented, (void *)*desc->opptr.l); // callc cfunc_unimplemented + } } } @@ -1902,7 +2019,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x20: /* LB - MIPS I */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL - UML_CALLH(block, mips3.read8); // callh read8 + UML_CALLH(block, mips3.read8[mips3.cstate->mode >> 1]); // callh read8 if (RTREG != 0) UML_DSEXT1(block, R64(RTREG), IREG(0)); // dsext1 ,i0 if (!in_delay_slot) @@ -1911,7 +2028,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x21: /* LH - MIPS I */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL - UML_CALLH(block, mips3.read16); // callh read16 + UML_CALLH(block, mips3.read16[mips3.cstate->mode >> 1]); // callh read16 if (RTREG != 0) UML_DSEXT2(block, R64(RTREG), IREG(0)); // dsext2 ,i0 if (!in_delay_slot) @@ -1920,7 +2037,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x23: /* LW - MIPS I */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL - UML_CALLH(block, mips3.read32); // callh read32 + UML_CALLH(block, mips3.read32[mips3.cstate->mode >> 1]); // callh read32 if (RTREG != 0) UML_DSEXT4(block, R64(RTREG), IREG(0)); // dsext4 ,i0 if (!in_delay_slot) @@ -1929,7 +2046,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x24: /* LBU - MIPS I */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL - UML_CALLH(block, mips3.read8); // callh read8 + UML_CALLH(block, mips3.read8[mips3.cstate->mode >> 1]); // callh read8 if (RTREG != 0) UML_DZEXT1(block, R64(RTREG), IREG(0)); // dzext1 ,i0 if (!in_delay_slot) @@ -1938,7 +2055,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x25: /* LHU - MIPS I */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL - UML_CALLH(block, mips3.read16); // callh read16 + UML_CALLH(block, mips3.read16[mips3.cstate->mode >> 1]); // callh read16 if (RTREG != 0) UML_DZEXT2(block, R64(RTREG), IREG(0)); // dzext2 ,i0 if (!in_delay_slot) @@ -1947,7 +2064,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x27: /* LWU - MIPS III */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL - UML_CALLH(block, mips3.read32); // callh read32 + UML_CALLH(block, mips3.read32[mips3.cstate->mode >> 1]); // callh read32 if (RTREG != 0) UML_DZEXT4(block, R64(RTREG), IREG(0)); // dzext4 ,i0 if (!in_delay_slot) @@ -1956,7 +2073,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x37: /* LD - MIPS III */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL - UML_CALLH(block, mips3.read64); // callh read64 + UML_CALLH(block, mips3.read64[mips3.cstate->mode >> 1]); // callh read64 if (RTREG != 0) UML_DMOV(block, R64(RTREG), IREG(0)); // dmov ,i0 if (!in_delay_slot) @@ -1969,7 +2086,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const if (!mips3.core->bigendian) UML_XOR(block, IREG(4), IREG(4), IMM(0x18)); // xor i4,i4,0x18 UML_SHR(block, IREG(2), IMM(~0), IREG(4)); // shr i2,~0,i4 - UML_CALLH(block, mips3.read32mask); // callh read32mask + UML_CALLH(block, mips3.read32mask[mips3.cstate->mode >> 1]); // callh read32mask if (RTREG != 0) { UML_SHL(block, IREG(2), IMM(~0), IREG(4)); // shl i2,~0,i4 @@ -1989,7 +2106,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const if (mips3.core->bigendian) UML_XOR(block, IREG(4), IREG(4), IMM(0x18)); // xor i4,i4,0x18 UML_SHL(block, IREG(2), IMM(~0), IREG(4)); // shl i2,~0,i4 - UML_CALLH(block, mips3.read32mask); // callh read32mask + UML_CALLH(block, mips3.read32mask[mips3.cstate->mode >> 1]); // callh read32mask if (RTREG != 0) { UML_SHR(block, IREG(2), IMM(~0), IREG(4)); // shr i2,~0,i4 @@ -2009,7 +2126,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const if (!mips3.core->bigendian) UML_XOR(block, IREG(4), IREG(4), IMM(0x38)); // xor i4,i4,0x38 UML_DSHR(block, IREG(2), IMM((UINT64)~0), IREG(4)); // dshr i2,~0,i4 - UML_CALLH(block, mips3.read64mask); // callh read64mask + UML_CALLH(block, mips3.read64mask[mips3.cstate->mode >> 1]); // callh read64mask if (RTREG != 0) { UML_DSHL(block, IREG(2), IMM((UINT64)~0), IREG(4)); // dshl i2,~0,i4 @@ -2028,7 +2145,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const if (mips3.core->bigendian) UML_XOR(block, IREG(4), IREG(4), IMM(0x38)); // xor i4,i4,0x38 UML_DSHL(block, IREG(2), IMM((UINT64)~0), IREG(4)); // dshl i2,~0,i4 - UML_CALLH(block, mips3.read64mask); // callh read64mask + UML_CALLH(block, mips3.read64mask[mips3.cstate->mode >> 1]); // callh read64mask if (RTREG != 0) { UML_DSHR(block, IREG(2), IMM((UINT64)~0), IREG(4)); // dshr i2,~0,i4 @@ -2043,7 +2160,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x31: /* LWC1 - MIPS I */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL - UML_CALLH(block, mips3.read32); // callh read32 + UML_CALLH(block, mips3.read32[mips3.cstate->mode >> 1]); // callh read32 UML_MOV(block, FPR32(RTREG), IREG(0)); // mov ,i0 if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); @@ -2051,7 +2168,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x35: /* LDC1 - MIPS III */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL - UML_CALLH(block, mips3.read64); // callh read64 + UML_CALLH(block, mips3.read64[mips3.cstate->mode >> 1]); // callh read64 UML_DMOV(block, FPR64(RTREG), IREG(0)); // dmov ,i0 if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); @@ -2059,7 +2176,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x32: /* LWC2 - MIPS I */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL - UML_CALLH(block, mips3.read32); // callh read32 + UML_CALLH(block, mips3.read32[mips3.cstate->mode >> 1]); // callh read32 UML_DZEXT4(block, CPR264(RTREG), IREG(0)); // dzext4 ,i0 if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); @@ -2067,7 +2184,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x36: /* LDC2 - MIPS II */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL - UML_CALLH(block, mips3.read64); // callh read64 + UML_CALLH(block, mips3.read64[mips3.cstate->mode >> 1]); // callh read64 UML_DMOV(block, CPR264(RTREG), IREG(0)); // dmov ,i0 if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); @@ -2079,7 +2196,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x28: /* SB - MIPS I */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL UML_MOV(block, IREG(1), R32(RTREG)); // mov i1, - UML_CALLH(block, mips3.write8); // callh write8 + UML_CALLH(block, mips3.write8[mips3.cstate->mode >> 1]); // callh write8 if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); return TRUE; @@ -2087,7 +2204,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x29: /* SH - MIPS I */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL UML_MOV(block, IREG(1), R32(RTREG)); // mov i1, - UML_CALLH(block, mips3.write16); // callh write16 + UML_CALLH(block, mips3.write16[mips3.cstate->mode >> 1]); // callh write16 if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); return TRUE; @@ -2095,7 +2212,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x2b: /* SW - MIPS I */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL UML_MOV(block, IREG(1), R32(RTREG)); // mov i1, - UML_CALLH(block, mips3.write32); // callh write32 + UML_CALLH(block, mips3.write32[mips3.cstate->mode >> 1]); // callh write32 if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); return TRUE; @@ -2103,7 +2220,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x3f: /* SD - MIPS III */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL UML_DMOV(block, IREG(1), R64(RTREG)); // dmov i1, - UML_CALLH(block, mips3.write64); // callh write64 + UML_CALLH(block, mips3.write64[mips3.cstate->mode >> 1]); // callh write64 if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); return TRUE; @@ -2116,7 +2233,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_XOR(block, IREG(4), IREG(4), IMM(0x18)); // xor i4,i4,0x18 UML_SHR(block, IREG(2), IMM(~0), IREG(4)); // shr i2,~0,i4 UML_SHR(block, IREG(1), IREG(1), IREG(4)); // shr i1,i1,i4 - UML_CALLH(block, mips3.write32mask); // callh write32mask + UML_CALLH(block, mips3.write32mask[mips3.cstate->mode >> 1]); // callh write32mask if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); return TRUE; @@ -2129,7 +2246,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_XOR(block, IREG(4), IREG(4), IMM(0x18)); // xor i4,i4,0x18 UML_SHL(block, IREG(2), IMM(~0), IREG(4)); // shl i2,~0,i4 UML_SHL(block, IREG(1), IREG(1), IREG(4)); // shl i1,i1,i4 - UML_CALLH(block, mips3.write32mask); // callh write32mask + UML_CALLH(block, mips3.write32mask[mips3.cstate->mode >> 1]); // callh write32mask if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); return TRUE; @@ -2142,7 +2259,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_XOR(block, IREG(4), IREG(4), IMM(0x38)); // xor i4,i4,0x38 UML_DSHR(block, IREG(2), IMM((UINT64)~0), IREG(4)); // dshr i2,~0,i4 UML_DSHR(block, IREG(1), IREG(1), IREG(4)); // dshr i1,i1,i4 - UML_CALLH(block, mips3.write64mask); // callh write64mask + UML_CALLH(block, mips3.write64mask[mips3.cstate->mode >> 1]); // callh write64mask if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); return TRUE; @@ -2155,7 +2272,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_XOR(block, IREG(4), IREG(4), IMM(0x38)); // xor i4,i4,0x38 UML_DSHL(block, IREG(2), IMM((UINT64)~0), IREG(4)); // dshl i2,~0,i4 UML_DSHL(block, IREG(1), IREG(1), IREG(4)); // dshl i1,i1,i4 - UML_CALLH(block, mips3.write64mask); // callh write64mask + UML_CALLH(block, mips3.write64mask[mips3.cstate->mode >> 1]); // callh write64mask if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); return TRUE; @@ -2163,7 +2280,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x39: /* SWC1 - MIPS I */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL UML_MOV(block, IREG(1), FPR32(RTREG)); // mov i1, - UML_CALLH(block, mips3.write32); // callh write32 + UML_CALLH(block, mips3.write32[mips3.cstate->mode >> 1]); // callh write32 if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); return TRUE; @@ -2171,7 +2288,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x3d: /* SDC1 - MIPS III */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL UML_DMOV(block, IREG(1), FPR64(RTREG)); // dmov i1, - UML_CALLH(block, mips3.write64); // callh write64 + UML_CALLH(block, mips3.write64[mips3.cstate->mode >> 1]); // callh write64 if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); return TRUE; @@ -2179,7 +2296,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x3a: /* SWC2 - MIPS I */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL UML_MOV(block, IREG(1), CPR232(RTREG)); // mov i1, - UML_CALLH(block, mips3.write32); // callh write32 + UML_CALLH(block, mips3.write32[mips3.cstate->mode >> 1]); // callh write32 if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); return TRUE; @@ -2187,7 +2304,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x3e: /* SDC2 - MIPS II */ UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,,SIMMVAL UML_DMOV(block, IREG(1), CPR264(RTREG)); // dmov i1, - UML_CALLH(block, mips3.write64); // callh write64 + UML_CALLH(block, mips3.write64[mips3.cstate->mode >> 1]); // callh write64 if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); return TRUE; @@ -2789,8 +2906,7 @@ static int generate_set_cop0_reg(drcuml_block *block, compiler_state *compiler, generate_update_cycles(block, compiler, desc->pc, NULL, !in_delay_slot);// UML_MOV(block, IREG(1), CPR032(COP0_Status)); // mov i1,[Status] UML_MOV(block, CPR032(COP0_Status), IREG(0)); // mov [Status],i0 - UML_SHR(block, IREG(2), IREG(1), IMM(26)); // shr i2,i1,26 - UML_AND(block, MEM(&mips3.cstate->mode), IREG(2), IMM(1)); // and [mode],i2,1 + generate_update_mode(block); UML_XOR(block, IREG(0), IREG(0), IREG(1)); // xor i0,i0,i1 UML_TEST(block, IREG(0), IMM(0x8000)); // test i0,0x8000 UML_CALLCc(block, IF_NZ, mips3com_update_cycle_counting, mips3.core); // callc mips3com_update_cycle_counting,mips.core,NZ @@ -2896,18 +3012,15 @@ static int generate_cop0(drcuml_block *block, compiler_state *compiler, const op { UINT32 op = *desc->opptr.l; UINT8 opswitch = RSREG; + drcuml_codelabel okay; + int skip; /* generate an exception if COP0 is disabled or we are not in kernel mode */ - if (mips3.drcoptions & MIPS3DRC_STRICT_COP0) - { - drcuml_codelabel okay; - - UML_TEST(block, CPR032(COP0_Status), IMM(SR_KSU_MASK)); // test [Status],SR_KSU_MASK - UML_JMPc(block, IF_Z, okay = compiler->labelnum++); // jmp okay,Z - UML_TEST(block, CPR032(COP0_Status), IMM(SR_COP0)); // test [Status],SR_COP0 - UML_EXHc(block, IF_Z, mips3.exception[EXCEPTION_BADCOP], IMM(0)); // exh cop,0,Z - UML_LABEL(block, okay); // okay: - } + UML_TEST(block, CPR032(COP0_Status), IMM(SR_KSU_MASK)); // test [Status],SR_KSU_MASK + UML_JMPc(block, IF_Z, okay = compiler->labelnum++); // jmp okay,Z + UML_TEST(block, CPR032(COP0_Status), IMM(SR_COP0)); // test [Status],SR_COP0 + UML_EXHc(block, IF_Z, mips3.exception[EXCEPTION_BADCOP], IMM(0)); // exh cop,0,Z + UML_LABEL(block, okay); // okay: switch (opswitch) { @@ -2981,12 +3094,25 @@ static int generate_cop0(drcuml_block *block, compiler_state *compiler, const op return TRUE; case 0x18: /* ERET */ - UML_AND(block, CPR032(COP0_Status), CPR032(COP0_Status), IMM(~SR_EXL)); - // and [Status],[Status],~SR_EXL + UML_MOV(block, IREG(0), CPR032(COP0_Status)); // mov i0,[Status] + UML_TEST(block, IREG(0), IMM(SR_ERL)); // test i0,SR_ERL + UML_JMPc(block, IF_NZ, skip = compiler->labelnum++); // jmp skip,nz + UML_AND(block, IREG(0), IREG(0), IMM(~SR_EXL)); // and i0,i0,~SR_EXL + UML_MOV(block, CPR032(COP0_Status), IREG(0)); // mov [Status],i0 + generate_update_mode(block); compiler->checkints = TRUE; generate_update_cycles(block, compiler, 0, LOPTR(&mips3.core->cpr[0][COP0_EPC]), TRUE); // - UML_HASHJMP(block, IMM(mips3.cstate->mode), CPR032(COP0_EPC), mips3.nocode); + UML_HASHJMP(block, MEM(&mips3.cstate->mode), CPR032(COP0_EPC), mips3.nocode); + // hashjmp ,[EPC],nocode + UML_LABEL(block, skip); // skip: + UML_AND(block, IREG(0), IREG(0), IMM(~SR_ERL)); // and i0,i0,~SR_ERL + UML_MOV(block, CPR032(COP0_Status), IREG(0)); // mov [Status],i0 + generate_update_mode(block); + compiler->checkints = TRUE; + generate_update_cycles(block, compiler, 0, LOPTR(&mips3.core->cpr[0][COP0_ErrorPC]), TRUE); + // + UML_HASHJMP(block, MEM(&mips3.cstate->mode), CPR032(COP0_ErrorPC), mips3.nocode); // hashjmp ,[EPC],nocode return TRUE; @@ -3381,7 +3507,7 @@ static int generate_cop1x(drcuml_block *block, compiler_state *compiler, const o { case 0x00: /* LWXC1 - MIPS IV */ UML_ADD(block, IREG(0), R32(RSREG), R32(RTREG)); // add i0,, - UML_CALLH(block, mips3.read32); // callh read32 + UML_CALLH(block, mips3.read32[mips3.cstate->mode >> 1]); // callh read32 UML_MOV(block, FPR32(RDREG), IREG(0)); // mov ,i0 if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); @@ -3389,7 +3515,7 @@ static int generate_cop1x(drcuml_block *block, compiler_state *compiler, const o case 0x01: /* LDXC1 - MIPS IV */ UML_ADD(block, IREG(0), R32(RSREG), R32(RTREG)); // add i0,, - UML_CALLH(block, mips3.read64); // callh read64 + UML_CALLH(block, mips3.read64[mips3.cstate->mode >> 1]); // callh read64 UML_DMOV(block, FPR64(RDREG), IREG(0)); // dmov ,i0 if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); @@ -3398,7 +3524,7 @@ static int generate_cop1x(drcuml_block *block, compiler_state *compiler, const o case 0x08: /* SWXC1 - MIPS IV */ UML_ADD(block, IREG(0), R32(RSREG), R32(RTREG)); // add i0,, UML_MOV(block, IREG(1), FPR32(RTREG)); // mov i1, - UML_CALLH(block, mips3.write32); // callh write32 + UML_CALLH(block, mips3.write32[mips3.cstate->mode >> 1]); // callh write32 if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); return TRUE; @@ -3406,7 +3532,7 @@ static int generate_cop1x(drcuml_block *block, compiler_state *compiler, const o case 0x09: /* SDXC1 - MIPS IV */ UML_ADD(block, IREG(0), R32(RSREG), R32(RTREG)); // add i0,, UML_DMOV(block, IREG(1), FPR64(RTREG)); // dmov i1, - UML_CALLH(block, mips3.write64); // callh write64 + UML_CALLH(block, mips3.write64[mips3.cstate->mode >> 1]); // callh write64 if (!in_delay_slot) generate_update_cycles(block, compiler, desc->pc + 4, 0, TRUE); return TRUE; @@ -3589,7 +3715,10 @@ static void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, i /* disassemle the current instruction and output it to the log */ #if (LOG_UML || LOG_NATIVE) - dasmmips3(buffer, desclist->pc, *desclist->opptr.l); + if (desclist->flags & OPFLAG_VIRTUAL_NOOP) + strcpy(buffer, ""); + else + dasmmips3(buffer, desclist->pc, *desclist->opptr.l); #else strcpy(buffer, "???"); #endif diff --git a/src/emu/cpu/mips/mips3fe.c b/src/emu/cpu/mips/mips3fe.c index 78b1a6dbb9f..b6c9e1ef6ff 100644 --- a/src/emu/cpu/mips/mips3fe.c +++ b/src/emu/cpu/mips/mips3fe.c @@ -516,7 +516,7 @@ static int describe_instruction_cop0(mips3_state *mips, UINT32 op, opcode_desc * return TRUE; case 0x18: /* ERET */ - desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + desc->flags |= OPFLAG_CAN_CHANGE_MODES | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; return TRUE; } return FALSE;