mirror of
https://github.com/holub/mame
synced 2025-04-19 15:11:37 +03:00
Merge branch 'z80-perf-v2'
Some checks are pending
CI (Windows) / build-windows (gcc, gcc, g++, mame, mame) (push) Waiting to run
Some checks are pending
CI (Windows) / build-windows (gcc, gcc, g++, mame, mame) (push) Waiting to run
This commit is contained in:
commit
28309e82e6
@ -3031,9 +3031,10 @@ end
|
||||
--@src/devices/cpu/z80/kl5c80a12.h,CPUS["KC80"] = true
|
||||
--@src/devices/cpu/z80/kl5c80a16.h,CPUS["KC80"] = true
|
||||
--@src/devices/cpu/z80/ky80.h,CPUS["KC80"] = true
|
||||
--@src/devices/cpu/z80/t6a84.h,CPUS["T6A84"] = true
|
||||
--------------------------------------------------
|
||||
|
||||
if CPUS["Z80"] or CPUS["KC80"] or CPUS["Z80N"] then
|
||||
if CPUS["Z80"] or CPUS["KC80"] or CPUS["Z80N"] or CPUS["T6A84"] then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/cpu/z80/z80.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/z80/z80.h",
|
||||
@ -3055,18 +3056,22 @@ if CPUS["Z80"] or CPUS["KC80"] or CPUS["Z80N"] then
|
||||
MAME_DIR .. "src/devices/cpu/z80/r800.h",
|
||||
MAME_DIR .. "src/devices/cpu/z80/z84c015.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/z80/z84c015.h",
|
||||
MAME_DIR .. "src/devices/cpu/z80/t6a84.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/z80/t6a84.h",
|
||||
}
|
||||
|
||||
dependency {
|
||||
{ MAME_DIR .. "src/devices/cpu/z80/z80.cpp", GEN_DIR .. "emu/cpu/z80/z80.hxx" },
|
||||
{ MAME_DIR .. "src/devices/cpu/z80/nsc800.cpp", GEN_DIR .. "emu/cpu/z80/ncs800.hxx" },
|
||||
{ MAME_DIR .. "src/devices/cpu/z80/r800.cpp", GEN_DIR .. "emu/cpu/z80/r800.hxx" },
|
||||
{ MAME_DIR .. "src/devices/cpu/z80/t6a84.cpp", GEN_DIR .. "emu/cpu/z80/t6a84.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/ncs800.hxx", { MAME_DIR .. "src/devices/cpu/z80/z80make.py" }, { "@echo Generating NSC800 source file...", PYTHON .. " $(1) ncs800 $(<) $(@)" } },
|
||||
{ MAME_DIR .. "src/devices/cpu/z80/z80.lst", GEN_DIR .. "emu/cpu/z80/r800.hxx", { MAME_DIR .. "src/devices/cpu/z80/z80make.py" }, { "@echo Generating R800 source file...", PYTHON .. " $(1) r800 $(<) $(@)" } },
|
||||
{ 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/ncs800.hxx", { MAME_DIR .. "src/devices/cpu/z80/z80make.py" }, { "@echo Generating NSC800 source file...", PYTHON .. " $(1) ncs800 $(<) $(@)" } },
|
||||
{ MAME_DIR .. "src/devices/cpu/z80/z80.lst", GEN_DIR .. "emu/cpu/z80/r800.hxx", { MAME_DIR .. "src/devices/cpu/z80/z80make.py" }, { "@echo Generating R800 source file...", PYTHON .. " $(1) r800 $(<) $(@)" } },
|
||||
{ MAME_DIR .. "src/devices/cpu/z80/z80.lst", GEN_DIR .. "emu/cpu/z80/t6a84.hxx", { MAME_DIR .. "src/devices/cpu/z80/z80make.py" }, { "@echo Generating T6A84 source file...", PYTHON .. " $(1) t6a84 $(<) $(@)" } },
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -9,9 +9,13 @@
|
||||
#include "emu.h"
|
||||
#include "t6a84.h"
|
||||
|
||||
#define LOG_PAGE_R (1U << 1)
|
||||
#define LOG_PAGE_W (1U << 2)
|
||||
#define LOG_MEM (1U << 3)
|
||||
#include "z80.inc"
|
||||
|
||||
#define LOG_INT (1U << 1) // z80.lst
|
||||
#define LOG_UNDOC (1U << 2)
|
||||
#define LOG_PAGE_R (1U << 3)
|
||||
#define LOG_PAGE_W (1U << 4)
|
||||
#define LOG_MEM (1U << 5)
|
||||
|
||||
//#define VERBOSE (LOG_PAGE_R | LOG_PAGE_W | LOG_MEM)
|
||||
#include "logmacro.h"
|
||||
@ -38,6 +42,9 @@ t6a84_device::t6a84_device(const machine_config &mconfig, device_type type, cons
|
||||
, m_data_space_config("data", ENDIANNESS_LITTLE, 8, 20, 0, 16, 0)
|
||||
, m_stack_space_config("stack", ENDIANNESS_LITTLE, 8, 20, 0, 16, 0)
|
||||
, m_io_space_config("io", ENDIANNESS_LITTLE, 8, 16, 0, io_map)
|
||||
, m_branch_cb(*this)
|
||||
, m_irqfetch_cb(*this)
|
||||
, m_reti_cb(*this)
|
||||
, m_code_page(0)
|
||||
, m_delay_code_page(0)
|
||||
, m_is_delay_code_page_set(false)
|
||||
@ -76,6 +83,11 @@ t6a84_device::t6a84_device(const machine_config &mconfig, device_type type, cons
|
||||
});
|
||||
}
|
||||
|
||||
void t6a84_device::execute_run()
|
||||
{
|
||||
#include "cpu/z80/t6a84.hxx"
|
||||
}
|
||||
|
||||
void t6a84_device::device_start()
|
||||
{
|
||||
z80_device::device_start();
|
||||
|
@ -40,6 +40,10 @@ public:
|
||||
uint32_t data_address(uint16_t address);
|
||||
uint32_t stack_address(uint16_t address);
|
||||
|
||||
auto branch_cb() { return m_branch_cb.bind(); }
|
||||
auto irqfetch_cb() { return m_irqfetch_cb.bind(); }
|
||||
auto reti_cb() { return m_reti_cb.bind(); }
|
||||
|
||||
protected:
|
||||
t6a84_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor io_map);
|
||||
|
||||
@ -47,6 +51,9 @@ protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_execute_interface implementation
|
||||
virtual void execute_run() override;
|
||||
|
||||
// z80 overrides
|
||||
virtual uint8_t stack_read(uint16_t addr) override;
|
||||
virtual void stack_write(uint16_t addr, uint8_t value) override;
|
||||
@ -71,6 +78,10 @@ protected:
|
||||
|
||||
memory_access<16, 0, 0, ENDIANNESS_LITTLE>::specific m_stack;
|
||||
|
||||
devcb_write_line m_branch_cb;
|
||||
devcb_write_line m_irqfetch_cb;
|
||||
devcb_write_line m_reti_cb;
|
||||
|
||||
private:
|
||||
uint8_t m_code_page;
|
||||
uint8_t m_delay_code_page;
|
||||
|
@ -822,9 +822,6 @@ z80_device::z80_device(const machine_config &mconfig, device_type type, const ch
|
||||
m_nomreq_cb(*this),
|
||||
m_halt_cb(*this),
|
||||
m_busack_cb(*this),
|
||||
m_branch_cb(*this),
|
||||
m_irqfetch_cb(*this),
|
||||
m_reti_cb(*this),
|
||||
m_m1_cycles(4),
|
||||
m_memrq_cycles(3),
|
||||
m_iorq_cycles(4)
|
||||
|
@ -43,12 +43,6 @@ public:
|
||||
auto halt_cb() { return m_halt_cb.bind(); }
|
||||
auto busack_cb() { return m_busack_cb.bind(); }
|
||||
|
||||
// Extra callbacks that do not map to any documented signals.
|
||||
// Used by derived classes to customise instruction behaviour.
|
||||
auto branch_cb() { return m_branch_cb.bind(); }
|
||||
auto irqfetch_cb() { return m_irqfetch_cb.bind(); }
|
||||
auto reti_cb() { return m_reti_cb.bind(); }
|
||||
|
||||
// output pins state
|
||||
int halt_r() { return m_halt; }
|
||||
int busack_r() { return m_busack_state; }
|
||||
@ -143,12 +137,6 @@ protected:
|
||||
devcb_write_line m_halt_cb;
|
||||
devcb_write_line m_busack_cb;
|
||||
|
||||
// Extra callbacks that do not map to any documented signals.
|
||||
// Used by derived classes to customise instruction behaviour.
|
||||
devcb_write_line m_branch_cb;
|
||||
devcb_write_line m_irqfetch_cb;
|
||||
devcb_write_line m_reti_cb;
|
||||
|
||||
PAIR16 m_prvpc;
|
||||
PAIR16 m_pc;
|
||||
PAIR16 m_sp;
|
||||
|
@ -4,7 +4,7 @@
|
||||
# macros
|
||||
##########################################################
|
||||
macro nomreq_addr
|
||||
if (!m_nomreq_cb.isunset())
|
||||
if (nomemrq_en)
|
||||
m_nomreq_cb(TADR, 0x00, 0xff);
|
||||
+ 1
|
||||
|
||||
@ -47,7 +47,7 @@ macro wm16_sp
|
||||
|
||||
macro rop
|
||||
m_m1_cycles-2 !! TDAT8 = opcode_read();
|
||||
if (!m_refresh_cb.isunset())
|
||||
if (refresh_en)
|
||||
m_refresh_cb((I << 8) | (R2 & 0x80) | (R & 0x7f), 0x00, 0xff);
|
||||
+ 2
|
||||
PC++; R++; Q = QT; QT = YF | XF;
|
||||
@ -87,9 +87,23 @@ macro push
|
||||
macro jp
|
||||
call arg16
|
||||
PC = TDAT; WZ = PC;
|
||||
|
||||
macro t6a84:jp
|
||||
call arg16
|
||||
PC = TDAT; WZ = PC;
|
||||
m_branch_cb(1);
|
||||
|
||||
macro jp_cond
|
||||
if (TDAT8) {
|
||||
call arg16
|
||||
PC = TDAT; WZ = PC;
|
||||
} else {
|
||||
// implicit do PC += 2
|
||||
call arg16
|
||||
WZ = TDAT;
|
||||
}
|
||||
|
||||
macro t6a84:jp_cond
|
||||
if (TDAT8) {
|
||||
call arg16
|
||||
PC = TDAT; WZ = PC;
|
||||
@ -105,6 +119,12 @@ macro jr
|
||||
TADR = PC-1;
|
||||
5 * call nomreq_addr
|
||||
PC += (s8)TDAT8; WZ = PC;
|
||||
|
||||
macro t6a84:jr
|
||||
call arg
|
||||
TADR = PC-1;
|
||||
5 * call nomreq_addr
|
||||
PC += (s8)TDAT8; WZ = PC;
|
||||
m_branch_cb(1);
|
||||
|
||||
macro r800:jr
|
||||
@ -167,6 +187,11 @@ macro z80n:retn
|
||||
LOGMASKED(LOG_INT, "RETN m_iff1:%d m_iff2:%d\n", m_iff1, m_iff2); WZ = PC; m_iff1 = m_iff2;
|
||||
|
||||
macro reti
|
||||
call pop
|
||||
PC = TDAT; WZ = PC; m_iff1 = m_iff2;
|
||||
daisy_call_reti_device();
|
||||
|
||||
macro t6a84:reti
|
||||
call pop
|
||||
PC = TDAT; WZ = PC; m_iff1 = m_iff2;
|
||||
m_reti_cb(1);
|
||||
@ -508,11 +533,11 @@ macro r800:otdr
|
||||
|
||||
macro jump %opcode
|
||||
m_ref = 0x%opcode00;
|
||||
continue;
|
||||
goto process;
|
||||
|
||||
macro jump_prefixed %prefix
|
||||
m_ref = (%prefix << 16) | (TDAT8 << 8);
|
||||
continue;
|
||||
goto process;
|
||||
|
||||
macro take_nmi
|
||||
// Check if processor was halted
|
||||
@ -530,6 +555,23 @@ macro take_nmi
|
||||
WZ = PC;
|
||||
m_nmi_pending = false;
|
||||
|
||||
macro irqfetch
|
||||
{
|
||||
// fetch the IRQ vector
|
||||
device_z80daisy_interface *intf = daisy_get_irq_device();
|
||||
m_tmp_irq_vector = (intf != nullptr) ? intf->z80daisy_irq_ack() : standard_irq_callback(0, m_pc.w);
|
||||
LOGMASKED(LOG_INT, "single INT m_tmp_irq_vector $%02x\n", m_tmp_irq_vector);
|
||||
}
|
||||
|
||||
macro t6a84:irqfetch
|
||||
{
|
||||
// fetch the IRQ vector
|
||||
m_irqfetch_cb(1);
|
||||
device_z80daisy_interface *intf = daisy_get_irq_device();
|
||||
m_tmp_irq_vector = (intf != nullptr) ? intf->z80daisy_irq_ack() : standard_irq_callback(0, m_pc.w);
|
||||
LOGMASKED(LOG_INT, "single INT m_tmp_irq_vector $%02x\n", m_tmp_irq_vector);
|
||||
}
|
||||
|
||||
macro take_interrupt
|
||||
// check if processor was halted
|
||||
leave_halt();
|
||||
@ -539,13 +581,7 @@ macro take_interrupt
|
||||
// Not precise in all cases. z80 must finish current instruction (NOP) to reach this state - in such case frame timings are shifter from cb event if calculated based on it.
|
||||
m_irqack_cb(1);
|
||||
m_r++;
|
||||
{
|
||||
// fetch the IRQ vector
|
||||
m_irqfetch_cb(1);
|
||||
device_z80daisy_interface *intf = daisy_get_irq_device();
|
||||
m_tmp_irq_vector = (intf != nullptr) ? intf->z80daisy_irq_ack() : standard_irq_callback(0, m_pc.w);
|
||||
LOGMASKED(LOG_INT, "single INT m_tmp_irq_vector $%02x\n", m_tmp_irq_vector);
|
||||
}
|
||||
call irqfetch
|
||||
// 'interrupt latency' cycles
|
||||
+ 2
|
||||
// Interrupt mode 2. Call [i:databyte]
|
||||
@ -671,20 +707,21 @@ macro ncs800:check_interrupts
|
||||
# ROP
|
||||
##########################################################
|
||||
ffff
|
||||
rop:
|
||||
m_ref = 0xffff00;
|
||||
if (m_icount <= 0) return;
|
||||
if (m_busrq_state) {
|
||||
if (!m_busack_state) {
|
||||
m_busack_state = 1;
|
||||
m_busack_cb(1);
|
||||
if (busack_en) {
|
||||
if (m_busrq_state) {
|
||||
if (!m_busack_state) {
|
||||
m_busack_state = 1;
|
||||
m_busack_cb(1);
|
||||
}
|
||||
if (m_icount > 0)
|
||||
m_icount = 0;
|
||||
return;
|
||||
} else if (m_busack_state) {
|
||||
m_busack_state = 0;
|
||||
m_busack_cb(0);
|
||||
}
|
||||
if (m_icount > 0)
|
||||
m_icount = 0;
|
||||
return;
|
||||
} else if (m_busack_state) {
|
||||
m_busack_state = 0;
|
||||
m_busack_cb(0);
|
||||
}
|
||||
call check_interrupts
|
||||
m_after_ei = false;
|
||||
@ -693,13 +730,13 @@ ffff
|
||||
debugger_wait_hook();
|
||||
call rop
|
||||
PC--;
|
||||
goto rop;
|
||||
continue;
|
||||
} else {
|
||||
PRVPC = PC;
|
||||
debugger_instruction_hook(PC);
|
||||
call rop
|
||||
m_ref = (0x00 << 16) | (TDAT8 << 8);
|
||||
continue;
|
||||
goto process;
|
||||
}
|
||||
|
||||
|
||||
|
@ -49,59 +49,91 @@ class IndStr:
|
||||
|
||||
|
||||
class Opcode:
|
||||
def __init__(self, code):
|
||||
def __init__(self, prefix, code):
|
||||
self.prefix = prefix
|
||||
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
|
||||
def with_steps(self):
|
||||
for i in range(0, len(self.source)):
|
||||
tokens = self.source[i].line().split()
|
||||
if (tokens[0] == '+') or (len(tokens) > 2 and tokens[1] == "!!"):
|
||||
return True
|
||||
return False
|
||||
|
||||
def save_dasm(self, step_switch: bool, f):
|
||||
has_steps = self.with_steps()
|
||||
if has_steps:
|
||||
print("\t\tswitch (u8(m_ref))", file=f)
|
||||
print("\t\t{", file=f)
|
||||
print("\t\tcase 0x00:", file=f)
|
||||
if step_switch:
|
||||
print("\t\tswitch (u8(m_ref))", file=f)
|
||||
print("\t\t{", file=f)
|
||||
print("\t\tcase 0x00:", file=f)
|
||||
else:
|
||||
print("\t\t//case 0x00:", file=f)
|
||||
step = 0
|
||||
for i in range(0, len(self.source)):
|
||||
il = self.source[i]
|
||||
if not has_steps:
|
||||
if not has_steps or not step_switch:
|
||||
il.indent = ""
|
||||
line = il.line()
|
||||
tokens = line.split()
|
||||
last_line = i + 1 == len(self.source)
|
||||
|
||||
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 (m_icount <= 0) {", f)
|
||||
il.print(" m_ref = (m_ref & 0xffff00) | %s;" % (to_step), f)
|
||||
il.print(" return;", f)
|
||||
il.print("}", f)
|
||||
il.print("[[fallthrough]];", f)
|
||||
print("\t\tcase %s:" % (to_step), file=f)
|
||||
if not last_line:
|
||||
to_step = hex(256 + step)[3:]
|
||||
il.print(" m_ref = 0x%s%s%s;" % (self.prefix, self.code, to_step), f)
|
||||
il.print(" return;", f)
|
||||
il.print("}", f)
|
||||
if step_switch:
|
||||
il.print("[[fallthrough]];", f)
|
||||
print("\t\tcase 0x%s:" % (to_step), file=f)
|
||||
else:
|
||||
print("\t\t//case 0x%s:" % (to_step), file=f)
|
||||
else:
|
||||
il.print(" m_ref = 0xffff00;", f)
|
||||
il.print(" return;", f)
|
||||
il.print("}", f)
|
||||
elif (len(tokens) > 2 and tokens[1] == "!!"):
|
||||
il.print("[[fallthrough]];", f)
|
||||
step += 1;
|
||||
print("\t\tcase 0x%s:" % (hex(256 + step)[3:]), file=f)
|
||||
if step_switch:
|
||||
il.print("[[fallthrough]];", f)
|
||||
print("\t\tcase 0x%s:" % (hex(256 + step)[3:]), file=f)
|
||||
else:
|
||||
print("\t\t//case 0x%s:" % (hex(256 + step)[3:]), file=f)
|
||||
il.print("%s" % " ".join(tokens[2:]), f)
|
||||
il.print("m_icount -= %s;" % (tokens[0]), f)
|
||||
il.print("if (m_icount <= 0) {", f)
|
||||
il.print(" if (access_to_be_redone()) {", f)
|
||||
il.print(" m_icount += %s;" % (tokens[0]), f)
|
||||
il.print(" m_ref = (m_ref & 0xffff00) | 0x%s;" % (hex(256 + step)[3:]), f)
|
||||
il.print(" } else", f)
|
||||
step += 1
|
||||
to_step = "0x%s" % (hex(256 + step)[3:])
|
||||
il.print(" m_ref = (m_ref & 0xffff00) | %s;" % (to_step), f)
|
||||
il.print(" return;", f)
|
||||
il.print("}", f)
|
||||
il.print("[[fallthrough]];", f)
|
||||
print("\t\tcase %s:" % (to_step), file=f)
|
||||
il.print(" m_ref = 0x%s%s%s;" % (self.prefix, self.code, hex(256 + step)[3:]), f)
|
||||
il.print(" } else {", f)
|
||||
if not last_line:
|
||||
step += 1
|
||||
to_step = hex(256 + step)[3:]
|
||||
il.print(" m_ref = 0x%s%s%s;" % (self.prefix, self.code, to_step), f)
|
||||
il.print(" }", f)
|
||||
il.print(" return;", f)
|
||||
il.print("}", f)
|
||||
if step_switch:
|
||||
il.print("[[fallthrough]];", f)
|
||||
print("\t\tcase 0x%s:" % (to_step), file=f)
|
||||
else:
|
||||
print("\t\t//case 0x%s:" % (to_step), file=f)
|
||||
else:
|
||||
il.print(" m_ref = 0xffff00;", f)
|
||||
il.print(" }", f)
|
||||
il.print(" return;", f)
|
||||
il.print("}", f)
|
||||
else:
|
||||
il.print("%s" % line, f)
|
||||
if has_steps:
|
||||
print("\t\t\tbreak;\n", file=f)
|
||||
if has_steps and step_switch:
|
||||
print("\t\t}", file=f)
|
||||
|
||||
class Macro:
|
||||
@ -122,7 +154,7 @@ class Macro:
|
||||
class OpcodeList:
|
||||
def __init__(self, gen, fname):
|
||||
self.gen = gen
|
||||
self.opcode_info = []
|
||||
self.opcode_info = {} # prefix -> [Opcode]
|
||||
self.macros = {}
|
||||
|
||||
try:
|
||||
@ -167,33 +199,32 @@ class OpcodeList:
|
||||
self.macros[nnames[0]] = inf
|
||||
else:
|
||||
ntokens = tokens[0].split(":")
|
||||
if len(ntokens) == 2:
|
||||
inf = Opcode(ntokens[1])
|
||||
if ntokens[0] == self.gen:
|
||||
# Replace in list when already present, otherwise append
|
||||
found = False
|
||||
found_index = 0
|
||||
for i in range(len(self.opcode_info)):
|
||||
if self.opcode_info[i].code == inf.code:
|
||||
found = True
|
||||
found_index = i
|
||||
if found:
|
||||
self.opcode_info[found_index] = inf
|
||||
else:
|
||||
self.opcode_info.append(inf)
|
||||
else:
|
||||
inf = Opcode(ntokens[0])
|
||||
if None == self.gen:
|
||||
self.opcode_info.append(inf)
|
||||
else:
|
||||
# Only place in list when not already present
|
||||
found = False
|
||||
for i in range(len(self.opcode_info)):
|
||||
if self.opcode_info[i].code == inf.code:
|
||||
found = True
|
||||
if not found:
|
||||
self.opcode_info.append(inf)
|
||||
gen = None if len(ntokens) == 1 else ntokens[0]
|
||||
prefix = ntokens[0][:2] if len(ntokens) == 1 else ntokens[1][:2]
|
||||
opcode = ntokens[0][2:] if len(ntokens) == 1 else ntokens[1][2:]
|
||||
if self.opcode_info.get(prefix) is None:
|
||||
self.opcode_info[prefix] = []
|
||||
opcodes = self.opcode_info[prefix]
|
||||
|
||||
if None == gen:
|
||||
inf = Opcode(prefix, opcode)
|
||||
opcodes.append(inf)
|
||||
elif gen == self.gen:
|
||||
# Replace for ext generator
|
||||
found = False
|
||||
found_index = 0
|
||||
for i in range(len(opcodes)):
|
||||
if opcodes[i].code == opcode:
|
||||
found = True
|
||||
found_index = i
|
||||
if found:
|
||||
inf = Opcode(prefix, opcode)
|
||||
opcodes[found_index] = inf
|
||||
else:
|
||||
sys.stderr.write("[%s] Cannot find opcode: %s%s\n" % (gen, prefix, opcode))
|
||||
sys.exit(1)
|
||||
else:
|
||||
inf = Opcode(prefix, '/dev/null')
|
||||
|
||||
def pre_process(self, iline):
|
||||
out = []
|
||||
@ -220,39 +251,72 @@ class OpcodeList:
|
||||
out.append(iline.with_str(line))
|
||||
return out
|
||||
|
||||
def switch_prefix(self, prefixes, reenter: bool, f):
|
||||
prefix_switch = len(prefixes) > 1
|
||||
|
||||
if prefix_switch:
|
||||
print("switch (u8(m_ref >> 16)) // prefix", file=f)
|
||||
print("{", file=f)
|
||||
|
||||
for prefix in prefixes:
|
||||
is_rop = prefix == 'ff'
|
||||
if prefix_switch:
|
||||
print("case 0x%s:" % (prefix), file=f)
|
||||
print("{", file=f)
|
||||
if not is_rop:
|
||||
print("\tswitch (u8(m_ref >> 8)) // opcode", file=f)
|
||||
print("\t{", file=f)
|
||||
for opc in self.opcode_info[prefix]:
|
||||
# reenter loop only process steps > 0
|
||||
if not reenter or opc.with_steps():
|
||||
if not is_rop:
|
||||
print("\tcase 0x%s:" % (opc.code), file=f)
|
||||
opc.save_dasm(step_switch=reenter, f=f)
|
||||
print("\t\tcontinue;", file=f)
|
||||
print("", file=f)
|
||||
if not is_rop:
|
||||
print("\t}", file=f)
|
||||
|
||||
if prefix_switch:
|
||||
print("} break; // prefix: %s" % (prefix), file=f)
|
||||
print("", file=f)
|
||||
if prefix_switch:
|
||||
print("} // switch prefix", file=f)
|
||||
|
||||
def save_exec(self, f):
|
||||
prefix = None
|
||||
print("if (m_wait_state)", file=f)
|
||||
print("{", file=f)
|
||||
print("\tm_icount = 0; // stalled", file=f)
|
||||
print("\treturn;", file=f)
|
||||
print("}", file=f)
|
||||
print("while (true) {", file=f)
|
||||
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("\t\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)
|
||||
opc.save_dasm(f)
|
||||
print("\t\tgoto rop;", 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)
|
||||
print("const bool nomemrq_en = !m_nomreq_cb.isunset();", file=f)
|
||||
print("[[maybe_unused]] const bool refresh_en = !m_refresh_cb.isunset();", file=f)
|
||||
print("const bool busack_en = !m_busack_cb.isunset();", file=f)
|
||||
print("", file=f)
|
||||
print("bool interrupted = true;", file=f)
|
||||
print("while (u8(m_ref) != 0x00) {", file=f)
|
||||
print("\t// workaround to simulate main loop behavior where continue statement relays on having it set after", file=f)
|
||||
print("\tif (!interrupted) {", file=f)
|
||||
print("\t\tm_ref = 0xffff00;", file=f)
|
||||
print("\t\tcontinue;", file=f)
|
||||
print("\t}", file=f)
|
||||
print("\tinterrupted = false;", file=f)
|
||||
print("", file=f)
|
||||
self.switch_prefix(self.opcode_info.keys(), reenter=True, f=f)
|
||||
print("", file=f)
|
||||
print('assert((void("switch statement above must cover all possible cases!"), false));', file=f)
|
||||
print("}", file=f)
|
||||
print("", file=f)
|
||||
print("if (m_ref != 0xffff00) goto process;", file=f)
|
||||
print("", file=f)
|
||||
print("while (true) {", file=f)
|
||||
print("", file=f)
|
||||
print("\t\t// unwrapped ff prefix", file=f)
|
||||
self.switch_prefix(['ff'], reenter=False, f=f)
|
||||
print("", file=f)
|
||||
print("process:", file=f)
|
||||
self.switch_prefix(self.opcode_info.keys() - ['ff'], reenter=False, f=f)
|
||||
print("", file=f)
|
||||
print("} // while (true)", file=f)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user