1 ; pa-risc.s -- assembly support.
3 ; QuickThreads -- Threads-building toolkit.
4 ; Copyright (c) 1993 by David Keppel
6 ; Permission to use, copy, modify and distribute this software and
7 ; its documentation for any purpose and without fee is hereby
8 ; granted, provided that the above copyright notice and this notice
9 ; appear in all copies. This software is provided as a
10 ; proof-of-concept and for demonstration purposes; there is no
11 ; representation about the suitability of this software for any
14 ; This file (pa-risc.s) is part of the port of QuickThreads for
15 ; PA-RISC 1.1 architecture. This file implements context switches
16 ; and thread startup. It was written in 1994 by Uwe Reder
17 ; (`uereder@cip.informatik.uni-erlangen.de') for the Operating
18 ; Systems Department (IMMD4) at the University of Erlangen/Nuernberg
22 ; Callee saves general registers gr3..gr18,
23 ; floating-point registers fr12..fr21.
27 .IMPORT $$dyncall, MILLICODE
28 .IMPORT qt_error, CODE
30 .EXPORT qt_blocki, ENTRY
31 .EXPORT qt_block, ENTRY
32 .EXPORT qt_abort, ENTRY
33 .EXPORT qt_start, ENTRY
34 .EXPORT qt_vstart, ENTRY
37 ; arg0: ptr to function (helper) to call once curr is suspended
38 ; and control is on arg3's stack.
39 ; arg1: 1'th arg to *arg0.
40 ; arg2: 2'th arg to *arg0.
41 ; arg3: sp of new thread.
45 .CALLINFO CALLER, FRAME=0, SAVE_RP, ENTRY_GR=18
48 stw %rp,-20(%sp) ; save rp to old frame-marker
50 stwm %r3,128(%sp) ; save callee-saves general registers
68 copy %arg0,%r22 ; helper to be called by $$dyncall
69 copy %sp,%arg0 ; pass current sp as arg0 to helper
70 copy %arg3,%sp ; set new sp
73 bl $$dyncall,%mrp ; call helper
76 ldw -68(%sp),%r18 ; restore general registers
92 ldw -148(%sp),%rp ; restore return-pointer
94 bv %r0(%rp) ; return to caller
103 .CALLINFO CALLER, FRAME=0, SAVE_RP, ENTRY_FR=21
106 stw %rp,-20(%sp) ; save rp to old frame-marker
108 fstds,ma %fr12,8(%sp) ; save callee-saves float registers
109 fstds,ma %fr13,8(%sp)
110 fstds,ma %fr14,8(%sp)
111 fstds,ma %fr15,8(%sp)
112 fstds,ma %fr16,8(%sp)
113 fstds,ma %fr17,8(%sp)
114 fstds,ma %fr18,8(%sp)
115 fstds,ma %fr19,8(%sp)
116 fstds,ma %fr20,8(%sp)
117 fstds,ma %fr21,8(%sp)
125 fldds,mb -8(%sp),%fr21 ; restore callee-saves float registers
126 fldds,mb -8(%sp),%fr20
127 fldds,mb -8(%sp),%fr19
128 fldds,mb -8(%sp),%fr18
129 fldds,mb -8(%sp),%fr17
130 fldds,mb -8(%sp),%fr16
131 fldds,mb -8(%sp),%fr15
132 fldds,mb -8(%sp),%fr14
133 fldds,mb -8(%sp),%fr13
135 ldw -28(%sp),%rp ; restore return-pointer
137 bv %r0(%rp) ; return to caller.
138 fldds,mb -8(%sp),%fr12
146 .CALLINFO CALLER, FRAME=0
149 copy %r18,%arg0 ; set user arg `pu'.
150 copy %r17,%arg1 ; ... user function pt.
151 copy %r16,%arg2 ; ... user function userf.
152 ; %r22 is a caller-saves register
153 copy %r15,%r22 ; function to be called by $$dyncall
156 bl $$dyncall,%mrp ; call `only'.
159 bl,n qt_error,%r0 ; `only' erroniously returned.
167 ; First, call `startup' with the `pt' argument.
169 ; Next, call the user's function with all arguments.
170 ; We don't know whether arguments are integers, 32-bit floating-points or
171 ; even 64-bit floating-points, so we reload all the registers, possibly
172 ; with garbage arguments. The thread creator provided non-garbage for
173 ; the arguments that the callee actually uses, so the callee never gets
176 ; -48 -44 -40 -36 -32
177 ; | arg3 | arg2 | arg1 | arg0 |
178 ; -----------------------------
179 ; integers: arg3 arg2 arg1 arg0
180 ; 32-bit fps: farg3 farg2 farg1 farg0
181 ; 64-bit fps: <---farg3--> <---farg1-->
183 ; Finally, call `cleanup' with the `pt' argument and with the return value
184 ; from the user's function. It is an error for `cleanup' to return.
188 .CALLINFO CALLER, FRAME=0
191 ; Because the startup function may damage the fixed arguments
192 ; on the stack (PA-RISC Procedure Calling Conventions Reference
193 ; Manual, 2.4 Fixed Arguments Area), we allocate a seperate
194 ; stack frame for it.
197 ; call: void startup(void *pt)
199 copy %r15,%arg0 ; `pt' is arg0 to `startup'.
202 bl $$dyncall,%mrp ; Call `startup'.
207 ; call: void *qt_vuserf_t(...)
209 ldw -36(%sp),%arg0 ; Load args to integer registers.
213 ; Index of fld[w|d]s only ranges from -16 to 15, so we
214 ; take r22 to be our new base register.
216 fldws -4(%r22),%farg0 ; Load args to floating-point registers.
217 fldds -8(%r22),%farg1
218 fldws -12(%r22),%farg2
219 fldds -16(%r22),%farg3
222 bl $$dyncall,%mrp ; Call `userf'.
225 ; call: void cleanup(void *pt, void *vuserf_return)
227 copy %r15,%arg0 ; `pt' is arg0 to `cleanup'.
228 copy %ret0,%arg1 ; Return-value is arg1 to `cleanup'.
231 bl $$dyncall,%mrp ; Call `cleanup'.