/*
 *	leaf←linkage.h
 *		modeled after <sun4/asm←linkage.h>
 *	
 *	Peter B. Kessler, November 15, 1989 12:08:37 pm PST	
 */

/*
 *	This code assumes the save areas are double word aligned,
 *	and big enough to hold the data.
 *	The point here is to get the even numbered registers
 *	in even numbered slots so I can use std/ldd intructions on them.
 *
 *	The save area is used as follows:
 *		saveArea+0x00:	%l0
 *		...		...
 *		saveArea+0x1C:	%l7
 *		saveArea+0x020:	%i0
 *		...		...
 *		saveArea+0x3C:	%i7
 *		saveArea+0x40:	%cc	-- just the condition codes from %psr.
 *		saveArea+0x44:	%g1
 *		...		...
 *		saveArea+0x58:	%g7
 *		saveArea+0x60:	%y
 *		saveArea+0x64:	%o1	-- we trash %o0,
 *		...		...
 *		saveArea+0x78:	%o6	-- likewise for %o7.
 *	and if you save the floating point stuff:
 *		saveArea+0x7c:	%fsr
 *		saveArea+0x80:	%f0
 *		...		...
 *		saveArea+0xFC:	%f31
 */
 
/*
 *	Everything except the floating point registers
 */
 
#define	L0	( 0)
#define	L1	( 1)
#define	L2	( 2)
#define L3	( 3)
#define L4	( 4)
#define	L5	( 5)
#define	L6	( 6)
#define	L7	( 7)
#define LEAF←SAVE←LOCALS(RP)		\
	std	%l0, [RP + L0*4];	\
	std	%l2, [RP + L2*4];	\
	std	%l4, [RP + L4*4];	\
	std	%l6, [RP + L6*4];
#define LEAF←RESTORE←LOCALS(RP)		\
	ldd	[RP + L0*4], %l0;	\
	ldd	[RP + L2*4], %l2;	\
	ldd	[RP + L4*4], %l4;	\
	ldd	[RP + L6*4], %l6;

#define	I0	( 8)
#define	I1	( 9)
#define	I2	(10)
#define	I3	(11)
#define	I4	(12)
#define	I5	(13)
#define	I6	(14)
#define	I7	(15)
#define LEAF←SAVE←INS(RP)		\
	std	%i0, [RP + I0*4];	\
	std	%i2, [RP + I2*4];	\
	std	%i4, [RP + I4*4];	\
	std	%i6, [RP + I6*4];
#define LEAF←RESTORE←INS(RP)		\
	ldd	[RP + I0*4], %i0;	\
	ldd	[RP + I2*4], %i2;	\
	ldd	[RP + I4*4], %i4;	\
	ldd	[RP + I6*4], %i6;

#define CC	(16)
#define 		GETCC (0x20)
#define 		SETCC (0x21)
#define G1	(17)
#define G2	(18)
#define G3	(19)
#define G4	(20)
#define G5	(21)
#define G6	(22)
#define G7	(23)
#define Y	(24)
#define LEAF←SAVE←GLOBALS(RP)		\
	st	%g1, [RP + G1*4];	\
	std	%g2, [RP + G2*4];	\
	std	%g4, [RP + G4*4];	\
	std	%g6, [RP + G6*4];	\
	ta	GETCC;			\
	st	%g1, [RP + CC*4];	\
	mov	%y, %g1;		\
	st	%g1, [RP + Y*4]
#define LEAF←RESTORE←GLOBALS(RP)	\
	ld	[RP + CC*4], %g1;	\
	ta	SETCC;			\
	ld	[RP + Y*4], %g1;	\
	mov	%g1, %y;		\
	ld	[RP + G1*4], %g1;	\
	ldd	[RP + G2*4], %g2;	\
	ldd	[RP + G4*4], %g4;	\
	ldd	[RP + G6*4], %g6;

#define O1	(25)
#define O2	(26)
#define O3	(27)
#define O4	(28)
#define O5	(29)
#define O6	(30)
#define LEAF←SAVE←OUTS(RP)		\
	st	%o1, [RP + O1*4];	\
	std	%o2, [RP + O2*4];	\
	std	%o4, [RP + O4*4];	\
	st	%o6, [RP + O6*4];
#define LEAF←RESTORE←OUTS(RP)		\
	ld	[RP + O1*4], %o1;	\
	ldd	[RP + O2*4], %o2;	\
	ldd	[RP + O4*4], %o4;	\
	ld	[RP + O6*4], %o6;
	
/*
 *	Everything for the floating point registers.
 */
 
#define FSR	(31)
#define F0	(32)
#define F2	(34)
#define F4	(36)
#define F6	(38)
#define F8	(40)
#define F10	(42)
#define F12	(44)
#define F14	(46)
#define F16	(48)
#define F18	(50)
#define F20	(52)
#define F22	(54)
#define F24	(56)
#define F26	(58)
#define F28	(60)
#define F30	(62)

#define LEAF←SAVE←FLOATS(RP)		\
	st	%fsr, [RP + FSR*4];	\
	std	%f0,  [RP + F0*4];	\
	std	%f2,  [RP + F2*4];	\
	std	%f4,  [RP + F4*4];	\
	std	%f6,  [RP + F6*4];	\
	std	%f8,  [RP + F8*4];	\
	std	%f10, [RP + F10*4];	\
	std	%f12, [RP + F12*4];	\
	std	%f14, [RP + F14*4];	\
	std	%f16, [RP + F16*4];	\
	std	%f18, [RP + F18*4];	\
	std	%f20, [RP + F20*4];	\
	std	%f22, [RP + F22*4];	\
	std	%f24, [RP + F24*4];	\
	std	%f26, [RP + F26*4];	\
	std	%f28, [RP + F28*4];	\
	std	%f30, [RP + F30*4];

#define LEAF←RESTORE←FLOATS(RP)		\
	ld	[RP + FSR*4], %fsr;	\
	ldd	[RP + F0*4],  %f0;	\
	ldd	[RP + F2*4],  %f2;	\
	ldd	[RP + F4*4],  %f4;	\
	ldd	[RP + F6*4],  %f6;	\
	ldd	[RP + F8*4],  %f8;	\
	ldd	[RP + F10*4], %f10;	\
	ldd	[RP + F12*4], %f12;	\
	ldd	[RP + F14*4], %f14;	\
	ldd	[RP + F16*4], %f16;	\
	ldd	[RP + F18*4], %f18;	\
	ldd	[RP + F20*4], %f20;	\
	ldd	[RP + F22*4], %f22;	\
	ldd	[RP + F24*4], %f24;	\
	ldd	[RP + F26*4], %f26;	\
	ldd	[RP + F28*4], %f28;	\
	ldd	[RP + F30*4], %f30;

#define	STATESIZE	(64)
#define	GET←STATESIZE() \
	mov	STATESIZE*4, %o0