| /* |
| * QuickThreads -- Threads-building toolkit. |
| * Copyright (c) 1993 by David Keppel |
| * |
| * Permission to use, copy, modify and distribute this software and |
| * its documentation for any purpose and without fee is hereby |
| * granted, provided that the above copyright notice and this notice |
| * appear in all copies. This software is provided as a |
| * proof-of-concept and for demonstration purposes; there is no |
| * representation about the suitability of this software for any |
| * purpose. |
| */ |
| |
| #ifndef QUICKTHREADS_M88K_H |
| #define QUICKTHREADS_M88K_H |
| |
| typedef unsigned long qt_word_t; |
| |
| #define QUICKTHREADS_GROW_DOWN |
| |
| /* Stack layout on the mips: |
| |
| Callee-save registers are: $16-$23, $30; $f20-$f30. |
| Also save $31, return pc. |
| |
| Non-varargs: |
| |
| +--- |
| | r30 (fp) on startup === 0 |
| | r25 |
| | r24 |
| | r23 |
| | r22 |
| | r21 |
| | r20 |
| | r19 |
| | r18 |
| | r17 on startup === `only' |
| | r16 on startup === `userf' |
| | r15 on startup === `pt' |
| | r14 on startup === `pu' |
| | r1 on startup === `qt_start' |
| | 0 |
| | 0 |
| +--- |
| | 0 |
| | ... (8 regs worth === 32 bytes of homing area) |
| | 0 <--- sp |
| +--- |
| |
| Conventions for varargs: |
| |
| | : |
| | arg8 |
| +--- |
| | r30 (fp) arg7 |
| | r25 arg6 |
| | r24 arg5 |
| | r23 arg4 |
| | r22 arg3 |
| | r21 arg2 |
| | r20 arg1 |
| | r19 arg0 |
| | r18 |
| | r17 on startup === `startup' |
| | r16 on startup === `vuserf' |
| | r15 on startup === `pt' |
| | r14 on startup === `cleanup' |
| | r1 on startup === `qt_vstart' |
| | 0 |
| | 0 |
| +--- |
| | 0 |
| | ... (8 regs worth === 32 bytes of homing area) |
| | 0 <--- sp |
| +--- |
| |
| */ |
| |
| |
| /* Stack must be doubleword aligned. */ |
| #define QUICKTHREADS_STKALIGN (16) /* Doubleword aligned. */ |
| |
| /* How much space is allocated to hold all the crud for |
| initialization: saved registers plus padding to keep the stack |
| aligned plus 8 words of padding to use as a `homing area' (for |
| r2-r9) when calling helper functions on the stack of the (not yet |
| started) thread. The varargs save area is small because it gets |
| overlapped with the top of the parameter list. In case the |
| parameter list is less than 8 args, QUICKTHREADS_ARGS_MD0 adds some dead |
| space at the top of the stack. */ |
| |
| #define QUICKTHREADS_STKBASE (16*4 + 8*4) |
| #define QUICKTHREADS_VSTKBASE (8*4 + 8*4) |
| |
| |
| /* Index of various registers. */ |
| #define QUICKTHREADS_1 (8+2) |
| #define QUICKTHREADS_14 (8+3) |
| #define QUICKTHREADS_15 (8+4) |
| #define QUICKTHREADS_16 (8+5) |
| #define QUICKTHREADS_17 (8+6) |
| #define QUICKTHREADS_30 (8+15) |
| |
| |
| /* When a never-before-run thread is restored, the return pc points |
| to a fragment of code that starts the thread running. For |
| non-vargs functions, it sets up arguments and calls the client's |
| `only' function. For varargs functions, the startup code calls the |
| startup, user, and cleanup functions. |
| |
| For non-varargs functions, we set the frame pointer to 0 to |
| null-terminate the call chain. |
| |
| For varargs functions, the frame pointer register is used to hold |
| one of the arguments, so that all arguments can be laid out in |
| memory by the conventional `qt_vargs' varargs initialization |
| routine. |
| |
| The varargs startup routine always reads 8 words of arguments from |
| the stack. If there are less than 8 words of arguments, then the |
| arg list could call off the top of the stack. To prevent fall-off, |
| always allocate 8 words. */ |
| |
| extern void qt_start(void); |
| #define QUICKTHREADS_ARGS_MD(sp) \ |
| (QUICKTHREADS_SPUT (sp, QUICKTHREADS_1, qt_start), \ |
| QUICKTHREADS_SPUT (sp, QUICKTHREADS_30, 0)) |
| |
| |
| /* The m88k uses a struct for `va_list', so pass a pointer to the |
| struct. */ |
| |
| typedef void (qt_function_t)(void); |
| |
| struct qt_t; |
| extern struct qt_t *qt_vargs (struct qt_t *sp, int nbytes, |
| void *vargs, void *pt, |
| qt_function_t *startup, |
| qt_function_t *vuserf, |
| qt_function_t *cleanup); |
| |
| #define QUICKTHREADS_VARGS(sp, nbytes, vargs, pt, startup, vuserf, cleanup) \ |
| (qt_vargs (sp, nbytes, &(vargs), pt, (qt_function_t *)startup, \ |
| (qt_function_t *)vuserf, (qt_function_t *)cleanup)) |
| |
| |
| /* The *index* (positive offset) of where to put each value. */ |
| #define QUICKTHREADS_ONLY_INDEX (QUICKTHREADS_17) |
| #define QUICKTHREADS_USER_INDEX (QUICKTHREADS_16) |
| #define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_15) |
| #define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_14) |
| |
| #define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_14) |
| #define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_16) |
| #define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_17) |
| #define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_15) |
| |
| #endif /* ndef QUICKTHREADS_M88K_H */ |