diff options
Diffstat (limited to 'ext/systemc/src/sysc/qt/md/powerpc_sys5.h')
-rw-r--r-- | ext/systemc/src/sysc/qt/md/powerpc_sys5.h | 566 |
1 files changed, 566 insertions, 0 deletions
diff --git a/ext/systemc/src/sysc/qt/md/powerpc_sys5.h b/ext/systemc/src/sysc/qt/md/powerpc_sys5.h new file mode 100644 index 000000000..8c0730704 --- /dev/null +++ b/ext/systemc/src/sysc/qt/md/powerpc_sys5.h @@ -0,0 +1,566 @@ +/* + + * QuickThreads -- Threads-building toolkit. + + * Copyright (c) 1993 by David Keppel + + * + + * Permission to use, copy, modify and distribute this software and + + * its documentation for any purpose and without fee is hereby + + * granted, provided that the above copyright notice and this notice + + * appear in all copies. This software is provided as a + + * proof-of-concept and for demonstration purposes; there is no + + * representation about the suitability of this software for any + + * purpose. + + * + + + * PowerPC-Sys5 thread switching module. + + * + + * This software is largely based on the original PowerPC-Linux porting + + * developed by Ken Aaker <kenaaker@silverbacksystems.com> + + * + + * Marco Bucci <marco.bucci@inwind.it> + + * December 2002 + + * + + */ + + +#ifndef QUICKTHREADS_POWERPC_H +#define QUICKTHREADS_POWERPC_H + + +/***************************************************************************** + * + * DESCRIPTION + * + * This is the QuickThreads switching module implementation for PowerPC + * running under System V ABI (Application Binary Interface) [2]. It was + * developed by porting the MacOS X version and tested under LinuxPPC. + * + * Notice that this is not the same than the PowerPC Mach ABI used by MacOSX + * [1]. + * + * IMPLEMENTATION NOTES + * + * 1) Porting on System V ABI + * Excluding the variant argument calling convention, Mach and System V ABI + * are enough similar and it could be possible to use some simple macro, to + * adapt the code for both the ABIs. Actually, the only relevant difference + * is in the linkage area structure and in the position where the Link and + * the Condition registers are saved. As to the calling conventions, there + * are differences with floating points argument passing and with variant + * argument lists. Notice that, on Mach, the caller's stack frame allocates + * space to hold all arguments ([1] p.51), while on System V, the caller's + * stack frame allocates space to hold just the arguments that don't fit into + * registers ([2] p.3.18). + * + * 2) Variant argument list implementation + * Variant argument calling on a RISC machine is not easy to implement since + * parameters are passed via registers instead of via stack. In a general + * variant argument implementation, the caller's stack must map the whole + * parameter list following the rules related to the use of the GPR and FPR + * parameter registers and the stack alignment ([2] p.3-21). + * This implementation is quite simple and not general. It works under the + * hypothesis that arguments are 4-bytes aligned integers. + * + * 3) This heather file organisation + * I preferred to not make confusion between macros that are needed (i.e. + * directly used) by QuickThreads and internal "implementation" macros. You + * will find QuickThreds macros in the end of this header. Sometime they just + * refer to an analogous "internal" macro. On the top, there are the macros + * that I used to make more clean (I hope) the implementation. I could include + * some system heather (as to stack layout definitions, prologs and epilogs, + * etc.), but I preferred to have a self-contained heather in order to make + * all more clear for mantaining and for possible porting on another ABI. + * + * + * REFERENCES + * + * [1] - Mach-O Runtime Architecture + * Runtime Concepts and Conventions for Mac OS X Programs + * Preliminary July 2002 + * + * [2] - SYSTEM V APPLICATION BINARY INTERFACE + * PowerPC Processor Supplement + * September 1995 + * + + *****************************************************************************/ + +/***************************************************************************** + * + * PowerPC System V Stack frame (see [2]) + * + + ................ + + + + | | + +--------------------------+ + | | Caller's LR + + CALLER'S LINKAGE AREA + + backchain -> | | Caller's backchain + +==========================+ + | | FPR31 + + FPR SAVE AREA + + .............. + + + + | | FPRn + +--------------------------+ + | | GPR31 + + GPR SAVE AREA + + .............. + + + + | | GPRn + +--------------------------+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + | CR SAVE | + +--------------------------+ + | | + + LOCAL VARIABLES AREA + + .............. + + + + | | + +--------------------------+ + | | PAR(n-7) + + + + | | + + PARAMETER AREA + + .............. + + for FUTURE call + + | | PAR(9) + + + + SP + 8 -> | | PAR(8) + +--------------------------+ + SP + 4 -> | | LR callee-save for FUTURE call + + LINKAGE AREA + + SP -> | | backchain + +==========================+ + STACK TOP (lower address) + + Stack grows down + | + V + + + * NOTE: + * + * 1) In this figure parameter are supposed to be integer 4-bytes aligned and + * are numbered 0, 1, 2,... n. + * + * 2) Parameter are allocated in the CALLER's parameter area. This area must + * be large enough to hold all parameters that cannot fit in registers (no + * more parameter registers are available); + * + * 3) The callee saves LR in the caller's linkage area. CR as all other + * callee's state are saved in its own stack frame. + * + + *****************************************************************************/ + + +/***************************************************************************** + * + * Stack initialization for a single argument thread + * + + + top + QUICKTHREADS_STKBASE -> STACK BOTTOM (higher address) + +==========================+ + | | + + + + .............. + + + + | | + +--------------------------+ + top + QUICKTHREADS_ONLY_INDEX * 4 -> | only param | PAR(3) + + + + top + QUICKTHREADS_USER_INDEX * 4 -> | userf param | PAR(2) + + + + top + QUICKTHREADS_ARGT_INDEX * 4 -> | t param | PAR(1) + + + + top + QUICKTHREADS_ARGU_INDEX * 4 -> | u param | PAR(0) + +--------------------------+ + top + QUICKTHREADS_RETURN_INDEX * 4 -> | qt_start | LR save + + + + top + QUICKTHREADS_BLOCKI_FRAME_SIZE -> | top + QUICKTHREADS_STKBASE | backchain + +==========================+ + | | + + + + .............. + + + + | | + +--------------------------+ + | | + + + + top -> |top + QUICKTHREADS_BLOCKI_FRAME_SIZE| backchain + +==========================+ + STACK TOP (lower address) + + Stack grows down + | + V + + ***************************************************************************** + * + * Stack initialization for a variant argument thread + * + + bottom -> STACK BOTTOM (higher address) + +==========================+ + | | + + + + .............. + + + + top + QUICKTHREADS_VSTKBASE -> | arg(0) | PAR(4) + +--------------------------+ + top + QUICKTHREADS_CLEANUP_INDEX * 4 -> | cleanup param | PAR(3) + + + + top + QUICKTHREADS_USER_INDEX * 4 -> | userf param | PAR(2) + + + + top + QUICKTHREADS_VSTARTUP_INDEX * 4 ->| startup param | PAR(1) + + + + top + QUICKTHREADS_ARGT_INDEX * 4 -> | t param | PAR(0) + +--------------------------+ + top + QUICKTHREADS_RETURN_INDEX * 4 -> | qt_start | LR save + + + + top + QUICKTHREADS_BLOCKI_FRAME_SIZE -> | top + QUICKTHREADS_STKBASE | backchain + +==========================+ + | | + + + + .............. + + + + | | + +--------------------------+ + | | + + + + top -> |top + QUICKTHREADS_BLOCKI_FRAME_SIZE| backchain + +==========================+ + STACK TOP (lower address) + + Stack grows down + | + V + +* NOTE: +* +* Parameters are passed to "qt_start" or to "qt_vstart" putting them into +* the stack frames of "qt_start" or "qt_vstart" themselves. This not a +* conventional parameter passing because parameters should be put into the +* caller's stack, not into the callee's one. Actually we must consider +* that as a preload of the parameter area that "qt_start" or "qt_vstart" +* will use for their own calls. +* Be aware of the fact that, during a call, the caller's parameter area is, +* in a certain sense, volatile. In facts, the callee can save parameter +* registers on the caller's parameter area. +* + *****************************************************************************/ + + +/***************************************************************************** + + Define PowerPC System V related macros + + *****************************************************************************/ + + + +typedef unsigned long PPC_W; + +/* Stack pointer must always be a multiple of 16 */ +#define PPC_STACK_INCR 16 +#define PPC_ROUND_STACK(length) \ + (((length)+PPC_STACK_INCR-1) & ~(PPC_STACK_INCR-1)) + + +#define PPC_LINKAGE_AREA 8 +#define PPC_LR_SAVE 4 + +#define PPC_PARAM_AREA(n) (4*(n)) + +#define PPC_GPR_SAVE_AREA (4*19) /* GPR13-GPR31 must be saved */ +#define PPC_FPR_SAVE_AREA (8*18) /* FPR14-FPR31 must be saved */ + +/* Define parameter offset on the stack. + * NOTICE: Parameters are numbered 0, 1, ..., n. +*/ +#define PPC_PAR(i) (PPC_LINKAGE_AREA+(i)*4) + +/***************************************************************************** + + Define stack frames + + *****************************************************************************/ + + +/* Define the "qt_blocki" and "qt_abort" stack frame. We use the same stack + * frame for both. + * + + top + S -> + +==========================+ + top + S - 4 -> | | GPR31 + + GPR SAVE AREA + + .............. + + + + top + S - 19 * 4 -> | | GPR13 + +--------------------------+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + top + 8 -> | CR SAVE | + +--------------------------+ + | | + + LINKAGE AREA + + top -> | | + +==========================+ + */ + +#define QUICKTHREADS_BLOCKI_FRAME_SIZE \ + PPC_ROUND_STACK(PPC_LINKAGE_AREA+4+PPC_GPR_SAVE_AREA) + +#define QUICKTHREADS_BLOCKI_CR_SAVE 8 + +/* Offset to the base of the GPR save area. Save from GPR13 to GPR31 + * increasing address. + */ +#define QUICKTHREADS_BLOCKI_GPR_SAVE(i) (QUICKTHREADS_BLOCKI_FRAME_SIZE-4+(i-31)*4) + + + +/* Define the "qt_block" stack frame. Notice that since "qt_black" calls + * "qt_blocki", GPR registers are saved into "qt_blocki" stack frame. + * + + top + S -> + +==========================+ + top + S - 8 -> | | FPR31 + + FPR SAVE AREA + + .............. + + + + top + S - 18 * 8 -> | | FPR14 + +--------------------------+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + | | + + LINKAGE AREA + + top -> | | + +==========================+ + */ + +#define QUICKTHREADS_BLOCK_FRAME_SIZE \ + PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_FPR_SAVE_AREA) + +/* Offset to the location where registers are saved. + */ +#define QUICKTHREADS_BLOCK_FPR_SAVE(i) (QUICKTHREADS_BLOCK_FRAME_SIZE-8+(i-31)*8) + + +/* Define the "qt_start" frame size. It consists just of the linkage area and + * the parameter area. + * + + +==========================+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + | | only par + + + + | | userf par + + PARAMETER AREA + + | | t par + + + + top + 8 -> | | u par + +--------------------------+ + | | + + LINKAGE AREA + + top -> | | + +==========================+ + + */ +#define QUICKTHREADS_START_FRAME_SIZE PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_PARAM_AREA(4)) + + + +/* Define the "qt_vstart" frame. It consists of the linkage area, the fix parameter + * area, the variant argument list and a local variable area used in "qt_vstart" + * implementation. + * + + backchain -> + +==========================+ + backchain - 4 -> | | + + LOCAL VARIABLES AREA + + .............. + + + + | | + +--------------------------+ + | | + + ALIGNMEBNT PAD + + .............. + + (if needed) + + | | + +--------------------------+ + | | arg(n) + + + + | | + + VARIABLE ARGUMENT LIST + + .............. + + for userf call + + | | arg(1) + + + + top + 8 + 16 -> | | arg(0) + +--------------------------+ + | | cleanup par + + + + | | userf par + + PARAMETER AREA + + | | startup par + + + + top + 8 -> | | t par + +--------------------------+ + | | + + LINKAGE AREA + + top -> | | + +==========================+ + + */ +#define QUICKTHREADS_VARGS_LOCAL_AREA (4*4) /* local variable area */ + +/* The offset the stack will be moved back before to call "userf(...)". + * The linckage area must be moved to be adiacent to the part of the variant + * argument list that is in the stack. Notice that, since the first 8 + * parameters are passed via registers, the offset is equal to the size of + * 4+8 parameters. */ +#define QUICKTHREADS_VARGS_BKOFF PPC_PARAM_AREA(4+8) + +#define QUICKTHREADS_VSTART_FRAME_SIZE(varbytes) \ + PPC_ROUND_STACK(PPC_LINKAGE_AREA+QUICKTHREADS_VARGS_BKOFF+(varbytes)+ \ + QUICKTHREADS_VARGS_LOCAL_AREA) + +/* Offset to the base of the varian argument list */ +#define QUICKTHREADS_VSTART_LIST_BASE (PPC_LINKAGE_AREA+PPC_PARAM_AREA(4)) + + +/* Notice that qt_start and qt_vstart have no parameters, actually their + * parameters are written in their stack frame during thread initialization + */ +extern void qt_start(void); +extern void qt_vstart(void); + + + +/* Offset (in words) of the location where the block routine saves its return + * address (i.e. LR). SP points the top of the block routine stack and, + * following ppc calling conventions, the return address is saved in the + * previous (caller's) stack frame. + */ +#define QUICKTHREADS_RETURN_INDEX ((QUICKTHREADS_BLOCKI_FRAME_SIZE+PPC_LR_SAVE)/sizeof(PPC_W)) + +/* static variable used to get the stack bottom in "VARGS" initialization */ +static void *qt_sp_bottom_save; + +#define QUICKTHREADS_ARG_INDEX(i) ((QUICKTHREADS_BLOCKI_FRAME_SIZE+PPC_PAR(i))/sizeof(PPC_W)) + +/***************************************************************************** + + QuickThreads needed definitions + + *****************************************************************************/ + + +#define QUICKTHREADS_GROW_DOWN +#define QUICKTHREADS_STKALIGN PPC_STACK_INCR +typedef PPC_W qt_word_t; + + +/* This macro is used by "QUICKTHREADS_ARGS" to initialize a single argument thread. + * - set "qt_start" as the "qt_block" or "qt_blocki" return address; + * - set the top of the stack backchain; + * - set the next backchain (not needed, but just to be "clean"). + */ +#define QUICKTHREADS_ARGS_MD(sp) \ + (QUICKTHREADS_SPUT (sp, QUICKTHREADS_RETURN_INDEX, qt_start), \ + QUICKTHREADS_SPUT (sp, 0, sp+QUICKTHREADS_BLOCKI_FRAME_SIZE), \ + QUICKTHREADS_SPUT (sp, QUICKTHREADS_BLOCKI_FRAME_SIZE/sizeof(PPC_W), \ + sp+QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_START_FRAME_SIZE)) + + +/* This macro is used by "QUICKTHREADS_VARGS" to initialize a variant argument thread. + * It returns the pointer to the top of the argument list. + * We also use it to get the stack bottom via a static variable. This is a bit + * "dirty", it could be better to do it in "qt_vargs", but we don't want change + * anything out of this file. + * We need the stack bottom to allocate a local variable area used by + * "qt_vstart". + */ +#define QUICKTHREADS_VARGS_MD0(sp, varbytes) \ + ((qt_sp_bottom_save = sp), \ + ((qt_t *)(((char *)(sp)) - \ + (QUICKTHREADS_VSTART_FRAME_SIZE(varbytes)-QUICKTHREADS_VSTART_LIST_BASE)))) + + +/* This macro is used by "QUICKTHREADS_VARGS" to initialize a variant argument thread. + * - set "qt_start" as the "qt_block" or "qt_blocki" return address; + * - set the top of the stackback chain; + * - set the next backchain (it points the stack botton). + */ +#define QUICKTHREADS_VARGS_MD1(sp) \ + (QUICKTHREADS_SPUT (sp, QUICKTHREADS_RETURN_INDEX, qt_vstart), \ + QUICKTHREADS_SPUT (sp, 0, sp+QUICKTHREADS_BLOCKI_FRAME_SIZE), \ + QUICKTHREADS_SPUT (sp, (QUICKTHREADS_BLOCKI_FRAME_SIZE)/sizeof(PPC_W), \ + qt_sp_bottom_save)) + + +/* Activate "qt_vargs" as the initialization routine for the variant + * argument threads + */ +#define QUICKTHREADS_VARGS_DEFAULT + +/* Override "qt_vargs" with "qt_vargs_stdarg". + * On LinuxPPC "qt_vargs" doesn't work, "qt_vargs_stdarg" uses a more + * standard way to retrieve arguments from the variant list. + */ +#define QUICKTHREADS_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \ + ((qt_t *)qt_vargs_stdarg (sp, nbytes, vargs, pt, startup, vuserf, cleanup)) + + +/* This macro is used by "QUICKTHREADS_ADJ(sp)" to get the stack top form the stack + * bottom during a single argument thread initialization. + * It is the space we need to allocate for a single argument thread: the stack + * frame for the block routine ("qt_block" or "qt_blocki") and for "qt_start". + */ +#define QUICKTHREADS_STKBASE \ + (QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_START_FRAME_SIZE) + +/* This macro is used by "QUICKTHREADS_VADJ(sp)" to get the stack top from the base + * of the variant argument list during a variant argument thread initialization. + */ +#define QUICKTHREADS_VSTKBASE (QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_VSTART_LIST_BASE) + +/* The *index* (positive offset) of where to put each value. */ + +#define QUICKTHREADS_ARGU_INDEX QUICKTHREADS_ARG_INDEX(0) +#define QUICKTHREADS_ARGT_INDEX QUICKTHREADS_ARG_INDEX(1) +#define QUICKTHREADS_USER_INDEX QUICKTHREADS_ARG_INDEX(2) +#define QUICKTHREADS_ONLY_INDEX QUICKTHREADS_ARG_INDEX(3) + + +#define QUICKTHREADS_VARGT_INDEX QUICKTHREADS_ARG_INDEX(0) +#define QUICKTHREADS_VSTARTUP_INDEX QUICKTHREADS_ARG_INDEX(1) +#define QUICKTHREADS_VUSERF_INDEX QUICKTHREADS_ARG_INDEX(2) +#define QUICKTHREADS_VCLEANUP_INDEX QUICKTHREADS_ARG_INDEX(3) + +#endif /* ndef QUICKTHREADS_POWERPC_H */ + |