1 /* $OpenBSD: db_disasm.c,v 1.15 2007/10/21 17:30:18 drahn 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 disasm_str[0] = '\0'; 1084 1085 while (*pfmt != '\0') { 1086 if (*pfmt == '%') { 1087 disasm_process_field(addr, instr, &pfmt, disasm_str, 1088 bufsize); 1089 } else { 1090 cbuf[0] = *pfmt; 1091 cbuf[1] = '\0'; 1092 strlcat(disasm_str, cbuf, bufsize); 1093 pfmt++; 1094 } 1095 } 1096 } 1097 1098 void 1099 op_base(u_int32_t addr, instr_t instr) 1100 { 1101 dis_ppc(addr, opcodes, instr); 1102 } 1103 1104 void 1105 op_cl_x13(u_int32_t addr, instr_t instr) 1106 { 1107 dis_ppc(addr, opcodes_13, instr); 1108 } 1109 1110 void 1111 op_cl_x1e(u_int32_t addr, instr_t instr) 1112 { 1113 dis_ppc(addr, opcodes_1e, instr); 1114 } 1115 1116 void 1117 op_cl_x1f(u_int32_t addr, instr_t instr) 1118 { 1119 dis_ppc(addr, opcodes_1f, instr); 1120 } 1121 1122 void 1123 op_cl_x3a(u_int32_t addr, instr_t instr) 1124 { 1125 dis_ppc(addr, opcodes_3a, instr); 1126 } 1127 1128 void 1129 op_cl_x3b(u_int32_t addr, instr_t instr) 1130 { 1131 dis_ppc(addr, opcodes_3b, instr); 1132 } 1133 1134 void 1135 op_cl_x3e(u_int32_t addr, instr_t instr) 1136 { 1137 dis_ppc(addr, opcodes_3e, instr); 1138 } 1139 1140 void 1141 op_cl_x3f(u_int32_t addr, instr_t instr) 1142 { 1143 dis_ppc(addr, opcodes_3f, instr); 1144 } 1145 1146 void 1147 dis_ppc(u_int32_t addr, const struct opcode *opcodeset, instr_t instr) 1148 { 1149 const struct opcode *op; 1150 int i; 1151 char disasm_str[80]; 1152 1153 for (i=0; opcodeset[i].mask != 0; i++) { 1154 op = &opcodeset[i]; 1155 if ((instr & op->mask) == op->code) { 1156 disasm_fields(addr, op, instr, disasm_str, 1157 sizeof disasm_str); 1158 db_printf("%s%s\n", op->name, disasm_str); 1159 return; 1160 } 1161 } 1162 op_ill(addr, instr); 1163 } 1164 1165 db_addr_t 1166 db_disasm(db_addr_t loc, boolean_t extended) 1167 { 1168 int class; 1169 instr_t opcode; 1170 opcode = *(instr_t *)(loc); 1171 class = opcode >> 26; 1172 (opcodes_base[class])(loc, opcode); 1173 1174 return loc + 4; 1175 } 1176