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