;
;	framz8ca.s
;
;	P/ECE Z80 Emulator (高速版)
;
;	CLiP - Common Library for P/ECE
;	Copyright (C) 2001-2005 Naoyuki Sawa
;
;	* Mon Jan 10 19:00:00 JST 2005 Naoyuki Sawa
;	- 作成開始。
;	* Mon Mar 07 02:08:00 JST 2005 Naoyuki Sawa
;	- HALT=1の状態でm6502cpu_runが呼ばれたときに、m6502cpu.cycle=0で終了するよう修正。
;	  これまでは、m6502cpu.cycleを変化せずに終了してしまっていたために、
;	  Cycleの端数を次回のm6502cpu_runへ繰り延べるような処理に不具合が生じていました。
;
;#include "clipz8ca.h"
;
;	clipz8ca.h
;
;	P/ECE Z80 Emulator (高速版)
;
;	CLiP - Common Library for P/ECE
;	Copyright (C) 2001-2005 Naoyuki Sawa
;
;	* Mon Jan 10 19:00:00 JST 2005 Naoyuki Sawa
;	- 作成開始。
;

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

;****************************************************************************
;	Z80CPU構造体
;****************************************************************************

; 通常、レジスタに保持するフィールドは、"_.._"というシンボルにしてあります。
; うっかり読み書きして、保持している値との不整合が発生するのを防ぐためです。
				; /*typedef*/ struct _Z80CPU {
;#define _AF_		 0	; unsigned short af;		/* + 0,2 */
;#define BC		 2	; unsigned short bc;		/* + 2,2 */
;#define DE		 4	; unsigned short de;		/* + 4,2 */
;#define HL		 6	; unsigned short hl;		/* + 6,2 */
;#define AF2		 8	; unsigned short af2;		/* + 8,2 */
;#define BC2		10	; unsigned short bc2;		/* +10,2 */
;#define DE2		12	; unsigned short de2;		/* +12,2 */
;#define HL2		14	; unsigned short hl2;		/* +14,2 */
;#define IX		16	; unsigned short ix;		/* +16,2 */
;#define IY		18	; unsigned short iy;		/* +18,2 */
;#define SP		20	; unsigned short sp;		/* +20,2 */
;#define _PC_		22	; unsigned short pc;		/* +22,2 */
;#define R		24	; unsigned char r;		/* +24,1 */
;#define I		25	; unsigned char i;		/* +25,1 */
;#define IM		26	; unsigned char im;		/* +26,1 */
;#define IFF1		27	; unsigned char iff1;		/* +27,1 */
;#define IFF2		28	; unsigned char iff2;		/* +28,1 */
;#define HALT		29	; unsigned char halt;		/* +29,1 */
;#define PENDING		30	; unsigned char pending;	/* +30,1 */
;#define PENDING_NO	31	; unsigned char pending_no;	/* +31,1 */
;#define _CYCLE_		32	; cycle;			/* +32,4 */
;#define IN		36	; Z80CPUIN* in;			/* +36,4 */
;#define OUT		40	; Z80CPUOUT* out;		/* +40,4 */
;#define SIZEOF_Z80CPU	44	; } /*Z80CPU*/;			/* =44   */

;#define _F_		 0
;#define _A_		 1
;#define C		 2
;#define B		 3
;#define E		 4
;#define D		 5
;#define L		 6
;#define H		 7
;#define IXL		16
;#define IXH		17
;#define IYL		18
;#define IYH		19

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

;#define A		r0	; Aレジスタを保持。              [31:8]は常に0。
;#define F		r1	; Fレジスタを(NHCPZS)形式で保持。[31:6]は常に0。
;#define PC		r2	; PCレジスタを(&z80mem[PC])形式で保持。
;#define CYCLE		r3	; 残りCycle数を保持。
;#define CPU		r4	; z80cpuの先頭アドレスに固定。
;#define MEM		r5	; z80memの先頭アドレスに固定。
;#define s0		r6	; 命令ルーチンにて使用。サブルーチンは値を維持する。
;#define s1		r7	; 命令ルーチンにて使用。サブルーチンは値を維持する。
;			r8	; ゼロレジスタ。      (P/ECE仕様)
;			r9	; スクラッチレジスタ。(S1C33仕様)
;#define a0		r10	; 命令ルーチンからサブルーチンへの第一引数／サブルーチンからの戻り値。戻り値が無い場合、サブルーチンは値を破壊する。
;#define a1		r11	; 命令ルーチンからサブルーチンへの第二引数／サブルーチンからの戻り値。戻り値が無い場合、サブルーチンは値を破壊する。
;#define t0		r12	; 命令ルーチンおよびサブルーチンにて使用。サブルーチンは値を破壊する。
;#define t1		r13	; 命令ルーチンおよびサブルーチンにて使用。サブルーチンは値を破壊する。
;#define t2		r14	; 命令ルーチンおよびサブルーチンにて使用。サブルーチンは値を破壊する。
;#define t3		r15	; 命令ルーチンおよびサブルーチンにて使用。サブルーチンは値を破壊する。

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

; * %rFレジスタのフラグビットです。すなわち、F(NHCPZS)の並びです。
; - アルファベット2文字のフラグ名称は、"Undocumented Z80"から借用しました。
;#define SF	0x01
;#define ZF	0x02
;#define PF	0x04
;#define CF	0x08
;#define HF	0x10
;#define NF	0x20

;****************************************************************************
;	8-Bit Load Group
;****************************************************************************

;#define CYCLE_LD_A_n		7
;#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_IXH		8
;#define CYCLE_LD_A_IXL		8
;#define CYCLE_LD_A_IYH		8
;#define CYCLE_LD_A_IYL		8
;#define CYCLE_LD_B_n		7
;#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_IXH		8
;#define CYCLE_LD_B_IXL		8
;#define CYCLE_LD_B_IYH		8
;#define CYCLE_LD_B_IYL		8
;#define CYCLE_LD_C_n		7
;#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_IXH		8
;#define CYCLE_LD_C_IXL		8
;#define CYCLE_LD_C_IYH		8
;#define CYCLE_LD_C_IYL		8
;#define CYCLE_LD_D_n		7
;#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_IXH		8
;#define CYCLE_LD_D_IXL		8
;#define CYCLE_LD_D_IYH		8
;#define CYCLE_LD_D_IYL		8
;#define CYCLE_LD_E_n		7
;#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_IXH		8
;#define CYCLE_LD_E_IXL		8
;#define CYCLE_LD_E_IYH		8
;#define CYCLE_LD_E_IYL		8
;#define CYCLE_LD_H_n		7
;#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_L_n		7
;#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_IXH_n		11
;#define CYCLE_LD_IXH_A		8
;#define CYCLE_LD_IXH_B		8
;#define CYCLE_LD_IXH_C		8
;#define CYCLE_LD_IXH_D		8
;#define CYCLE_LD_IXH_E		8
;#define CYCLE_LD_IXH_IXH	8
;#define CYCLE_LD_IXH_IXL	8
;#define CYCLE_LD_IXL_n		11
;#define CYCLE_LD_IXL_A		8
;#define CYCLE_LD_IXL_B		8
;#define CYCLE_LD_IXL_C		8
;#define CYCLE_LD_IXL_D		8
;#define CYCLE_LD_IXL_E		8
;#define CYCLE_LD_IXL_IXH	8
;#define CYCLE_LD_IXL_IXL	8
;#define CYCLE_LD_IYH_n		11
;#define CYCLE_LD_IYH_A		8
;#define CYCLE_LD_IYH_B		8
;#define CYCLE_LD_IYH_C		8
;#define CYCLE_LD_IYH_D		8
;#define CYCLE_LD_IYH_E		8
;#define CYCLE_LD_IYH_IYH	8
;#define CYCLE_LD_IYH_IYL	8
;#define CYCLE_LD_IYL_n		11
;#define CYCLE_LD_IYL_A		8
;#define CYCLE_LD_IYL_B		8
;#define CYCLE_LD_IYL_C		8
;#define CYCLE_LD_IYL_D		8
;#define CYCLE_LD_IYL_E		8
;#define CYCLE_LD_IYL_IYH	8
;#define CYCLE_LD_IYL_IYL	8

;#define CYCLE_LD_A_IlmI		13
;#define CYCLE_LD_A_IBCI		7
;#define CYCLE_LD_A_IDEI		7
;#define CYCLE_LD_A_IHLI		7
;#define CYCLE_LD_B_IHLI		7
;#define CYCLE_LD_C_IHLI		7
;#define CYCLE_LD_D_IHLI		7
;#define CYCLE_LD_E_IHLI		7
;#define CYCLE_LD_H_IHLI		7
;#define CYCLE_LD_L_IHLI		7
;#define CYCLE_LD_A_IIX_dI	19
;#define CYCLE_LD_B_IIX_dI	19
;#define CYCLE_LD_C_IIX_dI	19
;#define CYCLE_LD_D_IIX_dI	19
;#define CYCLE_LD_E_IIX_dI	19
;#define CYCLE_LD_H_IIX_dI	19
;#define CYCLE_LD_L_IIX_dI	19
;#define CYCLE_LD_A_IIY_dI	19
;#define CYCLE_LD_B_IIY_dI	19
;#define CYCLE_LD_C_IIY_dI	19
;#define CYCLE_LD_D_IIY_dI	19
;#define CYCLE_LD_E_IIY_dI	19
;#define CYCLE_LD_H_IIY_dI	19
;#define CYCLE_LD_L_IIY_dI	19

;#define CYCLE_LD_IlmI_A		13
;#define CYCLE_LD_IHLI_n		10
;#define CYCLE_LD_IBCI_A		7
;#define CYCLE_LD_IDEI_A		7
;#define CYCLE_LD_IHLI_A		7
;#define CYCLE_LD_IHLI_B		7
;#define CYCLE_LD_IHLI_C		7
;#define CYCLE_LD_IHLI_D		7
;#define CYCLE_LD_IHLI_E		7
;#define CYCLE_LD_IHLI_H		7
;#define CYCLE_LD_IHLI_L		7
;#define CYCLE_LD_IIX_dI_n	19
;#define CYCLE_LD_IIY_dI_n	19
;#define CYCLE_LD_IIX_dI_A	19
;#define CYCLE_LD_IIX_dI_B	19
;#define CYCLE_LD_IIX_dI_C	19
;#define CYCLE_LD_IIX_dI_D	19
;#define CYCLE_LD_IIX_dI_E	19
;#define CYCLE_LD_IIX_dI_H	19
;#define CYCLE_LD_IIX_dI_L	19
;#define CYCLE_LD_IIY_dI_A	19
;#define CYCLE_LD_IIY_dI_B	19
;#define CYCLE_LD_IIY_dI_C	19
;#define CYCLE_LD_IIY_dI_D	19
;#define CYCLE_LD_IIY_dI_E	19
;#define CYCLE_LD_IIY_dI_H	19
;#define CYCLE_LD_IIY_dI_L	19

;#define CYCLE_LD_A_I		9
;#define CYCLE_LD_A_R		9
;#define CYCLE_LD_I_A		9
;#define CYCLE_LD_R_A		9

;****************************************************************************
;	16-Bit Load Group
;****************************************************************************

;#define CYCLE_LD_SP_HL		6
;#define CYCLE_LD_SP_IX		10
;#define CYCLE_LD_SP_IY		10

;#define CYCLE_LD_BC_lm		10
;#define CYCLE_LD_DE_lm		10
;#define CYCLE_LD_HL_lm		10
;#define CYCLE_LD_SP_lm		10
;#define CYCLE_LD_IX_lm		14
;#define CYCLE_LD_IY_lm		14

;#define CYCLE_LD_BC_IlmI	20
;#define CYCLE_LD_DE_IlmI	20
;#define CYCLE_LD_HL_IlmI	16
;#define CYCLE_LD_SP_IlmI	20
;#define CYCLE_LD_IX_IlmI	20
;#define CYCLE_LD_IY_IlmI	20

;#define CYCLE_LD_IlmI_BC	20
;#define CYCLE_LD_IlmI_DE	20
;#define CYCLE_LD_IlmI_HL	16
;#define CYCLE_LD_IlmI_SP	20
;#define CYCLE_LD_IlmI_IX	20
;#define CYCLE_LD_IlmI_IY	20

;#define CYCLE_POP_AF		10
;#define CYCLE_POP_BC		10
;#define CYCLE_POP_DE		10
;#define CYCLE_POP_HL		10
;#define CYCLE_POP_IX		14
;#define CYCLE_POP_IY		14

;#define CYCLE_PUSH_AF		11
;#define CYCLE_PUSH_BC		11
;#define CYCLE_PUSH_DE		11
;#define CYCLE_PUSH_HL		11
;#define CYCLE_PUSH_IX		15
;#define CYCLE_PUSH_IY		15

;****************************************************************************
;	Exchange, Block Transfer, and Search Group
;****************************************************************************

;#define CYCLE_EX_ISPI_HL	19
;#define CYCLE_EX_ISPI_IX	23
;#define CYCLE_EX_ISPI_IY	23
;#define CYCLE_EX_AF_AF2		4
;#define CYCLE_EX_DE_HL		4
;#define CYCLE_EXX		4

;#define CYCLE_LDI		16
;#define CYCLE_LDIR		16
;#define CYCLE_LDD		16
;#define CYCLE_LDDR		16

;#define CYCLE_CPI		16
;#define CYCLE_CPIR		16
;#define CYCLE_CPD		16
;#define CYCLE_CPDR		16

;****************************************************************************
;	8-Bit Arithmetic Group
;****************************************************************************

;#define CYCLE_ADD_A_n		7
;#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_IXH		8
;#define CYCLE_ADD_A_IXL		8
;#define CYCLE_ADD_A_IYH		8
;#define CYCLE_ADD_A_IYL		8
;#define CYCLE_ADD_A_IHLI	7
;#define CYCLE_ADD_A_IIX_dI	19
;#define CYCLE_ADD_A_IIY_dI	19

;#define CYCLE_ADC_A_n		7
;#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_IXH		8
;#define CYCLE_ADC_A_IXL		8
;#define CYCLE_ADC_A_IYH		8
;#define CYCLE_ADC_A_IYL		8
;#define CYCLE_ADC_A_IHLI	7
;#define CYCLE_ADC_A_IIX_dI	19
;#define CYCLE_ADC_A_IIY_dI	19

;#define CYCLE_SUB_n		7
;#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_IXH		8
;#define CYCLE_SUB_IXL		8
;#define CYCLE_SUB_IYH		8
;#define CYCLE_SUB_IYL		8
;#define CYCLE_SUB_IHLI		7
;#define CYCLE_SUB_IIX_dI	19
;#define CYCLE_SUB_IIY_dI	19

;#define CYCLE_SBC_A_n		7
;#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_IXH		8
;#define CYCLE_SBC_A_IXL		8
;#define CYCLE_SBC_A_IYH		8
;#define CYCLE_SBC_A_IYL		8
;#define CYCLE_SBC_A_IHLI	7
;#define CYCLE_SBC_A_IIX_dI	19
;#define CYCLE_SBC_A_IIY_dI	19

;#define CYCLE_AND_n		7
;#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_IXH		8
;#define CYCLE_AND_IXL		8
;#define CYCLE_AND_IYH		8
;#define CYCLE_AND_IYL		8
;#define CYCLE_AND_IHLI		7
;#define CYCLE_AND_IIX_dI	19
;#define CYCLE_AND_IIY_dI	19

;#define CYCLE_OR_n		7
;#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_IXH		8
;#define CYCLE_OR_IXL		8
;#define CYCLE_OR_IYH		8
;#define CYCLE_OR_IYL		8
;#define CYCLE_OR_IHLI		7
;#define CYCLE_OR_IIX_dI		19
;#define CYCLE_OR_IIY_dI		19

;#define CYCLE_XOR_n		7
;#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_IXH		8
;#define CYCLE_XOR_IXL		8
;#define CYCLE_XOR_IYH		8
;#define CYCLE_XOR_IYL		8
;#define CYCLE_XOR_IHLI		7
;#define CYCLE_XOR_IIX_dI	19
;#define CYCLE_XOR_IIY_dI	19

;#define CYCLE_CP_n		7
;#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_IXH		8
;#define CYCLE_CP_IXL		8
;#define CYCLE_CP_IYH		8
;#define CYCLE_CP_IYL		8
;#define CYCLE_CP_IHLI		7
;#define CYCLE_CP_IIX_dI		19
;#define CYCLE_CP_IIY_dI		19

;#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_IXH		8
;#define CYCLE_INC_IXL		8
;#define CYCLE_INC_IYH		8
;#define CYCLE_INC_IYL		8
;#define CYCLE_INC_IHLI		11
;#define CYCLE_INC_IIX_dI	23
;#define CYCLE_INC_IIY_dI	23

;#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_IXH		8
;#define CYCLE_DEC_IXL		8
;#define CYCLE_DEC_IYH		8
;#define CYCLE_DEC_IYL		8
;#define CYCLE_DEC_IHLI		11
;#define CYCLE_DEC_IIX_dI	23
;#define CYCLE_DEC_IIY_dI	23

;****************************************************************************
;	General-Purpose Arithmetic and CPU Control Group
;****************************************************************************

;#define CYCLE_DAA		4
;#define CYCLE_CPL		4
;#define CYCLE_NEG		8
;#define CYCLE_CCF		4
;#define CYCLE_SCF		4
;#define CYCLE_NOP		4
;#define CYCLE_HALT		4
;#define CYCLE_DI		4
;#define CYCLE_EI		4
;#define CYCLE_IM_0		8
;#define CYCLE_IM_1		8
;#define CYCLE_IM_2		8

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

;#define CYCLE_ADD_HL_BC		11
;#define CYCLE_ADD_HL_DE		11
;#define CYCLE_ADD_HL_HL		11
;#define CYCLE_ADD_HL_SP		11
;#define CYCLE_ADD_IX_BC		15
;#define CYCLE_ADD_IX_DE		15
;#define CYCLE_ADD_IX_IX		15
;#define CYCLE_ADD_IX_SP		15
;#define CYCLE_ADD_IY_BC		15
;#define CYCLE_ADD_IY_DE		15
;#define CYCLE_ADD_IY_IY		15
;#define CYCLE_ADD_IY_SP		15

;#define CYCLE_ADC_HL_BC		15
;#define CYCLE_ADC_HL_DE		15
;#define CYCLE_ADC_HL_HL		15
;#define CYCLE_ADC_HL_SP		15

;#define CYCLE_SBC_HL_BC		15
;#define CYCLE_SBC_HL_DE		15
;#define CYCLE_SBC_HL_HL		15
;#define CYCLE_SBC_HL_SP		15

;#define CYCLE_INC_BC		6
;#define CYCLE_INC_DE		6
;#define CYCLE_INC_HL		6
;#define CYCLE_INC_SP		6
;#define CYCLE_INC_IX		10
;#define CYCLE_INC_IY		10

;#define CYCLE_DEC_BC		6
;#define CYCLE_DEC_DE		6
;#define CYCLE_DEC_HL		6
;#define CYCLE_DEC_SP		6
;#define CYCLE_DEC_IX		10
;#define CYCLE_DEC_IY		10

;****************************************************************************
;	Rotate and Shift Group
;****************************************************************************

;#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		15
;#define CYCLE_RL_IaddrI		23

;#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		15
;#define CYCLE_RLC_IaddrI	23

;#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		15
;#define CYCLE_RR_IaddrI		23

;#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		15
;#define CYCLE_RRC_IaddrI	23

;#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		15
;#define CYCLE_SLA_IaddrI	23

;#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		15
;#define CYCLE_SRA_IaddrI	23

;#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		15
;#define CYCLE_SRL_IaddrI	23

;#define CYCLE_RLD		18
;#define CYCLE_RRD		18

;****************************************************************************
;	Bit Set, Reset, and Test Group
;****************************************************************************

;#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_0_IaddrI	20
;#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_1_IaddrI	20
;#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_2_IaddrI	20
;#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_3_IaddrI	20
;#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_4_IaddrI	20
;#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_5_IaddrI	20
;#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_6_IaddrI	20
;#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_BIT_7_IaddrI	20

;#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	15
;#define CYCLE_SET_0_IaddrI	23
;#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	15
;#define CYCLE_SET_1_IaddrI	23
;#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	15
;#define CYCLE_SET_2_IaddrI	23
;#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	15
;#define CYCLE_SET_3_IaddrI	23
;#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	15
;#define CYCLE_SET_4_IaddrI	23
;#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	15
;#define CYCLE_SET_5_IaddrI	23
;#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	15
;#define CYCLE_SET_6_IaddrI	23
;#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	15
;#define CYCLE_SET_7_IaddrI	23

;#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	15
;#define CYCLE_RES_0_IaddrI	23
;#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	15
;#define CYCLE_RES_1_IaddrI	23
;#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	15
;#define CYCLE_RES_2_IaddrI	23
;#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	15
;#define CYCLE_RES_3_IaddrI	23
;#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	15
;#define CYCLE_RES_4_IaddrI	23
;#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	15
;#define CYCLE_RES_5_IaddrI	23
;#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	15
;#define CYCLE_RES_6_IaddrI	23
;#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	15
;#define CYCLE_RES_7_IaddrI	23

;****************************************************************************
;	Jump Group
;****************************************************************************

;#define CYCLE_JP_IHLI		4
;#define CYCLE_JP_IIXI		8
;#define CYCLE_JP_IIYI		8

;#define CYCLE_JP_lm		10
;#define CYCLE_JP_Z_lm		10
;#define CYCLE_JP_NZ_lm		10
;#define CYCLE_JP_C_lm		10
;#define CYCLE_JP_NC_lm		10
;#define CYCLE_JP_PE_lm		10
;#define CYCLE_JP_PO_lm		10
;#define CYCLE_JP_M_lm		10
;#define CYCLE_JP_P_lm		10

;#define CYCLE_JR_e		12
;#define CYCLE_JR_Z_e		7
;#define CYCLE_JR_NZ_e		7
;#define CYCLE_JR_C_e		7
;#define CYCLE_JR_NC_e		7

;#define CYCLE_DJNZ_e		8

;****************************************************************************
;	Call and Return Group
;****************************************************************************

;#define CYCLE_CALL_lm		17
;#define CYCLE_CALL_Z_lm		10
;#define CYCLE_CALL_NZ_lm	10
;#define CYCLE_CALL_C_lm		10
;#define CYCLE_CALL_NC_lm	10
;#define CYCLE_CALL_PE_lm	10
;#define CYCLE_CALL_PO_lm	10
;#define CYCLE_CALL_M_lm		10
;#define CYCLE_CALL_P_lm		10

;#define CYCLE_RET		10
;#define CYCLE_RET_Z		5
;#define CYCLE_RET_NZ		5
;#define CYCLE_RET_C		5
;#define CYCLE_RET_NC		5
;#define CYCLE_RET_PE		5
;#define CYCLE_RET_PO		5
;#define CYCLE_RET_M		5
;#define CYCLE_RET_P		5

;#define CYCLE_RETI		14
;#define CYCLE_RETN		14

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

;****************************************************************************
;	Input and Output Group
;****************************************************************************

;#define CYCLE_IN_A_ICI		12
;#define CYCLE_IN_B_ICI		12
;#define CYCLE_IN_C_ICI		12
;#define CYCLE_IN_D_ICI		12
;#define CYCLE_IN_E_ICI		12
;#define CYCLE_IN_H_ICI		12
;#define CYCLE_IN_L_ICI		12
;#define CYCLE_IN_A_InI		11

;#define CYCLE_INI		16
;#define CYCLE_INIR		16
;#define CYCLE_IND		16
;#define CYCLE_INDR		16

;#define CYCLE_OUT_ICI_A		12
;#define CYCLE_OUT_ICI_B		12
;#define CYCLE_OUT_ICI_C		12
;#define CYCLE_OUT_ICI_D		12
;#define CYCLE_OUT_ICI_E		12
;#define CYCLE_OUT_ICI_H		12
;#define CYCLE_OUT_ICI_L		12
;#define CYCLE_OUT_InI_A		11

;#define CYCLE_OUTI		16
;#define CYCLE_OTIR		16
;#define CYCLE_OUTD		16
;#define CYCLE_OTDR		16

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

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

	.code
	.align 2

	; 高速化のため、Z80CPU構造体を高速RAMに配置します。
	.global z80cpu
z80cpu:
	.space 44

	.code
	.align 1

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

	.global z80cpu_run
z80cpu_run:
	pushn  %r3
	;
	ext	z80cpu+0x20@ah	; 	xld.w [z80cpu+0x20], %r12	; 実行コンテキストを取り出します。
	ext	z80cpu+0x20@al
	ld.w	[%r8],%r12
	ext	z80cpu_enter@rm	; 	xcall  z80cpu_enter
	call	z80cpu_enter@rl
	;
	ext	0x1d		; 	xbtst [%r4+0x1d], 0x0		; 既にHALT中ならば、残り実行サイクル数を0にして、
	btst	[%r4],0x0
	jreq   2			;  すぐにループを抜けます。(z80cpu.cycle=0で終了。)
	ld.w   %r3, 0		; (skip?)
	;
	jp	z80cpu_run_LOOP	; 	xjp    z80cpu_run_LOOP		; Cycle=0が指定された場合のために、まず条件判定から。
z80cpu_run_DO:
;----------------------------------------------------------------------------
;/#define Z80CPU_RUN_TRACE
;#ifdef Z80CPU_RUN_TRACE
;	; トレースデバッグを行う場合は、このブロックを有効にしてください。
;	; その際、z80cpu_trace()は、アプリケーションにて定義してください。
;	; z80cpu_trace()は、ライブラリ内では定義していません。
;	xcall  z80cpu_leave
;	xcall  z80cpu_trace
;	xcall  z80cpu_enter
;#endif /*Z80CPU_RUN_TRACE*/
;----------------------------------------------------------------------------
	ld.ub  %r12, [%r2]+		; OpCodeを取得し、PCを進めます。
	sll	%r12,0x2	; 	xsll   %r12, 2			; OpCodeに対応する命令ルーチンを呼び出します。
	ext    z80cpu_XXops@ah
	ext    z80cpu_XXops@al
	ld.w   %r12, [%r12]
	call   %r12
z80cpu_run_LOOP:
	cmp	%r3,0x0		; 	xcmp   %r3, 0		; Cycleが0以下になるまで繰り返します。
	jrgt	z80cpu_run_DO	; 	xjrgt  z80cpu_run_DO
	;
	ext	z80cpu_leave@rm	; 	xcall  z80cpu_leave		; 実行コンテキストを書き戻します。
	call	z80cpu_leave@rl
	;
	popn   %r3
	ret

;
;	CB xx
;	   ++- OpCode
;
	.global z80cpu_CB
z80cpu_CB:
	ld.ub %r12, [%r2]+		; OpCode
	sll	%r12,0x2	; 	xsll  %r12, 2
	ext z80cpu_CBops@ah
	ext z80cpu_CBops@al
	ld.w  %r12, [%r12]
	jp    %r12

;
;	ED xx
;	   ++- OpCode
;
	.global z80cpu_ED
z80cpu_ED:
	ld.ub %r12, [%r2]+		; OpCode
	sll	%r12,0x2	; 	xsll  %r12, 2
	ext z80cpu_EDops@ah
	ext z80cpu_EDops@al
	ld.w  %r12, [%r12]
	jp %r12

;
;	DD xx
;	   ++- OpCode
;
	.global z80cpu_DD
z80cpu_DD:
	ld.ub %r12, [%r2]+		; OpCode
	sll	%r12,0x2	; 	xsll  %r12, 2
	ext z80cpu_DDops@ah
	ext z80cpu_DDops@al
	ld.w  %r12, [%r12]
	jp %r12

;
;	FD xx
;	   ++- OpCode
;
	.global z80cpu_FD
z80cpu_FD:
	ld.ub %r12, [%r2]+		; OpCode
	sll	%r12,0x2	; 	xsll  %r12, 2
	ext z80cpu_FDops@ah
	ext z80cpu_FDops@al
	ld.w  %r12, [%r12]
	jp %r12

;
;	DD CB d xx
;	      | ++- OpCode
;	      +---- IX+"d"
;
; [note]
;	* DD CB d xx 系列の命令は全て同じバイト構成で、[IX+d]を引数に取ります。
;	  あらかじめここで、&z80ram[IX+d]のメモリアドレスを求めておきます。
;	  これ以降は、FD CB d xx 系列と同じなので、命令ルーチンを共有できます。
;	* DD CB d xx 系列の命令ルーチンは %s0 = mem+IX+d の引数で呼び出されます。
;	  命令ルーチンの中で、メモリアドレスを計算する必要はありません。
;	* DD CB d xx 系列の命令ルーチンには xxx_IaddrI という名前を付けました。
;	  (z80cpu_RLC_IaddrI、z80cpu_BIT_0_IaddrI など)
;
	.global z80cpu_DDCB
z80cpu_DDCB:
	ext	0x10		; 	xld.uh %r6, [%r4+0x10]		; %s0 = &z80mem[IX+d(signed)]
	ld.uh	%r6,[%r4]
	ld.b   %r12, [%r2]+
	add    %r6, %r12
	add    %r6, %r5
	ld.ub  %r12, [%r2]+		; OpCode
	sll	%r12,0x2	; 	xsll   %r12, 2
	ext z80cpu_XXCBops@ah		; 
	ext z80cpu_XXCBops@al
	ld.w   %r12, [%r12]
	jp     %r12

;
;	FD CB d xx
;	      | ++- OpCode
;	      +---- IY+"d"
;
; [note]
;	* FD CB d xx 系列の命令は全て同じバイト構成で、[IY+d]を引数に取ります。
;	  あらかじめここで、&z80ram[IY+d]のメモリアドレスを求めておきます。
;	  これ以降は、DD CB d xx 系列と同じなので、命令ルーチンを共有できます。
;	* FD CB d xx 系列の命令ルーチンは %s0 = mem+IX+d の引数で呼び出されます。
;	  命令ルーチンの中で、メモリアドレスを計算する必要はありません。
;	* FD CB d xx 系列の命令ルーチンには xxx_IaddrI という名前を付けました。
;	  (z80cpu_RLC_IaddrI、z80cpu_BIT_0_IaddrI など)
;
	.global z80cpu_FDCB
z80cpu_FDCB:
	ext	0x12		; 	xld.uh %r6, [%r4+0x12]		; %s0 = &z80mem[IY+d(signed)]
	ld.uh	%r6,[%r4]
	ld.b   %r12, [%r2]+
	add    %r6, %r12
	add    %r6, %r5
	ld.ub  %r12, [%r2]+		; OpCode
	sll	%r12,0x2	; 	xsll   %r12, 2
	ext z80cpu_XXCBops@ah
	ext z80cpu_XXCBops@al
	ld.w   %r12, [%r12]
	jp     %r12

;****************************************************************************
;	16-Bit Load Group
;****************************************************************************

;
;	PUSH rr
;
; [in]
;	%a0		rr
;
	.global z80cpu_push
z80cpu_push:
	ext	0x14		; 	xld.uh %r12, [%r4+0x14]		; %t0 = SP
	ld.uh	%r12,[%r4]
	add    %r12, %r5		; %t0 = mem+SP
	rr	%r10,0x8	; 	xrr    %r10, 8			; %a0[7:0] = hi(rr)
	sub	%r12,0x1	; 	xsub   %r12, %r12, 1		; %t0 = mem+SP-1
	ld.b  [%r12], %r10		; [mem+SP-1] = hi(rr)
	rl	%r10,0x8	; 	xrl    %r10, 8			; %a0[7:0] = lo(rr)
	sub	%r12,0x1	; 	xsub   %r12, %r12, 1		; %t0 = mem+SP-2
	ld.b  [%r12], %r10		; [mem+SP-2] = lo(rr)
	sub    %r12, %r5		; %s0 = SP-2
	ext	0x14		; 	xld.h [%r4+0x14], %r12		; SP = SP-2
	ld.h	[%r4],%r12
	ret

;
;	POP rr
;
; [out]
;	%a0		rr
;
	.global z80cpu_pop
z80cpu_pop:
	ext	0x14		; 	xld.uh %r12, [%r4+0x14]		; %t0 = SP
	ld.uh	%r12,[%r4]
	add    %r12, %r5		; %t0 = mem+SP
	ld.ub  %r10, [%r12]+		; %a0 = [mem+SP+0], %t0 = mem+SP+1
	ld.ub  %r11, [%r12]+		; %a1 = [mem+SP+1], %t0 = mem+SP+2
	sub    %r12, %r5		; %t0 = SP+2
	ext	0x14		; 	xld.h [%r4+0x14], %r12		; SP  = SP+2
	ld.h	[%r4],%r12
	sll	%r11,0x8	; 	xsll   %r11, 8			; %a0 = lo(rr)|hi(rr)<<8
	ret.d
	or     %r10, %r11			; *delay*

;****************************************************************************
;	8-Bit Arithmetic Group
;****************************************************************************

;
;	ADD A, r
;
;	S	is set if result is negative, reset otherwise
;	Z	is set if result is zero, reset otherwise
;	H	is set if carry from bit 3, reset otherwise
;	P/V	is set if overflow, reset otherwise
;	N	is reset
;	C	is set if carry from bit 7, reset otherwise
;
; [in]
;	%a0	r
;
	.global z80cpu_add8
z80cpu_add8:
	swap %r12, %r0			; %t0[31:24] = A
	swap %r13, %r10			; %t1[31:24] = r
	add  %r12, %r13			; %t0[31:24] = A+r
	;
	ld.w %r1, %psr			; %F = F(00CPZS)
	and	%r1,0xf		; 	xand %r1, %r1, 0xf
	and	%r0,0xf		; 	xand %r0, %r0, 0xf		; %F = F(0HCPZS)
	and	%r10,0xf	; 	xand %r10, %r10, 0xf
	add  %r0, %r10
	and	%r0,0x10	; 	xand %r0, %r0, 0x10
	or   %r1, %r0
	;
	ret.d
	swap %r0, %r12			; %A = A+r *delay*

;
;	ADC A, r
;
;	S	is set if result is negative, reset otherwise
;	Z	is set if result is zero, reset otherwise
;	H	is set if carry from bit 3, reset otherwise
;	P/V	is set if overflow, reset otherwise
;	N	is reset
;	C	is set if carry from bit 7: reset otherwise
;
; [in]
;	%a0	r
;
	.global z80cpu_adc8
z80cpu_adc8:
	ld.w  %r14, %psr			; %t2 = F(C)
	and	%r14,0x37	; 	xand  %r14, %r14, -9
	and	%r1,0x8		; 	xand  %r1, %r1, 0x08
	or    %r14, %r1
	;
	swap  %r12, %r0			; %t0[31:24] = A
	swap  %r13, %r10			; %t1[31:24] = r
	ext	0x1f		; 	xoor  %r13, %r13, 0xffffff	; %t1[23: 0] = 0xffffff
	ext	0x1fff
	or	%r13,0x3f
	ld.w  %psr, %r14			; %t0[31:24] = A+r+F(C)
	adc   %r12, %r13
	;
	ld.w  %r1, %psr			; %F = F(00CP0S)
	and	%r1,0xd		; 	xand  %r1, %r1, 0xd		; (%t0[23:0]不定のため、%psr(Z)は未確定です)
	and	%r0,0xf		; 	xand  %r0, %r0, 0xf		; %F = F(0HCP0S)
	and	%r10,0xf	; 	xand  %r10, %r10, 0xf
	ld.w  %psr, %r14
	adc   %r0, %r10
	and	%r0,0x10	; 	xand  %r0, %r0, 0x10
	or    %r1, %r0
	;
	swap  %r0, %r12			; %A[7:0] = A+r+F(C)
	ld.ub %r0, %r0			; %A = A+r+F(C)
	or    %r0, %r0			; %F = F(0HCPZS)
	jrne  2
	add   %r1, 0x02			; (skip?)
	ret

;
;	SUB r
;
;	S	is set if result is negative, reset otherwise
;	Z	is set if result is zero, reset otherwise
;	H	is set if borrow from bit 4, reset otherwise
;	P/V	is set if overflow, reset otherwise
;	N	is set
;	C	is set if borrow, reset otherwise
;
; [in]
;	%a0	r
;
	.global z80cpu_sub8
z80cpu_sub8:
	swap %r12, %r0			; %t0[31:24] = A
	swap %r13, %r10			; %t1[31:24] = r
	sub  %r12, %r13			; %t0[31:24] = A-r
	;
	ld.w %r1, %psr			; %F = F(00CPZS)
	and	%r1,0xf		; 	xand %r1, %r1, 0xf
	add	%r1,0x20	; 	xadd %r1, %r1, 0x20			; %F = F(N0CPZS)
	and	%r0,0xf		; 	xand %r0, %r0, 0xf		; %F = F(NHCPZS)
	and	%r10,0xf	; 	xand %r10, %r10, 0xf
	sub  %r0, %r10
	and	%r0,0x10	; 	xand %r0, %r0, 0x10
	or   %r1, %r0
	;
	ret.d
	swap %r0, %r12			; %A = A-r *delay*

;
;	SBC A, r
;
;	S	is set if result is negative, reset otherwise
;	Z	is set if result is zero, reset otherwise
;	H	is set if borrow from bit 4, reset otherwise
;	P/V	is reset if overflow, reset otherwise
;	N	is set
;	C	is set if borrow, reset otherwise
;
; [in]
;	%a0	r
;
	.global z80cpu_sbc8
z80cpu_sbc8:
	ld.w  %r14, %psr			; %t2 = F(C)
	and	%r14,0x37	; 	xand  %r14, %r14, -9
	and	%r1,0x8		; 	xand  %r1, %r1, 0x08
	or    %r14, %r1
	;
	swap  %r12, %r0			; %t0[31:24] = A
	swap  %r13, %r10			; %t1[31:24] = r
	ld.w  %psr, %r14			; %t0[31:24] = A-r-F(C)
	sbc   %r12, %r13
	;
	ld.w  %r1, %psr			; %F = F(00CP0S)
	and	%r1,0xd		; 	xand  %r1, %r1, 0xd		; (%t0[23:0]不定のため、%psr(Z)は未確定です)
	add	%r1,0x20	; 	xadd  %r1, %r1, 0x20		; %F = F(N0CP0S)
	and	%r0,0xf		; 	xand  %r0, %r0, 0xf		; %F = F(NHCP0S)
	and	%r10,0xf	; 	xand  %r10, %r10, 0xf
	ld.w  %psr, %r14
	sbc   %r0, %r10
	and	%r0,0x10	; 	xand  %r0, %r0, 0x10
	or    %r1, %r0
	;
	swap  %r0, %r12			; %A[7:0] = A-r-F(C)
	ld.ub %r0, %r0			; %A = A-r-F(C)
	or    %r0, %r0			; %F = F(NHCPZS)
	jrne  2
	add   %r1, 0x02			; (skip?)
	ret

;
;	AND r
;
;	S	is set if result is negative, reset otherwise
;	Z	is set if result is zero, reset otherwise
;	H	is set
;	P/V	is set if parity is even, reset otherwise
;	N	is reset
;	C	is reset
;
; [in]
;	%a0	r
;
	.global z80cpu_and
z80cpu_and:
	swap  %r12, %r0			; %t0[31:24] = A
	swap  %r13, %r10			; %t1[31:24] = r
	and   %r12, %r13			; %t0[31:24] = A&r
	;
	ld.w  %r1, %psr			; %F = F(0000ZS)
	and	%r1,0x3		; 	xand  %r1, %r1, 0x3
	add	%r1,0x10	; 	xadd  %r1, %r1, 0x10		; %F = F(0N00ZS)
	swap  %r0, %r12			; %A = A&r
	ext z80cpu_parity@ah		; %F = F(0N0PZS)
	ext z80cpu_parity@al
	ld.ub %r12, [%r0]
	ret.d
	or    %r1, %r12			; *delay*

;
;	OR r
;
;	S	is set if result is negative, reset otherwise
;	Z	is set if result is zero, reset otherwise
;	H	is reset
;	P/V	is set if parity is even, reset otherwise
;	N	is reset
;	C	is reset
;
; [in]
;	%a0	r
;
	.global z80cpu_or
z80cpu_or:
	swap  %r12, %r0			; %t0[31:24] = A
	swap  %r13, %r10			; %t1[31:24] = r
	or    %r12, %r13			; %t0[31:24] = A|r
	;
	ld.w  %r1, %psr			; %F = F(0000ZS)
	and	%r1,0x3		; 	xand  %r1, %r1, 0x3
	swap  %r0, %r12			; %A = A|r
	ext z80cpu_parity@ah		; %F = F(000PZS)
	ext z80cpu_parity@al
	ld.ub %r12, [%r0]
	ret.d
	or    %r1, %r12			; *delay*

;
;	XOR r
;
;	S	is set if result is negative, reset otherwise
;	Z	is set if result is zero, reset otherwise
;	H	is reset
;	P/V	is set if parity is even, reset otherwise
;	N	is reset
;	C	is reset
;
; [in]
;	%a0	r
;
	.global z80cpu_xor
z80cpu_xor:
	swap  %r12, %r0			; %t0[31:24] = A
	swap  %r13, %r10			; %t1[31:24] = r
	xor   %r12, %r13			; %t0[31:24] = A^r
	;
	ld.w  %r1, %psr			; %F = F(0000ZS)
	and	%r1,0x3		; 	xand  %r1, %r1, 0x3
	swap  %r0, %r12			; %A = A^r
	ext z80cpu_parity@ah		; %F = F(000PZS)
	ext z80cpu_parity@al
	ld.ub %r12, [%r0]
	ret.d
	or    %r1, %r12			; *delay*

;
;	CP r
;
;	S	is set if result is negative, reset otherwise
;	Z	is set if result is zero, reset otherwise
;	H	is set if borrow from bit 4, reset otherwise
;	P/V	is set if overflow, reset otherwise
;	N	is set
;	C	is set if borrow, reset otherwise
;
; [in]
;	%a0	r
;
	.global z80cpu_cp
z80cpu_cp:
	swap %r12, %r0			; %t0[31:24] = A
	swap %r13, %r10			; %t1[31:24] = r
	cmp  %r12, %r13			; %t0[31:24] = A-r
	;
	ld.w %r1, %psr			; %F = F(00CPZS)
	and	%r1,0xf		; 	xand %r1, %r1, 0xf
	add	%r1,0x20	; 	xadd %r1, %r1, 0x20			; %F = F(N0CPZS)
	ext	0xf		; 	xand %r12, %r0, 0xf		; %F = F(NHCPZS)
	and	%r12,%r0
	and	%r10,0xf	; 	xand %r10, %r10, 0xf
	sub  %r12, %r10
	and	%r12,0x10	; 	xand %r12, %r12, 0x10
	;
	ret.d
	or   %r1, %r12			; *delay*

;
;	INC r
;
;	S	is set if result is negative, reset otherwise
;	Z	is set if result is zero, reset otherwise
;	H	is set if carry from bit 3, reset otherwise
;	P/V	is set if r was 7FH before operation, reset otherwise
;	N	is reset
;	C	is not affected
;
; [in]
;	%a0	r
; [out]
;	%a0	r+1
;
	.global z80cpu_inc8
z80cpu_inc8:
	ext	0x8		; 	xand %r13, %r1, 0x08		; %t1 = F(00C0000)
	and	%r13,%r1
	swap %r12, %r10			; %t0[31:24] = r
	ext	0x20		; 	xadd %r12, %r12, 0x1000000		; %t0[31:24] = r+1
	ext	0x0
	add	%r12,0x0
	;
	ld.w %r1, %psr			; %F = F(000PZS)
	and	%r1,0x7		; 	xand %r1, %r1, 0x7
	and	%r10,0xf	; 	xand %r10, %r10, 0xf		; %F = F(0H0PZS)
	add	%r10,0x1	; 	xadd %r10, %r10, 1
	and	%r10,0x10	; 	xand %r10, %r10, 0x10
	or   %r1, %r10
	or   %r1, %r13			; %F = F(0HCPZS)
	;
	ret.d
	swap %r10, %r12			; %a0 = r+1 *delay*

;
;	DEC r
;
;	S	is set if result is negative, reset otherwise
;	Z	is set if result is zero, reset otherwise
;	H	is set if borrow from bit 4, reset otherwise
;	P/V	is set if m was 80H before operation, reset otherwise
;	N	is set
;	C	is not affected
;
; [in]
;	%a0	r
; [out]
;	%a0	r-1
;
	.global z80cpu_dec8
z80cpu_dec8:
	ext	0x8		; 	xand %r13, %r1, 0x08		; %t1 = F(00C0000)
	and	%r13,%r1
	swap %r12, %r10			; %t0[31:24] = r
	ext	0x20		; 	xsub %r12, %r12, 0x1000000		; %t0[31:24] = r-1
	ext	0x0
	sub	%r12,0x0
	;
	ld.w %r1, %psr			; %F = F(000PZS)
	and	%r1,0x7		; 	xand %r1, %r1, 0x7
	add	%r1,0x20	; 	xadd %r1, %r1, 0x20			; %F = F(N00PZS)
	and	%r10,0xf	; 	xand %r10, %r10, 0xf		; %F = F(NH0PZS)
	sub	%r10,0x1	; 	xsub %r10, %r10, 1
	and	%r10,0x10	; 	xand %r10, %r10, 0x10
	or   %r1, %r10
	or   %r1, %r13			; %F = F(NHCPZS)
	;
	ret.d
	swap %r10, %r12			; %a0 = r-1 *delay*

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

;
;	ADD rr, ss
;
;	S	is not affected
;	Z	is not affected
;	H	is set if carry out of bit 11, reset otherwise
;	P/V	is not affected
;	N	is reset
;	C	is set if carry from bit 15, reset otherwise
;
; [in]
;	%a0	rr
;	%a1	ss
; [out]
;	%a0	rr+ss
;
	.global z80cpu_add16
z80cpu_add16:
	ext	0x7		; 	xand %r14, %r1, 0x7		; %t2 = F(000PZS)
	and	%r14,%r1
	ld.w %r12, %r10			; %t0[31:16] = rr
	sll	%r12,0x8	; 	xsll %r12, 16
	sll	%r12,0x8
	ld.w %r13, %r11			; %t1[31:16] = ss
	sll	%r13,0x8	; 	xsll %r13, 16
	sll	%r13,0x8
	add  %r12, %r13			; %t0[31:16] = rr+ss
	;
	ld.w %r1, %psr			; %F = F(00C000)
	and	%r1,0x8		; 	xand %r1, %r1, 0x08
	ext	0x3f		; 	xand %r10, %r10, 0xfff		; %F = F(0HC000)
	and	%r10,0x3f
	ext	0x3f		; 	xand %r11, %r11, 0xfff
	and	%r11,0x3f
	add  %r10, %r11
	srl	%r10,0x8	; 	xsrl %r10, 8
	and	%r10,0x10	; 	xand %r10, %r10, 0x10
	or   %r1, %r10
	or   %r1, %r14			; %F = F(0HCPZS)
	;
	srl	%r12,0x8	; 	xsrl %r12, 16			; %t0 = rr+ss
	srl	%r12,0x8
	ret.d
	ld.w %r10, %r12			; %a0 = rr+ss *delay*

;
;	ADC rr, ss
;
;	S	is set if result is negative, reset otherwise
;	Z	is set if result is zero, reset otherwise
;	H	is set if carry out of bit 11, reset otherwise
;	P/V	is set if overflow, reset otherwise
;	N	is reset
;	C	is set if carry from bit 15, reset otherwise
;
; [in]
;	%a0	rr
;	%a1	ss
; [out]
;	%a0	rr+ss+F(C)
;
	.global z80cpu_adc16
z80cpu_adc16:
	ld.w %r14, %psr			; %t2 = F(C)
	and	%r14,0x37	; 	xand %r14, %r14, -9
	and	%r1,0x8		; 	xand %r1, %r1, 0x08
	or   %r14, %r1
	;
	ld.w %r12, %r10			; %t0[31:16] = rr
	sll	%r12,0x8	; 	xsll %r12, 16
	sll	%r12,0x8
	ld.w %r13, %r11			; %t1[31:16] = ss
	sll	%r13,0x8	; 	xsll %r13, 16
	sll	%r13,0x8
	ext	0x3ff		; 	xoor %r13, %r13, 0xffff	; %t1[15: 0] = 0xffff
	or	%r13,0x3f
	ld.w %psr, %r14			; %t0[31:16] = rr+ss+F(C)
	adc  %r12, %r13
	;
	ld.w %r1, %psr			; %F = F(00CP0S)
	and	%r1,0xd		; 	xand %r1, %r1, 0xd		; (%t0[15:0]不定のため、%psr(Z)は未確定です)
	ext	0x3f		; 	xand %r10, %r10, 0xfff		; %F = F(0HCP0S)
	and	%r10,0x3f
	ext	0x3f		; 	xand %r11, %r11, 0xfff
	and	%r11,0x3f
	ld.w %psr, %r14
	adc  %r10, %r11
	srl	%r10,0x8	; 	xsrl %r10, 8
	and	%r10,0x10	; 	xand %r10, %r10, 0x10
	or   %r1, %r10
	;
	srl	%r12,0x8	; 	xsrl %r12, 16			; %t0 = rr+ss+F(C)
	srl	%r12,0x8
	jrne 2				; %F = F(0HCPZS)
	add  %r1, 0x02			; (skip?)
	ret.d
	ld.w %r10, %r12			; %a0 = rr+ss+F(C) *delay*

;
;	SBC rr, ss
;
;	S is set if result is negative, reset otherwise
;	Z is set if result is zero, reset otherwise
;	H is set if a borrow from bit 12, reset otherwise
;	P/V is set if overflow, reset otherwise
;	N is set
;	C is set if borrow, reset otherwise
;
; [in]
;	%a0	rr
;	%a1	ss
; [out]
;	%a0	rr-ss-F(C)
;
	.global z80cpu_sbc16
z80cpu_sbc16:
	ld.w %r14, %psr			; %t2 = F(C)
	and	%r14,0x37	; 	xand %r14, %r14, -9
	and	%r1,0x8		; 	xand %r1, %r1, 0x08
	or   %r14, %r1
	;
	ld.w %r12, %r10			; %t0[31:16] = rr
	sll	%r12,0x8	; 	xsll %r12, 16
	sll	%r12,0x8
	ld.w %r13, %r11			; %t1[31:16] = ss
	sll	%r13,0x8	; 	xsll %r13, 16
	sll	%r13,0x8
	ld.w %psr, %r14			; %t0[31:16] = rr-ss-F(C)
	sbc  %r12, %r13
	;
	ld.w %r1, %psr			; %F = F(00CP0S)
	and	%r1,0xd		; 	xand %r1, %r1, 0xd		; (%t0[15:0]不定のため、%psr(Z)は未確定です)
	add	%r1,0x20	; 	xadd %r1, %r1, 0x20			; %F = F(N0CP0S)
	ext	0x3f		; 	xand %r10, %r10, 0xfff		; %F = F(NHCP0S)
	and	%r10,0x3f
	ext	0x3f		; 	xand %r11, %r11, 0xfff
	and	%r11,0x3f
	ld.w %psr, %r14
	sbc  %r10, %r11
	srl	%r10,0x8	; 	xsrl %r10, 8
	and	%r10,0x10	; 	xand %r10, %r10, 0x10
	or   %r1, %r10
	;
	srl	%r12,0x8	; 	xsrl %r12, 16			; %t0 = rr-ss-F(C)
	srl	%r12,0x8
	jrne 2				; %F = F(NHCPZS)
	add  %r1, 0x02			; (skip?)
	ret.d
	ld.w %r10, %r12			; %a0 = rr-ss-F(C) *delay*

;****************************************************************************
;	Rotate and Shift Group
;****************************************************************************

;
;	RL r
;
;	S	is set if result is negative, reset otherwise
;	Z	is set if result is zero, reset otherwise
;	H	is reset
;	P/V	is set if parity is even, reset otherwise
;	N	is reset
;	C	is data from bit 7 of source register
;
; [in]
;	%a0	r
; [out]
;	%a0	RL r
;
	.global z80cpu_rl
z80cpu_rl:
;;	ld.w  %t0, %a0			; %t0 = 0:rrrrrrrr
;;	xsll  %a0, 1			; %a0 = r:rrrrrrr0
;;	xand  %F, %F, CF		; %F  = 0:0000C000
;;	xsrl  %F, 3-0			; %F  = 0:0000000C
;;	or    %a0, %F			; %a0 = r:rrrrrrrC
;;	ld.b  %a0, %a0			; %a0 = ?:rrrrrrrC (signed)
;;	or    %a0, %a0			; (%psrへ反映するために必要です)
;;	;
;;	ld.w  %F, %psr			; %F  = F(000000ZS)
;;	and   %F, ZF|SF
;;	xsrl  %t0, 7-3			; %t0 = 0:0000rrrr
;;	xand  %t0, %t0, CF		; %t0 = 0:0000r000
;;	or    %F, %t0			; %F  = F(0000C0ZS)
;;	ld.ub %a0, %a0			; %a0 = 0:rrrrrrrC (unsigned)
;;	ext z80cpu_parity@ah		; %t0 = F(00000P00)
;;	ext z80cpu_parity@al
;;	ld.ub %t0, [%a0]
;;	ret.d
;;	or    %F, %t0			; %F  = F(0000CPZS) *delay*
;;↓僅かに高速化しました。たぶん大丈夫だと思うけれど、しばらく様子見です。
	ld.w  %r12, %r10			; %t0 = 0:rrrrrrrr
	sll	%r10,0x1	; 	xsll  %r10, 1			; %a0 = r:rrrrrrr0          -+- この二行を逆にすると間違いです。
	ld.b  %r10, %r10			; %a0 = ?:rrrrrrr0 (signed) -+  逆にしないよう注意してください!!
	and	%r1,0x8		; 	xand  %r1, %r1, 0x08		; %F  = 0:0000C000
	srl	%r1,0x3		; 	xsrl  %r1, 0x3			; %F  = 0:0000000C
	or    %r10, %r1			; %a0 = ?:rrrrrrrC (signed)
	;
	ld.w  %r1, %psr			; %F  = F(000000ZS)
	and   %r1, 0x3
	srl	%r12,0x4	; 	xsrl  %r12, 0x4			; %t0 = 0:0000rrrr
	and	%r12,0x8	; 	xand  %r12, %r12, 0x08		; %t0 = 0:0000r000
	or    %r1, %r12			; %F  = F(0000C0ZS)
	ld.ub %r10, %r10			; %a0 = 0:rrrrrrrC (unsigned)
	ext z80cpu_parity@ah		; %t0 = F(00000P00)
	ext z80cpu_parity@al
	ld.ub %r12, [%r10]
	ret.d
	or    %r1, %r12			; %F  = F(0000CPZS) *delay*

;
;	RLC r
;
;	S	is set if result is negative, reset otherwise
;	Z	is set if result is zero, reset otherwise
;	H	is reset
;	P/V	is set if parity is even, reset otherwise
;	N	is reset
;	C	is data from bit 7 of source register
;
; [in]
;	%a0	r
; [out]
;	%a0	RLC r
;
	.global z80cpu_rlc
z80cpu_rlc:
;;	ld.w  %t0, %a0			; %t0 = 0:rrrrrrrr
;;	ld.w  %t1, %a0			; %t1 = 0:rrrrrrrr
;;	xsll  %a0, 1			; %a0 = r:rrrrrrr0
;;	xsrl  %t1, 7			; %t1 = 0:0000000r
;;	or    %a0, %t1			; %a0 = r:rrrrrrrr
;;	ld.b  %a0, %a0			; %a0 = ?:rrrrrrrr (signed)
;;	or    %a0, %a0			; (%psrへ反映するために必要です)
;;	;
;;	ld.w  %F, %psr			; %F  = F(000000ZS)
;;	and   %F, ZF|SF
;;	xsrl  %t0, 7-3			; %t0 = 0:0000rrrr
;;	xand  %t0, %t0, CF		; %t0 = 0:0000r000
;;	or    %F, %t0			; %F  = F(0000C0ZS)
;;	ld.ub %a0, %a0			; %a0 = 0:rrrrrrrC (unsigned)
;;	ext z80cpu_parity@ah		; %t0 = F(00000P00)
;;	ext z80cpu_parity@al
;;	ld.ub %t0, [%a0]
;;	ret.d
;;	or    %F, %t0			; %F  = F(0000CPZS) *delay*
;;↓僅かに高速化しました。たぶん大丈夫だと思うけれど、しばらく様子見です。
	ld.w  %r12, %r10			; %t0 = 0:rrrrrrrr
	ld.w  %r13, %r10			; %t1 = 0:rrrrrrrr
	sll	%r10,0x1	; 	xsll  %r10, 1			; %a0 = r:rrrrrrr0          -+- この二行を逆にすると間違いです。
	ld.b  %r10, %r10			; %a0 = ?:rrrrrrr0 (signed) -+  逆にしないよう注意してください!!
	srl	%r13,0x7	; 	xsrl  %r13, 7			; %t1 = 0:0000000r
	or    %r10, %r13			; %a0 = ?:rrrrrrrr (signed)
	;
	ld.w  %r1, %psr			; %F  = F(000000ZS)
	and   %r1, 0x3
	srl	%r12,0x4	; 	xsrl  %r12, 0x4			; %t0 = 0:0000rrrr
	and	%r12,0x8	; 	xand  %r12, %r12, 0x08		; %t0 = 0:0000r000
	or    %r1, %r12			; %F  = F(0000C0ZS)
	ld.ub %r10, %r10			; %a0 = 0:rrrrrrrC (unsigned)
	ext z80cpu_parity@ah		; %t0 = F(00000P00)
	ext z80cpu_parity@al
	ld.ub %r12, [%r10]
	ret.d
	or    %r1, %r12			; %F  = F(0000CPZS) *delay*

;
;	RR r
;
;	S	is set if result is negative, reset otherwise
;	Z	is set if result is zero, reset otherwise
;	H	is reset
;	P/V	is set if parity is even, reset otherwise
;	N	is reset
;	C	is data from bit 0 of source register
;
; [in]
;	%a0	r
; [out]
;	%a0	RR r
;
	.global z80cpu_rr
z80cpu_rr:
;;	ld.w  %t0, %a0			; %t0 = 0:rrrrrrrr
;;	xsrl  %a0, 1			; %a0 = 0:0rrrrrrr
;;	xand  %F, %F, CF		; %F  = 0:0000C000
;;	xsll  %F, 7-3			; %F  = 0:C0000000
;;	or    %a0, %F			; %a0 = 0:Crrrrrrr
;;	ld.b  %a0, %a0			; %a0 = ?:Crrrrrrr (signed)
;;	or    %a0, %a0			; (%psrへ反映するために必要です)
;;	;
;;	ld.w  %F, %psr			; %F  = F(000000ZS)
;;	and   %F, ZF|SF
;;	xsll  %t0, 3-0			; %t0 = r:rrrrr000
;;	xand  %t0, %t0, CF		; %t0 = 0:0000r000
;;	or    %F, %t0			; %F  = F(0000C0ZS)
;;	ld.ub %a0, %a0			; %a0 = 0:Crrrrrrr (unsigned)
;;	ext z80cpu_parity@ah		; %t0 = F(00000P00)
;;	ext z80cpu_parity@al
;;	ld.ub %t0, [%a0]
;;	ret.d
;;	or    %F, %t0			; %F  = F(0000CPZS) *delay*
;;↓僅かに高速化しました。たぶん大丈夫だと思うけれど、しばらく様子見です。
	ld.w  %r12, %r10			; %t0 = 0:rrrrrrrr
	srl	%r10,0x1	; 	xsrl  %r10, 1			; %a0 = 0:0rrrrrrr
	and	%r1,0x8		; 	xand  %r1, %r1, 0x08		; %F  = 0:0000C000
	sll	%r1,0x4		; 	xsll  %r1, 0x4			; %F  = 0:C0000000          -+- この二行を逆にすると間違いです。
	ld.b  %r1, %r1			; %F  = ?:C0000000 (signed) -+  逆にしないよう注意してください!!
	or    %r10, %r1			; %a0 = ?:Crrrrrrr (signed)
	;
	ld.w  %r1, %psr			; %F  = F(000000ZS)
	and   %r1, 0x3
	sll	%r12,0x3	; 	xsll  %r12, 0x3			; %t0 = r:rrrrr000
	and	%r12,0x8	; 	xand  %r12, %r12, 0x08		; %t0 = 0:0000r000
	or    %r1, %r12			; %F  = F(0000C0ZS)
	ld.ub %r10, %r10			; %a0 = 0:Crrrrrrr (unsigned)
	ext z80cpu_parity@ah		; %t0 = F(00000P00)
	ext z80cpu_parity@al
	ld.ub %r12, [%r10]
	ret.d
	or    %r1, %r12			; %F  = F(0000CPZS) *delay*

;
;	RRC r
;
;	S	is set if result is negative, reset otherwise
;	Z	is set if result is zero, reset otherwise
;	H	is reset
;	P/V	is set if parity is even, reset otherwise
;	N	is reset
;	C	is data from bit 0 of source register
;
; [in]
;	%a0	r
; [out]
;	%a0	RRC r
;
	.global z80cpu_rrc
z80cpu_rrc:
;;	ld.w  %t0, %a0			; %t0 = 0:rrrrrrrr
;;	ld.w  %t1, %a0			; %t1 = 0:rrrrrrrr
;;	xsrl  %a0, 1			; %a0 = 0:0rrrrrrr
;;	xsll  %t1, 7			; %t1 = r:r0000000
;;	or    %a0, %t1			; %a0 = r:rrrrrrrr
;;	ld.b  %a0, %a0			; %a0 = ?:rrrrrrrr (signed)
;;	or    %a0, %a0			; (%psrへ反映するために必要です)
;;	;
;;	ld.w  %F, %psr			; %F  = F(000000ZS)
;;	and   %F, ZF|SF
;;	xsll  %t0, 3-0			; %t0 = r:rrrrr000
;;	xand  %t0, %t0, CF		; %t0 = 0:0000r000
;;	or    %F, %t0			; %F  = F(0000C0ZS)
;;	ld.ub %a0, %a0			; %a0 = 0:Crrrrrrr (unsigned)
;;	ext z80cpu_parity@ah		; %t0 = F(00000P00)
;;	ext z80cpu_parity@al
;;	ld.ub %t0, [%a0]
;;	ret.d
;;	or    %F, %t0			; %F  = F(0000CPZS) *delay*
;;↓僅かに高速化しました。たぶん大丈夫だと思うけれど、しばらく様子見です。
	ld.w  %r12, %r10			; %t0 = 0:rrrrrrrr
	ld.w  %r13, %r10			; %t1 = 0:rrrrrrrr
	srl	%r10,0x1	; 	xsrl  %r10, 1			; %a0 = 0:0rrrrrrr
	sll	%r13,0x7	; 	xsll  %r13, 7			; %t1 = r:r0000000          -+- この二行を逆にすると間違いです。
	ld.b  %r13, %r13			; %t1 = ?:r0000000 (signed) -+  逆にしないよう注意してください!!
	or    %r10, %r13			; %a0 = ?:rrrrrrrr (signed)
	;
	ld.w  %r1, %psr			; %F  = F(000000ZS)
	and   %r1, 0x3
	sll	%r12,0x3	; 	xsll  %r12, 0x3			; %t0 = r:rrrrr000
	and	%r12,0x8	; 	xand  %r12, %r12, 0x08		; %t0 = 0:0000r000
	or    %r1, %r12			; %F  = F(0000C0ZS)
	ld.ub %r10, %r10			; %a0 = 0:Crrrrrrr (unsigned)
	ext z80cpu_parity@ah		; %t0 = F(00000P00)
	ext z80cpu_parity@al
	ld.ub %r12, [%r10]
	ret.d
	or    %r1, %r12			; %F  = F(0000CPZS) *delay*

;
;	SLA r
;
;	S	is set if result is negative, reset otherwise
;	Z	is set if result is zero, reset otherwise
;	H	is reset
;	P/V	is set if parity is even, reset otherwise
;	N	is reset
;	C	is data from bit 7
;
; [in]
;	%a0	r
; [out]
;	%a0	SLA r
;
	.global z80cpu_sla
z80cpu_sla:
	ld.w  %r12, %r10			; %t0 = 0:rrrrrrrr
	sll	%r10,0x1	; 	xsll  %r10, 1			; %a0 = r:rrrrrrr0
	ld.b  %r10, %r10			; %a0 = ?:rrrrrrr0 (signed)
	or    %r10, %r10			; (%psrへ反映するために必要です)
	;
	ld.w  %r1, %psr			; %F  = F(000000ZS)
	and   %r1, 0x3
	srl	%r12,0x4	; 	xsrl  %r12, 0x4			; %t0 = 0:0000rrrr
	and	%r12,0x8	; 	xand  %r12, %r12, 0x08		; %t0 = 0:0000r000
	or    %r1, %r12			; %F  = F(0000C0ZS)
	ld.ub %r10, %r10			; %a0 = 0:rrrrrrr0 (unsigned)
	ext z80cpu_parity@ah		; %t0 = F(00000P00)
	ext z80cpu_parity@al
	ld.ub %r12, [%r10]
	ret.d
	or    %r1, %r12			; %F  = F(0000CPZS) *delay*

;
;	SRA r
;
;	S	is set if result is negative, reset otherwise
;	Z	is set if result is zero, reset otherwise
;	H	is reset
;	P/V	is set if parity is even, reset otherwise
;	N	is reset
;	C	is data from bit 0 of source register
;
; [in]
;	%a0	r
; [out]
;	%a0	SRA r
;
	.global z80cpu_sra
z80cpu_sra:
	ld.w  %r12, %r10			; %t0 = 0:rrrrrrrr
	ld.b  %r10, %r10			; %a0 = ?:rrrrrrrr (signed) -+- この二行を逆にすると間違いです。
	sra	%r10,0x1	; 	xsra  %r10, 1			; %a0 = ?:?rrrrrrr (signed) -+  逆にしないよう注意してください!!
	;
	ld.w  %r1, %psr			; %F  = F(000000ZS)
	and   %r1, 0x3
	sll	%r12,0x3	; 	xsll  %r12, 0x3			; %t0 = r:rrrrr000
	and	%r12,0x8	; 	xand  %r12, %r12, 0x08		; %t0 = 0:0000r000
	or    %r1, %r12			; %F  = F(0000C0ZS)
	ld.ub %r10, %r10			; %a0 = 0:?rrrrrrr (unsigned)
	ext z80cpu_parity@ah		; %t0 = F(00000P00)
	ext z80cpu_parity@al
	ld.ub %r12, [%r10]
	ret.d
	or    %r1, %r12			; %F  = F(0000CPZS) *delay*

;
;	SRL r
;
;	S	is reset
;	Z	is set if result is zero, reset otherwise
;	H	is reset
;	P/V	is set if parity is even, reset otherwise
;	N	is reset
;	C	is data from bit 0 of source register
;
; [in]
;	%a0	r
; [out]
;	%a0	SRL r
;
	.global z80cpu_srl
z80cpu_srl:
	ld.w %r12, %r10			; %t0 = 0:rrrrrrrr
	srl	%r10,0x1	; 	xsrl %r10, 1			; %a0 = 0:0rrrrrrr
	;
	ld.w  %r1, %psr			; %F  = F(000000ZS)
	and   %r1, 0x3
	sll	%r12,0x3	; 	xsll  %r12, 0x3			; %t0 = r:rrrrr000
	and	%r12,0x8	; 	xand  %r12, %r12, 0x08		; %t0 = 0:0000r000
	or    %r1, %r12			; %F  = F(0000C0ZS)
	ext z80cpu_parity@ah		; %t0 = F(00000P00)
	ext z80cpu_parity@al
	ld.ub %r12, [%r10]
	ret.d
	or    %r1, %r12			; %F  = F(0000CPZS) *delay*

;****************************************************************************
;	Bit Set, Reset, and Test Group
;****************************************************************************

;
;	BIT b, r
;
;	S	is unknown
;		  ↓Undoc'd
;		  (b=7)かつ(r[7]=1)の場合にset、さもなくばresetされます。
;		  SG-1000用チョップリフターは、この挙動に依存しています。
;	Z	is set if specified bit is 0, reset otherwise
;	H	is set
;	P/V	is unknown
;		  ↓Undoc'd
;		  Zフラグと同じ値になります。
;	N	is reset
;	C	is not affected
;
; [in]
;	%a0	b
;	%a1	r
;
	.global z80cpu_bit
z80cpu_bit:
	and	%r1,0x8		; 	xand  %r1, %r1, 0x08		; %F = F(00C000)
	add	%r1,0x10	; 	xadd  %r1, %r1, 0x10		; %F = F(0HC000)
	;
	ext	0x20		; 	xld.w %r12, 0x1000000		; %t0[31:24] = 1<<b
	ext	0x0
	ld.w	%r12,0x0
	sll   %r12, %r10			; (0≦%a0≦7なので、xsllは必要ありません)
	swap  %r11, %r11			; %a1[31:24] = r
	and   %r11, %r12			; %a1[31:24] = r&(1<<b)
	;
	ld.w  %r12, %psr
	jrne.d 3
	and   %r12, 0x3		; %t0 = F(0000ZS) *delay*
	add   %r12, 0x04			; %t0 = F(000PZS) (skip?)
	;
	ret.d
	or    %r1, %r12			; %F  = F(0HCPZS) *delay*

;****************************************************************************
;	Input and Output Group
;****************************************************************************

;
;	IN r, (C)
;
;	S	is set if input data is negative, reset otherwise
;	Z	is set if input data is zero, reset otherwise
;	H	is reset
;	P/V	is set if parity is even, reset otherwise
;	N	is reset
;	C	is not affected
;
; [out]
;	%a0	r
;
; [note]
;	* %a0 は %r10 の別名です。
;	  誤って破壊しないよう、注意してください。
;
	.global z80cpu_in
z80cpu_in:
	sub	%sp,0x2		; 	xsub   %sp, %sp, 8
	ld.w	[%sp+0x0],%r6	; 	xld.w [%sp+0x0], %r6		; %r6退避
	ld.w	[%sp+0x1],%r7	; 	xld.w [%sp+0x4], %r7		; %r7退避
	;
	ext	0x24		; 	xld.w  %r11, [%r4+0x24]		; %r11 = IN
	ld.w	%r11,[%r4]
	ext	0x2		; 	xld.uh %r12, [%r4+0x2]		; %r12 = BC (アドレスバスのbit15-8にはBレジスタの値が出力されます)
	ld.uh	%r12,[%r4]
	call   %r11			; %r10 = IN (C)
	ld.ub  %r10, %r10		; (戻り値のbit31-8をClear。必要です!!)
	ext	z80cpu+0x0@h	; 	xld.w  %r4, z80cpu		; %r4復元
	ext	z80cpu+0x0@m
	ld.w	%r4,z80cpu+0x0@l
	ext	z80mem+0x0@h	; 	xld.w  %r5, z80mem		; %r5復元
	ext	z80mem+0x0@m
	ld.w	%r5,z80mem+0x0@l
	;
	and	%r1,0x8		; 	xand   %r1, %r1, 0x08		; %F  = F(00C000)
	ld.b   %r12, %r10			; %t0 = IN (C) (signed)
	or     %r12, %r12			; (%psrへ反映するために必要です)
	ld.w   %r12, %psr		; %t0 = F(0000ZS)
	and	%r12,0x3	; 	xand   %r12, %r12, 0x3
	or     %r1, %r12			; %F  = F(00C0ZS)
	ext z80cpu_parity@ah		; %t0 = F(000P00)
	ext z80cpu_parity@al
	ld.ub  %r12, [%r10]
	or     %r1, %r12			; %F  = F(00CPZS)
	;
	ld.w	%r6,[%sp+0x0]	; 	xld.w  %r6, [%sp+0x0]		; %r6復元
	ld.w	%r7,[%sp+0x1]	; 	xld.w  %r7, [%sp+0x4]		; %r6復元
	add	%sp,0x2		; 	xadd   %sp, %sp, 8
	ret

;
;	OUT (C), r
;
;	Condition Bits Affected: None
;
; [in]
;	%a0	r
;
; [note]
;	* %a0 は %r10 の別名です。
;	  誤って破壊しないよう、注意してください。
;
	.global z80cpu_out
z80cpu_out:
	sub	%sp,0x2		; 	xsub   %sp, %sp, 8
	ld.w	[%sp+0x0],%r6	; 	xld.w [%sp+0x0], %r6		; %r6退避
	ld.w	[%sp+0x1],%r7	; 	xld.w [%sp+0x4], %r7		; %r7退避
	;
	ext	0x28		; 	xld.w  %r11, [%r4+0x28]		; %r11 = OUT
	ld.w	%r11,[%r4]
	ext	0x2		; 	xld.uh %r12, [%r4+0x2]		; %r12 = BC (アドレスバスのbit15-8にはBレジスタの値が出力されます)
	ld.uh	%r12,[%r4]
	call.d %r11			; OUT (C), r
	ld.w   %r13, %r10		; %r13 = r *delay*
	ext	z80cpu+0x0@h	; 	xld.w  %r4, z80cpu		; %r4復元
	ext	z80cpu+0x0@m
	ld.w	%r4,z80cpu+0x0@l
	ext	z80mem+0x0@h	; 	xld.w  %r5, z80mem		; %r5復元
	ext	z80mem+0x0@m
	ld.w	%r5,z80mem+0x0@l
	;
	ld.w	%r6,[%sp+0x0]	; 	xld.w  %r6, [%sp+0x0]		; %r6復元
	ld.w	%r7,[%sp+0x1]	; 	xld.w  %r7, [%sp+0x4]		; %r6復元
	add	%sp,0x2		; 	xadd   %sp, %sp, 8
	ret

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