vax.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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_VAX_H
  14. #define QT_VAX_H
  15. typedef unsigned long qt_word_t;
  16. /* Thread's initial stack layout on the VAX:
  17. non-varargs:
  18. +---
  19. | arg[2] === `userf' on startup
  20. | arg[1] === `pt' on startup
  21. | arg[0] === `pu' on startup
  22. | ... === `only' on startup.
  23. +---
  24. | ret pc === `qt_start' on startup
  25. | fp === 0 on startup
  26. | ap === 0 on startup
  27. | <mask>
  28. | 0 (handler) <--- qt_t.sp
  29. +---
  30. When a non-varargs thread is started, it ``returns'' to the start
  31. routine, which calls the client's `only' function.
  32. The varargs case is clearly bad code. The various values should be
  33. stored in a save area and snarfed in to callee-save registers on
  34. startup. However, it's too painful to figure out the register
  35. mask (right now), so do it the slow way.
  36. +---
  37. | arg[n-1]
  38. | ..
  39. | arg[0]
  40. | nargs
  41. +---
  42. | === `cleanup'
  43. | === `vuserf'
  44. | === `startup'
  45. | === `pt'
  46. +---
  47. | ret pc === `qt_start' on startup
  48. | fp === 0 on startup
  49. | ap === 0 on startup
  50. | <mask>
  51. | 0 (handler) <--- qt_t.sp
  52. +---
  53. When a varargs thread is started, it ``returns'' to the `qt_vstart'
  54. startup code. The startup code pops all the extra arguments, then
  55. calls the appropriate functions. */
  56. /* What to do to start a thread running. */
  57. extern void qt_start (void);
  58. extern void qt_vstart (void);
  59. /* Initial call frame for non-varargs and varargs cases. */
  60. #define QT_STKBASE (10 * 4)
  61. #define QT_VSTKBASE (9 * 4)
  62. /* Stack "must be" 4-byte aligned. (Actually, no, but it's
  63. easiest and probably fastest to do so.) */
  64. #define QT_STKALIGN (4)
  65. /* Where to place various arguments. */
  66. #define QT_ONLY_INDEX (5)
  67. #define QT_USER_INDEX (8)
  68. #define QT_ARGT_INDEX (7)
  69. #define QT_ARGU_INDEX (6)
  70. #define QT_VSTARTUP_INDEX (6)
  71. #define QT_VUSERF_INDEX (7)
  72. #define QT_VCLEANUP_INDEX (8)
  73. #define QT_VARGT_INDEX (5)
  74. /* Stack grows down. The top of the stack is the first thing to
  75. pop off (predecrement, postincrement). */
  76. #define QT_GROW_DOWN
  77. extern void qt_error (void);
  78. #define QT_VAX_GMASK_NOREGS (0)
  79. /* Push on the error return address, null termination to call chains,
  80. number of arguments to `only', register save mask (save no
  81. registers). */
  82. #define QT_ARGS_MD(sto) \
  83. (QT_SPUT (sto, 0, 0), \
  84. QT_SPUT (sto, 1, QT_VAX_GMASK_NOREGS), \
  85. QT_SPUT (sto, 2, 0), \
  86. QT_SPUT (sto, 3, 0), \
  87. QT_SPUT (sto, 4, qt_start))
  88. #define QT_VARGS_MD0(sto, nbytes) \
  89. (QT_SPUT (sto, (-(nbytes)/4)-1, (nbytes)/4), \
  90. ((char *)(((sto)-4) - QT_STKROUNDUP(nbytes))))
  91. #define QT_VARGS_ADJUST(sp) ((char *)sp + 4)
  92. #define QT_VARGS_MD1(sto) \
  93. (QT_SPUT (sto, 0, 0), \
  94. QT_SPUT (sto, 1, QT_VAX_GMASK_NOREGS), \
  95. QT_SPUT (sto, 2, 0), \
  96. QT_SPUT (sto, 3, 0), \
  97. QT_SPUT (sto, 4, qt_vstart))
  98. #define QT_VARGS_DEFAULT
  99. #endif /* QT_VAX_H */