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