h12787
s 00126/00059/00268
d D 1.4 85/06/03 18:29:51 dock 4 3
c added typing of breakpoints 
c expanded breakpoints so that more than one temporary could be set 
c breakpoint names can now be used and displayed 
e
s 00005/00004/00322
d D 1.3 85/02/13 00:23:29 dock 3 2
c added mapping checks to isbrkset
e
s 00015/00002/00311
d D 1.2 84/11/30 22:02:12 dock 2 1
c added ifdef MMUBRK, to turn on or off mmu-type breakpointing
e
s 00313/00000/00000
d D 1.1 84/11/01 22:37:08 dock 1 0
c date and time created 84/11/01 22:37:08 by dock
e
u
U
t
T
I 1
D 4
/* brk.c -- breakpointing routines for monitor
E 4
I 4

/*
 * %M%: version %I% of %H%
 *
 * breakpointing routines for monitor
E 4
 * copyright (c) 1984  American Information Systems Corporation
D 4
 *  Dock Williams
 *  November, 1983
E 4
I 4
 *  Dock Williams  November, 1983
E 4
 *
 */

#include "monitor.h"
#include "3200config.h"
#include "vctype.h"


brkpnt(argc,argv)
    int argc;
    char *argv[];

/* brkpnt(argc,argv)
 * 	in:	argc		argument count
 *	in:	argv		argument vector
 *
 *	Main breakpoint handler for setting, clearing, and displaying
 *	breakpoints.  Syntax and examples:
 *
 *	b		A single 'b' will cause all set breakpoints to
 *			be displayed, including MMU breakpoints.
I 4
 *
E 4
 *	-<#> b		A minus sign followed by number will clear that
 *			particularly numbered breakpoint.
I 4
 * 
E 4
 *	<address> - b	An address followed by a minus sign will clear
 *			the breakpoint set at that address.
I 4
 *
E 4
D 2
 *	<address> <r,w,e,a,p,0|1> b    An address followed by a set of
E 2
I 2
 *	<address> <r,w,e,a,p,0|1> [count] b 
 *			An address followed by a set of
E 2
 *			letters which specify breakpoint settings in an
 *			MMU breakpoint, will set a breakpoint in the MMU
 *			If a count is given as the third argument a count
 *			will be set for that breakpoint also.
D 4
 *	-* b		A minus sign followed by and asterisk clears all
E 4
I 4
 *
 *	-* b		A minus sign followed by an asterisk clears all
E 4
 *			breakpoints.
D 4
 *	<address> b	An address followed by a 'b' will set a breakpoint 
E 4
I 4
 *
 *	<address> [string] b
 *			An address followed by a 'b' will set a breakpoint 
E 4
 *			at that	address, if possible and not already set.
I 4
 *			The string is a name that can be associated with
 *			this breakpoint.
E 4
 *
 *	Functions called:
 *	conv, psym, clrbrk, setbrk, printf
 */
{
    register int b;
    register char *addr, *opt;
    register int optx, brkadr;
D 4
    int brkcnt, rval;
E 4
I 4
    int brkcnt, rval, tmp;
E 4

    /* if the first argument is an address convert it to binary */
    if ( (argc>1) && (*argv[0] != '-')) {
	if (conv(argv[0],&rval)) addr = (char *)(0x00ffffff & rval);
	else return;
    }

    switch(argc) {
D 4
    case 1:
E 4
I 4
    case 1:					/* display all breakpoints */
E 4
	for(b=0; b<MAXBRK; b++) {
	    if(brktab[b].flag) {
D 4
		printf("%x:  ",b);
		if (cflags & CF_SYMP) psym(brktab[b].addr);
E 4
I 4
		printf("%x:  ",b);				/* number */
		if (cflags & CF_SYMP) psym(brktab[b].addr);	/* address */
E 4
		else printf("%6x    ",brktab[b].addr);
D 4
		mdisasm(brktab[b].addr, &rval, 1, brktab[b].map);
E 4
I 4
		mdisasm(brktab[b].addr, 1, brktab[b].map);   /* instruction */
		prbrkname(brktab[b].addr);			/* name */
E 4
		OUTCHR('\n');
	    }
	}
I 2

#ifdef MMUBRK
E 2
	if (cflags & CF_MMUBRK) {
	    printf("bpr0: %6x ",env->mmu.bpr0);
	    pbrkflgs(env->mmu.bpr0);
	    printf("  bcnt: %6x\n",env->mmu.bcnt);
	    printf("brp1: %6x ",env->mmu.bpr1);
	    pbrkflgs(env->mmu.bpr1);
	    OUTCHR('\n');
	}
I 2
#endif MMUBRK

E 2
	break;
    case 2:
	if (*argv[0] == '-') {
D 4
	    addr = argv[0];
	    clrbrk(0,*++addr);		/* clear breakpoint by number */
	} else setbrk(addr);		/* set a breakpoint */
E 4
I 4
		addr = argv[0];
		clrbrk(0,*++addr);	/* clear breakpoint by number */
	} else setbrk(addr,"",B_NORM);	/* set a breakpoint no name given */
E 4
	break;
    case 3:
D 4
	if(*argv[1] == '-') {		/* clear breakpoint */
	    clrbrk(addr,'s');		/* otherwise mmu type breakpoint */
	    break;
E 4
I 4
	if ( *argv[1] == '-' ) {	/* clear breakpoint */
		clrbrk(addr,'s');
		break;
E 4
	}
I 4
	if ( isalpha(*argv[1]) ) {	/* set breakpoint */
		setbrk(addr,argv[1],B_NORM);
		break;
	}
E 4
I 2

#ifdef MMUBRK
E 2
    case 4:
	brkadr = (int)addr;
	optx = 1;
	rval = 3;
	if(argc == 4) {
	    if ( !conv(argv[1],&brkcnt) ) return;
	    brkadr |= BRK_C;
	    optx = 2;
	} else brkcnt = 0;
	opt = argv[optx];
	while (isalpha(*opt) || *opt == '1' || *opt == '0') {
	    switch(*opt++) {
	    case 'r':	brkadr |= BRK_R; break;
	    case 'w':	brkadr |= BRK_W; break;
	    case 'x':	brkadr |= BRK_X; break;
	    case 'p':	brkadr |= BRK_P; break;
	    case 'a':	brkadr |= BRK_A; break;
	    case '0':	rval = 0; break;
	    case '1':
		rval = 1;
		if (brkcnt) printf("bpr0 only");
		break;
	    default:
		break;
	    }
	}

#ifdef DEBUG1
printf("brk: addr=%8x cnt=%8x reg=%x\n",brkadr,brkcnt,rval); /* DBG */
#endif

	if (rval == 1) {
		cflags |= CF_MMUBRK;
		prgb1(brkadr);		/* call assembler routine */
		env->mmu.bpr1 = brkadr;
	}
	else if(rval == 0) {
		cflags |= CF_MMUBRK;
		prgb0(brkadr,brkcnt);
		env->mmu.bpr0 = brkadr;
		env->mmu.bcnt = brkcnt;
	}
	else printf("brk reg?\n");
I 2
	break;
#endif MMUBRK

    default:
	    printf("?brk?\n");
E 2
    }
}



clrbrk(addr,number)
    char number;
    register char *addr;

/* clrbrk(addr,number)
 *	in:	addr		address at which to clear breakpoint
 *	in:	number		number of a breakpoint in breakpoint table
 *				    alternative to using address
 *
 *	If number is not a legal hex digit then addr is considered
 *	valid and a breakpoint is cleared, if it is set at the given
 *	address;  otherwise we clear the nth entry in the breakpoint 
 *	table which is specified by number
I 4
 *	If number is B_REPL we set the B_REPL flag and clear all others
 *	so as to temporarily clear the breakpoint
E 4
 *
 *	Functions called:
 *	ctox
 */
{
    register int b;

    if (isxdigit(number)) {		/* clear a breakpoint by its number */
	b = ctox(number);
	brktab[b].ins = 0;
	brktab[b].flag = 0;
    } else if (number == '*') {		/* clear all breakpoints */
	cflags &= ~CF_MMUBRK;
	env->mmu.bpr0 = env->mmu.bpr1 = 0;
    	for (b=0; b<MAXBRK; b++) {
	    brktab[b].ins = 0;
	    brktab[b].flag = 0;
	}
    } else for (b=0; b<MAXBRK; b++) {	/* clear breakpoint at this address */
	if( brktab[b].addr == addr) {
D 4
	    brktab[b].ins = 0;
	    brktab[b].flag = 0;
	    break;
E 4
I 4
	    if (number == B_REPL)
		 brktab[b].flag = B_REPL;
	    else {
		    brktab[b].ins = 0;
		    brktab[b].flag = 0;
		    break;
	    }
E 4
	}
    }
}



D 4
msetbrk(baddr, maptype)
    register char *baddr;
    register int maptype;
E 4
I 4
msetbrk(baddr, name, brktype, maptype)
register char *baddr;
register char *name;
int brktype;
register int maptype;
E 4

D 4
/* msetbrk(baddr, maptype)
E 4
I 4
/* msetbrk(baddr, name, brktype, maptype)
E 4
 *	in:	baddr		address at which to set breakpoint
I 4
 *	in:	name		name to give this breakpoint
 *	in:	brktype		type of breakpoint B_NORM or B_TEMP
E 4
 *	in:	maptype		byte specifying how to map baddr
 *
 *	Set a breakpoint at the argument address.  Check if the breakpoint
 *	is already set and also that it can be set in valid ram.
 *
 *	Functions called:
 *	printf
 */
{
D 4
    register int b;
    char fflag;
E 4
I 4
    register int b,i;
    register char foundentry;
E 4

D 4
    fflag = 0;	/* an empty entry for a breakpoint has been found flag */

E 4
    /* is there already a brk at this address */
I 4
    foundentry = 0;
E 4
    for(b=0;b<MAXBRK;b++) {
D 4
	if ( (brktab[b].addr == baddr) && (brktab[b].map == maptype) ) {
	    if (brktab[b].flag) {
		printf("brk set\n");
		return;
	    } else {
		fflag++;	/* no, then use this one */
		break;
	    }
E 4
I 4
	if (brktab[b].addr == baddr)  {
		if (brktype & B_NORM) {
			foundentry++;
			brktab[b].flag = 0;
			break;
		}
E 4
	}
    }
D 4
	
    /* find an empty entry is the breakpoint table */
    if (!fflag)
	for(b=0,fflag=0;b<MAXBRK;b++)
	    if( brktab[b].flag == 0) { fflag++; break; };
E 4

D 4
    /* check for legality and enter info in table if ok */
    if (fflag) {
	brktab[b].ins = mrdbyte(baddr, maptype);
#ifdef DB32
	mwrtmbyte(baddr, maptype, BRKCODE);	/* can we set this breakpoint */
	if(mrdbyte(baddr, maptype) != BRKCODE) {
	    printf("brk not set\n");
	    return;
	}
	mwrtmbyte(baddr, maptype, brktab[b].ins);	/* reset the instr */
#endif
	brktab[b].addr = baddr;
	brktab[b].map = maptype;
	brktab[b].flag++;
    } else printf("full\n");
E 4
I 4
    /*
     * if this breakpoint was previously set; we found an old entry
     * reuse information from old setting if possible 
     * (the name string)
     */
    if (!foundentry) b=0;

    /*
     * otherwise, find an empty entry in the breakpoint table
     * and fill in the breakpoint information
     */
    for(;b<MAXBRK;b++)
		if( brktab[b].flag == 0) {
			brktab[b].ins = mrdbyte(baddr, maptype);
			/* can we set this breakpoint */
			mwrtmbyte(baddr, maptype, BRKCODE);
			if(mrdbyte(baddr, maptype) != BRKCODE) {
				printf("cannot set brkpnt\n");
				return;
			}
			/* reset the instr */
			mwrtmbyte(baddr, maptype, brktab[b].ins);	
			brktab[b].flag = brktype;
			brktab[b].addr = baddr;
			brktab[b].map = maptype;
			if (name[0] || !foundentry)
				strncpy( &brktab[b].name[0], name, BRKNMSZ-1 );
				/* for(i=0;i<BRKNMSZ;i++)
					brktab[b].name[i] = name[i]; */

			/* terminate string for sure */
			brktab[b].name[BRKNMSZ-1] = 0;
			return;
		}

    printf("full\n");
E 4
}

	
D 4
misbrkset(baddr, maptype)
E 4
I 4
misbrkset(baddr, brktype, maptype)
E 4
    register char *baddr;
    register int maptype;
I 4
    int brktype;
E 4

D 4
/* misbrkset (baddr, maptype)
E 4
I 4
/* misbrkset (baddr, brktype, maptype)
E 4
 *	in:	baddr		address to check for a breakpoint set
I 4
 *	in:	brktype		type of breakpoints to check for
E 4
 *	in:	maptype		mapping flag
 *
 *  a 'boolean' function that returns a one if a brkpoint is set at the
 *  argument address and a zero otherwise
 */
{
    register int b;

    for(b=0; b<MAXBRK; b++)
D 3
	if ( (brktab[b].addr == baddr) && (brktab[b].map == maptype) &&
							(brktab[b].flag) ) {
	    return(1);
	}
E 3
I 3
D 4
	if ( (brktab[b].addr == baddr) && brktab[b].flag )
E 4
I 4
	if ( (brktab[b].addr == baddr) && (brktab[b].flag & brktype) )
E 4
		if (brktab[b].map == maptype)
			return(1);
		else if ( mem_addr(baddr,PHYS) == mem_addr(baddr,maptype) )
			return(1);
E 3
    return(0);
}


brkexec()

/* brkexec()
 * 
 * set all breakpoints in the breakpoint table
 * this routine is called in returning from the debugger 
 * and also just prior to doing an xcall debugger command
 */
{
    register int b;

    for(b=0; b<MAXBRK; b++)
D 4
	if(brktab[b].flag) 
E 4
I 4
	/* 
	 * if flags are set 
	 * and this is not temporarily cleared breakpoint
	 * then write the breakpoint code at the breakpoint address
	 */
	if ( brktab[b].flag && (!(brktab[b].flag&B_REPL)) ) 
E 4
	    mwrtmbyte (brktab[b].addr, brktab[b].map, BRKCODE);
}




brkinit()

/* brkinit()
 * 
 *  replace all set breakpoints with their previous instruction byte
 *  this function is called every time the monitor is entered via
 *  trap
 */
{
    register int b;

    for(b=0; b<MAXBRK; b++)
	if(brktab[b].flag) 
	    mwrtmbyte (brktab[b].addr, brktab[b].map, brktab[b].ins);
}



D 2

E 2
I 2
#ifdef MMUBRK
E 2
    static 
pbrkflgs(bpr)
    register int bpr;

/* pbrkflgs(bpr)
 *	in:	bpr		breakpoint register
 *
 *	Print an interpretation of the flags set in the given
 *	breakpoint register
 */
{
    OUTCHR('(');
    if(bpr & BRK_A) printf(" AS");
    if(bpr & BRK_P) printf(" VP");
    if(bpr & BRK_X) printf(" BE");
    if(bpr & BRK_R) printf(" BR");
    if(bpr & BRK_W) printf(" BW");
    if(bpr & BRK_C) printf(" CE");
    printf(" )");
}
I 2
#endif MMUBRK
E 2

I 4

prbrkname(addr)
    register char *addr;

/* prbrkname(addr)
 *	in:	addr		possible breakpoint address
 *
 *	print the name of the breakpoint at the argument address
 *	if it exists
 */
{
	register int b;

	for(b=0; b<MAXBRK; b++) {
	    if (brktab[b].flag && (brktab[b].addr == addr) ) {
		if (brktab[b].flag & B_TEMP) printf("     (temporary)");
		else if (brktab[b].name[0])
				printf("     (%s)",brktab[b].name);
	    }
	}
}
E 4
E 1
