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
5 University of Utah (pa-gdb-bugs@cs.utah.edu).
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_5r_store (insn
), stream
);
222 fput_const (extract_5R_store (insn
), stream
);
225 fput_const (extract_11 (insn
), stream
);
228 fput_const (extract_14 (insn
), stream
);
231 fput_const (extract_21 (insn
), stream
);
235 fprintf_filtered (stream
, ",n ");
237 fprintf_filtered (stream
, " ");
240 print_address (memaddr
+ 8 + extract_12 (insn
), stream
);
243 op
= GET_FIELD (insn
, 0, 5);
245 if (op
== 0x38 /* be */ || op
== 0x39 /* ble */)
246 fput_const (extract_17 (insn
), stream
);
248 print_address (memaddr
+ 8 + extract_17 (insn
), stream
);
254 if (space
= GET_FIELD (insn
, 16, 17))
255 fprintf_filtered (stream
, "sr%d,", space
);
256 fput_reg (GET_FIELD (insn
, 6, 10), stream
);
260 fprintf_filtered (stream
, "%d",
261 31 - GET_FIELD (insn
, 22, 26));
264 fprintf_filtered (stream
, "%d",
265 GET_FIELD (insn
, 22, 26));
268 fprintf_filtered (stream
, "%d",
269 GET_FIELD (insn
, 11, 15));
272 fprintf_filtered (stream
, "%d",
273 32 - GET_FIELD (insn
, 27, 31));
276 fput_const (GET_FIELD (insn
, 6, 18), stream
);
279 if (GET_FIELD (insn
, 26, 26))
280 fprintf_filtered (stream
, ",m ");
282 fprintf_filtered (stream
, " ");
285 fput_const (GET_FIELD (insn
, 6, 31), stream
);
288 fprintf_filtered (stream
, ",%d", GET_FIELD (insn
, 23, 25));
291 fput_const ((GET_FIELD (insn
, 6,20) << 5 |
292 GET_FIELD (insn
, 27, 31)), stream
);
295 fput_const (GET_FIELD (insn
, 6, 20), stream
);
298 fput_const ((GET_FIELD (insn
, 6, 22) << 5 |
299 GET_FIELD (insn
, 27, 31)), stream
);
302 fput_const ((GET_FIELD (insn
, 11, 20) << 5 |
303 GET_FIELD (insn
, 27, 31)), stream
);
306 fput_const ((GET_FIELD (insn
, 16, 20) << 5 |
307 GET_FIELD (insn
, 27, 31)), stream
);
310 fprintf_filtered (stream
, "%d", GET_FIELD (insn
, 23, 25));
313 /* if no destination completer, need a space here */
314 if (GET_FIELD (insn
, 21, 22) == 1)
315 fputs_filtered (float_format_names
[GET_FIELD (insn
, 19, 20)],
318 fprintf_filtered (stream
, "%s ",
319 float_format_names
[GET_FIELD
323 fprintf_filtered (stream
, "%s ",
324 float_format_names
[GET_FIELD (insn
,
328 fputs_filtered (float_format_names
[GET_FIELD
329 (insn
, 26, 26)], stream
);
332 fputs_filtered (float_comp_names
[GET_FIELD (insn
, 27, 31)],
336 fprintf_filtered (stream
, "fp%d", GET_FIELD (insn
, 6, 10));
339 fprintf_filtered (stream
, "fp%d", GET_FIELD (insn
, 11, 15));
342 if (GET_FIELD (insn
, 23, 25) == 0)
343 fprintf_filtered (stream
, "fp%d",
344 GET_FIELD (insn
, 27, 31));
346 fprintf_filtered (stream
, "cp%d",
347 GET_FIELD (insn
, 27, 31));
350 fprintf_filtered (stream
, "%c", *s
);
355 /* If this is an external branch, examine the previous instruction and see if
356 it was an ldil that loaded something into the same base reg. If so, then
357 calculate the branch target from the constants in both instructions, and
360 op
= GET_FIELD (insn
, 0, 5);
361 if (op
== 0x38 /* be */ || op
== 0x39 /* ble */)
363 CORE_ADDR target_address
;
365 int basereg
, basereg_prev
;
367 target_address
= extract_17 (insn
);
368 basereg
= GET_FIELD (insn
, 6, 10);
371 prev_insn
= read_memory_integer (memaddr
- 4,
373 basereg_prev
= GET_FIELD (prev_insn
, 6, 10);
375 if ((prev_insn
& 0xfc000000) == 0x20000000 /* ldil */
376 && basereg
== basereg_prev
)
377 target_address
+= extract_21 (prev_insn
);
379 fprintf_filtered (stream
, "\t! ");
380 print_address (target_address
, stream
);
386 fprintf_filtered (stream
, "%#8x", insn
);
390 /* Utility function to print registers */
393 fput_reg (reg
, stream
)
398 fputs_filtered (reg_names
[reg
], stream
);
400 fputs_filtered ("r0", stream
);
404 fput_reg_r (reg
, stream
)
409 fputs_filtered (reg_names
[reg
], stream
);
411 fputs_filtered ("r0", stream
);
412 fputs_filtered ("R", stream
);
416 fput_creg (reg
, stream
)
420 fputs_filtered (control_reg
[reg
], stream
);
423 /* print constants with sign */
426 fput_const (num
, stream
)
431 fprintf_filtered (stream
, "-%x", -(int)num
);
433 fprintf_filtered (stream
, "%x", num
);
This page took 0.073581 seconds and 5 git commands to generate.