123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- ; pa-risc.s -- assembly support.
- ; 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.
- ; This file (pa-risc.s) is part of the port of QuickThreads for
- ; PA-RISC 1.1 architecture. This file implements context switches
- ; and thread startup. It was written in 1994 by Uwe Reder
- ; (`uereder@cip.informatik.uni-erlangen.de') for the Operating
- ; Systems Department (IMMD4) at the University of Erlangen/Nuernberg
- ; Germany.
- ; Callee saves general registers gr3..gr18,
- ; floating-point registers fr12..fr21.
- .CODE
- .IMPORT $$dyncall, MILLICODE
- .IMPORT qt_error, CODE
- .EXPORT qt_blocki, ENTRY
- .EXPORT qt_block, ENTRY
- .EXPORT qt_abort, ENTRY
- .EXPORT qt_start, ENTRY
- .EXPORT qt_vstart, ENTRY
- ; arg0: ptr to function (helper) to call once curr is suspended
- ; and control is on arg3's stack.
- ; arg1: 1'th arg to *arg0.
- ; arg2: 2'th arg to *arg0.
- ; arg3: sp of new thread.
- qt_blocki
- .PROC
- .CALLINFO CALLER, FRAME=0, SAVE_RP, ENTRY_GR=18
- .ENTRY
- stw %rp,-20(%sp) ; save rp to old frame-marker
- stwm %r3,128(%sp) ; save callee-saves general registers
- stw %r4,-124(%sp)
- stw %r5,-120(%sp)
- stw %r6,-116(%sp)
- stw %r7,-112(%sp)
- stw %r8,-108(%sp)
- stw %r9,-104(%sp)
- stw %r10,-100(%sp)
- stw %r11,-96(%sp)
- stw %r12,-92(%sp)
- stw %r13,-88(%sp)
- stw %r14,-84(%sp)
- stw %r15,-80(%sp)
- stw %r16,-76(%sp)
- stw %r17,-72(%sp)
- stw %r18,-68(%sp)
- qt_abort
- copy %arg0,%r22 ; helper to be called by $$dyncall
- copy %sp,%arg0 ; pass current sp as arg0 to helper
- copy %arg3,%sp ; set new sp
- .CALL
- bl $$dyncall,%mrp ; call helper
- copy %mrp,%rp
- ldw -68(%sp),%r18 ; restore general registers
- ldw -72(%sp),%r17
- ldw -76(%sp),%r16
- ldw -80(%sp),%r15
- ldw -84(%sp),%r14
- ldw -88(%sp),%r13
- ldw -92(%sp),%r12
- ldw -96(%sp),%r11
- ldw -100(%sp),%r10
- ldw -104(%sp),%r9
- ldw -108(%sp),%r8
- ldw -112(%sp),%r7
- ldw -116(%sp),%r6
- ldw -120(%sp),%r5
- ldw -124(%sp),%r4
- ldw -148(%sp),%rp ; restore return-pointer
- bv %r0(%rp) ; return to caller
- ldwm -128(%sp),%r3
- .EXIT
- .PROCEND
- qt_block
- .PROC
- .CALLINFO CALLER, FRAME=0, SAVE_RP, ENTRY_FR=21
- .ENTRY
- stw %rp,-20(%sp) ; save rp to old frame-marker
- fstds,ma %fr12,8(%sp) ; save callee-saves float registers
- fstds,ma %fr13,8(%sp)
- fstds,ma %fr14,8(%sp)
- fstds,ma %fr15,8(%sp)
- fstds,ma %fr16,8(%sp)
- fstds,ma %fr17,8(%sp)
- fstds,ma %fr18,8(%sp)
- fstds,ma %fr19,8(%sp)
- fstds,ma %fr20,8(%sp)
- fstds,ma %fr21,8(%sp)
- .CALL
- bl qt_blocki,%rp
- ldo 48(%sp),%sp
- ldo -48(%sp),%sp
- fldds,mb -8(%sp),%fr21 ; restore callee-saves float registers
- fldds,mb -8(%sp),%fr20
- fldds,mb -8(%sp),%fr19
- fldds,mb -8(%sp),%fr18
- fldds,mb -8(%sp),%fr17
- fldds,mb -8(%sp),%fr16
- fldds,mb -8(%sp),%fr15
- fldds,mb -8(%sp),%fr14
- fldds,mb -8(%sp),%fr13
- ldw -28(%sp),%rp ; restore return-pointer
-
- bv %r0(%rp) ; return to caller.
- fldds,mb -8(%sp),%fr12
-
- .EXIT
- .PROCEND
- qt_start
- .PROC
- .CALLINFO CALLER, FRAME=0
- .ENTRY
- copy %r18,%arg0 ; set user arg `pu'.
- copy %r17,%arg1 ; ... user function pt.
- copy %r16,%arg2 ; ... user function userf.
- ; %r22 is a caller-saves register
- copy %r15,%r22 ; function to be called by $$dyncall
- .CALL ; in=%r22
- bl $$dyncall,%mrp ; call `only'.
- copy %mrp,%rp
-
- bl,n qt_error,%r0 ; `only' erroniously returned.
- .EXIT
- .PROCEND
- ; Varargs
- ;
- ; First, call `startup' with the `pt' argument.
- ;
- ; Next, call the user's function with all arguments.
- ; We don't know whether arguments are integers, 32-bit floating-points or
- ; even 64-bit floating-points, so we reload all the registers, possibly
- ; with garbage arguments. The thread creator provided non-garbage for
- ; the arguments that the callee actually uses, so the callee never gets
- ; garbage.
- ;
- ; -48 -44 -40 -36 -32
- ; | arg3 | arg2 | arg1 | arg0 |
- ; -----------------------------
- ; integers: arg3 arg2 arg1 arg0
- ; 32-bit fps: farg3 farg2 farg1 farg0
- ; 64-bit fps: <---farg3--> <---farg1-->
- ;
- ; Finally, call `cleanup' with the `pt' argument and with the return value
- ; from the user's function. It is an error for `cleanup' to return.
- qt_vstart
- .PROC
- .CALLINFO CALLER, FRAME=0
- .ENTRY
- ; Because the startup function may damage the fixed arguments
- ; on the stack (PA-RISC Procedure Calling Conventions Reference
- ; Manual, 2.4 Fixed Arguments Area), we allocate a seperate
- ; stack frame for it.
- ldo 64(%sp),%sp
- ; call: void startup(void *pt)
- copy %r15,%arg0 ; `pt' is arg0 to `startup'.
- copy %r16,%r22
- .CALL
- bl $$dyncall,%mrp ; Call `startup'.
- copy %mrp,%rp
- ldo -64(%sp),%sp
- ; call: void *qt_vuserf_t(...)
- ldw -36(%sp),%arg0 ; Load args to integer registers.
- ldw -40(%sp),%arg1
- ldw -44(%sp),%arg2
- ldw -48(%sp),%arg3
- ; Index of fld[w|d]s only ranges from -16 to 15, so we
- ; take r22 to be our new base register.
- ldo -32(%sp),%r22
- fldws -4(%r22),%farg0 ; Load args to floating-point registers.
- fldds -8(%r22),%farg1
- fldws -12(%r22),%farg2
- fldds -16(%r22),%farg3
- copy %r17,%r22
- .CALL
- bl $$dyncall,%mrp ; Call `userf'.
- copy %mrp,%rp
- ; call: void cleanup(void *pt, void *vuserf_return)
- copy %r15,%arg0 ; `pt' is arg0 to `cleanup'.
- copy %ret0,%arg1 ; Return-value is arg1 to `cleanup'.
- copy %r18,%r22
- .CALL
- bl $$dyncall,%mrp ; Call `cleanup'.
- copy %mrp,%rp
- bl,n qt_error,%r0
- .EXIT
- .PROCEND
|