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