1 /* $OpenBSD: db_disasm.c,v 1.16 2014/04/26 06:17:26 jsg 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 case Opf_mb: 898 { 899 u_int mb, mbl, mbh; 900 mbl = extract_field(instr, 25, 4); 901 mbh = extract_field(instr, 26, 1); 902 mb = mbh << 4 | mbl; 903 snprintf(lbuf, sizeof (lbuf), ", %d", mb); 904 strlcat (disasm_buf, lbuf, bufsize); 905 } 906 break; 907 case Opf_sh: 908 { 909 u_int sh, shl, shh; 910 shl = extract_field(instr, 19, 4); 911 shh = extract_field(instr, 20, 1); 912 sh = shh << 4 | shl; 913 snprintf(lbuf, sizeof (lbuf), ", %d", sh); 914 strlcat (disasm_buf, lbuf, bufsize); 915 } 916 break; 917 case Opf_spr: 918 { 919 u_int spr; 920 u_int sprl; 921 u_int sprh; 922 char *reg; 923 sprl = extract_field(instr, 15, 5); 924 sprh = extract_field(instr, 20, 5); 925 spr = sprh << 5 | sprl; 926 927 /* this table could be written better */ 928 switch (spr) { 929 case 1: 930 reg = "xer"; 931 break; 932 case 8: 933 reg = "lr"; 934 break; 935 case 9: 936 reg = "ctr"; 937 break; 938 case 18: 939 reg = "dsisr"; 940 break; 941 case 19: 942 reg = "dar"; 943 break; 944 case 22: 945 reg = "dec"; 946 break; 947 case 25: 948 reg = "sdr1"; 949 break; 950 case 26: 951 reg = "srr0"; 952 break; 953 case 27: 954 reg = "srr1"; 955 break; 956 case 272: 957 reg = "SPRG0"; 958 break; 959 case 273: 960 reg = "SPRG1"; 961 break; 962 case 274: 963 reg = "SPRG3"; 964 break; 965 case 275: 966 reg = "SPRG3"; 967 break; 968 case 280: 969 reg = "asr"; 970 break; 971 case 282: 972 reg = "aer"; 973 break; 974 case 287: 975 reg = "pvr"; 976 break; 977 case 528: 978 reg = "ibat0u"; 979 break; 980 case 529: 981 reg = "ibat0l"; 982 break; 983 case 530: 984 reg = "ibat1u"; 985 break; 986 case 531: 987 reg = "ibat1l"; 988 break; 989 case 532: 990 reg = "ibat2u"; 991 break; 992 case 533: 993 reg = "ibat2l"; 994 break; 995 case 534: 996 reg = "ibat3u"; 997 break; 998 case 535: 999 reg = "ibat3l"; 1000 break; 1001 case 536: 1002 reg = "dbat0u"; 1003 break; 1004 case 537: 1005 reg = "dbat0l"; 1006 break; 1007 case 538: 1008 reg = "dbat1u"; 1009 break; 1010 case 539: 1011 reg = "dbat1l"; 1012 break; 1013 case 540: 1014 reg = "dbat2u"; 1015 break; 1016 case 541: 1017 reg = "dbat2l"; 1018 break; 1019 case 542: 1020 reg = "dbat3u"; 1021 break; 1022 case 543: 1023 reg = "dbat3l"; 1024 break; 1025 case 1013: 1026 reg = "dabr"; 1027 break; 1028 default: 1029 reg = 0; 1030 } 1031 if (reg == 0) { 1032 snprintf(lbuf, sizeof (lbuf), "spr%d", spr); 1033 strlcat (disasm_buf, lbuf, bufsize); 1034 } else { 1035 snprintf(lbuf, sizeof (lbuf), "%s", reg); 1036 strlcat (disasm_buf, lbuf, bufsize); 1037 } 1038 } 1039 break; 1040 case Opf_tbr: 1041 { 1042 u_int tbr; 1043 u_int tbrl; 1044 u_int tbrh; 1045 char *reg = NULL; 1046 tbrl = extract_field(instr, 15, 5); 1047 tbrh = extract_field(instr, 20, 5); 1048 tbr = tbrh << 5 | tbrl; 1049 1050 switch (tbr) { 1051 case 268: 1052 reg = "tbl"; 1053 break; 1054 case 269: 1055 reg = "tbu"; 1056 break; 1057 default: 1058 reg = 0; 1059 } 1060 if (reg == NULL) { 1061 snprintf(lbuf, sizeof (lbuf), "tbr%d", tbr); 1062 strlcat (disasm_buf, lbuf, bufsize); 1063 } else { 1064 snprintf(lbuf, sizeof (lbuf), "%s", reg); 1065 strlcat (disasm_buf, lbuf, bufsize); 1066 } 1067 } 1068 break; 1069 } 1070 } 1071 1072 void 1073 disasm_fields(u_int32_t addr, const struct opcode *popcode, instr_t instr, 1074 char *disasm_str, size_t bufsize) 1075 { 1076 char *pfmt; 1077 char cbuf[2]; 1078 if (popcode->decode_str == NULL || popcode->decode_str[0] == '0') { 1079 return; 1080 } 1081 pfmt = popcode->decode_str; 1082 disasm_str[0] = '\0'; 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 } 1175