diff --git a/scripts/src/emu.lua b/scripts/src/emu.lua index df53570a61e..07ec7180412 100644 --- a/scripts/src/emu.lua +++ b/scripts/src/emu.lua @@ -237,20 +237,22 @@ files { MAME_DIR .. "src/emu/debug/debughlp.h", MAME_DIR .. "src/emu/debug/debugvw.cpp", MAME_DIR .. "src/emu/debug/debugvw.h", - MAME_DIR .. "src/emu/debug/dvdisasm.cpp", - MAME_DIR .. "src/emu/debug/dvdisasm.h", - MAME_DIR .. "src/emu/debug/dvmemory.cpp", - MAME_DIR .. "src/emu/debug/dvmemory.h", MAME_DIR .. "src/emu/debug/dvbpoints.cpp", MAME_DIR .. "src/emu/debug/dvbpoints.h", + MAME_DIR .. "src/emu/debug/dvdisasm.cpp", + MAME_DIR .. "src/emu/debug/dvdisasm.h", + MAME_DIR .. "src/emu/debug/dvepoints.cpp", + MAME_DIR .. "src/emu/debug/dvepoints.h", + MAME_DIR .. "src/emu/debug/dvmemory.cpp", + MAME_DIR .. "src/emu/debug/dvmemory.h", MAME_DIR .. "src/emu/debug/dvrpoints.cpp", MAME_DIR .. "src/emu/debug/dvrpoints.h", - MAME_DIR .. "src/emu/debug/dvwpoints.cpp", - MAME_DIR .. "src/emu/debug/dvwpoints.h", MAME_DIR .. "src/emu/debug/dvstate.cpp", MAME_DIR .. "src/emu/debug/dvstate.h", MAME_DIR .. "src/emu/debug/dvtext.cpp", MAME_DIR .. "src/emu/debug/dvtext.h", + MAME_DIR .. "src/emu/debug/dvwpoints.cpp", + MAME_DIR .. "src/emu/debug/dvwpoints.h", MAME_DIR .. "src/emu/debug/express.cpp", MAME_DIR .. "src/emu/debug/express.h", MAME_DIR .. "src/emu/debug/points.cpp", diff --git a/scripts/src/osd/mac.lua b/scripts/src/osd/mac.lua index 4ac915a645f..f72c8605365 100644 --- a/scripts/src/osd/mac.lua +++ b/scripts/src/osd/mac.lua @@ -103,6 +103,8 @@ project ("osd_" .. _OPTIONS["osd"]) MAME_DIR .. "src/osd/modules/debugger/osx/disassemblyview.h", MAME_DIR .. "src/osd/modules/debugger/osx/errorlogviewer.mm", MAME_DIR .. "src/osd/modules/debugger/osx/errorlogviewer.h", + MAME_DIR .. "src/osd/modules/debugger/osx/exceptionpointsview.mm", + MAME_DIR .. "src/osd/modules/debugger/osx/exceptionpointsview.h", MAME_DIR .. "src/osd/modules/debugger/osx/memoryview.mm", MAME_DIR .. "src/osd/modules/debugger/osx/memoryview.h", MAME_DIR .. "src/osd/modules/debugger/osx/memoryviewer.mm", diff --git a/scripts/src/osd/sdl.lua b/scripts/src/osd/sdl.lua index 3115c4d644f..93dba9ae67a 100644 --- a/scripts/src/osd/sdl.lua +++ b/scripts/src/osd/sdl.lua @@ -357,6 +357,8 @@ project ("osd_" .. _OPTIONS["osd"]) MAME_DIR .. "src/osd/modules/debugger/osx/disassemblyviewer.h", MAME_DIR .. "src/osd/modules/debugger/osx/errorlogview.mm", MAME_DIR .. "src/osd/modules/debugger/osx/errorlogview.h", + MAME_DIR .. "src/osd/modules/debugger/osx/exceptionpointsview.mm", + MAME_DIR .. "src/osd/modules/debugger/osx/exceptionpointsview.h", MAME_DIR .. "src/osd/modules/debugger/osx/disassemblyview.h", MAME_DIR .. "src/osd/modules/debugger/osx/errorlogviewer.mm", MAME_DIR .. "src/osd/modules/debugger/osx/errorlogviewer.h", diff --git a/src/devices/cpu/e132xs/32xsdasm.cpp b/src/devices/cpu/e132xs/32xsdasm.cpp index 13f0d5cf810..f385e5fd4f7 100644 --- a/src/devices/cpu/e132xs/32xsdasm.cpp +++ b/src/devices/cpu/e132xs/32xsdasm.cpp @@ -871,7 +871,7 @@ offs_t hyperstone_disassembler::disassemble(std::ostream &stream, offs_t pc, con // LD/STHS.D/A util::stream_format(stream, "%sH%c.%c %s, %s, $%x", inst, (dis & 1) ? 'S' : 'U', mode, dest, source, dis & ~1); if (!dest_bit && (dest_code == PC_REGISTER)) - util::stream_format(stream, " ; $%x", uint32_t(pc + size + (dis & ~1))); + util::stream_format(stream, " ; $%x", uint32_t(pc + size + (dis & ~1)) & ~1); break; case 3: @@ -888,7 +888,7 @@ offs_t hyperstone_disassembler::disassemble(std::ostream &stream, offs_t pc, con util::stream_format(stream, "%s%c.%c %s, %s, $%x", inst, (dis & 1) ? 'D' : 'W', mode, dest, source, dis & ~3); } if (!dest_bit && (dest_code == PC_REGISTER)) - util::stream_format(stream, " ; $%x", uint32_t(pc + size + (dis & ~3))); + util::stream_format(stream, " ; $%x", uint32_t(pc + size + (dis & ~3)) & ~3); break; } break; @@ -921,23 +921,17 @@ offs_t hyperstone_disassembler::disassemble(std::ostream &stream, offs_t pc, con case 0: // LD/STBS.N util::stream_format(stream, "%sBS.N %s, %s, $%x", inst, dest, source, dis); - if (!dest_bit && (dest_code == PC_REGISTER)) - util::stream_format(stream, " ; $%x", uint32_t(pc + size + dis)); break; case 1: // LD/STBU.N util::stream_format(stream, "%sBU.N %s, %s, $%x", inst, dest, source, dis); - if (!dest_bit && (dest_code == PC_REGISTER)) - util::stream_format(stream, " ; $%x", uint32_t(pc + size + dis)); break; case 2: // LD/STHU.N // LD/STHS.N util::stream_format(stream, "%sH%c.N %s, %s, $%x", inst, (dis & 1) ? 'S' : 'U', dest, source, dis & ~1); - if (!dest_bit && (dest_code == PC_REGISTER)) - util::stream_format(stream, " ; $%x", uint32_t(pc + size + (dis & ~1))); break; case 3: @@ -945,8 +939,6 @@ offs_t hyperstone_disassembler::disassemble(std::ostream &stream, offs_t pc, con { // LD/STW.S util::stream_format(stream, "%sW.S %s, %s, $%x", inst, dest, source, dis & ~3); - if (!dest_bit && (dest_code == PC_REGISTER)) - util::stream_format(stream, " ; $%x", uint32_t(pc + size + (dis & ~3))); } else if ((dis & 3) == 2) { @@ -958,8 +950,6 @@ offs_t hyperstone_disassembler::disassemble(std::ostream &stream, offs_t pc, con // LD/STW.N // LD/STD.N util::stream_format(stream, "%s%c.N %s, %s, $%x", inst, (dis & 1) ? 'D' : 'W', dest, source, dis & ~3); - if (!dest_bit && (dest_code == PC_REGISTER)) - util::stream_format(stream, " ; $%x", uint32_t(pc + size + (dis & ~3))); } break; } diff --git a/src/devices/cpu/e132xs/e132xs.cpp b/src/devices/cpu/e132xs/e132xs.cpp index 00654a9275c..63e3cb6918b 100644 --- a/src/devices/cpu/e132xs/e132xs.cpp +++ b/src/devices/cpu/e132xs/e132xs.cpp @@ -32,7 +32,6 @@ TODO: - All instructions should clear the H flag (not just MOV/MOVI) - - Fix behaviour of exceptions in delay slots - Fix behaviour of branches in delay slots - Many wrong cycle counts - No emulation of memory access latency and pipleline @@ -41,9 +40,6 @@ - Verify register wrapping with sregf/dregf on hardware - Tracing doesn't work properly DRC does not generate trace exceptions on branch or return - - Interpreter does not implement privilege check on setting L flag - - DRC does not update ILC and P on some privilege error exceptions - - Support for debugger exception points should be implemented *********************************************************************/ @@ -489,9 +485,11 @@ void hyperstone_device::set_global_register(uint8_t code, uint32_t val) return; case SR_REGISTER: { - // FIXME: generate exception on attempt to set L from user mode const bool exception = !GET_S && !GET_L && (val & L_MASK); + const bool privilege_error = !GET_S && !GET_L && (val & L_MASK); SET_LOW_SR(val); // only a RET instruction can change the full content of SR - SR &= ~0x40; //reserved bit 6 always zero + SR &= ~0x40; // reserved bit 6 always zero + if (privilege_error) + execute_exception(TRAPNO_PRIVILEGE_ERROR); } return; case 2: @@ -584,8 +582,14 @@ do /* if PC is used in a delay instruction, the delayed PC should be used */ \ if (m_core->delay_slot) \ { \ - PC = m_core->delay_pc; \ + 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) @@ -761,7 +765,16 @@ void hyperstone_device::execute_exception(uint8_t trapno) const uint32_t addr = get_trap_addr(trapno); const uint8_t reg = GET_FP + GET_FL; - SET_ILC(m_instruction_length); + + if (!m_core->delay_slot_taken) + SET_ILC(m_instruction_length); + else + PC = m_core->delay_pc; + + // RET does not automatically set P + if (((m_op & 0xfef0) != 0x0400) || !(m_op & 0x010e)) + SET_P(1); + const uint32_t oldSR = SR; SET_FL(2); @@ -1101,9 +1114,9 @@ void hyperstone_device::device_start() save_item(NAME(m_core->global_regs)); save_item(NAME(m_core->local_regs)); save_item(NAME(m_core->trap_entry)); - save_item(NAME(m_core->delay_pc)); save_item(NAME(m_instruction_length)); save_item(NAME(m_core->intblock)); + save_item(NAME(m_core->delay_pc)); save_item(NAME(m_core->delay_slot)); save_item(NAME(m_core->delay_slot_taken)); save_item(NAME(m_core->tr_clocks_per_tick)); diff --git a/src/devices/cpu/e132xs/e132xs.h b/src/devices/cpu/e132xs/e132xs.h index b848924af62..27a5f896864 100644 --- a/src/devices/cpu/e132xs/e132xs.h +++ b/src/devices/cpu/e132xs/e132xs.h @@ -466,16 +466,16 @@ private: std::pair generate_get_d_code_dis(const opcode_desc *opcode); void generate_get_global_register_high(drcuml_block &block, compiler_state &compiler, uint32_t code, uml::parameter dst); - void generate_set_global_register(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t dst_code); - void generate_set_global_register_low(drcuml_block &block, compiler_state &compiler, uint32_t dst_code, uml::parameter src); + void generate_set_global_register_low(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t dst_code, uml::parameter src); void generate_set_global_register_high(drcuml_block &block, compiler_state &compiler, uint32_t dst_code, uml::parameter src); void generate_load_operand(drcuml_block &block, compiler_state &compiler, reg_bank global, uint32_t code, uml::parameter dst, uml::parameter localidx); void generate_load_src_addsub(drcuml_block &block, compiler_state &compiler, reg_bank global, uint32_t code, uml::parameter dst, uml::parameter localidx, uml::parameter sr); uml::parameter generate_load_address_ad(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, reg_bank global, uint32_t code, uml::parameter dst, uml::parameter localidx); void generate_load_address_ns(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, reg_bank global, uint32_t code, uml::parameter dst, uml::parameter localidx, uint16_t d_code, uint32_t dis); - void generate_load_address_rp(drcuml_block &block, compiler_state &compiler, uint32_t code, uml::parameter dst, uml::parameter localidx, uint32_t dis); + void generate_load_address_rp(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t code, uml::parameter dst, uml::parameter localidx, uint32_t dis); void generate_add_dis(drcuml_block &block, compiler_state &compiler, uml::parameter dst, uml::parameter base, uint32_t dis, unsigned alignment); + void generate_set_register(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, reg_bank global, uint32_t code, uml::parameter src, uml::parameter localidx, bool calcidx); void generate_set_dst(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, reg_bank global, uint32_t code, uml::parameter src, uml::parameter localidx, bool calcidx); void generate_update_flags_addsub(drcuml_block &block, compiler_state &compiler, uml::parameter sr); void generate_update_flags_addsubc(drcuml_block &block, compiler_state &compiler, uml::parameter sr); @@ -487,7 +487,9 @@ private: template void generate_trap_exception_or_int(drcuml_block &block, uml::code_label &label, uml::parameter trapno); void generate_software(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc); - void generate_trap_on_overflow(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uml::parameter sr); + void generate_raise_exception(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint8_t trapno, uml::parameter sr); + void generate_raise_exception(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint8_t trapno); + void generate_exception_on_overflow(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uml::parameter sr); template void generate_logic_op(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, T &&body); template void generate_logic_op_imm(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t dst_code, T &&body); diff --git a/src/devices/cpu/e132xs/e132xsdrc.cpp b/src/devices/cpu/e132xs/e132xsdrc.cpp index 112a11821e4..a943e95082d 100644 --- a/src/devices/cpu/e132xs/e132xsdrc.cpp +++ b/src/devices/cpu/e132xs/e132xsdrc.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Ryan Holtz +// copyright-holders:Ryan Holtz, Vas Crabb #include "emu.h" #include "e132xs.h" @@ -799,17 +799,19 @@ void hyperstone_device::generate_sequence_instruction(drcuml_block &block, compi if (compiler.check_delay()) { // if PC is used in a delay instruction, the delayed PC should be used - const int nodelay = compiler.next_label(); + const int set_delay_pc = compiler.next_label(); const int done = compiler.next_label(); - UML_TEST(block, mem(&m_core->delay_slot), 1); - UML_JMPc(block, uml::COND_Z, nodelay); + UML_TEST(block, mem(&m_core->delay_slot), ~uint32_t(0)); + UML_JMPc(block, uml::COND_NZ, set_delay_pc); + + UML_ADD(block, DRC_PC, DRC_PC, desc->length); + UML_MOV(block, mem(&m_core->delay_slot_taken), 0); + UML_JMP(block, done); + + UML_LABEL(block, set_delay_pc); UML_MOV(block, DRC_PC, mem(&m_core->delay_pc)); UML_MOV(block, mem(&m_core->delay_slot), 0); UML_MOV(block, mem(&m_core->delay_slot_taken), 1); - UML_JMP(block, done); - UML_LABEL(block, nodelay); - UML_ADD(block, DRC_PC, DRC_PC, desc->length); - UML_MOV(block, mem(&m_core->delay_slot_taken), 0); UML_LABEL(block, done); } else diff --git a/src/devices/cpu/e132xs/e132xsdrc_ops.hxx b/src/devices/cpu/e132xs/e132xsdrc_ops.hxx index b51833fd49c..19e7e3c50a2 100644 --- a/src/devices/cpu/e132xs/e132xsdrc_ops.hxx +++ b/src/devices/cpu/e132xs/e132xsdrc_ops.hxx @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Ryan Holtz +// copyright-holders:Ryan Holtz, Vas Crabb #ifndef MAME_CPU_E132XS_E132XSDRC_OPS_HXX #define MAME_CPU_E132XS_E132XSDRC_OPS_HXX @@ -150,101 +150,7 @@ void hyperstone_device::generate_get_global_register_high(drcuml_block &block, c } } -void hyperstone_device::generate_set_global_register(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t dst_code) -{ - // TODO: this function should be refactored away - // Expects value in I5, clobbers I6 when setting high registers - if (dst_code < 16) - { - if (dst_code == 0) - { - UML_AND(block, DRC_PC, I5, ~1); - } - else if (dst_code == 1) - { - // TODO: privilege check on setting L in user mode - UML_ROLINS(block, DRC_SR, I5, 0, 0x0000ffff); - UML_AND(block, DRC_SR, DRC_SR, ~0x40); - } - else - { - UML_MOV(block, mem(&m_core->global_regs[dst_code]), I5); - } - } - else - { - UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), I7); - UML_MOV(block, I7, 0); - - if ((dst_code <= 17) || (dst_code == BCR_REGISTER) || (dst_code == WCR_REGISTER)) - { - UML_MOV(block, mem(&m_core->global_regs[dst_code]), I5); - } - else if (dst_code < BCR_REGISTER) - { - // SP or UB - UML_AND(block, mem(&m_core->global_regs[dst_code]), I5, ~uint32_t(3)); - } - else if (dst_code == TPR_REGISTER) - { - const int skip_compute_tr = compiler.next_label(); - UML_MOV(block, mem(&m_core->global_regs[dst_code]), I5); - UML_TEST(block, I5, 0x80000000); - UML_JMPc(block, uml::COND_NZ, skip_compute_tr); - UML_CALLC(block, &c_funcs::compute_tr, this); - UML_CALLC(block, &c_funcs::update_timer_prescale, this); - UML_LABEL(block, skip_compute_tr); - UML_CALLC(block, &c_funcs::adjust_timer_interrupt, this); - } - else if (dst_code == TCR_REGISTER) - { - const int done = compiler.next_label(); - UML_MOV(block, I6, mem(&m_core->global_regs[dst_code])); - UML_CMP(block, I6, I5); - UML_JMPc(block, uml::COND_E, done); - UML_MOV(block, mem(&m_core->global_regs[dst_code]), I5); - UML_CALLC(block, &c_funcs::adjust_timer_interrupt, this); - UML_LABEL(block, done); - } - else if (dst_code == TR_REGISTER) - { - UML_MOV(block, mem(&m_core->global_regs[dst_code]), I5); - UML_MOV(block, mem(&m_core->tr_base_value), I5); - UML_CALLC(block, &c_funcs::total_cycles, this); - UML_DMOV(block, mem(&m_core->tr_base_cycles), mem(&m_core->numcycles)); - UML_CALLC(block, &c_funcs::adjust_timer_interrupt, this); - } - else if (dst_code == ISR_REGISTER) - { - // ISR - read-only - } - else if (dst_code == FCR_REGISTER) - { - const int skip_adjust_timer = compiler.next_label(); - UML_MOV(block, I6, mem(&m_core->global_regs[dst_code])); - UML_XOR(block, I6, I6, I5); - UML_TEST(block, I6, 0x80000000); - UML_JMPc(block, uml::COND_Z, skip_adjust_timer); - UML_CALLC(block, &c_funcs::adjust_timer_interrupt, this); - UML_LABEL(block, skip_adjust_timer); - UML_MOV(block, mem(&m_core->global_regs[dst_code]), I5); - } - else if (dst_code == MCR_REGISTER) - { - UML_ROLAND(block, I6, I5, 20, 0x7); - UML_LOAD(block, I6, (void *)s_trap_entries, I6, SIZE_DWORD, SCALE_x4); - UML_MOV(block, mem(&m_core->trap_entry), I6); - UML_MOV(block, mem(&m_core->global_regs[dst_code]), I5); - } - else - { - // reserved register - just store the value - UML_MOV(block, mem(&m_core->global_regs[dst_code]), I5); - } - } -} - -void hyperstone_device::generate_set_global_register_low(drcuml_block &block, compiler_state &compiler, uint32_t dst_code, uml::parameter src) +void hyperstone_device::generate_set_global_register_low(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t dst_code, uml::parameter src) { // clobbers I4 when setting SR if (dst_code == PC_REGISTER) @@ -275,8 +181,7 @@ void hyperstone_device::generate_set_global_register_low(drcuml_block &block, co UML_ROLINS(block, I4, src, 0, 0x0000ffff); UML_AND(block, I4, I4, ~0x40); // keep reserved bit clear } - UML_MOV(block, DRC_SR, I4); - UML_EXH(block, *m_exception, TRAPNO_PRIVILEGE_ERROR); + generate_raise_exception(block, compiler, desc, TRAPNO_PRIVILEGE_ERROR, uml::I4); UML_LABEL(block, no_exception); if (src.is_immediate()) { @@ -425,7 +330,7 @@ uml::parameter hyperstone_device::generate_load_address_ad(drcuml_block &block, else if ((code == PC_REGISTER) && ((desc->flags & OPFLAG_IN_DELAY_SLOT) || !compiler.check_delay())) { if (!compiler.pc()) - UML_EXH(block, *m_exception, TRAPNO_POINTER_ERROR); + generate_raise_exception(block, compiler, desc, TRAPNO_POINTER_ERROR); return compiler.pc(); } else @@ -440,8 +345,11 @@ uml::parameter hyperstone_device::generate_load_address_ad(drcuml_block &block, UML_LOAD(block, dst, (void *)m_core->local_regs, localidx, SIZE_DWORD, SCALE_x4); } + const int no_exception = compiler.next_label(); UML_TEST(block, dst, ~uint32_t(0)); - UML_EXHc(block, uml::COND_Z, *m_exception, TRAPNO_POINTER_ERROR); + UML_JMPc(block, uml::COND_NZ, no_exception); + generate_raise_exception(block, compiler, desc, TRAPNO_POINTER_ERROR); + UML_LABEL(block, no_exception); return dst; } @@ -474,12 +382,12 @@ void hyperstone_device::generate_load_address_ns(drcuml_block &block, compiler_s UML_MOV(block, mem(&m_core->global_regs[code]), dst); else UML_STORE(block, (void *)m_core->local_regs, localidx, dst, SIZE_DWORD, SCALE_x4); - UML_EXH(block, *m_exception, TRAPNO_POINTER_ERROR); + generate_raise_exception(block, compiler, desc, TRAPNO_POINTER_ERROR); UML_LABEL(block, no_exception); } -void hyperstone_device::generate_load_address_rp(drcuml_block &block, compiler_state &compiler, uint32_t code, uml::parameter dst, uml::parameter localidx, uint32_t dis) +void hyperstone_device::generate_load_address_rp(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t code, uml::parameter dst, uml::parameter localidx, uint32_t dis) { // expects frame pointer in I3 if local // sets I0 to masked address @@ -488,25 +396,42 @@ void hyperstone_device::generate_load_address_rp(drcuml_block &block, compiler_s generate_load_operand(block, compiler, LOCAL, code, dst, localidx); + const int no_exception = compiler.next_label(); UML_TEST(block, dst, ~uint32_t(0)); + UML_JMPc(block, uml::COND_NZ, no_exception); if (dis) { - const int no_exception = compiler.next_label(); - UML_JMPc(block, uml::COND_NZ, no_exception); UML_ADD(block, dst, dst, dis); UML_STORE(block, (void *)m_core->local_regs, localidx, dst, SIZE_DWORD, SCALE_x4); - UML_EXH(block, *m_exception, TRAPNO_POINTER_ERROR); - UML_LABEL(block, no_exception); - } - else - { - UML_EXHc(block, uml::COND_Z, *m_exception, TRAPNO_POINTER_ERROR); } + generate_raise_exception(block, compiler, desc, TRAPNO_POINTER_ERROR); + UML_LABEL(block, no_exception); UML_AND(block, I0, dst, ~uint32_t(3)); } +void hyperstone_device::generate_set_register(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, reg_bank global, uint32_t code, uml::parameter src, uml::parameter localidx, bool calcidx) +{ + // expects frame pointer in I3 if local and calcidx is true + // sets localidx if local and calcidx is true before storing src + // localidx is input if local and calcidx is false + // clobbers I4 when setting SR + if (global) + { + generate_set_global_register_low(block, compiler, desc, code, src); + } + else + { + if (calcidx) + { + UML_ADD(block, localidx, I3, code); + UML_AND(block, localidx, localidx, 0x3f); + } + UML_STORE(block, (void *)m_core->local_regs, localidx, src, SIZE_DWORD, SCALE_x4); + } +} + void hyperstone_device::generate_set_dst(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, reg_bank global, uint32_t code, uml::parameter src, uml::parameter localidx, bool calcidx) { // expects frame pointer in I3 if local and calcidx is true @@ -515,7 +440,7 @@ void hyperstone_device::generate_set_dst(drcuml_block &block, compiler_state &co // clobbers I4 when setting SR if (global) { - generate_set_global_register_low(block, compiler, code, src); + generate_set_global_register_low(block, compiler, desc, code, src); if (code == PC_REGISTER) { UML_AND(block, DRC_SR, DRC_SR, ~M_MASK); @@ -646,6 +571,55 @@ void hyperstone_device::generate_update_nz_d(drcuml_block &block, compiler_state } +void hyperstone_device::generate_raise_exception(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint8_t trapno, uml::parameter sr) +{ + if (desc->flags & OPFLAG_IN_DELAY_SLOT) + { + // definitely in delay slot - saved PC/ILC reflect delayed branch + UML_OR(block, sr, sr, P_MASK); + UML_MOV(block, DRC_PC, desc->pc); + } + else if (!compiler.check_delay()) + { + // not in delay slot - saved PC/ILC reflect current instruction + UML_ROLINS(block, sr, ((desc->length >> 1) << ILC_SHIFT) | P_MASK, 0, ILC_MASK | P_MASK); + } + else + { + // possibly in delay slot + const int set_delay_pc = compiler.next_label(); + const int done = compiler.next_label(); + UML_TEST(block, mem(&m_core->delay_slot_taken), ~uint32_t(0)); + UML_JMPc(block, uml::COND_NZ, set_delay_pc); + + UML_ROLINS(block, sr, ((desc->length >> 1) << ILC_SHIFT) | P_MASK, 0, ILC_MASK | P_MASK); + UML_JMP(block, done); + + UML_LABEL(block, set_delay_pc); + UML_OR(block, sr, sr, P_MASK); + UML_MOV(block, DRC_PC, desc->pc); + UML_LABEL(block, done); + } + UML_MOV(block, DRC_SR, sr); + UML_EXH(block, *m_exception, trapno); +} + +void hyperstone_device::generate_raise_exception(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint8_t trapno) +{ + UML_MOV(block, I2, DRC_SR); + generate_raise_exception(block, compiler, desc, trapno, uml::I2); +} + +void hyperstone_device::generate_exception_on_overflow(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uml::parameter sr) +{ + const int no_exception = compiler.next_label(); + UML_TEST(block, sr, V_MASK); + UML_JMPc(block, uml::COND_Z, no_exception); + generate_raise_exception(block, compiler, desc, TRAPNO_RANGE_ERROR, sr); + UML_LABEL(block, no_exception); +} + + template void hyperstone_device::generate_trap_exception_or_int(drcuml_block &block, uml::code_label &label, uml::parameter trapno) { @@ -696,17 +670,6 @@ void hyperstone_device::generate_trap_exception_or_int(drcuml_block &block, uml: UML_HASHJMP(block, 1, I0, *m_nocode); // T cleared and S set - mode will always be 1 } -void hyperstone_device::generate_trap_on_overflow(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uml::parameter sr) -{ - const int no_exception = compiler.next_label(); - UML_TEST(block, sr, V_MASK); - UML_JMPc(block, uml::COND_Z, no_exception); - UML_ROLINS(block, sr, ((desc->length >> 1) << ILC_SHIFT) | P_MASK, 0, ILC_MASK | P_MASK); - UML_MOV(block, DRC_SR, sr); - UML_EXH(block, *m_exception, TRAPNO_RANGE_ERROR); - UML_LABEL(block, no_exception); -} - template inline void hyperstone_device::generate_logic_op(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, T &&body) @@ -892,9 +855,7 @@ void hyperstone_device::generate_chk(drcuml_block &block, compiler_state &compil } } - UML_ROLINS(block, I2, ((desc->length >> 1) << ILC_SHIFT) | P_MASK, 0, ILC_MASK | P_MASK); - UML_MOV(block, DRC_SR, I2); - UML_EXH(block, *m_exception, TRAPNO_RANGE_ERROR); + generate_raise_exception(block, compiler, desc, TRAPNO_RANGE_ERROR, uml::I2); if (!unconditional) UML_LABEL(block, done); @@ -994,9 +955,8 @@ void hyperstone_device::generate_movd(drcuml_block &block, compiler_state &compi UML_AND(block, DRC_SR, DRC_SR, ~N_MASK); if (DstGlobal) { - generate_set_global_register_low(block, compiler, dst_code, 0); - UML_MOV(block, I5, 0); - generate_set_global_register(block, compiler, desc, dstf_code); + generate_set_global_register_low(block, compiler, desc, dst_code, 0); + generate_set_global_register_low(block, compiler, desc, dstf_code, 0); } else { @@ -1011,10 +971,9 @@ void hyperstone_device::generate_movd(drcuml_block &block, compiler_state &compi } else // Rd doesn't denote PC and Rs doesn't denote SR { + UML_MOV(block, I2, DRC_SR); if (!SrcGlobal || !DstGlobal) - { - UML_ROLAND(block, I3, DRC_SR, 32 - FP_SHIFT, 0x7f); - } + UML_ROLAND(block, I3, I2, 32 - FP_SHIFT, 0x7f); if (SrcGlobal) { @@ -1023,39 +982,37 @@ void hyperstone_device::generate_movd(drcuml_block &block, compiler_state &compi } else { - UML_ADD(block, I0, I3, src_code); - UML_AND(block, I0, I0, 0x3f); - UML_LOAD(block, I0, (void *)m_core->local_regs, I0, SIZE_DWORD, SCALE_x4); - UML_ADD(block, I1, I3, srcf_code); + 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); + + 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); } - UML_AND(block, DRC_SR, DRC_SR, ~(Z_MASK | N_MASK)); - - UML_OR(block, I2, I0, I1); - UML_TEST(block, I2, ~0); - UML_SETc(block, uml::COND_Z, I2); - UML_ROLINS(block, DRC_SR, I2, Z_SHIFT, Z_MASK); - - UML_TEST(block, I0, 0x80000000); - UML_SETc(block, uml::COND_NZ, I2); - UML_ROLINS(block, DRC_SR, I2, N_SHIFT, N_MASK); + UML_AND(block, I2, I2, ~(Z_MASK | N_MASK)); + UML_OR(block, I4, I0, I1); + UML_SETc(block, uml::COND_Z, I4); + UML_ROLINS(block, I2, I4, Z_SHIFT, Z_MASK); + UML_ROLAND(block, I4, I0, N_SHIFT + 1, N_MASK); + UML_OR(block, I2, I2, I4); + UML_MOV(block, DRC_SR, I2); if (DstGlobal) { - generate_set_global_register_low(block, compiler, dst_code, uml::I0); - UML_MOV(block, I5, I1); - generate_set_global_register(block, compiler, desc, dstf_code); + generate_set_global_register_low(block, compiler, desc, dst_code, uml::I0); + generate_set_global_register_low(block, compiler, desc, dstf_code, uml::I1); } else { - UML_ADD(block, I2, I3, dst_code); - UML_AND(block, I2, I2, 0x3f); - UML_STORE(block, (void *)m_core->local_regs, I2, I0, SIZE_DWORD, SCALE_x4); - UML_ADD(block, I2, I3, dstf_code); - UML_AND(block, I2, I2, 0x3f); - UML_STORE(block, (void *)m_core->local_regs, I2, I1, SIZE_DWORD, SCALE_x4); + UML_ADD(block, I3, I3, dst_code); + UML_AND(block, I3, I3, 0x3f); + UML_STORE(block, (void *)m_core->local_regs, I3, I0, SIZE_DWORD, SCALE_x4); + + UML_ADD(block, I3, I3, 1); + UML_AND(block, I3, I3, 0x3f); + UML_STORE(block, (void *)m_core->local_regs, I3, I1, SIZE_DWORD, SCALE_x4); } } } @@ -1138,8 +1095,7 @@ void hyperstone_device::generate_divsu(drcuml_block &block, compiler_state &comp UML_JMP(block, done); UML_LABEL(block, no_result); - UML_ROLINS(block, DRC_SR, ((desc->length >> 1) << ILC_SHIFT) | P_MASK | V_MASK, 0, ILC_MASK | P_MASK | V_MASK); - UML_EXH(block, *m_exception, TRAPNO_RANGE_ERROR); + generate_raise_exception(block, compiler, desc, TRAPNO_RANGE_ERROR); UML_LABEL(block, done); } @@ -1161,8 +1117,12 @@ void hyperstone_device::generate_xm(drcuml_block &block, compiler_state &compile if (next & 0x8000) extra_u = ((extra_u & 0xfff) << 16) | m_pr16(desc->pc + 4); - if ((SrcGlobal && (src_code == SR_REGISTER)) || (DstGlobal && (dst_code < 2))) + if ((SrcGlobal && (src_code == SR_REGISTER)) || (DstGlobal && (dst_code <= SR_REGISTER))) + { + // reserved for future expansion + osd_printf_error("Denoted PC or SR in hyperstone_xm. PC = %08X\n", desc->pc); return; + } UML_MOV(block, I2, DRC_SR); if (!SrcGlobal || !DstGlobal) @@ -1172,22 +1132,19 @@ void hyperstone_device::generate_xm(drcuml_block &block, compiler_state &compile UML_SHL(block, I0, I1, sub_type & 3); - // FIXME: exception before branch generate_set_dst(block, compiler, desc, DstGlobal, dst_code, uml::I0, uml::I3, true); if (sub_type < 4) { - const int done = compiler.next_label(); + const int no_exception = compiler.next_label(); UML_CMP(block, I1, extra_u); if (SrcGlobal && (src_code == PC_REGISTER)) - UML_JMPc(block, uml::COND_B, done); + UML_JMPc(block, uml::COND_B, no_exception); else - UML_JMPc(block, uml::COND_BE, done); + UML_JMPc(block, uml::COND_BE, no_exception); - UML_ROLINS(block, I2, ((desc->length >> 1) << ILC_SHIFT) | P_MASK, 0, ILC_MASK | P_MASK); - UML_MOV(block, DRC_SR, I2); - UML_EXH(block, *m_exception, TRAPNO_RANGE_ERROR); - UML_LABEL(block, done); + generate_raise_exception(block, compiler, desc, TRAPNO_RANGE_ERROR, uml::I2); + UML_LABEL(block, no_exception); } } @@ -1283,9 +1240,22 @@ void hyperstone_device::generate_sums(drcuml_block &block, compiler_state &compi generate_update_flags_addsubs(block, compiler, uml::I2); UML_MOV(block, DRC_SR, I2); - // FIXME: exception before branch - generate_set_dst(block, compiler, desc, DstGlobal, dst_code, uml::I0, uml::I3, true); - generate_trap_on_overflow(block, compiler, desc, uml::I2); + generate_set_register(block, compiler, desc, DstGlobal, dst_code, uml::I0, uml::I3, true); + generate_exception_on_overflow(block, compiler, desc, uml::I2); + + if (DstGlobal && (dst_code == PC_REGISTER)) + { + UML_AND(block, DRC_SR, DRC_SR, ~M_MASK); + if (desc->targetpc == BRANCH_TARGET_DYNAMIC) + { + UML_AND(block, I0, I0, ~uint32_t(1)); + generate_branch(block, compiler, compiler.mode(), uml::I0, desc); + } + else + { + generate_branch(block, compiler, compiler.mode(), desc->targetpc, desc); + } + } } @@ -1320,16 +1290,21 @@ void hyperstone_device::generate_mov(drcuml_block &block, compiler_state &compil const uint32_t src_code = op & 0xf; const uint32_t dst_code = (op & 0xf0) >> 4; - UML_AND(block, I2, DRC_SR, ~(Z_MASK | N_MASK)); + UML_MOV(block, I2, DRC_SR); if (!SrcGlobal || !DstGlobal) UML_ROLAND(block, I3, I2, 32 - FP_SHIFT, 0x7f); if (DstGlobal && compiler.user_mode()) { + const int no_exception = compiler.next_label(); UML_TEST(block, I2, H_MASK); - UML_EXHc(block, uml::COND_NZ, *m_exception, TRAPNO_PRIVILEGE_ERROR); + UML_JMPc(block, uml::COND_Z, no_exception); + generate_raise_exception(block, compiler, desc, TRAPNO_PRIVILEGE_ERROR, uml::I2); + UML_LABEL(block, no_exception); } + UML_AND(block, I2, I2, ~(Z_MASK | N_MASK)); + if (SrcGlobal) { if (!DstGlobal || compiler.supervisor_mode()) @@ -1380,7 +1355,7 @@ void hyperstone_device::generate_mov(drcuml_block &block, compiler_state &compil UML_JMPc(block, uml::COND_NZ, highglobal); UML_MOV(block, DRC_SR, I2); - generate_set_global_register_low(block, compiler, dst_code, uml::I0); + generate_set_global_register_low(block, compiler, desc, dst_code, uml::I0); if (dst_code == PC_REGISTER) { UML_AND(block, DRC_SR, DRC_SR, ~M_MASK); @@ -1402,7 +1377,7 @@ void hyperstone_device::generate_mov(drcuml_block &block, compiler_state &compil else { UML_MOV(block, DRC_SR, I2); - generate_set_global_register_low(block, compiler, dst_code, uml::I0); + generate_set_global_register_low(block, compiler, desc, dst_code, uml::I0); if (dst_code == PC_REGISTER) { UML_AND(block, DRC_SR, DRC_SR, ~M_MASK); @@ -1523,9 +1498,22 @@ void hyperstone_device::generate_adds(drcuml_block &block, compiler_state &compi generate_update_flags_addsubs(block, compiler, uml::I2); UML_MOV(block, DRC_SR, I2); - // FIXME: exception before branch - generate_set_dst(block, compiler, desc, DstGlobal, dst_code, uml::I0, uml::I3, false); - generate_trap_on_overflow(block, compiler, desc, uml::I2); + generate_set_register(block, compiler, desc, DstGlobal, dst_code, uml::I0, uml::I3, false); + generate_exception_on_overflow(block, compiler, desc, uml::I2); + + if (DstGlobal && (dst_code == PC_REGISTER)) + { + UML_AND(block, DRC_SR, DRC_SR, ~M_MASK); + if (desc->targetpc == BRANCH_TARGET_DYNAMIC) + { + UML_AND(block, I0, I0, ~uint32_t(1)); + generate_branch(block, compiler, compiler.mode(), uml::I0, desc); + } + else + { + generate_branch(block, compiler, compiler.mode(), desc->targetpc, desc); + } + } } @@ -1629,9 +1617,22 @@ void hyperstone_device::generate_subs(drcuml_block &block, compiler_state &compi generate_update_flags_addsubs(block, compiler, uml::I2); UML_MOV(block, DRC_SR, I2); - // FIXME: exception before branch - generate_set_dst(block, compiler, desc, DstGlobal, dst_code, uml::I0, uml::I3, false); - generate_trap_on_overflow(block, compiler, desc, uml::I2); + generate_set_register(block, compiler, desc, DstGlobal, dst_code, uml::I0, uml::I3, false); + generate_exception_on_overflow(block, compiler, desc, uml::I2); + + if (DstGlobal && (dst_code == PC_REGISTER)) + { + UML_AND(block, DRC_SR, DRC_SR, ~M_MASK); + if (desc->targetpc == BRANCH_TARGET_DYNAMIC) + { + UML_AND(block, I0, I0, ~uint32_t(1)); + generate_branch(block, compiler, compiler.mode(), uml::I0, desc); + } + else + { + generate_branch(block, compiler, compiler.mode(), desc->targetpc, desc); + } + } } @@ -1712,11 +1713,24 @@ void hyperstone_device::generate_negs(drcuml_block &block, compiler_state &compi generate_update_flags_addsubs(block, compiler, uml::I2); UML_MOV(block, DRC_SR, I2); - // FIXME: exception before branch - generate_set_dst(block, compiler, desc, DstGlobal, dst_code, uml::I0, uml::I3, true); + generate_set_register(block, compiler, desc, DstGlobal, dst_code, uml::I0, uml::I3, true); if (!SrcGlobal || (src_code != SR_REGISTER)) // negating carry cannot result in overflow - generate_trap_on_overflow(block, compiler, desc, uml::I2); + generate_exception_on_overflow(block, compiler, desc, uml::I2); + + if (DstGlobal && (dst_code == PC_REGISTER)) + { + UML_AND(block, DRC_SR, DRC_SR, ~M_MASK); + if (desc->targetpc == BRANCH_TARGET_DYNAMIC) + { + UML_AND(block, I0, I0, ~uint32_t(1)); + generate_branch(block, compiler, compiler.mode(), uml::I0, desc); + } + else + { + generate_branch(block, compiler, compiler.mode(), desc->targetpc, desc); + } + } } @@ -1829,14 +1843,18 @@ void hyperstone_device::generate_movi(drcuml_block &block, compiler_state &compi else src = op & 0x0f; - UML_AND(block, I2, DRC_SR, ~(Z_MASK | N_MASK)); + UML_MOV(block, I2, DRC_SR); if (DstGlobal && compiler.user_mode()) { + const int no_exception = compiler.next_label(); UML_TEST(block, I2, H_MASK); - UML_EXHc(block, uml::COND_NZ, *m_exception, TRAPNO_PRIVILEGE_ERROR); + UML_JMPc(block, uml::COND_Z, no_exception); + generate_raise_exception(block, compiler, desc, TRAPNO_PRIVILEGE_ERROR, uml::I2); + UML_LABEL(block, no_exception); } + UML_AND(block, I2, I2, ~(Z_MASK | N_MASK)); if (!src) UML_OR(block, I2, I2, Z_MASK); else if (src & 0x80000000) @@ -1856,7 +1874,7 @@ void hyperstone_device::generate_movi(drcuml_block &block, compiler_state &compi UML_JMPc(block, uml::COND_NZ, highglobal); UML_MOV(block, DRC_SR, I2); - generate_set_global_register_low(block, compiler, dst_code, src); + generate_set_global_register_low(block, compiler, desc, dst_code, src); if (dst_code == PC_REGISTER) { UML_AND(block, DRC_SR, DRC_SR, ~M_MASK); @@ -1877,7 +1895,7 @@ void hyperstone_device::generate_movi(drcuml_block &block, compiler_state &compi else { UML_MOV(block, DRC_SR, I2); - generate_set_global_register_low(block, compiler, dst_code, src); + generate_set_global_register_low(block, compiler, desc, dst_code, src); if (dst_code == PC_REGISTER) { UML_AND(block, DRC_SR, DRC_SR, ~M_MASK); @@ -2668,7 +2686,7 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp if (SrcGlobal) { - generate_set_global_register_low(block, compiler, src_code, uml::I1); + generate_set_global_register_low(block, compiler, desc, src_code, uml::I1); if (src_code == PC_REGISTER) { UML_AND(block, I1, I1, ~uint32_t(1)); @@ -2692,7 +2710,7 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp if (SrcGlobal) { - generate_set_global_register_low(block, compiler, src_code, uml::I1); + generate_set_global_register_low(block, compiler, desc, src_code, uml::I1); if (src_code == PC_REGISTER) { UML_AND(block, I1, I1, ~uint32_t(1)); @@ -2717,7 +2735,7 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp if (SrcGlobal) { - generate_set_global_register_low(block, compiler, src_code, uml::I1); + generate_set_global_register_low(block, compiler, desc, src_code, uml::I1); if (src_code == PC_REGISTER) { UML_AND(block, I1, I1, ~uint32_t(1)); @@ -2731,41 +2749,20 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp UML_STORE(block, (void *)m_core->local_regs, I3, I1, SIZE_DWORD, SCALE_x4); } break; + case 1: // LDD.D/A UML_MOV(block, I7, mem(&m_core->clock_cycles_2)); UML_CALLH(block, *m_mem_read32); - - if (SrcGlobal) - { - generate_set_global_register_low(block, compiler, src_code, uml::I1); - if (src_code == PC_REGISTER) - { - UML_AND(block, I1, I1, ~uint32_t(1)); - generate_branch(block, compiler, compiler.mode(), uml::I1, desc); - } - } - else - { - UML_ADD(block, I2, I3, src_code); - UML_AND(block, I2, I2, 0x3f); - UML_STORE(block, (void *)m_core->local_regs, I2, I1, SIZE_DWORD, SCALE_x4); - } + generate_set_register(block, compiler, desc, SrcGlobal, src_code, uml::I1, uml::I2, true); UML_ADD(block, I0, I0, 4); UML_CALLH(block, *m_mem_read32); + generate_set_register(block, compiler, desc, SrcGlobal, srcf_code, uml::I1, uml::I3, true); - if (SrcGlobal) - { - UML_MOV(block, I5, I1); - generate_set_global_register(block, compiler, desc, srcf_code); - } - else - { - UML_ADD(block, I3, I3, srcf_code); - UML_AND(block, I3, I3, 0x3f); - UML_STORE(block, (void *)m_core->local_regs, I3, I1, SIZE_DWORD, SCALE_x4); - } + if (src_code == PC_REGISTER) + generate_branch(block, compiler, compiler.mode(), desc->targetpc, desc); break; + case 2: // LDW.IOD/A UML_MOV(block, I7, mem(&m_core->clock_cycles_1)); UML_ROLAND(block, I0, I0, 21, 0x7ffc); @@ -2773,8 +2770,8 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp if (SrcGlobal) { - generate_set_global_register_low(block, compiler, src_code, uml::I1); - if (src_code == 0) + generate_set_global_register_low(block, compiler, desc, src_code, uml::I1); + if (src_code == PC_REGISTER) { UML_AND(block, I1, I1, ~uint32_t(1)); generate_branch(block, compiler, compiler.mode(), uml::I1, desc); @@ -2792,37 +2789,14 @@ void hyperstone_device::generate_ldxx1(drcuml_block &block, compiler_state &comp UML_MOV(block, I7, mem(&m_core->clock_cycles_2)); UML_ROLAND(block, I0, I0, 21, 0x7ffc); UML_CALLH(block, *m_io_read32); - - if (SrcGlobal) - { - generate_set_global_register_low(block, compiler, src_code, uml::I1); - if (src_code == PC_REGISTER) - { - UML_AND(block, I1, I1, ~uint32_t(1)); - generate_branch(block, compiler, compiler.mode(), uml::I1, desc); - } - } - else - { - UML_ADD(block, I2, I3, src_code); - UML_AND(block, I2, I2, 0x3f); - UML_STORE(block, (void *)m_core->local_regs, I2, I1, SIZE_DWORD, SCALE_x4); - } + generate_set_register(block, compiler, desc, SrcGlobal, src_code, uml::I1, uml::I2, true); UML_ADD(block, I0, I0, 4); UML_CALLH(block, *m_io_read32); + generate_set_register(block, compiler, desc, SrcGlobal, srcf_code, uml::I1, uml::I3, true); - if (SrcGlobal) - { - UML_MOV(block, I5, I1); - generate_set_global_register(block, compiler, desc, srcf_code); - } - else - { - UML_ADD(block, I3, I3, srcf_code); - UML_AND(block, I3, I3, 0x3f); - UML_STORE(block, (void *)m_core->local_regs, I3, I1, SIZE_DWORD, SCALE_x4); - } + if (src_code == PC_REGISTER) + generate_branch(block, compiler, compiler.mode(), desc->targetpc, desc); break; } break; @@ -2910,13 +2884,12 @@ void hyperstone_device::generate_ldxx2(drcuml_block &block, compiler_state &comp if (SrcGlobal) { - generate_set_global_register_low(block, compiler, src_code, uml::I1); + generate_set_global_register_low(block, compiler, desc, src_code, uml::I1); UML_ADD(block, I0, I0, 4); UML_CALLH(block, *m_mem_read32); - UML_MOV(block, I5, I1); - generate_set_global_register(block, compiler, desc, srcf_code); + generate_set_global_register_low(block, compiler, desc, srcf_code, uml::I1); } else { @@ -3018,9 +2991,12 @@ void hyperstone_device::generate_stxx1(drcuml_block &block, compiler_state &comp if (sub_type == 0) { + const int no_exception = compiler.next_label(); UML_SEXT(block, I0, I1, SIZE_BYTE); UML_CMP(block, I0, I1); - UML_EXHc(block, uml::COND_NZ, *m_exception, TRAPNO_RANGE_ERROR); + UML_JMPc(block, uml::COND_E, no_exception); + generate_raise_exception(block, compiler, desc, TRAPNO_RANGE_ERROR); + UML_LABEL(block, no_exception); } break; @@ -3031,9 +3007,12 @@ void hyperstone_device::generate_stxx1(drcuml_block &block, compiler_state &comp if (extra_s & 1) { + const int no_exception = compiler.next_label(); UML_SEXT(block, I0, I1, SIZE_WORD); UML_CMP(block, I0, I1); - UML_EXHc(block, uml::COND_NZ, *m_exception, TRAPNO_RANGE_ERROR); + UML_JMPc(block, uml::COND_E, no_exception); + generate_raise_exception(block, compiler, desc, TRAPNO_RANGE_ERROR); + UML_LABEL(block, no_exception); } break; @@ -3149,9 +3128,12 @@ void hyperstone_device::generate_stxx2(drcuml_block &block, compiler_state &comp if (sub_type == 0) { + const int no_exception = compiler.next_label(); UML_SEXT(block, I0, I1, SIZE_BYTE); UML_CMP(block, I0, I1); - UML_EXHc(block, uml::COND_NZ, *m_exception, TRAPNO_RANGE_ERROR); + UML_JMPc(block, uml::COND_E, no_exception); + generate_raise_exception(block, compiler, desc, TRAPNO_RANGE_ERROR); + UML_LABEL(block, no_exception); } break; @@ -3169,9 +3151,12 @@ void hyperstone_device::generate_stxx2(drcuml_block &block, compiler_state &comp if (extra_s & 1) { + const int no_exception = compiler.next_label(); UML_SEXT(block, I0, I1, SIZE_WORD); UML_CMP(block, I0, I1); - UML_EXHc(block, uml::COND_NZ, *m_exception, TRAPNO_RANGE_ERROR); + UML_JMPc(block, uml::COND_E, no_exception); + generate_raise_exception(block, compiler, desc, TRAPNO_RANGE_ERROR); + UML_LABEL(block, no_exception); } break; @@ -3461,9 +3446,9 @@ void hyperstone_device::generate_ldwr(drcuml_block &block, compiler_state &compi UML_ROLAND(block, I3, DRC_SR, 32 - FP_SHIFT, 0x7f); if (SrcGlobal || (src_code != dst_code)) - generate_load_address_rp(block, compiler, dst_code, uml::I0, uml::I2, 0); + generate_load_address_rp(block, compiler, desc, dst_code, uml::I0, uml::I2, 0); else - generate_load_address_rp(block, compiler, dst_code, uml::I0, uml::I3, 0); + generate_load_address_rp(block, compiler, desc, dst_code, uml::I0, uml::I3, 0); UML_CALLH(block, *m_mem_read32); @@ -3486,21 +3471,20 @@ void hyperstone_device::generate_lddr(drcuml_block &block, compiler_state &compi UML_ROLAND(block, I3, DRC_SR, 32 - FP_SHIFT, 0x7f); if (!SrcGlobal && (src_code != dst_code)) - generate_load_address_rp(block, compiler, dst_code, uml::I0, uml::I2, 0); + generate_load_address_rp(block, compiler, desc, dst_code, uml::I0, uml::I2, 0); else - generate_load_address_rp(block, compiler, dst_code, uml::I0, uml::I3, 0); + generate_load_address_rp(block, compiler, desc, dst_code, uml::I0, uml::I3, 0); UML_CALLH(block, *m_mem_read32); if (SrcGlobal) { - generate_set_global_register_low(block, compiler, src_code, uml::I1); + generate_set_global_register_low(block, compiler, desc, src_code, uml::I1); UML_ADD(block, I0, I0, 4); UML_CALLH(block, *m_mem_read32); - UML_MOV(block, I5, I1); - generate_set_global_register(block, compiler, desc, src_code + 1); + generate_set_global_register_low(block, compiler, desc, src_code + 1, uml::I1); } else { @@ -3533,9 +3517,9 @@ void hyperstone_device::generate_ldwp(drcuml_block &block, compiler_state &compi UML_ROLAND(block, I3, DRC_SR, 32 - FP_SHIFT, 0x7f); if (SrcGlobal || (src_code != dst_code)) - generate_load_address_rp(block, compiler, dst_code, uml::I4, uml::I2, 4); + generate_load_address_rp(block, compiler, desc, dst_code, uml::I4, uml::I2, 4); else - generate_load_address_rp(block, compiler, dst_code, uml::I4, uml::I3, 4); + generate_load_address_rp(block, compiler, desc, dst_code, uml::I4, uml::I3, 4); UML_CALLH(block, *m_mem_read32); @@ -3565,9 +3549,9 @@ void hyperstone_device::generate_lddp(drcuml_block &block, compiler_state &compi UML_ROLAND(block, I3, DRC_SR, 32 - FP_SHIFT, 0x7f); if (SrcGlobal || (src_code != dst_code)) - generate_load_address_rp(block, compiler, dst_code, uml::I4, uml::I2, 8); + generate_load_address_rp(block, compiler, desc, dst_code, uml::I4, uml::I2, 8); else - generate_load_address_rp(block, compiler, dst_code, uml::I4, uml::I3, 8); + generate_load_address_rp(block, compiler, desc, dst_code, uml::I4, uml::I3, 8); UML_CALLH(block, *m_mem_read32); @@ -3579,13 +3563,12 @@ void hyperstone_device::generate_lddp(drcuml_block &block, compiler_state &compi if (SrcGlobal) { - generate_set_global_register_low(block, compiler, src_code, uml::I1); + generate_set_global_register_low(block, compiler, desc, src_code, uml::I1); UML_ADD(block, I0, I0, 4); UML_CALLH(block, *m_mem_read32); - UML_MOV(block, I5, I1); - generate_set_global_register(block, compiler, desc, src_code + 1); + generate_set_global_register_low(block, compiler, desc, src_code + 1, uml::I1); } else { @@ -3618,9 +3601,9 @@ void hyperstone_device::generate_stwr(drcuml_block &block, compiler_state &compi UML_ROLAND(block, I3, DRC_SR, 32 - FP_SHIFT, 0x7f); if (SrcGlobal || (src_code != dst_code)) - generate_load_address_rp(block, compiler, dst_code, uml::I0, uml::I2, 0); + generate_load_address_rp(block, compiler, desc, dst_code, uml::I0, uml::I2, 0); else - generate_load_address_rp(block, compiler, dst_code, uml::I1, uml::I3, 0); + generate_load_address_rp(block, compiler, desc, dst_code, uml::I1, uml::I3, 0); if (SrcGlobal) { @@ -3652,9 +3635,9 @@ void hyperstone_device::generate_stdr(drcuml_block &block, compiler_state &compi UML_ROLAND(block, I3, DRC_SR, 32 - FP_SHIFT, 0x7f); if (SrcGlobal || (src_code != dst_code)) - generate_load_address_rp(block, compiler, dst_code, uml::I0, uml::I2, 0); + generate_load_address_rp(block, compiler, desc, dst_code, uml::I0, uml::I2, 0); else - generate_load_address_rp(block, compiler, dst_code, uml::I1, uml::I3, 0); + generate_load_address_rp(block, compiler, desc, dst_code, uml::I1, uml::I3, 0); uml::parameter srcfp = uml::I2; if (SrcGlobal) @@ -3703,9 +3686,9 @@ void hyperstone_device::generate_stwp(drcuml_block &block, compiler_state &compi UML_ROLAND(block, I3, DRC_SR, 32 - FP_SHIFT, 0x7f); if (SrcGlobal || (src_code != dst_code)) - generate_load_address_rp(block, compiler, dst_code, uml::I4, uml::I2, 4); + generate_load_address_rp(block, compiler, desc, dst_code, uml::I4, uml::I2, 4); else - generate_load_address_rp(block, compiler, dst_code, uml::I1, uml::I3, 4); + generate_load_address_rp(block, compiler, desc, dst_code, uml::I1, uml::I3, 4); if (SrcGlobal) { @@ -3748,9 +3731,9 @@ void hyperstone_device::generate_stdp(drcuml_block &block, compiler_state &compi UML_ROLAND(block, I3, DRC_SR, 32 - FP_SHIFT, 0x7f); if (SrcGlobal || (src_code != dst_code)) - generate_load_address_rp(block, compiler, dst_code, uml::I4, uml::I2, 8); + generate_load_address_rp(block, compiler, desc, dst_code, uml::I4, uml::I2, 8); else - generate_load_address_rp(block, compiler, dst_code, uml::I1, uml::I3, 8); + generate_load_address_rp(block, compiler, desc, dst_code, uml::I1, uml::I3, 8); if (SrcGlobal) { @@ -3962,8 +3945,7 @@ void hyperstone_device::generate_frame(drcuml_block &block, compiler_state &comp UML_TEST(block, I4, ~uint32_t(0)); UML_JMPc(block, uml::COND_Z, done); - UML_ROLINS(block, DRC_SR, ((desc->length >> 1) << ILC_SHIFT) | P_MASK, 0, ILC_MASK | P_MASK); - UML_EXH(block, *m_exception, TRAPNO_FRAME_ERROR); + generate_raise_exception(block, compiler, desc, TRAPNO_FRAME_ERROR); UML_LABEL(block, done); } diff --git a/src/emu/debug/debugvw.cpp b/src/emu/debug/debugvw.cpp index 54fe57ecf5a..7412ddd2f60 100644 --- a/src/emu/debug/debugvw.cpp +++ b/src/emu/debug/debugvw.cpp @@ -14,6 +14,7 @@ #include "debugcpu.h" #include "dvbpoints.h" #include "dvdisasm.h" +#include "dvepoints.h" #include "dvmemory.h" #include "dvrpoints.h" #include "dvstate.h" @@ -369,6 +370,9 @@ debug_view *debug_view_manager::alloc_view(debug_view_type type, debug_view_osd_ case DVT_REGISTER_POINTS: return append(new debug_view_registerpoints(machine(), osdupdate, osdprivate)); + case DVT_EXCEPTION_POINTS: + return append(new debug_view_exceptionpoints(machine(), osdupdate, osdprivate)); + default: fatalerror("Attempt to create invalid debug view type %d\n", type); } diff --git a/src/emu/debug/debugvw.h b/src/emu/debug/debugvw.h index 73f93d14f32..64bd5dac10a 100644 --- a/src/emu/debug/debugvw.h +++ b/src/emu/debug/debugvw.h @@ -35,7 +35,8 @@ enum debug_view_type DVT_LOG, DVT_BREAK_POINTS, DVT_WATCH_POINTS, - DVT_REGISTER_POINTS + DVT_REGISTER_POINTS, + DVT_EXCEPTION_POINTS }; diff --git a/src/emu/debug/dvepoints.cpp b/src/emu/debug/dvepoints.cpp new file mode 100644 index 00000000000..2ebc53a6609 --- /dev/null +++ b/src/emu/debug/dvepoints.cpp @@ -0,0 +1,314 @@ +// license:BSD-3-Clause +// copyright-holders:Andrew Gardner, Vas Crabb +/********************************************************************* + + dvepoints.cpp + + Exceptionpoint debugger view. + +***************************************************************************/ + +#include "emu.h" +#include "dvepoints.h" + +#include "debugcpu.h" +#include "points.h" + +#include +#include + + + +// Sorting functors for the qsort function +static bool cIndexAscending(const debug_exceptionpoint *a, const debug_exceptionpoint *b) +{ + return a->index() < b->index(); +} + +static bool cIndexDescending(const debug_exceptionpoint *a, const debug_exceptionpoint *b) +{ + return cIndexAscending(b, a); +} + +static bool cEnabledAscending(const debug_exceptionpoint *a, const debug_exceptionpoint *b) +{ + return !a->enabled() && b->enabled(); +} + +static bool cEnabledDescending(const debug_exceptionpoint *a, const debug_exceptionpoint *b) +{ + return cEnabledAscending(b, a); +} + +static bool cCpuAscending(const debug_exceptionpoint *a, const debug_exceptionpoint *b) +{ + return strcmp(a->debugInterface()->device().tag(), b->debugInterface()->device().tag()) < 0; +} + +static bool cCpuDescending(const debug_exceptionpoint *a, const debug_exceptionpoint *b) +{ + return cCpuAscending(b, a); +} + +static bool cTypeAscending(const debug_exceptionpoint *a, const debug_exceptionpoint *b) +{ + return a->type() < b->type(); +} + +static bool cTypeDescending(const debug_exceptionpoint *a, const debug_exceptionpoint *b) +{ + return cTypeAscending(b, a); +} + +static bool cConditionAscending(const debug_exceptionpoint *a, const debug_exceptionpoint *b) +{ + return strcmp(a->condition(), b->condition()) < 0; +} + +static bool cConditionDescending(const debug_exceptionpoint *a, const debug_exceptionpoint *b) +{ + return cConditionAscending(b, a); +} + +static bool cActionAscending(const debug_exceptionpoint *a, const debug_exceptionpoint *b) +{ + return a->action() < b->action(); +} + +static bool cActionDescending(const debug_exceptionpoint *a, const debug_exceptionpoint *b) +{ + return cActionAscending(b, a); +} + + +//************************************************************************** +// DEBUG VIEW BREAK POINTS +//************************************************************************** + +static const int tableBreaks[] = { 5, 9, 31, 45, 63, 80 }; + + +//------------------------------------------------- +// debug_view_exceptionpoints - constructor +//------------------------------------------------- + +debug_view_exceptionpoints::debug_view_exceptionpoints(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate) + : debug_view(machine, DVT_EXCEPTION_POINTS, osdupdate, osdprivate) + , m_sortType(cIndexAscending) +{ + // fail if no available sources + enumerate_sources(); + if (m_source_list.empty()) + throw std::bad_alloc(); +} + + +//------------------------------------------------- +// ~debug_view_exceptionpoints - destructor +//------------------------------------------------- + +debug_view_exceptionpoints::~debug_view_exceptionpoints() +{ +} + + +//------------------------------------------------- +// enumerate_sources - enumerate all possible +// sources for a disassembly view +//------------------------------------------------- + +void debug_view_exceptionpoints::enumerate_sources() +{ + // start with an empty list + m_source_list.clear(); + + // iterate over devices with disassembly interfaces + for (device_disasm_interface &dasm : disasm_interface_enumerator(machine().root_device())) + { + m_source_list.emplace_back( + std::make_unique( + util::string_format("%s '%s'", dasm.device().name(), dasm.device().tag()), + &dasm.device())); + } + + // reset the source to a known good entry + if (!m_source_list.empty()) + set_source(*m_source_list[0]); +} + + +//------------------------------------------------- +// view_click - handle a mouse click within the +// current view +//------------------------------------------------- + +void debug_view_exceptionpoints::view_click(const int button, const debug_view_xy& pos) +{ + bool clickedTopRow = (m_topleft.y == pos.y); + + if (clickedTopRow) + { + if (pos.x < tableBreaks[0]) + m_sortType = (m_sortType == &cIndexAscending) ? &cIndexDescending : &cIndexAscending; + else if (pos.x < tableBreaks[1]) + m_sortType = (m_sortType == &cEnabledAscending) ? &cEnabledDescending : &cEnabledAscending; + else if (pos.x < tableBreaks[2]) + m_sortType = (m_sortType == &cCpuAscending) ? &cCpuDescending : &cCpuAscending; + else if (pos.x < tableBreaks[3]) + m_sortType = (m_sortType == &cTypeAscending) ? &cTypeDescending : &cTypeAscending; + else if (pos.x < tableBreaks[4]) + m_sortType = (m_sortType == &cConditionAscending) ? &cConditionDescending : &cConditionAscending; + else if (pos.x < tableBreaks[5]) + m_sortType = (m_sortType == &cActionAscending) ? &cActionDescending : &cActionAscending; + } + else + { + // Gather a sorted list of all the exceptionpoints for all the CPUs + gather_exceptionpoints(); + + int epIndex = pos.y - 1; + if ((epIndex >= m_buffer.size()) || (epIndex < 0)) + return; + + // Enable / disable + const_cast(*m_buffer[epIndex]).setEnabled(!m_buffer[epIndex]->enabled()); + + machine().debug_view().update_all(DVT_DISASSEMBLY); + } + + begin_update(); + m_update_pending = true; + end_update(); +} + + +void debug_view_exceptionpoints::pad_ostream_to_length(std::ostream& str, int len) +{ + auto const current = str.tellp(); + if (current < decltype(current)(len)) + str << std::setw(decltype(current)(len) - current) << ""; +} + + +void debug_view_exceptionpoints::gather_exceptionpoints() +{ + m_buffer.resize(0); + for (auto &source : m_source_list) + { + // Collect + device_debug &debugInterface = *source->device()->debug(); + for (const auto &epp : debugInterface.exceptionpoint_list()) + m_buffer.push_back(epp.second.get()); + } + + // And now for the sort + if (!m_buffer.empty()) + std::stable_sort(m_buffer.begin(), m_buffer.end(), m_sortType); +} + + +//------------------------------------------------- +// view_update - update the contents of the +// exceptionpoints view +//------------------------------------------------- + +void debug_view_exceptionpoints::view_update() +{ + // Gather a list of all the exceptionpoints for all the CPUs + gather_exceptionpoints(); + + // Set the view region so the scroll bars update + m_total.x = tableBreaks[std::size(tableBreaks) - 1]; + m_total.y = m_buffer.size() + 1; + if (m_total.y < 10) + m_total.y = 10; + + // Draw + debug_view_char *dest = &m_viewdata[0]; + util::ovectorstream linebuf; + linebuf.reserve(std::size(tableBreaks) - 1); + + // Header + if (m_visible.y > 0) + { + linebuf.clear(); + linebuf.rdbuf()->clear(); + linebuf << "ID"; + if (m_sortType == &cIndexAscending) linebuf.put('\\'); + else if (m_sortType == &cIndexDescending) linebuf.put('/'); + pad_ostream_to_length(linebuf, tableBreaks[0]); + linebuf << "En"; + if (m_sortType == &cEnabledAscending) linebuf.put('\\'); + else if (m_sortType == &cEnabledDescending) linebuf.put('/'); + pad_ostream_to_length(linebuf, tableBreaks[1]); + linebuf << "CPU"; + if (m_sortType == &cCpuAscending) linebuf.put('\\'); + else if (m_sortType == &cCpuDescending) linebuf.put('/'); + pad_ostream_to_length(linebuf, tableBreaks[2]); + linebuf << "Type"; + if (m_sortType == &cTypeAscending) linebuf.put('\\'); + else if (m_sortType == &cTypeDescending) linebuf.put('/'); + pad_ostream_to_length(linebuf, tableBreaks[3]); + linebuf << "Condition"; + if (m_sortType == &cConditionAscending) linebuf.put('\\'); + else if (m_sortType == &cConditionDescending) linebuf.put('/'); + pad_ostream_to_length(linebuf, tableBreaks[4]); + linebuf << "Action"; + if (m_sortType == &cActionAscending) linebuf.put('\\'); + else if (m_sortType == &cActionDescending) linebuf.put('/'); + pad_ostream_to_length(linebuf, tableBreaks[5]); + + auto const &text(linebuf.vec()); + for (u32 i = m_topleft.x; i < (m_topleft.x + m_visible.x); i++, dest++) + { + dest->byte = (i < text.size()) ? text[i] : ' '; + dest->attrib = DCA_ANCILLARY; + } + } + + for (int row = 1; row < m_visible.y; row++) + { + // Breakpoints + int epi = row + m_topleft.y - 1; + if ((epi < m_buffer.size()) && (epi >= 0)) + { + const debug_exceptionpoint *const ep = m_buffer[epi]; + + linebuf.clear(); + linebuf.rdbuf()->clear(); + util::stream_format(linebuf, "%2X", ep->index()); + pad_ostream_to_length(linebuf, tableBreaks[0]); + linebuf.put(ep->enabled() ? 'X' : 'O'); + pad_ostream_to_length(linebuf, tableBreaks[1]); + linebuf << ep->debugInterface()->device().tag(); + pad_ostream_to_length(linebuf, tableBreaks[2]); + util::stream_format(linebuf, "%X", ep->type()); + pad_ostream_to_length(linebuf, tableBreaks[3]); + if (strcmp(ep->condition(), "1")) + linebuf << ep->condition(); + pad_ostream_to_length(linebuf, tableBreaks[4]); + linebuf << ep->action(); + pad_ostream_to_length(linebuf, tableBreaks[5]); + + auto const &text(linebuf.vec()); + for (u32 i = m_topleft.x; i < (m_topleft.x + m_visible.x); i++, dest++) + { + dest->byte = (i < text.size()) ? text[i] : ' '; + dest->attrib = DCA_NORMAL; + + // Color disabled exceptionpoints red + if ((i >= tableBreaks[0]) && (i < tableBreaks[1]) && !ep->enabled()) + dest->attrib |= DCA_CHANGED; + } + } + else + { + // Fill the remaining vertical space + for (u32 i = m_topleft.x; i < (m_topleft.x + m_visible.x); i++, dest++) + { + dest->byte = ' '; + dest->attrib = DCA_NORMAL; + } + } + } +} diff --git a/src/emu/debug/dvepoints.h b/src/emu/debug/dvepoints.h new file mode 100644 index 00000000000..3b042218e2a --- /dev/null +++ b/src/emu/debug/dvepoints.h @@ -0,0 +1,49 @@ +// license:BSD-3-Clause +// copyright-holders:Andrew Gardner, Vas Crabb +/********************************************************************* + + dvepoints.h + + Exceptionpoint debugger view. + +***************************************************************************/ +#ifndef MAME_EMU_DEBUG_DVEPOINTS_H +#define MAME_EMU_DEBUG_DVEPOINTS_H + +#pragma once + +#include "debugvw.h" + +#include + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +// debug view for exceptionpoints +class debug_view_exceptionpoints : public debug_view +{ + friend class debug_view_manager; + + // construction/destruction + debug_view_exceptionpoints(running_machine &machine, debug_view_osd_update_func osdupdate, void *osdprivate); + virtual ~debug_view_exceptionpoints(); + +protected: + // view overrides + virtual void view_update() override; + virtual void view_click(const int button, const debug_view_xy& pos) override; + +private: + // internal helpers + void enumerate_sources(); + void pad_ostream_to_length(std::ostream& str, int len); + void gather_exceptionpoints(); + + // internal state + bool (*m_sortType)(const debug_exceptionpoint *, const debug_exceptionpoint *); + std::vector m_buffer; +}; + +#endif // MAME_EMU_DEBUG_DVEPOINTS_H diff --git a/src/osd/modules/debugger/osx/exceptionpointsview.h b/src/osd/modules/debugger/osx/exceptionpointsview.h new file mode 100644 index 00000000000..73e3958c9b8 --- /dev/null +++ b/src/osd/modules/debugger/osx/exceptionpointsview.h @@ -0,0 +1,23 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +//============================================================ +// +// exceptionpointsview.h - MacOS X Cocoa debug window handling +// +//============================================================ + +#import "debugosx.h" + +#import "debugview.h" + + +#import + + +@interface MAMEExceptionpointsView : MAMEDebugView +{ +} + +- (id)initWithFrame:(NSRect)f machine:(running_machine &)m; + +@end diff --git a/src/osd/modules/debugger/osx/exceptionpointsview.mm b/src/osd/modules/debugger/osx/exceptionpointsview.mm new file mode 100644 index 00000000000..c15f9c56f4f --- /dev/null +++ b/src/osd/modules/debugger/osx/exceptionpointsview.mm @@ -0,0 +1,27 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +//============================================================ +// +// exceptionpointsview.m - MacOS X Cocoa debug window handling +// +//============================================================ + +#import "exceptionpointsview.h" + +#include "debug/debugvw.h" + + +@implementation MAMEExceptionpointsView + +- (id)initWithFrame:(NSRect)f machine:(running_machine &)m { + if (!(self = [super initWithFrame:f type:DVT_EXCEPTION_POINTS machine:m wholeLineScroll:YES])) + return nil; + return self; +} + + +- (void)dealloc { + [super dealloc]; +} + +@end diff --git a/src/osd/modules/debugger/osx/pointsviewer.mm b/src/osd/modules/debugger/osx/pointsviewer.mm index 8b2f69c50b5..0fafe35a799 100644 --- a/src/osd/modules/debugger/osx/pointsviewer.mm +++ b/src/osd/modules/debugger/osx/pointsviewer.mm @@ -10,6 +10,7 @@ #import "pointsviewer.h" #import "breakpointsview.h" +#import "exceptionpointsview.h" #import "registerpointsview.h" #import "watchpointsview.h" @@ -19,9 +20,9 @@ @implementation MAMEPointsViewer - (id)initWithMachine:(running_machine &)m console:(MAMEDebugConsole *)c { - MAMEDebugView *breakView, *watchView, *registerView; - NSScrollView *breakScroll, *watchScroll, *registerScroll; - NSTabViewItem *breakTab, *watchTab, *registerTab; + MAMEDebugView *breakView, *watchView, *registerView, *exceptionView; + NSScrollView *breakScroll, *watchScroll, *registerScroll, *exceptionScroll; + NSTabViewItem *breakTab, *watchTab, *registerTab, *exceptionTab; NSPopUpButton *actionButton; NSRect subviewFrame; @@ -48,6 +49,9 @@ [[[subviewButton menu] addItemWithTitle:@"All Registerpoints" action:NULL keyEquivalent:@""] setTag:2]; + [[[subviewButton menu] addItemWithTitle:@"All Exceptionpoints" + action:NULL + keyEquivalent:@""] setTag:3]; [subviewButton sizeToFit]; subviewFrame = [subviewButton frame]; subviewFrame.origin.x = subviewFrame.size.height; @@ -118,7 +122,23 @@ [registerTab setView:registerScroll]; [registerScroll release]; - // create a tabless tabview for the two subviews + // create the exceptionpoints view + exceptionView = [[MAMEExceptionpointsView alloc] initWithFrame:NSMakeRect(0, 0, 100, 100) + machine:*machine]; + exceptionScroll = [[NSScrollView alloc] initWithFrame:[breakScroll frame]]; + [exceptionScroll setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; + [exceptionScroll setHasHorizontalScroller:YES]; + [exceptionScroll setHasVerticalScroller:YES]; + [exceptionScroll setAutohidesScrollers:YES]; + [exceptionScroll setBorderType:NSNoBorder]; + [exceptionScroll setDrawsBackground:NO]; + [exceptionScroll setDocumentView:exceptionView]; + [exceptionView release]; + exceptionTab = [[NSTabViewItem alloc] initWithIdentifier:@""]; + [exceptionTab setView:exceptionScroll]; + [exceptionScroll release]; + + // create a tabless tabview for the four subviews tabs = [[NSTabView alloc] initWithFrame:[breakScroll frame]]; [tabs setTabViewType:NSNoTabsNoBorder]; [tabs setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)]; @@ -128,6 +148,8 @@ [watchTab release]; [tabs addTabViewItem:registerTab]; [registerTab release]; + [tabs addTabViewItem:exceptionTab]; + [exceptionTab release]; [[window contentView] addSubview:tabs]; [tabs release]; @@ -156,8 +178,14 @@ borderType:[registerScroll borderType] controlSize:NSControlSizeRegular scrollerStyle:NSScrollerStyleOverlay]; - NSSize const desired = NSMakeSize(std::max({ breakDesired.width, watchDesired.width, registerDesired.width }), - std::max({ breakDesired.height, watchDesired.height, registerDesired.height })); + NSSize const exceptionDesired = [NSScrollView frameSizeForContentSize:[exceptionView maximumFrameSize] + horizontalScrollerClass:[NSScroller class] + verticalScrollerClass:[NSScroller class] + borderType:[exceptionScroll borderType] + controlSize:NSControlSizeRegular + scrollerStyle:NSScrollerStyleOverlay]; + NSSize const desired = NSMakeSize(std::max({ breakDesired.width, watchDesired.width, registerDesired.width, exceptionDesired.width }), + std::max({ breakDesired.height, watchDesired.height, registerDesired.height, exceptionDesired.height })); [self cascadeWindowWithDesiredSize:desired forView:tabs]; // don't forget the result diff --git a/src/osd/modules/debugger/qt/breakpointswindow.cpp b/src/osd/modules/debugger/qt/breakpointswindow.cpp index dd3f473dc12..7dc3db34179 100644 --- a/src/osd/modules/debugger/qt/breakpointswindow.cpp +++ b/src/osd/modules/debugger/qt/breakpointswindow.cpp @@ -70,6 +70,12 @@ BreakpointsWindow::BreakpointsWindow(DebuggerQt &debugger, QWidget *parent) : typeRegister->setActionGroup(typeGroup); typeRegister->setShortcut(QKeySequence("Ctrl+3")); + QAction *typeException = new QAction("Exceptionpoints", this); + typeException->setObjectName("typeexception"); + typeException->setCheckable(true); + typeException->setActionGroup(typeGroup); + typeException->setShortcut(QKeySequence("Ctrl+4")); + typeBreak->setChecked(true); connect(typeGroup, &QActionGroup::triggered, this, &BreakpointsWindow::typeChanged); @@ -116,6 +122,9 @@ void BreakpointsWindow::saveConfigurationToNode(util::xml::data_node &node) case DVT_REGISTER_POINTS: node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 2); break; + case DVT_EXCEPTION_POINTS: + node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 3); + break; default: break; } @@ -147,6 +156,11 @@ void BreakpointsWindow::typeChanged(QAction* changedTo) m_breakpointsView = new DebuggerView(DVT_REGISTER_POINTS, m_machine, this); setWindowTitle("Debug: All Registerpoints"); } + else if (changedTo->text() == "Exceptionpoints") + { + m_breakpointsView = new DebuggerView(DVT_EXCEPTION_POINTS, m_machine, this); + setWindowTitle("Debug: All Exceptionpoints"); + } // Re-register QVBoxLayout *layout = findChild("vlayout"); diff --git a/src/osd/modules/debugger/win/debugwininfo.h b/src/osd/modules/debugger/win/debugwininfo.h index e766ca69c12..cf3587253f6 100644 --- a/src/osd/modules/debugger/win/debugwininfo.h +++ b/src/osd/modules/debugger/win/debugwininfo.h @@ -110,6 +110,7 @@ protected: ID_SHOW_BREAKPOINTS, ID_SHOW_WATCHPOINTS, ID_SHOW_REGISTERPOINTS, + ID_SHOW_EXCEPTIONPOINTS, ID_CLEAR_LOG, diff --git a/src/osd/modules/debugger/win/pointswininfo.cpp b/src/osd/modules/debugger/win/pointswininfo.cpp index f8fb4f6ce8d..70ec6606280 100644 --- a/src/osd/modules/debugger/win/pointswininfo.cpp +++ b/src/osd/modules/debugger/win/pointswininfo.cpp @@ -36,6 +36,7 @@ pointswin_info::pointswin_info(debugger_windows_interface &debugger) : AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_BREAKPOINTS, TEXT("Breakpoints\tCtrl+1")); AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_WATCHPOINTS, TEXT("Watchpoints\tCtrl+2")); AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_REGISTERPOINTS, TEXT("Registerpoints\tCtrl+3")); + AppendMenu(optionsmenu, MF_ENABLED, ID_SHOW_EXCEPTIONPOINTS, TEXT("Exceptionpoints\tCtrl+4")); AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options")); // compute a client rect @@ -76,6 +77,10 @@ bool pointswin_info::handle_key(WPARAM wparam, LPARAM lparam) case '3': SendMessage(window(), WM_COMMAND, ID_SHOW_REGISTERPOINTS, 0); return true; + + case '4': + SendMessage(window(), WM_COMMAND, ID_SHOW_EXCEPTIONPOINTS, 0); + return true; } } @@ -91,6 +96,7 @@ void pointswin_info::update_menu() CheckMenuItem(menu, ID_SHOW_BREAKPOINTS, MF_BYCOMMAND | (m_views[0]->type() == DVT_BREAK_POINTS ? MF_CHECKED : MF_UNCHECKED)); CheckMenuItem(menu, ID_SHOW_WATCHPOINTS, MF_BYCOMMAND | (m_views[0]->type() == DVT_WATCH_POINTS ? MF_CHECKED : MF_UNCHECKED)); CheckMenuItem(menu, ID_SHOW_REGISTERPOINTS, MF_BYCOMMAND | (m_views[0]->type() == DVT_REGISTER_POINTS ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_SHOW_EXCEPTIONPOINTS, MF_BYCOMMAND | (m_views[0]->type() == DVT_EXCEPTION_POINTS ? MF_CHECKED : MF_UNCHECKED)); } @@ -128,6 +134,15 @@ bool pointswin_info::handle_command(WPARAM wparam, LPARAM lparam) win_set_window_text_utf8(window(), "All Registerpoints"); recompute_children(); return true; + + case ID_SHOW_EXCEPTIONPOINTS: + m_views[0].reset(); + m_views[0].reset(new debugview_info(debugger(), *this, window(), DVT_EXCEPTION_POINTS)); + if (!m_views[0]->is_valid()) + m_views[0].reset(); + win_set_window_text_utf8(window(), "All Exceptionpoints"); + recompute_children(); + return true; } break; } @@ -148,6 +163,9 @@ void pointswin_info::restore_configuration_from_node(util::xml::data_node const case 2: SendMessage(window(), WM_COMMAND, ID_SHOW_REGISTERPOINTS, 0); break; + case 3: + SendMessage(window(), WM_COMMAND, ID_SHOW_EXCEPTIONPOINTS, 0); + break; } debugwin_info::restore_configuration_from_node(node); @@ -170,6 +188,9 @@ void pointswin_info::save_configuration_to_node(util::xml::data_node &node) case DVT_REGISTER_POINTS: node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 2); break; + case DVT_EXCEPTION_POINTS: + node.set_attribute_int(ATTR_WINDOW_POINTS_TYPE, 3); + break; default: break; }