1 /* $OpenBSD: db_disasm.c,v 1.21 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
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
op_ill(u_int32_t addr,instr_t instr)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
extract_field(u_int32_t value,u_int32_t base,u_int32_t width)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 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
disasm_process_field(u_int32_t addr,instr_t instr,char ** ppfmt,char * disasm_buf,size_t bufsize)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 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
1083 void
disasm_fields(u_int32_t addr,const struct opcode * popcode,instr_t instr,char * disasm_str,size_t bufsize)1084 disasm_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
1108 void
op_base(u_int32_t addr,instr_t instr)1109 op_base(u_int32_t addr, instr_t instr)
1110 {
1111 dis_ppc(addr, opcodes, instr);
1112 }
1113
1114 void
op_cl_x13(u_int32_t addr,instr_t instr)1115 op_cl_x13(u_int32_t addr, instr_t instr)
1116 {
1117 dis_ppc(addr, opcodes_13, instr);
1118 }
1119
1120 void
op_cl_x1e(u_int32_t addr,instr_t instr)1121 op_cl_x1e(u_int32_t addr, instr_t instr)
1122 {
1123 dis_ppc(addr, opcodes_1e, instr);
1124 }
1125
1126 void
op_cl_x1f(u_int32_t addr,instr_t instr)1127 op_cl_x1f(u_int32_t addr, instr_t instr)
1128 {
1129 dis_ppc(addr, opcodes_1f, instr);
1130 }
1131
1132 void
op_cl_x3a(u_int32_t addr,instr_t instr)1133 op_cl_x3a(u_int32_t addr, instr_t instr)
1134 {
1135 dis_ppc(addr, opcodes_3a, instr);
1136 }
1137
1138 void
op_cl_x3b(u_int32_t addr,instr_t instr)1139 op_cl_x3b(u_int32_t addr, instr_t instr)
1140 {
1141 dis_ppc(addr, opcodes_3b, instr);
1142 }
1143
1144 void
op_cl_x3e(u_int32_t addr,instr_t instr)1145 op_cl_x3e(u_int32_t addr, instr_t instr)
1146 {
1147 dis_ppc(addr, opcodes_3e, instr);
1148 }
1149
1150 void
op_cl_x3f(u_int32_t addr,instr_t instr)1151 op_cl_x3f(u_int32_t addr, instr_t instr)
1152 {
1153 dis_ppc(addr, opcodes_3f, instr);
1154 }
1155
1156 void
dis_ppc(u_int32_t addr,const struct opcode * opcodeset,instr_t instr)1157 dis_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
1175 vaddr_t
db_disasm(vaddr_t loc,int extended)1176 db_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