mmap trick works

execution stages

Operand Fetch not needed for write-only ops
Operand Store not needed for read-only ops

Immediate

Opcode Fetch
Operand Fetch
Execute


Zero Page

Opcode Fetch
Address Fetch
Operand Load
Execute
Operand Store


Zero Page, X(Y)

Opcode Fetch
Address Fetch
X(Y) add  (8-bit)
Operand Load
Execute
Operand Store


Absolute
Opcode Fetch
Address L Fetch
Address H Fetch
Operand Load
Execute
Operand Store


Absolute, X/Y

Opcode Fetch
Address L Fetch
Address H Fetch
X(Y) Add (8-bit)
If add carries, inc internal address reg, 1-cycle extra to inc Address H
Operand Load
Execute
Operand Store


Indirect, X

Opcode Fetch
Address L Fetch
Address H Fetch
X Add (8-bit)
Address L Load
Address H Load
Operand Load
Execute
Operand Store


Indirect, Y

Opcode Fetch
Address L Fetch (Address H zeroed)
Address L Load
Address H Load
Y Add (8-bit)
If add carries, inc Address H (1-cycle delay)
Operand Load
Execute
Operand Store


Implied/Accumulator

Opcode Fetch
Execute


Indirect

Opcode Fetch
Address L Fetch
Address H Fetch
PC L Load
PC H Load


Relative

Opcode Fetch
Address L Fetch
Condition Check
If (Condition)
Operand Fetch
PC Add (8-bit)
If (carry)
inc PC High


Fetch

if !(PC & 0xE000)
  PC &= 0x7FF
mov tmp, [PC]


Load

if !(PC & 0xE000)
  PC &= 0x7FF
  mov tmp, [PC]
if (PC < 0x6000)
  mov tmp, Read_Register(PC)
mov tmp, [PC]


Store

if !(PC & 0xE000)
  PC &= 0x7FF
  mov [PC], tmp
if (PC < 0x6000)
  mov tmp, Read_Register(PC)
mov [PC], tmp

format of context block

10000h A
10001h X
10002h Y
10003h P
10004h S
10005h PC
10007h/TOS tmpflag (Format V_BDI___)

Register assignment


AL - A
AH - P
BL - tmp
BH - tmp
CL - X
CH - Y
DL - tmp
DH - tmp
ESI - PC
EDI - temp
EBP - cycle counter


(Ind, X) wraps around zero page
(Ind), Y may not


6502 flags
SV_BDIZC

x86 flags
V___SZ_____C


opcodes
decrementing ebp (cycle count) has to be the last thing 
before the jmp end_table, to preserve flags for cycle timeout

PACK_FLAGS
takes 0 arguments, tmpflag in bh, x86 format in ah
exits with bh = 1, dl = 6502 format flags

_PUSH
take 1 arg, stack pointer in edi
xchg ebx, edi
mov  [ebx], arg
dec  bl
xchg ebx, edi

_POP
same as _PUSH, with the mov inverted

_FETCHB
takes 1 arg, must be 8 bit reg
mov  arg, [esi]
inc  esi

_FETCHBX
takes 1 arg, must be 32 bit reg
movzx arg, byte [esi]
inc  esi

_FETCHW
takes 1 arg, must be 32 bit reg
movzx arg, word [esi]
add   esi, 2

_ZPREADB
takes 8-bit reg arg
mov   arg, [edi]

_READB
call
returns byte in dl, reads from edi

_WRITEB
call
writes byte in dl to edi

AM_IMM
mov  edi, esi

AM_ZP
_FETCHBX(edi)

AM_ZPX
_FETCHB(dl)
add dl, ch
movzx edi, dl

AM_ZPY
_FETCHB(dl)
add dl, cl
movzx edi, dl

AM_ABS
_FETCHW(edi)

AM_ASBX  -- base opcode time in edi -- ends with actual time in dh, addr in edi
_FETCHW(edx)
add  dl, ch
setc bh
add  dh, bh
xchg edx, edi
add  dl, bh
xchg dl, dh
mov  bh, 1

AM_ABSY  -- base opcode time in edi -- ends with actual time in dh, addr in edi
_FETCHW(edx)
add  dl, cl
setc bh
add  dh, bh
xchg edx, edi
add  dl, bh
xchg dl, dh
mov  bh, 1

AM_ASBX_FIXED -- fixed time
_FETCHW(edx)
add  dl, ch
adc  dh, 0
xchg edx, edi

AM_ABSY_FIXED -- fixed time
_FETCHW(edx)
add  dl, cl
adc  dh, 0
xchg edx, edi

AM_REL -- base opcode time in edi -- ends with page adjusted time in dh
FIXME

AM_INDX
_FETCHBX(edx)
xchg ebx, edi
add  dl, ch
mov  bl, [edx]
inc  dl
mov  bh, [edx]
xchg ebx, edi

AM_INDY -- base opcode time in bh -- ends with actual time in dh, addr in edi
_FETCHBX(edx)
xchg ebx, edi
mov  bl, [edx]
inc  dl
mov  bh, [edx]
add  bl, cl
setc dl
add  bh, dl
xchg ebx, edi
add  bh, dl
mov  dh, 1
xchg bh, dh

AM_IND
_FETCHW(edx)
xchg ebx, edi
mov  bl, [edx]
inc  dl
mov  bh, [edx]
xchg ebx, edi