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; +}