;
;	fram65ca.s
;
;	P/ECE MOS6502 Emulator (高速版)
;
;	CLiP - Common Library for P/ECE
;	Copyright (C) 2001-2005 Naoyuki Sawa
;
;	* Fri Jan 28 03:55:00 JST 2005 Naoyuki Sawa
;	- 作成開始。
;	* Mon Mar 07 02:08:00 JST 2005 Naoyuki Sawa
;	- WAI=1の状態でm6502cpu_runが呼ばれたときに、m6502cpu.cycle=0で終了するよう修正。
;	  これまでは、m6502cpu.cycleを変化せずに終了してしまっていたために、
;	  Cycleの端数を次回のm6502cpu_runへ繰り延べるような処理に不具合が生じていました。
;	* Wed Mar 17 06:43:00 JST 2005 Naoyuki Sawa
;	- CMP,CPX,CPY命令ルーチンの最後の"ld.ub %NZ,%NZ"を遅延スロットへ移動しました。
;	  (ld.ubが遅延可能な命令であることが判明したため)
;	* Thu Mar 17 18:45:00 JST 2005 Naoyuki Sawa
;	- m6502cpu_runにトレースデバッグ用ブロックを追加しました。
;	  トレースデバッグを行うときは、M6502CPU_RUN_TRACEシンボルを定義してください。
;	* Fri Mar 18 07:27:00 JST 2005 Naoyuki Sawa
;	- AddressMode関数にて、ZeroPage内のWraparoundに対応しました。
;	- AddressMode関数にて、    64KB内のWraparoundに対応しました。
;	* Wed Mar 23 06:04:00 JST 2005 Naoyuki Sawa
;	- m6502cpu_pack中のext命令を、pp33のビットフィールド取得演算子を使って、判り易く書き直しました。
;	  ソースコードが判り易くなっただけで、生成バイナリには変化ありません。
;	  展開結果が変更前と同じであることを、変更前と変更後のfram65ca.msを比較して確認しました。
;	* Wed Apr 13 06:48:00 JST 2005 Naoyuki Sawa
;	- CMP Immediate のサイクル数を [誤]3cycle→[正]2cycle に修正しました。
;
;#include "clip65ca.h"
;
;	clip65ca.h
;
;	P/ECE MOS6502 Emulator (高速版)
;
;	CLiP - Common Library for P/ECE
;	Copyright (C) 2001-2005 Naoyuki Sawa
;
;	* Fri Jan 28 03:55:00 JST 2005 Naoyuki Sawa
;	- 作成開始。
;	* Sat Apr 09 16:38:00 JST 2005 Naoyuki Sawa
;	- レジスタ割り当てを変更しました。
;

; clip65ca.s、fram65ca.sにインクルードして使います。

;****************************************************************************
;	M6502CPU構造体
;****************************************************************************

				; typedef struct _M6502CPU {
;#define CA		 0	; unsigned short ca;	/* + 0,2 -------C AAAAAAAA */
;#define _NZ_		 2	; unsigned short nz;	/* + 2,2 N------- NZZZZZZZ */
;#define BDI		 4	; unsigned char bdi;	/* + 4,1          001BDI00 */
;#define V		 5	; unsigned char v;	/* + 5,1          V------- */
;#define _X_		 6	; unsigned char x;	/* + 6,1          XXXXXXXX */
;#define _Y_		 7	; unsigned char y;	/* + 7,1          YYYYYYYY */
;#define _PC_		 8	; unsigned char* pc;	/* + 8,4 &mem[PC]          */
;#define _SP_		12	; unsigned char sp;	/* +12,1          SPSPSPSP */
				; //			/* +13,3 (パディング)      */
;#define FLAGS		16	; int flags;		/* +16,4          ------IW */
;#define _CYCLE_		20	; int cycle;		/* +20,4 残りCycle         */
;#define READ		24	; void* read;		/* +24,4 メモリ読み出しルーチン */
;#define WRITE		28	; void* write;		/* +28,4 メモリ書き込みルーチン */
;#define SIZEOF_M6502CPU	32	; } M6502CPU;		/* =32   */

;****************************************************************************
;	レジスタ割り当て
;****************************************************************************

;#define addr	r0	; 現在の命令のアドレスモードを解決したアドレスを保持します。
			; AddressModeルーチンが初期化し、Actionルーチンが参照します。
			; Operationルーチン、その他のサブルーチンからは使用不可です。
;#define data	r1	; 現在の命令へ渡すデータ、命令からの戻りデータを保持します。
			; メモリ読み込みを行う命令の場合、Actionルーチンが初期化し、Operationルーチンが使用します。
			; メモリ書き込みを行う命令の場合、Operationルーチンが初期化し、Actionルーチンが使用します。
			; その他の場合、汎用ワークレジスタとして使用可能です。
;#define ptbl	r2	; 現在の命令に対応するm6502tblエントリ内の走査ポインタです。
			; m6502cpu_runが初期化し、m6502cpu_runとActionルーチンが使用します。
			; AddressModeルーチン、Operationルーチン、その他のサブルーチンからは使用不可です。
;#define TBL	r3	; m6502tblの先頭アドレスを保持します。
			; m6502cpu_enter〜m6502cpu_leaveの間、不変です。
;#define A	r4	; Aレジスタの値を保持します。D31:8は常に0とします。
			; Operationルーチンが使用します。
			; m6502cpu_run、Actionルーチン、AddressModeルーチン、その他のサブルーチンからは使用不可です。
;#define X	r5	; Xレジスタの値を保持します。D31:8は常に0とします。
			; Operationルーチンが使用します。
			; m6502cpu_run、Actionルーチン、AddressModeルーチン、その他のサブルーチンからは使用不可です。
;#define Y	r6	; Yレジスタの値を保持します。D31:8は常に0とします。
			; Operationルーチンが使用します。
			; m6502cpu_run、Actionルーチン、AddressModeルーチン、その他のサブルーチンからは使用不可です。
;#define NZ	r7	; PSR(N,Z)を表す2バイト値を保持します。詳しくは、M6502CPU構造体のコメントを参照してください。
			; Operationルーチンが使用します。
			; m6502cpu_run、Actionルーチン、AddressModeルーチン、その他のサブルーチンからは使用不可です。
;		r8	; 
;		r9	; 
;#define PC	r10	; &m6502mem[PC]を保持します。
			; 任意のルーチンが、Jump、Callなどの処理にて、適切に設定します。
;#define SP	r11	; SPレジスタの値を保持します。D31:8は常に0とします。
			; 任意のルーチンが、Push、Pull、Callなどの処理にて、適切に設定します。
;#define t0	r12	; 汎用ワークレジスタです。
;#define t1	r13	; 汎用ワークレジスタです。
;#define CPU	r14	; m6502cpuの先頭アドレスを保持します。
			; m6502cpu_enter〜m6502cpu_leaveの間、不変です。
;#define CYCLE	r15	; 残り実行サイクル数を保持します。
			; 任意のルーチンが、適切に残りサイクル数を減らします。

;****************************************************************************
;	
;****************************************************************************

	.code
	.align 1

;****************************************************************************
;	
;****************************************************************************

; 実行コンテキストを取り出します。
;
; [in]
;	ありません。
;
; [out]
;	規定のレジスタを設定します。
;
; [use]
;	規定のレジスタを設定すること以外は、全レジスタを保存します。
;
; [note]
;	* 実行コンテキスト外からのみ呼び出し可能です。
;	  このルーチンを呼び出すと、実行コンテキスト内に入ります。
;
	.global	m6502cpu_enter
m6502cpu_enter:
	ext	m6502tbl+0x3@h	; 	xld.w	%r3  , m6502tbl+0x3		; 書き戻し不要
	ext	m6502tbl+0x3@m
	ld.w	%r3,m6502tbl+0x3@l
	ext	m6502cpu+0x0@h	; 	xld.w	%r14  , m6502cpu		; 書き戻し不要
	ext	m6502cpu+0x0@m
	ld.w	%r14,m6502cpu+0x0@l
	ld.ub	%r4,[%r14]	; 	xld.ub	%r4    , [%r14+0x0   ]
	ext	0x6		; 	xld.ub	%r5    , [%r14+0x6    ]
	ld.ub	%r5,[%r14]
	ext	0x7		; 	xld.ub	%r6    , [%r14+0x7    ]
	ld.ub	%r6,[%r14]
	ext	0x2		; 	xld.uh	%r7   , [%r14+0x2   ]
	ld.uh	%r7,[%r14]
	ext	0x8		; 	xld.w	%r10   , [%r14+0x8   ]
	ld.w	%r10,[%r14]
	ext	0xc		; 	xld.ub	%r11   , [%r14+0xc   ]
	ld.ub	%r11,[%r14]
	ext	0x14		; 	xld.w	%r15, [%r14+0x14]
	ld.w	%r15,[%r14]
	ret

; 実行コンテキストを書き戻します。
;
; [in]
;	規定のレジスタが設定されていること。
;
; [out]
;	ありません。
;
; [use]
;	全レジスタを保存します。
;
; [note]
;	* 実行コンテキスト内からのみ呼び出し可能です。
;	  このルーチンを呼び出すと、実行コンテキストを抜けます。
;
	.global	m6502cpu_leave
m6502cpu_leave:
	ld.b	[%r14],%r4	; 	xld.b	[%r14+0x0   ], %r4
	ext	0x6		; 	xld.b	[%r14+0x6    ], %r5
	ld.b	[%r14],%r5
	ext	0x7		; 	xld.b	[%r14+0x7    ], %r6
	ld.b	[%r14],%r6
	ext	0x2		; 	xld.h	[%r14+0x2   ], %r7
	ld.h	[%r14],%r7
	ext	0x8		; 	xld.w	[%r14+0x8   ], %r10
	ld.w	[%r14],%r10
	ext	0xc		; 	xld.b	[%r14+0xc   ], %r11
	ld.b	[%r14],%r11
	ext	0x14		; 	xld.w	[%r14+0x14], %r15
	ld.w	[%r14],%r15
	ret

;****************************************************************************
;	
;****************************************************************************

; 単純なメモリ読み出しルーチンです。
;
; [in]
;	%addr		読み出すアドレス。
;
; [out]
;	%data		読み出したデータ。
;
; [use]
;	戻り値以外は、全レジスタを保存します。
;
; [note]
;	* 実行コンテキスト内からのみ呼び出し可能です。
;	  実行コンテキスト外から呼び出すことはできません。
;
;	* m6502cpu_reset()にて、メモリ読み出しルーチンが指定されなかった場合は、
;	  このルーチンを利用します。
;
	.global	m6502mem_read
m6502mem_read:
	ext	m6502mem@ah
	ext	m6502mem@al
	ld.ub	%r1, [%r0]
	ret

; 単純なメモリ書き込みルーチンです。
;
; [in]
;	%addr		読み出すアドレス。
;	%data		書き込むデータ。
;
; [out]
;	ありません。
;
; [use]
;	全レジスタを保存します。
;
; [note]
;	* 実行コンテキスト内からのみ呼び出し可能です。
;	  実行コンテキスト外から呼び出すことはできません。
;
;	* m6502cpu_reset()にて、メモリ書き込みルーチンが指定されなかった場合は、
;	  このルーチンを利用します。
;
	.global	m6502mem_write
m6502mem_write:
	ext	m6502mem@ah
	ext	m6502mem@al
	ld.b	[%r0], %r1
	ret

;****************************************************************************
;	
;****************************************************************************

; PSRをパックします。
;
; [in,out]
;	m6502cpu.ca --------+
;	m6502cpu.bdi --++++ |
;	m6502cpu.v ---+|||| |
;	              ||||| |
;	             NV1BDIZC --> %data
;	              |     |
;	%NZ ----------+-----+
;
; [use]
;	%dataに戻り値を設定すること以外は、全レジスタを保存します。
;
; [note]
;	* 実行コンテキスト内からのみ呼び出し可能です。
;	  実行コンテキスト外から呼び出すことはできません。
;
	.global	m6502cpu_pack
m6502cpu_pack:
	ext	0x4		; 	xld.ub	%r1, [%r14+0x4]		; %data |= 001BDI00
	ld.ub	%r1,[%r14]
	;
	ext	0x5		; 	xbtst	[%r14+0x5], 0x7			; %data |= 0V000000
	btst	[%r14],0x7
	jreq	3
	;ext	1<<(6-6)			; (skip?)
	;or	%data, 0			; (skip?)
	;↓* Wed Mar 23 06:04:00 JST 2005 Naoyuki Sawa
	;↓- m6502cpu_pack中のext命令を、pp33のビットフィールド取得演算子を使って、判り易く書き直しました。
	;↓  ソースコードが判り易くなっただけで、生成バイナリには変化ありません。
	;↓  展開結果が変更前と同じであることを、変更前と変更後のfram65ca.msを比較して確認しました。
	ext	       0x1			; (skip?)
	or	%r1, 0x0			; (skip?)
	;
	ext	0x1		; 	xbtst	[%r14+0x1], 0x0			; %data |= 0000000C
	btst	[%r14],0x0
	jreq	2
	or	%r1, 0x1			; (skip?)
	;
	ext	0x4		; 	xand	%r9, %r7, 0x8080		; %data |= N0000000
	ext	0x80
	and	%r9,%r7
	jreq	3
	;ext	1<<(7-6)			; (skip?)
	;or	%data, 0			; (skip?)
	;↓* Wed Mar 23 06:04:00 JST 2005 Naoyuki Sawa
	;↓- m6502cpu_pack中のext命令を、pp33のビットフィールド取得演算子を使って、判り易く書き直しました。
	;↓  ソースコードが判り易くなっただけで、生成バイナリには変化ありません。
	;↓  展開結果が変更前と同じであることを、変更前と変更後のfram65ca.msを比較して確認しました。
	ext	       0x2			; (skip?)
	or	%r1, 0x0			; (skip?)
	;
	ext	0xff		; 	xand	%r9, %r7, 0xff			; %data |= 000000Z0
	and	%r9,%r7
	jrne	2
	or	%r1, 0x2			; (skip?)
	;
	ret

; PSRをアンパックします。
;
; [in,out]
;	          +--------> m6502cpu.v
;	          |++++----> m6502cpu.bdi
;	          ||||| +--> m6502cpu.ca
;	          |1||| |
;	data --> NV-BDIZC
;	         |     |
;	         +-----+---> %NZ
;
; [use]
;	%NZに戻り値を設定すること以外は、全レジスタを保存します。
;
; [note]
;	* 実行コンテキスト内からのみ呼び出し可能です。
;	  実行コンテキスト外から呼び出すことはできません。
;
	.global	m6502cpu_unpack
m6502cpu_unpack:
	ext	0x1c		; 	xand	%r9, %r1, 0x1c		; BDI = 001BDI00
	and	%r9,%r1
	add	%r9,0x20	; 	xadd	%r9, %r9, 0x20			;         +------ 必ず1に!
	ext	0x4		; 	xld.b	[%r14+0x4], %r9
	ld.b	[%r14],%r9
	;
	ext	0x40		; 	xand	%r9, %r1, 0x40		; V   = V0000000
	and	%r9,%r1
	sll	%r9,0x1		; 	xsll	%r9, 1
	ext	0x5		; 	xld.b	[%r14+0x5], %r9
	ld.b	[%r14],%r9
	;
	ext	0x1		; 	xand	%r9, %r1, 0x1		; C   = 0000000C
	and	%r9,%r1
	ext	0x1		; 	xld.b	[%r14+0x1], %r9
	ld.b	[%r14],%r9
	;
	ext	0x80		; 	xand	%r7, %r1, 0x80		; %NZ = N0000000 00000000
	and	%r7,%r1
	sll	%r7,0x8		; 	xsll	%r7, 8
	;
	ext	0x2		; 	xand	%r9, %r1, 0x2		; %NZ = N0000000 00000010 (Z=0)
	and	%r9,%r1
	xor	%r9,0x2		; 	xxor	%r9, %r9,   0x2		;       N0000000 00000000 (Z=1)
	ret.d
	or	%r7, %r9			; *delay*

;****************************************************************************
;	
;****************************************************************************

; * スタック領域($100-$1FF)はすべてメインメモリと仮定して、高速化してあります。
;   Push/PullでI/Oアクセスを行うようなプログラムは、正しく動作しません。

; * スタック領域内のWraparoundに依存するプログラムは無いと仮定して、高速化してあります。
;   もしもスタック領域内のWraparoundに依存するプログラムがあったならば、変更が必要です。
;   ↓(2005/03/12追記)
;   SPのWraparoundに対応しました。
;   ファミコン用ゲームでは、SPのWraparoundに依存するソフトはほとんどありませんが、
;   ATARI VCS用ゲームの多くが、初期化時にSPのWraparoundに依存しているため、必要です。

; 1バイト値をスタックに積みます。
;
; [in]
;	%data[7:0]	スタックに積む値。
;			%data[31:8]は不定で構いません。
;
; [use]
;	%SPが適切に変化すること以外は、全レジスタを保存します。
;
; [note]
;	* 実行コンテキスト内からのみ呼び出し可能です。
;	  実行コンテキスト外から呼び出すことはできません。
;
;	* PCをスタックに積む手順は、次のようになります。
;
;	m6502cpu_CALL:
;		ld.w	%t0, [%ptbl]+		; %t0 = AddressMode
;		call	%t0			; %addr = AddressMode()
;		;
;		ext	m6502mem+1@ah		; %data = PC-1 (仕様)
;		ext	m6502mem+1@al
;		sub	%data, %PC
;		xcall.d	m6502cpu_push		; Push HI(PC-1)
;		rr	%data, 8		; *delay*
;		xcall.d	m6502cpu_push		; Push LO(PC-1)
;		rl	%data, 8		; *delay*
;		;
;		ext	m6502mem@ah		; %PC = &mem[addr]
;		ext	m6502mem@al
;		add	%PC, %addr
;		ret
;
	.global	m6502cpu_push
m6502cpu_push:
	ext	m6502mem+0x100@ah		; %r9 = &mem[$100|SP]
	ext	m6502mem+0x100@al
	add	%r9, %r11
	ld.b	[%r9], %r1			; mem[$100|SP] = data
	sub	%r11,0x1	; 	xsub	%r11, %r11, 1			; %SP = SP-1
	ret.d
	ld.ub	%r11, %r11			; Wraparound *delay*

; 1バイト値をスタックから取り出します。
;
; [out]
;	%data[7:0]	スタックから取り出した値。
;			%data[31:8]は必ず0になります。
;
; [use]
;	%SPが適切に変化すること以外は、全レジスタを保存します。
;
; [note]
;	* 実行コンテキスト内からのみ呼び出し可能です。
;	  実行コンテキスト外から呼び出すことはできません。
;
;	* PCをスタックから取り出す手順は、次のようになります。
;
;	m6502cpu_RTS:
;		xcall	m6502cpu_pull		; Pull LO(PC-1)
;		xcall.d	m6502cpu_pull		; Pull HI(PC-1)
;		ld.w	%PC, %data		; *delay*
;		xsll	%data, 8		; %PC = PC-1 (仕様)
;		or	%PC, %data
;		;
;		ext	m6502mem+1@ah		; %PC = &mem[PC]
;		ext	m6502mem+1@al
;		add	%PC, %PC
;		ret
;
	.global	m6502cpu_pull
m6502cpu_pull:
	add	%r11,0x1	; 	xadd	%r11, %r11, 1			; %SP = SP+1
	ld.ub	%r11, %r11			; Wraparound
	ext	m6502mem+0x100@ah		; %r9 = &mem[$100|SP+1]
	ext	m6502mem+0x100@al
	add	%r9, %r11
	ld.ub	%r1, [%r9]
	ret

;****************************************************************************
;	
;****************************************************************************

	.global	m6502cpu_run
m6502cpu_run:
	pushn	%r3
	;
	ext	m6502cpu+0x14@ah	; 	xld.w	[m6502cpu+0x14], %r12	; 必要!!
	ext	m6502cpu+0x14@al
	ld.w	[%r8],%r12
	call	m6502cpu_enter	; 	xcall	m6502cpu_enter			; 実行コンテキストを取り出します。
	;
	ext	0x10		; 	xbtst	[%r14+0x10], 0x0			; 既にWAI中ならば、残り実行サイクル数を0にして、
	btst	[%r14],0x0
	jreq	2				;  すぐにループを抜けます。(m6502cpu.cycle=0で終了。)
	ld.w	%r15, 0			; (skip?)
	;
	jp	m6502cpu_run_LOOP	; 	xjp	m6502cpu_run_LOOP		; Cycle=0が指定された場合のために、まず条件判定から。
m6502cpu_run_DO:
;----------------------------------------------------------------------------
;/#define M6502CPU_RUN_TRACE
;#ifdef M6502CPU_RUN_TRACE
;	; トレースデバッグを行う場合は、このブロックを有効にしてください。
;	; その際、m6502cpu_trace()は、アプリケーションにて定義してください。
;	; m6502cpu_trace()は、ライブラリ内では定義していません。
;	xcall  m6502cpu_leave
;	xcall  m6502cpu_trace
;	xcall  m6502cpu_enter
;#endif /*M6502CPU_RUN_TRACE*/
;----------------------------------------------------------------------------
	ld.ub	%r2, [%r10]+			; %ptbl = OpCode
	sll	%r2,0x4		; 	xsll	%r2, 4			; %ptbl = &(tbl+3)[OpCode<<4]
	add	%r2, %r3
	ld.ub	%r12, [%r2]+			; %t0 = 消費Cycle
	ld.w	%r13, [%r2]+			; %t1 = Action or Operation
	call.d	%r13
	sub	%r15, %r12			; Cycle - 消費Cycle *delay*
m6502cpu_run_LOOP:
	cmp	%r15,0x0	; 	xcmp	%r15, 0			; Cycleが0以下になるまで繰り返します。
	jrgt	m6502cpu_run_DO	; 	xjrgt	m6502cpu_run_DO
	;
	call	m6502cpu_leave	; 	xcall	m6502cpu_leave			; 実行コンテキストを書き戻します。
	;
	popn	%r3
	ret

;****************************************************************************
;	Action
;****************************************************************************

m6502cpu_ACCUMULATOR:
	ld.w	%r12, [%r2]			; %t0 = Operation
	call.d	%r12				; %data = Operation(data)
	ld.w	%r1, %r4			; %data = A *delay*
	ret.d
	ld.w	%r4, %r1			; %A = data *delay*

m6502cpu_IMMEDIATE:
	ld.w	%r12, [%r2]			; %t0 = Operation
	ld.ub	%r1, [%r10]+			; %data = imm
	jp	%r12				; Operation(data)

m6502cpu_READ:
	ld.w	%r12, [%r2]+			; %t0 = AddressMode
	call	%r12				; %addr = AddressMode()
	ext	0x18		; 	xld.w	%r12, [%r14+0x18]		; %data = Read(addr)
	ld.w	%r12,[%r14]
	call	%r12
	ld.w	%r12, [%r2]			; %t0 = Operation
	jp	%r12				; Operation(data)

m6502cpu_WRITE:
	ld.w	%r12, [%r2]+			; %t0 = AddressMode
	call	%r12				; %addr = AddressMode()
	ld.w	%r12, [%r2]			; %t0 = Operation
	call	%r12				; %data = Operation(data)
	ext	0x1c		; 	xld.w	%r12, [%r14+0x1c]		; Write(addr, data)
	ld.w	%r12,[%r14]
	jp	%r12

m6502cpu_READ_WRITE:
	ld.w	%r12, [%r2]+			; %t0 = AddressMode
	call	%r12				; %addr = AddressMode()
	ext	0x18		; 	xld.w	%r12, [%r14+0x18]		; %data = Read(addr)
	ld.w	%r12,[%r14]
	call	%r12
	ld.w	%r12, [%r2]			; %t0 = Operation
	call	%r12				; %data = Operation(data)
	ext	0x1c		; 	xld.w	%r12, [%r14+0x1c]		; Write(addr, data)
	ld.w	%r12,[%r14]
	jp	%r12

m6502cpu_BRANCH_EQ:
	ld.w	%r12, [%r2]			; %t0 = Operation
	call	%r12				; Condition check
	ld.b	%r13, [%r10]+			; %t1 = rel
	jrne	3				; if(!ne) {
	add	%r10, %r13			;   PC += rel (skip?)
	sub	%r15, 1			;   Cycle--   (skip?)
	ret					; }

m6502cpu_BRANCH_NE:
	ld.w	%r12, [%r2]			; %t0 = Operation
	call	%r12				; Condition check
	ld.b	%r13, [%r10]+			; %t1 = rel
	jreq	3				; if(!eq) {
	add	%r10, %r13			;   PC += rel (skip?)
	sub	%r15, 1			;   Cycle--   (skip?)
	ret					; }

m6502cpu_JUMP:
	ld.w	%r12, [%r2]			; %t0 = AddressMode
	call	%r12				; %addr = AddressMode()
	ext	m6502mem@ah			; %PC = &mem[addr]
	ext	m6502mem@al
	add	%r10, %r0
	ret

m6502cpu_CALL:
	ld.w	%r12, [%r2]			; %t0 = AddressMode
	call	%r12				; %addr = AddressMode()
	;
	ext	m6502mem+0x1@ah			; %data = PC-1 (仕様)
	ext	m6502mem+0x1@al
	sub	%r1, %r10
	call.d	m6502cpu_push	; 	xcall.d	m6502cpu_push			; Push HI(PC-1)
	rr	%r1, 8			; *delay*
	call.d	m6502cpu_push	; 	xcall.d	m6502cpu_push			; Push LO(PC-1)
	rl	%r1, 8			; *delay*
	;
	ext	m6502mem@ah			; %PC = &mem[addr]
	ext	m6502mem@al
	add	%r10, %r0
	ret

;****************************************************************************
;	AddressMode
;****************************************************************************

; * アドレッシングのアクセスはすべてメインメモリと仮定して、高速化してあります。
;   アドレッシングでI/Oアクセスを行うようなプログラムは、正しく動作しません。
;
; * ZeroPage内のWraparoundに依存するプログラムは無いと仮定して、高速化してあります。
;   もしもZeroPage内のWraparoundに依存するプログラムがあったならば、変更が必要です。
;   たとえばZeropage,XのWraparoundにきちんと対応するには、次のような変更が必要です。
;
;	m6502cpu_ZEROPAGE_X:
;		ld.ub	%addr, [%PC]+		; %addr = ZeroPage
;		add	%addr, %X		; %addr = ZeroPage+X
;		ld.ub	%addr, %addr		; Wraparound
;		ret
;
;   ↓(2005/03/18 追記)
;   ATARI VCS用Space InvadersがZeroPage内のWraparoundを使っているため、対応しました。
;   上述の変更例は"ld.ub"が遅延可能であることを発見する前に書いたものであり、
;   実際には、"ld.ub"を遅延スロットに入れる形で変更しました。
;   なお、本エミュレーションモジュールを使っていた既存のプログラムも、少し遅くなります。
;
; * 64KB内のWraparoundに依存するプログラムは無いと仮定して、高速化してあります。
;   もしも64KB内のWraparoundに依存するプログラムがあったならば、変更が必要です。
;   たとえばAbsolute,XのWraparoundにきちんと対応するには、次のような変更が必要です。
;
;	m6502cpu_ABSOLUTE_X:
;		ld.ub	%addr, [%PC]+		; %addr = LO(Absolute)
;		ld.ub	%t0, [%PC]+		; %t0   = HI(Absolute)
;		xsll	%t0, 8			; %addr = Absolute
;		or	%addr, %t0
;		add	%addr, %X		; %addr = Absolute+X
;		ld.uh	%addr, %addr		; Wraparound
;		ret
;
;   ↓(2005/03/18 追記)
;   ZeroPage内のWraparoundに対応したこと併せて、64KB内のWraparoundにも対応しました。
;   64KB内のWraparoundを使っているプログラムはまだ見つけていませんが、念のため、です。
;   上述の変更例は"ld.uh"が遅延可能であることを発見する前に書いたものであり、
;   実際には、"ld.uh"を遅延スロットに入れる形で変更しました。
;   なお、本エミュレーションモジュールを使っていた既存のプログラムも、少し遅くなります。
;

m6502cpu_ZEROPAGE:
	ld.ub	%r0, [%r10]+			; %addr = ZeroPage
	ret

m6502cpu_ZEROPAGE_X:
	ld.ub	%r0, [%r10]+			; %addr = ZeroPage
	add	%r0, %r5			; %addr = ZeroPage+X
	ret.d
	ld.ub	%r0, %r0			; Wraparound *delay*

m6502cpu_ZEROPAGE_Y:
	ld.ub	%r0, [%r10]+			; %addr = ZeroPage
	add	%r0, %r6			; %addr = ZeroPage+Y
	ret.d
	ld.ub	%r0, %r0			; Wraparound *delay*

m6502cpu_ABSOLUTE:
	ld.ub	%r0, [%r10]+			; %addr = LO(Absolute)
	ld.ub	%r12,   [%r10]+			; %t0   = HI(Absolute)
	sll	%r12,0x8	; 	xsll	%r12, 8				; %addr = Absolute
	ret.d
	or	%r0, %r12			; *delay*

m6502cpu_ABSOLUTE_X:
	ld.ub	%r0, [%r10]+			; %addr = LO(Absolute)
	ld.ub	%r12, [%r10]+			; %t0   = HI(Absolute)
	sll	%r12,0x8	; 	xsll	%r12, 8				; %addr = Absolute
	or	%r0, %r12
	add	%r0, %r5			; %addr = Absolute+X
	ret.d
	ld.uh	%r0, %r0			; Wraparound *delay*

m6502cpu_ABSOLUTE_Y:
	ld.ub	%r0, [%r10]+			; %addr = LO(Absolute)
	ld.ub	%r12, [%r10]+			; %t0   = HI(Absolute)
	sll	%r12,0x8	; 	xsll	%r12, 8				; %addr = Absolute
	or	%r0, %r12
	add	%r0, %r6			; %addr = Absolute+Y
	ret.d
	ld.uh	%r0, %r0			; Wraparound *delay*

m6502cpu_INDIRECT:
	ld.ub	%r0, [%r10]+			; %addr = LO(Absolute)
	ld.ub	%r12,   [%r10]+			; %t0   = HI(Absolute)
	sll	%r12,0x8	; 	xsll	%r12, 8				; %addr = Absolute
	or	%r0, %r12
	ext	m6502mem@ah			; %t1   = &mem[addr]
	ext	m6502mem@al
	add	%r13, %r0
	ld.ub	%r0, [%r13]+			; %addr = LO(Indirect)
	ld.ub	%r12,   [%r13]			; %t0   = HI(Indirect)
	sll	%r12,0x8	; 	xsll	%r12, 8				; %addr = Indirect
	ret.d
	or	%r0, %r12			; *delay*

m6502cpu_INDIRECT_X:
	ld.ub	%r0, [%r10]+			; %addr = ZeroPage
	add	%r0, %r5			; %addr = ZeroPage+X
	ld.ub	%r0, %r0			; Wraparound
	ext	m6502mem@ah			; %t1   = &mem[addr]
	ext	m6502mem@al
	add	%r13, %r0
	ld.ub	%r0, [%r13]+			; %addr = LO(Indirect)
	ld.ub	%r12,   [%r13]			; %t0   = HI(Indirect)
	sll	%r12,0x8	; 	xsll	%r12, 8				; %addr = Indirect
	ret.d
	or	%r0, %r12			; *delay*

m6502cpu_INDIRECT_Y:
	ld.ub	%r0, [%r10]+			; %addr = ZeroPage
	ext	m6502mem@ah			; %t1   = &mem[addr]
	ext	m6502mem@al
	add	%r13, %r0
	ld.ub	%r0, [%r13]+			; %addr = LO(Indirect)
	ld.ub	%r12,   [%r13]			; %t0   = HI(Indirect)
	sll	%r12,0x8	; 	xsll	%r12, 8				; %addr = Indirect
	or	%r0, %r12
	add	%r0, %r6			; %addr = Indirect+Y
	ret.d
	ld.uh	%r0, %r0			; Wraparound *delay*

;****************************************************************************
;	Operation
;****************************************************************************

m6502cpu_LDA:
	ld.w	%r4, %r1
	ret.d
	ld.w	%r7, %r4				; *delay*

m6502cpu_LDX:
	ld.w	%r5, %r1
	ret.d
	ld.w	%r7, %r5				; *delay*

m6502cpu_LDY:
	ld.w	%r6, %r1
	ret.d
	ld.w	%r7, %r6				; *delay*

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

m6502cpu_STA:
	ret.d
	ld.w	%r1, %r4			; *delay*

m6502cpu_STX:
	ret.d
	ld.w	%r1, %r5			; *delay*

m6502cpu_STY:
	ret.d
	ld.w	%r1, %r6			; *delay*

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

m6502cpu_TXA:
	ld.w	%r4, %r5
	ret.d
	ld.w	%r7, %r4				; *delay*

m6502cpu_TYA:
	ld.w	%r4, %r6
	ret.d
	ld.w	%r7, %r4				; *delay*

m6502cpu_TAX:
	ld.w	%r5, %r4
	ret.d
	ld.w	%r7, %r5				; *delay*

m6502cpu_TAY:
	ld.w	%r6, %r4
	ret.d
	ld.w	%r7, %r6				; *delay*

m6502cpu_TSX:
	ld.w	%r5, %r11
	ret.d
	ld.w	%r7, %r5				; *delay*

m6502cpu_TXS:
	ret.d
	ld.w	%r11, %r5				; *delay*
	; no PSR affected

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

m6502cpu_PHA:
	ext	m6502cpu_push@rm	; 	xjp.d	m6502cpu_push			; Push A
	jp.d	m6502cpu_push@rl
	ld.w	%r1, %r4			; *delay*

m6502cpu_PHP:
	ext	m6502cpu_pack@rm	; 	xcall	m6502cpu_pack			; Push PSR
	call	m6502cpu_pack@rl
	ext	m6502cpu_push@rm	; 	xjp	m6502cpu_push
	jp	m6502cpu_push@rl

m6502cpu_PLA:
	ext	m6502cpu_pull@rm	; 	xcall	m6502cpu_pull			; Pull A
	call	m6502cpu_pull@rl
	ld.w	%r4, %r1
	ret.d
	ld.w	%r7, %r4				; *delay*

m6502cpu_PLP:
	ext	m6502cpu_pull@rm	; 	xcall	m6502cpu_pull			; Pull PSR
	call	m6502cpu_pull@rl
	ext	m6502cpu_unpack@rm	; 	xcall	m6502cpu_unpack
	call	m6502cpu_unpack@rl
	ext	m6502cpu_check_pending@rm	; 	xjp	m6502cpu_check_pending		; 保留IRQ要求を調べます。
	jp	m6502cpu_check_pending@rl

;****************************************************************************
;	Operation
;****************************************************************************

m6502cpu_ADC:
	ext	0x4		; 	xbtst	[%r14+0x4], 0x3
	btst	[%r14],0x3
	jrne	m6502cpu_ADCD	; 	xjrne	m6502cpu_ADCD
	;
	ld.w	%r12, %r4				; %t0 = A+data+C
	ext	0x1		; 	xbtst	[%r14+0x1], 0x0
	btst	[%r14],0x0
	jreq.d	3
	add	%r12, %r1			; *delay*
	add	%r12, 1				; (skip?)
	;
	ld.h	[%r14],%r12	; 	xld.h	[%r14+0x0], %r12			; C = (A+data+C)[8]
	;
	xor	%r1, %r4			; %data =  (A^data)
	not	%r1, %r1			; %data = ~(A^data)
	xor	%r4, %r12				; %A    =           (A^(A+data+C))
	and	%r1, %r4			; %data = ~(A^data)&(A^(A+data+C))
	ext	0x5		; 	xld.b	[%r14+0x5], %r1			; V     = ~(A^data)&(A^(A+data+C))[7]
	ld.b	[%r14],%r1
	;
	ld.ub	%r4, %r12				; %A = A+data+C (unsigned)
	ret.d
	ld.w	%r7, %r4				; *delay*

m6502cpu_ADCD:
	ext	m6502cpu_leave@rm	; 	xcall	m6502cpu_leave
	call	m6502cpu_leave@rl
	ext	m6502cpu_adcd@rm	; 	xcall.d	m6502cpu_adcd
	call.d	m6502cpu_adcd@rl
	ld.w	%r12, %r1			; *delay*
	ext	m6502cpu_enter@rm	; 	xjp	m6502cpu_enter
	jp	m6502cpu_enter@rl

m6502cpu_SBC:
	ext	0x4		; 	xbtst	[%r14+0x4], 0x3
	btst	[%r14],0x3
	jrne	m6502cpu_SBCD	; 	xjrne	m6502cpu_SBCD
	;
	ld.w	%r12, %r4				; %t0 = A-data-~C
	ext	0x1		; 	xbtst	[%r14+0x1], 0x0
	btst	[%r14],0x0
	jrne.d	3
	sub	%r12, %r1			; *delay*
	sub	%r12, 1				; (skip?)
	;
	not	%r13, %r12			; C = ~(A-data-~C)[8]
	ld.h	[%r14],%r13	; 	xld.h	[%r14+0x0], %r13
	;
	xor	%r1, %r4			; %data = (A^data)
	xor	%r4, %r12				; %A    =          (A^(A-data-~C))
	and	%r1, %r4			; %data = (A^data)&(A^(A-data-~C))
	ext	0x5		; 	xld.b	[%r14+0x5], %r1			; V     = (A^data)&(A^(A-data-~C))[7]
	ld.b	[%r14],%r1
	;
	ld.ub	%r4, %r12				; %A = A-data-~C (unsigned)
	ret.d
	ld.w	%r7, %r4				; *delay*

m6502cpu_SBCD:
	ext	m6502cpu_leave@rm	; 	xcall	m6502cpu_leave
	call	m6502cpu_leave@rl
	ext	m6502cpu_sbcd@rm	; 	xcall.d	m6502cpu_sbcd
	call.d	m6502cpu_sbcd@rl
	ld.w	%r12, %r1			; *delay*
	ext	m6502cpu_enter@rm	; 	xjp	m6502cpu_enter
	jp	m6502cpu_enter@rl

m6502cpu_CMP:
	ld.w	%r7, %r4				; %NZ = A-data
	sub	%r7, %r1
	not	%r12, %r7			; C = ~(A-data)[8]
	ld.h	[%r14],%r12	; 	xld.h	[%r14+0x0], %r12
	ret.d
	ld.ub	%r7, %r7			; 必要!! *delay*

m6502cpu_CPX:
	ld.w	%r7, %r5				; %NZ = X-data
	sub	%r7, %r1
	not	%r12, %r7			; C = ~(X-data)[8]
	ld.h	[%r14],%r12	; 	xld.h	[%r14+0x0], %r12
	ret.d
	ld.ub	%r7, %r7			; 必要!! *delay*

m6502cpu_CPY:
	ld.w	%r7, %r6				; %NZ = Y-data
	sub	%r7, %r1
	not	%r12, %r7			; C = ~(Y-data)[8]
	ld.h	[%r14],%r12	; 	xld.h	[%r14+0x0], %r12
	ret.d
	ld.ub	%r7, %r7			; 必要!! *delay*

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

m6502cpu_INC:
	add	%r1,0x1		; 	xadd	%r1, %r1, 1
	ld.ub	%r1, %r1			; 必要!!
	ret.d
	ld.w	%r7, %r1			; *delay*

m6502cpu_INX:
	add	%r5,0x1		; 	xadd	%r5, %r5, 1
	ld.ub	%r5, %r5				; 必要!!
	ret.d
	ld.w	%r7, %r5				; *delay*

m6502cpu_INY:
	add	%r6,0x1		; 	xadd	%r6, %r6, 1
	ld.ub	%r6, %r6				; 必要!!
	ret.d
	ld.w	%r7, %r6				; *delay*

m6502cpu_DEC:
	sub	%r1,0x1		; 	xsub	%r1, %r1, 1
	ld.ub	%r1, %r1			; 必要!!
	ret.d
	ld.w	%r7, %r1			; *delay*

m6502cpu_DEX:
	sub	%r5,0x1		; 	xsub	%r5, %r5, 1
	ld.ub	%r5, %r5				; 必要!!
	ret.d
	ld.w	%r7, %r5				; *delay*

m6502cpu_DEY:
	sub	%r6,0x1		; 	xsub	%r6, %r6, 1
	ld.ub	%r6, %r6				; 必要!!
	ret.d
	ld.w	%r7, %r6				; *delay*

;****************************************************************************
;	Operation
;****************************************************************************

m6502cpu_AND:
	and	%r4, %r1
	ret.d
	ld.w	%r7, %r4				; *delay*

m6502cpu_ORA:
	or	%r4, %r1
	ret.d
	ld.w	%r7, %r4				; *delay*

m6502cpu_EOR:
	xor	%r4, %r1
	ret.d
	ld.w	%r7, %r4				; *delay*

m6502cpu_ASL:
	sll	%r1,0x1		; 	xsll	%r1, 1			; %data = -------7 6543210-
	ld.h	[%r14],%r1	; 	xld.h	[%r14+0x0], %r1		;                +------------> C
	ld.ub	%r1, %r1			; %data = -------- 6543210-
	ret.d
	ld.w	%r7, %r1			; *delay*

m6502cpu_LSR:
	ext	0x1		; 	xld.b	[%r14+0x1], %r1		; %data = -------- 76543210 +-> C
	ld.b	[%r14],%r1
	srl	%r1,0x1		; 	xsrl	%r1, 1			; %data = -------- -7654321
	ret.d
	ld.w	%r7, %r1			; *delay *

m6502cpu_ROL:
	ext	0x1		; 	xld.ub	%r12, [%r14+0x1]		; %t0   = -------- -------C
	ld.ub	%r12,[%r14]
	and	%r12,0x1	; 	xand	%r12, %r12, 1
	sll	%r1,0x1		; 	xsll	%r1, 1			; %data = -------7 6543210-
	ld.h	[%r14],%r1	; 	xld.h	[%r14+0x0], %r1		;                +------------> C
	ld.ub	%r1, %r1			; %data = -------- 6543210-
	or	%r1, %r12			; %data = -------- 6543210C
	ret.d
	ld.w	%r7, %r1			; *delay*

m6502cpu_ROR:
	ext	0x1		; 	xld.ub	%r12, [%r14+0x1]		; %t0   = -------- -------C
	ld.ub	%r12,[%r14]
	and	%r12,0x1	; 	xand	%r12, %r12, 1
	sll	%r12,0x7	; 	xsll	%r12, 7				; %t0   = -------- C-------
	ext	0x1		; 	xld.b	[%r14+0x1], %r1		; %data = -------- 76543210 +-> C
	ld.b	[%r14],%r1
	srl	%r1,0x1		; 	xsrl	%r1, 1			; %data = -------- -7654321
	or	%r1, %r12			; %data = -------- C7654321
	ret.d
	ld.w	%r7, %r1

m6502cpu_BIT:
	ld.w	%r7, %r1			; V   =          V-------
	sll	%r7,0x1		; 	xsll	%r7, 1				;                +-------- (  data)[6]
	ext	0x5		; 	xld.b	[%r14+0x5], %r7			; %NZ = N------- NZZZZZZZ
	ld.b	[%r14],%r7
	sll	%r7,0x7		; 	xsll	%r7, 7				;       |        ++++++++- (A&data)
	and	%r1, %r4			;       |        +-------- (A&data)[7]
	ret.d					;       +----------------- (  data)[7]
	or	%r7, %r1			; *delay*

;****************************************************************************
;	Operation
;****************************************************************************

m6502cpu_BCC:
m6502cpu_BCS:
	ext	0x1		; 	xbtst	[%r14+0x1], 0x0
	btst	[%r14],0x0
	ret

m6502cpu_BNE:
m6502cpu_BEQ:
	ext	0xff		; 	xand	%r9, %r7, 0xff
	and	%r9,%r7
	ret

m6502cpu_BVC:
m6502cpu_BVS:
	ext	0x5		; 	xbtst	[%r14+0x5], 0x7
	btst	[%r14],0x7
	ret

m6502cpu_BPL:
m6502cpu_BMI:
	ext	0x4		; 	xand	%r9, %r7, 0x8080
	ext	0x80
	and	%r9,%r7
	ret

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

m6502cpu_BRK:
	ext	0x3ff		; 	xld.w	%r0, 0xfffe			; BRKを実行します。
	ld.w	%r0,0x3e
	ext	m6502cpu_interrupt@rm	; 	xjp.d	m6502cpu_interrupt
	jp.d	m6502cpu_interrupt@rl
	ld.w	%r1, 1			; *delay*

m6502cpu_RTS:
	ext	m6502cpu_pull@rm	; 	xcall	m6502cpu_pull			; Pull LO(PC-1)
	call	m6502cpu_pull@rl
	ext	m6502cpu_pull@rm	; 	xcall.d	m6502cpu_pull			; Pull HI(PC-1)
	call.d	m6502cpu_pull@rl
	ld.w	%r10, %r1			; *delay*
	sll	%r1,0x8		; 	xsll	%r1, 8			; %PC = PC-1 (仕様)
	or	%r10, %r1
	;
	ext	m6502mem+0x1@ah			; %PC = &mem[PC]
	ext	m6502mem+0x1@al
	add	%r10, %r10
	ret

m6502cpu_RTI:
	ext	m6502cpu_pull@rm	; 	xcall	m6502cpu_pull			; Pull PSR
	call	m6502cpu_pull@rl
	ext	m6502cpu_unpack@rm	; 	xcall	m6502cpu_unpack
	call	m6502cpu_unpack@rl
	;
	ext	m6502cpu_pull@rm	; 	xcall	m6502cpu_pull			; Pull LO(PC)
	call	m6502cpu_pull@rl
	ext	m6502cpu_pull@rm	; 	xcall.d	m6502cpu_pull			; Pull HI(PC)
	call.d	m6502cpu_pull@rl
	ld.w	%r10, %r1			; *delay*
	sll	%r1,0x8		; 	xsll	%r1, 8			; %PC = PC
	or	%r10, %r1
	;
	ext	m6502mem@ah			; %PC = &mem[PC]
	ext	m6502mem@al
	add	%r10, %r10
	;
	ext	m6502cpu_check_pending@rm	; 	xjp	m6502cpu_check_pending		; 保留IRQ要求を調べます。
	jp	m6502cpu_check_pending@rl

;****************************************************************************
;	Operation
;****************************************************************************

m6502cpu_SEC:
	ext	0x1		; 	xbset	[%r14+0x1], 0x0
	bset	[%r14],0x0
	ret

m6502cpu_CLC:
	ext	0x1		; 	xbclr	[%r14+0x1], 0x0
	bclr	[%r14],0x0
	ret

m6502cpu_SEI:
	ext	0x4		; 	xbset	[%r14+0x4], 0x2
	bset	[%r14],0x2
	ret

m6502cpu_CLI:
	ext	0x4		; 	xbclr	[%r14+0x4], 0x2
	bclr	[%r14],0x2
	ext	m6502cpu_check_pending@rm	; 	xjp	m6502cpu_check_pending		; 保留IRQ要求を調べます。
	jp	m6502cpu_check_pending@rl

m6502cpu_SED:
	ext	0x4		; 	xbset	[%r14+0x4], 0x3
	bset	[%r14],0x3
	ret

m6502cpu_CLD:
	ext	0x4		; 	xbclr	[%r14+0x4], 0x3
	bclr	[%r14],0x3
	ret

m6502cpu_CLV:
	ext	0x5		; 	xbclr	[%r14+0x5], 0x7
	bclr	[%r14],0x7
	ret

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

m6502cpu_NOP:
	ret

m6502cpu_WAI:
	ext	0x10		; 	xbset	[%r14+0x10], 0x0
	bset	[%r14],0x0
	ret.d
	ld.w	%r15, 0

;****************************************************************************
;	
;****************************************************************************

; 高速化のため、M6502CPU構造体を高速RAMに配置します。
; 高速RAMへ配置するために、.codeセクションとします。
	.code
	.align	2
	.global	m6502cpu
m6502cpu:
	.space	32

;****************************************************************************
;	
;****************************************************************************

; 制御テーブルは、高速RAMではなくSRAMに配置します。
; SRAMへ配置するために、.dataセクションとします。
	.data
m6502tbl:
	; [00] BRK Implied
	.word 0x7000000
	.word m6502cpu_BRK
	.word -1
	.word -1
	; [01] ORA Indirect,X
	.word 0x6000000
	.word m6502cpu_READ
	.word m6502cpu_INDIRECT_X
	.word m6502cpu_ORA
	; [02] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [03] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [04] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [05] ORA ZeroPage
	.word 0x3000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_ORA
	; [06] ASL ZeroPage
	.word 0x5000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_ASL
	; [07] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [08] PHP Implied
	.word 0x3000000
	.word m6502cpu_PHP
	.word -1
	.word -1
	; [09] ORA Immediate
	.word 0x2000000
	.word m6502cpu_IMMEDIATE
	.word m6502cpu_ORA
	.word -1
	; [0A] ASL Accumulator
	.word 0x2000000
	.word m6502cpu_ACCUMULATOR
	.word m6502cpu_ASL
	.word -1
	; [0B] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [0C] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [0D] ORA Absolute
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_ORA
	; [0E] ASL Absolute
	.word 0x6000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_ASL
	; [0F] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [10] BPL Relative
	.word 0x2000000
	.word m6502cpu_BRANCH_EQ
	.word m6502cpu_BPL
	.word -1
	; [11] ORA Indirect,Y
	.word 0x5000000
	.word m6502cpu_READ
	.word m6502cpu_INDIRECT_Y
	.word m6502cpu_ORA
	; [12] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [13] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [14] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [15] ORA ZeroPage,X
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE_X
	.word m6502cpu_ORA
	; [16] ASL ZeroPage,X
	.word 0x6000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ZEROPAGE_X
	.word m6502cpu_ASL
	; [17] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [18] CLC Implied
	.word 0x2000000
	.word m6502cpu_CLC
	.word -1
	.word -1
	; [19] ORA Absolute,Y
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE_Y
	.word m6502cpu_ORA
	; [1A] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [1B] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [1C] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [1D] ORA Absolute,X
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE_X
	.word m6502cpu_ORA
	; [1E] ASL Absolute,X
	.word 0x7000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ABSOLUTE_X
	.word m6502cpu_ASL
	; [1F] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [20] JSR Absolute
	.word 0x6000000
	.word m6502cpu_CALL
	.word m6502cpu_ABSOLUTE
	.word -1
	; [21] AND Indirect,X
	.word 0x6000000
	.word m6502cpu_READ
	.word m6502cpu_INDIRECT_X
	.word m6502cpu_AND
	; [22] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [23] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [24] BIT ZeroPage
	.word 0x3000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_BIT
	; [25] AND ZeroPage
	.word 0x3000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_AND
	; [26] ROL ZeroPage
	.word 0x5000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_ROL
	; [27] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [28] PLP Implied
	.word 0x4000000
	.word m6502cpu_PLP
	.word -1
	.word -1
	; [29] AND Immediate
	.word 0x2000000
	.word m6502cpu_IMMEDIATE
	.word m6502cpu_AND
	.word -1
	; [2A] ROL Accumulator
	.word 0x2000000
	.word m6502cpu_ACCUMULATOR
	.word m6502cpu_ROL
	.word -1
	; [2B] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [2C] BIT Absolute
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_BIT
	; [2D] AND Absolute
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_AND
	; [2E] ROL Absolute
	.word 0x6000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_ROL
	; [2F] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [30] BMI Relative
	.word 0x2000000
	.word m6502cpu_BRANCH_NE
	.word m6502cpu_BMI
	.word -1
	; [31] AND Indirect,Y
	.word 0x5000000
	.word m6502cpu_READ
	.word m6502cpu_INDIRECT_Y
	.word m6502cpu_AND
	; [32] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [33] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [34] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [35] AND ZeroPage,X
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE_X
	.word m6502cpu_AND
	; [36] ROL ZeroPage,X
	.word 0x6000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ZEROPAGE_X
	.word m6502cpu_ROL
	; [37] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [38] SEC Implied
	.word 0x2000000
	.word m6502cpu_SEC
	.word -1
	.word -1
	; [39] AND Absolute,Y
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE_Y
	.word m6502cpu_AND
	; [3A] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [3B] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [3C] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [3D] AND Absolute,X
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE_X
	.word m6502cpu_AND
	; [3E] ROL Absolute,X
	.word 0x7000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ABSOLUTE_X
	.word m6502cpu_ROL
	; [3F] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [40] RTI Implied
	.word 0x6000000
	.word m6502cpu_RTI
	.word -1
	.word -1
	; [41] EOR Indirect,X
	.word 0x6000000
	.word m6502cpu_READ
	.word m6502cpu_INDIRECT_X
	.word m6502cpu_EOR
	; [42] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [43] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [44] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [45] EOR ZeroPage
	.word 0x3000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_EOR
	; [46] LSR ZeroPage
	.word 0x5000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_LSR
	; [47] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [48] PHA Implied
	.word 0x3000000
	.word m6502cpu_PHA
	.word -1
	.word -1
	; [49] EOR Immediate
	.word 0x2000000
	.word m6502cpu_IMMEDIATE
	.word m6502cpu_EOR
	.word -1
	; [4A] LSR Accumulator
	.word 0x2000000
	.word m6502cpu_ACCUMULATOR
	.word m6502cpu_LSR
	.word -1
	; [4B] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [4C] JMP Absolute
	.word 0x3000000
	.word m6502cpu_JUMP
	.word m6502cpu_ABSOLUTE
	.word -1
	; [4D] EOR Absolute
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_EOR
	; [4E] LSR Absolute
	.word 0x6000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_LSR
	; [4F] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [50] BVC Relative
	.word 0x2000000
	.word m6502cpu_BRANCH_EQ
	.word m6502cpu_BVC
	.word -1
	; [51] EOR Indirect,Y
	.word 0x5000000
	.word m6502cpu_READ
	.word m6502cpu_INDIRECT_Y
	.word m6502cpu_EOR
	; [52] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [53] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [54] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [55] EOR ZeroPage,X
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE_X
	.word m6502cpu_EOR
	; [56] LSR ZeroPage,X
	.word 0x6000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ZEROPAGE_X
	.word m6502cpu_LSR
	; [57] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [58] CLI Implied
	.word 0x2000000
	.word m6502cpu_CLI
	.word -1
	.word -1
	; [59] EOR Absolute,Y
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE_Y
	.word m6502cpu_EOR
	; [5A] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [5B] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [5C] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [5D] EOR Absolute,X
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE_X
	.word m6502cpu_EOR
	; [5E] LSR Absolute,X
	.word 0x7000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ABSOLUTE_X
	.word m6502cpu_LSR
	; [5F] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [60] RTS Implied
	.word 0x6000000
	.word m6502cpu_RTS
	.word -1
	.word -1
	; [61] ADC Indirect,X
	.word 0x6000000
	.word m6502cpu_READ
	.word m6502cpu_INDIRECT_X
	.word m6502cpu_ADC
	; [62] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [63] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [64] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [65] ADC ZeroPage
	.word 0x3000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_ADC
	; [66] ROR ZeroPage
	.word 0x5000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_ROR
	; [67] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [68] PLA Implied
	.word 0x4000000
	.word m6502cpu_PLA
	.word -1
	.word -1
	; [69] ADC Immediate
	.word 0x2000000
	.word m6502cpu_IMMEDIATE
	.word m6502cpu_ADC
	.word -1
	; [6A] ROR Accumulator
	.word 0x2000000
	.word m6502cpu_ACCUMULATOR
	.word m6502cpu_ROR
	.word -1
	; [6B] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [6C] JMP Indirect
	.word 0x5000000
	.word m6502cpu_JUMP
	.word m6502cpu_INDIRECT
	.word -1
	; [6D] ADC Absolute
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_ADC
	; [6E] ROR Absolute
	.word 0x6000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_ROR
	; [6F] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [70] BVS Relative
	.word 0x2000000
	.word m6502cpu_BRANCH_NE
	.word m6502cpu_BVS
	.word -1
	; [71] ADC Indirect,Y
	.word 0x5000000
	.word m6502cpu_READ
	.word m6502cpu_INDIRECT_Y
	.word m6502cpu_ADC
	; [72] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [73] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [74] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [75] ADC ZeroPage,X
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE_X
	.word m6502cpu_ADC
	; [76] ROR ZeroPage,X
	.word 0x6000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ZEROPAGE_X
	.word m6502cpu_ROR
	; [77] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [78] SEI Implied
	.word 0x2000000
	.word m6502cpu_SEI
	.word -1
	.word -1
	; [79] ADC Absolute,Y
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE_Y
	.word m6502cpu_ADC
	; [7A] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [7B] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [7C] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [7D] ADC Absolute,X
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE_X
	.word m6502cpu_ADC
	; [7E] ROR Absolute,X
	.word 0x7000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ABSOLUTE_X
	.word m6502cpu_ROR
	; [7F] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [80] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [81] STA Indirect,X
	.word 0x6000000
	.word m6502cpu_WRITE
	.word m6502cpu_INDIRECT_X
	.word m6502cpu_STA
	; [82] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [83] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [84] STY ZeroPage
	.word 0x3000000
	.word m6502cpu_WRITE
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_STY
	; [85] STA ZeroPage
	.word 0x3000000
	.word m6502cpu_WRITE
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_STA
	; [86] STX ZeroPage
	.word 0x3000000
	.word m6502cpu_WRITE
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_STX
	; [87] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [88] DEY Implied
	.word 0x2000000
	.word m6502cpu_DEY
	.word -1
	.word -1
	; [89] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [8A] TXA Implied
	.word 0x2000000
	.word m6502cpu_TXA
	.word -1
	.word -1
	; [8B] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [8C] STY Absolute
	.word 0x4000000
	.word m6502cpu_WRITE
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_STY
	; [8D] STA Absolute
	.word 0x4000000
	.word m6502cpu_WRITE
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_STA
	; [8E] STX Absolute
	.word 0x4000000
	.word m6502cpu_WRITE
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_STX
	; [8F] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [90] BCC Relative
	.word 0x2000000
	.word m6502cpu_BRANCH_EQ
	.word m6502cpu_BCC
	.word -1
	; [91] STA Indirect,Y
	.word 0x6000000
	.word m6502cpu_WRITE
	.word m6502cpu_INDIRECT_Y
	.word m6502cpu_STA
	; [92] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [93] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [94] STY ZeroPage,X
	.word 0x4000000
	.word m6502cpu_WRITE
	.word m6502cpu_ZEROPAGE_X
	.word m6502cpu_STY
	; [95] STA ZeroPage,X
	.word 0x4000000
	.word m6502cpu_WRITE
	.word m6502cpu_ZEROPAGE_X
	.word m6502cpu_STA
	; [96] STX ZeroPage,Y
	.word 0x4000000
	.word m6502cpu_WRITE
	.word m6502cpu_ZEROPAGE_Y
	.word m6502cpu_STX
	; [97] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [98] TYA Implied
	.word 0x2000000
	.word m6502cpu_TYA
	.word -1
	.word -1
	; [99] STA Absolute,Y
	.word 0x5000000
	.word m6502cpu_WRITE
	.word m6502cpu_ABSOLUTE_Y
	.word m6502cpu_STA
	; [9A] TXS Implied
	.word 0x2000000
	.word m6502cpu_TXS
	.word -1
	.word -1
	; [9B] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [9C] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [9D] STA Absolute,X
	.word 0x5000000
	.word m6502cpu_WRITE
	.word m6502cpu_ABSOLUTE_X
	.word m6502cpu_STA
	; [9E] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [9F] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [A0] LDY Immediate
	.word 0x2000000
	.word m6502cpu_IMMEDIATE
	.word m6502cpu_LDY
	.word -1
	; [A1] LDA Indirect,X
	.word 0x6000000
	.word m6502cpu_READ
	.word m6502cpu_INDIRECT_X
	.word m6502cpu_LDA
	; [A2] LDX Immediate
	.word 0x2000000
	.word m6502cpu_IMMEDIATE
	.word m6502cpu_LDX
	.word -1
	; [A3] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [A4] LDY ZeroPage
	.word 0x3000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_LDY
	; [A5] LDA ZeroPage
	.word 0x3000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_LDA
	; [A6] LDX ZeroPage
	.word 0x3000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_LDX
	; [A7] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [A8] TAY Implied
	.word 0x2000000
	.word m6502cpu_TAY
	.word -1
	.word -1
	; [A9] LDA Immediate
	.word 0x2000000
	.word m6502cpu_IMMEDIATE
	.word m6502cpu_LDA
	.word -1
	; [AA] TAX Implied
	.word 0x2000000
	.word m6502cpu_TAX
	.word -1
	.word -1
	; [AB] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [AC] LDY Absolute
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_LDY
	; [AD] LDA Absolute
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_LDA
	; [AE] LDX Absolute
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_LDX
	; [AF] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [B0] BCS Relative
	.word 0x2000000
	.word m6502cpu_BRANCH_NE
	.word m6502cpu_BCS
	.word -1
	; [B1] LDA Indirect,Y
	.word 0x5000000
	.word m6502cpu_READ
	.word m6502cpu_INDIRECT_Y
	.word m6502cpu_LDA
	; [B2] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [B3] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [B4] LDY ZeroPage,X
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE_X
	.word m6502cpu_LDY
	; [B5] LDA ZeroPage,X
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE_X
	.word m6502cpu_LDA
	; [B6] LDX ZeroPage,Y
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE_Y
	.word m6502cpu_LDX
	; [B7] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [B8] CLV Implied
	.word 0x2000000
	.word m6502cpu_CLV
	.word -1
	.word -1
	; [B9] LDA Absolute,Y
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE_Y
	.word m6502cpu_LDA
	; [BA] TSX Implied
	.word 0x2000000
	.word m6502cpu_TSX
	.word -1
	.word -1
	; [BB] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [BC] LDY Absolute,X
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE_X
	.word m6502cpu_LDY
	; [BD] LDA Absolute,X
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE_X
	.word m6502cpu_LDA
	; [BE] LDX Absolute,Y
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE_Y
	.word m6502cpu_LDX
	; [BF] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [C0] CPY Immediate
	.word 0x2000000
	.word m6502cpu_IMMEDIATE
	.word m6502cpu_CPY
	.word -1
	; [C1] CMP Indirect,X
	.word 0x6000000
	.word m6502cpu_READ
	.word m6502cpu_INDIRECT_X
	.word m6502cpu_CMP
	; [C2] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [C3] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [C4] CPY ZeroPage
	.word 0x3000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_CPY
	; [C5] CMP ZeroPage
	.word 0x3000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_CMP
	; [C6] DEC ZeroPage
	.word 0x5000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_DEC
	; [C7] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [C8] INY Implied
	.word 0x2000000
	.word m6502cpu_INY
	.word -1
	.word -1
	; [C9] CMP Immediate
	.word 0x2000000
	.word m6502cpu_IMMEDIATE
	.word m6502cpu_CMP
	.word -1
	; [CA] DEX Implied
	.word 0x2000000
	.word m6502cpu_DEX
	.word -1
	.word -1
	; [CB] WAI Implied
	.word 0x3000000
	.word m6502cpu_WAI
	.word -1
	.word -1
	; [CC] CPY Absolute
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_CPY
	; [CD] CMP Absolute
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_CMP
	; [CE] DEC Absolute
	.word 0x6000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_DEC
	; [CF] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [D0] BNE Relative
	.word 0x2000000
	.word m6502cpu_BRANCH_NE
	.word m6502cpu_BNE
	.word -1
	; [D1] CMP Indirect,Y
	.word 0x5000000
	.word m6502cpu_READ
	.word m6502cpu_INDIRECT_Y
	.word m6502cpu_CMP
	; [D2] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [D3] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [D4] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [D5] CMP ZeroPage,X
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE_X
	.word m6502cpu_CMP
	; [D6] DEC ZeroPage,X
	.word 0x6000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ZEROPAGE_X
	.word m6502cpu_DEC
	; [D7] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [D8] CLD Implied
	.word 0x2000000
	.word m6502cpu_CLD
	.word -1
	.word -1
	; [D9] CMP Absolute,Y
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE_Y
	.word m6502cpu_CMP
	; [DA] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [DB] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [DC] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [DD] CMP Absolute,X
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE_X
	.word m6502cpu_CMP
	; [DE] DEC Absolute,X
	.word 0x7000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ABSOLUTE_X
	.word m6502cpu_DEC
	; [DF] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [E0] CPX Immediate
	.word 0x2000000
	.word m6502cpu_IMMEDIATE
	.word m6502cpu_CPX
	.word -1
	; [E1] SBC Indirect,X
	.word 0x6000000
	.word m6502cpu_READ
	.word m6502cpu_INDIRECT_X
	.word m6502cpu_SBC
	; [E2] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [E3] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [E4] CPX ZeroPage
	.word 0x3000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_CPX
	; [E5] SBC ZeroPage
	.word 0x3000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_SBC
	; [E6] INC ZeroPage
	.word 0x5000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ZEROPAGE
	.word m6502cpu_INC
	; [E7] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [E8] INX Implied
	.word 0x2000000
	.word m6502cpu_INX
	.word -1
	.word -1
	; [E9] SBC Immediate
	.word 0x2000000
	.word m6502cpu_IMMEDIATE
	.word m6502cpu_SBC
	.word -1
	; [EA] NOP Implied
	.word 0x2000000
	.word m6502cpu_NOP
	.word -1
	.word -1
	; [EB] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [EC] CPX Absolute
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_CPX
	; [ED] SBC Absolute
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_SBC
	; [EE] INC Absolute
	.word 0x6000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ABSOLUTE
	.word m6502cpu_INC
	; [EF] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [F0] BEQ Relative
	.word 0x2000000
	.word m6502cpu_BRANCH_EQ
	.word m6502cpu_BEQ
	.word -1
	; [F1] SBC Indirect,Y
	.word 0x5000000
	.word m6502cpu_READ
	.word m6502cpu_INDIRECT_Y
	.word m6502cpu_SBC
	; [F2] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [F3] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [F4] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [F5] SBC ZeroPage,X
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ZEROPAGE_X
	.word m6502cpu_SBC
	; [F6] INC ZeroPage,X
	.word 0x6000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ZEROPAGE_X
	.word m6502cpu_INC
	; [F7] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [F8] SED Implied
	.word 0x2000000
	.word m6502cpu_SED
	.word -1
	.word -1
	; [F9] SBC Absolute,Y
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE_Y
	.word m6502cpu_SBC
	; [FA] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [FB] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [FC] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
	; [FD] SBC Absolute,X
	.word 0x4000000
	.word m6502cpu_READ
	.word m6502cpu_ABSOLUTE_X
	.word m6502cpu_SBC
	; [FE] INC Absolute,X
	.word 0x7000000
	.word m6502cpu_READ_WRITE
	.word m6502cpu_ABSOLUTE_X
	.word m6502cpu_INC
	; [FF] ERR
	.word 0x0
	.word m6502cpu_ERR
	.word -1
	.word -1
