summaryrefslogtreecommitdiff
path: root/ext/systemc/src/sysc/qt/md/powerpc_sys5.h
diff options
context:
space:
mode:
Diffstat (limited to 'ext/systemc/src/sysc/qt/md/powerpc_sys5.h')
-rw-r--r--ext/systemc/src/sysc/qt/md/powerpc_sys5.h566
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 */
+