Home | History | Annotate | Line # | Download | only in powerpc
db_interface.c revision 1.24
      1  1.24       scw /*	$NetBSD: db_interface.c,v 1.24 2002/12/20 15:23:12 scw Exp $ */
      2   1.1  sakamoto /*	$OpenBSD: db_interface.c,v 1.2 1996/12/28 06:21:50 rahnds Exp $	*/
      3   1.3  jonathan 
      4  1.10    simonb #define USERACC
      5  1.10    simonb 
      6   1.3  jonathan #include "opt_ddb.h"
      7  1.17       dbj #include "opt_kgdb.h"
      8  1.10    simonb #include "opt_ppcarch.h"
      9   1.1  sakamoto 
     10   1.1  sakamoto #include <sys/param.h>
     11   1.1  sakamoto #include <sys/proc.h>
     12   1.4    tsubai #include <sys/systm.h>
     13   1.6    kleink 
     14  1.11    simonb #include <dev/cons.h>
     15  1.11    simonb 
     16   1.7    tsubai #include <machine/db_machdep.h>
     17   1.7    tsubai #include <machine/frame.h>
     18  1.10    simonb #ifdef PPC_IBM4XX
     19  1.10    simonb #include <machine/tlb.h>
     20  1.10    simonb #include <powerpc/spr.h>
     21  1.10    simonb #include <uvm/uvm_extern.h>
     22  1.10    simonb #endif
     23   1.7    tsubai 
     24  1.17       dbj #ifdef DDB
     25   1.6    kleink #include <ddb/db_sym.h>
     26   1.6    kleink #include <ddb/db_command.h>
     27   1.6    kleink #include <ddb/db_extern.h>
     28   1.6    kleink #include <ddb/db_access.h>
     29  1.22       scw #include <ddb/db_lex.h>
     30   1.6    kleink #include <ddb/db_output.h>
     31   1.6    kleink #include <ddb/ddbvar.h>
     32  1.17       dbj #endif
     33  1.17       dbj 
     34  1.17       dbj #ifdef KGDB
     35  1.17       dbj #include <sys/kgdb.h>
     36  1.17       dbj #endif
     37  1.17       dbj 
     38  1.17       dbj #include <dev/ofw/openfirm.h>
     39   1.1  sakamoto 
     40  1.11    simonb int	db_active = 0;
     41  1.11    simonb 
     42  1.19      matt db_regs_t ddb_regs;
     43   1.8    tsubai 
     44  1.10    simonb void ddb_trap(void);				/* Call into trap_subr.S */
     45  1.10    simonb int ddb_trap_glue(struct trapframe *);		/* Called from trap_subr.S */
     46  1.10    simonb #ifdef PPC_IBM4XX
     47  1.10    simonb static void db_ppc4xx_ctx(db_expr_t, int, db_expr_t, char *);
     48  1.10    simonb static void db_ppc4xx_pv(db_expr_t, int, db_expr_t, char *);
     49  1.10    simonb static void db_ppc4xx_reset(db_expr_t, int, db_expr_t, char *);
     50  1.10    simonb static void db_ppc4xx_tf(db_expr_t, int, db_expr_t, char *);
     51  1.10    simonb static void db_ppc4xx_dumptlb(db_expr_t, int, db_expr_t, char *);
     52  1.22       scw static void db_ppc4xx_dcr(db_expr_t, int, db_expr_t, char *);
     53  1.22       scw static db_expr_t db_ppc4xx_mfdcr(db_expr_t);
     54  1.22       scw static void db_ppc4xx_mtdcr(db_expr_t, db_expr_t);
     55  1.10    simonb #ifdef USERACC
     56  1.10    simonb static void db_ppc4xx_useracc(db_expr_t, int, db_expr_t, char *);
     57  1.10    simonb #endif
     58  1.10    simonb #endif /* PPC_IBM4XX */
     59   1.9    briggs 
     60  1.17       dbj #ifdef DDB
     61   1.1  sakamoto void
     62   1.5  jdolecek cpu_Debugger()
     63   1.1  sakamoto {
     64   1.1  sakamoto 	ddb_trap();
     65   1.1  sakamoto }
     66  1.17       dbj #endif
     67   1.1  sakamoto 
     68   1.1  sakamoto int
     69   1.1  sakamoto ddb_trap_glue(frame)
     70   1.1  sakamoto 	struct trapframe *frame;
     71   1.1  sakamoto {
     72  1.24       scw #ifndef PPC_IBM4XX
     73   1.1  sakamoto 	if (!(frame->srr1 & PSL_PR)
     74  1.18    kleink 	    && (frame->exc == EXC_TRC || frame->exc == EXC_RUNMODETRC
     75   1.1  sakamoto 		|| (frame->exc == EXC_PGM
     76   1.1  sakamoto 		    && (frame->srr1 & 0x20000))
     77   1.1  sakamoto 		|| frame->exc == EXC_BPT)) {
     78  1.17       dbj 		int type = frame->exc;
     79  1.17       dbj 		if (type == EXC_PGM && (frame->srr1 & 0x20000)) {
     80  1.17       dbj 			type = T_BREAKPOINT;
     81  1.17       dbj 		}
     82  1.17       dbj 		return kdb_trap(type, frame);
     83   1.1  sakamoto 	}
     84   1.1  sakamoto 	return 0;
     85  1.24       scw #else
     86  1.24       scw 	return kdb_trap(frame->exc, frame);
     87  1.24       scw #endif
     88   1.8    tsubai }
     89   1.8    tsubai 
     90   1.8    tsubai int
     91   1.8    tsubai kdb_trap(type, v)
     92   1.8    tsubai 	int type;
     93   1.8    tsubai 	void *v;
     94   1.8    tsubai {
     95   1.8    tsubai 	struct trapframe *frame = v;
     96   1.8    tsubai 
     97  1.17       dbj #ifdef DDB
     98   1.8    tsubai 	switch (type) {
     99   1.8    tsubai 	case T_BREAKPOINT:
    100   1.8    tsubai 	case -1:
    101   1.8    tsubai 		break;
    102   1.8    tsubai 	default:
    103   1.8    tsubai 		if (!db_onpanic && db_recover == 0)
    104   1.8    tsubai 			return 0;
    105   1.8    tsubai 		if (db_recover != 0) {
    106   1.8    tsubai 			db_error("Faulted in DDB; continuing...\n");
    107   1.8    tsubai 			/*NOTREACHED*/
    108   1.8    tsubai 		}
    109   1.8    tsubai 	}
    110  1.17       dbj #endif
    111   1.8    tsubai 
    112   1.8    tsubai 	/* XXX Should switch to kdb's own stack here. */
    113   1.8    tsubai 
    114  1.12       wiz 	memcpy(DDB_REGS->r, frame->fixreg, 32 * sizeof(u_int32_t));
    115   1.8    tsubai 	DDB_REGS->iar = frame->srr0;
    116   1.8    tsubai 	DDB_REGS->msr = frame->srr1;
    117  1.10    simonb 	DDB_REGS->lr = frame->lr;
    118  1.10    simonb 	DDB_REGS->ctr = frame->ctr;
    119  1.10    simonb 	DDB_REGS->cr = frame->cr;
    120  1.10    simonb 	DDB_REGS->xer = frame->xer;
    121  1.16       dbj #ifdef PPC_IBM4XX
    122  1.10    simonb 	DDB_REGS->dear = frame->dear;
    123  1.10    simonb 	DDB_REGS->esr = frame->esr;
    124  1.10    simonb 	DDB_REGS->pid = frame->pid;
    125  1.10    simonb #endif
    126   1.8    tsubai 
    127  1.17       dbj #ifdef DDB
    128  1.11    simonb 	db_active++;
    129  1.11    simonb 	cnpollc(1);
    130  1.15       dbj 	db_trap(type, 0);
    131  1.11    simonb 	cnpollc(0);
    132  1.11    simonb 	db_active--;
    133  1.17       dbj #elif defined(KGDB)
    134  1.17       dbj 	if (!kgdb_trap(type, DDB_REGS))
    135  1.17       dbj 		return 0;
    136  1.17       dbj #endif
    137  1.17       dbj 
    138  1.17       dbj 	/* KGDB isn't smart about advancing PC if we
    139  1.17       dbj 	 * take a breakpoint trap after kgdb_active is set.
    140  1.17       dbj 	 * Therefore, we help out here.
    141  1.17       dbj 	 */
    142  1.17       dbj 	if (IS_BREAKPOINT_TRAP(type, 0)) {
    143  1.17       dbj 		int bkpt;
    144  1.17       dbj 		db_read_bytes(PC_REGS(DDB_REGS),BKPT_SIZE,(void *)&bkpt);
    145  1.17       dbj 		if (bkpt== BKPT_INST) {
    146  1.17       dbj 			PC_REGS(DDB_REGS) += BKPT_SIZE;
    147  1.17       dbj 		}
    148  1.17       dbj 	}
    149   1.8    tsubai 
    150  1.12       wiz 	memcpy(frame->fixreg, DDB_REGS->r, 32 * sizeof(u_int32_t));
    151   1.8    tsubai 	frame->srr0 = DDB_REGS->iar;
    152   1.8    tsubai 	frame->srr1 = DDB_REGS->msr;
    153  1.10    simonb 	frame->lr = DDB_REGS->lr;
    154  1.10    simonb 	frame->ctr = DDB_REGS->ctr;
    155  1.10    simonb 	frame->cr = DDB_REGS->cr;
    156  1.10    simonb 	frame->xer = DDB_REGS->xer;
    157  1.16       dbj #ifdef PPC_IBM4XX
    158  1.10    simonb 	frame->dear = DDB_REGS->dear;
    159  1.10    simonb 	frame->esr = DDB_REGS->esr;
    160  1.10    simonb 	frame->pid = DDB_REGS->pid;
    161  1.10    simonb #endif
    162   1.8    tsubai 
    163   1.8    tsubai 	return 1;
    164   1.1  sakamoto }
    165  1.10    simonb 
    166  1.10    simonb #ifdef PPC_IBM4XX
    167  1.24       scw db_addr_t
    168  1.24       scw branch_taken(int inst, db_addr_t pc, db_regs_t *regs)
    169  1.24       scw {
    170  1.24       scw 
    171  1.24       scw 	if ((inst & M_B ) == I_B || (inst & M_B ) == I_BL) {
    172  1.24       scw 		db_expr_t off;
    173  1.24       scw 		off = ((db_expr_t)((inst & 0x03fffffc) << 6)) >> 6;
    174  1.24       scw 		return (((inst & 0x2) ? 0 : pc) + off);
    175  1.24       scw 	}
    176  1.24       scw 
    177  1.24       scw 	if ((inst & M_BC) == I_BC || (inst & M_BC) == I_BCL) {
    178  1.24       scw 		db_expr_t off;
    179  1.24       scw 		off = ((db_expr_t)((inst & 0x0000fffc) << 16)) >> 16;
    180  1.24       scw 		return (((inst & 0x2) ? 0 : pc) + off);
    181  1.24       scw 	}
    182  1.24       scw 
    183  1.24       scw 	if ((inst & M_RTS) == I_RTS || (inst & M_RTS) == I_BLRL)
    184  1.24       scw 		return (regs->lr);
    185  1.24       scw 
    186  1.24       scw 	if ((inst & M_BCTR) == I_BCTR || (inst & M_BCTR) == I_BCTRL)
    187  1.24       scw 		return (regs->ctr);
    188  1.24       scw 
    189  1.24       scw 	db_printf("branch_taken: can't figure out branch target for 0x%x!\n",
    190  1.24       scw 	    inst);
    191  1.24       scw 	return (0);
    192  1.24       scw }
    193  1.24       scw 
    194  1.10    simonb const struct db_command db_machine_command_table[] = {
    195  1.10    simonb 	{ "ctx",	db_ppc4xx_ctx,		0,	0 },
    196  1.10    simonb 	{ "pv",		db_ppc4xx_pv,		0,	0 },
    197  1.10    simonb 	{ "reset",	db_ppc4xx_reset,	0,	0 },
    198  1.22       scw 	{ "tf",		db_ppc4xx_tf,		0,	0 },
    199  1.10    simonb 	{ "tlb",	db_ppc4xx_dumptlb,	0,	0 },
    200  1.22       scw 	{ "dcr",	db_ppc4xx_dcr,		CS_MORE|CS_SET_DOT,	0 },
    201  1.10    simonb #ifdef USERACC
    202  1.10    simonb 	{ "user",	db_ppc4xx_useracc,	0,	0 },
    203  1.10    simonb #endif
    204  1.10    simonb 	{ NULL, }
    205  1.10    simonb };
    206  1.10    simonb 
    207  1.10    simonb static void
    208  1.10    simonb db_ppc4xx_ctx(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
    209  1.10    simonb {
    210  1.10    simonb 	struct proc *p;
    211  1.10    simonb 
    212  1.10    simonb 	/* XXX LOCKING XXX */
    213  1.10    simonb 	for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
    214  1.10    simonb 		if (p->p_stat) {
    215  1.10    simonb 			db_printf("process %p:", p);
    216  1.10    simonb 			db_printf("pid:%d pmap:%p ctx:%d %s\n",
    217  1.10    simonb 				p->p_pid, p->p_vmspace->vm_map.pmap,
    218  1.10    simonb 				p->p_vmspace->vm_map.pmap->pm_ctx,
    219  1.10    simonb 				p->p_comm);
    220  1.10    simonb 		}
    221  1.10    simonb 	}
    222  1.10    simonb 	return;
    223  1.10    simonb }
    224  1.10    simonb 
    225  1.10    simonb static void
    226  1.10    simonb db_ppc4xx_pv(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
    227  1.10    simonb {
    228  1.10    simonb 	struct pv_entry {
    229  1.10    simonb 		struct pv_entry *pv_next;	/* Linked list of mappings */
    230  1.10    simonb 		vaddr_t pv_va;			/* virtual address of mapping */
    231  1.10    simonb 		struct pmap *pv_pm;
    232  1.10    simonb 	};
    233  1.10    simonb 	struct pv_entry *pa_to_pv(paddr_t);
    234  1.10    simonb 	struct pv_entry *pv;
    235  1.10    simonb 
    236  1.10    simonb 	if (!have_addr) {
    237  1.10    simonb 		db_printf("pv: <pa>\n");
    238  1.10    simonb 		return;
    239  1.10    simonb 	}
    240  1.10    simonb 	pv = pa_to_pv(addr);
    241  1.10    simonb 	db_printf("pv at %p\n", pv);
    242  1.10    simonb 	while (pv && pv->pv_pm) {
    243  1.10    simonb 		db_printf("next %p va %p pmap %p\n", pv->pv_next,
    244  1.10    simonb 			(void *)pv->pv_va, pv->pv_pm);
    245  1.10    simonb 		pv = pv->pv_next;
    246  1.10    simonb 	}
    247  1.10    simonb }
    248  1.10    simonb 
    249  1.10    simonb static void
    250  1.10    simonb db_ppc4xx_reset(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
    251  1.10    simonb {
    252  1.10    simonb 	printf("Reseting...\n");
    253  1.10    simonb 	ppc4xx_reset();
    254  1.10    simonb }
    255  1.10    simonb 
    256  1.10    simonb static void
    257  1.10    simonb db_ppc4xx_tf(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
    258  1.10    simonb {
    259  1.10    simonb 	struct trapframe *f;
    260  1.10    simonb 
    261  1.10    simonb 
    262  1.10    simonb 	if (have_addr) {
    263  1.10    simonb 		f = (struct trapframe *)addr;
    264  1.10    simonb 
    265  1.10    simonb 		db_printf("r0-r3:  \t%8.8x %8.8x %8.8x %8.8x\n",
    266  1.10    simonb 			f->fixreg[0], f->fixreg[1],
    267  1.10    simonb 			f->fixreg[2], f->fixreg[3]);
    268  1.10    simonb 		db_printf("r4-r7:  \t%8.8x %8.8x %8.8x %8.8x\n",
    269  1.10    simonb 			f->fixreg[4], f->fixreg[5],
    270  1.10    simonb 			f->fixreg[6], f->fixreg[7]);
    271  1.10    simonb 		db_printf("r8-r11: \t%8.8x %8.8x %8.8x %8.8x\n",
    272  1.10    simonb 			f->fixreg[8], f->fixreg[9],
    273  1.10    simonb 			f->fixreg[10], f->fixreg[11]);
    274  1.10    simonb 		db_printf("r12-r15:\t%8.8x %8.8x %8.8x %8.8x\n",
    275  1.10    simonb 			f->fixreg[12], f->fixreg[13],
    276  1.10    simonb 			f->fixreg[14], f->fixreg[15]);
    277  1.10    simonb 		db_printf("r16-r19:\t%8.8x %8.8x %8.8x %8.8x\n",
    278  1.10    simonb 			f->fixreg[16], f->fixreg[17],
    279  1.10    simonb 			f->fixreg[18], f->fixreg[19]);
    280  1.10    simonb 		db_printf("r20-r23:\t%8.8x %8.8x %8.8x %8.8x\n",
    281  1.10    simonb 			f->fixreg[20], f->fixreg[21],
    282  1.10    simonb 			f->fixreg[22], f->fixreg[23]);
    283  1.10    simonb 		db_printf("r24-r27:\t%8.8x %8.8x %8.8x %8.8x\n",
    284  1.10    simonb 			f->fixreg[24], f->fixreg[25],
    285  1.10    simonb 			f->fixreg[26], f->fixreg[27]);
    286  1.10    simonb 		db_printf("r28-r31:\t%8.8x %8.8x %8.8x %8.8x\n",
    287  1.10    simonb 			f->fixreg[28], f->fixreg[29],
    288  1.10    simonb 			f->fixreg[30], f->fixreg[31]);
    289  1.10    simonb 
    290  1.10    simonb 		db_printf("lr: %8.8x cr: %8.8x xer: %8.8x ctr: %8.8x\n",
    291  1.10    simonb 			f->lr, f->cr, f->xer, f->ctr);
    292  1.10    simonb 		db_printf("srr0(pc): %8.8x srr1(msr): %8.8x "
    293  1.10    simonb 			"dear: %8.8x esr: %8.8x\n",
    294  1.10    simonb 			f->srr0, f->srr1, f->dear, f->esr);
    295  1.10    simonb 		db_printf("exc: %8.8x pid: %8.8x\n",
    296  1.10    simonb 			f->exc, f->pid);
    297  1.10    simonb 	}
    298  1.10    simonb 	return;
    299  1.10    simonb }
    300  1.10    simonb 
    301  1.10    simonb static const char *const tlbsizes[] = {
    302  1.10    simonb 	  "1kB",
    303  1.10    simonb 	  "4kB",
    304  1.10    simonb 	 "16kB",
    305  1.10    simonb 	 "64kB",
    306  1.10    simonb 	"256kB",
    307  1.10    simonb 	  "1MB",
    308  1.10    simonb 	  "4MB",
    309  1.10    simonb 	 "16MB"
    310  1.10    simonb };
    311  1.10    simonb 
    312  1.10    simonb static void
    313  1.10    simonb db_ppc4xx_dumptlb(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
    314  1.10    simonb {
    315  1.10    simonb 	int i, zone, tlbsize;
    316  1.10    simonb 	u_int zpr, pid, opid, msr;
    317  1.10    simonb 	u_long tlblo, tlbhi, tlbmask;
    318  1.10    simonb 
    319  1.10    simonb 	zpr = mfspr(SPR_ZPR);
    320  1.10    simonb 	for (i = 0; i < NTLB; i++) {
    321  1.10    simonb 		asm volatile("mfmsr %3;"
    322  1.10    simonb 			"mfpid %4;"
    323  1.10    simonb 			"li %0,0;"
    324  1.10    simonb 			"mtmsr %0;"
    325  1.10    simonb 			"sync; isync;"
    326  1.21   thorpej 			"tlbrelo %0,%5;"
    327  1.21   thorpej 			"tlbrehi %1,%5;"
    328  1.10    simonb 			"mfpid %2;"
    329  1.10    simonb 			"mtpid %4;"
    330  1.10    simonb 			"mtmsr %3;"
    331  1.10    simonb 			"sync; isync"
    332  1.10    simonb 			: "=&r" (tlblo), "=&r" (tlbhi), "=r" (pid),
    333  1.10    simonb 			"=&r" (msr), "=&r" (opid) : "r" (i));
    334  1.10    simonb 
    335  1.10    simonb 		if (strchr(modif, 'v') && !(tlbhi & TLB_VALID))
    336  1.10    simonb 			continue;
    337  1.10    simonb 
    338  1.10    simonb 		tlbsize = (tlbhi & TLB_SIZE_MASK) >> TLB_SIZE_SHFT;
    339  1.10    simonb 		/* map tlbsize 0 .. 7 to masks for 1kB .. 16MB */
    340  1.10    simonb 		tlbmask = ~(1 << (tlbsize * 2 + 10)) + 1;
    341  1.10    simonb 
    342  1.10    simonb 		if (have_addr && ((tlbhi & tlbmask) != (addr & tlbmask)))
    343  1.10    simonb 			continue;
    344  1.10    simonb 
    345  1.10    simonb 		zone = (tlblo & TLB_ZSEL_MASK) >> TLB_ZSEL_SHFT;
    346  1.10    simonb 		db_printf("tlb%c%2d", tlbhi & TLB_VALID ? ' ' : '*', i);
    347  1.10    simonb 		db_printf("  PID %3d EPN 0x%08lx %-5s",
    348  1.10    simonb 		    pid,
    349  1.10    simonb 		    tlbhi & tlbmask,
    350  1.10    simonb 		    tlbsizes[tlbsize]);
    351  1.10    simonb 		db_printf("  RPN 0x%08lx  ZONE %2d%c  %s %s %c%c%c%c%c %s",
    352  1.10    simonb 		    tlblo & tlbmask,
    353  1.10    simonb 		    zone,
    354  1.10    simonb 		    "NTTA"[(zpr >> ((15 - zone) * 2)) & 3],
    355  1.10    simonb 		    tlblo & TLB_EX ? "EX" : "  ",
    356  1.10    simonb 		    tlblo & TLB_WR ? "WR" : "  ",
    357  1.10    simonb 		    tlblo & TLB_W ? 'W' : ' ',
    358  1.10    simonb 		    tlblo & TLB_I ? 'I' : ' ',
    359  1.10    simonb 		    tlblo & TLB_M ? 'M' : ' ',
    360  1.10    simonb 		    tlblo & TLB_G ? 'G' : ' ',
    361  1.10    simonb 		    tlbhi & TLB_ENDIAN ? 'E' : ' ',
    362  1.10    simonb 		    tlbhi & TLB_U0 ? "U0" : "  ");
    363  1.10    simonb 		db_printf("\n");
    364  1.10    simonb 	}
    365  1.22       scw }
    366  1.22       scw 
    367  1.22       scw static void
    368  1.22       scw db_ppc4xx_dcr(db_expr_t address, int have_addr, db_expr_t count, char *modif)
    369  1.22       scw {
    370  1.22       scw 	db_expr_t new_value;
    371  1.22       scw 	db_expr_t addr;
    372  1.23       scw 
    373  1.23       scw 	if (address < 0 || address > 0x3ff)
    374  1.23       scw 		db_error("Invalid DCR address (Valid range is 0x0 - 0x3ff)\n");
    375  1.22       scw 
    376  1.22       scw 	addr = address;
    377  1.22       scw 
    378  1.22       scw 	while (db_expression(&new_value)) {
    379  1.22       scw 		db_printf("dcr 0x%lx\t\t%s = ", addr,
    380  1.22       scw 		    db_num_to_str(db_ppc4xx_mfdcr(addr)));
    381  1.22       scw 		db_ppc4xx_mtdcr(addr, new_value);
    382  1.22       scw 		db_printf("%s\n", db_num_to_str(db_ppc4xx_mfdcr(addr)));
    383  1.22       scw 		addr += 1;
    384  1.22       scw 	}
    385  1.22       scw 
    386  1.22       scw 	if (addr == address) {
    387  1.22       scw 		db_next = (db_addr_t)addr + 1;
    388  1.22       scw 		db_prev = (db_addr_t)addr;
    389  1.22       scw 		db_printf("dcr 0x%lx\t\t%s\n", addr,
    390  1.22       scw 		    db_num_to_str(db_ppc4xx_mfdcr(addr)));
    391  1.22       scw 	} else {
    392  1.22       scw 		db_next = (db_addr_t)addr;
    393  1.22       scw 		db_prev = (db_addr_t)addr - 1;
    394  1.22       scw 	}
    395  1.22       scw 
    396  1.22       scw 	db_skip_to_eol();
    397  1.22       scw }
    398  1.22       scw 
    399  1.22       scw /*
    400  1.22       scw  * XXX Grossness Alert! XXX
    401  1.22       scw  *
    402  1.22       scw  * Please look away now if you don't like self-modifying code
    403  1.22       scw  */
    404  1.22       scw static u_int32_t db_ppc4xx_dcrfunc[4];
    405  1.22       scw 
    406  1.22       scw static db_expr_t
    407  1.22       scw db_ppc4xx_mfdcr(db_expr_t reg)
    408  1.22       scw {
    409  1.22       scw 	db_expr_t (*func)(void);
    410  1.22       scw 
    411  1.22       scw 	reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
    412  1.22       scw 	db_ppc4xx_dcrfunc[0] = 0x7c0004ac;		/* sync */
    413  1.22       scw 	db_ppc4xx_dcrfunc[1] = 0x4c00012c;		/* isync */
    414  1.22       scw 	db_ppc4xx_dcrfunc[2] = 0x7c600286 | reg;	/* mfdcr reg, r3 */
    415  1.22       scw 	db_ppc4xx_dcrfunc[3] = 0x4e800020;		/* blr */
    416  1.22       scw 
    417  1.22       scw 	__syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
    418  1.22       scw 	func = (db_expr_t (*)(void))(void *)db_ppc4xx_dcrfunc;
    419  1.22       scw 
    420  1.22       scw 	return ((*func)());
    421  1.22       scw }
    422  1.22       scw 
    423  1.22       scw static void
    424  1.22       scw db_ppc4xx_mtdcr(db_expr_t reg, db_expr_t val)
    425  1.22       scw {
    426  1.22       scw 	db_expr_t (*func)(db_expr_t);
    427  1.22       scw 
    428  1.22       scw 	reg = (((reg & 0x1f) << 5) | ((reg >> 5) & 0x1f)) << 11;
    429  1.22       scw 	db_ppc4xx_dcrfunc[0] = 0x7c0004ac;		/* sync */
    430  1.22       scw 	db_ppc4xx_dcrfunc[1] = 0x4c00012c;		/* isync */
    431  1.22       scw 	db_ppc4xx_dcrfunc[2] = 0x7c600386 | reg;	/* mtdcr r3, reg */
    432  1.22       scw 	db_ppc4xx_dcrfunc[3] = 0x4e800020;		/* blr */
    433  1.22       scw 
    434  1.22       scw 	__syncicache((void *)db_ppc4xx_dcrfunc, sizeof(db_ppc4xx_dcrfunc));
    435  1.22       scw 	func = (db_expr_t (*)(db_expr_t))(void *)db_ppc4xx_dcrfunc;
    436  1.22       scw 
    437  1.22       scw 	(*func)(val);
    438  1.10    simonb }
    439  1.10    simonb 
    440  1.10    simonb #ifdef USERACC
    441  1.10    simonb static void
    442  1.10    simonb db_ppc4xx_useracc(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
    443  1.10    simonb {
    444  1.10    simonb 	static paddr_t oldaddr = -1;
    445  1.10    simonb 	int instr = 0;
    446  1.10    simonb 	int data;
    447  1.10    simonb 	extern vaddr_t opc_disasm(vaddr_t loc, int);
    448  1.10    simonb 
    449  1.10    simonb 
    450  1.10    simonb 	if (!have_addr) {
    451  1.10    simonb 		addr = oldaddr;
    452  1.10    simonb 	}
    453  1.10    simonb 	if (addr == -1) {
    454  1.10    simonb 		db_printf("no address\n");
    455  1.10    simonb 		return;
    456  1.10    simonb 	}
    457  1.10    simonb 	addr &= ~0x3; /* align */
    458  1.10    simonb 	{
    459  1.10    simonb 		register char c, *cp = modif;
    460  1.10    simonb 		while ((c = *cp++) != 0)
    461  1.10    simonb 			if (c == 'i')
    462  1.10    simonb 				instr = 1;
    463  1.10    simonb 	}
    464  1.10    simonb 	while (count--) {
    465  1.10    simonb 		if (db_print_position() == 0) {
    466  1.10    simonb 			/* Always print the address. */
    467  1.10    simonb 			db_printf("%8.4lx:\t", addr);
    468  1.10    simonb 		}
    469  1.10    simonb 		oldaddr=addr;
    470  1.10    simonb 		copyin((void *)addr, &data, sizeof(data));
    471  1.10    simonb 		if (instr) {
    472  1.10    simonb 			opc_disasm(addr, data);
    473  1.10    simonb 		} else {
    474  1.10    simonb 			db_printf("%4.4x\n", data);
    475  1.10    simonb 		}
    476  1.10    simonb 		addr += 4;
    477  1.10    simonb 		db_end_line();
    478  1.10    simonb 	}
    479  1.10    simonb 
    480  1.10    simonb }
    481  1.10    simonb #endif
    482  1.10    simonb 
    483  1.10    simonb #endif /* PPC_IBM4XX */
    484