* complaints.c: New file, code moved from utils.c.
[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
192 while (1) {
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;
205 if (tmp > 11) {
9efdc2fe 206 fprintf (stream, "{unknown cond code: 0x%x}", insn_word);
41abdfbd
JG
207 tmp = 0;
208 }
9efdc2fe 209 fprintf (stream, "%s", cond_code [tmp]);
41abdfbd
JG
210 break;
211
41abdfbd
JG
212 case A2 :
213 case TA14 :
214 tmp = (insn_word & 0xfffc);
215 if (tmp & 0x8000) /* fix sign extension */
216 tmp -= 0x10000;
217
218 if ((insn_word & 0x2) == 0) /* if AA not set */
219 tmp += memaddr;
220
9efdc2fe 221 print_address (tmp, stream);
41abdfbd
JG
222 break;
223
224 case TA24 :
225 tmp = insn_word & 0x03fffffc;
226 if (tmp & 0x2000000)
227 tmp -= 0x4000000;
228
229 if ((insn_word & 0x2) == 0) /* if no AA bit set */
230 tmp += memaddr;
231
9efdc2fe 232 print_address (tmp, stream);
41abdfbd
JG
233 break;
234
235 case LEV : /* for svc only */
236 if (insn_word & 0x2) { /* SA is set */
237 nocomma = 1;
41abdfbd
JG
238 }
239 else
9efdc2fe 240 fprintf (stream, "%d", (insn_word >> 5) & 0x7f);
41abdfbd
JG
241 break;
242
243 case FL1 : /* for svc only */
244 if (insn_word & 0x2) { /* SA is set */
245 nocomma = 1;
41abdfbd
JG
246 }
247 else
9efdc2fe 248 fprintf (stream, "%d", (insn_word >> 12) & 0xf);
41abdfbd
JG
249 break;
250
251 case FL2 : /* for svc only */
252 nocomma = 0;
253 if (insn_word & 0x2) /* SA is set */
9efdc2fe 254 fprintf (stream, "%d", (insn_word >> 2) & 0x3fff);
41abdfbd 255 else
9efdc2fe 256 fprintf (stream, "%d", (insn_word >> 2) & 0x7);
41abdfbd
JG
257 break;
258
259 case RA :
260 if (nocomma) {
9efdc2fe 261 fprintf (stream, "r%d)", (insn_word >> 16) & 0x1f);
41abdfbd
JG
262 nocomma = 0;
263 }
264 else
9efdc2fe 265 fprintf (stream, "r%d", (insn_word >> 16) & 0x1f);
41abdfbd
JG
266 break;
267
268 case RB :
9efdc2fe 269 fprintf (stream, "r%d", (insn_word >> 11) & 0x1f);
41abdfbd
JG
270 break;
271
272 case SI :
273 tmp = insn_word & 0xffff;
274 if (tmp & 0x8000)
275 tmp -= 0x10000;
9efdc2fe 276 fprintf (stream, "%d", tmp);
41abdfbd
JG
277 break;
278
279 case UI :
9efdc2fe 280 fprintf (stream, "%d", insn_word & 0xffff);
41abdfbd
JG
281 break;
282
283 case BF :
9efdc2fe 284 fprintf (stream, "%d", (insn_word >> 23) & 0x7);
41abdfbd
JG
285 break;
286
287 case BFA :
9efdc2fe 288 fprintf (stream, "%d", (insn_word >> 18) & 0x7);
41abdfbd
JG
289 break;
290
291 case BT :
9efdc2fe 292 fprintf (stream, "%d", (insn_word >> 21) & 0x1f);
41abdfbd
JG
293 break;
294
295 case BA :
9efdc2fe 296 fprintf (stream, "%d", (insn_word >> 16) & 0x1f);
41abdfbd
JG
297 break;
298
299 case BB :
9efdc2fe 300 fprintf (stream, "%d", (insn_word >> 11) & 0x1f);
41abdfbd
JG
301 break;
302
303 case BO :
9efdc2fe 304 fprintf (stream, "%d", (insn_word >> 21) & 0x1f);
41abdfbd
JG
305 break;
306
307 case BI :
9efdc2fe 308 fprintf (stream, "%d", (insn_word >> 16) & 0x1f);
41abdfbd
JG
309 break;
310
311 case SH :
9efdc2fe 312 fprintf (stream, "%d", (insn_word >> 11) & 0x1f);
41abdfbd
JG
313 break;
314
315 case MB :
9efdc2fe 316 fprintf (stream, "0x%x", (insn_word >> 6) & 0x1f);
41abdfbd
JG
317 break;
318
319 case ME :
9efdc2fe 320 fprintf (stream, "0x%x", (insn_word >> 1) & 0x1f);
41abdfbd
JG
321 break;
322
323 case SPR :
9efdc2fe 324 fprintf (stream, "%d", (insn_word >> 16) & 0x1f);
41abdfbd
JG
325 break;
326
327 case DIS :
328 nocomma = 1;
329 tmp = insn_word & 0xffff;
330 if (tmp & 0x8000)
331 tmp -= 0x10000;
9efdc2fe 332 fprintf (stream, "%d(", tmp);
41abdfbd
JG
333 break;
334
335 case FXM :
9efdc2fe 336 fprintf (stream, "0x%x", (insn_word >> 12) & 0xff);
41abdfbd
JG
337 break;
338
339 case FRT :
340 case FRS :
9efdc2fe 341 fprintf (stream, "f%d", (insn_word >> 21) & 0x1f);
41abdfbd
JG
342 break;
343
344 case FRA :
9efdc2fe 345 fprintf (stream, "f%d", (insn_word >> 16) & 0x1f);
41abdfbd
JG
346 break;
347
348 case FRB :
9efdc2fe 349 fprintf (stream, "f%d", (insn_word >> 11) & 0x1f);
41abdfbd
JG
350 break;
351
352 case FRC :
9efdc2fe 353 fprintf (stream, "f%d", (insn_word >> 6) & 0x1f);
41abdfbd
JG
354 break;
355
356 case FLM :
9efdc2fe 357 fprintf (stream, "0x%x", (insn_word >> 17) & 0xff);
41abdfbd
JG
358 break;
359
360 case NB :
9efdc2fe 361 fprintf (stream, "%d", (insn_word >> 11) & 0x1f);
41abdfbd
JG
362 break;
363
364 case I :
9efdc2fe 365 fprintf (stream, "%d", (insn_word >> 12) & 0xf);
41abdfbd
JG
366 break;
367
368 default :
9efdc2fe
PB
369 fprintf (stream,
370 "{Internal error: Unknown operand format identifier %d}",
371 *pp);
41abdfbd 372 }
41abdfbd
JG
373 ++pp;
374
375 if (*pp == '\0')
376 break;
377 else if (!nocomma)
9efdc2fe 378 fputc(',', stream);
41abdfbd 379 }
41abdfbd 380}
This page took 0.079946 seconds and 4 git commands to generate.