diff options
author | 2008-06-16 03:12:49 +0000 | |
---|---|---|
committer | 2008-06-16 03:12:49 +0000 | |
commit | 5deab27d6d41791498aac45246d3b7cc5ea6281f (patch) | |
tree | 56c1910008a5e3df2cc6ea0034b409044765d041 /src | |
parent | cd0703d80ab10309a691929f66efd792b5fff6ca (diff) |
Created common virtual TLB managment module.
Updated MIPS and PowerPC code to make use of it.
Diffstat (limited to 'src')
-rw-r--r-- | src/emu/cpu/cpu.mak | 9 | ||||
-rw-r--r-- | src/emu/cpu/mips/mips3.c | 3 | ||||
-rw-r--r-- | src/emu/cpu/mips/mips3com.c | 333 | ||||
-rw-r--r-- | src/emu/cpu/mips/mips3com.h | 11 | ||||
-rw-r--r-- | src/emu/cpu/mips/mips3drc.c | 46 | ||||
-rw-r--r-- | src/emu/cpu/powerpc/ppccom.c | 188 | ||||
-rw-r--r-- | src/emu/cpu/powerpc/ppccom.h | 14 | ||||
-rw-r--r-- | src/emu/cpu/powerpc/ppcdrc.c | 217 | ||||
-rw-r--r-- | src/emu/cpu/vtlb.c | 284 | ||||
-rw-r--r-- | src/emu/cpu/vtlb.h | 89 |
10 files changed, 755 insertions, 439 deletions
diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak index 8a0cb72fc38..6dce0300f22 100644 --- a/src/emu/cpu/cpu.mak +++ b/src/emu/cpu/cpu.mak @@ -15,6 +15,15 @@ CPUOBJ = $(EMUOBJ)/cpu #------------------------------------------------- +# Shared code +#------------------------------------------------- + +OBJDIRS += $(CPUOBJ) +CPUOBJS += $(CPUOBJ)/vtlb.o + + + +#------------------------------------------------- # Dynamic recompiler objects #------------------------------------------------- diff --git a/src/emu/cpu/mips/mips3.c b/src/emu/cpu/mips/mips3.c index 78d7a097813..ed12d7f8d7a 100644 --- a/src/emu/cpu/mips/mips3.c +++ b/src/emu/cpu/mips/mips3.c @@ -556,8 +556,7 @@ INLINE void set_cop0_reg(int idx, UINT64 val) if ((mips3.core.cpr[0][idx] ^ val) & 0xff) { mips3.core.cpr[0][idx] = val; - mips3com_unmap_tlb_entries(&mips3.core); - mips3com_map_tlb_entries(&mips3.core); + mips3com_asid_changed(&mips3.core); } mips3.core.cpr[0][idx] = val; break; diff --git a/src/emu/cpu/mips/mips3com.c b/src/emu/cpu/mips/mips3com.c index cdf8e69bf67..74d1a8f8bac 100644 --- a/src/emu/cpu/mips/mips3com.c +++ b/src/emu/cpu/mips/mips3com.c @@ -13,7 +13,7 @@ DEBUGGING ***************************************************************************/ -#define PRINTF_TLB (1) +#define PRINTF_TLB (0) @@ -26,8 +26,36 @@ static TIMER_CALLBACK( compare_int_callback ); static UINT32 compute_config_register(const mips3_state *mips); static UINT32 compute_prid_register(const mips3_state *mips); -static void tlb_write_common(mips3_state *mips, int index); -static void tlb_entry_log_half(mips3_tlb_entry *tlbent, int index, int which); +static void tlb_map_entry(mips3_state *mips, int tlbindex); +static void tlb_write_common(mips3_state *mips, int tlbindex); +static void tlb_entry_log_half(mips3_tlb_entry *entry, int tlbindex, int which); + + + +/*************************************************************************** + INLINE FUNCTIONS +***************************************************************************/ + +/*------------------------------------------------- + tlb_entry_matches_asid - TRUE if the given + TLB entry matches the provided ASID +-------------------------------------------------*/ + +INLINE int tlb_entry_matches_asid(const mips3_tlb_entry *entry, UINT8 asid) +{ + return (entry->entry_hi & 0xff) == asid; +} + + +/*------------------------------------------------- + tlb_entry_is_global - TRUE if the given + TLB entry is global +-------------------------------------------------*/ + +INLINE int tlb_entry_is_global(const mips3_tlb_entry *entry) +{ + return (entry->entry_lo[0] & entry->entry_lo[1] & TLB_GLOBAL); +} @@ -40,14 +68,8 @@ static void tlb_entry_log_half(mips3_tlb_entry *tlbent, int index, int which); structure based on the configured type -------------------------------------------------*/ -size_t mips3com_init(mips3_state *mips, mips3_flavor flavor, int bigendian, int index, int clock, const mips3_config *config, int (*irqcallback)(int), void *memory) +void mips3com_init(mips3_state *mips, mips3_flavor flavor, int bigendian, int index, int clock, const mips3_config *config, int (*irqcallback)(int)) { - int tlbindex; - - /* if no memory, return the amount needed */ - if (memory == NULL) - return sizeof(mips->tlb_table[0]) * (1 << (MIPS3_MAX_PADDR_SHIFT - MIPS3_MIN_PAGE_SHIFT)); - /* initialize based on the config */ memset(mips, 0, sizeof(*mips)); mips->flavor = flavor; @@ -61,25 +83,25 @@ size_t mips3com_init(mips3_state *mips, mips3_flavor flavor, int bigendian, int /* set up the endianness */ mips->memory = *memory_get_accessors(ADDRESS_SPACE_PROGRAM, 32, mips->bigendian ? CPU_IS_BE : CPU_IS_LE); - /* allocate memory */ - mips->tlb_table = memory; - - /* 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 the virtual TLB */ + mips->vtlb = vtlb_alloc(cpu_getactivecpu(), ADDRESS_SPACE_PROGRAM, 2 * MIPS3_TLB_ENTRIES + 2, 0); /* allocate a timer for the compare interrupt */ mips->compare_int_timer = timer_alloc(compare_int_callback, NULL); /* reset the state */ mips3com_reset(mips); - return 0; +} + + +/*------------------------------------------------- + mips3com_exit - common cleanup/exit +-------------------------------------------------*/ + +void mips3com_exit(mips3_state *mips) +{ + if (mips->vtlb != NULL) + vtlb_free(mips->vtlb); } @@ -90,6 +112,8 @@ size_t mips3com_init(mips3_state *mips, mips3_flavor flavor, int bigendian, int void mips3com_reset(mips3_state *mips) { + int tlbindex; + /* initialize the state */ mips->pc = 0xbfc00000; mips->cpr[0][COP0_Status] = SR_BEV | SR_ERL; @@ -100,8 +124,21 @@ void mips3com_reset(mips3_state *mips) mips->cpr[0][COP0_PRId] = compute_prid_register(mips); mips->count_zero_time = activecpu_gettotalcycles(); - /* recompute the TLB table */ - mips3com_recompute_tlb_table(mips); + /* initialize the TLB state */ + for (tlbindex = 0; tlbindex < ARRAY_LENGTH(mips->tlb); tlbindex++) + { + mips3_tlb_entry *entry = &mips->tlb[tlbindex]; + entry->page_mask = 0; + entry->entry_hi = 0xffffffff; + entry->entry_lo[0] = 0xfffffff8; + entry->entry_lo[1] = 0xfffffff8; + vtlb_load(mips->vtlb, 2 * tlbindex + 0, 0, 0, 0); + vtlb_load(mips->vtlb, 2 * tlbindex + 1, 0, 0, 0); + } + + /* load the fixed TLB range */ + vtlb_load(mips->vtlb, 2 * MIPS3_TLB_ENTRIES + 0, (0xa0000000 - 0x80000000) >> MIPS3_MIN_PAGE_SHIFT, 0x80000000, 0x00000000 | VTLB_READ_ALLOWED | VTLB_WRITE_ALLOWED | VTLB_FETCH_ALLOWED | VTLB_FLAG_VALID); + vtlb_load(mips->vtlb, 2 * MIPS3_TLB_ENTRIES + 1, (0xc0000000 - 0xa0000000) >> MIPS3_MIN_PAGE_SHIFT, 0xa0000000, 0x00000000 | VTLB_READ_ALLOWED | VTLB_WRITE_ALLOWED | VTLB_FETCH_ALLOWED | VTLB_FLAG_VALID); } @@ -154,99 +191,18 @@ void mips3com_update_cycle_counting(mips3_state *mips) ***************************************************************************/ /*------------------------------------------------- - mips3com_map_tlb_entries - map entries from the - TLB into the tlb_table --------------------------------------------------*/ - -void mips3com_map_tlb_entries(mips3_state *mips) -{ - int valid_asid = mips->cpr[0][COP0_EntryHi] & 0xff; - int index; - - /* iterate over all TLB entries */ - for (index = 0; index < ARRAY_LENGTH(mips->tlb); index++) - { - mips3_tlb_entry *tlbent = &mips->tlb[index]; - - /* 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; - int which, i; - - /* ignore if the virtual address is beyond 32 bits */ - if (vpn < (1 << (MIPS3_MAX_PADDR_SHIFT - MIPS3_MIN_PAGE_SHIFT))) - - /* loop over both the even and odd pages */ - 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; - - for (i = 0; i <= count; i++, vpn++, pfn++) - if (vpn < 0x80000 || vpn >= 0xc0000) - mips->tlb_table[vpn] = (pfn << MIPS3_MIN_PAGE_SHIFT) | wp; - } - } - } -} - - -/*------------------------------------------------- - mips3com_unmap_tlb_entries - unmap entries from - the TLB into the tlb_table + mips3com_asid_changed - remap all non-global + TLB entries -------------------------------------------------*/ -void mips3com_unmap_tlb_entries(mips3_state *mips) +void mips3com_asid_changed(mips3_state *mips) { - int index; - - /* iterate over all TLB entries */ - for (index = 0; index < ARRAY_LENGTH(mips->tlb); index++) - { - mips3_tlb_entry *tlbent = &mips->tlb[index]; - UINT32 count = (tlbent->page_mask >> 13) & 0x00fff; - UINT32 vpn = ((tlbent->entry_hi >> 13) & 0x07ffffff) << 1; - int which, i; - - /* ignore if the virtual address is beyond 32 bits */ - if (vpn < (1 << (MIPS3_MAX_PADDR_SHIFT - MIPS3_MIN_PAGE_SHIFT))) - - /* loop over both the even and odd pages */ - for (which = 0; which < 2; which++) - for (i = 0; i <= count; i++, vpn++) - if (vpn < 0x80000 || vpn >= 0xc0000) - mips->tlb_table[vpn] = 0; - } -} - - -/*------------------------------------------------- - mips3com_recompute_tlb_table - recompute the TLB - table from scratch --------------------------------------------------*/ - -void mips3com_recompute_tlb_table(mips3_state *mips) -{ - UINT32 addr; - - /* 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) | TLB_PRESENT | TLB_DIRTY | TLB_VALID | TLB_GLOBAL; - - /* reset everything else to unmapped */ - 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)); + int tlbindex; - /* remap all the entries in the TLB */ - mips3com_map_tlb_entries(mips); + /* iterate over all non-global TLB entries and remap them */ + for (tlbindex = 0; tlbindex < ARRAY_LENGTH(mips->tlb); tlbindex++) + if (!tlb_entry_is_global(&mips->tlb[tlbindex])) + tlb_map_entry(mips, tlbindex); } @@ -260,10 +216,11 @@ int mips3com_translate_address(mips3_state *mips, int space, int intention, offs /* only applies to the program address space */ if (space == ADDRESS_SPACE_PROGRAM) { - UINT32 result = mips->tlb_table[*address >> MIPS3_MIN_PAGE_SHIFT]; - if (!(result & TLB_PRESENT) || !(result & TLB_VALID)) + const vtlb_entry *table = vtlb_table(mips->vtlb); + vtlb_entry entry = table[*address >> MIPS3_MIN_PAGE_SHIFT]; + if ((entry & (1 << (intention & (TRANSLATE_TYPE_MASK | TRANSLATE_USER_MASK)))) == 0) return FALSE; - *address = (result & ~MIPS3_MIN_PAGE_MASK) | (*address & MIPS3_MIN_PAGE_MASK); + *address = (entry & ~MIPS3_MIN_PAGE_MASK) | (*address & MIPS3_MIN_PAGE_MASK); } return TRUE; } @@ -275,18 +232,18 @@ int mips3com_translate_address(mips3_state *mips, int space, int intention, offs void mips3com_tlbr(mips3_state *mips) { - UINT32 index = mips->cpr[0][COP0_Index] & 0x3f; + UINT32 tlbindex = mips->cpr[0][COP0_Index] & 0x3f; /* only handle entries within the TLB */ - if (index < ARRAY_LENGTH(mips->tlb)) + if (tlbindex < ARRAY_LENGTH(mips->tlb)) { - mips3_tlb_entry *tlbent = &mips->tlb[index]; + mips3_tlb_entry *entry = &mips->tlb[tlbindex]; /* copy data from the TLB entry into the COP0 registers */ - mips->cpr[0][COP0_PageMask] = tlbent->page_mask; - mips->cpr[0][COP0_EntryHi] = tlbent->entry_hi; - mips->cpr[0][COP0_EntryLo0] = tlbent->entry_lo[0]; - mips->cpr[0][COP0_EntryLo1] = tlbent->entry_lo[1]; + mips->cpr[0][COP0_PageMask] = entry->page_mask; + mips->cpr[0][COP0_EntryHi] = entry->entry_hi; + mips->cpr[0][COP0_EntryLo0] = entry->entry_lo[0]; + mips->cpr[0][COP0_EntryLo1] = entry->entry_lo[1]; } } @@ -310,14 +267,14 @@ void mips3com_tlbwr(mips3_state *mips) { UINT32 wired = mips->cpr[0][COP0_Wired] & 0x3f; UINT32 unwired = ARRAY_LENGTH(mips->tlb) - wired; - UINT32 index = ARRAY_LENGTH(mips->tlb) - 1; + UINT32 tlbindex = ARRAY_LENGTH(mips->tlb) - 1; /* "random" is based off of the current cycle counting through the non-wired pages */ if (unwired > 0) - index = ((activecpu_gettotalcycles() - mips->count_zero_time) % unwired + wired) & 0x3f; + tlbindex = ((activecpu_gettotalcycles() - mips->count_zero_time) % unwired + wired) & 0x3f; - /* use the common handler to write to this index */ - tlb_write_common(mips, index); + /* use the common handler to write to this tlbindex */ + tlb_write_common(mips, tlbindex); } @@ -327,35 +284,29 @@ void mips3com_tlbwr(mips3_state *mips) void mips3com_tlbp(mips3_state *mips) { - UINT32 index; + UINT32 tlbindex; UINT64 vpn; /* iterate over TLB entries */ - for (index = 0; index < ARRAY_LENGTH(mips->tlb); index++) + for (tlbindex = 0; tlbindex < ARRAY_LENGTH(mips->tlb); tlbindex++) { - mips3_tlb_entry *tlbent = &mips->tlb[index]; - UINT64 mask = ~((tlbent->page_mask >> 13) & 0xfff) << 13; + mips3_tlb_entry *entry = &mips->tlb[tlbindex]; + UINT64 mask = ~((entry->page_mask >> 13) & 0xfff) << 13; /* if the relevant bits of EntryHi match the relevant bits of the TLB */ - if ((tlbent->entry_hi & mask) == (mips->cpr[0][COP0_EntryHi] & mask)) + if ((entry->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 & 0xff) == (mips->cpr[0][COP0_EntryHi] & 0xff) || ((tlbent->entry_lo[0] & tlbent->entry_lo[1]) & TLB_GLOBAL)) + if ((entry->entry_hi & 0xff) == (mips->cpr[0][COP0_EntryHi] & 0xff) || ((entry->entry_lo[0] & entry->entry_lo[1]) & TLB_GLOBAL)) break; } /* validate that our tlb_table was in sync */ vpn = ((mips->cpr[0][COP0_EntryHi] >> 13) & 0x07ffffff) << 1; - if (index != ARRAY_LENGTH(mips->tlb)) - { - assert(mips->tlb_table[vpn & 0xfffff] & TLB_PRESENT); - mips->cpr[0][COP0_Index] = index; - } + if (tlbindex != ARRAY_LENGTH(mips->tlb)) + mips->cpr[0][COP0_Index] = tlbindex; else - { - assert(!(mips->tlb_table[vpn & 0xfffff] & TLB_PRESENT)); mips->cpr[0][COP0_Index] = 0x80000000; - } } @@ -828,32 +779,90 @@ static UINT32 compute_prid_register(const mips3_state *mips) /*------------------------------------------------- + tlb_map_entry - map a single TLB + entry +-------------------------------------------------*/ + +static void tlb_map_entry(mips3_state *mips, int tlbindex) +{ + int current_asid = mips->cpr[0][COP0_EntryHi] & 0xff; + mips3_tlb_entry *entry = &mips->tlb[tlbindex]; + UINT32 count, vpn; + int which; + + /* the ASID doesn't match the current ASID, and if the page isn't global, unmap it from the TLB */ + if (!tlb_entry_matches_asid(entry, current_asid) && !tlb_entry_is_global(entry)) + { + vtlb_load(mips->vtlb, 2 * tlbindex + 0, 0, 0, 0); + vtlb_load(mips->vtlb, 2 * tlbindex + 1, 0, 0, 0); + return; + } + + /* extract the VPN index; ignore if the virtual address is beyond 32 bits */ + vpn = ((entry->entry_hi >> 13) & 0x07ffffff) << 1; + if (vpn >= (1 << (MIPS3_MAX_PADDR_SHIFT - MIPS3_MIN_PAGE_SHIFT))) + { + vtlb_load(mips->vtlb, 2 * tlbindex + 0, 0, 0, 0); + vtlb_load(mips->vtlb, 2 * tlbindex + 1, 0, 0, 0); + return; + } + + /* get the number of pages from the page mask */ + count = ((entry->page_mask >> 13) & 0x00fff) + 1; + + /* loop over both the even and odd pages */ + for (which = 0; which < 2; which++) + { + UINT32 effvpn = vpn + count * which; + UINT64 lo = entry->entry_lo[which]; + UINT32 pfn = (lo >> 6) & 0x00ffffff; + UINT32 flags = 0; + + /* valid? */ + if ((lo & 2) != 0) + { + flags |= VTLB_FLAG_VALID | VTLB_READ_ALLOWED | VTLB_FETCH_ALLOWED; + + /* writable? */ + if ((lo & 4) != 0) + flags |= VTLB_WRITE_ALLOWED; + + /* mirror the flags for user mode if the VPN is in user space */ + if (effvpn < (0x80000000 >> MIPS3_MIN_PAGE_SHIFT)) + flags |= (flags << 4) & (VTLB_USER_READ_ALLOWED | VTLB_USER_WRITE_ALLOWED | VTLB_USER_FETCH_ALLOWED); + } + + /* load the virtual TLB with the corresponding entries */ + if ((effvpn + count) <= (0x80000000 >> MIPS3_MIN_PAGE_SHIFT) || effvpn >= (0xc0000000 >> MIPS3_MIN_PAGE_SHIFT)) + vtlb_load(mips->vtlb, 2 * tlbindex + which, count, effvpn << MIPS3_MIN_PAGE_SHIFT, (pfn << MIPS3_MIN_PAGE_SHIFT) | flags); + } +} + + +/*------------------------------------------------- tlb_write_common - common routine for writing a TLB entry -------------------------------------------------*/ -static void tlb_write_common(mips3_state *mips, int index) +static void tlb_write_common(mips3_state *mips, int tlbindex) { /* only handle entries within the TLB */ - if (index < ARRAY_LENGTH(mips->tlb)) + if (tlbindex < ARRAY_LENGTH(mips->tlb)) { - mips3_tlb_entry *tlbent = &mips->tlb[index]; - - /* unmap what we have */ - mips3com_unmap_tlb_entries(mips); + mips3_tlb_entry *entry = &mips->tlb[tlbindex]; /* fill in the new TLB entry from the COP0 registers */ - tlbent->page_mask = mips->cpr[0][COP0_PageMask]; - tlbent->entry_hi = mips->cpr[0][COP0_EntryHi] & ~(tlbent->page_mask & U64(0x0000000001ffe000)); - tlbent->entry_lo[0] = mips->cpr[0][COP0_EntryLo0]; - tlbent->entry_lo[1] = mips->cpr[0][COP0_EntryLo1]; + entry->page_mask = mips->cpr[0][COP0_PageMask]; + entry->entry_hi = mips->cpr[0][COP0_EntryHi] & ~(entry->page_mask & U64(0x0000000001ffe000)); + entry->entry_lo[0] = mips->cpr[0][COP0_EntryLo0]; + entry->entry_lo[1] = mips->cpr[0][COP0_EntryLo1]; - /* remap the TLB */ - mips3com_map_tlb_entries(mips); + /* remap this TLB entry */ + tlb_map_entry(mips, tlbindex); /* log the two halves once they are in */ - tlb_entry_log_half(tlbent, index, 0); - tlb_entry_log_half(tlbent, index, 1); + tlb_entry_log_half(entry, tlbindex, 0); + tlb_entry_log_half(entry, tlbindex, 1); } } @@ -863,24 +872,24 @@ static void tlb_write_common(mips3_state *mips, int index) entry -------------------------------------------------*/ -static void tlb_entry_log_half(mips3_tlb_entry *tlbent, int index, int which) +static void tlb_entry_log_half(mips3_tlb_entry *entry, int tlbindex, int which) { #if PRINTF_TLB - UINT64 hi = tlbent->entry_hi; - UINT64 lo = tlbent->entry_lo[which]; + UINT64 hi = entry->entry_hi; + UINT64 lo = entry->entry_lo[which]; UINT32 vpn = (((hi >> 13) & 0x07ffffff) << 1); UINT32 asid = hi & 0xff; UINT32 r = (hi >> 62) & 3; UINT32 pfn = (lo >> 6) & 0x00ffffff; UINT32 c = (lo >> 3) & 7; - UINT32 pagesize = (((tlbent->page_mask >> 13) & 0xfff) + 1) << MIPS3_MIN_PAGE_SHIFT; + UINT32 pagesize = (((entry->page_mask >> 13) & 0xfff) + 1) << MIPS3_MIN_PAGE_SHIFT; UINT64 vaddr = (UINT64)vpn * MIPS3_MIN_PAGE_SIZE; UINT64 paddr = (UINT64)pfn * MIPS3_MIN_PAGE_SIZE; vaddr += pagesize * 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, + printf("index=%08X pagesize=%08X vaddr=%08X%08X paddr=%08X%08X asid=%02X r=%X c=%X dvg=%c%c%c\n", + tlbindex, pagesize, (UINT32)(vaddr >> 32), (UINT32)vaddr, (UINT32)(paddr >> 32), (UINT32)paddr, 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 b970b659b48..67de9a615d9 100644 --- a/src/emu/cpu/mips/mips3com.h +++ b/src/emu/cpu/mips/mips3com.h @@ -11,6 +11,7 @@ #include "cpuintrf.h" #include "mips3.h" +#include "cpu/vtlb.h" /*************************************************************************** @@ -205,8 +206,8 @@ struct _mips3_state size_t dcache_size; /* MMU */ + vtlb_state * vtlb; mips3_tlb_entry tlb[MIPS3_TLB_ENTRIES]; - UINT32 * tlb_table; /* for use by specific implementations */ mips3imp_state *impstate; @@ -218,16 +219,18 @@ struct _mips3_state FUNCTION PROTOTYPES ***************************************************************************/ -size_t mips3com_init(mips3_state *mips, mips3_flavor flavor, int bigendian, int index, int clock, const mips3_config *config, int (*irqcallback)(int), void *memory); +void mips3com_init(mips3_state *mips, mips3_flavor flavor, int bigendian, int index, int clock, const mips3_config *config, int (*irqcallback)(int)); +void mips3com_exit(mips3_state *mips); + void mips3com_reset(mips3_state *mips); #ifdef ENABLE_DEBUGGER offs_t mips3com_dasm(mips3_state *mips, char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); #endif void mips3com_update_cycle_counting(mips3_state *mips); +void mips3com_map_tlb_entry(mips3_state *mips, int tlbindex); void mips3com_map_tlb_entries(mips3_state *mips); -void mips3com_unmap_tlb_entries(mips3_state *mips); -void mips3com_recompute_tlb_table(mips3_state *mips); +void mips3com_asid_changed(mips3_state *mips); int mips3com_translate_address(mips3_state *mips, int space, int intention, offs_t *address); void mips3com_tlbr(mips3_state *mips); void mips3com_tlbwi(mips3_state *mips); diff --git a/src/emu/cpu/mips/mips3drc.c b/src/emu/cpu/mips/mips3drc.c index 8f8dbccb403..225f58dfe19 100644 --- a/src/emu/cpu/mips/mips3drc.c +++ b/src/emu/cpu/mips/mips3drc.c @@ -353,26 +353,19 @@ static void mips3_init(mips3_flavor flavor, int bigendian, int index, int clock, drccache *cache; drcbe_info beinfo; UINT32 flags = 0; - size_t extrasize; - void *extramem; int regnum; - /* determine how much memory beyond the core size we need */ - extrasize = mips3com_init(NULL, flavor, bigendian, index, clock, config, irqcallback, NULL); - /* allocate enough space for the cache and the core */ - cache = drccache_alloc(CACHE_SIZE + sizeof(*mips3) + extrasize); + cache = drccache_alloc(CACHE_SIZE + sizeof(*mips3)); if (cache == NULL) - fatalerror("Unable to allocate cache of size %d", (UINT32)(CACHE_SIZE + sizeof(*mips3) + extrasize)); + fatalerror("Unable to allocate cache of size %d", (UINT32)(CACHE_SIZE + sizeof(*mips3))); - /* allocate the core and the extra memory */ + /* allocate the core memory */ mips3 = drccache_memory_alloc_near(cache, sizeof(*mips3)); memset(mips3, 0, sizeof(*mips3)); - extramem = drccache_memory_alloc(cache, extrasize); - memset(extramem, 0, extrasize); /* initialize the core */ - mips3com_init(mips3, flavor, bigendian, index, clock, config, irqcallback, extramem); + mips3com_init(mips3, flavor, bigendian, index, clock, config, irqcallback); /* allocate the implementation-specific state from the full cache */ mips3->impstate = drccache_memory_alloc_near(cache, sizeof(*mips3->impstate)); @@ -532,6 +525,8 @@ static int mips3_execute(int cycles) static void mips3_exit(void) { + mips3com_exit(mips3); + /* clean up the DRC */ drcfe_exit(mips3->impstate->drcfe); drcuml_free(mips3->impstate->drcuml); @@ -1063,17 +1058,17 @@ static void static_generate_tlb_mismatch(drcuml_state *drcuml) UML_RECOVER(block, IREG(0), MAPVAR_PC); // recover i0,PC UML_MOV(block, MEM(&mips3->pc), IREG(0)); // mov <pc>,i0 UML_SHR(block, IREG(1), IREG(0), IMM(12)); // shr i1,i0,12 - UML_LOAD(block, IREG(1), mips3->tlb_table, IREG(1), DWORD); // load i1,[tlb_table],i1,dword + UML_LOAD(block, IREG(1), (void *)vtlb_table(mips3->vtlb), IREG(1), DWORD); // load i1,[vtlb_table],i1,dword if (PRINTF_MMU) { UML_MOV(block, MEM(&mips3->impstate->arg0), IREG(0)); // mov [arg0],i0 UML_MOV(block, MEM(&mips3->impstate->arg1), IREG(1)); // mov [arg1],i1 UML_CALLC(block, cfunc_printf_debug, "TLB mismatch @ %08X (ent=%08X)\n"); // callc printf_debug } - UML_TEST(block, IREG(1), IMM(TLB_VALID)); // test i1,TLB_VALID + UML_TEST(block, IREG(1), IMM(VTLB_FETCH_ALLOWED)); // test i1,VTLB_FETCH_ALLOWED UML_JMPc(block, IF_NZ, 1); // jmp 1,nz - UML_TEST(block, IREG(1), IMM(TLB_PRESENT)); // test i1,TLB_PRESENT - UML_EXHc(block, IF_NZ, mips3->impstate->exception[EXCEPTION_TLBLOAD], IREG(0)); // exh exception[TLBLOAD],i0,nz + UML_TEST(block, IREG(1), IMM(VTLB_FLAG_VALID)); // test i1,VTLB_FLAG_VALID + UML_EXHc(block, IF_Z, mips3->impstate->exception[EXCEPTION_TLBLOAD], IREG(0)); // exh exception[TLBLOAD],i0,z UML_EXH(block, mips3->impstate->exception[EXCEPTION_TLBLOAD_FILL], IREG(0)); // exh exception[TLBLOAD_FILL],i0 UML_LABEL(block, 1); // 1: save_fast_iregs(block); @@ -1229,8 +1224,8 @@ static void static_generate_memory_accessor(drcuml_state *drcuml, int mode, int /* general case: assume paging and perform a translation */ UML_SHR(block, IREG(3), IREG(0), IMM(12)); // shr i3,i0,12 - UML_LOAD(block, IREG(3), mips3->tlb_table, IREG(3), DWORD); // load i3,[tlb_table],i3,dword - UML_TEST(block, IREG(3), IMM(iswrite ? TLB_DIRTY : TLB_VALID)); // test i3,iswrite ? TLB_DIRTY : TLB_VALID + UML_LOAD(block, IREG(3), (void *)vtlb_table(mips3->vtlb), IREG(3), DWORD); // load i3,[vtlb_table],i3,dword + UML_TEST(block, IREG(3), IMM(iswrite ? VTLB_WRITE_ALLOWED : VTLB_READ_ALLOWED));// test i3,iswrite ? VTLB_WRITE_ALLOWED : VTLB_READ_ALLOWED UML_JMPc(block, IF_Z, tlbmiss = label++); // jmp tlbmiss,z UML_ROLINS(block, IREG(0), IREG(3), IMM(0), IMM(0xfffff000)); // rolins i0,i3,0,0xfffff000 @@ -1385,12 +1380,12 @@ static void static_generate_memory_accessor(drcuml_state *drcuml, int mode, int UML_LABEL(block, tlbmiss); // tlbmiss: if (iswrite) { - UML_TEST(block, IREG(3), IMM(TLB_VALID)); // test i3,TLB_VALID + UML_TEST(block, IREG(3), IMM(VTLB_READ_ALLOWED)); // test i3,VTLB_READ_ALLOWED UML_EXHc(block, IF_NZ, mips3->impstate->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_TEST(block, IREG(3), IMM(VTLB_FLAG_VALID)); // test i3,VTLB_FLAG_VALID + UML_EXHc(block, IF_Z, exception_tlb, IREG(0)); // exh tlb,i0,z UML_EXH(block, exception_tlbfill, IREG(0)); // exh tlbfill,i0 } @@ -1590,16 +1585,18 @@ static void generate_sequence_instruction(drcuml_block *block, compiler_state *c /* validate our TLB entry at this PC; if we fail, we need to handle it */ if ((desc->flags & OPFLAG_VALIDATE_TLB) && (desc->pc < 0x80000000 || desc->pc >= 0xc0000000)) { + const vtlb_entry *tlbtable = vtlb_table(mips3->vtlb); + /* if we currently have a valid TLB read entry, we just verify */ - if (mips3->tlb_table[desc->pc >> 12] & TLB_VALID) + if (tlbtable[desc->pc >> 12] & VTLB_FETCH_ALLOWED) { if (PRINTF_MMU) { UML_MOV(block, MEM(&mips3->impstate->arg0), IMM(desc->pc)); // mov [arg0],desc->pc UML_CALLC(block, cfunc_printf_debug, "Checking TLB at @ %08X\n"); // callc printf_debug } - UML_LOAD(block, IREG(0), &mips3->tlb_table[desc->pc >> 12], IMM(0), DWORD);// load i0,tlb_table[desc->pc >> 12],0,dword - UML_CMP(block, IREG(0), IMM(mips3->tlb_table[desc->pc >> 12])); // cmp i0,*tlbentry + UML_LOAD(block, IREG(0), &tlbtable[desc->pc >> 12], IMM(0), DWORD); // load i0,tlbtable[desc->pc >> 12],0,dword + UML_CMP(block, IREG(0), IMM(tlbtable[desc->pc >> 12])); // cmp i0,*tlbentry UML_EXHc(block, IF_NE, mips3->impstate->tlb_mismatch, IMM(0)); // exh tlb_mismatch,0,NE } @@ -2781,8 +2778,7 @@ static int generate_set_cop0_reg(drcuml_block *block, compiler_state *compiler, UML_MOV(block, CPR032(reg), IREG(0)); // mov cpr0[reg],i0 UML_TEST(block, IREG(1), IMM(0xff)); // test i1,0xff UML_JMPc(block, IF_Z, link = compiler->labelnum++); // jmp link,z - UML_CALLC(block, mips3com_unmap_tlb_entries, mips3); // callc mips3com_unmap_tlb_entries - UML_CALLC(block, mips3com_map_tlb_entries, mips3); // callc mips3com_map_tlb_entries + UML_CALLC(block, mips3com_asid_changed, mips3); // callc mips3com_asid_changed UML_LABEL(block, link); // link: return TRUE; diff --git a/src/emu/cpu/powerpc/ppccom.c b/src/emu/cpu/powerpc/ppccom.c index 6994c73c52a..6a56669d009 100644 --- a/src/emu/cpu/powerpc/ppccom.c +++ b/src/emu/cpu/powerpc/ppccom.c @@ -14,7 +14,6 @@ DEBUGGING ***************************************************************************/ -#define PRINTF_TLB_FILL (1) #define PRINTF_SPU (0) #define PRINTF_DECREMENTER (0) @@ -61,51 +60,6 @@ INLINE int page_access_allowed(int transtype, UINT8 key, UINT8 protbits) /*------------------------------------------------- - tlb_entry_free - free an entry from the TLB, - by index --------------------------------------------------*/ - -INLINE void tlb_entry_free(powerpc_state *ppc, int entrynum) -{ - int oldentry = ppc->tlb_entries[entrynum]; - - /* if we're mapped to something, free the entry in the table */ - if (oldentry != 0) - { - ppc->tlb_table[oldentry - 1] = 0; - ppc->tlb_entries[entrynum] = 0; - } -} - - -/*------------------------------------------------- - tlb_entry_allocate - allocate a TLB entry - for the given address, if needed, and set its - new value --------------------------------------------------*/ - -INLINE int tlb_entry_allocate(powerpc_state *ppc, int entrynum, offs_t address, UINT32 value) -{ - UINT32 *entry = &ppc->tlb_table[address >> 12]; - int allocated = FALSE; - - /* only need to allocate if we are empty */ - if (*entry == 0) - { - /* if there's already a TLB entry at the current index, zap it */ - tlb_entry_free(ppc, entrynum); - - /* allocate a new entry and advance to the next one */ - ppc->tlb_entries[entrynum] = (address >> 12) + 1; - allocated = TRUE; - } - *entry = value; - - return allocated; -} - - -/*------------------------------------------------- get_cr - return the current CR value -------------------------------------------------*/ @@ -229,12 +183,8 @@ INLINE void set_decrementer(powerpc_state *ppc, UINT32 newdec) structure based on the configured type -------------------------------------------------*/ -size_t ppccom_init(powerpc_state *ppc, powerpc_flavor flavor, UINT8 cap, int tb_divisor, int clock, const powerpc_config *config, int (*irqcallback)(int), void *memory) +void ppccom_init(powerpc_state *ppc, powerpc_flavor flavor, UINT8 cap, int tb_divisor, int clock, const powerpc_config *config, int (*irqcallback)(int)) { - /* if no memory, return the amount needed */ - if (memory == NULL) - return sizeof(ppc->tlb_table[0]) * (POWERPC_TLB_ENTRIES + PPC603_FIXED_TLB_ENTRIES + (1 << (32 - POWERPC_MIN_PAGE_SHIFT))); - /* initialize based on the config */ memset(ppc, 0, sizeof(*ppc)); ppc->cpunum = cpu_getactivecpu(); @@ -247,9 +197,8 @@ size_t ppccom_init(powerpc_state *ppc, powerpc_flavor flavor, UINT8 cap, int tb_ ppc->system_clock = (config != NULL) ? config->bus_frequency : clock; ppc->tb_divisor = (ppc->tb_divisor * clock + ppc->system_clock / 2 - 1) / ppc->system_clock; - /* initialize the TLB state */ - ppc->tlb_entries = memory; - ppc->tlb_table = ppc->tlb_entries + POWERPC_TLB_ENTRIES + PPC603_FIXED_TLB_ENTRIES; + /* allocate the virtual TLB */ + ppc->vtlb = vtlb_alloc(cpu_getactivecpu(), ADDRESS_SPACE_PROGRAM, (cap & PPCCAP_603_MMU) ? PPC603_FIXED_TLB_ENTRIES : 0, POWERPC_TLB_ENTRIES); /* allocate a timer for the compare interrupt */ if (cap & PPCCAP_OEA) @@ -265,7 +214,17 @@ size_t ppccom_init(powerpc_state *ppc, powerpc_flavor flavor, UINT8 cap, int tb_ /* reset the state */ ppccom_reset(ppc); - return 0; +} + + +/*------------------------------------------------- + ppccom_exit - common cleanup/exit +-------------------------------------------------*/ + +void ppccom_exit(powerpc_state *ppc) +{ + if (ppc->vtlb != NULL) + vtlb_free(ppc->vtlb); } @@ -276,6 +235,8 @@ size_t ppccom_init(powerpc_state *ppc, powerpc_flavor flavor, UINT8 cap, int tb_ void ppccom_reset(powerpc_state *ppc) { + int tlbindex; + /* initialize the OEA state */ if (ppc->cap & PPCCAP_OEA) { @@ -307,9 +268,10 @@ void ppccom_reset(powerpc_state *ppc) ppc->irq_pending = 0; /* flush the TLB */ - ppc->tlb_index = 0; - memset(ppc->tlb_entries, 0, sizeof(ppc->tlb_entries[0]) * (POWERPC_TLB_ENTRIES + PPC603_FIXED_TLB_ENTRIES)); - memset(ppc->tlb_table, 0, sizeof(ppc->tlb_table[0]) * (1 << (32 - POWERPC_MIN_PAGE_SHIFT))); + vtlb_flush_dynamic(ppc->vtlb); + if (ppc->cap & PPCCAP_603_MMU) + for (tlbindex = 0; tlbindex < PPC603_FIXED_TLB_ENTRIES; tlbindex++) + vtlb_load(ppc->vtlb, tlbindex, 0, 0, 0); } @@ -349,6 +311,28 @@ static UINT32 ppccom_translate_address_internal(powerpc_state *ppc, int intentio int batbase, batnum, hashnum; UINT32 segreg; + /* 4xx case: "TLB" really just caches writes and checks compare registers */ + if (ppc->cap & PPCCAP_4XX) + { + /* we don't support the MMU of the 403GCX */ + if (ppc->flavor == PPC_MODEL_403GCX && (ppc->msr & MSROEA_DR)) + fatalerror("MMU enabled but not supported!"); + + /* only check if PE is enabled */ + if (transtype == TRANSLATE_WRITE && (ppc->msr & MSR4XX_PE)) + { + /* are we within one of the protection ranges? */ + int inrange1 = ((*address >> 12) >= (ppc->spr[SPR4XX_PBL1] >> 12) && (*address >> 12) < (ppc->spr[SPR4XX_PBU1] >> 12)); + int inrange2 = ((*address >> 12) >= (ppc->spr[SPR4XX_PBL2] >> 12) && (*address >> 12) < (ppc->spr[SPR4XX_PBU2] >> 12)); + + /* if PX == 1, writes are only allowed OUTSIDE of the bounds */ + if (((ppc->msr & MSR4XX_PX) && (inrange1 || inrange2)) || (!(ppc->msr & MSR4XX_PX) && (!inrange1 && !inrange2))) + return 0x002; + } + *address &= 0x7fffffff; + return 0x001; + } + /* only applies if we support the OEA */ if (!(ppc->cap & PPCCAP_OEA)) return 0x001; @@ -471,56 +455,7 @@ int ppccom_translate_address(powerpc_state *ppc, int space, int intention, offs_ void ppccom_tlb_fill(powerpc_state *ppc) { - int transuser = (ppc->msr & MSR_PR) ? TRANSLATE_USER_MASK : 0; - offs_t address = ppc->param0; - int transtype = ppc->param1; - offs_t transaddr = address; - UINT32 entryval; - - /* 4xx case: "TLB" really just caches writes and checks compare registers */ - if (ppc->cap & PPCCAP_4XX) - { - /* assume success and direct translation */ - ppc->param0 = 1; - transaddr = address & 0x7fffffff; - - /* we don't support the MMU of the 403GCX */ - if (ppc->flavor == PPC_MODEL_403GCX && (ppc->msr & MSROEA_DR)) - fatalerror("MMU enabled but not supported!"); - - /* only check if PE is enabled */ - if (transtype == TRANSLATE_WRITE && (ppc->msr & MSR4XX_PE)) - { - /* are we within one of the protection ranges? */ - int inrange1 = ((address >> 12) >= (ppc->spr[SPR4XX_PBL1] >> 12) && (address >> 12) < (ppc->spr[SPR4XX_PBU1] >> 12)); - int inrange2 = ((address >> 12) >= (ppc->spr[SPR4XX_PBL2] >> 12) && (address >> 12) < (ppc->spr[SPR4XX_PBU2] >> 12)); - - /* if PX == 1, writes are only allowed OUTSIDE of the bounds */ - if (((ppc->msr & MSR4XX_PX) && (inrange1 || inrange2)) || (!(ppc->msr & MSR4XX_PX) && (!inrange1 && !inrange2))) - ppc->param0 = 2; - } - } - - /* OEA case: perform an address translation */ - else - ppc->param0 = ppccom_translate_address_internal(ppc, transtype | transuser, &transaddr); - - /* log information and return upon failure */ - if (PRINTF_TLB_FILL) - printf("tlb_fill: %08X (%s%s) -> ", address, (transtype == TRANSLATE_READ) ? "R" : (transtype == TRANSLATE_WRITE) ? "W" : "F", transuser ? "U" : "S"); - if (ppc->param0 > 1) - { - if (PRINTF_TLB_FILL) - printf("failed(%08X)\n", ppc->param0); - return; - } - - /* if we did translate the address, get a pointer to our entry in the TLB table and fill it in */ - if (PRINTF_TLB_FILL) - printf("succeeded(%d) -> %08X\n", ppc->param0, transaddr); - entryval = (transaddr & 0xfffff000) | TLB_READ | ((ppc->param0 & 1) ? TLB_WRITE : 0); - if (tlb_entry_allocate(ppc, ppc->tlb_index, address, entryval)) - ppc->tlb_index = (ppc->tlb_index + 1) % POWERPC_TLB_ENTRIES; + vtlb_fill(ppc->vtlb, ppc->param0, ppc->param1); } @@ -531,11 +466,7 @@ void ppccom_tlb_fill(powerpc_state *ppc) void ppccom_tlb_flush(powerpc_state *ppc) { - int entnum; - - /* iterate over entries and invalidate them */ - for (entnum = 0; entnum < POWERPC_TLB_ENTRIES; entnum++) - tlb_entry_free(ppc, entnum); + vtlb_flush_dynamic(ppc->vtlb); } @@ -551,10 +482,7 @@ void ppccom_tlb_flush(powerpc_state *ppc) void ppccom_execute_tlbie(powerpc_state *ppc) { - offs_t address = ppc->param0; - - /* just nuke it in the table; we may have spare entries referencing it, but no harm */ - ppc->tlb_table[address >> 12] = 0; + vtlb_flush_address(ppc->vtlb, ppc->param0); } @@ -565,7 +493,7 @@ void ppccom_execute_tlbie(powerpc_state *ppc) void ppccom_execute_tlbia(powerpc_state *ppc) { - ppccom_tlb_flush(ppc); + vtlb_flush_dynamic(ppc->vtlb); } @@ -578,19 +506,21 @@ void ppccom_execute_tlbl(powerpc_state *ppc) { UINT32 address = ppc->param0; int isitlb = ppc->param1; - UINT32 entrynum, entryval; - + vtlb_entry flags = 0; + int entrynum; + /* determine entry number; we use rand() for associativity */ entrynum = ((address >> 12) & 0x1f) | (mame_rand(Machine) & 0x20) | (isitlb ? 0x40 : 0); - /* invalidate any existing TLB entry here */ - ppc->tlb_table[address >> 12] = 0; + /* determine the flags */ + flags = VTLB_FLAG_VALID | VTLB_READ_ALLOWED | VTLB_FETCH_ALLOWED; + if (ppc->spr[SPR603_RPA] & 0x80) + flags |= VTLB_WRITE_ALLOWED; + if (isitlb) + flags |= VTLB_FETCH_ALLOWED; - /* allocate this entry */ - entryval = (ppc->spr[SPR603_RPA] & 0xfffff000) | TLB_READ | ((ppc->spr[SPR603_RPA] & 0x80) ? TLB_WRITE : 0); - tlb_entry_allocate(ppc, POWERPC_TLB_ENTRIES + entrynum, address, entryval); - if (PRINTF_TLB_FILL) - printf("tlb_load: %08X (%sS) -> %08X\n", address, isitlb ? "F" : "R", ppc->spr[SPR603_RPA] & 0xfffff000); + /* load the entry */ + vtlb_load(ppc->vtlb, entrynum, 1, address, (ppc->spr[SPR603_RPA] & 0xfffff000) | flags); } @@ -1897,8 +1827,8 @@ void ppc4xx_get_info(powerpc_state *ppc, UINT32 state, cpuinfo *info) case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break; case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 31; break; - case CPUINFO_INT_LOGADDR_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 0; break; - case CPUINFO_INT_PAGE_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break; + case CPUINFO_INT_LOGADDR_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break; + case CPUINFO_INT_PAGE_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = POWERPC_MIN_PAGE_SHIFT;break; /* --- the following bits of info are returned as pointers to data or functions --- */ case CPUINFO_PTR_INIT: /* provided per-CPU */ break; diff --git a/src/emu/cpu/powerpc/ppccom.h b/src/emu/cpu/powerpc/ppccom.h index ff61e82c8e1..e825728a93c 100644 --- a/src/emu/cpu/powerpc/ppccom.h +++ b/src/emu/cpu/powerpc/ppccom.h @@ -11,6 +11,7 @@ #include "cpuintrf.h" #include "ppc.h" +#include "cpu/vtlb.h" /*************************************************************************** @@ -39,11 +40,6 @@ #define PPCCAP_603_MMU 0x20 /* TRUE if we have 603-class MMU features */ -/* bits in our internal TLB */ -#define TLB_READ 0x01 /* reads are allowed */ -#define TLB_WRITE 0x02 /* writes are allowed */ - - /* PowerPC flavors */ enum _powerpc_flavor { @@ -531,9 +527,7 @@ struct _powerpc_state UINT32 param1; /* MMU */ - UINT32 * tlb_table; - UINT32 * tlb_entries; - UINT32 tlb_index; + vtlb_state * vtlb; /* architectural distinctions */ powerpc_flavor flavor; @@ -574,7 +568,9 @@ struct _powerpc_state FUNCTION PROTOTYPES ***************************************************************************/ -size_t ppccom_init(powerpc_state *ppc, powerpc_flavor flavor, UINT8 cap, int tb_divisor, int clock, const powerpc_config *config, int (*irqcallback)(int), void *memory); +void ppccom_init(powerpc_state *ppc, powerpc_flavor flavor, UINT8 cap, int tb_divisor, int clock, const powerpc_config *config, int (*irqcallback)(int)); +void ppccom_exit(powerpc_state *ppc); + void ppccom_reset(powerpc_state *ppc); #ifdef ENABLE_DEBUGGER offs_t ppccom_dasm(powerpc_state *ppc, char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram); diff --git a/src/emu/cpu/powerpc/ppcdrc.c b/src/emu/cpu/powerpc/ppcdrc.c index 51597e8e100..6ec4a47680c 100644 --- a/src/emu/cpu/powerpc/ppcdrc.c +++ b/src/emu/cpu/powerpc/ppcdrc.c @@ -199,24 +199,24 @@ struct _ppcimp_state drcuml_codehandle * out_of_cycles; /* out of cycles exception handler */ drcuml_codehandle * tlb_mismatch; /* tlb mismatch handler */ drcuml_codehandle * swap_tgpr; /* swap TGPR handler */ - drcuml_codehandle * lsw[4][32]; /* lsw entries */ - drcuml_codehandle * stsw[4][32]; /* stsw entries */ - drcuml_codehandle * read8[4]; /* read byte */ - drcuml_codehandle * write8[4]; /* write byte */ - drcuml_codehandle * read16[4]; /* read half */ - drcuml_codehandle * read16mask[4]; /* read half */ - drcuml_codehandle * write16[4]; /* write half */ - drcuml_codehandle * write16mask[4]; /* write half */ - drcuml_codehandle * read32[4]; /* read word */ - drcuml_codehandle * read32align[4]; /* read word aligned */ - drcuml_codehandle * read32mask[4]; /* read word */ - drcuml_codehandle * write32[4]; /* write word */ - drcuml_codehandle * write32align[4]; /* write word aligned */ - drcuml_codehandle * write32mask[4]; /* write word */ - drcuml_codehandle * read64[4]; /* read double */ - drcuml_codehandle * read64mask[4]; /* read double */ - drcuml_codehandle * write64[4]; /* write double */ - drcuml_codehandle * write64mask[4]; /* write double */ + drcuml_codehandle * lsw[8][32]; /* lsw entries */ + drcuml_codehandle * stsw[8][32]; /* stsw entries */ + drcuml_codehandle * read8[8]; /* read byte */ + drcuml_codehandle * write8[8]; /* write byte */ + drcuml_codehandle * read16[8]; /* read half */ + drcuml_codehandle * read16mask[8]; /* read half */ + drcuml_codehandle * write16[8]; /* write half */ + drcuml_codehandle * write16mask[8]; /* write half */ + drcuml_codehandle * read32[8]; /* read word */ + drcuml_codehandle * read32align[8]; /* read word aligned */ + drcuml_codehandle * read32mask[8]; /* read word */ + drcuml_codehandle * write32[8]; /* write word */ + drcuml_codehandle * write32align[8]; /* write word aligned */ + drcuml_codehandle * write32mask[8]; /* write word */ + drcuml_codehandle * read64[8]; /* read double */ + drcuml_codehandle * read64mask[8]; /* read double */ + drcuml_codehandle * write64[8]; /* write double */ + drcuml_codehandle * write64mask[8]; /* write double */ drcuml_codehandle * exception[EXCEPTION_COUNT]; /* array of exception handlers */ drcuml_codehandle * exception_norecover[EXCEPTION_COUNT]; /* array of exception handlers */ @@ -545,27 +545,20 @@ static void ppcdrc_init(powerpc_flavor flavor, UINT8 cap, int tb_divisor, int cl }; drcbe_info beinfo; UINT32 flags = 0; - size_t extrasize; drccache *cache; - void *extramem; int regnum; - /* determine how much memory beyond the core size we need */ - extrasize = ppccom_init(NULL, flavor, cap, tb_divisor, clock, config, irqcallback, NULL); - /* allocate enough space for the cache and the core */ - cache = drccache_alloc(CACHE_SIZE + sizeof(*ppc) + extrasize); + cache = drccache_alloc(CACHE_SIZE + sizeof(*ppc)); if (cache == NULL) - fatalerror("Unable to allocate cache of size %d", (UINT32)(CACHE_SIZE + sizeof(*ppc) + extrasize)); + fatalerror("Unable to allocate cache of size %d", (UINT32)(CACHE_SIZE + sizeof(*ppc))); - /* allocate the core from the near cache, and the extra memory from the full cache */ + /* allocate the core from the near cache */ ppc = drccache_memory_alloc_near(cache, sizeof(*ppc)); memset(ppc, 0, sizeof(*ppc)); - extramem = drccache_memory_alloc(cache, extrasize); - memset(extramem, 0, extrasize); /* initialize the core */ - ppccom_init(ppc, flavor, cap, tb_divisor, clock, config, irqcallback, extramem); + ppccom_init(ppc, flavor, cap, tb_divisor, clock, config, irqcallback); /* allocate the implementation-specific state from the full cache */ ppc->impstate = drccache_memory_alloc_near(cache, sizeof(*ppc->impstate)); @@ -729,6 +722,8 @@ static int ppcdrc_execute(int cycles) static void ppcdrc_exit(void) { + ppccom_exit(ppc); + /* clean up the DRC */ drcfe_exit(ppc->impstate->drcfe); drcuml_free(ppc->impstate->drcuml); @@ -897,7 +892,7 @@ static void code_flush_cache(drcuml_state *drcuml) } /* add subroutines for memory accesses */ - for (mode = 0; mode < 4; mode++) + for (mode = 0; mode < 8; mode++) { static_generate_memory_accessor(drcuml, mode, 1, FALSE, FALSE, "read8", &ppc->impstate->read8[mode], NULL); static_generate_memory_accessor(drcuml, mode, 1, TRUE, FALSE, "write8", &ppc->impstate->write8[mode], NULL); @@ -1232,8 +1227,10 @@ static void static_generate_tlb_mismatch(drcuml_state *drcuml) UML_MOV(block, MEM(&ppc->param0), IREG(0)); // mov [param0],i0 UML_MOV(block, MEM(&ppc->param1), IMM(TRANSLATE_FETCH)); // mov [param1],TRANSLATE_FETCH UML_CALLC(block, ppccom_tlb_fill, ppc); // callc tlbfill,ppc - UML_CMP(block, MEM(&ppc->param0), IMM(1)); // cmp [param0],1 - UML_JMPc(block, IF_A, isi = label++); // jmp isi,A + UML_SHR(block, IREG(1), IREG(0), IMM(12)); // shr i1,i0,11 + UML_LOAD(block, IREG(1), (void *)vtlb_table(ppc->vtlb), IREG(1), DWORD); // load i1,[vtlb],i1,dword + UML_TEST(block, IREG(1), IMM(VTLB_FETCH_ALLOWED)); // test i1,VTLB_FETCH_ALLOWED + UML_JMPc(block, IF_Z, isi = label++); // jmp isi,z UML_MOV(block, MEM(&ppc->pc), IREG(0)); // mov <pc>,i0 save_fast_iregs(block); // <save fastregs> UML_EXIT(block, IMM(EXECUTE_MISSING_CODE)); // exit EXECUTE_MISSING_CODE @@ -1447,12 +1444,18 @@ static void static_generate_memory_accessor(drcuml_state *drcuml, int mode, int int fastxor = BYTE8_XOR_BE(0) >> (activecpu_databus_width(ADDRESS_SPACE_PROGRAM) < 64); drcuml_block *block; jmp_buf errorbuf; + int translate_type; int tlbreturn = 0; int unaligned = 0; int alignex = 0; int tlbmiss = 0; int label = 1; int ramnum; + + if (mode & MODE_USER) + translate_type = iswrite ? TRANSLATE_WRITE_USER : TRANSLATE_READ_USER; + else + translate_type = iswrite ? TRANSLATE_WRITE : TRANSLATE_READ; /* if we get an error back, we're screwed */ if (setjmp(errorbuf) != 0) @@ -1498,8 +1501,8 @@ static void static_generate_memory_accessor(drcuml_state *drcuml, int mode, int if (((ppc->cap & PPCCAP_OEA) && (mode & MODE_DATA_TRANSLATION)) || (iswrite && (ppc->cap & PPCCAP_4XX) && (mode & MODE_PROTECTION))) { UML_SHR(block, IREG(3), IREG(0), IMM(12)); // shr i3,i0,12 - UML_LOAD(block, IREG(3), ppc->tlb_table, IREG(3), DWORD); // load i3,[tlb_table],i3,dword - UML_TEST(block, IREG(3), IMM(iswrite ? TLB_WRITE : TLB_READ)); // test i3,iswrite ? TLB_WRITE : TLB_READ + UML_LOAD(block, IREG(3), (void *)vtlb_table(ppc->vtlb), IREG(3), DWORD); // load i3,[vtlb],i3,dword + UML_TEST(block, IREG(3), IMM((UINT64)1 << translate_type)); // test i3,1 << translate_type UML_JMPc(block, IF_Z, tlbmiss = label++); // jmp tlbmiss,z UML_LABEL(block, tlbreturn = label++); // tlbreturn: UML_ROLINS(block, IREG(0), IREG(3), IMM(0), IMM(0xfffff000)); // rolins i0,i3,0,0xfffff000 @@ -1786,18 +1789,14 @@ static void static_generate_memory_accessor(drcuml_state *drcuml, int mode, int /* handle a TLB miss */ if (tlbmiss != 0) { - int dsi; - UML_LABEL(block, tlbmiss); // tlbmiss: UML_MOV(block, MEM(&ppc->param0), IREG(0)); // mov [param0],i0 - UML_MOV(block, MEM(&ppc->param1), IMM(iswrite ? TRANSLATE_WRITE : TRANSLATE_READ)); // mov [param1],TRANSLATE_READ/WRITE + UML_MOV(block, MEM(&ppc->param1), IMM(translate_type)); // mov [param1],translate_type UML_CALLC(block, ppccom_tlb_fill, ppc); // callc tlbfill,ppc - UML_CMP(block, MEM(&ppc->param0), IMM(1)); // cmp [param0],1 - UML_JMPc(block, IF_A, dsi = label++); // jmp dsi,A UML_SHR(block, IREG(3), IREG(0), IMM(12)); // shr i3,i0,12 - UML_LOAD(block, IREG(3), ppc->tlb_table, IREG(3), DWORD); // load i3,[tlb_table],i3,dword - UML_JMP(block, tlbreturn); // jmp tlbreturn - UML_LABEL(block, dsi); // dsi: + UML_LOAD(block, IREG(3), (void *)vtlb_table(ppc->vtlb), IREG(3), DWORD); // load i3,[vtlb],i3,dword + UML_TEST(block, IREG(3), IMM((UINT64)1 << translate_type)); // test i3,1 << translate_type + UML_JMPc(block, IF_NZ, tlbreturn); // jmp tlbreturn,nz /* 4XX case: protection exception */ if (ppc->cap & PPCCAP_4XX) @@ -2166,16 +2165,18 @@ static void generate_sequence_instruction(drcuml_block *block, compiler_state *c /* validate our TLB entry at this PC; if we fail, we need to handle it */ if ((desc->flags & OPFLAG_VALIDATE_TLB) && (ppc->impstate->mode & MODE_DATA_TRANSLATION)) { + const vtlb_entry *tlbtable = vtlb_table(ppc->vtlb); + /* if we currently have a valid TLB read entry, we just verify */ - if (ppc->tlb_table[desc->pc >> 12] != 0) + if (tlbtable[desc->pc >> 12] != 0) { if (PRINTF_MMU) { UML_MOV(block, MEM(&ppc->impstate->arg0), IMM(desc->pc)); // mov [arg0],desc->pc UML_CALLC(block, cfunc_printf_debug, "Checking TLB at @ %08X\n"); // callc printf_debug } - UML_LOAD(block, IREG(0), &ppc->tlb_table[desc->pc >> 12], IMM(0), DWORD); // load i0,tlb_table[desc->pc >> 12],dword - UML_CMP(block, IREG(0), IMM(ppc->tlb_table[desc->pc >> 12])); // cmp i0,*tlbentry + UML_LOAD(block, IREG(0), &tlbtable[desc->pc >> 12], IMM(0), DWORD); // load i0,tlbtable[desc->pc >> 12],dword + UML_CMP(block, IREG(0), IMM(tlbtable[desc->pc >> 12])); // cmp i0,*tlbentry UML_EXHc(block, IF_NE, ppc->impstate->tlb_mismatch, IMM(0)); // exh tlb_mismatch,0,NE } @@ -2184,20 +2185,20 @@ static void generate_sequence_instruction(drcuml_block *block, compiler_state *c { if (PRINTF_MMU) { - UML_MOV(block, MEM(&ppc->impstate->arg0), IMM(desc->pc)); // mov [arg0],desc->pc + UML_MOV(block, MEM(&ppc->impstate->arg0), IMM(desc->pc)); // mov [arg0],desc->pc UML_CALLC(block, cfunc_printf_debug, "No valid TLB @ %08X\n"); // callc printf_debug } - UML_EXH(block, ppc->impstate->tlb_mismatch, IMM(0)); // exh tlb_mismatch,0 + UML_EXH(block, ppc->impstate->tlb_mismatch, IMM(0)); // exh tlb_mismatch,0 } } /* if this is an invalid opcode, generate the exception now */ if (desc->flags & OPFLAG_INVALID_OPCODE) - UML_EXH(block, ppc->impstate->exception[EXCEPTION_PROGRAM], IMM(0x80000)); // exh exception_program,0x80000 + UML_EXH(block, ppc->impstate->exception[EXCEPTION_PROGRAM], IMM(0x80000)); // exh exception_program,0x80000 /* if this is a privileged opcode in user mode, generate the exception */ else if ((desc->flags & OPFLAG_PRIVILEGED) && (ppc->impstate->mode & MODE_USER)) - UML_EXH(block, ppc->impstate->exception[EXCEPTION_PROGRAM], IMM(0x40000)); // exh exception_program,0x40000 + UML_EXH(block, ppc->impstate->exception[EXCEPTION_PROGRAM], IMM(0x40000)); // exh exception_program,0x40000 /* otherwise, unless this is a virtual no-op, it's a regular instruction */ else if (!(desc->flags & OPFLAG_VIRTUAL_NOOP)) @@ -2205,7 +2206,7 @@ static void generate_sequence_instruction(drcuml_block *block, compiler_state *c /* compile the instruction */ if (!generate_opcode(block, compiler, desc)) { - UML_MOV(block, MEM(&ppc->pc), IMM(desc->pc)); // mov [pc],desc->pc + UML_MOV(block, MEM(&ppc->pc), IMM(desc->pc)); // mov [pc],desc->pc UML_CALLC(block, cfunc_unimplemented, (void *)(FPTR)*desc->opptr.l); // callc cfunc_unimplemented } } @@ -2493,7 +2494,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x22: /* LBZ */ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op) - UML_CALLH(block, ppc->impstate->read8[ppc->impstate->mode & 3]); // callh read8 + UML_CALLH(block, ppc->impstate->read8[ppc->impstate->mode]); // callh read8 UML_AND(block, R32(G_RD(op)), IREG(0), IMM(0xff)); // and rd,i0,0xff generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -2501,7 +2502,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x28: /* LHZ */ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op) - UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode & 3]); // callh read16 + UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode]); // callh read16 UML_AND(block, R32(G_RD(op)), IREG(0), IMM(0xffff)); // and rd,i0,0xffff generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -2509,7 +2510,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x2a: /* LHA */ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op) - UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode & 3]); // callh read16 + UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode]); // callh read16 UML_SEXT(block, R32(G_RD(op)), IREG(0), WORD); // sext rd,i0,word generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -2517,7 +2518,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x20: /* LWZ */ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op) - UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode & 3]); // callh read32 + UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode]); // callh read32 UML_MOV(block, R32(G_RD(op)), IREG(0)); // mov rd,i0 generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -2526,7 +2527,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_ADD(block, IREG(0), R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op) - UML_CALLH(block, ppc->impstate->read8[ppc->impstate->mode & 3]); // callh read8 + UML_CALLH(block, ppc->impstate->read8[ppc->impstate->mode]); // callh read8 UML_AND(block, R32(G_RD(op)), IREG(0), IMM(0xff)); // and rd,i0,0xff UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> @@ -2536,7 +2537,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_ADD(block, IREG(0), R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op) - UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode & 3]); // callh read16 + UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode]); // callh read16 UML_AND(block, R32(G_RD(op)), IREG(0), IMM(0xffff)); // and rd,i0,0xffff UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> @@ -2546,7 +2547,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_ADD(block, IREG(0), R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op) - UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode & 3]); // callh read16 + UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode]); // callh read16 UML_SEXT(block, R32(G_RD(op)), IREG(0), WORD); // sext rd,i0,word UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> @@ -2556,7 +2557,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_ADD(block, IREG(0), R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op) - UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode & 3]); // callh read32 + UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode]); // callh read32 UML_MOV(block, R32(G_RD(op)), IREG(0)); // mov rd,i0 UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> @@ -2566,7 +2567,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm UML_AND(block, IREG(1), R32(G_RS(op)), IMM(0xff)); // and i1,rs,0xff UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op) - UML_CALLH(block, ppc->impstate->write8[ppc->impstate->mode & 3]); // callh write8 + UML_CALLH(block, ppc->impstate->write8[ppc->impstate->mode]); // callh write8 generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -2574,7 +2575,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm UML_AND(block, IREG(1), R32(G_RS(op)), IMM(0xffff)); // and i1,rs,0xffff UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op) - UML_CALLH(block, ppc->impstate->write16[ppc->impstate->mode & 3]); // callh write16 + UML_CALLH(block, ppc->impstate->write16[ppc->impstate->mode]); // callh write16 generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -2582,7 +2583,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm UML_MOV(block, IREG(1), R32(G_RS(op))); // mov i1,rs UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op) - UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32 + UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode]); // callh write32 generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -2591,7 +2592,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_AND(block, IREG(1), R32(G_RS(op)), IMM(0xff)); // and i1,rs,0xff UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op) - UML_CALLH(block, ppc->impstate->write8[ppc->impstate->mode & 3]); // callh write8 + UML_CALLH(block, ppc->impstate->write8[ppc->impstate->mode]); // callh write8 UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -2601,7 +2602,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_AND(block, IREG(1), R32(G_RS(op)), IMM(0xffff)); // and i1,rs,0xffff UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op) - UML_CALLH(block, ppc->impstate->write16[ppc->impstate->mode & 3]); // callh write16 + UML_CALLH(block, ppc->impstate->write16[ppc->impstate->mode]); // callh write16 UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -2611,7 +2612,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_MOV(block, IREG(1), R32(G_RS(op))); // mov i1,rs UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op) - UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32 + UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode]); // callh write32 UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -2623,7 +2624,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const { UML_ADD(block, IREG(0), MEM(&ppc->impstate->tempaddr), IMM((INT16)G_SIMM(op) + 4 * (regnum - G_RD(op)))); // add i0,[tempaddr],simm + 4*(regnum-rd) - UML_CALLH(block, ppc->impstate->read32align[ppc->impstate->mode & 3]); // callh read32align + UML_CALLH(block, ppc->impstate->read32align[ppc->impstate->mode]); // callh read32align UML_MOV(block, R32(regnum), IREG(0)); // mov regnum,i0 } generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> @@ -2637,7 +2638,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_ADD(block, IREG(0), MEM(&ppc->impstate->tempaddr), IMM((INT16)G_SIMM(op) + 4 * (regnum - G_RS(op)))); // add i0,[tempaddr],simm + 4*(regnum-rs) UML_MOV(block, IREG(1), R32(regnum)); // mov i1,regnum - UML_CALLH(block, ppc->impstate->write32align[ppc->impstate->mode & 3]); // callh write32align + UML_CALLH(block, ppc->impstate->write32align[ppc->impstate->mode]); // callh write32align } generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -2645,7 +2646,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x30: /* LFS */ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op) - UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode & 3]); // callh read32 + UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode]); // callh read32 UML_MOV(block, MEM(&ppc->impstate->tempdata.w.l), IREG(0)); // mov [tempdata],i0 UML_FDFRFLT(block, F64(G_RD(op)), MEM(&ppc->impstate->tempdata.w.l), DWORD); // fdfrflt fd,[tempdata],dword generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> @@ -2654,7 +2655,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const case 0x32: /* LFD */ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op) - UML_CALLH(block, ppc->impstate->read64[ppc->impstate->mode & 3]); // callh read64 + UML_CALLH(block, ppc->impstate->read64[ppc->impstate->mode]); // callh read64 UML_DMOV(block, MEM(&ppc->impstate->tempdata.d), IREG(0)); // dmov [tempdata],i0 UML_FDMOV(block, F64(G_RD(op)), MEM(&ppc->impstate->tempdata.d)); // fdmov fd,[tempdata] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> @@ -2664,7 +2665,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_ADD(block, IREG(0), R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op) - UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode & 3]); // callh read32 + UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode]); // callh read32 UML_MOV(block, MEM(&ppc->impstate->tempdata.w.l), IREG(0)); // mov [tempdata],i0 UML_FDFRFLT(block, F64(G_RD(op)), MEM(&ppc->impstate->tempdata.w.l), DWORD); // fdfrflt fd,[tempdata],dword UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] @@ -2675,7 +2676,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_ADD(block, IREG(0), R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op) - UML_CALLH(block, ppc->impstate->read64[ppc->impstate->mode & 3]); // callh read64 + UML_CALLH(block, ppc->impstate->read64[ppc->impstate->mode]); // callh read64 UML_DMOV(block, MEM(&ppc->impstate->tempdata.d), IREG(0)); // dmov [tempdata],i0 UML_FDMOV(block, F64(G_RD(op)), MEM(&ppc->impstate->tempdata.d)); // fdmov fd,[tempdata] UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] @@ -2687,7 +2688,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_FSFRFLT(block, MEM(&ppc->impstate->tempdata.w.l), F64(G_RS(op)), QWORD); // fsfrflt [tempdata],rs,qword UML_MOV(block, IREG(1), MEM(&ppc->impstate->tempdata.w.l)); // mov i1,[tempdata] UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op) - UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32 + UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode]); // callh write32 generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -2696,7 +2697,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_FDMOV(block, MEM(&ppc->impstate->tempdata.d), F64(G_RS(op))); // fdmov [tempdata],rs UML_DMOV(block, IREG(1), MEM(&ppc->impstate->tempdata.d)); // dmov i1,[tempdata] UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op) - UML_CALLH(block, ppc->impstate->write64[ppc->impstate->mode & 3]); // callh write64 + UML_CALLH(block, ppc->impstate->write64[ppc->impstate->mode]); // callh write64 generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -2706,7 +2707,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_MOV(block, IREG(1), MEM(&ppc->impstate->tempdata.w.l)); // mov i1,[tempdata] UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op) - UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32 + UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode]); // callh write32 UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -2717,7 +2718,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const UML_DMOV(block, IREG(1), MEM(&ppc->impstate->tempdata.d)); // dmov i1,[tempdata] UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op) - UML_CALLH(block, ppc->impstate->write64[ppc->impstate->mode & 3]); // callh write64 + UML_CALLH(block, ppc->impstate->write64[ppc->impstate->mode]); // callh write64 UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3169,7 +3170,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler case 0x057: /* LBZX */ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->read8[ppc->impstate->mode & 3]); // callh read8 + UML_CALLH(block, ppc->impstate->read8[ppc->impstate->mode]); // callh read8 UML_AND(block, R32(G_RD(op)), IREG(0), IMM(0xff)); // and rd,i0,0xff generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3177,7 +3178,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler case 0x117: /* LHZX */ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode & 3]); // callh read16 + UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode]); // callh read16 UML_AND(block, R32(G_RD(op)), IREG(0), IMM(0xffff)); // and rd,i0,0xffff generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3185,7 +3186,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler case 0x157: /* LHAX */ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode & 3]); // callh read16 + UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode]); // callh read16 UML_SEXT(block, R32(G_RD(op)), IREG(0), WORD); // sext rd,i0,word generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3193,7 +3194,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler case 0x017: /* LWZX */ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode & 3]); // callh read32 + UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode]); // callh read32 UML_MOV(block, R32(G_RD(op)), IREG(0)); // mov rd,i0 generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3201,7 +3202,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler case 0x217: /* LFSX */ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode & 3]); // callh read32 + UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode]); // callh read32 UML_MOV(block, MEM(&ppc->impstate->tempdata.w.l), IREG(0)); // mov [tempdata],i0 UML_FDFRFLT(block, F64(G_RD(op)), MEM(&ppc->impstate->tempdata.w.l), DWORD); // fdfrflt fd,[tempdata],dword generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> @@ -3210,7 +3211,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler case 0x257: /* LFDX */ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->read64[ppc->impstate->mode & 3]); // callh read64 + UML_CALLH(block, ppc->impstate->read64[ppc->impstate->mode]); // callh read64 UML_DMOV(block, MEM(&ppc->impstate->tempdata.d), IREG(0)); // dmov [tempdata],i0 UML_FDMOV(block, F64(G_RD(op)), MEM(&ppc->impstate->tempdata.d)); // fdmov fd,[tempdata] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> @@ -3219,7 +3220,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler case 0x316: /* LHBRX */ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode & 3]); // callh read16 + UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode]); // callh read16 UML_BSWAP(block, IREG(0), IREG(0)); // bswap i0,i0 UML_SHR(block, R32(G_RD(op)), IREG(0), IMM(16)); // shr rd,i0,16 generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> @@ -3228,7 +3229,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler case 0x216: /* LWBRX */ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->read32align[ppc->impstate->mode & 3]); // callh read32align + UML_CALLH(block, ppc->impstate->read32align[ppc->impstate->mode]); // callh read32align UML_BSWAP(block, R32(G_RD(op)), IREG(0)); // bswap rd,i0 generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3237,7 +3238,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_ADD(block, IREG(0), R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDXU(op)); // mapvar dsisr,DSISR_IDXU(op) - UML_CALLH(block, ppc->impstate->read8[ppc->impstate->mode & 3]); // callh read8 + UML_CALLH(block, ppc->impstate->read8[ppc->impstate->mode]); // callh read8 UML_AND(block, R32(G_RD(op)), IREG(0), IMM(0xff)); // and rd,i0,0xff UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> @@ -3247,7 +3248,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_ADD(block, IREG(0), R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDXU(op)); // mapvar dsisr,DSISR_IDXU(op) - UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode & 3]); // callh read16 + UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode]); // callh read16 UML_AND(block, R32(G_RD(op)), IREG(0), IMM(0xffff)); // and rd,i0,0xffff UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> @@ -3257,7 +3258,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_ADD(block, IREG(0), R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDXU(op)); // mapvar dsisr,DSISR_IDXU(op) - UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode & 3]); // callh read16 + UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode]); // callh read16 UML_SEXT(block, R32(G_RD(op)), IREG(0), WORD); // sext rd,i0,word UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> @@ -3267,7 +3268,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_ADD(block, IREG(0), R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDXU(op)); // mapvar dsisr,DSISR_IDXU(op) - UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode & 3]); // callh read32 + UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode]); // callh read32 UML_MOV(block, R32(G_RD(op)), IREG(0)); // mov rd,i0 UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> @@ -3277,7 +3278,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_ADD(block, IREG(0), R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode & 3]); // callh read32 + UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode]); // callh read32 UML_MOV(block, MEM(&ppc->impstate->tempdata.w.l), IREG(0)); // mov [tempdata],i0 UML_FDFRFLT(block, F64(G_RD(op)), MEM(&ppc->impstate->tempdata.w.l), DWORD); // fdfrflt fd,[tempdata],dword UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] @@ -3288,7 +3289,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_ADD(block, IREG(0), R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->read64[ppc->impstate->mode & 3]); // callh read64 + UML_CALLH(block, ppc->impstate->read64[ppc->impstate->mode]); // callh read64 UML_DMOV(block, MEM(&ppc->impstate->tempdata.d), IREG(0)); // dmov [tempdata],i0 UML_FDMOV(block, F64(G_RD(op)), MEM(&ppc->impstate->tempdata.d)); // fdmov fd,[tempdata] UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] @@ -3298,7 +3299,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler case 0x014: /* LWARX */ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->read32align[ppc->impstate->mode & 3]); // callh read32align + UML_CALLH(block, ppc->impstate->read32align[ppc->impstate->mode]); // callh read32align UML_MOV(block, R32(G_RD(op)), IREG(0)); // mov rd,i0 generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3306,7 +3307,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler case 0x255: /* LSWI */ UML_MOV(block, MEM(&ppc->impstate->updateaddr), R32Z(G_RA(op))); // mov [updateaddr],ra UML_MOV(block, MEM(&ppc->impstate->swcount), IMM(((G_NB(op) - 1) & 0x1f) + 1)); // mov [swcount],G_NB - UML_CALLH(block, ppc->impstate->lsw[ppc->impstate->mode & 3][G_RD(op)]); // call lsw[rd] + UML_CALLH(block, ppc->impstate->lsw[ppc->impstate->mode][G_RD(op)]); // call lsw[rd] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3314,7 +3315,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_ADD(block, MEM(&ppc->impstate->updateaddr), R32Z(G_RA(op)), R32(G_RB(op))); // add [updateaddr],ra,rb UML_AND(block, MEM(&ppc->impstate->swcount), SPR32(SPR_XER), IMM(0x7f)); // and [swcount],[xer],0x7f UML_SUB(block, MEM(&ppc->icount), MEM(&ppc->icount), MEM(&ppc->impstate->swcount));// sub icount,icount,[swcount] - UML_CALLHc(block, IF_NZ, ppc->impstate->lsw[ppc->impstate->mode & 3][G_RD(op)]);// call lsw[rd],nz + UML_CALLHc(block, IF_NZ, ppc->impstate->lsw[ppc->impstate->mode][G_RD(op)]);// call lsw[rd],nz generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3326,7 +3327,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_AND(block, IREG(1), R32(G_RS(op)), IMM(0xff)); // and i1,rs,0xff UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->write8[ppc->impstate->mode & 3]); // callh write8 + UML_CALLH(block, ppc->impstate->write8[ppc->impstate->mode]); // callh write8 generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3334,7 +3335,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_AND(block, IREG(1), R32(G_RS(op)), IMM(0xffff)); // and i1,rs UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->write16[ppc->impstate->mode & 3]); // callh write16 + UML_CALLH(block, ppc->impstate->write16[ppc->impstate->mode]); // callh write16 generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3342,7 +3343,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_MOV(block, IREG(1), R32(G_RS(op))); // mov i1,rs UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32 + UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode]); // callh write32 generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3351,7 +3352,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_FSFRFLT(block, MEM(&ppc->impstate->tempdata.w.l), F64(G_RS(op)), QWORD); // fsfrflt [tempdata],rs,qword UML_MOV(block, IREG(1), MEM(&ppc->impstate->tempdata.w.l)); // mov i1,[tempdata] UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32 + UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode]); // callh write32 generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3360,7 +3361,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_FDMOV(block, MEM(&ppc->impstate->tempdata.d), F64(G_RS(op))); // fdmov [tempdata],rs UML_MOV(block, IREG(1), MEM(&ppc->impstate->tempdata.w.l)); // mov i1,[tempdata.lo] UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32 + UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode]); // callh write32 generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3369,7 +3370,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_FDMOV(block, MEM(&ppc->impstate->tempdata.d), F64(G_RS(op))); // fdmov [tempdata],rs UML_DMOV(block, IREG(1), MEM(&ppc->impstate->tempdata.d)); // dmov i1,[tempdata] UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->write64[ppc->impstate->mode & 3]); // callh write64 + UML_CALLH(block, ppc->impstate->write64[ppc->impstate->mode]); // callh write64 generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3378,7 +3379,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_BSWAP(block, IREG(1), R32(G_RS(op))); // bswap i1,rs UML_SHR(block, IREG(1), IREG(1), IMM(16)); // shr i1,i1,16 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->write16[ppc->impstate->mode & 3]); // callh write16 + UML_CALLH(block, ppc->impstate->write16[ppc->impstate->mode]); // callh write16 generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3386,7 +3387,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_BSWAP(block, IREG(1), R32(G_RS(op))); // bswap i1,rs UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32 + UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode]); // callh write32 generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3395,7 +3396,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_AND(block, IREG(1), R32(G_RS(op)), IMM(0xff)); // and i1,rs,0xff UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->write8[ppc->impstate->mode & 3]); // callh write8 + UML_CALLH(block, ppc->impstate->write8[ppc->impstate->mode]); // callh write8 UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3405,7 +3406,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_AND(block, IREG(1), R32(G_RS(op)), IMM(0xffff)); // and i1,rs,0xffff UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->write16[ppc->impstate->mode & 3]); // callh write16 + UML_CALLH(block, ppc->impstate->write16[ppc->impstate->mode]); // callh write16 UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3415,7 +3416,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_MOV(block, IREG(1), R32(G_RS(op))); // mov i1,rs UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDXU(op)); // mapvar dsisr,DSISR_IDXU(op) - UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32 + UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode]); // callh write32 UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3426,7 +3427,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_MOV(block, IREG(1), MEM(&ppc->impstate->tempdata.w.l)); // mov i1,[tempdata] UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32 + UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode]); // callh write32 UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3437,7 +3438,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_DMOV(block, IREG(1), MEM(&ppc->impstate->tempdata.d)); // dmov i1,[tempdata] UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0 UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->write64[ppc->impstate->mode & 3]); // callh write64 + UML_CALLH(block, ppc->impstate->write64[ppc->impstate->mode]); // callh write64 UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3446,7 +3447,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb UML_MOV(block, IREG(1), R32(G_RS(op))); // mov i1,rs UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op) - UML_CALLH(block, ppc->impstate->write32align[ppc->impstate->mode & 3]); // callh write32align + UML_CALLH(block, ppc->impstate->write32align[ppc->impstate->mode]); // callh write32align generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> UML_CMP(block, IREG(0), IREG(0)); // cmp i0,i0 generate_compute_flags(block, desc, TRUE, 0, FALSE); // <update flags> @@ -3455,7 +3456,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler case 0x2d5: /* STSWI */ UML_MOV(block, MEM(&ppc->impstate->updateaddr), R32Z(G_RA(op))); // mov [updateaddr],ra UML_MOV(block, MEM(&ppc->impstate->swcount), IMM(((G_NB(op) - 1) & 0x1f) + 1)); // mov [swcount],G_NB - UML_CALLH(block, ppc->impstate->stsw[ppc->impstate->mode & 3][G_RD(op)]); // call stsw[rd] + UML_CALLH(block, ppc->impstate->stsw[ppc->impstate->mode][G_RD(op)]); // call stsw[rd] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3463,7 +3464,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler UML_ADD(block, MEM(&ppc->impstate->updateaddr), R32Z(G_RA(op)), R32(G_RB(op))); // add [updateaddr],ra,rb UML_AND(block, MEM(&ppc->impstate->swcount), SPR32(SPR_XER), IMM(0x7f)); // and [swcount],[xer],0x7f UML_SUB(block, MEM(&ppc->icount), MEM(&ppc->icount), MEM(&ppc->impstate->swcount));// sub icount,icount,[swcount] - UML_CALLHc(block, IF_NZ, ppc->impstate->stsw[ppc->impstate->mode & 3][G_RD(op)]);// call stsw[rd] + UML_CALLHc(block, IF_NZ, ppc->impstate->stsw[ppc->impstate->mode][G_RD(op)]);// call stsw[rd] generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles> return TRUE; @@ -3491,7 +3492,7 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler { UML_ADD(block, IREG(0), MEM(&ppc->impstate->tempaddr), IMM(8 * item)); // add i0,[tempaddr],8*item UML_DMOV(block, IREG(1), IMM(0)); // dmov i1,0 - UML_CALLH(block, ppc->impstate->write64[ppc->impstate->mode & 3]); // callh write64 + UML_CALLH(block, ppc->impstate->write64[ppc->impstate->mode]); // callh write64 } return TRUE; diff --git a/src/emu/cpu/vtlb.c b/src/emu/cpu/vtlb.c new file mode 100644 index 00000000000..932b3b4c5a5 --- /dev/null +++ b/src/emu/cpu/vtlb.c @@ -0,0 +1,284 @@ +/*************************************************************************** + + vtlb.c + + Generic virtual TLB implementation. + + Copyright Aaron Giles + Released for general non-commercial use under the MAME license + Visit http://mamedev.org for licensing and usage restrictions. + +***************************************************************************/ + +#include "vtlb.h" + + + +/*************************************************************************** + DEBUGGING +***************************************************************************/ + +#define PRINTF_TLB (0) + + + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +/* VTLB state */ +struct _vtlb_state +{ + int space; /* address space */ + int dynamic; /* number of dynamic entries */ + int fixed; /* number of fixed entries */ + int dynindex; /* index of next dynamic entry */ + int pageshift; /* bits to shift to get page index */ + int addrwidth; /* logical address bus width */ + offs_t * live; /* array of live entries by table index */ + int * fixedpages; /* number of pages each fixed entry covers */ + vtlb_entry * table; /* table of entries by address */ + cpu_translate_func translate; /* translate function */ +}; + + + +/*************************************************************************** + INITIALIZATION/TEARDOWN +***************************************************************************/ + +/*------------------------------------------------- + vtlb_alloc - allocate a new VTLB for the + given CPU +-------------------------------------------------*/ + +vtlb_state *vtlb_alloc(int cpunum, int space, int fixed_entries, int dynamic_entries) +{ + vtlb_state *vtlb; + + /* allocate memory for the core structure */ + vtlb = malloc_or_die(sizeof(*vtlb)); + memset(vtlb, 0, sizeof(*vtlb)); + + /* fill in CPU information */ + vtlb->space = space; + vtlb->dynamic = dynamic_entries; + vtlb->fixed = fixed_entries; + vtlb->pageshift = cpunum_page_shift(cpunum, space); + vtlb->addrwidth = cpunum_logaddr_width(cpunum, space); + vtlb->translate = (cpu_translate_func)cpunum_get_info_fct(cpunum, CPUINFO_PTR_TRANSLATE); + + /* validate CPU information */ + assert((1 << vtlb->pageshift) > VTLB_FLAGS_MASK); + assert(vtlb->translate != NULL); + assert(vtlb->addrwidth > vtlb->pageshift); + + /* allocate the entry array */ + vtlb->live = malloc_or_die(sizeof(vtlb->live[0]) * (fixed_entries + dynamic_entries)); + memset(vtlb->live, 0, sizeof(vtlb->live[0]) * (fixed_entries + dynamic_entries)); + + /* allocate the lookup table */ + vtlb->table = malloc_or_die(sizeof(vtlb->table[0]) << (vtlb->addrwidth - vtlb->pageshift)); + memset(vtlb->table, 0, sizeof(vtlb->table[0]) << (vtlb->addrwidth - vtlb->pageshift)); + + /* allocate the fixed page count array */ + if (fixed_entries > 0) + { + vtlb->fixedpages = malloc_or_die(sizeof(vtlb->fixedpages[0]) * fixed_entries); + memset(vtlb->fixedpages, 0, sizeof(vtlb->fixedpages[0]) * fixed_entries); + } + + return vtlb; +} + + +/*------------------------------------------------- + vtlb_free - free an allocated VTLB +-------------------------------------------------*/ + +void vtlb_free(vtlb_state *vtlb) +{ + /* free the fixed pages if allocated */ + if (vtlb->fixedpages != NULL) + free(vtlb->fixedpages); + + /* free the table and array if they exist */ + if (vtlb->live != NULL) + free(vtlb->live); + if (vtlb->table != NULL) + free(vtlb->table); + + /* and then the VTLB object itself */ + free(vtlb); +} + + + +/*************************************************************************** + FILLING +***************************************************************************/ + +/*------------------------------------------------- + vtlb_fill - rcalled by the CPU core in + response to an unmapped access +-------------------------------------------------*/ + +int vtlb_fill(vtlb_state *vtlb, offs_t address, int intention) +{ + offs_t tableindex = address >> vtlb->pageshift; + vtlb_entry entry = vtlb->table[tableindex]; + offs_t taddress; + + if (PRINTF_TLB) + printf("vtlb_fill: %08X(%X) ... ", address, intention); + + /* should not be called here if the entry is in the table already */ +// assert((entry & (1 << intention)) == 0); + + /* if we have no dynamic entries, we always fail */ + if (vtlb->dynamic == 0) + { + if (PRINTF_TLB) + printf("failed: no dynamic entries\n"); + return FALSE; + } + + /* ask the CPU core to translate for us */ + taddress = address; + if (!(*vtlb->translate)(vtlb->space, intention, &taddress)) + { + if (PRINTF_TLB) + printf("failed: no translation\n"); + return FALSE; + } + + /* if this is the first successful translation for this address, allocate a new entry */ + if ((entry & VTLB_FLAGS_MASK) == 0) + { + int liveindex = vtlb->dynindex++ % vtlb->dynamic; + + /* if an entry already exists at this index, free it */ + if (vtlb->live[liveindex] != 0) + vtlb->table[vtlb->live[liveindex] - 1] = 0; + + /* claim this new entry */ + vtlb->live[liveindex] = tableindex + 1; + + /* form a new blank entry */ + entry = (taddress >> vtlb->pageshift) << vtlb->pageshift; + entry |= VTLB_FLAG_VALID; + + if (PRINTF_TLB) + printf("success (%08X), new entry\n", taddress); + } + + /* otherwise, ensure that different intentions do not produce different addresses */ + else + { + assert((entry >> vtlb->pageshift) == (taddress >> vtlb->pageshift)); + assert(entry & VTLB_FLAG_VALID); + + if (PRINTF_TLB) + printf("success (%08X), existing entry\n", taddress); + } + + /* add the intention to the list of valid intentions and store */ + entry |= 1 << (intention & (TRANSLATE_TYPE_MASK | TRANSLATE_USER_MASK)); + vtlb->table[tableindex] = entry; + return TRUE; +} + + +/*------------------------------------------------- + vtlb_load - load a fixed VTLB entry +-------------------------------------------------*/ + +void vtlb_load(vtlb_state *vtlb, int entrynum, int numpages, offs_t address, vtlb_entry value) +{ + offs_t tableindex = address >> vtlb->pageshift; + int liveindex = vtlb->dynamic + entrynum; + int pagenum; + + /* must be in range */ + assert(entrynum >= 0 && entrynum < vtlb->fixed); + + if (PRINTF_TLB) + printf("vtlb_load %d for %d pages at %08X == %08X\n", entrynum, numpages, address, value); + + /* if an entry already exists at this index, free it */ + if (vtlb->live[liveindex] != 0) + { + int pagecount = vtlb->fixedpages[entrynum]; + for (pagenum = 0; pagenum < pagecount; pagenum++) + vtlb->table[vtlb->live[liveindex] - 1 + pagenum] = 0; + } + + /* claim this new entry */ + vtlb->live[liveindex] = tableindex + 1; + + /* store the raw value, making sure the "fixed" flag is set */ + value |= VTLB_FLAG_FIXED; + for (pagenum = 0; pagenum < numpages; pagenum++) + vtlb->table[tableindex + pagenum] = value + (pagenum << vtlb->pageshift); +} + + + +/*************************************************************************** + FLUSHING +***************************************************************************/ + +/*------------------------------------------------- + vtlb_flush_dynamic - flush all knowledge + from the dynamic part of the VTLB +-------------------------------------------------*/ + +void vtlb_flush_dynamic(vtlb_state *vtlb) +{ + int liveindex; + + if (PRINTF_TLB) + printf("vtlb_flush_dynamic\n"); + + /* loop over live entries and release them from the table */ + for (liveindex = 0; liveindex < vtlb->dynamic; liveindex++) + if (vtlb->live[liveindex] != 0) + { + offs_t tableindex = vtlb->live[liveindex] - 1; + vtlb->table[tableindex] = 0; + vtlb->live[liveindex] = 0; + } +} + + +/*------------------------------------------------- + vtlb_flush_address - flush knowledge of a + particular address from the VTLB +-------------------------------------------------*/ + +void vtlb_flush_address(vtlb_state *vtlb, offs_t address) +{ + offs_t tableindex = address >> vtlb->pageshift; + + if (PRINTF_TLB) + printf("vtlb_flush_address %08X\n", address); + + /* free the entry in the table; for speed, we leave the entry in the live array */ + vtlb->table[tableindex] = 0; +} + + + +/*************************************************************************** + ACCESSORS +***************************************************************************/ + +/*------------------------------------------------- + vtlb_table - return a pointer to the base of + the linear VTLB lookup table +-------------------------------------------------*/ + +const vtlb_entry *vtlb_table(vtlb_state *vtlb) +{ + return vtlb->table; +} diff --git a/src/emu/cpu/vtlb.h b/src/emu/cpu/vtlb.h new file mode 100644 index 00000000000..c6b2045e7cd --- /dev/null +++ b/src/emu/cpu/vtlb.h @@ -0,0 +1,89 @@ +/*************************************************************************** + + vtlb.h + + Generic virtual TLB implementation. + + Copyright Aaron Giles + Released for general non-commercial use under the MAME license + Visit http://mamedev.org for licensing and usage restrictions. + +***************************************************************************/ + +#pragma once + +#ifndef __VTLB_H__ +#define __VTLB_H__ + +#include "cpuintrf.h" + + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +#define VTLB_FLAGS_MASK 0xff + +#define VTLB_READ_ALLOWED 0x01 /* (1 << TRANSLATE_READ) */ +#define VTLB_WRITE_ALLOWED 0x02 /* (1 << TRANSLATE_WRITE) */ +#define VTLB_FETCH_ALLOWED 0x04 /* (1 << TRANSLATE_FETCH) */ +#define VTLB_FLAG_VALID 0x08 +#define VTLB_USER_READ_ALLOWED 0x10 /* (1 << TRANSLATE_READ_USER) */ +#define VTLB_USER_WRITE_ALLOWED 0x20 /* (1 << TRANSLATE_WRITE_USER) */ +#define VTLB_USER_FETCH_ALLOWED 0x40 /* (1 << TRANSLATE_FETCH_USER) */ +#define VTLB_FLAG_FIXED 0x80 + + + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +/* represents an entry in the VTLB */ +typedef UINT32 vtlb_entry; + + +/* opaque structure describing VTLB state */ +typedef struct _vtlb_state vtlb_state; + + + +/*************************************************************************** + FUNCTION PROTOTYPES +***************************************************************************/ + + +/* ----- initialization/teardown ----- */ + +/* allocate a new VTLB for the given CPU */ +vtlb_state *vtlb_alloc(int cpunum, int space, int fixed_entries, int dynamic_entries); + +/* free an allocated VTLB */ +void vtlb_free(vtlb_state *vtlb); + + +/* ----- filling ----- */ + +/* called by the CPU core in response to an unmapped access */ +int vtlb_fill(vtlb_state *vtlb, offs_t address, int intention); + +/* load a fixed VTLB entry */ +void vtlb_load(vtlb_state *vtlb, int entrynum, int numpages, offs_t address, vtlb_entry value); + + +/* ----- flushing ----- */ + +/* flush all knowledge from the dynamic part of the VTLB */ +void vtlb_flush_dynamic(vtlb_state *vtlb); + +/* flush knowledge of a particular address from the VTLB */ +void vtlb_flush_address(vtlb_state *vtlb, offs_t address); + + +/* ----- accessors ----- */ + +/* return a pointer to the base of the linear VTLB lookup table */ +const vtlb_entry *vtlb_table(vtlb_state *vtlb); + + +#endif |