summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Olivier Galibert <galibert@pobox.com>2013-03-20 16:14:39 +0000
committer Olivier Galibert <galibert@pobox.com>2013-03-20 16:14:39 +0000
commit90362d4baff3172511db16a78136d642a98c92be (patch)
treee35655c9c4679511e31ca9b65e412b39f84cee8c
parent88162e112845bc3b25559970c40dfb80643ba1e8 (diff)
m6502: Seriously untested multi-dispatch-table support [O. Galibert]
-rw-r--r--docs/m6502.txt16
-rw-r--r--src/emu/cpu/m6502/m6502.c7
-rw-r--r--src/emu/cpu/m6502/m6502.h3
-rwxr-xr-xsrc/emu/cpu/m6502/m6502make.py22
4 files changed, 33 insertions, 15 deletions
diff --git a/docs/m6502.txt b/docs/m6502.txt
index 6b010e64ab0..56e761ebf5a 100644
--- a/docs/m6502.txt
+++ b/docs/m6502.txt
@@ -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.
diff --git a/src/emu/cpu/m6502/m6502.c b/src/emu/cpu/m6502/m6502.c
index d944a433415..2d15dadd967 100644
--- a/src/emu/cpu/m6502/m6502.c
+++ b/src/emu/cpu/m6502/m6502.c
@@ -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);
diff --git a/src/emu/cpu/m6502/m6502.h b/src/emu/cpu/m6502/m6502.h
index 766f30a1fe3..0588442e9bd 100644
--- a/src/emu/cpu/m6502/m6502.h
+++ b/src/emu/cpu/m6502/m6502.h
@@ -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;
diff --git a/src/emu/cpu/m6502/m6502make.py b/src/emu/cpu/m6502/m6502make.py
index e6da2f2e992..38ac41841d9 100755
--- a/src/emu/cpu/m6502/m6502make.py
+++ b/src/emu/cpu/m6502/m6502make.py
@@ -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)