/* Copyright (c)1994-2000 Begemot Computer Associates. All rights reserved.
 * See the file COPYRIGHT for details of redistribution and use. */
/* $Id: instruct.h 461 2000-12-04 17:03:43Z hbb $ */

# if defined(INS_I386)

/************************************************************
 *
 * processor emulation - I386
 */
/*
 * Some of the byte patterns generate as warnings, but there is no way
 * to generate the byte register names.
 */

/*
 * fast block move, addresses are aligned on 16bit boundaries
 * It turns out that this isn't faster than bcopy!
# define CopyW(T,F,C)	asm("cld; 			\
			     movl %2, %%ecx;		\
			     andl $1, %2;		\
			     shrl $1, %%ecx;		\
			     rep; movsl;		\
			     movl %2, %%ecx;		\
			     rep; movsw"		\
			   : : "D"(T), "S"(F), "r"(C) : "ecx")
 */
# define CopyW(T,F,C)	memcpy((T), (F), (C) << 1)

/*
 * Test word/byte and set N and Z
 */
# define TestW(V)	asm("testw %2, %2; setz %0; sets %1" 		\
			   : "=m"(proc.z), "=m"(proc.n) 		\
			   : "r"((short)V) : "cc")
# define TestB(V)	asm("testb %2, %2; setz %0; sets %1" 		\
			   : "=m"(proc.z), "=m"(proc.n) 		\
			   : "q"(V) : "cc")

/*
 * compare words/bytes and set NZCV
 */
# define CmpW(D,S)	asm("subw %4, %5; setz %0; sets %1; setb %2; seto %3" \
			   : "=m"(proc.z), "=m"(proc.n), "=m"(proc.c), "=m"(proc.v) \
			   : "r"((short)D), "r"((short)S) : "cc")
# define CmpB(D,S)	asm("subb %4, %5; setz %0; sets %1; setb %2; seto %3" \
			   : "=m"(proc.z), "=m"(proc.n), "=m"(proc.c), "=m"(proc.v) \
			   : "q"(D), "q"(S) : "cc")

/*
 * sub/add words/bytes and set NZCV
 */
# define SubWC(D,S)	asm("subw %6, %5; setz %0; sets %1; setb %2; seto %3" \
			   : "=m"(proc.z), "=m"(proc.n), "=m"(proc.c), "=m"(proc.v), "=r"(D) \
			   : "4"((short)D), "g"((short)S) : "cc")
# define AddWC(D,S)	asm("addw %6, %5; setz %0; sets %1; setb %2; seto %3" \
			   : "=m"(proc.z), "=m"(proc.n), "=m"(proc.c), "=m"(proc.v), "=r"(D) \
			   : "4"((short)D), "g"((short)S) : "cc")
# define SubBC(D,S)	asm("subb %%dl, %%al; setz %0; sets %1; setb %2; seto %3" \
			   : "=m"(proc.z), "=m"(proc.n), "=m"(proc.c), "=m"(proc.v), "=a"(D) \
			   : "4"(D), "d"(S) : "cc")
# define AddBC(D,S)	asm("addb %%dl, %%al; setz %0; sets %1; setb %2; seto %3" \
			   : "=m"(proc.z), "=m"(proc.n), "=m"(proc.c), "=m"(proc.v), "=a"(D) \
			   : "4"(D), "d"(S) : "cc")

/*
 * sub/add words/bytes and set NZV
 */
# define SubW(D,S)	asm("subw %5, %4; setz %0; sets %1; seto %2" \
			   : "=m"(proc.z), "=m"(proc.n), "=m"(proc.v), "=g"(D) \
			   : "3"((short)D), "r"((short)S) : "cc")
# define AddW(D,S)	asm("addw %5, %4; setz %0; sets %1; seto %2" \
			   : "=m"(proc.z), "=m"(proc.n), "=m"(proc.v), "=g"(D) \
			   : "3"((short)D), "r"((short)S) : "cc")
# define SubB(D,S)	asm("subb %%dl, %%al; setz %0; sets %1; seto %2" \
			   : "=m"(proc.z), "=m"(proc.n), "=m"(proc.v), "=a"(D) \
			   : "3"(D), "d"(S) : "cc")
# define AddB(D,S)	asm("addb %%dl, %%al; setz %0; sets %1; seto %2" \
			   : "=m"(proc.z), "=m"(proc.n), "=m"(proc.v), "=a"(D) \
			   : "3"(D), "d"(S) : "cc")

# define SwabB(D)	asm("xchgb %%al, %%ah" : "=a"(D) : "0"((short)D) : "cc");

/*
 * this is a workaround for a bug in cc1
# define SCHAR(S)	({ u_short _tm1 = (S); (signed short)(signed char)_tm1; })
*/
# define SCHAR(S)	((signed short)(signed char)(S))


/* v/d -> v1
 * v%d -> v2
 * idivl: %eax / %e?x -> %eax
 *        %eax % %e?x -> %edx
 * ==> v1==a v2==d
 *     v==v1
 * Force d into %cx - gcc may put it into %edx and this will fail!
 */
# define Div(V1,V2,V,D)	asm("cltd; idivl %3"		\
		   	   : "=a"(V1), "=d"(V2)		\
		   	   : "0"(V), "c"(D))

# elif defined(INS_SPARC)

/************************************************************
 *
 * processor emulation - SPARC
 */

/*
 * fast block move, addresses are aligned on 16bit boundaries
 */
# define CopyW(T,F,C)	memcpy((T), (F), (C) << 1)

/*
 * Test word/byte and set N and Z
 */
# define TestW(V)	asm("	sll	%2,16,%%g1			;\
				tst	%%g1				;\
				be,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%0				;\
				bneg,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%1"			\
			: "=m"(proc.z), "=m"(proc.n)			\
			: "r"((short)V) : "g1", "cc")

# define TestB(V)	asm("	sll	%2,24,%%g1			;\
				tst	%%g1				;\
				be,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%0				;\
				bneg,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%1"			\
			: "=m"(proc.z), "=m"(proc.n)			\
			: "r"(V) : "g1", "cc")

/*
 * compare words/bytes and set NZCV
 */
# define CmpW(D,S)	asm("	sll	%4,16,%4			;\
				sll	%5,16,%5			;\
				cmp	%5,%4				;\
				be,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%0				;\
				bneg,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%1				;\
				addx	%%g0,0,%%g1			;\
				stb	%%g1,%2				;\
				bvs,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%3"			\
			: "=m"(proc.z), "=m"(proc.n), "=m"(proc.c), "=m"(proc.v) \
			: "r"((short)D), "r"((short)S) : "g1", "cc" )

# define CmpB(D,S)	asm("	sll	%4,24,%4			;\
				sll	%5,24,%5			;\
				cmp	%5,%4				;\
				be,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%0				;\
				bneg,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%1				;\
				addx	%%g0,0,%%g1			;\
				stb	%%g1,%2				;\
				bvs,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%3"			\
			: "=m"(proc.z), "=m"(proc.n), "=m"(proc.c), "=m"(proc.v) \
			: "r"((short)D), "r"((short)S) : "g1", "cc" )

/*
 * sub/add words/bytes and set NZCV
 */
# define SubWC(D,S)	asm("	sll	%6,16,%6			;\
				sll	%5,16,%5			;\
				subcc	%5,%6,%4			;\
				sra	%4,16,%4			;\
				be,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%0				;\
				bneg,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%1				;\
				addx	%%g0,0,%%g1			;\
				stb	%%g1,%2				;\
				bvs,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%3"			\
			: "=m"(proc.z), "=m"(proc.n), "=m"(proc.c), "=m"(proc.v), "=r"(D) \
			: "4"((short)D), "r"((short)S) : "g1", "cc" )

# define AddWC(D,S)	asm("	sll	%6,16,%6			;\
				sll	%5,16,%5			;\
				addcc	%6,%5,%4			;\
				sra	%4,16,%4			;\
				be,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%0				;\
				bneg,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%1				;\
				addx	%%g0,0,%%g1			;\
				stb	%%g1,%2				;\
				bvs,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%3"			\
			: "=m"(proc.z), "=m"(proc.n), "=m"(proc.c), "=m"(proc.v), "=r"(D) \
			: "4"((short)D), "r"((short)S) : "g1", "cc" )

# define SubBC(D,S)	asm("	sll	%6,24,%6			;\
				sll	%5,24,%5			;\
				subcc	%5,%6,%4			;\
				sra	%4,24,%4			;\
				be,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%0				;\
				bneg,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%1				;\
				addx	%%g0,0,%%g1			;\
				stb	%%g1,%2				;\
				bvs,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%3"			\
			: "=m"(proc.z), "=m"(proc.n), "=m"(proc.c), "=m"(proc.v), "=r"(D) \
			: "4"((short)D), "r"((short)S) : "g1", "cc" )

# define AddBC(D,S)	asm("	sll	%6,24,%6			;\
				sll	%5,24,%5			;\
				addcc	%6,%5,%4			;\
				sra	%4,24,%4			;\
				be,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%0				;\
				bneg,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%1				;\
				addx	%%g0,0,%%g1			;\
				stb	%%g1,%2				;\
				bvs,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%3"			\
			: "=m"(proc.z), "=m"(proc.n), "=m"(proc.c), "=m"(proc.v), "=r"(D) \
			: "4"((short)D), "r"((short)S) : "g1", "cc" )

/*
 * sub/add words/bytes and set NZV
 */
# define SubW(D,S)	asm("	sll	%5,16,%5			;\
				sll	%4,16,%4			;\
				subcc	%4,%5,%3			;\
				sra	%3,16,%3			;\
				be,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%0				;\
				bneg,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%1				;\
				bvs,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%2"			\
			: "=m"(proc.z), "=m"(proc.n), "=m"(proc.v), "=r"(D) \
			: "3"((short)D), "r"((short)S) : "g1", "cc" )

# define AddW(D,S)	asm("	sll	%5,16,%5			;\
				sll	%4,16,%4			;\
				addcc	%5,%4,%3			;\
				sra	%3,16,%3			;\
				be,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%0				;\
				bneg,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%1				;\
				bvs,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%2"			\
			: "=m"(proc.z), "=m"(proc.n), "=m"(proc.v), "=r"(D) \
			: "3"((short)D), "r"((short)S) : "g1", "cc" )

# define SubB(D,S)	asm("	sll	%5,24,%5			;\
				sll	%4,24,%4			;\
				subcc	%4,%5,%3			;\
				sra	%3,24,%3			;\
				be,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%0				;\
				bneg,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%1				;\
				bvs,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%2"			\
			: "=m"(proc.z), "=m"(proc.n), "=m"(proc.v), "=r"(D) \
			: "3"((short)D), "r"((short)S) : "g1", "cc" )

# define AddB(D,S)	asm("	sll	%5,24,%5			;\
				sll	%4,24,%4			;\
				addcc	%5,%4,%3			;\
				sra	%3,24,%3			;\
				be,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%0				;\
				bneg,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%1				;\
				bvs,a	1f				;\
				mov	1,%%g1				;\
				mov	0,%%g1				;\
			1:						;\
				stb	%%g1,%2"			\
			: "=m"(proc.z), "=m"(proc.n), "=m"(proc.v), "=r"(D) \
			: "3"((short)D), "r"((short)S) : "g1", "cc" )


# define SwabB(D)	(D)=((((D)<<8)&0xff00)|(((D)>>8)&0xff))

# define SCHAR(S)	((signed short)(signed char)(S))

# define Div(v1,v2,v,d)	(v1 = v/d, v2 = v%d)


# else
/************************************************************
 *
 * processor emulation - GENERIC
 */
/*
 * fast block move, addresses are aligned on 16bit boundaries
 */
# define CopyW(T,F,C)	memcpy((T), (F), (C) << 1)


# define SCHAR(S)	((signed short)(signed char)(S))

# define WTEST(R)	(void)((proc.n = ((signed short)(R) < 0)),	\
			       (proc.z = ((u_short)(R) == 0)))
# define BTEST(R)	(void)((proc.n = ((signed char)(R) < 0)),	\
			       (proc.z = ((u_char)(R) == 0)))
# define WC(R)		(void)(proc.c = ((R) >> 16) & 1)
# define BC(R)		(void)(proc.c = ((R) >> 8) & 1)
# define WV_SUB(D,S,R)	(void)(proc.v = (((D) ^ (S)) & ((S) ^ (u_short)(R)) & 0x8000) != 0)
# define BV_SUB(D,S,R)	(void)(proc.v = (((D) ^ (S)) & ((S) ^ (u_short)(R)) & 0x80) != 0)
# define WV_ADD(D,S,R)	(void)(proc.v = (~((D) ^ (S)) & ((S) ^ (u_short)(R)) & 0x8000) != 0)
# define BV_ADD(D,S,R)	(void)(proc.v = (~((D) ^ (S)) & ((S) ^ (u_short)(R)) & 0x80) != 0)

/*
 * Test word/byte set NZ
 */
# define TestW(S)	WTEST((S))
# define TestB(S)	BTEST((S))

/*
 * Compare word/byte set NZVC
 */
# define CmpW(D,S) 	do { u_long _r = (u_long)(S) - (u_long)(D);	\
			     WTEST(_r); WC(_r); WV_SUB((D),(S),_r); } while(0)
# define CmpB(D,S) 	do { u_long _r = (u_long)(S) - (u_long)(D);	\
			     BTEST(_r); BC(_r); BV_SUB((D),(S),_r); } while(0)

/*
 * Subtract/add word/byte and set NZVC
 */
# define SubWC(D,S)	do { u_long _r = (u_long)(D) - (u_long)(S);	\
			     WTEST(_r); WC(_r); WV_SUB((S),(D),_r); (D)=_r; } while(0)
# define AddWC(D,S)	do { u_long _r = (u_long)(D) + (u_long)(S);	\
			     WTEST(_r); WC(_r); WV_ADD((D),(S),_r); (D)=_r; } while(0)
# define SubBC(D,S)	do { u_long _r = (u_long)(D) - (u_long)(S);	\
			     BTEST(_r); BC(_r); BV_SUB((S),(D),_r); (D)=_r; } while(0)
# define AddBC(D,S)	do { u_long _r = (u_long)(D) + (u_long)(S);	\
			     BTEST(_r); BC(_r); BV_ADD((D),(S),_r); (D)=_r; } while(0)

/*
 * Subtract/add word/byte and set NZV
 */
# define SubW(D,S)	do { u_long _r = (u_long)(D) - (u_long)(S);	\
			     WTEST(_r); WV_SUB((S),(D),_r); (D)=_r; } while(0)
# define AddW(D,S)	do { u_long _r = (u_long)(D) + (u_long)(S);	\
			     WTEST(_r); WV_ADD((D),(S),_r); (D)=_r; } while(0)
# define SubB(D,S)	do { u_long _r = (u_long)(D) - (u_long)(S);	\
			     BTEST(_r); BV_SUB((S),(D),_r); (D)=_r; } while(0)
# define AddB(D,S)	do { u_long _r = (u_long)(D) + (u_long)(S);	\
			     BTEST(_r); BV_ADD((D),(S),_r); (D)=_r; } while(0)

/*
 * swap bytes no flags
 */
# define SwabB(D)	(void)((D) = ((((D)<<8)&0xff00)|(((D)>>8)&0xff)))

/*
 * divide et impera, no flags
 */
# define Div(v1,v2,v,d)	(void)(v1 = v/d, v2 = v%d)
# endif

void ret(void);
void MOV(void);
void MOVB(void);
void CMP(void);
void BIT(void);
void BIC(void);
void BIS(void);
void ADD(void);
void SUB(void);
void CMPB(void);
void BITB(void);
void BICB(void);
void BISB(void);
void JSR(void);
void RTS(void);
void JMP(void);
void CLR(void);
void CLRB(void);
void COM(void);
void COMB(void);
void INC(void);
void INCB(void);
void DEC(void);
void DECB(void);
void NEG(void);
void NEGB(void);
void ADC(void);
void ADCB(void);
void SBC(void);
void SBCB(void);
void TST(void);
void TSTB(void);
void ROR(void);
void RORB(void);
void ROL(void);
void ROLB(void);
void ASR(void);
void ASRB(void);
void ASL(void);
void ASLB(void);
void MARK(void);
void CSM(void);
void MFPI(void);
void MFPD(void);
void MTPI(void);
void MTPD(void);
void WRTLCK(void);
void TSTSET(void);
void MFPS(void);
void MTPS(void);
void SXT(void);
void SWAB(void);
void MUL(void);
void DIV(void);
void ASH(void);
void ASHC(void);
void XOR(void);
void SOB(void);
void BR(void);
void BNE(void);
void BEQ(void);
void BGE(void);
void BLT(void);
void BGT(void);
void BLE(void);
void BPL(void);
void BMI(void);
void BHI(void);
void BLOS(void);
void BVC(void);
void BVS(void);
void BCC(void);
void BCS(void);
void BPT(void);
void IOT(void);
void EMT(void);
void TRAP(void);
void HALT(void);
void WAIT(void);
void RESET(void);
void dorti(void);
void RTI(void);
void RTT(void);
void SPL(void);
void MFPT(void);
void SCC(void);
void CCC(void);
void ILL(void);
