/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1986,1987,1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:rtflgen.h 12.0$ */
/* $ACIS:rtflgen.h 12.0$ */
/* $Source: /ibm/acis/usr/src/lib/libc/ca/gen/RCS/rtflgen.h,v $ */

#include <machine/rtflops.h>
#include <frame.h>

#define	UI_SIZE 64	/* size of universal floating point instruction  */
#define UI_GPRS 0xbc01	/* scratch general purpose regs. (0,2,3,4,5,15)  */
#define UI_FPRS 0xc0	/* scratch floatinf point regs.  (0, and 1)      */

#define scratch_r0r4r5r15	0x8c01
#define scratch_r0r3r4r5r15	0x9c01
#define scratch_r0r2r3r4r5r15	0xbc01

#define scratch_fr0fr1		0xc0

/*
 * Macro name: UI_COM_TXT
 * Function  : Build the common text for a profiled and non-profiled floating    * point universal instruction.
 * Formal parameters :
 * - name: function name
 */

#define UI_COM_TXT(name) \
        .globl	.oVncs; \
	.set	.oVncs,0; \
	.text; \
	.globl	_./**/name; \
	_./**/name:  

#ifdef PROF
/*
 * Macro name: UI_PROF_TXT
 * Function  : Build the text for a profiled floating point universal 
 * instruction.
 * Formal parameters :
 * - name: function name
 */

#define UI_PROF_TXT(name) \
	/* \
	 * Since, no argument are passed to this routine use the argument\
	 * save area for temporary local storage (save r0, r14, and r15).\
         */\
	st	r0,ARG2_OFFSET(r1); \
	stm	r14,ARG3_OFFSET(r1); \
	/* Set registers for then call mcount */\
	ai	r1,-REG_SAVE_SZ; \
	get	r14,$_/**/name; \
	mr	r0,r15; \
	bali	r15,mcount; \
	/* Restore registers and branch to universal floating point instr. */\
	ai	r1,REG_SAVE_SZ; \
	l 	r0,ARG2_OFFSET(r1); \
	lm	r14,ARG3_OFFSET(r1); \
	inc	r0,8;\
	br	r0; 
#else
#define UI_PROF_TXT(name)  \
	inc	r0,4;\
	br	r0; 
#endif

/*
 * Macro name: UI_TXT
 * Function  : Build the text for a profiled or non-profiled floating point 
 * universal instruction.
 * Formal parameters :
 * - name: function name
 */

#define UI_TXT(name) UI_COM_TXT(name); UI_PROF_TXT(name);

/*
 * Macro name: UI_PROF_DATA
 * Function  : If profiling build a pointer for mcounts use; if no profliing
 * no pointer.
 */

#ifdef PROF
#define UI_PROF_DATA 	.long 0; /* pointer for mcounts use		     */
#else     
#define UI_PROF_DATA	;
#endif

/*
 * Macro name: UI_DATA_COM
 * Function  : Build the data area of a universal floating point instruction up  * to the arguments.                   
 * Formal parameters :
 * - name:   function name
 * - opcode: universal floating point opcode
 * - args:   number of UFI arguments         
 * - gprs:   scratch general registers
 * - fprs:   scratch floating point registers
 * - size:   size of UIF structure
 */

#define UI_DATA_COM(name,opcode,args,gprs,fprs,size) \
.data; \
	.align	2; \
	.globl	_/**/name; \
_/**/name: .long	_./**/name; \
	UI_PROF_DATA \
	/* Universal Floating Point Instruction	*/\
	cas	r0,r15,r0; \
	.long	FPGLUE ; \
	.byte	opcode ; 			/* float point opcode  */\
	.byte	args ; 				/* number of arguments */\
	.short	gprs ; 				/* scratch gpr's       */\
	.byte	size;                        	/* size of this struct */\
	.byte	fprs ; 				/* scratch fp regs.    */\


/*
 * Macro name: UI_DATA_END
 * Function  : Add the fill to the end of the universal floating point           * instruction.
 * Formal parameters :
 * - name:   function name
 * - size:   the size of the UIF structure                             
 */

#define UI_DATA_END(name,size)\
_/**/name/**/end:\
	.fill	(size - (_/**/name/**/end - _/**/name)),1,0;


/*
 * Macro name: UI
 * Function  : Build a monadic RTFL instruction
 * Input: a double in register pair 2 & 3.
 * output: a double in register pair 2 & 3.
 * Formal parameters : 
 * - name: function name
 * - opcode: universal floating point opcode
 * - gprs: scratch general purpose registers
 * - fprs: scratch floating point registers
 * - alt: name of alternate function to call; if no hardware available 
 * - size: size of the UIF structure                                   
 */

#define UI(name,opcode,gprs,fprs,alt,size) \
	UI_TXT(name); 				/* the text portion of a UIF*/\
	UI_DATA_COM(name,opcode,2,gprs,fprs,size);	/* common data */\
	.byte	(GREGTYPE + DBLETYPE);		/* operand 1 */\
	.byte	0x23; \
	.byte	(ADDRTYPE + FUNCTYPE);		/* operand 2 */\
	.byte	0; \
	.align	2; \
	.long	__/**/alt;			/* alt function name */\
	UI_DATA_END(name,size); 			/* common end */



/*
 * Macro name: UI_NO_ALT
 * Function  : Build a monadic RTFL instruction (no alternate function)
 * Input: a double in register pair 2 & 3.
 * output: a double in register pair 2 & 3.
 * Formal parameters : 
 * - name: function name
 * - opcode: universal floating point opcode
 * - gprs: scratch general purpose registers
 * - fprs: scratch floating point registers
 * - size: size of the UIF structure                                   
*/
#define UI_NO_ALT(name,opcode,gprs,fprs,size) \
	UI_TXT(name); 				/* the text of a UIF    */\
	UI_DATA_COM(name,opcode,1,gprs,fprs,size);	/* common data */\
	.byte	(GREGTYPE + DBLETYPE);		/* operand 1 */\
	.byte	0x23; \
	UI_DATA_END(name,size); 			/* common end */

/*
 * Macro name: UID
 * Function  : Build a dyadic RTFL instruction
 * Inputs: two doubles in regsiter pairs 2 & 3 and 4 & 5.
 * output: a double in register pair 2 & 3.
 * Formal parameters : 
 * - name: function name
 * - opcode: universal floating point opcode
 * - gprs: scratch general purpose registers
 * - fprs: scratch floating point registers
 * - alt: name of alternate function to call; if no hardware available 
 * - size: size of the UIF structure                                   
 */

#define UID(name,opcode,gprs,fprs,alt,size) \
	UI_TXT(name); 				/* the text of a UIF    */\
	UI_DATA_COM(name,opcode,3,gprs,fprs,size);	/* common data */\
	.byte	(GREGTYPE + DBLETYPE);		/* operand 1 */\
	.byte	0x23; \
	.byte	(GREGTYPE + DBLETYPE);		/* operand 2 */\
	.byte	0x45; \
	.byte	(ADDRTYPE + FUNCTYPE);		/* operand 3 */\
	.byte	0; \
	.byte	0; 			/* manually align on word boundary */\
	.byte	0; 			/* just to make as happy! */\
	.align	2; \
	.long	__/**/alt;			/* alt function name */\
	UI_DATA_END(name,size); 			/* common end */

/*
 * Macro name: UIDI
 * Function  : Build a dyadic RTFL instruction
 * Inputs: a doubles in regsiter pairs 2 & 3.
 *	   an INTEGER in register 4.
 * output: a double in register pair 2 & 3.
 * Formal parameters : 
 * - name: function name
 * - opcode: universal floating point opcode
 * - gprs: scratch general purpose registers
 * - fprs: scratch floating point registers
 * - alt: name of alternate function to call; if no hardware available 
 * - size: size of the UIF structure                                   
 */

#define UIDI(name,opcode,gprs,fprs,alt,size) \
	UI_TXT(name); 				/* the text of a UIF    */\
	UI_DATA_COM(name,opcode,3,gprs,fprs,size);	/* common data */\
	.byte	(GREGTYPE + DBLETYPE);		/* operand 1 */\
	.byte	0x23; \
	.byte	(GREGTYPE + INTTYPE);		/* operand 2 */\
	.byte	0x04; \
	.byte	(ADDRTYPE + FUNCTYPE);		/* operand 3, alt function */\
	.byte	0; \
	.byte	0; 			/* manually align on word boundary */\
	.byte	0; 			/* just to make as happy! */\
	.align	2; \
	.long	__/**/alt;			/* alt function name */\
	UI_DATA_END(name,size); 			/* common end */

/*
 * Macro name: UIC
 * Function  : Build a RTFL instruction for misc libc functions.
 * Input: an integer in register 2.
 * output: an integer in register 2.
 * Formal parameters : 
 * - name: function name
 * - opcode: universal floating point opcode
 * - gprs: scratch general purpose registers
 * - fprs: scratch floating point registers
 * - size: size of the UIF structure                                   
 */

#define UIC(name,opcode,gprs,fprs,size) \
	UI_TXT(name); 				/* the text of a UIF    */\
	UI_DATA_COM(name,opcode,1,gprs,fprs,size);	/* common data */\
	.byte	(GREGTYPE + INTTYPE);		/* operand 1 */\
	.byte	0x02; \
	UI_DATA_END(name,size); 			/* common end */


