m68008: Implement as a 68000 variant

m68000mcu: Extract from m68000
This commit is contained in:
Olivier Galibert 2023-05-16 15:14:36 +02:00
parent 9ce44eaf8e
commit 78661e9aa9
21 changed files with 1053471 additions and 18710 deletions

View File

@ -1950,10 +1950,18 @@ if CPUS["M680X0"] then
MAME_DIR .. "src/devices/cpu/m68000/m68000-sif.cpp",
MAME_DIR .. "src/devices/cpu/m68000/m68000-sdp.cpp",
MAME_DIR .. "src/devices/cpu/m68000/m68000-sip.cpp",
MAME_DIR .. "src/devices/cpu/m68000/m68000-sdfm.cpp",
MAME_DIR .. "src/devices/cpu/m68000/m68000-sifm.cpp",
MAME_DIR .. "src/devices/cpu/m68000/m68000-sdpm.cpp",
MAME_DIR .. "src/devices/cpu/m68000/m68000-sipm.cpp",
MAME_DIR .. "src/devices/cpu/m68000/m68000mcu-head.h",
MAME_DIR .. "src/devices/cpu/m68000/m68000mcu-sdfm.cpp",
MAME_DIR .. "src/devices/cpu/m68000/m68000mcu-sifm.cpp",
MAME_DIR .. "src/devices/cpu/m68000/m68000mcu-sdpm.cpp",
MAME_DIR .. "src/devices/cpu/m68000/m68000mcu-sipm.cpp",
MAME_DIR .. "src/devices/cpu/m68000/m68000mcu.h",
MAME_DIR .. "src/devices/cpu/m68000/m68000mcu.cpp",
MAME_DIR .. "src/devices/cpu/m68000/m68008-head.h",
MAME_DIR .. "src/devices/cpu/m68000/m68008-sdf8.cpp",
MAME_DIR .. "src/devices/cpu/m68000/m68008-sif8.cpp",
MAME_DIR .. "src/devices/cpu/m68000/m68008-sdp8.cpp",
MAME_DIR .. "src/devices/cpu/m68000/m68008-sip8.cpp",
MAME_DIR .. "src/devices/cpu/m68000/m68008.h",
MAME_DIR .. "src/devices/cpu/m68000/m68008.cpp",
MAME_DIR .. "src/devices/cpu/m68000/m68010.h",

File diff suppressed because it is too large Load Diff

View File

@ -25,10 +25,12 @@ m68000_device::m68000_device(const machine_config &mconfig, device_type type, co
m_opcodes_config("opcodes", ENDIANNESS_BIG, 16, 24),
m_uprogram_config("uprogram", ENDIANNESS_BIG, 16, 24),
m_uopcodes_config("uopcodes", ENDIANNESS_BIG, 16, 24),
m_cpu_space_config("cpu_space", ENDIANNESS_BIG, 16, 24, 0, address_map_constructor(FUNC(m68000_device::default_autovectors_map), this))
m_cpu_space_config("cpu_space", ENDIANNESS_BIG, 16, 24, 0, address_map_constructor(FUNC(m68000_device::default_autovectors_map), this)),
m_mmu(nullptr),
m_disable_spaces(false),
m_disable_specifics(false),
m_disable_interrupt_callback(false)
{
m_mmu = nullptr;
m_disable_interrupt_callback = false;
}
void m68000_device::abort_access(u32 reason)
@ -150,7 +152,7 @@ device_memory_interface::space_config_vector m68000_device::memory_space_config(
void m68000_device::default_autovectors_map(address_map &map)
{
if(m_cpu_space_id == AS_CPU_SPACE && !has_configured_map(AS_CPU_SPACE)) {
offs_t mask = make_bitmask<offs_t>(24) - 0xf;
offs_t mask = make_bitmask<offs_t>(m_cpu_space_config.m_addr_width) - 0xf;
map(mask + 0x3, mask + 0x3).before_time(*this, FUNC(m68000_device::vpa_sync)).after_delay(*this, FUNC(m68000_device::vpa_after)).lr8(NAME([] () -> u8 { return autovector(1); }));
map(mask + 0x5, mask + 0x5).before_time(*this, FUNC(m68000_device::vpa_sync)).after_delay(*this, FUNC(m68000_device::vpa_after)).lr8(NAME([] () -> u8 { return autovector(2); }));
map(mask + 0x7, mask + 0x7).before_time(*this, FUNC(m68000_device::vpa_sync)).after_delay(*this, FUNC(m68000_device::vpa_after)).lr8(NAME([] () -> u8 { return autovector(3); }));
@ -170,17 +172,21 @@ void m68000_device::device_start()
m_rte_instr_callback.resolve();
m_tas_write_callback.resolve();
m_s_program = &space(AS_PROGRAM);
m_s_opcodes = has_space(AS_OPCODES) ? &space(AS_OPCODES) : m_s_program;
m_s_uprogram = has_space(AS_USER_PROGRAM) ? &space(AS_USER_PROGRAM) : m_s_program;
m_s_uopcodes = has_space(AS_USER_OPCODES) ? &space(AS_USER_OPCODES) : has_space(AS_USER_PROGRAM) ? m_s_uprogram : m_s_opcodes;
m_s_cpu_space = &space(m_cpu_space_id);
if(!m_disable_spaces) {
m_s_program = &space(AS_PROGRAM);
m_s_opcodes = has_space(AS_OPCODES) ? &space(AS_OPCODES) : m_s_program;
m_s_uprogram = has_space(AS_USER_PROGRAM) ? &space(AS_USER_PROGRAM) : m_s_program;
m_s_uopcodes = has_space(AS_USER_OPCODES) ? &space(AS_USER_OPCODES) : has_space(AS_USER_PROGRAM) ? m_s_uprogram : m_s_opcodes;
m_s_cpu_space = &space(m_cpu_space_id);
}
m_s_program->specific(m_r_program);
m_s_opcodes->specific(m_r_opcodes);
m_s_uprogram->specific(m_r_uprogram);
m_s_uopcodes->specific(m_r_uopcodes);
m_s_cpu_space->specific(m_cpu_space);
if(!(m_disable_specifics || m_disable_spaces)) {
m_s_program->specific(m_r_program);
m_s_opcodes->specific(m_r_opcodes);
m_s_uprogram->specific(m_r_uprogram);
m_s_uopcodes->specific(m_r_uopcodes);
m_s_cpu_space->specific(m_cpu_space);
}
if(m_mmu) {
m_handlers_f = s_handlers_if;
@ -467,105 +473,3 @@ void m68000_device::end_interrupt_vector_lookup()
m_int_vector = (m_edb & 0xff) << 2;
m_int_next_state = 0;
}
m68000_mcu_device::m68000_mcu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
m68000_device(mconfig, type, tag, owner, clock)
{
m_disable_interrupt_callback = true;
}
void m68000_mcu_device::execute_run()
{
internal_update(total_cycles());
m_icount -= m_count_before_instruction_step;
if(m_icount < 0) {
m_count_before_instruction_step = -m_icount;
m_icount = 0;
} else
m_count_before_instruction_step = 0;
while(m_bcount && m_icount <= m_bcount)
internal_update(total_cycles() + m_icount - m_bcount);
while(m_icount > 0) {
for(;;) {
if(m_icount > m_bcount && m_inst_substate)
(this->*(m_handlers_p[m_inst_state]))();
while(m_icount > m_bcount) {
if(m_inst_state >= S_first_instruction) {
m_ipc = m_pc - 2;
m_irdi = m_ird;
if(machine().debug_flags & DEBUG_FLAG_ENABLED)
debugger_instruction_hook(m_ipc);
}
(this->*(m_handlers_f[m_inst_state]))();
}
if(m_post_run)
do_post_run();
else
break;
}
if(m_icount > 0)
while(m_bcount && m_icount <= m_bcount)
internal_update(total_cycles() + m_icount - m_bcount);
if(m_icount > 0 && m_inst_substate) {
(this->*(m_handlers_p[m_inst_state]))();
if(m_post_run)
do_post_run();
}
}
if(m_icount < 0) {
m_count_before_instruction_step = -m_icount;
m_icount = 0;
}
}
void m68000_mcu_device::recompute_bcount(uint64_t event_time)
{
if(!event_time || event_time >= total_cycles() + m_icount) {
m_bcount = 0;
return;
}
m_bcount = total_cycles() + m_icount - event_time;
}
void m68000_mcu_device::add_event(uint64_t &event_time, uint64_t new_event)
{
if(!new_event)
return;
if(!event_time || event_time > new_event)
event_time = new_event;
}
void m68000_mcu_device::device_start()
{
m68000_device::device_start();
if(m_mmu) {
m_handlers_f = s_handlers_ifm;
m_handlers_p = s_handlers_ipm;
} else {
m_handlers_f = s_handlers_dfm;
m_handlers_p = s_handlers_dpm;
}
}
void m68000_mcu_device::set_current_interrupt_level(u32 level)
{
if(level == m_int_level)
return;
m_int_level = level;
/* A transition from < 7 to 7 always interrupts (NMI) */
/* Note: Level 7 can also level trigger like a normal IRQ */
if(m_int_level == 7)
m_nmi_pending = true;
update_interrupt();
}

View File

@ -120,10 +120,6 @@ protected:
static const handler s_handlers_if[];
static const handler s_handlers_dp[];
static const handler s_handlers_ip[];
static const handler s_handlers_dfm[];
static const handler s_handlers_ifm[];
static const handler s_handlers_dpm[];
static const handler s_handlers_ipm[];
const handler *m_handlers_f;
const handler *m_handlers_p;
@ -148,6 +144,9 @@ protected:
// MMU, if one present
mmu *m_mmu;
bool m_disable_spaces;
bool m_disable_specifics;
// Internal processor state, in inverse size order
u32 m_da[17]; // 8 data, 7 address, usp, ssp in that order
@ -196,7 +195,7 @@ protected:
void end_interrupt_vector_lookup();
// update needed stuff on priviledge level switch
void update_user_super();
virtual void update_user_super();
// update needed stuff on interrupt level switch
void update_interrupt();
@ -928,22 +927,6 @@ protected:
}
};
class m68000_mcu_device : public m68000_device
{
protected:
m68000_mcu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
virtual void execute_run() override;
void recompute_bcount(uint64_t event_time);
static void add_event(uint64_t &event_time, uint64_t new_event);
void internal_update();
virtual void internal_update(uint64_t current_time) = 0;
virtual void device_start() override;
void set_current_interrupt_level(u32 level);
};
DECLARE_DEVICE_TYPE(M68000, m68000_device)
#endif

View File

@ -799,6 +799,7 @@ class GEN(IntEnum):
direct = 0x0001
full = 0x0002
mcu = 0x0004
m68008 = 0x0008
# Load the instruction list
@ -1906,7 +1907,7 @@ def generate_code_from_blocks(blocks, ir, irmask, tvn, priv, group01):
# Propagate bus accesses from bus initiation to access completion in
# the code blocks
def propagate_bus_access(blocks, code, critical):
def propagate_bus_access(blocks, code, critical, gen_mode):
def propagate(blocks, code, seen, i, bus_access, bid, critical):
if i in seen:
return bid, critical
@ -1920,7 +1921,10 @@ def propagate_bus_access(blocks, code, critical):
ci += bus_access[1:]
ci.append(critical)
bus_access = None
bid += 2
if (gen_mode & GEN.m68008) and ci[2] != 2 and not ci[3]:
bid += 4
else:
bid += 2
elif ci[0] == "drop_critical":
critical = False
for nc in blocks[i][3]:
@ -1947,30 +1951,30 @@ def detect_reset_toggling(blocks, code):
# Generic code generation
def generate_intermediate_code(a1, a2, a3, ir, irmask, tvn, critical, priv, group01, name):
def generate_intermediate_code(a1, a2, a3, ir, irmask, tvn, critical, priv, group01, gen_mode, name):
fwd, suc = generate_forward_graph(a1, a2, a3, ir, irmask)
blocks = generate_blocks(fwd)
# show_blocks(blocks)
code = generate_code_from_blocks(blocks, ir, irmask, tvn, priv, group01)
propagate_bus_access(blocks, code, critical)
propagate_bus_access(blocks, code, critical, gen_mode)
detect_reset_toggling(blocks, code)
return code
# Generate the code for an instruction
def generate_intermediate_code_from_instruction(ir, irmask, name):
def generate_intermediate_code_from_instruction(ir, irmask, name, gen_mode):
# Avoid the rel16 case when looking for rel8
if (ir & 0xf000) == 0x6000 and irmask == 0xff00:
ir |= 0x0002
a1 = a1_pal_apply(ir)
a2, a3 = a23_pal_apply(ir)
return generate_intermediate_code(a1, a2, a3, ir, irmask, None, False, priv_test(ir), False, name)
return generate_intermediate_code(a1, a2, a3, ir, irmask, None, False, priv_test(ir), False, gen_mode, name)
# Generate the code for a state
def generate_intermediate_code_from_state(state):
return generate_intermediate_code(state[0], 0x3ff, 0x3ff, 0xffff, 0, state[2], state[3], False, True, "state_" + state[1])
def generate_intermediate_code_from_state(state, gen_mode):
return generate_intermediate_code(state[0], 0x3ff, 0x3ff, 0xffff, 0, state[2], state[3], False, True, gen_mode, "state_" + state[1])
# Create the base C++ method name for handling a state
@ -2002,7 +2006,7 @@ def generate_source_from_code(code, gen_mode):
if ci == R.dcro8:
return "1 << (m_dcr & 7)"
if ci == "ftu-i":
return "0xfff0 | ((m_next_state >> 23) & 0xe)"
return "0xfff1 | ((m_next_state >> 23) & 0xe)" if gen_mode & GEN.m68008 else "0xfff0 | ((m_next_state >> 23) & 0xe)"
if ci == "ftu-ssw":
return "(m_ftu & ~0x1f) | m_ssw"
if ci == "trap-tvn":
@ -2107,77 +2111,122 @@ def generate_source_from_code(code, gen_mode):
is_interrupt_vector_lookup = not ci[4] and ci[2] == 2
if is_interrupt_vector_lookup:
source.append("\tstart_interrupt_vector_lookup();")
if not (gen_mode & GEN.full):
source.append("\t[[fallthrough]]; case %d:" % (ci[1]))
if ci[4]:
if ci[3]:
if ci[8]:
source.append("\tif(!m_tas_write_callback.isnull())")
source.append("\t\tm_tas_write_callback(m_aob, m_dbout);")
source.append("\telse")
if gen_mode & GEN.direct:
source.append("\t\t%s.write_interruptible(m_aob & ~1, m_dbout, (m_aob & 1) ? 0x00ff : 0xff00);" % (["m_opcodes", "m_program"][ci[2]]))
else:
source.append("\t\tm_mmu->write_%s(m_aob & ~1, m_dbout, (m_aob & 1) ? 0x00ff : 0xff00);" % (["program", "data"][ci[2]]))
elif gen_mode & GEN.direct:
source.append("\t%s.write_interruptible(m_aob & ~1, m_dbout, (m_aob & 1) ? 0x00ff : 0xff00);" % (["m_opcodes", "m_program"][ci[2]]))
else:
source.append("\tm_mmu->write_%s(m_aob & ~1, m_dbout, (m_aob & 1) ? 0x00ff : 0xff00);" % (["program", "data"][ci[2]]))
else:
if gen_mode & GEN.direct:
source.append("\t%s.write_interruptible(m_aob & ~1, m_dbout);" % (["m_opcodes", "m_program"][ci[2]]))
else:
source.append("\tm_mmu->write_%s(m_aob & ~1, m_dbout, 0xffff);" % (["program", "data"][ci[2]]))
else:
if ci[2] == 2:
# cpu space access, e.g. interrupt vector lookup
if gen_mode & GEN.direct:
source.append("\tm_edb = m_cpu_space.read_interruptible(m_aob);")
else:
source.append("\tm_edb = m_mmu->read_cpu(m_aob, 0xffff);")
elif ci[3]:
if gen_mode & GEN.direct:
source.append("\tm_edb = %s.read_interruptible(m_aob & ~1, m_aob & 1 ? 0x00ff : 0xff00);" % (["m_opcodes", "m_program"][ci[2]]))
else:
source.append("\tm_edb = m_mmu->read_%s(m_aob & ~1, m_aob & 1 ? 0x00ff : 0xff00);" % (["program", "data"][ci[2]]))
source.append("\tif(!(m_aob & 1))")
source.append("\t\tm_edb >>= 8;")
else:
if gen_mode & GEN.direct:
source.append("\tm_edb = %s.read_interruptible(m_aob & ~1);" % (["m_opcodes", "m_program"][ci[2]]))
else:
source.append("\tm_edb = m_mmu->read_%s(m_aob & ~1, 0xffff);" % (["program", "data"][ci[2]]))
source.append("\tm_icount -= 4;")
if ci[8]:
access_steps = 2 if (gen_mode & GEN.m68008) and ci[2] != 2 and not ci[3] else 1
cid = ci[1]
for access_step in range(access_steps):
if not (gen_mode & GEN.full):
source.append("\t[[fallthrough]]; case %d:" % (cid))
if ci[4]:
if ci[3]:
if ci[8]:
source.append("\tif(!m_tas_write_callback.isnull())")
source.append("\t\tm_tas_write_callback(m_aob, m_dbout);")
source.append("\telse")
if gen_mode & GEN.m68008:
if gen_mode & GEN.direct:
source.append("\t\t%s.write_interruptible(m_aob, m_dbout);" % (["m_opcodes8", "m_program8"][ci[2]]))
else:
source.append("\t\tm_mmu8->write_%s(m_aob, m_dbout);" % (["program", "data"][ci[2]]))
else:
if gen_mode & GEN.direct:
source.append("\t\t%s.write_interruptible(m_aob & ~1, m_dbout, (m_aob & 1) ? 0x00ff : 0xff00);" % (["m_opcodes", "m_program"][ci[2]]))
else:
source.append("\t\tm_mmu->write_%s(m_aob & ~1, m_dbout, (m_aob & 1) ? 0x00ff : 0xff00);" % (["program", "data"][ci[2]]))
elif gen_mode & GEN.m68008:
if gen_mode & GEN.direct:
source.append("\t%s.write_interruptible(m_aob, m_dbout);" % (["m_opcodes8", "m_program8"][ci[2]]))
else:
source.append("\tm_mmu8->write_%s(m_aob, m_dbout);" % (["program", "data"][ci[2]]))
else:
if gen_mode & GEN.direct:
source.append("\t%s.write_interruptible(m_aob & ~1, m_dbout, (m_aob & 1) ? 0x00ff : 0xff00);" % (["m_opcodes", "m_program"][ci[2]]))
else:
source.append("\tm_mmu->write_%s(m_aob & ~1, m_dbout, (m_aob & 1) ? 0x00ff : 0xff00);" % (["program", "data"][ci[2]]))
elif gen_mode & GEN.m68008:
if gen_mode & GEN.direct:
source.append("\t%s.write_interruptible(m_aob%s, m_dbout%s);" % (["m_opcodes8", "m_program8"][ci[2]], " | 1" if access_step == 1 else " & ~1", "" if access_step == 1 else " >> 8"))
else:
source.append("\tm_mmu8->write_%s(m_aob%s, m_dbout%s);" % (["program", "data"][ci[2]], " | 1" if access_step == 1 else " & ~1", "" if access_step == 1 else " >> 8"))
else:
if gen_mode & GEN.direct:
source.append("\t%s.write_interruptible(m_aob & ~1, m_dbout);" % (["m_opcodes", "m_program"][ci[2]]))
else:
source.append("\tm_mmu->write_%s(m_aob & ~1, m_dbout, 0xffff);" % (["program", "data"][ci[2]]))
else:
if ci[2] == 2:
# cpu space access, e.g. interrupt vector lookup
if gen_mode & GEN.m68008:
if gen_mode & GEN.direct:
source.append("\tm_edb = m_cpu_space8.read_interruptible(m_aob);")
else:
source.append("\tm_edb = m_mmu8->read_cpu(m_aob);")
else:
if gen_mode & GEN.direct:
source.append("\tm_edb = m_cpu_space.read_interruptible(m_aob);")
else:
source.append("\tm_edb = m_mmu->read_cpu(m_aob, 0xffff);")
elif ci[3]:
if gen_mode & GEN.m68008:
if gen_mode & GEN.direct:
source.append("\tm_edb = %s.read_interruptible(m_aob);" % (["m_opcodes8", "m_program8"][ci[2]]))
else:
source.append("\tm_edb = m_mmu8->read_%s(m_aob);" % (["program", "data"][ci[2]]))
else:
if gen_mode & GEN.direct:
source.append("\tm_edb = %s.read_interruptible(m_aob & ~1, m_aob & 1 ? 0x00ff : 0xff00);" % (["m_opcodes", "m_program"][ci[2]]))
else:
source.append("\tm_edb = m_mmu->read_%s(m_aob & ~1, m_aob & 1 ? 0x00ff : 0xff00);" % (["program", "data"][ci[2]]))
source.append("\tif(!(m_aob & 1))")
source.append("\t\tm_edb >>= 8;")
else:
if gen_mode & GEN.m68008:
if access_step == 1:
if gen_mode & GEN.direct:
source.append("\tm_edb |= %s.read_interruptible(m_aob | 1);" % (["m_opcodes8", "m_program8"][ci[2]]))
else:
source.append("\tm_edb |= m_mmu8->read_%s(m_aob | 1);" % (["program", "data"][ci[2]]))
else:
if gen_mode & GEN.direct:
source.append("\tm_edb = %s.read_interruptible(m_aob & ~1) << 8;" % (["m_opcodes8", "m_program8"][ci[2]]))
else:
source.append("\tm_edb = m_mmu8->read_%s(m_aob & ~1) << 8;" % (["program", "data"][ci[2]]))
else:
if gen_mode & GEN.direct:
source.append("\tm_edb = %s.read_interruptible(m_aob & ~1);" % (["m_opcodes", "m_program"][ci[2]]))
else:
source.append("\tm_edb = m_mmu->read_%s(m_aob & ~1, 0xffff);" % (["program", "data"][ci[2]]))
source.append("\tm_icount -= 4;")
if ci[8]:
if ci[4]:
source.append("\tif(m_icount <= %s) {" % ("m_bcount" if gen_mode & GEN.mcu else "0"))
source.append("\t\tif(access_to_be_redone()) {")
source.append("\t\t\tm_icount += 4;")
source.append("\t\t\tm_inst_substate = %d;" % (cid-2))
source.append("\t\t} else")
source.append("\t\t\tm_inst_substate = %d;" % (cid+1))
source.append("\t\treturn;")
source.append("\t}")
else:
source.append("\tif(m_icount <= %s && access_to_be_redone()) {" % ("m_bcount" if gen_mode & GEN.mcu else "0"))
source.append("\t\tm_icount += 4;")
source.append("\t\tm_inst_substate = %d;" % cid)
source.append("\t\treturn;")
source.append("\t}")
else:
source.append("\tif(m_icount <= %s) {" % ("m_bcount" if gen_mode & GEN.mcu else "0"))
source.append("\t\tif(access_to_be_redone()) {")
source.append("\t\t\tm_icount += 4;")
source.append("\t\t\tm_inst_substate = %d;" % (ci[1]-2))
source.append("\t\t\tm_inst_substate = %d;" % cid)
source.append("\t\t} else")
source.append("\t\t\tm_inst_substate = %d;" % (ci[1]+1))
source.append("\t\t\tm_inst_substate = %d;" % (cid+1))
source.append("\t\treturn;")
source.append("\t}")
else:
source.append("\tif(m_icount <= %s && access_to_be_redone()) {" % ("m_bcount" if gen_mode & GEN.mcu else "0"))
source.append("\t\tm_icount += 4;")
source.append("\t\tm_inst_substate = %d;" % ci[1])
source.append("\t\treturn;")
source.append("\t}")
else:
source.append("\tif(m_icount <= %s) {" % ("m_bcount" if gen_mode & GEN.mcu else "0"))
source.append("\t\tif(access_to_be_redone()) {")
source.append("\t\t\tm_icount += 4;")
source.append("\t\t\tm_inst_substate = %d;" % ci[1])
source.append("\t\t} else")
source.append("\t\t\tm_inst_substate = %d;" % (ci[1]+1))
source.append("\t\treturn;")
source.append("\t}")
if not (gen_mode & GEN.full):
source.append("\t[[fallthrough]]; case %d:" % (ci[1]+1))
if not (gen_mode & GEN.full):
source.append("\t[[fallthrough]]; case %d:" % (cid+1))
cid += 2
if is_interrupt_vector_lookup:
source.append("\tend_interrupt_vector_lookup();")
if not ci[3]:
if not ci[3] and (ci[2] != 2 or not (gen_mode & GEN.m68008)):
source.append("\tif(m_aob & 1) {")
source.append("\t\tm_icount -= 4;")
source.append("\t\tm_inst_state = %s;" % ("S_DOUBLE_FAULT" if ci[8] else "S_ADDRESS_ERROR"));
@ -2312,22 +2361,26 @@ def generate_source_file(fname, cmd, gen_mode):
suf = 'd' if gen_mode & GEN.direct else 'i'
suf += 'f' if gen_mode & GEN.full else 'p'
suf += 'm' if gen_mode & GEN.mcu else ''
suf += '8' if gen_mode & GEN.m68008 else ''
print("Generating %s" % suf)
cpu = "m68008" if gen_mode & GEN.m68008 else "m68000_mcu" if gen_mode & GEN.mcu else "m68000"
head = "m68008" if gen_mode & GEN.m68008 else "m68000mcu" if gen_mode & GEN.mcu else "m68000"
print("// Instruction handlers for the m68000 (%s, %s, %s)" % ("direct" if gen_mode & GEN.direct else "indirect", "full" if gen_mode & GEN.full else "partial", "mcu" if gen_mode & GEN.mcu else "cpu"), file=out)
print("//", file=out)
print("// Generated by m68000gen.py %s" % cmd, file=out)
print("", file=out)
print("#include \"emu.h\"", file=out)
print("#include \"m68000.h\"", file=out)
print("#include \"%s.h\"" % head, file=out)
print("", file=out)
for st in states:
# print(handler_name_for_state(st))
code = generate_intermediate_code_from_state(st)
code = generate_intermediate_code_from_state(st, gen_mode)
source = generate_source_from_code(code, gen_mode)
print("void m68000_device::%s_%s()" % (handler_name_for_state(st), suf), file=out)
print("void %s_device::%s_%s()" % (cpu, handler_name_for_state(st), suf), file=out)
print("{", file=out)
for l in source:
print(l, file=out)
@ -2338,24 +2391,24 @@ def generate_source_file(fname, cmd, gen_mode):
if ii[0] == 0xa000 or ii[0] == 0xf000 or ii[0] == 0x4afc:
continue
# print(handler_name_for_instruction(ii))
code = generate_intermediate_code_from_instruction(ii[0], ii[1], " ".join(ii[2]))
code = generate_intermediate_code_from_instruction(ii[0], ii[1], " ".join(ii[2]), gen_mode)
source = generate_source_from_code(code, gen_mode)
print("void m68000_device::%s_%s() // %04x %04x" % (handler_name_for_instruction(ii), suf, ii[0], ii[1]), file=out)
print("void %s_device::%s_%s() // %04x %04x" % (cpu, handler_name_for_instruction(ii), suf, ii[0], ii[1]), file=out)
print("{", file=out)
for l in source:
print(l, file=out)
print("}", file=out)
print("", file=out)
print("const m68000_device::handler m68000_device::s_handlers_%s[] = {" % suf, file=out)
print("const %s_device::%s %s_device::s_handlers_%s[] = {" % (cpu, "handler8" if gen_mode & GEN.m68008 else "handlerm" if gen_mode & GEN.mcu else "handler", cpu, suf), file=out)
for st in states:
name = handler_name_for_state(st)
print("\t&m68000_device::%s_%s," % (name, suf), file=out)
print("\t&%s_device::%s_%s," % (cpu, name, suf), file=out)
for ii in instructions:
if ii[0] == 0xa000 or ii[0] == 0xf000 or ii[0] == 0x4afc:
continue
name = handler_name_for_instruction(ii)
print("\t&m68000_device::%s_%s," % (name, suf), file=out)
print("\t&%s_device::%s_%s," % (cpu, name, suf), file=out)
print("};", file=out)
@ -2373,7 +2426,7 @@ if sys.argv[1] == "i":
if line == None or ii[0] == 0xa000 or ii[0] == 0xf000 or ii[0] == 0x4afc:
print("Illegal instruction")
sys.exit(0)
code = generate_intermediate_code_from_instruction(ii[0], ii[2], " ".join(ii[2]))
code = generate_intermediate_code_from_instruction(ii[0], ii[2], " ".join(ii[2]), 0)
source = generate_source_from_code(code, GEN.direct|GEN.full)
print("# %s" % handler_name_for_instruction(ii))
for l in source:
@ -2422,7 +2475,39 @@ if sys.argv[1] == 'header':
print("//", file=out)
print("// Generated by m68000gen.py %s" % ' '.join(sys.argv[1:]), file=out)
print("", file=out)
for variant in ["df", "if", "dp", "ip", "dfm", "ifm", "dpm", "ipm"]:
for variant in ["df", "if", "dp", "ip"]:
for st in states:
name = handler_name_for_state(st)
print("void %s_%s();" % (name, variant), file=out)
for ii in instructions:
if ii[0] == 0xa000 or ii[0] == 0xf000 or ii[0] == 0x4afc:
continue
name = handler_name_for_instruction(ii)
print("void %s_%s();" % (name, variant), file=out)
if sys.argv[1] == 'headerm':
out = open(sys.argv[3], 'wt')
print("// Header fragment for the handlers", file=out)
print("//", file=out)
print("// Generated by m68000gen.py %s" % ' '.join(sys.argv[1:]), file=out)
print("", file=out)
for variant in ["dfm", "ifm", "dpm", "ipm"]:
for st in states:
name = handler_name_for_state(st)
print("void %s_%s();" % (name, variant), file=out)
for ii in instructions:
if ii[0] == 0xa000 or ii[0] == 0xf000 or ii[0] == 0x4afc:
continue
name = handler_name_for_instruction(ii)
print("void %s_%s();" % (name, variant), file=out)
if sys.argv[1] == 'header8':
out = open(sys.argv[3], 'wt')
print("// Header fragment for the handlers", file=out)
print("//", file=out)
print("// Generated by m68000gen.py %s" % ' '.join(sys.argv[1:]), file=out)
print("", file=out)
for variant in ["df8", "if8", "dp8" ,"ip8"]:
for st in states:
name = handler_name_for_state(st)
print("void %s_%s();" % (name, variant), file=out)
@ -2457,3 +2542,15 @@ if sys.argv[1] == 'sdpm':
if sys.argv[1] == 'sipm':
generate_source_file(sys.argv[3], ' '.join(sys.argv[1:]), GEN.mcu)
if sys.argv[1] == 'sdf8':
generate_source_file(sys.argv[3], ' '.join(sys.argv[1:]), GEN.direct|GEN.full|GEN.m68008)
if sys.argv[1] == 'sif8':
generate_source_file(sys.argv[3], ' '.join(sys.argv[1:]), GEN.full|GEN.m68008)
if sys.argv[1] == 'sdp8':
generate_source_file(sys.argv[3], ' '.join(sys.argv[1:]), GEN.direct|GEN.m68008)
if sys.argv[1] == 'sip8':
generate_source_file(sys.argv[3], ' '.join(sys.argv[1:]), GEN.m68008)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,109 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
#include "emu.h"
#include "m68000mcu.h"
m68000_mcu_device::m68000_mcu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) :
m68000_device(mconfig, type, tag, owner, clock)
{
m_disable_interrupt_callback = true;
}
void m68000_mcu_device::execute_run()
{
internal_update(total_cycles());
m_icount -= m_count_before_instruction_step;
if(m_icount < 0) {
m_count_before_instruction_step = -m_icount;
m_icount = 0;
} else
m_count_before_instruction_step = 0;
while(m_bcount && m_icount <= m_bcount)
internal_update(total_cycles() + m_icount - m_bcount);
while(m_icount > 0) {
for(;;) {
if(m_icount > m_bcount && m_inst_substate)
(this->*(m_handlers_p[m_inst_state]))();
while(m_icount > m_bcount) {
if(m_inst_state >= S_first_instruction) {
m_ipc = m_pc - 2;
m_irdi = m_ird;
if(machine().debug_flags & DEBUG_FLAG_ENABLED)
debugger_instruction_hook(m_ipc);
}
(this->*(m_handlers_f[m_inst_state]))();
}
if(m_post_run)
do_post_run();
else
break;
}
if(m_icount > 0)
while(m_bcount && m_icount <= m_bcount)
internal_update(total_cycles() + m_icount - m_bcount);
if(m_icount > 0 && m_inst_substate) {
(this->*(m_handlers_p[m_inst_state]))();
if(m_post_run)
do_post_run();
}
}
if(m_icount < 0) {
m_count_before_instruction_step = -m_icount;
m_icount = 0;
}
}
void m68000_mcu_device::recompute_bcount(uint64_t event_time)
{
if(!event_time || event_time >= total_cycles() + m_icount) {
m_bcount = 0;
return;
}
m_bcount = total_cycles() + m_icount - event_time;
}
void m68000_mcu_device::add_event(uint64_t &event_time, uint64_t new_event)
{
if(!new_event)
return;
if(!event_time || event_time > new_event)
event_time = new_event;
}
void m68000_mcu_device::device_start()
{
m68000_device::device_start();
// Theoretically UB, in practice works, the alternative (putting
// everything in m68000_device) is annoying
if(m_mmu) {
m_handlers_f = reinterpret_cast<const handler *>(s_handlers_ifm);
m_handlers_p = reinterpret_cast<const handler *>(s_handlers_ipm);
} else {
m_handlers_f = reinterpret_cast<const handler *>(s_handlers_dfm);
m_handlers_p = reinterpret_cast<const handler *>(s_handlers_dpm);
}
}
void m68000_mcu_device::set_current_interrupt_level(u32 level)
{
if(level == m_int_level)
return;
m_int_level = level;
/* A transition from < 7 to 7 always interrupts (NMI) */
/* Note: Level 7 can also level trigger like a normal IRQ */
if(m_int_level == 7)
m_nmi_pending = true;
update_interrupt();
}

View File

@ -0,0 +1,36 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
#ifndef MAME_CPU_M68000_M68000mcu_H
#define MAME_CPU_M68000_M68000mcu_H
#pragma once
#include "m68000.h"
class m68000_mcu_device : public m68000_device
{
protected:
// Opcode handlers (d = direct, i = indirect, f = full, p = partial)
using handlerm = void (m68000_mcu_device::*)();
#include "m68000mcu-head.h"
static const handlerm s_handlers_dfm[];
static const handlerm s_handlers_ifm[];
static const handlerm s_handlers_dpm[];
static const handlerm s_handlers_ipm[];
m68000_mcu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
virtual void execute_run() override;
void recompute_bcount(uint64_t event_time);
static void add_event(uint64_t &event_time, uint64_t new_event);
void internal_update();
virtual void internal_update(uint64_t current_time) = 0;
virtual void device_start() override;
void set_current_interrupt_level(u32 level);
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Karl Stenerud
// copyright-holders:Olivier Galibert
#include "emu.h"
#include "m68008.h"
@ -19,24 +19,84 @@ std::unique_ptr<util::disasm_interface> m68008fn_device::create_disassembler()
}
m68008_device::m68008_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: m68000_musashi_device(mconfig, tag, owner, clock, M68008, 8,20)
: m68008_device(mconfig, M68008, tag, owner, clock)
{
}
m68008_device::m68008_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
: m68000_device(mconfig, type, tag, owner, clock),
m_mmu8(nullptr)
{
m_cpu_space_config.m_addr_width = m_cpu_space_config.m_logaddr_width = 20;
m_program_config.m_addr_width = m_program_config.m_logaddr_width = 20;
m_opcodes_config.m_addr_width = m_opcodes_config.m_logaddr_width = 20;
m_uprogram_config.m_addr_width = m_uprogram_config.m_logaddr_width = 20;
m_uopcodes_config.m_addr_width = m_uopcodes_config.m_logaddr_width = 20;
m_cpu_space_config.m_data_width = 8;
m_program_config.m_data_width = 8;
m_opcodes_config.m_data_width = 8;
m_uprogram_config.m_data_width = 8;
m_uopcodes_config.m_data_width = 8;
m_disable_specifics = true;
}
void m68008_device::device_start()
{
m68000_musashi_device::device_start();
init_cpu_m68008();
m68000_device::device_start();
m_s_program->specific(m_r_program8);
m_s_opcodes->specific(m_r_opcodes8);
m_s_uprogram->specific(m_r_uprogram8);
m_s_uopcodes->specific(m_r_uopcodes8);
m_s_cpu_space->specific(m_cpu_space8);
// Theoretically UB, in practice works, the alternative (putting
// everything in m68000_device) is annoying
if(m_mmu8) {
m_handlers_f = reinterpret_cast<const handler *>(s_handlers_if8);
m_handlers_p = reinterpret_cast<const handler *>(s_handlers_ip8);
} else {
m_handlers_f = reinterpret_cast<const handler *>(s_handlers_df8);
m_handlers_p = reinterpret_cast<const handler *>(s_handlers_dp8);
}
}
void m68008_device::update_user_super()
{
if(m_sr & SR_S) {
m_sp = 16;
m_program8 = m_r_program8;
m_opcodes8 = m_r_opcodes8;
if(m_mmu8)
m_mmu8->set_super(true);
} else {
m_sp = 15;
m_program8 = m_r_uprogram8;
m_opcodes8 = m_r_uopcodes8;
if(m_mmu8)
m_mmu8->set_super(false);
}
}
m68008fn_device::m68008fn_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: m68000_musashi_device(mconfig, tag, owner, clock, M68008FN, 8,22)
: m68008_device(mconfig, M68008FN, tag, owner, clock)
{
m_cpu_space_config.m_addr_width = m_cpu_space_config.m_logaddr_width = 22;
m_program_config.m_addr_width = m_program_config.m_logaddr_width = 22;
m_opcodes_config.m_addr_width = m_opcodes_config.m_logaddr_width = 22;
m_uprogram_config.m_addr_width = m_uprogram_config.m_logaddr_width = 22;
m_uopcodes_config.m_addr_width = m_uopcodes_config.m_logaddr_width = 22;
m_cpu_space_config.m_data_width = 8;
m_program_config.m_data_width = 8;
m_opcodes_config.m_data_width = 8;
m_uprogram_config.m_data_width = 8;
m_uopcodes_config.m_data_width = 8;
}
void m68008fn_device::device_start()
{
m68000_musashi_device::device_start();
init_cpu_m68008();
m68008_device::device_start();
}

View File

@ -1,28 +1,61 @@
// license:BSD-3-Clause
// copyright-holders:Karl Stenerud
// copyright-holders:Olivier Galibert
#ifndef MAME_CPU_M68000_M68008_H
#define MAME_CPU_M68000_M68008_H
#pragma once
#include "m68kmusashi.h"
#include "m68000.h"
class m68008_device : public m68000_musashi_device
class m68008_device : public m68000_device
{
public:
struct mmu8 {
virtual u8 read_program(offs_t addr) = 0;
virtual void write_program(offs_t addr, u8 data) = 0;
virtual u8 read_data(offs_t addr) = 0;
virtual void write_data(offs_t addr, u8 data) = 0;
virtual u8 read_cpu(offs_t addr) = 0;
virtual void set_super(bool super) = 0;
};
// construction/destruction
m68008_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
virtual u32 execute_min_cycles() const noexcept override { return 4; }
virtual u32 execute_max_cycles() const noexcept override { return 158; }
void set_current_mmu(mmu8 *m);
// device-level overrides
virtual void device_start() override;
protected:
// Typed constructor
m68008_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
using handler8 = void (m68008_device::*)();
#include "m68008-head.h"
static const handler8 s_handlers_df8[];
static const handler8 s_handlers_if8[];
static const handler8 s_handlers_dp8[];
static const handler8 s_handlers_ip8[];
// Fixed specifics
memory_access<24, 0, 0, ENDIANNESS_BIG>::specific m_r_program8, m_r_opcodes8, m_r_uprogram8, m_r_uopcodes8, m_cpu_space8;
// Dynamic specifics, depending on supervisor state
memory_access<24, 0, 0, ENDIANNESS_BIG>::specific m_program8, m_opcodes8;
// MMU, if one present
mmu8 *m_mmu8;
virtual void update_user_super() override;
};
class m68008fn_device : public m68000_musashi_device
class m68008fn_device : public m68008_device
{
public:
// construction/destruction

View File

@ -5,7 +5,7 @@
#pragma once
#include "m68000.h"
#include "m68000mcu.h"
class tmp68301_device : public m68000_mcu_device
{

View File

@ -237,7 +237,7 @@ uint8_t abc1600_mac_device::read(offs_t offset)
}
}
if (!m_magic && (fc == M68K_FC_USER_PROGRAM))
if (!m_magic && (fc == 2))
{
task = 0;
}
@ -245,18 +245,8 @@ uint8_t abc1600_mac_device::read(offs_t offset)
bool nonx, wp;
offs_t virtual_offset = get_physical_offset(offset, task, nonx, wp);
if (!machine().side_effects_disabled())
{
if (nonx)
{
LOGMASKED(LOG_ERRORS, "%s BUS ERROR R %05x:%06x (NONX %u WP %u TASK %u FC %u MAGIC %u)\n",
machine().describe_context(), offset, virtual_offset, nonx, wp, task, fc, m_magic);
machine().debug_break();
m_cpu->set_buserror_details(offset, 1, m_cpu->get_fc());
m_cpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
m_cpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
}
}
if (!machine().side_effects_disabled() && nonx)
m_cpu->trigger_bus_error();
return space().read_byte(virtual_offset);
}
@ -289,27 +279,8 @@ void abc1600_mac_device::write(offs_t offset, uint8_t data)
bool nonx, wp;
offs_t virtual_offset = get_physical_offset(offset, task, nonx, wp);
if (!machine().side_effects_disabled())
{
if (nonx)
{
LOGMASKED(LOG_ERRORS, "%s BUS ERROR W %05x:%06x (NONX %u WP %u TASK %u FC %u MAGIC %u)\n",
machine().describe_context(), offset, virtual_offset, nonx, wp, task, fc, m_magic);
machine().debug_break();
m_cpu->set_buserror_details(offset, 0, m_cpu->get_fc());
m_cpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
m_cpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
}
if (!wp)
{
LOGMASKED(LOG_ERRORS, "%s BUS ERROR W %05x:%06x (NONX %u WP %u TASK %u FC %u MAGIC %u)\n",
machine().describe_context(), offset, virtual_offset, nonx, wp, task, fc, m_magic);
machine().debug_break();
m_cpu->set_buserror_details(offset, 0, m_cpu->get_fc());
m_cpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
m_cpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
}
}
if (!machine().side_effects_disabled() && (nonx || !wp))
m_cpu->trigger_bus_error();
space().write_byte(virtual_offset, data);
}