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