| 1 | /* |
| 2 | * QuickThreads -- Threads-building toolkit. |
| 3 | * Copyright (c) 1993 by David Keppel |
| 4 | * |
| 5 | * Permission to use, copy, modify and distribute this software and |
| 6 | * its documentation for any purpose and without fee is hereby |
| 7 | * granted, provided that the above copyright notice and this notice |
| 8 | * appear in all copies. This software is provided as a |
| 9 | * proof-of-concept and for demonstration purposes; there is no |
| 10 | * representation about the suitability of this software for any |
| 11 | * purpose. |
| 12 | */ |
| 13 | |
| 14 | /* |
| 15 | * This file (pa-risc.h) is part of the port of QuickThreads for the |
| 16 | * PA-RISC 1.1 architecture. This file is a machine dependent header |
| 17 | * file. It was written in 1994 by Uwe Reder |
| 18 | * (`uereder@cip.informatik.uni-erlangen.de') for the Operating Systems |
| 19 | * Department (IMMD4) at the University of Erlangen/Nuernberg Germany. |
| 20 | */ |
| 21 | |
| 22 | |
| 23 | #ifndef QT_PA_RISC_H |
| 24 | #define QT_PA_RISC_H |
| 25 | |
| 26 | #include <qt.h> |
| 27 | |
| 28 | /* size of an integer-register (32 bit) */ |
| 29 | typedef unsigned long qt_word_t; |
| 30 | |
| 31 | /* PA-RISC's stack grows up */ |
| 32 | #define QT_GROW_UP |
| 33 | |
| 34 | /* Stack layout on PA-RISC according to PA-RISC Procedure Calling Conventions: |
| 35 | |
| 36 | Callee-save registers are: gr3-gr18, fr12-fr21. |
| 37 | Also save gr2, return pointer. |
| 38 | |
| 39 | +--- |
| 40 | | fr12 Each floating register is a double word (8 bytes). |
| 41 | | fr13 Floating registers are only saved if `qt_block' is |
| 42 | | fr14 called, in which case it saves the floating-point |
| 43 | | fr15 registers then calls `qt_blocki' to save the integer |
| 44 | | fr16 registers. |
| 45 | | fr17 |
| 46 | | fr18 |
| 47 | | fr19 |
| 48 | | fr20 |
| 49 | | fr21 |
| 50 | | <arg word 3> fixed arguments (must be allocated; may remain unused) |
| 51 | | <arg word 2> |
| 52 | | <arg word 1> |
| 53 | | <arg word 0> |
| 54 | | <LPT> frame marker |
| 55 | | <LPT'> |
| 56 | | <RP'> |
| 57 | | <Current RP> |
| 58 | | <Static Link> |
| 59 | | <Clean Up> |
| 60 | | <RP''> |
| 61 | | <Previous SP> |
| 62 | +--- |
| 63 | | gr3 word each (4 bytes) |
| 64 | | gr4 |
| 65 | | gr5 |
| 66 | | gr6 |
| 67 | | gr7 |
| 68 | | gr8 |
| 69 | | gr9 |
| 70 | | gr10 |
| 71 | | gr11 |
| 72 | | gr12 |
| 73 | | gr13 |
| 74 | | gr14 |
| 75 | | gr15 |
| 76 | | gr16 |
| 77 | | gr17 |
| 78 | | gr18 |
| 79 | | <16 bytes filled in (sp has to be 64-bytes aligned)> |
| 80 | | <arg word 3> fixed arguments (must be allocated; may remain unused) |
| 81 | | <arg word 2> |
| 82 | | <arg word 1> |
| 83 | | <arg word 0> |
| 84 | | <LPT> frame marker |
| 85 | | <LPT'> |
| 86 | | <RP'> |
| 87 | | <Current RP> |
| 88 | | <Static Link> |
| 89 | | <Clean Up> |
| 90 | | <RP''> |
| 91 | | <Previous SP> |
| 92 | +--- <--- sp |
| 93 | */ |
| 94 | |
| 95 | /* When a never-before-run thread is restored, the return pc points |
| 96 | to a fragment of code that starts the thread running. For |
| 97 | non-vargs functions, it just calls the client's `only' function. |
| 98 | For varargs functions, it calls the startup, user, and cleanup |
| 99 | functions. */ |
| 100 | |
| 101 | /* Note: Procedue Labels on PA-RISC |
| 102 | |
| 103 | <--2--><-------28---------><1-><1-> |
| 104 | ----------------------------------- |
| 105 | | SID | Adress Part | L | X | |
| 106 | ----------------------------------- |
| 107 | |
| 108 | On HP-UX the L field is used to flag wheather the procedure |
| 109 | label (plabel) is a pointer to an LT entry or to the entry point |
| 110 | of the procedure (PA-RISC Procedure Calling Conventions Reference |
| 111 | Manual, 5.3.2 Procedure Labels and Dynamic Calls). */ |
| 112 | |
| 113 | #define QT_PA_RISC_READ_PLABEL(plabel) \ |
| 114 | ( (((int)plabel) & 2) ? \ |
| 115 | ( (*((int *)(((int)plabel) & 0xfffffffc)))) : ((int)plabel) ) |
| 116 | |
| 117 | /* Stack must be 64 bytes aligned. */ |
| 118 | #define QT_STKALIGN (64) |
| 119 | |
| 120 | /* Internal helper for putting stuff on stack (negative index!). */ |
| 121 | #define QT_SPUT(top, at, val) \ |
| 122 | (((qt_word_t *)(top))[-(at)] = (qt_word_t)(val)) |
| 123 | |
| 124 | /* Offsets of various registers which are modified on the stack. |
| 125 | rp (return-pointer) has to be stored in the frame-marker-area |
| 126 | of the "older" stack-segment. */ |
| 127 | |
| 128 | #define QT_crp (12+4+16+5) |
| 129 | #define QT_15 (12+4+4) |
| 130 | #define QT_16 (12+4+3) |
| 131 | #define QT_17 (12+4+2) |
| 132 | #define QT_18 (12+4+1) |
| 133 | |
| 134 | |
| 135 | /** This stuff is for NON-VARARGS. **/ |
| 136 | |
| 137 | /* Stack looks like this (2 stack frames): |
| 138 | |
| 139 | <--- 64-bytes aligned --><------- 64-bytes aligned ------------> |
| 140 | | || | |
| 141 | <--16--><------48-------><----16*4-----><--16-><------48-------> |
| 142 | || | || | | || |
| 143 | ||filler|arg|frame-marker||register-save|filler|arg|frame-marker|| |
| 144 | ------------------------------------------------------------------ |
| 145 | */ |
| 146 | |
| 147 | #define QT_STKBASE (16+48+(16*sizeof(qt_word_t))+16+48) |
| 148 | |
| 149 | /* The index, relative to sp, of where to put each value. */ |
| 150 | #define QT_ONLY_INDEX (QT_15) |
| 151 | #define QT_USER_INDEX (QT_16) |
| 152 | #define QT_ARGT_INDEX (QT_17) |
| 153 | #define QT_ARGU_INDEX (QT_18) |
| 154 | |
| 155 | extern void qt_start(void); |
| 156 | #define QT_ARGS_MD(sp) \ |
| 157 | (QT_SPUT (sp, QT_crp, QT_PA_RISC_READ_PLABEL(qt_start))) |
| 158 | |
| 159 | |
| 160 | /** This is for VARARGS. **/ |
| 161 | |
| 162 | #define QT_VARGS_DEFAULT |
| 163 | |
| 164 | /* Stack looks like this (2 stack frames): |
| 165 | |
| 166 | <------ 64-bytes aligned -------><--------- 64-bytes aligned ----------> |
| 167 | | || | |
| 168 | <---?--><--?---><16><----32-----><----16*4-----><-16--><16><----32-----> |
| 169 | || | | | || | | | || |
| 170 | ||filler|varargs|arg|frame-marker||register-save|filler|arg|frame-marker|| |
| 171 | -------------------------------------------------------------------------- |
| 172 | */ |
| 173 | |
| 174 | /* Sp is moved to the end of the first stack frame. */ |
| 175 | #define QT_VARGS_MD0(sp, vasize) \ |
| 176 | ((qt_t *)(((char *)sp) + QT_STKROUNDUP(vasize + 4*4 + 32))) |
| 177 | |
| 178 | /* To reach the arguments from the end of the first stack frame use 32 |
| 179 | as a negative adjustment. */ |
| 180 | #define QT_VARGS_ADJUST(sp) ((qt_t *)(((char *)sp) - 32)) |
| 181 | |
| 182 | /* Offset to reach the end of the second stack frame. */ |
| 183 | #define QT_VSTKBASE ((16*sizeof(qt_word_t)) + 16 + 4*4 + 32) |
| 184 | |
| 185 | extern void qt_vstart(void); |
| 186 | #define QT_VARGS_MD1(sp) \ |
| 187 | (QT_SPUT (sp, QT_crp, QT_PA_RISC_READ_PLABEL(qt_vstart))) |
| 188 | |
| 189 | #define QT_VARGT_INDEX (QT_15) |
| 190 | #define QT_VSTARTUP_INDEX (QT_16) |
| 191 | #define QT_VUSERF_INDEX (QT_17) |
| 192 | #define QT_VCLEANUP_INDEX (QT_18) |
| 193 | |
| 194 | #endif /* ndef QT_PA_RISC_H */ |