/*
 * sparc/solaris2/sunc_threads.c
 * Sparc threading information for SparcWorks compiler.
 *
 * Copyright (c) 1996,97 T. J. Wilkinson & Associates, London, UK.
 *
 * See the file "license.terms" for information on usage and redistribution
 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * Written by Gilles Dauphin <dauphin@sig.enst.fr>
 */

/*
 * We only need this if we're using the SparcWorks Prof C 4.0 compiler.
 */
#if defined(USE_SPARC_PROF_C)

#pragma unknow_control_flow (ThreadSwitch)

void
ThreadSwitch( ctx * to,  ctx * from )
{
        int regstore[6];
        register int *reg;		/* %i5 */
        register uint8 ** frp;		/* %i4 */
        register uint8 ** trp;		/* %i3 */
 
 
        reg = regstore; /* avoid compiler optimisation */
        frp =  &((from)->restorePoint);
        trp =  &((to)->restorePoint);
 
        asm("                                                   \n\
                call 1f                                         \n\
                nop                                             \n\
1:                                                              \n\
                add %o7,%lo(2f-1b+8),%l0                        \n\
                                                                \n\
                ta 3                                            \n\
                st %l0,[%i5+0]                                  \n\
                st %fp,[%i5+4]                                  \n\
                st %sp,[%i5+8]                                  \n\
                st %l7,[%i5+12]                                 \n\
                st %i7,[%i5+16]                                 \n\
                st %i5,[%i4]                                    \n\
                                                                \n\
                ld [%i3],%i5                                    \n\
                ld [%i5+16],%i7                                 \n\
                ld [%i5+12],%l7                                 \n\
                ld [%i5+8],%sp                                  \n\
                ld [%i5+4],%fp                                  \n\
                ld [%i5+0],%l0                                  \n\
                                                                \n\
                jmpl %l0,%g0                                    \n\
                nop                                             \n\
2:              nop"
        );
}

void
ThreadInit( ctx * to, void (*func)() )  /* ou func = void *  */
{
        int* regstore = (int*)((to)->stackEnd - (6 * 4));

        (to)->restorePoint = (void*)regstore;
        regstore[0] = (int)func;
        regstore[1] = ((int)regstore) - (16 * 4);
        regstore[2] = regstore[1];
        regstore[3] = 0;
        regstore[4] = 0;
}
 
void
ThreadInfo(ctx * ee)
{
        void** ptr;     /* %fp -4 */
        int i;          /* %fp -8 */
                        /* no return value */
 
        asm("   ta 3");              
/* gnu as       asm("mov %%sp,%0" : "=r" (ptr)); */
        asm("   mov %sp,%o4");       
        asm("   st %o4,[%fp-4]");    
                                     
        for (i = 0; i != 2; i++) {   
                ptr = (void**)ptr[14];
        }                            
                                     
        (ee)->restorePoint = 0;      
        (ee)->stackEnd = (void*)ptr; 
        (ee)->stackBase = (ee)->stackEnd - threadStackSize;
        (ee)->flags = THREAD_FLAGS_NOSTACKALLOC;
}                                    
                                     
int
ThreadFrames( thread* tid)       
{                                    
        void** ptr;             /* %fp -8 */
        int cnt = 0;            /* %fp -12 */
                                /* return value is in %fp-4 */
                                     
        if (tid == currentThread) {  
                asm("   ta 3");      
/* gcc asm              asm("mov %%sp,%0" : "=r" (ptr));*/
                asm("   mov %sp,%o3");
                asm("   st %o3,[%fp-8]"); 
        } else {                     
                ptr = ((void***)TCTX(tid)->restorePoint)[2];
        }                            
        while (*ptr != 0) {          
                cnt++ ;              
                ptr = (void**)ptr[14];
        }                            
        return cnt;                  
}                                    

#endif
