/* Copyright (c)1994-2000 Begemot Computer Associates. All rights reserved.
 * See the file COPYRIGHT for details of redistribution and use. */

# include "regi.h"
# include "proc.h"
# include "instruct.h"

RCSID("$Id: special.c 454 2000-11-24 10:34:24Z hbb $")

# ifdef USE_SPECIAL

# define CN 	(proc.n = 0)
# define CZ 	(proc.z = 0)
# define CC 	(proc.c = 0)
# define CV 	(proc.v = 0)

# define SN 	(proc.n = 1)
# define SZ 	(proc.z = 1)
# define SC 	(proc.c = 1)
# define SV 	(proc.v = 1)

/*
 * RTS PC
 * 1.96%
 */
void RTS7(void);
void
RTS7(void)
{
	u_short sp = proc.reg[6];

	proc.reg[6] += 2;
	proc.mmr1reg[0] = 6;
	proc.mmr1chg[0] += 2;
	if(sp & 1)
		Trap4(0100);
	proc.reg[7] = mfetch(sp, 1);
}

/*
 * JSR PC, (PC)+
 * 1.15%
 */
void JSR737(void);
void
JSR737(void)
{
	u_short pc = proc.reg[7];

	/* fetch destination address */
	proc.reg[7] += 2;
	src = mfetch(pc, 0);

	/* push pc */
	proc.reg[6] -= 2;
	proc.mmr1reg[1] = 6;
	proc.mmr1chg[1] = -2;
	proc.push++;
	if(proc.reg[6] & 1)
		Trap4(0100);
	mstore(proc.reg[6], 1, proc.reg[7]);

	/* Jump */
	proc.reg[7] = src;
}

/*
 * JSR PC,@R1
 * 1.05%
 */
void JSR711(void);
void
JSR711(void)
{
	/* push pc */
	proc.reg[6] -= 2;
	proc.mmr1reg[1] = 6;
	proc.mmr1chg[1] = -2;
	proc.push++;
	if(proc.reg[6] & 1)
		Trap4(0100);
	mstore(proc.reg[6], 1, proc.reg[7]);

	/* Jump */
	proc.reg[7] = proc.reg[1];
}

/*
 * JSR R5, XXX(PC)
 * 0.98%
 */
void JSR567(void);
void
JSR567(void)
{
	u_short pc = proc.reg[7];

	/* fetch destination address */
	proc.reg[7] += 2;
	src = mfetch(pc, 0) + proc.reg[7];

	/* push R5 */
	proc.reg[6] -= 2;
	proc.mmr1reg[1] = 6;
	proc.mmr1chg[1] = -2;
	proc.push++;
	if(proc.reg[6] & 1)
		Trap4(0100);
	mstore(proc.reg[6], 1, proc.reg[5]);

	/* Jump */
	proc.reg[5] = proc.reg[7];
	proc.reg[7] = src;
}

/*
 * SOB R0
 * 2.1%
 */
void SOB0(void);
void
SOB0(void)
{
	if(--proc.reg[0] != 0)
		proc.reg[7] -= (proc.cmd & 077) << 1;
}

/*
 * MOV R0,-(SP)		0.33%
 * MOV R1,-(SP)		0.36%
 * MOV R2,-(SP)		1.37%
 * MOV R3,-(SP)		1.30%
 * MOV R4,-(SP)		1.34%
 * MOV R5,-(SP)		0.16%
 */
# define PUSH(R)					\
void MOV0##R##46(void);					\
void							\
MOV0##R##46(void)					\
{							\
	TestW(proc.reg[R]); CV;				\
							\
	proc.reg[6] -= 2;				\
	proc.mmr1reg[1] = 6;				\
	proc.mmr1chg[1] = -2;				\
	proc.push++;					\
	if(proc.reg[6] & 1)				\
		Trap4(0100);				\
	mstore(proc.reg[6], 1, proc.reg[R]);	\
}

PUSH(0) PUSH(1) PUSH(2) PUSH(3) PUSH(4) PUSH(5)

/*
 * MOV XXX,-(SP)
 * 1.39%
 */
void MOV6746(void);
void
MOV6746(void)
{
	u_short a;

	a = proc.reg[7];
	proc.reg[7] += 2;
	a += mfetch(a, 0) + 2;
	if(a & 1)
		Trap4(0100);
	src = mfetch(a, 1);

	TestW(src); CV;

	proc.reg[6] -= 2;
	proc.mmr1reg[1] = 6;
	proc.mmr1chg[1] = -2;
	proc.push++;
	if(proc.reg[6] & 1)
		Trap4(0100);
	mstore(proc.reg[6], 1, src);
}

/*
 * MOV (R1)+, (R2)+
 * 1.8%
 */
void MOV2122(void);
void
MOV2122(void)
{
	u_short a;

	a = proc.reg[1];
	proc.reg[1] += 2;
	proc.mmr1reg[0] = 1;
	proc.mmr1chg[0] = 2;
	if(proc.reg[1] & 1)
		Trap4(0100);
	src = mfetch(a, 1);

	TestW(src); CV;

	a = proc.reg[2];
	proc.reg[2] += 2;
	proc.mmr1reg[1] = 2;
	proc.mmr1chg[1] = 2;
	if(proc.reg[2] & 1)
		Trap4(0100);
	mstore(a, 1, src);
}

/*
 * MOV RX,RY
 */
# define REGMOV(S,D)					\
void MOV0##S##0##D(void);				\
void							\
MOV0##S##0##D(void)					\
{							\
	proc.reg[D] = proc.reg[S];			\
	TestW(proc.reg[D]); CV;				\
}

REGMOV(0,0) REGMOV(0,1) REGMOV(0,2) REGMOV(0,3) REGMOV(0,4) REGMOV(0,5)
REGMOV(1,0) REGMOV(1,1) REGMOV(1,2) REGMOV(1,3) REGMOV(1,4) REGMOV(1,5)
REGMOV(2,0) REGMOV(2,1) REGMOV(2,2) REGMOV(2,3) REGMOV(2,4) REGMOV(2,5)
REGMOV(3,0) REGMOV(3,1) REGMOV(3,2) REGMOV(3,3) REGMOV(3,4) REGMOV(3,5)
REGMOV(4,0) REGMOV(4,1) REGMOV(4,2) REGMOV(4,3) REGMOV(4,4) REGMOV(4,5)
REGMOV(5,0) REGMOV(5,1) REGMOV(5,2) REGMOV(5,3) REGMOV(5,4) REGMOV(5,5)

# endif
