| /* | |
| * 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_MIPS_H | |
| #define QUICKTHREADS_MIPS_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: | |
| +--- | |
| | $f30 The first clump is only saved if `qt_block' | |
| | $f28 is called, in which case it saves the fp regs | |
| | $f26 then calls `qt_blocki' to save the int regs. | |
| | $f24 | |
| | $f22 | |
| | $f20 | |
| | $31 === return pc in `qt_block' | |
| +--- | |
| | $31 === return pc; on startup == qt_start | |
| | $30 | |
| | $23 | |
| | $22 | |
| | $21 | |
| | $20 | |
| | $19 on startup === only | |
| | $18 on startup === $a2 === userf | |
| | $17 on startup === $a1 === pt | |
| | $16 on startup === $a0 === pu | |
| | <a3> save area req'd by MIPS calling convention | |
| | <a2> save area req'd by MIPS calling convention | |
| | <a1> save area req'd by MIPS calling convention | |
| | <a0> save area req'd by MIPS calling convention <--- sp | |
| +--- | |
| Conventions for varargs: | |
| | args ... | |
| +--- | |
| | : | |
| | : | |
| | $21 | |
| | $20 | |
| | $19 on startup === `userf' | |
| | $18 on startup === `startup' | |
| | $17 on startup === `pt' | |
| | $16 on startup === `cleanup' | |
| | <a3> | |
| | <a2> | |
| | <a1> | |
| | <a0> <--- sp | |
| +--- | |
| Note: if we wanted to, we could muck about and try to get the 4 | |
| argument registers loaded in to, e.g., $22, $23, $30, and $31, | |
| and the return pc in, say, $20. Then, the first 4 args would | |
| not need to be loaded from memory, they could just use | |
| register-to-register copies. */ | |
| /* Stack must be doubleword aligned. */ | |
| #define QUICKTHREADS_STKALIGN (8) /* Doubleword aligned. */ | |
| /* How much space is allocated to hold all the crud for | |
| initialization: $16-$23, $30, $31. Just do an integer restore, | |
| no need to restore floating-point. Four words are needed for the | |
| argument save area for the helper function that will be called for | |
| the old thread, just before the new thread starts to run. */ | |
| #define QUICKTHREADS_STKBASE (14 * 4) | |
| #define QUICKTHREADS_VSTKBASE QUICKTHREADS_STKBASE | |
| /* Offsets of various registers. */ | |
| #define QUICKTHREADS_31 (9+4) | |
| #define QUICKTHREADS_19 (3+4) | |
| #define QUICKTHREADS_18 (2+4) | |
| #define QUICKTHREADS_17 (1+4) | |
| #define QUICKTHREADS_16 (0+4) | |
| /* 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 just calls the client's `only' function. | |
| For varargs functions, it calls the startup, user, and cleanup | |
| functions. | |
| The varargs startup routine always reads 4 words of arguments from | |
| the stack. If there are less than 4 words of arguments, then the | |
| startup routine can read off the top of the stack. To prevent | |
| errors we always allocate 4 words. If there are more than 3 words | |
| of arguments, the 4 preallocated words are simply wasted. */ | |
| extern void qt_start(void); | |
| #define QUICKTHREADS_ARGS_MD(sp) (QUICKTHREADS_SPUT (sp, QUICKTHREADS_31, qt_start)) | |
| #define QUICKTHREADS_VARGS_MD0(sp, vabytes) \ | |
| ((qt_t *)(((char *)(sp)) - 4*4 - QUICKTHREADS_STKROUNDUP(vabytes))) | |
| extern void qt_vstart(void); | |
| #define QUICKTHREADS_VARGS_MD1(sp) (QUICKTHREADS_SPUT (sp, QUICKTHREADS_31, qt_vstart)) | |
| #define QUICKTHREADS_VARGS_DEFAULT | |
| /* The *index* (positive offset) of where to put each value. */ | |
| #define QUICKTHREADS_ONLY_INDEX (QUICKTHREADS_19) | |
| #define QUICKTHREADS_USER_INDEX (QUICKTHREADS_18) | |
| #define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_17) | |
| #define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_16) | |
| #define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_16) | |
| #define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_19) | |
| #define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_18) | |
| #define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_17) | |
| #endif /* ndef QUICKTHREADS_MIPS_H */ |