m88k.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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_M88K_H
  14. #define QT_M88K_H
  15. typedef unsigned long qt_word_t;
  16. #define QT_GROW_DOWN
  17. /* Stack layout on the mips:
  18. Callee-save registers are: $16-$23, $30; $f20-$f30.
  19. Also save $31, return pc.
  20. Non-varargs:
  21. +---
  22. | r30 (fp) on startup === 0
  23. | r25
  24. | r24
  25. | r23
  26. | r22
  27. | r21
  28. | r20
  29. | r19
  30. | r18
  31. | r17 on startup === `only'
  32. | r16 on startup === `userf'
  33. | r15 on startup === `pt'
  34. | r14 on startup === `pu'
  35. | r1 on startup === `qt_start'
  36. | 0
  37. | 0
  38. +---
  39. | 0
  40. | ... (8 regs worth === 32 bytes of homing area)
  41. | 0 <--- sp
  42. +---
  43. Conventions for varargs:
  44. | :
  45. | arg8
  46. +---
  47. | r30 (fp) arg7
  48. | r25 arg6
  49. | r24 arg5
  50. | r23 arg4
  51. | r22 arg3
  52. | r21 arg2
  53. | r20 arg1
  54. | r19 arg0
  55. | r18
  56. | r17 on startup === `startup'
  57. | r16 on startup === `vuserf'
  58. | r15 on startup === `pt'
  59. | r14 on startup === `cleanup'
  60. | r1 on startup === `qt_vstart'
  61. | 0
  62. | 0
  63. +---
  64. | 0
  65. | ... (8 regs worth === 32 bytes of homing area)
  66. | 0 <--- sp
  67. +---
  68. */
  69. /* Stack must be doubleword aligned. */
  70. #define QT_STKALIGN (16) /* Doubleword aligned. */
  71. /* How much space is allocated to hold all the crud for
  72. initialization: saved registers plus padding to keep the stack
  73. aligned plus 8 words of padding to use as a `homing area' (for
  74. r2-r9) when calling helper functions on the stack of the (not yet
  75. started) thread. The varargs save area is small because it gets
  76. overlapped with the top of the parameter list. In case the
  77. parameter list is less than 8 args, QT_ARGS_MD0 adds some dead
  78. space at the top of the stack. */
  79. #define QT_STKBASE (16*4 + 8*4)
  80. #define QT_VSTKBASE (8*4 + 8*4)
  81. /* Index of various registers. */
  82. #define QT_1 (8+2)
  83. #define QT_14 (8+3)
  84. #define QT_15 (8+4)
  85. #define QT_16 (8+5)
  86. #define QT_17 (8+6)
  87. #define QT_30 (8+15)
  88. /* When a never-before-run thread is restored, the return pc points
  89. to a fragment of code that starts the thread running. For
  90. non-vargs functions, it sets up arguments and calls the client's
  91. `only' function. For varargs functions, the startup code calls the
  92. startup, user, and cleanup functions.
  93. For non-varargs functions, we set the frame pointer to 0 to
  94. null-terminate the call chain.
  95. For varargs functions, the frame pointer register is used to hold
  96. one of the arguments, so that all arguments can be laid out in
  97. memory by the conventional `qt_vargs' varargs initialization
  98. routine.
  99. The varargs startup routine always reads 8 words of arguments from
  100. the stack. If there are less than 8 words of arguments, then the
  101. arg list could call off the top of the stack. To prevent fall-off,
  102. always allocate 8 words. */
  103. extern void qt_start(void);
  104. #define QT_ARGS_MD(sp) \
  105. (QT_SPUT (sp, QT_1, qt_start), \
  106. QT_SPUT (sp, QT_30, 0))
  107. /* The m88k uses a struct for `va_list', so pass a pointer to the
  108. struct. */
  109. typedef void (qt_function_t)(void);
  110. struct qt_t;
  111. extern struct qt_t *qt_vargs (struct qt_t *sp, int nbytes,
  112. void *vargs, void *pt,
  113. qt_function_t *startup,
  114. qt_function_t *vuserf,
  115. qt_function_t *cleanup);
  116. #define QT_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \
  117. (qt_vargs (sp, nbytes, &(vargs), pt, (qt_function_t *)startup, \
  118. (qt_function_t *)vuserf, (qt_function_t *)cleanup))
  119. /* The *index* (positive offset) of where to put each value. */
  120. #define QT_ONLY_INDEX (QT_17)
  121. #define QT_USER_INDEX (QT_16)
  122. #define QT_ARGT_INDEX (QT_15)
  123. #define QT_ARGU_INDEX (QT_14)
  124. #define QT_VCLEANUP_INDEX (QT_14)
  125. #define QT_VUSERF_INDEX (QT_16)
  126. #define QT_VSTARTUP_INDEX (QT_17)
  127. #define QT_VARGT_INDEX (QT_15)
  128. #endif /* ndef QT_M88K_H */