From 3466c47229c837919539e0d228c524f1d3a07b39 Mon Sep 17 00:00:00 2001 From: AJR Date: Sun, 7 Feb 2016 01:17:17 -0500 Subject: [PATCH 1/2] Renaming (nw) --- src/{devices/cpu/vtlb.cpp => emu/divtlb.cpp} | 0 src/{devices/cpu/vtlb.h => emu/divtlb.h} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/{devices/cpu/vtlb.cpp => emu/divtlb.cpp} (100%) rename src/{devices/cpu/vtlb.h => emu/divtlb.h} (100%) diff --git a/src/devices/cpu/vtlb.cpp b/src/emu/divtlb.cpp similarity index 100% rename from src/devices/cpu/vtlb.cpp rename to src/emu/divtlb.cpp diff --git a/src/devices/cpu/vtlb.h b/src/emu/divtlb.h similarity index 100% rename from src/devices/cpu/vtlb.h rename to src/emu/divtlb.h From 0d8df9d595aa49dd1ce77fa7ecd1db5b286a6f9f Mon Sep 17 00:00:00 2001 From: AJR Date: Sun, 7 Feb 2016 01:42:58 -0500 Subject: [PATCH 2/2] Make generic VTLB implementation a modern device interface (nw) --- scripts/src/cpu.lua | 9 - scripts/src/emu.lua | 2 + src/devices/cpu/i386/i386.cpp | 61 ++-- src/devices/cpu/i386/i386.h | 8 +- src/devices/cpu/i386/i386ops.inc | 2 +- src/devices/cpu/i386/i386priv.h | 4 +- src/devices/cpu/i386/i486ops.inc | 8 +- src/devices/cpu/mips/mips3.cpp | 67 ++-- src/devices/cpu/mips/mips3.h | 6 +- src/devices/cpu/mips/mips3com.cpp | 12 +- src/devices/cpu/mips/mips3com.h | 1 - src/devices/cpu/mips/mips3drc.cpp | 6 +- src/devices/cpu/powerpc/ppc.h | 7 +- src/devices/cpu/powerpc/ppccom.cpp | 28 +- src/devices/cpu/powerpc/ppcdrc.cpp | 10 +- src/emu/dimemory.h | 18 -- src/emu/divtlb.cpp | 471 +++++++++++++++-------------- src/emu/divtlb.h | 79 ++--- 18 files changed, 390 insertions(+), 409 deletions(-) diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 0c2882df5e5..ed6378f93f8 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -9,14 +9,6 @@ -- --------------------------------------------------------------------------- --------------------------------------------------- --- Shared code --------------------------------------------------- - -files { - MAME_DIR .. "src/devices/cpu/vtlb.cpp", -} - -------------------------------------------------- -- Dynamic recompiler objects -------------------------------------------------- @@ -43,7 +35,6 @@ if (CPUS["SH2"]~=null or CPUS["MIPS"]~=null or CPUS["POWERPC"]~=null or CPUS["RS MAME_DIR .. "src/devices/cpu/drcbex64.cpp", MAME_DIR .. "src/devices/cpu/drcbex64.h", MAME_DIR .. "src/devices/cpu/drcumlsh.h", - MAME_DIR .. "src/devices/cpu/vtlb.h", MAME_DIR .. "src/devices/cpu/x86emit.h", } end diff --git a/scripts/src/emu.lua b/scripts/src/emu.lua index b49756676ce..e0358285114 100644 --- a/scripts/src/emu.lua +++ b/scripts/src/emu.lua @@ -117,6 +117,8 @@ files { MAME_DIR .. "src/emu/distate.h", MAME_DIR .. "src/emu/divideo.cpp", MAME_DIR .. "src/emu/divideo.h", + MAME_DIR .. "src/emu/divtlb.cpp", + MAME_DIR .. "src/emu/divtlb.h", MAME_DIR .. "src/emu/drawgfx.cpp", MAME_DIR .. "src/emu/drawgfx.h", MAME_DIR .. "src/emu/drawgfxm.h", diff --git a/src/devices/cpu/i386/i386.cpp b/src/devices/cpu/i386/i386.cpp index f0d57ada9a0..62a65155a59 100644 --- a/src/devices/cpu/i386/i386.cpp +++ b/src/devices/cpu/i386/i386.cpp @@ -41,23 +41,31 @@ const device_type PENTIUM4 = &device_creator; i386_device::i386_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : cpu_device(mconfig, I386, "I386", tag, owner, clock, "i386", __FILE__) + , device_vtlb_interface(mconfig, *this, AS_PROGRAM) , m_program_config("program", ENDIANNESS_LITTLE, 32, 32, 0) , m_io_config("io", ENDIANNESS_LITTLE, 32, 16, 0) , m_smiact(*this) { m_program_config.m_logaddr_width = 32; m_program_config.m_page_shift = 12; + + // 32 unified + set_vtlb_dynamic_entries(32); } i386_device::i386_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source, int program_data_width, int program_addr_width, int io_data_width) : cpu_device(mconfig, type, name, tag, owner, clock, shortname, source) + , device_vtlb_interface(mconfig, *this, AS_PROGRAM) , m_program_config("program", ENDIANNESS_LITTLE, program_data_width, program_addr_width, 0) , m_io_config("io", ENDIANNESS_LITTLE, io_data_width, 16, 0) , m_smiact(*this) { m_program_config.m_logaddr_width = 32; m_program_config.m_page_shift = 12; + + // 32 unified + set_vtlb_dynamic_entries(32); } i386SX_device::i386SX_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) @@ -73,11 +81,15 @@ i486_device::i486_device(const machine_config &mconfig, const char *tag, device_ pentium_device::pentium_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : i386_device(mconfig, PENTIUM, "PENTIUM", tag, owner, clock, "pentium", __FILE__) { + // 64 dtlb small, 8 dtlb large, 32 itlb + set_vtlb_dynamic_entries(96); } pentium_device::pentium_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) : i386_device(mconfig, type, name, tag, owner, clock, shortname, source) { + // 64 dtlb small, 8 dtlb large, 32 itlb + set_vtlb_dynamic_entries(96); } mediagx_device::mediagx_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) @@ -93,21 +105,29 @@ pentium_pro_device::pentium_pro_device(const machine_config &mconfig, const char pentium_mmx_device::pentium_mmx_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : pentium_device(mconfig, PENTIUM_MMX, "Pentium MMX", tag, owner, clock, "pentium_mmx", __FILE__) { + // 64 dtlb small, 8 dtlb large, 32 itlb small, 2 itlb large + set_vtlb_dynamic_entries(96); } pentium2_device::pentium2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : pentium_device(mconfig, PENTIUM2, "Pentium II", tag, owner, clock, "pentium2", __FILE__) { + // 64 dtlb small, 8 dtlb large, 32 itlb small, 2 itlb large + set_vtlb_dynamic_entries(96); } pentium3_device::pentium3_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : pentium_device(mconfig, PENTIUM3, "Pentium III", tag, owner, clock, "pentium3", __FILE__) { + // 64 dtlb small, 8 dtlb large, 32 itlb small, 2 itlb large + set_vtlb_dynamic_entries(96); } pentium4_device::pentium4_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : pentium_device(mconfig, PENTIUM4, "Pentium 4", tag, owner, clock, "pentium4", __FILE__) { + // 128 dtlb, 64 itlb + set_vtlb_dynamic_entries(196); } @@ -1306,7 +1326,7 @@ void i386_device::i386_task_switch(UINT16 selector, UINT8 nested) } m_cr[3] = READ32(tss+0x1c); // CR3 (PDBR) if(oldcr3 != m_cr[3]) - vtlb_flush_dynamic(m_vtlb); + vtlb_flush_dynamic(); /* Set the busy bit in the new task's descriptor */ if(selector & 0x0004) @@ -3178,7 +3198,7 @@ void i386_device::i386_postload() CHANGE_PC(m_eip); } -void i386_device::i386_common_init(int tlbsize) +void i386_device::i386_common_init() { int i, j; static const int regs8[8] = {AL,CL,DL,BL,AH,CH,DH,BH}; @@ -3211,7 +3231,6 @@ void i386_device::i386_common_init(int tlbsize) m_program = &space(AS_PROGRAM); m_direct = &m_program->direct(); m_io = &space(AS_IO); - m_vtlb = vtlb_alloc(this, AS_PROGRAM, 0, tlbsize); m_smi = false; m_debugger_temp = 0; m_lock = false; @@ -3294,7 +3313,7 @@ void i386_device::i386_common_init(int tlbsize) void i386_device::device_start() { - i386_common_init(32); + i386_common_init(); build_opcode_table(OP_I386); m_cycle_table_rm = cycle_table_rm[CPU_CYCLES_I386].get(); @@ -3698,7 +3717,6 @@ void i386_device::zero_state() void i386_device::device_reset() { zero_state(); - vtlb_flush_dynamic(m_vtlb); m_sreg[CS].selector = 0xf000; m_sreg[CS].base = 0xffff0000; @@ -3890,7 +3908,7 @@ void i386_device::i386_set_a20_line(int state) m_a20_mask = ~(1 << 20); } // TODO: how does A20M and the tlb interact - vtlb_flush_dynamic(m_vtlb); + vtlb_flush_dynamic(); } void i386_device::execute_run() @@ -3976,7 +3994,7 @@ offs_t i386_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *opr void i486_device::device_start() { - i386_common_init(32); + i386_common_init(); build_opcode_table(OP_I386 | OP_FPU | OP_I486); build_x87_opcode_table(); @@ -3989,7 +4007,6 @@ void i486_device::device_start() void i486_device::device_reset() { zero_state(); - vtlb_flush_dynamic(m_vtlb); m_sreg[CS].selector = 0xf000; m_sreg[CS].base = 0xffff0000; @@ -4033,8 +4050,7 @@ void i486_device::device_reset() void pentium_device::device_start() { - // 64 dtlb small, 8 dtlb large, 32 itlb - i386_common_init(96); + i386_common_init(); register_state_i386_x87(); build_opcode_table(OP_I386 | OP_FPU | OP_I486 | OP_PENTIUM); @@ -4046,7 +4062,6 @@ void pentium_device::device_start() void pentium_device::device_reset() { zero_state(); - vtlb_flush_dynamic(m_vtlb); m_sreg[CS].selector = 0xf000; m_sreg[CS].base = 0xffff0000; @@ -4107,8 +4122,7 @@ void pentium_device::device_reset() void mediagx_device::device_start() { - // probably 32 unified - i386_common_init(32); + i386_common_init(); register_state_i386_x87(); build_x87_opcode_table(); @@ -4120,7 +4134,6 @@ void mediagx_device::device_start() void mediagx_device::device_reset() { zero_state(); - vtlb_flush_dynamic(m_vtlb); m_sreg[CS].selector = 0xf000; m_sreg[CS].base = 0xffff0000; @@ -4172,8 +4185,7 @@ void mediagx_device::device_reset() void pentium_pro_device::device_start() { - // 64 dtlb small, 32 itlb - i386_common_init(96); + i386_common_init(); register_state_i386_x87(); build_x87_opcode_table(); @@ -4185,7 +4197,6 @@ void pentium_pro_device::device_start() void pentium_pro_device::device_reset() { zero_state(); - vtlb_flush_dynamic(m_vtlb); m_sreg[CS].selector = 0xf000; m_sreg[CS].base = 0xffff0000; @@ -4247,8 +4258,7 @@ void pentium_pro_device::device_reset() void pentium_mmx_device::device_start() { - // 64 dtlb small, 8 dtlb large, 32 itlb small, 2 itlb large - i386_common_init(96); + i386_common_init(); register_state_i386_x87(); build_x87_opcode_table(); @@ -4260,7 +4270,6 @@ void pentium_mmx_device::device_start() void pentium_mmx_device::device_reset() { zero_state(); - vtlb_flush_dynamic(m_vtlb); m_sreg[CS].selector = 0xf000; m_sreg[CS].base = 0xffff0000; @@ -4320,8 +4329,7 @@ void pentium_mmx_device::device_reset() void pentium2_device::device_start() { - // 64 dtlb small, 8 dtlb large, 32 itlb small, 2 itlb large - i386_common_init(96); + i386_common_init(); register_state_i386_x87(); build_x87_opcode_table(); @@ -4333,7 +4341,6 @@ void pentium2_device::device_start() void pentium2_device::device_reset() { zero_state(); - vtlb_flush_dynamic(m_vtlb); m_sreg[CS].selector = 0xf000; m_sreg[CS].base = 0xffff0000; @@ -4387,8 +4394,7 @@ void pentium2_device::device_reset() void pentium3_device::device_start() { - // 64 dtlb small, 8 dtlb large, 32 itlb small, 2 itlb large - i386_common_init(96); + i386_common_init(); register_state_i386_x87_xmm(); build_x87_opcode_table(); @@ -4400,7 +4406,6 @@ void pentium3_device::device_start() void pentium3_device::device_reset() { zero_state(); - vtlb_flush_dynamic(m_vtlb); m_sreg[CS].selector = 0xf000; m_sreg[CS].base = 0xffff0000; @@ -4456,8 +4461,7 @@ void pentium3_device::device_reset() void pentium4_device::device_start() { - // 128 dtlb, 64 itlb - i386_common_init(196); + i386_common_init(); register_state_i386_x87_xmm(); build_x87_opcode_table(); @@ -4469,7 +4473,6 @@ void pentium4_device::device_start() void pentium4_device::device_reset() { zero_state(); - vtlb_flush_dynamic(m_vtlb); m_sreg[CS].selector = 0xf000; m_sreg[CS].base = 0xffff0000; diff --git a/src/devices/cpu/i386/i386.h b/src/devices/cpu/i386/i386.h index c9ef38b4280..979aaf08f45 100644 --- a/src/devices/cpu/i386/i386.h +++ b/src/devices/cpu/i386/i386.h @@ -8,7 +8,7 @@ #include "softfloat/milieu.h" #include "softfloat/softfloat.h" #include "debug/debugcpu.h" -#include "cpu/vtlb.h" +#include "divtlb.h" #define INPUT_LINE_A20 1 @@ -24,7 +24,7 @@ #define X86_NUM_CPUS 4 -class i386_device : public cpu_device +class i386_device : public cpu_device, public device_vtlb_interface { public: // construction/destruction @@ -270,8 +270,6 @@ struct I386_CALL_GATE UINT8 *m_cycle_table_pm; UINT8 *m_cycle_table_rm; - vtlb_state *m_vtlb; - bool m_smm; bool m_smi; bool m_smi_latched; @@ -1411,7 +1409,7 @@ struct I386_CALL_GATE void build_x87_opcode_table_df(); void build_x87_opcode_table(); void i386_postload(); - void i386_common_init(int tlbsize); + void i386_common_init(); void build_opcode_table(UINT32 features); void pentium_smi(); void zero_state(); diff --git a/src/devices/cpu/i386/i386ops.inc b/src/devices/cpu/i386/i386ops.inc index dc237c98469..ea15f9a5923 100644 --- a/src/devices/cpu/i386/i386ops.inc +++ b/src/devices/cpu/i386/i386ops.inc @@ -701,7 +701,7 @@ void i386_device::i386_mov_cr_r32() // Opcode 0x0f 22 case 2: CYCLES(CYCLES_MOV_REG_CR2); break; case 3: CYCLES(CYCLES_MOV_REG_CR3); - vtlb_flush_dynamic(m_vtlb); + vtlb_flush_dynamic(); break; case 4: CYCLES(1); break; // TODO default: diff --git a/src/devices/cpu/i386/i386priv.h b/src/devices/cpu/i386/i386priv.h index fa7ae0d4945..339e630d1cd 100644 --- a/src/devices/cpu/i386/i386priv.h +++ b/src/devices/cpu/i386/i386priv.h @@ -486,7 +486,7 @@ int i386_device::translate_address(int pl, int type, UINT32 *address, UINT32 *er if(!(m_cr[0] & 0x80000000)) // Some (very few) old OS's won't work with this return TRUE; - const vtlb_entry *table = vtlb_table(m_vtlb); + const vtlb_entry *table = vtlb_table(); UINT32 index = *address >> 12; vtlb_entry entry = table[index]; if(type == TRANSLATE_FETCH) @@ -506,7 +506,7 @@ int i386_device::translate_address(int pl, int type, UINT32 *address, UINT32 *er *error |= 1; return FALSE; } - vtlb_dynload(m_vtlb, index, *address, entry); + vtlb_dynload(index, *address, entry); return TRUE; } if(!(entry & (1 << type))) diff --git a/src/devices/cpu/i386/i486ops.inc b/src/devices/cpu/i386/i486ops.inc index d22f6c079c3..8be406692d4 100644 --- a/src/devices/cpu/i386/i486ops.inc +++ b/src/devices/cpu/i386/i486ops.inc @@ -312,7 +312,7 @@ void i386_device::i486_group0F01_16() // Opcode 0x0f 01 } ea = GetEA(modrm,-1); CYCLES(25); // TODO: add to cycles.h - vtlb_flush_address(m_vtlb, ea); + vtlb_flush_address(ea); break; } default: @@ -430,7 +430,7 @@ void i386_device::i486_group0F01_32() // Opcode 0x0f 01 } ea = GetEA(modrm,-1); CYCLES(25); // TODO: add to cycles.h - vtlb_flush_address(m_vtlb, ea); + vtlb_flush_address(ea); break; } default: @@ -500,12 +500,12 @@ void i386_device::i486_mov_cr_r32() // Opcode 0x0f 22 case 0: CYCLES(CYCLES_MOV_REG_CR0); if((oldcr ^ m_cr[cr]) & 0x80010000) - vtlb_flush_dynamic(m_vtlb); + vtlb_flush_dynamic(); break; case 2: CYCLES(CYCLES_MOV_REG_CR2); break; case 3: CYCLES(CYCLES_MOV_REG_CR3); - vtlb_flush_dynamic(m_vtlb); + vtlb_flush_dynamic(); break; case 4: CYCLES(1); break; // TODO default: diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp index f4747b7304c..711b9c3edf4 100644 --- a/src/devices/cpu/mips/mips3.cpp +++ b/src/devices/cpu/mips/mips3.cpp @@ -120,8 +120,10 @@ const device_type RM7000BE = &device_creator; const device_type RM7000LE = &device_creator; +// VR4300 and VR5432 have 4 fewer PFN bits, and only 32 TLB entries mips3_device::mips3_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, mips3_flavor flavor, endianness_t endianness) : cpu_device(mconfig, type, name, tag, owner, clock, shortname, __FILE__) + , device_vtlb_interface(mconfig, *this, AS_PROGRAM) , m_program_config("program", endianness, 32, 32, 0, 32, MIPS3_MIN_PAGE_SHIFT) , m_flavor(flavor) , m_core(nullptr) @@ -134,7 +136,6 @@ mips3_device::mips3_device(const machine_config &mconfig, device_type type, cons , m_ll_value(0) , m_lld_value(0) , m_badcop_value(0) - , m_tlb_table(nullptr) , m_lwl(endianness == ENDIANNESS_BIG ? &mips3_device::lwl_be : &mips3_device::lwl_le) , m_lwr(endianness == ENDIANNESS_BIG ? &mips3_device::lwr_be : &mips3_device::lwr_le) , m_swl(endianness == ENDIANNESS_BIG ? &mips3_device::swl_be : &mips3_device::swl_le) @@ -144,14 +145,13 @@ mips3_device::mips3_device(const machine_config &mconfig, device_type type, cons , m_sdl(endianness == ENDIANNESS_BIG ? &mips3_device::sdl_be : &mips3_device::sdl_le) , m_sdr(endianness == ENDIANNESS_BIG ? &mips3_device::sdr_be : &mips3_device::sdr_le) , c_system_clock(0) - , m_pfnmask(0) - , m_tlbentries(0) + , m_pfnmask(flavor == MIPS3_TYPE_VR4300 ? 0x000fffff : 0x00ffffff) + , m_tlbentries(flavor == MIPS3_TYPE_VR4300 ? 32 : MIPS3_MAX_TLB_ENTRIES) , m_bigendian(endianness == ENDIANNESS_BIG) , m_byte_xor(m_bigendian ? BYTE4_XOR_BE(0) : BYTE4_XOR_LE(0)) , m_word_xor(m_bigendian ? WORD_XOR_BE(0) : WORD_XOR_LE(0)) , c_icache_size(0) , c_dcache_size(0) - , m_vtlb(nullptr) , m_fastram_select(0) , m_debugger_temp(0) , m_cache(CACHE_SIZE + sizeof(internal_mips3_state)) @@ -190,17 +190,14 @@ mips3_device::mips3_device(const machine_config &mconfig, device_type type, cons } memset(m_fastram, 0, sizeof(m_fastram)); memset(m_hotspot, 0, sizeof(m_hotspot)); + + // configure the virtual TLB + set_vtlb_fixed_entries(2 * m_tlbentries + 2); } void mips3_device::device_stop() { - if (m_vtlb != nullptr) - { - vtlb_free(m_vtlb); - m_vtlb = nullptr; - } - if (m_drcfe != nullptr) { m_drcfe = nullptr; @@ -331,28 +328,12 @@ void mips3_device::device_start() m_program = &space(AS_PROGRAM); m_direct = &m_program->direct(); - /* configure flavor-specific parameters */ - m_pfnmask = 0x00ffffff; - m_tlbentries = MIPS3_MAX_TLB_ENTRIES; - - /* VR4300 and VR5432 have 4 fewer PFN bits, and only 32 TLB entries */ - if (m_flavor == MIPS3_TYPE_VR4300) - { - m_pfnmask = 0x000fffff; - m_tlbentries = 32; - } - /* set up the endianness */ m_program->accessors(m_memory); - /* allocate the virtual TLB */ - m_vtlb = vtlb_alloc(this, AS_PROGRAM, 2 * m_tlbentries + 2, 0); - /* allocate a timer for the compare interrupt */ m_compare_int_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(mips3_device::compare_int_callback), this)); - m_tlb_table = vtlb_table(m_vtlb); - UINT32 flags = 0; /* initialize the UML generator */ m_drcuml = std::make_unique(*this, m_cache, flags, 8, 32, 2); @@ -950,13 +931,13 @@ void mips3_device::device_reset() entry->entry_hi = 0xffffffff; entry->entry_lo[0] = 0xfffffff8; entry->entry_lo[1] = 0xfffffff8; - vtlb_load(m_vtlb, 2 * tlbindex + 0, 0, 0, 0); - vtlb_load(m_vtlb, 2 * tlbindex + 1, 0, 0, 0); + vtlb_load(2 * tlbindex + 0, 0, 0, 0); + vtlb_load(2 * tlbindex + 1, 0, 0, 0); } /* load the fixed TLB range */ - vtlb_load(m_vtlb, 2 * m_tlbentries + 0, (0xa0000000 - 0x80000000) >> MIPS3_MIN_PAGE_SHIFT, 0x80000000, 0x00000000 | VTLB_READ_ALLOWED | VTLB_WRITE_ALLOWED | VTLB_FETCH_ALLOWED | VTLB_FLAG_VALID); - vtlb_load(m_vtlb, 2 * m_tlbentries + 1, (0xc0000000 - 0xa0000000) >> MIPS3_MIN_PAGE_SHIFT, 0xa0000000, 0x00000000 | VTLB_READ_ALLOWED | VTLB_WRITE_ALLOWED | VTLB_FETCH_ALLOWED | VTLB_FLAG_VALID); + vtlb_load(2 * m_tlbentries + 0, (0xa0000000 - 0x80000000) >> MIPS3_MIN_PAGE_SHIFT, 0x80000000, 0x00000000 | VTLB_READ_ALLOWED | VTLB_WRITE_ALLOWED | VTLB_FETCH_ALLOWED | VTLB_FLAG_VALID); + vtlb_load(2 * m_tlbentries + 1, (0xc0000000 - 0xa0000000) >> MIPS3_MIN_PAGE_SHIFT, 0xa0000000, 0x00000000 | VTLB_READ_ALLOWED | VTLB_WRITE_ALLOWED | VTLB_FETCH_ALLOWED | VTLB_FLAG_VALID); m_core->mode = (MODE_KERNEL << 1) | 0; m_cache_dirty = TRUE; @@ -969,7 +950,7 @@ bool mips3_device::memory_translate(address_spacenum spacenum, int intention, of /* only applies to the program address space */ if (spacenum == AS_PROGRAM) { - const vtlb_entry *table = vtlb_table(m_vtlb); + const vtlb_entry *table = vtlb_table(); vtlb_entry entry = table[address >> MIPS3_MIN_PAGE_SHIFT]; if ((entry & (1 << (intention & (TRANSLATE_TYPE_MASK | TRANSLATE_USER_MASK)))) == 0) return false; @@ -998,7 +979,7 @@ offs_t mips3_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *op inline bool mips3_device::RBYTE(offs_t address, UINT32 *result) { - const UINT32 tlbval = m_tlb_table[address >> 12]; + const UINT32 tlbval = vtlb_table()[address >> 12]; if (tlbval & VTLB_READ_ALLOWED) { const UINT32 tlbaddress = (tlbval & ~0xfff) | (address & 0xfff); @@ -1031,7 +1012,7 @@ inline bool mips3_device::RBYTE(offs_t address, UINT32 *result) inline bool mips3_device::RHALF(offs_t address, UINT32 *result) { - const UINT32 tlbval = m_tlb_table[address >> 12]; + const UINT32 tlbval = vtlb_table()[address >> 12]; if (tlbval & VTLB_READ_ALLOWED) { const UINT32 tlbaddress = (tlbval & ~0xfff) | (address & 0xfff); @@ -1064,7 +1045,7 @@ inline bool mips3_device::RHALF(offs_t address, UINT32 *result) inline bool mips3_device::RWORD(offs_t address, UINT32 *result) { - const UINT32 tlbval = m_tlb_table[address >> 12]; + const UINT32 tlbval = vtlb_table()[address >> 12]; if (tlbval & VTLB_READ_ALLOWED) { const UINT32 tlbaddress = (tlbval & ~0xfff) | (address & 0xfff); @@ -1097,7 +1078,7 @@ inline bool mips3_device::RWORD(offs_t address, UINT32 *result) inline bool mips3_device::RWORD_MASKED(offs_t address, UINT32 *result, UINT32 mem_mask) { - const UINT32 tlbval = m_tlb_table[address >> 12]; + const UINT32 tlbval = vtlb_table()[address >> 12]; if (tlbval & VTLB_READ_ALLOWED) { *result = (*m_memory.read_dword_masked)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), mem_mask); @@ -1120,7 +1101,7 @@ inline bool mips3_device::RWORD_MASKED(offs_t address, UINT32 *result, UINT32 me inline bool mips3_device::RDOUBLE(offs_t address, UINT64 *result) { - const UINT32 tlbval = m_tlb_table[address >> 12]; + const UINT32 tlbval = vtlb_table()[address >> 12]; if (tlbval & VTLB_READ_ALLOWED) { *result = (*m_memory.read_qword)(*m_program, (tlbval & ~0xfff) | (address & 0xfff)); @@ -1143,7 +1124,7 @@ inline bool mips3_device::RDOUBLE(offs_t address, UINT64 *result) inline bool mips3_device::RDOUBLE_MASKED(offs_t address, UINT64 *result, UINT64 mem_mask) { - const UINT32 tlbval = m_tlb_table[address >> 12]; + const UINT32 tlbval = vtlb_table()[address >> 12]; if (tlbval & VTLB_READ_ALLOWED) { *result = (*m_memory.read_qword_masked)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), mem_mask); @@ -1166,7 +1147,7 @@ inline bool mips3_device::RDOUBLE_MASKED(offs_t address, UINT64 *result, UINT64 inline void mips3_device::WBYTE(offs_t address, UINT8 data) { - const UINT32 tlbval = m_tlb_table[address >> 12]; + const UINT32 tlbval = vtlb_table()[address >> 12]; if (tlbval & VTLB_WRITE_ALLOWED) { const UINT32 tlbaddress = (tlbval & ~0xfff) | (address & 0xfff); @@ -1200,7 +1181,7 @@ inline void mips3_device::WBYTE(offs_t address, UINT8 data) inline void mips3_device::WHALF(offs_t address, UINT16 data) { - const UINT32 tlbval = m_tlb_table[address >> 12]; + const UINT32 tlbval = vtlb_table()[address >> 12]; if (tlbval & VTLB_WRITE_ALLOWED) { const UINT32 tlbaddress = (tlbval & ~0xfff) | (address & 0xfff); @@ -1234,7 +1215,7 @@ inline void mips3_device::WHALF(offs_t address, UINT16 data) inline void mips3_device::WWORD(offs_t address, UINT32 data) { - const UINT32 tlbval = m_tlb_table[address >> 12]; + const UINT32 tlbval = vtlb_table()[address >> 12]; if (tlbval & VTLB_WRITE_ALLOWED) { const UINT32 tlbaddress = (tlbval & ~0xfff) | (address & 0xfff); @@ -1268,7 +1249,7 @@ inline void mips3_device::WWORD(offs_t address, UINT32 data) inline void mips3_device::WWORD_MASKED(offs_t address, UINT32 data, UINT32 mem_mask) { - const UINT32 tlbval = m_tlb_table[address >> 12]; + const UINT32 tlbval = vtlb_table()[address >> 12]; if (tlbval & VTLB_WRITE_ALLOWED) { (*m_memory.write_dword_masked)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), data, mem_mask); @@ -1292,7 +1273,7 @@ inline void mips3_device::WWORD_MASKED(offs_t address, UINT32 data, UINT32 mem_m inline void mips3_device::WDOUBLE(offs_t address, UINT64 data) { - const UINT32 tlbval = m_tlb_table[address >> 12]; + const UINT32 tlbval = vtlb_table()[address >> 12]; if (tlbval & VTLB_WRITE_ALLOWED) { (*m_memory.write_qword)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), data); @@ -1316,7 +1297,7 @@ inline void mips3_device::WDOUBLE(offs_t address, UINT64 data) inline void mips3_device::WDOUBLE_MASKED(offs_t address, UINT64 data, UINT64 mem_mask) { - const UINT32 tlbval = m_tlb_table[address >> 12]; + const UINT32 tlbval = vtlb_table()[address >> 12]; if (tlbval & VTLB_WRITE_ALLOWED) { (*m_memory.write_qword_masked)(*m_program, (tlbval & ~0xfff) | (address & 0xfff), data, mem_mask); diff --git a/src/devices/cpu/mips/mips3.h b/src/devices/cpu/mips/mips3.h index 9e0de9ed419..1715861bb89 100644 --- a/src/devices/cpu/mips/mips3.h +++ b/src/devices/cpu/mips/mips3.h @@ -15,7 +15,7 @@ #define __MIPS3_H__ -#include "cpu/vtlb.h" +#include "divtlb.h" #include "cpu/drcfe.h" #include "cpu/drcuml.h" #include "cpu/drcumlsh.h" @@ -245,7 +245,7 @@ struct compiler_state class mips3_frontend; -class mips3_device : public cpu_device +class mips3_device : public cpu_device, public device_vtlb_interface { friend class mips3_frontend; @@ -355,7 +355,6 @@ private: UINT32 m_ll_value; UINT64 m_lld_value; UINT32 m_badcop_value; - const vtlb_entry *m_tlb_table; /* endian-dependent load/store */ typedef void (mips3_device::*loadstore_func)(UINT32 op); @@ -389,7 +388,6 @@ private: size_t c_dcache_size; /* MMU */ - vtlb_state * m_vtlb; mips3_tlb_entry m_tlb[MIPS3_MAX_TLB_ENTRIES]; /* fast RAM */ diff --git a/src/devices/cpu/mips/mips3com.cpp b/src/devices/cpu/mips/mips3com.cpp index bcd6f6f349a..2fcf8de1844 100644 --- a/src/devices/cpu/mips/mips3com.cpp +++ b/src/devices/cpu/mips/mips3com.cpp @@ -325,8 +325,8 @@ void mips3_device::tlb_map_entry(int tlbindex) /* 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(m_vtlb, 2 * tlbindex + 0, 0, 0, 0); - vtlb_load(m_vtlb, 2 * tlbindex + 1, 0, 0, 0); + vtlb_load(2 * tlbindex + 0, 0, 0, 0); + vtlb_load(2 * tlbindex + 1, 0, 0, 0); return; } @@ -334,8 +334,8 @@ void mips3_device::tlb_map_entry(int tlbindex) vpn = ((entry->entry_hi >> 13) & 0x07ffffff) << 1; if (vpn >= (1 << (MIPS3_MAX_PADDR_SHIFT - MIPS3_MIN_PAGE_SHIFT))) { - vtlb_load(m_vtlb, 2 * tlbindex + 0, 0, 0, 0); - vtlb_load(m_vtlb, 2 * tlbindex + 1, 0, 0, 0); + vtlb_load(2 * tlbindex + 0, 0, 0, 0); + vtlb_load(2 * tlbindex + 1, 0, 0, 0); return; } @@ -369,9 +369,9 @@ void mips3_device::tlb_map_entry(int tlbindex) /* load the virtual TLB with the corresponding entries */ if ((effvpn + count) <= (0x80000000 >> MIPS3_MIN_PAGE_SHIFT) || effvpn >= (0xc0000000 >> MIPS3_MIN_PAGE_SHIFT)) - vtlb_load(m_vtlb, 2 * tlbindex + which, count, effvpn << MIPS3_MIN_PAGE_SHIFT, (pfn << MIPS3_MIN_PAGE_SHIFT) | flags); + vtlb_load(2 * tlbindex + which, count, effvpn << MIPS3_MIN_PAGE_SHIFT, (pfn << MIPS3_MIN_PAGE_SHIFT) | flags); else - vtlb_load(m_vtlb, 2 * tlbindex + which, 0, 0, 0); + vtlb_load(2 * tlbindex + which, 0, 0, 0); } } diff --git a/src/devices/cpu/mips/mips3com.h b/src/devices/cpu/mips/mips3com.h index 86d7f0c7a05..20facae78d0 100644 --- a/src/devices/cpu/mips/mips3com.h +++ b/src/devices/cpu/mips/mips3com.h @@ -14,7 +14,6 @@ #define __MIPS3COM_H__ #include "mips3.h" -#include "cpu/vtlb.h" /*************************************************************************** diff --git a/src/devices/cpu/mips/mips3drc.cpp b/src/devices/cpu/mips/mips3drc.cpp index 4e6e9771a38..7b6da3a1626 100644 --- a/src/devices/cpu/mips/mips3drc.cpp +++ b/src/devices/cpu/mips/mips3drc.cpp @@ -667,7 +667,7 @@ void mips3_device::static_generate_tlb_mismatch() UML_RECOVER(block, I0, MAPVAR_PC); // recover i0,PC UML_MOV(block, mem(&m_core->pc), I0); // mov ,i0 UML_SHR(block, I1, I0, 12); // shr i1,i0,12 - UML_LOAD(block, I1, (void *)vtlb_table(m_vtlb), I1, SIZE_DWORD, SCALE_x4);// load i1,[vtlb_table],i1,dword + UML_LOAD(block, I1, (void *)vtlb_table(), I1, SIZE_DWORD, SCALE_x4);// load i1,[vtlb_table],i1,dword if (PRINTF_MMU) { static const char text[] = "TLB mismatch @ %08X (ent=%08X)\n"; @@ -839,7 +839,7 @@ void mips3_device::static_generate_memory_accessor(int mode, int size, int iswri /* general case: assume paging and perform a translation */ UML_SHR(block, I3, I0, 12); // shr i3,i0,12 - UML_LOAD(block, I3, (void *)vtlb_table(m_vtlb), I3, SIZE_DWORD, SCALE_x4);// load i3,[vtlb_table],i3,dword + UML_LOAD(block, I3, (void *)vtlb_table(), I3, SIZE_DWORD, SCALE_x4);// load i3,[vtlb_table],i3,dword UML_TEST(block, I3, iswrite ? VTLB_WRITE_ALLOWED : VTLB_READ_ALLOWED);// test i3,iswrite ? VTLB_WRITE_ALLOWED : VTLB_READ_ALLOWED UML_JMPc(block, COND_Z, tlbmiss = label++); // jmp tlbmiss,z UML_ROLINS(block, I0, I3, 0, 0xfffff000); // rolins i0,i3,0,0xfffff000 @@ -1226,7 +1226,7 @@ void mips3_device::generate_sequence_instruction(drcuml_block *block, compiler_s /* 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(m_vtlb); + const vtlb_entry *tlbtable = vtlb_table(); /* if we currently have a valid TLB read entry, we just verify */ if (tlbtable[desc->pc >> 12] & VTLB_FETCH_ALLOWED) diff --git a/src/devices/cpu/powerpc/ppc.h b/src/devices/cpu/powerpc/ppc.h index 5e40ee88249..450b4ca2257 100644 --- a/src/devices/cpu/powerpc/ppc.h +++ b/src/devices/cpu/powerpc/ppc.h @@ -14,7 +14,7 @@ #ifndef __PPC_H__ #define __PPC_H__ -#include "cpu/vtlb.h" +#include "divtlb.h" #include "cpu/drcfe.h" #include "cpu/drcuml.h" #include "cpu/drcumlsh.h" @@ -171,7 +171,7 @@ enum class ppc_frontend; -class ppc_device : public cpu_device +class ppc_device : public cpu_device, public device_vtlb_interface { friend class ppc_frontend; @@ -462,9 +462,6 @@ protected: UINT32 m_sebr; UINT32 m_ser; - /* MMU */ - vtlb_state *m_vtlb; - /* architectural distinctions */ powerpc_flavor m_flavor; UINT32 m_cap; diff --git a/src/devices/cpu/powerpc/ppccom.cpp b/src/devices/cpu/powerpc/ppccom.cpp index 9036ff2c794..a9a26b29a5c 100644 --- a/src/devices/cpu/powerpc/ppccom.cpp +++ b/src/devices/cpu/powerpc/ppccom.cpp @@ -209,11 +209,11 @@ const device_type PPC405GP = &device_creator; ppc_device::ppc_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, int address_bits, int data_bits, powerpc_flavor flavor, UINT32 cap, UINT32 tb_divisor, address_map_constructor internal_map) : cpu_device(mconfig, type, name, tag, owner, clock, shortname, __FILE__) + , device_vtlb_interface(mconfig, *this, AS_PROGRAM) , m_program_config("program", ENDIANNESS_BIG, data_bits, address_bits, 0, internal_map) , c_bus_frequency(0) , m_core(nullptr) , m_bus_freq_multiplier(1) - , m_vtlb(nullptr) , m_flavor(flavor) , m_cap(cap) , m_tb_divisor(tb_divisor) @@ -224,6 +224,11 @@ ppc_device::ppc_device(const machine_config &mconfig, device_type type, const ch { m_program_config.m_logaddr_width = 32; m_program_config.m_page_shift = POWERPC_MIN_PAGE_SHIFT; + + // configure the virtual TLB + set_vtlb_dynamic_entries(POWERPC_TLB_ENTRIES); + if (m_cap & PPCCAP_603_MMU) + set_vtlb_fixed_entries(PPC603_FIXED_TLB_ENTRIES); } //ppc403_device::ppc403_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) @@ -708,9 +713,6 @@ void ppc_device::device_start() if (!(m_cap & PPCCAP_4XX) && space_config()->m_endianness != ENDIANNESS_NATIVE) m_codexor = 4; - /* allocate the virtual TLB */ - m_vtlb = vtlb_alloc(this, AS_PROGRAM, (m_cap & PPCCAP_603_MMU) ? PPC603_FIXED_TLB_ENTRIES : 0, POWERPC_TLB_ENTRIES); - /* allocate a timer for the compare interrupt */ if ((m_cap & PPCCAP_OEA) && (m_tb_divisor)) m_decrementer_int_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ppc_device::decrementer_int_callback), this)); @@ -1148,9 +1150,6 @@ void ppc_device::state_string_export(const device_state_entry &entry, std::strin void ppc_device::device_stop() { - if (m_vtlb != nullptr) - vtlb_free(m_vtlb); - m_vtlb = nullptr; } @@ -1199,12 +1198,11 @@ void ppc_device::device_reset() m_core->irq_pending = 0; /* flush the TLB */ - vtlb_flush_dynamic(m_vtlb); if (m_cap & PPCCAP_603_MMU) { for (int tlbindex = 0; tlbindex < PPC603_FIXED_TLB_ENTRIES; tlbindex++) { - vtlb_load(m_vtlb, tlbindex, 0, 0, 0); + vtlb_load(tlbindex, 0, 0, 0); } } @@ -1385,7 +1383,7 @@ UINT32 ppc_device::ppccom_translate_address_internal(int intention, offs_t &addr /* if we're simulating the 603 MMU, fill in the data and stop here */ if (m_cap & PPCCAP_603_MMU) { - UINT32 entry = vtlb_table(m_vtlb)[address >> 12]; + UINT32 entry = vtlb_table()[address >> 12]; m_core->mmu603_cmp = 0x80000000 | ((segreg & 0xffffff) << 7) | (0 << 6) | ((address >> 22) & 0x3f); m_core->mmu603_hash[0] = hashbase | ((hash << 6) & hashmask); m_core->mmu603_hash[1] = hashbase | ((~hash << 6) & hashmask); @@ -1465,7 +1463,7 @@ bool ppc_device::memory_translate(address_spacenum spacenum, int intention, offs void ppc_device::ppccom_tlb_fill() { - vtlb_fill(m_vtlb, m_core->param0, m_core->param1); + vtlb_fill(m_core->param0, m_core->param1); } @@ -1476,7 +1474,7 @@ void ppc_device::ppccom_tlb_fill() void ppc_device::ppccom_tlb_flush() { - vtlb_flush_dynamic(m_vtlb); + vtlb_flush_dynamic(); } @@ -1492,7 +1490,7 @@ void ppc_device::ppccom_tlb_flush() void ppc_device::ppccom_execute_tlbie() { - vtlb_flush_address(m_vtlb, m_core->param0); + vtlb_flush_address(m_core->param0); } @@ -1503,7 +1501,7 @@ void ppc_device::ppccom_execute_tlbie() void ppc_device::ppccom_execute_tlbia() { - vtlb_flush_dynamic(m_vtlb); + vtlb_flush_dynamic(); } @@ -1530,7 +1528,7 @@ void ppc_device::ppccom_execute_tlbl() flags |= VTLB_FETCH_ALLOWED; /* load the entry */ - vtlb_load(m_vtlb, entrynum, 1, address, (m_core->spr[SPR603_RPA] & 0xfffff000) | flags); + vtlb_load(entrynum, 1, address, (m_core->spr[SPR603_RPA] & 0xfffff000) | flags); } diff --git a/src/devices/cpu/powerpc/ppcdrc.cpp b/src/devices/cpu/powerpc/ppcdrc.cpp index ed502d344de..35b984d240d 100644 --- a/src/devices/cpu/powerpc/ppcdrc.cpp +++ b/src/devices/cpu/powerpc/ppcdrc.cpp @@ -743,11 +743,11 @@ void ppc_device::static_generate_tlb_mismatch() UML_HANDLE(block, *m_tlb_mismatch); // handle tlb_mismatch UML_RECOVER(block, I0, MAPVAR_PC); // recover i0,PC UML_SHR(block, I1, I0, 12); // shr i1,i0,12 - UML_LOAD(block, I2, (void *)vtlb_table(m_vtlb), I1, SIZE_DWORD, SCALE_x4); // load i2,[vtlb],i1,dword + UML_LOAD(block, I2, (void *)vtlb_table(), I1, SIZE_DWORD, SCALE_x4); // load i2,[vtlb],i1,dword UML_MOV(block, mem(&m_core->param0), I0); // mov [param0],i0 UML_MOV(block, mem(&m_core->param1), TRANSLATE_FETCH); // mov [param1],TRANSLATE_FETCH UML_CALLC(block, (c_function)cfunc_ppccom_tlb_fill, this); // callc tlbfill,ppc - UML_LOAD(block, I1, (void *)vtlb_table(m_vtlb), I1, SIZE_DWORD, SCALE_x4); // load i1,[vtlb],i1,dword + UML_LOAD(block, I1, (void *)vtlb_table(), I1, SIZE_DWORD, SCALE_x4); // load i1,[vtlb],i1,dword UML_TEST(block, I1, VTLB_FETCH_ALLOWED); // test i1,VTLB_FETCH_ALLOWED UML_JMPc(block, COND_Z, isi = label++); // jmp isi,z UML_CMP(block, I2, 0); // cmp i2,0 @@ -1021,7 +1021,7 @@ void ppc_device::static_generate_memory_accessor(int mode, int size, int iswrite if (((m_cap & PPCCAP_OEA) && (mode & MODE_DATA_TRANSLATION)) || (iswrite && (m_cap & PPCCAP_4XX) && (mode & MODE_PROTECTION))) { UML_SHR(block, I3, I0, 12); // shr i3,i0,12 - UML_LOAD(block, I3, (void *)vtlb_table(m_vtlb), I3, SIZE_DWORD, SCALE_x4);// load i3,[vtlb],i3,dword + UML_LOAD(block, I3, (void *)vtlb_table(), I3, SIZE_DWORD, SCALE_x4);// load i3,[vtlb],i3,dword UML_TEST(block, I3, (UINT64)1 << translate_type); // test i3,1 << translate_type UML_JMPc(block, COND_Z, tlbmiss = label++); // jmp tlbmiss,z UML_LABEL(block, tlbreturn = label++); // tlbreturn: @@ -1338,7 +1338,7 @@ void ppc_device::static_generate_memory_accessor(int mode, int size, int iswrite UML_MOV(block, mem(&m_core->param1), translate_type); // mov [param1],translate_type UML_CALLC(block, (c_function)cfunc_ppccom_tlb_fill, this); // callc tlbfill,ppc UML_SHR(block, I3, I0, 12); // shr i3,i0,12 - UML_LOAD(block, I3, (void *)vtlb_table(m_vtlb), I3, SIZE_DWORD, SCALE_x4);// load i3,[vtlb],i3,dword + UML_LOAD(block, I3, (void *)vtlb_table(), I3, SIZE_DWORD, SCALE_x4);// load i3,[vtlb],i3,dword UML_TEST(block, I3, (UINT64)1 << translate_type); // test i3,1 << translate_type UML_JMPc(block, COND_NZ, tlbreturn); // jmp tlbreturn,nz @@ -1703,7 +1703,7 @@ void ppc_device::generate_sequence_instruction(drcuml_block *block, compiler_sta /* validate our TLB entry at this PC; if we fail, we need to handle it */ if ((desc->flags & OPFLAG_VALIDATE_TLB) && (m_core->mode & MODE_DATA_TRANSLATION)) { - const vtlb_entry *tlbtable = vtlb_table(m_vtlb); + const vtlb_entry *tlbtable = vtlb_table(); /* if we currently have a valid TLB read entry, we just verify */ if (tlbtable[desc->pc >> 12] != 0) diff --git a/src/emu/dimemory.h b/src/emu/dimemory.h index 66561b5a5cf..0998fd4ae9a 100644 --- a/src/emu/dimemory.h +++ b/src/emu/dimemory.h @@ -131,22 +131,4 @@ typedef device_interface_iterator memory_interface_iter -//************************************************************************** -// INLINE HELPERS -//************************************************************************** - -//------------------------------------------------- -// device_get_space_config - return a pointer -// to sthe given address space's configuration -//------------------------------------------------- - -inline const address_space_config *device_get_space_config(const device_t &device, address_spacenum spacenum = AS_0) -{ - const device_memory_interface *intf; - if (!device.interface(intf)) - throw emu_fatalerror("Device '%s' does not have memory interface", device.tag()); - return intf->space_config(spacenum); -} - - #endif /* __DIMEMORY_H__ */ diff --git a/src/emu/divtlb.cpp b/src/emu/divtlb.cpp index 4c9a9a2f311..01be30919cb 100644 --- a/src/emu/divtlb.cpp +++ b/src/emu/divtlb.cpp @@ -2,309 +2,340 @@ // copyright-holders:Aaron Giles /*************************************************************************** - vtlb.c + divtlb.c - Generic virtual TLB implementation. + Device generic virtual TLB interface. ***************************************************************************/ #include "emu.h" -#include "vtlb.h" +#include "divtlb.h" +#include "validity.h" -/*************************************************************************** - DEBUGGING -***************************************************************************/ +//************************************************************************** +// DEBUGGING +//************************************************************************** #define PRINTF_TLB (0) -/*************************************************************************** - TYPE DEFINITIONS -***************************************************************************/ +//************************************************************************** +// DEVICE VTLB INTERFACE +//************************************************************************** -/* VTLB state */ -struct vtlb_state +//------------------------------------------------- +// device_vtlb_interface - constructor +//------------------------------------------------- + +device_vtlb_interface::device_vtlb_interface(const machine_config &mconfig, device_t &device, address_spacenum space) + : device_interface(device, "vtlb"), + m_space(space), + m_dynamic(0), + m_fixed(0), + m_dynindex(0), + m_pageshift(0), + m_addrwidth(0) { - cpu_device * cpudevice; /* CPU device */ - address_spacenum 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 */ - std::vector live; /* array of live entries by table index */ - std::vector fixedpages; /* number of pages each fixed entry covers */ - std::vector table; /* table of entries by address */ -}; - - - -/*************************************************************************** - INITIALIZATION/TEARDOWN -***************************************************************************/ - -/*------------------------------------------------- - vtlb_alloc - allocate a new VTLB for the - given CPU --------------------------------------------------*/ - -vtlb_state *vtlb_alloc(device_t *cpu, address_spacenum space, int fixed_entries, int dynamic_entries) -{ - vtlb_state *vtlb; - - /* allocate memory for the core structure */ - vtlb = auto_alloc_clear(cpu->machine(), ()); - - /* fill in CPU information */ - vtlb->cpudevice = downcast(cpu); - vtlb->space = space; - vtlb->dynamic = dynamic_entries; - vtlb->fixed = fixed_entries; - const address_space_config *spaceconfig = device_get_space_config(*cpu, space); - assert(spaceconfig != nullptr); - vtlb->pageshift = spaceconfig->m_page_shift; - vtlb->addrwidth = spaceconfig->m_logaddr_width; - - /* validate CPU information */ - assert((1 << vtlb->pageshift) > VTLB_FLAGS_MASK); - assert(vtlb->addrwidth > vtlb->pageshift); - - /* allocate the entry array */ - vtlb->live.resize(fixed_entries + dynamic_entries); - memset(&vtlb->live[0], 0, vtlb->live.size()*sizeof(vtlb->live[0])); - cpu->save_item(NAME(vtlb->live)); - - /* allocate the lookup table */ - vtlb->table.resize((size_t) 1 << (vtlb->addrwidth - vtlb->pageshift)); - memset(&vtlb->table[0], 0, vtlb->table.size()*sizeof(vtlb->table[0])); - cpu->save_item(NAME(vtlb->table)); - - /* allocate the fixed page count array */ - if (fixed_entries > 0) - { - vtlb->fixedpages.resize(fixed_entries); - memset(&vtlb->fixedpages[0], 0, fixed_entries*sizeof(vtlb->fixedpages[0])); - cpu->save_item(NAME(vtlb->fixedpages)); - } - return vtlb; } -/*------------------------------------------------- - vtlb_free - free an allocated VTLB --------------------------------------------------*/ +//------------------------------------------------- +// device_vtlb_interface - destructor +//------------------------------------------------- -void vtlb_free(vtlb_state *vtlb) +device_vtlb_interface::~device_vtlb_interface() { - auto_free(vtlb->cpudevice->machine(), vtlb); } +//------------------------------------------------- +// interface_validity_check - validation for a +// device after the configuration has been +// constructed +//------------------------------------------------- -/*************************************************************************** - 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) +void device_vtlb_interface::interface_validity_check(validity_checker &valid) const { - 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->cpudevice->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 */ + const device_memory_interface *intf; + if (!device().interface(intf)) + osd_printf_error("Device does not have memory interface\n"); else { - assert((entry >> vtlb->pageshift) == (taddress >> vtlb->pageshift)); - assert(entry & VTLB_FLAG_VALID); + // validate CPU information + const address_space_config *spaceconfig = intf->space_config(m_space); + if (spaceconfig == nullptr) + osd_printf_error("No memory address space configuration found for space %d\n", m_space); + else if ((1 << spaceconfig->m_page_shift) <= VTLB_FLAGS_MASK || spaceconfig->m_logaddr_width <= spaceconfig->m_page_shift) + osd_printf_error("Invalid page shift %d for VTLB\n", spaceconfig->m_page_shift); + } +} - if (PRINTF_TLB) - printf("success (%08X), existing entry\n", taddress); + +//------------------------------------------------- +// interface_pre_start - work to be done prior to +// actually starting a device +//------------------------------------------------- + +void device_vtlb_interface::interface_pre_start() +{ + // fill in CPU information + const address_space_config *spaceconfig = device().memory().space_config(m_space); + m_pageshift = spaceconfig->m_page_shift; + m_addrwidth = spaceconfig->m_logaddr_width; + + // allocate the entry array + m_live.resize(m_fixed + m_dynamic); + memset(&m_live[0], 0, m_live.size()*sizeof(m_live[0])); + + // allocate the lookup table + m_table.resize((size_t) 1 << (m_addrwidth - m_pageshift)); + memset(&m_table[0], 0, m_table.size()*sizeof(m_table[0])); + + // allocate the fixed page count array + if (m_fixed > 0) + { + m_fixedpages.resize(m_fixed); + memset(&m_fixedpages[0], 0, m_fixed*sizeof(m_fixedpages[0])); + } +} + + +//------------------------------------------------- +// interface_post_start - work to be done after +// actually starting a device +//------------------------------------------------- + +void device_vtlb_interface::interface_post_start() +{ + device().save_item(NAME(m_live)); + device().save_item(NAME(m_table)); + if (m_fixed > 0) + device().save_item(NAME(m_fixedpages)); +} + + +//------------------------------------------------- +// interface_pre_reset - work to be done prior to +// actually resetting a device +//------------------------------------------------- + +void device_vtlb_interface::interface_pre_reset() +{ + vtlb_flush_dynamic(); +} + + +//************************************************************************** +// FILLING +//************************************************************************** + +//------------------------------------------------- +// vtlb_fill - called by the CPU core in +// response to an unmapped access +//------------------------------------------------- + +int device_vtlb_interface::vtlb_fill(offs_t address, int intention) +{ + offs_t tableindex = address >> m_pageshift; + vtlb_entry entry = m_table[tableindex]; + offs_t taddress; + +#if PRINTF_TLB + osd_printf_debug("vtlb_fill: %08X(%X) ... ", address, intention); +#endif + + // 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 (m_dynamic == 0) + { +#if PRINTF_TLB + osd_printf_debug("failed: no dynamic entries\n"); +#endif + return FALSE; } - /* add the intention to the list of valid intentions and store */ + // ask the CPU core to translate for us + taddress = address; + if (!device().memory().translate(m_space, intention, taddress)) + { +#if PRINTF_TLB + osd_printf_debug("failed: no translation\n"); +#endif + return FALSE; + } + + // if this is the first successful translation for this address, allocate a new entry + if ((entry & VTLB_FLAGS_MASK) == 0) + { + int liveindex = m_dynindex++ % m_dynamic; + + // if an entry already exists at this index, free it + if (m_live[liveindex] != 0) + m_table[m_live[liveindex] - 1] = 0; + + // claim this new entry + m_live[liveindex] = tableindex + 1; + + // form a new blank entry + entry = (taddress >> m_pageshift) << m_pageshift; + entry |= VTLB_FLAG_VALID; + +#if PRINTF_TLB + osd_printf_debug("success (%08X), new entry\n", taddress); +#endif + } + + // otherwise, ensure that different intentions do not produce different addresses + else + { + assert((entry >> m_pageshift) == (taddress >> m_pageshift)); + assert(entry & VTLB_FLAG_VALID); + +#if PRINTF_TLB + osd_printf_debug("success (%08X), existing entry\n", taddress); +#endif + } + + // add the intention to the list of valid intentions and store entry |= 1 << (intention & (TRANSLATE_TYPE_MASK | TRANSLATE_USER_MASK)); - vtlb->table[tableindex] = entry; + m_table[tableindex] = entry; return TRUE; } -/*------------------------------------------------- - vtlb_load - load a fixed VTLB entry --------------------------------------------------*/ +//------------------------------------------------- +// vtlb_load - load a fixed VTLB entry +//------------------------------------------------- -void vtlb_load(vtlb_state *vtlb, int entrynum, int numpages, offs_t address, vtlb_entry value) +void device_vtlb_interface::vtlb_load(int entrynum, int numpages, offs_t address, vtlb_entry value) { - offs_t tableindex = address >> vtlb->pageshift; - int liveindex = vtlb->dynamic + entrynum; + offs_t tableindex = address >> m_pageshift; + int liveindex = m_dynamic + entrynum; int pagenum; - /* must be in range */ - assert(entrynum >= 0 && entrynum < vtlb->fixed); + // must be in range + assert(entrynum >= 0 && entrynum < m_fixed); - if (PRINTF_TLB) - printf("vtlb_load %d for %d pages at %08X == %08X\n", entrynum, numpages, address, value); +#if PRINTF_TLB + osd_printf_debug("vtlb_load %d for %d pages at %08X == %08X\n", entrynum, numpages, address, value); +#endif - /* if an entry already exists at this index, free it */ - if (vtlb->live[liveindex] != 0) + // if an entry already exists at this index, free it + if (m_live[liveindex] != 0) { - int pagecount = vtlb->fixedpages[entrynum]; - int oldtableindex = vtlb->live[liveindex] - 1; + int pagecount = m_fixedpages[entrynum]; + int oldtableindex = m_live[liveindex] - 1; for (pagenum = 0; pagenum < pagecount; pagenum++) - vtlb->table[oldtableindex + pagenum] = 0; + m_table[oldtableindex + pagenum] = 0; } - /* claim this new entry */ - vtlb->live[liveindex] = tableindex + 1; + // claim this new entry + m_live[liveindex] = tableindex + 1; - /* store the raw value, making sure the "fixed" flag is set */ + // store the raw value, making sure the "fixed" flag is set value |= VTLB_FLAG_FIXED; - vtlb->fixedpages[entrynum] = numpages; + m_fixedpages[entrynum] = numpages; for (pagenum = 0; pagenum < numpages; pagenum++) - vtlb->table[tableindex + pagenum] = value + (pagenum << vtlb->pageshift); + m_table[tableindex + pagenum] = value + (pagenum << m_pageshift); } -/*------------------------------------------------- - vtlb_dynload - load a dynamic VTLB entry --------------------------------------------------*/ +//------------------------------------------------- +// vtlb_dynload - load a dynamic VTLB entry +//------------------------------------------------- -void vtlb_dynload(vtlb_state *vtlb, UINT32 index, offs_t address, vtlb_entry value) +void device_vtlb_interface::vtlb_dynload(UINT32 index, offs_t address, vtlb_entry value) { - vtlb_entry entry = vtlb->table[index]; + vtlb_entry entry = m_table[index]; - if (vtlb->dynamic == 0) + if (m_dynamic == 0) { - if (PRINTF_TLB) - printf("failed: no dynamic entries\n"); +#if PRINTF_TLB + osd_printf_debug("failed: no dynamic entries\n"); +#endif return; } - int liveindex = vtlb->dynindex++ % vtlb->dynamic; - /* is entry already live? */ + int liveindex = m_dynindex++ % m_dynamic; + // is entry already live? if (!(entry & VTLB_FLAG_VALID)) { - /* if an entry already exists at this index, free it */ - if (vtlb->live[liveindex] != 0) - vtlb->table[vtlb->live[liveindex] - 1] = 0; + // if an entry already exists at this index, free it + if (m_live[liveindex] != 0) + m_table[m_live[liveindex] - 1] = 0; - /* claim this new entry */ - vtlb->live[liveindex] = index + 1; + // claim this new entry + m_live[liveindex] = index + 1; } - /* form a new blank entry */ - entry = (address >> vtlb->pageshift) << vtlb->pageshift; + // form a new blank entry + entry = (address >> m_pageshift) << m_pageshift; entry |= VTLB_FLAG_VALID | value; - if (PRINTF_TLB) - printf("success (%08X), new entry\n", address); - - vtlb->table[index] = entry; +#if PRINTF_TLB + osd_printf_debug("success (%08X), new entry\n", address); +#endif + m_table[index] = entry; } -/*************************************************************************** - FLUSHING -***************************************************************************/ +//************************************************************************** +// FLUSHING +//************************************************************************** -/*------------------------------------------------- - vtlb_flush_dynamic - flush all knowledge - from the dynamic part of the VTLB --------------------------------------------------*/ +//------------------------------------------------- +// vtlb_flush_dynamic - flush all knowledge +// from the dynamic part of the VTLB +//------------------------------------------------- -void vtlb_flush_dynamic(vtlb_state *vtlb) +void device_vtlb_interface::vtlb_flush_dynamic() { - int liveindex; +#if PRINTF_TLB + osd_printf_debug("vtlb_flush_dynamic\n"); +#endif - 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) + // loop over live entries and release them from the table + for (int liveindex = 0; liveindex < m_dynamic; liveindex++) + if (m_live[liveindex] != 0) { - offs_t tableindex = vtlb->live[liveindex] - 1; - vtlb->table[tableindex] = 0; - vtlb->live[liveindex] = 0; + offs_t tableindex = m_live[liveindex] - 1; + m_table[tableindex] = 0; + m_live[liveindex] = 0; } } -/*------------------------------------------------- - vtlb_flush_address - flush knowledge of a - particular address from the VTLB --------------------------------------------------*/ +//------------------------------------------------- +// vtlb_flush_address - flush knowledge of a +// particular address from the VTLB +//------------------------------------------------- -void vtlb_flush_address(vtlb_state *vtlb, offs_t address) +void device_vtlb_interface::vtlb_flush_address(offs_t address) { - offs_t tableindex = address >> vtlb->pageshift; + offs_t tableindex = address >> m_pageshift; - if (PRINTF_TLB) - printf("vtlb_flush_address %08X\n", address); +#if PRINTF_TLB + osd_printf_debug("vtlb_flush_address %08X\n", address); +#endif - /* free the entry in the table; for speed, we leave the entry in the live array */ - vtlb->table[tableindex] = 0; + // free the entry in the table; for speed, we leave the entry in the live array + m_table[tableindex] = 0; } -/*************************************************************************** - ACCESSORS -***************************************************************************/ +//************************************************************************** +// ACCESSORS +//************************************************************************** -/*------------------------------------------------- - vtlb_table - return a pointer to the base of - the linear VTLB lookup table --------------------------------------------------*/ +//------------------------------------------------- +// vtlb_table - return a pointer to the base of +// the linear VTLB lookup table +//------------------------------------------------- -const vtlb_entry *vtlb_table(vtlb_state *vtlb) +const vtlb_entry *device_vtlb_interface::vtlb_table() const { - return &vtlb->table[0]; + return &m_table[0]; } diff --git a/src/emu/divtlb.h b/src/emu/divtlb.h index f63a0ac50f6..eccd2947da3 100644 --- a/src/emu/divtlb.h +++ b/src/emu/divtlb.h @@ -2,7 +2,7 @@ // copyright-holders:Aaron Giles /*************************************************************************** - vtlb.h + divtlb.h Generic virtual TLB implementation. @@ -10,8 +10,8 @@ #pragma once -#ifndef __VTLB_H__ -#define __VTLB_H__ +#ifndef __DIVTLB_H__ +#define __DIVTLB_H__ @@ -40,49 +40,50 @@ typedef UINT32 vtlb_entry; -/* opaque structure describing VTLB state */ -struct vtlb_state; +// ======================> device_vtlb_interface +class device_vtlb_interface : public device_interface +{ +public: + // construction/destruction + device_vtlb_interface(const machine_config &mconfig, device_t &device, address_spacenum space); + virtual ~device_vtlb_interface(); + // configuration helpers + void set_vtlb_dynamic_entries(int entries) { m_dynamic = entries; } + void set_vtlb_fixed_entries(int entries) { m_fixed = entries; } -/*************************************************************************** - FUNCTION PROTOTYPES -***************************************************************************/ + // filling + int vtlb_fill(offs_t address, int intention); + void vtlb_load(int entrynum, int numpages, offs_t address, vtlb_entry value); + void vtlb_dynload(UINT32 index, offs_t address, vtlb_entry value); + // flushing + void vtlb_flush_dynamic(); + void vtlb_flush_address(offs_t address); -/* ----- initialization/teardown ----- */ + // accessors + const vtlb_entry *vtlb_table() const; -/* allocate a new VTLB for the given CPU */ -vtlb_state *vtlb_alloc(device_t *cpu, address_spacenum space, int fixed_entries, int dynamic_entries); +protected: + // interface-level overrides + virtual void interface_validity_check(validity_checker &valid) const override; + virtual void interface_pre_start() override; + virtual void interface_post_start() override; + virtual void interface_pre_reset() override; -/* 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); - -/* load a dynamic VTLB entry */ -void vtlb_dynload(vtlb_state *vtlb, UINT32 index, 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); +private: + // private state + address_spacenum m_space; // address space + int m_dynamic; // number of dynamic entries + int m_fixed; // number of fixed entries + int m_dynindex; // index of next dynamic entry + int m_pageshift; // bits to shift to get page index + int m_addrwidth; // logical address bus width + std::vector m_live; // array of live entries by table index + std::vector m_fixedpages; // number of pages each fixed entry covers + std::vector m_table; // table of entries by address +}; #endif /* __VTLB_H__ */