* c-valprint.c (c_val_print): Handle TYPE_CODE_BOOLEAN.
[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;
30 FILE *stream;
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:
111 fprintf (stream, "0x%08x", the_insn);
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
9efdc2fe 187 fprintf (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 :
9efdc2fe 195 fprintf (stream, "%d", (insn_word >> 21) & 0x1f);
41abdfbd
JG
196 break;
197
198 case RT :
199 case RS :
9efdc2fe 200 fprintf (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) {
9efdc2fe 215 fprintf (stream, "{unknown cond code: 0x%x}", insn_word);
41abdfbd
JG
216 tmp = 0;
217 }
9efdc2fe 218 fprintf (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. */
224 fprintf (stream, "%d", tmp);
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
9efdc2fe 256 fprintf (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
9efdc2fe 264 fprintf (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 */
9efdc2fe 270 fprintf (stream, "%d", (insn_word >> 2) & 0x3fff);
41abdfbd 271 else
9efdc2fe 272 fprintf (stream, "%d", (insn_word >> 2) & 0x7);
41abdfbd
JG
273 break;
274
275 case RA :
276 if (nocomma) {
9efdc2fe 277 fprintf (stream, "r%d)", (insn_word >> 16) & 0x1f);
41abdfbd
JG
278 nocomma = 0;
279 }
280 else
9efdc2fe 281 fprintf (stream, "r%d", (insn_word >> 16) & 0x1f);
41abdfbd
JG
282 break;
283
284 case RB :
9efdc2fe 285 fprintf (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;
9efdc2fe 292 fprintf (stream, "%d", tmp);
41abdfbd
JG
293 break;
294
295 case UI :
9efdc2fe 296 fprintf (stream, "%d", insn_word & 0xffff);
41abdfbd
JG
297 break;
298
299 case BF :
9efdc2fe 300 fprintf (stream, "%d", (insn_word >> 23) & 0x7);
41abdfbd
JG
301 break;
302
303 case BFA :
9efdc2fe 304 fprintf (stream, "%d", (insn_word >> 18) & 0x7);
41abdfbd
JG
305 break;
306
307 case BT :
9efdc2fe 308 fprintf (stream, "%d", (insn_word >> 21) & 0x1f);
41abdfbd
JG
309 break;
310
311 case BA :
9efdc2fe 312 fprintf (stream, "%d", (insn_word >> 16) & 0x1f);
41abdfbd
JG
313 break;
314
315 case BB :
9efdc2fe 316 fprintf (stream, "%d", (insn_word >> 11) & 0x1f);
41abdfbd
JG
317 break;
318
319 case BO :
9efdc2fe 320 fprintf (stream, "%d", (insn_word >> 21) & 0x1f);
41abdfbd
JG
321 break;
322
323 case BI :
9efdc2fe 324 fprintf (stream, "%d", (insn_word >> 16) & 0x1f);
41abdfbd
JG
325 break;
326
327 case SH :
9efdc2fe 328 fprintf (stream, "%d", (insn_word >> 11) & 0x1f);
41abdfbd
JG
329 break;
330
331 case MB :
9efdc2fe 332 fprintf (stream, "0x%x", (insn_word >> 6) & 0x1f);
41abdfbd
JG
333 break;
334
335 case ME :
9efdc2fe 336 fprintf (stream, "0x%x", (insn_word >> 1) & 0x1f);
41abdfbd
JG
337 break;
338
339 case SPR :
9efdc2fe 340 fprintf (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;
9efdc2fe 348 fprintf (stream, "%d(", tmp);
41abdfbd
JG
349 break;
350
351 case FXM :
9efdc2fe 352 fprintf (stream, "0x%x", (insn_word >> 12) & 0xff);
41abdfbd
JG
353 break;
354
355 case FRT :
356 case FRS :
9efdc2fe 357 fprintf (stream, "f%d", (insn_word >> 21) & 0x1f);
41abdfbd
JG
358 break;
359
360 case FRA :
9efdc2fe 361 fprintf (stream, "f%d", (insn_word >> 16) & 0x1f);
41abdfbd
JG
362 break;
363
364 case FRB :
9efdc2fe 365 fprintf (stream, "f%d", (insn_word >> 11) & 0x1f);
41abdfbd
JG
366 break;
367
368 case FRC :
9efdc2fe 369 fprintf (stream, "f%d", (insn_word >> 6) & 0x1f);
41abdfbd
JG
370 break;
371
372 case FLM :
9efdc2fe 373 fprintf (stream, "0x%x", (insn_word >> 17) & 0xff);
41abdfbd
JG
374 break;
375
376 case NB :
9efdc2fe 377 fprintf (stream, "%d", (insn_word >> 11) & 0x1f);
41abdfbd
JG
378 break;
379
380 case I :
9efdc2fe 381 fprintf (stream, "%d", (insn_word >> 12) & 0xf);
41abdfbd
JG
382 break;
383
384 default :
9efdc2fe
PB
385 fprintf (stream,
386 "{Internal error: Unknown operand format identifier %d}",
387 *pp);
41abdfbd 388 }
41abdfbd
JG
389 ++pp;
390
944c1c2f 391 if (*pp != '\0' && !nocomma)
9efdc2fe 392 fputc(',', stream);
41abdfbd 393 }
41abdfbd 394}
This page took 0.123669 seconds and 4 git commands to generate.