/*
 * Common part of gemlib bindings
 *
 *	++jrb	bammi@cadence.com
 *	modified: mj -- ntomczak@vm.ucs.ualberta.ca
 * modified: cg -- d2cg@dtek.chalmers.se
 */
#define __IN_COMMON_C
#include "common.h"
#include	"xgemdosc.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]
 */

#ifndef	PURE_C

#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 __OLD__
/* 
 * 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	__OLD__

#else	/*Pure C*/

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 */
    
    xgemdoscall(0xc8L,(long)&_aesparams[0]);

    return (int)_int_out[0];
}

#endif

#ifndef	PURE_C
/* 
 * 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 */
     );
}

#else

/* 
 * 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 */
    
    xgemdoscall(VDICALL,(long)&_vdiparams[0]);
}

void vdi(void)
{
	xgemdoscall(VDICALL,(long)&_vdiparams[0]);
}

#endif	/*PURE_C*/
/* -eof- */
