All pastes #744012 Raw Edit

n6502.asm

public text v1 · immutable
·published 2007-10-21 00:12 UTC
rendered paste body
;n6502 cpu emulator
;copyright 1997 Bloodlust Software
;free for public use

;MSVC equ 1

                .386
      locals
      .model flat,C

      .data

     PUBLIC ncpu

F_CARRY = 01h
F_ZERO  = 02h
F_INT   = 04h
F_DEC   = 08h
F_BREAK = 10h
F_RSRVD = 20h
F_OVER  = 40h
F_SIGN  = 80h


;------------------------------------
;degenerate flagtable

i=0
flagtable label dword
rept 100h
  db (i AND F_ZERO) XOR F_ZERO
  db ((i AND F_OVER) SHR 6)
  db (i AND F_CARRY)
  db (i AND F_SIGN)
 i=i+1
endm


;------------------------------------
;cpu struc
n6502cpu struc
        rA  db ?
        rS  db ?
        rX  db ?
        rY  db ?

        rF  db ?  ;flags
        rPC dw ?  ;PC
 trapbadops db ?

      db ?
      db ?
 degenflags LABEL DWORD
  zero    db  ? ;degenerate flags
  over    db  ?

  carry   db  ? ;(keep zero & sign in diff dwords)
  sign    db  ?
      db ?
      db ?

 cycles      dd ?
 totalcycles dd ?

 PCBASE dd ?
 ROM    dd   ?  ;pointer to ROM at 8000-FFFF
 RAM    dd   ? ;pointer to RAM at 0-7FF

 readtrap  dd ?
 writetrap dd ?

 breakpoint dd ?

   ends


;main cpu
align
ncpu n6502cpu ?


      .code

       PUBLIC n6502_execute
       PUBLIC n6502_int,n6502_nmi

;------------------------------------
;fetch macros

fetchbyte macro reg
     mov     reg,byte ptr [esi]
     inc  esi
     endm

fetchbytesx macro reg
     movsx   reg,byte ptr [esi]
     inc  esi
     endm

fetchbytezx macro reg
     movzx   reg,byte ptr [esi]
     inc  esi
     endm

fetchword macro reg
     mov     reg,word ptr [esi]
     add  esi,2
     endm

npushb macro reg
   mov [ebp+edx+100h],reg
   dec dl
  endm

npopb macro reg
   inc dl
   mov reg,[ebp+edx+100h]
  endm


;-----------------------------
; PC nat/denat
; these must be customized

;converts 16-bit PC to a 32-bit base+PC in ESI
naturalizeESI proc
   cmp esi,8000h ;upper rom?
   jb  @@NOTROM
   mov [ncpu.PCBASE],edi
   add esi,edi
   ret

@@NOTROM:
   cmp esi,2000h ;mirrored ram?
   jae @@NOTRAM
   and esi,7FFh  ;mirror lower 2k
@@NOTRAM:
   mov [ncpu.PCBASE],ebp
   add esi,ebp
   ret
  endp

;converts 32-bit base+PC to 16-bit PC
denaturalizeESI macro
   sub esi,[ncpu.PCBASE]
  endm


;--------------------------------
; read/write memory functions
; these must be customized

readbyte proc
   cmp edx,8000h
   jb  @@NOTROM
   mov al,[edi+edx]
   ret
@@NOTROM:
   cmp edx,2000h ;mirrored ram?
   jae @@NOTRAM
   and edx,7FFh  ;mirror lower 2k
   mov al,[ebp+edx]
   ret

@@NOTRAM:
   push ebx
   push ecx
   push edx
   push esi
   push edi
  ifdef MSVC
   mov ecx,edx
  else
   mov eax,edx
  endif

   call [ncpu.readtrap]
   pop  edi
   pop  esi
   pop  edx
   pop  ecx
   pop  ebx
   and  eax,0FFh
   ret
        endp

writebyte proc
   cmp edx,2000h
   jae @@NOTRAM
   and edx,7FFh  ;mirror lower 2k
   mov [ebp+edx],al
   ret

@@NOTRAM:
   push ebx
   push ecx
   push edx
   push esi
   push edi

  ifdef MSVC
   mov ecx,eax
  endif

   call [ncpu.writetrap]
   pop  edi
   pop  esi

   test eax,eax
   jz   @@NOBANK
   denaturalizeESI    ;reset ESI
   mov  edi,[ncpu.ROM]
   call naturalizeESI
@@NOBANK:

   pop  edx
   pop  ecx
   pop  ebx
   xor  eax,eax
   ret
  endp




;----------------------------
; flag store macros

;saves zero,sign flags
savef macro reg
   mov [ncpu.zero],reg
   mov [ncpu.sign],reg
  endm

;saves zero,sign,carry flags
savefc macro reg
   setc [ncpu.carry]
   mov [ncpu.zero],reg
   mov [ncpu.sign],reg
  endm

;saves zero,sign,overflow flags
savefo macro reg
   seto [ncpu.over]
   mov [ncpu.zero],reg
   mov [ncpu.sign],reg
  endm

;saves zero,sign,carry,overflow flags
savefco macro reg
   setc [ncpu.carry]
   seto [ncpu.over]
   mov [ncpu.zero],reg
   mov [ncpu.sign],reg
  endm

;gets carry flag (Assumes ah=0)
getc macro
     cmp ah,[ncpu.carry]
    endm


;-------------------------------------
; flag conversion macros

;al -> lastval,carry,over
degenerateflags macro
   mov [ncpu.rF],al ;store full flags
   mov eax,[flagtable+eax*4]
   mov dword ptr [ncpu.degenflags],eax
   xor eax,eax
  endm

;lastval,carry,over -> al
generateflags macro
   mov al,[ncpu.rF] ;al=RSRVD|DEC|INT|BREAK
   push edx

   and al,3Ch
   mov dl,[ncpu.over]

   cmp   ah,[ncpu.zero]
   jne  @@NOTZERO
   or   al,F_ZERO  ;set zero flag
@@NOTZERO:

   mov  ah,[ncpu.sign]
   and  dl,1

   shl  dl,6
   and  ah,F_SIGN

   or   al,[ncpu.carry]  ;carry=bit 0
   or   dl,ah

   or   al,dl            ;over=bit 7
   pop  edx

   xor ah,ah
  endm


;-------------------
; execute function

n6502_execute proc
      push ebp
      push esi
      push edi
      push ebx

      xor   eax,eax
      xor   esi,esi
      mov   edi,[ncpu.ROM]
      mov   ebp,[ncpu.RAM]
      mov   bx,word ptr [ncpu.rA]
      mov   cx,word ptr [ncpu.rX]
      mov   si,[ncpu.rPC]

      mov   al,[ncpu.rF] ;get flags
      degenerateflags

      call  naturalizeESI

      xor   edx,edx
      xor   eax,eax

executeloop:
      sub   [ncpu.cycles],eax ;3
      jle   done

      mov   al,[esi]          ;1
      inc   esi

      xor   edx,edx  ;agi

      jmp   [n6502jmptable+eax*4] ;5


;      mov   edx,[ncpu.cycles] ;1
;      sub   edx,eax          ;1
;      mov   al,[esi]
;      mov   [ncpu.cycles],edx ;1
;      jle   done
;      xor   edx,edx           ;1
;      inc   esi
;      jmp  [n6502jmptable+eax*4] ;5


badopcode:
      mov   eax,4               ;nop cycles
      cmp   [ncpu.trapbadops],0 ;continue anyway?
      jne   executeloop

      dec   esi ;decrease PC ;abort
      mov   eax,-1
      jmp   short leave

done: xor   eax,eax

leave:
      sub   esi,[ncpu.PCBASE]
      mov   word ptr [ncpu.rA],bx
      mov   word ptr [ncpu.rX],cx
      mov   [ncpu.rPC],si ;store PC

      push eax
      xor  eax,eax
      generateflags    ;set flags
      mov  [ncpu.rF],al
      pop  eax

      pop ebx
      pop edi
      pop esi
      pop ebp
      ret
     endp


;-----------------------------------
; interrupts


n6502_nmi proc
   push ebp
   push edx
   push edi

   xor edx,edx
   xor eax,eax

   mov ebp,[ncpu.RAM]
   mov edi,[ncpu.ROM]

   mov ax,[ncpu.rPC] ;get pc
   mov dl,[ncpu.rS] ;get stack

   ;push pc
   npushb ah
   npushb al

   ;push flags
   mov al,[ncpu.rF]
   and al,NOT F_BREAK ;remove break flag ?
   npushb al

   ;store S
   mov [ncpu.rS],dl

   ;turn on interrupt flag
   or  al,F_INT
   mov [ncpu.rF],al

   ;PC=NMI vector
   mov ax,[edi+0FFFAh]
   mov [ncpu.rPC],ax

   pop edi
   pop edx
   pop ebp
   ret
  endp



n6502_int proc
   test [ncpu.rF],F_INT
   jnz  @@DONE

   push ebp
   push edx
   push edi

   xor edx,edx
   xor eax,eax

   mov ebp,[ncpu.RAM]
   mov edi,[ncpu.RAM]
   mov dl,[ncpu.rS] ;get stack
   mov ax,[ncpu.rPC] ;get pc

   ;push pc
   npushb ah
   npushb al

   ;push flags
   mov al,[ncpu.rF]
   and al,NOT F_BREAK ;remove break flag ?
   npushb al

   ;store S
   mov [ncpu.rS],dl

   or  al,F_INT ;turn on interrupt flag
   mov [ncpu.rF],al

   ;PC=INT vector
   mov edi,[ncpu.ROM]
   mov ax,[edi+0FFFEh]
   mov [ncpu.rPC],ax

   pop edi
   pop edx
   pop ebp
@@DONE:
   ret
  endp







;--------------------------------------
; opcode header/footer macros

opbegin macro O
  align
  op&O proc
 endm


opend macro C
   mov al,C ;store cycles
   jmp executeloop
  endp
 endm

opendzx macro C
   mov eax,C ;store cycles
   jmp executeloop
  endp
 endm

;---------------------------

nX equ cl
nY equ ch
nA equ bl
nS equ bh


;---------------------------------
; lea macros

;$XX
lea_zero macro
    fetchbyte dl
        endm

;$XX,x
lea_zeroX   macro
    fetchbyte dl
    add dl,nX
        endm

;$XX,y
lea_zeroY   macro
    fetchbyte dl
    add dl,nY
        endm

;$XXXX
lea_abs macro
    fetchword dx
        endm

;$XXXX,x
lea_absX   macro
    fetchword dx
    add  dl,nX
    adc  dh,ah ;ah=0
        endm

;$XXXX,y
lea_absY   macro
    fetchword dx
    add  dl,nY
    adc  dh,ah ;ah=0
        endm


;($XX,x)
lea_indX   macro
    fetchbyte dl
    add dl,nX
    mov dx,[ebp+edx]
        endm

;($XX),y
lea_indY   macro
    fetchbyte dl
    mov  dx,[ebp+edx]
    add  dl,nY
    adc  dh,ah  ;ah=0
        endm


;--------------------------------------
; read macros


;$XX
Rzero macro
    lea_zero
    mov al,[ebp+edx]
   endm

;$XX,x
RzeroX  macro
    lea_zeroX
    mov al,[ebp+edx]
   endm

;$XX,y
RzeroY   macro
    lea_zeroY
    mov al,[ebp+edx]
   endm

;$XXXX
Rabs macro
    lea_abs
    call readbyte
   endm

;$XXXX,x
RabsX   macro
    lea_absX
    call readbyte
   endm

;$XXXX,y
RabsY   macro
    lea_absY
    call readbyte
   endm


;($XX,x)
RindX   macro
    lea_indX
    call readbyte
   endm

;($XX),y
RindY   macro
    lea_indY
    call readbyte
   endm


;#$XX
Rimmb macro
    fetchbyte al
   endm



;-------------------------------------------
; write macros

;$XX
Wzero macro
    mov [ebp+edx],al
   endm

;$XX,x
WzeroX  macro
    mov [ebp+edx],al
   endm

;$XX,y
WzeroY   macro
    mov [ebp+edx],al
   endm

;$XXXX
Wabs macro
    call writebyte
   endm

;$XXXX,x
WabsX   macro
    call writebyte
   endm

;$XXXX,y
WabsY   macro
    call writebyte
   endm

;($XX,x)
WindX   macro
    call writebyte
   endm

;($XX),y
WindY   macro
    call writebyte
   endm


;------------------------------------
;opcodes

;NOP
opbegin %0EAh
opend 2


;----------------
; bit/logic/arithmetic ops


;nA=nA+al+carry (decimal)
DECADC proc
   getc
   adc al,nA
   daa         ;cheap, probably incorrect
   savefco al
   mov nA,al
  opend 4

;nA=nA-al+carry (decimal)
DECSBC proc
   getc
   cmc
   sbb nA,al
   mov al,nA
   das         ;cheap, probably incorrect
   cmc
   savefco al
   mov nA,al
  opend 4

ADC_op macro amode,op,cy
  opbegin op
   R&amode
   test [ncpu.rF],F_DEC
   jnz  DECADC
   getc
   adc nA,al
   savefco nA
  opend cy
 endm

SBC_op macro amode,op,cy
  local carry
  opbegin op
   R&amode
   test [ncpu.rF],F_DEC
   jnz  DECSBC
   xor  al,0FFh
   getc
   adc nA,al
   savefco nA
  opend cy
 endm

ADC_op  immb,%69h,2
ADC_op  zero,%65h,3
ADC_op zeroX,%75h,4
ADC_op   abs,%6Dh,4
ADC_op  absX,%7Dh,4
ADC_op  absY,%79h,4
ADC_op  indX,%61h,6
ADC_op  indY,%71h,5

SBC_op  immb,%0E9h,2
SBC_op  zero,%0E5h,2
SBC_op zeroX,%0F5h,4
SBC_op   abs,%0EDh,4
SBC_op  absX,%0FDh,4
SBC_op  absY,%0F9h,4
SBC_op  indX,%0E1h,6
SBC_op  indY,%0F1h,5


LOG_op  macro operator,amode,op,cy
  opbegin op
    R&amode
    operator nA,al
    savef nA
  opend cy
 ENDM

;AND
LOG_op and, immb,%29h,2
LOG_op and, zero,%25h,3
LOG_op and,zeroX,%35h,4
LOG_op and,  abs,%2Dh,4
LOG_op and, absX,%3Dh,4
LOG_op and, absY,%39h,4
LOG_op and, indX,%21h,6
LOG_op and, indY,%31h,5

;OR
LOG_op  or, immb,%09h,2
LOG_op  or, zero,%05h,3
LOG_op  or,zeroX,%15h,4
LOG_op  or,  abs,%0Dh,4
LOG_op  or, absX,%1Dh,4
LOG_op  or, absY,%19h,4
LOG_op  or, indX,%01h,6
LOG_op  or, indY,%11h,5

;EOR
LOG_op xor, immb,%49h,2
LOG_op xor, zero,%45h,3
LOG_op xor,zeroX,%55h,4
LOG_op xor,  abs,%4Dh,4
LOG_op xor, absX,%5Dh,4
LOG_op xor, absY,%59h,4
LOG_op xor, indX,%41h,6
LOG_op xor, indY,%51h,5



BIT_op  macro amode,op,cy
  opbegin op
    R&amode
    mov   dl,al

    shr   al,6
    mov   [ncpu.sign],dl ;sign=mem

    and   dl,nA     ;acc & mem
    and   al,1      ;isolate bit 40h

    mov   [ncpu.zero],dl ;set zero
    mov   [ncpu.over],al
  opend cy
 ENDM

;BIT
BIT_op   zero,%24h,3
BIT_op    abs,%2Ch,4


;------------
;load/store


LDx_OP  macro reg,amode,op,cy
  opbegin op
    R&amode
    mov reg,al
    savef al
  opend cy
 ENDM

;LDA a
LDx_OP nA, immb,%0A9h,2
LDx_OP nA, zero,%0A5h,3
LDx_OP nA,zeroX,%0B5h,4
LDx_OP nA,  abs,%0ADh,4
LDx_OP nA, absX,%0BDh,4
LDx_OP nA, absY,%0B9h,4
LDx_OP nA, indX,%0A1h,6
LDx_OP nA, indY,%0B1h,5

;LDX a
LDx_OP nX, immb,%0A2h,2
LDx_OP nX, zero,%0A6h,3
LDx_OP nX,zeroY,%0B6h,4
LDx_OP nX,  abs,%0AEh,4
LDx_OP nX, absY,%0BEh,4

;LDY a
LDx_OP nY, immb,%0A0h,2
LDx_OP nY, zero,%0A4h,3
LDx_OP nY,zeroX,%0B4h,4
LDx_OP nY,  abs,%0ACh,4
LDx_OP nY, absX,%0BCh,4


STx_OP  macro reg,amode,op,cy
  opbegin op
    lea_&amode
    mov  al,reg
    W&amode
  opend cy
 ENDM


;STA a
STx_OP nA, zero,%085h,3
STx_OP nA,zeroX,%095h,4
STx_OP nA,  abs,%08Dh,4
STx_OP nA, absX,%09Dh,5
STx_OP nA, absY,%099h,5
STx_OP nA, indX,%081h,6
STx_OP nA, indY,%091h,6

;STX a
STx_OP nX, zero,%086h,3
STx_OP nX,zeroY,%096h,4
STx_OP nX, abs ,%08Eh,4

;STY a
STx_OP nY, zero,%084h,3
STx_OP nY,zeroX,%094h,4
STx_OP nY, abs ,%08Ch,4



;--------------------------------
; compare


CMP_op  macro reg,amode,op,cy
  opbegin op
    R&amode
    mov ah,reg
    sub ah,al
    setnc [ncpu.carry]
    mov  [ncpu.sign],ah
    mov  [ncpu.zero],ah
  opendzx cy
 ENDM


;CMP a
CMP_op nA, immb,%0C9h,2
CMP_op nA, zero,%0C5h,3
CMP_op nA,zeroX,%0D5h,4
CMP_op nA,  abs,%0CDh,4
CMP_op nA, absX,%0DDh,4
CMP_op nA, absY,%0D9h,4
CMP_op nA, indX,%0C1h,6
CMP_op nA, indY,%0D1h,5


;CPX a
CMP_op nX, immb,%0E0h,2
CMP_op nX, zero,%0E4h,3
CMP_op nX,  abs,%0ECh,4

;CPY a
CMP_op nY, immb,%0C0h,2
CMP_op nY, zero,%0C4h,3
CMP_op nY,  abs,%0CCh,4



;-------------------------------
;INC/DEC

;INX
opbegin %0E8h
   inc nX
   savef nX
opend 2

;INY
opbegin %0C8h
   inc nY
   savef nY
opend 2


;DEX
opbegin %0CAh
   dec nX
   savef nX
opend 2

;DEY
opbegin %088h
   dec nY
   savef nY
opend 2


INC_op  macro amode,op,cy
  opbegin op
    R&amode
    inc  al
    savef al
    W&amode
  opend cy
 ENDM

DEC_op  macro amode,op,cy
  opbegin op
    R&amode
    dec  al
    savef al
    W&amode
  opend cy
 ENDM

INC_op  zero ,%0E6h,5
INC_op  zeroX,%0F6h,6
INC_op   abs ,%0EEh,6
INC_op   absX,%0FEh,7

DEC_op  zero ,%0C6h,5
DEC_op  zeroX,%0D6h,6
DEC_op   abs ,%0CEh,6
DEC_op   absX,%0DEh,7


;----------------
; shift


;ASLA
opbegin %0Ah
  shl nA,1
  savefc nA
opend 2

;LSRA
opbegin %4Ah
  shr nA,1
  savefc nA
opend 2

;ROLA
opbegin %2Ah
  getc
  rcl nA,1
  savefc nA
opend 2

;RORA
opbegin %6Ah
  getc
  rcr nA,1
  savefc nA
opend 2


ASL_op macro amode,op,cy
  opbegin op
    R&amode
    shl    al,1
    savefc al
    W&amode
  opend cy
 ENDM

LSR_op macro amode,op,cy
  opbegin op
    R&amode
    shr    al,1
    savefc al
    W&amode
  opend cy
 ENDM


ROL_op macro amode,op,cy
  opbegin op
    R&amode
    getc
    rcl    al,1
    savefc al
    W&amode
  opend cy
 ENDM

ROR_op macro amode,op,cy
  opbegin op
    R&amode
    getc
    rcr    al,1
    savefc al
    W&amode
  opend cy
 ENDM

ASL_op   zero,%006h,5
ASL_op  zeroX,%016h,6
ASL_op    abs,%00Eh,6
ASL_op   absX,%01Eh,7

LSR_op   zero,%046h,5
LSR_op  zeroX,%056h,6
LSR_op    abs,%04Eh,6
LSR_op   absX,%05Eh,7

ROL_op   zero,%026h,5
ROL_op  zeroX,%036h,6
ROL_op    abs,%02Eh,6
ROL_op   absX,%03Eh,7

ROR_op   zero,%066h,5
ROR_op  zeroX,%076h,6
ROR_op    abs,%06Eh,6
ROR_op   absX,%07Eh,7



;----------
;flag

;CLC
opbegin %018h
  mov [ncpu.carry],dl ;dl=0
opend 2

;CLD
opbegin %0D8h
  and [ncpu.rF],NOT F_DEC
opend 2

;CLI
opbegin %058h
  and [ncpu.rF],NOT F_INT
opend 2

;CLV
opbegin %0B8h
  mov [ncpu.over],dl
opend 2

;SEC
opbegin %038h
  mov [ncpu.carry],01h
opend 2

;SED
opbegin %0F8h
  or [ncpu.rF],F_DEC
opend 2

;SEI
opbegin %078h
  or [ncpu.rF],F_INT
opend 2


;---------------
; Txx

;TAX
opbegin %0AAh
   mov nX,nA
   savef nA
opend 2

;TXA
opbegin %08Ah
   mov nA,nX
   savef nX
opend 2

;TAY
opbegin %0A8h
   mov nY,nA
   savef nA
opend 2

;TYA
opbegin %098h
   mov nA,nY
   savef nY
opend 2

;TSX
opbegin %0BAh
   mov nX,nS
   savef nS
opend 2

;TXS
opbegin %09Ah
   mov nS,nX
opend 2



;-----------------
; branch

;execute branch
quickbranch:
  fetchbytesx edx
  mov al,4        ;4 cycles for branch taken  (should check page)
  add esi,edx
  jmp executeloop

dobranch:
  mov al,[esi]
  inc esi

  sub esi,[ncpu.PCBASE]
  test al,al

  mov edx,esi
  jl  brbackward

  ;forward branch
brforward:
  add dl,al ;add branch
  jnc short donebranch
  inc dh
  mov esi,edx
  mov al,4   ;4 cycles
;  call naturalizeESI
  add esi,[ncpu.PCBASE]
  jmp executeloop

  ;backward branch
brbackward:
  add dl,al ;add branch
  jc  short donebranch
  dec dh
  mov esi,edx
  mov al,4   ;4 cycles
;  call naturalizeESI
  add esi,[ncpu.PCBASE]
  jmp executeloop

  ;no page crossing
donebranch:
  mov esi,edx
  mov al,3    ;3 cycles
;  call naturalizeESI
  add esi,[ncpu.PCBASE]
  jmp executeloop




;BPL rel
opbegin %010h
  mov  dl,[ncpu.sign]

  test dl,dl
  jns dobranch
  inc esi
opend 2

;BMI rel
opbegin %030h
  mov  dl,[ncpu.sign]

  test dl,dl
  js  dobranch
  inc esi
opend 2

;BVC rel
opbegin %050h
  cmp dl,[ncpu.over]
  je  dobranch
  inc esi
opend 2

;BVS rel
opbegin %070h
  cmp dl,[ncpu.over]
  jne  dobranch
  inc esi
opend 2


;BCC rel
opbegin %090h
  cmp dl,[ncpu.carry]
  je  dobranch
  inc esi
opend 2

;BCS rel
opbegin %0B0h
  cmp dl,[ncpu.carry]
  jne  dobranch
  inc esi
opend 2


;BNE rel
opbegin %0D0h
  cmp dl,[ncpu.zero]
  jne dobranch
  inc esi
opend 2


;BEQ rel
opbegin %0F0h
  cmp dl,[ncpu.zero]
  je  dobranch
  inc esi
opend 2


;---------------
;jump


;JMP $XXXX
opbegin %04Ch
   movzx esi,word ptr [esi]
   call naturalizeESI
opend 3


;JMP ($XXXX)
opbegin %06Ch
   push ebx
   mov  dx,word ptr [esi] ;get addr of address
   xor  ebx,ebx

   call readbyte
   mov  bl,al

   inc  dl

   call readbyte
   mov  bh,al

   mov  esi,ebx
   pop  ebx
   call naturalizeESI
opend   5

;JSR $XXXX
opbegin %20h
   mov   eax,esi  ;get 32-bit PC
   xor   esi,esi

   mov   dl,nS    ;get SP
   mov   si,[eax] ;get new PC

   sub   eax,[ncpu.PCBASE] ;get 16-bit PC
   call  naturalizeESI ;set new 32-bit PC

   inc ax            ;increase old PC
   npushb ah
   npushb al

   mov nS,dl         ;set SP
opendzx 6


;RTS
opbegin %60h
  mov dl,nS ;get SP

  ;pop PC
  npopb al
  npopb ah

  ;store SP inc PC
  mov nS,dl
  inc ax

  ;set new PC
  mov  esi,eax
  call naturalizeESI
opendzx 6


;RTI
opbegin %40h
  mov dl,nS ;get SP

  ;pop flags
  npopb al
  or  al,F_RSRVD
  degenerateflags

  ;pop PC
  npopb al
  npopb ah

  ;store SP
  mov nS,dl

  ;set new PC
  mov  esi,eax
  call naturalizeESI
opendzx 6



;-------------------
; stack


;PHA
opbegin %48h
  mov dl,nS
  dec nS
  mov [ebp+edx+100h],nA
opend 3

;PHP
opbegin %08h
  mov dl,nS
  dec nS
  generateflags
  mov [ebp+edx+100h],al
opend 3

;PLA
opbegin %68h
  inc nS
  mov dl,nS
  mov nA,[ebp+edx+100h]
  savef nA
opend 4

;PLP
opbegin %28h
  inc nS
  mov dl,nS
  mov al,[ebp+edx+100h]
  or  al,F_RSRVD
  degenerateflags
opend 4


;---------------------------
; BRK


opbegin %00h
   denaturalizeESI
   mov eax,esi ;get pc

   mov dl,nS   ;get stack
   inc ax

   ;push pc
   npushb ah
   npushb al

   ;push flags
   mov al,[ncpu.rF]
   or  al,F_BREAK ;set break flag ?
   npushb al

   ;store S
   mov nS,dl

   ;adjust flags
   or  al,F_INT ;turn on interrupt
   xor esi,esi
   mov [ncpu.rF],al

   ;PC=BRK vector
   mov si,word ptr [edi+0FFFEh]
   call naturalizeESI
opendzx 7



;--------------------------------------
        .data

   ;jump table
makeopcode macro X
 ifdef op&X
  dd offset op&X
 else
  dd offset badopcode
 endif
endm

n6502jmptable label dword
i=0
rept 256
  makeopcode %i
  i=i+1
endm

      end