/*	
 *	framssm.c
 *
 *	P/ECE S-SMP (SPC700) Emulator
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2004 Naoyuki Sawa
 *
 *	* Sun Jan 04 21:33:00 JST 2004 Naoyuki Sawa
 *	- 作成開始。
 */
#include "clip.h"
#include "clipssmi.h"	/*SSMPエミュレータ実装用マクロ*/

/****************************************************************************
 *	SSMPコア内蔵のメインメモリREAD/WRITE外部関数
 ****************************************************************************/

/* SSMP構\造体(24バイト)の直後にメインメモリが配置されていることを仮定します。
 * バイナリレイアウトが異なる場合や、バンク切替などの特例処理が必要な場合は、
 * アプリケーション定義の外部関数を用意してください。
 */

#ifndef SSMP_ASM	/****************************************************/

unsigned char
ssmp_internal_read(SSMP* ssmp, unsigned short addr)
{
	return ((unsigned char*)(ssmp + 1))[addr];
}
void
ssmp_internal_write(SSMP* ssmp, unsigned short addr, unsigned char data)
{
	((unsigned char*)(ssmp + 1))[addr] = data;
}

#else	/********************************************************************/

asm("
	.code
	.align 1
	.global ssmp_internal_read
ssmp_internal_read:
	add %r12, %r13
	xld.ub %r10, [%r12+24]
	ret
");
asm("
	.code
	.align 1
	.global ssmp_internal_write
ssmp_internal_write:
	add %r12, %r13
	xld.b [%r12+24], %r14
	ret
");

#endif	/********************************************************************/

/****************************************************************************
 *	
 ****************************************************************************/

#ifndef SSMP_ASM

void
ssmp_run(SSMP* ssmp, int cycle)
{
	unsigned char code;
	const SSMPOP* op;
	int arg1 = 0; /* 警告抑制 */
	int arg2 = 0; /* 警告抑制 */

	CYCLE = cycle;
	while(!SLEEP && CYCLE > 0) {
#ifdef SSMP_TRACE
		ssmp_dump(ssmp);
#endif /*SSMP_TRACE*/
		SSMPTRACE("%04x: ", PC);
		FETCH(code);
		op = &ssmp_op_table[code];
		switch(op->addr) {
		/*==== operand bytes=0 ====*/
		case SSMP_IMPLIED:				/* A,X,Y,etc */
			break;
		case SSMP_INDIRECT:				/* (X) */
			arg1 = (PSW & 0x20) << 3 | X;
			break;
		case SSMP_INDIRECT_AUTO_INCREMENT:		/* (X)+ */
			arg1 = (PSW & 0x20) << 3 | X++;
			break;
		case SSMP_INDIRECT_PAGE_TO_IP:			/* (X),(Y) */
			arg1 = (PSW & 0x20) << 3 | X;
			arg2 = (PSW & 0x20) << 3 | Y;
			break;
		/*==== operand bytes=1 ====*/
		case SSMP_INMEDIATE_DATA:			/* #inm */
			FETCH(arg1);
			break;
		case SSMP_DIRECT_PAGE:				/* dp */
			FETCH(arg1);
			arg1 |= (PSW & 0x20) << 3;
			break;
		case SSMP_X_INDEXED_DIRECT_PAGE:		/* dp+X */
			FETCH(arg1);
			arg1 += X;
			arg1 &= 0xff;
			arg1 |= (PSW & 0x20) << 3;
			break;
		case SSMP_Y_INDEXED_DIRECT_PAGE:		/* dp+Y */
			FETCH(arg1);
			arg1 += Y;
			arg1 &= 0xff;
			arg1 |= (PSW & 0x20) << 3;
			break;
		case SSMP_X_INDEXED_INDIRECT:			/* (dp+X) */
			FETCH(arg1);
			arg1 += X;
			arg1 = READ(( arg1      & 0xff) | (PSW & 0x20) << 3)
			     | READ(((arg1 + 1) & 0xff) | (PSW & 0x20) << 3) << 8;
			break;
		case SSMP_INDIRECT_Y_INDEXED_INDIRECT:		/* (dp)+Y */
			FETCH(arg1);
			arg1 = READ(( arg1            ) | (PSW & 0x20) << 3)
			     | READ(((arg1 + 1) & 0xff) | (PSW & 0x20) << 3) << 8;
			arg1 += Y;
			arg1 &= 0xffff;
			break;
		case SSMP_RELATIVE:				/* rel */
			FETCH(arg1);
			arg1 = PC + (char)arg1;
			arg1 &= 0xffff;
			break;
		/*==== operand bytes=2 ====*/
		case SSMP_DIRECT_PAGE_TO_DP:			/* dp(d),dp(s) */
			/* 機械語:	[0]	[1]	[2]
			 *		命令	dp(s)	dp(d)
			 *			     ×
			 * 読み込み:	code	arg1	arg2
			 *		命令	dp(d)	dp(s)
			 */
			FETCH(arg2);
			arg2 |= (PSW & 0x20) << 3;
			FETCH(arg1);
			arg1 |= (PSW & 0x20) << 3;
			break;
		case SSMP_INMEDIATE_DATA_TO_DP:			/* dp,#inm */
			/* 機械語:	[0]	[1]	[2]
			 *		命令	#inm	dp
			 *			     ×
			 * 読み込み:	code	arg1	arg2
			 *		命令	dp	#inm
			 */
			FETCH(arg2);
			FETCH(arg1);
			arg1 |= (PSW & 0x20) << 3;
			break;
		case SSMP_DIRECT_PAGE_RELATIVE:			/* dp,rel */
			/* 機械語:	[0]	[1]	[2]
			 *		命令	dp	rel
			 *			 |	 |
			 * 読み込み:	code	arg1	arg2
			 *		命令	dp	rel
			 */
			FETCH(arg1);
			arg1 |= (PSW & 0x20) << 3;
			FETCH(arg2);
			arg2 = PC + (char)arg2;
			arg2 &= 0xffff;
			break;
		case SSMP_ABSOLUTE_BOOLEAN_BIT:			/* mem.bit */
			/* 機械語:	[0]	[1]	[2]
			 *		命令	==mem.bit==
			 *
			 *		==[２]== ==[１]==
			 *		bbbaaaaa_aaaaaaaa
			 *		|||+++++-++++++++- mem ($0000〜$1fff)
			 *		+++--------------- bit (0〜7)
			 *
			 * 読み込み:	code	arg1	arg2
			 *		命令	mem	bit
			 */
			FETCH(arg1);
			FETCH(arg2);
			arg1 |= (arg2 & 0x1f) << 8;
			arg2 >>= 5;
			break;
		case SSMP_ABSOLUTE:				/* labs */
			/* 機械語:	[0]	[1]	[2]
			 *		命令	labsLo	labsHi
			 *			 |   ／
			 * 読み込み:	code	arg1
			 *		命令	labs
			 */
			FETCH(arg1);
			FETCH(arg2);
			arg1 |= arg2 << 8;
			break;
		case SSMP_X_INDEXED_ABSOLUTE:			/* labs+X */
			/* 機械語:	[0]	[1]	[2]
			 *		命令	labsLo	labsHi
			 *			 |   ／
			 * 読み込み:	code	arg1
			 *		命令	labs+X
			 */
			FETCH(arg1);
			FETCH(arg2);
			arg1 |= arg2 << 8;
			arg1 += X;
			arg1 &= 0xffff;
			break;
		case SSMP_Y_INDEXED_ABSOLUTE:			/* labs+Y */
			/* 機械語:	[0]	[1]	[2]
			 *		命令	labsLo	labsHi
			 *			 |   ／
			 * 読み込み:	code	arg1
			 *		命令	labs+Y
			 */
			FETCH(arg1);
			FETCH(arg2);
			arg1 |= arg2 << 8;
			arg1 += Y;
			arg1 &= 0xffff;
			break;
		case SSMP_X_INDEXED_ABSOLUTE_INDIRECT:		/* (labs+X) */
			/* 機械語:	[0]	[1]	[2]
			 *		命令	labsLo	labsHi
			 *			 |   ／
			 * 読み込み:	code	arg1
			 *		命令	(labs+X)
			 */
			FETCH(arg1);
			FETCH(arg2);
			arg1 |= arg2 << 8;
			arg1 += X;
			arg1 &= 0xffff;
			arg1 = READW(arg1);
			break;
		case SSMP_X_INDEXED_DIRECT_PAGE_RELATIVE:	/* dp+X,rel */
			/* 機械語:	[0]	[1]	[2]
			 *		命令	dp	rel
			 *			 |	 |
			 * 読み込み:	code	arg1	arg2
			 *		命令	dp+X	labs
			 */
			FETCH(arg1);
			arg1 += X;
			arg1 &= 0xff;
			arg1 |= (PSW & 0x20) << 3;
			FETCH(arg2);
			arg2 = PC + (char)arg2;
			arg2 &= 0xffff;
			break;
#ifndef PIECE /* P/ECEでは高速RAMメモリ不足のためカット */
		default:
			DIE();
#endif /*PIECE*/
		}
		EXEC();
		SSMPTRACE("\n");
	}
}

#endif /*SSMP_ASM*/

/****************************************************************************
 *	
 ****************************************************************************/

