trunk/src/emu/cpu/m6502/m6502.c
| r21986 | r21987 | |
| 100 | 100 | save_item(NAME(v_state)); |
| 101 | 101 | save_item(NAME(inst_state)); |
| 102 | 102 | save_item(NAME(inst_substate)); |
| 103 | save_item(NAME(inst_state_base)); |
| 103 | 104 | save_item(NAME(irq_taken)); |
| 104 | 105 | save_item(NAME(inhibit_interrupts)); |
| 105 | 106 | |
| r21986 | r21987 | |
| 122 | 123 | v_state = false; |
| 123 | 124 | inst_state = STATE_RESET; |
| 124 | 125 | inst_substate = 0; |
| 126 | inst_state_base = 0; |
| 125 | 127 | sync = false; |
| 126 | 128 | end_cycles = 0; |
| 127 | 129 | inhibit_interrupts = false; |
| r21986 | r21987 | |
| 131 | 133 | { |
| 132 | 134 | inst_state = STATE_RESET; |
| 133 | 135 | inst_substate = 0; |
| 136 | inst_state_base = 0; |
| 134 | 137 | nmi_state = false; |
| 135 | 138 | irq_state = false; |
| 136 | 139 | apu_irq_state = false; |
| r21986 | r21987 | |
| 406 | 409 | while(icount > 0) { |
| 407 | 410 | if(inst_state < 0x100) { |
| 408 | 411 | PPC = NPC; |
| 409 | | inst_state = IR; |
| 412 | inst_state = IR | inst_state_base; |
| 410 | 413 | if(machine().debug_flags & DEBUG_FLAG_ENABLED) |
| 411 | 414 | debugger_instruction_hook(this, NPC); |
| 412 | 415 | } |
| r21986 | r21987 | |
| 479 | 482 | |
| 480 | 483 | offs_t m6502_device::disassemble_generic(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options, const disasm_entry *table) |
| 481 | 484 | { |
| 482 | | const disasm_entry &e = table[oprom[0]]; |
| 485 | const disasm_entry &e = table[oprom[0] | inst_state_base]; |
| 483 | 486 | UINT32 flags = e.flags | DASMFLAG_SUPPORTED; |
| 484 | 487 | buffer += sprintf(buffer, "%s", e.opcode); |
| 485 | 488 | |
trunk/src/emu/cpu/m6502/m6502make.py
| r21986 | r21987 | |
| 7 | 7 | import sys |
| 8 | 8 | import logging |
| 9 | 9 | |
| 10 | | MAX_STATES = 0x101 |
| 10 | MAX_STATES = 0 |
| 11 | 11 | |
| 12 | 12 | def load_opcodes(fname): |
| 13 | 13 | """Load opcodes from .lst file""" |
| r21986 | r21987 | |
| 174 | 174 | """ |
| 175 | 175 | |
| 176 | 176 | DISASM_PROLOG="""\ |
| 177 | | const %(device)s::disasm_entry %(device)s::disasm_entries[0x100] = { |
| 177 | const %(device)s::disasm_entry %(device)s::disasm_entries[0x%(disasm_count)x] = { |
| 178 | 178 | """ |
| 179 | 179 | |
| 180 | 180 | DISASM_EPILOG="""\ |
| r21986 | r21987 | |
| 182 | 182 | """ |
| 183 | 183 | |
| 184 | 184 | def save_tables(f, device, states): |
| 185 | total_states = len(states) |
| 186 | |
| 185 | 187 | d = { "device": device, |
| 188 | "disasm_count": total_states-1 |
| 186 | 189 | } |
| 187 | | |
| 188 | | assert len(states) == MAX_STATES |
| 189 | | |
| 190 | |
| 191 | |
| 190 | 192 | emit(f, DO_EXEC_FULL_PROLOG % d) |
| 191 | 193 | for n, state in enumerate(states): |
| 192 | 194 | if state == ".": continue |
| 193 | | if n < MAX_STATES - 1: |
| 195 | if n < total_states - 1: |
| 194 | 196 | emit(f, "\tcase 0x%02x: %s_full(); break;\n" % (n, state)) |
| 195 | 197 | else: |
| 196 | 198 | emit(f, "\tcase %s: %s_full(); break;\n" % ("STATE_RESET", state)) |
| r21986 | r21987 | |
| 199 | 201 | emit(f, DO_EXEC_PARTIAL_PROLOG % d) |
| 200 | 202 | for n, state in enumerate(states): |
| 201 | 203 | if state == ".": continue |
| 202 | | if n < MAX_STATES - 1: |
| 204 | if n < total_states - 1: |
| 203 | 205 | emit(f, "\tcase 0x%02x: %s_partial(); break;\n" % (n, state)) |
| 204 | 206 | else: |
| 205 | 207 | emit(f, "\tcase %s: %s_partial(); break;\n" % ("STATE_RESET", state)) |
| 206 | 208 | emit(f, DO_EXEC_PARTIAL_EPILOG % d) |
| 207 | 209 | |
| 208 | | emit(f, DISASM_PROLOG % d) |
| 210 | emit(f, DISASM_PROLOG % d ) |
| 209 | 211 | for n, state in enumerate(states): |
| 210 | 212 | if state == ".": continue |
| 211 | | if n == MAX_STATES - 1: break |
| 213 | if n == total_states - 1: break |
| 212 | 214 | tokens = state.split("_") |
| 213 | 215 | opc = tokens[0] |
| 214 | 216 | mode = tokens[-1] |
| r21986 | r21987 | |
| 262 | 264 | |
| 263 | 265 | states = load_disp(argv[3]) |
| 264 | 266 | logging.info("loaded %s states", len(states)) |
| 265 | | assert len(states) == MAX_STATES |
| 266 | 267 | |
| 268 | assert (len(states) & 0xff) == 1 |
| 267 | 269 | save(argv[4], device_name, opcodes, states) |
| 268 | 270 | |
| 269 | 271 | |
trunk/docs/m6502.txt
| r21986 | r21987 | |
| 252 | 252 | instruction in the middle. This is done through a two-level state |
| 253 | 253 | machine with updates only at the boundaries. More precisely, |
| 254 | 254 | inst_state tells you which main state you're in. It's equal to the |
| 255 | | opcode byte when 0-255, and 256 means reset. It's always valid and |
| 255 | opcode byte when 0-255, and 0xff00 means reset. It's always valid and |
| 256 | 256 | used by instructions like rmb. inst_substate indicates at which step |
| 257 | 257 | we are in an instruction, but it set only when an instruction has been |
| 258 | 258 | interrupted. Let's go back to the asl <abs> code: |
| r21986 | r21987 | |
| 458 | 458 | state goes further than the scheduling slice of the cpu. That should |
| 459 | 459 | not usually be the case, so the cost should be minimal. |
| 460 | 460 | |
| 461 | | 10. Current TODO |
| 461 | 10. Multi-dispatch variants |
| 462 | 462 | |
| 463 | Some variants currently in the process of being supported change |
| 464 | instruction set depending on an internal flag, either switching to a |
| 465 | 16-bits mode or changing some register accesses to memory accesses. |
| 466 | This is handled by having multiple dispatch tables for the cpu, the |
| 467 | d<cpu>.lst not being 257 entries anymore but 256*n+1. The variable |
| 468 | inst_state_base must select which instruction table to use at a given |
| 469 | time. It must be a multiple of 256, and is in fact simply or-ed to |
| 470 | the first instruction byte to get the dispatch table index (aka |
| 471 | inst_state). |
| 472 | |
| 473 | 11. Current TODO |
| 474 | |
| 463 | 475 | - Implement the bus contention/wait states stuff, but that requires |
| 464 | 476 | support on the memory map side first. |
| 465 | 477 | |