i386.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /*
  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. */
  13. #ifndef QT_386_H
  14. #define QT_386_H
  15. typedef unsigned long qt_word_t;
  16. /* Thread's initial stack layout on the i386:
  17. non-varargs:
  18. +---
  19. | arg[2] === `userf' on startup
  20. | arg[1] === `pt' on startup
  21. | arg[0] === `pu' on startup
  22. +---
  23. | ret pc === qt_error
  24. +---
  25. | ret pc === `only' on startup
  26. +---
  27. | %ebp
  28. | %esi
  29. | %edi
  30. | %ebx <--- qt_t.sp
  31. +---
  32. When a non-varargs thread is started, it ``returns'' directly to
  33. the client's `only' function.
  34. varargs:
  35. +---
  36. | arg[n-1]
  37. | ..
  38. | arg[0]
  39. +---
  40. | ret pc === `qt_vstart'
  41. +---
  42. | %ebp === `startup'
  43. | %esi === `cleanup'
  44. | %edi === `pt'
  45. | %ebx === `vuserf' <--- qt_t.sp
  46. +---
  47. When a varargs thread is started, it ``returns'' to the `qt_vstart'
  48. startup code. The startup code calls the appropriate functions. */
  49. /* What to do to start a varargs thread running. */
  50. extern void qt_vstart (void);
  51. /* Hold 4 saved regs plus two return pcs (qt_error, qt_start) plus
  52. three args. */
  53. #define QT_STKBASE (9 * 4)
  54. /* Hold 4 saved regs plus one return pc (qt_vstart). */
  55. #define QT_VSTKBASE (5 * 4)
  56. /* Stack must be 4-byte aligned. */
  57. #define QT_STKALIGN (4)
  58. /* Where to place various arguments. */
  59. #define QT_ONLY_INDEX (QT_PC)
  60. #define QT_USER_INDEX (QT_ARG2)
  61. #define QT_ARGT_INDEX (QT_ARG1)
  62. #define QT_ARGU_INDEX (QT_ARG0)
  63. #define QT_VSTARTUP_INDEX (QT_EBP)
  64. #define QT_VUSERF_INDEX (QT_EBX)
  65. #define QT_VCLEANUP_INDEX (QT_ESI)
  66. #define QT_VARGT_INDEX (QT_EDI)
  67. #define QT_EBX 0
  68. #define QT_EDI 1
  69. #define QT_ESI 2
  70. #define QT_EBP 3
  71. #define QT_PC 4
  72. /* The following are defined only for non-varargs. */
  73. #define QT_RPC 5
  74. #define QT_ARG0 6
  75. #define QT_ARG1 7
  76. #define QT_ARG2 8
  77. /* Stack grows down. The top of the stack is the first thing to
  78. pop off (preincrement, postdecrement). */
  79. #define QT_GROW_DOWN
  80. extern void qt_error (void);
  81. /* Push on the error return address. */
  82. #define QT_ARGS_MD(sto) \
  83. (QT_SPUT (sto, QT_RPC, qt_error))
  84. /* When varargs are pushed, allocate space for all the args. */
  85. #define QT_VARGS_MD0(sto, nbytes) \
  86. ((qt_t *)(((char *)(sto)) - QT_STKROUNDUP(nbytes)))
  87. #define QT_VARGS_MD1(sto) \
  88. (QT_SPUT (sto, QT_PC, qt_vstart))
  89. #define QT_VARGS_DEFAULT
  90. #endif /* QT_386_H */