i386.s 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /* i386.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. /* NOTE: double-labeled `_name' and `name' for System V compatability. */
  14. /* NOTE: Comment lines start like this one, or with '//' ONLY. Sorry! */
  15. /* Callee-save: %esi, %edi, %ebx, %ebp
  16. // Caller-save: %eax, %ecx
  17. // Can't tell: %edx (seems to work w/o saving it.)
  18. //
  19. // Assignment:
  20. //
  21. // See ``i386.h'' for the somewhat unconventional stack layout. */
  22. .text
  23. .align 2
  24. .globl _qt_abort
  25. .globl qt_abort
  26. .globl _qt_block
  27. .globl qt_block
  28. .globl _qt_blocki
  29. .globl qt_blocki
  30. /* These all have the type signature
  31. //
  32. // void *blocking (helper, arg0, arg1, new)
  33. //
  34. // On procedure entry, the helper is at 4(sp), args at 8(sp) and
  35. // 12(sp) and the new thread's sp at 16(sp). It *appears* that the
  36. // calling convention for the 8X86 requires the caller to save all
  37. // floating-point registers, this makes our life easy. */
  38. /* Halt the currently-running thread. Save it's callee-save regs on
  39. // to the stack, 32 bytes. Switch to the new stack (next == 16+32(sp))
  40. // and call the user function (f == 4+32(sp) with arguments: old sp
  41. // arg1 (8+32(sp)) and arg2 (12+32(sp)). When the user function is
  42. // done, restore the new thread's state and return.
  43. //
  44. // `qt_abort' is (currently) an alias for `qt_block' because most of
  45. // the work is shared. We could save the insns up to `qt_common' by
  46. // replicating, but w/o replicating we need an inital subtract (to
  47. // offset the stack as if it had been a qt_block) and then a jump
  48. // to qt_common. For the cost of a jump, we might as well just do
  49. // all the work.
  50. //
  51. // The helper function (4(sp)) can return a void* that is returned
  52. // by the call to `qt_blockk{,i}'. Since we don't touch %eax in
  53. // between, we get that ``for free''. */
  54. _qt_abort:
  55. qt_abort:
  56. _qt_block:
  57. qt_block:
  58. _qt_blocki:
  59. qt_blocki:
  60. pushl %ebp /* Save callee-save, sp-=4. */
  61. pushl %esi /* Save callee-save, sp-=4. */
  62. pushl %edi /* Save callee-save, sp-=4. */
  63. pushl %ebx /* Save callee-save, sp-=4. */
  64. movl %esp, %eax /* Remember old stack pointer. */
  65. qt_common:
  66. movl 32(%esp), %esp /* Move to new thread. */
  67. pushl 28(%eax) /* Push arg 2. */
  68. pushl 24(%eax) /* Push arg 1. */
  69. pushl %eax /* Push arg 0. */
  70. movl 20(%eax), %ebx /* Get function to call. */
  71. call *%ebx /* Call f. */
  72. addl $12, %esp /* Pop args. */
  73. popl %ebx /* Restore callee-save, sp+=4. */
  74. popl %edi /* Restore callee-save, sp+=4. */
  75. popl %esi /* Restore callee-save, sp+=4. */
  76. popl %ebp /* Restore callee-save, sp+=4. */
  77. ret /* Resume the stopped function. */
  78. hlt
  79. /* Start a varargs thread. */
  80. .globl _qt_vstart
  81. .globl qt_vstart
  82. _qt_vstart:
  83. qt_vstart:
  84. pushl %edi /* Push `pt' arg to `startup'. */
  85. call *%ebp /* Call `startup'. */
  86. popl %eax /* Clean up the stack. */
  87. call *%ebx /* Call the user's function. */
  88. pushl %eax /* Push return from user's. */
  89. pushl %edi /* Push `pt' arg to `cleanup'. */
  90. call *%esi /* Call `cleanup'. */
  91. hlt /* `cleanup' never returns. */