1 /* Disassembler for the PA-RISC. Somewhat derived from sparc-pinsn.c.
2 Copyright 1989, 1990, 1992 Free Software Foundation, Inc.
4 Contributed by the Center for Software Science at the
7 This file is part of GDB.
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.
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.
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. */
25 #include "opcode/hppa.h"
27 static char *control_reg[] =
28 { "rctr", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
29 "pidr1", "pidr2", "ccr", "sar", "pidr3", "pidr4",
30 "iva", "eiem", "itmr", "pcsq", "pcoq", "iir", "isr",
31 "ior", "ipsw", "eirr", "tr0", "tr1", "tr2", "tr3",
32 "tr4", "tr5", "tr6", "tr7"
35 static char *compare_cond_names[] =
36 { "", ",=", ",<", ",<=", ",<<", ",<<=", ",sv",
37 ",od", ",tr", ",<>", ",>=", ",>", ",>>=",
41 static char *add_cond_names[] =
42 { "", ",=", ",<", ",<=", ",nuv", ",znv", ",sv",
43 ",od", ",tr", ",<>", ",>=", ",>", ",uv",
47 static char *logical_cond_names[] =
48 { "", ",=", ",<", ",<=", 0, 0, 0, ",od",
49 ",tr", ",<>", ",>=", ",>", 0, 0, 0, ",ev"
52 static char *unit_cond_names[] =
53 { "", 0, ",sbz", ",shz", ",sdc", 0, ",sbc", ",shc",
54 ",tr", 0, ",nbz", ",nhz", ",ndc", 0, ",nbc", ",nhc"
57 static char *shift_cond_names[] =
58 {"", ",=", ",<", ",od", ",tr", ",<>", ",>=", ",ev"};
60 static char *index_compl_names[] = {"", ",m", ",s", ",sm"};
61 static char *short_ldst_compl_names[] = {"", ",ma", "", ",mb"};
62 static char *short_bytes_compl_names[] = {"", ",b,m", ",e", ",e,m"};
63 static char *float_format_names[] = {",sgl", ",dbl", ",quad"};
64 static char *float_comp_names[] =
65 {",false?", ",false", ",?", ",!<=>", ",=", ",=t", ",?=", ",!<>",
66 ",!?>=", ",<", ",?<", ",!>=", ",!?>", ",<=", ",?<=", ",!>",
67 ",!?<=", ",>", ",?>", ",!<=", ",!?<", ",>=", ",?>=", ",!<",
68 ",!?=", ",<>", ",!=", ",!=t", ",!?", ",<=>", ",true?", ",true"
71 /* For a bunch of different instructions form an index into a
72 completer name table. */
73 #define GET_COMPL(insn) (GET_FIELD (insn, 26, 26) | \
74 GET_FIELD (insn, 18, 18) << 1)
76 #define GET_COND(insn) (GET_FIELD ((insn), 16, 18) + \
77 (GET_FIELD ((insn), 19, 19) ? 8 : 0))
79 static void fput_reg PARAMS ((unsigned reg, FILE *stream));
80 static void fput_const PARAMS ((unsigned num, FILE *stream));
81 static void fput_reg_r PARAMS ((unsigned reg, FILE *stream));
82 static void fput_creg PARAMS ((unsigned reg, FILE *stream));
84 /* Print one instruction from MEMADDR on STREAM. */
86 print_insn (memaddr, stream)
93 insn = read_memory_integer (memaddr, sizeof (insn));
95 for (i = 0; i < NUMOPCODES; ++i)
97 const struct pa_opcode *opcode = &pa_opcodes[i];
98 if ((insn & opcode->mask) == opcode->match)
100 register const char *s;
102 fputs_filtered (opcode->name, stream);
104 if (!index ("cCY<?!@-+&U>~nZFM", opcode->args[0]))
105 fputs_filtered (" ", stream);
106 for (s = opcode->args; *s != '\0'; ++s)
111 fput_reg (GET_FIELD (insn, 11, 15), stream);
114 if (GET_FIELD (insn, 25, 25))
115 fput_reg_r (GET_FIELD (insn, 11, 15), stream);
117 fput_reg (GET_FIELD (insn, 11, 15), stream);
120 fput_reg (GET_FIELD (insn, 6, 10), stream);
123 fput_creg (GET_FIELD (insn, 6, 10), stream);
126 if (GET_FIELD (insn, 25, 25))
127 fput_reg_r (GET_FIELD (insn, 6, 10), stream);
129 fput_reg (GET_FIELD (insn, 6, 10), stream);
132 fput_reg (GET_FIELD (insn, 27, 31), stream);
135 if (GET_FIELD (insn, 25, 25))
136 fput_reg_r (GET_FIELD (insn, 27, 31), stream);
138 fput_reg (GET_FIELD (insn, 27, 31), stream);
141 fput_creg (GET_FIELD (insn, 6, 10), stream);
144 fput_reg (GET_FIELD (insn, 11, 15), stream);
147 fput_reg (GET_FIELD (insn, 27, 31), stream);
150 fput_reg (GET_FIELD (insn, 16, 20), stream);
153 fput_reg (GET_FIELD (insn, 21, 25), stream);
156 fput_const (extract_5_load (insn), stream);
160 fprintf_filtered (stream, "sr%d", extract_3 (insn));
163 fprintf_filtered (stream, "%s ",
164 index_compl_names[GET_COMPL (insn)]);
167 fprintf_filtered (stream, "%s ",
168 short_ldst_compl_names[GET_COMPL (insn)]);
171 fprintf_filtered (stream, "%s ",
172 short_bytes_compl_names[GET_COMPL (insn)]);
174 /* these four conditions are for the set of instructions
175 which distinguish true/false conditions by opcode rather
176 than by the 'f' bit (sigh): comb, comib, addb, addib */
178 fputs_filtered (compare_cond_names[GET_FIELD (insn, 16, 18)],
182 fputs_filtered (compare_cond_names[GET_FIELD (insn, 16, 18) + 8],
186 fputs_filtered (add_cond_names[GET_FIELD (insn, 16, 18)],
190 fputs_filtered (add_cond_names[GET_FIELD (insn, 16, 18) + 8],
194 fprintf_filtered (stream, "%s ",
195 compare_cond_names[GET_COND (insn)]);
198 fprintf_filtered (stream, "%s ",
199 add_cond_names[GET_FIELD (insn, 16, 18)]);
203 fprintf_filtered (stream, "%s ",
204 logical_cond_names[GET_COND (insn)]);
207 fprintf_filtered (stream, "%s ",
208 unit_cond_names[GET_COND (insn)]);
212 fprintf_filtered (stream, "%s ",
213 shift_cond_names[GET_FIELD (insn, 16, 18)]);
216 fput_const (extract_5_store (insn), stream);
219 fput_const (extract_11 (insn), stream);
222 fput_const (extract_14 (insn), stream);
225 fput_const (extract_21 (insn), stream);
229 fprintf_filtered (stream, ",n ");
231 fprintf_filtered (stream, " ");
234 print_address (memaddr + 8 + extract_12 (insn), stream);
237 op = GET_FIELD (insn, 0, 5);
239 if (op == 0x38 /* be */ || op == 0x39 /* ble */)
240 fput_const (extract_17 (insn), stream);
242 print_address (memaddr + 8 + extract_17 (insn), stream);
248 if (space = GET_FIELD (insn, 16, 17))
249 fprintf_filtered (stream, "sr%d,", space);
250 fput_reg (GET_FIELD (insn, 6, 10), stream);
254 fprintf_filtered (stream, "%d",
255 31 - GET_FIELD (insn, 22, 26));
258 fprintf_filtered (stream, "%d",
259 GET_FIELD (insn, 22, 26));
262 fprintf_filtered (stream, "%d",
263 GET_FIELD (insn, 11, 15));
266 fprintf_filtered (stream, "%d",
267 32 - GET_FIELD (insn, 27, 31));
270 fput_const (GET_FIELD (insn, 6, 18), stream);
273 if (GET_FIELD (insn, 26, 26))
274 fprintf_filtered (stream, ",m ");
276 fprintf_filtered (stream, " ");
279 fput_const (GET_FIELD (insn, 6, 31), stream);
282 fprintf_filtered (stream, ",%d", GET_FIELD (insn, 23, 25));
285 fput_const ((GET_FIELD (insn, 6,20) << 5 |
286 GET_FIELD (insn, 27, 31)), stream);
289 fput_const (GET_FIELD (insn, 6, 20), stream);
292 fput_const ((GET_FIELD (insn, 6, 22) << 5 |
293 GET_FIELD (insn, 27, 31)), stream);
296 fput_const ((GET_FIELD (insn, 11, 20) << 5 |
297 GET_FIELD (insn, 27, 31)), stream);
300 fput_const ((GET_FIELD (insn, 16, 20) << 5 |
301 GET_FIELD (insn, 27, 31)), stream);
304 fprintf_filtered (stream, "%d", GET_FIELD (insn, 23, 25));
307 /* if no destination completer, need a space here */
308 if (GET_FIELD (insn, 21, 22) == 1)
309 fputs_filtered (float_format_names[GET_FIELD (insn, 19, 20)],
312 fprintf_filtered (stream, "%s ",
313 float_format_names[GET_FIELD
317 fprintf_filtered (stream, "%s ",
318 float_format_names[GET_FIELD (insn,
322 fputs_filtered (float_format_names[GET_FIELD
323 (insn, 26, 26)], stream);
326 fputs_filtered (float_comp_names[GET_FIELD (insn, 27, 31)],
330 fprintf_filtered (stream, "fp%d", GET_FIELD (insn, 6, 10));
333 fprintf_filtered (stream, "fp%d", GET_FIELD (insn, 11, 15));
336 if (GET_FIELD (insn, 23, 25) == 0)
337 fprintf_filtered (stream, "fp%d",
338 GET_FIELD (insn, 27, 31));
340 fprintf_filtered (stream, "cp%d",
341 GET_FIELD (insn, 27, 31));
344 fprintf_filtered (stream, "%c", *s);
349 /* If this is an external branch, examine the previous instruction and see if
350 it was an ldil that loaded something into the same base reg. If so, then
351 calculate the branch target from the constants in both instructions, and
354 op = GET_FIELD (insn, 0, 5);
355 if (op == 0x38 /* be */ || op == 0x39 /* ble */)
357 CORE_ADDR target_address;
359 int basereg, basereg_prev;
361 target_address = extract_17 (insn);
362 basereg = GET_FIELD (insn, 6, 10);
365 prev_insn = read_memory_integer (memaddr - 4,
367 basereg_prev = GET_FIELD (prev_insn, 6, 10);
369 if ((prev_insn & 0xfc000000) == 0x20000000 /* ldil */
370 && basereg == basereg_prev)
371 target_address += extract_21 (prev_insn);
373 fprintf_filtered (stream, "\t! ");
374 print_address (target_address, stream);
380 fprintf_filtered (stream, "%#8x", insn);
384 /* Utility function to print registers */
387 fput_reg (reg, stream)
392 fputs_filtered (reg_names[reg], stream);
394 fputs_filtered ("r0", stream);
398 fput_reg_r (reg, stream)
403 fputs_filtered (reg_names[reg], stream);
405 fputs_filtered ("r0", stream);
406 fputs_filtered ("R", stream);
410 fput_creg (reg, stream)
414 fputs_filtered (control_reg[reg], stream);
417 /* print constants with sign */
420 fput_const (num, stream)
425 fprintf_filtered (stream, "-%x", -(int)num);
427 fprintf_filtered (stream, "%x", num);