diff options
author | 2025-04-01 10:13:14 +1100 | |
---|---|---|
committer | 2025-04-01 10:13:14 +1100 | |
commit | 7efe37938f9dd6a366eda453af217c9993eb8442 (patch) | |
tree | c00ca39a2ba3fec4c233c85882df6bc3a877541b /src/devices/cpu/e132xs | |
parent | 4e80f6e0d920c089c83204dad1d58027de8c9216 (diff) |
-cpu/e132xs: Log bus control and memory control setup.
-cpu/drcbearm64.cpp: Simplified logic for choosing optimal AND strategy.
Diffstat (limited to 'src/devices/cpu/e132xs')
-rw-r--r-- | src/devices/cpu/e132xs/32xsdefs.h | 1 | ||||
-rw-r--r-- | src/devices/cpu/e132xs/e132xs.cpp | 154 | ||||
-rw-r--r-- | src/devices/cpu/e132xs/e132xs.h | 2 | ||||
-rw-r--r-- | src/devices/cpu/e132xs/e132xsdrc.cpp | 10 | ||||
-rw-r--r-- | src/devices/cpu/e132xs/e132xsdrc_ops.hxx | 19 |
5 files changed, 150 insertions, 36 deletions
diff --git a/src/devices/cpu/e132xs/32xsdefs.h b/src/devices/cpu/e132xs/32xsdefs.h index 4b75bcaf2af..9117d8ddb0b 100644 --- a/src/devices/cpu/e132xs/32xsdefs.h +++ b/src/devices/cpu/e132xs/32xsdefs.h @@ -24,6 +24,7 @@ enum { PC_REGISTER = 0, SR_REGISTER = 1, + FER_REGISTER = 2, SP_REGISTER = 18, UB_REGISTER = 19, BCR_REGISTER = 20, diff --git a/src/devices/cpu/e132xs/e132xs.cpp b/src/devices/cpu/e132xs/e132xs.cpp index 63e3cb6918b..22a1f8c3e0d 100644 --- a/src/devices/cpu/e132xs/e132xs.cpp +++ b/src/devices/cpu/e132xs/e132xs.cpp @@ -34,9 +34,11 @@ - All instructions should clear the H flag (not just MOV/MOVI) - Fix behaviour of branches in delay slots - Many wrong cycle counts + - Prevent reading write-only BCR, TPR, FCR and MCR + - IRAM selection should happen before EA calculation - No emulation of memory access latency and pipleline - Should a zero bit shift clear C or leave it unchanged? - - What actually happens on trying to load memory to PC or SR? + - What actually happens on trying to load to PC, SR, G14 or G15? - Verify register wrapping with sregf/dregf on hardware - Tracing doesn't work properly DRC does not generate trace exceptions on branch or return @@ -370,17 +372,16 @@ void hyperstone_device::adjust_timer_interrupt() if (cycles_until_next_clock == 0) cycles_until_next_clock = (uint64_t)(1 << m_core->clck_scale); - /* special case: if we have a change pending, set a timer to fire then */ if (TPR & 0x80000000) { + // special case: if we have a change pending, set a timer to fire then uint64_t clocks_until_int = m_core->tr_clocks_per_tick - (clocks_since_base % m_core->tr_clocks_per_tick); uint64_t cycles_until_int = (clocks_until_int << m_core->clck_scale) + cycles_until_next_clock; m_timer->adjust(cycles_to_attotime(cycles_until_int + 1), 1); } - - /* else if the timer interrupt is enabled, configure it to fire at the appropriate time */ else if (!(FCR & 0x00800000)) { + // else if the timer interrupt is enabled, configure it to fire at the appropriate time uint32_t curtr = m_core->tr_base_value + (clocks_since_base / m_core->tr_clocks_per_tick); uint32_t delta = TCR - curtr; if (delta > 0x80000000) @@ -395,10 +396,108 @@ void hyperstone_device::adjust_timer_interrupt() m_timer->adjust(cycles_to_attotime(cycles_until_int)); } } - - /* otherwise, disable the timer */ else + { + // otherwise, disable the timer m_timer->adjust(attotime::never); + } +} + +void hyperstone_device::update_bus_control() +{ + const uint32_t val = m_core->global_regs[BCR_REGISTER]; + + LOG("%s: Set BCR = 0x%08x\n", machine().describe_context(), val); + if (BIT(m_core->global_regs[MCR_REGISTER], 21)) + { + LOG("MEM0 access time %d cycles, hold time %d cycles, setup time %d cycles\n", + BIT(val, 16, 4) + 1, + BIT(val, 11, 3), + BIT(val, 14, 2)); + } + else + { + char const *const refresh[8] = { + "every 256 prescaler time units", + "every 128 prescaler time units", + "every 64 prescaler time units", + "every 32 prescaler time units", + "every 16 prescaler time units", + "every 8 prescaler time units", + "every 4 prescaler time units", + "disabled" }; + char const *const page[8] = { "64K", "32K", "16K", "8K", "4K", "2K", "1K", "512" }; + LOG("MEM0 RAS precharge time %d cycles, RAS to CAS delay time %d cycles, CAS access time %d cycles, %s byte rows, refresh %s\n", + BIT(val, 18, 2) + 1 + (BIT(m_core->global_regs[MCR_REGISTER], 8) * 2), + BIT(val, 14, 2) + 1, + BIT(val, 16, 2) + 1 + (BIT(m_core->global_regs[MCR_REGISTER], 8) * 2), + page[BIT(val, 4, 3)], + refresh[BIT(val, 11, 3)]); + } + LOG("MEM1 access time %d cycles, hold time %d cycles\n", + BIT(val, 20, 3) + 1, + BIT(val, 22) + BIT(val, 23)); + LOG("MEM2 access time %d cycles, hold time %d cycles, setup time %d cycles\n", + BIT(val, 24, 4) + 1, + BIT(val, 0, 3), + BIT(val, 3)); + LOG("MEM3 access time %d cycles, hold time %d cycles, setup time %d cycles\n", + BIT(val, 28, 4) + 1, + BIT(val, 8, 3), + BIT(val, 7)); + +} + +void hyperstone_device::update_memory_control() +{ + const uint32_t val = m_core->global_regs[MCR_REGISTER]; + + static char const *const entrymap[8] = { "MEM0", "MEM1", "MEM2", "IRAM", "reserved", "reserved", "reserved", "MEM3" }; + LOG("%s: Set MCR = 0x%08x entry map in %s\n", + machine().describe_context(), + val, + entrymap[BIT(val, 12, 3)]); + + static char const *const size[4] = { "32 bit", "reserved", "16 bit", "8 bit" }; + if (BIT(val, 21)) + { + LOG("MEM0 %s, bus hold break %s, parity %s, byte %s\n", + size[BIT(val, 0, 2)], // MEM0 bus size + BIT(val, 8) ? "disabled" : "enabled", // MEM0 bus hold break + BIT(val, 28) ? "disabled" : "enabled", // MEM0 parity + BIT(val, 15) ? "strobe" : "enable"); // MEM0 byte mode + } + else + { + static char const *const dramtype[4] = { "S", "S", "EDO ", "fast page " }; + LOG("MEM0 %s %sDRAM, hold time %s, parity %s\n", + size[BIT(val, 0, 2)], // MEM0 bus size + dramtype[bitswap<2>(val, 15, 22)], // MEM0 DRAM type + BIT(val, 8) ? "1 cycle" : "0 cycles", // MEM0 bus hold + BIT(val, 28) ? "disabled" : "enabled", // MEM0 parity + BIT(val, 15) ? "strobe" : "enable"); // MEM0 byte mode + } + LOG("MEM1 %s, bus hold break %s, parity %s, byte %s\n", + size[BIT(val, 2, 2)], // MEM1 bus size + BIT(val, 9) ? "disabled" : "enabled", // MEM1 bus hold break + BIT(val, 29) ? "disabled" : "enabled", // MEM1 parity + BIT(val, 19) ? "strobe" : "enable"); // MEM1 byte mode + LOG("MEM2 %s, bus hold break %s, parity %s, byte %s, wait %s\n", + size[BIT(val, 4, 2)], // MEM2 bus size + BIT(val, 10) ? "disabled" : "enabled", // MEM2 bus hold break + BIT(val, 30) ? "disabled" : "enabled", // MEM2 parity + BIT(val, 23) ? "strobe" : "enable", // MEM2 byte mode + BIT(val, 26) ? "disabled" : "enabled"); // MEM2 wait + LOG("MEM3 %s, bus hold break %s, parity %s\n", + size[BIT(val, 6, 2)], // MEM3 bus size + BIT(val, 11) ? "disabled" : "enabled", // MEM3 bus hold break + BIT(val, 31) ? "disabled" : "enabled"); // MEM3 parity + + + // bits 14..12 EntryTableMap + const int which = (val & 0x7000) >> 12; + assert(which < 4 || which == 7); + m_core->trap_entry = s_trap_entries[which]; } TIMER_CALLBACK_MEMBER( hyperstone_device::timer_callback ) @@ -460,7 +559,7 @@ uint32_t hyperstone_device::get_global_register(uint8_t code) */ if (code == TR_REGISTER) { - /* it is common to poll this in a loop */ + // it is common to poll this in a loop if (m_core->icount > m_core->tr_clocks_per_tick / 2) m_core->icount -= m_core->tr_clocks_per_tick / 2; compute_tr(); @@ -517,6 +616,7 @@ void hyperstone_device::set_global_register(uint8_t code, uint32_t val) return; case BCR_REGISTER: m_core->global_regs[code] = val; + update_bus_control(); return; case TPR_REGISTER: m_core->global_regs[code] = val; @@ -551,14 +651,9 @@ void hyperstone_device::set_global_register(uint8_t code, uint32_t val) m_core->global_regs[code] = val; return; case MCR_REGISTER: - { - // bits 14..12 EntryTableMap - const int which = (val & 0x7000) >> 12; - assert(which < 4 || which == 7); - m_core->trap_entry = s_trap_entries[which]; m_core->global_regs[code] = val; + update_memory_control(); return; - } case 28: case 29: case 30: @@ -1014,19 +1109,20 @@ void hyperstone_device::device_start() const uint32_t umlflags = 0; m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, umlflags, 4, 32, 1); - // add UML symbols- - m_drcuml->symbol_add(&m_core->global_regs[PC_REGISTER], sizeof(m_core->global_regs[PC_REGISTER]), "pc"); - m_drcuml->symbol_add(&m_core->global_regs[SR_REGISTER], sizeof(m_core->global_regs[SR_REGISTER]), "sr"); - m_drcuml->symbol_add(&m_core->global_regs[SP_REGISTER], sizeof(m_core->global_regs[SP_REGISTER]), "sp"); - m_drcuml->symbol_add(&m_core->global_regs[UB_REGISTER], sizeof(m_core->global_regs[UB_REGISTER]), "ub"); - m_drcuml->symbol_add(&m_core->trap_entry, sizeof(m_core->trap_entry), "trap_entry"); - m_drcuml->symbol_add(&m_core->delay_pc, sizeof(m_core->delay_pc), "delay_pc"); - m_drcuml->symbol_add(&m_core->delay_slot, sizeof(m_core->delay_slot), "delay_slot"); - m_drcuml->symbol_add(&m_core->delay_slot_taken, sizeof(m_core->delay_slot_taken), "delay_slot_taken"); - m_drcuml->symbol_add(&m_core->intblock, sizeof(m_core->intblock), "intblock"); - m_drcuml->symbol_add(&m_core->arg0, sizeof(m_core->arg0), "arg0"); - m_drcuml->symbol_add(&m_core->arg1, sizeof(m_core->arg1), "arg1"); - m_drcuml->symbol_add(&m_core->icount, sizeof(m_core->icount), "icount"); + // add UML symbols + m_drcuml->symbol_add(&m_core->global_regs[PC_REGISTER], sizeof(m_core->global_regs[PC_REGISTER]), "pc"); + m_drcuml->symbol_add(&m_core->global_regs[SR_REGISTER], sizeof(m_core->global_regs[SR_REGISTER]), "sr"); + m_drcuml->symbol_add(&m_core->global_regs[FER_REGISTER], sizeof(m_core->global_regs[FER_REGISTER]), "fer"); + m_drcuml->symbol_add(&m_core->global_regs[SP_REGISTER], sizeof(m_core->global_regs[SP_REGISTER]), "sp"); + m_drcuml->symbol_add(&m_core->global_regs[UB_REGISTER], sizeof(m_core->global_regs[UB_REGISTER]), "ub"); + m_drcuml->symbol_add(&m_core->trap_entry, sizeof(m_core->trap_entry), "trap_entry"); + m_drcuml->symbol_add(&m_core->delay_pc, sizeof(m_core->delay_pc), "delay_pc"); + m_drcuml->symbol_add(&m_core->delay_slot, sizeof(m_core->delay_slot), "delay_slot"); + m_drcuml->symbol_add(&m_core->delay_slot_taken, sizeof(m_core->delay_slot_taken), "delay_slot_taken"); + m_drcuml->symbol_add(&m_core->intblock, sizeof(m_core->intblock), "intblock"); + m_drcuml->symbol_add(&m_core->arg0, sizeof(m_core->arg0), "arg0"); + m_drcuml->symbol_add(&m_core->arg1, sizeof(m_core->arg1), "arg1"); + m_drcuml->symbol_add(&m_core->icount, sizeof(m_core->icount), "icount"); char buf[4]; buf[3] = '\0'; @@ -1227,9 +1323,9 @@ void hyperstone_device::device_reset() m_core->trap_entry = s_trap_entries[E132XS_ENTRY_MEM3]; // default entry point @ MEM3 - set_global_register(BCR_REGISTER, ~0); - set_global_register(MCR_REGISTER, ~0); - set_global_register(FCR_REGISTER, ~0); + set_global_register(BCR_REGISTER, ~uint32_t(0)); + set_global_register(MCR_REGISTER, ~uint32_t(0)); + set_global_register(FCR_REGISTER, ~uint32_t(0)); set_global_register(TPR_REGISTER, 0xc000000); PC = get_trap_addr(TRAPNO_RESET); diff --git a/src/devices/cpu/e132xs/e132xs.h b/src/devices/cpu/e132xs/e132xs.h index 27a5f896864..694c0aec2c7 100644 --- a/src/devices/cpu/e132xs/e132xs.h +++ b/src/devices/cpu/e132xs/e132xs.h @@ -258,6 +258,8 @@ protected: void update_timer_prescale(); void compute_tr(); void adjust_timer_interrupt(); + void update_bus_control(); + void update_memory_control(); void e116_16k_iram_map(address_map &map) ATTR_COLD; void e116_4k_iram_map(address_map &map) ATTR_COLD; diff --git a/src/devices/cpu/e132xs/e132xsdrc.cpp b/src/devices/cpu/e132xs/e132xsdrc.cpp index a943e95082d..b61255b98e8 100644 --- a/src/devices/cpu/e132xs/e132xsdrc.cpp +++ b/src/devices/cpu/e132xs/e132xsdrc.cpp @@ -86,6 +86,16 @@ struct hyperstone_device::c_funcs reinterpret_cast<hyperstone_device *>(param)->update_timer_prescale(); } + static void update_bus_control(void *param) + { + reinterpret_cast<hyperstone_device *>(param)->update_bus_control(); + } + + static void update_memory_control(void *param) + { + reinterpret_cast<hyperstone_device *>(param)->update_memory_control(); + } + #if E132XS_LOG_DRC_REGS || E132XS_LOG_INTERPRETER_REGS static void dump_registers(void *param) { diff --git a/src/devices/cpu/e132xs/e132xsdrc_ops.hxx b/src/devices/cpu/e132xs/e132xsdrc_ops.hxx index 19e7e3c50a2..a94e1cddd0d 100644 --- a/src/devices/cpu/e132xs/e132xsdrc_ops.hxx +++ b/src/devices/cpu/e132xs/e132xsdrc_ops.hxx @@ -212,7 +212,6 @@ void hyperstone_device::generate_set_global_register_high(drcuml_block &block, c { case 16: // G16 reserved case 17: // G17 reserved - case BCR_REGISTER: // G20 Bus Control Register case WCR_REGISTER: // G24 Watchdog Compare Register case 28: // G28 reserved case 29: // G29 reserved @@ -221,9 +220,15 @@ void hyperstone_device::generate_set_global_register_high(drcuml_block &block, c UML_MOV(block, mem(&m_core->global_regs[dst_code]), src); break; case SP_REGISTER: // G18 Stack Pointer + UML_MOV(block, mem(&m_core->global_regs[dst_code]), src); + break; case UB_REGISTER: // G19 Upper Stack Bound UML_AND(block, mem(&m_core->global_regs[dst_code]), src, ~uint32_t(3)); break; + case BCR_REGISTER: // G20 Bus Control Register + UML_MOV(block, mem(&m_core->global_regs[dst_code]), src); + UML_CALLC(block, &c_funcs::update_bus_control, this); + break; case TPR_REGISTER: // G21 Timer Prescaler Register { const int skip_compute_tr = compiler.next_label(); @@ -269,10 +274,8 @@ void hyperstone_device::generate_set_global_register_high(drcuml_block &block, c } break; case MCR_REGISTER: // G27 Memory Control Register - UML_ROLAND(block, I6, src, 20, 0x7); - UML_LOAD(block, I6, (void *)s_trap_entries, I6, SIZE_DWORD, SCALE_x4); - UML_MOV(block, mem(&m_core->trap_entry), I6); UML_MOV(block, mem(&m_core->global_regs[dst_code]), src); + UML_CALLC(block, &c_funcs::update_memory_control, this); break; default: throw emu_fatalerror("%s: invalid high global register G%u\n", dst_code); @@ -951,8 +954,10 @@ void hyperstone_device::generate_movd(drcuml_block &block, compiler_state &compi } else if (SrcGlobal && (src_code == SR_REGISTER)) // Rd doesn't denote PC and Rs denotes SR { - UML_OR(block, DRC_SR, DRC_SR, Z_MASK); - UML_AND(block, DRC_SR, DRC_SR, ~N_MASK); + UML_MOV(block, I2, DRC_SR); + UML_OR(block, I2, I2, Z_MASK); + UML_AND(block, I2, I2, ~N_MASK); + UML_MOV(block, DRC_SR, I2); if (DstGlobal) { generate_set_global_register_low(block, compiler, desc, dst_code, 0); @@ -960,7 +965,7 @@ void hyperstone_device::generate_movd(drcuml_block &block, compiler_state &compi } else { - UML_ROLAND(block, I0, DRC_SR, 32 - FP_SHIFT, 0x7f); + UML_ROLAND(block, I0, I2, 32 - FP_SHIFT, 0x7f); UML_ADD(block, I0, I0, dst_code); UML_AND(block, I0, I0, 0x3f); UML_STORE(block, (void *)m_core->local_regs, I0, 0, SIZE_DWORD, SCALE_x4); |