summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/mips/mips3com.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/cpu/mips/mips3com.c')
-rw-r--r--src/emu/cpu/mips/mips3com.c979
1 files changed, 979 insertions, 0 deletions
diff --git a/src/emu/cpu/mips/mips3com.c b/src/emu/cpu/mips/mips3com.c
new file mode 100644
index 00000000000..55fc05bcacd
--- /dev/null
+++ b/src/emu/cpu/mips/mips3com.c
@@ -0,0 +1,979 @@
+/***************************************************************************
+
+ mips3com.c
+
+ Common MIPS III/IV definitions and functions
+
+***************************************************************************/
+
+#include "mips3com.h"
+
+
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
+
+#define PRINTF_TLB (1)
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+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 UINT64 program_read_qword_32be(offs_t offset);
+static UINT64 program_read_qword_masked_32be(offs_t offset, UINT64 mem_mask);
+
+static void program_write_qword_32be(offs_t offset, UINT64 data);
+static void program_write_qword_masked_32be(offs_t offset, UINT64 data, UINT64 mem_mask);
+
+static UINT64 program_read_qword_32le(offs_t offset);
+static UINT64 program_read_qword_masked_32le(offs_t offset, UINT64 mem_mask);
+
+static void program_write_qword_32le(offs_t offset, UINT64 data);
+static void program_write_qword_masked_32le(offs_t offset, UINT64 data, UINT64 mem_mask);
+
+
+
+/***************************************************************************
+ PRIVATE GLOBAL VARIABLES
+***************************************************************************/
+
+static const memory_handlers be_memory =
+{
+ program_read_byte_32be,
+ program_read_word_32be,
+ program_read_dword_32be,
+ program_read_masked_32be,
+ program_read_qword_32be,
+ program_read_qword_masked_32be,
+
+ program_write_byte_32be,
+ program_write_word_32be,
+ program_write_dword_32be,
+ program_write_masked_32be,
+ program_write_qword_32be,
+ program_write_qword_masked_32be
+};
+
+static const memory_handlers le_memory =
+{
+ program_read_byte_32le,
+ program_read_word_32le,
+ program_read_dword_32le,
+ program_read_masked_32le,
+ program_read_qword_32le,
+ program_read_qword_masked_32le,
+
+ program_write_byte_32le,
+ program_write_word_32le,
+ program_write_dword_32le,
+ program_write_masked_32le,
+ program_write_qword_32le,
+ program_write_qword_masked_32le
+};
+
+
+
+/***************************************************************************
+ INITIALIZATION AND SHUTDOWN
+***************************************************************************/
+
+/*-------------------------------------------------
+ mips3com_init - initialize the mips3_state
+ structure based on the configured type
+-------------------------------------------------*/
+
+void mips3com_init(mips3_state *mips, mips3_flavor flavor, int bigendian, int index, int clock, const struct mips3_config *config, int (*irqcallback)(int))
+{
+ /* initialize the state */
+ memset(mips, 0, sizeof(*mips));
+
+ /* initialize based on the config */
+ mips->flavor = flavor;
+ mips->bigendian = bigendian;
+ mips->cpu_clock = clock;
+ mips->irq_callback = irqcallback;
+ mips->icache_size = config->icache;
+ mips->dcache_size = config->dcache;
+ mips->system_clock = config->system_clock;
+
+ /* set up the endianness */
+ if (mips->bigendian)
+ mips->memory = be_memory;
+ else
+ mips->memory = le_memory;
+
+ /* allocate memory */
+ mips->icache = auto_malloc(config->icache);
+ mips->dcache = auto_malloc(config->dcache);
+ mips->tlb_table = auto_malloc(sizeof(mips->tlb_table[0]) * (1 << (MIPS3_MAX_PADDR_SHIFT - MIPS3_MIN_PAGE_SHIFT)));
+
+ /* allocate a timer for the compare interrupt */
+ mips->compare_int_timer = timer_alloc(compare_int_callback);
+
+ /* reset the state */
+ mips3com_reset(mips);
+}
+
+
+/*-------------------------------------------------
+ mips3com_reset - reset the state of all the
+ registers
+-------------------------------------------------*/
+
+void mips3com_reset(mips3_state *mips)
+{
+ /* initialize the state */
+ mips->pc = 0xbfc00000;
+ mips->cpr[0][COP0_Status] = SR_BEV | SR_ERL;
+ mips->cpr[0][COP0_Compare] = 0xffffffff;
+ mips->cpr[0][COP0_Count] = 0;
+ mips->cpr[0][COP0_Config] = compute_config_register(mips);
+ mips->cpr[0][COP0_PRId] = compute_prid_register(mips);
+ mips->count_zero_time = activecpu_gettotalcycles64();
+
+ /* recompute the TLB table */
+ mips3com_recompute_tlb_table(mips);
+}
+
+
+/*-------------------------------------------------
+ mips3com_dasm - handle disassembly for a
+ CPU
+-------------------------------------------------*/
+
+#ifdef MAME_DEBUG
+offs_t mips3com_dasm(mips3_state *mips, char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram)
+{
+ extern unsigned dasmmips3(char *, unsigned, UINT32);
+ UINT32 op = *(UINT32 *)oprom;
+ if (mips->bigendian)
+ op = BIG_ENDIANIZE_INT32(op);
+ else
+ op = LITTLE_ENDIANIZE_INT32(op);
+ return dasmmips3(buffer, pc, op);
+}
+#endif /* MAME_DEBUG */
+
+
+
+/*-------------------------------------------------
+ mips3com_update_cycle_counting - update cycle
+ counts and the timers
+-------------------------------------------------*/
+
+void mips3com_update_cycle_counting(mips3_state *mips)
+{
+ /* modify the timer to go off */
+ if ((mips->cpr[0][COP0_Status] & 0x8000) && mips->cpr[0][COP0_Compare] != 0xffffffff)
+ {
+ UINT32 count = (activecpu_gettotalcycles64() - mips->count_zero_time) / 2;
+ UINT32 compare = mips->cpr[0][COP0_Compare];
+ UINT32 cyclesleft = compare - count;
+ attotime newtime = ATTOTIME_IN_CYCLES(((INT64)cyclesleft * 2), cpu_getactivecpu());
+
+ /* due to accuracy issues, don't bother setting timers unless they're for less than 100msec */
+ if (attotime_compare(newtime, ATTOTIME_IN_MSEC(100)) < 0)
+ timer_adjust(mips->compare_int_timer, newtime, cpu_getactivecpu(), attotime_zero);
+ }
+ else
+ timer_adjust(mips->compare_int_timer, attotime_never, cpu_getactivecpu(), attotime_zero);
+}
+
+
+
+/***************************************************************************
+ TLB HANDLING
+***************************************************************************/
+
+/*-------------------------------------------------
+ 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 global or if the ASID matches */
+ if ((tlbent->entry_hi & 0x1000) || valid_asid == (tlbent->entry_hi & 0xff))
+ {
+ 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];
+
+ /* only map if the TLB entry is valid */
+ if (lo & 2)
+ {
+ UINT32 pfn = (lo >> 6) & 0x00ffffff;
+ UINT32 wp = (~lo >> 2) & 1;
+
+ for (i = 0; i <= count; i++, vpn++, pfn++)
+ if (vpn < 0x80000 || vpn >= 0xc0000)
+ mips->tlb_table[vpn] = (pfn << MIPS3_MIN_PAGE_SHIFT) | wp;
+ }
+
+ /* otherwise, advance by the number of pages we would have mapped */
+ else
+ vpn += count + 1;
+ }
+ }
+ }
+}
+
+
+/*-------------------------------------------------
+ mips3com_unmap_tlb_entries - unmap entries from
+ the TLB into the tlb_table
+-------------------------------------------------*/
+
+void mips3com_unmap_tlb_entries(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] = 0xffffffff;
+ }
+}
+
+
+/*-------------------------------------------------
+ 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;
+
+ /* reset everything else to unmapped */
+ memset(&mips->tlb_table[0x00000000 >> MIPS3_MIN_PAGE_SHIFT], 0xff, sizeof(mips->tlb_table[0]) * (0x80000000 >> MIPS3_MIN_PAGE_SHIFT));
+ memset(&mips->tlb_table[0xc0000000 >> MIPS3_MIN_PAGE_SHIFT], 0xff, sizeof(mips->tlb_table[0]) * (0x40000000 >> MIPS3_MIN_PAGE_SHIFT));
+
+ /* remap all the entries in the TLB */
+ mips3com_map_tlb_entries(mips);
+}
+
+
+/*-------------------------------------------------
+ mips3com_translate_address - translate an address
+ from logical to physical
+-------------------------------------------------*/
+
+int mips3com_translate_address(mips3_state *mips, int space, offs_t *address)
+{
+ /* only applies to the program address space */
+ if (space == ADDRESS_SPACE_PROGRAM)
+ {
+ UINT32 result = mips->tlb_table[*address >> MIPS3_MIN_PAGE_SHIFT];
+ if (result == 0xffffffff)
+ return FALSE;
+ *address = (result & ~MIPS3_MIN_PAGE_MASK) | (*address & MIPS3_MIN_PAGE_MASK);
+ }
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ mips3com_tlbr - execute the tlbr instruction
+-------------------------------------------------*/
+
+void mips3com_tlbr(mips3_state *mips)
+{
+ UINT32 index = mips->cpr[0][COP0_Index] & 0x3f;
+
+ /* only handle entries within the TLB */
+ if (index < ARRAY_LENGTH(mips->tlb))
+ {
+ mips3_tlb_entry *tlbent = &mips->tlb[index];
+
+ /* 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];
+ }
+}
+
+
+/*-------------------------------------------------
+ mips3com_tlbwi - execute the tlbwi instruction
+-------------------------------------------------*/
+
+void mips3com_tlbwi(mips3_state *mips)
+{
+ /* use the common handler and write based off the COP0 Index register */
+ tlb_write_common(mips, mips->cpr[0][COP0_Index] & 0x3f);
+}
+
+
+/*-------------------------------------------------
+ mips3com_tlbwr - execute the tlbwr instruction
+-------------------------------------------------*/
+
+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;
+
+ /* "random" is based off of the current cycle counting through the non-wired pages */
+ if (unwired > 0)
+ index = ((activecpu_gettotalcycles64() - mips->count_zero_time) % unwired + wired) & 0x3f;
+
+ /* use the common handler to write to this index */
+ tlb_write_common(mips, index);
+}
+
+
+/*-------------------------------------------------
+ mips3com_tlbp - execute the tlbp instruction
+-------------------------------------------------*/
+
+void mips3com_tlbp(mips3_state *mips)
+{
+ UINT32 index;
+ UINT64 vpn;
+
+ /* iterate over TLB entries */
+ for (index = 0; index < ARRAY_LENGTH(mips->tlb); index++)
+ {
+ mips3_tlb_entry *tlbent = &mips->tlb[index];
+ UINT64 mask = ~((tlbent->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))
+
+ /* and if we are either global or matching the current ASID, then stop */
+ if ((tlbent->entry_hi & 0x1000) || (tlbent->entry_hi & 0xff) == (mips->cpr[0][COP0_EntryHi] & 0xff))
+ break;
+ }
+
+ /* validate that our tlb_table was in sync */
+ vpn = ((mips->cpr[0][COP0_EntryHi] >> 13) & 0x07ffffff) << 1;
+ if (index != ARRAY_LENGTH(mips->tlb))
+ {
+ /* we can't assert this because the TLB entry may not be valid */
+ /* assert(mips->tlb_table[vpn & 0xfffff] != 0xffffffff); */
+ mips->cpr[0][COP0_Index] = index;
+ }
+ else
+ {
+ assert(mips->tlb_table[vpn & 0xfffff] == 0xffffffff);
+ mips->cpr[0][COP0_Index] = 0x80000000;
+ }
+}
+
+
+
+/***************************************************************************
+ COMMON GET/SET INFO
+***************************************************************************/
+
+/*-------------------------------------------------
+ mips3com_set_info - set information about
+ a MIPS 3 CPU
+-------------------------------------------------*/
+
+void mips3com_set_info(mips3_state *mips, UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ0: mips3com_set_irq_line(mips, MIPS3_IRQ0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ1: mips3com_set_irq_line(mips, MIPS3_IRQ1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ2: mips3com_set_irq_line(mips, MIPS3_IRQ2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ3: mips3com_set_irq_line(mips, MIPS3_IRQ3, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ4: mips3com_set_irq_line(mips, MIPS3_IRQ4, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ5: mips3com_set_irq_line(mips, MIPS3_IRQ5, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + MIPS3_PC: mips->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_SR: mips->cpr[0][COP0_Status] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_EPC: mips->cpr[0][COP0_EPC] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_CAUSE: mips->cpr[0][COP0_Cause] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_COUNT: mips->cpr[0][COP0_Count] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_COMPARE: mips->cpr[0][COP0_Compare] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_INDEX: mips->cpr[0][COP0_Index] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_RANDOM: mips->cpr[0][COP0_Random] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_ENTRYHI: mips->cpr[0][COP0_EntryHi] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_ENTRYLO0: mips->cpr[0][COP0_EntryLo0] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_ENTRYLO1: mips->cpr[0][COP0_EntryLo1] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_PAGEMASK: mips->cpr[0][COP0_PageMask] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_WIRED: mips->cpr[0][COP0_Wired] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_BADVADDR: mips->cpr[0][COP0_BadVAddr] = info->i; break;
+
+ case CPUINFO_INT_REGISTER + MIPS3_R0: /* can't change R0 */ break;
+ case CPUINFO_INT_REGISTER + MIPS3_R1: mips->r[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R2: mips->r[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R3: mips->r[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R4: mips->r[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R5: mips->r[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R6: mips->r[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R7: mips->r[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R8: mips->r[8] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R9: mips->r[9] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R10: mips->r[10] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R11: mips->r[11] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R12: mips->r[12] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R13: mips->r[13] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R14: mips->r[14] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R15: mips->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R16: mips->r[16] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R17: mips->r[17] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R18: mips->r[18] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R19: mips->r[19] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R20: mips->r[20] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R21: mips->r[21] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R22: mips->r[22] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R23: mips->r[23] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R24: mips->r[24] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R25: mips->r[25] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R26: mips->r[26] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R27: mips->r[27] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R28: mips->r[28] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R29: mips->r[29] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R30: mips->r[30] = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + MIPS3_R31: mips->r[31] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_HI: mips->r[REG_HI] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_LO: mips->r[REG_LO] = info->i; break;
+
+ case CPUINFO_INT_REGISTER + MIPS3_FPR0: mips->cpr[1][0] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR1: mips->cpr[1][1] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR2: mips->cpr[1][2] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR3: mips->cpr[1][3] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR4: mips->cpr[1][4] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR5: mips->cpr[1][5] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR6: mips->cpr[1][6] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR7: mips->cpr[1][7] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR8: mips->cpr[1][8] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR9: mips->cpr[1][9] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR10: mips->cpr[1][10] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR11: mips->cpr[1][11] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR12: mips->cpr[1][12] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR13: mips->cpr[1][13] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR14: mips->cpr[1][14] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR15: mips->cpr[1][15] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR16: mips->cpr[1][16] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR17: mips->cpr[1][17] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR18: mips->cpr[1][18] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR19: mips->cpr[1][19] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR20: mips->cpr[1][20] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR21: mips->cpr[1][21] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR22: mips->cpr[1][22] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR23: mips->cpr[1][23] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR24: mips->cpr[1][24] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR25: mips->cpr[1][25] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR26: mips->cpr[1][26] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR27: mips->cpr[1][27] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR28: mips->cpr[1][28] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR29: mips->cpr[1][29] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR30: mips->cpr[1][30] = info->i; break;
+ case CPUINFO_INT_REGISTER + MIPS3_FPR31: mips->cpr[1][31] = info->i; break;
+ }
+}
+
+
+/*-------------------------------------------------
+ mips3com_get_info - get information about
+ a MIPS 3 CPU
+-------------------------------------------------*/
+
+void mips3com_get_info(mips3_state *mips, UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: /* provided by core */ break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 6; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case CPUINFO_INT_ENDIANNESS: info->i = mips->bigendian ? CPU_IS_BE : CPU_IS_LE; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 40; break;
+
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = MIPS3_MAX_PADDR_SHIFT;break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
+ case CPUINFO_INT_ADDRBUS_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 = MIPS3_MIN_PAGE_SHIFT; break;
+
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ0: info->i = (mips->cpr[0][COP0_Cause] & 0x400) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ1: info->i = (mips->cpr[0][COP0_Cause] & 0x800) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ2: info->i = (mips->cpr[0][COP0_Cause] & 0x1000) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ3: info->i = (mips->cpr[0][COP0_Cause] & 0x2000) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ4: info->i = (mips->cpr[0][COP0_Cause] & 0x4000) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + MIPS3_IRQ5: info->i = (mips->cpr[0][COP0_Cause] & 0x8000) ? ASSERT_LINE : CLEAR_LINE; break;
+
+ case CPUINFO_INT_PREVIOUSPC: /* optionally implemented */ break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + MIPS3_PC: info->i = mips->pc; break;
+ case CPUINFO_INT_REGISTER + MIPS3_SR: info->i = mips->cpr[0][COP0_Status]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_EPC: info->i = mips->cpr[0][COP0_EPC]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_CAUSE: info->i = mips->cpr[0][COP0_Cause]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_COUNT: info->i = ((activecpu_gettotalcycles64() - mips->count_zero_time) / 2); break;
+ case CPUINFO_INT_REGISTER + MIPS3_COMPARE: info->i = mips->cpr[0][COP0_Compare]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_INDEX: info->i = mips->cpr[0][COP0_Index]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_RANDOM: info->i = mips->cpr[0][COP0_Random]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_ENTRYHI: info->i = mips->cpr[0][COP0_EntryHi]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_ENTRYLO0: info->i = mips->cpr[0][COP0_EntryLo0]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_ENTRYLO1: info->i = mips->cpr[0][COP0_EntryLo1]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_PAGEMASK: info->i = mips->cpr[0][COP0_PageMask]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_WIRED: info->i = mips->cpr[0][COP0_Wired]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_BADVADDR: info->i = mips->cpr[0][COP0_BadVAddr]; break;
+
+ case CPUINFO_INT_REGISTER + MIPS3_R0: info->i = mips->r[0]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R1: info->i = mips->r[1]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R2: info->i = mips->r[2]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R3: info->i = mips->r[3]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R4: info->i = mips->r[4]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R5: info->i = mips->r[5]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R6: info->i = mips->r[6]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R7: info->i = mips->r[7]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R8: info->i = mips->r[8]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R9: info->i = mips->r[9]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R10: info->i = mips->r[10]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R11: info->i = mips->r[11]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R12: info->i = mips->r[12]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R13: info->i = mips->r[13]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R14: info->i = mips->r[14]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R15: info->i = mips->r[15]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R16: info->i = mips->r[16]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R17: info->i = mips->r[17]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R18: info->i = mips->r[18]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R19: info->i = mips->r[19]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R20: info->i = mips->r[20]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R21: info->i = mips->r[21]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R22: info->i = mips->r[22]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R23: info->i = mips->r[23]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R24: info->i = mips->r[24]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R25: info->i = mips->r[25]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R26: info->i = mips->r[26]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R27: info->i = mips->r[27]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R28: info->i = mips->r[28]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R29: info->i = mips->r[29]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_R30: info->i = mips->r[30]; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + MIPS3_R31: info->i = mips->r[31]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_HI: info->i = mips->r[REG_HI]; break;
+ case CPUINFO_INT_REGISTER + MIPS3_LO: info->i = mips->r[REG_LO]; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_SET_INFO: /* provided by core */ break;
+ case CPUINFO_PTR_GET_CONTEXT: /* provided by core */ break;
+ case CPUINFO_PTR_SET_CONTEXT: /* provided by core */ break;
+ case CPUINFO_PTR_INIT: /* provided by core */ break;
+ case CPUINFO_PTR_RESET: /* provided by core */ break;
+ case CPUINFO_PTR_EXIT: /* provided by core */ break;
+ case CPUINFO_PTR_EXECUTE: /* provided by core */ break;
+ case CPUINFO_PTR_TRANSLATE: /* provided by core */ break;
+ case CPUINFO_PTR_DISASSEMBLE: /* provided by core */ break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &mips->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "MIPS III"); break;
+ case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "MIPS III"); break;
+ case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "3.0"); break;
+ case CPUINFO_STR_CORE_FILE: /* provided by core */ break;
+ case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright (C) Aaron Giles 2000-2007"); break;
+
+ case CPUINFO_STR_FLAGS: strcpy(info->s, " "); break;
+
+ case CPUINFO_STR_REGISTER + MIPS3_PC: sprintf(info->s, "PC: %08X", mips->pc); break;
+ case CPUINFO_STR_REGISTER + MIPS3_SR: sprintf(info->s, "SR: %08X", (UINT32)mips->cpr[0][COP0_Status]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_EPC: sprintf(info->s, "EPC:%08X", (UINT32)mips->cpr[0][COP0_EPC]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_CAUSE: sprintf(info->s, "Cause:%08X", (UINT32)mips->cpr[0][COP0_Cause]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_COUNT: sprintf(info->s, "Count:%08X", (UINT32)((activecpu_gettotalcycles64() - mips->count_zero_time) / 2)); break;
+ case CPUINFO_STR_REGISTER + MIPS3_COMPARE: sprintf(info->s, "Compare:%08X", (UINT32)mips->cpr[0][COP0_Compare]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_INDEX: sprintf(info->s, "Index:%08X", (UINT32)mips->cpr[0][COP0_Index]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_RANDOM: sprintf(info->s, "Random:%08X", (UINT32)mips->cpr[0][COP0_Random]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_ENTRYHI: sprintf(info->s, "EntryHi:%08X%08X", (UINT32)(mips->cpr[0][COP0_EntryHi] >> 32), (UINT32)mips->cpr[0][COP0_EntryHi]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_ENTRYLO0: sprintf(info->s, "EntryLo0:%08X%08X", (UINT32)(mips->cpr[0][COP0_EntryLo0] >> 32), (UINT32)mips->cpr[0][COP0_EntryLo0]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_ENTRYLO1: sprintf(info->s, "EntryLo1:%08X%08X", (UINT32)(mips->cpr[0][COP0_EntryLo1] >> 32), (UINT32)mips->cpr[0][COP0_EntryLo1]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_PAGEMASK: sprintf(info->s, "PageMask:%08X%08X", (UINT32)(mips->cpr[0][COP0_PageMask] >> 32), (UINT32)mips->cpr[0][COP0_PageMask]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_WIRED: sprintf(info->s, "Wired:%08X", (UINT32)mips->cpr[0][COP0_Wired]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_BADVADDR: sprintf(info->s, "BadVAddr:%08X", (UINT32)mips->cpr[0][COP0_BadVAddr]); break;
+
+ case CPUINFO_STR_REGISTER + MIPS3_R0: sprintf(info->s, "R0: %08X%08X", (UINT32)(mips->r[0] >> 32), (UINT32)mips->r[0]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R1: sprintf(info->s, "R1: %08X%08X", (UINT32)(mips->r[1] >> 32), (UINT32)mips->r[1]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R2: sprintf(info->s, "R2: %08X%08X", (UINT32)(mips->r[2] >> 32), (UINT32)mips->r[2]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R3: sprintf(info->s, "R3: %08X%08X", (UINT32)(mips->r[3] >> 32), (UINT32)mips->r[3]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R4: sprintf(info->s, "R4: %08X%08X", (UINT32)(mips->r[4] >> 32), (UINT32)mips->r[4]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R5: sprintf(info->s, "R5: %08X%08X", (UINT32)(mips->r[5] >> 32), (UINT32)mips->r[5]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R6: sprintf(info->s, "R6: %08X%08X", (UINT32)(mips->r[6] >> 32), (UINT32)mips->r[6]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R7: sprintf(info->s, "R7: %08X%08X", (UINT32)(mips->r[7] >> 32), (UINT32)mips->r[7]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R8: sprintf(info->s, "R8: %08X%08X", (UINT32)(mips->r[8] >> 32), (UINT32)mips->r[8]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R9: sprintf(info->s, "R9: %08X%08X", (UINT32)(mips->r[9] >> 32), (UINT32)mips->r[9]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R10: sprintf(info->s, "R10:%08X%08X", (UINT32)(mips->r[10] >> 32), (UINT32)mips->r[10]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R11: sprintf(info->s, "R11:%08X%08X", (UINT32)(mips->r[11] >> 32), (UINT32)mips->r[11]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R12: sprintf(info->s, "R12:%08X%08X", (UINT32)(mips->r[12] >> 32), (UINT32)mips->r[12]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R13: sprintf(info->s, "R13:%08X%08X", (UINT32)(mips->r[13] >> 32), (UINT32)mips->r[13]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R14: sprintf(info->s, "R14:%08X%08X", (UINT32)(mips->r[14] >> 32), (UINT32)mips->r[14]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R15: sprintf(info->s, "R15:%08X%08X", (UINT32)(mips->r[15] >> 32), (UINT32)mips->r[15]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R16: sprintf(info->s, "R16:%08X%08X", (UINT32)(mips->r[16] >> 32), (UINT32)mips->r[16]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R17: sprintf(info->s, "R17:%08X%08X", (UINT32)(mips->r[17] >> 32), (UINT32)mips->r[17]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R18: sprintf(info->s, "R18:%08X%08X", (UINT32)(mips->r[18] >> 32), (UINT32)mips->r[18]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R19: sprintf(info->s, "R19:%08X%08X", (UINT32)(mips->r[19] >> 32), (UINT32)mips->r[19]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R20: sprintf(info->s, "R20:%08X%08X", (UINT32)(mips->r[20] >> 32), (UINT32)mips->r[20]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R21: sprintf(info->s, "R21:%08X%08X", (UINT32)(mips->r[21] >> 32), (UINT32)mips->r[21]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R22: sprintf(info->s, "R22:%08X%08X", (UINT32)(mips->r[22] >> 32), (UINT32)mips->r[22]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R23: sprintf(info->s, "R23:%08X%08X", (UINT32)(mips->r[23] >> 32), (UINT32)mips->r[23]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R24: sprintf(info->s, "R24:%08X%08X", (UINT32)(mips->r[24] >> 32), (UINT32)mips->r[24]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R25: sprintf(info->s, "R25:%08X%08X", (UINT32)(mips->r[25] >> 32), (UINT32)mips->r[25]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R26: sprintf(info->s, "R26:%08X%08X", (UINT32)(mips->r[26] >> 32), (UINT32)mips->r[26]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R27: sprintf(info->s, "R27:%08X%08X", (UINT32)(mips->r[27] >> 32), (UINT32)mips->r[27]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R28: sprintf(info->s, "R28:%08X%08X", (UINT32)(mips->r[28] >> 32), (UINT32)mips->r[28]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R29: sprintf(info->s, "R29:%08X%08X", (UINT32)(mips->r[29] >> 32), (UINT32)mips->r[29]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R30: sprintf(info->s, "R30:%08X%08X", (UINT32)(mips->r[30] >> 32), (UINT32)mips->r[30]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_R31: sprintf(info->s, "R31:%08X%08X", (UINT32)(mips->r[31] >> 32), (UINT32)mips->r[31]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_HI: sprintf(info->s, "HI: %08X%08X", (UINT32)(mips->r[REG_HI] >> 32), (UINT32)mips->r[REG_HI]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_LO: sprintf(info->s, "LO: %08X%08X", (UINT32)(mips->r[REG_LO] >> 32), (UINT32)mips->r[REG_LO]); break;
+
+ case CPUINFO_STR_REGISTER + MIPS3_FPR0: sprintf(info->s, "FPR0: %08X%08X", (UINT32)(mips->cpr[1][0] >> 32), (UINT32)mips->cpr[1][0]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR1: sprintf(info->s, "FPR1: %08X%08X", (UINT32)(mips->cpr[1][1] >> 32), (UINT32)mips->cpr[1][1]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR2: sprintf(info->s, "FPR2: %08X%08X", (UINT32)(mips->cpr[1][2] >> 32), (UINT32)mips->cpr[1][2]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR3: sprintf(info->s, "FPR3: %08X%08X", (UINT32)(mips->cpr[1][3] >> 32), (UINT32)mips->cpr[1][3]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR4: sprintf(info->s, "FPR4: %08X%08X", (UINT32)(mips->cpr[1][4] >> 32), (UINT32)mips->cpr[1][4]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR5: sprintf(info->s, "FPR5: %08X%08X", (UINT32)(mips->cpr[1][5] >> 32), (UINT32)mips->cpr[1][5]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR6: sprintf(info->s, "FPR6: %08X%08X", (UINT32)(mips->cpr[1][6] >> 32), (UINT32)mips->cpr[1][6]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR7: sprintf(info->s, "FPR7: %08X%08X", (UINT32)(mips->cpr[1][7] >> 32), (UINT32)mips->cpr[1][7]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR8: sprintf(info->s, "FPR8: %08X%08X", (UINT32)(mips->cpr[1][8] >> 32), (UINT32)mips->cpr[1][8]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR9: sprintf(info->s, "FPR9: %08X%08X", (UINT32)(mips->cpr[1][9] >> 32), (UINT32)mips->cpr[1][9]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR10: sprintf(info->s, "FPR10:%08X%08X", (UINT32)(mips->cpr[1][10] >> 32), (UINT32)mips->cpr[1][10]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR11: sprintf(info->s, "FPR11:%08X%08X", (UINT32)(mips->cpr[1][11] >> 32), (UINT32)mips->cpr[1][11]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR12: sprintf(info->s, "FPR12:%08X%08X", (UINT32)(mips->cpr[1][12] >> 32), (UINT32)mips->cpr[1][12]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR13: sprintf(info->s, "FPR13:%08X%08X", (UINT32)(mips->cpr[1][13] >> 32), (UINT32)mips->cpr[1][13]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR14: sprintf(info->s, "FPR14:%08X%08X", (UINT32)(mips->cpr[1][14] >> 32), (UINT32)mips->cpr[1][14]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR15: sprintf(info->s, "FPR15:%08X%08X", (UINT32)(mips->cpr[1][15] >> 32), (UINT32)mips->cpr[1][15]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR16: sprintf(info->s, "FPR16:%08X%08X", (UINT32)(mips->cpr[1][16] >> 32), (UINT32)mips->cpr[1][16]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR17: sprintf(info->s, "FPR17:%08X%08X", (UINT32)(mips->cpr[1][17] >> 32), (UINT32)mips->cpr[1][17]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR18: sprintf(info->s, "FPR18:%08X%08X", (UINT32)(mips->cpr[1][18] >> 32), (UINT32)mips->cpr[1][18]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR19: sprintf(info->s, "FPR19:%08X%08X", (UINT32)(mips->cpr[1][19] >> 32), (UINT32)mips->cpr[1][19]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR20: sprintf(info->s, "FPR20:%08X%08X", (UINT32)(mips->cpr[1][20] >> 32), (UINT32)mips->cpr[1][20]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR21: sprintf(info->s, "FPR21:%08X%08X", (UINT32)(mips->cpr[1][21] >> 32), (UINT32)mips->cpr[1][21]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR22: sprintf(info->s, "FPR22:%08X%08X", (UINT32)(mips->cpr[1][22] >> 32), (UINT32)mips->cpr[1][22]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR23: sprintf(info->s, "FPR23:%08X%08X", (UINT32)(mips->cpr[1][23] >> 32), (UINT32)mips->cpr[1][23]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR24: sprintf(info->s, "FPR24:%08X%08X", (UINT32)(mips->cpr[1][24] >> 32), (UINT32)mips->cpr[1][24]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR25: sprintf(info->s, "FPR25:%08X%08X", (UINT32)(mips->cpr[1][25] >> 32), (UINT32)mips->cpr[1][25]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR26: sprintf(info->s, "FPR26:%08X%08X", (UINT32)(mips->cpr[1][26] >> 32), (UINT32)mips->cpr[1][26]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR27: sprintf(info->s, "FPR27:%08X%08X", (UINT32)(mips->cpr[1][27] >> 32), (UINT32)mips->cpr[1][27]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR28: sprintf(info->s, "FPR28:%08X%08X", (UINT32)(mips->cpr[1][28] >> 32), (UINT32)mips->cpr[1][28]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR29: sprintf(info->s, "FPR29:%08X%08X", (UINT32)(mips->cpr[1][29] >> 32), (UINT32)mips->cpr[1][29]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR30: sprintf(info->s, "FPR30:%08X%08X", (UINT32)(mips->cpr[1][30] >> 32), (UINT32)mips->cpr[1][30]); break;
+ case CPUINFO_STR_REGISTER + MIPS3_FPR31: sprintf(info->s, "FPR31:%08X%08X", (UINT32)(mips->cpr[1][31] >> 32), (UINT32)mips->cpr[1][31]); break;
+ }
+}
+
+
+/***************************************************************************
+ INTERNAL HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ compare_int_callback - callback that fires
+ whenever a compare interrupt is generated
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( compare_int_callback )
+{
+ cpunum_set_input_line(param, MIPS3_IRQ5, ASSERT_LINE);
+}
+
+
+/*-------------------------------------------------
+ compute_config_register - compute the value
+ of the config register
+-------------------------------------------------*/
+
+static UINT32 compute_config_register(const mips3_state *mips)
+{
+ /* set the cache line size to 32 bytes */
+ UINT32 configreg = 0x00026030;
+ int divisor;
+
+ /* set the data cache size */
+ if (mips->icache_size <= 0x01000) configreg |= 0 << 6;
+ else if (mips->icache_size <= 0x02000) configreg |= 1 << 6;
+ else if (mips->icache_size <= 0x04000) configreg |= 2 << 6;
+ else if (mips->icache_size <= 0x08000) configreg |= 3 << 6;
+ else if (mips->icache_size <= 0x10000) configreg |= 4 << 6;
+ else if (mips->icache_size <= 0x20000) configreg |= 5 << 6;
+ else if (mips->icache_size <= 0x40000) configreg |= 6 << 6;
+ else configreg |= 7 << 6;
+
+ /* set the instruction cache size */
+ if (mips->icache_size <= 0x01000) configreg |= 0 << 9;
+ else if (mips->icache_size <= 0x02000) configreg |= 1 << 9;
+ else if (mips->icache_size <= 0x04000) configreg |= 2 << 9;
+ else if (mips->icache_size <= 0x08000) configreg |= 3 << 9;
+ else if (mips->icache_size <= 0x10000) configreg |= 4 << 9;
+ else if (mips->icache_size <= 0x20000) configreg |= 5 << 9;
+ else if (mips->icache_size <= 0x40000) configreg |= 6 << 9;
+ else configreg |= 7 << 9;
+
+ /* set the endianness bit */
+ if (mips->bigendian)
+ configreg |= 0x00008000;
+
+ /* set the system clock divider */
+ divisor = 2;
+ if (mips->system_clock != 0)
+ {
+ divisor = mips->cpu_clock / mips->system_clock;
+ if (mips->system_clock * divisor != mips->cpu_clock)
+ {
+ configreg |= 0x80000000;
+ divisor = mips->cpu_clock * 2 / mips->system_clock;
+ }
+ }
+ configreg |= (((divisor < 2) ? 2 : (divisor > 8) ? 8 : divisor) - 2) << 28;
+
+ return configreg;
+}
+
+
+/*-------------------------------------------------
+ compute_prid_register - compute the value
+ of the PRId register
+-------------------------------------------------*/
+
+static UINT32 compute_prid_register(const mips3_state *mips)
+{
+ switch (mips->flavor)
+ {
+ case MIPS3_TYPE_R4600:
+ case MIPS3_TYPE_R4650:
+ return 0x2000;
+
+ case MIPS3_TYPE_R4700:
+ return 0x2100;
+
+ case MIPS3_TYPE_R5000:
+ case MIPS3_TYPE_QED5271:
+ return 0x2300;
+
+ case MIPS3_TYPE_RM7000:
+ return 0x2700;
+
+ default:
+ fatalerror("Unknown MIPS flavor specified");
+ }
+ return 0x2000;
+}
+
+
+/*-------------------------------------------------
+ tlb_write_common - common routine for writing
+ a TLB entry
+-------------------------------------------------*/
+
+static void tlb_write_common(mips3_state *mips, int index)
+{
+ /* only handle entries within the TLB */
+ if (index < ARRAY_LENGTH(mips->tlb))
+ {
+ mips3_tlb_entry *tlbent = &mips->tlb[index];
+
+ /* unmap what we have */
+ mips3com_unmap_tlb_entries(mips);
+
+ /* 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];
+
+ /* remap the TLB */
+ mips3com_map_tlb_entries(mips);
+
+ /* 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 - log half of a single TLB
+ entry
+-------------------------------------------------*/
+
+static void tlb_entry_log_half(mips3_tlb_entry *tlbent, int index, int which)
+{
+#if PRINTF_TLB
+ UINT64 hi = tlbent->entry_hi;
+ UINT64 lo = tlbent->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;
+ 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,
+ asid, r, c, (lo & 4) ? 'd' : '.', (lo & 2) ? 'v' : '.', (hi & 0x1000) ? 'g' : '.');
+#endif
+}
+
+
+
+/***************************************************************************
+ DOUBLEWORD READS/WRITES
+***************************************************************************/
+
+/*-------------------------------------------------
+ program_read_qword_32be - read a 64-bit
+ big-endian value
+-------------------------------------------------*/
+
+static UINT64 program_read_qword_32be(offs_t offset)
+{
+ UINT64 result = (UINT64)program_read_dword_32be(offset) << 32;
+ return result | program_read_dword_32be(offset + 4);
+}
+
+
+/*-------------------------------------------------
+ program_read_qword_masked_32be - read a 64-bit
+ big-endian value with explicit masking
+-------------------------------------------------*/
+
+static UINT64 program_read_qword_masked_32be(offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result = 0;
+ if ((mem_mask & U64(0xffffffff00000000)) != U64(0xffffffff00000000))
+ result |= (UINT64)program_read_masked_32be(offset, mem_mask >> 32) << 32;
+ if ((mem_mask & U64(0x00000000ffffffff)) != U64(0x00000000ffffffff))
+ result |= program_read_masked_32be(offset + 4, mem_mask);
+ return result;
+}
+
+
+/*-------------------------------------------------
+ program_read_qword_32le - read a 64-bit
+ little-endian value
+-------------------------------------------------*/
+
+static UINT64 program_read_qword_32le(offs_t offset)
+{
+ UINT64 result = program_read_dword_32le(offset);
+ return result | ((UINT64)program_read_dword_32le(offset + 4) << 32);
+}
+
+
+/*-------------------------------------------------
+ program_read_qword_masked_32le - read a 64-bit
+ little-endian value with explicit masking
+-------------------------------------------------*/
+
+static UINT64 program_read_qword_masked_32le(offs_t offset, UINT64 mem_mask)
+{
+ UINT64 result = 0;
+ if ((mem_mask & U64(0x00000000ffffffff)) != U64(0x00000000ffffffff))
+ result |= program_read_masked_32le(offset, mem_mask);
+ if ((mem_mask & U64(0xffffffff00000000)) != U64(0xffffffff00000000))
+ result |= (UINT64)program_read_masked_32le(offset + 4, mem_mask >> 32) << 32;
+ return result;
+}
+
+
+/*-------------------------------------------------
+ program_write_qword_32be - write a 64-bit
+ big-endian value
+-------------------------------------------------*/
+
+static void program_write_qword_32be(offs_t offset, UINT64 data)
+{
+ program_write_dword_32be(offset, data >> 32);
+ program_write_dword_32be(offset + 4, data);
+}
+
+
+/*-------------------------------------------------
+ program_write_qword_masked_32be - write a
+ 64-bit big-endian value with explicit masking
+-------------------------------------------------*/
+
+static void program_write_qword_masked_32be(offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ if ((mem_mask & U64(0xffffffff00000000)) != U64(0xffffffff00000000))
+ program_write_masked_32be(offset, data >> 32, mem_mask >> 32);
+ if ((mem_mask & U64(0x00000000ffffffff)) != U64(0x00000000ffffffff))
+ program_write_masked_32be(offset + 4, data, mem_mask);
+}
+
+
+/*-------------------------------------------------
+ program_write_qword_32le - write a 64-bit
+ little-endian value
+-------------------------------------------------*/
+
+static void program_write_qword_32le(offs_t offset, UINT64 data)
+{
+ program_write_dword_32le(offset, data);
+ program_write_dword_32le(offset + 4, data >> 32);
+}
+
+
+/*-------------------------------------------------
+ program_write_qword_masked_32le - write a
+ 64-bit little-endian value with explicit masking
+-------------------------------------------------*/
+
+static void program_write_qword_masked_32le(offs_t offset, UINT64 data, UINT64 mem_mask)
+{
+ if ((mem_mask & U64(0x00000000ffffffff)) != U64(0x00000000ffffffff))
+ program_write_masked_32le(offset, data, mem_mask);
+ if ((mem_mask & U64(0xffffffff00000000)) != U64(0xffffffff00000000))
+ program_write_masked_32le(offset + 4, data >> 32, mem_mask >> 32);
+}