Annotation of sys/arch/powerpc/ddb/db_disasm.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: db_disasm.c,v 1.14 2003/12/21 15:17:29 miod Exp $ */
! 2: /*
! 3: * Copyright (c) 1996, 2001, 2003 Dale Rahn. All rights reserved.
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: * 1. Redistributions of source code must retain the above copyright
! 9: * notice, this list of conditions and the following disclaimer.
! 10: * 2. Redistributions in binary form must reproduce the above copyright
! 11: * notice, this list of conditions and the following disclaimer in the
! 12: * documentation and/or other materials provided with the distribution.
! 13: *
! 14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 15: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 16: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 17: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 18: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 19: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 20: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 21: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 22: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 23: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 24: */
! 25:
! 26: #include <sys/param.h>
! 27: #include <sys/proc.h>
! 28: #include <sys/systm.h>
! 29:
! 30: #include <machine/db_machdep.h>
! 31:
! 32: #include <ddb/db_access.h>
! 33: #include <ddb/db_sym.h>
! 34: #include <ddb/db_variables.h>
! 35: #include <ddb/db_interface.h>
! 36: #include <ddb/db_output.h>
! 37:
! 38: enum opf {
! 39: Opf_INVALID,
! 40: Opf_A,
! 41: Opf_A0,
! 42: Opf_B,
! 43: Opf_BI,
! 44: Opf_BI1,
! 45: Opf_BO,
! 46: Opf_CRM,
! 47: Opf_D,
! 48: Opf_S,
! 49: Opf_FM,
! 50: Opf_LK,
! 51: Opf_RC,
! 52: Opf_AA,
! 53: Opf_LI,
! 54: Opf_OE,
! 55: Opf_SR,
! 56: Opf_TO,
! 57: Opf_SIMM,
! 58: Opf_UIMM,
! 59: Opf_d,
! 60: Opf_crbA,
! 61: Opf_crbB,
! 62: Opf_crbD,
! 63: Opf_crfD,
! 64: Opf_crfS,
! 65: Opf_spr,
! 66: Opf_tbr,
! 67:
! 68: Opf_BD,
! 69: Opf_C,
! 70:
! 71: Opf_NB,
! 72:
! 73: Opf_sh,
! 74: Opf_SH,
! 75: Opf_mb,
! 76: Opf_MB,
! 77: Opf_ME,
! 78: };
! 79:
! 80:
! 81: struct db_field {
! 82: char *name;
! 83: enum opf opf;
! 84: } db_fields[] = {
! 85: { "A", Opf_A },
! 86: { "A0", Opf_A0 },
! 87: { "B", Opf_B },
! 88: { "D", Opf_D },
! 89: { "S", Opf_S },
! 90: { "AA", Opf_AA },
! 91: { "LI", Opf_LI },
! 92: { "BD", Opf_BD },
! 93: { "BI", Opf_BI },
! 94: { "BI1", Opf_BI1 },
! 95: { "BO", Opf_BO },
! 96: { "CRM", Opf_CRM },
! 97: { "FM", Opf_FM },
! 98: { "LK", Opf_LK },
! 99: { "MB", Opf_MB },
! 100: { "ME", Opf_ME },
! 101: { "NB", Opf_NB },
! 102: { "OE", Opf_OE },
! 103: { "RC", Opf_RC },
! 104: { "SH", Opf_SH },
! 105: { "SR", Opf_SR },
! 106: { "TO", Opf_TO },
! 107: { "SIMM", Opf_SIMM },
! 108: { "UIMM", Opf_UIMM },
! 109: { "crbA", Opf_crbA },
! 110: { "crbB", Opf_crbB },
! 111: { "crbD", Opf_crbD },
! 112: { "crfD", Opf_crfD },
! 113: { "crfS", Opf_crfS },
! 114: { "d", Opf_d },
! 115: { "mb", Opf_mb },
! 116: { "sh", Opf_sh },
! 117: { "spr", Opf_spr },
! 118: { "tbr", Opf_tbr },
! 119: { NULL, 0 }
! 120: };
! 121:
! 122: struct opcode {
! 123: char *name;
! 124: u_int32_t mask;
! 125: u_int32_t code;
! 126: char *decode_str;
! 127: };
! 128:
! 129: typedef u_int32_t instr_t;
! 130: typedef void (op_class_func) (u_int32_t addr, instr_t instr);
! 131:
! 132: u_int32_t extract_field(u_int32_t value, u_int32_t base, u_int32_t width);
! 133: void disasm_fields(u_int32_t addr, const struct opcode *popcode, instr_t instr,
! 134: char *disasm_str, size_t bufsize);
! 135: void disasm_process_field(u_int32_t addr, instr_t instr, char **ppfmt,
! 136: char *ppoutput, size_t bufsize);
! 137: void dis_ppc(u_int32_t addr, const struct opcode *opcodeset, instr_t instr);
! 138:
! 139:
! 140: op_class_func op_ill, op_base;
! 141: op_class_func op_cl_x13, op_cl_x1e, op_cl_x1f;
! 142: op_class_func op_cl_x3a, op_cl_x3b;
! 143: op_class_func op_cl_x3e, op_cl_x3f;
! 144:
! 145: op_class_func *opcodes_base[] = {
! 146: /*x00*/ op_ill, op_ill, op_base, op_ill,
! 147: /*x04*/ op_ill, op_ill, op_ill, op_base,
! 148: /*x08*/ op_base, op_base, op_base, op_base,
! 149: /*x0C*/ op_base, op_base, op_base/*XXX*/, op_base/*XXX*/,
! 150: /*x10*/ op_base, op_base, op_base, op_cl_x13,
! 151: /*x14*/ op_base, op_base, op_ill, op_base,
! 152: /*x18*/ op_base, op_base, op_base, op_base,
! 153: /*x1C*/ op_base, op_base, op_cl_x1e, op_cl_x1f,
! 154: /*x20*/ op_base, op_base, op_base, op_base,
! 155: /*x24*/ op_base, op_base, op_base, op_base,
! 156: /*x28*/ op_base, op_base, op_base, op_base,
! 157: /*x2C*/ op_base, op_base, op_base, op_base,
! 158: /*x30*/ op_base, op_base, op_base, op_base,
! 159: /*x34*/ op_base, op_base, op_base, op_base,
! 160: /*x38*/ op_ill, op_ill, op_cl_x3a, op_cl_x3b,
! 161: /*x3C*/ op_ill, op_ill, op_cl_x3e, op_cl_x3f
! 162: };
! 163:
! 164:
! 165: /* This table could be modified to make significant the "reserved" fields
! 166: * of the opcodes, But I didn't feel like it when typing in the table,
! 167: * I would recommend that this table be looked over for errors,
! 168: * This was derived from the table in Appendix A.2 of (Mot part # MPCFPE/AD)
! 169: * PowerPC Microprocessor Family: The Programming Environments
! 170: */
! 171:
! 172: const struct opcode opcodes[] = {
! 173: { "tdi", 0xfc000000, 0x08000000, " %{TO},%{A},%{SIMM}" },
! 174: { "twi", 0xfc000000, 0x0c000000, " %{TO},%{A},%{SIMM}" },
! 175:
! 176: { "mulli", 0xfc000000, 0x1c000000, " %{D},%{A},%{SIMM}" },
! 177: { "subfic", 0xfc000000, 0x20000000, " %{D},%{A},%{SIMM}" },
! 178: { "cmpli", 0xff800000, 0x28000000, " %{A},%{UIMM}" },
! 179: { "cmpli", 0xfc400000, 0x28000000, " %{crfD}%{A}, %{UIMM}" },
! 180: { "cmpi", 0xff800000, 0x2c000000, " %{A},%{SIMM}"},
! 181: { "cmpi", 0xfc400000, 0x2c000000, " %{crfD}%{A},%{SIMM}" },
! 182: { "addic", 0xfc000000, 0x30000000, " %{D},%{A},%{SIMM}" },
! 183: { "addic.", 0xfc000000, 0x34000000, " %{D},%{A},%{SIMM}" },
! 184: { "addi", 0xfc000000, 0x38000000, " %{D},%{A0}%{SIMM}" },
! 185: { "addis", 0xfc000000, 0x3c000000, " %{D},%{A0}%{SIMM}" },
! 186: { "sc", 0xffffffff, 0x44000002, "" },
! 187: { "b", 0xfc000000, 0x40000000, "%{BO}%{LK}%{AA} %{BI}%{BD}" },
! 188: { "b", 0xfc000000, 0x48000000, "%{LK}%{AA} %{LI}" },
! 189:
! 190: { "rlwimi", 0xfc000000, 0x50000000, "%{RC} %{A},%{S},%{SH},%{MB},%{ME}" },
! 191: { "rlwinm", 0xfc000000, 0x54000000, "%{RC} %{A},%{S},%{SH},%{MB},%{ME}" },
! 192: { "rlwnm", 0xfc000000, 0x5c000000, "%{RC} %{A},%{S},%{SH},%{MB},%{ME}" },
! 193:
! 194: { "ori", 0xfc000000, 0x60000000, " %{A},%{S},%{UIMM}" },
! 195: { "oris", 0xfc000000, 0x64000000, " %{A},%{S},%{UIMM}" },
! 196: { "xori", 0xfc000000, 0x68000000, " %{A},%{S},%{UIMM}" },
! 197: { "xoris", 0xfc000000, 0x6c000000, " %{A},%{S},%{UIMM}" },
! 198:
! 199: { "andi.", 0xfc000000, 0x70000000, " %{A},%{S},%{UIMM}" },
! 200: { "andis.", 0xfc000000, 0x74000000, " %{A},%{S},%{UIMM}" },
! 201:
! 202: { "lwz", 0xfc000000, 0x80000000, " %{D},%{d}(%{A})" },
! 203: { "lwzu", 0xfc000000, 0x84000000, " %{D},%{d}(%{A})" },
! 204: { "lbz", 0xfc000000, 0x88000000, " %{D},%{d}(%{A})" },
! 205: { "lbzu", 0xfc000000, 0x8c000000, " %{D},%{d}(%{A})" },
! 206: { "stw", 0xfc000000, 0x90000000, " %{S},%{d}(%{A})" },
! 207: { "stwu", 0xfc000000, 0x94000000, " %{S},%{d}(%{A})" },
! 208: { "stb", 0xfc000000, 0x98000000, " %{S},%{d}(%{A})" },
! 209: { "stbu", 0xfc000000, 0x9c000000, " %{S},%{d}(%{A})" },
! 210:
! 211: { "lhz", 0xfc000000, 0xa0000000, " %{D},%{d}(%{A})" },
! 212: { "lhzu", 0xfc000000, 0xa4000000, " %{D},%{d}(%{A})" },
! 213: { "lha", 0xfc000000, 0xa8000000, " %{D},%{d}(%{A})" },
! 214: { "lhau", 0xfc000000, 0xac000000, " %{D},%{d}(%{A})" },
! 215: { "sth", 0xfc000000, 0xb0000000, " %{S},%{d}(%{A})" },
! 216: { "sthu", 0xfc000000, 0xb4000000, " %{S},%{d}(%{A})" },
! 217: { "lmw", 0xfc000000, 0xb8000000, " %{D},%{d}(%{A})" },
! 218: { "stmw", 0xfc000000, 0xbc000000, " %{S},%{d}(%{A})" },
! 219:
! 220: { "lfs", 0xfc000000, 0xc0000000, " %{D},%{d}(%{A})" },
! 221: { "lfsu", 0xfc000000, 0xc4000000, " %{D},%{d}(%{A})" },
! 222: { "lfd", 0xfc000000, 0xc8000000, " %{D},%{d}(%{A})" },
! 223: { "lfdu", 0xfc000000, 0xcc000000, " %{D},%{d}(%{A})" },
! 224:
! 225: { "stfs", 0xfc000000, 0xd0000000, " %{S},%{d}(%{A})" },
! 226: { "stfsu", 0xfc000000, 0xd4000000, " %{S},%{d}(%{A})" },
! 227: { "stfd", 0xfc000000, 0xd8000000, " %{S},%{d}(%{A})" },
! 228: { "stfdu", 0xfc000000, 0xdc000000, " %{S},%{d}(%{A})" },
! 229: { "", 0x0, 0x0, "" }
! 230:
! 231: };
! 232:
! 233: /* 13 * 4 = 4c */
! 234: const struct opcode opcodes_13[] = {
! 235: /* 0x13 << 2 */
! 236: { "mcrf", 0xfc0007fe, 0x4c000000, " %{crfD},%{crfS}" },
! 237: { "b",/*bclr*/ 0xfc0007fe, 0x4c000020, "%{BO}lr%{LK} %{BI1}" },
! 238: { "crnor", 0xfc0007fe, 0x4c000042, " %{crbD},%{crbA},%{crbB}" },
! 239: { "rfi", 0xfc0007fe, 0x4c000064, "" },
! 240: { "crandc", 0xfc0007fe, 0x4c000102, " %{crbD},%{crbA},%{crbB}" },
! 241: { "isync", 0xfc0007fe, 0x4c00012c, "" },
! 242: { "crxor", 0xfc0007fe, 0x4c000182, " %{crbD},%{crbA},%{crbB}" },
! 243: { "crnand", 0xfc0007fe, 0x4c0001c2, " %{crbD},%{crbA},%{crbB}" },
! 244: { "crand", 0xfc0007fe, 0x4c000202, " %{crbD},%{crbA},%{crbB}" },
! 245: { "creqv", 0xfc0007fe, 0x4c000242, " %{crbD},%{crbA},%{crbB}" },
! 246: { "crorc", 0xfc0007fe, 0x4c000342, " %{crbD},%{crbA},%{crbB}" },
! 247: { "cror", 0xfc0007fe, 0x4c000382, " %{crbD},%{crbA},%{crbB}" },
! 248: { "b"/*bcctr*/, 0xfc0007fe, 0x4c000420, "%{BO}ctr%{LK} %{BI1}" },
! 249: { "", 0x0, 0x0, "" }
! 250: };
! 251:
! 252: /* 1e * 4 = 78 */
! 253: const struct opcode opcodes_1e[] = {
! 254: { "rldicl", 0xfc00001c, 0x78000000, " %{A},%{S},%{sh},%{mb}" },
! 255: { "rldicr", 0xfc00001c, 0x78000004, " %{A},%{S},%{sh},%{mb}" },
! 256: { "rldic", 0xfc00001c, 0x78000008, " %{A},%{S},%{sh},%{mb}" },
! 257: { "rldimi", 0xfc00001c, 0x7800000c, " %{A},%{S},%{sh},%{mb}" },
! 258: { "rldcl", 0xfc00003e, 0x78000010, " %{A},%{S},%{B},%{mb}" },
! 259: { "rldcr", 0xfc00003e, 0x78000012, " %{A},%{S},%{B},%{mb}" },
! 260: { "", 0x0, 0x0, "" }
! 261: };
! 262:
! 263: /* 1f * 4 = 7c */
! 264: const struct opcode opcodes_1f[] = {
! 265: /* 1f << 2 */
! 266: { "cmpd", 0xfc2007fe, 0x7c200000, " %{crfD}%{A},%{B}" },
! 267: { "cmpw", 0xfc2007fe, 0x7c000000, " %{crfD}%{A},%{B}" },
! 268: { "tw", 0xfc0007fe, 0x7c000008, " %{TO},%{A},%{B}" },
! 269: { "subfc", 0xfc0003fe, 0x7c000010, "%{OE}%{RC} %{D},%{A},%{B}" },
! 270: { "mulhdu", 0xfc0007fe, 0x7c000012, "%{RC} %{D},%{A},%{B}" },
! 271: { "addc", 0xfc0003fe, 0x7c000014, "%{OE}%{RC} %{D},%{A},%{B}" },
! 272: { "mulhwu", 0xfc0007fe, 0x7c000016, "%{RC} %{D},%{A},%{B}" },
! 273:
! 274: { "mfcr", 0xfc0007fe, 0x7c000026, " %{D}" },
! 275: { "lwarx", 0xfc0007fe, 0x7c000028, " %{D},%{A0}%{B}" },
! 276: { "ldx", 0xfc0007fe, 0x7c00002a, " %{D},%{A0}%{B}" },
! 277: { "lwzx", 0xfc0007fe, 0x7c00002e, " %{D},%{A0}%{B}" },
! 278: { "slw", 0xfc0007fe, 0x7c000030, "%{RC} %{A},%{S},%{B}" },
! 279: { "cntlzw", 0xfc0007fe, 0x7c000034, "%{RC} %{A},%{S}" },
! 280: { "sld", 0xfc0007fe, 0x7c000036, "%{RC} %{A},%{S},%{B}" },
! 281: { "and", 0xfc0007fe, 0x7c000038, "%{RC} %{A},%{S},%{B}" },
! 282: { "cmpld", 0xfc2007fe, 0x7c200040, " %{crfD}%{A},%{B}" },
! 283: { "cmplw", 0xfc2007fe, 0x7c000040, " %{crfD}%{A},%{B}" },
! 284: { "subf", 0xfc0003fe, 0x7c000050, "%{OE}%{RC} %{D},%{A},%{B}" },
! 285: { "ldux", 0xfc0007fe, 0x7c00006a, " %{D},%{A},%{B}" },
! 286: { "dcbst", 0xfc0007fe, 0x7c00006c, " %{A0}%{B}" },
! 287: { "lwzux", 0xfc0007fe, 0x7c00006e, " %{D},%{A},%{B}" },
! 288: { "cntlzd", 0xfc0007fe, 0x7c000074, "%{RC} %{A},%{S}" },
! 289: { "andc", 0xfc0007fe, 0x7c000078, "%{RC} %{A},%{S},%{B}" },
! 290: { "td", 0xfc0007fe, 0x7c000088, " %{TO},%{A},%{B}" },
! 291: { "mulhd", 0xfc0007fe, 0x7c000092, "%{RC} %{D},%{A},%{B}" },
! 292: { "mulhw", 0xfc0007fe, 0x7c000096, "%{RC} %{D},%{A},%{B}" },
! 293: { "mfmsr", 0xfc0007fe, 0x7c0000a6, " %{D}" },
! 294: { "ldarx", 0xfc0007fe, 0x7c0000a8, " %{D},%{A0}%{B}" },
! 295: { "dcbf", 0xfc0007fe, 0x7c0000ac, " %{A0}%{B}" },
! 296: { "lbzx", 0xfc0007fe, 0x7c0000ae, " %{D},%{A0}%{B}" },
! 297: { "neg", 0xfc0003fe, 0x7c0000d0, "%{OE}%{RC} %{D},%{A}" },
! 298: { "lbzux", 0xfc0007fe, 0x7c0000ee, " %{D},%{A},%{B}" },
! 299: { "nor", 0xfc0007fe, 0x7c0000f8, "%{RC} %{A},%{S}" },
! 300: { "subfe", 0xfc0003fe, 0x7c000110, "%{OE}%{RC} %{D},%{A}" },
! 301: { "adde", 0xfc0003fe, 0x7c000114, "%{OE}%{RC} %{D},%{A}" },
! 302: { "mtcrf", 0xfc0007fe, 0x7c000120, " %{S},%{CRM}" },
! 303: { "mtmsr", 0xfc0007fe, 0x7c000124, " %{S}" },
! 304: { "stdx", 0xfc0007fe, 0x7c00012a, " %{S},%{A0}%{B}" },
! 305: { "stwcx.", 0xfc0007ff, 0x7c00012d, " %{S},%{A},%{B}" },
! 306: { "stwx", 0xfc0007fe, 0x7c00012e, " %{S},%{A},%{B}" },
! 307: { "stdux", 0xfc0007fe, 0x7c00016a, " %{S},%{A},%{B}" },
! 308: { "stwux", 0xfc0007fe, 0x7c00016e, " %{S},%{A},%{B}" },
! 309: { "subfze", 0xfc0003fe, 0x7c000190, "%{OE}%{RC} %{D},%{A}" },
! 310: { "addze", 0xfc0003fe, 0x7c000194, "%{OE}%{RC} %{D},%{A}" },
! 311: { "mtsr", 0xfc0007fe, 0x7c0001a4, " %{SR},%{S}" },
! 312: { "stdcx.", 0xfc0007ff, 0x7c0001ad, " %{S},%{A0}%{B}" },
! 313: { "stbx", 0xfc0007fe, 0x7c0001ae, " %{S},%{A0}%{B}" },
! 314: { "subfme", 0xfc0003fe, 0x7c0001d0, "%{OE}%{RC} %{D},%{A}" },
! 315: { "mulld", 0xfc0003fe, 0x7c0001d2, "%{OE}%{RC} %{D},%{A},%{B}" },
! 316: { "addme", 0xfc0003fe, 0x7c0001d4, "%{OE}%{RC} %{D},%{A}" },
! 317: { "mullw", 0xfc0003fe, 0x7c0001d6, "%{OE}%{RC} %{D},%{A},%{B}" },
! 318: { "mtsrin", 0xfc0007fe, 0x7c0001e4, " %{S},%{B}" },
! 319: { "dcbtst", 0xfc0007fe, 0x7c0001ec, " %{A0}%{B}" },
! 320: { "stbux", 0xfc0007fe, 0x7c0001ee, " %{S},%{A},%{B}" },
! 321: { "add", 0xfc0003fe, 0x7c000214, "" },
! 322: { "dcbt", 0xfc0007fe, 0x7c00022c, " %{A0}%{B}" },
! 323: { "lhzx", 0xfc0007ff, 0x7c00022e, " %{D},%{A0}%{B}" },
! 324: { "eqv", 0xfc0007fe, 0x7c000238, "%{RC} %{A},%{S},%{B}" },
! 325: { "tlbie", 0xfc0007fe, 0x7c000264, " %{B}" },
! 326: { "eciwx", 0xfc0007fe, 0x7c00026c, " %{D},%{A0}%{B}" },
! 327: { "lhzux", 0xfc0007fe, 0x7c00026e, " %{D},%{A},%{B}" },
! 328: { "xor", 0xfc0007fe, 0x7c000278, "%{RC} %{A},%{S},%{B}" },
! 329: { "mfspr", 0xfc0007fe, 0x7c0002a6, " %{D},%{spr}" },
! 330: { "lwax", 0xfc0007fe, 0x7c0002aa, " %{D},%{A0}%{B}" },
! 331: { "lhax", 0xfc0007fe, 0x7c0002ae, " %{D},%{A},%{B}" },
! 332: { "tlbia", 0xfc0007fe, 0x7c0002e4, "" },
! 333: { "mftb", 0xfc0007fe, 0x7c0002e6, " %{D},%{tbr}" },
! 334: { "lwaux", 0xfc0007fe, 0x7c0002ea, " %{D},%{A},%{B}" },
! 335: { "lhaux", 0xfc0007fe, 0x7c0002ee, " %{D},%{A},%{B}" },
! 336: { "sthx", 0xfc0007fe, 0x7c00032e, " %{S},%{A0}%{B}" },
! 337: { "orc", 0xfc0007fe, 0x7c000338, "%{RC} %{A},%{S},%{B}" },
! 338: { "ecowx", 0xfc0007fe, 0x7c00036c, "%{RC} %{S},%{A0}%{B}" },
! 339: { "slbie", 0xfc0007fc, 0x7c000364, " %{B}" },
! 340: { "sthux", 0xfc0007fe, 0x7c00036e, " %{S},%{A0}%{B}" },
! 341: { "or", 0xfc0007fe, 0x7c000378, "%{RC} %{A},%{S},%{B}" },
! 342: { "divdu", 0xfc0003fe, 0x7c000392, "%{OE}%{RC} %{S},%{A},%{B}" },
! 343: { "divwu", 0xfc0003fe, 0x7c000396, "%{OE}%{RC} %{S},%{A},%{B}" },
! 344: { "mtspr", 0xfc0007fe, 0x7c0003a6, " %{spr},%{S}" },
! 345: { "dcbi", 0xfc0007fe, 0x7c0003ac, " %{A0}%{B}" },
! 346: { "nand", 0xfc0007fe, 0x7c0003b8, "%{RC} %{A},%{S},%{B}" },
! 347: { "divd", 0xfc0003fe, 0x7c0003d2, "%{OE}%{RC} %{S},%{A},%{B}" },
! 348: { "divw", 0xfc0003fe, 0x7c0003d6, "%{OE}%{RC} %{S},%{A},%{B}" },
! 349: { "slbia", 0xfc0003fe, 0x7c0003e4, "%{OE}%{RC} %{S},%{A},%{B}" },
! 350: { "mcrxr", 0xfc0007fe, 0x7c000400, "crfD1" },
! 351: { "lswx", 0xfc0007fe, 0x7c00042a, " %{D},%{A0}%{B}" },
! 352: { "lwbrx", 0xfc0007fe, 0x7c00042c, " %{D},%{A0}%{B}" },
! 353: { "lfsx", 0xfc0007fe, 0x7c00042e, " %{D},%{A},%{B}" },
! 354: { "srw", 0xfc0007fe, 0x7c000430, "%{RC} %{A},%{S},%{B}" },
! 355: { "srd", 0xfc0007fe, 0x7c000436, "%{RC} %{A},%{S},%{B}" },
! 356: { "tlbsync", 0xffffffff, 0x7c00046c, "" },
! 357: { "lfsux", 0xfc0007fe, 0x7c00046e, " %{D},%{A},%{B}" },
! 358: { "mfsr", 0xfc0007fe, 0x7c0004a6, " %{D},%{SR}" },
! 359: { "lswi", 0xfc0007fe, 0x7c0004aa, " %{D},%{A},%{NB}" },
! 360: { "sync", 0xfc0007fe, 0x7c0004ac, "" },
! 361: { "lfdx", 0xfc0007fe, 0x7c0004ae, " %{D},%{A},%{B}" },
! 362: { "lfdux", 0xfc0007fe, 0x7c0004ee, " %{D},%{A},%{B}" },
! 363: { "mfsrin", 0xfc0007fe, 0x7c000526, "" },
! 364: { "stswx", 0xfc0007fe, 0x7c00052a, " %{S},%{A0}%{B}" },
! 365: { "stwbrx", 0xfc0007fe, 0x7c00052c, " %{S},%{A0}%{B}" },
! 366: { "stfsx", 0xfc0007fe, 0x7c00052e, " %{S},%{A0}%{B}" },
! 367: { "stfsux", 0xfc0007fe, 0x7c00056e, " %{S},%{A},%{B}" },
! 368: { "stswi", 0xfc0007fe, 0x7c0005aa, "%{S},%{A0}%{NB}" },
! 369: { "stfdx", 0xfc0007fe, 0x7c0005ae, " %{S},%{A0}%{B}" },
! 370: { "stfdux", 0xfc0007fe, 0x7c0005ee, " %{S},%{A},%{B}" },
! 371: { "lhbrx", 0xfc0007fe, 0x7c00062c, " %{D},%{A0}%{B}" },
! 372: { "sraw", 0xfc0007fe, 0x7c000630, " %{A},%{S},%{B}" },
! 373: { "srad", 0xfc0007fe, 0x7c000634, "%{RC} %{A},%{S},%{B}" },
! 374: { "srawi", 0xfc0007fe, 0x7c000670, "%{RC} %{A},%{SH}" },
! 375: { "sradi", 0xfc0007fc, 0x7c000674, " %{A},%{S},%{sh}" },
! 376: { "eieio", 0xfc0007fe, 0x7c0006ac, "" }, /* MASK? */
! 377: { "sthbrx", 0xfc0007fe, 0x7c00072c, " %{S},%{A0}%{B}" },
! 378: { "extsh", 0xfc0007fe, 0x7c000734, "%{RC} %{A},%{S}" },
! 379: { "extsb", 0xfc0007fe, 0x7c000774, "%{RC} %{A},%{S}" },
! 380: { "icbi", 0xfc0007fe, 0x7c0007ac, " %{A0}%{B}" },
! 381:
! 382: { "stfiwx", 0xfc0007fe, 0x7c0007ae, " %{S},%{A0}%{B}" },
! 383: { "extsw", 0xfc0007fe, 0x7c0007b4, "%{RC} %{A},%{S}" },
! 384: { "dcbz", 0xfc0007fe, 0x7c0007ec, " %{A0}%{B}" },
! 385: { "", 0x0, 0x0, 0, }
! 386: };
! 387:
! 388: /* 3a * 4 = e8 */
! 389: const struct opcode opcodes_3a[] = {
! 390: { "ld", 0xfc000003, 0xe8000000, " %{D},${ds}${A}" },
! 391: { "ldu", 0xfc000003, 0xe8000001, " %{D},${ds}${A}" },
! 392: { "lwa", 0xfc000003, 0xe8000002, " %{D},${ds}${A}" },
! 393: { "", 0x0, 0x0, "" }
! 394: };
! 395:
! 396: /* 3b * 4 = ec */
! 397: const struct opcode opcodes_3b[] = {
! 398: { "fdivs", 0xfc00003e, 0xec000024, "%{RC} f%{D},f%{A},f%{B}" },
! 399: { "fsubs", 0xfc00003e, 0xec000028, "%{RC} f%{D},f%{A},f%{B}" },
! 400:
! 401: { "fadds", 0xfc00003e, 0xec00002a, "%{RC} f%{D},f%{A},f%{B}" },
! 402: { "fsqrts", 0xfc00003e, 0xec00002c, "" },
! 403: { "fres", 0xfc00003e, 0xec000030, "" },
! 404: { "fmuls", 0xfc00003e, 0xec000032, "%{RC} f%{D},f%{A},f%{C}" },
! 405: { "fmsubs", 0xfc00003e, 0xec000038, "%{RC} f%{D},f%{A},f%{C},f%{B}" },
! 406: { "fmadds", 0xfc00003e, 0xec00003a, "%{RC} f%{D},f%{A},f%{C},f%{B}" },
! 407: { "fnmsubs", 0xfc00003e, 0xec00003c, "%{RC} f%{D},f%{A},f%{C},f%{B}" },
! 408: { "fnmadds", 0xfc00003e, 0xec00003e, "%{RC} f%{D},f%{A},f%{C},f%{B}" },
! 409: { "", 0x0, 0x0, "" }
! 410: };
! 411:
! 412: /* 3e * 4 = f8 */
! 413: const struct opcode opcodes_3e[] = {
! 414: { "std", 0xfc000003, 0xf8000000, " %{D},${ds}${A}" },
! 415: { "stdu", 0xfc000003, 0xf8000001, " %{D},${ds}${A}" },
! 416: { "", 0x0, 0x0, "" }
! 417: };
! 418:
! 419: /* 3f * 4 = fc */
! 420: const struct opcode opcodes_3f[] = {
! 421: { "fcmpu", 0xfc0007fe, 0xfc000000, " %{crfD},f%{A},f%{B}" },
! 422: { "frsp", 0xfc0007fe, 0xfc000018, "%{RC} f%{D},f%{B}" },
! 423: { "fctiw", 0xfc0007fe, 0xfc00001c, "%{RC} f%{D},f%{B}" },
! 424: { "fctiwz", 0xfc0007fe, 0xfc00001e, "%{RC} f%{D},f%{B}" },
! 425:
! 426: { "fdiv", 0xfc00003e, 0xfc000024, "%{RC} f%{D},f%{A},f%{B}" },
! 427: { "fsub", 0xfc00003e, 0xfc000028, "%{RC} f%{D},f%{A},f%{B}" },
! 428: { "fadd", 0xfc00003e, 0xfc00002a, "%{RC} f%{D},f%{A},f%{B}" },
! 429: { "fsqrt", 0xfc00003e, 0xfc00002c, "%{RC} f%{D},f%{B}" },
! 430: { "fsel", 0xfc00003e, 0xfc00002e, "%{RC} f%{D},f%{A},f%{C},f%{B}" },
! 431: { "fmul", 0xfc00003e, 0xfc000032, "%{RC} f%{D},f%{A},f%{C}" },
! 432: { "frsqrte", 0xfc00003e, 0xfc000034, "%{RC} f%{D},f%{B}" },
! 433: { "fmsub", 0xfc00003e, 0xfc000038, "%{RC} f%{D},f%{A},f%{C},f%{B}" },
! 434: { "fmadd", 0xfc00003e, 0xfc00003a, "%{RC} f%{D},f%{A},f%{C},f%{B}" },
! 435: { "fnmsub", 0xfc00003e, 0xfc00003c, "%{RC} f%{D},f%{A},f%{C},f%{B}" },
! 436: { "fnmadd", 0xfc00003e, 0xfc00003e, "%{RC} f%{D},f%{A},f%{C},f%{B}" },
! 437:
! 438: { "fcmpo", 0xfc0007fe, 0xfc000040, "%{RC} f%{D},f%{A},f%{C}" },
! 439: { "mtfsb1", 0xfc0007fe, 0xfc00004c, "%{RC} f%{D},f%{A},f%{C}" },
! 440: { "fneg", 0xfc0007fe, 0xfc000050, "%{RC} f%{D},f%{A},f%{C}" },
! 441: { "mcrfs", 0xfc0007fe, 0xfc000080, "%{RC} f%{D},f%{A},f%{C}" },
! 442: { "mtfsb0", 0xfc0007fe, 0xfc00008c, "%{RC} %{crfD},f%{C}" },
! 443: { "fmr", 0xfc0007fe, 0xfc000090, "%{RC} f%{D},f%{B}" },
! 444: { "mtfsfi", 0xfc0007fe, 0xfc00010c, "%{RC} %{crfD},f%{C},%{IMM}" },
! 445:
! 446: { "fnabs", 0xfc0007fe, 0xfc000110, "%{RC} f%{D},f%{B}" },
! 447: { "fabs", 0xfc0007fe, 0xfc000210, "%{RC} f%{D},f%{B}" },
! 448: { "mffs", 0xfc0007fe, 0xfc00048e, "%{RC} f%{D},f%{B}" },
! 449: { "mtfsf", 0xfc0007fe, 0xfc00058e, "%{RC} %{FM},f%{B}" },
! 450: { "fctid", 0xfc0007fe, 0xfc00065c, "%{RC} f%{D},f%{B}" },
! 451: { "fctidz", 0xfc0007fe, 0xfc00065e, "%{RC} f%{D},f%{B}" },
! 452: { "fcfid", 0xfc0007fe, 0xfc00069c, "%{RC} f%{D},f%{B}" },
! 453: { "", 0x0, 0x0, "" }
! 454: };
! 455:
! 456: void
! 457: op_ill(u_int32_t addr, instr_t instr)
! 458: {
! 459: db_printf("illegal instruction %x\n", instr);
! 460: }
! 461:
! 462: /*
! 463: * Extracts bits out of an instruction opcode, base indicates the lsb
! 464: * to keep.
! 465: * Note that this uses the PowerPC bit number for base, MSb == 0
! 466: * because all of the documentation is written that way.
! 467: */
! 468: u_int32_t
! 469: extract_field(u_int32_t value, u_int32_t base, u_int32_t width)
! 470: {
! 471: u_int32_t mask = (1 << width) - 1;
! 472: return ((value >> (31 - base)) & mask);
! 473: }
! 474:
! 475: const struct opcode * search_op(const struct opcode *);
! 476:
! 477: char *db_BOBI_cond[] = {
! 478: "ge",
! 479: "le",
! 480: "ne",
! 481: "ns",
! 482: "lt",
! 483: "gt",
! 484: "eq",
! 485: "so"
! 486: };
! 487: /* what about prediction directions? */
! 488: char *db_BO_op[] = {
! 489: "dnzf",
! 490: "dnzf-",
! 491: "dzf",
! 492: "dzf-",
! 493: "",
! 494: "",
! 495: "",
! 496: "",
! 497: "dnzt",
! 498: "dnzt-",
! 499: "dzt",
! 500: "dzt-",
! 501: "",
! 502: "",
! 503: "",
! 504: "",
! 505: "dnz",
! 506: "dnz",
! 507: "dz",
! 508: "dz",
! 509: "",
! 510: "",
! 511: "",
! 512: "",
! 513: "dnz",
! 514: "dnz",
! 515: "dz",
! 516: "dz",
! 517: "",
! 518: "",
! 519: "",
! 520: ""
! 521: };
! 522:
! 523: char *BItbl[] = {
! 524: "", "gt", "eq", "so"
! 525: };
! 526:
! 527: char BO_uses_tbl[32] = {
! 528: /* 0 */ 1,
! 529: /* 1 */ 1,
! 530: /* 2 */ 1,
! 531: /* 3 */ 1,
! 532: /* 4 */ 0,
! 533: /* 5 */ 0,
! 534: /* 6 */ 0, /* invalid */
! 535: /* 7 */ 0, /* invalid */
! 536: /* 8 */ 1,
! 537: /* 9 */ 1,
! 538: /* a */ 1,
! 539: /* b */ 1,
! 540: /* c */ 0,
! 541: /* d */ 0,
! 542: /* e */ 0, /* invalid */
! 543: /* f */ 1,
! 544: /* 10 */ 1,
! 545: /* 11 */ 1,
! 546: /* 12 */ 1,
! 547: /* 13 */ 1,
! 548: /* 14 */ 1,
! 549: /* 15 */ 0, /* invalid */
! 550: /* 16 */ 0, /* invalid */
! 551: /* 17 */ 0, /* invalid */
! 552: /* 18 */ 0, /* invalid */
! 553: /* 19 */ 0, /* invalid */
! 554: /* 1a */ 0, /* invalid */
! 555: /* 1b */ 0, /* invalid */
! 556: /* 1c */ 0, /* invalid */
! 557: /* 1d */ 0, /* invalid */
! 558: /* 1e */ 0, /* invalid */
! 559: /* 1f */ 0, /* invalid */
! 560: };
! 561:
! 562: void
! 563: disasm_process_field(u_int32_t addr, instr_t instr, char **ppfmt,
! 564: char *disasm_buf, size_t bufsize)
! 565: {
! 566: char field [8];
! 567: char lbuf[50];
! 568: int i;
! 569: char *pfmt = *ppfmt;
! 570: enum opf opf;
! 571: char *name;
! 572: db_expr_t offset;
! 573:
! 574: /* find field */
! 575: if (pfmt[0] != '%' || pfmt[1] != '{') {
! 576: printf("error in disasm fmt [%s]\n", pfmt);
! 577: }
! 578: pfmt = &pfmt[2];
! 579: for (i = 0;
! 580: pfmt[i] != '\0' && pfmt[i] != '}' && i < sizeof(field);
! 581: i++) {
! 582: field[i] = pfmt[i];
! 583: }
! 584: if (i == sizeof(field)) {
! 585: printf("error in disasm fmt [%s]\n", pfmt);
! 586: return;
! 587: }
! 588: field[i] = 0;
! 589: if (pfmt[i] == '\0') {
! 590: /* match following close paren { */
! 591: printf("disasm_process_field: missing } in [%s]\n", pfmt);
! 592: }
! 593: *ppfmt = &pfmt[i+1];
! 594: opf = Opf_INVALID;
! 595: for (i = 0; db_fields[i].name != NULL; i++) {
! 596: if (strcmp(db_fields[i].name, field) == 0) {
! 597: opf = db_fields[i].opf;
! 598: break;
! 599: }
! 600: }
! 601: switch (opf) {
! 602: case Opf_INVALID:
! 603: {
! 604: printf("unable to find variable [%s]\n", field);
! 605: }
! 606: case Opf_A:
! 607: {
! 608: u_int A;
! 609: A = extract_field(instr, 15, 5);
! 610: snprintf(lbuf, sizeof (lbuf), "r%d", A);
! 611: strlcat (disasm_buf, lbuf, bufsize);
! 612: }
! 613: break;
! 614: case Opf_A0:
! 615: {
! 616: u_int A;
! 617: A = extract_field(instr, 15, 5);
! 618: if (A != 0) {
! 619: snprintf(lbuf, sizeof (lbuf), "r%d,", A);
! 620: strlcat (disasm_buf, lbuf, bufsize);
! 621: }
! 622: }
! 623: break;
! 624: case Opf_AA:
! 625: if (instr & 0x2) {
! 626: strlcat (disasm_buf, "a", bufsize);
! 627: }
! 628: break;
! 629: case Opf_LI:
! 630: {
! 631: u_int LI;
! 632: LI = extract_field(instr, 29, 24);
! 633: LI = LI << 2;
! 634: if (LI & 0x02000000) {
! 635: LI |= ~0x03ffffff;
! 636: }
! 637: if ((instr & (1 << 1)) == 0) {
! 638: /* CHECK AA bit */
! 639: LI = addr + LI;
! 640: }
! 641: db_find_sym_and_offset(LI, &name, &offset);
! 642: if (name) {
! 643: if (offset == 0) {
! 644: snprintf(lbuf, sizeof (lbuf),
! 645: "0x%x (%s)", LI, name);
! 646: strlcat (disasm_buf, lbuf, bufsize);
! 647: } else {
! 648: snprintf(lbuf, sizeof (lbuf),
! 649: "0x%x (%s+0x%lx)", LI, name,
! 650: offset);
! 651: strlcat (disasm_buf, lbuf, bufsize);
! 652: }
! 653: } else {
! 654: snprintf(lbuf, sizeof (lbuf), "0x%x", LI);
! 655: strlcat (disasm_buf, lbuf, bufsize);
! 656: }
! 657: }
! 658: break;
! 659: case Opf_B:
! 660: {
! 661: u_int B;
! 662: B = extract_field(instr, 20, 5);
! 663: snprintf(lbuf, sizeof (lbuf), "r%d", B);
! 664: strlcat (disasm_buf, lbuf, bufsize);
! 665: }
! 666: break;
! 667: case Opf_BD:
! 668: {
! 669: u_int BD;
! 670: BD = extract_field(instr, 29, 14);
! 671: BD = BD << 2;
! 672: if (BD & 0x00008000) {
! 673: BD &= ~0x00007fff;
! 674: }
! 675: if ((instr & (1 << 1)) == 0) {
! 676: /* CHECK AA bit */
! 677: BD = addr + BD;
! 678: }
! 679: db_find_sym_and_offset(BD, &name, &offset);
! 680: if (name) {
! 681: if (offset == 0) {
! 682: snprintf(lbuf, sizeof (lbuf),
! 683: "0x%x (%s)", BD, name);
! 684: strlcat (disasm_buf, lbuf, bufsize);
! 685: } else {
! 686: snprintf(lbuf, sizeof (lbuf),
! 687: "0x%x (%s+0x%lx)", BD, name, offset);
! 688: strlcat (disasm_buf, lbuf, bufsize);
! 689: }
! 690: } else {
! 691: snprintf(lbuf, sizeof (lbuf), "0x%x", BD);
! 692: strlcat (disasm_buf, lbuf, bufsize);
! 693: }
! 694: }
! 695: break;
! 696: case Opf_BI1:
! 697: case Opf_BI:
! 698: {
! 699: int BO, BI, cr, printcomma = 0;
! 700: BO = extract_field(instr, 10, 5);
! 701: BI = extract_field(instr, 15, 5);
! 702: cr = (BI >> 2) & 7;
! 703: if (cr != 0) {
! 704: snprintf(lbuf, sizeof (lbuf), "cr%d", cr);
! 705: strlcat (disasm_buf, lbuf, bufsize);
! 706: printcomma = 1;
! 707: }
! 708: if (BO_uses_tbl[BO]) {
! 709: if ((cr != 0) && ((BI & 3) != 0) &&
! 710: BO_uses_tbl[BO] != 0)
! 711: strlcat (disasm_buf, "+", bufsize);
! 712:
! 713: snprintf(lbuf, sizeof (lbuf), "%s",
! 714: BItbl[BI & 3]);
! 715: strlcat (disasm_buf, lbuf, bufsize);
! 716: printcomma = 1;
! 717: }
! 718: if ((opf == Opf_BI) && printcomma)
! 719: strlcat (disasm_buf, ",", bufsize);
! 720: }
! 721: break;
! 722: case Opf_BO:
! 723: {
! 724: int BO, BI;
! 725: BO = extract_field(instr, 10, 5);
! 726: strlcat (disasm_buf, db_BO_op[BO], bufsize);
! 727: if ((BO & 4) != 0) {
! 728: BI = extract_field(instr, 15, 5);
! 729: strlcat (disasm_buf,
! 730: db_BOBI_cond[(BI & 0x3)| (((BO & 8) >> 1))],
! 731: bufsize);
! 732:
! 733: if (BO & 1)
! 734: strlcat (disasm_buf, "-", bufsize);
! 735: }
! 736: }
! 737: break;
! 738: case Opf_C:
! 739: {
! 740: u_int C;
! 741: C = extract_field(instr, 25, 5);
! 742: snprintf(lbuf, sizeof (lbuf), "r%d, ", C);
! 743: strlcat (disasm_buf, lbuf, bufsize);
! 744: }
! 745: break;
! 746: case Opf_CRM:
! 747: {
! 748: u_int CRM;
! 749: CRM = extract_field(instr, 19, 8);
! 750: snprintf(lbuf, sizeof (lbuf), "0x%x", CRM);
! 751: strlcat (disasm_buf, lbuf, bufsize);
! 752: }
! 753: break;
! 754: case Opf_FM:
! 755: {
! 756: u_int FM;
! 757: FM = extract_field(instr, 10, 8);
! 758: snprintf(lbuf, sizeof (lbuf), "%d", FM);
! 759: strlcat (disasm_buf, lbuf, bufsize);
! 760: }
! 761: break;
! 762: case Opf_LK:
! 763: if (instr & 0x1) {
! 764: strlcat (disasm_buf, "l", bufsize);
! 765: }
! 766: break;
! 767: case Opf_MB:
! 768: {
! 769: u_int MB;
! 770: MB = extract_field(instr, 20, 5);
! 771: snprintf(lbuf, sizeof (lbuf), "%d", MB);
! 772: strlcat (disasm_buf, lbuf, bufsize);
! 773: }
! 774: break;
! 775: case Opf_ME:
! 776: {
! 777: u_int ME;
! 778: ME = extract_field(instr, 25, 5);
! 779: snprintf(lbuf, sizeof (lbuf), "%d", ME);
! 780: strlcat (disasm_buf, lbuf, bufsize);
! 781: }
! 782: break;
! 783: case Opf_NB:
! 784: {
! 785: u_int NB;
! 786: NB = extract_field(instr, 20, 5);
! 787: if (NB == 0 ) {
! 788: NB=32;
! 789: }
! 790: snprintf(lbuf, sizeof (lbuf), "%d", NB);
! 791: strlcat (disasm_buf, lbuf, bufsize);
! 792: }
! 793: break;
! 794: case Opf_OE:
! 795: if (instr & (1 << (31-21))) {
! 796: strlcat (disasm_buf, "o", bufsize);
! 797: }
! 798: break;
! 799: case Opf_RC:
! 800: if (instr & 0x1) {
! 801: strlcat (disasm_buf, ".", bufsize);
! 802: }
! 803: break;
! 804: case Opf_S:
! 805: case Opf_D:
! 806: {
! 807: u_int D;
! 808: /* S and D are the same */
! 809: D = extract_field(instr, 10, 5);
! 810: snprintf(lbuf, sizeof (lbuf), "r%d", D);
! 811: strlcat (disasm_buf, lbuf, bufsize);
! 812: }
! 813: break;
! 814: case Opf_SH:
! 815: {
! 816: u_int SH;
! 817: SH = extract_field(instr, 20, 5);
! 818: snprintf(lbuf, sizeof (lbuf), "%d", SH);
! 819: strlcat (disasm_buf, lbuf, bufsize);
! 820: }
! 821: break;
! 822: case Opf_SIMM:
! 823: case Opf_d:
! 824: {
! 825: int32_t IMM;
! 826: IMM = extract_field(instr, 31, 16);
! 827: if (IMM & 0x8000)
! 828: IMM |= ~0x7fff;
! 829: snprintf(lbuf, sizeof (lbuf), "%d", IMM);
! 830: strlcat (disasm_buf, lbuf, bufsize);
! 831: }
! 832: break;
! 833: case Opf_UIMM:
! 834: {
! 835: u_int32_t IMM;
! 836: IMM = extract_field(instr, 31, 16);
! 837: snprintf(lbuf, sizeof (lbuf), "0x%x", IMM);
! 838: strlcat (disasm_buf, lbuf, bufsize);
! 839: }
! 840: break;
! 841: case Opf_SR:
! 842: {
! 843: u_int SR;
! 844: SR = extract_field(instr, 15, 3);
! 845: snprintf(lbuf, sizeof (lbuf), "sr%d", SR);
! 846: strlcat (disasm_buf, lbuf, bufsize);
! 847: }
! 848: break;
! 849: case Opf_TO:
! 850: {
! 851: u_int TO;
! 852: TO = extract_field(instr, 10, 1);
! 853: snprintf(lbuf, sizeof (lbuf), "%d", TO);
! 854: strlcat (disasm_buf, lbuf, bufsize);
! 855: }
! 856: break;
! 857: case Opf_crbA:
! 858: {
! 859: u_int crbA;
! 860: crbA = extract_field(instr, 15, 5);
! 861: snprintf(lbuf, sizeof (lbuf), "%d", crbA);
! 862: strlcat (disasm_buf, lbuf, bufsize);
! 863: }
! 864: break;
! 865: case Opf_crbB:
! 866: {
! 867: u_int crbB;
! 868: crbB = extract_field(instr, 20, 5);
! 869: snprintf(lbuf, sizeof (lbuf), "%d", crbB);
! 870: strlcat (disasm_buf, lbuf, bufsize);
! 871: }
! 872: break;
! 873: case Opf_crbD:
! 874: {
! 875: u_int crfD;
! 876: crfD = extract_field(instr, 8, 3);
! 877: snprintf(lbuf, sizeof (lbuf), "crf%d", crfD);
! 878: strlcat (disasm_buf, lbuf, bufsize);
! 879: }
! 880: break;
! 881: case Opf_crfD:
! 882: {
! 883: u_int crfD;
! 884: crfD = extract_field(instr, 8, 3);
! 885: snprintf(lbuf, sizeof (lbuf), "crf%d", crfD);
! 886: strlcat (disasm_buf, lbuf, bufsize);
! 887: }
! 888: break;
! 889: case Opf_crfS:
! 890: {
! 891: u_int crfS;
! 892: crfS = extract_field(instr, 13, 3);
! 893: snprintf(lbuf, sizeof (lbuf), "%d", crfS);
! 894: strlcat (disasm_buf, lbuf, bufsize);
! 895: }
! 896: break;
! 897: break;
! 898: case Opf_mb:
! 899: {
! 900: u_int mb, mbl, mbh;
! 901: mbl = extract_field(instr, 25, 4);
! 902: mbh = extract_field(instr, 26, 1);
! 903: mb = mbh << 4 | mbl;
! 904: snprintf(lbuf, sizeof (lbuf), ", %d", mb);
! 905: strlcat (disasm_buf, lbuf, bufsize);
! 906: }
! 907: break;
! 908: case Opf_sh:
! 909: {
! 910: u_int sh, shl, shh;
! 911: shl = extract_field(instr, 19, 4);
! 912: shh = extract_field(instr, 20, 1);
! 913: sh = shh << 4 | shl;
! 914: snprintf(lbuf, sizeof (lbuf), ", %d", sh);
! 915: strlcat (disasm_buf, lbuf, bufsize);
! 916: }
! 917: break;
! 918: case Opf_spr:
! 919: {
! 920: u_int spr;
! 921: u_int sprl;
! 922: u_int sprh;
! 923: char *reg;
! 924: sprl = extract_field(instr, 15, 5);
! 925: sprh = extract_field(instr, 20, 5);
! 926: spr = sprh << 5 | sprl;
! 927:
! 928: /* this table could be written better */
! 929: switch (spr) {
! 930: case 1:
! 931: reg = "xer";
! 932: break;
! 933: case 8:
! 934: reg = "lr";
! 935: break;
! 936: case 9:
! 937: reg = "ctr";
! 938: break;
! 939: case 18:
! 940: reg = "dsisr";
! 941: break;
! 942: case 19:
! 943: reg = "dar";
! 944: break;
! 945: case 22:
! 946: reg = "dec";
! 947: break;
! 948: case 25:
! 949: reg = "sdr1";
! 950: break;
! 951: case 26:
! 952: reg = "srr0";
! 953: break;
! 954: case 27:
! 955: reg = "srr1";
! 956: break;
! 957: case 272:
! 958: reg = "SPRG0";
! 959: break;
! 960: case 273:
! 961: reg = "SPRG1";
! 962: break;
! 963: case 274:
! 964: reg = "SPRG3";
! 965: break;
! 966: case 275:
! 967: reg = "SPRG3";
! 968: break;
! 969: case 280:
! 970: reg = "asr";
! 971: break;
! 972: case 282:
! 973: reg = "aer";
! 974: break;
! 975: case 287:
! 976: reg = "pvr";
! 977: break;
! 978: case 528:
! 979: reg = "ibat0u";
! 980: break;
! 981: case 529:
! 982: reg = "ibat0l";
! 983: break;
! 984: case 530:
! 985: reg = "ibat1u";
! 986: break;
! 987: case 531:
! 988: reg = "ibat1l";
! 989: break;
! 990: case 532:
! 991: reg = "ibat2u";
! 992: break;
! 993: case 533:
! 994: reg = "ibat2l";
! 995: break;
! 996: case 534:
! 997: reg = "ibat3u";
! 998: break;
! 999: case 535:
! 1000: reg = "ibat3l";
! 1001: break;
! 1002: case 536:
! 1003: reg = "dbat0u";
! 1004: break;
! 1005: case 537:
! 1006: reg = "dbat0l";
! 1007: break;
! 1008: case 538:
! 1009: reg = "dbat1u";
! 1010: break;
! 1011: case 539:
! 1012: reg = "dbat1l";
! 1013: break;
! 1014: case 540:
! 1015: reg = "dbat2u";
! 1016: break;
! 1017: case 541:
! 1018: reg = "dbat2l";
! 1019: break;
! 1020: case 542:
! 1021: reg = "dbat3u";
! 1022: break;
! 1023: case 543:
! 1024: reg = "dbat3l";
! 1025: break;
! 1026: case 1013:
! 1027: reg = "dabr";
! 1028: break;
! 1029: default:
! 1030: reg = 0;
! 1031: }
! 1032: if (reg == 0) {
! 1033: snprintf(lbuf, sizeof (lbuf), "spr%d", spr);
! 1034: strlcat (disasm_buf, lbuf, bufsize);
! 1035: } else {
! 1036: snprintf(lbuf, sizeof (lbuf), "%s", reg);
! 1037: strlcat (disasm_buf, lbuf, bufsize);
! 1038: }
! 1039: }
! 1040: break;
! 1041: case Opf_tbr:
! 1042: {
! 1043: u_int tbr;
! 1044: u_int tbrl;
! 1045: u_int tbrh;
! 1046: char *reg = NULL;
! 1047: tbrl = extract_field(instr, 15, 5);
! 1048: tbrh = extract_field(instr, 20, 5);
! 1049: tbr = tbrh << 5 | tbrl;
! 1050:
! 1051: switch (tbr) {
! 1052: case 268:
! 1053: reg = "tbl";
! 1054: break;
! 1055: case 269:
! 1056: reg = "tbu";
! 1057: break;
! 1058: default:
! 1059: reg = 0;
! 1060: }
! 1061: if (reg == NULL) {
! 1062: snprintf(lbuf, sizeof (lbuf), "tbr%d", tbr);
! 1063: strlcat (disasm_buf, lbuf, bufsize);
! 1064: } else {
! 1065: snprintf(lbuf, sizeof (lbuf), "%s", reg);
! 1066: strlcat (disasm_buf, lbuf, bufsize);
! 1067: }
! 1068: }
! 1069: break;
! 1070: }
! 1071: }
! 1072:
! 1073: void
! 1074: disasm_fields(u_int32_t addr, const struct opcode *popcode, instr_t instr,
! 1075: char *disasm_str, size_t bufsize)
! 1076: {
! 1077: char *pfmt;
! 1078: char cbuf[2];
! 1079: if (popcode->decode_str == NULL || popcode->decode_str[0] == '0') {
! 1080: return;
! 1081: }
! 1082: pfmt = popcode->decode_str;
! 1083:
! 1084: while (*pfmt != '\0') {
! 1085: if (*pfmt == '%') {
! 1086: disasm_process_field(addr, instr, &pfmt, disasm_str,
! 1087: bufsize);
! 1088: } else {
! 1089: cbuf[0] = *pfmt;
! 1090: cbuf[1] = '\0';
! 1091: strlcat(disasm_str, cbuf, bufsize);
! 1092: pfmt++;
! 1093: }
! 1094: }
! 1095: }
! 1096:
! 1097: void
! 1098: op_base(u_int32_t addr, instr_t instr)
! 1099: {
! 1100: dis_ppc(addr, opcodes, instr);
! 1101: }
! 1102:
! 1103: void
! 1104: op_cl_x13(u_int32_t addr, instr_t instr)
! 1105: {
! 1106: dis_ppc(addr, opcodes_13, instr);
! 1107: }
! 1108:
! 1109: void
! 1110: op_cl_x1e(u_int32_t addr, instr_t instr)
! 1111: {
! 1112: dis_ppc(addr, opcodes_1e, instr);
! 1113: }
! 1114:
! 1115: void
! 1116: op_cl_x1f(u_int32_t addr, instr_t instr)
! 1117: {
! 1118: dis_ppc(addr, opcodes_1f, instr);
! 1119: }
! 1120:
! 1121: void
! 1122: op_cl_x3a(u_int32_t addr, instr_t instr)
! 1123: {
! 1124: dis_ppc(addr, opcodes_3a, instr);
! 1125: }
! 1126:
! 1127: void
! 1128: op_cl_x3b(u_int32_t addr, instr_t instr)
! 1129: {
! 1130: dis_ppc(addr, opcodes_3b, instr);
! 1131: }
! 1132:
! 1133: void
! 1134: op_cl_x3e(u_int32_t addr, instr_t instr)
! 1135: {
! 1136: dis_ppc(addr, opcodes_3e, instr);
! 1137: }
! 1138:
! 1139: void
! 1140: op_cl_x3f(u_int32_t addr, instr_t instr)
! 1141: {
! 1142: dis_ppc(addr, opcodes_3f, instr);
! 1143: }
! 1144:
! 1145: void
! 1146: dis_ppc(u_int32_t addr, const struct opcode *opcodeset, instr_t instr)
! 1147: {
! 1148: const struct opcode *op;
! 1149: int i;
! 1150: char disasm_str[80];
! 1151:
! 1152: for (i=0; opcodeset[i].mask != 0; i++) {
! 1153: op = &opcodeset[i];
! 1154: if ((instr & op->mask) == op->code) {
! 1155: disasm_fields(addr, op, instr, disasm_str,
! 1156: sizeof disasm_str);
! 1157: db_printf("%s%s\n", op->name, disasm_str);
! 1158: return;
! 1159: }
! 1160: }
! 1161: op_ill(addr, instr);
! 1162: }
! 1163:
! 1164: db_addr_t
! 1165: db_disasm(db_addr_t loc, boolean_t extended)
! 1166: {
! 1167: int class;
! 1168: instr_t opcode;
! 1169: opcode = *(instr_t *)(loc);
! 1170: class = opcode >> 26;
! 1171: (opcodes_base[class])(loc, opcode);
! 1172:
! 1173: return loc + 4;
! 1174: }
CVSweb