hppa.s 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. ; pa-risc.s -- assembly support.
  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. ; This file (pa-risc.s) is part of the port of QuickThreads for
  13. ; PA-RISC 1.1 architecture. This file implements context switches
  14. ; and thread startup. It was written in 1994 by Uwe Reder
  15. ; (`uereder@cip.informatik.uni-erlangen.de') for the Operating
  16. ; Systems Department (IMMD4) at the University of Erlangen/Nuernberg
  17. ; Germany.
  18. ; Callee saves general registers gr3..gr18,
  19. ; floating-point registers fr12..fr21.
  20. .CODE
  21. .IMPORT $$dyncall, MILLICODE
  22. .IMPORT qt_error, CODE
  23. .EXPORT qt_blocki, ENTRY
  24. .EXPORT qt_block, ENTRY
  25. .EXPORT qt_abort, ENTRY
  26. .EXPORT qt_start, ENTRY
  27. .EXPORT qt_vstart, ENTRY
  28. ; arg0: ptr to function (helper) to call once curr is suspended
  29. ; and control is on arg3's stack.
  30. ; arg1: 1'th arg to *arg0.
  31. ; arg2: 2'th arg to *arg0.
  32. ; arg3: sp of new thread.
  33. qt_blocki
  34. .PROC
  35. .CALLINFO CALLER, FRAME=0, SAVE_RP, ENTRY_GR=18
  36. .ENTRY
  37. stw %rp,-20(%sp) ; save rp to old frame-marker
  38. stwm %r3,128(%sp) ; save callee-saves general registers
  39. stw %r4,-124(%sp)
  40. stw %r5,-120(%sp)
  41. stw %r6,-116(%sp)
  42. stw %r7,-112(%sp)
  43. stw %r8,-108(%sp)
  44. stw %r9,-104(%sp)
  45. stw %r10,-100(%sp)
  46. stw %r11,-96(%sp)
  47. stw %r12,-92(%sp)
  48. stw %r13,-88(%sp)
  49. stw %r14,-84(%sp)
  50. stw %r15,-80(%sp)
  51. stw %r16,-76(%sp)
  52. stw %r17,-72(%sp)
  53. stw %r18,-68(%sp)
  54. qt_abort
  55. copy %arg0,%r22 ; helper to be called by $$dyncall
  56. copy %sp,%arg0 ; pass current sp as arg0 to helper
  57. copy %arg3,%sp ; set new sp
  58. .CALL
  59. bl $$dyncall,%mrp ; call helper
  60. copy %mrp,%rp
  61. ldw -68(%sp),%r18 ; restore general registers
  62. ldw -72(%sp),%r17
  63. ldw -76(%sp),%r16
  64. ldw -80(%sp),%r15
  65. ldw -84(%sp),%r14
  66. ldw -88(%sp),%r13
  67. ldw -92(%sp),%r12
  68. ldw -96(%sp),%r11
  69. ldw -100(%sp),%r10
  70. ldw -104(%sp),%r9
  71. ldw -108(%sp),%r8
  72. ldw -112(%sp),%r7
  73. ldw -116(%sp),%r6
  74. ldw -120(%sp),%r5
  75. ldw -124(%sp),%r4
  76. ldw -148(%sp),%rp ; restore return-pointer
  77. bv %r0(%rp) ; return to caller
  78. ldwm -128(%sp),%r3
  79. .EXIT
  80. .PROCEND
  81. qt_block
  82. .PROC
  83. .CALLINFO CALLER, FRAME=0, SAVE_RP, ENTRY_FR=21
  84. .ENTRY
  85. stw %rp,-20(%sp) ; save rp to old frame-marker
  86. fstds,ma %fr12,8(%sp) ; save callee-saves float registers
  87. fstds,ma %fr13,8(%sp)
  88. fstds,ma %fr14,8(%sp)
  89. fstds,ma %fr15,8(%sp)
  90. fstds,ma %fr16,8(%sp)
  91. fstds,ma %fr17,8(%sp)
  92. fstds,ma %fr18,8(%sp)
  93. fstds,ma %fr19,8(%sp)
  94. fstds,ma %fr20,8(%sp)
  95. fstds,ma %fr21,8(%sp)
  96. .CALL
  97. bl qt_blocki,%rp
  98. ldo 48(%sp),%sp
  99. ldo -48(%sp),%sp
  100. fldds,mb -8(%sp),%fr21 ; restore callee-saves float registers
  101. fldds,mb -8(%sp),%fr20
  102. fldds,mb -8(%sp),%fr19
  103. fldds,mb -8(%sp),%fr18
  104. fldds,mb -8(%sp),%fr17
  105. fldds,mb -8(%sp),%fr16
  106. fldds,mb -8(%sp),%fr15
  107. fldds,mb -8(%sp),%fr14
  108. fldds,mb -8(%sp),%fr13
  109. ldw -28(%sp),%rp ; restore return-pointer
  110. bv %r0(%rp) ; return to caller.
  111. fldds,mb -8(%sp),%fr12
  112. .EXIT
  113. .PROCEND
  114. qt_start
  115. .PROC
  116. .CALLINFO CALLER, FRAME=0
  117. .ENTRY
  118. copy %r18,%arg0 ; set user arg `pu'.
  119. copy %r17,%arg1 ; ... user function pt.
  120. copy %r16,%arg2 ; ... user function userf.
  121. ; %r22 is a caller-saves register
  122. copy %r15,%r22 ; function to be called by $$dyncall
  123. .CALL ; in=%r22
  124. bl $$dyncall,%mrp ; call `only'.
  125. copy %mrp,%rp
  126. bl,n qt_error,%r0 ; `only' erroniously returned.
  127. .EXIT
  128. .PROCEND
  129. ; Varargs
  130. ;
  131. ; First, call `startup' with the `pt' argument.
  132. ;
  133. ; Next, call the user's function with all arguments.
  134. ; We don't know whether arguments are integers, 32-bit floating-points or
  135. ; even 64-bit floating-points, so we reload all the registers, possibly
  136. ; with garbage arguments. The thread creator provided non-garbage for
  137. ; the arguments that the callee actually uses, so the callee never gets
  138. ; garbage.
  139. ;
  140. ; -48 -44 -40 -36 -32
  141. ; | arg3 | arg2 | arg1 | arg0 |
  142. ; -----------------------------
  143. ; integers: arg3 arg2 arg1 arg0
  144. ; 32-bit fps: farg3 farg2 farg1 farg0
  145. ; 64-bit fps: <---farg3--> <---farg1-->
  146. ;
  147. ; Finally, call `cleanup' with the `pt' argument and with the return value
  148. ; from the user's function. It is an error for `cleanup' to return.
  149. qt_vstart
  150. .PROC
  151. .CALLINFO CALLER, FRAME=0
  152. .ENTRY
  153. ; Because the startup function may damage the fixed arguments
  154. ; on the stack (PA-RISC Procedure Calling Conventions Reference
  155. ; Manual, 2.4 Fixed Arguments Area), we allocate a seperate
  156. ; stack frame for it.
  157. ldo 64(%sp),%sp
  158. ; call: void startup(void *pt)
  159. copy %r15,%arg0 ; `pt' is arg0 to `startup'.
  160. copy %r16,%r22
  161. .CALL
  162. bl $$dyncall,%mrp ; Call `startup'.
  163. copy %mrp,%rp
  164. ldo -64(%sp),%sp
  165. ; call: void *qt_vuserf_t(...)
  166. ldw -36(%sp),%arg0 ; Load args to integer registers.
  167. ldw -40(%sp),%arg1
  168. ldw -44(%sp),%arg2
  169. ldw -48(%sp),%arg3
  170. ; Index of fld[w|d]s only ranges from -16 to 15, so we
  171. ; take r22 to be our new base register.
  172. ldo -32(%sp),%r22
  173. fldws -4(%r22),%farg0 ; Load args to floating-point registers.
  174. fldds -8(%r22),%farg1
  175. fldws -12(%r22),%farg2
  176. fldds -16(%r22),%farg3
  177. copy %r17,%r22
  178. .CALL
  179. bl $$dyncall,%mrp ; Call `userf'.
  180. copy %mrp,%rp
  181. ; call: void cleanup(void *pt, void *vuserf_return)
  182. copy %r15,%arg0 ; `pt' is arg0 to `cleanup'.
  183. copy %ret0,%arg1 ; Return-value is arg1 to `cleanup'.
  184. copy %r18,%r22
  185. .CALL
  186. bl $$dyncall,%mrp ; Call `cleanup'.
  187. copy %mrp,%rp
  188. bl,n qt_error,%r0
  189. .EXIT
  190. .PROCEND