powerpc_sys5.h

Go to the documentation of this file.
00001 /*
00002    + * QuickThreads -- Threads-building toolkit.
00003    + * Copyright (c) 1993 by David Keppel
00004    + *
00005    + * Permission to use, copy, modify and distribute this software and
00006    + * its documentation for any purpose and without fee is hereby
00007    + * granted, provided that the above copyright notice and this notice
00008    + * appear in all copies.  This software is provided as a
00009    + * proof-of-concept and for demonstration purposes; there is no
00010    + * representation about the suitability of this software for any
00011    + * purpose.
00012    + *
00013 
00014    + * PowerPC-Sys5 thread switching module.
00015    + * 
00016    + * This software is largely based on the original PowerPC-Linux porting
00017    + * developed by Ken Aaker <kenaaker@silverbacksystems.com>
00018    + * 
00019    + * Marco Bucci <marco.bucci@inwind.it>
00020    + * December 2002
00021    + *
00022    + */
00023 
00024 
00025 #ifndef QUICKTHREADS_POWERPC_H
00026 #define QUICKTHREADS_POWERPC_H
00027 
00028 
00029 /*****************************************************************************
00030  *
00031  * DESCRIPTION
00032  *
00033  * This is the QuickThreads switching module implementation for PowerPC 
00034  * running under System V ABI (Application Binary Interface) [2]. It was
00035  * developed by porting the MacOS X version and tested under LinuxPPC.
00036  *
00037  * Notice that this is not the same than the PowerPC Mach  ABI used by MacOSX
00038  * [1].
00039  *
00040  * IMPLEMENTATION NOTES
00041  *
00042  * 1) Porting on System V ABI
00043  * Excluding the variant argument calling convention, Mach and System V ABI
00044  * are enough similar and it could be possible to use some simple macro, to
00045  * adapt the code for both the ABIs. Actually, the only relevant difference 
00046  * is in the linkage area structure and in the position where the Link and
00047  * the Condition registers are saved. As to the calling conventions, there
00048  * are differences with floating points argument passing and with variant
00049  * argument lists. Notice that, on Mach, the caller's stack frame allocates
00050  * space to hold all arguments ([1] p.51), while on System V, the caller's
00051  * stack frame allocates space to hold just the arguments that don't fit into
00052  * registers ([2] p.3.18).
00053  *
00054  * 2) Variant argument list implementation
00055  * Variant argument calling on a RISC machine is not easy to implement since
00056  * parameters are passed via registers instead of via stack. In a general
00057  * variant argument implementation, the caller's stack must map the whole
00058  * parameter list following the rules related to the use of the GPR and FPR
00059  * parameter registers and the stack alignment ([2] p.3-21). 
00060  * This implementation is quite simple and not general. It works under the
00061  * hypothesis that arguments are 4-bytes aligned integers.
00062  *
00063  * 3) This heather file organisation
00064  * I preferred to not make confusion between macros that are needed (i.e.
00065  * directly used) by QuickThreads and internal "implementation" macros. You
00066  * will find QuickThreds macros in the end of this header. Sometime they just
00067  * refer to an analogous "internal" macro. On the top, there are the macros
00068  * that I used to make more clean (I hope) the implementation. I could include
00069  * some system heather (as to stack layout definitions, prologs and epilogs,
00070  * etc.), but I preferred to have a self-contained heather in order to make
00071  * all more clear for mantaining and for possible porting on another ABI.
00072  *
00073  *
00074  * REFERENCES
00075  *
00076  * [1] - Mach-O Runtime Architecture
00077  *       Runtime Concepts and Conventions for Mac OS X Programs
00078  *       Preliminary July 2002
00079  *
00080  * [2] - SYSTEM V APPLICATION BINARY INTERFACE
00081  *       PowerPC Processor Supplement
00082  *       September 1995
00083  *
00084 
00085  *****************************************************************************/
00086 
00087 /*****************************************************************************
00088  *
00089  *  PowerPC System V Stack frame (see [2])
00090  *  
00091   
00092                       ................
00093                 +                          +
00094                 |                          | 
00095                 +--------------------------+
00096                 |                          | Caller's LR
00097                 +  CALLER'S LINKAGE AREA   +
00098  backchain ->   |                          | Caller's backchain
00099                 +==========================+
00100                 |                          | FPR31
00101                 +      FPR SAVE AREA       +
00102                        ..............
00103                 +                          +
00104                 |                          | FPRn
00105                 +--------------------------+
00106                 |                          | GPR31
00107                 +      GPR SAVE AREA       +
00108                        ..............
00109                 +                          +
00110                 |                          | GPRn
00111                 +--------------------------+
00112                 |                          | 
00113                 +      ALIGNMEBNT PAD      +
00114                        ..............
00115                 +       (if needed)        +
00116                 |                          |
00117                 +--------------------------+
00118                 |         CR SAVE          |
00119                 +--------------------------+
00120                 |                          | 
00121                 +   LOCAL VARIABLES AREA   +
00122                        ..............
00123                 +                          +
00124                 |                          |
00125                 +--------------------------+
00126                 |                          | PAR(n-7)
00127                 +                          +
00128                 |                          | 
00129                 +      PARAMETER AREA      +
00130                        ..............
00131                 +      for FUTURE call     +
00132                 |                          | PAR(9)
00133                 +                          +
00134  SP + 8 ->      |                          | PAR(8)
00135                 +--------------------------+
00136  SP + 4 ->      |                          | LR callee-save for FUTURE call
00137                 +       LINKAGE AREA       +
00138  SP ->          |                          | backchain
00139                 +==========================+
00140                 STACK TOP (lower address)
00141   
00142                      Stack grows down
00143                              |
00144                              V
00145  
00146 
00147  * NOTE:
00148  *
00149  * 1) In this figure parameter are supposed to be integer 4-bytes aligned and
00150  * are numbered 0, 1, 2,... n.
00151  *
00152  * 2) Parameter are allocated in the CALLER's parameter area. This area must
00153  * be large enough to hold all parameters that cannot fit in registers (no 
00154  * more parameter registers are available);
00155  *
00156  * 3) The callee saves LR in the caller's linkage area. CR as all other
00157  * callee's state are saved in its own stack frame.
00158  *
00159  
00160  *****************************************************************************/ 
00161 
00162 
00163 /*****************************************************************************
00164  * 
00165  * Stack initialization for a single argument thread
00166  *
00167 
00168 
00169  top + QUICKTHREADS_STKBASE ->           STACK BOTTOM (higher address)
00170                                +==========================+
00171                                |                          |
00172                                +                          +
00173                                      ..............
00174                                +                          +
00175                                |                          |
00176                                +--------------------------+
00177  top + QUICKTHREADS_ONLY_INDEX * 4 ->    | only param               | PAR(3)
00178                                +                          +
00179  top + QUICKTHREADS_USER_INDEX * 4 ->    | userf param              | PAR(2)
00180                                +                          +
00181  top + QUICKTHREADS_ARGT_INDEX * 4 ->    | t param                  | PAR(1)
00182                                +                          +
00183  top + QUICKTHREADS_ARGU_INDEX * 4 ->    | u param                  | PAR(0)
00184                                +--------------------------+
00185  top + QUICKTHREADS_RETURN_INDEX * 4 ->  | qt_start                 | LR save
00186                                +                          +
00187  top + QUICKTHREADS_BLOCKI_FRAME_SIZE -> | top + QUICKTHREADS_STKBASE         | backchain                     
00188                                +==========================+
00189                                |                          |
00190                                +                          +
00191                                      ..............
00192                                +                          +
00193                                |                          |
00194                                +--------------------------+
00195                                |                          | 
00196                                +                          +
00197  top ->                        |top + QUICKTHREADS_BLOCKI_FRAME_SIZE| backchain
00198                                +==========================+
00199                                STACK TOP (lower address)
00200   
00201                                     Stack grows down
00202                                            |
00203                                            V
00204 
00205  *****************************************************************************
00206  *
00207  * Stack initialization for a variant argument thread
00208  *
00209 
00210  bottom ->                     STACK BOTTOM (higher address)
00211                                +==========================+
00212                                |                          |
00213                                +                          +
00214                                      ..............
00215                                +                          +
00216  top + QUICKTHREADS_VSTKBASE ->          | arg(0)                   | PAR(4)
00217                                +--------------------------+
00218  top + QUICKTHREADS_CLEANUP_INDEX * 4 -> | cleanup param            | PAR(3)
00219                                +                          +
00220  top + QUICKTHREADS_USER_INDEX * 4 ->    | userf param              | PAR(2)  
00221                                +                          +
00222  top + QUICKTHREADS_VSTARTUP_INDEX * 4 ->| startup param            | PAR(1)
00223                                +                          +
00224  top + QUICKTHREADS_ARGT_INDEX * 4 ->    | t param                  | PAR(0)
00225                                +--------------------------+
00226  top + QUICKTHREADS_RETURN_INDEX * 4 ->  | qt_start                 | LR save
00227                                +                          +
00228  top + QUICKTHREADS_BLOCKI_FRAME_SIZE -> | top + QUICKTHREADS_STKBASE         | backchain                     
00229                                +==========================+
00230                                |                          |
00231                                +                          +
00232                                      ..............
00233                                +                          +
00234                                |                          |
00235                                +--------------------------+
00236                                |                          | 
00237                                +                          +
00238  top ->                        |top + QUICKTHREADS_BLOCKI_FRAME_SIZE| backchain
00239                                +==========================+
00240                                STACK TOP (lower address)
00241   
00242                                     Stack grows down
00243                                           |
00244                                           V
00245 
00246 * NOTE:
00247 *
00248 * Parameters are passed to "qt_start" or to "qt_vstart" putting them into
00249 * the stack frames of "qt_start" or "qt_vstart" themselves. This not a
00250 * conventional parameter passing because parameters should be put into the
00251 * caller's stack, not into the callee's one. Actually  we must consider
00252 * that as a preload of the parameter area that "qt_start" or "qt_vstart"
00253 * will use for their own calls.
00254 *  Be aware of the fact that, during a call, the caller's parameter area is,
00255 * in a certain sense, volatile. In facts, the callee can save parameter
00256 * registers on the caller's parameter area.
00257 *
00258  *****************************************************************************/ 
00259 
00260 
00261 /*****************************************************************************
00262  
00263    Define PowerPC System V related macros
00264  
00265  *****************************************************************************/ 
00266 
00267 
00268 
00269 typedef unsigned long PPC_W;
00270 
00271 /* Stack pointer must always be a multiple of 16 */
00272 #define PPC_STACK_INCR  16      
00273 #define PPC_ROUND_STACK(length) \
00274     (((length)+PPC_STACK_INCR-1) & ~(PPC_STACK_INCR-1))
00275 
00276 
00277 #define PPC_LINKAGE_AREA 8                  
00278 #define PPC_LR_SAVE 4
00279 
00280 #define PPC_PARAM_AREA(n) (4*(n))
00281 
00282 #define PPC_GPR_SAVE_AREA (4*19)        /* GPR13-GPR31 must be saved */
00283 #define PPC_FPR_SAVE_AREA (8*18)        /* FPR14-FPR31 must be saved */
00284 
00285 /* Define parameter offset on the stack.
00286  * NOTICE: Parameters are numbered 0, 1, ..., n. 
00287 */
00288 #define PPC_PAR(i) (PPC_LINKAGE_AREA+(i)*4)
00289 
00290 /*****************************************************************************
00291  
00292    Define stack frames
00293  
00294  *****************************************************************************/ 
00295 
00296 
00297 /* Define the "qt_blocki" and "qt_abort" stack frame. We use the same stack
00298  * frame for both. 
00299  *
00300 
00301  top + S ->  
00302                         +==========================+
00303  top + S - 4 ->         |                          | GPR31 
00304                         +      GPR SAVE AREA       +
00305                                ..............
00306                         +                          +
00307  top + S - 19 * 4 ->    |                          | GPR13
00308                         +--------------------------+
00309                         |                          | 
00310                         +      ALIGNMEBNT PAD      +
00311                                ..............
00312                         +       (if needed)        +
00313                         |                          |
00314                         +--------------------------+
00315  top + 8 ->             |         CR SAVE          |
00316                         +--------------------------+
00317                         |                          |
00318                         +       LINKAGE AREA       +
00319  top ->                 |                          |
00320                         +==========================+
00321  */
00322 
00323 #define QUICKTHREADS_BLOCKI_FRAME_SIZE \
00324     PPC_ROUND_STACK(PPC_LINKAGE_AREA+4+PPC_GPR_SAVE_AREA)
00325     
00326 #define QUICKTHREADS_BLOCKI_CR_SAVE 8
00327 
00328 /* Offset to the base of the GPR save area. Save from GPR13 to GPR31
00329  * increasing address. 
00330  */
00331 #define QUICKTHREADS_BLOCKI_GPR_SAVE(i) (QUICKTHREADS_BLOCKI_FRAME_SIZE-4+(i-31)*4)
00332 
00333 
00334 
00335 /* Define the "qt_block" stack frame. Notice that since "qt_black" calls
00336  * "qt_blocki", GPR registers are saved into "qt_blocki" stack frame.
00337  *
00338 
00339  top + S ->  
00340                         +==========================+
00341  top + S - 8 ->         |                          | FPR31 
00342                         +      FPR SAVE AREA       +
00343                                ..............
00344                         +                          +
00345  top + S - 18 * 8 ->    |                          | FPR14
00346                         +--------------------------+
00347                         |                          | 
00348                         +      ALIGNMEBNT PAD      +
00349                                ..............
00350                         +       (if needed)        +
00351                         |                          |
00352                         +--------------------------+
00353                         |                          |
00354                         +       LINKAGE AREA       +
00355  top ->                 |                          |
00356                         +==========================+
00357  */
00358 
00359 #define QUICKTHREADS_BLOCK_FRAME_SIZE \
00360     PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_FPR_SAVE_AREA)
00361 
00362 /* Offset to the location where registers are saved.
00363  */
00364 #define QUICKTHREADS_BLOCK_FPR_SAVE(i) (QUICKTHREADS_BLOCK_FRAME_SIZE-8+(i-31)*8)
00365 
00366 
00367 /* Define the "qt_start" frame size. It consists just of the linkage area and 
00368  * the parameter area. 
00369  *
00370 
00371                         +==========================+
00372                         |                          | 
00373                         +      ALIGNMEBNT PAD      +
00374                                ..............
00375                         +       (if needed)        +
00376                         |                          |
00377                         +--------------------------+
00378                         |                          | only par
00379                         +                          +
00380                         |                          | userf par
00381                         +      PARAMETER AREA      +
00382                         |                          | t par
00383                         +                          +
00384  top + 8 ->             |                          | u par
00385                         +--------------------------+
00386                         |                          |
00387                         +       LINKAGE AREA       +
00388  top ->                 |                          |
00389                         +==========================+
00390 
00391  */
00392 #define QUICKTHREADS_START_FRAME_SIZE PPC_ROUND_STACK(PPC_LINKAGE_AREA+PPC_PARAM_AREA(4))
00393 
00394 
00395 
00396 /* Define the "qt_vstart" frame. It consists of the linkage area, the fix parameter 
00397  * area, the variant argument list and a local variable area used in "qt_vstart"
00398  * implementation.
00399  *
00400 
00401  backchain ->  
00402                         +==========================+
00403  backchain - 4 ->       |                          | 
00404                         +   LOCAL VARIABLES AREA   +
00405                                ..............
00406                         +                          +
00407                         |                          |
00408                         +--------------------------+
00409                         |                          | 
00410                         +      ALIGNMEBNT PAD      +
00411                                ..............
00412                         +       (if needed)        +
00413                         |                          |
00414                         +--------------------------+
00415                         |                          | arg(n)
00416                         +                          +
00417                         |                          | 
00418                         +  VARIABLE ARGUMENT LIST  +
00419                                ..............
00420                         +      for userf call      +
00421                         |                          | arg(1)
00422                         +                          +
00423  top + 8 + 16 ->        |                          | arg(0)
00424                         +--------------------------+
00425                         |                          | cleanup par
00426                         +                          +
00427                         |                          | userf par
00428                         +      PARAMETER AREA      +
00429                         |                          | startup par
00430                         +                          +
00431  top + 8 ->             |                          | t par
00432                         +--------------------------+
00433                         |                          |
00434                         +       LINKAGE AREA       +
00435  top ->                 |                          |
00436                         +==========================+
00437 
00438  */
00439 #define QUICKTHREADS_VARGS_LOCAL_AREA (4*4)     /* local variable area */
00440 
00441 /* The offset the stack will be moved back before to call "userf(...)".
00442  * The linckage area must be moved to be adiacent to the part of the variant
00443  * argument list that is in the stack. Notice that, since the first 8
00444  * parameters are passed via registers, the offset is equal to the size of
00445  * 4+8 parameters. */
00446 #define QUICKTHREADS_VARGS_BKOFF PPC_PARAM_AREA(4+8)
00447 
00448 #define QUICKTHREADS_VSTART_FRAME_SIZE(varbytes) \
00449     PPC_ROUND_STACK(PPC_LINKAGE_AREA+QUICKTHREADS_VARGS_BKOFF+(varbytes)+ \
00450         QUICKTHREADS_VARGS_LOCAL_AREA)
00451 
00452 /* Offset to the base of the varian argument list */
00453 #define QUICKTHREADS_VSTART_LIST_BASE (PPC_LINKAGE_AREA+PPC_PARAM_AREA(4))
00454 
00455 
00456 /* Notice that qt_start and qt_vstart have no parameters, actually their
00457  * parameters are written in their stack frame during thread initialization
00458  */
00459 extern void qt_start(void);
00460 extern void qt_vstart(void);
00461 
00462 
00463 
00464 /* Offset (in words) of the location where the block routine saves its return
00465  * address (i.e. LR). SP points the top of the block routine stack and,
00466  * following ppc calling conventions, the return address is saved in the
00467  * previous (caller's) stack frame.
00468  */
00469 #define QUICKTHREADS_RETURN_INDEX ((QUICKTHREADS_BLOCKI_FRAME_SIZE+PPC_LR_SAVE)/sizeof(PPC_W))
00470 
00471 /* static variable used to get the stack bottom in "VARGS" initialization */
00472 static void *qt_sp_bottom_save;
00473 
00474 #define QUICKTHREADS_ARG_INDEX(i) ((QUICKTHREADS_BLOCKI_FRAME_SIZE+PPC_PAR(i))/sizeof(PPC_W))
00475 
00476 /*****************************************************************************
00477 
00478     QuickThreads needed definitions
00479 
00480  *****************************************************************************/
00481 
00482 
00483 #define QUICKTHREADS_GROW_DOWN
00484 #define QUICKTHREADS_STKALIGN   PPC_STACK_INCR
00485 typedef PPC_W qt_word_t;
00486 
00487 
00488 /* This macro is used by "QUICKTHREADS_ARGS" to initialize a single argument thread.
00489  * - set "qt_start" as the "qt_block" or "qt_blocki" return address;
00490  * - set the top of the stack backchain;
00491  * - set the next backchain (not needed, but just to be "clean").   
00492  */
00493 #define QUICKTHREADS_ARGS_MD(sp) \
00494     (QUICKTHREADS_SPUT (sp, QUICKTHREADS_RETURN_INDEX, qt_start), \
00495     QUICKTHREADS_SPUT (sp, 0, sp+QUICKTHREADS_BLOCKI_FRAME_SIZE), \
00496     QUICKTHREADS_SPUT (sp, QUICKTHREADS_BLOCKI_FRAME_SIZE/sizeof(PPC_W), \
00497         sp+QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_START_FRAME_SIZE))
00498 
00499 
00500 /* This macro is used by "QUICKTHREADS_VARGS" to initialize a variant argument thread. 
00501  * It returns the pointer to the top of the argument list.
00502  * We also use it to get the stack bottom via a static variable. This is a bit 
00503  * "dirty", it could be better to do it in "qt_vargs", but we don't want change 
00504  * anything out of this file.
00505  * We need the stack bottom to allocate a local variable area used by
00506  * "qt_vstart". 
00507  */
00508 #define QUICKTHREADS_VARGS_MD0(sp, varbytes) \
00509   ((qt_sp_bottom_save = sp), \
00510   ((qt_t *)(((char *)(sp)) - \
00511         (QUICKTHREADS_VSTART_FRAME_SIZE(varbytes)-QUICKTHREADS_VSTART_LIST_BASE))))
00512 
00513 
00514 /* This macro is used by "QUICKTHREADS_VARGS" to initialize a variant argument thread.
00515  * - set "qt_start" as the "qt_block" or "qt_blocki" return address;
00516  * - set the top of the stackback chain;
00517  * - set the next backchain (it points the stack botton).   
00518  */
00519 #define QUICKTHREADS_VARGS_MD1(sp) \
00520     (QUICKTHREADS_SPUT (sp, QUICKTHREADS_RETURN_INDEX, qt_vstart), \
00521     QUICKTHREADS_SPUT (sp, 0, sp+QUICKTHREADS_BLOCKI_FRAME_SIZE), \
00522     QUICKTHREADS_SPUT (sp, (QUICKTHREADS_BLOCKI_FRAME_SIZE)/sizeof(PPC_W), \
00523         qt_sp_bottom_save))
00524 
00525 
00526 /* Activate "qt_vargs" as the initialization routine for the variant 
00527  * argument threads
00528  */ 
00529 #define QUICKTHREADS_VARGS_DEFAULT 
00530 
00531 /* Override "qt_vargs" with "qt_vargs_stdarg".
00532  * On LinuxPPC "qt_vargs" doesn't work, "qt_vargs_stdarg" uses a more
00533  * standard way to retrieve arguments from the variant list.
00534  */
00535 #define QUICKTHREADS_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \
00536       ((qt_t *)qt_vargs_stdarg (sp, nbytes, vargs, pt, startup, vuserf, cleanup))
00537 
00538 
00539 /* This macro is used by "QUICKTHREADS_ADJ(sp)" to get the stack top form the stack
00540  * bottom during a single argument thread initialization.
00541  * It is the space we need to allocate for a single argument thread: the stack 
00542  * frame for the block routine ("qt_block" or "qt_blocki") and for "qt_start".
00543  */
00544 #define QUICKTHREADS_STKBASE \
00545     (QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_START_FRAME_SIZE)
00546 
00547 /* This macro is used by "QUICKTHREADS_VADJ(sp)" to get the stack top from the base
00548  * of the variant argument list during a variant argument thread initialization.
00549  */
00550 #define QUICKTHREADS_VSTKBASE   (QUICKTHREADS_BLOCKI_FRAME_SIZE+QUICKTHREADS_VSTART_LIST_BASE)
00551 
00552 /* The *index* (positive offset) of where to put each value. */
00553 
00554 #define QUICKTHREADS_ARGU_INDEX QUICKTHREADS_ARG_INDEX(0)
00555 #define QUICKTHREADS_ARGT_INDEX QUICKTHREADS_ARG_INDEX(1)
00556 #define QUICKTHREADS_USER_INDEX QUICKTHREADS_ARG_INDEX(2)
00557 #define QUICKTHREADS_ONLY_INDEX QUICKTHREADS_ARG_INDEX(3)
00558 
00559 
00560 #define QUICKTHREADS_VARGT_INDEX        QUICKTHREADS_ARG_INDEX(0)
00561 #define QUICKTHREADS_VSTARTUP_INDEX QUICKTHREADS_ARG_INDEX(1)
00562 #define QUICKTHREADS_VUSERF_INDEX       QUICKTHREADS_ARG_INDEX(2)
00563 #define QUICKTHREADS_VCLEANUP_INDEX QUICKTHREADS_ARG_INDEX(3)
00564 
00565 #endif /* ndef QUICKTHREADS_POWERPC_H */
00566 

Generated on Wed Jan 21 15:32:10 2009 for SystemC by  doxygen 1.5.5