/*
 * Common part of gemlib bindings
 *
 *	++jrb	bammi@cadence.com
 *	modified: mj -- ntomczak@vm.ucs.ualberta.ca
 */
#define __IN_COMMON_C
#include "common.h"

/* vdi binding arrays (extern everywhere else) */
unsigned short	_contrl[CNTRLMAX];
short		_intin[INTINMAX];
short		_intout[INTOUTMAX];
short		_ptsin[2 * PTSINMAX];	/* upto PTSINMAX vertices are allowed
					   - currently 1024 */
short		_ptsout[2 * PTSOUTMAX]; /* likewise */

/*
 * aes binding arrays  - we need only global, other overlapped with
 * arrays for vdi - see common.h
 */
unsigned short	_global[GLOBMAX];	/* this should be exact */

/* aes binding params */
void	*_aesparams[6] =	   { (void *)&_control[0],
					 (void *)&_global[0],
				 (void *)&_int_in[0],
				 (void *)&_int_out[0],
				 (void *)&_addrin[0],
				 (void *)&_addrout[0] };
/* why did atari do this when apid is avail on appl_init ?? */
int gl_apid;			/* initialized in appl_init */
int gl_ap_version;		/* initialized in appl_init */

/* vdi binding params */
void	*_vdiparams[5] =	   { (void *)&_contrl[0],
				 (void *)&_intin[0],
				 (void *)&_ptsin[0],
				 (void *)&_intout[0],
				 (void *)&_ptsout[0] };
/*
 * the common interface to aes
 *	int __aes__(coded control);
 *	unsigned long coded control;
 * coded control: (1 byte for each element of control in the long)
 *	DD CC BB AA
 * DD : aes opcode
 * CC : sizeof _int_in
 * BB : sizeof _int_out
 * AA : sizeof _addrin
 *
 * Note: sizeof _addrout is needed only for rsrc_gaddr and is special
 *	 cased below.
 *
 * output: the value (int)_intout[0]
 */

#ifdef __OLD__
int __aes__(unsigned long coded_control)
{
	register unsigned char	*p = (unsigned char *)&coded_control;
	register unsigned short *q = &_control[0];

	/* decode control */
	do
	{
	*q++ = (unsigned short)(*p++);
	} while(q < &_control[4]);

	/* only rsrc_gaddr() needs this */
	*q = (_control[0] == 112) ? 1 : 0;

	/* call aes */
	__asm__ volatile
	("  movl    %0,    d1
		movw	#0xc8, d0
		trap	#2"
	 :				/* no outputs */
	 : "g"(&_aesparams[0])  /* inputs     */
	 : "d0", "d1", "d2", "a0", "a1", "a2"    /* clobbered regs */
	 );
	return (int)_int_out[0];
}
#else
/*
 * new more efficient coding thanks to Thomas Koenig (UI0T@DKAUNI2.BITNET)
 * "I made use here of the movep instruction for the 680xx, which transfers
 * data from a data register to alternate bytes of memory. The odd
 * address makes sure that these bytes are transferred to the lower half
 * of the words."
 */
int __aes__(unsigned long coded_control)
{

	/* call aes */
	__asm__ volatile
	("  movel   %1,  d1
		lea __contrl, a0	| arrays _contrl and _control overlap
	moveq	#0,  d0
	movepl	d0,  a0@(0) | clear high bytes of control array
		movepl	d1,  a0@(1)
		movl	%0,    d1
		movw	#0xc8, d0	| note -- no movq here, it sign extends
		trap	#2"
	 :				/* no outputs */
	 : "g"(&_aesparams[0]), "g"(coded_control)  /* inputs     */
	 : "d0", "d1", "d2", "a0", "a1", "a2"    /* clobbered regs */
	 );
	return (int)_int_out[0];
}
#endif

/*
 * the common interface to vdi
 *	void __vdi__(coded contrl, handle);
 *	unsigned long coded contrl;
 *	int handle;
 * coded contrl:
 *	DD BB CC AA
 * DD : subfunc 	(_contrl[5])	5 bits
 * BB : nvert. _ptsin	(_contrl[1])	11 (== # vertices, size = 2 * CC)
 * CC : sizeof _intin	(_contrl[3])	8 bits
 * AA : vdi opcode	(_contrl[0])	8
 *
 * output : void (because it is so inconsistent, individual binding funcs
 *		  will pull info out of the appro. binding arrays)
 */

void __vdi__(unsigned long coded_contrl, int handle)
{
	/* decode contrl */
	_contrl[0] = (unsigned short)(coded_contrl & 0xff);
	_contrl[3] = (unsigned short)((coded_contrl >>= 8) & 0xff);
	_contrl[1] = (unsigned short)((coded_contrl >>= 8) & 0x7ff);
	_contrl[5] = (unsigned short)(coded_contrl >> 11);

	_contrl[6] = handle;

	/* call vdi */
	__asm__ volatile
	("  movl    %0,    d1
		movq	#0x73, d0
		trap	#2"
	 :				/* no outputs */
	 : "g"(&_vdiparams[0])  /* inputs     */
	 : "d0", "d1", "d2", "a0", "a1", "a2"    /* clobbered regs */
	 );
}

void vdi(void)
{
	__asm__ volatile
	("  movl    %0,    d1
		movq	#0x73, d0
		trap	#2"
	 :				/* no outputs */
	 : "g"(&_vdiparams[0])  /* inputs     */
	 : "d0", "d1", "d2", "a0", "a1", "a2"    /* clobbered regs */
	 );
}
/* -eof- */
