From 436431d99b4f2d8a502fd4fc911830ac0d237db5 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Thu, 3 Apr 2025 02:40:43 +1100 Subject: [PATCH] -cpu/e132xs: Miscellaneous fixes/optimisation: * Fixed behaviour of delayed branches, trace exceptions, and saved PC calculation for error exceptions in delay slots for the interpreter. All instructions in delay slots, branching instructions that can raise exceptions and tracing shoud now (mis)behave properly for the interpreter, including things the manual says you shouldn't do. * Fixed and optimised flag updates for left shifts for the recompiler. * Optimised ROL instruction for the recompiler and made flag calculation equivalent to the interpreter both with and without the "Missioncraft flags" compile-time option. * Only block interrupts for one instruction following a delayed branch. * Optimised the SOFTWARE instruction a little for the recompiler. * Added more SDRAM configuration logging and cleaned up code a bit. -cpu/drcbearm64.cpp: Apply the change from 7efe37938f9dd6a366e to OR and XOR instructions as well, and fix some cases where a 32-bit logical operation would fail to clear the upper bits of a register. -cpu/drcbex64.cpp: Avoid more conditional branches on conditional MOV. --- src/devices/cpu/drcbearm64.cpp | 108 +++++++---- src/devices/cpu/drcbex64.cpp | 43 +++-- src/devices/cpu/e132xs/e132xs.cpp | 126 +++++++------ src/devices/cpu/e132xs/e132xs.h | 6 +- src/devices/cpu/e132xs/e132xsdrc_ops.hxx | 218 ++++++++++++----------- src/devices/cpu/e132xs/e132xsop.hxx | 207 +++++++++++---------- 6 files changed, 412 insertions(+), 296 deletions(-) diff --git a/src/devices/cpu/drcbearm64.cpp b/src/devices/cpu/drcbearm64.cpp index db39f093383..c32d3067834 100644 --- a/src/devices/cpu/drcbearm64.cpp +++ b/src/devices/cpu/drcbearm64.cpp @@ -4091,6 +4091,7 @@ void drcbe_arm64::op_and(a64::Assembler &a, const uml::instruction &inst) } const a64::Gp dst = dstp.select_register(TEMP_REG3, inst.size()); + const a64::Gp src1 = src1p.select_register(dst, inst.size()); if (src1p.is_immediate_value(0) || src2p.is_immediate_value(0)) { @@ -4108,21 +4109,33 @@ void drcbe_arm64::op_and(a64::Assembler &a, const uml::instruction &inst) } else if (src2p.is_immediate() && is_valid_immediate_mask(src2p.immediate(), inst.size())) { - const a64::Gp src1 = src1p.select_register(dst, inst.size()); mov_reg_param(a, inst.size(), src1, src1p); a.emit(opcode, dst, src1, src2p.immediate()); } else if ((inst.size() == 8) && src2p.is_immediate() && is_valid_immediate_mask(src2p.immediate(), 4) && (!inst.flags() || !BIT(src2p.immediate(), 31))) { - const a64::Gp src1 = src1p.select_register(dst, inst.size()); mov_reg_param(a, inst.size(), src1, src1p); a.emit(opcode, dst.w(), src1.w(), src2p.immediate()); } + else if (src2p.is_immediate_value(util::make_bitmask(inst.size() * 8)) || (src1p == src2p)) + { + if ((dstp == src1p) && !inst.flags()) + { + if ((inst.size() == 8) || (dstp.is_memory() && !dstp.is_cold_register())) + return; + } + + mov_reg_param(a, inst.size(), src1, src1p); + + if ((dst.id() != src1.id()) || ((inst.size() == 4) && (dstp == src1p) && dstp.is_int_register())) + a.emit(opcode, dst, src1, src1); + else if (inst.flags()) + a.tst(dst, dst); + } else { - const a64::Gp src1 = src1p.select_register(dst, inst.size()); const a64::Gp src2 = src2p.select_register(TEMP_REG1, inst.size()); mov_reg_param(a, inst.size(), src1, src1p); mov_reg_param(a, inst.size(), src2, src2p); @@ -4194,35 +4207,45 @@ void drcbe_arm64::op_or(a64::Assembler &a, const uml::instruction &inst) be_parameter src1p(*this, inst.param(1), PTYPE_MRI); be_parameter src2p(*this, inst.param(2), PTYPE_MRI); - const a64::Gp src1 = src1p.select_register(TEMP_REG1, inst.size()); - const a64::Gp src2 = src2p.select_register(TEMP_REG2, inst.size()); + if (src1p.is_immediate() || (dstp.is_int_register() && (dstp == src2p))) + { + using std::swap; + swap(src1p, src2p); + } + const a64::Gp dst = dstp.select_register(TEMP_REG3, inst.size()); + const a64::Gp src1 = src1p.select_register(dst, inst.size()); if (src1p.is_immediate() && src2p.is_immediate()) { get_imm_relative(a, dst, src1p.immediate() | src2p.immediate()); } - else if (src2p.is_immediate() && is_valid_immediate_mask(src2p.immediate(), inst.size())) + else if (src2p.is_immediate_value(util::make_bitmask(inst.size() * 8))) + { + a.mov(dst, src2p.immediate()); + } + else if (src2p.is_immediate_value(0) || (src1p == src2p)) + { + if ((dstp == src1p) && !inst.flags()) + { + if ((inst.size() == 8) || (dstp.is_memory() && !dstp.is_cold_register())) + return; + } + + mov_reg_param(a, inst.size(), src1, src1p); + + if ((dst.id() != src1.id()) || ((inst.size() == 4) && (dstp == src1p) && dstp.is_int_register())) + a.mov(dst, src1); + } + else if (src2p.is_immediate() && is_valid_immediate(src2p.immediate(), 12)) { mov_reg_param(a, inst.size(), src1, src1p); - if (src2p.is_immediate_value(0)) - { - if (dst.id() != src1.id()) - a.mov(dst, src1); - } - else if (is_valid_immediate(src2p.immediate(), 12)) - { - a.orr(dst, src1, src2p.immediate()); - } - else - { - a.mov(SCRATCH_REG1, src2p.immediate()); - a.orr(dst, src1, select_register(SCRATCH_REG1, inst.size())); - } + a.orr(dst, src1, src2p.immediate()); } else { + const a64::Gp src2 = src2p.select_register(TEMP_REG1, inst.size()); mov_reg_param(a, inst.size(), src1, src1p); mov_reg_param(a, inst.size(), src2, src2p); @@ -4248,30 +4271,51 @@ void drcbe_arm64::op_xor(a64::Assembler &a, const uml::instruction &inst) be_parameter src1p(*this, inst.param(1), PTYPE_MRI); be_parameter src2p(*this, inst.param(2), PTYPE_MRI); - const a64::Gp src1 = src1p.select_register(TEMP_REG1, inst.size()); - const a64::Gp src2 = src2p.select_register(TEMP_REG2, inst.size()); + if (src1p.is_immediate() || (dstp.is_int_register() && (dstp == src2p))) + { + using std::swap; + swap(src1p, src2p); + } + const a64::Gp dst = dstp.select_register(TEMP_REG3, inst.size()); + const a64::Gp src1 = src1p.select_register(dst, inst.size()); if (src1p.is_immediate() && src2p.is_immediate()) { get_imm_relative(a, dst, src1p.immediate() ^ src2p.immediate()); } - else if (src2p.is_immediate() && is_valid_immediate_mask(src2p.immediate(), inst.size())) + else if (src2p.is_immediate_value(0)) + { + if ((dstp == src1p) && !inst.flags()) + { + if ((inst.size() == 8) || (dstp.is_memory() && !dstp.is_cold_register())) + return; + } + + mov_reg_param(a, inst.size(), src1, src1p); + + if ((dst.id() != src1.id()) || ((inst.size() == 4) && (dstp == src1p) && dstp.is_int_register())) + a.mov(dst, src1); + } + else if (src2p.is_immediate_value(util::make_bitmask(inst.size() * 8))) { mov_reg_param(a, inst.size(), src1, src1p); - if (src2p.is_immediate_value(0)) - { - if (dst.id() != src1.id()) - a.mov(dst, src1); - } - else - { - a.eor(dst, src1, src2p.immediate()); - } + a.mvn(dst, src1); + } + else (src2p.is_immediate() && is_valid_immediate_mask(src2p.immediate())) + { + mov_reg_param(a, inst.size(), src1, src1p); + + a.eor(dst, src1, src2p.immediate()); + } + else if (src1p == src2p) + { + a.mov(dst, select_register(a64::xzr, inst.size())); } else { + const a64::Gp src2 = src2p.select_register(TEMP_REG1, inst.size()); mov_reg_param(a, inst.size(), src1, src1p); mov_reg_param(a, inst.size(), src2, src2p); diff --git a/src/devices/cpu/drcbex64.cpp b/src/devices/cpu/drcbex64.cpp index 45d442e8576..f95a3700804 100644 --- a/src/devices/cpu/drcbex64.cpp +++ b/src/devices/cpu/drcbex64.cpp @@ -3661,26 +3661,28 @@ void drcbe_x64::op_mov(Assembler &a, const instruction &inst) // add a conditional branch unless a conditional move is possible Label skip; - if (inst.condition() != uml::COND_ALWAYS && !(dstp.is_int_register() && !srcp.is_immediate())) + const bool need_skip = (inst.condition() != uml::COND_ALWAYS) && !dstp.is_int_register(); + if (need_skip) { skip = a.newLabel(); a.short_().j(X86_NOT_CONDITION(inst.condition()), skip); } - // register to memory if (dstp.is_memory() && srcp.is_int_register()) { + // register to memory Gp const src = Gp::fromTypeAndId((inst.size() == 4) ? RegType::kX86_Gpd : RegType::kX86_Gpq, srcp.ireg()); a.mov(MABS(dstp.memory()), src); } - // immediate to memory else if (dstp.is_memory() && srcp.is_immediate() && short_immediate(srcp.immediate())) + { + // immediate to memory a.mov(MABS(dstp.memory(), inst.size()), s32(srcp.immediate())); - - // conditional memory to register + } else if (dstp.is_int_register() && srcp.is_memory()) { + // conditional memory to register Gp const dst = Gp::fromTypeAndId((inst.size() == 4) ? RegType::kX86_Gpd : RegType::kX86_Gpq, dstp.ireg()); if (inst.condition() != uml::COND_ALWAYS) @@ -3688,30 +3690,41 @@ void drcbe_x64::op_mov(Assembler &a, const instruction &inst) else a.mov(dst, MABS(srcp.memory())); } - - // conditional register to register - else if (dstp.is_int_register() && srcp.is_int_register()) + else if (dstp.is_int_register()) { - Gp const src = Gp::fromTypeAndId((inst.size() == 4) ? RegType::kX86_Gpd : RegType::kX86_Gpq, srcp.ireg()); + // conditional register to register Gp const dst = Gp::fromTypeAndId((inst.size() == 4) ? RegType::kX86_Gpd : RegType::kX86_Gpq, dstp.ireg()); if (inst.condition() != uml::COND_ALWAYS) - a.cmov(X86_CONDITION(inst.condition()), dst, src); + { + if (srcp.is_int_register()) + { + Gp const src = Gp::fromTypeAndId((inst.size() == 4) ? RegType::kX86_Gpd : RegType::kX86_Gpq, srcp.ireg()); + a.cmov(X86_CONDITION(inst.condition()), dst, src); + } + else + { + Gp const src = (inst.size() == 4) ? Gp(eax) : Gp(rax); + mov_reg_param(a, src, srcp, true); + a.cmov(X86_CONDITION(inst.condition()), dst, src); + } + } else - a.mov(dst, src); + { + mov_reg_param(a, dst, srcp, true); + } } - - // general case else { - Gp dstreg = (inst.size() == 4) ? dstp.select_register(eax) : dstp.select_register(rax); + // general case + Gp const dstreg = (inst.size() == 4) ? dstp.select_register(eax) : dstp.select_register(rax); mov_reg_param(a, dstreg, srcp, true); mov_param_reg(a, dstp, dstreg); } // resolve the jump - if (inst.condition() != uml::COND_ALWAYS && !(dstp.is_int_register() && !srcp.is_immediate())) + if (need_skip) a.bind(skip); } diff --git a/src/devices/cpu/e132xs/e132xs.cpp b/src/devices/cpu/e132xs/e132xs.cpp index 22a1f8c3e0d..97b25a1d6af 100644 --- a/src/devices/cpu/e132xs/e132xs.cpp +++ b/src/devices/cpu/e132xs/e132xs.cpp @@ -32,7 +32,7 @@ TODO: - All instructions should clear the H flag (not just MOV/MOVI) - - Fix behaviour of branches in delay slots + - Fix behaviour of branches in delay slots for recompiler - Many wrong cycle counts - Prevent reading write-only BCR, TPR, FCR and MCR - IRAM selection should happen before EA calculation @@ -40,7 +40,7 @@ - Should a zero bit shift clear C or leave it unchanged? - 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 + - Tracing doesn't work properly for the recompiler DRC does not generate trace exceptions on branch or return *********************************************************************/ @@ -453,7 +453,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", + LOG("%s: Set MCR = 0x%08x, entry map in %s\n", machine().describe_context(), val, entrymap[BIT(val, 12, 3)]); @@ -472,7 +472,7 @@ void hyperstone_device::update_memory_control() 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 + dramtype[bitswap<2>(val, 22, 15)], // 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 @@ -493,6 +493,13 @@ void hyperstone_device::update_memory_control() BIT(val, 11) ? "disabled" : "enabled", // MEM3 bus hold break BIT(val, 31) ? "disabled" : "enabled"); // MEM3 parity + // install SDRAM mode and control handlers if appropriate + if (!BIT(val, 21) && !BIT(val, 22)) + { + m_program->unmap_read(0x20000000, 0x3fffffff); + m_program->install_write_handler(0x20000000, 0x2fffffff, emu::rw_delegate(*this, FUNC(hyperstone_device::sdram_mode_w))); + m_program->install_write_handler(0x30000000, 0x3fffffff, emu::rw_delegate(*this, FUNC(hyperstone_device::sdram_control_w))); + } // bits 14..12 EntryTableMap const int which = (val & 0x7000) >> 12; @@ -500,6 +507,24 @@ void hyperstone_device::update_memory_control() m_core->trap_entry = s_trap_entries[which]; } +void hyperstone_device::sdram_mode_w(offs_t offset, uint32_t data) +{ + // writes to mode register of the connected SDRAM + LOG("%s: set SDRAM mode = 0x%07x\n", machine().describe_context(), offset); +} + +void hyperstone_device::sdram_control_w(offs_t offset, uint32_t data) +{ + const uint32_t val = offset << 2; + LOG("%s: set SDCR = 0x%08x\n", machine().describe_context(), val); + LOG("MEM0 SDRAM bank bits 0x%08x, second SDRAM chip select CS#1 %s, A%u selects CS#0/CS#1, CAS latency %s, SDCLK CPU clock%s\n", + BIT(val, 12, 9) << 20, + BIT(val, 11) ? "disabled" : "enabled", + BIT(val, 8, 3) + 21, + BIT(val, 6) ? "2 clock cycles" : "1 clock cycle", + BIT(val, 3) ? " / 2" : ""); +} + TIMER_CALLBACK_MEMBER( hyperstone_device::timer_callback ) { int update = param; @@ -671,26 +696,27 @@ void hyperstone_device::set_global_register(uint8_t code, uint32_t val) constexpr uint32_t WRITE_ONLY_REGMASK = (1 << BCR_REGISTER) | (1 << TPR_REGISTER) | (1 << FCR_REGISTER) | (1 << MCR_REGISTER); -#define check_delay_PC() \ -do \ -{ \ - /* if PC is used in a delay instruction, the delayed PC should be used */ \ - if (m_core->delay_slot) \ - { \ - using std::swap; \ - swap(PC, m_core->delay_pc); \ - m_core->delay_slot = 0; \ - m_core->delay_slot_taken = 1; \ - } \ - else \ - { \ - m_core->delay_slot_taken = 0; \ - } \ -} while (0) +inline ATTR_FORCE_INLINE void hyperstone_device::check_delay_pc() +{ + // if PC is used in a delay instruction, the delayed PC should be used + if (!m_core->delay_slot) + { + m_core->delay_slot_taken = 0; + } + else + { + using std::swap; + swap(PC, m_core->delay_pc); + m_core->delay_slot = 0; + m_core->delay_slot_taken = 1; + } +} void hyperstone_device::ignore_immediate_s() { - static const uint32_t lengths[16] = { 1<<19, 3<<19, 2<<19, 2<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19, 1<<19 }; + static const uint32_t lengths[16] = { + 1 << ILC_SHIFT, 3 << ILC_SHIFT, 2 << ILC_SHIFT, 2 << ILC_SHIFT, 1 << ILC_SHIFT, 1 << ILC_SHIFT, 1 << ILC_SHIFT, 1 << ILC_SHIFT, + 1 << ILC_SHIFT, 1 << ILC_SHIFT, 1 << ILC_SHIFT, 1 << ILC_SHIFT, 1 << ILC_SHIFT, 1 << ILC_SHIFT, 1 << ILC_SHIFT, 1 << ILC_SHIFT }; static const uint32_t offsets[16] = { 0, 4, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const uint8_t nybble = m_op & 0x0f; m_instruction_length = lengths[nybble]; @@ -706,21 +732,21 @@ uint32_t hyperstone_device::decode_immediate_s() return 16; case 1: { - m_instruction_length = (3<<19); + m_instruction_length = 3 << ILC_SHIFT; uint32_t extra_u = (m_pr16(PC) << 16) | m_pr16(PC + 2); PC += 4; return extra_u; } case 2: { - m_instruction_length = (2<<19); + m_instruction_length = 2 << ILC_SHIFT; uint32_t extra_u = m_pr16(PC); PC += 2; return extra_u; } case 3: { - m_instruction_length = (2<<19); + m_instruction_length = 2 << ILC_SHIFT; uint32_t extra_u = 0xffff0000 | m_pr16(PC); PC += 2; return extra_u; @@ -741,7 +767,7 @@ uint32_t hyperstone_device::decode_const() const uint16_t imm_2 = m_pr16(PC); PC += 2; - m_instruction_length = (3<<19); + m_instruction_length = 3 << ILC_SHIFT; uint32_t imm = imm_2; imm |= ((imm_1 & 0x3fff) << 16); @@ -752,7 +778,7 @@ uint32_t hyperstone_device::decode_const() } else { - m_instruction_length = (2<<19); + m_instruction_length = 2 << ILC_SHIFT; uint32_t imm = imm_1 & 0x3fff; @@ -769,7 +795,7 @@ int32_t hyperstone_device::decode_pcrel() uint16_t next = m_pr16(PC); PC += 2; - m_instruction_length = (2<<19); + m_instruction_length = 2 << ILC_SHIFT; int32_t offset = (OP & 0x7f) << 16; offset |= (next & 0xfffe); @@ -790,26 +816,15 @@ int32_t hyperstone_device::decode_pcrel() } } -void hyperstone_device::ignore_pcrel() +inline void hyperstone_device::ignore_pcrel() { if (m_op & 0x80) { PC += 2; - m_instruction_length = (2<<19); + m_instruction_length = 2 << ILC_SHIFT; } } -void hyperstone_device::hyperstone_br() -{ - const int32_t offset = decode_pcrel(); - check_delay_PC(); - - PC += offset; - SR &= ~M_MASK; - - m_core->icount -= m_core->clock_cycles_2; -} - void hyperstone_device::execute_trap(uint8_t trapno) { debugger_exception_hook(int(unsigned(trapno))); @@ -864,7 +879,7 @@ void hyperstone_device::execute_exception(uint8_t trapno) if (!m_core->delay_slot_taken) SET_ILC(m_instruction_length); else - PC = m_core->delay_pc; + PC = m_core->delay_pc - (m_instruction_length >> ILC_SHIFT); // RET does not automatically set P if (((m_op & 0xfef0) != 0x0400) || !(m_op & 0x010e)) @@ -888,14 +903,14 @@ void hyperstone_device::execute_exception(uint8_t trapno) void hyperstone_device::execute_software() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SRC_CODE; const uint32_t sreg = m_core->local_regs[(src_code + fp) & 0x3f]; const uint32_t sregf = m_core->local_regs[(src_code + 1 + fp) & 0x3f]; - SET_ILC(1<<19); + SET_ILC(1 << ILC_SHIFT); const uint32_t addr = get_emu_code_addr((m_op & 0xff00) >> 8); const uint8_t reg = fp + GET_FL; @@ -943,7 +958,7 @@ void hyperstone_device::execute_software() #define IO2_LINE_STATE (ISR & 0x20) #define IO3_LINE_STATE (ISR & 0x40) -template +template void hyperstone_device::check_interrupts() { // Interrupt-Lock flag isn't set @@ -951,7 +966,7 @@ void hyperstone_device::check_interrupts() return; // quick exit if nothing - if (TIMER == NO_TIMER && (ISR & 0x7f) == 0) + if (Timer == NO_TIMER && (ISR & 0x7f) == 0) return; // IO3 is priority 5; state is in bit 6 of ISR; FCR bit 10 enables input and FCR bit 8 inhibits interrupt @@ -963,7 +978,7 @@ void hyperstone_device::check_interrupts() } // timer int might be priority 6 if FCR bits 20-21 == 3; FCR bit 23 inhibits interrupt - if (TIMER && (FCR & 0x00b00000) == 0x00300000) + if (Timer && (FCR & 0x00b00000) == 0x00300000) { m_core->timer_int_pending = 0; execute_int(get_trap_addr(TRAPNO_TIMER)); @@ -979,7 +994,7 @@ void hyperstone_device::check_interrupts() } // timer int might be priority 8 if FCR bits 20-21 == 2; FCR bit 23 inhibits interrupt - if (TIMER && (FCR & 0x00b00000) == 0x00200000) + if (Timer && (FCR & 0x00b00000) == 0x00200000) { m_core->timer_int_pending = 0; execute_int(get_trap_addr(TRAPNO_TIMER)); @@ -995,7 +1010,7 @@ void hyperstone_device::check_interrupts() } // timer int might be priority 10 if FCR bits 20-21 == 1; FCR bit 23 inhibits interrupt - if (TIMER && (FCR & 0x00b00000) == 0x00100000) + if (Timer && (FCR & 0x00b00000) == 0x00100000) { m_core->timer_int_pending = 0; execute_int(get_trap_addr(TRAPNO_TIMER)); @@ -1011,7 +1026,7 @@ void hyperstone_device::check_interrupts() } // timer int might be priority 12 if FCR bits 20-21 == 0; FCR bit 23 inhibits interrupt - if (TIMER && (FCR & 0x00b00000) == 0x00000000) + if (Timer && (FCR & 0x00b00000) == 0x00000000) { m_core->timer_int_pending = 0; execute_int(get_trap_addr(TRAPNO_TIMER)); @@ -1323,8 +1338,10 @@ void hyperstone_device::device_reset() m_core->trap_entry = s_trap_entries[E132XS_ENTRY_MEM3]; // default entry point @ MEM3 - set_global_register(BCR_REGISTER, ~uint32_t(0)); - set_global_register(MCR_REGISTER, ~uint32_t(0)); + m_core->global_regs[BCR_REGISTER] = ~uint32_t(0); + m_core->global_regs[MCR_REGISTER] = ~uint32_t(0); + update_bus_control(); + update_memory_control(); set_global_register(FCR_REGISTER, ~uint32_t(0)); set_global_register(TPR_REGISTER, 0xc000000); @@ -1337,7 +1354,7 @@ void hyperstone_device::device_reset() SET_T(0); SET_L(1); SET_S(1); - SET_ILC(1<<19); + SET_ILC(1 << ILC_SHIFT); set_local_register(0, (PC & 0xfffffffe) | GET_S); set_local_register(1, SR); @@ -1492,7 +1509,7 @@ void hyperstone_device::hyperstone_trap() false, false, false, false, true, false, true, false, true, false, true, false, true, false, true, false }; - check_delay_PC(); + check_delay_pc(); const uint8_t trapno = (m_op & 0xfc) >> 2; const uint8_t code = ((m_op & 0x300) >> 6) | (m_op & 0x03); @@ -1910,7 +1927,10 @@ void hyperstone_device::execute_run() } if (GET_T && GET_P && !m_core->delay_slot) /* Not in a Delayed Branch instructions */ + { + m_core->delay_slot_taken = 0; execute_exception(TRAPNO_TRACE_EXCEPTION); + } } } diff --git a/src/devices/cpu/e132xs/e132xs.h b/src/devices/cpu/e132xs/e132xs.h index 694c0aec2c7..f38343c9bca 100644 --- a/src/devices/cpu/e132xs/e132xs.h +++ b/src/devices/cpu/e132xs/e132xs.h @@ -261,6 +261,9 @@ protected: void update_bus_control(); void update_memory_control(); + void sdram_mode_w(offs_t offset, uint32_t data); + void sdram_control_w(offs_t offset, uint32_t data); + void e116_16k_iram_map(address_map &map) ATTR_COLD; void e116_4k_iram_map(address_map &map) ATTR_COLD; void e116_8k_iram_map(address_map &map) ATTR_COLD; @@ -299,7 +302,7 @@ protected: private: // internal functions - template void check_interrupts(); + template void check_interrupts(); void set_global_register(uint8_t code, uint32_t val); void set_local_register(uint8_t code, uint32_t val); @@ -315,6 +318,7 @@ private: TIMER_CALLBACK_MEMBER(timer_callback); + void check_delay_pc(); uint32_t decode_const(); uint32_t decode_immediate_s(); void ignore_immediate_s(); diff --git a/src/devices/cpu/e132xs/e132xsdrc_ops.hxx b/src/devices/cpu/e132xs/e132xsdrc_ops.hxx index a94e1cddd0d..3bba381da1e 100644 --- a/src/devices/cpu/e132xs/e132xsdrc_ops.hxx +++ b/src/devices/cpu/e132xs/e132xsdrc_ops.hxx @@ -733,39 +733,27 @@ void hyperstone_device::generate_software(drcuml_block &block, compiler_state &c const uint16_t op = desc->opptr.w[0]; + const uint32_t num = op >> 8; const uint32_t src_code = op & 0xf; - const uint32_t srcf_code = src_code + 1; const uint32_t dst_code = (op & 0xf0) >> 4; - UML_ROLAND(block, I3, DRC_SR, 32 - FP_SHIFT, 0x7f); // I3 = FP + UML_MOV(block, I2, DRC_SR); + UML_ROLAND(block, I3, I2, 32 - FP_SHIFT, 0x7f); // I3 = FP - UML_ADD(block, I2, I3, src_code); - UML_AND(block, I4, I2, 0x3f); - UML_LOAD(block, I0, (void *)m_core->local_regs, I4, SIZE_DWORD, SCALE_x4); // I0 = sreg - UML_ADD(block, I2, I3, srcf_code); - UML_AND(block, I4, I2, 0x3f); - UML_LOAD(block, I1, (void *)m_core->local_regs, I4, SIZE_DWORD, SCALE_x4); // I1 = sregf + UML_ADD(block, I1, I3, src_code); + UML_AND(block, I1, I1, 0x3f); + UML_LOAD(block, I0, (void *)m_core->local_regs, I1, SIZE_DWORD, SCALE_x4); // I0 = sreg + UML_ADD(block, I1, I1, 1); + UML_AND(block, I1, I1, 0x3f); + UML_LOAD(block, I1, (void *)m_core->local_regs, I1, SIZE_DWORD, SCALE_x4); // I1 = sregf - UML_ROLINS(block, DRC_SR, 1, ILC_SHIFT, ILC_MASK); + UML_AND(block, I2, I2, ~ILC_MASK); + UML_OR(block, I2, I2, 1 << ILC_SHIFT); + UML_MOV(block, DRC_SR, I2); - uint32_t num = op >> 8; - int mem3 = compiler.next_label(); - int have_code_addr = compiler.next_label(); - UML_MOV(block, I4, mem(&m_core->trap_entry)); - UML_CMP(block, I4, 0xffffff00); - UML_JMPc(block, uml::COND_E, mem3); - UML_OR(block, I5, I4, (0x10c | ((0xcf - num) << 4))); - UML_JMP(block, have_code_addr); - - UML_LABEL(block, mem3); - UML_SUB(block, I5, I4, 0x100); - UML_OR(block, I5, I5, ((num & 0xf) << 4)); // I5 = addr - - UML_LABEL(block, have_code_addr); - - UML_ROLAND(block, I2, DRC_SR, 32 - FL_SHIFT, 0xf); - UML_MOVc(block, uml::COND_Z, I2, 16); - UML_ADD(block, I4, I2, I3); // I4 = reg + UML_ROLAND(block, I4, I2, 32 - FL_SHIFT, 0xf); + UML_MOVc(block, uml::COND_Z, I4, 16); + UML_ADD(block, I4, I4, I3); // I4 = reg UML_AND(block, I2, mem(&SP), 0xffffff00); UML_ADD(block, I6, I2, 0x100); // I6 = (SP & ~0xff) + 0x100 @@ -776,31 +764,44 @@ void hyperstone_device::generate_software(drcuml_block &block, compiler_state &c UML_AND(block, I2, I4, 0x3f); UML_STORE(block, (void *)m_core->local_regs, I2, I6, SIZE_DWORD, SCALE_x4); // m_core->local_regs[(reg + 0) & 0x3f] = stack_of_dst; - UML_ADD(block, I6, I2, 1); - UML_AND(block, I2, I6, 0x3f); + UML_ADD(block, I2, I2, 1); + UML_AND(block, I2, I2, 0x3f); UML_STORE(block, (void *)m_core->local_regs, I2, I0, SIZE_DWORD, SCALE_x4); // m_core->local_regs[(reg + 1) & 0x3f] = sreg; - UML_ADD(block, I6, I2, 1); - UML_AND(block, I2, I6, 0x3f); + UML_ADD(block, I2, I2, 1); + UML_AND(block, I2, I2, 0x3f); UML_STORE(block, (void *)m_core->local_regs, I2, I1, SIZE_DWORD, SCALE_x4); // m_core->local_regs[(reg + 2) & 0x3f] = sregf; UML_AND(block, I0, DRC_PC, ~uint32_t(1)); UML_ROLINS(block, I0, DRC_SR, 32 - S_SHIFT, 1); - UML_ADD(block, I6, I2, 1); - UML_AND(block, I2, I6, 0x3f); + UML_ADD(block, I2, I2, 1); + UML_AND(block, I2, I2, 0x3f); UML_STORE(block, (void *)m_core->local_regs, I2, I0, SIZE_DWORD, SCALE_x4); // m_core->local_regs[(reg + 3) & 0x3f] = (PC & ~1) | GET_S; - UML_ADD(block, I6, I2, 1); - UML_AND(block, I2, I6, 0x3f); + UML_ADD(block, I2, I2, 1); + UML_AND(block, I2, I2, 0x3f); UML_STORE(block, (void *)m_core->local_regs, I2, DRC_SR, SIZE_DWORD, SCALE_x4); // m_core->local_regs[(reg + 4) & 0x3f] = oldSR; - UML_MOV(block, DRC_PC, I5); // PC = addr + const int mem3 = compiler.next_label(); + const int have_code_addr = compiler.next_label(); + UML_MOV(block, I1, mem(&m_core->trap_entry)); + UML_CMP(block, I1, 0xffffff00); + UML_JMPc(block, uml::COND_E, mem3); + UML_OR(block, I1, I1, (0x10c | ((0xcf - num) << 4))); + UML_JMP(block, have_code_addr); + + UML_LABEL(block, mem3); + UML_SUB(block, I1, I1, 0x100); + UML_OR(block, I1, I1, ((num & 0xf) << 4)); + + UML_LABEL(block, have_code_addr); + UML_MOV(block, DRC_PC, I1); // PC = addr UML_MOV(block, I0, DRC_SR); UML_ROLINS(block, I0, (6 << FL_SHIFT) | L_MASK, 0, FL_MASK | T_MASK | L_MASK | M_MASK); // FL = 6, T = 0, L = 1, M = 0 UML_ROLINS(block, I0, I4, FP_SHIFT, FP_MASK); // SET_FP(reg) UML_MOV(block, DRC_SR, I0); - generate_branch(block, compiler, compiler.mode() & 0x1, uml::I5, desc); // T cleared - only keep S in bit zero of mode + generate_branch(block, compiler, compiler.mode() & 0x1, uml::I1, desc); // T cleared - only keep S in bit zero of mode } @@ -2412,7 +2413,7 @@ void hyperstone_device::generate_shldi(drcuml_block &block, compiler_state &comp generate_load_operand(block, compiler, LOCAL, dst_code, uml::I1, uml::I4); generate_load_operand(block, compiler, LOCAL, dst_code + 1, uml::I0, uml::I5); - UML_AND(block, I2, I2, ~(C_MASK | Z_MASK | N_MASK)); + UML_AND(block, I2, I2, ~(C_MASK | Z_MASK | N_MASK | V_MASK)); if (n) UML_SHR(block, I3, I1, 32 - n); @@ -2472,7 +2473,7 @@ void hyperstone_device::generate_shld(drcuml_block &block, compiler_state &compi generate_load_operand(block, compiler, LOCAL, src_code, uml::I1, uml::I3); const int no_shift = compiler.next_label(); - UML_AND(block, I2, I2, ~(C_MASK | Z_MASK | N_MASK)); + UML_AND(block, I2, I2, ~(C_MASK | Z_MASK | N_MASK | V_MASK)); UML_AND(block, I1, I1, 0x1f); UML_JMPc(block, uml::COND_Z, no_shift); UML_SUB(block, I3, 64, I1); @@ -2516,33 +2517,37 @@ void hyperstone_device::generate_shl(drcuml_block &block, compiler_state &compil UML_MOV(block, I2, DRC_SR); UML_ROLAND(block, I3, I2, 32 - FP_SHIFT, 0x7f); - generate_load_operand(block, compiler, LOCAL, src_code, uml::I1, uml::I1); - generate_load_operand(block, compiler, LOCAL, dst_code, uml::I0, uml::I3); + if (dst_code != src_code) + { + generate_load_operand(block, compiler, LOCAL, src_code, uml::I1, uml::I1); + generate_load_operand(block, compiler, LOCAL, dst_code, uml::I0, uml::I3); + UML_AND(block, I1, I1, 0x1f); + } + else + { + generate_load_operand(block, compiler, LOCAL, dst_code, uml::I0, uml::I3); + UML_AND(block, I1, I0, 0x1f); + } - const int no_shift = compiler.next_label(); - UML_AND(block, I2, I2, ~(C_MASK | Z_MASK | N_MASK)); - UML_AND(block, I1, I1, 0x1f); - UML_JMPc(block, uml::COND_Z, no_shift); - UML_SUB(block, I5, 32, I1); - UML_SHR(block, I4, I0, I5); + UML_AND(block, I2, I2, ~(C_MASK | Z_MASK | N_MASK | V_MASK)); + + UML_SUB(block, I4, 32, I1); + UML_SHR(block, I5, ~uint32_t(0), I4); + UML_SHR(block, I4, I0, I4); + UML_TEST(block, I1, 0xffffffff); + UML_MOVc(block, uml::COND_Z, I4, 0); + UML_MOVc(block, uml::COND_Z, I5, 0); UML_ROLINS(block, I2, I4, C_SHIFT, C_MASK); - UML_LABEL(block, no_shift); UML_SHL(block, I0, I0, I1); - - const int no_overflow = compiler.next_label(); - UML_TEST(block, I1, ~uint32_t(0)); - UML_JMPc(block, uml::COND_Z, no_overflow); - UML_SHR(block, I1, ~uint32_t(0), I5); - UML_TEST(block, I0, ~uint32_t(0)); - UML_MOVc(block, uml::COND_NS, I1, 0); - UML_CMP(block, I4, I1); - UML_JMPc(block, uml::COND_E, no_overflow); - UML_OR(block, I2, I2, V_MASK); - UML_LABEL(block, no_overflow); - - UML_TEST(block, I0, ~uint32_t(0)); + UML_MOVc(block, uml::COND_NS, I5, 0); generate_update_nz(block, compiler, uml::I2); + + UML_XOR(block, I4, I4, I5); + UML_MOV(block, I1, V_MASK); + UML_MOVc(block, uml::COND_Z, I1, 0); + UML_OR(block, I2, I2, I1); + UML_MOV(block, DRC_SR, I2); UML_STORE(block, (void *)m_core->local_regs, I3, I0, SIZE_DWORD, SCALE_x4); @@ -2564,25 +2569,27 @@ void hyperstone_device::generate_shli(drcuml_block &block, compiler_state &compi generate_load_operand(block, compiler, DstGlobal, dst_code, uml::I0, uml::I3); - UML_AND(block, I2, I2, ~(C_MASK | Z_MASK | N_MASK)); + UML_AND(block, I2, I2, ~(C_MASK | Z_MASK | N_MASK | V_MASK)); if (n) { UML_SHR(block, I4, I0, 32 - n); + UML_MOV(block, I5, util::make_bitmask(n)); UML_ROLAND(block, I1, I4, C_SHIFT, C_MASK); UML_OR(block, I2, I2, I1); } UML_SHL(block, I0, I0, n); + if (n) + { + UML_MOVc(block, uml::COND_NS, I5, 0); + } generate_update_nz(block, compiler, uml::I2); if (n) { - UML_TEST(block, I0, ~uint32_t(0)); - UML_MOV(block, I1, util::make_bitmask(n)); - UML_MOVc(block, uml::COND_NS, I1, 0); - UML_CMP(block, I4, I1); + UML_XOR(block, I4, I4, I5); UML_MOV(block, I1, V_MASK); - UML_MOVc(block, uml::COND_E, I1, 0); + UML_MOVc(block, uml::COND_Z, I1, 0); UML_OR(block, I2, I2, I1); } @@ -2618,49 +2625,50 @@ void hyperstone_device::generate_rol(drcuml_block &block, compiler_state &compil const uint32_t dst_code = (op & 0xf0) >> 4; const uint32_t src_code = op & 0xf; - UML_ROLAND(block, I3, DRC_SR, 32 - FP_SHIFT, 0x7f); + UML_MOV(block, I2, DRC_SR); + UML_ROLAND(block, I3, I2, 32 - FP_SHIFT, 0x7f); - UML_ADD(block, I2, I3, dst_code); - UML_AND(block, I4, I2, 0x3f); - UML_LOAD(block, I0, (void *)m_core->local_regs, I4, SIZE_DWORD, SCALE_x4); // I0 = dreg + if (dst_code != src_code) + { + generate_load_operand(block, compiler, LOCAL, src_code, uml::I1, uml::I1); + generate_load_operand(block, compiler, LOCAL, dst_code, uml::I0, uml::I3); + UML_AND(block, I1, I1, 0x1f); + } + else + { + generate_load_operand(block, compiler, LOCAL, dst_code, uml::I0, uml::I3); + UML_AND(block, I1, I0, 0x1f); + } - UML_ADD(block, I2, I3, src_code); - UML_AND(block, I1, I2, 0x3f); - UML_LOAD(block, I5, (void *)m_core->local_regs, I1, SIZE_DWORD, SCALE_x4); - UML_AND(block, I1, I5, 0x1f); // I1 = sreg & 0x1f +#ifdef MISSIONCRAFT_FLAGS + UML_AND(block, I2, I2, ~(C_MASK | Z_MASK | N_MASK | V_MASK)); - int no_shift = compiler.next_label(); - UML_CMP(block, I1, 0); - UML_JMPc(block, uml::COND_E, no_shift); - UML_ROL(block, I2, I0, I1); - UML_LABEL(block, no_shift); + UML_SUB(block, I4, 32, I1); + UML_SHR(block, I4, ~uint32_t(0), I4); + UML_TEST(block, I1, 0xffffffff); + UML_MOVc(block, uml::COND_Z, I4, 0); + UML_MOV(block, I5, I4); +#else + UML_AND(block, I2, I2, ~(C_MASK | Z_MASK | N_MASK)); +#endif - UML_DSHR(block, I5, 0xffffffff00000000ULL, I1); - UML_AND(block, I3, I0, I5); + UML_ROL(block, I0, I0, I1); +#ifdef MISSIONCRAFT_FLAGS + UML_MOVc(block, uml::COND_NS, I4, 0); +#endif + generate_update_nz(block, compiler, uml::I2); - UML_MOV(block, I6, 0); +#ifdef MISSIONCRAFT_FLAGS + UML_AND(block, I1, I5, I0); + UML_XOR(block, I4, I4, I1); + UML_MOV(block, I1, V_MASK); + UML_MOVc(block, uml::COND_Z, I1, 0); + UML_OR(block, I2, I2, I1); +#endif - int no_hi_bit = compiler.next_label(); - UML_TEST(block, I0, 0x80000000); - UML_JMPc(block, uml::COND_Z, no_hi_bit); + UML_MOV(block, DRC_SR, I2); - UML_XOR(block, I3, I3, I5); - - int done_shift = compiler.next_label(); - UML_LABEL(block, no_hi_bit); - UML_TEST(block, I3, ~0); - UML_JMPc(block, uml::COND_Z, done_shift); - UML_OR(block, I6, I6, V_MASK); - - UML_LABEL(block, done_shift); - UML_TEST(block, I2, ~uint32_t(0)); - UML_SETc(block, uml::COND_Z, I5); - UML_SHL(block, I5, I5, Z_SHIFT); - UML_ROLINS(block, I5, I2, N_SHIFT + 1, N_MASK); - - UML_OR(block, I5, I5, I6); - UML_ROLINS(block, DRC_SR, I5, 0, (V_MASK | N_MASK | Z_MASK | C_MASK)); - UML_STORE(block, (void *)m_core->local_regs, I4, I2, SIZE_DWORD, SCALE_x4); + UML_STORE(block, (void *)m_core->local_regs, I3, I0, SIZE_DWORD, SCALE_x4); } @@ -3857,7 +3865,7 @@ void hyperstone_device::generate_dbr(drcuml_block &block, compiler_state &compil UML_ADD(block, I0, DRC_PC, target); UML_MOV(block, mem(&m_core->delay_slot), 1); UML_MOV(block, mem(&m_core->delay_pc), I0); - UML_MOV(block, mem(&m_core->intblock), 3); + UML_MOV(block, mem(&m_core->intblock), 2); auto const *delayslot = desc->delay.first(); if (delayslot) @@ -3869,7 +3877,7 @@ void hyperstone_device::generate_dbr(drcuml_block &block, compiler_state &compil generate_update_cycles(block); - UML_MOV(block, mem(&m_core->intblock), 2); + UML_MOV(block, mem(&m_core->intblock), 1); #if E132XS_LOG_DRC_REGS UML_CALLC(block, &c_funcs::dump_registers, this); diff --git a/src/devices/cpu/e132xs/e132xsop.hxx b/src/devices/cpu/e132xs/e132xsop.hxx index 953c793b21b..25848e55796 100644 --- a/src/devices/cpu/e132xs/e132xsop.hxx +++ b/src/devices/cpu/e132xs/e132xsop.hxx @@ -28,7 +28,7 @@ void hyperstone_device::set_double_word(uint8_t dst_code, uint8_t dstf_code, uin template void hyperstone_device::hyperstone_chk() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -52,7 +52,7 @@ void hyperstone_device::hyperstone_chk() template void hyperstone_device::hyperstone_movd() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -134,7 +134,7 @@ void hyperstone_device::hyperstone_movd() template void hyperstone_device::hyperstone_divsu() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t dst_code = DstGlobal ? DST_CODE : ((DST_CODE + fp) & 0x3f); @@ -194,7 +194,7 @@ void hyperstone_device::hyperstone_xm() m_instruction_length = (2<<19); } - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -224,7 +224,7 @@ template global_regs[SRC_CODE] : m_core->local_regs[(SRC_CODE + GET_FP) & 0x3f]) & extra_u; if (dreg == 0) @@ -244,7 +244,7 @@ template global_regs[src_code]) : m_core->local_regs[src_code]; @@ -275,7 +275,7 @@ void hyperstone_device::hyperstone_sums() { const int32_t extra_s = decode_const(); - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -311,7 +311,7 @@ void hyperstone_device::hyperstone_sums() template void hyperstone_device::hyperstone_cmp() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -341,7 +341,7 @@ void hyperstone_device::hyperstone_mov() { m_core->icount -= m_core->clock_cycles_1; - check_delay_PC(); + check_delay_pc(); const bool h = (SR & H_MASK) != 0; SR &= ~H_MASK; @@ -378,7 +378,7 @@ void hyperstone_device::hyperstone_mov() template void hyperstone_device::hyperstone_add() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -417,7 +417,7 @@ void hyperstone_device::hyperstone_add() template void hyperstone_device::hyperstone_adds() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -456,7 +456,7 @@ void hyperstone_device::hyperstone_adds() template void hyperstone_device::hyperstone_cmpb() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -476,7 +476,7 @@ void hyperstone_device::hyperstone_cmpb() template void hyperstone_device::hyperstone_andn() { - check_delay_PC(); + check_delay_pc(); const uint32_t dst_code = DstGlobal ? DST_CODE : ((DST_CODE + GET_FP) & 0x3f); const uint32_t sreg = SrcGlobal ? m_core->global_regs[SRC_CODE] : m_core->local_regs[(SRC_CODE + GET_FP) & 0x3f]; @@ -498,7 +498,7 @@ void hyperstone_device::hyperstone_andn() template void hyperstone_device::hyperstone_or() { - check_delay_PC(); + check_delay_pc(); const uint32_t dst_code = DstGlobal ? DST_CODE : ((DST_CODE + GET_FP) & 0x3f); const uint32_t sreg = SrcGlobal ? m_core->global_regs[SRC_CODE] : m_core->local_regs[(SRC_CODE + GET_FP) & 0x3f]; @@ -520,7 +520,7 @@ void hyperstone_device::hyperstone_or() template void hyperstone_device::hyperstone_xor() { - check_delay_PC(); + check_delay_pc(); const uint32_t dst_code = DstGlobal ? DST_CODE : ((DST_CODE + GET_FP) & 0x3f); const uint32_t sreg = SrcGlobal ? m_core->global_regs[SRC_CODE] : m_core->local_regs[(SRC_CODE + GET_FP) & 0x3f]; @@ -544,7 +544,7 @@ void hyperstone_device::hyperstone_xor() template void hyperstone_device::hyperstone_subc() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -579,7 +579,7 @@ void hyperstone_device::hyperstone_subc() template void hyperstone_device::hyperstone_not() { - check_delay_PC(); + check_delay_pc(); const uint32_t dreg = ~(SrcGlobal ? m_core->global_regs[SRC_CODE] : m_core->local_regs[(SRC_CODE + GET_FP) & 0x3f]); @@ -599,7 +599,7 @@ void hyperstone_device::hyperstone_not() template void hyperstone_device::hyperstone_sub() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -638,7 +638,7 @@ void hyperstone_device::hyperstone_sub() template void hyperstone_device::hyperstone_subs() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -674,7 +674,7 @@ void hyperstone_device::hyperstone_subs() template void hyperstone_device::hyperstone_addc() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -719,7 +719,7 @@ void hyperstone_device::hyperstone_addc() template void hyperstone_device::hyperstone_and() { - check_delay_PC(); + check_delay_pc(); const uint32_t dst_code = DstGlobal ? DST_CODE : ((DST_CODE + GET_FP) & 0x3f); const uint32_t sreg = SrcGlobal ? m_core->global_regs[SRC_CODE] : m_core->local_regs[(SRC_CODE + GET_FP) & 0x3f]; @@ -741,7 +741,7 @@ void hyperstone_device::hyperstone_and() template void hyperstone_device::hyperstone_neg() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -770,7 +770,7 @@ void hyperstone_device::hyperstone_neg() template void hyperstone_device::hyperstone_negs() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -813,7 +813,7 @@ void hyperstone_device::hyperstone_cmpi() if (ImmLong) imm = decode_immediate_s(); - check_delay_PC(); + check_delay_pc(); if (!ImmLong) imm = m_op & 0x0f; @@ -844,7 +844,7 @@ void hyperstone_device::hyperstone_movi() uint32_t imm; if (ImmLong) imm = decode_immediate_s(); - check_delay_PC(); + check_delay_pc(); if (!ImmLong) imm = m_op & 0x0f; @@ -887,7 +887,7 @@ void hyperstone_device::hyperstone_addi() uint32_t imm; if (ImmLong) imm = decode_immediate_s(); - check_delay_PC(); + check_delay_pc(); const uint32_t dst_code = DstGlobal ? DST_CODE : ((DST_CODE + GET_FP) & 0x3f); uint32_t dreg = (DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code]; @@ -929,7 +929,7 @@ template global_regs : m_core->local_regs)[dst_code]; @@ -940,7 +940,7 @@ void hyperstone_device::hyperstone_addsi() if (ImmLong) { imm = decode_immediate_s(); - check_delay_PC(); + check_delay_pc(); } else { @@ -952,7 +952,7 @@ void hyperstone_device::hyperstone_addsi() if (ImmLong) { ignore_immediate_s(); - check_delay_PC(); + check_delay_pc(); } imm = SR & (((SR & Z_MASK) ? 0 : 1) | (dreg & 0x01)); } @@ -989,7 +989,7 @@ template global_regs[DST_CODE] : m_core->local_regs[(DST_CODE + GET_FP) & 0x3f]; @@ -1002,7 +1002,7 @@ void hyperstone_device::hyperstone_cmpbi() if (ImmLong) { ignore_immediate_s(); - check_delay_PC(); + check_delay_pc(); } imm = 0x7fffffff; // bit 31 = 0, others = 1 } @@ -1011,7 +1011,7 @@ void hyperstone_device::hyperstone_cmpbi() if (ImmLong) { imm = decode_immediate_s(); - check_delay_PC(); + check_delay_pc(); } else { @@ -1029,7 +1029,7 @@ void hyperstone_device::hyperstone_cmpbi() if (ImmLong) { ignore_immediate_s(); - check_delay_PC(); + check_delay_pc(); } if ((dreg & 0xff000000) == 0 || (dreg & 0x00ff0000) == 0 || (dreg & 0x0000ff00) == 0 || (dreg & 0x000000ff) == 0) SR |= Z_MASK; @@ -1047,7 +1047,7 @@ void hyperstone_device::hyperstone_andni() if (ImmLong) imm = decode_immediate_s(); - check_delay_PC(); + check_delay_pc(); if (N_OP_MASK == 0x10f) imm = 0x7fffffff; // bit 31 = 0, others = 1 @@ -1089,7 +1089,7 @@ void hyperstone_device::hyperstone_ori() if (ImmLong) imm = decode_immediate_s(); - check_delay_PC(); + check_delay_pc(); if (!ImmLong) imm = m_op & 0x0f; @@ -1127,7 +1127,7 @@ void hyperstone_device::hyperstone_xori() if (ImmLong) imm = decode_immediate_s(); - check_delay_PC(); + check_delay_pc(); if (!ImmLong) imm = m_op & 0x0f; @@ -1162,7 +1162,7 @@ void hyperstone_device::hyperstone_xori() template void hyperstone_device::hyperstone_shrdi() { - check_delay_PC(); + check_delay_pc(); const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f; const uint32_t dstf_code = (dst_code + 1) & 0x3f; @@ -1191,7 +1191,7 @@ void hyperstone_device::hyperstone_shrdi() void hyperstone_device::hyperstone_shrd() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = (SRC_CODE + fp) & 0x3f; @@ -1227,7 +1227,7 @@ void hyperstone_device::hyperstone_shrd() void hyperstone_device::hyperstone_shr() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t dst_code = (DST_CODE + fp) & 0x3f; @@ -1253,7 +1253,7 @@ void hyperstone_device::hyperstone_shr() template void hyperstone_device::hyperstone_sardi() { - check_delay_PC(); + check_delay_pc(); const uint32_t dst_code = (DST_CODE + GET_FP) & 0x3f; const uint32_t dstf_code = (dst_code + 1) & 0x3f; @@ -1285,7 +1285,7 @@ void hyperstone_device::hyperstone_sardi() void hyperstone_device::hyperstone_sard() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = (SRC_CODE + fp) & 0x3f; @@ -1327,7 +1327,7 @@ void hyperstone_device::hyperstone_sard() void hyperstone_device::hyperstone_sar() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t dst_code = (DST_CODE + fp) & 0x3f; @@ -1361,7 +1361,7 @@ void hyperstone_device::hyperstone_sar() template void hyperstone_device::hyperstone_shldi() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t code = DST_CODE; @@ -1396,7 +1396,7 @@ void hyperstone_device::hyperstone_shldi() void hyperstone_device::hyperstone_shld() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t d_code = DST_CODE; @@ -1441,7 +1441,7 @@ void hyperstone_device::hyperstone_shld() void hyperstone_device::hyperstone_shl() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; uint32_t src_code = SRC_CODE + fp; @@ -1470,7 +1470,7 @@ void hyperstone_device::hyperstone_shl() void hyperstone_device::hyperstone_testlz() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t sreg = m_core->local_regs[(SRC_CODE + fp) & 0x3f]; @@ -1483,7 +1483,7 @@ void hyperstone_device::hyperstone_testlz() void hyperstone_device::hyperstone_rol() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t dst_code = (DST_CODE + fp) & 0x3f; @@ -1545,7 +1545,7 @@ void hyperstone_device::hyperstone_ldxx1() extra_s |= 0xfffff000; } - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -1670,7 +1670,7 @@ void hyperstone_device::hyperstone_ldxx2() extra_s |= 0xfffff000; } - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : (SRC_CODE + fp) & 0x3f; @@ -1833,7 +1833,7 @@ void hyperstone_device::hyperstone_stxx1() extra_s |= 0xfffff000; } - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -1931,7 +1931,7 @@ void hyperstone_device::hyperstone_stxx2() extra_s |= 0xfffff000; } - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -2030,7 +2030,7 @@ void hyperstone_device::hyperstone_stxx2() template void hyperstone_device::hyperstone_shri() { - check_delay_PC(); + check_delay_pc(); const uint32_t dst_code = DstGlobal ? DST_CODE : ((DST_CODE + GET_FP) & 0x3f); uint32_t val = (DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code]; @@ -2058,7 +2058,7 @@ void hyperstone_device::hyperstone_shri() template void hyperstone_device::hyperstone_sari() { - check_delay_PC(); + check_delay_pc(); const uint32_t dst_code = DstGlobal ? DST_CODE : ((DST_CODE + GET_FP) & 0x3f); @@ -2094,7 +2094,7 @@ void hyperstone_device::hyperstone_sari() template void hyperstone_device::hyperstone_shli() { - check_delay_PC(); + check_delay_pc(); const uint32_t dst_code = DstGlobal ? DST_CODE : ((DST_CODE + GET_FP) & 0x3f); uint32_t val = (DstGlobal ? m_core->global_regs : m_core->local_regs)[dst_code]; @@ -2128,7 +2128,7 @@ void hyperstone_device::hyperstone_shli() template void hyperstone_device::hyperstone_mulsu() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -2162,7 +2162,7 @@ void hyperstone_device::hyperstone_mulsu() template void hyperstone_device::hyperstone_set() { - check_delay_PC(); + check_delay_pc(); const uint32_t dst_code = DstGlobal ? DST_CODE : ((DST_CODE + GET_FP) & 0x3f); const uint32_t n = LO_N_VALUE; @@ -2222,7 +2222,7 @@ void hyperstone_device::hyperstone_set() template void hyperstone_device::hyperstone_mul() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -2256,7 +2256,7 @@ void hyperstone_device::hyperstone_extend() m_instruction_length = (2<<19); const uint32_t func = m_pr16(PC); PC += 2; - check_delay_PC(); + check_delay_pc(); //TODO: add locks, overflow error and other things const uint32_t fp = GET_FP; @@ -2371,7 +2371,7 @@ void hyperstone_device::hyperstone_extend() template void hyperstone_device::hyperstone_ldwr() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t dreg = m_core->local_regs[(DST_CODE + fp) & 0x3f]; @@ -2392,7 +2392,7 @@ void hyperstone_device::hyperstone_ldwr() template void hyperstone_device::hyperstone_lddr() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -2421,7 +2421,7 @@ void hyperstone_device::hyperstone_lddr() template void hyperstone_device::hyperstone_ldwp() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t dst_code = (DST_CODE + fp) & 0x3f; @@ -2455,7 +2455,7 @@ void hyperstone_device::hyperstone_ldwp() template void hyperstone_device::hyperstone_lddp() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -2493,7 +2493,7 @@ void hyperstone_device::hyperstone_lddp() template void hyperstone_device::hyperstone_stwr() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -2514,7 +2514,7 @@ void hyperstone_device::hyperstone_stwr() template void hyperstone_device::hyperstone_stdr() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -2538,7 +2538,7 @@ void hyperstone_device::hyperstone_stdr() template void hyperstone_device::hyperstone_stwp() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -2562,7 +2562,7 @@ void hyperstone_device::hyperstone_stwp() template void hyperstone_device::hyperstone_stdp() { - check_delay_PC(); + check_delay_pc(); const uint32_t fp = GET_FP; const uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -2592,40 +2592,44 @@ template delay_slot) { - if (SR & condition_masks[Condition]) + m_core->delay_slot_taken = 0; + if (taken) { const int32_t offset = decode_pcrel(); - check_delay_PC(); m_core->delay_slot = 1; m_core->delay_pc = PC + offset; - m_core->intblock = 3; + m_core->intblock = 2; + m_core->icount -= m_core->clock_cycles_2; } else { ignore_pcrel(); - check_delay_PC(); + m_core->icount -= m_core->clock_cycles_1; } } else { - if (SR & condition_masks[Condition]) + m_core->delay_slot = 0; + m_core->delay_slot_taken = 1; + if (taken) { - ignore_pcrel(); - check_delay_PC(); - m_core->icount -= m_core->clock_cycles_1; + const int32_t offset = decode_pcrel(); + PC = m_core->delay_pc + offset; + SR &= ~M_MASK; + + m_core->icount -= m_core->clock_cycles_2; } else { - const int32_t offset = decode_pcrel(); - check_delay_PC(); - m_core->delay_slot = 1; - m_core->delay_pc = PC + offset; - m_core->intblock = 3; - m_core->icount -= m_core->clock_cycles_2; + ignore_pcrel(); + PC = m_core->delay_pc; + + m_core->icount -= m_core->clock_cycles_1; } } } @@ -2633,18 +2637,30 @@ void hyperstone_device::hyperstone_db() void hyperstone_device::hyperstone_dbr() { const int32_t offset = decode_pcrel(); - check_delay_PC(); + if (!m_core->delay_slot) + { + m_core->delay_pc = PC + offset; + m_core->delay_slot = 1; + m_core->delay_slot_taken = 0; + m_core->intblock = 2; - m_core->delay_slot = 1; - m_core->delay_pc = PC + offset; - m_core->intblock = 3; + m_core->icount -= m_core->clock_cycles_2; + } + else + { + m_core->delay_slot = 0; + m_core->delay_slot_taken = 1; - m_core->icount -= m_core->clock_cycles_2; + PC = m_core->delay_pc + offset; + SR &= ~M_MASK; + + m_core->icount -= m_core->clock_cycles_2; + } } void hyperstone_device::hyperstone_frame() { - check_delay_PC(); + check_delay_pc(); const uint8_t realfp = GET_FP - SRC_CODE; const uint8_t dst_code = DST_CODE; @@ -2708,7 +2724,7 @@ void hyperstone_device::hyperstone_call() extra_s |= 0xffffc000; } - check_delay_PC(); + check_delay_pc(); uint32_t fp = GET_FP; uint32_t src_code = SrcGlobal ? SRC_CODE : ((SRC_CODE + fp) & 0x3f); @@ -2750,7 +2766,7 @@ void hyperstone_device::hyperstone_b() else { ignore_pcrel(); - check_delay_PC(); + check_delay_pc(); m_core->icount -= m_core->clock_cycles_1; } } @@ -2759,7 +2775,7 @@ void hyperstone_device::hyperstone_b() if (SR & condition_masks[Condition]) { ignore_pcrel(); - check_delay_PC(); + check_delay_pc(); m_core->icount -= m_core->clock_cycles_1; } else @@ -2768,3 +2784,14 @@ void hyperstone_device::hyperstone_b() } } } + +void hyperstone_device::hyperstone_br() +{ + const int32_t offset = decode_pcrel(); + check_delay_pc(); + + PC += offset; + SR &= ~M_MASK; + + m_core->icount -= m_core->clock_cycles_2; +}