mips.s 5.0 KB

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