-cpu/e132xs.cpp: Improved exception emulation:

* Fixed behaviour of exceptions in delay slots, and fixed recompiler not
  updating ILC and P for some exceptions.
* Implemented privilege error exception on setting L in user mode for
  interpreter.

-emu/debug, osd/modules/debugger: Added an option to show
 exceptionpoints in breakpoints windows.
This commit is contained in:
Vas Crabb 2025-04-01 03:45:36 +11:00
parent e0ea955d1b
commit 1dca832b37
18 changed files with 798 additions and 321 deletions

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

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

View File

@ -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));

View File

@ -466,16 +466,16 @@ private:
std::pair<uint16_t, uint32_t> 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 <trap_exception_or_int TYPE> 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 <reg_bank DstGlobal, reg_bank SrcGlobal, typename T> void generate_logic_op(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, T &&body);
template <reg_bank DstGlobal, typename T> void generate_logic_op_imm(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, uint32_t dst_code, T &&body);

View File

@ -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

View File

@ -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 <hyperstone_device::trap_exception_or_int TYPE>
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 <hyperstone_device::reg_bank DstGlobal, hyperstone_device::reg_bank SrcGlobal, typename T>
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);
}

View File

@ -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);
}

View File

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

314
src/emu/debug/dvepoints.cpp Normal file
View File

@ -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 <algorithm>
#include <iomanip>
// 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<debug_view_source>(
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<debug_exceptionpoint &>(*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;
}
}
}
}

49
src/emu/debug/dvepoints.h Normal file
View File

@ -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 <vector>
//**************************************************************************
// 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<const debug_exceptionpoint *> m_buffer;
};
#endif // MAME_EMU_DEBUG_DVEPOINTS_H

View File

@ -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 <Cocoa/Cocoa.h>
@interface MAMEExceptionpointsView : MAMEDebugView
{
}
- (id)initWithFrame:(NSRect)f machine:(running_machine &)m;
@end

View File

@ -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

View File

@ -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

View File

@ -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<QVBoxLayout *>("vlayout");

View File

@ -110,6 +110,7 @@ protected:
ID_SHOW_BREAKPOINTS,
ID_SHOW_WATCHPOINTS,
ID_SHOW_REGISTERPOINTS,
ID_SHOW_EXCEPTIONPOINTS,
ID_CLEAR_LOG,

View File

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