1/* $OpenBSD: db_disasm.c,v 1.4 2024/05/22 05:51:49 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 38enum 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 82struct 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 124struct opcode { 125 char *name; 126 u_int32_t mask; 127 u_int32_t code; 128 char *decode_str; 129}; 130 131typedef u_int32_t instr_t; 132typedef void (op_class_func) (u_int32_t addr, instr_t instr); 133 134u_int32_t extract_field(u_int32_t value, u_int32_t base, u_int32_t width); 135void disasm_fields(u_int32_t addr, const struct opcode *popcode, instr_t instr, 136 char *disasm_str, size_t bufsize); 137void disasm_process_field(u_int32_t addr, instr_t instr, char **ppfmt, 138 char *ppoutput, size_t bufsize); 139void dis_ppc(u_int32_t addr, const struct opcode *opcodeset, instr_t instr); 140 141 142op_class_func op_ill, op_base; 143op_class_func op_cl_x13, op_cl_x1e, op_cl_x1f; 144op_class_func op_cl_x3a, op_cl_x3b; 145op_class_func op_cl_x3e, op_cl_x3f; 146 147op_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 174const 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 */ 236const 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 */ 255const 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 */ 266const 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 */ 391const 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 */ 399const 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 */ 415const 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 */ 422const 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 458void 459op_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 */ 470u_int32_t 471extract_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 477char *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? */ 488char *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 523char *BItbl[] = { 524 "", "gt", "eq", "so" 525}; 526 527char 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 562void 563disasm_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 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 int 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_int 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_ds: 898 { 899 int ds; 900 ds = extract_field(instr, 29, 14); 901 ds = ds << 2; 902 if (ds & 0x8000) 903 ds |= ~0x7fff; 904 snprintf(lbuf, sizeof (lbuf), "%d", ds); 905 strlcat (disasm_buf, lbuf, bufsize); 906 } 907 break; 908 case Opf_mb: 909 { 910 u_int mb, mbl, mbh; 911 mbl = extract_field(instr, 25, 4); 912 mbh = extract_field(instr, 26, 1); 913 mb = mbh << 4 | mbl; 914 snprintf(lbuf, sizeof (lbuf), ", %d", mb); 915 strlcat (disasm_buf, lbuf, bufsize); 916 } 917 break; 918 case Opf_sh: 919 { 920 u_int sh, shl, shh; 921 shl = extract_field(instr, 19, 4); 922 shh = extract_field(instr, 20, 1); 923 sh = shh << 4 | shl; 924 snprintf(lbuf, sizeof (lbuf), ", %d", sh); 925 strlcat (disasm_buf, lbuf, bufsize); 926 } 927 break; 928 case Opf_spr: 929 { 930 u_int spr; 931 u_int sprl; 932 u_int sprh; 933 char *reg; 934 sprl = extract_field(instr, 15, 5); 935 sprh = extract_field(instr, 20, 5); 936 spr = sprh << 5 | sprl; 937 938 /* this table could be written better */ 939 switch (spr) { 940 case 1: 941 reg = "xer"; 942 break; 943 case 8: 944 reg = "lr"; 945 break; 946 case 9: 947 reg = "ctr"; 948 break; 949 case 18: 950 reg = "dsisr"; 951 break; 952 case 19: 953 reg = "dar"; 954 break; 955 case 22: 956 reg = "dec"; 957 break; 958 case 25: 959 reg = "sdr1"; 960 break; 961 case 26: 962 reg = "srr0"; 963 break; 964 case 27: 965 reg = "srr1"; 966 break; 967 case 272: 968 reg = "SPRG0"; 969 break; 970 case 273: 971 reg = "SPRG1"; 972 break; 973 case 274: 974 reg = "SPRG3"; 975 break; 976 case 275: 977 reg = "SPRG3"; 978 break; 979 case 280: 980 reg = "asr"; 981 break; 982 case 282: 983 reg = "aer"; 984 break; 985 case 287: 986 reg = "pvr"; 987 break; 988 case 528: 989 reg = "ibat0u"; 990 break; 991 case 529: 992 reg = "ibat0l"; 993 break; 994 case 530: 995 reg = "ibat1u"; 996 break; 997 case 531: 998 reg = "ibat1l"; 999 break; 1000 case 532: 1001 reg = "ibat2u"; 1002 break; 1003 case 533: 1004 reg = "ibat2l"; 1005 break; 1006 case 534: 1007 reg = "ibat3u"; 1008 break; 1009 case 535: 1010 reg = "ibat3l"; 1011 break; 1012 case 536: 1013 reg = "dbat0u"; 1014 break; 1015 case 537: 1016 reg = "dbat0l"; 1017 break; 1018 case 538: 1019 reg = "dbat1u"; 1020 break; 1021 case 539: 1022 reg = "dbat1l"; 1023 break; 1024 case 540: 1025 reg = "dbat2u"; 1026 break; 1027 case 541: 1028 reg = "dbat2l"; 1029 break; 1030 case 542: 1031 reg = "dbat3u"; 1032 break; 1033 case 543: 1034 reg = "dbat3l"; 1035 break; 1036 case 1013: 1037 reg = "dabr"; 1038 break; 1039 default: 1040 reg = 0; 1041 } 1042 if (reg == 0) { 1043 snprintf(lbuf, sizeof (lbuf), "spr%d", spr); 1044 strlcat (disasm_buf, lbuf, bufsize); 1045 } else { 1046 snprintf(lbuf, sizeof (lbuf), "%s", reg); 1047 strlcat (disasm_buf, lbuf, bufsize); 1048 } 1049 } 1050 break; 1051 case Opf_tbr: 1052 { 1053 u_int tbr; 1054 u_int tbrl; 1055 u_int tbrh; 1056 char *reg = NULL; 1057 tbrl = extract_field(instr, 15, 5); 1058 tbrh = extract_field(instr, 20, 5); 1059 tbr = tbrh << 5 | tbrl; 1060 1061 switch (tbr) { 1062 case 268: 1063 reg = "tbl"; 1064 break; 1065 case 269: 1066 reg = "tbu"; 1067 break; 1068 default: 1069 reg = 0; 1070 } 1071 if (reg == NULL) { 1072 snprintf(lbuf, sizeof (lbuf), "tbr%d", tbr); 1073 strlcat (disasm_buf, lbuf, bufsize); 1074 } else { 1075 snprintf(lbuf, sizeof (lbuf), "%s", reg); 1076 strlcat (disasm_buf, lbuf, bufsize); 1077 } 1078 } 1079 break; 1080 } 1081} 1082 1083void 1084disasm_fields(u_int32_t addr, const struct opcode *popcode, instr_t instr, 1085 char *disasm_str, size_t bufsize) 1086{ 1087 char *pfmt; 1088 char cbuf[2]; 1089 if (popcode->decode_str == NULL || popcode->decode_str[0] == '0') { 1090 return; 1091 } 1092 pfmt = popcode->decode_str; 1093 disasm_str[0] = '\0'; 1094 1095 while (*pfmt != '\0') { 1096 if (*pfmt == '%') { 1097 disasm_process_field(addr, instr, &pfmt, disasm_str, 1098 bufsize); 1099 } else { 1100 cbuf[0] = *pfmt; 1101 cbuf[1] = '\0'; 1102 strlcat(disasm_str, cbuf, bufsize); 1103 pfmt++; 1104 } 1105 } 1106} 1107 1108void 1109op_base(u_int32_t addr, instr_t instr) 1110{ 1111 dis_ppc(addr, opcodes, instr); 1112} 1113 1114void 1115op_cl_x13(u_int32_t addr, instr_t instr) 1116{ 1117 dis_ppc(addr, opcodes_13, instr); 1118} 1119 1120void 1121op_cl_x1e(u_int32_t addr, instr_t instr) 1122{ 1123 dis_ppc(addr, opcodes_1e, instr); 1124} 1125 1126void 1127op_cl_x1f(u_int32_t addr, instr_t instr) 1128{ 1129 dis_ppc(addr, opcodes_1f, instr); 1130} 1131 1132void 1133op_cl_x3a(u_int32_t addr, instr_t instr) 1134{ 1135 dis_ppc(addr, opcodes_3a, instr); 1136} 1137 1138void 1139op_cl_x3b(u_int32_t addr, instr_t instr) 1140{ 1141 dis_ppc(addr, opcodes_3b, instr); 1142} 1143 1144void 1145op_cl_x3e(u_int32_t addr, instr_t instr) 1146{ 1147 dis_ppc(addr, opcodes_3e, instr); 1148} 1149 1150void 1151op_cl_x3f(u_int32_t addr, instr_t instr) 1152{ 1153 dis_ppc(addr, opcodes_3f, instr); 1154} 1155 1156void 1157dis_ppc(u_int32_t addr, const struct opcode *opcodeset, instr_t instr) 1158{ 1159 const struct opcode *op; 1160 int i; 1161 char disasm_str[80]; 1162 1163 for (i=0; opcodeset[i].mask != 0; i++) { 1164 op = &opcodeset[i]; 1165 if ((instr & op->mask) == op->code) { 1166 disasm_fields(addr, op, instr, disasm_str, 1167 sizeof disasm_str); 1168 db_printf("%s%s\n", op->name, disasm_str); 1169 return; 1170 } 1171 } 1172 op_ill(addr, instr); 1173} 1174 1175vaddr_t 1176db_disasm(vaddr_t loc, int extended) 1177{ 1178 int class; 1179 instr_t opcode; 1180 opcode = *(instr_t *)(loc); 1181 class = opcode >> 26; 1182 (opcodes_base[class])(loc, opcode); 1183 1184 return loc + 4; 1185} 1186