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_VAX_H 15#define QUICKTHREADS_VAX_H 16 17typedef unsigned long qt_word_t; 18 19/* Thread's initial stack layout on the VAX: 20 21 non-varargs: 22 23 +--- 24 | arg[2] === `userf' on startup 25 | arg[1] === `pt' on startup 26 | arg[0] === `pu' on startup 27 | ... === `only' on startup. 28 +--- 29 | ret pc === `qt_start' on startup 30 | fp === 0 on startup 31 | ap === 0 on startup 32 | <mask> 33 | 0 (handler) <--- qt_t.sp 34 +--- 35 36 When a non-varargs thread is started, it ``returns'' to the start 37 routine, which calls the client's `only' function. 38 39 The varargs case is clearly bad code. The various values should be 40 stored in a save area and snarfed in to callee-save registers on 41 startup. However, it's too painful to figure out the register 42 mask (right now), so do it the slow way. 43 44 +--- 45 | arg[n-1] 46 | .. 47 | arg[0] 48 | nargs 49 +--- 50 | === `cleanup' 51 | === `vuserf' 52 | === `startup' 53 | === `pt' 54 +--- 55 | ret pc === `qt_start' on startup 56 | fp === 0 on startup 57 | ap === 0 on startup 58 | <mask> 59 | 0 (handler) <--- qt_t.sp 60 +--- 61 62 When a varargs thread is started, it ``returns'' to the `qt_vstart' 63 startup code. The startup code pops all the extra arguments, then 64 calls the appropriate functions. */ 65 66 67/* What to do to start a thread running. */ 68extern void qt_start (void); 69extern void qt_vstart (void); 70 71 72/* Initial call frame for non-varargs and varargs cases. */ 73#define QUICKTHREADS_STKBASE (10 * 4) 74#define QUICKTHREADS_VSTKBASE (9 * 4) 75 76 77/* Stack "must be" 4-byte aligned. (Actually, no, but it's 78 easiest and probably fastest to do so.) */ 79 80#define QUICKTHREADS_STKALIGN (4) 81 82 83/* Where to place various arguments. */ 84#define QUICKTHREADS_ONLY_INDEX (5) 85#define QUICKTHREADS_USER_INDEX (8) 86#define QUICKTHREADS_ARGT_INDEX (7) 87#define QUICKTHREADS_ARGU_INDEX (6) 88 89#define QUICKTHREADS_VSTARTUP_INDEX (6) 90#define QUICKTHREADS_VUSERF_INDEX (7) 91#define QUICKTHREADS_VCLEANUP_INDEX (8) 92#define QUICKTHREADS_VARGT_INDEX (5) 93 94 95/* Stack grows down. The top of the stack is the first thing to 96 pop off (predecrement, postincrement). */ 97#define QUICKTHREADS_GROW_DOWN 98 99 100extern void qt_error (void); 101 102#define QUICKTHREADS_VAX_GMASK_NOREGS (0) 103 104/* Push on the error return address, null termination to call chains, 105 number of arguments to `only', register save mask (save no 106 registers). */ 107 108#define QUICKTHREADS_ARGS_MD(sto) \ 109 (QUICKTHREADS_SPUT (sto, 0, 0), \ 110 QUICKTHREADS_SPUT (sto, 1, QUICKTHREADS_VAX_GMASK_NOREGS), \ 111 QUICKTHREADS_SPUT (sto, 2, 0), \ 112 QUICKTHREADS_SPUT (sto, 3, 0), \ 113 QUICKTHREADS_SPUT (sto, 4, qt_start)) 114 115#define QUICKTHREADS_VARGS_MD0(sto, nbytes) \ 116 (QUICKTHREADS_SPUT (sto, (-(nbytes)/4)-1, (nbytes)/4), \ 117 ((char *)(((sto)-4) - QUICKTHREADS_STKROUNDUP(nbytes)))) 118 119#define QUICKTHREADS_VARGS_ADJUST(sp) ((char *)sp + 4) 120 121#define QUICKTHREADS_VARGS_MD1(sto) \ 122 (QUICKTHREADS_SPUT (sto, 0, 0), \ 123 QUICKTHREADS_SPUT (sto, 1, QUICKTHREADS_VAX_GMASK_NOREGS), \ 124 QUICKTHREADS_SPUT (sto, 2, 0), \ 125 QUICKTHREADS_SPUT (sto, 3, 0), \ 126 QUICKTHREADS_SPUT (sto, 4, qt_vstart)) 127 128#define QUICKTHREADS_VARGS_DEFAULT 129 130#endif /* QUICKTHREADS_VAX_H */ 131