;	
;	framssma.s
;
;	P/ECE S-SMP (SPC700) Emulator
;
;	CLiP - Common Library for P/ECE
;	Copyright (C) 2001-2004 Naoyuki Sawa
;
;	* Sun Jan 07 06:00:00 JST 2004 Naoyuki Sawa
;	- 作成開始。
;
#include "clipssma.h"
#ifdef SSMP_ASM

	.code
	.align 1

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

;
;	SSMP構造体
;
/*===== レジスタ =====*/
#define PSW	 0
#define SP	 1
#define PC	 2
#define YA	 4
#define A	 4
#define Y	 5
#define X	 6
/*===== 内部状態 =====*/
#define CYCLE	 8
#define SLEEP	12
/*===== 外部関数 =====*/
#define READ	16
#define WRITE	20

;
;	C33=>S-SMPフラグ変換表
;
				; C33(C,V,Z,N) => S-SMP(S,Z,V,C)
				; ====C33====     ===S-SMP===
ssmp_FLAG_CONV:			; ----CVZN        NV----ZC
	.byte	0x00		; 00000000 00     00000000 00
	.byte	0x80		; 00000001 01     10000000 80
	.byte	0x02		; 00000010 02     00000010 02
	.byte	0x82		; 00000011 03     10000010 82
	.byte	0x40		; 00000100 04     01000000 40
	.byte	0xc0		; 00000101 05     11000000 c0
	.byte	0x42		; 00000110 06     01000010 42
	.byte	0xc2		; 00000111 07     11000010 c2
	.byte	0x01		; 00001000 08     00000001 01
	.byte	0x81		; 00001001 09     10000001 81
	.byte	0x03		; 00001010 0a     00000011 03
	.byte	0x83		; 00001011 0b     10000011 83
	.byte	0x41		; 00001100 0c     01000001 41
	.byte	0xc1		; 00001101 0d     11000001 c1
	.byte	0x43		; 00001110 0e     01000011 43
	.byte	0xc3		; 00001111 0f     11000011 c3

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

	.align 2
ssmp_run_table:
	;===== operand bytes=0 =====
	.word ssmp_run_implied				;  0	/* A,X,Y,etc */
	.word ssmp_run_indirect				;  1	/* (X) */
	.word ssmp_run_indirect_auto_increment		;  2	/* (X)+ */
	.word ssmp_run_indirect_page_to_ip		;  3	/* (X),(Y) */
	;===== operand bytes=1 =====
	.word ssmp_run_inmediate_data			;  4	/* #inm */
	.word ssmp_run_direct_page			;  5	/* dp */
	.word ssmp_run_x_indexed_direct_page		;  6	/* dp+X */
	.word ssmp_run_y_indexed_direct_page		;  7	/* dp+Y */
	.word ssmp_run_x_indexed_indirect		;  8	/* (dp+X) */
	.word ssmp_run_indirect_y_indexed_indirect	;  9	/* (dp)+Y */
	.word ssmp_run_relative				; 10	/* rel */
	;===== operand bytes=2 =====
	.word ssmp_run_direct_page_to_dp		; 11	/* dp(d),dp(s) */
	.word ssmp_run_inmediate_data_to_dp		; 12	/* dp,#inm */
	.word ssmp_run_direct_page_relative		; 13	/* dp,rel */
	.word ssmp_run_absolute_boolean_bit		; 14	/* mem.bit */
	.word ssmp_run_absolute				; 15	/* labs */
	.word ssmp_run_x_indexed_absolute		; 16	/* labs+X */
	.word ssmp_run_y_indexed_absolute		; 17	/* labs+Y */
	.word ssmp_run_x_indexed_absolute_indirect	; 18	/* (labs+X) */
	.word ssmp_run_x_indexed_direct_page_relative	; 19	/* dp+X,rel */
	.align 1

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

/* (X) */
#macro INDIRECT
	xld.ub %r14, [%r0+X]		; %r14 = X
	;
	xbtst [%r0+PSW], 5		; if(P) %r14 |= 0x100
	xjreq ssmp_run_exec		; !NO-DELAY!
	xoor %r14, %r14, 0x100
	xjp ssmp_run_exec		; !NO-DELAY!
#endm

/* (X)+ */
#macro INDIRECT_AUTO_INCREMENT
	xld.ub %r14, [%r0+X]		; %r14 = X
	xadd %r10, %r14, 1		; X++ (extを挟むからINTERLOCKしない?)
	xld.b [%r0+X], %r10
	;
	xbtst [%r0+PSW], 5		; if(P) %r14 |= 0x100
	xjreq ssmp_run_exec		; !NO-DELAY!
	xoor %r14, %r14, 0x100
	xjp ssmp_run_exec		; !NO-DELAY!
#endm

/* (X),(Y) */
#macro INDIRECT_PAGE_TO_IP
	xld.ub %r14, [%r0+X]		; %r14 = X
	xld.ub %r15, [%r0+Y]		; %r15 = Y
	;
	xbtst [%r0+PSW], 5		; if(P) %r14 |= 0x100, %r15 |= 0x100
	xjreq ssmp_run_exec		; !NO-DELAY!
	xoor %r14, %r14, 0x100
	xoor %r15, %r15, 0x100
	xjp ssmp_run_exec		; !NO-DELAY!
#endm

/* #inm */
#macro INMEDIATE_DATA
	xld.b [%sp+0], %r13		; (save code)
	;
	ld.uh %r13, %r1			; %r14 = #inm
	call.d %r3
	ld.w %r12, %r0			; *delay*
	ld.ub %r14, %r10
	;
	xld.ub %r13, [%sp+0]		; (restore code)
	xjp.d ssmp_run_exec
	add %r1, 1			; PC++ *delay*
#endm

/* dp */
#macro DIRECT_PAGE
	xld.b [%sp+0], %r13		; (save code)
	;
	ld.uh %r13, %r1			; %r14 = dp
	call.d %r3
	ld.w %r12, %r0			; *delay*
	ld.w %r14, %r10
	;
	xld.ub %r13, [%sp+0]		; (restore code)
	;
	xbtst [%r0+PSW], 5		; if(P) %r14 |= 0x100
	xjreq.d ssmp_run_exec
	add %r1, 1			; PC++ *delay*
	xoor %r14, %r14, 0x100
	xjp ssmp_run_exec		; !NO-DELAY!
#endm

/* dp+X */
#macro X_INDEXED_DIRECT_PAGE
	xld.b [%sp+0], %r13		; (save code)
	;
	ld.uh %r13, %r1			; %r10 = dp
	call.d %r3
	ld.w %r12, %r0			; *delay*
	;
	xld.ub %r14, [%r0+X]		; %r14 = dp+X
	xld.ub %r13, [%sp+0]		; (restore code) *anti-interlock*
	add %r14, %r10
	ld.ub %r14, %r14
	;
	xbtst [%r0+PSW], 5		; if(P) %r14 |= 0x100
	xjreq.d ssmp_run_exec
	add %r1, 1			; PC++ *delay*
	xoor %r14, %r14, 0x100
	xjp ssmp_run_exec		; !NO-DELAY!
#endm

/* dp+Y */
#macro Y_INDEXED_DIRECT_PAGE
	xld.b [%sp+0], %r13		; (save code)
	;
	ld.uh %r13, %r1			; %r10 = dp
	call.d %r3
	ld.w %r12, %r0			; *delay*
	;
	xld.ub %r14, [%r0+Y]		; %r14 = dp+Y
	xld.ub %r13, [%sp+0]		; (restore code) *anti-interlock*
	add %r14, %r10
	ld.ub %r14, %r14
	;
	xbtst [%r0+PSW], 5		; if(P) %r14 |= 0x100
	xjreq.d ssmp_run_exec
	add %r1, 1			; PC++ *delay*
	xoor %r14, %r14, 0x100
	xjp ssmp_run_exec		; !NO-DELAY!
#endm

/* (dp+X) */
#macro X_INDEXED_INDIRECT
	xld.b [%sp+0], %r13		; (save code)
	;
	ld.uh %r13, %r1			; %r10 = dp
	call.d %r3
	ld.w %r12, %r0			; *delay*
	;
	xld.ub %r13, [%r0+X]		; %r13 = dp+X+0
	xld.w %r14, 1			; *anti-interlock*
	add %r13, %r10
	add %r14, %r13			; %r14 = dp+X+1
	ld.ub %r13, %r13
	ld.ub %r14, %r14
	xbtst [%r0+PSW], 5		; if(P) %r13 |= 0x100, %r14 |= 0x100
	xjreq $$1			; !NO-DELAY!
	xoor %r13, %r13, 0x100
	xoor %r14, %r14, 0x100
$$1:
	xld.h [%sp+2], %r14		; (save dp+X+1)
	;
	call.d %r3			; %r10 = (dp+X+0)
	ld.w %r12, %r0			; *delay*
	xld.b [%sp+1], %r10		; (save (dp+X+0))
	;
	xld.uh %r13, [%sp+2]		; (restore dp+X+1)
	call.d %r3			; %r10 = (dp+X+1)
	ld.w %r12, %r0			; *delay*
	;
	xld.ub %r14, [%sp+1]		; (restore (dp+X+0))
	xsll %r10, 8			; %r14 = (dp+X)
	or %r14, %r10
	;
	xld.ub %r13, [%sp+0]		; (restore code)
	xjp.d ssmp_run_exec
	add %r1, 1			; PC++ *delay*
#endm

/* (dp)+Y */
#macro INDIRECT_Y_INDEXED_INDIRECT
	xld.b [%sp+0], %r13		; (save code)
	;
	ld.uh %r13, %r1			; %r10 = dp
	call.d %r3
	ld.w %r12, %r0			; *delay*
	;
	ld.w %r13, %r10			; %r13 = dp+0
	xadd %r10, %r10, 1		; %r14 = dp+1
	ld.ub %r14, %r10
	xbtst [%r0+PSW], 5		; if(P) %r13 |= 0x100, %r14 |= 0x100
	xjreq $$1			; !NO-DELAY!
	xoor %r13, %r13, 0x100
	xoor %r14, %r14, 0x100
$$1:
	xld.h [%sp+2], %r14		; (save dp+1)
	;
	call.d %r3			; %r10 = (dp+0)
	ld.w %r12, %r0			; *delay*
	xld.b [%sp+1], %r10		; (save (dp+0))
	;
	xld.uh %r13, [%sp+2]		; (restore dp+1)
	call.d %r3			; %r10 = (dp+1)
	ld.w %r12, %r0			; *delay*
	;
	xld.ub %r14, [%sp+1]		; (restore (dp+0))
	xsll %r10, 8			; %r14 = (dp)+Y
	xld.ub %r11, [%r0+Y]
	or %r14, %r10			; *anti-interlock*
	add %r14, %r11
	ld.uh %r14, %r14
	;
	xld.ub %r13, [%sp+0]		; (restore code)
	xjp.d ssmp_run_exec
	add %r1, 1			; PC++ *delay*
#endm

/* rel */
#macro RELATIVE
	xld.b [%sp+0], %r13		; (save code)
	;
	ld.uh %r13, %r1			; %r13 = rel
	call.d %r3
	ld.w %r12, %r0			; *delay*
	xadd %r1, %r1, 1		; PC++
	;
	ld.b %r14, %r10			; %r14 = PC + (char)rel
	add %r14, %r1
	ld.uh %r14, %r14
	;
	xld.ub %r13, [%sp+0]		; (restore code)
	xjp ssmp_run_exec		; !NO-DELAY!
#endm

/* dp(d),dp(s) */
#macro DIRECT_PAGE_TO_DP
	xld.b [%sp+0], %r13		; (save code)
	;
	ld.uh %r13, %r1			; %r10 = dp(s)
	call.d %r3
	ld.w %r12, %r0			; *delay*
	xadd %r1, %r1, 1		; PC++
	xld.b [%sp+1], %r10		; (save dp(s))
	;
	ld.uh %r13, %r1			; %r14 = dp(d)
	call.d %r3
	ld.w %r12, %r0			; *delay*
	ld.w %r14, %r10
	;
	xld.ub %r15, [%sp+1]		; (restore dp(s))
	xld.ub %r13, [%sp+0]		; (restore code)
	;
	xbtst [%r0+PSW], 5		; if(P) %r14 |= 0x100, %r15 |= 0x100
	xjreq.d ssmp_run_exec
	add %r1, 1			; PC++ *delay*
	xoor %r14, %r14, 0x100
	xoor %r15, %r15, 0x100
	xjp ssmp_run_exec		; !NO-DELAY!
#endm

/* dp,#inm */
#macro INMEDIATE_DATA_TO_DP
	xld.b [%sp+0], %r13		; (save code)
	;
	ld.uh %r13, %r1			; %r10 = #inm
	call.d %r3
	ld.w %r12, %r0			; *delay*
	xadd %r1, %r1, 1		; PC++
	xld.b [%sp+1], %r10		; (save #inm)
	;
	ld.uh %r13, %r1			; %r14 = dp
	call.d %r3
	ld.w %r12, %r0			; *delay*
	ld.w %r14, %r10
	;
	xld.ub %r15, [%sp+1]		; (restore #inm)
	xld.ub %r13, [%sp+0]		; (restore code)
	;
	xbtst [%r0+PSW], 5		; if(P) %r14 |= 0x100
	xjreq.d ssmp_run_exec
	add %r1, 1			; PC++ *delay*
	xoor %r14, %r14, 0x100
	xjp ssmp_run_exec		; !NO-DELAY!
#endm

/* dp,rel */
#macro DIRECT_PAGE_RELATIVE
	xld.b [%sp+0], %r13		; (save code)
	;
	ld.uh %r13, %r1			; %r10 = dp
	call.d %r3
	ld.w %r12, %r0			; *delay*
	xadd %r1, %r1, 1		; PC++
	xld.b [%sp+1], %r10		; (save dp)
	;
	ld.uh %r13, %r1			; %r10 = rel
	call.d %r3
	ld.w %r12, %r0			; *delay*
	xadd %r1, %r1, 1		; PC++
	;
	ld.b %r15, %r10			; %r15 = PC + (char)rel
	add %r15, %r1
	ld.uh %r15, %r15
	;
	xld.ub %r14, [%sp+1]		; (restore dp)
	xld.ub %r13, [%sp+0]		; (restore code)
	;
	xbtst [%r0+PSW], 5		; if(P) %r14 |= 0x100
	xjreq ssmp_run_exec		; !NO-DELAY!
	xoor %r14, %r14, 0x100
	xjp ssmp_run_exec		; !NO-DELAY!
#endm

/* mem.bit */
#macro ABSOLUTE_BOOLEAN_BIT
	xld.b [%sp+0], %r13		; (save code)
	;
	ld.uh %r13, %r1			; %r10 = LO(mem.bit)
	call.d %r3
	ld.w %r12, %r0			; *delay*
	xadd %r1, %r1, 1		; PC++
	xld.b [%sp+1], %r10		; (save LO(mem.bit))
	;
	ld.uh %r13, %r1			; %r10 = HI(mem.bit)
	call.d %r3
	ld.w %r12, %r0			; *delay*
	;
	xld.ub %r14, [%sp+1]		; (restore LO(mem.bit))
	xld.ub %r13, [%sp+0]		; (restore code) *anti-interlock*
	;
	ld.w %r15, %r14			; %r15 = bit
	xsrl %r15, 5
	xand %r14, %r14, 0x1f		; %r14 = mem
	xsll %r14, 8
	or %r14, %r10
	;
	xjp.d ssmp_run_exec
	add %r1, 1			; PC++ *delay*
#endm

/* labs */
#macro ABSOLUTE
	xld.b [%sp+0], %r13		; (save code)
	;
	ld.uh %r13, %r1			; %r10 = LO(labs)
	call.d %r3
	ld.w %r12, %r0			; *delay*
	xadd %r1, %r1, 1		; PC++
	xld.b [%sp+1], %r10		; (save LO(labs))
	;
	ld.uh %r13, %r1			; %r10 = HI(labs)
	call.d %r3
	ld.w %r12, %r0			; *delay*
	;
	xld.ub %r14, [%sp+1]		; (restore LO(labs))
	xsll %r10, 8			; %r14 = labs
	or %r14, %r10
	;
	xld.ub %r13, [%sp+0]		; (restore code)
	xjp.d ssmp_run_exec
	add %r1, 1			; PC++ *delay*
#endm

/* labs+X */
#macro X_INDEXED_ABSOLUTE
	xld.b [%sp+0], %r13		; (save code)
	;
	ld.uh %r13, %r1			; %r10 = LO(labs)
	call.d %r3
	ld.w %r12, %r0			; *delay*
	xadd %r1, %r1, 1		; PC++
	xld.b [%sp+1], %r10		; (save LO(labs))
	;
	ld.uh %r13, %r1			; %r10 = HI(labs)
	call.d %r3
	ld.w %r12, %r0			; *delay*
	;
	xld.ub %r14, [%sp+1]		; (restore LO(labs))
	xld.ub %r11, [%r0+X]		; %r14 = labs+X
	xsll %r10, 8
	or %r14, %r10
	add %r14, %r11
	ld.uh %r14, %r14
	;
	xld.ub %r13, [%sp+0]		; (restore code)
	xjp.d ssmp_run_exec
	add %r1, 1			; PC++ *delay*
#endm

/* labs+Y */
#macro Y_INDEXED_ABSOLUTE
	xld.b [%sp+0], %r13		; (save code)
	;
	ld.uh %r13, %r1			; %r10 = LO(labs)
	call.d %r3
	ld.w %r12, %r0			; *delay*
	xadd %r1, %r1, 1		; PC++
	xld.b [%sp+1], %r10		; (save LO(labs))
	;
	ld.uh %r13, %r1			; %r10 = HI(labs)
	call.d %r3
	ld.w %r12, %r0			; *delay*
	;
	xld.ub %r14, [%sp+1]		; (restore LO(labs))
	xld.ub %r11, [%r0+Y]		; %r14 = labs+Y
	xsll %r10, 8
	or %r14, %r10
	add %r14, %r11
	ld.uh %r14, %r14
	;
	xld.ub %r13, [%sp+0]		; (restore code)
	xjp.d ssmp_run_exec
	add %r1, 1			; PC++ *delay*
#endm

/* (labs+X) */
#macro X_INDEXED_ABSOLUTE_INDIRECT
	xld.b [%sp+0], %r13		; (save code)
	;
	ld.uh %r13, %r1			; %r10 = LO(labs)
	call.d %r3
	ld.w %r12, %r0			; *delay*
	xadd %r1, %r1, 1		; PC++
	xld.b [%sp+1], %r10		; (save LO(labs))
	;
	ld.uh %r13, %r1			; %r10 = HI(labs)
	call.d %r3
	ld.w %r12, %r0			; *delay*
	;
	xld.ub %r13, [%sp+1]		; (restore LO(labs))
	xld.ub %r11, [%r0+X]		; %r13 = labs+X+0
	xsll %r10, 8
	or %r13, %r10
	add %r13, %r11
	ld.uh %r13, %r13
	xadd %r14, %r13, 1		; %r14 = labs+X+1
	xld.h [%sp+2], %r14		; (save labs+X+1)
	;
	call.d %r3			; %r10 = (labs+X+0)
	ld.w %r12, %r0			; *delay*
	xld.b [%sp+1], %r10		; (save (labs+X+0))
	xld.uh %r13, [%sp+2]		; (restore labs+X+1)
	call.d %r3			; %r10 = (labs+X+1)
	ld.w %r12, %r0			; *delay*
	;
	xld.ub %r14, [%sp+1]		; (restore (labs+X+0))
	xsll %r10, 8			; %r14 = (labs+X)
	or %r14, %r10
	;
	xld.ub %r13, [%sp+0]		; (restore code)
	xjp.d ssmp_run_exec
	add %r1, 1			; PC++ *delay*
#endm

/* dp+X,rel */
#macro X_INDEXED_DIRECT_PAGE_RELATIVE
	xld.b [%sp+0], %r13		; (save code)
	;
	ld.uh %r13, %r1			; %r10 = dp
	call.d %r3
	ld.w %r12, %r0			; *delay*
	;
	xld.ub %r11, [%r0+X]		; %r10 = dp+X
	xadd %r1, %r1, 1		; PC++ *anti-interlock*
	add %r10, %r11
	xld.b [%sp+1], %r10		; (save dp+X)
	;
	ld.uh %r13, %r1			; %r10 = rel
	call.d %r3
	ld.w %r12, %r0			; *delay*
	xadd %r1, %r1, 1		; PC++
	;
	ld.b %r15, %r10			; %r15 = PC + (char)rel
	add %r15, %r1
	ld.uh %r15, %r15
	;
	xld.ub %r14, [%sp+1]		; (restore dp+X)
	xld.ub %r13, [%sp+0]		; (restore code)
	;
	xbtst [%r0+PSW], 5		; if(P) %r14 |= 0x100
	xjreq ssmp_run_exec		; !NO-DELAY!
	xoor %r14, %r14, 0x100
	xjp ssmp_run_exec		; !NO-DELAY!
#endm

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

	.global ssmp_run
ssmp_run:
	pushn %r3
	xsub %sp, %sp, 4
	;
	ld.w %r0, %r12			; ssmp
	xld.w %r3, [%r0+READ]		; ssmp->read
	xld.w [%r0+CYCLE], %r13		; CYCLE
	xcmp %r13, 0			; if(CYCLE <= 0) break
	xjrle ssmp_run_exit
	;
ssmp_run_L10:
	xld.ub %r10, [%r0+SLEEP]	; if(SLEEP) break
	xld.uh %r1, [%r0+PC]		; PC *anti-interlock*
	xcmp %r10, 0
	xjrne ssmp_run_exit
	;
	ld.uh %r13, %r1			; code = ssmp->read(ssmp, PC++)
	call.d %r3
	ld.w %r12, %r0			; *delay*
	ld.ub %r13, %r10
	;
	xld.w %r2, ssmp_op_table	; op = &ssmp_op_table[code]
	xsll %r10, 3
	add %r2, %r10
	;
	xld.ub %r10, [%r2+4]		; switch(op->addr)
	xld.w %r11, ssmp_run_table	; *anti-interlock*
	xsll %r10, 2
	add %r10, %r11
	xld.w %r10, [%r10]
	add %r1, 1			; *anti-interlock*
	jp %r10
	;
	; "xjp/xjr?? ssmp_run_exec"の距離が+-256バイトに収まれば、ext拡張が不要になり、高速化できます。
	; 使用頻度の高いものがssmp_run_execに近くなるよう、使用頻度降順(よく使うものほど下)で並べます。
	;
ssmp_run_x_indexed_direct_page_relative:
	X_INDEXED_DIRECT_PAGE_RELATIVE
ssmp_run_x_indexed_absolute_indirect:
	X_INDEXED_ABSOLUTE_INDIRECT
ssmp_run_y_indexed_absolute:
	Y_INDEXED_ABSOLUTE
ssmp_run_x_indexed_absolute:
	X_INDEXED_ABSOLUTE
ssmp_run_absolute:
	ABSOLUTE
ssmp_run_absolute_boolean_bit:
	ABSOLUTE_BOOLEAN_BIT
ssmp_run_direct_page_relative:
	DIRECT_PAGE_RELATIVE
ssmp_run_inmediate_data_to_dp:
	INMEDIATE_DATA_TO_DP
ssmp_run_direct_page_to_dp:
	DIRECT_PAGE_TO_DP
ssmp_run_relative:
	RELATIVE
ssmp_run_indirect_y_indexed_indirect:
	INDIRECT_Y_INDEXED_INDIRECT
ssmp_run_x_indexed_indirect:
	X_INDEXED_INDIRECT
ssmp_run_y_indexed_direct_page:
	Y_INDEXED_DIRECT_PAGE
ssmp_run_x_indexed_direct_page:
	X_INDEXED_DIRECT_PAGE
ssmp_run_direct_page:
	DIRECT_PAGE
ssmp_run_inmediate_data:
	INMEDIATE_DATA
ssmp_run_indirect_page_to_ip:
	INDIRECT_PAGE_TO_IP
ssmp_run_indirect_auto_increment:
	INDIRECT_AUTO_INCREMENT
ssmp_run_indirect:
	INDIRECT
	;
ssmp_run_implied:
ssmp_run_exec:
	xld.w %r10, [%r2+0]		; op->proc(arg)
	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			; !INTERLOCK!
	xld.w [%r0+CYCLE], %r10
	xjrgt ssmp_run_L10		; if(CYCLE <= 0) break
ssmp_run_exit:
	;
	xadd %sp, %sp, 4
	popn %r3
	ret

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

; BOP8 ... 8bit Binary Operation

#macro BOP8_r_DATA $1, $2
	pushn %r0
	;
	xld.ub %r13, [%r12+$2]
	xcall.d ssmp_$1
	ld.w %r0, %r12			; *delay*
	;
	xld.b [%r0+$2], %r10
	;
	popn %r0
	ret
#endm

#macro BOP8_r_ADDRESS $1, $2
	pushn %r0
	;
	xld.w %r10, [%r12+READ]
	ld.w %r13, %r14
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	ld.w %r14, %r10
	xld.ub %r13, [%r0+$2]
	xcall.d ssmp_$1
	ld.w %r0, %r12			; *delay*
	;
	xld.b [%r0+$2], %r10
	;
	popn %r0
	ret
#endm

#macro BOP8_ADDRESS_DATA $1
	pushn %r2
	;
	ld.w %r1, %r14			; (save dest-address)
	ld.w %r2, %r15			; (save src-data)
	;
	xld.w %r10, [%r12+READ]
	ld.w %r13, %r1			; *anti-interlock*
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	ld.w %r13, %r10
	ld.w %r14, %r2			; (restore src-data)
	xcall.d ssmp_$1
	ld.w %r12, %r0			; *delay*
	;
	ld.w %r14, %r10
	xld.w %r10, [%r0+WRITE]
	ld.w %r13, %r1			; *anti-interlock*
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	popn %r2
	ret
#endm

#macro BOP8_ADDRESS_ADDRESS $1
	pushn %r2
	;
	ld.w %r1, %r14			; (save dest-address)
	;
	xld.w %r10, [%r12+READ]
	ld.w %r13, %r15			; *anti-interlock*
	call.d %r10
	ld.w %r0, %r12			; *delay*
	ld.w %r2, %r10			; (save src-data)
	;
	xld.w %r10, [%r0+READ]
	ld.w %r13, %r1			; *anti-interlock*
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	ld.w %r13, %r10
	ld.w %r14, %r2			; (restore src-data)
	xcall.d ssmp_$1
	ld.w %r12, %r0			; *delay*
	;
	ld.w %r14, %r10
	xld.w %r10, [%r0+WRITE]
	ld.w %r13, %r1			; *anti-interlock*
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	popn %r2
	ret
#endm

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

; UOP8 ... 8bit Unary Operation

#macro UOP8_r $1, $2
	pushn %r0
	;
	xld.ub %r13, [%r12+$2]
	xcall.d ssmp_$1
	ld.w %r0, %r12			; *delay*
	;
	xld.b [%r0+$2], %r10
	;
	popn %r0
	ret
#endm

#macro UOP8_ADDRESS $1
	pushn %r1
	;
	ld.w %r1, %r14			; (save address)
	;
	xld.w %r10, [%r12+READ]
	ld.w %r13, %r1			; *anti-interlock*
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	ld.w %r13, %r10
	xcall.d ssmp_$1
	ld.w %r12, %r0			; *delay*
	;
	ld.w %r14, %r10
	xld.w %r10, [%r0+WRITE]
	ld.w %r13, %r1			; *anti-interlock*
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	popn %r1
	ret
#endm

;****************************************************************************
;	8-BIT DATA TRANSMISSION COMMANDS GROUP 1
;****************************************************************************

#macro MOV_r_DATA $1
	xld.ub %r11, [%r12+PSW]
	xld.b [%r12+$1], %r14		; *anti-interlock*
	xand %r11, %r11, ~0x82		; PSW(N,Z)=0
	xrr %r14, 8
	ld.w %r14, %psr			; ????????_??????ZN
	xsll %r14, 7			; ???????Z_N0000000
	or %r11, %r14			; PSW(N)
	xsrl %r14, 7			; ????????_??????ZN
	xand %r14, %r14, 2		; 00000000_000000Z0
	or %r11, %r14			; PSW(Z)
	xld.b [%r12+PSW], %r11
	ret
#endm

#macro MOV_r_ADDRESS $1
	pushn %r0
	;
	xld.w %r10, [%r12+READ]
	ld.w %r13, %r14			; *anti-interlock*
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	xld.ub %r11, [%r0+PSW]
	xld.b [%r0+$1], %r10		; *anti-interlock*
	xand %r11, %r11, ~0x82		; PSW(N,Z)=0
	xrr %r10, 8
	ld.w %r10, %psr			; ????????_??????ZN
	xsll %r10, 7			; ???????Z_N0000000
	or %r11, %r10			; PSW(N)
	xsrl %r10, 7			; ????????_??????ZN
	xand %r10, %r10, 2		; 00000000_000000Z0
	or %r11, %r10			; PSW(Z)
	xld.b [%r0+PSW], %r11
	;
	popn %r0
	ret
#endm

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

	.global ssmpop_MOV_A_DATA
ssmpop_MOV_A_DATA:
	MOV_r_DATA A
	.global ssmpop_MOV_X_DATA
ssmpop_MOV_X_DATA:
	MOV_r_DATA X
	.global ssmpop_MOV_Y_DATA
ssmpop_MOV_Y_DATA:
	MOV_r_DATA Y
	.global ssmpop_MOV_A_ADDRESS
ssmpop_MOV_A_ADDRESS:
	MOV_r_ADDRESS A
	.global ssmpop_MOV_X_ADDRESS
ssmpop_MOV_X_ADDRESS:
	MOV_r_ADDRESS X
	.global ssmpop_MOV_Y_ADDRESS
ssmpop_MOV_Y_ADDRESS:
	MOV_r_ADDRESS Y

;****************************************************************************
;	8-BIT DATA TRANSMISSION COMMANDS GROUP 2
;****************************************************************************

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

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

	.global ssmpop_MOV_ADDRESS_A
ssmpop_MOV_ADDRESS_A:
	MOV_ADDRESS_r A
	.global ssmpop_MOV_ADDRESS_X
ssmpop_MOV_ADDRESS_X:
	MOV_ADDRESS_r X
	.global ssmpop_MOV_ADDRESS_Y
ssmpop_MOV_ADDRESS_Y:
	MOV_ADDRESS_r Y

;****************************************************************************
;	8-BIT DATA TRANSMISSION COMMANDS GROUP 3
;****************************************************************************

#macro MOV_r_r $1, $2
	xld.ub %r14, [%r12+$2]
	xld.ub %r11, [%r12+PSW]		; *anti-interlock*
	xld.b [%r12+$1], %r14		; *anti-interlock*
	xand %r11, %r11, ~0x82		; PSW(N,Z)=0
	xrr %r14, 8
	ld.w %r14, %psr			; ????????_??????ZN
	xsll %r14, 7			; ???????Z_N0000000
	or %r11, %r14			; PSW(N)
	xsrl %r14, 7			; ????????_??????ZN
	xand %r14, %r14, 2		; 00000000_000000Z0
	or %r11, %r14			; PSW(Z)
	xld.b [%r12+PSW], %r11
	ret
#endm

#macro MOV_ADDRESS_DATA
	xld.w %r10, [%r12+WRITE]
	ld.w %r13, %r14			; *anti-interlock*
	call.d %r10
	ld.w %r14, %r15			; *delay*
	ret
#endm

#macro MOV_ADDRESS_ADDRESS
	pushn %r1
	;
	xld.w %r10, [%r12+READ]
	ld.w %r1, %r14			; (save dest)
	ld.w %r13, %r15
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	xld.w %r11, [%r0+WRITE]
	ld.w %r13, %r1			; (restore dest)
	ld.w %r14, %r10
	call.d %r11
	ld.w %r12, %r0			; *delay*
	;
	popn %r1
	ret
#endm

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

	.global ssmpop_MOV_A_X
ssmpop_MOV_A_X:
	MOV_r_r A X
	.global ssmpop_MOV_A_Y
ssmpop_MOV_A_Y:
	MOV_r_r A Y
	.global ssmpop_MOV_X_A
ssmpop_MOV_X_A:
	MOV_r_r X A
	.global ssmpop_MOV_Y_A
ssmpop_MOV_Y_A:
	MOV_r_r Y A
	.global ssmpop_MOV_X_SP
ssmpop_MOV_X_SP:
	MOV_r_r X SP
	.global ssmpop_MOV_SP_X
ssmpop_MOV_SP_X:
	xld.ub %r10, [%r12+X]
	xld.b [%r12+SP], %r10
	/* NO FLAGS AFFECTED */
	ret

	.global ssmpop_MOV_ADDRESS_DATA
ssmpop_MOV_ADDRESS_DATA:
	MOV_ADDRESS_DATA
	.global ssmpop_MOV_ADDRESS_ADDRESS
ssmpop_MOV_ADDRESS_ADDRESS:
	MOV_ADDRESS_ADDRESS

;****************************************************************************
;	8-BIT ARITHMETIC OPERATION COMMANDS
;****************************************************************************

	.global ssmp_ADC
ssmp_ADC:
	xld.ub %r4, [%r12+PSW]		; PSW
	swap %r5, %r13
	swap %r6, %r14
	ld.w %r7, %r4			; c = PSW(C)
	xand %r7, %r7, 1
	swap %r7, %r7
	xand %r4, %r4, ~0xcb		; PSW(N,V,H,Z,C) = 0
	;
	add %r5, %r6			; a + b
	;
	ld.w %r10, %psr			; %psr(C1,V1)
	xand %r10, %r10, 0xc
	;
	add %r5, %r7			; a + b + c
	;
	ld.w %r11, %psr			; %psr(C1|C2,V1^V2,Z2,N2)
	xand %r15, %r11, 0x4
	xor %r10, %r15
	xand %r11, %r11, 0xb
	or %r10, %r11
	xld.ub %r10, [%r10+ssmp_FLAG_CONV]	; PSW(N,V,Z,C)
	;
	; ※TODO: PSW(H)未対応
	;
	or %r4, %r10			; PSW
	xld.b [%r12+PSW], %r4
	;
	ret.d
	swap %r10, %r5			; *delay*

	.global ssmp_SBC
ssmp_SBC:
	xld.ub %r4, [%r12+PSW]		; PSW
	swap %r5, %r13
	swap %r6, %r14
	not %r7, %r4			; c = ~PSW(C)
	xand %r7, %r7, 1
	swap %r7, %r7
	xand %r4, %r4, ~0xcb		; PSW(N,V,H,Z,C) = 0
	;
	sub %r5, %r6			; a - b
	;
	ld.w %r10, %psr			; %psr(C1,V1)
	xand %r10, %r10, 0xc
	;
	sub %r5, %r7			; a + b + c
	;
	ld.w %r11, %psr			; %psr(C1|C2,V1^V2,Z2,N2)
	xand %r15, %r11, 0x4
	xor %r10, %r15
	xand %r11, %r11, 0xb
	or %r10, %r11
	xld.ub %r10, [%r10+ssmp_FLAG_CONV]	; PSW(N,V,Z,C)
	;
	; ※TODO: PSW(H)未対応
	;
	xxor %r10, %r10, 1		; PSW(C) = ~PSW(C)
	or %r4, %r10			; PSW
	xld.b [%r12+PSW], %r4
	;
	ret.d
	swap %r10, %r5			; *delay*

	.global ssmp_CMP
ssmp_CMP:
	xld.ub %r4, [%r12+PSW]		; PSW
	swap %r5, %r13
	swap %r6, %r14
	xand %r4, %r4, ~0x83		; PSW(N,Z,C) = 0
	;
	sub %r5, %r6			; a - b
	;
	ld.w %r10, %psr			; %psr(C,Z,N)
	xand %r10, %r10, 0xb
	xld.ub %r10, [%r10+ssmp_FLAG_CONV]	; PSW(N,Z,C)
	;
	xxor %r10, %r10, 1		; PSW(C) = ~PSW(C) !INTERLOCK!
	or %r4, %r10			; PSW
	xld.b [%r12+PSW], %r4
	;
	ret

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

#macro CMP_r_DATA $1, $2
	xld.ub %r13, [%r12+$2]
	xjp ssmp_$1
#endm

#macro CMP_r_ADDRESS $1, $2
	pushn %r0
	;
	xld.w %r10, [%r12+READ]
	ld.w %r13, %r14
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	ld.w %r14, %r10
	xld.ub %r13, [%r0+$2]
	xcall.d ssmp_$1
	ld.w %r0, %r12			; *delay*
	;
	popn %r0
	ret
#endm

#macro CMP_ADDRESS_DATA $1
	pushn %r2
	;
	ld.w %r1, %r14			; (save dest-address)
	ld.w %r2, %r15			; (save src-data)
	;
	xld.w %r10, [%r12+READ]
	ld.w %r13, %r1			; *anti-interlock*
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	ld.w %r13, %r10
	ld.w %r14, %r2			; (restore src-data)
	xcall.d ssmp_$1
	ld.w %r12, %r0
	;
	popn %r2
	ret
#endm

#macro CMP_ADDRESS_ADDRESS $1
	pushn %r2
	;
	ld.w %r1, %r14			; (save dest-address)
	;
	xld.w %r10, [%r12+READ]
	ld.w %r13, %r15			; *anti-interlock*
	call.d %r10
	ld.w %r0, %r12			; *delay*
	ld.w %r2, %r10			; (save src-data)
	;
	xld.w %r10, [%r0+READ]
	ld.w %r13, %r1			; *anti-interlock*
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	ld.w %r13, %r10
	ld.w %r14, %r2			; (restore src-data)
	xcall.d ssmp_$1
	ld.w %r12, %r0
	;
	popn %r2
	ret
#endm

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

	.global ssmpop_ADC_A_DATA
ssmpop_ADC_A_DATA:
	BOP8_r_DATA ADC, A
	.global ssmpop_SBC_A_DATA
ssmpop_SBC_A_DATA:
	BOP8_r_DATA SBC, A
	.global ssmpop_CMP_A_DATA
ssmpop_CMP_A_DATA:
	CMP_r_DATA CMP, A
	.global ssmpop_CMP_X_DATA
ssmpop_CMP_X_DATA:
	CMP_r_DATA CMP, X
	.global ssmpop_CMP_Y_DATA
ssmpop_CMP_Y_DATA:
	CMP_r_DATA CMP, Y

	.global ssmpop_ADC_A_ADDRESS
ssmpop_ADC_A_ADDRESS:
	BOP8_r_ADDRESS ADC, A
	.global ssmpop_SBC_A_ADDRESS
ssmpop_SBC_A_ADDRESS:
	BOP8_r_ADDRESS SBC, A
	.global ssmpop_CMP_A_ADDRESS
ssmpop_CMP_A_ADDRESS:
	CMP_r_ADDRESS CMP, A
	.global ssmpop_CMP_X_ADDRESS
ssmpop_CMP_X_ADDRESS:
	CMP_r_ADDRESS CMP, X
	.global ssmpop_CMP_Y_ADDRESS
ssmpop_CMP_Y_ADDRESS:
	CMP_r_ADDRESS CMP, Y

	.global ssmpop_ADC_ADDRESS_DATA
ssmpop_ADC_ADDRESS_DATA:
	BOP8_ADDRESS_DATA ADC
	.global ssmpop_SBC_ADDRESS_DATA
ssmpop_SBC_ADDRESS_DATA:
	BOP8_ADDRESS_DATA SBC
	.global ssmpop_CMP_ADDRESS_DATA
ssmpop_CMP_ADDRESS_DATA:
	CMP_ADDRESS_DATA CMP

	.global ssmpop_ADC_ADDRESS_ADDRESS
ssmpop_ADC_ADDRESS_ADDRESS:
	BOP8_ADDRESS_ADDRESS ADC
	.global ssmpop_SBC_ADDRESS_ADDRESS
ssmpop_SBC_ADDRESS_ADDRESS:
	BOP8_ADDRESS_ADDRESS SBC
	.global ssmpop_CMP_ADDRESS_ADDRESS
ssmpop_CMP_ADDRESS_ADDRESS:
	CMP_ADDRESS_ADDRESS CMP

;****************************************************************************
;	8-BIT LOGIC OPERATION COMMANDS
;****************************************************************************

	.global ssmp_AND
ssmp_AND:
	and %r13, %r14
	xld.ub %r11, [%r12+PSW]
	ld.w %r10, %r13			; *anti-interlock*
	xand %r11, %r11, ~0x82		; PSW(N,Z)=0
	;
	xrr %r13, 8
	ld.w %r13, %psr			; ????????_??????ZN
	xsll %r13, 7			; ???????Z_N0000000
	or %r11, %r13			; PSW(N)
	xsrl %r13, 7			; ????????_??????ZN
	xand %r13, %r13, 2		; 00000000_000000Z0
	or %r11, %r13			; PSW(Z)
	xld.b [%r12+PSW], %r11
	;
	ret

	.global ssmp_OR
ssmp_OR:
	or %r13, %r14
	xld.ub %r11, [%r12+PSW]
	ld.w %r10, %r13			; *anti-interlock*
	xand %r11, %r11, ~0x82		; PSW(N,Z)=0
	;
	xrr %r13, 8
	ld.w %r13, %psr			; ????????_??????ZN
	xsll %r13, 7			; ???????Z_N0000000
	or %r11, %r13			; PSW(N)
	xsrl %r13, 7			; ????????_??????ZN
	xand %r13, %r13, 2		; 00000000_000000Z0
	or %r11, %r13			; PSW(Z)
	xld.b [%r12+PSW], %r11
	;
	ret

	.global ssmp_EOR
ssmp_EOR:
	xor %r13, %r14
	xld.ub %r11, [%r12+PSW]
	ld.w %r10, %r13			; *anti-interlock*
	xand %r11, %r11, ~0x82		; PSW(N,Z)=0
	;
	xrr %r13, 8
	ld.w %r13, %psr			; ????????_??????ZN
	xsll %r13, 7			; ???????Z_N0000000
	or %r11, %r13			; PSW(N)
	xsrl %r13, 7			; ????????_??????ZN
	xand %r13, %r13, 2		; 00000000_000000Z0
	or %r11, %r13			; PSW(Z)
	xld.b [%r12+PSW], %r11
	;
	ret

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

	.global ssmpop_AND_A_DATA
ssmpop_AND_A_DATA:
	BOP8_r_DATA AND, A
	.global ssmpop_OR_A_DATA
ssmpop_OR_A_DATA:
	BOP8_r_DATA OR, A
	.global ssmpop_EOR_A_DATA
ssmpop_EOR_A_DATA:
	BOP8_r_DATA EOR, A

	.global ssmpop_AND_A_ADDRESS
ssmpop_AND_A_ADDRESS:
	BOP8_r_ADDRESS AND, A
	.global ssmpop_OR_A_ADDRESS
ssmpop_OR_A_ADDRESS:
	BOP8_r_ADDRESS OR, A
	.global ssmpop_EOR_A_ADDRESS
ssmpop_EOR_A_ADDRESS:
	BOP8_r_ADDRESS EOR, A

	.global ssmpop_AND_ADDRESS_DATA
ssmpop_AND_ADDRESS_DATA:
	BOP8_ADDRESS_DATA AND
	.global ssmpop_OR_ADDRESS_DATA
ssmpop_OR_ADDRESS_DATA:
	BOP8_ADDRESS_DATA OR
	.global ssmpop_EOR_ADDRESS_DATA
ssmpop_EOR_ADDRESS_DATA:
	BOP8_ADDRESS_DATA EOR

	.global ssmpop_AND_ADDRESS_ADDRESS
ssmpop_AND_ADDRESS_ADDRESS:
	BOP8_ADDRESS_ADDRESS AND
	.global ssmpop_OR_ADDRESS_ADDRESS
ssmpop_OR_ADDRESS_ADDRESS:
	BOP8_ADDRESS_ADDRESS OR
	.global ssmpop_EOR_ADDRESS_ADDRESS
ssmpop_EOR_ADDRESS_ADDRESS:
	BOP8_ADDRESS_ADDRESS EOR

;****************************************************************************
;	ADDITION & SUBTRACTION COMMANDS
;****************************************************************************

	.global ssmp_INC
ssmp_INC:
	xld.ub %r11, [%r12+PSW]
	xadd %r13, %r13, 1		; *anti-interlock*
	xand %r11, %r11, ~0x82		; PSW(N,Z)=0
	ld.ub %r13, %r13
	ld.w %r10, %r13
	;
	xrr %r13, 8
	ld.w %r13, %psr			; ????????_??????ZN
	xsll %r13, 7			; ???????Z_N0000000
	or %r11, %r13			; PSW(N)
	xsrl %r13, 7			; ????????_??????ZN
	xand %r13, %r13, 2		; 00000000_000000Z0
	or %r11, %r13			; PSW(Z)
	xld.b [%r12+PSW], %r11
	;
	ret

	.global ssmp_DEC
ssmp_DEC:
	xld.ub %r11, [%r12+PSW]
	xsub %r13, %r13, 1		; *anti-interlock*
	xand %r11, %r11, ~0x82		; PSW(N,Z)=0
	ld.ub %r13, %r13
	ld.w %r10, %r13
	;
	xrr %r13, 8
	ld.w %r13, %psr			; ????????_??????ZN
	xsll %r13, 7			; ???????Z_N0000000
	or %r11, %r13			; PSW(N)
	xsrl %r13, 7			; ????????_??????ZN
	xand %r13, %r13, 2		; 00000000_000000Z0
	or %r11, %r13			; PSW(Z)
	xld.b [%r12+PSW], %r11
	;
	ret

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

	.global ssmpop_INC_A
ssmpop_INC_A:
	UOP8_r INC, A
	.global ssmpop_INC_X
ssmpop_INC_X:
	UOP8_r INC, X
	.global ssmpop_INC_Y
ssmpop_INC_Y:
	UOP8_r INC, Y

	.global ssmpop_DEC_A
ssmpop_DEC_A:
	UOP8_r DEC, A
	.global ssmpop_DEC_X
ssmpop_DEC_X:
	UOP8_r DEC, X
	.global ssmpop_DEC_Y
ssmpop_DEC_Y:
	UOP8_r DEC, Y

	.global ssmpop_INC_ADDRESS
ssmpop_INC_ADDRESS:
	UOP8_ADDRESS INC
	.global ssmpop_DEC_ADDRESS
ssmpop_DEC_ADDRESS:
	UOP8_ADDRESS DEC

;****************************************************************************
;	BRANCHING COMMANDS
;****************************************************************************

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

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

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

	.global ssmpop_JMP_ADDRESS
ssmpop_JMP_ADDRESS:
	xld.h [%r12+PC], %r14
	ret
	.global ssmpop_BCC_ADDRESS
ssmpop_BCC_ADDRESS:
	BNcc_ADDRESS 0
	.global ssmpop_BCS_ADDRESS
ssmpop_BCS_ADDRESS:
	Bcc_ADDRESS 0
	.global ssmpop_BNE_ADDRESS
ssmpop_BNE_ADDRESS:
	BNcc_ADDRESS 1
	.global ssmpop_BEQ_ADDRESS
ssmpop_BEQ_ADDRESS:
	Bcc_ADDRESS 1
	.global ssmpop_BVC_ADDRESS
ssmpop_BVC_ADDRESS:
	BNcc_ADDRESS 6
	.global ssmpop_BVS_ADDRESS
ssmpop_BVS_ADDRESS:
	Bcc_ADDRESS 6
	.global ssmpop_BPL_ADDRESS
ssmpop_BPL_ADDRESS:
	BNcc_ADDRESS 7
	.global ssmpop_BMI_ADDRESS
ssmpop_BMI_ADDRESS:
	Bcc_ADDRESS 7

;****************************************************************************
;	SUB-ROUTINE CALL RETURN COMMANDS
;****************************************************************************

	.global ssmpop_CALL_ADDRESS
ssmpop_CALL_ADDRESS:
	pushn %r2
	;
	xld.ub %r1, [%r12+SP]		; SP|0x100
	xld.uh %r2, [%r12+PC]		; PC *anti-interlock*
	xoor %r1, %r1, 0x100
	;
	xld.h [%r12+PC], %r14		; PC <= address
	;
	xld.w %r10, [%r12+WRITE]	; PUSH(PCH)
	ld.w %r13, %r1
	ld.w %r14, %r2
	xsrl %r14, 8
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	;				; SP|0x100 == 0x100      〜0x1ff
	xsub %r1, %r1, 1		; -1       => 0x0ff      〜0x1fe
	xoor %r1, %r1, 0x100		;   |0x100 => 0x1ff,0x100〜0x1fe
	;
	xld.w %r10, [%r0+WRITE]		; PUSH(PCL)
	ld.w %r13, %r1
	ld.ub %r14, %r2
	call.d %r10
	ld.w %r12, %r0			; *delay*
	;
	xsub %r1, %r1, 1		; SP--
	xld.b [%r0+SP], %r1
	;
	popn %r2
	ret

	.global ssmpop_RET
ssmpop_RET:
	pushn %r2
	;
	xld.ub %r1, [%r12+SP]		; SP         == 0x000〜      0x0ff
	xld.w %r10, [%r12+READ]		; *anti-interlock*
	xadd %r1, %r1, 1		; SP++       => 0x001〜      0x100
	xoor %r1, %r1, 0x100		; SP++|0x100 => 0x101〜0x1ff,0x100
	;
	ld.w %r13, %r1			; POP(PCL)
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	ld.w %r2, %r10			; (save PCL)
	;
	;				; SP|0x100 == 0x100〜      0x1ff
	xadd %r1, %r1, 1		; +1       => 0x101〜      0x200
	ld.ub %r1, %r1			;          => 0x001〜0x0ff,0x000
	xoor %r1, %r1, 0x100		;   |0x100 => 0x101〜0x1ff,0x100
	;
	xld.w %r10, [%r0+READ]		; POP(PCH)
	ld.w %r13, %r1			; *anti-interlock*
	call.d %r10
	ld.w %r12, %r0			; *delay*
	;
	xsll %r10, 8			; PC = PCL | PCH << 8
	or %r10, %r2
	xld.h [%r0+PC], %r10
	;
	xld.b [%r0+SP], %r1		; SP
	;
	popn %r2
	ret

;****************************************************************************
;	STACK OPERATION COMMANDS
;****************************************************************************/

#macro PUSH_r $1
	xld.w %r10, [%r12+WRITE]
	xld.ub %r13, [%r12+SP]
	xld.ub %r14, [%r12+$1]		; *anti-interlock*
	xsub %r11, %r13, 1
	xld.b [%r12+SP], %r11
	xoor %r13, %r13, 0x100
	call %r10
	ret
#endm

#macro POP_r $1
	pushn %r0
	;
	xld.ub %r13, [%r12+SP]
	xld.w %r10, [%r12+READ]		; *anti-interlock*
	xadd %r13, %r13, 1
	xld.b [%r12+SP], %r13
	ld.ub %r13, %r13
	xoor %r13, %r13, 0x100
	call.d %r10
	ld.w %r0, %r12			; *delay*
	;
	xld.b [%r0+$1], %r10
	;
	popn %r0
	ret
#endm

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

	.global ssmpop_PUSH_A
ssmpop_PUSH_A:
	PUSH_r A
	.global ssmpop_PUSH_X
ssmpop_PUSH_X:
	PUSH_r X
	.global ssmpop_PUSH_Y
ssmpop_PUSH_Y:
	PUSH_r Y
	.global ssmpop_PUSH_PSW
ssmpop_PUSH_PSW:
	PUSH_r PSW

	.global ssmpop_POP_A
ssmpop_POP_A:
	POP_r A
	.global ssmpop_POP_X
ssmpop_POP_X:
	POP_r X
	.global ssmpop_POP_Y
ssmpop_POP_Y:
	POP_r Y
	.global ssmpop_POP_PSW
ssmpop_POP_PSW:
	POP_r PSW

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

#endif /*SSMP_ASM*/
