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