m6502: Seriously untested multi-dispatch-table support [O. Galibert]

This commit is contained in:
Olivier Galibert 2013-03-20 16:14:39 +00:00
parent 88162e1128
commit 90362d4baf
4 changed files with 33 additions and 15 deletions

View File

@ -252,7 +252,7 @@ A code generator is used to support interrupting and restarting an
instruction in the middle. This is done through a two-level state
machine with updates only at the boundaries. More precisely,
inst_state tells you which main state you're in. It's equal to the
opcode byte when 0-255, and 256 means reset. It's always valid and
opcode byte when 0-255, and 0xff00 means reset. It's always valid and
used by instructions like rmb. inst_substate indicates at which step
we are in an instruction, but it set only when an instruction has been
interrupted. Let's go back to the asl <abs> code:
@ -458,7 +458,19 @@ to note that the exception path only happens when the contention/wait
state goes further than the scheduling slice of the cpu. That should
not usually be the case, so the cost should be minimal.
10. Current TODO
10. Multi-dispatch variants
Some variants currently in the process of being supported change
instruction set depending on an internal flag, either switching to a
16-bits mode or changing some register accesses to memory accesses.
This is handled by having multiple dispatch tables for the cpu, the
d<cpu>.lst not being 257 entries anymore but 256*n+1. The variable
inst_state_base must select which instruction table to use at a given
time. It must be a multiple of 256, and is in fact simply or-ed to
the first instruction byte to get the dispatch table index (aka
inst_state).
11. Current TODO
- Implement the bus contention/wait states stuff, but that requires
support on the memory map side first.

View File

@ -100,6 +100,7 @@ void m6502_device::init()
save_item(NAME(v_state));
save_item(NAME(inst_state));
save_item(NAME(inst_substate));
save_item(NAME(inst_state_base));
save_item(NAME(irq_taken));
save_item(NAME(inhibit_interrupts));
@ -122,6 +123,7 @@ void m6502_device::init()
v_state = false;
inst_state = STATE_RESET;
inst_substate = 0;
inst_state_base = 0;
sync = false;
end_cycles = 0;
inhibit_interrupts = false;
@ -131,6 +133,7 @@ void m6502_device::device_reset()
{
inst_state = STATE_RESET;
inst_substate = 0;
inst_state_base = 0;
nmi_state = false;
irq_state = false;
apu_irq_state = false;
@ -406,7 +409,7 @@ void m6502_device::execute_run()
while(icount > 0) {
if(inst_state < 0x100) {
PPC = NPC;
inst_state = IR;
inst_state = IR | inst_state_base;
if(machine().debug_flags & DEBUG_FLAG_ENABLED)
debugger_instruction_hook(this, NPC);
}
@ -479,7 +482,7 @@ UINT32 m6502_device::disasm_max_opcode_bytes() const
offs_t m6502_device::disassemble_generic(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options, const disasm_entry *table)
{
const disasm_entry &e = table[oprom[0]];
const disasm_entry &e = table[oprom[0] | inst_state_base];
UINT32 flags = e.flags | DASMFLAG_SUPPORTED;
buffer += sprintf(buffer, "%s", e.opcode);

View File

@ -97,7 +97,7 @@ protected:
};
enum {
STATE_RESET = 0x100,
STATE_RESET = 0xff00,
};
enum {
@ -182,6 +182,7 @@ protected:
UINT8 Y; /* Y index register */
UINT8 P; /* Processor status */
UINT8 IR; /* Prefetched instruction register */
int inst_state_base; /* Current instruction bank */
memory_interface *mintf;
int inst_state, inst_substate;

View File

@ -7,7 +7,7 @@ Usage:
import sys
import logging
MAX_STATES = 0x101
MAX_STATES = 0
def load_opcodes(fname):
"""Load opcodes from .lst file"""
@ -174,7 +174,7 @@ DO_EXEC_PARTIAL_EPILOG="""\
"""
DISASM_PROLOG="""\
const %(device)s::disasm_entry %(device)s::disasm_entries[0x100] = {
const %(device)s::disasm_entry %(device)s::disasm_entries[0x%(disasm_count)x] = {
"""
DISASM_EPILOG="""\
@ -182,15 +182,17 @@ DISASM_EPILOG="""\
"""
def save_tables(f, device, states):
total_states = len(states)
d = { "device": device,
"disasm_count": total_states-1
}
assert len(states) == MAX_STATES
emit(f, DO_EXEC_FULL_PROLOG % d)
for n, state in enumerate(states):
if state == ".": continue
if n < MAX_STATES - 1:
if n < total_states - 1:
emit(f, "\tcase 0x%02x: %s_full(); break;\n" % (n, state))
else:
emit(f, "\tcase %s: %s_full(); break;\n" % ("STATE_RESET", state))
@ -199,16 +201,16 @@ def save_tables(f, device, states):
emit(f, DO_EXEC_PARTIAL_PROLOG % d)
for n, state in enumerate(states):
if state == ".": continue
if n < MAX_STATES - 1:
if n < total_states - 1:
emit(f, "\tcase 0x%02x: %s_partial(); break;\n" % (n, state))
else:
emit(f, "\tcase %s: %s_partial(); break;\n" % ("STATE_RESET", state))
emit(f, DO_EXEC_PARTIAL_EPILOG % d)
emit(f, DISASM_PROLOG % d)
emit(f, DISASM_PROLOG % d )
for n, state in enumerate(states):
if state == ".": continue
if n == MAX_STATES - 1: break
if n == total_states - 1: break
tokens = state.split("_")
opc = tokens[0]
mode = tokens[-1]
@ -262,8 +264,8 @@ def main(argv):
states = load_disp(argv[3])
logging.info("loaded %s states", len(states))
assert len(states) == MAX_STATES
assert (len(states) & 0xff) == 1
save(argv[4], device_name, opcodes, states)