home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / presto / prest_04.lha / src / callstate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-08-08  |  7.8 KB  |  320 lines

  1. /*
  2.  * callstate.c
  3.  *
  4.  * Machine dependent code to remember and restore the callstate
  5.  * so that we can "squirrel" away a user's function call and make it
  6.  * later.
  7.  *
  8.  *
  9.  *    Last modified:        12/21/87
  10.  *    by:            bnb
  11.  *    reason:            make preempt safe by updating sp before
  12.  *                copy args gets done, rather than after.
  13.  *
  14.  *    Chase 8/1/88        added vax code
  15.  */
  16.  
  17.  
  18.  
  19. #define _CALLSTATE_C
  20. #include "presto.h"
  21.  
  22. #ifdef sun
  23. private_t long _fctaddr;
  24. #ifdef mc68020
  25. //
  26. // nargs.c -- Jim and Janet Carson, 12/27/88 @ 1:04am CST
  27. //
  28. //    Implementation of C-callable get-number-arguments function
  29. //    for the motorola 680x0 series microprocessors.
  30. //    I suppose this should be inline...
  31. //
  32. //    This function is dedicated to the poor students of Comp 320,
  33. //    Spring 1989, who had this as a question on their open-book
  34. //    final exam.
  35. //
  36. static int   _ipc;   /* program counter = address of next instruction */
  37. static short _instr; /* instruction at ipc                            */
  38.  
  39. #define     ADDQW1     0x584f
  40. #define     ADDQW2     0x504f
  41. #define     LEA        0x4fef
  42.  
  43. int nargs()
  44. {
  45.     asm("movl     a6, sp@-       "); // 1. Save the frame pointer.
  46.     asm("movl     a6@, a6        "); // 2. Trace back one frame -- not to
  47.                                      //    the routine that called nargs(),
  48.                                      //    but to the routine that called the
  49.                                      //    routine that called nargs().
  50.     asm("movl     a6@(4), __ipc  "); // 3. Get the return address
  51.     asm("movl     sp@+, a6       "); // 4. Restore the frame pointer
  52.  
  53.     _instr = *((short *) _ipc);      // 5. Get the next instruction after the
  54.                                      //    return address.  The next
  55.                                      //    instruction is one of the following:
  56.     if (_instr == ADDQW1)            // a. addql #4.  There was ONE argument.
  57.        return(1);
  58.     else if (_instr == ADDQW2)       // b. addql #8.  There were TWO arguments.
  59.        return(2);
  60.     else if ( _instr  == LEA)        // c. lea sp@(JJ), sp.  (where JJ is the
  61.                                      //    short word following the lea instr.)
  62.                                      //    There were JJ/4 arguments.
  63.        return ((int)(*(((short *)_ipc)+1))/4);
  64.     else                             // d. Something else.  There were NO
  65.        return(0);                    //    arguments.
  66. }
  67. #endif mc68020
  68. #endif sun
  69. #ifdef vax
  70. //
  71. // Caller's saved AP points to the number of args for caller.
  72. // Could be an inline asm.
  73. //
  74. int
  75. nargs()
  76. {
  77.      asm("movl *8(fp), r0");
  78. }
  79. #endif
  80.  
  81. //
  82. // Callstate set called with:
  83. //    pointer to function to be called later on
  84. //    number of args (longwords) it should get called with
  85. //    a pointer to the base of those args
  86. //
  87. // We store this information away and later shove it on to the call
  88. // stack of the function we want to call.
  89. //
  90.  
  91. extern void    bcopy(char*, char*, int);
  92.  
  93. Callstate::~Callstate()
  94. {
  95.     if (cs_argvd)
  96.         delete cs_argvd;
  97. }
  98.  
  99.  
  100. //
  101. // Copy the arglist into the callstate.  
  102. //    If there are args,
  103. //        and the # args > size of cs space, then
  104. //                delete the existing dynamic cs space
  105. //                make some new ones
  106. //                record size of new cs space
  107. //                copy args into new dynamic space
  108. //        else, have enough room somewhere.  Copy args
  109. //        into dynamic space (if we have it), else into
  110. //        static area.
  111. //
  112. // For the vax, we need to make sure we have two words at the front
  113. // of the cs_argvd block for the arg count and "this" argument.  See
  114. // comments in Callstate::call below.
  115. //
  116. void
  117. Callstate::set(PFany f, int argc, int *argv)
  118. {
  119.     register int *ap;
  120.  
  121.     cs_func = f;
  122.     cs_argc = argc;
  123.     if (argc)    {
  124.         if (argc > cs_len)    {
  125.             delete cs_argvd;
  126. #ifdef vax
  127.             cs_argvd = new int [argc+2];
  128.             ap = &cs_argvd[2];
  129. #else
  130.             cs_argvd = new int [argc];
  131.             ap = cs_argvd;
  132. #endif
  133.             cs_len = cs_argc;
  134.         } else {
  135. #ifdef vax
  136.             ap = (cs_argvd) ? &cs_argvd[2] : cs_argvs;
  137. #else
  138.             ap = (cs_argvd) ? cs_argvd : cs_argvs;
  139. #endif
  140.         }
  141.         bcopy((char*)argv, (char*)ap, argc * sizeof(int));
  142.     }
  143. }
  144.  
  145.  
  146. //
  147. // Perform the actual call.
  148. //
  149. //    WARNING (for sequent ns32000 version):
  150. //        if the routine we are calling tries to do an nargs
  151. //        its gonna get the wrong answer (0) since we wont
  152. //        have an constant in the adjspb field after the jsr r0
  153. //            'cest la vie...
  154. //
  155.  
  156. void
  157. Callstate::call(int *sp = 0, Objany obj = 0)
  158. {
  159.     int local = 0;
  160. #ifdef sun
  161.     int func = (int)cs_func;
  162. #else
  163.     int *func = (int *)cs_func;
  164. #endif sun
  165.     int stackbytes = cs_argc * sizeof(long);
  166.  
  167. #ifdef vax
  168.     //
  169.     // We want to use CALLG to avoid copying the args onto the stack.
  170.     // This is weird...we need a contiguous block of longwords containing
  171.     // the arg count followed by the arguments.  We have to play some games
  172.     // since the arguments may be in the callstate struct itself or they
  173.     // may be in the allocated block pointed to by cs_argvd.  If they are
  174.     // in a cs_argvd block, the block will have two extra words at the top
  175.     // for the arg count and the "this" argument.
  176.     //
  177.  
  178.     register int *ap;        // ptr to arg block for callg
  179.  
  180.         if (cs_argvd)
  181.         ap = cs_argvd;
  182.     else
  183.         ap = &cs_argc;
  184.  
  185.     //
  186.     // Hack to properly handle "this" argument with callg.  Yuck.
  187.     //
  188.     if (obj) {
  189.         ap[0] = ++cs_argc;
  190.         ap[1] = (int)obj;
  191.     } else {
  192.         ap++;
  193.         *ap = cs_argc;        // gag
  194.     }
  195.  
  196.     local = (int)ap;
  197.     thisthread->andstate(~TS_VIRGIN);   // XXX WINDOW?
  198.  
  199.         asm("callg *-4(fp), *-8(fp)");
  200.     asm("movl r0, -4(fp)");
  201. #endif vax
  202.  
  203. #if    (sequent || sun)
  204.     //
  205.     // can just toss the args right onto the stack, and do the
  206.     // call ourselves.  Remember to adjust the sp correctly
  207.     // once the call returns
  208.     //
  209.     if (sp == 0)        {     // figure it out for ourselves
  210. #ifdef    ns32000
  211.         asm("sprd    sp, -4(fp)");
  212. #endif
  213. #ifdef    i386
  214.         asm("movl    %esp, -4(%ebp)");
  215. #endif
  216. #ifdef mc68020
  217.         asm("movl       sp, a6@(-4)");
  218. #endif mc68020
  219.         sp = (int*)local;
  220.     }
  221.  
  222.     //
  223.     // Copy argv from callstate into stack for callee
  224.     // Can't use bcopy here cuz we would be copying over our actual
  225.     // stack.
  226.     //
  227.     if (cs_argc)    {    
  228.         register int *s = cs_argvd ? (cs_argvd) : (cs_argvs);
  229.         register int *d = (int*)(sp - cs_argc);
  230.         //
  231.         // update where we the sp is before we start
  232.         // writing into the stack.  Save ourselves from async
  233.         // interrupts.
  234.         //
  235.         local = (int)(sp - cs_argc);
  236. #ifdef    ns32000
  237.         asm("lprd        sp, -4(fp)");        // sp = local
  238. #endif
  239. #ifdef    i386
  240.         asm("movl        -4(%ebp), %esp");    // sp = local
  241. #endif
  242. #ifdef mc68020
  243.         asm("movl         a6@(-4), sp");    // sp = local;
  244. #endif mc68020
  245.         while (d != sp)    
  246.             *d++ = *s++;
  247.     }
  248.  
  249.     if (obj)    {
  250.         // shove hidden first argument "this"
  251.         local = (int)obj;
  252. #ifdef    ns32000
  253.         asm("movd        -4(fp), tos");    // sp-- = local
  254. #endif
  255. #ifdef    i386
  256.         asm("pushl        -4(%ebp)");    // sp-- = local
  257. #endif
  258. #ifdef mc68020
  259.         asm("movl         a6@(-4), sp@-"); // sp-- = local
  260. #endif mc68020
  261.     }
  262.     
  263.     
  264.     // remember the byte count so we can undo  it when func returns
  265.     if (obj)    
  266.         local = -(stackbytes + sizeof(Objany));    // (-4(fp))
  267.     else
  268.         local = -stackbytes;
  269.         
  270.  
  271.     //
  272.     // Safe to preempt now that stack has been set
  273.     //
  274.     thisthread->andstate(~TS_VIRGIN);
  275.  
  276.  
  277.     //
  278.     // Call intended function and return anything left over in r0.
  279.     //
  280. #ifdef mc68020
  281.     asm("movl        a6@(-8), __fctaddr " ); // a0 = func
  282.     asm("jsr        __fctaddr@       " ); // call func
  283.     asm("addql         #4, sp           ");  // up sp count
  284.     asm("movl        d0, a6@(-4)        " ); // local = d0
  285. #endif mc68020
  286. #ifdef    ns32000
  287.     asm("movd        -8(fp), r0");        // r0 = func
  288.     asm("jsr        r0");            // call
  289.     asm("adjspb        -4(fp)");        // up sp count
  290.     asm("movd        r0, -4(fp)");        // local = r0;
  291. #endif
  292. #ifdef    i386
  293.     asm("call        *-8(%ebp)");        // call func
  294.     asm("popl        %ecx");            // up sp count
  295.     asm("movl        %eax, -4(%ebp)");    // local = return value
  296. #endif
  297. #endif    sequent    
  298.     
  299.     thisthread->terminate((Objany)local);
  300.     //
  301.     // NOT REACHED!
  302.     //
  303.  
  304. }
  305.  
  306.  
  307. void
  308. Callstate::print(ostream& s)
  309. {
  310.     s << form("(Callstate)this=0x%x, cs_func=0x%x, cs_argc=0x%x, cs_argvs=0x%x, cs_argvd=0x%x", 
  311.         this, cs_func, cs_argc, cs_argvs, cs_argvd);
  312. }
  313.  
  314.  
  315. ostream& operator<<(ostream& s, Callstate& c)
  316. {
  317.     c.print(s);
  318.     return s;
  319. }
  320.