| /* | |
| * 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_AXP_H | |
| #define QUICKTHREADS_AXP_H | |
| #define QUICKTHREADS_GROW_DOWN | |
| typedef unsigned long qt_word_t; | |
| /* Stack layout on the Alpha: | |
| Integer: | |
| Caller-save: r0..r8, r22..r25, r27..r29 | |
| argument/caller-save: r16..r21 | |
| callee-save: r9..r15 | |
| return pc *callee-save*: r26 | |
| stack pointer: r30 | |
| zero: r31 | |
| Floating-point: | |
| Caller-save: f0..f1, f10..f15 | |
| argument/caller-save: f16..f21, f22..f30 | |
| callee-save: f2..f9 | |
| zero: f31 | |
| Non-varargs: | |
| +--- | |
| | padding | |
| | f9 | |
| | f8 | |
| | f7 | |
| | f6 | |
| | f5 | |
| | f4 | |
| | f3 | |
| | f2 | |
| | r26 | |
| +--- | |
| | padding | |
| | r29 | |
| | r15 | |
| | r14 | |
| | r13 | |
| | r12 on startup === `only' | |
| | r11 on startup === `userf' | |
| | r10 on startup === `qt' | |
| | r9 on startup === `qu' | |
| | r26 on startup === qt_start <--- qt.sp | |
| +--- | |
| Conventions for varargs startup: | |
| | : | |
| | arg6 | |
| | iarg5 | |
| | : | |
| | iarg0 | |
| | farg5 | |
| | : | |
| | farg0 | |
| +--- | |
| | padding | |
| | r29 | |
| | r15 | |
| | r14 | |
| | r13 | |
| | r12 on startup === `startup' | |
| | r11 on startup === `vuserf' | |
| | r10 on startup === `cleanup' | |
| | r9 on startup === `qt' | |
| | r26 on startup === qt_vstart <--- qt.sp | |
| +--- | |
| Note: this is a pretty cheap/sleazy way to get things going, | |
| but ``there must be a better way.'' For instance, some varargs | |
| parameters could be loaded in to integer registers, or the return | |
| address could be stored on top of the stack. */ | |
| /* Stack must be 16-byte aligned. */ | |
| #define QUICKTHREADS_STKALIGN (16) | |
| /* How much space is allocated to hold all the crud for | |
| initialization: 7 registers times 8 bytes/register. */ | |
| #define QUICKTHREADS_STKBASE (10 * 8) | |
| #define QUICKTHREADS_VSTKBASE QUICKTHREADS_STKBASE | |
| /* Offsets of various registers. */ | |
| #define QUICKTHREADS_R26 0 | |
| #define QUICKTHREADS_R9 1 | |
| #define QUICKTHREADS_R10 2 | |
| #define QUICKTHREADS_R11 3 | |
| #define QUICKTHREADS_R12 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 12 8-byte arguments from | |
| the stack. If fewer argumets were pushed, the startup routine | |
| would read off the top of the stack. To prevent errors we always | |
| allocate enough space. When there are fewer args, the preallocated | |
| words are simply wasted. */ | |
| extern void qt_start(void); | |
| #define QUICKTHREADS_ARGS_MD(sp) (QUICKTHREADS_SPUT (sp, QUICKTHREADS_R26, qt_start)) | |
| /* The AXP uses a struct for `va_list', so pass a pointer to the | |
| struct. This may break some uses of `QUICKTHREADS_VARGS', but then we never | |
| claimed it was totally portable. */ | |
| typedef void (qt_function_t)(void); | |
| struct qt_t; | |
| struct va_list; | |
| extern struct qt_t *qt_vargs (struct qt_t *sp, int nbytes, | |
| struct va_list *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, (struct va_list *)(&(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_R12) | |
| #define QUICKTHREADS_USER_INDEX (QUICKTHREADS_R11) | |
| #define QUICKTHREADS_ARGT_INDEX (QUICKTHREADS_R10) | |
| #define QUICKTHREADS_ARGU_INDEX (QUICKTHREADS_R9) | |
| #define QUICKTHREADS_VCLEANUP_INDEX (QUICKTHREADS_R10) | |
| #define QUICKTHREADS_VUSERF_INDEX (QUICKTHREADS_R11) | |
| #define QUICKTHREADS_VSTARTUP_INDEX (QUICKTHREADS_R12) | |
| #define QUICKTHREADS_VARGT_INDEX (QUICKTHREADS_R9) | |
| #endif /* ndef QUICKTHREADS_AXP_H */ |