⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nios_gprof.c

📁 ALTERA的NIOS处理器!文件直接可以打开直接选择器件重新编译!
💻 C
📖 第 1 页 / 共 2 页
字号:
 asm(".global nios_mcount
        nios_mcount: 
                mov    %o1,%i7 
                mov    %o0,%o7 
                save   %sp,-23
                mov    %o0,%i0
                mov    %o1,%i1
                pfx    %hi(internal_mcount@h)
                movi   %o2, %lo(internal_mcount@h)
		"
#ifdef __nios32__
                "pfx    %xhi(internal_mcount@h)
                movhi  %o2, %xlo(internal_mcount@h)
		"
#endif
                "call   %o2
                nop
                restore
                jmp    %o7
                nop
                ");


/*
 *      Parameters are the return address for mcount,
 *      and the return address for mcount's caller.
 */
static void internal_mcount(selfpc, frompcindex)
register char            *selfpc;
register unsigned short  *frompcindex;
{
    register struct tostruct *top;
    register struct tostruct *prevtop;
    register long   toindex;
    static char already_setup;

/* A little error checking first: if the stack pointer is below the
   data, then we corrupted data and all bets are off: 
*/
    long a, b;
    int x;
    a = PTR2LONG (sbrk (0));
    b = PTR2LONG (&x);

    if ( a >  b) {
        printf("Error - stack underflow - memory corruption\n !!");
	printf("End of data = 0x%08lx , Stack = 0x%08lx \n", (long) a, (long) b);

    }

/* CBV - the frompcindex and selfpc addresses are currently divided
   by 2. So, in order to bring them back in sync with the rest
   of the code, I must make them from jump adddresses to absolute
   addresses.
*/
    frompcindex = (unsigned short *) (2 * ((unsigned int) frompcindex));

    selfpc = (unsigned char *) (2 * ((unsigned int) selfpc));

    if(!already_setup) {

        extern char etext[];

        already_setup = 1;

        monstartup((char *)(unsigned int) nasys_program_mem, 
                   (char *)((unsigned int) etext));


/* CBV - We don't have the operating system on_exit  */
/* call, so force it to use at_exit.  */
/*#ifdef USE_ONEXIT  */
/*          on_exit(_mcleanup, 0);  */
/*#else  */

          atexit(_mcleanup); 

/*#endif  */

    }
        /*
         *      check that we are profiling
         *      and that we aren't recursively invoked.
         */
    if (profiling) {
            goto out;
    }
    profiling++;

        /*
         *      check that frompcindex is a reasonable pc value.
         *      for example:    signal catchers get called from the stack,
         *                      not from text space.  too bad.
         */

    frompcindex = (unsigned short *)(((unsigned int) frompcindex) - 
                  ((unsigned int) s_lowpc));

    if ((unsigned int)frompcindex > s_textsize) {
        goto done;
    }

    frompcindex = (unsigned short *) ((unsigned int) &froms[
                  ((unsigned int) frompcindex) / 
                  (unsigned int) (HASHFRACTION * sizeof(*froms))]);

    toindex = PTR2LONG (*frompcindex);

    if (((unsigned int) toindex) == 0) {
            /*
             *      first time traversing this arc
             */
        toindex = ++tos[0].link;
        if (toindex >= tolimit) {
            goto overflow;
        }

        *frompcindex = (unsigned short) toindex;
        top = &tos[toindex];
        top->selfpc = selfpc;
        top->count = 1;
        top->link = 0;
        goto done;
    }
    top = &tos[toindex];

    if (top->selfpc == selfpc) {
        /*
         *      arc at front of chain; usual case.
         */
        top->count++;
        goto done;
    }
        /*
         *      have to go looking down chain for it.
         *      top points to what we are looking at,
         *      prevtop points to previous top.
         *      we know it is not at the head of the chain.
         */
    for (; /* goto done */; ) {
        if (top->link == 0) {
            /*
             *      top is end of the chain and none of the chain
             *      had top->selfpc == selfpc.
             *      so we allocate a new tostruct
             *      and link it to the head of the chain.
             */
            toindex = ++tos[0].link;
            if (toindex >= tolimit) {
                goto overflow;
            }
            top = &tos[toindex];
            top->selfpc = selfpc;
            top->count = 1;
            top->link = *frompcindex;
            *frompcindex = (unsigned short) toindex;
            goto done;
        }
        /*
         *      otherwise, check the next arc on the chain.
         */
        prevtop = top;
        top = &tos[top->link];
        if (top->selfpc == selfpc) {
        /*
         *      there it is.
         *      increment its count
         *      move it to the head of the chain.
         */
            top->count++;
            toindex = prevtop->link;
            prevtop->link = top->link;
            top->link = *frompcindex;
            *frompcindex = (unsigned short) toindex;
            goto done;
        }
    }
done:
    profiling--;
    /* and fall through */
out:
    return;         /* normal return restores saved registers */

overflow:
    profiling++; /* halt further profiling */
#   define      TOLIMIT "mcount: tos overflow\n"
    nios_write(2, TOLIMIT, sizeof(TOLIMIT));
    goto out;
}


/*
 * Control profiling
 *	profiling is what mcount checks to see if
 *	all the data structures are ready.
 */
static void moncontrol(mode)
    int mode;
{
    if (mode) {
	/* start */
        nios_profil((unsigned short *)(sbuf + sizeof(struct phdr)),
               (unsigned long)(ssiz - sizeof(struct phdr)),
               (unsigned long)((unsigned int)s_lowpc), s_scale);
	profiling = 0;
    } else {
	/* stop */
	nios_profil((unsigned short *)0, 0L, 0L, 0L);
	profiling = 3;
    }
}


void nios_write (int stream, char *msg, int size_of_message)
{
    int i;

    for(i = 0; i < size_of_message; i++) {
        if((i & 0x000f) == 0) {
            printf("\n### ");  /* 3 #'s for convert program */
        }
        printf("%02x ",msg[i] & 0x000000ff);
    }
    printf("*\n");
}

/*
 * start or stop profiling
 *
 * profiling goes into the SAMPLES buffer of size SIZE (which is treated
 * as an array of unsigned shorts of size size/2)
 * 
 * each bin represents a range of pc addresses from OFFSET.  The number
 * of pc addresses in a bin depends on SCALE.  (A scale of 65536 maps
 * each bin to two addresses, A scale of 32768 maps each bin to 4 addresses,
 * a scale of 1 maps each bin to 128k addreses).  Scale may be 1 - 65536,
 * or zero to turn off profiling
 */
void
nios_profile_ctl (struct profinfo * p, char *samples, unsigned long size,
	     unsigned long offset, long scale)
{
    unsigned long maxbin;

    if (scale > 65536) {
      printf ("Error - scale factor overflow!!! \n");
    }

    profile_off (p);
    if (scale) {
        memset (samples, 0, size);
        memset (p, 0, sizeof *p);
        maxbin = size >> 1;
        prof.counter = (unsigned short *) samples;
        prof.lowpc = offset;
        prof.highpc = PROFADDR (maxbin, offset, scale);
        prof.scale = scale;

        profile_on (p);
    }
}

/* Equivalent to unix profil() 
   Every SLEEPTIME interval, the user's program counter (PC) is examined: 
   offset is subtracted and the result is multiplied by scale.  
   The word pointed to by this address is incremented.  Buf is unused. */

void
nios_profil (unsigned short *bigbuffer, unsigned long buff_size, 
                  unsigned long base, long buf_scale)
{
    nios_profile_ctl (&prof, (char *) bigbuffer, buff_size, base, buf_scale);
}

void profile_off (struct profinfo *p)
{
    /* Disable the timer */
    DoDisableTimerInterrupt();
}


#ifndef na_timer1     /* If the timer is not defined, stubb out timer funcs */

void profile_on (struct profinfo *p)
{
	printf("\n\n---->> WARNING!!! na_timer1 NOT defined. The");
	printf(" output generated by nios_gprof will NOT contain");
	printf(" any usefull information!!!");
}

void nios_prof_hdr_timer_ISR(int context, int irq_number, int interruptee)
{}
static void DoEnableTimerInterrupt(void)
{}
static void DoDisableTimerInterrupt(void)
{}

#else


void profile_on (struct profinfo *p)
{
    np_timer *timer = na_timer1;
    long timerPeriod = nasys_clock_freq / TIMER_SAMPLE_RATE;

    timer->np_timerperiodh = timerPeriod >> 16;
    timer->np_timerperiodl = timerPeriod & 0xffff;

    timer->np_timercontrol = np_timercontrol_start_mask |
                             np_timercontrol_cont_mask;

    DoEnableTimerInterrupt();
}

typedef struct
{
    long interruptCount;    // increment with each interrupt
    np_timer *timer;
} TimerISRContext;

static TimerISRContext gC = {0,0};

void nios_prof_hdr_timer_ISR(int context,int irq_number, int interruptee)
{
    struct profinfo *p = (struct profinfo *) &prof;
    unsigned int pc, idx;

    TimerISRContext *c;

    long a, b;
    int x;
    a = PTR2LONG (sbrk (0));
    b = PTR2LONG (&x);

    if (a > b) {
        printf("Error - stack underflow - memory corruption\n !!");
	printf("End of data = 0x%08lx , Stack = 0x%08lx \n",(long) a, (long) b);

    }

    c = (TimerISRContext *)context;

    c->interruptCount++;

  /* first, we must get the PC from the return address before the interrupt */

    pc = 2 * interruptee; /* Convert return address into absolute address */

  /* Now increment the appropriate counter slot: */
    if (pc >= p->lowpc && pc < p->highpc)
    {
        idx = PROFIDX (pc, p->lowpc, p->scale);
        p->counter[idx]++;
    }

    c->timer->np_timerstatus = 0;   // write anything to clear the IRQ
}

// Turn on interrupts: enable interrupt bit, and
// install a user ISR

static void DoEnableTimerInterrupt(void)
{
    gC.timer = na_timer1;
    nr_installuserisr2(na_timer1_irq,(nios_isrhandlerproc2)nios_prof_hdr_timer_ISR, (unsigned int)&gC);

    gC.timer->np_timercontrol = gC.timer->np_timercontrol | 
                                np_timercontrol_ito_mask;
}

static void DoDisableTimerInterrupt(void)
{
    gC.timer = na_timer1;
    nr_installuserisr2(na_timer1_irq,0,0);

    gC.timer->np_timercontrol = gC.timer->np_timercontrol & 
                                ~np_timercontrol_ito_mask;
}

#endif  /* na_timer */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -