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