mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-01 04:10:18 +02:00
237 lines
7.9 KiB
ArmAsm
237 lines
7.9 KiB
ArmAsm
; 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
|