mirror of
https://github.com/aaronsgiles/uuUndo.git
synced 2024-11-24 14:31:25 +00:00
1 line
10 KiB
C
1 line
10 KiB
C
|
//
// When __PROFILE is called, stack frame looks like this:
//
// sp+08 Caller's return address
// sp+04 Address of function name string
// sp Return address to start of function
//
// After we save registers and such, stack frame looks like this:
//
// sp+28 Caller's return address
// sp+24 Address of function name string
// sp+20 Return address to start of function
// sp+16 saved A0
// sp+12 saved A1
// sp+08 saved D0
// sp+04 saved D1
// sp saved D2
//
// Upon returning from __PROFILE, stack frame should look like this:
//
// sp Address of __PROFILEEND
//
//
#include <Profiler.h>
#include <Threads.h>
#include <Timer.h>
#include <stdio.h>
#include <string.h>
#pragma profile off
#if defined(powerc) || defined(__powerc)
extern void Profile_GetTime(UnsignedWide *time);
#else
#define Profile_GetTime(time) Microseconds(time)
#endif
#define THREAD_OFFSET 100
#define NAME_LENGTH 23
#define MAX_FUNCS 1000
#define MAX_THREADS 50
#define STACK_DEPTH 100
typedef struct {
char name[NAME_LENGTH+1];
int calls;
long address;
UnsignedWide totalTime;
} FunctionInfo;
typedef struct {
FunctionInfo *callerFunction;
long returnAddress;
} StackFrame;
typedef struct {
StackFrame stack[STACK_DEPTH];
StackFrame *stackPtr;
FunctionInfo *currentFunction;
UnsignedWide startTime;
} ThreadInfo;
static ThreadInfo gThread[MAX_THREADS];
static FunctionInfo gFunction[MAX_FUNCS];
static long gProfilerOn = false;
static ThreadInfo *gCurrentThread;
static FunctionInfo *gCallerFunction;
static long gSaveArea[5];
static FunctionInfo *GetIndex(char *functionName:__A0, long address:__D0):__A0;
static void StartTime(FunctionInfo *function:__A0, int call:__D0);
static void StopTime(int index:__D0);
static void GetThreadInfo(void);
static void PushFrame(long returnAddress:__D0);
static long PopFrame(void):__D0;
static asm pascal void __PROFILEEND(void);
#pragma parameter AddToWide(__A0, __A1)
void AddToWide(UnsignedWide *a, UnsignedWide *b) = {
0x2011, // move.l 0(a1),d0 ;d0 = hi
0x2229, 0x0004, // move.l 4(a1),d1 ;d1 = lo
0x2410, // move.l 0(a0),d2 ;d2 = hi
0xD2A8, 0x0004, // add.l 4(a0),d1 ;add lo parts
0xD580, // addx.l d0,d2 ;add hi parts with carry
0x2082, // move.l d2,0(a0) ;store high result
0x2141, 0x0004 // move.l d1,4(a0) ;store low result
};
#pragma parameter SubFromWide(__A1, __A0)
void SubFromWide(UnsignedWide *a, UnsignedWide *b) = {
0x2011, // move.l 0(a1),d0 ;d0 = hi
0x2229, 0x0004, // move.l 4(a1),d1 ;d1 = lo
0x2410, // move.l 0(a0),d2 ;d2 = hi
0x92A8, 0x0004, // sub.l 4(a0),d1 ;add lo parts
0x9580, // subx.l d0,d2 ;add hi parts with carry
0x2082, // move.l d2,0(a0) ;store high result
0x2141, 0x0004 // move.l d1,4(a0) ;store low result
};
pascal OSErr ProfilerInit(ProfilerCollectionMethod method, ProfilerTimeBase timeBase, short numFunctions, short stackDepth)
{
int i;
// initialize the function table
memset(gFunction, 0, sizeof(gFunction));
strcpy(gFunction[0].name, "Root_Function");
gFunction[0].address = -1;
gFunction[0].calls = 1;
// initialize the thread table
memset(gThread, 0, sizeof(gThread));
for (i = 0; i < MAX_THREADS; i++) gThread[i].stackPtr = gThread[i].stack;
Profile_GetTime(&gThread[0].startTime);
gThread[0].currentFunction = gFunction;
// make sure we're turned off
gProfilerOn = false;
return noErr;
}
pascal void ProfilerSetStatus(short on)
{
gProfilerOn = (on) ? true : false;
}
pascal OSErr ProfilerDump(StringPtr filename)
{
/*
static char cfile[256];
FunctionInfo *function;
double temp;
FILE *f;
int i;
BlockMoveData(filename + 1, cfile, *filename);
cfile[*filename] = 0;
f = fopen(cfile, "w");
if (f) {
for (i = 0, function = gFunction; i < MAX_FUNCS; i++, function++)
if (function->address) {
temp = ((double)function->totalTime.hi * 65536.0 * 65536.0) + (double)function->to
|