mips-irix5.s 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /* mips.s -- assembly support. */
  2. /*
  3. * QuickThreads -- Threads-building toolkit.
  4. * Copyright (c) 1993 by David Keppel
  5. *
  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
  12. * purpose.
  13. */
  14. /* Callee-save $16-$23, $30-$31.
  15. *
  16. * $25 is used as a procedure value pointer, used to discover constants
  17. * in a callee. Thus, each caller here sets $25 before the call.
  18. *
  19. * On startup, restore regs so retpc === call to a function to start.
  20. * We're going to call a function ($4) from within this routine.
  21. * We're passing 3 args, therefore need to allocate 12 extra bytes on
  22. * the stack for a save area. The start routine needs a like 16-byte
  23. * save area. Must be doubleword aligned (_mips r3000 risc
  24. * architecture_, gerry kane, pg d-23).
  25. */
  26. /*
  27. * Modified by Assar Westerlund <assar@sics.se> to support Irix 5.x
  28. * calling conventions for dynamically-linked code.
  29. */
  30. /* Make this position-independent code. */
  31. .option pic2
  32. .globl qt_block
  33. .globl qt_blocki
  34. .globl qt_abort
  35. .globl qt_start
  36. .globl qt_vstart
  37. /*
  38. ** $4: ptr to function to call once curr is suspended
  39. ** and control is on $7's stack.
  40. ** $5: 1'th arg to $4.
  41. ** $6: 2'th arg to $4
  42. ** $7: sp of thread to suspend.
  43. **
  44. ** Totally gross hack: The MIPS calling convention reserves
  45. ** 4 words on the stack for a0..a3. This routine "ought" to
  46. ** allocate space for callee-save registers plus 4 words for
  47. ** the helper function, but instead we use the 4 words
  48. ** provided by the function that called us (we don't need to
  49. ** save our argument registers). So what *appears* to be
  50. ** allocating only 40 bytes is actually allocating 56, by
  51. ** using the caller's 16 bytes.
  52. **
  53. ** The helper routine returns a value that is passed on as the
  54. ** return value from the blocking routine. Since we don't
  55. ** touch $2 between the helper's return and the end of
  56. ** function, we get this behavior for free.
  57. */
  58. qt_blocki:
  59. sub $sp,$sp,40 /* Allocate reg save space. */
  60. sw $16, 0+16($sp)
  61. sw $17, 4+16($sp)
  62. sw $18, 8+16($sp)
  63. sw $19,12+16($sp)
  64. sw $20,16+16($sp)
  65. sw $21,20+16($sp)
  66. sw $22,24+16($sp)
  67. sw $23,28+16($sp)
  68. sw $30,32+16($sp)
  69. sw $31,36+16($sp)
  70. add $2, $sp,$0 /* $2 <= old sp to pass to func@$4. */
  71. qt_abort:
  72. add $sp, $7,$0 /* $sp <= new sp. */
  73. .set noreorder
  74. add $25, $4,$0 /* Set helper function procedure value. */
  75. jal $31,$25 /* Call helper func@$4 . */
  76. add $4, $2,$0 /* $a0 <= pass old sp as a parameter. */
  77. .set reorder
  78. lw $31,36+16($sp) /* Restore callee-save regs... */
  79. lw $30,32+16($sp)
  80. lw $23,28+16($sp)
  81. lw $22,24+16($sp)
  82. lw $21,20+16($sp)
  83. lw $20,16+16($sp)
  84. lw $19,12+16($sp)
  85. lw $18, 8+16($sp)
  86. lw $17, 4+16($sp)
  87. lw $16, 0+16($sp) /* Restore callee-save */
  88. add $sp,$sp,40 /* Deallocate reg save space. */
  89. j $31 /* Return to caller. */
  90. /*
  91. ** Non-varargs thread startup.
  92. ** Note: originally, 56 bytes were allocated on the stack.
  93. ** The thread restore routine (_blocki/_abort) removed 40
  94. ** of them, which means there is still 16 bytes for the
  95. ** argument area required by the MIPS calling convention.
  96. */
  97. qt_start:
  98. add $4, $16,$0 /* Load up user function pu. */
  99. add $5, $17,$0 /* ... user function pt. */
  100. add $6, $18,$0 /* ... user function userf. */
  101. add $25, $19,$0 /* Set `only' procedure value. */
  102. jal $31,$25 /* Call `only'. */
  103. la $25,qt_error /* Set `qt_error' procedure value. */
  104. j $25
  105. /*
  106. ** Save calle-save floating-point regs $f20-$f30
  107. ** See comment in `qt_block' about calling conventinos and
  108. ** reserved space. Use the same trick here, but here we
  109. ** actually have to allocate all the bytes since we have to
  110. ** leave 4 words leftover for `qt_blocki'.
  111. **
  112. ** Return value from `qt_block' is the same as the return from
  113. ** `qt_blocki'. We get that for free since we don't touch $2
  114. ** between the return from `qt_blocki' and the return from
  115. ** `qt_block'.
  116. */
  117. qt_block:
  118. sub $sp, $sp,56 /* 6 8-byte regs, saved ret pc, aligned. */
  119. swc1 $f20, 0+16($sp)
  120. swc1 $f22, 8+16($sp)
  121. swc1 $f24, 16+16($sp)
  122. swc1 $f26, 24+16($sp)
  123. swc1 $f28, 32+16($sp)
  124. swc1 $f30, 40+16($sp)
  125. sw $31, 48+16($sp)
  126. jal qt_blocki
  127. lwc1 $f20, 0+16($sp)
  128. lwc1 $f22, 8+16($sp)
  129. lwc1 $f24, 16+16($sp)
  130. lwc1 $f26, 24+16($sp)
  131. lwc1 $f28, 32+16($sp)
  132. lwc1 $f30, 40+16($sp)
  133. lw $31, 48+16($sp)
  134. add $sp, $sp,56
  135. j $31
  136. /*
  137. ** First, call `startup' with the `pt' argument.
  138. **
  139. ** Next, call the user's function with all arguments.
  140. ** Note that we don't know whether args were passed in
  141. ** integer regs, fp regs, or on the stack (See Gerry Kane
  142. ** "MIPS R2000 RISC Architecture" pg D-22), so we reload
  143. ** all the registers, possibly with garbage arguments.
  144. **
  145. ** Finally, call `cleanup' with the `pt' argument and with
  146. ** the return value from the user's function. It is an error
  147. ** for `cleanup' to return.
  148. */
  149. qt_vstart:
  150. add $4, $17,$0 /* `pt' is arg0 to `startup'. */
  151. add $25, $18,$0 /* Set `startup' procedure value. */
  152. jal $31, $25 /* Call `startup'. */
  153. add $sp, $sp,16 /* Free extra save space. */
  154. lw $4, 0($sp) /* Load up args. */
  155. lw $5, 4($sp)
  156. lw $6, 8($sp)
  157. lw $7, 12($sp)
  158. lwc1 $f12, 0($sp) /* Load up fp args. */
  159. lwc1 $f14, 8($sp)
  160. add $25, $19,$0 /* Set `userf' procedure value. */
  161. jal $31,$25 /* Call `userf'. */
  162. add $4, $17,$0 /* `pt' is arg0 to `cleanup'. */
  163. add $5, $2,$0 /* Ret. val is arg1 to `cleanup'. */
  164. add $25, $16,$0 /* Set `cleanup' procedure value. */
  165. jal $31, $25 /* Call `cleanup'. */
  166. la $25,qt_error /* Set `qt_error' procedure value. */
  167. j $25