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