diff options
Diffstat (limited to 'sys/arch/mvme88k')
-rw-r--r-- | sys/arch/mvme88k/conf/files.mvme88k | 5 | ||||
-rw-r--r-- | sys/arch/mvme88k/ddb/db_disasm.c | 689 | ||||
-rw-r--r-- | sys/arch/mvme88k/ddb/db_sstep.c | 337 | ||||
-rw-r--r-- | sys/arch/mvme88k/ddb/db_trace.c | 1143 |
4 files changed, 1 insertions, 2173 deletions
diff --git a/sys/arch/mvme88k/conf/files.mvme88k b/sys/arch/mvme88k/conf/files.mvme88k index 5f9fcce0556..f1dd4d37ab5 100644 --- a/sys/arch/mvme88k/conf/files.mvme88k +++ b/sys/arch/mvme88k/conf/files.mvme88k @@ -1,4 +1,4 @@ -# $OpenBSD: files.mvme88k,v 1.29 2004/05/07 18:12:55 miod Exp $ +# $OpenBSD: files.mvme88k,v 1.30 2004/06/19 18:28:37 miod Exp $ # maxpartitions 16 @@ -88,10 +88,7 @@ file arch/mvme88k/mvme88k/mem.c file arch/mvme88k/mvme88k/pmap.c file arch/mvme88k/mvme88k/pmap_table.c file arch/mvme88k/mvme88k/vm_machdep.c -file arch/mvme88k/ddb/db_disasm.c ddb file arch/mvme88k/ddb/db_interface.c ddb -file arch/mvme88k/ddb/db_sstep.c ddb -file arch/mvme88k/ddb/db_trace.c ddb file arch/mvme88k/dev/bugio.c file arch/mvme88k/dev/mainbus.c file arch/mvme88k/dev/memdevs.c nvram | sram diff --git a/sys/arch/mvme88k/ddb/db_disasm.c b/sys/arch/mvme88k/ddb/db_disasm.c deleted file mode 100644 index e97647618cb..00000000000 --- a/sys/arch/mvme88k/ddb/db_disasm.c +++ /dev/null @@ -1,689 +0,0 @@ -/* $OpenBSD: db_disasm.c,v 1.13 2004/01/07 17:52:30 miod Exp $ */ -/* - * Mach Operating System - * Copyright (c) 1993-1991 Carnegie Mellon University - * Copyright (c) 1991 OMRON Corporation - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND - * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ - -/* - * m88k disassembler for use in ddb - */ - -#include <sys/param.h> /* cputyp and friends */ -#include <sys/types.h> - -#include <machine/db_machdep.h> - -#include <ddb/db_sym.h> /* DB_STGY_PROC, db_printsym() */ -#include <ddb/db_access.h> /* db_get_value() */ -#include <ddb/db_output.h> /* db_printf() */ -#include <ddb/db_interface.h> - -static const char *instwidth[4] = { - ".d", " ", ".h", ".b" -}; - -static const char *condname[6] = { - "gt0 ", "eq0 ", "ge0 ", "lt0 ", "ne0 ", "le0 " -}; - -static const char *m88100_ctrlreg[64] = { - "cr0(PID) ", - "cr1(PSR) ", - "cr2(EPSR) ", - "cr3(SSBR) ", - "cr4(SXIP) ", - "cr5(SNIP) ", - "cr6(SFIP) ", - "cr7(VBR) ", - "cr8(DMT0) ", - "cr9(DMD0) ", - "cr10(DMA0) ", - "cr11(DMT1) ", - "cr12(DMD1) ", - "cr13(DMA1) ", - "cr14(DMT2) ", - "cr15(DMD2) ", - "cr16(DMA2) ", - "cr17(SR0) ", - "cr18(SR1) ", - "cr19(SR2) ", - "cr20(SR3) ", - "fcr0(FPECR)", - "fcr1(FPHS1)", - "fcr2(FPLS1)", - "fcr3(FPHS2)", - "fcr4(FPLS2)", - "fcr5(FPPT) ", - "fcr6(FPRH) ", - "fcr7(FPRL) ", - "fcr8(FPIT) ", - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - "fcr62(FPSR)", - "fcr63(FPCR)" -}; - -static const char *m88110_ctrlreg[64] = { - "cr0(PID) ", - "cr1(PSR) ", - "cr2(EPSR) ", - NULL, - "cr4(EXIP) ", - "cr5(ENIP) ", - NULL, - "cr7(VBR) ", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "cr14(RES1) ", - "cr15(RES2) ", - "cr16(SR0) ", - "cr17(SR1) ", - "cr18(SR2) ", - "cr19(SR3) ", - "cr20(SR4) ", - "fcr0(FPECR)", - NULL, - NULL, - NULL, - "cr25(ICMD) ", - "cr26(ICTL) ", - "cr27(ISAR) ", - "cr28(ISAP) ", - "cr29(IUAP) ", - "cr30(IIR) ", - "cr31(IBP) ", - "cr32(IPPU) ", - "cr33(IPPL) ", - "cr34(ISR) ", - "cr35(ILAR) ", - "cr36(IPAR) ", - NULL, - NULL, - NULL, - "cr40(DCMD) ", - "cr41(DCTL) ", - "cr42(DSAR) ", - "cr43(DSAP) ", - "cr44(DUAP) ", - "cr45(DIR) ", - "cr46(DBP) ", - "cr47(DPPU) ", - "cr48(DPPL) ", - "cr49(DSR) ", - "cr50(DLAR) ", - "cr51(DPAR) ", - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, - "fcr62(FPSR)", - "fcr63(FPCR)" -}; - -#define printval(x) \ - do { \ - if ((x) < 0) \ - db_printf("-0x%X", -(x)); \ - else \ - db_printf("0x%X", (x)); \ - } while (0) - -/* prototypes */ -void oimmed(int, const char *, long); -void ctrlregs(int, const char *, long); -void printsod(int); -void sindou(int, const char *, long); -void jump(int, const char *, long); -void instset(int, const char *, long); -void symofset(int, int, int); -void obranch(int, const char *, long); -void brcond(int, const char *, long); -void otrap(int, const char *, long); -void obit(int, const char *, long); -void bitman(int, const char *, long); -void immem(int, const char *, long); -void nimmem(int, const char *, long); -void lognim(int, const char *, long); -void onimmed(int, const char *, long); - -/* Handlers immediate integer arithmetic instructions */ -void -oimmed(int inst, const char *opcode, long iadr) -{ - int Linst = inst & 0177777; - int Hinst = inst >> 16; - int H6inst = Hinst >> 10; - int rs1 = Hinst & 037; - int rd = ( Hinst >> 5 ) & 037; - - if (( H6inst > 017 ) && ( H6inst < 030 ) && ( H6inst & 01) == 1 ) - db_printf("\t%s.u",opcode); - else { - db_printf("\t%s",opcode); - db_printf(" "); - } - db_printf("\t\tr%-3d,r%-3d,", rd, rs1); - printval(Linst); -} - - -/* Handles instructions dealing with control registers */ -void -ctrlregs(int inst, const char *opcode, long iadr) -{ - int L6inst = (inst >> 11) & 037; - int creg = (inst >> 5) & 077; - int rd = (inst >> 21) & 037; - int rs1 = (inst >> 16) & 037; - - db_printf("\t%s",opcode); - - if ( L6inst == 010 || L6inst == 011 ) - db_printf("\t\tr%-3d,%s", rd, - cputyp == CPU_88100 ? m88100_ctrlreg[creg] : m88110_ctrlreg[creg]); - else if ( L6inst == 020 || L6inst == 021 ) - db_printf("\t\tr%-3d,%s", rs1, - cputyp == CPU_88100 ? m88100_ctrlreg[creg] : m88110_ctrlreg[creg]); - else - db_printf("\t\tr%-3d,r%-3d,%s", rd, rs1, - cputyp == CPU_88100 ? m88100_ctrlreg[creg] : m88110_ctrlreg[creg]); -} - - -void -printsod(int t) -{ - if ( t == 0 ) - db_printf("s"); - else - db_printf("d"); -} - -/* Handles floating point instructions */ -void -sindou(int inst, const char *opcode, long iadr) -{ - int rs2 = inst & 037; - int td = ( inst >> 5 ) & 03; - int t2 = ( inst >> 7 ) & 03; - int t1 = ( inst >> 9 ) & 03; - int rs1 = ( inst >> 16 ) & 037; - int rd = ( inst >> 21 ) & 037; - int checkbits = ( inst >> 11 ) & 037; - - db_printf("\t%s.",opcode); - printsod(td); - if (( checkbits > 010 && checkbits < 014 ) || ( checkbits == 04 )) { - printsod(t2); - db_printf(" "); - if ( checkbits == 012 || checkbits == 013 ) - db_printf("\t\tr%-3d,r%-3d", rd, rs2); - else - db_printf("\t\tr%-3d,r%-3d", rd, rs2); - } else { - printsod(t1);printsod(t2); - db_printf("\t\tr%-3d,r%-3d,r%-3d", rd, rs1, rs2); - } -} - - -void -jump(int inst, const char *opcode, long iadr) -{ - int rs2 = inst & 037; - int Nbit = ( inst >> 10 ) & 01; - - db_printf("\t%s",opcode); - if ( Nbit == 1 ) - db_printf(".n"); - else - db_printf(" "); - db_printf("\t\tr%-3d",rs2); -} - - -/* Handles ff1, ff0, tbnd and rte instructions */ -void -instset(int inst, const char *opcode, long iadr) -{ - int rs2 = inst & 037; - int rs1 = ( inst >> 16 ) & 037; - int rd = ( inst >> 21 ) & 037; - int checkbits = ( inst >> 10 ) & 077; - int H6inst = ( inst >> 26 ) & 077; - - db_printf("\t%s",opcode); - if ( H6inst == 076 ) { - db_printf("\t\tr%-3d,",rs1); - printval(inst & 0177777); - } else if (( checkbits == 072 ) || ( checkbits == 073 )) - db_printf("\t\tr%-3d,r%-3d", rd, rs2); - else if ( checkbits == 076 ) - db_printf("\t\tr%-3d,r%-3d",rs1,rs2); -} - -void -symofset(int disp, int bit, int iadr) -{ - long addr; - - if ( disp & (1 << (bit-1)) ) { - /* negative value */ - addr = iadr + ((disp << 2) | (~0 << bit)); - } else { - addr = iadr + (disp << 2); - } - db_printsym(addr,DB_STGY_PROC, db_printf); - return; -} - -void -obranch(int inst, const char *opcode, long iadr) -{ - int cond = ( inst >> 26 ) & 01; - int disp = inst &0377777777; - - if ( cond == 0 ) { - db_printf("\t%s\t\t",opcode); - symofset(disp, 26, iadr); - } else { - db_printf("\t%s.n\t\t",opcode); - symofset(disp, 26, iadr); - } -} - - -/* Handles branch on conditions instructions */ -void -brcond(int inst, const char *opcode, long iadr) -{ - int cond = ( inst >> 26 ) & 1; - int match = ( inst >> 21 ) & 037; - int rs = ( inst >> 16 ) & 037; - int disp = ( inst & 0177777 ); - - if ( cond == 0 ) - db_printf("\t%s\t\t", opcode); - else - db_printf("\t%s.n\t\t", opcode); - if ( ( ( inst >> 27 ) & 03 ) == 1 ) - switch (match) { - case 1 : db_printf("%s,", condname[0]); break; - case 2 : db_printf("%s,", condname[1]); break; - case 3 : db_printf("%s,", condname[2]); break; - case 12: db_printf("%s,", condname[3]); break; - case 13: db_printf("%s,", condname[4]); break; - case 14: db_printf("%s,", condname[5]); break; - default: printval(match); - db_printf(","); - } else { - printval(match); - db_printf(","); - } - - db_printf("r%-3d,", rs); - symofset(disp, 16, iadr); -} - - -void -otrap(int inst, const char *opcode, long iadr) -{ - int vecno = inst & 0777; - int match = ( inst >> 21 ) & 037; - int rs = ( inst >> 16 ) & 037; - - db_printf("\t%s\t",opcode); - if ( ( ( inst >> 12 ) & 017 ) == 0xe ) - switch (match) { - case 1 : db_printf("%s,", condname[0]);break; - case 2 : db_printf("%s,", condname[1]);break; - case 3 : db_printf("%s,", condname[2]);break; - case 12: db_printf("%s,", condname[3]);break; - case 13: db_printf("%s,", condname[4]);break; - case 14: db_printf("%s,", condname[5]);break; - default: printval(match); - db_printf(","); - } else { - printval(match); - db_printf(","); - } - db_printf("\tr%-3d,", rs); - printval(vecno); -} - - -/* Handles 10 bit immediate bit field operations */ -void -obit(int inst, const char *opcode, long iadr) -{ - int rs = ( inst >> 16 ) & 037; - int rd = ( inst >> 21 ) & 037; - int width = ( inst >> 5 ) & 037; - int offset = ( inst & 037 ); - - db_printf("\t%s\t\tr%-3d,r%-3d,", opcode, rd, rs); - if ( ( ( inst >> 10 ) & 077 ) == 052 ) { - db_printf("<"); - printval(offset); - db_printf(">"); - } else { - printval(width); - db_printf("<"); - printval(offset); - db_printf(">"); - } -} - - -/* Handles triadic mode bit field instructions */ -void -bitman(int inst, const char *opcode, long iadr) -{ - - int rs1 = ( inst >> 16 ) & 037; - int rd = ( inst >> 21 ) & 037; - int rs2 = inst & 037; - - db_printf("\t%s\t\tr%-3d,r%-3d,r%-3d", opcode, rd, rs1, rs2); -} - - -/* Handles immediate load/store/exchange instructions */ -void -immem(int inst, const char *opcode, long iadr) -{ - int immed = inst & 0xFFFF; - int rd = (inst >> 21) & 037; - int rs = (inst >> 16) & 037; - int st_lda = (inst >> 28) & 03; - int aryno = (inst >> 26) & 03; - char c = ' '; - - if (!st_lda) { - if ((aryno == 0) || (aryno == 01)) - opcode = "xmem"; - else - opcode = "ld"; - if (aryno == 0) - aryno = 03; - if (!(aryno == 01)) - c = 'u'; - } else - if (st_lda == 01) - opcode = "ld"; - - db_printf("\t%s%s%c\t\tr%-3d,r%-3d,", opcode, instwidth[aryno], - c, rd, rs); - printval(immed); -} - - -/* Handles triadic mode load/store/exchange instructions */ -void -nimmem(int inst, const char *opcode, long iadr) -{ - int scaled = (inst >> 9) & 01; - int rd = (inst >> 21) & 037; - int rs1 = (inst >> 16) & 037; - int rs2 = inst & 037; - int st_lda = (inst >> 12) & 03; - int aryno = (inst >> 10) & 03; - int user_bit = 0; - int signed_fg = 1; - char *user = " "; - char c = ' '; - - if (!st_lda) { - if ((aryno == 0) || (aryno == 01)) - opcode = "xmem"; - else - opcode = "ld"; - if (aryno == 0) - aryno = 03; - if (!(aryno == 01)) { - c = 'u'; - signed_fg = 0; - } - } else - if (st_lda == 01) - opcode = "ld"; - - if (!(st_lda == 03)) { - user_bit = (inst >> 8) & 01; - if (user_bit) - user = ".usr"; - } - - if (user_bit && signed_fg && (aryno == 01)) { - if (st_lda) - db_printf("\t%s%s\tr%-3d,r%-3d", opcode, - user, rd, rs1); - else - db_printf("\t%s%s\tr%-3d,r%-3d", opcode, - user, rd, rs1); - } else - if (user_bit && signed_fg) - db_printf("\t%s%s%s\tr%-3d,r%-3d", opcode, - instwidth[aryno], user, rd, rs1); - else - db_printf("\t%s%s%c%s\tr%-3d,r%-3d", opcode, - instwidth[aryno], c, user, rd, rs1); - - if (scaled) - db_printf("[r%-3d]", rs2); - else - db_printf(",r%-3d", rs2); -} - - -/* Handles triadic mode logical instructions */ -void -lognim(int inst, const char *opcode, long iadr) -{ - int rd = (inst >> 21) & 037; - int rs1 = (inst >> 16) & 037; - int rs2 = inst & 037; - int complemt = (inst >> 10) & 01; - char *c = " "; - - if (complemt) - c = ".c"; - - db_printf("\t%s%s\t\tr%-3d,r%-3d,r%-3d", opcode, c, rd, rs1, rs2); -} - - -/* Handles triadic mode arithmetic instructions */ -void -onimmed(int inst, const char *opcode, long iadr) -{ - int rd = (inst >> 21) & 037; - int rs1 = (inst >> 16) & 037; - int rs2 = inst & 037; - int carry = (inst >> 8) & 03; - int nochar = (inst >> 10) & 07; - int nodecode = (inst >> 11) & 01; - char *tab, *c ; - - if (nochar > 02) - tab = "\t\t"; - else - tab = "\t"; - - if (!nodecode) { - if (carry == 01) - c = ".co "; - else - if (carry == 02) - c = ".ci "; - else - if (carry == 03) - c = ".cio"; - else - c = " "; - } else - c = " "; - - db_printf("\t%s%s%sr%-3d,r%-3d,r%-3d", opcode, c, - tab, rd, rs1, rs2); -} - -static const struct opdesc { - unsigned mask, match; - void (*opfun)(int, const char *, long); - const char *farg; -} opdecode[] = { - - /* ORDER IS IMPORTANT BELOW */ - - { 0xF0000000U, 0x00000000U, immem, NULL}, - { 0xF0000000U, 0x10000000U, immem, NULL}, - { 0xF0000000U, 0x20000000U, immem, "st"}, - { 0xF0000000U, 0x30000000U, immem, "lda"}, - - { 0xF8000000U, 0x40000000U, oimmed, "and"}, - { 0xF8000000U, 0x48000000U, oimmed, "mask"}, - { 0xF8000000U, 0x50000000U, oimmed, "xor"}, - { 0xF8000000U, 0x58000000U, oimmed, "or"}, - { 0xFC000000U, 0x60000000U, oimmed, "addu"}, - { 0xFC000000U, 0x64000000U, oimmed, "subu"}, - { 0xFC000000U, 0x68000000U, oimmed, "divu"}, - { 0xFC000000U, 0x6C000000U, oimmed, "mul"}, - { 0xFC000000U, 0x70000000U, oimmed, "add"}, - { 0xFC000000U, 0x74000000U, oimmed, "sub"}, - { 0xFC000000U, 0x78000000U, oimmed, "div"}, - { 0xFC000000U, 0x7C000000U, oimmed, "cmp"}, - - { 0xFC00F800U, 0x80004000U, ctrlregs, "ldcr"}, - { 0xFC00F800U, 0x80004800U, ctrlregs, "fldcr"}, - { 0xFC00F800U, 0x80008000U, ctrlregs, "stcr"}, - { 0xFC00F800U, 0x80008800U, ctrlregs, "fstcr"}, - { 0xFC00F800U, 0x8000C000U, ctrlregs, "xcr"}, - { 0xFC00F800U, 0x8000C800U, ctrlregs, "fxcr"}, - - { 0xFC00F800U, 0x84000000U, sindou, "fmul"}, - { 0xFC1FFF80U, 0x84002000U, sindou, "flt"}, - { 0xFC00F800U, 0x84002800U, sindou, "fadd"}, - { 0xFC00F800U, 0x84003000U, sindou, "fsub"}, - { 0xFC00F860U, 0x84003800U, sindou, "fcmp"}, - { 0xFC1FFE60U, 0x84004800U, sindou, "int"}, - { 0xFC1FFE60U, 0x84005000U, sindou, "nint"}, - { 0xFC1FFE60U, 0x84005800U, sindou, "trnc"}, - { 0xFC00F800U, 0x84007000U, sindou, "fdiv"}, - - { 0xF8000000U, 0xC0000000U, obranch, "br"}, - { 0xF8000000U, 0xC8000000U, obranch, "bsr"}, - - { 0xF8000000U, 0xD0000000U, brcond, "bb0"}, - { 0xF8000000U, 0xD8000000U, brcond, "bb1"}, - { 0xF8000000U, 0xE8000000U, brcond, "bcnd"}, - - { 0xFC00FC00U, 0xF0008000U, obit, "clr"}, - { 0xFC00FC00U, 0xF0008800U, obit, "set"}, - { 0xFC00FC00U, 0xF0009000U, obit, "ext"}, - { 0xFC00FC00U, 0xF0009800U, obit, "extu"}, - { 0xFC00FC00U, 0xF000A000U, obit, "mak"}, - { 0xFC00FC00U, 0xF000A800U, obit, "rot"}, - - { 0xFC00FE00U, 0xF000D000U, otrap, "tb0"}, - { 0xFC00FE00U, 0xF000D800U, otrap, "tb1"}, - { 0xFC00FE00U, 0xF000E800U, otrap, "tcnd"}, - - { 0xFC00F2E0U, 0xF4000000U, nimmem, NULL}, - { 0xFC00F2E0U, 0xF4000200U, nimmem, NULL}, - { 0xFC00F2E0U, 0xF4001000U, nimmem, NULL}, - { 0xFC00F2E0U, 0xF4001200U, nimmem, NULL}, - { 0xFC00F2E0U, 0xF4002000U, nimmem, "st"}, - { 0xFC00F2E0U, 0xF4002200U, nimmem, "st"}, - { 0xFC00F2E0U, 0xF4003000U, nimmem, "lda"}, - { 0xFC00F2E0U, 0xF4003200U, nimmem, "lda"}, - - { 0xFC00FBE0U, 0xF4004000U, lognim, "and"}, - { 0xFC00FBE0U, 0xF4005000U, lognim, "xor"}, - { 0xFC00FBE0U, 0xF4005800U, lognim, "or"}, - - { 0xFC00FCE0U, 0xF4006000U, onimmed, "addu"}, - { 0xFC00FCE0U, 0xF4006400U, onimmed, "subu"}, - { 0xFC00FCE0U, 0xF4006800U, onimmed, "divu"}, - { 0xFC00FCE0U, 0xF4006C00U, onimmed, "mul"}, - { 0xFC00FCE0U, 0xF4007000U, onimmed, "add"}, - { 0xFC00FCE0U, 0xF4007400U, onimmed, "sub"}, - { 0xFC00FCE0U, 0xF4007800U, onimmed, "div"}, - { 0xFC00FCE0U, 0xF4007C00U, onimmed, "cmp"}, - - { 0xFC00FFE0U, 0xF4008000U, bitman, "clr"}, - { 0xFC00FFE0U, 0xF4008800U, bitman, "set"}, - { 0xFC00FFE0U, 0xF4009000U, bitman, "ext"}, - { 0xFC00FFE0U, 0xF4009800U, bitman, "extu"}, - { 0xFC00FFE0U, 0xF400A000U, bitman, "mak"}, - { 0xFC00FFE0U, 0xF400A800U, bitman, "rot"}, - - { 0xFC00FBE0U, 0xF400C000U, jump, "jmp"}, - { 0xFC00FBE0U, 0xF400C800U, jump, "jsr"}, - - { 0xFC00FFE0U, 0xF400E800U, instset, "ff1"}, - { 0xFC00FFE0U, 0xF400EC00U, instset, "ff0"}, - { 0xFC00FFE0U, 0xF400F800U, instset, "tbnd"}, - { 0xFC00FFE0U, 0xF400FC00U, instset, "rte"}, - { 0xFC000000U, 0xF8000000U, instset, "tbnd"}, - { 0, 0, NULL, NULL} -}; - -static const char *badop = "\t???"; - -int -m88k_print_instruction(unsigned iadr, long inst) -{ - const struct opdesc *p; - - /* this messes up "orb" instructions ever so slightly, */ - /* but keeps us in sync between routines... */ - if (inst == 0) { - db_printf ("\t.word 0"); - } else { - for (p = opdecode; p->mask; p++) - if ((inst & p->mask) == p->match) { - (*p->opfun) (inst, p->farg, iadr); - break; - } - if (!p->mask) - db_printf (badop); - } - - return iadr+4; -} - -db_addr_t -db_disasm(db_addr_t loc, boolean_t altfmt) -{ - m88k_print_instruction(loc, db_get_value(loc, 4, FALSE)); - db_printf ("\n"); - return loc+4; -} diff --git a/sys/arch/mvme88k/ddb/db_sstep.c b/sys/arch/mvme88k/ddb/db_sstep.c deleted file mode 100644 index e281eebe6b5..00000000000 --- a/sys/arch/mvme88k/ddb/db_sstep.c +++ /dev/null @@ -1,337 +0,0 @@ -/* $OpenBSD: db_sstep.c,v 1.14 2004/01/07 17:52:30 miod Exp $ */ -/* - * Mach Operating System - * Copyright (c) 1993-1991 Carnegie Mellon University - * Copyright (c) 1991 OMRON Corporation - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND - * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ - -#include <sys/param.h> -#include <sys/systm.h> - -#include <machine/db_machdep.h> - -#include <ddb/db_access.h> /* db_get_value() */ -#include <ddb/db_break.h> /* db_breakpoint_t */ - -/* - * Support routines for software single step. - * - * Author: Daniel Stodolsky (danner@cs.cmu.edu) - * - */ - -boolean_t inst_delayed(unsigned int ins); - -#ifdef INTERNAL_SSTEP -db_breakpoint_t db_not_taken_bkpt = 0; -db_breakpoint_t db_taken_bkpt = 0; -#endif - -/* - * Returns TRUE is the instruction a branch or jump instruction - * (br, bb0, bb1, bcnd, jmp) but not a function call (bsr or jsr) - */ -boolean_t -inst_branch(ins) - unsigned int ins; -{ - /* check high five bits */ - switch (ins >> (32 - 5)) { - case 0x18: /* br */ - case 0x1a: /* bb0 */ - case 0x1b: /* bb1 */ - case 0x1d: /* bcnd */ - return TRUE; - break; - case 0x1e: /* could be jmp */ - if ((ins & 0xfffffbe0U) == 0xf400c000U) - return TRUE; - } - - return FALSE; -} - -/* - * inst_load(ins) - * Returns the number of words the instruction loads. byte, - * half and word count as 1; double word as 2 - */ -unsigned -inst_load(ins) - unsigned int ins; -{ - /* look at the top six bits, for starters */ - switch (ins >> (32 - 6)) { - case 0x0: /* xmem byte imm */ - case 0x1: /* xmem word imm */ - - case 0x2: /* unsigned half-word load imm */ - case 0x3: /* unsigned byte load imm */ - case 0x5: /* signed word load imm */ - case 0x6: /* signed half-word load imm */ - case 0x7: /* signed byte load imm */ - return 1; - - case 0x4: /* signed double word load imm */ - return 2; - - case 0x3d: /* load/store/xmem scaled/unscaled instruction */ - if ((ins & 0xf400c0e0U) == 0xf4000000U) /* is load/xmem */ - switch ((ins & 0x0000fce0) >> 5) { /* look at bits 15-5, but mask bits 8-9 */ - case 0x0: /* xmem byte */ - case 0x1: /* xmem word */ - case 0x2: /* unsigned half word */ - case 0x3: /* unsigned byte load */ - case 0x5: /* signed word load */ - case 0x6: /* signed half-word load */ - case 0x7: /* signed byte load */ - return 1; - - case 0x4: /* signed double word load */ - return 2; - } /* end switch load/xmem */ - break; - } /* end switch 32-6 */ - - return 0; -} - -/* - * inst_store - * Like inst_load, except for store instructions. - */ -unsigned -inst_store(ins) - unsigned int ins; -{ - /* decode top 6 bits again */ - switch (ins >> (32 - 6)) { - case 0x0: /* xmem byte imm */ - case 0x1: /* xmem word imm */ - case 0x9: /* store word imm */ - case 0xa: /* store half-word imm */ - case 0xb: /* store byte imm */ - return 1; - - case 0x8: /* store double word */ - return 2; - case 0x3d: /* load/store/xmem scaled/unscaled instruction */ - /* check bits 15,14,12,7,6,5 are all 0 */ - if ((ins & 0x0000d0e0U) == 0) - switch ((ins & 0x00003c00U) >> 10) { /* decode bits 10-13 */ - case 0x0: /* xmem byte imm */ - case 0x1: /* xmem word imm */ - case 0x9: /* store word */ - case 0xa: /* store half-word */ - case 0xb: /* store byte */ - return 1; - - case 0x8: /* store double word */ - return 2; - } /* end switch store/xmem */ - break; - } /* end switch 32-6 */ - - return 0; -} - -/* - * inst_delayed - * Returns TRUE if this instruction is followed by a delay slot. - * Could be br.n, bsr.n bb0.n, bb1.n, bcnd.n or jmp.n or jsr.n - */ -boolean_t -inst_delayed(ins) - unsigned int ins; -{ - /* check the br, bsr, bb0, bb1, bcnd cases */ - switch ((ins & 0xfc000000U) >> (32 - 6)) { - case 0x31: /* br */ - case 0x33: /* bsr */ - case 0x35: /* bb0 */ - case 0x37: /* bb1 */ - case 0x3b: /* bcnd */ - return TRUE; - } - - /* check the jmp, jsr cases */ - /* mask out bits 0-4, bit 11 */ - return ((ins & 0xfffff7e0U) == 0xf400c400U) ? TRUE : FALSE; -} - -/* - * next_instr_address(pc,delay_slot,task) has the following semantics. - * Let inst be the instruction at pc. - * If delay_slot = 1, next_instr_address should return - * the address of the instruction in the delay slot; if this instruction - * does not have a delay slot, it should return pc. - * If delay_slot = 0, next_instr_address should return the - * address of next sequential instruction, or pc if the instruction is - * followed by a delay slot. - * - * 91-11-28 jfriedl: I think the above is wrong. I think it should be: - * if delay_slot true, return address of the delay slot if there is one, - * return pc otherwise. - * if delay_slot false, return (pc + 4) regardless. - * - */ -db_addr_t -next_instr_address(pc, delay_slot) - db_addr_t pc; - unsigned delay_slot; -{ - if (delay_slot == 0) - return pc + 4; - else { - if (inst_delayed(db_get_value(pc, sizeof(int), FALSE))) - return pc + 4; - else - return pc; - } -} - - -/* - * branch_taken(instruction, program counter, func, func_data) - * - * instruction will be a control flow instruction location at address pc. - * Branch taken is supposed to return the address to which the instruction - * would jump if the branch is taken. Func can be used to get the current - * register values when invoked with a register number and func_data as - * arguments. - * - * If the instruction is not a control flow instruction, panic. - */ -db_addr_t -branch_taken(inst, pc, func, func_data) - u_int inst; - db_addr_t pc; - db_expr_t (*func)(db_regs_t *, int); - db_regs_t *func_data; -{ - /* check if br/bsr */ - if ((inst & 0xf0000000U) == 0xc0000000U) { - /* signed 26 bit pc relative displacement, shift left two bits */ - inst = (inst & 0x03ffffffU) << 2; - /* check if sign extension is needed */ - if (inst & 0x08000000U) - inst |= 0xf0000000U; - return pc + inst; - } - - /* check if bb0/bb1/bcnd case */ - switch ((inst & 0xf8000000U)) { - case 0xd0000000U: /* bb0 */ - case 0xd8000000U: /* bb1 */ - case 0xe8000000U: /* bcnd */ - /* signed 16 bit pc relative displacement, shift left two bits */ - inst = (inst & 0x0000ffffU) << 2; - /* check if sign extension is needed */ - if (inst & 0x00020000U) - inst |= 0xfffc0000U; - return pc + inst; - } - - /* check jmp/jsr case */ - /* check bits 5-31, skipping 10 & 11 */ - if ((inst & 0xfffff3e0U) == 0xf400c000U) { - return (*func)(func_data, (inst & 0x0000001fU)); /* the register value */ - } - - - panic("branch_taken"); - return 0; /* keeps compiler happy */ -} - -/* - * getreg_val - handed a register number and an exception frame. - * Returns the value of the register in the specified - * frame. Only makes sense for general registers. - */ - -db_expr_t -getreg_val(frame, regno) - db_regs_t *frame; - int regno; -{ - if (regno == 0) - return 0; - else if (regno < 31) - return frame->r[regno]; - else - panic("bad register number (%d) to getreg_val.", regno); -} - -#ifdef INTERNAL_SSTEP -void -db_set_single_step(regs) - db_regs_t *regs; -{ - if (cputyp == CPU_88110) { - ((regs)->epsr |= (PSR_TRACE | PSR_SER)); - } else { - db_addr_t pc = PC_REGS(regs); -#ifndef SOFTWARE_SSTEP_EMUL - db_addr_t brpc; - u_int inst; - - /* - * User was stopped at pc, e.g. the instruction - * at pc was not executed. - */ - inst = db_get_value(pc, sizeof(int), FALSE); - if (inst_branch(inst) || inst_call(inst) || inst_return(inst)) { - brpc = branch_taken(inst, pc, getreg_val, regs); - if (brpc != pc) { /* self-branches are hopeless */ - db_taken_bkpt = db_set_temp_breakpoint(brpc); - } -#if 0 - /* XXX this seems like a true bug, no? */ - pc = next_instr_address(pc, 1); -#endif - } -#endif /*SOFTWARE_SSTEP_EMUL*/ - pc = next_instr_address(pc, 0); - db_not_taken_bkpt = db_set_temp_breakpoint(pc); - } -} - -void -db_clear_single_step(regs) - db_regs_t *regs; -{ - if (cputyp == CPU_88110) { - ((regs)->epsr &= ~(PSR_TRACE | PSR_SER)); - } else { - if (db_taken_bkpt != 0) { - db_delete_temp_breakpoint(db_taken_bkpt); - db_taken_bkpt = 0; - } - if (db_not_taken_bkpt != 0) { - db_delete_temp_breakpoint(db_not_taken_bkpt); - db_not_taken_bkpt = 0; - } - } -} -#endif diff --git a/sys/arch/mvme88k/ddb/db_trace.c b/sys/arch/mvme88k/ddb/db_trace.c deleted file mode 100644 index 93204aaf84e..00000000000 --- a/sys/arch/mvme88k/ddb/db_trace.c +++ /dev/null @@ -1,1143 +0,0 @@ -/* $OpenBSD: db_trace.c,v 1.27 2004/01/29 21:39:05 deraadt Exp $ */ -/* - * Mach Operating System - * Copyright (c) 1993-1991 Carnegie Mellon University - * Copyright (c) 1991 OMRON Corporation - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON AND OMRON ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON AND OMRON DISCLAIM ANY LIABILITY OF ANY KIND - * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ - -#include <sys/param.h> -#include <sys/systm.h> - -#include <machine/db_machdep.h> -#include <machine/locore.h> - -#include <ddb/db_variables.h> /* db_variable, DB_VAR_GET, etc. */ -#include <ddb/db_output.h> /* db_printf */ -#include <ddb/db_sym.h> /* DB_STGY_PROC, etc. */ -#include <ddb/db_command.h> /* db_recover */ -#include <ddb/db_access.h> -#include <ddb/db_interface.h> - -union instruction { - unsigned rawbits; - - struct { - unsigned int : 5; - unsigned int n: 1; - signed int d26:26; - } br; - - struct { - unsigned int : 4; - unsigned int isbb1: 1; /* isbb1==0 means bb0, isbb1==1 means bb1 */ - unsigned int n : 1; - unsigned int b5 : 5; - unsigned int s1 : 5; - signed int d16 :16; - } bb; /* bcnd too, except "isbb1" makes no sense for bcnd */ - - struct { - unsigned int : 6; - unsigned int b5 : 5; - unsigned int s1 : 5; - unsigned int : 7; - unsigned int vec9 : 9; - } tb; /* tcnd too */ - - struct { - unsigned int :21; - unsigned int n : 1; - unsigned int : 5; - unsigned int s2 : 5; - } jump; /* jmp, jsr */ - - struct { - unsigned int : 6; - unsigned int d : 5; - unsigned int s1 : 5; - unsigned int i16 :16; - } diatic; /* general reg/reg/i16 instructions */ - - struct { - unsigned int : 6; - unsigned int d : 5; - unsigned int s1 : 5; - unsigned int :11; - unsigned int s2 : 5; - } triatic; /* general reg/reg/reg instructions */ - -}; - -static inline unsigned br_dest(unsigned addr, union instruction inst) -{ - return addr + inst.br.d26 * 4; -} - - -#define TRACE_DEBUG /* undefine to disable debugging */ - -int frame_is_sane(db_regs_t *regs, int); -char *m88k_exception_name(unsigned vector); -unsigned db_trace_get_val(vaddr_t addr, unsigned *ptr); - -/* - * Some macros to tell if the given text is the instruction. - */ -#define JMPN_R1(I) ( (I) == 0xf400c401U) /* jmp.n r1 */ -#define JMP_R1(I) ( (I) == 0xf400c001U) /* jmp r1 */ - -/* gets the IMM16 value from an instruction */ -#define IMM16VAL(I) (((union instruction)(I)).diatic.i16) - -/* subu r31, r31, IMM */ -#define SUBU_R31_R31_IMM(I) (((I) & 0xffff0000U) == 0x67ff0000U) - -/* st r1, r31, IMM */ -#define ST_R1_R31_IMM(I) (((I) & 0xffff0000U) == 0x243f0000U) - -static int trace_flags; -#define TRACE_DEBUG_FLAG 0x01 -#define TRACE_SHOWCALLPRESERVED_FLAG 0x02 -#define TRACE_SHOWADDRESS_FLAG 0x04 -#define TRACE_SHOWFRAME_FLAG 0x08 -#define TRACE_USER_FLAG 0x10 - -#ifdef TRACE_DEBUG - #define DEBUGGING_ON (trace_flags & TRACE_DEBUG_FLAG) -#endif - -#ifndef TRACE_DEBUG - #define SHOW_INSTRUCTION(Addr, Inst, Note) { /*nothing*/ } -#else - #define SHOW_INSTRUCTION(Addr, Inst, Note) if (DEBUGGING_ON) { \ - db_printf("%s0x%x: (0x%08x) ", Note, (unsigned)(Addr), (Inst)); \ - m88k_print_instruction((unsigned)(Addr), (Inst)); \ - db_printf("\n"); \ - } -#endif - -extern label_t *db_recover; - -/* - * m88k trace/register state interface for ddb. - */ - -/* lifted from mips */ -static int -db_setf_regs(struct db_variable *vp, - db_expr_t *valuep, - int op) /* read/write */ -{ - int *regp = (int *) ((char *) DDB_REGS + (int) (vp->valuep)); - - if (op == DB_VAR_GET) - *valuep = *regp; - else if (op == DB_VAR_SET) - *regp = *valuep; - - return (0); /* silence warning */ -} - -#define N(s, x) {s, (long *)&(((db_regs_t *) 0)->x), db_setf_regs} - -struct db_variable db_regs[] = { - N("r1", r[1]), N("r2", r[2]), N("r3", r[3]), N("r4", r[4]), - N("r5", r[5]), N("r6", r[6]), N("r7", r[7]), N("r8", r[8]), - N("r9", r[9]), N("r10", r[10]), N("r11", r[11]), N("r12", r[12]), - N("r13", r[13]), N("r14", r[14]), N("r15", r[15]), N("r16", r[16]), - N("r17", r[17]), N("r18", r[18]), N("r19", r[19]), N("r20", r[20]), - N("r21", r[21]), N("r22", r[22]), N("r23", r[23]), N("r24", r[24]), - N("r25", r[25]), N("r26", r[26]), N("r27", r[27]), N("r28", r[28]), - N("r29", r[29]), N("r30", r[30]), N("r31", r[31]), N("epsr", epsr), - N("sxip", sxip), N("snip", snip), N("sfip", sfip), N("ssbr", ssbr), - N("dmt0", dmt0), N("dmd0", dmd0), N("dma0", dma0), N("dmt1", dmt1), - N("dmd1", dmd1), N("dma1", dma1), N("dmt2", dmt2), N("dmd2", dmd2), - N("dma2", dma2), N("fpecr", fpecr),N("fphs1", fphs1),N("fpls1", fpls1), - N("fphs2", fphs2), N("fpls2", fpls2),N("fppt", fppt), N("fprh", fprh), - N("fprl", fprl), N("fpit", fpit), N("fpsr", fpsr), N("fpcr", fpcr), -}; -#undef N - -struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]); - - -#define TRASHES 0x001 /* clobbers instruction field D */ -#define STORE 0x002 /* does a store to S1+IMM16 */ -#define LOAD 0x004 /* does a load from S1+IMM16 */ -#define DOUBLE 0x008 /* double-register */ -#define FLOW_CTRL 0x010 /* flow-control instruction */ -#define DELAYED 0x020 /* delayed flow control */ -#define JSR 0x040 /* flow-control is a jsr[.n] */ -#define BSR 0x080 /* flow-control is a bsr[.n] */ - -/* - * Given a word of instruction text, return some flags about that - * instruction (flags defined above). - */ -static unsigned -m88k_instruction_info(unsigned instruction) -{ - static const struct { - unsigned mask, value, flags; - } *ptr, control[] = { - /* runs in the same order as 2nd Ed 88100 manual Table 3-14 */ - { 0xf0000000U, 0x00000000U, /* xmem */ TRASHES | STORE | LOAD}, - { 0xec000000U, 0x00000000U, /* ld.d */ TRASHES | LOAD | DOUBLE}, - { 0xe0000000U, 0x00000000U, /* load */ TRASHES | LOAD}, - { 0xfc000000U, 0x20000000U, /* st.d */ STORE | DOUBLE}, - { 0xf0000000U, 0x20000000U, /* store */ STORE}, - { 0xc0000000U, 0x40000000U, /* arith */ TRASHES}, - { 0xfc004000U, 0x80004000U, /* ld cr */ TRASHES}, - { 0xfc004000U, 0x80000000U, /* st cr */ 0}, - { 0xfc008060U, 0x84000000U, /* f */ TRASHES}, - { 0xfc008060U, 0x84000020U, /* f.d */ TRASHES | DOUBLE}, - { 0xfc000000U, 0xcc000000U, /* bsr.n */ FLOW_CTRL | DELAYED | BSR}, - { 0xfc000000U, 0xc8000000U, /* bsr */ FLOW_CTRL | BSR}, - { 0xe4000000U, 0xc4000000U, /* br/bb.n */ FLOW_CTRL | DELAYED}, - { 0xe4000000U, 0xc0000000U, /* br/bb */ FLOW_CTRL}, - { 0xfc000000U, 0xec000000U, /* bcnd.n */ FLOW_CTRL | DELAYED}, - { 0xfc000000U, 0xe8000000U, /* bcnd */ FLOW_CTRL}, - { 0xfc00c000U, 0xf0008000U, /* bits */ TRASHES}, - { 0xfc00c000U, 0xf000c000U, /* trap */ 0}, - { 0xfc00f0e0U, 0xf4002000U, /* st */ 0}, - { 0xfc00cce0U, 0xf4000000U, /* ld.d */ TRASHES | DOUBLE}, - { 0xfc00c0e0U, 0xf4000000U, /* ld */ TRASHES}, - { 0xfc00c0e0U, 0xf4004000U, /* arith */ TRASHES}, - { 0xfc00c3e0U, 0xf4008000U, /* bits */ TRASHES}, - { 0xfc00ffe0U, 0xf400cc00U, /* jsr.n */ FLOW_CTRL | DELAYED | JSR}, - { 0xfc00ffe0U, 0xf400c800U, /* jsr */ FLOW_CTRL | JSR}, - { 0xfc00ffe0U, 0xf400c400U, /* jmp.n */ FLOW_CTRL | DELAYED}, - { 0xfc00ffe0U, 0xf400c000U, /* jmp */ FLOW_CTRL}, - { 0xfc00fbe0U, 0xf400e800U, /* ff */ TRASHES}, - { 0xfc00ffe0U, 0xf400f800U, /* tbnd */ 0}, - { 0xfc00ffe0U, 0xf400fc00U, /* rte */ FLOW_CTRL}, - { 0xfc000000U, 0xf8000000U, /* tbnd */ 0}, - }; -#define ctrl_count (sizeof(control)/sizeof(control[0])) - for (ptr = &control[0]; ptr < &control[ctrl_count]; ptr++) - if ((instruction & ptr->mask) == ptr->value) - return ptr->flags; - SHOW_INSTRUCTION(0, instruction, "bad m88k_instruction_info"); - return 0; -} - -static int -hex_value_needs_0x(unsigned value) -{ - int i; - unsigned last = 0; - unsigned char c; - unsigned have_a_hex_digit = 0; - - if (value <= 9) - return 0; - - for (i = 0; i < 8; i++) { - c = value & 0xf; - value >>= 4; - if (c) - last = c; - if (c > 9) - have_a_hex_digit = 1; - } - if (have_a_hex_digit == 0) - return 1; - if (last > 9) - return 1; - return 0; -} - -/* - * returns - * 1 if regs seems to be a reasonable kernel exception frame. - * 2 if regs seems to be a reasonable user exception frame - * (in the current task). - * 0 if this looks like neither. - */ -int -frame_is_sane(db_regs_t *regs, int quiet) -{ - /* no good if we can't read the whole frame */ - if (badwordaddr((vaddr_t)regs) || badwordaddr((vaddr_t)®s->fpit)) { - if (quiet == 0) - db_printf("[WARNING: frame at %p : unreadable]\n", regs); - return 0; - } - - /* r0 must be 0 (obviously) */ - if (regs->r[0] != 0) { - if (quiet == 0) - db_printf("[WARNING: frame at %p : r[0] != 0]\n", regs); - return 0; - } - - /* stack sanity ... r31 must be nonzero, and must be word aligned */ - if (regs->r[31] == 0 || (regs->r[31] & 3) != 0) { - if (quiet == 0) - db_printf("[WARNING: frame at %p : r[31] == 0 or not word aligned]\n", regs); - return 0; - } - - if (cputyp != CPU_88110) { - /* sxip is reasonable */ -#if 0 - if ((regs->sxip & 1) == 1) - return 0; -#endif - /* snip is reasonable */ - if ((regs->snip & 3) != 2) - return 0; - /* sfip is reasonable */ - if ((regs->sfip & 3) != 2) - return 0; - } - - /* epsr sanity */ - if ((regs->epsr & PSR_MODE)) { /* kernel mode */ - if (regs->epsr & PSR_BO) - return 0; - return 1; - } - if (!(regs->epsr & PSR_MODE)) { /* user mode */ - if (regs->epsr & PSR_BO) - return 0; - return 2; - } - if (quiet == 0) - db_printf("[WARNING: not an exception frame?]\n"); - return 0; -} - -char * -m88k_exception_name(unsigned vector) -{ - switch (vector) { - default: - case 0: return "Reset"; - case 1: return "Interrupt"; - case 2: return "Instruction Access Exception"; - case 3: return "Data Access Exception"; - case 4: return "Misaligned Access Exception"; - case 5: return "Unimplemented Opcode Exception"; - case 6: return "Privilege Violation"; - case 7: return "Bounds Check"; - case 8: return "Integer Divide Exception"; - case 9: return "Integer Overflow Exception"; - case 10: return "Error Exception"; - case 11: return "Non Maskable Interrupt"; - case 114: return "FPU precise"; - case 115: return "FPU imprecise"; - case DDB_ENTRY_BKPT_NO: - return "ddb break"; - case DDB_ENTRY_TRACE_NO: - return "ddb trace"; - case DDB_ENTRY_TRAP_NO: - return "ddb trap"; - case 451: return "Syscall"; - } -} - -/* - * Read a word at address addr. - * Return 1 if was able to read, 0 otherwise. - */ -unsigned -db_trace_get_val(vaddr_t addr, unsigned *ptr) -{ - label_t db_jmpbuf; - label_t *prev = db_recover; - - if (setjmp((db_recover = &db_jmpbuf)) != 0) { - db_recover = prev; - return 0; - } else { - db_read_bytes(addr, 4, (char *)ptr); - db_recover = prev; - return 1; - } -} - -#define FIRST_CALLPRESERVED_REG 14 -#define LAST_CALLPRESERVED_REG 29 -#define FIRST_ARG_REG 2 -#define LAST_ARG_REG 9 -#define RETURN_VAL_REG 1 - -static unsigned global_saved_list = 0x0; /* one bit per register */ -static unsigned local_saved_list = 0x0; /* one bit per register */ -static unsigned trashed_list = 0x0; /* one bit per register */ -static unsigned saved_reg[32]; /* one value per register */ - -#define reg_bit(reg) (1<<((reg)%32)) - -static void -save_reg(int reg, unsigned value) -{ -#ifdef TRACE_DEBUG - if (DEBUGGING_ON) db_printf("save_reg(%d, %x)\n", reg, value); -#endif - if (trashed_list & reg_bit(reg)) { -#ifdef TRACE_DEBUG - if (DEBUGGING_ON) db_printf("<trashed>\n"); -#endif - return; /* don't save trashed registers */ - } - saved_reg[(reg%32)] = value; - global_saved_list |= reg_bit(reg); - local_saved_list |= reg_bit(reg); -} - -#define mark_reg_trashed(reg) (trashed_list |= reg_bit(reg)) - -#define have_global_reg(reg) (global_saved_list & (1<<(reg))) -#define have_local_reg(reg) (local_saved_list & (1<<(reg))) - -#define clear_local_saved_regs() { local_saved_list = trashed_list = 0; } -#define clear_global_saved_regs() { local_saved_list = global_saved_list = 0; } - -#define saved_reg_value(reg) (saved_reg[(reg)]) - -/* - * Show any arguments that we might have been able to determine. - */ -static void -print_args(void) -{ - int reg, last_arg; - - /* find the highest argument register saved */ - for (last_arg = LAST_ARG_REG; last_arg >= FIRST_ARG_REG; last_arg--) - if (have_local_reg(last_arg)) - break; - if (last_arg < FIRST_ARG_REG) - return; /* none were saved */ - - db_printf("("); - - /* print each one, up to the highest */ - for (reg = FIRST_ARG_REG; /*nothing */; reg++) { - if (!have_local_reg(reg)) - db_printf("?"); - else { - unsigned value = saved_reg_value(reg); - db_printf("%s%x", hex_value_needs_0x(value) ? - "0x" : "", value); - } - if (reg == last_arg) - break; - else - db_printf(", "); - } - db_printf(")"); -} - - -#define JUMP_SOURCE_IS_BAD 0 -#define JUMP_SOURCE_IS_OK 1 -#define JUMP_SOURCE_IS_UNLIKELY 2 - -/* - * Give an address to where we return, and an address to where we'd jumped, - * Decided if it all makes sense. - * - * Gcc sometimes optimized something like - * if (condition) - * func1(); - * else - * OtherStuff... - * to - * bcnd !condition mark - * bsr.n func1 - * or r1, r0, mark2 - * mark: - * OtherStuff... - * mark2: - * - * So RETURN_TO will be MARK2, even though we really did branch via - * 'bsr.n func1', so this makes it difficult to be certaian about being - * wrong. - */ -static int -is_jump_source_ok(unsigned return_to, unsigned jump_to) -{ - unsigned flags; - union instruction instruction; - - /* - * Delayed branches are most common... look two instructions before - * where we were going to return to to see if it's a delayed branch. - */ - if (!db_trace_get_val(return_to - 8, &instruction.rawbits)) - return JUMP_SOURCE_IS_BAD; - flags = m88k_instruction_info(instruction.rawbits); - - if ((flags & FLOW_CTRL) && (flags & DELAYED) && (flags & (JSR|BSR))) { - if (flags & JSR) - return JUMP_SOURCE_IS_OK; /* have to assume it's correct */ - /* calculate the offset */ - if (br_dest(return_to - 8, instruction) == jump_to) - return JUMP_SOURCE_IS_OK; /* exactamundo! */ - else - return JUMP_SOURCE_IS_UNLIKELY; /* seems wrong */ - } - - /* - * Try again, looking for a non-delayed jump one back. - */ - if (!db_trace_get_val(return_to - 4, &instruction.rawbits)) - return JUMP_SOURCE_IS_BAD; - flags = m88k_instruction_info(instruction.rawbits); - - if ((flags & FLOW_CTRL) && !(flags & DELAYED) && (flags & (JSR|BSR))) { - if (flags & JSR) - return JUMP_SOURCE_IS_OK; /* have to assume it's correct */ - /* calculate the offset */ - if (br_dest(return_to - 4, instruction) == jump_to) - return JUMP_SOURCE_IS_OK; /* exactamundo! */ - else - return JUMP_SOURCE_IS_UNLIKELY; /* seems wrong */ - } - - return JUMP_SOURCE_IS_UNLIKELY; -} - -static char *note = 0; -static int next_address_likely_wrong = 0; - -/* How much slop we expect in the stack trace */ -#define FRAME_PLAY 8 - -/* - * Stack decode - - * unsigned addr; program counter - * unsigned *stack; IN/OUT stack pointer - * - * given an address within a function and a stack pointer, - * try to find the function from which this one was called - * and the stack pointer for that function. - * - * The return value is zero (if we get confused) or - * we determine that the return address has not yet - * been saved (early in the function prologue). Otherwise - * the return value is the address from which this function - * was called. - * - * Note that even is zero is returned (the second case) the - * stack pointer can be adjusted. - * - */ -static int -stack_decode(db_addr_t addr, unsigned *stack, int (*pr)(const char *, ...)) -{ - db_sym_t proc; - db_expr_t offset_from_proc; - unsigned instructions_to_search; - db_addr_t check_addr; - db_addr_t function_addr; /* start of function */ - unsigned r31 = *stack; /* the r31 of the function */ - unsigned inst; /* text of an instruction */ - unsigned ret_addr; /* address to which we return */ - unsigned tried_to_save_r1 = 0; - -#ifdef TRACE_DEBUG - if (DEBUGGING_ON) - (*pr)("\n>>>stack_decode(addr=%x, stack=%x)\n", - addr, *stack); -#endif - - /* get what we hope will be the db_sym_t for the function name */ - proc = db_search_symbol(addr, DB_STGY_PROC, &offset_from_proc); - if (offset_from_proc == addr) /* i.e. no symbol found */ - proc = DB_SYM_NULL; - - /* - * Somehow, find the start of this function. - * If we found a symbol above, it'll have the address. - * Otherwise, we've got to search for it.... - */ - if (proc != DB_SYM_NULL) { - char *names; - db_symbol_values(proc, &names, &function_addr); - if (names == 0) - return 0; -#ifdef TRACE_DEBUG - if (DEBUGGING_ON) (*pr)("name %s address 0x%x\n", - names, function_addr); -#endif - } else { - int instructions_to_check = 400; - /* - * hmm - unable to find symbol. Search back - * looking for a function prolog. - */ - for (check_addr = addr; instructions_to_check-- > 0; check_addr -= 4) { - if (!db_trace_get_val(check_addr, &inst)) - break; - - if (SUBU_R31_R31_IMM(inst)) { -#if 0 - /* - * If the next instruction is "st r1, r31, ####" - * then we can feel safe we have the start of - * a function. - */ - if (!db_trace_get_val(check_addr + 4, &inst)) - continue; - if (ST_R1_R31_IMM(instr)) - break; /* success */ -#else - /* - * Latest GCC optimizer is just too good... the store - * of r1 might come much later... so we'll have to - * settle for just the "subr r31, r31, ###" to mark - * the start.... - */ - break; -#endif - } - /* - * if we come across a [jmp r1] or [jmp.n r1] assume we have hit - * the previous functions epilogue and stop our search. - * Since we know we would have hit the "subr r31, r31" if it was - * right in front of us, we know this doesn't have one so - * we just return failure.... - */ - if (JMP_R1(inst) || JMPN_R1(inst)) { -#ifdef TRACE_DEBUG - if (DEBUGGING_ON) - (*pr)("ran into a [jmp r1] at %x (addr=%x)\n", - check_addr, addr); -#endif - return 0; - } - } - if (instructions_to_check < 0) { -#ifdef TRACE_DEBUG - if (DEBUGGING_ON) - (*pr)("couldn't find func start (addr=%x)\n", addr); -#endif - return 0; /* bummer, couldn't find it */ - } - function_addr = check_addr; - } - - /* - * We now know the start of the function (function_addr). - * If we're stopped right there, or if it's not a - * subu r31, r31, #### - * then we're done. - */ - if (addr == function_addr) { -#ifdef TRACE_DEBUG - if (DEBUGGING_ON) (*pr)("at start of func\n"); -#endif - return 0; - } - if (!db_trace_get_val(function_addr, &inst)) { -#ifdef TRACE_DEBUG - if (DEBUGGING_ON) (*pr)("couldn't read %x at line %d\n", - function_addr, __LINE__); -#endif - return 0; - } - SHOW_INSTRUCTION(function_addr, inst, "start of function: "); - if (!SUBU_R31_R31_IMM(inst)) { -#ifdef TRACE_DEBUG - if (DEBUGGING_ON) (*pr)("<not subu,r31,r31,imm>\n"); -#endif - return 0; - } - - /* add the size of this frame to the stack (for the next frame) */ - *stack += IMM16VAL(inst); - - /* - * Search from the beginning of the function (funstart) to where we are - * in the function (addr) looking to see what kind of registers have - * been saved on the stack. - * - * We'll stop looking before we get to ADDR if we hit a branch. - */ - clear_local_saved_regs(); - check_addr = function_addr + 4; /* we know the first inst isn't a store */ - - for (instructions_to_search = (addr - check_addr)/sizeof(long); - instructions_to_search-- > 0; - check_addr += 4) { - union instruction instruction; - unsigned flags; - - /* read the instruction */ - if (!db_trace_get_val(check_addr, &instruction.rawbits)) { -#ifdef TRACE_DEBUG - if (DEBUGGING_ON) (*pr)("couldn't read %x at line %d\n", - check_addr, __LINE__); -#endif - break; - } - - SHOW_INSTRUCTION(check_addr, instruction.rawbits, "prolog: "); - - /* find out the particulars about this instruction */ - flags = m88k_instruction_info(instruction.rawbits); - - /* if a store to something off the stack pointer, note the value */ - if ((flags & STORE) && instruction.diatic.s1 == /*stack pointer*/31) { - unsigned value; - if (!have_local_reg(instruction.diatic.d)) { - if (instruction.diatic.d == 1) - tried_to_save_r1 = r31 + instruction.diatic.i16 ; - if (db_trace_get_val(r31 + instruction.diatic.i16, &value)) - save_reg(instruction.diatic.d, value); - } - if ((flags & DOUBLE) && !have_local_reg(instruction.diatic.d + 1)) { - if (instruction.diatic.d == 0) - tried_to_save_r1 = r31+instruction.diatic.i16 +4; - if (db_trace_get_val(r31+instruction.diatic.i16 +4, &value)) - save_reg(instruction.diatic.d + 1, value); - } - } - - /* if an inst that kills D (and maybe D+1), note that */ - if (flags & TRASHES) { - mark_reg_trashed(instruction.diatic.d); - if (flags & DOUBLE) - mark_reg_trashed(instruction.diatic.d + 1); - } - - /* if a flow control instruction, stop now (or next if delayed) */ - if ((flags & FLOW_CTRL) && instructions_to_search != 0) - instructions_to_search = (flags & DELAYED) ? 1 : 0; - } - - /* - * If we didn't save r1 at some point, we're hosed. - */ - if (!have_local_reg(1)) { - if (tried_to_save_r1) { - (*pr)(" <return value of next fcn unreadable in %08x>\n", - tried_to_save_r1); - } -#ifdef TRACE_DEBUG - if (DEBUGGING_ON) (*pr)("didn't save r1\n"); -#endif - return 0; - } - - ret_addr = saved_reg_value(1); - -#ifdef TRACE_DEBUG - if (DEBUGGING_ON) - (*pr)("Return value is = %x, function_addr is %x.\n", - ret_addr, function_addr); -#endif - - /* - * In support of this, continuation.s puts the low bit on the - * return address for continuations (the return address will never - * be used, so it's ok to do anything you want to it). - */ - if (ret_addr & 1) { - note = "<<can not trace past a continuation>>"; - ret_addr = 0; - } else if (ret_addr != 0x00) { - switch (is_jump_source_ok(ret_addr, function_addr)) { - case JUMP_SOURCE_IS_OK: - break; /* excellent */ - - case JUMP_SOURCE_IS_BAD: -#ifdef TRACE_DEBUG - if (DEBUGGING_ON) (*pr)("jump is bad\n"); -#endif - return 0; /* bummer */ - - case JUMP_SOURCE_IS_UNLIKELY: - next_address_likely_wrong = 1; - break; - } - } - - return ret_addr; -} - -static void -db_stack_trace_cmd2(db_regs_t *regs, int (*pr)(const char *, ...)) -{ - unsigned stack; - unsigned depth=1; - unsigned where; - unsigned ft; - unsigned pair[2]; - int i; - - /* - * Frame_is_sane returns: - * 1 if regs seems to be a reasonable kernel exception frame. - * 2 if regs seems to be a reasonable user exception frame - * (in the current task). - * 0 if this looks like neither. - */ - if ((ft = frame_is_sane(regs, 1)) == 0) { - (*pr)("Register frame 0x%x is suspicious; skipping trace\n", regs); - return; - } - - /* if user space and no user space trace specified, puke */ - if (ft == 2 && !(trace_flags & TRACE_USER_FLAG)) - return; - - /* fetch address */ - /* use sxip if valid, otherwise try snip or sfip */ - if (cputyp == CPU_88110) { - where = regs->exip & ~3; - } else { - where = ((regs->sxip & 2) ? regs->sxip : - ((regs->snip & 2) ? regs->snip : - regs->sfip) ) & ~3; - } - stack = regs->r[31]; - (*pr)("stack base = 0x%x\n", stack); - (*pr)("(0) "); /*depth of trace */ - if (trace_flags & TRACE_SHOWADDRESS_FLAG) - (*pr)("%08x ", where); - db_printsym(where, DB_STGY_PROC, pr); - clear_global_saved_regs(); - - /* see if this routine had a stack frame */ - if ((where=stack_decode(where, &stack, pr))==0) { - where = regs->r[1]; - (*pr)("(stackless)"); - } else { - print_args(); - if (trace_flags & TRACE_SHOWFRAME_FLAG) - (*pr)(" [frame 0x%x]", stack); - } - (*pr)("\n"); - if (note) { - (*pr)(" %s\n", note); - note = 0; - } - - do { - /* - * If requested, show preserved registers at the time - * the next-shown call was made. Only registers known to have - * changed from the last exception frame are shown, as others - * can be gotten at by looking at the exception frame. - */ - if (trace_flags & TRACE_SHOWCALLPRESERVED_FLAG) { - int r, title_printed = 0; - - for (r = FIRST_CALLPRESERVED_REG; r<=LAST_CALLPRESERVED_REG; r++) { - if (have_global_reg(r)) { - unsigned value = saved_reg_value(r); - if (title_printed == 0) { - title_printed = 1; - (*pr)("[in next func:"); - } - if (value == 0) - (*pr)(" r%d", r); - else if (value <= 9) - (*pr)(" r%d=%x", r, value); - else - (*pr)(" r%d=x%x", r, value); - } - } - if (title_printed) - (*pr)("]\n"); - } - - (*pr)("(%d)%c", depth++, next_address_likely_wrong ? '?':' '); - next_address_likely_wrong = 0; - - if (trace_flags & TRACE_SHOWADDRESS_FLAG) - (*pr)("%08x ", where); - db_printsym(where, DB_STGY_PROC, pr); - where = stack_decode(where, &stack, pr); - print_args(); - if (trace_flags & TRACE_SHOWFRAME_FLAG) - (*pr)(" [frame 0x%x]", stack); - (*pr)("\n"); - if (note) { - (*pr)(" %s\n", note); - note = 0; - } - } while (where); - - /* try to trace back over trap/exception */ - - stack &= ~7; /* double word aligned */ - /* take last top of stack, and try to find an exception frame near it */ - - i = FRAME_PLAY; - -#ifdef TRACE_DEBUG - if (DEBUGGING_ON) - (*pr)("(searching for exception frame at 0x%x)\n", stack); -#endif - - while (i) { - /* - * On the stack, a pointer to the exception frame is written - * in two adjacent words. In the case of a fault from the kernel, - * this should point to the frame right above them: - * - * Exception Frame Top - * .. - * Exception Frame Bottom <-- frame addr - * frame addr - * frame addr <-- stack pointer - * - * In the case of a fault from user mode, the top of stack - * will just have the address of the frame - * replicated twice. - * - * frame addr <-- top of stack - * frame addr - * - * Here we are just looking for kernel exception frames. - */ - - if (badwordaddr((vaddr_t)stack) || - badwordaddr((vaddr_t)(stack+4))) - break; - - db_read_bytes((vaddr_t)stack, 2*sizeof(int), (char *)pair); - - /* the pairs should match and equal stack+8 */ - if (pair[0] == pair[1]) { - if (pair[0] != stack+8) { - /* - if (!badwordaddr((vaddr_t)pair[0]) && (pair[0]!=0)) - (*pr)("stack_trace:found pair 0x%x but != to stack+8\n", - pair[0]); - */ - } - - else if (frame_is_sane((db_regs_t*)pair[0], 1) != 0) { - struct trapframe *frame = - (struct trapframe *)pair[0]; - - (*pr)("-------------- %s [EF: 0x%x] -------------\n", - m88k_exception_name(frame->tf_vector), - frame); - db_stack_trace_cmd2(&frame->tf_regs, pr); - return; - } -#ifdef TRACE_DEBUG - else if (DEBUGGING_ON) - (*pr)("pair matched, but frame at 0x%x looks insane\n", - stack+8); -#endif - } - stack += 8; - i--; - } - - /* - * If we go here, crawling back on the stack failed to find us - * a previous exception frame. Look for a user frame pointer - * pointed to by a word 8 bytes off of the top of the stack - * if the "u" option was specified. - */ - if (trace_flags & TRACE_USER_FLAG) { - struct trapframe *user; - - /* Make sure we are back on the right page */ - stack -= 4*FRAME_PLAY; - stack = stack & ~(KERNEL_STACK_SIZE-1); /* point to the bottom */ - stack += KERNEL_STACK_SIZE - 8; - - if (badwordaddr((vaddr_t)stack) || - badwordaddr((vaddr_t)stack)) - return; - - db_read_bytes((vaddr_t)stack, 2*sizeof(int), (char *)pair); - if (pair[0] != pair[1]) - return; - - /* have a hit */ - user = *((struct trapframe **)stack); - - if (frame_is_sane(&user->tf_regs, 1) == 2) { - (*pr)("---------------- %s [EF : 0x%x] -------------\n", - m88k_exception_name(user->tf_vector), user); - db_stack_trace_cmd2(&user->tf_regs, pr); - } - } -} - -/* - * stack trace - needs a pointer to a m88k saved state. - * - * If argument f is given, the stack pointer of each call frame is - * printed. - */ -void -db_stack_trace_print(db_expr_t addr, - int have_addr, - db_expr_t count, - char *modif, - int (*pr)(const char *, ...)) -{ - enum { - Default, Stack, Frame - } style = Default; - db_regs_t frame; - db_regs_t *regs; - union { - db_regs_t *frame; - db_expr_t num; - } arg; - - arg.num = addr; - - trace_flags = 0; /* flags will be set via modifers */ - - while (modif && *modif) { - switch (*modif++) { - case 'd': -#ifdef TRACE_DEBUG - trace_flags |= TRACE_DEBUG_FLAG; -#else - db_printtf("<debug trace not compiled in, ignoring>\n"); -#endif - break; - - case 's': style = Stack ; break; - case 'f': style = Frame ; break; - case 'p': trace_flags |= TRACE_SHOWCALLPRESERVED_FLAG; break; - case 'a': trace_flags |= TRACE_SHOWADDRESS_FLAG; break; - case 'F': trace_flags |= TRACE_SHOWFRAME_FLAG; break; - case 'u': trace_flags |= TRACE_USER_FLAG; break; - default: - (*pr)("unknown trace modifier [%c]\n", modif[-1]); - /*FALLTHROUGH*/ - case 'h': - (*pr)("usage: trace/[MODIFIER] [ARG]\n"); - (*pr)(" u = include user trace\n"); - (*pr)(" F = print stack frames\n"); - (*pr)(" a = show return addresses\n"); - (*pr)(" p = show call-preserved registers\n"); - (*pr)(" s = ARG is a stack pointer\n"); - (*pr)(" f = ARG is a frame pointer\n"); -#ifdef TRACE_DEBUG - (*pr)(" d = trace-debugging output\n"); -#endif - return; - } - } - - if (!have_addr && style != Default) { - (*pr)("expecting argument with /s or /f\n"); - return; - } - if (have_addr && style == Default) - style = Frame; - - switch (style) { - case Default: - regs = DDB_REGS; - break; - case Frame: - regs = arg.frame; - break; - case Stack: - { - unsigned val1, val2, sxip; - unsigned ptr; - bzero((void *)&frame, sizeof(frame)); -#define REASONABLE_FRAME_DISTANCE 2048 - - /* - * We've got to find the top of a stack frame so we can get both - * a PC and and real SP. - */ - for (ptr = arg.num;/**/; ptr += 4) { - /* Read a word from the named stack */ - if (db_trace_get_val(ptr, &val1) == 0) { - (*pr)("can't read from %x, aborting.\n", ptr); - return; - } - - /* - * See if it's a frame pointer.... if so it will be larger than - * the address it was taken from (i.e. point back up the stack) - * and we'll be able to read where it points. - */ - if (val1 <= ptr || - (val1 & 3) || - val1 > (ptr + REASONABLE_FRAME_DISTANCE)) - continue; - - /* peek at the next word to see if it could be a return address */ - if (db_trace_get_val(ptr, &sxip) == 0) { - (*pr)("can't read from %x, aborting.\n", ptr); - return; - } - if (sxip == 0 || !db_trace_get_val(sxip, &val2)) - continue; - - if (db_trace_get_val(val1, &val2) == 0) { - (*pr)("can't read from %x, aborting.\n", val1); - continue; - } - - /* - * The value we've just read will be either another frame pointer, - * or the start of another exception frame. - */ - if ( -#ifdef JEFF_DEBUG - val2 == 0 -#else - val2 == 0x12345678 -#endif - && db_trace_get_val(val1-4, &val2) && val2 == val1 - && db_trace_get_val(val1-8, &val2) && val2 == val1) { - /* we've found a frame, so the stack must have been good */ - (*pr)("%x looks like a frame, accepting %x\n",val1,ptr); - break; - } - - if (val2 > val1 && (val2 & 3) == 0) { - /* well, looks close enough to be another frame pointer */ - (*pr)("*%x = %x looks like a stack frame pointer, accepting %x\n", val1, val2, ptr); - break; - } - } - frame.r[31] = ptr; - frame.epsr = 0x800003f0U; - if (cputyp != CPU_88110) { - frame.sxip = sxip | 2; - frame.snip = frame.sxip + 4; - frame.sfip = frame.snip + 4; - } - (*pr)("[r31=%x, %sxip=%x]\n", frame.r[31], - cputyp == CPU_88110 ? "e" : "s", frame.sxip); - regs = &frame; - } - } - db_stack_trace_cmd2(regs, pr); -} |