Personal tools
You are here: Home Projects C++ Cfront releases Release 3.0.3 source lib task_SPARC task hw_stack.h
Document Actions

hw_stack.h

by Michael L Powell last modified 2007-01-26 03:22

Click here to get the file

Size 14.5 kB - File type text/plain

File contents

/*ident	"@(#)cop4:sparc_task/task/hw_stack.h	1.1" */
/*******************************************************************************
 
C++ source for the C++ Language System, Release 3.0.  This product
is a new release of the original cfront developed in the computer
science research center of AT&T Bell Laboratories.

Copyright (c) 1991 AT&T and UNIX System Laboratories, Inc.
Copyright (c) 1984, 1989, 1990 AT&T.  All Rights Reserved.

THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of AT&T and UNIX System
Laboratories, Inc.  The copyright notice above does not evidence
any actual or intended publication of such source code.

*******************************************************************************/
/*
 * Copyright (c) 1990, 1991 by Sun Microsystems, Inc.
 */

#ifndef HW_STACK_H
#define HW_STACK_H

/* Machine-dependent macros, typedefs, and externs for task library.
 * Porting these requires intimate knowledge of the stack frame layout,
 * call and return sequences for the machine.
 * They are used by task.c and fudge.c and sim.c.
 * 
 * Some are grouped according to direction of stack growth.
 * 
 * New-style asms would eliminate function calls for TOP, AP, and FP.
 */

typedef unsigned char MACHINE_BYTE;

#if defined(M32) || defined(u3b2) || defined(u3b5) || defined(u3b15)
#define BELLMAC_CHIP
#endif
#if defined(u3b) || defined(BELLMAC_CHIP) 
#define PROC_3B
#endif

////////////////////////// AT&T 3B series //////////////////////////
#ifdef PROC_3B

#define	STACK_GROWS_UP
/* typedefs for the hardware state saved on the stack after a call */
typedef struct {
	unsigned long	r3;
	unsigned long	r4;
	unsigned long	r5;
	unsigned long	r6;
	unsigned long	r7;
	unsigned long	r8;

} HW_REGS;

struct FrameLayout {
	short   n_saved;	// number of registers saved in this frame.
				// (3B's don't have masks of regs saved)
		FrameLayout(int*);	// called with frame pointer
};

extern "C" {
extern int* FP();	/* FP of caller */
extern int* AP();	/* AP of caller */
extern void FUDGE_SP(int*, int*);	/* reset ap to first arg */
extern int* TOP();	/* SP-1 of caller (pnts to last used word in stack) */
}
extern void	save_saved_regs(HW_REGS*, int*);

#define MAXINT_AS_FLOAT 2147483647.0

/* Save all current regs and regs saved in this frame in reg_struct_p,
 * for restoration when child runs.
 * Note: SAVE_REGS needed in case task::restore() saves more regs
 * than task::task.
 */
#define	SAVE_CHILD_REGS(reg_struct_p)				\
	SAVE_REGS(reg_struct_p);				\
	save_saved_regs((reg_struct_p), ta_fp);

extern "C" {
extern void set_r3(int*);
extern void set_r4(int*);
extern void set_r5(int*);
extern void set_r6(int*);
extern void set_r7(int*);
extern void set_r8(int*);
}

#ifdef u3b

#define OLD_FP(fp)	( *( (int*)(fp) - 11 ) )
#define OLD_AP(fp)	( *( (int*)(fp) - 12 ) )
#define OLD_PC(fp)	( *( (int*)(fp) - 13 ) )
#define FIRST_SAVED_REG_P(fp, n)	((int*)(fp) - (n))
#define	LAST_SAVED_REG_P(fp,n)		((int*)(fp) - 1)

#define IS_SAVE_OPCODE(instr) ((MACHINE_BYTE)(instr) == (MACHINE_BYTE)0x7A)

/* Given a pointer to a save instruction, yield the number of registers saved */
#define N_SAVED_REGS(instr)	(((char *)(instr))[1] >> 4)


#else	/* u3b2, u3b5, u3b15 */


#define OLD_FP(fp)	( *( (int*)(fp) - 7 ) )
#define OLD_AP(fp)	( *( (int*)(fp) - 8 ) )
#define OLD_PC(fp)	( *( (int*)(fp) - 9 ) )	
#define FIRST_SAVED_REG_P(fp,n)	( (int*)(fp) - 6 )
#define LAST_SAVED_REG_P(fp,n)	( (int*)(fp) - 6 + (n) - 1)
 
#define SAVE_OPERAND(instr)	(((char *)(instr))[1] & 0xf)

/* Given a pointer to a save instruction, yield the number of registers saved */
#define N_SAVED_REGS(instr)	(8 - SAVE_OPERAND(instr) + 1)

#define IS_SAVE_OPCODE(instr) ((MACHINE_BYTE)(instr) == (MACHINE_BYTE)0x10)

#endif
/* u3b, u3b2, u3b5, u3b15 */
#endif /* PROC_3B */


//////////////////////////// DEC VAX ////////////////////////////
#ifdef vax

#define	STACK_GROWS_DOWN
extern "C" {
extern int* FP();	/* FP of caller */
extern int* TOP();	/* SP of caller (pnts to last used word in stack) */
}
#define FUDGE_SP(ap, fp)	/* unnecessary on vax */
#define AP()		0	/* unnecessary on vax */
#define OLD_AP(fp)		(*((int*)(fp) + 2))
#define OLD_FP(fp)		(*((int*)(fp) + 3))
#define OLD_PC(fp)		(*((int*)(fp) + 4))
#define	FIRST_SAVED_REG_P(fp,n)	  ((int*)(fp) + 5)
#define	LAST_SAVED_REG_P(fp,n)	  ((int*)(fp) + 5 + (n) - 1)
#define	ENTRY_MASK(fp)		(*((short*)(fp) + 3))
#define	N_VOL_REGS	6    /* assumes compiler only allocates r6-r11 for users */

#define MAXINT_AS_FLOAT 2147483647.0
#define	STACK_GROWS_DOWN

/* typedef for the hardware state saved on the stack after a call */
typedef struct {
	unsigned long	r6;
	unsigned long	r7;
	unsigned long	r8;
	unsigned long	r9;
	unsigned long	r10;
	unsigned long	r11;

} HW_REGS;

/* Save all current regs and regs saved in this frame in reg_struct_p,
 * for restoration when child runs.  On the VAX, save_saved_regs is
 * unnecessary because the return from swap will restore the regs saved
 * in task:task.
 */
#define	SAVE_CHILD_REGS(reg_struct_p)			\
	SAVE_REGS(reg_struct_p);			

extern "C" {
extern void set_r6(int*);
extern void set_r7(int*);
extern void set_r8(int*);
extern void set_r9(int*);
extern void set_r10(int*);
extern void set_r11(int*);
}

#endif		/* vax */

///////////////////// Motorola-680x0/Sun-3 (&Sun-2) /////////////////////
#ifdef mc68000		/* Really, ifdef sun--stack frame layout
			 * is different on a UNIX PC, for example
			 */

#define	STACK_GROWS_DOWN
/* typedefs for the hardware state saved on the stack after a call.
 * Assumes d0, d1, a0, a1 are scratch registers, a6 is fp, a7 is sp.
 * a0 and a1 are included so that loops through a mask word work correctly.
 */
typedef struct {
	unsigned long	d2;
	unsigned long	d3;
	unsigned long	d4;
	unsigned long	d5;
	unsigned long	d6;
	unsigned long	d7;
	unsigned long	a0;	/* should not be used */
	unsigned long	a1;	/* should not be used */
	unsigned long	a2;
	unsigned long	a3;
	unsigned long	a4;
	unsigned long	a5;
} HW_REGS;

struct FrameLayout {
	short	offset;			// of top of saved registers from fp
	unsigned short	mask;   	// of registers saved in frame
		FrameLayout(int*);	// called with frame pointer
};

extern int*	Skip_pc_p;		/* global for FUDGE_SP and fudge_sp */
extern "C" {
extern int* FP();			/* FP of caller */
extern void FUDGE_SP(int*, int*);	/* prepare to reset sp */
extern void fudge_sp();			/* reset sp on return through fudged
					 * frame */
extern int* TOP();			/* SP of caller
					 * (pnts to last used word in stack) */
}
#define AP()		0	/* unnecessary on mc68000 */
#define OLD_AP(fp)	0	/* unnecessary on mc68000 */
#define OLD_FP(fp)	(*((int*)(fp)))
#define	OLD_PC(fp)	(*((int*)(fp) + 1))
#define	OLD_PC_P(fp)	((int*)(fp) + 1)
#define FIRST_SAVED_REG_P(fp, o)	((int*)(fp) + (o))


extern void	save_saved_regs(HW_REGS*, int*);

/* Save all current regs and regs saved in this frame in reg_struct_p,
 * for restoration when child runs.
 * Note: SAVE_REGS needed in case task::restore() saves more regs
 * than task::task.
 */
#define	SAVE_CHILD_REGS(reg_struct_p)				\
	SAVE_REGS(reg_struct_p);				\
	save_saved_regs((reg_struct_p), ta_fp);

extern "C" {
extern void set_d2(int*);
extern void set_d3(int*);
extern void set_d4(int*);
extern void set_d5(int*);
extern void set_d6(int*);
extern void set_d7(int*);
extern void set_a2(int*);
extern void set_a3(int*);
extern void set_a4(int*);
extern void set_a5(int*);
}

#define MAXINT_AS_FLOAT 2147483647.0

#endif		/* mc68000 (sun) */

//////////////////////////// intel 80386/Sun-386 ////////////////////////////
#ifdef sun386

#define	STACK_GROWS_DOWN

/* typedefs for the hardware state saved on the stack after a call.
 * Assumes that only EDI, ESI and EBX are used as register vars,
 * and that they're always chosen (and saved) in that order.
 */
typedef struct {
	unsigned long	edi;
	unsigned long	esi;
	unsigned long	ebx;
} HW_REGS;

struct FrameLayout {
		// offset from %EBP to "top" of saved registers (i.e., to the
		// first one saved -- the one at the highest address)
	short	offset;
		// # of registers saved is always assumed to be 1 2 or 3
	unsigned char n_saved;
	unsigned short	mask;	// ?? fudge.c.386 that comes with AT&T insists on using
				//    FrameLayout::mask but it is never defined !!??...
		FrameLayout(int*);	// called with frame pointer
};

extern int*	Skip_pc_p;		/* global for FUDGE_SP and fudge_sp */
extern "C" {
extern int* FP();			/* FP of caller */
extern void FUDGE_SP(int*, int*);	/* prepare to reset sp */
extern void fudge_sp();			/* reset sp on return through fudged
					 * frame */
extern int* TOP();			/* SP of caller
					 * (pnts to last used word in stack) */
}
#define AP()		0	/* unnecessary on 386 */
#define OLD_AP(fp)	0	/* unnecessary on 386 */
#define OLD_FP(fp)	(*((int*)(fp)))
#define	OLD_PC(fp)	(*((int*)(fp) + 1))
#define	OLD_PC_P(fp)	((int*)(fp) + 1)
#define FIRST_SAVED_REG_P(fp, o)	((int*)(fp) - (o) - 1)


extern void	save_saved_regs(HW_REGS*, int*);

/* Save all current regs and regs saved in this frame in reg_struct_p,
 * for restoration when child runs.
 * Note: SAVE_REGS needed in case task::restore() saves more regs
 * than task::task.
 */
#define	SAVE_CHILD_REGS(reg_struct_p)				\
	SAVE_REGS(reg_struct_p);				\
	save_saved_regs((reg_struct_p), ta_fp);

extern "C" {
extern void set_ebx(int*);
extern void set_esi(int*);
extern void set_edi(int*);
}

#define MASK(x) ABS(x)
#define MAXINT_AS_FLOAT 2147483647.0

#endif		/* sun386 */

//////////////////////////// Sun SPARC/Sun-4 ////////////////////////////
#ifdef sparc

//
// The sparc is different from the other machines represented here
// in three major ways:
//	1- Its stack frames are disjoint (arguments to a function
//	   can be stored in the middle of the parent's frame);
//	2- The role of frame pointer is shared by two registers --
//	   %sp (%o6) and %fp (%i6);
//	3- Stack switching requires a little help from the kernel.
//


#define	STACK_GROWS_DOWN
#define	N_GLOBAL_REGS	7
#define	N_STK_PARAMS	6

/* typedefs for the hardware state saved on the stack after a call.
 * SPARC always saves the same number of registers.  Here we just worry
 * about the global (%g1 - %g7) registers and the six words in the
 * caller's frame where the callee might have dumped its in-register
 * parameters.  The locals and ins are taken care of by the way they're
 * represented in the standard stack frame, and the compilers do not
 * expect the out-registers to be preserved across calls.
 */

typedef struct {					// Offsets (bytes)
	unsigned long	global_regs[ N_GLOBAL_REGS ];	//  0 - 27
	unsigned long	param_dump[ N_STK_PARAMS ];	// 28 - 51
} HW_REGS;

struct FrameLayout {
		// FullFrameLen is the length (in bytes) from %sp to the
		// far end (highest addresses) of the parent's frame -- in
		// order to be sure of getting all of my in-parameters,
		// we need to copy the parent's whole frame.
	int	FullFrameLen;
		FrameLayout(int*);	// called with frame pointer
};

extern int*	Skip_pc_p;		/* global for FUDGE_SP and fudge_sp */
extern "C" {
extern int* FP();			/* FP of caller */
extern void FUDGE_SP(int*, int*);	/* prepare to reset sp */
extern void fudge_sp();			/* reset sp on return through fudged
					 * frame */
extern int* TOP();			/* SP of caller
					 * (pnts to last used word in stack) */
}
#define AP()		0	/* unnecessary on sparc */
#define OLD_AP(fp)	0	/* unnecessary on sparc */
#define OLD_FP(fp)	(*((int*)(fp) + 14))
#define	OLD_PC(fp)	(*((int*)(fp) + 15))
#define	OLD_PC_P(fp)	((int*)(fp) + 15)

#define SAVE_CHILD_REGS( reg_struct_p ) SAVE_REGS( reg_struct_p )

#define MASK(x) ABS(x)
#define MAXINT_AS_FLOAT 2147483647.0

#endif		/* sparc */



#ifdef uts


#define	STACK_GROWS_DOWN

struct FrameLayout {
	int	begreg;
	int	endreg;
	unsigned short mask;
	FrameLayout(int *);	// called with frame pointer
};

typedef struct {
	unsigned long	r0;
	unsigned long	r1;
	unsigned long	r2;
	unsigned long	r3;
	unsigned long	r4;
	unsigned long	r5;
	unsigned long	r6;
	unsigned long	r7;
	unsigned long	r8;
	unsigned long	r9;
	unsigned long	r10;
	unsigned long	r11;
	unsigned long	r12;
	unsigned long	r13;
	unsigned long	r14;
	unsigned long	r15;
} HW_REGS;

extern "C" {
extern int* FP();	/* FP of caller */
extern int* AP();	/* AP of caller */
extern int* TOP();	/* SP of caller (pnts to last used word in stack) */
extern void set_r2(int*);
extern void set_r3(int*);
extern void set_r4(int*);
extern void set_r5(int*);
extern void set_r6(int*);
extern void set_r7(int*);
extern void set_r8(int*);
extern void set_r9(int*);
extern void set_r10(int*);
extern void set_r11(int*);
};

#define OLD_FP(fp)      ( *( (int*)(fp) + 12 ) )
#define OLD_AP(fp)      ( *( (int*)(fp) + 12 ) )
#define OLD_PC(fp)      ( *( (int*)(fp) + 14 ) )
#define	OLD_SP(fp)	( *( (int*)(fp) + 13 ) )
#define FIRST_SAVED_REG_P(fp)	(fp) 
#define LAST_SAVED_REG_P(fp)    (fp + 15)
#define FUDGE_SP(ap, fp)	/* unnecessary on uts */

#define MAXINT_AS_FLOAT 2147483647.0

/* Save all current regs and regs saved in this frame in reg_struct_p,
 * for restoration when child runs.
 * Note: SAVE_REGS needed in case task::restore() saves more regs
 * than task::task.
 *
 * Note that for uts the FP and SP in New_task_regs must be adjusted to 
 * refer to the new child stack.
 */

#define	SAVE_CHILD_REGS(reg_struct_p)				\
	SAVE_REGS(reg_struct_p);				\
	save_saved_regs((reg_struct_p), ta_fp);			\
        OLD_FP(reg_struct_p) = int((int*)OLD_FP(ta_fp) - distance);\
        OLD_SP(reg_struct_p) = int((int*)OLD_SP(ta_fp) - distance);


extern void	save_saved_regs(HW_REGS*, int*);


#endif	/* uts */


//////////////////////////// Common code ////////////////////////////

#ifdef STACK_GROWS_DOWN
#  define STACK_LAST_WORD_P(b,s)	((b) - (s) + 1)
#  define COPY_STACK(f,c,t)   while ((c)--) *(t)-- = *(f)--
#  define ACTIVE_STK_SZ(b,t)  (b) - (t) + 1	/* size of active stack */
#  ifdef sparc
	/* SPARC Stack must be aligned on double-word boundary.  Can't
	 * use <machine/asm.h> (q.v.) macro "SA" directly because it
	 * rounds up and we want to round down, and because STACK_BASE
	 * is used with "int *" variables instead of "char *".
	 */
#     include <machine/asm_linkage.h>
#     define SA_DOWN(X) ((X) & ~(STACK_ALIGN-1))
#     define STACK_BASE(b,s) (int *) ( SA_DOWN( (int)((b)+(s)-1)) )
#  else
#     define STACK_BASE(b,s)     (b) + (s) - 1
#  endif
#  define SAVED_AREA(b,s)     (b) - (s) + 1
#endif

#ifdef STACK_GROWS_UP
#  define STACK_LAST_WORD_P(b,s)	((b) + (s) - 1)
#  define COPY_STACK(f,c,t)   while ((c)--)  *(t)++ = *(f)++
#  define ACTIVE_STK_SZ(b,t)  (t) - (b) + 1	/* size of active stack */
#  define STACK_BASE(b,s)     (b)
#  define SAVED_AREA(b,s)     (b)
#endif

/* externs needed for all machines, definitions in hw_stack.c */
extern "C" {
extern void SAVE_REGS(HW_REGS*);	/* call SAVE_REGS(&New_task_regs)
					 * copies caller's registers into
					 * a HW_REGS structure
					 */
}


#endif /* HW_STACK_H */
« December 2024 »
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: