cpu/z80/z80.cpp new generatable core (#12423)

This commit is contained in:
holub 2024-06-03 07:22:32 -04:00 committed by GitHub
parent 1efb9a831c
commit 0c42667cf0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 7053 additions and 2933 deletions

View File

@ -2975,6 +2975,18 @@ if (CPUS["Z80"]~=null or CPUS["KC80"]~=null) then
MAME_DIR .. "src/devices/cpu/z80/z84c015.cpp",
MAME_DIR .. "src/devices/cpu/z80/z84c015.h",
}
dependency {
{ MAME_DIR .. "src/devices/cpu/z80/z80.cpp", GEN_DIR .. "emu/cpu/z80/z80.hxx" },
{ MAME_DIR .. "src/devices/cpu/z80/z80.cpp", GEN_DIR .. "emu/cpu/z80/z80_rop.hxx" },
{ MAME_DIR .. "src/devices/cpu/z80/z80.cpp", GEN_DIR .. "emu/cpu/z80/z80_ncs800rop.hxx" },
}
custombuildtask {
{ MAME_DIR .. "src/devices/cpu/z80/z80.lst", GEN_DIR .. "emu/cpu/z80/z80.hxx", { MAME_DIR .. "src/devices/cpu/z80/z80make.py" }, { "@echo Generating Z80 source file...", PYTHON .. " $(1) $(<) $(@)" } },
{ MAME_DIR .. "src/devices/cpu/z80/z80.lst", GEN_DIR .. "emu/cpu/z80/z80_rop.hxx", { MAME_DIR .. "src/devices/cpu/z80/z80make.py" }, { "@echo Generating Z80 \\(rop\\) source file...", PYTHON .. " $(1) rop $(<) $(@)" } },
{ MAME_DIR .. "src/devices/cpu/z80/z80.lst", GEN_DIR .. "emu/cpu/z80/z80_ncs800rop.hxx", { MAME_DIR .. "src/devices/cpu/z80/z80make.py" }, { "@echo Generating NSC800 \\(rop\\) source file...", PYTHON .. " $(1) ncs800rop $(<) $(@)" } },
}
end
if CPUS["KC80"] then

File diff suppressed because it is too large Load Diff

View File

@ -49,10 +49,11 @@ protected:
// device_t implementation
virtual void device_validity_check(validity_checker &valid) const override;
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
// device_execute_interface implementation
virtual bool cpu_is_interruptible() const override { return true; }
virtual u32 execute_min_cycles() const noexcept override { return 2; }
virtual u32 execute_max_cycles() const noexcept override { return 16; }
virtual u32 execute_input_lines() const noexcept override { return 4; }
@ -73,122 +74,17 @@ protected:
// device_disasm_interface implementation
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
#undef PROTOTYPES
#define PROTOTYPES(prefix) \
void prefix##_00(); void prefix##_01(); void prefix##_02(); void prefix##_03(); \
void prefix##_04(); void prefix##_05(); void prefix##_06(); void prefix##_07(); \
void prefix##_08(); void prefix##_09(); void prefix##_0a(); void prefix##_0b(); \
void prefix##_0c(); void prefix##_0d(); void prefix##_0e(); void prefix##_0f(); \
void prefix##_10(); void prefix##_11(); void prefix##_12(); void prefix##_13(); \
void prefix##_14(); void prefix##_15(); void prefix##_16(); void prefix##_17(); \
void prefix##_18(); void prefix##_19(); void prefix##_1a(); void prefix##_1b(); \
void prefix##_1c(); void prefix##_1d(); void prefix##_1e(); void prefix##_1f(); \
void prefix##_20(); void prefix##_21(); void prefix##_22(); void prefix##_23(); \
void prefix##_24(); void prefix##_25(); void prefix##_26(); void prefix##_27(); \
void prefix##_28(); void prefix##_29(); void prefix##_2a(); void prefix##_2b(); \
void prefix##_2c(); void prefix##_2d(); void prefix##_2e(); void prefix##_2f(); \
void prefix##_30(); void prefix##_31(); void prefix##_32(); void prefix##_33(); \
void prefix##_34(); void prefix##_35(); void prefix##_36(); void prefix##_37(); \
void prefix##_38(); void prefix##_39(); void prefix##_3a(); void prefix##_3b(); \
void prefix##_3c(); void prefix##_3d(); void prefix##_3e(); void prefix##_3f(); \
void prefix##_40(); void prefix##_41(); void prefix##_42(); void prefix##_43(); \
void prefix##_44(); void prefix##_45(); void prefix##_46(); void prefix##_47(); \
void prefix##_48(); void prefix##_49(); void prefix##_4a(); void prefix##_4b(); \
void prefix##_4c(); void prefix##_4d(); void prefix##_4e(); void prefix##_4f(); \
void prefix##_50(); void prefix##_51(); void prefix##_52(); void prefix##_53(); \
void prefix##_54(); void prefix##_55(); void prefix##_56(); void prefix##_57(); \
void prefix##_58(); void prefix##_59(); void prefix##_5a(); void prefix##_5b(); \
void prefix##_5c(); void prefix##_5d(); void prefix##_5e(); void prefix##_5f(); \
void prefix##_60(); void prefix##_61(); void prefix##_62(); void prefix##_63(); \
void prefix##_64(); void prefix##_65(); void prefix##_66(); void prefix##_67(); \
void prefix##_68(); void prefix##_69(); void prefix##_6a(); void prefix##_6b(); \
void prefix##_6c(); void prefix##_6d(); void prefix##_6e(); void prefix##_6f(); \
void prefix##_70(); void prefix##_71(); void prefix##_72(); void prefix##_73(); \
void prefix##_74(); void prefix##_75(); void prefix##_76(); void prefix##_77(); \
void prefix##_78(); void prefix##_79(); void prefix##_7a(); void prefix##_7b(); \
void prefix##_7c(); void prefix##_7d(); void prefix##_7e(); void prefix##_7f(); \
void prefix##_80(); void prefix##_81(); void prefix##_82(); void prefix##_83(); \
void prefix##_84(); void prefix##_85(); void prefix##_86(); void prefix##_87(); \
void prefix##_88(); void prefix##_89(); void prefix##_8a(); void prefix##_8b(); \
void prefix##_8c(); void prefix##_8d(); void prefix##_8e(); void prefix##_8f(); \
void prefix##_90(); void prefix##_91(); void prefix##_92(); void prefix##_93(); \
void prefix##_94(); void prefix##_95(); void prefix##_96(); void prefix##_97(); \
void prefix##_98(); void prefix##_99(); void prefix##_9a(); void prefix##_9b(); \
void prefix##_9c(); void prefix##_9d(); void prefix##_9e(); void prefix##_9f(); \
void prefix##_a0(); void prefix##_a1(); void prefix##_a2(); void prefix##_a3(); \
void prefix##_a4(); void prefix##_a5(); void prefix##_a6(); void prefix##_a7(); \
void prefix##_a8(); void prefix##_a9(); void prefix##_aa(); void prefix##_ab(); \
void prefix##_ac(); void prefix##_ad(); void prefix##_ae(); void prefix##_af(); \
void prefix##_b0(); void prefix##_b1(); void prefix##_b2(); void prefix##_b3(); \
void prefix##_b4(); void prefix##_b5(); void prefix##_b6(); void prefix##_b7(); \
void prefix##_b8(); void prefix##_b9(); void prefix##_ba(); void prefix##_bb(); \
void prefix##_bc(); void prefix##_bd(); void prefix##_be(); void prefix##_bf(); \
void prefix##_c0(); void prefix##_c1(); void prefix##_c2(); void prefix##_c3(); \
void prefix##_c4(); void prefix##_c5(); void prefix##_c6(); void prefix##_c7(); \
void prefix##_c8(); void prefix##_c9(); void prefix##_ca(); void prefix##_cb(); \
void prefix##_cc(); void prefix##_cd(); void prefix##_ce(); void prefix##_cf(); \
void prefix##_d0(); void prefix##_d1(); void prefix##_d2(); void prefix##_d3(); \
void prefix##_d4(); void prefix##_d5(); void prefix##_d6(); void prefix##_d7(); \
void prefix##_d8(); void prefix##_d9(); void prefix##_da(); void prefix##_db(); \
void prefix##_dc(); void prefix##_dd(); void prefix##_de(); void prefix##_df(); \
void prefix##_e0(); void prefix##_e1(); void prefix##_e2(); void prefix##_e3(); \
void prefix##_e4(); void prefix##_e5(); void prefix##_e6(); void prefix##_e7(); \
void prefix##_e8(); void prefix##_e9(); void prefix##_ea(); void prefix##_eb(); \
void prefix##_ec(); void prefix##_ed(); void prefix##_ee(); void prefix##_ef(); \
void prefix##_f0(); void prefix##_f1(); void prefix##_f2(); void prefix##_f3(); \
void prefix##_f4(); void prefix##_f5(); void prefix##_f6(); void prefix##_f7(); \
void prefix##_f8(); void prefix##_f9(); void prefix##_fa(); void prefix##_fb(); \
void prefix##_fc(); void prefix##_fd(); void prefix##_fe(); void prefix##_ff();
PROTOTYPES(op)
PROTOTYPES(cb)
PROTOTYPES(dd)
PROTOTYPES(ed)
PROTOTYPES(fd)
PROTOTYPES(xycb)
void illegal_1();
void illegal_2();
void halt();
void leave_halt();
u8 in(u16 port);
void out(u16 port, u8 value);
u8 rm(u16 addr);
u8 rm_reg(u16 addr);
void rm16(u16 addr, PAIR &r);
void wm(u16 addr, u8 value);
void wm16(u16 addr, PAIR &r);
void wm16_sp(PAIR &r);
u8 rop();
u8 arg();
u16 arg16();
void eax();
void eay();
void pop(PAIR &r);
void push(PAIR &r);
void jp(void);
void jp_cond(bool cond);
void jr();
void jr_cond(bool cond, u8 opcode);
void call();
void call_cond(bool cond, u8 opcode);
void ret_cond(bool cond, u8 opcode);
void retn();
void reti();
void ld_r_a();
void ld_a_r();
void ld_i_a();
void ld_a_i();
void rst(u16 addr);
u8 inc(u8 value);
u8 dec(u8 value);
void inc(u8 &r);
void dec(u8 &r);
void rlca();
void rrca();
void rla();
void rra();
void rrd();
void rld();
void add_a(u8 value);
void adc_a(u8 value);
void sub(u8 value);
@ -200,10 +96,6 @@ protected:
void xor_a(u8 value);
void cp(u8 value);
void exx();
void ex_sp(PAIR &r);
void add16(PAIR &dr, PAIR &sr);
void adc_hl(PAIR &r);
void sbc_hl(PAIR &r);
u8 rlc(u8 value);
u8 rrc(u8 value);
u8 rl(u8 value);
@ -217,32 +109,13 @@ protected:
void bit_xy(int bit, u8 value);
u8 res(int bit, u8 value);
u8 set(int bit, u8 value);
void ldi();
void cpi();
u8 ini();
u8 outi();
void ldd();
void cpd();
u8 ind();
u8 outd();
void ldir();
void cpir();
void inir();
void otir();
void lddr();
void cpdr();
void indr();
void otdr();
void ei();
void set_f(u8 f);
void block_io_interrupted_flags(u8 data);
void block_io_interrupted_flags();
void execute_cycles(u8 icount);
virtual void check_interrupts();
void take_interrupt();
void take_nmi();
void nomreq_ir(s8 cycles);
void nomreq_addr(u16 addr, s8 cycles);
virtual void do_rop();
virtual void do_op();
bool check_icount(u8 to_step, int icount_saved, bool redonable);
virtual u8 data_read(u16 addr);
virtual void data_write(u16 addr, u8 value);
@ -296,8 +169,14 @@ protected:
u32 m_ea;
int m_icount;
int m_tmp_irq_vector;
PAIR16 m_shared_addr;
PAIR16 m_shared_data;
PAIR16 m_shared_data2;
u8 m_rtemp;
bool m_redone;
u32 m_ref;
u8 m_m1_cycles;
u8 m_memrq_cycles;
u8 m_iorq_cycles;
@ -312,15 +191,14 @@ public:
protected:
// device_t implementation
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_start() override ATTR_COLD;
virtual void device_reset() override ATTR_COLD;
// device_execute_interface implementation
virtual u32 execute_input_lines() const noexcept override { return 7; }
virtual void execute_set_input(int inputnum, int state) override;
virtual void check_interrupts() override;
void take_interrupt_nsc800();
virtual void do_rop() override;
u8 m_nsc800_irq_state[4]; // state of NSC800 restart interrupts A, B, C
};

6645
src/devices/cpu/z80/z80.lst Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,241 @@
#!/usr/bin/python
# license:BSD-3-Clause
# copyright-holders:Andre I. Holub
from __future__ import print_function
USAGE = """
Usage:
%s [type] z80.lst z80.inc
"""
import sys
class IndStr:
def __init__(self, src, indent = None):
self.str = src.strip()
self.indent = indent
if not indent:
self.indent = src[:len(src) - len(src.lstrip())]
def line(self):
return self.str
def get_indent(self):
return self.indent
def is_comment(self):
return self.str.startswith("#") and not self.str.startswith("#if") and not self.str.startswith("#endif")
def is_blank(self):
return not self.str
def has_indent(self):
return self.indent != ''
def replace(self, new):
self.str = new
def replace(self, old, new):
return IndStr(self.str.replace(old, new), self.indent)
def with_str(self, new_str):
return IndStr(new_str, self.indent)
def split(self):
return self.str.split()
def print(self, str, f):
print("\t\t%s%s" % (self.indent, str), file=f)
class Opcode:
def __init__(self, code):
self.code = code
self.source = []
def add_source_lines(self, lines):
self.source.extend(lines)
def save_dasm(self, f):
code = self.code
has_steps = len(self.source) > 1
if has_steps:
print("\t\tswitch (u8(m_ref))", file=f)
print("\t\t{", file=f)
print("\t\tcase 0x00:", file=f)
step = 0
for i in range(0, len(self.source)):
il = self.source[i]
line = il.line()
tokens = line.split()
if tokens[0] == '+':
il.print("m_icount -= %s;" % (" ".join(tokens[1:])), f)
step += 1
to_step = "0x%s" % (hex(256 + step)[3:])
il.print("if (check_icount(%s, 0, false)) return;" % (to_step), f)
print("\t\t[[fallthrough]];", file=f)
print("\t\tcase %s:" % (to_step), file=f)
elif (len(tokens) > 2 and tokens[1] == "!!"):
print("\t\t[[fallthrough]];", file=f)
step += 1;
print("\t\tcase 0x%s:" % (hex(256 + step)[3:]), file=f)
il.print("{", f)
il.print("\tconst int icount = m_icount;", f)
il.print("\t%s" % " ".join(tokens[2:]), f)
il.print("\tm_icount -= %s;" % (tokens[0]), f)
step += 1
to_step = "0x%s" % (hex(256 + step)[3:])
il.print("\tif (check_icount(%s, icount, true)) return;" % (to_step), f)
il.print("}", f)
print("\t\t[[fallthrough]];", file=f)
print("\t\tcase %s:" % (to_step), file=f)
else:
il.print("%s" % line, f)
if has_steps:
print("\t\tbreak;\n", file=f)
print("\t\t}", file=f)
class Macro:
def __init__(self, name, arg_name = None):
self.name = name
self.source = []
self.arg_name = arg_name
def apply(self, arg):
if self.arg_name is not None:
return [ r.replace(self.arg_name, arg) for r in self.source ]
else:
return self.source
def add_source_lines(self, lines):
self.source.extend(lines)
class OpcodeList:
def __init__(self, gen, fname):
self.gen = gen
self.opcode_info = []
self.macros = {}
try:
f = open(fname, "r")
except Exception:
err = sys.exc_info()[1]
sys.stderr.write("Cannot read opcodes file %s [%s]\n" % (fname, err))
sys.exit(1)
inf = None
for ln in f:
line = IndStr(ln)
# Skip comments except macros
if line.is_comment() or line.is_blank():
continue
if line.has_indent():
if inf is not None:
if isinstance(inf, Macro):
inf.add_source_lines([line])
else:
inf.add_source_lines(self.pre_process(line))
else:
# New opcode
tokens = line.split()
if tokens[0] == "macro":
name = tokens[1]
arg_name = None
if len(tokens) > 2:
arg_name = tokens[2]
inf = Macro(name, arg_name)
if name in self.macros:
sys.stderr.write("Replacing macro: %s\n" % name)
self.macros[name] = inf
else:
ntokens = tokens[0].split(":")
if len(ntokens) == 2:
inf = Opcode(ntokens[1])
if ntokens[0] == self.gen:
self.opcode_info.append(inf)
else:
inf = Opcode(ntokens[0])
if None == self.gen:
self.opcode_info.append(inf)
def pre_process(self, iline):
out = []
line = iline.str
line_toc = line.split()
times = 1
if len(line_toc) > 2 and line_toc[1] == "*":
times = int(line_toc[0])
line_toc = line_toc[2:]
line = " ".join(line_toc)
for i in range(times):
if line_toc[0] == 'call':
name = line_toc[1]
arg = None
if len(line_toc) > 2:
arg = line_toc[2]
if name in self.macros:
macro = self.macros[name]
([out.extend(self.pre_process(il)) for il in macro.apply(arg)])
else:
sys.stderr.write("Macro not found %s\n" % name)
out.append(iline.with_str("... %s" % name))
else:
out.append(iline.with_str(line))
return out
def save_exec(self, f):
prefix = None
print("switch (u8(m_ref >> 16)) // prefix", file=f)
print("{", file=f)
for opc in self.opcode_info:
if (opc.code[:2]) != prefix:
if prefix is not None:
print("\n\t}", file=f)
print("\tbreak;", file=f)
print("", file=f)
print("}", file=f)
print("break; // prefix: 0x%s" % (prefix), file=f)
print("", file=f)
prefix = opc.code[:2]
print("case 0x%s:" % (opc.code[:2]), file=f)
print("{", file=f)
print("\tswitch (u8(m_ref >> 8)) // opcode", file=f)
print("\t{", file=f)
print("\tcase 0x%s:" % (opc.code[2:]), file=f)
#print("\t{", file=f)
opc.save_dasm(f)
#print("\t}", file=f)
print("\tbreak;", file=f)
print("", file=f)
print("\t} // switch opcode", file=f)
print("}", file=f)
print("break; // prefix: 0x%s" % (prefix), file=f)
print("", file=f)
print("} // switch prefix", file=f)
def main(argv):
if len(argv) != 3 and len(argv) != 4:
print(USAGE % argv[0])
return 1
fidx = 1
gen = None
if len(argv) == 4:
gen = argv[1]
fidx = 2
opcodes = OpcodeList(gen, argv[fidx])
try:
f = open(argv[fidx + 1], "w")
except Exception:
err = sys.exc_info()[fidx]
sys.stderr.write("cannot write file %s [%s]\n" % (argv[fidx + 1], err))
sys.exit(1)
opcodes.save_exec(f)
f.close()
# ======================================================================
if __name__ == "__main__":
sys.exit(main(sys.argv))