
/*
 * stktrace.c: version 1.1 of 6/3/85
 * 
 * Stack Tracing routine
 */

#include "../INC5/monitor.h"
#define STACKSTART 0xf80000	/* well, who knows? */


tracestack(fpat,pcfrom)
int fpat,pcfrom;
{
	register int pcreturn;
	register int backup;
	register int tryaddr;
	register int instreturn,args,arg,i = 0;
	int calladdr;
	int tmp;
	int fpnext;
	unsigned char instry;

	pcreturn = memquad(fpat+4);	/* return pc */
	
	/*
	 * try to find where we were called from to get the address
	 * of our current function -- backup over the call and
	 * disassemble the instruction to find the called function.
	 */
	for (	backup = 2; 
		backup < 10;
		backup++) {
			tryaddr = pcreturn - backup;
			if ( (tmp=memword(tryaddr) & 0xff) == JSRCODE ) {
				if ( disasm(tryaddr,0) == backup ) {
					dot = tryaddr;
					incp = 2;
					printf("%6x:  ",tryaddr);
					/* if absolute mode print disp */
					if ((membyte(tryaddr+1)&0xf8) == 0xa8) {
						calladdr = getdisp();
						printf("%x", calladdr);
					} else {
						printf("???");
						pflag = 1;
						gen1(tmp>>11,tmp&3);
						pflag = 0;
					}
				}
			}
	}

	/*
 	 * now print the arguments if any
	 */
	OUTCHR('(');
	instreturn = memquad(pcreturn);
	if ((instreturn & 0xffff) == 0xa57c) {	/* adjspb size */
		args = 0 - ((instreturn >> 16) | 0xffffff00);
		while (args > 0) {
			arg = memquad(fpat+8+i);
			printf("%x",arg);
			i += 4;
			args -= 4;
			if (args > 0) OUTCHR(',');
		}
	} 

	printf(")\n");

	if ( quitchk() )	/* finished yet */
		return;	
	
	switch( INCHR() ) {			/* get a character */
	case '\r':				/* keep going */
	case '\n':
		fpnext = memquad(fpat);		/* next frame */
		if (fpcheck(fpnext))
			tracestack(fpnext,pcreturn);
		break;
	default:				/* otherwise, get out */
		break;
	}
}

fpcheck(fp)
{
	if ( (fp >= env->fp) && (fp < STACKSTART) )
		return(1);
	else
		return(0);
}



/*
 * instruction backup
 * look backward until a symbol is found
 * and disassemble forward to current address
 * then backup size of last instruction disassembled
 */

/***************************************************************
 * No instruction backup, for now
 *
ibackup(addrat)
{
	int newaddr,modf,off,symatch;
	int instlen = 0;
	char symfound[MAXSTRLEN];
	if (autoi(addrat)) {
		newaddr = addrat - 1;
		symatch = lookbyval(newaddr,&off,&modf,symfound);
		if (symatch) {
		    newaddr -= off;
		    while ((newaddr + instlen) < addrat) {
			newaddr += instlen;
			if (disasm(newaddr,FALSE) == 0) {
			} else return(addrat);
		    }
		    return(newaddr);
		}
	} 
	return(addrat);
}
**********************************************************/


/* 
 * No instruction skipping for now
 *****************************************************
skipinst()
{
int instlen, thepc;
	thepc = getreg(SPC);
	if ( instlen = disasm(thepc,FALSE) ) {
		setreg(SPC,(thepc + instlen));
	} else {
		printf("\r\ncan not skip this instruction\r\n");
	}
	showspot();
}
**************************************************/

