2 * QuickThreads -- Threads-building toolkit.
3 * Copyright (c) 1993 by David Keppel
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
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.
28 /* size of an integer-register (32 bit) */
29 typedef unsigned long qt_word_t;
31 /* PA-RISC's stack grows up */
34 /* Stack layout on PA-RISC according to PA-RISC Procedure Calling Conventions:
36 Callee-save registers are: gr3-gr18, fr12-fr21.
37 Also save gr2, return pointer.
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
50 | <arg word 3> fixed arguments (must be allocated; may remain unused)
63 | gr3 word each (4 bytes)
79 | <16 bytes filled in (sp has to be 64-bytes aligned)>
80 | <arg word 3> fixed arguments (must be allocated; may remain unused)
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
101 /* Note: Procedue Labels on PA-RISC
103 <--2--><-------28---------><1-><1->
104 -----------------------------------
105 | SID | Adress Part | L | X |
106 -----------------------------------
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). */
113 #define QT_PA_RISC_READ_PLABEL(plabel) \
114 ( (((int)plabel) & 2) ? \
115 ( (*((int *)(((int)plabel) & 0xfffffffc)))) : ((int)plabel) )
117 /* Stack must be 64 bytes aligned. */
118 #define QT_STKALIGN (64)
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))
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. */
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)
135 /** This stuff is for NON-VARARGS. **/
137 /* Stack looks like this (2 stack frames):
139 <--- 64-bytes aligned --><------- 64-bytes aligned ------------>
141 <--16--><------48-------><----16*4-----><--16-><------48------->
143 ||filler|arg|frame-marker||register-save|filler|arg|frame-marker||
144 ------------------------------------------------------------------
147 #define QT_STKBASE (16+48+(16*sizeof(qt_word_t))+16+48)
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)
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)))
160 /** This is for VARARGS. **/
162 #define QT_VARGS_DEFAULT
164 /* Stack looks like this (2 stack frames):
166 <------ 64-bytes aligned -------><--------- 64-bytes aligned ---------->
168 <---?--><--?---><16><----32-----><----16*4-----><-16--><16><----32----->
170 ||filler|varargs|arg|frame-marker||register-save|filler|arg|frame-marker||
171 --------------------------------------------------------------------------
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)))
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))
182 /* Offset to reach the end of the second stack frame. */
183 #define QT_VSTKBASE ((16*sizeof(qt_word_t)) + 16 + 4*4 + 32)
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)))
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)
194 #endif /* ndef QT_PA_RISC_H */