|  | /* | 
|  | * 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 */ |