;
;	framdmca.s
;
;	P/ECE DMG-CPU (Sharp LR35902) Emulator (高速版)
;	
;	CLiP - Common Library for P/ECE
;	Copyright (C) 2001-2005 Naoyuki Sawa
;	
;	* Sun Feb 13 03:10:00 JST 2005 Naoyuki Sawa
;	- 作成開始。
;
;#include "clipdmca.h"
;
;	clipdmca.h
;
;	P/ECE DMG-CPU (Sharp LR35902) Emulator (高速版)
;	
;	CLiP - Common Library for P/ECE
;	Copyright (C) 2001-2005 Naoyuki Sawa
;	
;	* Sun Feb 13 03:10:00 JST 2005 Naoyuki Sawa
;	- 作成開始。
;

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

; - トレースデバッグを行う場合は、DMGCPU_RUN_TRACEシンボルを定義してください。
;   DMGCPU_RUN_TRACEシンボルを定義すると、動作速度がとても遅くなるので、
;   通常はコメントアウトしておいてください。
; - DMGCPU_RUN_TRACEシンボルを参照してトレースログを出力しているのは、
;   dmgcpu_runとdmgcpu_EIです。(2005/03/05現在)
;   dmgcpu_runとdmgcpu_EIの実装を参照してください。
;;#define DMGCPU_RUN_TRACE

;****************************************************************************
;	DMGCPU構造体
;****************************************************************************

					; typedef struct _DMGCPU {
;#define CZ		 0		; 	unsigned short cz;		/* + 0,2: -------C zzzzzzzz (C=F(C),z=!F(Z)) */
;#define NH		 2		; 	unsigned char  nh;		/* + 2,1:          --NH---- (N=F(N),H= F(H)) */
;#define _A_		 3		; 	unsigned char   a;		/* + 3,1: A  */
;#define BC		 4		; 	unsigned short bc;		/* + 4,2: BC */
;#define DE		 6		; 	unsigned short de;		/* + 6,2: DE */
;#define HL		 8		; 	unsigned short hl;		/* + 8,2: HL */
;#define SP		10		; 	unsigned short sp;		/* +10,2: SP */
;#define _PC_		12		; 	unsigned short pc;		/* +12,2: PC */
;#define FLAGS		14		; 	unsigned char flags;		/* +14,1: -----SHI (S=STOP,H=HALT,I=IME) */
					; 	//				/* +15,1: (パディング) */
;#define _CYCLE_		16		; 	int cycle;			/* +16,4: 残り実行サイクル数 */
;#define _READ_		20		; 	void* read;			/* +20,4: メモリ読み出しルーチン */
;#define _WRITE_		24		; 	void* write;			/* +24,4: メモリ書き込みルーチン */
;#define SIZEOF_DMGCPU	28		; } DMGCPU;				/* =28 */

;#define C		 4
;#define B		 5
;#define E		 6
;#define D		 7
;#define L		 8
;#define H		 9

;****************************************************************************
;	フラグビット定義
;****************************************************************************

; * フラグフィールドのマスク定義、および、注意事項を記します。
;
; - 一時的にレジスタに保持しているNHフィールドに対して、Nフラグをセットするには、
;
;	xoor	%t0, %t0, 0x20		; D5だけセット (2命令に展開される)
;
;   よりも、
;
;	xoor	%t0, %t0, ~0x1f		; D31:5を全てセット (1命令で済む)
;
;   の方が有利です。同様に、Nフラグをクリアするには、
;
;	xand	%t0, %t0, ~0x20		; D5だけクリア (2命令に展開される)
;
;   よりも、
;
;	xand	%t0, %t0, 0x1f		; D31:5を全てクリア (1命令で済む)
;
;   の方が有利です。以上を踏まえて、フラグビットのマスク定義を行いました。
;
;	xoor	%t0, %t0, NF		; Nフラグをセット (1命令)
;	xand	%t0, %t0, ~NF		; Nフラグをクリア (1命令)
;
;   なお、NHフィールドは、F(N,H)より1ビット右にずれていることに注意してください。
;   1ビット右にずれていることの主な理由は、Hフラグの計算を容易にするためですが、
;   同時にNフラグも右にずれたために、都合良く、1命令でNフラグのセット、クリアが
;   できるようになりました。
;
; - H、Cフラグに関しては、1ビットだけをセット、クリアしてもコストは同じですが、
;   Nフラグに揃えて、連続ビットをセット、クリアすることにしました。
;
;	xoor	%t0, %t0, HF		; Hフラグをセット (1命令)
;	xand	%t0, %t0, ~HF		; Hフラグをクリア (1命令)
;
;	xoor	%t0, %t0, CF		; Cフラグをセット (2命令)
;	xand	%t0, %t0, ~CF		; Cフラグをクリア (2命令)
;
; - CZフィールド上のZフラグは、F(Z)の逆論理であることに注意してください。
;   CZフィールド上のZフラグがすべて0ならば、F(Z)=1を意味します。
;   CZフィールド上のZフラグのうち1ビットでも1ならば、F(Z)=0を意味します。
;   Zフラグをクリアする場合は、定義上、全ビットをクリアする必要があります。
;
;	xand	%t0, %t0, ~ZF		; Zフラグをクリア (2命令)
;
;   Zフラグをセットする場合は、定義上、どれか1ビットだけのセットで充分です。
;
;	xoor	%t0, %t0, ZF		; Zフラグをセット (2命令)
;	;↓上の方法でも構いませんが、次の方法がより低コストです。
;	xoor	%t0, %t0, 1		; Zフラグをセット (1命令)
;
; - メモリ上のフラグフィールドに対して、N、H、Cのセット、クリアを行う場合は、
;   通常どおりxbset、xbclrを使って、1ビットだけをセット、クリアしてください。
;   (Cフラグのクリアに関しては、全ビットをクリアする方が、より低コストです。)
;
;	xbset	[%CPU+NH], NF_BIT	; Nフラグをセット
;	xbclr	[%CPU+NH], NF_BIT	; Nフラグをクリア
;
;	xbset	[%CPU+NH], HF_BIT	; Hフラグをセット
;	xbclr	[%CPU+NH], HF_BIT	; Hフラグをクリア
;
;	xbset	[%CPU+CZ+1], 0		; Cフラグをセット
;	xbclr	[%CPU+CZ+1], 0		; Cフラグをクリア
;	;↓上の方法でも構いませんが、次の方法がより低コストです。
;	xld.b	[%CPU+CZ+1], %r8	; Cフラグをクリア
;
;   Zフラグをクリアする場合は、定義上、全ビットをクリアする必要があります。
;
;	xld.b	[%CPU+CZ+0], %r8	; Zフラグをクリア
;
;   Zフラグをセットする場合は、定義上、どれか1ビットだけのセットで充分です。
;
;	xbset	[%CPU+CZ+0], 0		; Zフラグをセット
;
; - 以上をまとめると、各フラグをセット、クリアする最善の方法は、次のとおりです。
;
;	一時的にレジスタに保持しているフラグフィールドに対して...
;
;	xoor	%t0, %t0, NF		; Nフラグをセット (1命令)
;	xand	%t0, %t0, ~NF		; Nフラグをクリア (1命令)
;
;	xoor	%t0, %t0, HF		; Hフラグをセット (1命令)
;	xand	%t0, %t0, ~HF		; Hフラグをクリア (1命令)
;
;	xoor	%t0, %t0, CF		; Cフラグをセット (2命令)
;	xand	%t0, %t0, ~CF		; Cフラグをクリア (2命令)
;
;	xoor	%t0, %t0, 1		; Zフラグをセット (1命令)
;	xand	%t0, %t0, ~ZF		; Zフラグをクリア (2命令)
;
;	メモリ上のフラグフィールドに対して...
;
;	xbset	[%CPU+NH], NF_BIT	; Nフラグをセット
;	xbclr	[%CPU+NH], NF_BIT	; Nフラグをクリア
;
;	xbset	[%CPU+NH], HF_BIT	; Hフラグをセット
;	xbclr	[%CPU+NH], HF_BIT	; Hフラグをクリア
;
;	xbset	[%CPU+CZ+1], 0		; Cフラグをセット
;	xld.b	[%CPU+CZ+1], %r8	; Cフラグをクリア
;
;	xbset	[%CPU+CZ+0], 0		; Zフラグをセット
;	xld.b	[%CPU+CZ+0], %r8	; Zフラグをクリア

;/* DMGCPU.cz */
;#define ZF		0xff
;#define CF		(~0xff)
;#define ZF_BIT		0..7
;#define CF_BIT		8

;/* DMGCPU.nh */
;#define HF		0x1f
;#define NF		(~0x1f)
;#define HF_BIT		4
;#define NF_BIT		5

;/* DMGCPU.flags */
;#define IME		(1<<0)
;#define HALT		(1<<1)
;#define STOP		(1<<2)
;#define IME_BIT		0
;#define HALT_BIT	1
;#define STOP_BIT	2

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

;#define addr		r0		; READ、WRITEルーチンへのアドレス引数です。
					; 命令ルーチンが初期化し、READ、WRITEルーチンが参照します。
					; 命令ルーチン以外が、このレジスタを変更してはいけません。
;#define data		r1		; READルーチンの戻り値、WRITEルーチンへのデータ引数です。
					; READルーチンが初期化し、命令ルーチンが参照します。
					; または、命令ルーチンが初期化し、WRITEルーチンが参照します。
					; WRITEルーチンは、このレジスタを変更してはいけません。
;#define s0		r2		; READ、WRITEルーチン呼び出し時に、一時的な値を保存するためのレジスタです。
					; 命令ルーチンが、任意に使用可能です。
					; READ、WRITEルーチンは、このレジスタを変更してはいけません。
;#define s1		r3		; (同上)
;#define CPU		r4		; dmgcpuのアドレスを保持します。
					; dmgcpu_enter〜dmgcpu_leaveの間、不変です。
					; READ、WRITEルーチンは、このレジスタを変更してはいけません。
;#define A		r5		; Aレジスタの値を保持します。
					; D31:8は常に0とします。
					; READ、WRITEルーチンは、このレジスタを変更してはいけません。
;#define PC		r6		; PCレジスタの値を保持します。
					; D31:16は常に0とします。
					; dmgcpu_run、命令ルーチン、および補助ルーチンが、適切に設定、参照します。
					; READ、WRITEルーチンは、このレジスタを変更してはいけません。
;#define CYCLE		r7		; 残り実行サイクル数を保持します。
					; 命令ルーチン、および補助ルーチンが、適切に設定、参照します。
					; READ、WRITEルーチンは、このレジスタを変更してはいけません。
;	 		r8
;	 		r9
;#define READ		r10		; READルーチンのアドレスを保持します。
					; dmgcpu_enter〜dmgcpu_leaveの間、不変です。
					; READ、WRITEルーチンは、このレジスタを変更してはいけません。
;#define WRITE		r11		; WRITEルーチンのアドレスを保持します。
					; dmgcpu_enter〜dmgcpu_leaveの間、不変です。
					; READ、WRITEルーチンは、このレジスタを変更してはいけません。
;#define t0		r12		; 汎用ワークレジスタです。
					; 全てのルーチンが、任意に使用可能です。
;#define t1		r13		; (同上)
;#define t2		r14		; (同上)
;#define t3		r15		; (同上)

;****************************************************************************
;	8-Bit Loads
;****************************************************************************

;#define CYCLE_LD_A_n		8
;#define CYCLE_LD_A_A		4
;#define CYCLE_LD_A_B		4
;#define CYCLE_LD_A_C		4
;#define CYCLE_LD_A_D		4
;#define CYCLE_LD_A_E		4
;#define CYCLE_LD_A_H		4
;#define CYCLE_LD_A_L		4
;#define CYCLE_LD_A_IHLI		8

;#define CYCLE_LD_B_n		8
;#define CYCLE_LD_B_A		4
;#define CYCLE_LD_B_B		4
;#define CYCLE_LD_B_C		4
;#define CYCLE_LD_B_D		4
;#define CYCLE_LD_B_E		4
;#define CYCLE_LD_B_H		4
;#define CYCLE_LD_B_L		4
;#define CYCLE_LD_B_IHLI		8

;#define CYCLE_LD_C_n		8
;#define CYCLE_LD_C_A		4
;#define CYCLE_LD_C_B		4
;#define CYCLE_LD_C_C		4
;#define CYCLE_LD_C_D		4
;#define CYCLE_LD_C_E		4
;#define CYCLE_LD_C_H		4
;#define CYCLE_LD_C_L		4
;#define CYCLE_LD_C_IHLI		8

;#define CYCLE_LD_D_n		8
;#define CYCLE_LD_D_A		4
;#define CYCLE_LD_D_B		4
;#define CYCLE_LD_D_C		4
;#define CYCLE_LD_D_D		4
;#define CYCLE_LD_D_E		4
;#define CYCLE_LD_D_H		4
;#define CYCLE_LD_D_L		4
;#define CYCLE_LD_D_IHLI		8

;#define CYCLE_LD_E_n		8
;#define CYCLE_LD_E_A		4
;#define CYCLE_LD_E_B		4
;#define CYCLE_LD_E_C		4
;#define CYCLE_LD_E_D		4
;#define CYCLE_LD_E_E		4
;#define CYCLE_LD_E_H		4
;#define CYCLE_LD_E_L		4
;#define CYCLE_LD_E_IHLI		8

;#define CYCLE_LD_H_n		8
;#define CYCLE_LD_H_A		4
;#define CYCLE_LD_H_B		4
;#define CYCLE_LD_H_C		4
;#define CYCLE_LD_H_D		4
;#define CYCLE_LD_H_E		4
;#define CYCLE_LD_H_H		4
;#define CYCLE_LD_H_L		4
;#define CYCLE_LD_H_IHLI		8

;#define CYCLE_LD_L_n		8
;#define CYCLE_LD_L_A		4
;#define CYCLE_LD_L_B		4
;#define CYCLE_LD_L_C		4
;#define CYCLE_LD_L_D		4
;#define CYCLE_LD_L_E		4
;#define CYCLE_LD_L_H		4
;#define CYCLE_LD_L_L		4
;#define CYCLE_LD_L_IHLI		8

;#define CYCLE_LD_IHLI_n		12
;#define CYCLE_LD_IHLI_A		8
;#define CYCLE_LD_IHLI_B		8
;#define CYCLE_LD_IHLI_C		8
;#define CYCLE_LD_IHLI_D		8
;#define CYCLE_LD_IHLI_E		8
;#define CYCLE_LD_IHLI_H		8
;#define CYCLE_LD_IHLI_L		8

;#define CYCLE_LD_A_InnI		16
;#define CYCLE_LD_InnI_A		16
;#define CYCLE_LD_A_IBCI		8
;#define CYCLE_LD_IBCI_A		8
;#define CYCLE_LD_A_IDEI		8
;#define CYCLE_LD_IDEI_A		8

;#define CYCLE_LD_A_ICI		8
;#define CYCLE_LD_ICI_A		8
;#define CYCLE_LDH_A_InI		12
;#define CYCLE_LDH_InI_A		12

;#define CYCLE_LDI_A_IHLI	8
;#define CYCLE_LDI_IHLI_A	8
;#define CYCLE_LDD_A_IHLI	8
;#define CYCLE_LDD_IHLI_A	8

;****************************************************************************
;	16-Bit Loads
;****************************************************************************

;#define CYCLE_LD_BC_nn		12
;#define CYCLE_LD_DE_nn		12
;#define CYCLE_LD_HL_nn		12
;#define CYCLE_LD_SP_nn		12

;#define CYCLE_LD_SP_HL		8
;#define CYCLE_LDHL_SP_e		12
;#define CYCLE_LD_InnI_SP	20

;#define CYCLE_PUSH_AF		16
;#define CYCLE_PUSH_BC		16
;#define CYCLE_PUSH_DE		16
;#define CYCLE_PUSH_HL		16

;#define CYCLE_POP_AF		12
;#define CYCLE_POP_BC		12
;#define CYCLE_POP_DE		12
;#define CYCLE_POP_HL		12

;****************************************************************************
;	8-Bit ALU
;****************************************************************************

;#define CYCLE_ADD_A_n		8
;#define CYCLE_ADD_A_A		4
;#define CYCLE_ADD_A_B		4
;#define CYCLE_ADD_A_C		4
;#define CYCLE_ADD_A_D		4
;#define CYCLE_ADD_A_E		4
;#define CYCLE_ADD_A_H		4
;#define CYCLE_ADD_A_L		4
;#define CYCLE_ADD_A_IHLI	8

;#define CYCLE_ADC_A_n		8
;#define CYCLE_ADC_A_A		4
;#define CYCLE_ADC_A_B		4
;#define CYCLE_ADC_A_C		4
;#define CYCLE_ADC_A_D		4
;#define CYCLE_ADC_A_E		4
;#define CYCLE_ADC_A_H		4
;#define CYCLE_ADC_A_L		4
;#define CYCLE_ADC_A_IHLI	8

;#define CYCLE_SUB_n		8
;#define CYCLE_SUB_A		4
;#define CYCLE_SUB_B		4
;#define CYCLE_SUB_C		4
;#define CYCLE_SUB_D		4
;#define CYCLE_SUB_E		4
;#define CYCLE_SUB_H		4
;#define CYCLE_SUB_L		4
;#define CYCLE_SUB_IHLI		8

;#define CYCLE_SBC_A_n		8
;#define CYCLE_SBC_A_A		4
;#define CYCLE_SBC_A_B		4
;#define CYCLE_SBC_A_C		4
;#define CYCLE_SBC_A_D		4
;#define CYCLE_SBC_A_E		4
;#define CYCLE_SBC_A_H		4
;#define CYCLE_SBC_A_L		4
;#define CYCLE_SBC_A_IHLI	8

;#define CYCLE_CP_n		8
;#define CYCLE_CP_A		4
;#define CYCLE_CP_B		4
;#define CYCLE_CP_C		4
;#define CYCLE_CP_D		4
;#define CYCLE_CP_E		4
;#define CYCLE_CP_H		4
;#define CYCLE_CP_L		4
;#define CYCLE_CP_IHLI		8

;#define CYCLE_AND_n		8
;#define CYCLE_AND_A		4
;#define CYCLE_AND_B		4
;#define CYCLE_AND_C		4
;#define CYCLE_AND_D		4
;#define CYCLE_AND_E		4
;#define CYCLE_AND_H		4
;#define CYCLE_AND_L		4
;#define CYCLE_AND_IHLI		8

;#define CYCLE_OR_n		8
;#define CYCLE_OR_A		4
;#define CYCLE_OR_B		4
;#define CYCLE_OR_C		4
;#define CYCLE_OR_D		4
;#define CYCLE_OR_E		4
;#define CYCLE_OR_H		4
;#define CYCLE_OR_L		4
;#define CYCLE_OR_IHLI		8

;#define CYCLE_XOR_n		8
;#define CYCLE_XOR_A		4
;#define CYCLE_XOR_B		4
;#define CYCLE_XOR_C		4
;#define CYCLE_XOR_D		4
;#define CYCLE_XOR_E		4
;#define CYCLE_XOR_H		4
;#define CYCLE_XOR_L		4
;#define CYCLE_XOR_IHLI		8

;#define CYCLE_INC_A		4
;#define CYCLE_INC_B		4
;#define CYCLE_INC_C		4
;#define CYCLE_INC_D		4
;#define CYCLE_INC_E		4
;#define CYCLE_INC_H		4
;#define CYCLE_INC_L		4
;#define CYCLE_INC_IHLI		12

;#define CYCLE_DEC_A		4
;#define CYCLE_DEC_B		4
;#define CYCLE_DEC_C		4
;#define CYCLE_DEC_D		4
;#define CYCLE_DEC_E		4
;#define CYCLE_DEC_H		4
;#define CYCLE_DEC_L		4
;#define CYCLE_DEC_IHLI		12

;****************************************************************************
;	16-Bit Arithmetic
;****************************************************************************

;#define CYCLE_ADD_HL_BC		8
;#define CYCLE_ADD_HL_DE		8
;#define CYCLE_ADD_HL_HL		8
;#define CYCLE_ADD_HL_SP		8
;#define CYCLE_ADD_SP_e		16

;#define CYCLE_INC_BC		8
;#define CYCLE_INC_DE		8
;#define CYCLE_INC_HL		8
;#define CYCLE_INC_SP		8

;#define CYCLE_DEC_BC		8
;#define CYCLE_DEC_DE		8
;#define CYCLE_DEC_HL		8
;#define CYCLE_DEC_SP		8

;****************************************************************************
;	Miscellaneous
;****************************************************************************

;#define CYCLE_SWAP_A		8
;#define CYCLE_SWAP_B		8
;#define CYCLE_SWAP_C		8
;#define CYCLE_SWAP_D		8
;#define CYCLE_SWAP_E		8
;#define CYCLE_SWAP_H		8
;#define CYCLE_SWAP_L		8
;#define CYCLE_SWAP_IHLI		16

;#define CYCLE_DAA		4
;#define CYCLE_CPL		4
;#define CYCLE_SCF		4
;#define CYCLE_CCF		4

;#define CYCLE_NOP		4
;#define CYCLE_HALT		4
;#define CYCLE_STOP		4
;#define CYCLE_DI		4
;#define CYCLE_EI		4

;****************************************************************************
;	Rotates & Shifts
;****************************************************************************

;#define CYCLE_RLA		4
;#define CYCLE_RLCA		4
;#define CYCLE_RRA		4
;#define CYCLE_RRCA		4

;#define CYCLE_RL_A		8
;#define CYCLE_RL_B		8
;#define CYCLE_RL_C		8
;#define CYCLE_RL_D		8
;#define CYCLE_RL_E		8
;#define CYCLE_RL_H		8
;#define CYCLE_RL_L		8
;#define CYCLE_RL_IHLI		16

;#define CYCLE_RLC_A		8
;#define CYCLE_RLC_B		8
;#define CYCLE_RLC_C		8
;#define CYCLE_RLC_D		8
;#define CYCLE_RLC_E		8
;#define CYCLE_RLC_H		8
;#define CYCLE_RLC_L		8
;#define CYCLE_RLC_IHLI		16

;#define CYCLE_RR_A		8
;#define CYCLE_RR_B		8
;#define CYCLE_RR_C		8
;#define CYCLE_RR_D		8
;#define CYCLE_RR_E		8
;#define CYCLE_RR_H		8
;#define CYCLE_RR_L		8
;#define CYCLE_RR_IHLI		16

;#define CYCLE_RRC_A		8
;#define CYCLE_RRC_B		8
;#define CYCLE_RRC_C		8
;#define CYCLE_RRC_D		8
;#define CYCLE_RRC_E		8
;#define CYCLE_RRC_H		8
;#define CYCLE_RRC_L		8
;#define CYCLE_RRC_IHLI		16

;#define CYCLE_SLA_A		8
;#define CYCLE_SLA_B		8
;#define CYCLE_SLA_C		8
;#define CYCLE_SLA_D		8
;#define CYCLE_SLA_E		8
;#define CYCLE_SLA_H		8
;#define CYCLE_SLA_L		8
;#define CYCLE_SLA_IHLI		16

;#define CYCLE_SRA_A		8
;#define CYCLE_SRA_B		8
;#define CYCLE_SRA_C		8
;#define CYCLE_SRA_D		8
;#define CYCLE_SRA_E		8
;#define CYCLE_SRA_H		8
;#define CYCLE_SRA_L		8
;#define CYCLE_SRA_IHLI		16

;#define CYCLE_SRL_A		8
;#define CYCLE_SRL_B		8
;#define CYCLE_SRL_C		8
;#define CYCLE_SRL_D		8
;#define CYCLE_SRL_E		8
;#define CYCLE_SRL_H		8
;#define CYCLE_SRL_L		8
;#define CYCLE_SRL_IHLI		16

;****************************************************************************
;	Bit Opcodes
;****************************************************************************

;#define CYCLE_BIT_0_A		8
;#define CYCLE_BIT_0_B		8
;#define CYCLE_BIT_0_C		8
;#define CYCLE_BIT_0_D		8
;#define CYCLE_BIT_0_E		8
;#define CYCLE_BIT_0_H		8
;#define CYCLE_BIT_0_L		8
;#define CYCLE_BIT_0_IHLI	12

;#define CYCLE_BIT_1_A		8
;#define CYCLE_BIT_1_B		8
;#define CYCLE_BIT_1_C		8
;#define CYCLE_BIT_1_D		8
;#define CYCLE_BIT_1_E		8
;#define CYCLE_BIT_1_H		8
;#define CYCLE_BIT_1_L		8
;#define CYCLE_BIT_1_IHLI	12

;#define CYCLE_BIT_2_A		8
;#define CYCLE_BIT_2_B		8
;#define CYCLE_BIT_2_C		8
;#define CYCLE_BIT_2_D		8
;#define CYCLE_BIT_2_E		8
;#define CYCLE_BIT_2_H		8
;#define CYCLE_BIT_2_L		8
;#define CYCLE_BIT_2_IHLI	12

;#define CYCLE_BIT_3_A		8
;#define CYCLE_BIT_3_B		8
;#define CYCLE_BIT_3_C		8
;#define CYCLE_BIT_3_D		8
;#define CYCLE_BIT_3_E		8
;#define CYCLE_BIT_3_H		8
;#define CYCLE_BIT_3_L		8
;#define CYCLE_BIT_3_IHLI	12

;#define CYCLE_BIT_4_A		8
;#define CYCLE_BIT_4_B		8
;#define CYCLE_BIT_4_C		8
;#define CYCLE_BIT_4_D		8
;#define CYCLE_BIT_4_E		8
;#define CYCLE_BIT_4_H		8
;#define CYCLE_BIT_4_L		8
;#define CYCLE_BIT_4_IHLI	12

;#define CYCLE_BIT_5_A		8
;#define CYCLE_BIT_5_B		8
;#define CYCLE_BIT_5_C		8
;#define CYCLE_BIT_5_D		8
;#define CYCLE_BIT_5_E		8
;#define CYCLE_BIT_5_H		8
;#define CYCLE_BIT_5_L		8
;#define CYCLE_BIT_5_IHLI	12

;#define CYCLE_BIT_6_A		8
;#define CYCLE_BIT_6_B		8
;#define CYCLE_BIT_6_C		8
;#define CYCLE_BIT_6_D		8
;#define CYCLE_BIT_6_E		8
;#define CYCLE_BIT_6_H		8
;#define CYCLE_BIT_6_L		8
;#define CYCLE_BIT_6_IHLI	12

;#define CYCLE_BIT_7_A		8
;#define CYCLE_BIT_7_B		8
;#define CYCLE_BIT_7_C		8
;#define CYCLE_BIT_7_D		8
;#define CYCLE_BIT_7_E		8
;#define CYCLE_BIT_7_H		8
;#define CYCLE_BIT_7_L		8
;#define CYCLE_BIT_7_IHLI	12

;#define CYCLE_SET_0_A		8
;#define CYCLE_SET_0_B		8
;#define CYCLE_SET_0_C		8
;#define CYCLE_SET_0_D		8
;#define CYCLE_SET_0_E		8
;#define CYCLE_SET_0_H		8
;#define CYCLE_SET_0_L		8
;#define CYCLE_SET_0_IHLI	16

;#define CYCLE_SET_1_A		8
;#define CYCLE_SET_1_B		8
;#define CYCLE_SET_1_C		8
;#define CYCLE_SET_1_D		8
;#define CYCLE_SET_1_E		8
;#define CYCLE_SET_1_H		8
;#define CYCLE_SET_1_L		8
;#define CYCLE_SET_1_IHLI	16

;#define CYCLE_SET_2_A		8
;#define CYCLE_SET_2_B		8
;#define CYCLE_SET_2_C		8
;#define CYCLE_SET_2_D		8
;#define CYCLE_SET_2_E		8
;#define CYCLE_SET_2_H		8
;#define CYCLE_SET_2_L		8
;#define CYCLE_SET_2_IHLI	16

;#define CYCLE_SET_3_A		8
;#define CYCLE_SET_3_B		8
;#define CYCLE_SET_3_C		8
;#define CYCLE_SET_3_D		8
;#define CYCLE_SET_3_E		8
;#define CYCLE_SET_3_H		8
;#define CYCLE_SET_3_L		8
;#define CYCLE_SET_3_IHLI	16

;#define CYCLE_SET_4_A		8
;#define CYCLE_SET_4_B		8
;#define CYCLE_SET_4_C		8
;#define CYCLE_SET_4_D		8
;#define CYCLE_SET_4_E		8
;#define CYCLE_SET_4_H		8
;#define CYCLE_SET_4_L		8
;#define CYCLE_SET_4_IHLI	16

;#define CYCLE_SET_5_A		8
;#define CYCLE_SET_5_B		8
;#define CYCLE_SET_5_C		8
;#define CYCLE_SET_5_D		8
;#define CYCLE_SET_5_E		8
;#define CYCLE_SET_5_H		8
;#define CYCLE_SET_5_L		8
;#define CYCLE_SET_5_IHLI	16

;#define CYCLE_SET_6_A		8
;#define CYCLE_SET_6_B		8
;#define CYCLE_SET_6_C		8
;#define CYCLE_SET_6_D		8
;#define CYCLE_SET_6_E		8
;#define CYCLE_SET_6_H		8
;#define CYCLE_SET_6_L		8
;#define CYCLE_SET_6_IHLI	16

;#define CYCLE_SET_7_A		8
;#define CYCLE_SET_7_B		8
;#define CYCLE_SET_7_C		8
;#define CYCLE_SET_7_D		8
;#define CYCLE_SET_7_E		8
;#define CYCLE_SET_7_H		8
;#define CYCLE_SET_7_L		8
;#define CYCLE_SET_7_IHLI	16

;#define CYCLE_RES_0_A		8
;#define CYCLE_RES_0_B		8
;#define CYCLE_RES_0_C		8
;#define CYCLE_RES_0_D		8
;#define CYCLE_RES_0_E		8
;#define CYCLE_RES_0_H		8
;#define CYCLE_RES_0_L		8
;#define CYCLE_RES_0_IHLI	16

;#define CYCLE_RES_1_A		8
;#define CYCLE_RES_1_B		8
;#define CYCLE_RES_1_C		8
;#define CYCLE_RES_1_D		8
;#define CYCLE_RES_1_E		8
;#define CYCLE_RES_1_H		8
;#define CYCLE_RES_1_L		8
;#define CYCLE_RES_1_IHLI	16

;#define CYCLE_RES_2_A		8
;#define CYCLE_RES_2_B		8
;#define CYCLE_RES_2_C		8
;#define CYCLE_RES_2_D		8
;#define CYCLE_RES_2_E		8
;#define CYCLE_RES_2_H		8
;#define CYCLE_RES_2_L		8
;#define CYCLE_RES_2_IHLI	16

;#define CYCLE_RES_3_A		8
;#define CYCLE_RES_3_B		8
;#define CYCLE_RES_3_C		8
;#define CYCLE_RES_3_D		8
;#define CYCLE_RES_3_E		8
;#define CYCLE_RES_3_H		8
;#define CYCLE_RES_3_L		8
;#define CYCLE_RES_3_IHLI	16

;#define CYCLE_RES_4_A		8
;#define CYCLE_RES_4_B		8
;#define CYCLE_RES_4_C		8
;#define CYCLE_RES_4_D		8
;#define CYCLE_RES_4_E		8
;#define CYCLE_RES_4_H		8
;#define CYCLE_RES_4_L		8
;#define CYCLE_RES_4_IHLI	16

;#define CYCLE_RES_5_A		8
;#define CYCLE_RES_5_B		8
;#define CYCLE_RES_5_C		8
;#define CYCLE_RES_5_D		8
;#define CYCLE_RES_5_E		8
;#define CYCLE_RES_5_H		8
;#define CYCLE_RES_5_L		8
;#define CYCLE_RES_5_IHLI	16

;#define CYCLE_RES_6_A		8
;#define CYCLE_RES_6_B		8
;#define CYCLE_RES_6_C		8
;#define CYCLE_RES_6_D		8
;#define CYCLE_RES_6_E		8
;#define CYCLE_RES_6_H		8
;#define CYCLE_RES_6_L		8
;#define CYCLE_RES_6_IHLI	16

;#define CYCLE_RES_7_A		8
;#define CYCLE_RES_7_B		8
;#define CYCLE_RES_7_C		8
;#define CYCLE_RES_7_D		8
;#define CYCLE_RES_7_E		8
;#define CYCLE_RES_7_H		8
;#define CYCLE_RES_7_L		8
;#define CYCLE_RES_7_IHLI	16

;****************************************************************************
;	Jumps
;****************************************************************************

;#define CYCLE_JP_nn		12
;#define CYCLE_JP_Z_nn		12	;* 16 */
;#define CYCLE_JP_NZ_nn		12	;* 16 */
;#define CYCLE_JP_C_nn		12	;* 16 */
;#define CYCLE_JP_NC_nn		12	;* 16 */
;#define CYCLE_JP_IHLI		4

;#define CYCLE_JR_e		8
;#define CYCLE_JR_Z_e		8	;* 12 */
;#define CYCLE_JR_NZ_e		8	;* 12 */
;#define CYCLE_JR_C_e		8	;* 12 */
;#define CYCLE_JR_NC_e		8	;* 12 */

;****************************************************************************
;	Calls
;****************************************************************************

;#define CYCLE_CALL_nn		12
;#define CYCLE_CALL_Z_nn		12	;* 24 */
;#define CYCLE_CALL_NZ_nn	12	;* 24 */
;#define CYCLE_CALL_C_nn		12	;* 24 */
;#define CYCLE_CALL_NC_nn	12	;* 24 */

;****************************************************************************
;	Restarts
;****************************************************************************

;#define CYCLE_RST_00H		16
;#define CYCLE_RST_08H		16
;#define CYCLE_RST_10H		16
;#define CYCLE_RST_18H		16
;#define CYCLE_RST_20H		16
;#define CYCLE_RST_28H		16
;#define CYCLE_RST_30H		16
;#define CYCLE_RST_38H		16

;****************************************************************************
;	Returns
;****************************************************************************

;#define CYCLE_RET		8
;#define CYCLE_RET_Z		8	;* 20 */
;#define CYCLE_RET_NZ		8	;* 20 */
;#define CYCLE_RET_C		8	;* 20 */
;#define CYCLE_RET_NC		8	;* 20 */
;#define CYCLE_RETI		8

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


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

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

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

	.code
	.align	1

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

	.global	dmgcpu_enter
dmgcpu_enter:
	ext	dmgcpu+0x0@h	; 	xld.w	%r4, dmgcpu
	ext	dmgcpu+0x0@m
	ld.w	%r4,dmgcpu+0x0@l
	ext	0x3		; 	xld.ub	%r5,     [%r4+0x3    ]
	ld.ub	%r5,[%r4]
	ext	0xc		; 	xld.uh	%r6,    [%r4+0xc   ]
	ld.uh	%r6,[%r4]
	ext	0x10		; 	xld.w	%r7, [%r4+0x10]
	ld.w	%r7,[%r4]
	ext	0x14		; 	xld.w	%r10,  [%r4+0x14 ]
	ld.w	%r10,[%r4]
	ext	0x18		; 	xld.w	%r11, [%r4+0x18]
	ld.w	%r11,[%r4]
	ret

	.global	dmgcpu_leave
dmgcpu_leave:
	ext	0x3		; 	xld.b	[%r4+0x3    ], %r5
	ld.b	[%r4],%r5
	ext	0xc		; 	xld.h	[%r4+0xc   ], %r6
	ld.h	[%r4],%r6
	ext	0x10		; 	xld.w	[%r4+0x10], %r7
	ld.w	[%r4],%r7
	ret

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

	.global	dmgmem_read
dmgmem_read:
	ext	dmgmem@ah
	ext	dmgmem@al
	ld.ub	%r1, [%r0]
	ret

	.global	dmgmem_write
dmgmem_write:
	ext	dmgmem@ah
	ext	dmgmem@al
	ld.b	[%r0], %r1
	ret

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

; * Wed Mar 23 06:04:00 JST 2005 Naoyuki Sawa
; - dmgcpu_pack中の以下の二行は、
;	ext	       0x80>>6
;	or	%data, 0x80&((1<<6)-1)
;   pp33のビットフィールド取得演算子を使って、判り易く
;	ext	       0x80^M
;	or	%data, 0x80^L
;   と書き直したいところですが、残念ながらできません。
;   Z80エミュレーションモジュールでは、シンボル"L"を整数値に定義しているため、
;	ext	       0x80^M
;	or	%data, 0x80^8	(#define L 8、clipdmca.h参照)
;   と解釈されてしまうからです。
;   うっかり^Lや^H演算子を使うと、発見しづらいバグになるので、ご注意ください。

	.global	dmgcpu_pack
dmgcpu_pack:
	ld.uh	%r12,[%r4]	; 	xld.uh	%r12, [%r4+0x0]			; %t0   = -------C zzzzzzzz
	ext	0x2		; 	xld.ub	%r13, [%r4+0x2]			; %t1   = -------- --NH----
	ld.ub	%r13,[%r4]
	ext	0x100		; 	xand	%r1, %r12, 0x100		; %data = 0000000C 00000000
	and	%r1,%r12
	srl	%r1,0x4		; 	xsrl	%r1, 4			; %data = 00000000 000C0000
	ext	0x3		; 	xand	%r12, %r12, 0xff			; test             zzzzzzzz
	and	%r12,0x3f
	jrne.d	4
	sll	%r13, 1				; %t1   = -------- -NH----- *delay*
	ext	       0x2			;                           (skip?)
	or	%r1, 0x0		; %data = 00000000 Z00C0000 (skip?)
	ext	0x1		; 	xand	%r13, %r13, 0x60			; %t1   = 00000000 0NH00000
	and	%r13,0x20
	ret.d
	or	%r1, %r13			; %data = 00000000 ZNHC0000 *delay*

	.global	dmgcpu_unpack
dmgcpu_unpack:
	and	%r1,0x30	; 	xand	%r1, %r1, -16		; %data = -------- ZNHC0000
	srl	%r1,0x1		; 	xsrl	%r1, 1			; %data = -------- -ZNHC000
	ext	0x2		; 	xld.b	[%r4+0x2], %r1		; NH    = -------- --NH----
	ld.b	[%r4],%r1
	ext	0x40		; 	xand	%r9, %r1, 0x40		; test              Z
	and	%r9,%r1
	jrne.d	3
	sll	%r1, 5			; %data = -------C 00000000 *delay*
	or	%r1, 1			; %data = -------C 0000000z (skip?)
	ld.h	[%r4],%r1	; 	xld.h	[%r4+0x0], %r1		; CZ    = -------C 0000000z
	ret

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

	.global	dmgcpu_run
dmgcpu_run:
	pushn	%r3
	;
	ext	dmgcpu+0x10@ah	; 	xld.w	[dmgcpu+0x10], %r12		; 実行コンテキストを取り出しす前に、まず、実行サイクル数の初期値を格納します。
	ext	dmgcpu+0x10@al
	ld.w	[%r8],%r12
	call	dmgcpu_enter	; 	xcall	dmgcpu_enter			; 実行コンテキストを取り出します。すぐ上で格納した、実行サイクル数も取り出します。
	;
	ext	0xe		; 	xld.ub	%r12, [%r4+0xe]		; 既にHALTまたはSTOP中ならば、残り実行サイクル数を0にして、すぐにループを抜けます。
	ld.ub	%r12,[%r4]
	and	%r12,0x6	; 	xand	%r12, %r12, 0x6	; HALT、STOPでループを抜ける場合も、アプリケーションが実行時間計測を計測するめに、
	jreq	2				; 終了時の状態は"dmgcpu.cycle<=0"となっていなければいけないことに注意してください。
	ld.w	%r7, 0			; (skip?)
	;
	jp	dmgcpu_run_LOOP	; 	xjp	dmgcpu_run_LOOP			; Cycle=0が指定された場合(またはHALT、STOPでCycle=0とした場合)のために、まず条件判定から。
dmgcpu_run_DO:
;----------------------------------------------------------------------------
;#ifdef DMGCPU_RUN_TRACE
;	; - トレースデバッグを行う場合は、このブロックを有効にしてください。
;	;   その際、dmgcpu_trace()は、アプリケーションにて定義してください。
;	;   dmgcpu_trace()は、ライブラリ内では定義していません。
;	; - DMGCPU_RUN_TRACEシンボルは、dmgcpu_runとdmgcpu_EIから参照するので、
;	;   clipdmca.hにて定義(またはコメントアウト)しています。
;	xcall dmgcpu_leave
;	xcall dmgcpu_trace
;	xcall dmgcpu_enter
;#endif /*DMGCPU_RUN_TRACE*/
;----------------------------------------------------------------------------
	call.d	%r10				; OpCodeを取得し、PCを進めます。
	ld.w	%r0, %r6
	add	%r6,0x1		; 	xadd	%r6, %r6, 1
	sll	%r1,0x2		; 	xsll	%r1, 2			; OpCodeに対応する命令ルーチンを呼び出します。
	ext	dmgcpu_XXops@ah
	ext	dmgcpu_XXops@al
	ld.w	%r1, [%r1]
	call	%r1
dmgcpu_run_LOOP:
	cmp	%r7,0x0		; 	xcmp	%r7, 0			; Cycleが0以下になるまで繰り返します。
	jrgt	dmgcpu_run_DO	; 	xjrgt	dmgcpu_run_DO
	;
dmgcpu_run_EXIT:
	call	dmgcpu_leave	; 	xcall	dmgcpu_leave			; 実行コンテキストを書き戻します。
	;
	popn	%r3
	ret

;
;	CB xx
;	   ++- OpCode
;
	.global	dmgcpu_CB
dmgcpu_CB:
	call.d	%r10				; OpCodeを取得し、PCを進めます。
	ld.w	%r0, %r6
	add	%r6,0x1		; 	xadd	%r6, %r6, 1
	sll	%r1,0x2		; 	xsll	%r1, 2			; OpCodeに対応する命令ルーチンを呼び出します。
	ext	dmgcpu_CBops@ah
	ext	dmgcpu_CBops@al
	ld.w	%r1, [%r1]
	jp	%r1

;****************************************************************************
;	16-Bit Loads
;****************************************************************************

;
;	PUSH	rr
; [in]
;	%data	rr
;
	.global	dmgcpu_push
dmgcpu_push:
	ld.w	%r2, %r1			; %s0    = rr
	srl	%r1,0x8		; 	xsrl	%r1, 8			; %data  = HI(rr)
	ext	0xa		; 	xld.uh	%r0, [%r4+0xa]		; %addr  = SP
	ld.uh	%r0,[%r4]
	call.d	%r11				; [SP-1] = HI(rr)
	sub	%r0, 1			; %addr  = SP-1 *delay*
	ld.ub	%r1, %r2			; %data  = LO(rr)
	call.d	%r11				; [SP-2] = LO(rr)
	sub	%r0, 1			; %addr  = SP-2 *delay*
	ext	0xa		; 	xld.h	[%r4+0xa], %r0		; SP     = SP-2
	ld.h	[%r4],%r0
	ret

;
;	POP	rr
; [out]
;	%data	rr
;
	.global	dmgcpu_pop
dmgcpu_pop:
	ext	0xa		; 	xld.uh	%r0, [%r4+0xa]		; %addr  = SP
	ld.uh	%r0,[%r4]
	call	%r10				; %data  = LO(rr) = [SP+0]
	ld.w	%r2, %r1			; %s0    = LO(rr)
	call.d	%r10				; %data  = HI(rr) = [SP+1]
	add	%r0, 1			; %addr  = SP+1             *delay*
	add	%r0,0x1		; 	xadd	%r0, %r0, 1			; %addr  = SP+2
	ext	0xa		; 	xld.h	[%r4+0xa], %r0		; SP     = SP+2
	ld.h	[%r4],%r0
	sll	%r1,0x8		; 	xsll	%r1, 8			; %data  = HI(rr)<<8
	ret.d
	or	%r1, %r2			; %data  = HI(rr)<<8|LO(rr) *delay*

;****************************************************************************
;	8-Bit ALU
;****************************************************************************

;
;	ADD	A,n
; [in]
;	%data	n
;
; Flags affected:
;	Z - Set if result is zero.
;	N - Reset.
;	H - Set if carry from bit 3.
;	C - Set if carry from bit 7.
;
	.global	dmgcpu_add
dmgcpu_add:
	ext	0xf		; 	xand	%r12, %r5, 0x0f			; %t0   = 0000AAAA
	and	%r12,%r5
	add	%r5, %r1			; %A    = A+n
	ld.h	[%r4],%r5	; 	xld.h	[%r4+0x0], %r5			; CZ    = -------C zzzzzzzz
	and	%r1,0xf		; 	xand	%r1, %r1, 0x0f		; %data = 0000nnnn
	add	%r12, %r1			; %t0   = 000H----
	ext	0x2		; 	xld.b	[%r4+0x2], %r12			; NH    = --NH---- (N=0)
	ld.b	[%r4],%r12
	ret.d
	ld.ub	%r5, %r5				; %A    = (unsigned char)(A+n) *delay*

;
;	ADC	A,n
; [in]
;	%data	n
;
; Flags affected:
;	Z - Set if result is zero.
;	N - Reset.
;	H - Set if carry from bit 3.
;	C - Set if carry from bit 7.
;
	.global	dmgcpu_adc
dmgcpu_adc:
	ext	0x1		; 	xld.ub	%r13, [%r4+0x1]		; %t1   = -------C
	ld.ub	%r13,[%r4]
	and	%r13,0x1	; 	xand	%r13, %r13, 1			; %t1   = 0000000C
	ext	0xf		; 	xand	%r12, %r5, 0x0f			; %t0   = 0000AAAA
	and	%r12,%r5
	add	%r5, %r1			; %A    = A+n
	add	%r5, %r13				; %A    = A+n+C
	ld.h	[%r4],%r5	; 	xld.h	[%r4+0x0], %r5			; CZ    = -------C zzzzzzzz
	and	%r1,0xf		; 	xand	%r1, %r1, 0x0f		; %data = 0000nnnn
	add	%r12, %r1			; %t0   = 000H----
	add	%r12, %r13
	ext	0x2		; 	xld.b	[%r4+0x2], %r12			; NH    = --NH---- (N=0)
	ld.b	[%r4],%r12
	ret.d
	ld.ub	%r5, %r5				; %A    = (unsigned char)(A+n+C) *delay*

;
;	SUB	n
; [in]
;	%data	n
;
; Flags affected:
;	Z - Set if result is zero.
;	N - Set.
;	H - Set if borrow from bit 4.
;	C - Set if borrow from bit 7.
;
	.global	dmgcpu_sub
dmgcpu_sub:
	ext	0xf		; 	xand	%r12, %r5, 0x0f			; %t0   = 0000AAAA
	and	%r12,%r5
	sub	%r5, %r1			; %A    = A-n
	ld.h	[%r4],%r5	; 	xld.h	[%r4+0x0], %r5			; CZ    = -------C zzzzzzzz
	and	%r1,0xf		; 	xand	%r1, %r1, 0x0f		; %data = 0000nnnn
	sub	%r12, %r1			; %t0   = ---H----
	or	%r12,0x20	; 	xoor	%r12, %r12, -32			; %t0   = 111H----
	ext	0x2		; 	xld.b	[%r4+0x2], %r12			; NH    = --NH---- (N=1)
	ld.b	[%r4],%r12
	ret.d
	ld.ub	%r5, %r5				; %A    = (unsigned char)(A-n) *delay*

;
;	SBC	A,n
; [in]
;	%data	n
;
; Flags affected:
;	Z - Set if result is zero.
;	N - Set.
;	H - Set if borrow from bit 4.
;	C - Set if borrow from bit 7.
;
	.global	dmgcpu_sbc
dmgcpu_sbc:
	ext	0x1		; 	xld.ub	%r13, [%r4+0x1]		; %t1   = -------C
	ld.ub	%r13,[%r4]
	and	%r13,0x1	; 	xand	%r13, %r13, 1			; %t1   = 0000000C
	ext	0xf		; 	xand	%r12, %r5, 0x0f			; %t0   = 0000AAAA
	and	%r12,%r5
	sub	%r5, %r1			; %A    = A-n
	sub	%r5, %r13				; %A    = A-n-C
	ld.h	[%r4],%r5	; 	xld.h	[%r4+0x0], %r5			; CZ    = -------C zzzzzzzz
	and	%r1,0xf		; 	xand	%r1, %r1, 0x0f		; %data = 0000nnnn
	sub	%r12, %r1			; %t0   = 000H----
	sub	%r12, %r13
	or	%r12,0x20	; 	xoor	%r12, %r12, -32			; %t0   = 111H----
	ext	0x2		; 	xld.b	[%r4+0x2], %r12			; NH    = --NH---- (N=1)
	ld.b	[%r4],%r12
	ret.d
	ld.ub	%r5, %r5				; %A    = (unsigned char)(A-n-C) *delay*

;
;	CP	n
; [in]
;	%data	n
;
; Flags affected:
;	Z - Set if result is zero.
;	N - Set.
;	H - Set if borrow from bit 4.
;	C - Set if borrow from bit 7.
;
	.global	dmgcpu_cp
dmgcpu_cp:
	ext	0xf		; 	xand	%r12, %r5, 0x0f			; %t0   = 0000AAAA
	and	%r12,%r5
	ld.w	%r13, %r5				; %t1   = A
	sub	%r13, %r1			; %t1   = A-n
	ld.h	[%r4],%r13	; 	xld.h	[%r4+0x0], %r13			; CZ    = -------C zzzzzzzz
	and	%r1,0xf		; 	xand	%r1, %r1, 0x0f		; %data = 0000nnnn
	sub	%r12, %r1			; %t0   = ---H----
	or	%r12,0x20	; 	xoor	%r12, %r12, -32			; %t0   = 111H----
	ext	0x2		; 	xld.b	[%r4+0x2], %r12			; NH    = --NH---- (N=1)
	ld.b	[%r4],%r12
	ret

;
;	AND	n
; [in]
;	%data	n
;
; Flags affected:
;	Z - Set if result is zero.
;	N - Reset.
;	H - Set.
;	C - Reset.
;
	.global	dmgcpu_and
dmgcpu_and:
	and	%r5, %r1			; %A  = A&n
	ld.h	[%r4],%r5	; 	xld.h	[%r4+0x0], %r5			; CZ  = -------C zzzzzzzz (C=0)
	ld.w	%r12,0x1f	; 	xld.w	%r12, 0x1f				; %t0 = 00011111
	ext	0x2		; 	xld.b	[%r4+0x2], %r12			; NH  = --NH---- (N=0,H=1)
	ld.b	[%r4],%r12
	ret

;
;	OR	n
; [in]
;	%data	n
;
; Flags affected:
;	Z - Set if result is zero.
;	N - Reset.
;	H - Reset.
;	C - Reset.
;
	.global	dmgcpu_or
dmgcpu_or:
	or	%r5, %r1			; %A  = A|n
	ld.h	[%r4],%r5	; 	xld.h	[%r4+0x0], %r5			; CZ  = -------C zzzzzzzz (C=0)
	ext	0x2		; 	xld.b	[%r4+0x2], %r8			; NH  = --NH---- (N=0,H=0)
	ld.b	[%r4],%r8
	ret

;
;	XOR	n
; [in]
;	%data	n
;
; Flags affected:
;	Z - Set if result is zero.
;	N - Reset.
;	H - Reset.
;	C - Reset.
;
	.global	dmgcpu_xor
dmgcpu_xor:
	xor	%r5, %r1			; %A  = A^n
	ld.h	[%r4],%r5	; 	xld.h	[%r4+0x0], %r5			; CZ  = -------C zzzzzzzz (C=0)
	ext	0x2		; 	xld.b	[%r4+0x2], %r8			; NH  = --NH---- (N=0,H=0)
	ld.b	[%r4],%r8
	ret

;
;	INC	r
; [in]
;	%data	r
; [out]
;	%data	r+1
;
; Flags affected:
;	Z - Set if result is zero.
;	N - Reset.
;	H - Set if carry from bit 3.
;	C - Not affected.
;
	.global	dmgcpu_inc
dmgcpu_inc:
	ext	0xf		; 	xand	%r12, %r1, 0x0f		; %t0   = 0000nnnn
	and	%r12,%r1
	add	%r1,0x1		; 	xadd	%r1, %r1, 1			; %data = r+1
	ld.b	[%r4],%r1	; 	xld.b	[%r4+0x0], %r1		; ZF    = zzzzzzzz
	add	%r12,0x1	; 	xadd	%r12, %r12, 1			; %t0   = 000H----
	ext	0x2		; 	xld.b	[%r4+0x2], %r12			; NH    = --NH---- (N=0)
	ld.b	[%r4],%r12
	ret.d
	ld.ub	%r1, %r1			; %data = (unsigned char)(r+1) *delay*

;
;	DEC	r
; [in]
;	%data	r
; [out]
;	%data	r-1
;
; Flags affected:
;	Z - Set if reselt is zero.
;	N - Set.
;	H - Set if borrow from bit 4.
;	C - Not affected.
;
	.global	dmgcpu_dec
dmgcpu_dec:
	ext	0xf		; 	xand	%r12, %r1, 0x0f		; %t0   = 0000nnnn
	and	%r12,%r1
	sub	%r1,0x1		; 	xsub	%r1, %r1, 1			; %data = r-1
	ld.b	[%r4],%r1	; 	xld.b	[%r4+0x0], %r1		; ZF    = zzzzzzzz
	sub	%r12,0x1	; 	xsub	%r12, %r12, 1			; %t0   = ---H----
	or	%r12,0x20	; 	xoor	%r12, %r12, -32			; %t0   = 111H----
	ext	0x2		; 	xld.b	[%r4+0x2], %r12			; NH    = --NH---- (N=1)
	ld.b	[%r4],%r12
	ret.d
	ld.ub	%r1, %r1			; %data = (unsigned char)(r-1) *delay*

;****************************************************************************
;	16-Bit Arithmetic
;****************************************************************************

;
;	ADD	HL,nn
; [in]
;	%data	nn
;
; Flags affected:
;	Z - Not affected.
;	N - Reset.
;	H - Set if carry from bit 11.
;	C - Set if carry from bit 15.
;
	.global	dmgcpu_addw
dmgcpu_addw:
	ext	0x8		; 	xld.uh	%r12, [%r4+0x8]			; %t0   = hlhlhlhl hlhlhlhl
	ld.uh	%r12,[%r4]
	ext	0xfff		; 	xand	%r13, %r12, 0x0fff		; %t1   = 0000hlhl hlhlhlhl
	and	%r13,%r12
	add	%r12, %r1			; %t0   = HL+nn
	ext	0x8		; 	xld.h	[%r4+0x8], %r12			; HL    = HL+nn
	ld.h	[%r4],%r12
	srl	%r12,0x8	; 	xsrl	%r12, 16				; %t0   = -------C
	srl	%r12,0x8
	ext	0x1		; 	xld.b	[%r4+0x1], %r12		; CF    = -------C
	ld.b	[%r4],%r12
	ext	0x3f		; 	xand	%r1, %r1, 0x0fff		; %data = 0000nnnn nnnnnnnn
	and	%r1,0x3f
	add	%r13, %r1			; %t1   = 000H---- --------
	srl	%r13,0x8	; 	xsrl	%r13, 8				; %t1   = 000H----
	ext	0x2		; 	xld.b	[%r4+0x2], %r13			; NH    = --NH---- (N=0)
	ld.b	[%r4],%r13
	ret

;****************************************************************************
;	Miscellaneous
;****************************************************************************

;
;	SWAP	r
; [in]
;	%data	r
; [in]
;	%data	r[7:4]<->r[3:0]
;
; Flags affected:
;	Z - Set if result is zero.
;	N - Reset.
;	H - Reset.
;	C - Reset.
;
	.global	dmgcpu_swap
dmgcpu_swap:
	ld.h	[%r4],%r1	; 	xld.h	[%r4+0x0], %r1		; CF    = -------C zzzzzzzz (C=0)
	;					;         D7:4<->D3:0反転しても零/非零は変わらないので、
	;					;         反転する前にフラグを格納しておくことにします。
	;					;	  こうしておけばret.dのDelaySlotが利用できます。
	ext	0x2		; 	xld.b	[%r4+0x2], %r8			; NH    = --NH---- (N=0,H=0)
	ld.b	[%r4],%r8
	sll	%r1,0x4		; 	xsll	%r1, 4			; %data = 0000abcd efgh0000
	ld.ub	%r12, %r1			; %t0   = 00000000 efgh0000
	srl	%r1,0x8		; 	xsrl	%r1, 8			; %data = 00000000 0000abcd
	ret.d
	or	%r1, %r12			; %data = 00000000 efghabcd *delay*

;****************************************************************************
;	Rotates & Shifts
;****************************************************************************

;
; Flags affected:
;	Z - Set if result is zero.
;	N - Reset.
;	H - Reset.
;	C - Contains old bit 7 data.
;
; [note]
;	* 自己採点: オーソドックスな実装です。70点。
;
	.global	dmgcpu_rl
dmgcpu_rl:
	ext	0x1		; 	xld.ub	%r12, [%r4+0x1]		; %t0   = 00000000 -------C
	ld.ub	%r12,[%r4]
	sll	%r1,0x1		; 	xsll	%r1, 1			; %data = 0000000a bcdefgh0 *anti-interlock*
	and	%r12,0x1	; 	xand	%r12, %r12, 1			; %t0   = 00000000 0000000C
	or	%r1, %r12			; %data = 0000000a bcdefghC
	ld.h	[%r4],%r1	; 	xld.h	[%r4+0x0], %r1		; CZ    = -------C zzzzzzzz
	ext	0x2		; 	xld.b	[%r4+0x2], %r8			; NH    =          --NH---- (N=0,H=0)
	ld.b	[%r4],%r8
	ret.d
	ld.ub	%r1, %r1			; %data = 00000000 bcdefghC *delay*

;
; Flags affected:
;	Z - Set if result is zero.
;	N - Reset.
;	H - Reset.
;	C - Contains old bit 7 data.
;
; [note]
;	* 自己採点: 綺麗に決まった実装です。100点。
;
	.global	dmgcpu_rlc
dmgcpu_rlc:
	sll	%r1,0x1		; 	xsll	%r1, 1			; %data = 0000000a bcdefgh0
	ld.w	%r12, %r1			; %t0   = 0000000a bcdefgh0
	srl	%r1,0x8		; 	xsrl	%r1, 8			; %data = 00000000 0000000a
	or	%r1, %r12			; %data = 0000000a bcdefgha
	ld.h	[%r4],%r1	; 	xld.h	[%r4+0x0], %r1		; CZ    = -------C zzzzzzzz
	ext	0x2		; 	xld.b	[%r4+0x2], %r8			; NH    =          --NH---- (N=0,H=0)
	ld.b	[%r4],%r8
	ret.d
	ld.ub	%r1, %r1			; %data = 00000000 bcdefgha *delay*

;
; Flags affected:
;	Z - Set if result is zero.
;	N - Reset.
;	H - Reset.
;	C - Contains old bit 0 data.
;
; [note]
;	* 自己採点: いまいち…50点。
;
	.global	dmgcpu_rr
dmgcpu_rr:
	ext	0x1		; 	xld.ub	%r12, [%r4+0x1]		; %t0   = 00000000 -------C
	ld.ub	%r12,[%r4]
	ext	0x1		; 	xld.b	[%r4+0x1], %r1		; CF    =          abcdefgh (C=h) *anti-interlock*
	ld.b	[%r4],%r1
	sll	%r12,0x7	; 	xsll	%r12, 7				; %t0   = 0------- C0000000
	srl	%r1,0x1		; 	xsrl	%r1, 1			; %data = 00000000 0abcdefg
	or	%r1, %r12			; %data = 0------- Cabcdefg
	ld.b	[%r4],%r1	; 	xld.b	[%r4+0x0], %r1		; ZF    =          Cabcdefg
	ext	0x2		; 	xld.b	[%r4+0x2], %r8			; NH    =          --NH---- (N=0,H=0)
	ld.b	[%r4],%r8
	ret.d
	ld.ub	%r1, %r1			; %data = 00000000 Cabcdefg *delay*

;
; Flags affected:
;	Z - Set if result is zero.
;	N - Reset.
;	H - Reset.
;	C - Contains old bit 0 data.
;
; [note]
;	* 自己採点: 自画自賛ですが(^^;芸術的です。200点。
;
	.global	dmgcpu_rrc
dmgcpu_rrc:
	sll	%r1,0x7		; 	xsll	%r1, 7			; %data = 0abcdefg h0000000
	ld.b	%r12, %r1			; %t0   = hhhhhhhh h0000000
	srl	%r1,0x8		; 	xsrl	%r1, 8			; %data = 00000000 0abcdefg
	or	%r1, %r12			; %t0   = hhhhhhhh habcdefg
	ld.h	[%r4],%r1	; 	xld.h	[%r4+0x0], %r1		; CZ    = -------C zzzzzzzz
	ext	0x2		; 	xld.b	[%r4+0x2], %r8			; NH    =          --NH---- (N=0,H=0)
	ld.b	[%r4],%r8
	ret.d
	ld.ub	%r1, %r1			; %data = 00000000 habcdefg *delay*

;
; Flags affected:
;	Z - Set if result is zero.
;	N - Reset.
;	H - Reset.
;	C - Contains old bit 7 data.
;
	.global	dmgcpu_sla
dmgcpu_sla:
	sll	%r1,0x1		; 	xsll	%r1, 1			; %data = 0000000a bcdefgh0
	ld.h	[%r4],%r1	; 	xld.h	[%r4+0x0], %r1		; CZ    = -------C zzzzzzzz
	ext	0x2		; 	xld.b	[%r4+0x2], %r8			; NH    =          --NH---- (N=0,H=0)
	ld.b	[%r4],%r8
	ret.d
	ld.ub	%r1, %r1			; %data = 00000000 bcdefgh0 *delay*

;
; Flags affected:
;	Z - Set if result is zero.
;	N - Reset.
;	H - Reset.
;	C - Contains old bit 0 data.
;
	.global	dmgcpu_sra
dmgcpu_sra:
	ext	0x1		; 	xld.b	[%r4+0x1], %r1		; CF    =          abcdefgh (C=h)
	ld.b	[%r4],%r1
	ld.b	%r1, %r1			; %data = aaaaaaaa abcdefgh
	sra	%r1,0x1		; 	xsra	%r1, 1			; %data = aaaaaaaa aabcdefg
	ld.b	[%r4],%r1	; 	xld.b	[%r4+0x0], %r1		; ZF    =          aabcdefg
	ext	0x2		; 	xld.b	[%r4+0x2], %r8			; NH    =          --NH---- (N=0,H=0)
	ld.b	[%r4],%r8
	ret.d
	ld.ub	%r1, %r1			; %data = 00000000 aabcdefg *delay*

;
; Flags affected:
;	Z - Set if result is zero.
;	N - Reset.
;	H - Reset.
;	C - Contains old bit 0 data.
;
	.global	dmgcpu_srl
dmgcpu_srl:
	ext	0x1		; 	xld.b	[%r4+0x1], %r1		; CF    =          abcdefgh (C=h)
	ld.b	[%r4],%r1
	srl	%r1,0x1		; 	xsrl	%r1, 1			; %data = 00000000 0abcdefg
	ld.b	[%r4],%r1	; 	xld.b	[%r4+0x0], %r1		; ZF    =          0abcdefg
	ext	0x2		; 	xld.b	[%r4+0x2], %r8			; NH    =          --NH---- (N=0,H=0)
	ld.b	[%r4],%r8
	ret

;****************************************************************************
;	Bit Opcodes
;****************************************************************************

;
;	BIT	b,r
; [in]
;	%data	r
;	%s0	b
;
; Flags affected:
;	Z - Set if bit b of register r is 0.
;	N - Reset.
;	H - Set.
;	C - Not affected.
;
	.global	dmgcpu_bit
dmgcpu_bit:
	srl	%r1, %r2			; %data = (r>>b) (0≦b≦7なので、xsrlは冗長です)
	and	%r1,0x1		; 	xand	%r1, %r1, 1			; %data = (r>>b)&1
	ld.b	[%r4],%r1	; 	xld.b	[%r4+0x0], %r1		; ZF    = (r>>b)&1
	ld.w	%r12,0x1f	; 	xld.w	%r12, 0x1f				; %t0   = 000HHHHH
	ext	0x2		; 	xld.b	[%r4+0x2], %r12			; NH    = --NH---- (N=0,H=1)
	ld.b	[%r4],%r12
	ret

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

