patch-2.2.12 linux/arch/ppc/xmon/xmon.c
Next file: linux/arch/sparc/defconfig
Previous file: linux/arch/ppc/xmon/subr_prf.c
Back to the patch index
Back to the overall index
- Lines: 1324
- Date:
Wed Aug 25 17:29:46 1999
- Orig file:
v2.2.11/linux/arch/ppc/xmon/xmon.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.2.11/linux/arch/ppc/xmon/xmon.c linux/arch/ppc/xmon/xmon.c
@@ -0,0 +1,1323 @@
+/*
+ * Routines providing a simple monitor for use on the PowerMac.
+ *
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <asm/ptrace.h>
+#include <asm/string.h>
+#include "nonstdio.h"
+#include "privinst.h"
+
+#define scanhex xmon_scanhex
+#define skipbl xmon_skipbl
+
+static unsigned adrs;
+static int size = 1;
+static unsigned ndump = 64;
+static unsigned nidump = 16;
+static int termch;
+
+static u_int bus_error_jmp[100];
+#define setjmp xmon_setjmp
+#define longjmp xmon_longjmp
+
+/* Breakpoint stuff */
+struct bpt {
+ unsigned address;
+ unsigned instr;
+ unsigned count;
+ unsigned char enabled;
+};
+
+#define NBPTS 16
+static struct bpt bpts[NBPTS];
+static struct bpt dabr;
+static struct bpt iabr;
+static unsigned bpinstr = 0x7fe00008; /* trap */
+
+/* Prototypes */
+extern void (*debugger_fault_handler)(struct pt_regs *);
+static int cmds(struct pt_regs *);
+static int mread(unsigned, void *, int);
+static int mwrite(unsigned, void *, int);
+static void handle_fault(struct pt_regs *);
+static void byterev(unsigned char *, int);
+static void memex(void);
+static int bsesc(void);
+static void dump(void);
+static void prdump(unsigned, int);
+#ifdef __MWERKS__
+static void prndump(unsigned, int);
+static int nvreadb(unsigned);
+#endif
+static int ppc_inst_dump(unsigned, int);
+void print_address(unsigned);
+static int getsp(void);
+static void dump_hash_table(void);
+static void backtrace(struct pt_regs *);
+static void excprint(struct pt_regs *);
+static void prregs(struct pt_regs *);
+static void memops(int);
+static void memlocate(void);
+static void memzcan(void);
+static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
+int skipbl(void);
+int scanhex(unsigned *valp);
+static void scannl(void);
+static int hexdigit(int);
+void getstring(char *, int);
+static void flush_input(void);
+static int inchar(void);
+static void take_input(char *);
+/* static void openforth(void); */
+static unsigned read_spr(int);
+static void write_spr(int, unsigned);
+static void super_regs(void);
+static void remove_bpts(void);
+static void insert_bpts(void);
+static struct bpt *at_breakpoint(unsigned pc);
+static void bpt_cmds(void);
+
+extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
+extern void printf(const char *fmt, ...);
+extern int putchar(int ch);
+extern int setjmp(u_int *);
+extern void longjmp(u_int *, int);
+
+#define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
+
+static char *help_string = "\
+Commands:\n\
+ d dump bytes\n\
+ di dump instructions\n\
+ df dump float values\n\
+ dd dump double values\n\
+ e print exception information\n\
+ h dump hash table\n\
+ m examine/change memory\n\
+ mm move a block of memory\n\
+ ms set a block of memory\n\
+ md compare two blocks of memory\n\
+ r print registers\n\
+ S print special registers\n\
+ t print backtrace\n\
+ x exit monitor\n\
+";
+
+static int xmon_trace;
+#define SSTEP 1 /* stepping because of 's' command */
+#define BRSTEP 2 /* stepping over breakpoint */
+
+void
+xmon(struct pt_regs *excp)
+{
+ struct pt_regs regs;
+ int msr, cmd;
+
+ printk("Entering xmon kernel debugger.\n");
+
+ if (excp == NULL) {
+ asm volatile ("stw 0,0(%0)\n\
+ lwz 0,0(1)\n\
+ stw 0,4(%0)\n\
+ stmw 2,8(%0)" : : "b" (®s));
+ regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1];
+ regs.msr = get_msr();
+ regs.ctr = get_ctr();
+ regs.xer = get_xer();
+ regs.ccr = get_cr();
+ regs.trap = 0;
+ excp = ®s;
+ }
+
+ msr = get_msr();
+ set_msr(msr & ~0x8000); /* disable interrupts */
+ remove_bpts();
+ excprint(excp);
+ cmd = cmds(excp);
+ if (cmd == 's') {
+ xmon_trace = SSTEP;
+ excp->msr |= 0x400;
+ } else if (at_breakpoint(excp->nip)) {
+ xmon_trace = BRSTEP;
+ excp->msr |= 0x400;
+ } else {
+ xmon_trace = 0;
+ insert_bpts();
+ }
+ set_msr(msr); /* restore interrupt enable */
+}
+
+void
+xmon_irq(int irq, void *d, struct pt_regs *regs)
+{
+ printf("Keyboard interrupt\n");
+ xmon(regs);
+}
+
+int
+xmon_bpt(struct pt_regs *regs)
+{
+ struct bpt *bp;
+
+ bp = at_breakpoint(regs->nip);
+ if (!bp)
+ return 0;
+ if (bp->count) {
+ --bp->count;
+ remove_bpts();
+ excprint(regs);
+ xmon_trace = BRSTEP;
+ regs->msr |= 0x400;
+ } else {
+ xmon(regs);
+ }
+ return 1;
+}
+
+int
+xmon_sstep(struct pt_regs *regs)
+{
+ if (!xmon_trace)
+ return 0;
+ if (xmon_trace == BRSTEP) {
+ xmon_trace = 0;
+ insert_bpts();
+ } else {
+ xmon(regs);
+ }
+ return 1;
+}
+
+int
+xmon_dabr_match(struct pt_regs *regs)
+{
+ if (dabr.enabled && dabr.count) {
+ --dabr.count;
+ remove_bpts();
+ excprint(regs);
+ xmon_trace = BRSTEP;
+ regs->msr |= 0x400;
+ } else {
+ dabr.instr = regs->nip;
+ xmon(regs);
+ }
+ return 1;
+}
+
+int
+xmon_iabr_match(struct pt_regs *regs)
+{
+ if (iabr.enabled && iabr.count) {
+ --iabr.count;
+ remove_bpts();
+ excprint(regs);
+ xmon_trace = BRSTEP;
+ regs->msr |= 0x400;
+ } else {
+ xmon(regs);
+ }
+ return 1;
+}
+
+static struct bpt *
+at_breakpoint(unsigned pc)
+{
+ int i;
+ struct bpt *bp;
+
+ if (dabr.enabled && pc == dabr.instr)
+ return &dabr;
+ if (iabr.enabled && pc == iabr.address)
+ return &iabr;
+ bp = bpts;
+ for (i = 0; i < NBPTS; ++i, ++bp)
+ if (bp->enabled && pc == bp->address)
+ return bp;
+ return 0;
+}
+
+static void
+insert_bpts()
+{
+ int i;
+ struct bpt *bp;
+
+ bp = bpts;
+ for (i = 0; i < NBPTS; ++i, ++bp) {
+ if (!bp->enabled)
+ continue;
+ if (mread(bp->address, &bp->instr, 4) != 4
+ || mwrite(bp->address, &bpinstr, 4) != 4) {
+ printf("Couldn't insert breakpoint at %x, disabling\n",
+ bp->address);
+ bp->enabled = 0;
+ }
+ }
+ if (dabr.enabled)
+ set_dabr(dabr.address);
+ if (iabr.enabled)
+ set_iabr(iabr.address);
+}
+
+static void
+remove_bpts()
+{
+ int i;
+ struct bpt *bp;
+ unsigned instr;
+
+ set_dabr(0);
+ set_iabr(0);
+ bp = bpts;
+ for (i = 0; i < NBPTS; ++i, ++bp) {
+ if (!bp->enabled)
+ continue;
+ if (mread(bp->address, &instr, 4) == 4
+ && instr == bpinstr
+ && mwrite(bp->address, &bp->instr, 4) != 4)
+ printf("Couldn't remove breakpoint at %x\n",
+ bp->address);
+ }
+}
+
+static char *last_cmd;
+
+/* Command interpreting routine */
+static int
+cmds(struct pt_regs *excp)
+{
+ int cmd;
+
+ last_cmd = NULL;
+ for(;;) {
+ printf("mon> ");
+ fflush(stdout);
+ flush_input();
+ termch = 0;
+ cmd = skipbl();
+ if( cmd == '\n' ) {
+ if (last_cmd == NULL)
+ continue;
+ take_input(last_cmd);
+ last_cmd = NULL;
+ cmd = inchar();
+ }
+ switch (cmd) {
+ case 'm':
+ cmd = inchar();
+ switch (cmd) {
+ case 'm':
+ case 's':
+ case 'd':
+ memops(cmd);
+ break;
+ case 'l':
+ memlocate();
+ break;
+ case 'z':
+ memzcan();
+ break;
+ default:
+ termch = cmd;
+ memex();
+ }
+ break;
+ case 'd':
+ dump();
+ break;
+ case 'r':
+ if (excp != NULL)
+ prregs(excp); /* print regs */
+ break;
+ case 'e':
+ if (excp == NULL)
+ printf("No exception information\n");
+ else
+ excprint(excp);
+ break;
+ case 'S':
+ super_regs();
+ break;
+ case 't':
+ backtrace(excp);
+ break;
+#if 0
+ case 'f':
+ openforth();
+ break;
+#endif
+ case 'h':
+ dump_hash_table();
+ break;
+ case 's':
+ case 'x':
+ case EOF:
+ return cmd;
+ case '?':
+ printf(help_string);
+ break;
+ default:
+ printf("Unrecognized command: ");
+ if( ' ' < cmd && cmd <= '~' )
+ putchar(cmd);
+ else
+ printf("\\x%x", cmd);
+ printf(" (type ? for help)\n");
+ break;
+ case 'b':
+ bpt_cmds();
+ break;
+ }
+ }
+}
+
+static void
+bpt_cmds(void)
+{
+ int cmd;
+ unsigned a;
+ int mode, i;
+ struct bpt *bp;
+
+ cmd = inchar();
+ switch (cmd) {
+ case 'd':
+ mode = 7;
+ cmd = inchar();
+ if (cmd == 'r')
+ mode = 5;
+ else if (cmd == 'w')
+ mode = 6;
+ else
+ termch = cmd;
+ dabr.address = 0;
+ dabr.count = 0;
+ dabr.enabled = scanhex(&dabr.address);
+ scanhex(&dabr.count);
+ if (dabr.enabled)
+ dabr.address = (dabr.address & ~7) | mode;
+ break;
+ case 'i':
+ iabr.address = 0;
+ iabr.count = 0;
+ iabr.enabled = scanhex(&iabr.address);
+ if (iabr.enabled)
+ iabr.address |= 3;
+ scanhex(&iabr.count);
+ break;
+ case 'c':
+ if (!scanhex(&a)) {
+ /* clear all breakpoints */
+ for (i = 0; i < NBPTS; ++i)
+ bpts[i].enabled = 0;
+ iabr.enabled = 0;
+ dabr.enabled = 0;
+ printf("All breakpoints cleared\n");
+ } else {
+ bp = at_breakpoint(a);
+ if (bp == 0) {
+ printf("No breakpoint at %x\n", a);
+ } else {
+ bp->enabled = 0;
+ }
+ }
+ break;
+ default:
+ termch = cmd;
+ if (!scanhex(&a)) {
+ /* print all breakpoints */
+ printf("type address count\n");
+ if (dabr.enabled) {
+ printf("data %.8x %8x [", dabr.address & ~7,
+ dabr.count);
+ if (dabr.address & 1)
+ printf("r");
+ if (dabr.address & 2)
+ printf("w");
+ printf("]\n");
+ }
+ if (iabr.enabled)
+ printf("inst %.8x %8x\n", iabr.address & ~3,
+ iabr.count);
+ for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
+ if (bp->enabled)
+ printf("trap %.8x %8x\n", bp->address,
+ bp->count);
+ break;
+ }
+ bp = at_breakpoint(a);
+ if (bp == 0) {
+ for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
+ if (!bp->enabled)
+ break;
+ if (bp >= &bpts[NBPTS]) {
+ printf("Sorry, no free breakpoints\n");
+ break;
+ }
+ }
+ bp->enabled = 1;
+ bp->address = a;
+ bp->count = 0;
+ scanhex(&bp->count);
+ break;
+ }
+}
+
+static void
+backtrace(struct pt_regs *excp)
+{
+ unsigned sp;
+ unsigned stack[2];
+ struct pt_regs regs;
+ extern char int_return, syscall_ret_1, syscall_ret_2;
+ extern char lost_irq_ret, do_bottom_half_ret, do_signal_ret;
+
+ if (excp != NULL)
+ sp = excp->gpr[1];
+ else
+ sp = getsp();
+ scanhex(&sp);
+ scannl();
+ for (; sp != 0; sp = stack[0]) {
+ if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
+ break;
+ printf("%x ", stack[1]);
+ if (stack[1] == (unsigned) &int_return
+ || stack[1] == (unsigned) &syscall_ret_1
+ || stack[1] == (unsigned) &syscall_ret_2
+ || stack[1] == (unsigned) &lost_irq_ret
+ || stack[1] == (unsigned) &do_bottom_half_ret
+ || stack[1] == (unsigned) &do_signal_ret) {
+ if (mread(sp+16, ®s, sizeof(regs)) != sizeof(regs))
+ break;
+ printf("\nexception:%x [%x] %x ", regs.trap, sp+16,
+ regs.nip);
+ sp = regs.gpr[1];
+ if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
+ break;
+ }
+ }
+ printf("\n");
+}
+
+int
+getsp()
+{
+ int x;
+
+ asm("mr %0,1" : "=r" (x) :);
+ return x;
+}
+
+void
+excprint(struct pt_regs *fp)
+{
+ printf("vector: %x at pc = %x, msr = %x, sp = %x [%x]\n",
+ fp->trap, fp->nip, fp->msr, fp->gpr[1], fp);
+ if (fp->trap == 0x300 || fp->trap == 0x600)
+ printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
+ if (current)
+ printf("current = %x, pid = %d, comm = %s\n",
+ current, current->pid, current->comm);
+}
+
+void
+prregs(struct pt_regs *fp)
+{
+ int n;
+ unsigned base;
+
+ if (scanhex(&base))
+ fp = (struct pt_regs *) base;
+ for (n = 0; n < 32; ++n)
+ printf("R%.2d = %.8x%s", n, fp->gpr[n],
+ (n & 3) == 3? "\n": " ");
+ printf("pc = %.8x msr = %.8x lr = %.8x cr = %.8x\n",
+ fp->nip, fp->msr, fp->link, fp->ccr);
+ printf("ctr = %.8x xer = %.8x trap = %4x\n",
+ fp->ctr, fp->xer, fp->trap);
+}
+
+unsigned int
+read_spr(int n)
+{
+ unsigned int instrs[2];
+ int (*code)(void);
+
+ instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
+ instrs[1] = 0x4e800020;
+ store_inst(instrs);
+ store_inst(instrs+1);
+ code = (int (*)(void)) instrs;
+ return code();
+}
+
+void
+write_spr(int n, unsigned int val)
+{
+ unsigned int instrs[2];
+ int (*code)(unsigned int);
+
+ instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
+ instrs[1] = 0x4e800020;
+ store_inst(instrs);
+ store_inst(instrs+1);
+ code = (int (*)(unsigned int)) instrs;
+ code(val);
+}
+
+static unsigned int regno;
+extern char exc_prolog;
+extern char dec_exc;
+
+void
+super_regs()
+{
+ int i, cmd;
+ unsigned val;
+
+ cmd = skipbl();
+ if (cmd == '\n') {
+ printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
+ printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
+ get_sprg2(), get_sprg3());
+ printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
+ printf("sr0-15 =");
+ for (i = 0; i < 16; ++i)
+ printf(" %x", get_sr(i));
+ printf("\n");
+ asm("mr %0,1" : "=r" (i) :);
+ printf("sp = %x ", i);
+ asm("mr %0,2" : "=r" (i) :);
+ printf("toc = %x\n", i);
+ return;
+ }
+
+ scanhex(®no);
+ switch (cmd) {
+ case 'w':
+ val = read_spr(regno);
+ scanhex(&val);
+ write_spr(regno, val);
+ /* fall through */
+ case 'r':
+ printf("spr %x = %x\n", regno, read_spr(regno));
+ break;
+ case 's':
+ val = get_sr(regno);
+ scanhex(&val);
+ set_sr(regno, val);
+ break;
+ case 'm':
+ val = get_msr();
+ scanhex(&val);
+ set_msr(val);
+ break;
+ }
+ scannl();
+}
+
+#if 0
+static void
+openforth()
+{
+ int c;
+ char *p;
+ char cmd[1024];
+ int args[5];
+ extern int (*prom_entry)(int *);
+
+ p = cmd;
+ c = skipbl();
+ while (c != '\n') {
+ *p++ = c;
+ c = inchar();
+ }
+ *p = 0;
+ args[0] = (int) "interpret";
+ args[1] = 1;
+ args[2] = 1;
+ args[3] = (int) cmd;
+ (*prom_entry)(args);
+ printf("\n");
+ if (args[4] != 0)
+ printf("error %x\n", args[4]);
+}
+#endif
+
+static void
+dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
+{
+ extern void *Hash;
+ extern unsigned long Hash_size;
+ unsigned *htab = Hash;
+ unsigned hsize = Hash_size;
+ unsigned v, hmask, va, last_va;
+ int found, last_found, i;
+ unsigned *hg, w1, last_w2, last_va0;
+
+ last_found = 0;
+ hmask = hsize / 64 - 1;
+ va = start;
+ start = (start >> 12) & 0xffff;
+ end = (end >> 12) & 0xffff;
+ for (v = start; v < end; ++v) {
+ found = 0;
+ hg = htab + (((v ^ seg) & hmask) * 16);
+ w1 = 0x80000000 | (seg << 7) | (v >> 10);
+ for (i = 0; i < 8; ++i, hg += 2) {
+ if (*hg == w1) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ w1 ^= 0x40;
+ hg = htab + ((~(v ^ seg) & hmask) * 16);
+ for (i = 0; i < 8; ++i, hg += 2) {
+ if (*hg == w1) {
+ found = 1;
+ break;
+ }
+ }
+ }
+ if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
+ if (last_found) {
+ if (last_va != last_va0)
+ printf(" ... %x", last_va);
+ printf("\n");
+ }
+ if (found) {
+ printf("%x to %x", va, hg[1]);
+ last_va0 = va;
+ }
+ last_found = found;
+ }
+ if (found) {
+ last_w2 = hg[1] & ~0x180;
+ last_va = va;
+ }
+ va += 4096;
+ }
+ if (last_found)
+ printf(" ... %x\n", last_va);
+}
+static unsigned hash_ctx;
+static unsigned hash_start;
+static unsigned hash_end;
+
+static void
+dump_hash_table()
+{
+ int seg;
+ unsigned seg_start, seg_end;
+
+ hash_ctx = 0;
+ hash_start = 0;
+ hash_end = 0xfffff000;
+ scanhex(&hash_ctx);
+ scanhex(&hash_start);
+ scanhex(&hash_end);
+ printf("Mappings for context %x\n", hash_ctx);
+ seg_start = hash_start;
+ for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
+ seg_end = (seg << 28) | 0x0ffff000;
+ if (seg_end > hash_end)
+ seg_end = hash_end;
+ dump_hash_table_seg((hash_ctx << 4) + seg, seg_start, seg_end);
+ seg_start = seg_end + 0x1000;
+ }
+}
+
+/*
+ * Stuff for reading and writing memory safely
+ */
+extern inline void sync(void)
+{
+ asm volatile("sync; isync");
+}
+
+extern inline void __delay(unsigned int loops)
+{
+ if (loops != 0)
+ __asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :
+ "r" (loops) : "ctr");
+}
+
+int
+mread(unsigned adrs, void *buf, int size)
+{
+ volatile int n;
+ char *p, *q;
+
+ n = 0;
+ if( setjmp(bus_error_jmp) == 0 ){
+ debugger_fault_handler = handle_fault;
+ sync();
+ p = (char *) adrs;
+ q = (char *) buf;
+ switch (size) {
+ case 2: *(short *)q = *(short *)p; break;
+ case 4: *(int *)q = *(int *)p; break;
+ default:
+ for( ; n < size; ++n ) {
+ *q++ = *p++;
+ sync();
+ }
+ }
+ sync();
+ /* wait a little while to see if we get a machine check */
+ __delay(200);
+ n = size;
+ }
+ debugger_fault_handler = 0;
+ return n;
+}
+
+int
+mwrite(unsigned adrs, void *buf, int size)
+{
+ volatile int n;
+ char *p, *q;
+
+ n = 0;
+ if( setjmp(bus_error_jmp) == 0 ){
+ debugger_fault_handler = handle_fault;
+ sync();
+ p = (char *) adrs;
+ q = (char *) buf;
+ switch (size) {
+ case 2: *(short *)p = *(short *)q; break;
+ case 4: *(int *)p = *(int *)q; break;
+ default:
+ for( ; n < size; ++n ) {
+ *p++ = *q++;
+ sync();
+ }
+ }
+ sync();
+ n = size;
+ } else {
+ printf("*** Error writing address %x\n", adrs + n);
+ }
+ debugger_fault_handler = 0;
+ return n;
+}
+
+static int fault_type;
+static char *fault_chars[] = { "--", "**", "##" };
+
+static void
+handle_fault(struct pt_regs *regs)
+{
+ fault_type = regs->trap == 0x200? 0: regs->trap == 0x300? 1: 2;
+ longjmp(bus_error_jmp, 1);
+}
+
+#define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
+
+void
+byterev(unsigned char *val, int size)
+{
+ int t;
+
+ switch (size) {
+ case 2:
+ SWAP(val[0], val[1], t);
+ break;
+ case 4:
+ SWAP(val[0], val[3], t);
+ SWAP(val[1], val[2], t);
+ break;
+ }
+}
+
+static int brev;
+static int mnoread;
+
+void
+memex()
+{
+ int cmd, inc, i, nslash;
+ unsigned n;
+ unsigned char val[4];
+
+ last_cmd = "m\n";
+ scanhex(&adrs);
+ while ((cmd = skipbl()) != '\n') {
+ switch( cmd ){
+ case 'b': size = 1; break;
+ case 'w': size = 2; break;
+ case 'l': size = 4; break;
+ case 'r': brev = !brev; break;
+ case 'n': mnoread = 1; break;
+ case '.': mnoread = 0; break;
+ }
+ }
+ if( size <= 0 )
+ size = 1;
+ else if( size > 4 )
+ size = 4;
+ for(;;){
+ if (!mnoread)
+ n = mread(adrs, val, size);
+ printf("%.8x%c", adrs, brev? 'r': ' ');
+ if (!mnoread) {
+ if (brev)
+ byterev(val, size);
+ putchar(' ');
+ for (i = 0; i < n; ++i)
+ printf("%.2x", val[i]);
+ for (; i < size; ++i)
+ printf("%s", fault_chars[fault_type]);
+ }
+ putchar(' ');
+ inc = size;
+ nslash = 0;
+ for(;;){
+ if( scanhex(&n) ){
+ for (i = 0; i < size; ++i)
+ val[i] = n >> (i * 8);
+ if (!brev)
+ byterev(val, size);
+ mwrite(adrs, val, size);
+ inc = size;
+ }
+ cmd = skipbl();
+ if (cmd == '\n')
+ break;
+ inc = 0;
+ switch (cmd) {
+ case '\'':
+ for(;;){
+ n = inchar();
+ if( n == '\\' )
+ n = bsesc();
+ else if( n == '\'' )
+ break;
+ for (i = 0; i < size; ++i)
+ val[i] = n >> (i * 8);
+ if (!brev)
+ byterev(val, size);
+ mwrite(adrs, val, size);
+ adrs += size;
+ }
+ adrs -= size;
+ inc = size;
+ break;
+ case ',':
+ adrs += size;
+ break;
+ case '.':
+ mnoread = 0;
+ break;
+ case ';':
+ break;
+ case 'x':
+ case EOF:
+ scannl();
+ return;
+ case 'b':
+ case 'v':
+ size = 1;
+ break;
+ case 'w':
+ size = 2;
+ break;
+ case 'l':
+ size = 4;
+ break;
+ case '^':
+ adrs -= size;
+ break;
+ break;
+ case '/':
+ if (nslash > 0)
+ adrs -= 1 << nslash;
+ else
+ nslash = 0;
+ nslash += 4;
+ adrs += 1 << nslash;
+ break;
+ case '\\':
+ if (nslash < 0)
+ adrs += 1 << -nslash;
+ else
+ nslash = 0;
+ nslash -= 4;
+ adrs -= 1 << -nslash;
+ break;
+ case 'm':
+ scanhex(&adrs);
+ break;
+ case 'n':
+ mnoread = 1;
+ break;
+ case 'r':
+ brev = !brev;
+ break;
+ case '<':
+ n = size;
+ scanhex(&n);
+ adrs -= n;
+ break;
+ case '>':
+ n = size;
+ scanhex(&n);
+ adrs += n;
+ break;
+ }
+ }
+ adrs += inc;
+ }
+}
+
+int
+bsesc()
+{
+ int c;
+
+ c = inchar();
+ switch( c ){
+ case 'n': c = '\n'; break;
+ case 'r': c = '\r'; break;
+ case 'b': c = '\b'; break;
+ case 't': c = '\t'; break;
+ }
+ return c;
+}
+
+#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
+ || ('a' <= (c) && (c) <= 'f') \
+ || ('A' <= (c) && (c) <= 'F'))
+void
+dump()
+{
+ int c;
+
+ c = inchar();
+ if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
+ termch = c;
+ scanhex(&adrs);
+ if( termch != '\n')
+ termch = 0;
+ if( c == 'i' ){
+ scanhex(&nidump);
+ if( nidump == 0 )
+ nidump = 16;
+ adrs += ppc_inst_dump(adrs, nidump);
+ last_cmd = "di\n";
+ } else {
+ scanhex(&ndump);
+ if( ndump == 0 )
+ ndump = 64;
+ prdump(adrs, ndump);
+ adrs += ndump;
+ last_cmd = "d\n";
+ }
+}
+
+void
+prdump(unsigned adrs, int ndump)
+{
+ register int n, m, c, r, nr;
+ unsigned char temp[16];
+
+ for( n = ndump; n > 0; ){
+ printf("%.8x", adrs);
+ putchar(' ');
+ r = n < 16? n: 16;
+ nr = mread(adrs, temp, r);
+ adrs += nr;
+ for( m = 0; m < r; ++m ){
+ putchar((m & 3) == 0 && m > 0? '.': ' ');
+ if( m < nr )
+ printf("%.2x", temp[m]);
+ else
+ printf("%s", fault_chars[fault_type]);
+ }
+ for(; m < 16; ++m )
+ printf(" ");
+ printf(" |");
+ for( m = 0; m < r; ++m ){
+ if( m < nr ){
+ c = temp[m];
+ putchar(' ' <= c && c <= '~'? c: '.');
+ } else
+ putchar(' ');
+ }
+ n -= r;
+ for(; m < 16; ++m )
+ putchar(' ');
+ printf("|\n");
+ if( nr < r )
+ break;
+ }
+}
+
+int
+ppc_inst_dump(unsigned adr, int count)
+{
+ int nr, dotted;
+ unsigned first_adr;
+ unsigned long inst, last_inst;
+ unsigned char val[4];
+
+ dotted = 0;
+ for (first_adr = adr; count > 0; --count, adr += 4){
+ nr = mread(adr, val, 4);
+ if( nr == 0 ){
+ const char *x = fault_chars[fault_type];
+ printf("%.8x %s%s%s%s\n", adr, x, x, x, x);
+ break;
+ }
+ inst = GETWORD(val);
+ if (adr > first_adr && inst == last_inst) {
+ if (!dotted) {
+ printf(" ...\n");
+ dotted = 1;
+ }
+ continue;
+ }
+ dotted = 0;
+ last_inst = inst;
+ printf("%.8x ", adr);
+ printf("%.8x\t", inst);
+ print_insn_big_powerpc(stdout, inst, adr); /* always returns 4 */
+ printf("\n");
+ }
+ return adr - first_adr;
+}
+
+void
+print_address(addr)
+unsigned addr;
+{
+ printf("0x%x", addr);
+}
+
+/*
+ * Memory operations - move, set, print differences
+ */
+static unsigned mdest; /* destination address */
+static unsigned msrc; /* source address */
+static unsigned mval; /* byte value to set memory to */
+static unsigned mcount; /* # bytes to affect */
+static unsigned mdiffs; /* max # differences to print */
+
+void
+memops(int cmd)
+{
+ scanhex(&mdest);
+ if( termch != '\n' )
+ termch = 0;
+ scanhex(cmd == 's'? &mval: &msrc);
+ if( termch != '\n' )
+ termch = 0;
+ scanhex(&mcount);
+ switch( cmd ){
+ case 'm':
+ memmove((void *)mdest, (void *)msrc, mcount);
+ break;
+ case 's':
+ memset((void *)mdest, mval, mcount);
+ break;
+ case 'd':
+ if( termch != '\n' )
+ termch = 0;
+ scanhex(&mdiffs);
+ memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
+ break;
+ }
+}
+
+void
+memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
+{
+ unsigned n, prt;
+
+ prt = 0;
+ for( n = nb; n > 0; --n )
+ if( *p1++ != *p2++ )
+ if( ++prt <= maxpr )
+ printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1 - 1,
+ p1[-1], (unsigned)p2 - 1, p2[-1]);
+ if( prt > maxpr )
+ printf("Total of %d differences\n", prt);
+}
+
+static unsigned mend;
+static unsigned mask;
+
+void
+memlocate()
+{
+ unsigned a, n;
+ unsigned char val[4];
+
+ last_cmd = "ml";
+ scanhex(&mdest);
+ if (termch != '\n') {
+ termch = 0;
+ scanhex(&mend);
+ if (termch != '\n') {
+ termch = 0;
+ scanhex(&mval);
+ mask = ~0;
+ if (termch != '\n') termch = 0;
+ scanhex(&mask);
+ }
+ }
+ n = 0;
+ for (a = mdest; a < mend; a += 4) {
+ if (mread(a, val, 4) == 4
+ && ((GETWORD(val) ^ mval) & mask) == 0) {
+ printf("%.8x: %.8x\n", a, GETWORD(val));
+ if (++n >= 10)
+ break;
+ }
+ }
+}
+
+static unsigned mskip = 0x1000;
+static unsigned mlim = 0xffffffff;
+
+void
+memzcan()
+{
+ unsigned char v;
+ unsigned a;
+ int ok, ook;
+
+ scanhex(&mdest);
+ if (termch != '\n') termch = 0;
+ scanhex(&mskip);
+ if (termch != '\n') termch = 0;
+ scanhex(&mlim);
+ ook = 0;
+ for (a = mdest; a < mlim; a += mskip) {
+ ok = mread(a, &v, 1);
+ if (ok && !ook) {
+ printf("%.8x .. ", a);
+ fflush(stdout);
+ } else if (!ok && ook)
+ printf("%.8x\n", a - mskip);
+ ook = ok;
+ if (a + mskip < a)
+ break;
+ }
+ if (ook)
+ printf("%.8x\n", a - mskip);
+}
+
+/* Input scanning routines */
+int
+skipbl()
+{
+ int c;
+
+ if( termch != 0 ){
+ c = termch;
+ termch = 0;
+ } else
+ c = inchar();
+ while( c == ' ' || c == '\t' )
+ c = inchar();
+ return c;
+}
+
+int
+scanhex(vp)
+unsigned *vp;
+{
+ int c, d;
+ unsigned v;
+
+ c = skipbl();
+ d = hexdigit(c);
+ if( d == EOF ){
+ termch = c;
+ return 0;
+ }
+ v = 0;
+ do {
+ v = (v << 4) + d;
+ c = inchar();
+ d = hexdigit(c);
+ } while( d != EOF );
+ termch = c;
+ *vp = v;
+ return 1;
+}
+
+void
+scannl()
+{
+ int c;
+
+ c = termch;
+ termch = 0;
+ while( c != '\n' )
+ c = inchar();
+}
+
+int
+hexdigit(c)
+{
+ if( '0' <= c && c <= '9' )
+ return c - '0';
+ if( 'A' <= c && c <= 'F' )
+ return c - ('A' - 10);
+ if( 'a' <= c && c <= 'f' )
+ return c - ('a' - 10);
+ return EOF;
+}
+
+void
+getstring(char *s, int size)
+{
+ int c;
+
+ c = skipbl();
+ do {
+ if( size > 1 ){
+ *s++ = c;
+ --size;
+ }
+ c = inchar();
+ } while( c != ' ' && c != '\t' && c != '\n' );
+ termch = c;
+ *s = 0;
+}
+
+static char line[256];
+static char *lineptr;
+
+void
+flush_input()
+{
+ lineptr = NULL;
+}
+
+int
+inchar()
+{
+ if (lineptr == NULL || *lineptr == 0) {
+ if (fgets(line, sizeof(line), stdin) == NULL) {
+ lineptr = NULL;
+ return EOF;
+ }
+ lineptr = line;
+ }
+ return *lineptr++;
+}
+
+void
+take_input(str)
+char *str;
+{
+ lineptr = str;
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)