blob: 2539ce61aa9c4aac388d3cbf0c6dea0621752add [file] [log] [blame]
/******************************************************************************
*
* Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
#include "profile.h"
#include "_profile_timer_hw.h"
#ifdef PROC_MICROBLAZE
#include "mblaze_nt_types.h"
#endif
/*
* The mcount fucntion is excluded from the library, if the user defines
* PROFILE_NO_GRAPH.
*/
#ifndef PROFILE_NO_GRAPH
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef PROFILE_NO_FUNCPTR
s32 searchpc(const struct fromto_struct *cgtable, s32 cgtable_size, u32 frompc );
#else
s32 searchpc(const struct fromstruct *froms, s32 fromssize, u32 frompc );
#endif
/*extern struct gmonparam *_gmonparam, */
#ifdef PROFILE_NO_FUNCPTR
s32 searchpc(const struct fromto_struct *cgtable, s32 cgtable_size, u32 frompc )
{
s32 index = 0 ;
while( (index < cgtable_size) && (cgtable[index].frompc != frompc) ){
index++ ;
}
if( index == cgtable_size ) {
return -1 ;
} else {
return index ;
}
}
#else
s32 searchpc(const struct fromstruct *froms, s32 fromssize, u32 frompc )
{
s32 index = 0 ;
s32 Status;
while( (index < fromssize) && (froms[index].frompc != frompc) ){
index++ ;
}
if( index == fromssize ) {
Status = -1 ;
} else {
Status = index ;
}
return Status;
}
#endif /* PROFILE_NO_FUNCPTR */
void mcount( u32 frompc, u32 selfpc )
{
register struct gmonparam *p = NULL;
register s32 toindex, fromindex;
s32 j;
disable_timer();
/*print("CG: "), putnum(frompc), print("->"), putnum(selfpc), print("\r\n") ,
* check that frompcindex is a reasonable pc value.
* for example: signal catchers get called from the stack,
* not from text space. too bad.
*/
for(j = 0; j < n_gmon_sections; j++ ){
if((frompc >= _gmonparam[j].lowpc) && (frompc < _gmonparam[j].highpc)) {
p = &_gmonparam[j];
break;
}
}
if( j == n_gmon_sections ) {
goto done;
}
#ifdef PROFILE_NO_FUNCPTR
fromindex = searchpc( p->cgtable, p->cgtable_size, frompc ) ;
if( fromindex == -1 ) {
fromindex = p->cgtable_size ;
p->cgtable_size++ ;
p->cgtable[fromindex].frompc = frompc ;
p->cgtable[fromindex].selfpc = selfpc ;
p->cgtable[fromindex].count = 1 ;
goto done ;
}
p->cgtable[fromindex].count++ ;
#else
fromindex = (s32)searchpc( p->froms, ((s32)p->fromssize), frompc ) ;
if( fromindex == -1 ) {
fromindex = (s32)p->fromssize ;
p->fromssize++ ;
/*if( fromindex >= N_FROMS ) {
* print("Error : From PC table overflow\r\n")
* goto overflow
*}*/
p->froms[fromindex].frompc = frompc ;
p->froms[fromindex].link = -1 ;
}else {
toindex = ((s32)(p->froms[fromindex].link));
while(toindex != -1) {
toindex = (((s32)p->tossize) - toindex)-1 ;
if( p->tos[toindex].selfpc == selfpc ) {
p->tos[toindex].count++ ;
goto done ;
}
toindex = ((s32)(p->tos[toindex].link)) ;
}
}
/*if( toindex == -1 ) { */
p->tos-- ;
p->tossize++ ;
/* if( toindex >= N_TOS ) {
* print("Error : To PC table overflow\r\n")
* goto overflow
*} */
p->tos[0].selfpc = selfpc ;
p->tos[0].count = 1 ;
p->tos[0].link = p->froms[fromindex].link ;
p->froms[fromindex].link = ((s32)(p->tossize))-((s32)1);
#endif
done:
p->state = GMON_PROF_ON;
goto enable_timer_label ;
/* overflow: */
/*p->state = GMON_PROF_ERROR */
enable_timer_label:
enable_timer();
return ;
}
#endif /* PROFILE_NO_GRAPH */