* Rename remote-es1800.c to remote-es.c
[deliverable/binutils-gdb.git] / gdb / hppa-pinsn.c
1 /* Disassembler for the PA-RISC. Somewhat derived from sparc-pinsn.c.
2 Copyright 1989, 1990, 1992 Free Software Foundation, Inc.
3
4 Contributed by the Center for Software Science at the
5 University of Utah (pa-gdb-bugs@cs.utah.edu).
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22
23 #include "defs.h"
24 #include "symtab.h"
25 #define OLD_TABLE
26 #include "opcode/hppa.h"
27
28 static char *control_reg[] =
29 { "rctr", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
30 "pidr1", "pidr2", "ccr", "sar", "pidr3", "pidr4",
31 "iva", "eiem", "itmr", "pcsq", "pcoq", "iir", "isr",
32 "ior", "ipsw", "eirr", "tr0", "tr1", "tr2", "tr3",
33 "tr4", "tr5", "tr6", "tr7"
34 };
35
36 static char *compare_cond_names[] =
37 { "", ",=", ",<", ",<=", ",<<", ",<<=", ",sv",
38 ",od", ",tr", ",<>", ",>=", ",>", ",>>=",
39 ",>>", ",nsv", ",ev"
40 };
41
42 static char *add_cond_names[] =
43 { "", ",=", ",<", ",<=", ",nuv", ",znv", ",sv",
44 ",od", ",tr", ",<>", ",>=", ",>", ",uv",
45 ",vnz", ",nsv", ",ev"
46 };
47
48 static char *logical_cond_names[] =
49 { "", ",=", ",<", ",<=", 0, 0, 0, ",od",
50 ",tr", ",<>", ",>=", ",>", 0, 0, 0, ",ev"
51 };
52
53 static char *unit_cond_names[] =
54 { "", 0, ",sbz", ",shz", ",sdc", 0, ",sbc", ",shc",
55 ",tr", 0, ",nbz", ",nhz", ",ndc", 0, ",nbc", ",nhc"
56 };
57
58 static char *shift_cond_names[] =
59 {"", ",=", ",<", ",od", ",tr", ",<>", ",>=", ",ev"};
60
61 static char *index_compl_names[] = {"", ",m", ",s", ",sm"};
62 static char *short_ldst_compl_names[] = {"", ",ma", "", ",mb"};
63 static char *short_bytes_compl_names[] = {"", ",b,m", ",e", ",e,m"};
64 static char *float_format_names[] = {",sgl", ",dbl", ",quad"};
65 static char *float_comp_names[] =
66 {",false?", ",false", ",?", ",!<=>", ",=", ",=t", ",?=", ",!<>",
67 ",!?>=", ",<", ",?<", ",!>=", ",!?>", ",<=", ",?<=", ",!>",
68 ",!?<=", ",>", ",?>", ",!<=", ",!?<", ",>=", ",?>=", ",!<",
69 ",!?=", ",<>", ",!=", ",!=t", ",!?", ",<=>", ",true?", ",true"
70 };
71
72 /* For a bunch of different instructions form an index into a
73 completer name table. */
74 #define GET_COMPL(insn) (GET_FIELD (insn, 26, 26) | \
75 GET_FIELD (insn, 18, 18) << 1)
76
77 #define GET_COND(insn) (GET_FIELD ((insn), 16, 18) + \
78 (GET_FIELD ((insn), 19, 19) ? 8 : 0))
79
80 static void fput_reg PARAMS ((unsigned reg, FILE *stream));
81 static void fput_const PARAMS ((unsigned num, FILE *stream));
82 static void fput_reg_r PARAMS ((unsigned reg, FILE *stream));
83 static void fput_creg PARAMS ((unsigned reg, FILE *stream));
84
85 /* Print one instruction from MEMADDR on STREAM. */
86 int
87 print_insn (memaddr, stream)
88 CORE_ADDR memaddr;
89 FILE *stream;
90 {
91 long insn;
92 unsigned int i, op;
93
94 insn = read_memory_integer (memaddr, sizeof (insn));
95
96 for (i = 0; i < NUMOPCODES; ++i)
97 {
98 const struct pa_opcode *opcode = &pa_opcodes[i];
99 if ((insn & opcode->mask) == opcode->match)
100 {
101 register const char *s;
102
103 fputs_filtered (opcode->name, stream);
104
105 if (!index ("cCY<?!@-+&U>~nZFIM", opcode->args[0]))
106 fputs_filtered (" ", stream);
107 for (s = opcode->args; *s != '\0'; ++s)
108 {
109 switch (*s)
110 {
111 case 'x':
112 fput_reg (GET_FIELD (insn, 11, 15), stream);
113 break;
114 case 'X':
115 if (GET_FIELD (insn, 25, 25))
116 fput_reg_r (GET_FIELD (insn, 11, 15), stream);
117 else
118 fput_reg (GET_FIELD (insn, 11, 15), stream);
119 break;
120 case 'b':
121 fput_reg (GET_FIELD (insn, 6, 10), stream);
122 break;
123 case '^':
124 fput_creg (GET_FIELD (insn, 6, 10), stream);
125 break;
126 case 'E':
127 if (GET_FIELD (insn, 25, 25))
128 fput_reg_r (GET_FIELD (insn, 6, 10), stream);
129 else
130 fput_reg (GET_FIELD (insn, 6, 10), stream);
131 break;
132 case 't':
133 fput_reg (GET_FIELD (insn, 27, 31), stream);
134 break;
135 case 'v':
136 if (GET_FIELD (insn, 25, 25))
137 fput_reg_r (GET_FIELD (insn, 27, 31), stream);
138 else
139 fput_reg (GET_FIELD (insn, 27, 31), stream);
140 break;
141 case '4':
142 fput_creg (GET_FIELD (insn, 6, 10), stream);
143 break;
144 case '6':
145 fput_reg (GET_FIELD (insn, 11, 15), stream);
146 break;
147 case '7':
148 fput_reg (GET_FIELD (insn, 27, 31), stream);
149 break;
150 case '8':
151 fput_reg (GET_FIELD (insn, 16, 20), stream);
152 break;
153 case '9':
154 fput_reg (GET_FIELD (insn, 21, 25), stream);
155 break;
156 case '5':
157 fput_const (extract_5_load (insn), stream);
158 break;
159 /* case 's': */
160 case 'S':
161 fprintf_filtered (stream, "sr%d", extract_3 (insn));
162 break;
163 case 'c':
164 fprintf_filtered (stream, "%s ",
165 index_compl_names[GET_COMPL (insn)]);
166 break;
167 case 'C':
168 fprintf_filtered (stream, "%s ",
169 short_ldst_compl_names[GET_COMPL (insn)]);
170 break;
171 case 'Y':
172 fprintf_filtered (stream, "%s ",
173 short_bytes_compl_names[GET_COMPL (insn)]);
174 break;
175 /* these four conditions are for the set of instructions
176 which distinguish true/false conditions by opcode rather
177 than by the 'f' bit (sigh): comb, comib, addb, addib */
178 case '<':
179 fputs_filtered (compare_cond_names[GET_FIELD (insn, 16, 18)],
180 stream);
181 break;
182 case '?':
183 fputs_filtered (compare_cond_names[GET_FIELD (insn, 16, 18) + 8],
184 stream);
185 break;
186 case '!':
187 fputs_filtered (add_cond_names[GET_FIELD (insn, 16, 18)],
188 stream);
189 break;
190 case '@':
191 fputs_filtered (add_cond_names[GET_FIELD (insn, 16, 18) + 8],
192 stream);
193 break;
194 case '-':
195 fprintf_filtered (stream, "%s ",
196 compare_cond_names[GET_COND (insn)]);
197 break;
198 case '+':
199 fprintf_filtered (stream, "%s ",
200 add_cond_names[GET_FIELD (insn, 16, 18)]);
201 break;
202
203 case '&':
204 fprintf_filtered (stream, "%s ",
205 logical_cond_names[GET_COND (insn)]);
206 break;
207 case 'U':
208 fprintf_filtered (stream, "%s ",
209 unit_cond_names[GET_COND (insn)]);
210 break;
211 case '>':
212 case '~':
213 fprintf_filtered (stream, "%s ",
214 shift_cond_names[GET_FIELD (insn, 16, 18)]);
215 break;
216 case 'V':
217 fput_const (extract_5_store (insn), stream);
218 break;
219 case 'r':
220 fput_const (extract_5r_store (insn), stream);
221 break;
222 case 'R':
223 fput_const (extract_5R_store (insn), stream);
224 break;
225 case 'i':
226 fput_const (extract_11 (insn), stream);
227 break;
228 case 'j':
229 fput_const (extract_14 (insn), stream);
230 break;
231 case 'k':
232 fput_const (extract_21 (insn), stream);
233 break;
234 case 'n':
235 if (insn & 0x2)
236 fprintf_filtered (stream, ",n ");
237 else
238 fprintf_filtered (stream, " ");
239 break;
240 case 'w':
241 print_address (memaddr + 8 + extract_12 (insn), stream);
242 break;
243 case 'W':
244 op = GET_FIELD (insn, 0, 5);
245
246 if (op == 0x38 /* be */ || op == 0x39 /* ble */)
247 fput_const (extract_17 (insn), stream);
248 else
249 print_address (memaddr + 8 + extract_17 (insn), stream);
250
251 break;
252 case 'B':
253 {
254 int space;
255 if (space = GET_FIELD (insn, 16, 17))
256 fprintf_filtered (stream, "sr%d,", space);
257 fput_reg (GET_FIELD (insn, 6, 10), stream);
258 break;
259 }
260 case 'p':
261 fprintf_filtered (stream, "%d",
262 31 - GET_FIELD (insn, 22, 26));
263 break;
264 case 'P':
265 fprintf_filtered (stream, "%d",
266 GET_FIELD (insn, 22, 26));
267 break;
268 case 'Q':
269 fprintf_filtered (stream, "%d",
270 GET_FIELD (insn, 11, 15));
271 break;
272 case 'T':
273 fprintf_filtered (stream, "%d",
274 32 - GET_FIELD (insn, 27, 31));
275 break;
276 case 'A':
277 fput_const (GET_FIELD (insn, 6, 18), stream);
278 break;
279 case 'Z':
280 if (GET_FIELD (insn, 26, 26))
281 fprintf_filtered (stream, ",m ");
282 else
283 fprintf_filtered (stream, " ");
284 break;
285 case 'D':
286 fput_const (GET_FIELD (insn, 6, 31), stream);
287 break;
288 case 'f':
289 fprintf_filtered (stream, ",%d", GET_FIELD (insn, 23, 25));
290 break;
291 case 'O':
292 fput_const ((GET_FIELD (insn, 6,20) << 5 |
293 GET_FIELD (insn, 27, 31)), stream);
294 break;
295 case 'o':
296 fput_const (GET_FIELD (insn, 6, 20), stream);
297 break;
298 case '2':
299 fput_const ((GET_FIELD (insn, 6, 22) << 5 |
300 GET_FIELD (insn, 27, 31)), stream);
301 break;
302 case '1':
303 fput_const ((GET_FIELD (insn, 11, 20) << 5 |
304 GET_FIELD (insn, 27, 31)), stream);
305 break;
306 case '0':
307 fput_const ((GET_FIELD (insn, 16, 20) << 5 |
308 GET_FIELD (insn, 27, 31)), stream);
309 break;
310 case 'u':
311 fprintf_filtered (stream, "%d", GET_FIELD (insn, 23, 25));
312 break;
313 case 'F':
314 /* if no destination completer, need a space here */
315 if (GET_FIELD (insn, 21, 22) == 1)
316 fputs_filtered (float_format_names[GET_FIELD (insn, 19, 20)],
317 stream);
318 else
319 fprintf_filtered (stream, "%s ",
320 float_format_names[GET_FIELD
321 (insn, 19, 20)]);
322 break;
323 case 'G':
324 fprintf_filtered (stream, "%s ",
325 float_format_names[GET_FIELD (insn,
326 17, 18)]);
327 break;
328 case 'H':
329 fputs_filtered (float_format_names[GET_FIELD
330 (insn, 26, 26)], stream);
331 break;
332 case 'I':
333 /* if no destination completer, need a space here */
334 if (GET_FIELD (insn, 21, 22) == 1)
335 fputs_filtered (float_format_names[GET_FIELD (insn, 20, 20)],
336 stream);
337 else
338 fprintf_filtered (stream, "%s ",
339 float_format_names[GET_FIELD
340 (insn, 20, 20)]);
341 break;
342 case 'J':
343 if (GET_FIELD (insn, 24, 24))
344 fput_reg_r (GET_FIELD (insn, 6, 10), stream);
345 else
346 fput_reg (GET_FIELD (insn, 6, 10), stream);
347
348 break;
349 case 'K':
350 if (GET_FIELD (insn, 19, 19))
351 fput_reg_r (GET_FIELD (insn, 11, 15), stream);
352 else
353 fput_reg (GET_FIELD (insn, 11, 15), stream);
354 break;
355 case 'M':
356 fputs_filtered (float_comp_names[GET_FIELD (insn, 27, 31)],
357 stream);
358 break;
359 case '}':
360 fprintf_filtered (stream, "fp%d", GET_FIELD (insn, 6, 10));
361 break;
362 case '|':
363 fprintf_filtered (stream, "fp%d", GET_FIELD (insn, 11, 15));
364 break;
365 case '{':
366 if (GET_FIELD (insn, 23, 25) == 0)
367 fprintf_filtered (stream, "fp%d",
368 GET_FIELD (insn, 27, 31));
369 else
370 fprintf_filtered (stream, "cp%d",
371 GET_FIELD (insn, 27, 31));
372 break;
373 default:
374 fprintf_filtered (stream, "%c", *s);
375 break;
376 }
377 }
378
379 /* If this is an external branch, examine the previous instruction and see if
380 it was an ldil that loaded something into the same base reg. If so, then
381 calculate the branch target from the constants in both instructions, and
382 print it out. */
383
384 op = GET_FIELD (insn, 0, 5);
385 if (op == 0x38 /* be */ || op == 0x39 /* ble */)
386 {
387 CORE_ADDR target_address;
388 long prev_insn;
389 int basereg, basereg_prev;
390
391 target_address = extract_17 (insn);
392 basereg = GET_FIELD (insn, 6, 10);
393 if (basereg != 0)
394 {
395 prev_insn = read_memory_integer (memaddr - 4,
396 sizeof(prev_insn));
397 basereg_prev = GET_FIELD (prev_insn, 6, 10);
398
399 if ((prev_insn & 0xfc000000) == 0x20000000 /* ldil */
400 && basereg == basereg_prev)
401 target_address += extract_21 (prev_insn);
402 }
403 fprintf_filtered (stream, "\t! ");
404 print_address (target_address, stream);
405 }
406
407 return sizeof(insn);
408 }
409 }
410 fprintf_filtered (stream, "%#8x", insn);
411 return sizeof(insn);
412 }
413
414 /* Utility function to print registers */
415
416 static void
417 fput_reg (reg, stream)
418 unsigned reg;
419 FILE *stream;
420 {
421 if (reg)
422 fputs_filtered (reg_names[reg], stream);
423 else
424 fputs_filtered ("r0", stream);
425 }
426
427 void
428 fput_reg_r (reg, stream)
429 unsigned reg;
430 FILE *stream;
431 {
432 if (reg)
433 fputs_filtered (reg_names[reg], stream);
434 else
435 fputs_filtered ("r0", stream);
436 fputs_filtered ("R", stream);
437 }
438
439 void
440 fput_creg (reg, stream)
441 unsigned reg;
442 FILE *stream;
443 {
444 fputs_filtered (control_reg[reg], stream);
445 }
446
447 /* print constants with sign */
448
449 void
450 fput_const (num, stream)
451 unsigned num;
452 FILE *stream;
453 {
454 if ((int)num < 0)
455 fprintf_filtered (stream, "-%x", -(int)num);
456 else
457 fprintf_filtered (stream, "%x", num);
458 }
This page took 0.042497 seconds and 4 git commands to generate.