;	
;	framdmga.s
;
;	P/ECE DMG-CPU Emulator
;
;	CLiP - Common Library for P/ECE
;	Copyright (C) 2001-2004 Naoyuki Sawa
;
;	* Thu Jan 15 20:09:00 JST 2004 Naoyuki Sawa
;	- 作成開始。
;
#include "clipdmga.h"
#ifdef DMG_ASM

	.code
	.align 1

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

;
;	DMG構造体
;
;===== レジスタ =====
#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 AF	 0
#define BC	 2
#define DE	 4
#define HL	 6
#define SP	 8
#define PC	10
;===== 内部状態 =====
#define IME	12
#define HALT	13
#define CYCLE	20
;===== 外部関数 =====
#define READ	24
#define WRITE	28

;
;	C33=>DMGフラグ変換表
;
;	注意!!
;	C33のNフラグは符号フラグ、DMGのNフラグは加減算フラグであり、別物です。
;	DMGは符号フラグを持っていません。
;
				; C33(C,V,Z,N) => DMG(Z,-,-,C)
				; ====C33====     ====DMG====
dmg_FLAG_CONV:			; ----CVZN        ZNHC----
	.byte	0x00		; 00000000 00     00000000 00
	.byte	0x00		; 00000001 01     00000000 00
	.byte	0x80		; 00000010 02     10000000 80
	.byte	0x80		; 00000011 03     10000000 80
	.byte	0x00		; 00000100 04     00000000 00
	.byte	0x00		; 00000101 05     00000000 00
	.byte	0x80		; 00000110 06     10000000 80
	.byte	0x80		; 00000111 07     10000000 80
	.byte	0x10		; 00001000 08     00010000 10
	.byte	0x10		; 00001001 09     00010000 10
	.byte	0x90		; 00001010 0a     10010000 90
	.byte	0x90		; 00001011 0b     10010000 90
	.byte	0x10		; 00001100 0c     00010000 10
	.byte	0x10		; 00001101 0d     00010000 10
	.byte	0x90		; 00001110 0e     10010000 90
	.byte	0x90		; 00001111 0f     10010000 90

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

	.global dmg_run
dmg_run:
	pushn %r3
	xsub %sp, %sp, 4
	;
	ld.w %r0, %r12			; dmg
	xld.w %r3, [%r0+READ]		; dmg->read
	xld.w [%r0+CYCLE], %r13		; CYCLE
	xcmp %r13, 0			; if(CYCLE <= 0) break
	xjrle dmg_run_EXIT
	;
dmg_run_LOOP:
	xld.ub %r10, [%r0+HALT]		; if(HALT) break
	xld.uh %r1, [%r0+PC]		; PC *anti-interlock*
	xcmp %r10, 0
	xjrne dmg_run_EXIT
	;
	ld.w %r12, %r0			; code = dmg->read(dmg, PC++)
	ld.uh %r13, %r1
	call.d %r3
	add %r1, 1			; *delay*
	ld.w %r13, %r10
	;
	xld.w %r2, dmg_op_table		; op = &dmg_op_table[code]
	xsll %r10, 3
	add %r2, %r10
	;
	xld.ub %r10, [%r2+4]		; argc == 0 ?
	xcmp %r10, 0	
	xjreq dmg_run_L10
	xld.b [%sp+0], %r13		; (save code)
	;
	ld.w %r12, %r0			; LO(arg) = dmg->read(dmg, PC++)
	ld.uh %r13, %r1
	call.d %r3
	add %r1, 1			; *delay*
	ld.w %r14, %r10
	;
	xld.ub %r10, [%r2+4]		; argc == 1 ?
	xcmp %r10, 1	
	xjreq dmg_run_L20
	xld.b [%sp+1], %r14		; (save LO(arg))
	;
	ld.w %r12, %r0			; HI(arg) = dmg->read(dmg, PC++)
	ld.w %r13, %r1
	call.d %r3
	add %r1, 1			; *delay*
	;
	xld.ub %r14, [%sp+1]		; (restore LO(arg))
	xsll %r10, 8			; *anti-interlock*
	or %r14, %r10			; arg = LO(arg) | HI(arg) << 8
dmg_run_L20:
	xld.ub %r13, [%sp+0]		; (restore code)
dmg_run_L10:
	;
	xld.w %r10, [%r2+0]		; op->proc(dmg, code, arg1, arg2)
	xld.h [%r0+PC], %r1		; PC *anti-interlock*
	call.d %r10
	ld.w %r12, %r0			; *delay*
	;
	xld.w %r10, [%r0+CYCLE]		; CYCLE -= op->cycle
	xld.ub %r11, [%r2+5]
	sub %r10, %r11
	xld.w [%r0+CYCLE], %r10
	xjrgt dmg_run_LOOP		; if(CYCLE <= 0) break
dmg_run_EXIT:
	;
	xadd %sp, %sp, 4
	popn %r3
	ret

	.global dmgop_CB
dmgop_CB:
	pushn %r2
	;
	ld.w %r0, %r12			; dmg
	xld.uh %r1, [%r0+PC]		; PC
	;
	xld.w %r11, [%r0+READ]		; code = dmg->read(dmg, PC++)
	ld.w %r12, %r0
	ld.uh %r13, %r1
	call.d %r11
	add %r1, 1			; *delay*
	ld.w %r13, %r10
	;
	xld.w %r2, dmg_op_table_CB	; op = &dmg_op_table_CB[code]
	xsll %r10, 3
	add %r2, %r10
	;
	xld.w %r10, [%r2+0]		; op->proc(dmg, code, arg1, arg2)
	xld.h [%r0+PC], %r1		; PC *anti-interlock*
	call.d %r10
	ld.w %r12, %r0			; *delay*
	;
	xld.w %r10, [%r0+CYCLE]		; CYCLE -= op->cycle
	xld.ub %r11, [%r2+5]
	sub %r10, %r11
	xld.w [%r0+CYCLE], %r10
	;
	popn %r2
	ret

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

#macro LD_r_r $1, $2
	xld.ub %r10, [%r12+$2]
	xld.b [%r12+$1], %r10
	ret
#endm

#macro LD_r_IrrI $1, $2
	pushn %r0
	;
	xld.w %r10, [%r12+READ]
	xld.uh %r13, [%r12+$2]		; *anti-interlock*
	call.d %r10
	ld.w %r0, %r12			; *delay*
	xld.b [%r0+$1], %r10
	;
	popn %r0
	ret
#endm

#macro LD_IrrI_r $1, $2
	xld.w %r10, [%r12+WRITE]
	xld.uh %r13, [%r12+$1]
	xld.ub %r14, [%r12+$2]
	call %r10
	ret
#endm

#macro LD_r_n $1
	xld.b [%r12+$1], %r14
	ret
#endm

#macro LD_IrrI_n $1
	xld.w %r10, [%r12+WRITE]
	xld.uh %r13, [%r12+$1]		; *anti-interlock*
	call %r10
	ret
#endm

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

	.global dmgop_LD_B_B
dmgop_LD_B_B:
	LD_r_r B, B
	.global dmgop_LD_B_C
dmgop_LD_B_C:
	LD_r_r B, C
	.global dmgop_LD_B_D
dmgop_LD_B_D:
	LD_r_r B, D
	.global dmgop_LD_B_E
dmgop_LD_B_E:
	LD_r_r B, E
	.global dmgop_LD_B_H
dmgop_LD_B_H:
	LD_r_r B, H
	.global dmgop_LD_B_L
dmgop_LD_B_L:
	LD_r_r B, L
	.global dmgop_LD_B_IHLI
dmgop_LD_B_IHLI:
	LD_r_IrrI B, HL
	.global dmgop_LD_B_A
dmgop_LD_B_A:
	LD_r_r B, A

	.global dmgop_LD_C_B
dmgop_LD_C_B:
	LD_r_r C, B
	.global dmgop_LD_C_C
dmgop_LD_C_C:
	LD_r_r C, C
	.global dmgop_LD_C_D
dmgop_LD_C_D:
	LD_r_r C, D
	.global dmgop_LD_C_E
dmgop_LD_C_E:
	LD_r_r C, E
	.global dmgop_LD_C_H
dmgop_LD_C_H:
	LD_r_r C, H
	.global dmgop_LD_C_L
dmgop_LD_C_L:
	LD_r_r C, L
	.global dmgop_LD_C_IHLI
dmgop_LD_C_IHLI:
	LD_r_IrrI C, HL
	.global dmgop_LD_C_A
dmgop_LD_C_A:
	LD_r_r C, A

	.global dmgop_LD_D_B
dmgop_LD_D_B:
	LD_r_r D, B
	.global dmgop_LD_D_C
dmgop_LD_D_C:
	LD_r_r D, C
	.global dmgop_LD_D_D
dmgop_LD_D_D:
	LD_r_r D, D
	.global dmgop_LD_D_E
dmgop_LD_D_E:
	LD_r_r D, E
	.global dmgop_LD_D_H
dmgop_LD_D_H:
	LD_r_r D, H
	.global dmgop_LD_D_L
dmgop_LD_D_L:
	LD_r_r D, L
	.global dmgop_LD_D_IHLI
dmgop_LD_D_IHLI:
	LD_r_IrrI D, HL
	.global dmgop_LD_D_A
dmgop_LD_D_A:
	LD_r_r D, A

	.global dmgop_LD_E_B
dmgop_LD_E_B:
	LD_r_r E, B
	.global dmgop_LD_E_C
dmgop_LD_E_C:
	LD_r_r E, C
	.global dmgop_LD_E_D
dmgop_LD_E_D:
	LD_r_r E, D
	.global dmgop_LD_E_E
dmgop_LD_E_E:
	LD_r_r E, E
	.global dmgop_LD_E_H
dmgop_LD_E_H:
	LD_r_r E, H
	.global dmgop_LD_E_L
dmgop_LD_E_L:
	LD_r_r E, L
	.global dmgop_LD_E_IHLI
dmgop_LD_E_IHLI:
	LD_r_IrrI E, HL
	.global dmgop_LD_E_A
dmgop_LD_E_A:
	LD_r_r E, A

	.global dmgop_LD_H_B
dmgop_LD_H_B:
	LD_r_r H, B
	.global dmgop_LD_H_C
dmgop_LD_H_C:
	LD_r_r H, C
	.global dmgop_LD_H_D
dmgop_LD_H_D:
	LD_r_r H, D
	.global dmgop_LD_H_E
dmgop_LD_H_E:
	LD_r_r H, E
	.global dmgop_LD_H_H
dmgop_LD_H_H:
	LD_r_r H, H
	.global dmgop_LD_H_L
dmgop_LD_H_L:
	LD_r_r H, L
	.global dmgop_LD_H_IHLI
dmgop_LD_H_IHLI:
	LD_r_IrrI H, HL
	.global dmgop_LD_H_A
dmgop_LD_H_A:
	LD_r_r H, A

	.global dmgop_LD_L_B
dmgop_LD_L_B:
	LD_r_r L, B
	.global dmgop_LD_L_C
dmgop_LD_L_C:
	LD_r_r L, C
	.global dmgop_LD_L_D
dmgop_LD_L_D:
	LD_r_r L, D
	.global dmgop_LD_L_E
dmgop_LD_L_E:
	LD_r_r L, E
	.global dmgop_LD_L_H
dmgop_LD_L_H:
	LD_r_r L, H
	.global dmgop_LD_L_L
dmgop_LD_L_L:
	LD_r_r L, L
	.global dmgop_LD_L_IHLI
dmgop_LD_L_IHLI:
	LD_r_IrrI L, HL
	.global dmgop_LD_L_A
dmgop_LD_L_A:
	LD_r_r L, A

	.global dmgop_LD_IHLI_B
dmgop_LD_IHLI_B:
	LD_IrrI_r HL, B
	.global dmgop_LD_IHLI_C
dmgop_LD_IHLI_C:
	LD_IrrI_r HL, C
	.global dmgop_LD_IHLI_D
dmgop_LD_IHLI_D:
	LD_IrrI_r HL, D
	.global dmgop_LD_IHLI_E
dmgop_LD_IHLI_E:
	LD_IrrI_r HL, E
	.global dmgop_LD_IHLI_H
dmgop_LD_IHLI_H:
	LD_IrrI_r HL, H
	.global dmgop_LD_IHLI_L
dmgop_LD_IHLI_L:
	LD_IrrI_r HL, L
	.global dmgop_LD_IHLI_A
dmgop_LD_IHLI_A:
	LD_IrrI_r HL, A

	.global dmgop_LD_A_B
dmgop_LD_A_B:
	LD_r_r A, B
	.global dmgop_LD_A_C
dmgop_LD_A_C:
	LD_r_r A, C
	.global dmgop_LD_A_D
dmgop_LD_A_D:
	LD_r_r A, D
	.global dmgop_LD_A_E
dmgop_LD_A_E:
	LD_r_r A, E
	.global dmgop_LD_A_H
dmgop_LD_A_H:
	LD_r_r A, H
	.global dmgop_LD_A_L
dmgop_LD_A_L:
	LD_r_r A, L
	.global dmgop_LD_A_IHLI
dmgop_LD_A_IHLI:
	LD_r_IrrI A, HL
	.global dmgop_LD_A_A
dmgop_LD_A_A:
	LD_r_r A, A

	.global dmgop_LD_B_n
dmgop_LD_B_n:
	LD_r_n B
	.global dmgop_LD_C_n
dmgop_LD_C_n:
	LD_r_n C
	.global dmgop_LD_D_n
dmgop_LD_D_n:
	LD_r_n D
	.global dmgop_LD_E_n
dmgop_LD_E_n:
	LD_r_n E
	.global dmgop_LD_H_n
dmgop_LD_H_n:
	LD_r_n H
	.global dmgop_LD_L_n
dmgop_LD_L_n:
	LD_r_n L
	.global dmgop_LD_IHLI_n
dmgop_LD_IHLI_n:
	LD_IrrI_n HL
	.global dmgop_LD_A_n
dmgop_LD_A_n:
	LD_r_n A

	.global dmgop_LD_IBCI_A
dmgop_LD_IBCI_A:
	LD_IrrI_r BC, A
	.global dmgop_LD_A_IBCI
dmgop_LD_A_IBCI:
	LD_r_IrrI A, BC
	.global dmgop_LD_IDEI_A
dmgop_LD_IDEI_A:
	LD_IrrI_r DE, A
	.global dmgop_LD_A_IDEI
dmgop_LD_A_IDEI:
	LD_r_IrrI A, DE

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

#macro LD_rr_nn $1
	xld.h [%r12+$1], %r14
	ret
#endm

#macro PUSH_rr $1
	pushn %r1
	;
	xld.uh %r1, [%r12+SP]		; SP
	;
	xld.w %r10, [%r12+WRITE]
	xsub %r1, %r1, 1		; SP--
	ld.uh %r13, %r1
	xld.ub %r14, [%r12+($1+1)]	; HI
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	xld.w %r10, [%r0+WRITE]
	xsub %r1, %r1, 1		; SP--
	ld.uh %r13, %r1
	xld.ub %r14, [%r0+($1+0)]	; LO
	call.d %r10
	ld.w %r12, %r0			; *delay*
	;
	xld.h [%r0+SP], %r1		; SP
	;
	popn %r1
	ret
#endm

#macro POP_rr $1
	pushn %r1
	;
	xld.uh %r1, [%r12+SP]		; SP
	;
	xld.w %r10, [%r12+READ]
	ld.uh %r13, %r1			; *anti-interlock*
	call.d %r10
	ld.w %r0, %r12			; *delay*
	xld.b [%r0+($1+0)], %r10	; LO
	xadd %r1, %r1, 1		; SP++
	;
	xld.w %r10, [%r0+READ]
	ld.uh %r13, %r1			; *anti-interlock*
	call.d %r10
	ld.w %r12, %r0			; *delay*
	xld.b [%r0+($1+1)], %r10	; HI
	xadd %r1, %r1, 1		; SP++
	;
	xld.h [%r0+SP], %r1		; SP
	;
	popn %r1
	ret
#endm

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

	.global dmgop_LD_BC_nn
dmgop_LD_BC_nn:
	LD_rr_nn BC
	.global dmgop_LD_DE_nn
dmgop_LD_DE_nn:
	LD_rr_nn DE
	.global dmgop_LD_HL_nn
dmgop_LD_HL_nn:
	LD_rr_nn HL
	.global dmgop_LD_SP_nn
dmgop_LD_SP_nn:
	LD_rr_nn SP

	.global dmgop_PUSH_AF
dmgop_PUSH_AF:
	PUSH_rr AF
	.global dmgop_PUSH_BC
dmgop_PUSH_BC:
	PUSH_rr BC
	.global dmgop_PUSH_DE
dmgop_PUSH_DE:
	PUSH_rr DE
	.global dmgop_PUSH_HL
dmgop_PUSH_HL:
	PUSH_rr HL

	.global dmgop_POP_AF
dmgop_POP_AF:
	POP_rr AF
	.global dmgop_POP_BC
dmgop_POP_BC:
	POP_rr BC
	.global dmgop_POP_DE
dmgop_POP_DE:
	POP_rr DE
	.global dmgop_POP_HL
dmgop_POP_HL:
	POP_rr HL

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

	.global dmg_ADD
dmg_ADD:
	xld.ub %r14, [%r12+A]			; A
	swap %r11, %r13				; *anti-interlock*
	swap %r10, %r14
	add %r10, %r11
	;
	ld.w %r11, %psr				; F(Z,C)
	xand %r11, %r11, 0xa
	xld.ub %r11, [%r11+dmg_FLAG_CONV]
	;
	swap %r10, %r10				; A
	xld.b [%r12+A], %r10
	;
	xand %r14, %r14, 0xf			; F(H)
	xand %r13, %r13, 0xf
	add %r14, %r13
	xand %r14, %r14, 0x10
	xsll %r14, 1
	or %r11, %r14
	;
	xld.b [%r12+F], %r11			; F
	;
	ret

	.global dmg_ADC
dmg_ADC:
	xld.ub %r15, [%r12+F]			; F(C)
	xld.ub %r14, [%r12+A]			; A *anti-interlock*
	xsrl %r15, 4
	xand %r15, %r15, 1
	;
	swap %r10, %r14				; A + n
	swap %r11, %r13
	add %r10, %r11
	;
	ld.w %r11, %psr				; %psr(C1)
	xand %r11, %r11, 0x8
	;
	swap %r4, %r15				; A + n + c
	add %r10, %r4
	;
	ld.w %r4, %psr				; %psr(C1|C2,Z2)
	xand %r4, %r4, 0xa
	or %r11, %r4
	xld.ub %r11, [%r11+dmg_FLAG_CONV]	; F(Z,C)
	;
	swap %r10, %r10				; A
	xld.b [%r12+A], %r10
	;
	xand %r14, %r14, 0xf			; F(H)
	xand %r13, %r13, 0xf
	add %r14, %r13
	add %r14, %r15
	xand %r14, %r14, 0x10
	xsll %r14, 1
	or %r11, %r14
	;
	xld.b [%r12+F], %r11			; F
	;
	ret

	.global dmg_SUB
dmg_SUB:
	xld.ub %r14, [%r12+A]			; A
	swap %r11, %r13				; *anti-interlock*
	swap %r10, %r14
	sub %r10, %r11
	;
	ld.w %r11, %psr				; F(Z,C)
	xand %r11, %r11, 0xa
	xld.ub %r11, [%r11+dmg_FLAG_CONV]
	;
	swap %r10, %r10				; A
	xld.b [%r12+A], %r10
	;
	xand %r14, %r14, 0xf			; F(H)
	xand %r13, %r13, 0xf
	sub %r14, %r13
	xand %r14, %r14, 0x10
	xsll %r14, 1
	or %r11, %r14
	;
	xoor %r11, %r11, 0x40			; F(N)
	;
	xld.b [%r12+F], %r11			; F
	;
	ret

	.global dmg_SBC
dmg_SBC:
	xld.ub %r15, [%r12+F]			; F(C)
	xld.ub %r14, [%r12+A]			; A *anti-interlock*
	xsrl %r15, 4
	xand %r15, %r15, 1
	;
	swap %r10, %r14				; A - n
	swap %r11, %r13
	sub %r10, %r11
	;
	ld.w %r11, %psr				; %psr(C1)
	xand %r11, %r11, 0x8
	;
	swap %r4, %r15				; A - n - c
	sub %r10, %r4
	;
	ld.w %r4, %psr				; %psr(C1|C2,Z2)
	xand %r4, %r4, 0xa
	or %r11, %r4
	xld.ub %r11, [%r11+dmg_FLAG_CONV]	; F(Z,C)
	;
	swap %r10, %r10				; A
	xld.b [%r12+A], %r10
	;
	xand %r14, %r14, 0xf			; F(H)
	xand %r13, %r13, 0xf
	sub %r14, %r13
	sub %r14, %r15
	xand %r14, %r14, 0x10
	xsll %r14, 1
	or %r11, %r14
	;
	xoor %r11, %r11, 0x40			; F(N)
	;
	xld.b [%r12+F], %r11			; F
	;
	ret

	.global dmg_AND
dmg_AND:
	xld.ub %r10, [%r12+A]			; A
	xld.w %r11, 0x20			; F(H) *anti-interlock*
	and %r10, %r13				; A & n
	xjrne dmg_AND_L10			; !NO-DELAY!
	xoor %r11, %r11, 0x80			; F(Z)
dmg_AND_L10:
	xld.b [%r12+A], %r10			; A
	xld.b [%r12+F], %r11			; F
	ret

	.global dmg_XOR
dmg_XOR:
	xld.ub %r10, [%r12+A]			; A
	xor %r10, %r13				; A ^ n !INTERLOCK!
	xjrne.d dmg_XOR_L10
	ld.w %r11, 0				; *delay*
	xoor %r11, %r11, 0x80			; F(Z)
dmg_XOR_L10:
	xld.b [%r12+A], %r10			; A
	xld.b [%r12+F], %r11			; F
	ret

	.global dmg_OR
dmg_OR:
	xld.ub %r10, [%r12+A]			; A
	or %r10, %r13				; A | n !INTERLOCK!
	xjrne.d dmg_OR_L10
	ld.w %r11, 0				; *delay*
	xoor %r11, %r11, 0x80			; F(Z)
dmg_OR_L10:
	xld.b [%r12+A], %r10			; A
	xld.b [%r12+F], %r11			; F
	ret

	.global dmg_CP
dmg_CP:
	xld.ub %r14, [%r12+A]			; A
	swap %r11, %r13				; *anti-interlock*
	swap %r10, %r14
	cmp %r10, %r11
	;
	ld.w %r11, %psr				; F(Z,C)
	xand %r11, %r11, 0xa
	xld.ub %r11, [%r11+dmg_FLAG_CONV]
	;
	xand %r14, %r14, 0xf			; F(H)
	xand %r13, %r13, 0xf
	sub %r14, %r13
	xand %r14, %r14, 0x20
	or %r11, %r14
	;
	xoor %r11, %r11, 0x40			; F(N)
	;
	xld.b [%r12+F], %r11			; F
	;
	ret

	;;;;;;;;;;;;;;;;;;;;;;;;
	; F(C) = KEEP
	; n++
	; n &= 0xff
	; if(n == 0x?0) {
	;   F(H) = SET
	;   if(n == 0x00) {
	;     F(Z) = SET
	;   }
	; }
	;;;;;;;;;;;;;;;;;;;;;;;;
	.global dmg_INC
dmg_INC:
	xld.ub %r11, [%r12+F]
	xadd %r13, %r13, 1			; n + 1 *anti-interlock*
	xand %r11, %r11, 0x10			; F(C)
	ld.ub %r10, %r13
	;
	xand %r13, %r13, 0xf			; 加算後 != 0x?0 => 分岐
	xjrne dmg_INC_L10
	xoor %r11, %r11, 0x20			; F(H)
	cmp %r10, 0				; 加算後 != 0x00 => 分岐
	xjrne dmg_INC_L10
	xoor %r11, %r11, 0x80			; F(Z)
dmg_INC_L10:
	;
	xld.b [%r12+F], %r11			; F
	ret

	;;;;;;;;;;;;;;;;;;;;;;;;
	; F(C) = KEEP
	; n--
	; if(n == 0x00) {
	;   F(Z) = SET
	; } else {
	;   n &= 0xff
	;   if(n == 0x?f) {
	;     F(H) = SET
	;   }
	; }
	; F(N) = SET
	;;;;;;;;;;;;;;;;;;;;;;;;
	.global dmg_DEC
dmg_DEC:
	xld.ub %r11, [%r12+F]
	xsub %r13, %r13, 1			; n - 1
	xjrne.d dmg_DEC_L10			; 減算後 != 0x00 => 分岐
	and %r11, 0x10				; F(C) *delay*
	;
	xoor %r11, %r11, 0x80			; F(Z)
	xjp.d dmg_DEC_L20
	ld.w %r10, %r13				; *delay*
	;
dmg_DEC_L10:
	ld.ub %r10, %r13
	xand %r13, %r13, 0xf
	xcmp %r13, 0xf
	xjrne dmg_DEC_L20			; 減算後 != 0x?0 => 分岐
	xoor %r11, %r11, 0x20			; F(H)
	;
dmg_DEC_L20:
	xoor %r11, %r11, 0x40			; F(N)
	xld.b [%r12+F], %r11			; F
	ret

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

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

	.global dmg_ADDW
dmg_ADDW:
	xld.ub %r11, [%r12+0]			; F(Z)
	xld.uh %r14, [%r12+HL]			; HL *anti-interlock*
	xand %r11, %r11, 0x80
	;
	ld.w %r10, %r13				; HL + nn
	add %r10, %r14
	xld.h [%r12+HL], %r10			; HL
	xsrl %r10, 12				; F(C)
	xand %r10, %r10, 0x10
	or %r11, %r10
dmg_ADDW_L10:
	;
	xand %r13, %r13, 0xfff			; F(H)
	xand %r14, %r14, 0xfff
	add %r13, %r14
	xsrl %r13, 7
	xand %r13, %r13, 0x20
	or %r11, %r13
	;
	xld.b [%r12+0], %r11			; F
	;
	ret

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

#macro INC_rr $1
	xld.uh %r10, [%r12+$1]
	xadd %r10, %r10, 1
	xld.h [%r12+$1], %r10
	ret
#endm

#macro DEC_rr $1
	xld.uh %r10, [%r12+$1]
	xsub %r10, %r10, 1
	xld.h [%r12+$1], %r10
	ret
#endm

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

	.global dmgop_INC_BC
dmgop_INC_BC:
	INC_rr BC
	.global dmgop_INC_DE
dmgop_INC_DE:
	INC_rr DE
	.global dmgop_INC_HL
dmgop_INC_HL:
	INC_rr HL
	.global dmgop_INC_SP
dmgop_INC_SP:
	INC_rr SP

	.global dmgop_DEC_BC
dmgop_DEC_BC:
	DEC_rr BC
	.global dmgop_DEC_DE
dmgop_DEC_DE:
	DEC_rr DE
	.global dmgop_DEC_HL
dmgop_DEC_HL:
	DEC_rr HL
	.global dmgop_DEC_SP
dmgop_DEC_SP:
	DEC_rr SP

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

#macro JP_rr $1
	xld.uh %r10, [%r12+$1]
	xld.h [%r12+PC], %r10		; PC !INTERLOCK!
	ret
#endm

#macro JP_cc_nn $1
	xbtst [%r12+F], $1
	xjreq $$1
	;
	xld.w %r10, [%r12+CYCLE]	; CYCLE -= 4
	xld.h [%r12+PC], %r14		; PC *anti-interlock*
	xsub %r10, %r10, 4
	xld.w [%r12+CYCLE], %r10
$$1:
	ret
#endm

#macro JP_Ncc_nn $1
	xbtst [%r12+F], $1
	xjrne $$1
	;
	xld.w %r10, [%r12+CYCLE]	; CYCLE -= 4
	xld.h [%r12+PC], %r14		; PC *anti-interlock*
	xsub %r10, %r10, 4
	xld.w [%r12+CYCLE], %r10
$$1:
	ret
#endm

#macro JR_e
	xld.uh %r10, [%r12+PC]		; PC+e
	ld.b %r14, %r14			; *anti-interlock*
	add %r14, %r10
	xld.h [%r12+PC], %r14		; PC
	ret
#endm

#macro JR_c_e $1
	xbtst [%r12+F], $1
	xjreq $$1
	;
	xld.uh %r10, [%r12+PC]		; PC+e
	ld.b %r14, %r14			; *anti-interlock*
	add %r14, %r10
	;
	xld.w %r10, [%r12+CYCLE]	; CYCLE -= 4
	xld.h [%r12+PC], %r14		; PC *anti-interlock*
	xsub %r10, %r10, 4
	xld.w [%r12+CYCLE], %r10
$$1:
	ret
#endm

#macro JR_Nc_e $1
	xbtst [%r12+F], $1
	xjrne $$1
	;
	xld.uh %r10, [%r12+PC]		; PC+e
	ld.b %r14, %r14			; *anti-interlock*
	add %r14, %r10
	;
	xld.w %r10, [%r12+CYCLE]	; CYCLE -= 4
	xld.h [%r12+PC], %r14		; PC *anti-interlock*
	xsub %r10, %r10, 4
	xld.w [%r12+CYCLE], %r10
$$1:
	ret
#endm

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

	.global dmgop_JP_IHLI
dmgop_JP_IHLI:
	JP_rr HL
	.global dmgop_JP_nn
dmgop_JP_nn:
	LD_rr_nn PC

	.global dmgop_JP_NZ_nn
dmgop_JP_NZ_nn:
	JP_Ncc_nn 7
	.global dmgop_JP_Z_nn
dmgop_JP_Z_nn:
	JP_cc_nn 7
	.global dmgop_JP_NC_nn
dmgop_JP_NC_nn:
	JP_Ncc_nn 4
	.global dmgop_JP_C_nn
dmgop_JP_C_nn:
	JP_cc_nn 4

	.global dmgop_JR_e
dmgop_JR_e:
	JR_e

	.global dmgop_JR_NZ_e
dmgop_JR_NZ_e:
	JR_Nc_e 7
	.global dmgop_JR_Z_e
dmgop_JR_Z_e:
	JR_c_e 7
	.global dmgop_JR_NC_e
dmgop_JR_NC_e:
	JR_Nc_e 4
	.global dmgop_JR_C_e
dmgop_JR_C_e:
	JR_c_e 4

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

#macro CALL_nn
	pushn %r2
	;
	ld.w %r2, %r14			; nn
	;
	xld.uh %r1, [%r12+SP]		; SP
	;
	xld.w %r10, [%r12+WRITE]
	xsub %r1, %r1, 1		; SP--
	ld.uh %r13, %r1
	xld.ub %r14, [%r12+(PC+1)]	; HI(PC)
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	xld.w %r10, [%r0+WRITE]
	xsub %r1, %r1, 1		; SP--
	ld.uh %r13, %r1
	xld.ub %r14, [%r0+(PC+0)]	; LO(PC)
	call.d %r10
	ld.w %r12, %r0			; *delay*
	;
	xld.h [%r0+SP], %r1		; SP
	;
	xld.h [%r0+PC], %r2		; PC
	;
	popn %r2
	ret
#endm

#macro CALL_c_nn $1
	xbtst [%r12+F], $1
	xjreq $$1
	;
	pushn %r2
	;
	ld.w %r2, %r14			; nn
	;
	xld.uh %r1, [%r12+SP]		; SP
	;
	xld.w %r10, [%r12+WRITE]
	xsub %r1, %r1, 1		; SP--
	ld.uh %r13, %r1
	xld.ub %r14, [%r12+(PC+1)]	; HI(PC)
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	xld.w %r10, [%r0+WRITE]
	xsub %r1, %r1, 1		; SP--
	ld.uh %r13, %r1
	xld.ub %r14, [%r0+(PC+0)]	; LO(PC)
	call.d %r10
	ld.w %r12, %r0			; *delay*
	;
	xld.h [%r0+SP], %r1		; SP
	;
	xld.w %r10, [%r0+CYCLE]		; CYCLE -= 12
	xld.h [%r0+PC], %r2		; PC *anti-interlock*
	xsub %r10, %r10, 12
	xld.w [%r0+CYCLE], %r10
	;
	popn %r2
$$1:
	ret
#endm

#macro CALL_Nc_nn $1
	xbtst [%r12+F], $1
	xjrne $$1
	;
	pushn %r2
	;
	ld.w %r2, %r14			; nn
	;
	xld.uh %r1, [%r12+SP]		; SP
	;
	xld.w %r10, [%r12+WRITE]
	xsub %r1, %r1, 1		; SP--
	ld.uh %r13, %r1
	xld.ub %r14, [%r12+(PC+1)]	; HI(PC)
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	xld.w %r10, [%r0+WRITE]
	xsub %r1, %r1, 1		; SP--
	ld.uh %r13, %r1
	xld.ub %r14, [%r0+(PC+0)]	; LO(PC)
	call.d %r10
	ld.w %r12, %r0			; *delay*
	;
	xld.h [%r0+SP], %r1		; SP
	;
	xld.w %r10, [%r0+CYCLE]		; CYCLE -= 12
	xld.h [%r0+PC], %r2		; PC *anti-interlock*
	xsub %r10, %r10, 12
	xld.w [%r0+CYCLE], %r10
	;
	popn %r2
$$1:
	ret
#endm

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

	.global dmgop_CALL_nn
dmgop_CALL_nn:
	CALL_nn

	.global dmgop_CALL_NZ_nn
dmgop_CALL_NZ_nn:
	CALL_Nc_nn 7
	.global dmgop_CALL_Z_nn
dmgop_CALL_Z_nn:
	CALL_c_nn 7
	.global dmgop_CALL_NC_nn
dmgop_CALL_NC_nn:
	CALL_Nc_nn 4
	.global dmgop_CALL_C_nn
dmgop_CALL_C_nn:
	CALL_c_nn 4

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

#macro RET
	pushn %r1
	;
	xld.uh %r1, [%r12+SP]		; SP
	;
	xld.w %r10, [%r12+READ]
	ld.uh %r13, %r1			; *anti-interlock*
	call.d %r10
	ld.w %r0, %r12			; *delay*
	xld.b [%r0+(PC+0)], %r10	; LO(PC)
	xadd %r1, %r1, 1		; SP++
	;
	xld.w %r10, [%r0+READ]
	ld.uh %r13, %r1			; *anti-interlock*
	call.d %r10
	ld.w %r12, %r0			; *delay*
	xld.b [%r0+(PC+1)], %r10	; HI(PC)
	xadd %r1, %r1, 1		; SP++
	;
	xld.h [%r0+SP], %r1		; SP
	;
	popn %r1
	ret
#endm

#macro RET_c $1
	xbtst [%r12+F], $1
	xjreq $$1
	;
	pushn %r1
	;
	xld.uh %r1, [%r12+SP]		; SP
	;
	xld.w %r10, [%r12+READ]
	ld.uh %r13, %r1			; *anti-interlock*
	call.d %r10
	ld.w %r0, %r12			; *delay*
	xld.b [%r0+(PC+0)], %r10	; LO(PC)
	xadd %r1, %r1, 1		; SP++
	;
	xld.w %r10, [%r0+READ]
	ld.uh %r13, %r1			; *anti-interlock*
	call.d %r10
	ld.w %r12, %r0			; *delay*
	xld.b [%r0+(PC+1)], %r10	; HI(PC)
	xadd %r1, %r1, 1		; SP++
	;
	xld.w %r10, [%r0+CYCLE]		; CYCLE -= 12
	xld.h [%r0+SP], %r1		; SP *anti-interlock*
	xsub %r10, %r10, 12
	xld.w [%r0+CYCLE], %r10
	;
	popn %r1
$$1:
	ret
#endm

#macro RET_Nc $1
	xbtst [%r12+F], $1
	xjrne $$1
	;
	pushn %r1
	;
	xld.uh %r1, [%r12+SP]		; SP
	;
	xld.w %r10, [%r12+READ]
	ld.uh %r13, %r1			; *anti-interlock*
	call.d %r10
	ld.w %r0, %r12			; *delay*
	xld.b [%r0+(PC+0)], %r10	; LO(PC)
	xadd %r1, %r1, 1		; SP++
	;
	xld.w %r10, [%r0+READ]
	ld.uh %r13, %r1			; *anti-interlock*
	call.d %r10
	ld.w %r12, %r0			; *delay*
	xld.b [%r0+(PC+1)], %r10	; HI(PC)
	xadd %r1, %r1, 1		; SP++
	;
	xld.w %r10, [%r0+CYCLE]		; CYCLE -= 12
	xld.h [%r0+SP], %r1		; SP *anti-interlock*
	xsub %r10, %r10, 12
	xld.w [%r0+CYCLE], %r10
	;
	popn %r1
$$1:
	ret
#endm

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

	.global dmgop_RET
dmgop_RET:
	RET

	.global dmgop_RET_NZ
dmgop_RET_NZ:
	RET_Nc 7
	.global dmgop_RET_Z
dmgop_RET_Z:
	RET_c 7
	.global dmgop_RET_NC
dmgop_RET_NC:
	RET_Nc 4
	.global dmgop_RET_C
dmgop_RET_C:
	RET_c 4

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

#endif /*DMG_ASM*/
