Home | History | Annotate | Line # | Download | only in powerpc
db_interface.c revision 1.12.6.3
      1  1.12.6.3  nathanw /*	$NetBSD: db_interface.c,v 1.12.6.3 2002/01/11 23:38:43 nathanw Exp $ */
      2  1.12.6.2  nathanw /*	$OpenBSD: db_interface.c,v 1.2 1996/12/28 06:21:50 rahnds Exp $	*/
      3  1.12.6.2  nathanw 
      4  1.12.6.2  nathanw #define USERACC
      5  1.12.6.2  nathanw 
      6  1.12.6.2  nathanw #include "opt_ddb.h"
      7  1.12.6.3  nathanw #include "opt_kgdb.h"
      8  1.12.6.2  nathanw #include "opt_ppcarch.h"
      9  1.12.6.2  nathanw 
     10  1.12.6.2  nathanw #include <sys/param.h>
     11  1.12.6.2  nathanw #include <sys/proc.h>
     12  1.12.6.2  nathanw #include <sys/systm.h>
     13  1.12.6.2  nathanw 
     14  1.12.6.2  nathanw #include <dev/cons.h>
     15  1.12.6.2  nathanw 
     16  1.12.6.2  nathanw #include <machine/db_machdep.h>
     17  1.12.6.2  nathanw #include <machine/frame.h>
     18  1.12.6.2  nathanw #ifdef PPC_IBM4XX
     19  1.12.6.2  nathanw #include <machine/tlb.h>
     20  1.12.6.2  nathanw #include <powerpc/spr.h>
     21  1.12.6.2  nathanw #include <uvm/uvm_extern.h>
     22  1.12.6.2  nathanw #endif
     23  1.12.6.2  nathanw 
     24  1.12.6.3  nathanw #ifdef DDB
     25  1.12.6.2  nathanw #include <ddb/db_sym.h>
     26  1.12.6.2  nathanw #include <ddb/db_command.h>
     27  1.12.6.2  nathanw #include <ddb/db_extern.h>
     28  1.12.6.2  nathanw #include <ddb/db_access.h>
     29  1.12.6.2  nathanw #include <ddb/db_output.h>
     30  1.12.6.2  nathanw #include <ddb/ddbvar.h>
     31  1.12.6.3  nathanw #endif
     32  1.12.6.3  nathanw 
     33  1.12.6.3  nathanw #ifdef KGDB
     34  1.12.6.3  nathanw #include <sys/kgdb.h>
     35  1.12.6.3  nathanw #endif
     36  1.12.6.3  nathanw 
     37  1.12.6.3  nathanw #include <dev/ofw/openfirm.h>
     38  1.12.6.2  nathanw 
     39  1.12.6.2  nathanw int	db_active = 0;
     40  1.12.6.2  nathanw 
     41  1.12.6.2  nathanw extern label_t *db_recover;
     42  1.12.6.2  nathanw 
     43  1.12.6.2  nathanw void ddb_trap(void);				/* Call into trap_subr.S */
     44  1.12.6.2  nathanw int ddb_trap_glue(struct trapframe *);		/* Called from trap_subr.S */
     45  1.12.6.2  nathanw #ifdef PPC_IBM4XX
     46  1.12.6.2  nathanw static void db_ppc4xx_ctx(db_expr_t, int, db_expr_t, char *);
     47  1.12.6.2  nathanw static void db_ppc4xx_pv(db_expr_t, int, db_expr_t, char *);
     48  1.12.6.2  nathanw static void db_ppc4xx_reset(db_expr_t, int, db_expr_t, char *);
     49  1.12.6.2  nathanw static void db_ppc4xx_tf(db_expr_t, int, db_expr_t, char *);
     50  1.12.6.2  nathanw static void db_ppc4xx_dumptlb(db_expr_t, int, db_expr_t, char *);
     51  1.12.6.2  nathanw #ifdef USERACC
     52  1.12.6.2  nathanw static void db_ppc4xx_useracc(db_expr_t, int, db_expr_t, char *);
     53  1.12.6.2  nathanw #endif
     54  1.12.6.2  nathanw #endif /* PPC_IBM4XX */
     55  1.12.6.2  nathanw 
     56  1.12.6.3  nathanw #ifdef DDB
     57  1.12.6.2  nathanw void
     58  1.12.6.2  nathanw cpu_Debugger()
     59  1.12.6.2  nathanw {
     60  1.12.6.2  nathanw 	ddb_trap();
     61  1.12.6.2  nathanw }
     62  1.12.6.3  nathanw #endif
     63  1.12.6.2  nathanw 
     64  1.12.6.2  nathanw int
     65  1.12.6.2  nathanw ddb_trap_glue(frame)
     66  1.12.6.2  nathanw 	struct trapframe *frame;
     67  1.12.6.2  nathanw {
     68  1.12.6.2  nathanw 	if (!(frame->srr1 & PSL_PR)
     69  1.12.6.2  nathanw 	    && (frame->exc == EXC_TRC
     70  1.12.6.2  nathanw 		|| (frame->exc == EXC_PGM
     71  1.12.6.2  nathanw 		    && (frame->srr1 & 0x20000))
     72  1.12.6.2  nathanw 		|| frame->exc == EXC_BPT)) {
     73  1.12.6.3  nathanw 		int type = frame->exc;
     74  1.12.6.3  nathanw 		if (type == EXC_PGM && (frame->srr1 & 0x20000)) {
     75  1.12.6.3  nathanw 			type = T_BREAKPOINT;
     76  1.12.6.3  nathanw 		}
     77  1.12.6.3  nathanw 		return kdb_trap(type, frame);
     78  1.12.6.2  nathanw 	}
     79  1.12.6.2  nathanw 	return 0;
     80  1.12.6.2  nathanw }
     81  1.12.6.2  nathanw 
     82  1.12.6.2  nathanw int
     83  1.12.6.2  nathanw kdb_trap(type, v)
     84  1.12.6.2  nathanw 	int type;
     85  1.12.6.2  nathanw 	void *v;
     86  1.12.6.2  nathanw {
     87  1.12.6.2  nathanw 	struct trapframe *frame = v;
     88  1.12.6.2  nathanw 
     89  1.12.6.3  nathanw #ifdef DDB
     90  1.12.6.2  nathanw 	switch (type) {
     91  1.12.6.2  nathanw 	case T_BREAKPOINT:
     92  1.12.6.2  nathanw 	case -1:
     93  1.12.6.2  nathanw 		break;
     94  1.12.6.2  nathanw 	default:
     95  1.12.6.2  nathanw 		if (!db_onpanic && db_recover == 0)
     96  1.12.6.2  nathanw 			return 0;
     97  1.12.6.2  nathanw 		if (db_recover != 0) {
     98  1.12.6.2  nathanw 			db_error("Faulted in DDB; continuing...\n");
     99  1.12.6.2  nathanw 			/*NOTREACHED*/
    100  1.12.6.2  nathanw 		}
    101  1.12.6.2  nathanw 	}
    102  1.12.6.3  nathanw #endif
    103  1.12.6.2  nathanw 
    104  1.12.6.2  nathanw 	/* XXX Should switch to kdb's own stack here. */
    105  1.12.6.2  nathanw 
    106  1.12.6.2  nathanw 	memcpy(DDB_REGS->r, frame->fixreg, 32 * sizeof(u_int32_t));
    107  1.12.6.2  nathanw 	DDB_REGS->iar = frame->srr0;
    108  1.12.6.2  nathanw 	DDB_REGS->msr = frame->srr1;
    109  1.12.6.2  nathanw 	DDB_REGS->lr = frame->lr;
    110  1.12.6.2  nathanw 	DDB_REGS->ctr = frame->ctr;
    111  1.12.6.2  nathanw 	DDB_REGS->cr = frame->cr;
    112  1.12.6.2  nathanw 	DDB_REGS->xer = frame->xer;
    113  1.12.6.2  nathanw #ifdef PPC_IBM4XX
    114  1.12.6.2  nathanw 	DDB_REGS->dear = frame->dear;
    115  1.12.6.2  nathanw 	DDB_REGS->esr = frame->esr;
    116  1.12.6.2  nathanw 	DDB_REGS->pid = frame->pid;
    117  1.12.6.2  nathanw #endif
    118  1.12.6.2  nathanw 
    119  1.12.6.3  nathanw #ifdef DDB
    120  1.12.6.2  nathanw 	db_active++;
    121  1.12.6.2  nathanw 	cnpollc(1);
    122  1.12.6.2  nathanw 	db_trap(type, 0);
    123  1.12.6.2  nathanw 	cnpollc(0);
    124  1.12.6.2  nathanw 	db_active--;
    125  1.12.6.3  nathanw #elif defined(KGDB)
    126  1.12.6.3  nathanw 	if (!kgdb_trap(type, DDB_REGS))
    127  1.12.6.3  nathanw 		return 0;
    128  1.12.6.3  nathanw #endif
    129  1.12.6.3  nathanw 
    130  1.12.6.3  nathanw 	/* KGDB isn't smart about advancing PC if we
    131  1.12.6.3  nathanw 	 * take a breakpoint trap after kgdb_active is set.
    132  1.12.6.3  nathanw 	 * Therefore, we help out here.
    133  1.12.6.3  nathanw 	 */
    134  1.12.6.3  nathanw 	if (IS_BREAKPOINT_TRAP(type, 0)) {
    135  1.12.6.3  nathanw 		int bkpt;
    136  1.12.6.3  nathanw 		db_read_bytes(PC_REGS(DDB_REGS),BKPT_SIZE,(void *)&bkpt);
    137  1.12.6.3  nathanw 		if (bkpt== BKPT_INST) {
    138  1.12.6.3  nathanw 			PC_REGS(DDB_REGS) += BKPT_SIZE;
    139  1.12.6.3  nathanw 		}
    140  1.12.6.3  nathanw 	}
    141  1.12.6.2  nathanw 
    142  1.12.6.2  nathanw 	memcpy(frame->fixreg, DDB_REGS->r, 32 * sizeof(u_int32_t));
    143  1.12.6.2  nathanw 	frame->srr0 = DDB_REGS->iar;
    144  1.12.6.2  nathanw 	frame->srr1 = DDB_REGS->msr;
    145  1.12.6.2  nathanw 	frame->lr = DDB_REGS->lr;
    146  1.12.6.2  nathanw 	frame->ctr = DDB_REGS->ctr;
    147  1.12.6.2  nathanw 	frame->cr = DDB_REGS->cr;
    148  1.12.6.2  nathanw 	frame->xer = DDB_REGS->xer;
    149  1.12.6.2  nathanw #ifdef PPC_IBM4XX
    150  1.12.6.2  nathanw 	frame->dear = DDB_REGS->dear;
    151  1.12.6.2  nathanw 	frame->esr = DDB_REGS->esr;
    152  1.12.6.2  nathanw 	frame->pid = DDB_REGS->pid;
    153  1.12.6.2  nathanw #endif
    154  1.12.6.2  nathanw 
    155  1.12.6.2  nathanw 	return 1;
    156  1.12.6.2  nathanw }
    157  1.12.6.2  nathanw 
    158  1.12.6.2  nathanw #ifdef PPC_IBM4XX
    159  1.12.6.2  nathanw const struct db_command db_machine_command_table[] = {
    160  1.12.6.2  nathanw 	{ "ctx",	db_ppc4xx_ctx,		0,	0 },
    161  1.12.6.2  nathanw 	{ "pv",		db_ppc4xx_pv,		0,	0 },
    162  1.12.6.2  nathanw 	{ "reset",	db_ppc4xx_reset,	0,	0 },
    163  1.12.6.2  nathanw 	{ "tf",		db_ppc4xx_tf,	0,	0 },
    164  1.12.6.2  nathanw 	{ "tlb",	db_ppc4xx_dumptlb,	0,	0 },
    165  1.12.6.2  nathanw #ifdef USERACC
    166  1.12.6.2  nathanw 	{ "user",	db_ppc4xx_useracc,	0,	0 },
    167  1.12.6.2  nathanw #endif
    168  1.12.6.2  nathanw 	{ NULL, }
    169  1.12.6.2  nathanw };
    170  1.12.6.2  nathanw 
    171  1.12.6.2  nathanw static void
    172  1.12.6.2  nathanw db_ppc4xx_ctx(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
    173  1.12.6.2  nathanw {
    174  1.12.6.2  nathanw 	struct proc *p;
    175  1.12.6.2  nathanw 
    176  1.12.6.2  nathanw 	/* XXX LOCKING XXX */
    177  1.12.6.2  nathanw 	for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
    178  1.12.6.2  nathanw 		if (p->p_stat) {
    179  1.12.6.2  nathanw 			db_printf("process %p:", p);
    180  1.12.6.2  nathanw 			db_printf("pid:%d pmap:%p ctx:%d %s\n",
    181  1.12.6.2  nathanw 				p->p_pid, p->p_vmspace->vm_map.pmap,
    182  1.12.6.2  nathanw 				p->p_vmspace->vm_map.pmap->pm_ctx,
    183  1.12.6.2  nathanw 				p->p_comm);
    184  1.12.6.2  nathanw 		}
    185  1.12.6.2  nathanw 	}
    186  1.12.6.2  nathanw 	return;
    187  1.12.6.2  nathanw }
    188  1.12.6.2  nathanw 
    189  1.12.6.2  nathanw static void
    190  1.12.6.2  nathanw db_ppc4xx_pv(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
    191  1.12.6.2  nathanw {
    192  1.12.6.2  nathanw 	struct pv_entry {
    193  1.12.6.2  nathanw 		struct pv_entry *pv_next;	/* Linked list of mappings */
    194  1.12.6.2  nathanw 		vaddr_t pv_va;			/* virtual address of mapping */
    195  1.12.6.2  nathanw 		struct pmap *pv_pm;
    196  1.12.6.2  nathanw 	};
    197  1.12.6.2  nathanw 	struct pv_entry *pa_to_pv(paddr_t);
    198  1.12.6.2  nathanw 	struct pv_entry *pv;
    199  1.12.6.2  nathanw 
    200  1.12.6.2  nathanw 	if (!have_addr) {
    201  1.12.6.2  nathanw 		db_printf("pv: <pa>\n");
    202  1.12.6.2  nathanw 		return;
    203  1.12.6.2  nathanw 	}
    204  1.12.6.2  nathanw 	pv = pa_to_pv(addr);
    205  1.12.6.2  nathanw 	db_printf("pv at %p\n", pv);
    206  1.12.6.2  nathanw 	while (pv && pv->pv_pm) {
    207  1.12.6.2  nathanw 		db_printf("next %p va %p pmap %p\n", pv->pv_next,
    208  1.12.6.2  nathanw 			(void *)pv->pv_va, pv->pv_pm);
    209  1.12.6.2  nathanw 		pv = pv->pv_next;
    210  1.12.6.2  nathanw 	}
    211  1.12.6.2  nathanw }
    212  1.12.6.2  nathanw 
    213  1.12.6.2  nathanw static void
    214  1.12.6.2  nathanw db_ppc4xx_reset(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
    215  1.12.6.2  nathanw {
    216  1.12.6.2  nathanw 	printf("Reseting...\n");
    217  1.12.6.2  nathanw 	ppc4xx_reset();
    218  1.12.6.2  nathanw }
    219  1.12.6.2  nathanw 
    220  1.12.6.2  nathanw static void
    221  1.12.6.2  nathanw db_ppc4xx_tf(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
    222  1.12.6.2  nathanw {
    223  1.12.6.2  nathanw 	struct trapframe *f;
    224  1.12.6.2  nathanw 
    225  1.12.6.2  nathanw 
    226  1.12.6.2  nathanw 	if (have_addr) {
    227  1.12.6.2  nathanw 		f = (struct trapframe *)addr;
    228  1.12.6.2  nathanw 
    229  1.12.6.2  nathanw 		db_printf("r0-r3:  \t%8.8x %8.8x %8.8x %8.8x\n",
    230  1.12.6.2  nathanw 			f->fixreg[0], f->fixreg[1],
    231  1.12.6.2  nathanw 			f->fixreg[2], f->fixreg[3]);
    232  1.12.6.2  nathanw 		db_printf("r4-r7:  \t%8.8x %8.8x %8.8x %8.8x\n",
    233  1.12.6.2  nathanw 			f->fixreg[4], f->fixreg[5],
    234  1.12.6.2  nathanw 			f->fixreg[6], f->fixreg[7]);
    235  1.12.6.2  nathanw 		db_printf("r8-r11: \t%8.8x %8.8x %8.8x %8.8x\n",
    236  1.12.6.2  nathanw 			f->fixreg[8], f->fixreg[9],
    237  1.12.6.2  nathanw 			f->fixreg[10], f->fixreg[11]);
    238  1.12.6.2  nathanw 		db_printf("r12-r15:\t%8.8x %8.8x %8.8x %8.8x\n",
    239  1.12.6.2  nathanw 			f->fixreg[12], f->fixreg[13],
    240  1.12.6.2  nathanw 			f->fixreg[14], f->fixreg[15]);
    241  1.12.6.2  nathanw 		db_printf("r16-r19:\t%8.8x %8.8x %8.8x %8.8x\n",
    242  1.12.6.2  nathanw 			f->fixreg[16], f->fixreg[17],
    243  1.12.6.2  nathanw 			f->fixreg[18], f->fixreg[19]);
    244  1.12.6.2  nathanw 		db_printf("r20-r23:\t%8.8x %8.8x %8.8x %8.8x\n",
    245  1.12.6.2  nathanw 			f->fixreg[20], f->fixreg[21],
    246  1.12.6.2  nathanw 			f->fixreg[22], f->fixreg[23]);
    247  1.12.6.2  nathanw 		db_printf("r24-r27:\t%8.8x %8.8x %8.8x %8.8x\n",
    248  1.12.6.2  nathanw 			f->fixreg[24], f->fixreg[25],
    249  1.12.6.2  nathanw 			f->fixreg[26], f->fixreg[27]);
    250  1.12.6.2  nathanw 		db_printf("r28-r31:\t%8.8x %8.8x %8.8x %8.8x\n",
    251  1.12.6.2  nathanw 			f->fixreg[28], f->fixreg[29],
    252  1.12.6.2  nathanw 			f->fixreg[30], f->fixreg[31]);
    253  1.12.6.2  nathanw 
    254  1.12.6.2  nathanw 		db_printf("lr: %8.8x cr: %8.8x xer: %8.8x ctr: %8.8x\n",
    255  1.12.6.2  nathanw 			f->lr, f->cr, f->xer, f->ctr);
    256  1.12.6.2  nathanw 		db_printf("srr0(pc): %8.8x srr1(msr): %8.8x "
    257  1.12.6.2  nathanw 			"dear: %8.8x esr: %8.8x\n",
    258  1.12.6.2  nathanw 			f->srr0, f->srr1, f->dear, f->esr);
    259  1.12.6.2  nathanw 		db_printf("exc: %8.8x pid: %8.8x\n",
    260  1.12.6.2  nathanw 			f->exc, f->pid);
    261  1.12.6.2  nathanw 	}
    262  1.12.6.2  nathanw 	return;
    263  1.12.6.2  nathanw }
    264  1.12.6.2  nathanw 
    265  1.12.6.2  nathanw static const char *const tlbsizes[] = {
    266  1.12.6.2  nathanw 	  "1kB",
    267  1.12.6.2  nathanw 	  "4kB",
    268  1.12.6.2  nathanw 	 "16kB",
    269  1.12.6.2  nathanw 	 "64kB",
    270  1.12.6.2  nathanw 	"256kB",
    271  1.12.6.2  nathanw 	  "1MB",
    272  1.12.6.2  nathanw 	  "4MB",
    273  1.12.6.2  nathanw 	 "16MB"
    274  1.12.6.2  nathanw };
    275  1.12.6.2  nathanw 
    276  1.12.6.2  nathanw static void
    277  1.12.6.2  nathanw db_ppc4xx_dumptlb(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
    278  1.12.6.2  nathanw {
    279  1.12.6.2  nathanw 	int i, zone, tlbsize;
    280  1.12.6.2  nathanw 	u_int zpr, pid, opid, msr;
    281  1.12.6.2  nathanw 	u_long tlblo, tlbhi, tlbmask;
    282  1.12.6.2  nathanw 
    283  1.12.6.2  nathanw 	zpr = mfspr(SPR_ZPR);
    284  1.12.6.2  nathanw 	for (i = 0; i < NTLB; i++) {
    285  1.12.6.2  nathanw 		asm volatile("mfmsr %3;"
    286  1.12.6.2  nathanw 			"mfpid %4;"
    287  1.12.6.2  nathanw 			"li %0,0;"
    288  1.12.6.2  nathanw 			"mtmsr %0;"
    289  1.12.6.2  nathanw 			"sync; isync;"
    290  1.12.6.2  nathanw 			"tlbre %0,%5,1;"
    291  1.12.6.2  nathanw 			"tlbre %1,%5,0;"
    292  1.12.6.2  nathanw 			"mfpid %2;"
    293  1.12.6.2  nathanw 			"mtpid %4;"
    294  1.12.6.2  nathanw 			"mtmsr %3;"
    295  1.12.6.2  nathanw 			"sync; isync"
    296  1.12.6.2  nathanw 			: "=&r" (tlblo), "=&r" (tlbhi), "=r" (pid),
    297  1.12.6.2  nathanw 			"=&r" (msr), "=&r" (opid) : "r" (i));
    298  1.12.6.2  nathanw 
    299  1.12.6.2  nathanw 		if (strchr(modif, 'v') && !(tlbhi & TLB_VALID))
    300  1.12.6.2  nathanw 			continue;
    301  1.12.6.2  nathanw 
    302  1.12.6.2  nathanw 		tlbsize = (tlbhi & TLB_SIZE_MASK) >> TLB_SIZE_SHFT;
    303  1.12.6.2  nathanw 		/* map tlbsize 0 .. 7 to masks for 1kB .. 16MB */
    304  1.12.6.2  nathanw 		tlbmask = ~(1 << (tlbsize * 2 + 10)) + 1;
    305  1.12.6.2  nathanw 
    306  1.12.6.2  nathanw 		if (have_addr && ((tlbhi & tlbmask) != (addr & tlbmask)))
    307  1.12.6.2  nathanw 			continue;
    308  1.12.6.2  nathanw 
    309  1.12.6.2  nathanw 		zone = (tlblo & TLB_ZSEL_MASK) >> TLB_ZSEL_SHFT;
    310  1.12.6.2  nathanw 		db_printf("tlb%c%2d", tlbhi & TLB_VALID ? ' ' : '*', i);
    311  1.12.6.2  nathanw 		db_printf("  PID %3d EPN 0x%08lx %-5s",
    312  1.12.6.2  nathanw 		    pid,
    313  1.12.6.2  nathanw 		    tlbhi & tlbmask,
    314  1.12.6.2  nathanw 		    tlbsizes[tlbsize]);
    315  1.12.6.2  nathanw 		db_printf("  RPN 0x%08lx  ZONE %2d%c  %s %s %c%c%c%c%c %s",
    316  1.12.6.2  nathanw 		    tlblo & tlbmask,
    317  1.12.6.2  nathanw 		    zone,
    318  1.12.6.2  nathanw 		    "NTTA"[(zpr >> ((15 - zone) * 2)) & 3],
    319  1.12.6.2  nathanw 		    tlblo & TLB_EX ? "EX" : "  ",
    320  1.12.6.2  nathanw 		    tlblo & TLB_WR ? "WR" : "  ",
    321  1.12.6.2  nathanw 		    tlblo & TLB_W ? 'W' : ' ',
    322  1.12.6.2  nathanw 		    tlblo & TLB_I ? 'I' : ' ',
    323  1.12.6.2  nathanw 		    tlblo & TLB_M ? 'M' : ' ',
    324  1.12.6.2  nathanw 		    tlblo & TLB_G ? 'G' : ' ',
    325  1.12.6.2  nathanw 		    tlbhi & TLB_ENDIAN ? 'E' : ' ',
    326  1.12.6.2  nathanw 		    tlbhi & TLB_U0 ? "U0" : "  ");
    327  1.12.6.2  nathanw 		db_printf("\n");
    328  1.12.6.2  nathanw 	}
    329  1.12.6.2  nathanw }
    330  1.12.6.2  nathanw 
    331  1.12.6.2  nathanw #ifdef USERACC
    332  1.12.6.2  nathanw static void
    333  1.12.6.2  nathanw db_ppc4xx_useracc(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
    334  1.12.6.2  nathanw {
    335  1.12.6.2  nathanw 	static paddr_t oldaddr = -1;
    336  1.12.6.2  nathanw 	int instr = 0;
    337  1.12.6.2  nathanw 	int data;
    338  1.12.6.2  nathanw 	extern vaddr_t opc_disasm(vaddr_t loc, int);
    339  1.12.6.2  nathanw 
    340  1.12.6.2  nathanw 
    341  1.12.6.2  nathanw 	if (!have_addr) {
    342  1.12.6.2  nathanw 		addr = oldaddr;
    343  1.12.6.2  nathanw 	}
    344  1.12.6.2  nathanw 	if (addr == -1) {
    345  1.12.6.2  nathanw 		db_printf("no address\n");
    346  1.12.6.2  nathanw 		return;
    347  1.12.6.2  nathanw 	}
    348  1.12.6.2  nathanw 	addr &= ~0x3; /* align */
    349  1.12.6.2  nathanw 	{
    350  1.12.6.2  nathanw 		register char c, *cp = modif;
    351  1.12.6.2  nathanw 		while ((c = *cp++) != 0)
    352  1.12.6.2  nathanw 			if (c == 'i')
    353  1.12.6.2  nathanw 				instr = 1;
    354  1.12.6.2  nathanw 	}
    355  1.12.6.2  nathanw 	while (count--) {
    356  1.12.6.2  nathanw 		if (db_print_position() == 0) {
    357  1.12.6.2  nathanw 			/* Always print the address. */
    358  1.12.6.2  nathanw 			db_printf("%8.4lx:\t", addr);
    359  1.12.6.2  nathanw 		}
    360  1.12.6.2  nathanw 		oldaddr=addr;
    361  1.12.6.2  nathanw 		copyin((void *)addr, &data, sizeof(data));
    362  1.12.6.2  nathanw 		if (instr) {
    363  1.12.6.2  nathanw 			opc_disasm(addr, data);
    364  1.12.6.2  nathanw 		} else {
    365  1.12.6.2  nathanw 			db_printf("%4.4x\n", data);
    366  1.12.6.2  nathanw 		}
    367  1.12.6.2  nathanw 		addr += 4;
    368  1.12.6.2  nathanw 		db_end_line();
    369  1.12.6.2  nathanw 	}
    370  1.12.6.2  nathanw 
    371  1.12.6.2  nathanw }
    372  1.12.6.2  nathanw #endif
    373  1.12.6.2  nathanw 
    374  1.12.6.2  nathanw #endif /* PPC_IBM4XX */
    375