* rs6000-pinsn.c: Make dis-assembly output more like
[deliverable/binutils-gdb.git] / gdb / rs6000-pinsn.c
1 /* Print IBM RS/6000 instructions for GNU software.
2 Copyright 1991 Free Software Foundation, Inc.
3 Contributed by IBM Corporation.
4
5 This file is part of GDB and the GNU binutils.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 #include "defs.h"
22 #include "rs6k-opcode.h"
23
24 /* Print the rs6k instruction at address MEMADDR in debugged memory,
25 on STREAM. Returns length of the instruction, in bytes. */
26
27 int
28 print_insn (memaddr, stream)
29 CORE_ADDR memaddr;
30 FILE *stream;
31 {
32 int pop, eop; /* primary and extended opcodes */
33 int min, max;
34 int best = -1; /* found best opcode index */
35 int oldbest = -1;
36 unsigned int the_insn;
37
38 read_memory (memaddr, &the_insn, sizeof (the_insn));
39 pop = (unsigned)(the_insn >> 26);
40 eop = ((the_insn) >> 1) & 0x3ff;
41 min = 0, max = NOPCODES-1;
42
43 while (min < max) {
44 best = (min + max) / 2;
45
46 /* see if we are running in loops */
47 if (best == oldbest)
48 goto not_found;
49 oldbest = best;
50
51 if (pop < rs6k_ops [best].p_opcode)
52 max = best;
53
54 else if (pop > rs6k_ops [best].p_opcode)
55 min = best;
56
57 else {
58 /* opcode matched, check extended opcode. */
59
60 if (rs6k_ops [best].e_opcode == -1) {
61 /* there is no valid extended opcode, what we've got is
62 just fine. */
63 goto insn_found;
64 }
65
66 else if (eop < rs6k_ops [best].e_opcode) {
67
68 while (pop == rs6k_ops [best].p_opcode) {
69 if (eop == rs6k_ops [best].e_opcode) /* found it! */
70 goto insn_found;
71 --best;
72 }
73 goto not_found;
74 }
75
76 else if (eop > rs6k_ops [best].e_opcode) {
77
78 while (pop == rs6k_ops [best].p_opcode) {
79 if (eop == rs6k_ops [best].e_opcode) /* found it! */
80 goto insn_found;
81 ++best;
82 }
83 goto not_found;
84 }
85
86 else /* eop == rs6k_ops [best].e_opcode */
87 goto insn_found;
88 }
89 }
90
91 best = min;
92 if (pop == rs6k_ops [best].p_opcode &&
93 (rs6k_ops [best].e_opcode == -1 || rs6k_ops [best].e_opcode == eop))
94 goto insn_found;
95
96 else
97 goto not_found;
98
99
100 insn_found:
101 print_operator (stream, memaddr, the_insn, best);
102 return 4;
103
104 not_found:
105 fprintf (stream, "0x%08x", the_insn);
106 return 4;
107 }
108
109
110
111 /* condition code names */
112 static char *cond_code [] = {
113 "lt", "gt", "eq", "so", "ge", "le", "ne", "ns", "nl", "ng", "z", "nz" };
114
115
116 print_operator (stream, memaddr, insn_word, insn_no)
117 FILE *stream;
118 long memaddr;
119 long insn_word;
120 int insn_no;
121 {
122 char buf [20];
123 char *qq = buf;
124 char *pp = rs6k_ops[insn_no].opr_ext;
125 int tmp;
126 int nocomma = 0; /* true if no comma needed */
127
128 if (pp) {
129 while (*pp) {
130
131 switch ( *pp ) {
132 case '.':
133 if (insn_word & 0x1)
134 *qq++ = '.';
135 break;
136
137 case 'l':
138 if (insn_word & 0x1)
139 *qq++ = 'l';
140 break;
141
142 case 't':
143 if ((insn_word & 0x03e00000) == 0x01800000)
144 *qq++ = 't';
145 break;
146
147 case 'f':
148 if ((insn_word & 0x03e00000) == 0x00800000)
149 *qq++ = 'f';
150 break;
151
152 case 'a':
153 if (insn_word & 0x2)
154 *qq++ = 'a';
155 break;
156
157 case 'o':
158 if (insn_word & 0x4000)
159 *qq++ = 'o';
160 break;
161
162 case '1': /* exception #1 for bb/bc ambiguity */
163 tmp = (insn_word >> 21) & 0x1f; /* extract BO */
164 if (tmp != 0xc && tmp != 0x4) {
165 /* you can't use `bb' now. switch to `bc' */
166 *(qq-1) = 'c';
167 ++insn_no;
168 pp = rs6k_ops[insn_no].opr_ext;
169 continue;
170 }
171 break;
172
173 default:
174 abort ();
175 }
176 ++pp;
177 }
178 }
179 *qq = '\0';
180
181 fprintf (stream, "%s%s\t", rs6k_ops[insn_no].operator, buf);
182
183 /* parse the operand now. */
184 pp = rs6k_ops[insn_no].oprnd_format;
185
186 while (1) {
187 switch (*pp) {
188 case TO :
189 fprintf (stream, "%d", (insn_word >> 21) & 0x1f);
190 break;
191
192 case RT :
193 case RS :
194 fprintf (stream, "r%d", (insn_word >> 21) & 0x1f);
195 break;
196
197 case LI :
198 tmp = (insn_word >> 16) & 0x1f;
199 if (tmp > 11) {
200 fprintf (stream, "{unknown cond code: 0x%x}", insn_word);
201 tmp = 0;
202 }
203 fprintf (stream, "%s", cond_code [tmp]);
204 break;
205
206 case A2 :
207 case TA14 :
208 tmp = (insn_word & 0xfffc);
209 if (tmp & 0x8000) /* fix sign extension */
210 tmp -= 0x10000;
211
212 if ((insn_word & 0x2) == 0) /* if AA not set */
213 tmp += memaddr;
214
215 print_address (tmp, stream);
216 break;
217
218 case TA24 :
219 tmp = insn_word & 0x03fffffc;
220 if (tmp & 0x2000000)
221 tmp -= 0x4000000;
222
223 if ((insn_word & 0x2) == 0) /* if no AA bit set */
224 tmp += memaddr;
225
226 print_address (tmp, stream);
227 break;
228
229 case LEV : /* for svc only */
230 if (insn_word & 0x2) { /* SA is set */
231 nocomma = 1;
232 }
233 else
234 fprintf (stream, "%d", (insn_word >> 5) & 0x7f);
235 break;
236
237 case FL1 : /* for svc only */
238 if (insn_word & 0x2) { /* SA is set */
239 nocomma = 1;
240 }
241 else
242 fprintf (stream, "%d", (insn_word >> 12) & 0xf);
243 break;
244
245 case FL2 : /* for svc only */
246 nocomma = 0;
247 if (insn_word & 0x2) /* SA is set */
248 fprintf (stream, "%d", (insn_word >> 2) & 0x3fff);
249 else
250 fprintf (stream, "%d", (insn_word >> 2) & 0x7);
251 break;
252
253 case RA :
254 if (nocomma) {
255 fprintf (stream, "r%d)", (insn_word >> 16) & 0x1f);
256 nocomma = 0;
257 }
258 else
259 fprintf (stream, "r%d", (insn_word >> 16) & 0x1f);
260 break;
261
262 case RB :
263 fprintf (stream, "r%d", (insn_word >> 11) & 0x1f);
264 break;
265
266 case SI :
267 tmp = insn_word & 0xffff;
268 if (tmp & 0x8000)
269 tmp -= 0x10000;
270 fprintf (stream, "%d", tmp);
271 break;
272
273 case UI :
274 fprintf (stream, "%d", insn_word & 0xffff);
275 break;
276
277 case BF :
278 fprintf (stream, "%d", (insn_word >> 23) & 0x7);
279 break;
280
281 case BFA :
282 fprintf (stream, "%d", (insn_word >> 18) & 0x7);
283 break;
284
285 case BT :
286 fprintf (stream, "%d", (insn_word >> 21) & 0x1f);
287 break;
288
289 case BA :
290 fprintf (stream, "%d", (insn_word >> 16) & 0x1f);
291 break;
292
293 case BB :
294 fprintf (stream, "%d", (insn_word >> 11) & 0x1f);
295 break;
296
297 case BO :
298 fprintf (stream, "%d", (insn_word >> 21) & 0x1f);
299 break;
300
301 case BI :
302 fprintf (stream, "%d", (insn_word >> 16) & 0x1f);
303 break;
304
305 case SH :
306 fprintf (stream, "%d", (insn_word >> 11) & 0x1f);
307 break;
308
309 case MB :
310 fprintf (stream, "0x%x", (insn_word >> 6) & 0x1f);
311 break;
312
313 case ME :
314 fprintf (stream, "0x%x", (insn_word >> 1) & 0x1f);
315 break;
316
317 case SPR :
318 fprintf (stream, "%d", (insn_word >> 16) & 0x1f);
319 break;
320
321 case DIS :
322 nocomma = 1;
323 tmp = insn_word & 0xffff;
324 if (tmp & 0x8000)
325 tmp -= 0x10000;
326 fprintf (stream, "%d(", tmp);
327 break;
328
329 case FXM :
330 fprintf (stream, "0x%x", (insn_word >> 12) & 0xff);
331 break;
332
333 case FRT :
334 case FRS :
335 fprintf (stream, "f%d", (insn_word >> 21) & 0x1f);
336 break;
337
338 case FRA :
339 fprintf (stream, "f%d", (insn_word >> 16) & 0x1f);
340 break;
341
342 case FRB :
343 fprintf (stream, "f%d", (insn_word >> 11) & 0x1f);
344 break;
345
346 case FRC :
347 fprintf (stream, "f%d", (insn_word >> 6) & 0x1f);
348 break;
349
350 case FLM :
351 fprintf (stream, "0x%x", (insn_word >> 17) & 0xff);
352 break;
353
354 case NB :
355 fprintf (stream, "%d", (insn_word >> 11) & 0x1f);
356 break;
357
358 case I :
359 fprintf (stream, "%d", (insn_word >> 12) & 0xf);
360 break;
361
362 default :
363 fprintf (stream,
364 "{Internal error: Unknown operand format identifier %d}",
365 *pp);
366 }
367 ++pp;
368
369 if (*pp == '\0')
370 break;
371 else if (!nocomma)
372 fputc(',', stream);
373 }
374 }
This page took 0.045492 seconds and 5 git commands to generate.