1 |
cebix |
1.1 |
/* |
2 |
|
|
* mon_ppc.cpp - PowerPC disassembler |
3 |
|
|
* |
4 |
cebix |
1.8 |
* cxmon (C) 1997-2004 Christian Bauer, Marc Hellwig |
5 |
cebix |
1.2 |
* |
6 |
|
|
* This program is free software; you can redistribute it and/or modify |
7 |
|
|
* it under the terms of the GNU General Public License as published by |
8 |
|
|
* the Free Software Foundation; either version 2 of the License, or |
9 |
|
|
* (at your option) any later version. |
10 |
|
|
* |
11 |
|
|
* This program is distributed in the hope that it will be useful, |
12 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 |
|
|
* GNU General Public License for more details. |
15 |
|
|
* |
16 |
|
|
* You should have received a copy of the GNU General Public License |
17 |
|
|
* along with this program; if not, write to the Free Software |
18 |
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
19 |
cebix |
1.1 |
*/ |
20 |
|
|
|
21 |
cebix |
1.2 |
#include "sysdeps.h" |
22 |
cebix |
1.1 |
|
23 |
|
|
#include "mon.h" |
24 |
cebix |
1.4 |
#include "mon_disass.h" |
25 |
cebix |
1.1 |
|
26 |
|
|
|
27 |
|
|
// Instruction fields |
28 |
gbeauche |
1.9 |
static int primop, exop, vxop, ra, rb, rc, rd; |
29 |
cebix |
1.1 |
static unsigned short imm; |
30 |
|
|
|
31 |
|
|
|
32 |
|
|
// Codes for trap instructions |
33 |
|
|
static char *to_code[32] = { |
34 |
|
|
NULL, "lgt", "llt", NULL, "eq", "lge", "lle", NULL, |
35 |
|
|
"gt", NULL, NULL, NULL, "ge", NULL, NULL, NULL, |
36 |
|
|
"lt", NULL, NULL, NULL, "le", NULL, NULL, NULL, |
37 |
|
|
"ne", NULL, NULL, NULL, NULL, NULL, NULL, "" |
38 |
|
|
}; |
39 |
|
|
|
40 |
|
|
|
41 |
|
|
// Macros for instruction forms |
42 |
|
|
#define iform(s, t) fprintf(f, "%s\t$%08x\n", s, t) |
43 |
|
|
|
44 |
|
|
#define bform(s, t) \ |
45 |
|
|
if (rd == 0) \ |
46 |
|
|
fprintf(f, "bdnzf%s\t%d,$%08x\n", s, ra, t); \ |
47 |
|
|
else if (rd == 2) \ |
48 |
|
|
fprintf(f, "bdzf%s\t%d,$%08x\n", s, ra, t); \ |
49 |
|
|
else if (rd == 4) { \ |
50 |
|
|
if (ra == 0) \ |
51 |
|
|
fprintf(f, "bge%s\t$%08x\n", s, t); \ |
52 |
|
|
else if (ra == 1) \ |
53 |
|
|
fprintf(f, "ble%s\t$%08x\n", s, t); \ |
54 |
|
|
else if (ra == 2) \ |
55 |
|
|
fprintf(f, "bne%s\t$%08x\n", s, t); \ |
56 |
|
|
else \ |
57 |
|
|
fprintf(f, "bf%s\t%d,$%08x\n", s, ra, t); \ |
58 |
|
|
} else if (rd == 8) \ |
59 |
|
|
fprintf(f, "bdnzt%s\t%d,$%08x\n", s, ra, t); \ |
60 |
|
|
else if (rd == 10) \ |
61 |
|
|
fprintf(f, "bdzt%s\t%d,$%08x\n", s, ra, t); \ |
62 |
|
|
else if (rd == 12) { \ |
63 |
|
|
if (ra == 0) \ |
64 |
|
|
fprintf(f, "blt%s\t$%08x\n", s, t); \ |
65 |
|
|
else if (ra == 1) \ |
66 |
|
|
fprintf(f, "bgt%s\t$%08x\n", s, t); \ |
67 |
|
|
else if (ra == 2) \ |
68 |
|
|
fprintf(f, "beq%s\t$%08x\n", s, t); \ |
69 |
|
|
else \ |
70 |
|
|
fprintf(f, "bt%s\t%d,$%08x\n", s, ra, t); \ |
71 |
|
|
} else if (rd == 16) \ |
72 |
|
|
fprintf(f, "bdnz%s\t$%08x\n", s, t); \ |
73 |
|
|
else if (rd == 18) \ |
74 |
|
|
fprintf(f, "bdz%s\t$%08x\n", s, t); \ |
75 |
|
|
else \ |
76 |
|
|
fprintf(f, "bc%s\t%d,%d,$%08x\n", s, rd, ra, t) |
77 |
|
|
|
78 |
|
|
#define scform(s) fprintf(f, s "\n") |
79 |
|
|
|
80 |
|
|
#define dform_ls(s) \ |
81 |
|
|
if (ra == 0) \ |
82 |
|
|
fprintf(f, "%s\tr%d,$%08x\n", s, rd, short(imm)); \ |
83 |
|
|
else \ |
84 |
|
|
fprintf(f, "%s\tr%d,$%04x(r%d)\n", s, rd, short(imm), ra) |
85 |
|
|
#define dform_fls(s) \ |
86 |
|
|
if (ra == 0) \ |
87 |
|
|
fprintf(f, "%s\tfr%d,$%08x\n", s, rd, short(imm)); \ |
88 |
|
|
else \ |
89 |
|
|
fprintf(f, "%s\tfr%d,$%04x(r%d)\n", s, rd, short(imm), ra) |
90 |
|
|
#define dform_simm(s) fprintf(f, "%s\tr%d,r%d,$%04x\n", s, rd, ra, short(imm)) |
91 |
|
|
#define dform_simmn(s) fprintf(f, "%s\tr%d,r%d,$%04x\n", s, rd, ra, (-imm) & 0xffff) |
92 |
|
|
#define dform_uimm(s) fprintf(f, "%s\tr%d,r%d,$%04x\n", s, ra, rd, imm) |
93 |
|
|
#define dform_crs(s) fprintf(f, "%s\tcrf%d,r%d,$%04x\n", s, rd >> 2, ra, short(imm)) |
94 |
|
|
#define dform_cru(s) fprintf(f, "%s\tcrf%d,r%d,$%04x\n", s, rd >> 2, ra, imm) |
95 |
|
|
#define dform_to(s) fprintf(f, "%s\t%d,r%d,$%04x\n", s, rd, ra, short(imm)) |
96 |
|
|
|
97 |
|
|
#define dsform(s) fprintf(f, "%s\tr%d,$%04x(r%d)\n", s, rd, short(imm & 0xfffc), ra) |
98 |
|
|
|
99 |
gbeauche |
1.9 |
#define xform_vls(s) \ |
100 |
|
|
if (ra == 0) \ |
101 |
|
|
fprintf(f, "%s\tv%d,r%d\n", s, rd, rb); \ |
102 |
|
|
else \ |
103 |
|
|
fprintf(f, "%s\tv%d,r%d,r%d\n", s, rd, ra, rb) |
104 |
cebix |
1.1 |
#define xform_ls(s) \ |
105 |
|
|
if (ra == 0) \ |
106 |
|
|
fprintf(f, "%s\tr%d,r%d\n", s, rd, rb); \ |
107 |
|
|
else \ |
108 |
|
|
fprintf(f, "%s\tr%d,r%d,r%d\n", s, rd, ra, rb) |
109 |
|
|
#define xform_fls(s) \ |
110 |
|
|
if (ra == 0) \ |
111 |
|
|
fprintf(f, "%s\tfr%d,r%d\n", s, rd, rb); \ |
112 |
|
|
else \ |
113 |
|
|
fprintf(f, "%s\tfr%d,r%d,r%d\n", s, rd, ra, rb) |
114 |
|
|
#define xform_lsswi(s) \ |
115 |
|
|
if (ra == 0) \ |
116 |
|
|
fprintf(f, "%s\tr%d,%d\n", s, rd, rb ? rb : 32); \ |
117 |
|
|
else \ |
118 |
|
|
fprintf(f, "%s\tr%d,r%d,%d\n", s, rd, ra, rb ? rb : 32) |
119 |
|
|
#define xform_db(s) fprintf(f, "%s\tr%d,r%d\n", s, rd, rb) |
120 |
|
|
#define xform_d(s) fprintf(f, "%s\tr%d\n", s, rd) |
121 |
|
|
#define xform_fsr(s) fprintf(f, s "\tr%d,%d\n", rd, ra & 0xf) |
122 |
|
|
#define xform_sabc(s) fprintf(f, "%s%s\tr%d,r%d,r%d\n", s, w & 1 ? "." : "", ra, rd, rb) |
123 |
|
|
#define xform_sac(s) fprintf(f, "%s%s\tr%d,r%d\n", s, w & 1 ? "." : "", ra, rd) |
124 |
|
|
#define xform_tsr(s) fprintf(f, s "\t%d,r%d\n", ra & 0xf, rd) |
125 |
|
|
#define xform_sash(s) fprintf(f, s "%s\tr%d,r%d,%d\n", w & 1 ? "." : "", ra, rd, rb) |
126 |
|
|
#define xform_crlab(s) fprintf(f, "%s\tcrf%d,r%d,r%d\n", s, rd >> 2, ra, rb) |
127 |
|
|
#define xform_fcrab(s) fprintf(f, "%s\tcrf%d,fr%d,fr%d\n", s, rd >> 2, ra, rb) |
128 |
|
|
#define xform_crcr(s) fprintf(f, "%s\tcrf%d,crf%d\n", s, rd >> 2, ra >> 2) |
129 |
|
|
#define xform_cr(s) fprintf(f, "%s\tcrf%d\n", s, rd >> 2) |
130 |
|
|
#define xform_cri(s) fprintf(f, s "%s\tcrf%d,%d\n", w & 1 ? "." : "", rd >> 2, rb >> 1) |
131 |
|
|
#define xform_to(s) fprintf(f, "%s\t%d,r%d,r%d\n", s, rd, ra, rb) |
132 |
|
|
#define xform_fdb(s) fprintf(f, "%s%s\tfr%d,fr%d\n", s, w & 1 ? "." : "", rd, rb) |
133 |
|
|
#define xform_fd(s) fprintf(f, "%s%s\tfr%d\n", s, w & 1 ? "." : "", rd) |
134 |
|
|
#define xform_crb(s) fprintf(f, "%s%s\tcrb%d\n", s, w & 1 ? "." : "", rd) |
135 |
|
|
#define xform_ab(s) fprintf(f, "%s\tr%d,r%d\n", s, ra, rb) |
136 |
|
|
#define xform_b(s) fprintf(f, "%s\tr%d\n", s, rb) |
137 |
|
|
#define xform(s) fprintf(f, s "\n") |
138 |
|
|
|
139 |
|
|
#define xlform_b(s) fprintf(f, "%s\t%d,%d\n", s, rd, ra) |
140 |
|
|
#define xlform_cr(s) fprintf(f, "%s\tcrb%d,crb%d,crb%d\n", s, rd, ra, rb) |
141 |
|
|
#define xlform_crcr(s) fprintf(f, "%s\tcrf%d,crf%d\n", s, rd >> 2, ra >> 2) |
142 |
|
|
#define xlform(s) fprintf(f, s "\n") |
143 |
|
|
|
144 |
|
|
#define xfxform_fspr(s) fprintf(f, "%s\tr%d,SPR%d\n", s, rd, ra | (rb << 5)) |
145 |
|
|
#define xfxform_crm(s) fprintf(f, s "\t$%02x,r%d\n", w >> 12 & 0xff, rd) |
146 |
|
|
#define xfxform_tspr(s) fprintf(f, "%s\tSPR%d,r%d\n", s, ra | (rb << 5), rd) |
147 |
|
|
#define xfxform_tb(s) fprintf(f, "%s\tr%d\n", s, rd) |
148 |
|
|
|
149 |
|
|
#define xflform(s) fprintf(f, s "%s\t$%02x,fr%d\n", w & 1 ? "." : "", w >> 17 & 0xff, rb) |
150 |
|
|
|
151 |
|
|
#define xsform(s) fprintf(f, s "%s\tr%d,r%d,%d\n", w & 1 ? "." : "", ra, rd, rb | (w & 2 ? 32 : 0)) |
152 |
|
|
|
153 |
|
|
#define xoform_dab(s) fprintf(f, "%s%s\tr%d,r%d,r%d\n", s, w & 1 ? "." : "", rd, ra, rb) |
154 |
|
|
#define xoform_da(s) fprintf(f, "%s%s\tr%d,r%d\n", s, w & 1 ? "." : "", rd, ra) |
155 |
|
|
|
156 |
|
|
#define aform_dab(s) fprintf(f, "%s%s\tfr%d,fr%d,fr%d\n", s, w & 1 ? "." : "", rd, ra, rb) |
157 |
|
|
#define aform_db(s) fprintf(f, "%s%s\tfr%d,fr%d\n", s, w & 1 ? "." : "", rd, rb) |
158 |
|
|
#define aform_dac(s) fprintf(f, "%s%s\tfr%d,fr%d,fr%d\n", s, w & 1 ? "." : "", rd, ra, rc) |
159 |
|
|
#define aform_dacb(s) fprintf(f, "%s%s\tfr%d,fr%d,fr%d,fr%d\n", s, w & 1 ? "." : "", rd, ra, rc, rb) |
160 |
|
|
|
161 |
|
|
#define mform(s) fprintf(f, "%s%s\tr%d,r%d,r%d,$%08x\n", s, w & 1 ? "." : "", ra, rd, rb, mbme2mask(w >> 6 & 31, w >>1 & 31)) |
162 |
|
|
#define mform_i(s) fprintf(f, "%s%s\tr%d,r%d,%d,$%08x\n", s, w & 1 ? "." : "", ra, rd, rb, mbme2mask(w >> 6 & 31, w >>1 & 31)) |
163 |
|
|
|
164 |
|
|
#define mdform(s) fprintf(f, "%s%s\tr%d,r%d,%d,%d\n", s, w & 1 ? "." : "", ra, rd, rb | (w & 2 ? 32 : 0), rc | (w & 32 ? 32 : 0)) |
165 |
|
|
|
166 |
|
|
#define mdsform(s) fprintf(f, "%s%s\tr%d,r%d,r%d,%d\n", s, w & 1 ? "." : "", ra, rd, rb, rc | (w & 32 ? 32 : 0)) |
167 |
|
|
|
168 |
gbeauche |
1.10 |
#define va_form(s) fprintf(f, "%s\tv%d,v%d,v%d,v%d\n", s, rd, ra, rb, rc) |
169 |
gbeauche |
1.9 |
#define vx_form(s) fprintf(f, "%s\tv%d,v%d,v%d\n", s, rd, ra, rb) |
170 |
gbeauche |
1.10 |
#define vxr_form(s) fprintf(f, "%s%s\tv%d,v%d,v%d\n", s, w & (1 << 10) ? "." : "", rd, ra, rb) |
171 |
|
|
#define vxi_ra_form(s) fprintf(f, "%s\tv%d,v%d,%d\n", s, rd, rb, ra) |
172 |
|
|
#define vx_raz_form(s) \ |
173 |
|
|
if (ra == 0) \ |
174 |
|
|
fprintf(f, "%s\tv%d,v%d\n", s, rd, rb); \ |
175 |
|
|
else \ |
176 |
|
|
fprintf(f, "?\n") |
177 |
|
|
#define vxi_ras_rbz_form(s) \ |
178 |
|
|
if (rb == 0) \ |
179 |
|
|
fprintf(f, "%s\tv%d,%d\n", s, rd, ra - (ra & 0x10 ? 0x20 : 0)); \ |
180 |
|
|
else \ |
181 |
|
|
fprintf(f, "?\n") |
182 |
cebix |
1.1 |
|
183 |
|
|
// Prototypes |
184 |
gbeauche |
1.9 |
static void disass4(FILE *f, unsigned int adr, unsigned int w); |
185 |
cebix |
1.1 |
static void disass19(FILE *f, unsigned int adr, unsigned int w); |
186 |
|
|
static void disass31(FILE *f, unsigned int adr, unsigned int w); |
187 |
|
|
static void disass59(FILE *f, unsigned int adr, unsigned int w); |
188 |
|
|
static void disass63(FILE *f, unsigned int adr, unsigned int w); |
189 |
|
|
static unsigned int mbme2mask(int mb, int me); |
190 |
|
|
static char *get_spr(int reg); |
191 |
|
|
|
192 |
|
|
|
193 |
|
|
/* |
194 |
|
|
* Disassemble one instruction |
195 |
|
|
*/ |
196 |
|
|
|
197 |
|
|
void disass_ppc(FILE *f, unsigned int adr, unsigned int w) |
198 |
|
|
{ |
199 |
|
|
// Divide instruction into fields |
200 |
|
|
primop = w >> 26; |
201 |
|
|
rd = w >> 21 & 0x1f; |
202 |
|
|
ra = w >> 16 & 0x1f; |
203 |
|
|
rb = w >> 11 & 0x1f; |
204 |
|
|
rc = w >> 6 & 0x1f; |
205 |
|
|
exop = w >> 1 & 0x3ff; |
206 |
gbeauche |
1.9 |
vxop = w & 0x7ff; |
207 |
cebix |
1.1 |
imm = w & 0xffff; |
208 |
|
|
|
209 |
|
|
// Decode primary opcode |
210 |
|
|
switch (primop) { |
211 |
|
|
case 2: // 64 bit |
212 |
|
|
if (to_code[rd] != NULL) |
213 |
|
|
fprintf(f, "td%si\tr%d,$%04x\n", to_code[rd], ra, short(imm)); |
214 |
|
|
else |
215 |
|
|
dform_to("tdi"); |
216 |
|
|
break; |
217 |
|
|
|
218 |
|
|
case 3: |
219 |
|
|
if (to_code[rd] != NULL) |
220 |
|
|
fprintf(f, "tw%si\tr%d,$%04x\n", to_code[rd], ra, short(imm)); |
221 |
|
|
else |
222 |
|
|
dform_to("twi"); |
223 |
|
|
break; |
224 |
|
|
|
225 |
gbeauche |
1.9 |
case 4: // AltiVec |
226 |
|
|
disass4(f, adr, w); |
227 |
|
|
break; |
228 |
cebix |
1.1 |
|
229 |
|
|
case 7: dform_simm("mulli"); break; |
230 |
|
|
case 8: dform_simm("subfic"); break; |
231 |
|
|
|
232 |
|
|
case 10: |
233 |
|
|
if (rd & 1) |
234 |
|
|
dform_cru("cmpldi"); // 64 bit |
235 |
|
|
else |
236 |
|
|
dform_cru("cmplwi"); |
237 |
|
|
break; |
238 |
|
|
|
239 |
|
|
case 11: |
240 |
|
|
if (rd & 1) |
241 |
|
|
dform_crs("cmpdi"); // 64 bit |
242 |
|
|
else |
243 |
|
|
dform_crs("cmpwi"); |
244 |
|
|
break; |
245 |
|
|
|
246 |
|
|
case 12: |
247 |
|
|
if (imm < 0x8000) |
248 |
|
|
dform_simm("addic"); |
249 |
|
|
else |
250 |
|
|
dform_simmn("subic"); |
251 |
|
|
break; |
252 |
|
|
|
253 |
|
|
case 13: |
254 |
|
|
if (imm < 0x8000) |
255 |
|
|
dform_simm("addic."); |
256 |
|
|
else |
257 |
|
|
dform_simmn("subic."); |
258 |
|
|
break; |
259 |
|
|
|
260 |
|
|
case 14: |
261 |
|
|
if (ra == 0) |
262 |
|
|
fprintf(f, "li\tr%d,$%04x\n", rd, short(imm)); |
263 |
|
|
else |
264 |
|
|
if (imm < 0x8000) |
265 |
|
|
dform_simm("addi"); |
266 |
|
|
else |
267 |
|
|
dform_simmn("subi"); |
268 |
|
|
break; |
269 |
|
|
|
270 |
|
|
case 15: |
271 |
|
|
if (ra == 0) |
272 |
|
|
fprintf(f, "lis\tr%d,$%04x\n", rd, imm); |
273 |
|
|
else |
274 |
|
|
if (imm < 0x8000) |
275 |
|
|
dform_simm("addis"); |
276 |
|
|
else |
277 |
|
|
dform_simmn("subis"); |
278 |
|
|
break; |
279 |
|
|
|
280 |
|
|
case 16: { |
281 |
|
|
int target = short(imm & 0xfffc); |
282 |
|
|
char *form; |
283 |
|
|
if (w & 1) |
284 |
|
|
if (w & 2) |
285 |
|
|
form = "la"; |
286 |
|
|
else { |
287 |
|
|
form = "l"; |
288 |
|
|
target += adr; |
289 |
|
|
} |
290 |
|
|
else |
291 |
|
|
if (w & 2) |
292 |
|
|
form = "a"; |
293 |
|
|
else { |
294 |
|
|
form = ""; |
295 |
|
|
target += adr; |
296 |
|
|
} |
297 |
|
|
bform(form, target); |
298 |
|
|
break; |
299 |
|
|
} |
300 |
|
|
|
301 |
|
|
case 17: |
302 |
|
|
if (w & 2) |
303 |
|
|
scform("sc"); |
304 |
|
|
else |
305 |
|
|
fprintf(f, "?\n"); |
306 |
|
|
break; |
307 |
|
|
|
308 |
|
|
case 18: { |
309 |
|
|
int target = w & 0x03fffffc; |
310 |
|
|
if (target & 0x02000000) |
311 |
|
|
target |= 0xfc000000; |
312 |
|
|
if (w & 1) |
313 |
|
|
if (w & 2) |
314 |
|
|
iform("bla", target); |
315 |
|
|
else |
316 |
|
|
iform("bl", adr + target); |
317 |
|
|
else |
318 |
|
|
if (w & 2) |
319 |
|
|
iform("ba", target); |
320 |
|
|
else |
321 |
|
|
iform("b", adr + target); |
322 |
|
|
break; |
323 |
|
|
} |
324 |
|
|
|
325 |
|
|
case 19: disass19(f, adr, w); break; |
326 |
|
|
case 20: mform_i("rlwimi"); break; |
327 |
|
|
case 21: mform_i("rlwinm"); break; |
328 |
|
|
case 23: mform("rlwnm"); break; |
329 |
|
|
|
330 |
|
|
case 24: |
331 |
|
|
if (rd == 0 && ra == 0 && imm == 0) |
332 |
|
|
fprintf(f, "nop\n"); |
333 |
|
|
else |
334 |
|
|
dform_uimm("ori"); |
335 |
|
|
break; |
336 |
|
|
|
337 |
|
|
case 25: dform_uimm("oris"); break; |
338 |
|
|
case 26: dform_uimm("xori"); break; |
339 |
|
|
case 27: dform_uimm("xoris"); break; |
340 |
|
|
case 28: dform_uimm("andi."); break; |
341 |
|
|
case 29: dform_uimm("andis."); break; |
342 |
|
|
|
343 |
|
|
case 30: // 64 bit |
344 |
|
|
switch (w >> 1 & 0xf) { |
345 |
|
|
case 0: case 1: mdform("rldicl"); break; |
346 |
|
|
case 2: case 3: mdform("rldicr"); break; |
347 |
|
|
case 4: case 5: mdform("rldic"); break; |
348 |
|
|
case 6: case 7: mdform("rldimi"); break; |
349 |
|
|
case 8: mdsform("rldcl"); break; |
350 |
|
|
case 9: mdsform("rldcr"); break; |
351 |
|
|
default: |
352 |
|
|
fprintf(f, "?\n"); |
353 |
|
|
break; |
354 |
|
|
}; |
355 |
|
|
break; |
356 |
|
|
|
357 |
|
|
case 31: disass31(f, adr, w); break; |
358 |
|
|
case 32: dform_ls("lwz"); break; |
359 |
|
|
case 33: dform_ls("lwzu"); break; |
360 |
|
|
case 34: dform_ls("lbz"); break; |
361 |
|
|
case 35: dform_ls("lbzu"); break; |
362 |
|
|
case 36: dform_ls("stw"); break; |
363 |
|
|
case 37: dform_ls("stwu"); break; |
364 |
|
|
case 38: dform_ls("stb"); break; |
365 |
|
|
case 39: dform_ls("stbu"); break; |
366 |
|
|
case 40: dform_ls("lhz"); break; |
367 |
|
|
case 41: dform_ls("lhzu"); break; |
368 |
|
|
case 42: dform_ls("lha"); break; |
369 |
|
|
case 43: dform_ls("lhau"); break; |
370 |
|
|
case 44: dform_ls("sth"); break; |
371 |
|
|
case 45: dform_ls("sthu"); break; |
372 |
|
|
case 46: dform_ls("lmw"); break; |
373 |
|
|
case 47: dform_ls("stmw"); break; |
374 |
|
|
case 48: dform_fls("lfs"); break; |
375 |
|
|
case 49: dform_fls("lfsu"); break; |
376 |
|
|
case 50: dform_fls("lfd"); break; |
377 |
|
|
case 51: dform_fls("lfdu"); break; |
378 |
|
|
case 52: dform_fls("stfs"); break; |
379 |
|
|
case 53: dform_fls("stfsu"); break; |
380 |
|
|
case 54: dform_fls("stfd"); break; |
381 |
|
|
case 55: dform_fls("stfdu"); break; |
382 |
|
|
|
383 |
|
|
case 58: // 64 bit |
384 |
|
|
switch (w & 3) { |
385 |
|
|
case 0: dsform("ld"); break; |
386 |
|
|
case 1: dsform("ldu"); break; |
387 |
|
|
case 2: dsform("lwa"); break; |
388 |
|
|
default: |
389 |
|
|
fprintf(f, "?\n"); |
390 |
|
|
break; |
391 |
|
|
} |
392 |
|
|
break; |
393 |
|
|
|
394 |
|
|
case 59: disass59(f, adr, w); break; |
395 |
|
|
|
396 |
|
|
case 62: // 64 bit |
397 |
|
|
switch (w & 3) { |
398 |
|
|
case 0: dsform("std"); break; |
399 |
|
|
case 1: dsform("stdu"); break; |
400 |
|
|
default: |
401 |
|
|
fprintf(f, "?\n"); |
402 |
|
|
break; |
403 |
|
|
} |
404 |
|
|
break; |
405 |
|
|
|
406 |
|
|
case 63: disass63(f, adr, w); break; |
407 |
|
|
|
408 |
|
|
default: |
409 |
|
|
if (!w) |
410 |
|
|
fprintf(f, "illegal\n"); |
411 |
|
|
else |
412 |
|
|
fprintf(f, "?\n"); |
413 |
|
|
break; |
414 |
|
|
} |
415 |
|
|
} |
416 |
|
|
|
417 |
|
|
|
418 |
|
|
/* |
419 |
gbeauche |
1.9 |
* Disassemble instruction with primary opcode = 4 (VX-Form) |
420 |
|
|
*/ |
421 |
|
|
|
422 |
|
|
static void disass4(FILE *f, unsigned int adr, unsigned int w) |
423 |
|
|
{ |
424 |
|
|
switch (vxop) { |
425 |
gbeauche |
1.10 |
case 1540: |
426 |
|
|
if (ra == 0 && rb == 0) |
427 |
|
|
fprintf(f, "mfvscr\tv%d\n", rd); |
428 |
|
|
else |
429 |
|
|
fprintf(f, "?\n"); |
430 |
|
|
break; |
431 |
|
|
case 1604: |
432 |
|
|
if (rd == 0 && ra == 0) |
433 |
|
|
fprintf(f, "mtvscr\tv%d\n", rb); |
434 |
|
|
else |
435 |
|
|
fprintf(f, "?\n"); |
436 |
|
|
break; |
437 |
gbeauche |
1.9 |
case 384: vx_form("vaddcuw"); break; |
438 |
|
|
case 10: vx_form("vaddfp"); break; |
439 |
|
|
case 768: vx_form("vaddsbs"); break; |
440 |
|
|
case 832: vx_form("vaddshs"); break; |
441 |
|
|
case 896: vx_form("vaddsws"); break; |
442 |
|
|
case 0: vx_form("vaddubm"); break; |
443 |
|
|
case 512: vx_form("vaddubs"); break; |
444 |
|
|
case 64: vx_form("vadduhm"); break; |
445 |
|
|
case 576: vx_form("vadduhs"); break; |
446 |
|
|
case 128: vx_form("vadduwm"); break; |
447 |
|
|
case 640: vx_form("vadduws"); break; |
448 |
|
|
case 1028: vx_form("vand"); break; |
449 |
|
|
case 1092: vx_form("vandc"); break; |
450 |
|
|
case 1282: vx_form("vavgsb"); break; |
451 |
|
|
case 1346: vx_form("vavgsh"); break; |
452 |
|
|
case 1410: vx_form("vavgsw"); break; |
453 |
|
|
case 1026: vx_form("vavgub"); break; |
454 |
|
|
case 1090: vx_form("vavguh"); break; |
455 |
|
|
case 1154: vx_form("vavguw"); break; |
456 |
gbeauche |
1.10 |
case 842: vxi_ra_form("vcfsx"); break; |
457 |
|
|
case 778: vxi_ra_form("vcfux"); break; |
458 |
|
|
case 966: case 966+1024: vxr_form("vcmpbfp"); break; |
459 |
|
|
case 198: case 198+1024: vxr_form("vcmpeqfp"); break; |
460 |
|
|
case 6: case 6+1024: vxr_form("vcmpequb"); break; |
461 |
|
|
case 70: case 70+1024: vxr_form("vcmpequh"); break; |
462 |
|
|
case 134: case 134+1024: vxr_form("vcmpequw"); break; |
463 |
|
|
case 454: case 454+1024: vxr_form("vcmpgefp"); break; |
464 |
|
|
case 710: case 710+1024: vxr_form("vcmpgtfp"); break; |
465 |
|
|
case 774: case 774+1024: vxr_form("vcmpgtsb"); break; |
466 |
|
|
case 838: case 838+1024: vxr_form("vcmpgtsh"); break; |
467 |
|
|
case 902: case 902+1024: vxr_form("vcmpgtsw"); break; |
468 |
|
|
case 518: case 518+1024: vxr_form("vcmpgtub"); break; |
469 |
|
|
case 582: case 582+1024: vxr_form("vcmpgtuh"); break; |
470 |
|
|
case 646: case 646+1024: vxr_form("vcmpgtuw"); break; |
471 |
|
|
case 970: vxi_ra_form("vctsxs"); break; |
472 |
|
|
case 906: vxi_ra_form("vctuxs"); break; |
473 |
|
|
case 394: vx_raz_form("vexptefp"); break; |
474 |
|
|
case 458: vx_raz_form("vlogefp"); break; |
475 |
gbeauche |
1.9 |
case 1034: vx_form("vmaxfp"); break; |
476 |
|
|
case 258: vx_form("vmaxsb"); break; |
477 |
|
|
case 322: vx_form("vmaxsh"); break; |
478 |
|
|
case 386: vx_form("vmaxsw"); break; |
479 |
|
|
case 2: vx_form("vmaxub"); break; |
480 |
gbeauche |
1.10 |
case 66: vx_form("vmaxuh"); break; |
481 |
gbeauche |
1.9 |
case 130: vx_form("vmaxuw"); break; |
482 |
|
|
case 1098: vx_form("vminfp"); break; |
483 |
|
|
case 770: vx_form("vminsb"); break; |
484 |
|
|
case 834: vx_form("vminsh"); break; |
485 |
|
|
case 898: vx_form("vminsw"); break; |
486 |
|
|
case 514: vx_form("vminub"); break; |
487 |
|
|
case 578: vx_form("vminuh"); break; |
488 |
|
|
case 642: vx_form("vminuw"); break; |
489 |
|
|
case 12: vx_form("vmrghb"); break; |
490 |
|
|
case 76: vx_form("vmrghh"); break; |
491 |
|
|
case 140: vx_form("vmrghw"); break; |
492 |
|
|
case 268: vx_form("vmrglb"); break; |
493 |
|
|
case 332: vx_form("vmrglh"); break; |
494 |
|
|
case 396: vx_form("vmrglw"); break; |
495 |
|
|
case 776: vx_form("vmulesb"); break; |
496 |
|
|
case 840: vx_form("vmulesh"); break; |
497 |
|
|
case 520: vx_form("vmuleub"); break; |
498 |
|
|
case 584: vx_form("vmuleuh"); break; |
499 |
|
|
case 264: vx_form("vmulosb"); break; |
500 |
|
|
case 328: vx_form("vmulosh"); break; |
501 |
|
|
case 8: vx_form("vmuloub"); break; |
502 |
|
|
case 72: vx_form("vmulouh"); break; |
503 |
|
|
case 1284: vx_form("vnor"); break; |
504 |
|
|
case 1156: vx_form("vor"); break; |
505 |
|
|
case 782: vx_form("vpkpx"); break; |
506 |
|
|
case 398: vx_form("vpkshss"); break; |
507 |
|
|
case 270: vx_form("vpkshus"); break; |
508 |
|
|
case 462: vx_form("vpkswss"); break; |
509 |
|
|
case 334: vx_form("vpkswus"); break; |
510 |
|
|
case 14: vx_form("vpkuhum"); break; |
511 |
|
|
case 142: vx_form("vpkuhus"); break; |
512 |
|
|
case 78: vx_form("vpkuwum"); break; |
513 |
|
|
case 206: vx_form("vpkuwus"); break; |
514 |
gbeauche |
1.10 |
case 266: vx_raz_form("vrefp"); break; |
515 |
|
|
case 714: vx_raz_form("vrfim"); break; |
516 |
|
|
case 522: vx_raz_form("vrfin"); break; |
517 |
|
|
case 650: vx_raz_form("vrfip"); break; |
518 |
|
|
case 586: vx_raz_form("vrfiz"); break; |
519 |
gbeauche |
1.9 |
case 4: vx_form("vrlb"); break; |
520 |
|
|
case 68: vx_form("vrlh"); break; |
521 |
|
|
case 132: vx_form("vrlw"); break; |
522 |
gbeauche |
1.10 |
case 330: vx_raz_form("vrsqrtefp"); break; |
523 |
gbeauche |
1.9 |
case 452: vx_form("vsl"); break; |
524 |
|
|
case 260: vx_form("vslb"); break; |
525 |
|
|
case 324: vx_form("vslh"); break; |
526 |
|
|
case 1036: vx_form("vslo"); break; |
527 |
|
|
case 388: vx_form("vslw"); break; |
528 |
gbeauche |
1.10 |
case 524: vxi_ra_form("vspltb"); break; |
529 |
|
|
case 588: vxi_ra_form("vsplth"); break; |
530 |
|
|
case 780: vxi_ras_rbz_form("vspltisb"); break; |
531 |
|
|
case 844: vxi_ras_rbz_form("vspltish"); break; |
532 |
|
|
case 908: vxi_ras_rbz_form("vspltisw"); break; |
533 |
|
|
case 652: vxi_ra_form("vspltw"); break; |
534 |
gbeauche |
1.9 |
case 708: vx_form("vsr"); break; |
535 |
|
|
case 772: vx_form("vsrab"); break; |
536 |
|
|
case 836: vx_form("vsrah"); break; |
537 |
|
|
case 900: vx_form("vsraw"); break; |
538 |
|
|
case 516: vx_form("vsrb"); break; |
539 |
|
|
case 580: vx_form("vsrh"); break; |
540 |
|
|
case 1100: vx_form("vsro"); break; |
541 |
|
|
case 644: vx_form("vsrw"); break; |
542 |
|
|
case 1408: vx_form("vsubcuw"); break; |
543 |
|
|
case 74: vx_form("vsubfp"); break; |
544 |
|
|
case 1792: vx_form("vsubsbs"); break; |
545 |
|
|
case 1856: vx_form("vsubshs"); break; |
546 |
|
|
case 1920: vx_form("vsubsws"); break; |
547 |
|
|
case 1024: vx_form("vsububm"); break; |
548 |
|
|
case 1536: vx_form("vsububs"); break; |
549 |
|
|
case 1088: vx_form("vsubuhm"); break; |
550 |
|
|
case 1600: vx_form("vsubuhs"); break; |
551 |
|
|
case 1152: vx_form("vsubuwm"); break; |
552 |
|
|
case 1664: vx_form("vsubuws"); break; |
553 |
|
|
case 1928: vx_form("vsumsws"); break; |
554 |
|
|
case 1672: vx_form("vsum2sws"); break; |
555 |
|
|
case 1800: vx_form("vsum4sbs"); break; |
556 |
|
|
case 1608: vx_form("vsum4shs"); break; |
557 |
|
|
case 1544: vx_form("vsum4ubs"); break; |
558 |
gbeauche |
1.10 |
case 846: vx_raz_form("vupkhpx"); break; |
559 |
|
|
case 526: vx_raz_form("vupkhsb"); break; |
560 |
|
|
case 590: vx_raz_form("vupkhsh"); break; |
561 |
|
|
case 974: vx_raz_form("vupklpx"); break; |
562 |
|
|
case 654: vx_raz_form("vupklsb"); break; |
563 |
|
|
case 718: vx_raz_form("vupklsh"); break; |
564 |
|
|
case 1220: vx_form("vxor"); break; |
565 |
gbeauche |
1.9 |
default: |
566 |
gbeauche |
1.10 |
if ((vxop & 0x43f) == 44) { // vsldoi vD,vA,vB,SHB |
567 |
|
|
fprintf(f, "vsldoi\tv%d,v%d,v%d,%d\n", rd, ra, rb, rc & 15); |
568 |
gbeauche |
1.9 |
break; |
569 |
|
|
} |
570 |
gbeauche |
1.10 |
switch (vxop & 0x3f) { // VA-form, must come last |
571 |
|
|
case 46: va_form("vmaddfp"); break; |
572 |
|
|
case 32: va_form("vmhaddshs"); break; |
573 |
|
|
case 33: va_form("vmhraddshs"); break; |
574 |
|
|
case 34: va_form("vmladduhm"); break; |
575 |
|
|
case 37: va_form("vmsummbm"); break; |
576 |
|
|
case 40: va_form("vmsumshm"); break; |
577 |
|
|
case 41: va_form("vmsumshs"); break; |
578 |
|
|
case 36: va_form("vmsumubm"); break; |
579 |
|
|
case 38: va_form("vmsumuhm"); break; |
580 |
|
|
case 39: va_form("vmsumuhs"); break; |
581 |
|
|
case 47: va_form("vnmsubfp"); break; |
582 |
|
|
case 43: va_form("vperm"); break; |
583 |
|
|
case 42: va_form("vsel"); break; |
584 |
|
|
default: fprintf(f, "?\n"); break; |
585 |
|
|
} |
586 |
gbeauche |
1.9 |
break; |
587 |
|
|
} |
588 |
|
|
} |
589 |
|
|
|
590 |
|
|
|
591 |
|
|
/* |
592 |
cebix |
1.1 |
* Disassemble instruction with primary opcode = 19 (XL-Form) |
593 |
|
|
*/ |
594 |
|
|
|
595 |
|
|
static void disass19(FILE *f, unsigned int adr, unsigned int w) |
596 |
|
|
{ |
597 |
|
|
switch (exop) { |
598 |
|
|
case 0: xlform_crcr("mcrf"); break; |
599 |
|
|
|
600 |
|
|
case 16: |
601 |
|
|
if (w & 1) |
602 |
|
|
if (rd == 20) |
603 |
|
|
fprintf(f, "blrl\n"); |
604 |
|
|
else |
605 |
|
|
xlform_b("bclrl"); |
606 |
|
|
else |
607 |
|
|
if (rd == 20) |
608 |
|
|
fprintf(f, "blr\n"); |
609 |
|
|
else |
610 |
|
|
xlform_b("bclr"); |
611 |
|
|
break; |
612 |
|
|
|
613 |
|
|
case 33: |
614 |
|
|
if (ra == rb) |
615 |
|
|
fprintf(f, "crnot\tcrb%d,crb%d\n", rd, ra); |
616 |
|
|
else |
617 |
|
|
xlform_cr("crnor"); |
618 |
|
|
break; |
619 |
|
|
|
620 |
|
|
case 50: xlform("rfi"); break; |
621 |
|
|
case 129: xlform_cr("crandc"); break; |
622 |
|
|
case 150: xlform("isync"); break; |
623 |
|
|
|
624 |
|
|
case 193: |
625 |
|
|
if (ra == rd && rb == rd) |
626 |
|
|
fprintf(f, "crclr\tcrb%d\n", rd); |
627 |
|
|
else |
628 |
|
|
xlform_cr("crxor"); |
629 |
|
|
break; |
630 |
|
|
|
631 |
|
|
case 225: xlform_cr("crnand"); break; |
632 |
|
|
case 257: xlform_cr("crand"); break; |
633 |
|
|
|
634 |
|
|
case 289: |
635 |
|
|
if (ra == rd && rb == rd) |
636 |
|
|
fprintf(f, "crset\tcrb%d\n", rd); |
637 |
|
|
else |
638 |
|
|
xlform_cr("creqv"); |
639 |
|
|
break; |
640 |
|
|
|
641 |
|
|
case 417: xlform_cr("crorc"); break; |
642 |
|
|
|
643 |
|
|
case 449: |
644 |
|
|
if (ra == rb) |
645 |
|
|
fprintf(f, "crmove\tcrb%d,crb%d\n", rd, ra); |
646 |
|
|
else |
647 |
|
|
xlform_cr("cror"); |
648 |
|
|
break; |
649 |
|
|
|
650 |
|
|
case 528: |
651 |
|
|
if (w & 1) |
652 |
|
|
if (rd == 20) |
653 |
|
|
fprintf(f, "bctrl\n"); |
654 |
|
|
else |
655 |
|
|
xlform_b("bcctrl"); |
656 |
|
|
else |
657 |
|
|
if (rd == 20) |
658 |
|
|
fprintf(f, "bctr\n"); |
659 |
|
|
else |
660 |
|
|
xlform_b("bcctr"); |
661 |
|
|
break; |
662 |
|
|
|
663 |
|
|
default: |
664 |
|
|
fprintf(f, "?\n"); |
665 |
|
|
break; |
666 |
|
|
} |
667 |
|
|
} |
668 |
|
|
|
669 |
|
|
|
670 |
|
|
/* |
671 |
|
|
* Disassemble instruction with primary opcode = 31 (X-Form/XO-Form/XFX-Form/XS-Form) |
672 |
|
|
*/ |
673 |
|
|
|
674 |
|
|
static void disass31(FILE *f, unsigned int adr, unsigned int w) |
675 |
|
|
{ |
676 |
|
|
switch (exop) { |
677 |
|
|
case 0: |
678 |
|
|
if (rd & 1) |
679 |
|
|
xform_crlab("cmpd"); // 64 bit |
680 |
|
|
else |
681 |
|
|
xform_crlab("cmpw"); |
682 |
|
|
break; |
683 |
|
|
|
684 |
|
|
case 4: |
685 |
|
|
if (rd == 31 && ra == 0 && rb == 0) |
686 |
|
|
xform("trap"); |
687 |
|
|
else if (to_code[rd] != NULL) |
688 |
|
|
fprintf(f, "tw%s\tr%d,r%d\n", to_code[rd], ra, rb); |
689 |
|
|
else |
690 |
|
|
xform_to("tw"); |
691 |
|
|
break; |
692 |
|
|
|
693 |
gbeauche |
1.9 |
case 6: xform_vls("lvsl"); break; |
694 |
|
|
case 7: xform_vls("lvebx"); break; |
695 |
cebix |
1.1 |
case 8: xoform_dab("subfc"); break; |
696 |
|
|
case 8+512: xoform_dab("subfco"); break; |
697 |
|
|
case 9: case 9+512: xoform_dab("mulhdu"); break; // 64 bit |
698 |
|
|
case 10: xoform_dab("addc"); break; |
699 |
|
|
case 10+512: xoform_dab("addco"); break; |
700 |
|
|
case 11: case 11+512: xoform_dab("mulhwu"); break; |
701 |
|
|
case 19: xform_d("mfcr"); break; |
702 |
|
|
case 20: xform_ls("lwarx"); break; |
703 |
|
|
case 21: xform_ls("ldx"); break; // 64 bit |
704 |
|
|
case 23: xform_ls("lwzx"); break; |
705 |
|
|
case 24: xform_sabc("slw"); break; |
706 |
|
|
case 26: xform_sac("cntlzw"); break; |
707 |
|
|
case 27: xform_sabc("sld"); break; // 64 bit |
708 |
|
|
case 28: xform_sabc("and"); break; |
709 |
|
|
|
710 |
|
|
case 32: |
711 |
|
|
if (rd & 1) |
712 |
|
|
xform_crlab("cmpld"); // 64 bit |
713 |
|
|
else |
714 |
|
|
xform_crlab("cmplw"); |
715 |
|
|
break; |
716 |
|
|
|
717 |
gbeauche |
1.9 |
case 38: xform_vls("lvsr"); break; |
718 |
|
|
case 39: xform_vls("lvehx"); break; |
719 |
cebix |
1.1 |
case 40: xoform_dab("subf"); break; |
720 |
|
|
case 40+512: xoform_dab("subfo"); break; |
721 |
|
|
case 53: xform_ls("ldux"); break; // 64 bit |
722 |
|
|
case 54: xform_ab("dcbst"); break; |
723 |
|
|
case 55: xform_ls("lwzux"); break; |
724 |
|
|
case 58: xform_sac("cntlzd"); break; // 64 bit |
725 |
|
|
case 60: xform_sabc("andc"); break; |
726 |
|
|
|
727 |
|
|
case 68: // 64 bit |
728 |
|
|
if (to_code[rd] != NULL) |
729 |
|
|
fprintf(f, "td%s\tr%d,r%d\n", to_code[rd], ra, rb); |
730 |
|
|
else |
731 |
|
|
xform_to("td"); |
732 |
|
|
break; |
733 |
|
|
|
734 |
gbeauche |
1.9 |
case 71: xform_vls("lvewx"); break; |
735 |
cebix |
1.1 |
case 73: case 73+512: xoform_dab("mulhd"); break; // 64 bit |
736 |
|
|
case 75: case 75+512: xoform_dab("mulhw"); break; |
737 |
|
|
case 83: xform_d("mfmsr"); break; |
738 |
|
|
case 84: xform_ls("ldarx"); break; // 64 bit |
739 |
|
|
case 86: xform_ab("dcbf"); break; |
740 |
|
|
case 87: xform_ls("lbzx"); break; |
741 |
gbeauche |
1.9 |
case 103: xform_vls("lvx"); break; |
742 |
cebix |
1.1 |
case 104: xoform_da("neg"); break; |
743 |
|
|
case 104+512: xoform_da("nego"); break; |
744 |
|
|
case 119: xform_ls("lbzux"); break; |
745 |
|
|
|
746 |
|
|
case 124: |
747 |
|
|
if (rd == rb) |
748 |
|
|
fprintf(f, "not%s\tr%d,r%d\n", w & 1 ? "." : "", ra, rd); |
749 |
|
|
else |
750 |
|
|
xform_sabc("nor"); |
751 |
|
|
break; |
752 |
|
|
|
753 |
gbeauche |
1.9 |
case 135: xform_vls("stvebx"); break; |
754 |
cebix |
1.1 |
case 136: xoform_dab("subfe"); break; |
755 |
|
|
case 136+512: xoform_dab("subfeo"); break; |
756 |
|
|
case 138: xoform_dab("adde"); break; |
757 |
|
|
case 138+512: xoform_dab("addeo"); break; |
758 |
|
|
case 144: xfxform_crm("mtcrf"); break; |
759 |
|
|
case 146: xform_d("mtmsr"); break; |
760 |
|
|
case 149: xform_ls("stdx"); break; // 64 bit |
761 |
|
|
|
762 |
|
|
case 150: |
763 |
|
|
if (w & 1) |
764 |
|
|
xform_ls("stwcx."); |
765 |
|
|
else |
766 |
|
|
fprintf(f, "?\n"); |
767 |
|
|
break; |
768 |
|
|
|
769 |
|
|
case 151: xform_ls("stwx"); break; |
770 |
gbeauche |
1.9 |
case 167: xform_vls("stvehx"); break; |
771 |
cebix |
1.1 |
case 181: xform_ls("stdux"); break; // 64 bit |
772 |
|
|
case 183: xform_ls("stwux"); break; |
773 |
gbeauche |
1.9 |
case 199: xform_vls("stvewx"); break; |
774 |
cebix |
1.1 |
case 200: xoform_da("subfze"); break; |
775 |
|
|
case 200+512: xoform_da("subfzeo"); break; |
776 |
|
|
case 202: xoform_da("addze"); break; |
777 |
|
|
case 202+512: xoform_da("addzeo"); break; |
778 |
|
|
case 210: xform_tsr("mtsr"); break; |
779 |
|
|
|
780 |
|
|
case 214: // 64 bit |
781 |
|
|
if (w & 1) |
782 |
|
|
xform_ls("stdcx"); |
783 |
|
|
else |
784 |
|
|
fprintf(f, "?\n"); |
785 |
|
|
break; |
786 |
|
|
|
787 |
|
|
case 215: xform_ls("stbx"); break; |
788 |
gbeauche |
1.9 |
case 231: xform_vls("stvx"); break; |
789 |
cebix |
1.1 |
case 232: xoform_da("subfme"); break; |
790 |
|
|
case 232+512: xoform_da("subfmeo"); break; |
791 |
|
|
case 233: xoform_dab("mulld"); break; // 64 bit |
792 |
|
|
case 233+512: xoform_dab("mulldo"); break; // 64 bit |
793 |
|
|
case 234: xoform_da("addme"); break; |
794 |
|
|
case 234+512: xoform_da("addmeo"); break; |
795 |
|
|
case 235: xoform_dab("mullw"); break; |
796 |
|
|
case 235+512: xoform_dab("mullwo"); break; |
797 |
|
|
case 242: xform_db("mtsrin"); break; |
798 |
|
|
case 246: xform_ab("dcbtst"); break; |
799 |
|
|
case 247: xform_ls("stbux"); break; |
800 |
|
|
case 266: xoform_dab("add"); break; |
801 |
|
|
case 266+512: xoform_dab("addo"); break; |
802 |
|
|
case 278: xform_ab("dcbt"); break; |
803 |
|
|
case 279: xform_ls("lhzx"); break; |
804 |
|
|
case 284: xform_sabc("eqv"); break; |
805 |
|
|
case 306: xform_b("tlbie"); break; |
806 |
|
|
case 310: xform_ls("eciwx"); break; |
807 |
|
|
case 311: xform_ls("lhzux"); break; |
808 |
|
|
case 316: xform_sabc("xor"); break; |
809 |
|
|
|
810 |
|
|
case 339: |
811 |
|
|
if ((ra | (rb << 5)) == 1) |
812 |
|
|
fprintf(f, "mfxer\tr%d\n", rd); |
813 |
|
|
else if ((ra | (rb << 5)) == 8) |
814 |
|
|
fprintf(f, "mflr\tr%d\n", rd); |
815 |
|
|
else if ((ra | (rb << 5)) == 9) |
816 |
|
|
fprintf(f, "mfctr\tr%d\n", rd); |
817 |
gbeauche |
1.9 |
else if ((ra | (rb << 5)) == 256) |
818 |
|
|
fprintf(f, "mfvrsave\tr%d\n", rd); |
819 |
cebix |
1.1 |
else { |
820 |
|
|
char *spr = get_spr(ra | (rb << 5)); |
821 |
|
|
if (spr) |
822 |
|
|
fprintf(f, "mfspr\tr%d,%s\n", rd, spr); |
823 |
|
|
else |
824 |
|
|
xfxform_fspr("mfspr"); |
825 |
|
|
} |
826 |
|
|
break; |
827 |
|
|
|
828 |
|
|
case 341: xform_ls("lwax"); break; // 64 bit |
829 |
|
|
case 343: xform_ls("lhax"); break; |
830 |
gbeauche |
1.9 |
case 359: xform_vls("lvxl"); break; |
831 |
cebix |
1.1 |
case 370: xform("tlbia"); break; |
832 |
|
|
|
833 |
gbeauche |
1.10 |
case 822: // AltiVec |
834 |
|
|
if ((rd & 0xc) == 0 && ra == 0 && rb == 0 && (w & 1) == 0) { |
835 |
|
|
if (rd & 0x10) |
836 |
|
|
fprintf(f, "dssall\n"); |
837 |
|
|
else |
838 |
|
|
fprintf(f, "dss\t%d\n", rd & 3); |
839 |
|
|
} |
840 |
|
|
else |
841 |
|
|
fprintf(f, "?\n"); |
842 |
|
|
break; |
843 |
|
|
|
844 |
|
|
case 342: // AltiVec |
845 |
|
|
if ((rd & 0xc) == 0 && (w & 1) == 0) |
846 |
|
|
fprintf(f, "dst%s\tr%d,r%d,%d\n", rd & 0x10 ? "t" : "", ra, rb, rd & 3); |
847 |
|
|
else |
848 |
|
|
fprintf(f, "?\n"); |
849 |
|
|
break; |
850 |
|
|
|
851 |
|
|
case 374: // AltiVec |
852 |
|
|
if ((rd & 0xc) == 0 && (w & 1) == 0) |
853 |
|
|
fprintf(f, "dstst%s\tr%d,r%d,%d\n", rd & 0x10 ? "t" : "", ra, rb, rd & 3); |
854 |
|
|
else |
855 |
|
|
fprintf(f, "?\n"); |
856 |
|
|
break; |
857 |
|
|
|
858 |
cebix |
1.1 |
case 371: |
859 |
|
|
if ((ra | (rb << 5)) == 268) |
860 |
|
|
xfxform_tb("mftb"); |
861 |
|
|
else if ((ra | (rb << 5)) == 269) |
862 |
|
|
xfxform_tb("mftbu"); |
863 |
|
|
else |
864 |
|
|
fprintf(f, "?\n"); |
865 |
|
|
break; |
866 |
|
|
|
867 |
|
|
case 373: xform_ls("lwaux"); break; // 64 bit |
868 |
|
|
case 375: xform_ls("lhaux"); break; |
869 |
|
|
case 407: xform_ls("sthx"); break; |
870 |
|
|
case 412: xform_sabc("orc"); break; |
871 |
|
|
case 434: xform_b("slbie"); break; // 64 bit |
872 |
|
|
case 438: xform_ls("ecowx"); break; |
873 |
|
|
case 439: xform_ls("sthux"); break; |
874 |
|
|
|
875 |
|
|
case 444: |
876 |
|
|
if (rd == rb) |
877 |
|
|
fprintf(f, "mr%s\tr%d,r%d\n", w & 1 ? "." : "", ra, rd); |
878 |
|
|
else |
879 |
|
|
xform_sabc("or"); |
880 |
|
|
break; |
881 |
|
|
|
882 |
|
|
case 457: xoform_dab("divdu"); break; // 64 bit |
883 |
|
|
case 457+512: xoform_dab("divduo"); break; // 64 bit |
884 |
|
|
case 459: xoform_dab("divwu"); break; |
885 |
|
|
case 459+512: xoform_dab("divwuo"); break; |
886 |
|
|
|
887 |
|
|
case 467: |
888 |
|
|
if ((ra | (rb << 5)) == 1) |
889 |
|
|
fprintf(f, "mtxer\tr%d\n", rd); |
890 |
|
|
else if ((ra | (rb << 5)) == 8) |
891 |
|
|
fprintf(f, "mtlr\tr%d\n", rd); |
892 |
|
|
else if ((ra | (rb << 5)) == 9) |
893 |
|
|
fprintf(f, "mtctr\tr%d\n", rd); |
894 |
gbeauche |
1.9 |
else if ((ra | (rb << 5)) == 256) |
895 |
|
|
fprintf(f, "mtvrsave\tr%d\n", rd); |
896 |
cebix |
1.1 |
else { |
897 |
|
|
char *spr = get_spr(ra | (rb << 5)); |
898 |
|
|
if (spr) |
899 |
|
|
fprintf(f, "mtspr\t%s,r%d\n", spr, rd); |
900 |
|
|
else |
901 |
|
|
xfxform_tspr("mtspr"); |
902 |
|
|
} |
903 |
|
|
break; |
904 |
|
|
|
905 |
|
|
case 470: xform_ab("dcbi"); break; |
906 |
|
|
case 476: xform_sabc("nand"); break; |
907 |
gbeauche |
1.9 |
case 487: xform_vls("stvxl"); break; |
908 |
cebix |
1.1 |
case 489: xoform_dab("divd"); break; // 64 bit |
909 |
|
|
case 489+512: xoform_dab("divdo"); break; // 64 bit |
910 |
|
|
case 491: xoform_dab("divw"); break; |
911 |
|
|
case 491+512: xoform_dab("divwo"); break; |
912 |
|
|
case 498: xform("slbia"); break; // 64 bit |
913 |
|
|
case 512: xform_cr("mcrxr"); break; |
914 |
|
|
case 533: xform_ls("lswx"); break; |
915 |
|
|
case 534: xform_ls("lwbrx"); break; |
916 |
|
|
case 535: xform_fls("lfsx"); break; |
917 |
|
|
case 536: xform_sabc("srw"); break; |
918 |
|
|
case 539: xform_sabc("srd"); break; // 64 bit |
919 |
|
|
case 566: xform("tlbsync"); break; |
920 |
|
|
case 567: xform_fls("lfsux"); break; |
921 |
|
|
case 595: xform_fsr("mfsr"); break; |
922 |
|
|
case 597: xform_lsswi("lswi"); break; |
923 |
|
|
case 598: xform("sync"); break; |
924 |
|
|
case 599: xform_fls("lfdx"); break; |
925 |
|
|
case 631: xform_fls("lfdux"); break; |
926 |
|
|
case 659: xform_db("mfsrin"); break; |
927 |
|
|
case 661: xform_ls("stswx"); break; |
928 |
|
|
case 662: xform_ls("stwbrx"); break; |
929 |
|
|
case 663: xform_fls("stfsx"); break; |
930 |
|
|
case 695: xform_fls("stfsux"); break; |
931 |
|
|
case 725: xform_lsswi("stswi"); break; |
932 |
|
|
case 727: xform_fls("stfdx"); break; |
933 |
|
|
case 758: xform_ab("dcba"); break; |
934 |
|
|
case 759: xform_fls("stfdux"); break; |
935 |
|
|
case 790: xform_ls("lhbrx"); break; |
936 |
|
|
case 792: xform_sabc("sraw"); break; |
937 |
|
|
case 794: xform_sabc("srad"); break; // 64 bit |
938 |
|
|
case 824: xform_sash("srawi"); break; |
939 |
|
|
case 826: case 827: xsform("sradi"); break; // 64 bit |
940 |
|
|
case 854: xform("eieio"); break; |
941 |
|
|
case 918: xform_ls("sthbrx"); break; |
942 |
|
|
case 922: xform_sac("extsh"); break; |
943 |
|
|
case 954: xform_sac("extsb"); break; |
944 |
|
|
case 978: fprintf(f, "tlbld\tr%d\n", rb); break; // 603 |
945 |
|
|
case 982: xform_ab("icbi"); break; |
946 |
|
|
case 983: xform_fls("stfiwx"); break; |
947 |
|
|
case 986: xform_sac("extsw"); break; // 64 bit |
948 |
|
|
case 1010: fprintf(f, "tlbli\tr%d\n", rb); break; // 603 |
949 |
|
|
case 1014: xform_ab("dcbz"); break; |
950 |
|
|
|
951 |
|
|
default: |
952 |
|
|
fprintf(f, "?\n"); |
953 |
|
|
break; |
954 |
|
|
} |
955 |
|
|
} |
956 |
|
|
|
957 |
|
|
|
958 |
|
|
/* |
959 |
|
|
* Disassemble instruction with primary opcode = 59 (A-Form) |
960 |
|
|
*/ |
961 |
|
|
|
962 |
|
|
static void disass59(FILE *f, unsigned int adr, unsigned int w) |
963 |
|
|
{ |
964 |
|
|
switch (exop & 0x1f) { |
965 |
|
|
case 18: aform_dab("fdivs"); break; |
966 |
|
|
case 20: aform_dab("fsubs"); break; |
967 |
|
|
case 21: aform_dab("fadds"); break; |
968 |
|
|
case 22: aform_db("fsqrts"); break; |
969 |
|
|
case 24: aform_db("fres"); break; |
970 |
|
|
case 25: aform_dac("fmuls"); break; |
971 |
|
|
case 28: aform_dacb("fmsubs"); break; |
972 |
|
|
case 29: aform_dacb("fmadds"); break; |
973 |
|
|
case 30: aform_dacb("fnmsubs"); break; |
974 |
|
|
case 31: aform_dacb("fnmadds"); break; |
975 |
|
|
|
976 |
|
|
default: |
977 |
|
|
fprintf(f, "?\n"); |
978 |
|
|
break; |
979 |
|
|
} |
980 |
|
|
} |
981 |
|
|
|
982 |
|
|
|
983 |
|
|
/* |
984 |
|
|
* Disassemble instruction with primary opcode = 63 (A-Form/X-Form/XFL-Form) |
985 |
|
|
*/ |
986 |
|
|
|
987 |
|
|
static void disass63(FILE *f, unsigned int adr, unsigned int w) |
988 |
|
|
{ |
989 |
|
|
if (exop & 0x10) |
990 |
|
|
switch (exop & 0x1f) { |
991 |
|
|
case 18: aform_dab("fdiv"); break; |
992 |
|
|
case 20: aform_dab("fsub"); break; |
993 |
|
|
case 21: aform_dab("fadd"); break; |
994 |
|
|
case 22: aform_db("fsqrt"); break; |
995 |
|
|
case 23: aform_dacb("fsel"); break; |
996 |
|
|
case 25: aform_dac("fmul"); break; |
997 |
|
|
case 26: aform_db("frsqrte"); break; |
998 |
|
|
case 28: aform_dacb("fmsub"); break; |
999 |
|
|
case 29: aform_dacb("fmadd"); break; |
1000 |
|
|
case 30: aform_dacb("fnmsub"); break; |
1001 |
|
|
case 31: aform_dacb("fnmadd"); break; |
1002 |
|
|
|
1003 |
|
|
default: |
1004 |
|
|
fprintf(f, "?\n"); |
1005 |
|
|
break; |
1006 |
|
|
} |
1007 |
|
|
else |
1008 |
|
|
switch (exop) { |
1009 |
|
|
case 0: xform_fcrab("fcmpu"); break; |
1010 |
|
|
case 12: xform_fdb("frsp"); break; |
1011 |
|
|
case 14: xform_fdb("fctiw"); break; |
1012 |
|
|
case 15: xform_fdb("fctiwz"); break; |
1013 |
|
|
case 32: xform_fcrab("fcmpo"); break; |
1014 |
|
|
case 38: xform_crb("mtfsb1"); break; |
1015 |
|
|
case 40: xform_fdb("fneg"); break; |
1016 |
|
|
case 64: xform_crcr("mcrfs"); break; |
1017 |
|
|
case 70: xform_crb("mtfsb0"); break; |
1018 |
|
|
case 72: xform_fdb("fmr"); break; |
1019 |
|
|
case 134: xform_cri("mtfsfi"); break; |
1020 |
|
|
case 136: xform_fdb("fnabs"); break; |
1021 |
|
|
case 264: xform_fdb("fabs"); break; |
1022 |
|
|
case 583: xform_fd("mffs"); break; |
1023 |
|
|
case 711: xflform("mtfsf"); break; |
1024 |
|
|
case 814: xform_fdb("fctid"); break; // 64 bit |
1025 |
|
|
case 815: xform_fdb("fctidz"); break; // 64 bit |
1026 |
|
|
case 846: xform_fdb("fcfid"); break; // 64 bit |
1027 |
|
|
|
1028 |
|
|
default: |
1029 |
|
|
fprintf(f, "?\n"); |
1030 |
|
|
break; |
1031 |
|
|
} |
1032 |
|
|
} |
1033 |
|
|
|
1034 |
|
|
|
1035 |
|
|
/* |
1036 |
|
|
* Convert mask begin/end to mask |
1037 |
|
|
*/ |
1038 |
|
|
|
1039 |
|
|
static unsigned int mbme2mask(int mb, int me) |
1040 |
|
|
{ |
1041 |
|
|
unsigned int m = 0; |
1042 |
|
|
int i; |
1043 |
|
|
|
1044 |
|
|
if (mb <= me) |
1045 |
|
|
for (i=mb; i<=me; i++) |
1046 |
|
|
m |= 1 << (31-i); |
1047 |
|
|
else { |
1048 |
|
|
for (i=0; i<=me; i++) |
1049 |
|
|
m |= 1 << (31-i); |
1050 |
|
|
for (i=mb; i<=31; i++) |
1051 |
|
|
m |= 1 << (31-i); |
1052 |
|
|
} |
1053 |
|
|
return m; |
1054 |
|
|
} |
1055 |
|
|
|
1056 |
|
|
|
1057 |
|
|
/* |
1058 |
|
|
* Convert SPR number to register name |
1059 |
|
|
*/ |
1060 |
|
|
|
1061 |
|
|
char *get_spr(int reg) |
1062 |
|
|
{ |
1063 |
|
|
switch (reg) { |
1064 |
|
|
case 1: return "xer"; |
1065 |
|
|
case 8: return "lr"; |
1066 |
|
|
case 9: return "ctr"; |
1067 |
|
|
case 18: return "dsisr"; |
1068 |
|
|
case 19: return "dar"; |
1069 |
|
|
case 22: return "dec"; |
1070 |
|
|
case 25: return "sdr1"; |
1071 |
|
|
case 26: return "srr0"; |
1072 |
|
|
case 27: return "srr1"; |
1073 |
|
|
case 272: return "sprg0"; |
1074 |
|
|
case 273: return "sprg1"; |
1075 |
|
|
case 274: return "sprg2"; |
1076 |
|
|
case 275: return "sprg3"; |
1077 |
|
|
case 280: return "asr"; // 64 bit |
1078 |
|
|
case 282: return "ear"; |
1079 |
|
|
case 284: return "tbl"; |
1080 |
|
|
case 285: return "tbu"; |
1081 |
|
|
case 287: return "pvr"; |
1082 |
|
|
case 528: return "ibat0u"; |
1083 |
|
|
case 529: return "ibat0l"; |
1084 |
|
|
case 530: return "ibat1u"; |
1085 |
|
|
case 531: return "ibat1l"; |
1086 |
|
|
case 532: return "ibat2u"; |
1087 |
|
|
case 533: return "ibat2l"; |
1088 |
|
|
case 534: return "ibat3u"; |
1089 |
|
|
case 535: return "ibat3l"; |
1090 |
|
|
case 536: return "dbat0u"; |
1091 |
|
|
case 537: return "dbat0l"; |
1092 |
|
|
case 538: return "dbat1u"; |
1093 |
|
|
case 539: return "dbat1l"; |
1094 |
|
|
case 540: return "dbat2u"; |
1095 |
|
|
case 541: return "dbat2l"; |
1096 |
|
|
case 542: return "dbat3u"; |
1097 |
|
|
case 543: return "dbat3l"; |
1098 |
|
|
case 1013: return "dabr"; |
1099 |
|
|
|
1100 |
|
|
case 0: return "mq"; // 601 |
1101 |
|
|
case 4: return "rtcu"; // 601 |
1102 |
|
|
case 5: return "rtcl"; // 601 |
1103 |
|
|
case 20: return "rtcu"; // 601 |
1104 |
|
|
case 21: return "rtcl"; // 601 |
1105 |
|
|
case 952: return "mmcr0"; // 604 |
1106 |
|
|
case 953: return "pmc1"; // 604 |
1107 |
|
|
case 954: return "pmc2"; // 604 |
1108 |
|
|
case 955: return "sia"; // 604 |
1109 |
|
|
case 956: return "mmcr1"; // 604e |
1110 |
|
|
case 957: return "pmc3"; // 604e |
1111 |
|
|
case 958: return "pmc4"; // 604e |
1112 |
|
|
case 959: return "sda"; // 604 |
1113 |
|
|
case 976: return "dmiss"; // 603 |
1114 |
|
|
case 977: return "dcmp"; // 603 |
1115 |
|
|
case 978: return "hash1"; // 603 |
1116 |
|
|
case 979: return "hash2"; // 603 |
1117 |
|
|
case 980: return "imiss"; // 603 |
1118 |
|
|
case 981: return "icmp"; // 603 |
1119 |
|
|
case 982: return "rpa"; // 603 |
1120 |
|
|
case 1008: return "hid0"; // 601/603/604 |
1121 |
|
|
case 1009: return "hid1"; // 601/603/604e |
1122 |
|
|
case 1010: return "iabr"; // 601/603 |
1123 |
|
|
case 1023: return "pir"; // 601/604 |
1124 |
|
|
|
1125 |
|
|
case 256: return "vrsave"; // AltiVec |
1126 |
|
|
|
1127 |
|
|
default: return NULL; |
1128 |
|
|
} |
1129 |
|
|
} |