m88k.c revision 12027
14486Sbinkertn@umich.edu/* 24486Sbinkertn@umich.edu * QuickThreads -- Threads-building toolkit. 34486Sbinkertn@umich.edu * Copyright (c) 1993 by David Keppel 44486Sbinkertn@umich.edu * 54486Sbinkertn@umich.edu * Permission to use, copy, modify and distribute this software and 64486Sbinkertn@umich.edu * its documentation for any purpose and without fee is hereby 74486Sbinkertn@umich.edu * granted, provided that the above copyright notice and this notice 84486Sbinkertn@umich.edu * appear in all copies. This software is provided as a 94486Sbinkertn@umich.edu * proof-of-concept and for demonstration purposes; there is no 104486Sbinkertn@umich.edu * representation about the suitability of this software for any 114486Sbinkertn@umich.edu * purpose. 124486Sbinkertn@umich.edu */ 134486Sbinkertn@umich.edu 144486Sbinkertn@umich.edu#include <stdarg.h> 154486Sbinkertn@umich.edu#include "qt.h" 164486Sbinkertn@umich.edu 174486Sbinkertn@umich.edu/* Varargs is harder on the m88k. Parameters are saved on the stack as 184486Sbinkertn@umich.edu something like (stack grows down to low memory; low at bottom of 194486Sbinkertn@umich.edu picture): 204486Sbinkertn@umich.edu 214486Sbinkertn@umich.edu | : 224486Sbinkertn@umich.edu | arg8 <-- va_list.__va_stk 234486Sbinkertn@umich.edu +--- 244486Sbinkertn@umich.edu | : 254486Sbinkertn@umich.edu +--- 264486Sbinkertn@umich.edu | arg7 274486Sbinkertn@umich.edu | : 284486Sbinkertn@umich.edu | iarg0 <-- va_list.__va_reg 293102SN/A +--- 303102SN/A | : 313102SN/A | va_list { __va_arg, __va_stk, __va_reg } 322667SN/A | : 332998SN/A +--- 343584SN/A 352667SN/A Here, `va_list.__va_arg' is the number of word-size arguments 364486Sbinkertn@umich.edu that have already been skipped. Doubles must be double-arligned. 374486Sbinkertn@umich.edu 384486Sbinkertn@umich.edu What this means for us is that the user's routine needs to be 394486Sbinkertn@umich.edu called with an arg list where some of the words in the `__va_stk' 404486Sbinkertn@umich.edu part of the parameter list have to be promoted to registers. 414486Sbinkertn@umich.edu 424486Sbinkertn@umich.edu BUG: doubleword register arguments must be double-aligned. If 431692SN/A something is passed as an even # arg and used as an odd # arg or 441366SN/A vice-versa, the code in the called routine (in the new thread) that 451310SN/A decides how to adjust the index will get it wrong, because it will 461310SN/A be expect it to be, say, doubleword aligned and it will really be 472901SN/A singleword aligned. 483170SN/A 493170SN/A I'm not sure you can solve this without knowing the types of all 501530SN/A the arguments. All in all, we never promised varargs would work 513620SN/A reliably. */ 523617SN/A 533617SN/A 543617SN/A 553617SN/A#define QUICKTHREADS_VADJ(sp) (((char *)sp) - QUICKTHREADS_VSTKBASE) 563617SN/A 573584SN/A/* Always allocate at least enough space for 8 args; waste some space 583584SN/A at the base of the stack to ensure the startup routine doesn't read 593584SN/A off the end of the stack. */ 603584SN/A 613584SN/A#define QUICKTHREADS_VARGS_MD0(sp, vabytes) \ 623584SN/A ((qt_t *)(((char *)(sp)) - 8*4 - QUICKTHREADS_STKROUNDUP(vabytes))) 633584SN/A 643584SN/Aextern void qt_vstart(void); 653584SN/A#define QUICKTHREADS_VARGS_MD1(sp) (QUICKTHREADS_SPUT (sp, QUICKTHREADS_1, qt_vstart)) 661445SN/A 671445SN/A 681310SN/A struct qt_t * 691310SN/Aqt_vargs (struct qt_t *qsp, int nbytes, void *vargs, 701310SN/A void *pt, qt_function_t *startup, 711310SN/A qt_function_t *vuserf, qt_function_t *cleanup) 721310SN/A{ 731310SN/A va_list ap; 741310SN/A int i; 751310SN/A int n; /* Number of words into original arg list. */ 761310SN/A qt_word_t *sp; 773878SN/A int *reg; /* Where to read passed-in-reg args. */ 783878SN/A int *stk; /* Where to read passed-on-stk args. */ 791310SN/A 801369SN/A ap = *(va_list *)vargs; 811310SN/A qsp = QUICKTHREADS_VARGS_MD0 (qsp, nbytes); 821634SN/A sp = (qt_word_t *)qsp; 834167SN/A 844167SN/A reg = (ap.__va_arg < 8) 852998SN/A ? &ap.__va_reg[ap.__va_arg] 862998SN/A : 0; 872998SN/A stk = &ap.__va_stk[8]; 882998SN/A n = ap.__va_arg; 892998SN/A for (i=0; i<nbytes/sizeof(qt_word_t) && n<8; ++i,++n) { 902998SN/A sp[i] = *reg++; 912998SN/A } 922998SN/A for (; i<nbytes/sizeof(qt_word_t); ++i) { 932998SN/A sp[i] = *stk++; 942998SN/A } 952998SN/A 962998SN/A#ifdef QUICKTHREADS_NDEF 972998SN/A for (i=0; i<nbytes/sizeof(qt_word_t); ++i) { 982998SN/A sp[i] = (n < 8) 992998SN/A ? *reg++ 1002998SN/A : *stk++; 1012998SN/A ++n; 1022998SN/A } 1032998SN/A#endif 1042998SN/A 1053017SN/A QUICKTHREADS_VARGS_MD1 (QUICKTHREADS_VADJ(sp)); 1062998SN/A QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VARGT_INDEX, pt); 107 QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VSTARTUP_INDEX, startup); 108 QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VUSERF_INDEX, vuserf); 109 QUICKTHREADS_SPUT (QUICKTHREADS_VADJ(sp), QUICKTHREADS_VCLEANUP_INDEX, cleanup); 110 return ((qt_t *)QUICKTHREADS_VADJ(sp)); 111} 112