diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2006-05-03 18:14:53 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2006-05-03 18:14:53 +0000 |
commit | cc45021fa213a0c090c34207d2932885afbc9fbf (patch) | |
tree | ecbe74776588b8b1cb3691f4dd28700882ba1b1a /sys/arch | |
parent | 0828a83f695728acaa443dcb3996777deabfdb0b (diff) |
Overhaul of the disassembler code, with random fixes, better conditionnal
branches decoding, correct control register descriptions, and (the reason
for these changes in the first place) 88110 instruction support.
ddb will now disassemble by default for the processor it is running for,
and using the alternate format (x/I) disassembles for the other.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/m88k/include/db_machdep.h | 4 | ||||
-rw-r--r-- | sys/arch/m88k/m88k/db_disasm.c | 1175 |
2 files changed, 767 insertions, 412 deletions
diff --git a/sys/arch/m88k/include/db_machdep.h b/sys/arch/m88k/include/db_machdep.h index 5090f386cb5..99ef457d89e 100644 --- a/sys/arch/m88k/include/db_machdep.h +++ b/sys/arch/m88k/include/db_machdep.h @@ -1,4 +1,4 @@ -/* $OpenBSD: db_machdep.h,v 1.8 2006/05/02 21:44:37 miod Exp $ */ +/* $OpenBSD: db_machdep.h,v 1.9 2006/05/03 18:14:51 miod Exp $ */ /* * Mach Operating System * Copyright (c) 1993-1991 Carnegie Mellon University @@ -75,7 +75,7 @@ int inst_load(u_int); int inst_store(u_int); int ddb_break_trap(int, db_regs_t *); int ddb_entry_trap(int, db_regs_t *); -int m88k_print_instruction(u_int, long); /* db_disasm.c */ +void m88k_print_instruction(int, u_int, u_int32_t); /* db_disasm.c */ /* * inst_call(ins) - is the instruction a function call. diff --git a/sys/arch/m88k/m88k/db_disasm.c b/sys/arch/m88k/m88k/db_disasm.c index 6b4fde134db..6aadf818291 100644 --- a/sys/arch/m88k/m88k/db_disasm.c +++ b/sys/arch/m88k/m88k/db_disasm.c @@ -1,4 +1,28 @@ -/* $OpenBSD: db_disasm.c,v 1.6 2005/12/02 20:01:33 miod Exp $ */ +/* $OpenBSD: db_disasm.c,v 1.7 2006/05/03 18:14:52 miod Exp $ */ +/* + * Copyright (c) 2006, Miodrag Vallat + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ /* * Mach Operating System * Copyright (c) 1993-1991 Carnegie Mellon University @@ -31,7 +55,7 @@ */ #include <sys/param.h> -#include <sys/types.h> +#include <sys/systm.h> #include <machine/db_machdep.h> @@ -40,537 +64,758 @@ #include <ddb/db_output.h> /* db_printf() */ #include <ddb/db_interface.h> -static const char *instwidth[4] = { - ".d", " ", ".h", ".b" -}; +void oimmed(int, u_int32_t, const char *, vaddr_t); +void ctrlregs(int, u_int32_t, const char *, vaddr_t); +void sindou(int, u_int32_t, const char *, vaddr_t); +void jump(int, u_int32_t, const char *, vaddr_t); +void instset(int, u_int32_t, const char *, vaddr_t); +void obranch(int, u_int32_t, const char *, vaddr_t); +void brcond(int, u_int32_t, const char *, vaddr_t); +void otrap(int, u_int32_t, const char *, vaddr_t); +void obit(int, u_int32_t, const char *, vaddr_t); +void bitman(int, u_int32_t, const char *, vaddr_t); +void immem(int, u_int32_t, const char *, vaddr_t); +void nimmem(int, u_int32_t, const char *, vaddr_t); +void lognim(int, u_int32_t, const char *, vaddr_t); +void onimmed(int, u_int32_t, const char *, vaddr_t); +void pinst(int, u_int32_t, const char *, vaddr_t); + +void printcmp(int, u_int); +void printcond(u_int); +void symofset(u_int, u_int, vaddr_t); +const char *cregname(int, u_int, u_int); -static const char *condname[6] = { - "gt0 ", "eq0 ", "ge0 ", "lt0 ", "ne0 ", "le0 " -}; +/* + * Common instruction modifiers + */ -#ifdef M88100 -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 *instwidth[] = { + ".d", " ", ".h", ".b", ".x" /* see nimmem() for use of last value */ }; -#endif -#ifdef M88110 -static const char *m88110_ctrlreg[64] = { - "cr0(PID) ", - "cr1(PSR) ", - "cr2(EPSR) ", - NULL, - "cr4(EXIP) ", - "cr5(ENIP) ", - NULL, - "cr7(VBR) ", - NULL, +static const char *xinstwidth[4] = { + ".d", " ", ".x", ".?" +}; +static const char *cmpname[] = { NULL, NULL, + "eq", + "ne", + "gt", + "le", + "lt", + "ge", + "hi", + "ls", + "lo", + "hs", + "be", + "nb", + "he", + "nh" +}; +static const char *condname[0x1f] = { NULL, + "gt", /* 00001 */ + "eq", /* 00010 */ + "ge", /* 00011 */ NULL, NULL, - "cr14(RES1) ", - "cr15(RES2) ", - "cr16(SRX) ", - "cr17(SR0) ", - "cr18(SR1) ", - "cr19(SR2) ", - "cr20(SR3) ", - "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)" + "lt", /* 01100 */ + "ne", /* 01101 */ + "le" /* 01110 */ +}; +static const char sodname[4] = "sdx?"; + +/* + * Descriptive control register names + */ + +static const char *m88100_ctrlreg[2][64] = { + { /* main unit */ + "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", + }, + { /* SFU1 = FPU */ + "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, + 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" + } }; -#endif -#if defined(M88100) && defined(M88110) -#define ctrlreg (CPU_IS88100 ? m88100_ctrlreg : m88110_ctrlreg) -#elif defined(M88100) -#define ctrlreg m88100_ctrlreg -#else -#define ctrlreg m88110_ctrlreg -#endif - -#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 */ + +static const char *m88110_ctrlreg[2][64] = { + { /* main unit */ + "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 #SRX", + "cr17 #SR0", + "cr18 #SR1", + "cr19 #SR2", + "cr20 #SR3", + NULL, + 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", + }, + { /* SFU1 = FPU */ + "fcr0 #FPECR", + 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, 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" + } +}; + +/* print a comparison code */ void -oimmed(int inst, const char *opcode, long iadr) +printcmp(int cpu, u_int code) { - int Linst = inst & 0177777; - int Hinst = inst >> 16; - int H6inst = Hinst >> 10; - int rs1 = Hinst & 037; - int rd = (Hinst >> 5) & 037; + const char *cmp; - if (H6inst > 017 && H6inst < 030 && (H6inst & 01) == 1) - db_printf("\t%s.u", opcode); + if (cpu == CPU_88100 && code > 11) + cmp = NULL; else - db_printf("\t%s ", opcode); - db_printf("\t\tr%-3d,r%-3d,", rd, rs1); - printval(Linst); + cmp = cmpname[code]; + if (cmp != NULL) + db_printf("%s(%d)", cmp, code); + else + db_printf("%d", code); } -/* Handles instructions dealing with control registers */ +/* print a condition mnemnonic */ void -ctrlregs(int inst, const char *opcode, long iadr) +printcond(u_int match) { - int L6inst = (inst >> 11) & 037; - int creg = (inst >> 5) & 077; - int rd = (inst >> 21) & 037; - int rs1 = (inst >> 16) & 037; + const char *cond; - db_printf("\t%s", opcode); - - if (L6inst == 010 || L6inst == 011) - db_printf("\t\tr%-3d,%s", rd, ctrlreg[creg]); - else if (L6inst == 020 || L6inst == 021) - db_printf("\t\tr%-3d,%s", rs1, ctrlreg[creg]); + cond = condname[match]; + if (cond != NULL) + db_printf("%s0", cond); else - db_printf("\t\tr%-3d,r%-3d,%s", rd, rs1, ctrlreg[creg]); + db_printf("%d", match); +} + +const char * +cregname(int cpu, u_int sfu, u_int regno) +{ + static char unnamed[20]; + const char *regname; + + switch (sfu) { + case 0: /* main unit */ + case 1: /* SFU1 = FPU */ + regname = cpu != CPU_88100 ? + m88110_ctrlreg[sfu][regno] : m88100_ctrlreg[sfu][regno]; + if (regname == NULL) { + snprintf(unnamed, sizeof unnamed, + sfu == 0 ? "cr%d" : "fcr%d", regno); + regname = unnamed; + } + break; + default: /* can't happen */ + snprintf(unnamed, sizeof unnamed, + "sfu%dcr%d", sfu, regno); + regname = unnamed; + break; + } + + return (regname); } void -printsod(int t) +symofset(u_int disp, u_int bit, vaddr_t iadr) { - if (t == 0) - db_printf("s"); - else - db_printf("d"); + vaddr_t addr; + + if (disp & (1 << (bit - 1))) { + /* negative value */ + addr = iadr + ((disp << 2) | (~0U << bit)); + } else { + addr = iadr + (disp << 2); + } + db_printsym(addr, DB_STGY_PROC, db_printf); +} + +/* Handles immediate integer arithmetic instructions */ +void +oimmed(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr) +{ + int32_t Linst = inst & 0xffff; + u_int32_t H6inst = inst >> 26; + u_int32_t rs1 = (inst >> 16) & 0x1f; + u_int32_t rd = (inst >> 21) & 0x1f; + + switch (H6inst) { + case 0x11: /* and.u */ + case 0x13: /* mask.u */ + case 0x15: /* xor.u */ + case 0x17: /* or.u */ + db_printf("\t%s.u", opcode); + break; + default: + db_printf("\t%s ", opcode); + break; + } + db_printf("\t\tr%d, r%d, 0x%04x", rd, rs1, Linst); +} + +/* Handles instructions dealing with control registers */ +void +ctrlregs(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr) +{ + u_int32_t dir = (inst >> 14) & 0x03; + u_int32_t sfu = (inst >> 11) & 0x07; + u_int32_t creg = (inst >> 5) & 0x3f; + u_int32_t rd = (inst >> 21) & 0x1f; + u_int32_t rs1 = (inst >> 16) & 0x1f; + + db_printf("\t%s\t\t", opcode); + + switch (dir) { + case 0x01: /* ldcr, fldcr */ + db_printf("r%d, %s", rd, cregname(cpu, sfu, creg)); + break; + case 0x02: /* stcr, fstcr */ + db_printf("r%d, %s", rs1, cregname(cpu, sfu, creg)); + break; + default: + case 0x03: /* xcr, fxcr */ + db_printf("r%d, r%d, %s", + rd, rs1, cregname(cpu, sfu, creg)); + break; + } } /* Handles floating point instructions */ void -sindou(int inst, const char *opcode, long iadr) +sindou(int cpu, u_int32_t inst, const char *opcode, vaddr_t 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); + u_int32_t rs2 = inst & 0x1f; + u_int32_t td = (inst >> 5) & 0x03; + u_int32_t t2 = (inst >> 7) & 0x03; + u_int32_t t1 = (inst >> 9) & 0x03; + u_int32_t rs1 = (inst >> 16) & 0x1f; + u_int32_t rd = (inst >> 21) & 0x1f; + u_int32_t checkbits = (inst >> 11) & 0x0f; + u_int32_t rf = (inst >> 15) & 0x01; + + /* do not display a specific fcmpu.s encoding as non-existing fcmpu.d */ + if (checkbits == 0x07) + td = 0; + + /* do not display dot modifiers for mov.x */ + if (checkbits == 0x08) { + db_printf("\t%s", opcode); } else { - printsod(t1); - printsod(t2); - db_printf("\t\tr%-3d,r%-3d,r%-3d", rd, rs1, rs2); + db_printf("\t%s.%c", opcode, sodname[td]); + } + + switch (checkbits) { + default: + case 0x00: /* fmul */ + case 0x05: /* fadd */ + case 0x06: /* fsub */ + case 0x0e: /* fdiv */ + db_printf("%c%c\t\t", sodname[t1], sodname[t2]); + if (rf != 0) + db_printf("x%d,x%d,x%d", rd, rs1, rs2); + else + db_printf("r%d,r%d,r%d", rd, rs1, rs2); + break; + case 0x01: /* fcvt */ + case 0x0f: /* fsqrt */ + db_printf("%c \t\t", sodname[t2]); + if (rf != 0) + db_printf("x%d, x%d", rd, rs2); + else + db_printf("r%d, r%d", rd, rs2); + break; + case 0x04: /* flt */ + db_printf("%c \t\t", sodname[t2]); + if ((inst & 0x200) != 0) /* does not use the RF bit... */ + db_printf("x%d, x%d", rd, rs2); + else + db_printf("r%d, r%d", rd, rs2); + break; + case 0x07: /* fcmp, fcmpu */ + db_printf("%c%c\t\t", sodname[t1], sodname[t2]); + db_printf("r%d, ", rd); + if (rf != 0) + db_printf("x%d, x%d", rs1, rs2); + else + db_printf("r%d, r%d", rs1, rs2); + break; + case 0x08: /* mov */ + if (rf != 0 && t1 == 0x01) { /* mov.x, displayed as mov */ + db_printf(" \t\t"); + db_printf("x%d, x%d", rd, rs2); + } else { + db_printf(".%c \t\t", sodname[t2]); + + if (t1 == 0) + db_printf("r%d, x%d", rd, rs2); + else + db_printf("x%d, r%d", rd, rs2); + } + break; + case 0x09: /* int */ + case 0x0a: /* nint */ + case 0x0b: /* trnc */ + db_printf("%c \t\t", sodname[t2]); + if (rf != 0) + db_printf("r%d, x%d", rd, rs2); + else + db_printf("r%d, r%d", rd, rs2); + break; } } void -jump(int inst, const char *opcode, long iadr) +jump(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr) { - int rs2 = inst & 037; - int Nbit = (inst >> 10) & 01; + u_int32_t rs2 = inst & 0x1f; db_printf("\t%s", opcode); - if (Nbit == 1) + if ((inst & (1 << 10)) != 0) db_printf(".n"); else db_printf(" "); - db_printf("\t\tr%-3d", rs2); + db_printf("\t\tr%d", rs2); } /* Handles ff1, ff0, tbnd and rte instructions */ void -instset(int inst, const char *opcode, long iadr) +instset(int cpu, u_int32_t inst, const char *opcode, vaddr_t 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; + u_int32_t rs2 = inst & 0x1f; + u_int32_t rs1 = (inst >> 16) & 0x1f; + u_int32_t rd = (inst >> 21) & 0x1f; + u_int32_t checkbits = (inst >> 10) & 0x3f; + u_int32_t H6inst = (inst >> 26) & 0x3f; 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)); + if (H6inst == 0x3e) { /* tbnd with imm16 */ + db_printf("\t\tr%d, 0x%04x", rs1, inst & 0xffff); } else { - addr = iadr + (disp << 2); + switch (checkbits) { + case 0x3a: /* ff1 */ + case 0x3b: /* ff0 */ + db_printf("\t\tr%d,r%d", rd, rs2); + break; + case 0x3e: /* tbnd */ + db_printf("\t\tr%d,r%d", rs1, rs2); + break; + case 0x3f: /* rte, illop */ + if (rs2 != 0) + db_printf("%d", rs2); + break; + } } - db_printsym(addr, DB_STGY_PROC, db_printf); } +/* Handles unconditionnal branches */ void -obranch(int inst, const char *opcode, long iadr) +obranch(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr) { - int cond = (inst >> 26) & 01; - int disp = inst & 0377777777; + u_int32_t disp = inst & 0x3ffffff; - if (cond == 0) - db_printf("\t%s\t\t", opcode); + db_printf("\t%s", opcode); + if ((inst & (1 << 26)) != 0) + db_printf(".n"); else - db_printf("\t%s.n\t\t", opcode); + db_printf(" "); + db_printf("\t\t"); symofset(disp, 26, iadr); } /* Handles branch on conditions instructions */ void -brcond(int inst, const char *opcode, long iadr) +brcond(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr) { - int cond = (inst >> 26) & 1; - int match = (inst >> 21) & 037; - int rs = (inst >> 16) & 037; - int disp = inst & 0177777; + u_int32_t match = (inst >> 21) & 0x1f; + u_int32_t rs = (inst >> 16) & 0x1f; + u_int32_t disp = inst & 0xffff; - if (cond == 0) - db_printf("\t%s\t\t", opcode); + db_printf("\t%s", opcode); + if ((inst & (1 << 26)) != 0) + db_printf(".n"); 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(","); - break; - } - } else { - printval(match); - db_printf(","); - } + db_printf(" "); + db_printf("\t\t"); + + if (((inst >> 27) & 0x03) == 1) /* bcnd */ + printcond(match); + else + printcmp(cpu, match); - db_printf("r%-3d,", rs); + db_printf(", r%d, ", rs); symofset(disp, 16, iadr); } +/* Handles trap instructions */ void -otrap(int inst, const char *opcode, long iadr) +otrap(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr) { - int vecno = inst & 0777; - int match = (inst >> 21) & 037; - int rs = (inst >> 16) & 037; + u_int32_t vecno = inst & 0x1ff; + u_int32_t match = (inst >> 21) & 0x1f; + u_int32_t rs = (inst >> 16) & 0x1f; 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(","); - break; - } - } else { - printval(match); - db_printf(","); - } - db_printf("\tr%-3d,", rs); - printval(vecno); + if (((inst >> 12) & 0x0f) == 0xe) /* tcnd */ + printcond(match); + else + printcmp(cpu, match); + db_printf(", r%d, 0x%x", rs, vecno); } /* Handles 10 bit immediate bit field operations */ void -obit(int inst, const char *opcode, long iadr) +obit(int cpu, u_int32_t inst, const char *opcode, vaddr_t 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) - printval(width); - db_printf("<"); - printval(offset); - db_printf(">"); + u_int32_t rs = (inst >> 16) & 0x1f; + u_int32_t rd = (inst >> 21) & 0x1f; + u_int32_t width = (inst >> 5) & 0x1f; + u_int32_t offset = inst & 0x1f; + + db_printf("\t%s\t\tr%d, r%d, ", opcode, rd, rs); + if (((inst >> 10) & 0x3f) != 0x2a) /* rot */ + db_printf("%d", width); + db_printf("<%d>", offset); } /* Handles triadic mode bit field instructions */ void -bitman(int inst, const char *opcode, long iadr) +bitman(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr) { - int rs1 = (inst >> 16) & 037; - int rd = (inst >> 21) & 037; - int rs2 = inst & 037; + u_int32_t rs1 = (inst >> 16) & 0x1f; + u_int32_t rd = (inst >> 21) & 0x1f; + u_int32_t rs2 = inst & 0x1f; - db_printf("\t%s\t\tr%-3d,r%-3d,r%-3d", opcode, rd, rs1, rs2); + db_printf("\t%s\t\tr%d, r%d, r%d", opcode, rd, rs1, rs2); } /* Handles immediate load/store/exchange instructions */ void -immem(int inst, const char *opcode, long iadr) +immem(int cpu, u_int32_t inst, const char *opcode, vaddr_t 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; + u_int32_t rd = (inst >> 21) & 0x1f; + u_int32_t rs = (inst >> 16) & 0x1f; + u_int32_t st_lda = (inst >> 28) & 0x03; + u_int32_t aryno = (inst >> 26) & 0x03; + int rf = 0; char c = ' '; switch (st_lda) { - case 0: - if (aryno == 0 || aryno == 01) - opcode = "xmem"; - else + case 0x00: + if ((aryno & 0x02) != 0) { /* 0x02, 0x03: ld.hu, ld.bu */ opcode = "ld"; - if (aryno == 0) - aryno = 03; - if (aryno != 01) c = 'u'; + } else { + if (cpu == CPU_88100) { + opcode = "xmem"; + if (aryno == 0) { /* xmem.bu */ + aryno = 3; + c = 'u'; + } + } else { + /* opcode = "ld"; */ + rf = 1; + } + } break; - case 1: - opcode = "ld"; + + case 0x03: + if (cpu != CPU_88100) { + rf = 1; + switch (st_lda) { + case 0x00: /* ld.x */ + aryno = 2; + break; + case 0x03: /* st, st.d, st.x */ + break; + } + } break; } - db_printf("\t%s%s%c\t\tr%-3d,r%-3d,", - opcode, instwidth[aryno], c, rd, rs); - printval(immed); + db_printf("\t%s%s%c\t\t", opcode, + rf != 0 ? xinstwidth[aryno] : instwidth[aryno], c); + if (rf != 0) + db_printf("x%d, r%d, ", rd, rs); + else + db_printf("r%d, r%d, ", rd, rs); + db_printf("0x%x", inst & 0xffff); } /* Handles triadic mode load/store/exchange instructions */ void -nimmem(int inst, const char *opcode, long iadr) +nimmem(int cpu, u_int32_t inst, const char *opcode, vaddr_t 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; + u_int32_t scaled = (inst >> 9) & 0x01; + u_int32_t rd = (inst >> 21) & 0x1f; + u_int32_t rs1 = (inst >> 16) & 0x1f; + u_int32_t rs2 = inst & 0x1f; + u_int32_t st_lda = (inst >> 12) & 0x03; + u_int32_t aryno = (inst >> 10) & 0x03; char c = ' '; - const char *user; + int rf = 0, wt = 0, usr = 0; switch (st_lda) { - case 0: - if (aryno == 0 || aryno == 01) + case 0x00: + switch (aryno) { + case 0x00: /* xmem.bu */ + aryno = 3; + c = 'u'; + /* FALLTHROUGH */ + case 0x01: /* xmem */ opcode = "xmem"; - else + break; + default: + case 0x02: /* ld.hu */ + case 0x03: /* ld.bu */ opcode = "ld"; - if (aryno == 0) - aryno = 03; - if (aryno != 01) c = 'u'; + break; + } break; - case 1: + case 0x01: opcode = "ld"; + if (cpu != CPU_88100) { + if ((inst & (1 << 26)) == 0) + rf = 1; + } + break; + case 0x02: /* st */ + if (cpu != CPU_88100) { + if ((inst & (1 << 26)) == 0) + rf = 1; + if ((inst & (1 << 7)) != 0) + wt = 1; + } + break; + case 0x03: + if (cpu != CPU_88100) { + /* cheat instwidth for lda.x */ + if (aryno == 3) + aryno = 4; + } break; } + if (st_lda != 0x03 && (inst & (1 << 8)) != 0) + usr = 1; - if (st_lda != 03 && ((inst >> 8) & 01) != 0) - user = ".usr"; + db_printf("\t%s%s%c%s%s\t", + opcode, rf != 0 ? xinstwidth[aryno] : instwidth[aryno], c, + usr != 0 ? ".usr" : " ", wt != 0 ? ".wt" : " "); + if (rf != 0) + db_printf("x%d, r%d", rd, rs1); else - user = " "; + db_printf("r%d, r%d", rd, rs1); - 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); + if (scaled != 0) + db_printf("[r%d]", rs2); else - db_printf(",r%-3d", rs2); + db_printf(", r%d", rs2); } /* Handles triadic mode logical instructions */ void -lognim(int inst, const char *opcode, long iadr) +lognim(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr) { - int rd = (inst >> 21) & 037; - int rs1 = (inst >> 16) & 037; - int rs2 = inst & 037; - int complemt = (inst >> 10) & 01; - char *c = " "; + u_int32_t rd = (inst >> 21) & 0x1f; + u_int32_t rs1 = (inst >> 16) & 0x1f; + u_int32_t rs2 = inst & 0x1f; - if (complemt) - c = ".c"; + db_printf("\t%s", opcode); + if ((inst & (1 << 10)) != 0) + db_printf(".c"); - db_printf("\t%s%s\t\tr%-3d,r%-3d,r%-3d", opcode, c, rd, rs1, rs2); + db_printf("\t\tr%d, r%d, r%d", rd, rs1, rs2); } /* Handles triadic mode arithmetic instructions */ void -onimmed(int inst, const char *opcode, long iadr) +onimmed(int cpu, u_int32_t inst, const char *opcode, vaddr_t 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; - const char *tab, *c; - - if (nochar > 02) - tab = "\t\t"; - else - tab = "\t"; + u_int32_t rd = (inst >> 21) & 0x1f; + u_int32_t rs1 = (inst >> 16) & 0x1f; + u_int32_t rs2 = inst & 0x1f; + u_int32_t carry = (inst >> 8) & 0x03; - if (!nodecode) { + db_printf("\t%s", opcode); + + if ((inst & (1 << 11)) == 0) { switch (carry) { - case 01: - c = ".co "; + case 0x01: + db_printf(".co"); break; - case 02: - c = ".ci "; + case 0x02: + db_printf(".ci"); break; - case 03: - c = ".cio"; - break; - default: - c = " "; + case 0x03: + db_printf(".cio"); break; } - } else - c = " "; + } else { + if (cpu != CPU_88100 && carry == 0x01) + db_printf(".d"); + } - db_printf("\t%s%s%sr%-3d,r%-3d,r%-3d", opcode, c, tab, rd, rs1, rs2); + db_printf("\tr%d, r%d, r%d", rd, rs1, rs2); +} + +/* Handles 88110 SFU2 instructions */ +void +pinst(int cpu, u_int32_t inst, const char *opcode, vaddr_t iadr) +{ + u_int32_t rd = (inst >> 21) & 0x1f; + u_int32_t rs1 = (inst >> 16) & 0x1f; + u_int32_t rs2 = inst & 0x1f; + u_int32_t tfield = (inst >> 5) & 0x03; + u_int32_t pfunc = (inst >> 11) & 0x1f; + const char *saturation[] = { NULL, ".u", ".us", ".s" }; + + db_printf("\t%s", opcode); + + switch (pfunc) { + case 0x0c: /* ppack */ + db_printf(".%d", (inst >> 5) & 0x3c); + break; + case 0x0e: /* prot */ + break; + default: /* other instructions have an S field or zero */ + { + u_int32_t sfield = (inst >> 7) & 0x03; + + if (sfield != 0) + db_printf("%s", saturation[sfield]); + } + break; + } + + if (tfield != 0 || pfunc == 0x0d /* punpk */) { + if (tfield != 3) + db_printf(".%c", "nbh"[tfield]); + } + + switch (pfunc) { + case 0x0d: /* punpk */ + db_printf("\tr%d, r%d", rd, rs1); + break; + case 0x0e: /* prot with immediate */ + db_printf("\tr%d, r%d, %d", rd, rs1, (inst >> 5) & 0x3f); + break; + default: + db_printf("\tr%d, r%d, r%d", rd, rs1, rs2); + break; + } } static const struct opdesc { - u_int mask, match; - void (*opfun)(int, const char *, long); - const char *farg; -} opdecode[] = { + u_int32_t mask, match; + void (*opfun)(int, u_int32_t, const char *, vaddr_t); + const char *opcode; +} opdecode_88100[] = { /* ORDER IS IMPORTANT BELOW */ - { 0xf0000000, 0x00000000, immem, NULL }, - { 0xf0000000, 0x10000000, immem, NULL }, + { 0xf0000000, 0x00000000, immem, NULL }, /* xmem/ld */ + { 0xf0000000, 0x10000000, immem, "ld" }, { 0xf0000000, 0x20000000, immem, "st" }, { 0xf0000000, 0x30000000, immem, "lda" }, @@ -622,14 +867,10 @@ static const struct opdesc { { 0xfc00fe00, 0xf000d800, otrap, "tb1" }, { 0xfc00fe00, 0xf000e800, otrap, "tcnd" }, - { 0xfc00f2e0, 0xf4000000, nimmem, NULL }, - { 0xfc00f2e0, 0xf4000200, nimmem, NULL }, - { 0xfc00f2e0, 0xf4001000, nimmem, NULL }, - { 0xfc00f2e0, 0xf4001200, nimmem, NULL }, - { 0xfc00f2e0, 0xf4002000, nimmem, "st" }, - { 0xfc00f2e0, 0xf4002200, nimmem, "st" }, - { 0xfc00f2e0, 0xf4003000, nimmem, "lda" }, - { 0xfc00f2e0, 0xf4003200, nimmem, "lda" }, + { 0xfc00f0e0, 0xf4000000, nimmem, NULL }, /* xmem/ld */ + { 0xfc00f0e0, 0xf4001000, nimmem, "ld" }, + { 0xfc00f0e0, 0xf4002000, nimmem, "st" }, + { 0xfc00f0e0, 0xf4003000, nimmem, "lda" }, { 0xfc00fbe0, 0xf4004000, lognim, "and" }, { 0xfc00fbe0, 0xf4005000, lognim, "xor" }, @@ -660,36 +901,150 @@ static const struct opdesc { { 0xfc00ffe0, 0xf400fc00, instset, "rte" }, { 0xfc000000, 0xf8000000, instset, "tbnd" }, { 0, 0, NULL, NULL } +}, opdecode_88110[] = { + /* ORDER IS IMPORTANT BELOW */ + { 0xe0000000, 0x00000000, immem, "ld" }, + { 0xf0000000, 0x20000000, immem, "st" }, + { 0xfc000000, 0x3c000000, immem, "ld" }, + { 0xf0000000, 0x30000000, immem, "st" }, + + { 0xf8000000, 0x40000000, oimmed, "and" }, + { 0xf8000000, 0x48000000, oimmed, "mask" }, + { 0xf8000000, 0x50000000, oimmed, "xor" }, + { 0xf8000000, 0x58000000, oimmed, "or" }, + { 0xfc000000, 0x60000000, oimmed, "addu" }, + { 0xfc000000, 0x64000000, oimmed, "subu" }, + { 0xfc000000, 0x68000000, oimmed, "divu" }, + { 0xfc000000, 0x6c000000, oimmed, "mulu" }, + { 0xfc000000, 0x70000000, oimmed, "add" }, + { 0xfc000000, 0x74000000, oimmed, "sub" }, + { 0xfc000000, 0x78000000, oimmed, "divs" }, + { 0xfc000000, 0x7c000000, oimmed, "cmp" }, + + { 0xfc1ff81f, 0x80004000, ctrlregs, "ldcr" }, + { 0xfc1ff81f, 0x80004800, ctrlregs, "fldcr" }, + { 0xffe0f800, 0x80008000, ctrlregs, "stcr" }, + { 0xffe0f800, 0x80008800, ctrlregs, "fstcr" }, + { 0xfc00f800, 0x8000c000, ctrlregs, "xcr" }, + { 0xfc00f800, 0x8000c800, ctrlregs, "fxcr" }, + + { 0xfc007800, 0x84000000, sindou, "fmul" }, + { 0xfc1f7e00, 0x84000800, sindou, "fcvt" }, + { 0xfc1ffd80, 0x84002000, sindou, "flt" }, + { 0xfc007800, 0x84002800, sindou, "fadd" }, + { 0xfc007800, 0x84003000, sindou, "fsub" }, + { 0xfc007860, 0x84003800, sindou, "fcmp" }, + { 0xfc007860, 0x84003820, sindou, "fcmpu" }, + { 0xfc1ffe60, 0x8400c000, sindou, "mov" }, + { 0xfc17fe60, 0x84004200, sindou, "mov" }, + { 0xfc1f7e60, 0x84004800, sindou, "int" }, + { 0xfc1f7e60, 0x84005000, sindou, "nint" }, + { 0xfc1f7e60, 0x84005800, sindou, "trnc" }, + { 0xfc007800, 0x84007000, sindou, "fdiv" }, + { 0xfc1f7e00, 0x84007800, sindou, "fsqrt" }, + + { 0xfc00ffe0, 0x88000000, pinst, "pmul" }, + { 0xfc00ff80, 0x88002000, pinst, "padd" }, + { 0xfc00fe00, 0x88002000, pinst, "padds" }, + { 0xfc00ff80, 0x88003000, pinst, "psub" }, + { 0xfc00fe00, 0x88003000, pinst, "psubs" }, + { 0xfc00ffe0, 0x88003860, pinst, "pcmp" }, + { 0xfc00f800, 0x88006000, pinst, "ppack" }, + { 0xfc00ff9f, 0x88006800, pinst, "punpk" }, + { 0xfc00f87f, 0x88007000, pinst, "prot" }, + { 0xfc00ffe0, 0x88007800, pinst, "prot" }, + + { 0xf8000000, 0xc0000000, obranch, "br" }, + { 0xf8000000, 0xc8000000, obranch, "bsr" }, + + { 0xf8000000, 0xd0000000, brcond, "bb0" }, + { 0xf8000000, 0xd8000000, brcond, "bb1" }, + { 0xf8000000, 0xe8000000, brcond, "bcnd" }, + + { 0xfc00fc00, 0xf0008000, obit, "clr" }, + { 0xfc00fc00, 0xf0008800, obit, "set" }, + { 0xfc00fc00, 0xf0009000, obit, "ext" }, + { 0xfc00fc00, 0xf0009800, obit, "extu" }, + { 0xfc00fc00, 0xf000a000, obit, "mak" }, + { 0xfc00ffe0, 0xf000a800, obit, "rot" }, + + { 0xfc00fe00, 0xf000d000, otrap, "tb0" }, + { 0xfc00fe00, 0xf000d800, otrap, "tb1" }, + { 0xfc00fe00, 0xf000e800, otrap, "tcnd" }, + + { 0xfc00f0e0, 0xf4000000, nimmem, NULL }, /* ld/xmem */ + { 0xf800f0e0, 0xf0001000, nimmem, "ld" }, + { 0xf800f060, 0xf0002000, nimmem, "st" }, + { 0xfc00f2e0, 0xf4003200, nimmem, "lda" }, + + { 0xfc00fbe0, 0xf4004000, lognim, "and" }, + { 0xfc00fbe0, 0xf4005000, lognim, "xor" }, + { 0xfc00fbe0, 0xf4005800, lognim, "or" }, + + { 0xfc00fce0, 0xf4006000, onimmed, "addu" }, + { 0xfc00fce0, 0xf4006400, onimmed, "subu" }, + { 0xfc00fee0, 0xf4006800, onimmed, "divu" }, + { 0xfc00fee0, 0xf4006c00, onimmed, "mulu" }, + { 0xfc00ffe0, 0xf4006e00, onimmed, "muls" }, + { 0xfc00fce0, 0xf4007000, onimmed, "add" }, + { 0xfc00fce0, 0xf4007400, onimmed, "sub" }, + { 0xfc00ffe0, 0xf4007800, onimmed, "divs" }, + { 0xfc00ffe0, 0xf4007c00, onimmed, "cmp" }, + + { 0xfc00ffe0, 0xf4008000, bitman, "clr" }, + { 0xfc00ffe0, 0xf4008800, bitman, "set" }, + { 0xfc00ffe0, 0xf4009000, bitman, "ext" }, + { 0xfc00ffe0, 0xf4009800, bitman, "extu" }, + { 0xfc00ffe0, 0xf400a000, bitman, "mak" }, + { 0xfc00ffe0, 0xf400a800, bitman, "rot" }, + + { 0xfffffbe0, 0xf400c000, jump, "jmp" }, + { 0xfffffbe0, 0xf400c800, jump, "jsr" }, + + { 0xfc1fffe0, 0xf400e800, instset, "ff1" }, + { 0xfc1fffe0, 0xf400ec00, instset, "ff0" }, + { 0xffe0ffe0, 0xf400f800, instset, "tbnd" }, + { 0xffffffff, 0xf400fc00, instset, "rte" }, + { 0xfffffffc, 0xf400fc00, instset, "illop" }, + { 0xffe00000, 0xf8000000, instset, "tbnd" }, + { 0, 0, NULL, NULL } }; -int -m88k_print_instruction(u_int iadr, long inst) +void +m88k_print_instruction(int cpu, u_int iadr, u_int32_t inst) { const struct opdesc *p; /* - * This messes up "orb" instructions ever so slightly, + * This messes up "or.b" instructions ever so slightly, * but keeps us in sync between routines... */ if (inst == 0) { - db_printf("\t.word 0"); + db_printf("\t.word\t0\n"); } else { - for (p = opdecode; p->mask; p++) + p = cpu != CPU_88100 ? opdecode_88110 : opdecode_88100; + while (p->mask != 0) { if ((inst & p->mask) == p->match) { - (*p->opfun)(inst, p->farg, iadr); - break; + (*p->opfun)(cpu, inst, p->opcode, iadr); + db_printf("\n"); + return; } - if (!p->mask) - db_printf("\t.word 0x%x", inst); + p++; + } + db_printf("\t.word\t0x%x\n", inst); } - - 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"); + int cpu; + + if (altfmt) + cpu = CPU_IS88100 ? CPU_88110 : CPU_88100; + else + cpu = cputyp; + + m88k_print_instruction(cpu, loc, db_get_value(loc, 4, FALSE)); return (loc + 4); } |