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
)
90 unsigned int insn
, i
, op
;
92 read_memory (memaddr
, &insn
, sizeof (insn
));
94 for (i
= 0; i
< NUMOPCODES
; ++i
)
96 const struct pa_opcode
*opcode
= &pa_opcodes
[i
];
97 if ((insn
& opcode
->mask
) == opcode
->match
)
99 register const char *s
;
101 fputs_filtered (opcode
->name
, stream
);
103 if (!index ("cCY<?!@-+&U>~nZFM", opcode
->args
[0]))
104 fputs_filtered (" ", stream
);
105 for (s
= opcode
->args
; *s
!= '\0'; ++s
)
110 fput_reg (GET_FIELD (insn
, 11, 15), stream
);
113 if (GET_FIELD (insn
, 25, 25))
114 fput_reg_r (GET_FIELD (insn
, 11, 15), stream
);
116 fput_reg (GET_FIELD (insn
, 11, 15), stream
);
119 fput_reg (GET_FIELD (insn
, 6, 10), stream
);
122 fput_creg (GET_FIELD (insn
, 6, 10), stream
);
125 if (GET_FIELD (insn
, 25, 25))
126 fput_reg_r (GET_FIELD (insn
, 6, 10), stream
);
128 fput_reg (GET_FIELD (insn
, 6, 10), stream
);
131 fput_reg (GET_FIELD (insn
, 27, 31), stream
);
134 if (GET_FIELD (insn
, 25, 25))
135 fput_reg_r (GET_FIELD (insn
, 27, 31), stream
);
137 fput_reg (GET_FIELD (insn
, 27, 31), stream
);
140 fput_creg (GET_FIELD (insn
, 6, 10), stream
);
143 fput_reg (GET_FIELD (insn
, 11, 15), stream
);
146 fput_reg (GET_FIELD (insn
, 27, 31), stream
);
149 fput_reg (GET_FIELD (insn
, 16, 20), stream
);
152 fput_reg (GET_FIELD (insn
, 21, 25), stream
);
155 fput_const (extract_5_load (insn
), stream
);
159 fprintf_filtered (stream
, "sr%d", extract_3 (insn
));
162 fprintf_filtered (stream
, "%s ",
163 index_compl_names
[GET_COMPL (insn
)]);
166 fprintf_filtered (stream
, "%s ",
167 short_ldst_compl_names
[GET_COMPL (insn
)]);
170 fprintf_filtered (stream
, "%s ",
171 short_bytes_compl_names
[GET_COMPL (insn
)]);
173 /* these four conditions are for the set of instructions
174 which distinguish true/false conditions by opcode rather
175 than by the 'f' bit (sigh): comb, comib, addb, addib */
177 fputs_filtered (compare_cond_names
[GET_FIELD (insn
, 16, 18)],
181 fputs_filtered (compare_cond_names
[GET_FIELD (insn
, 16, 18) + 8],
185 fputs_filtered (add_cond_names
[GET_FIELD (insn
, 16, 18)],
189 fputs_filtered (add_cond_names
[GET_FIELD (insn
, 16, 18) + 8],
193 fprintf_filtered (stream
, "%s ",
194 compare_cond_names
[GET_COND (insn
)]);
197 fprintf_filtered (stream
, "%s ",
198 add_cond_names
[GET_FIELD (insn
, 16, 18)]);
202 fprintf_filtered (stream
, "%s ",
203 logical_cond_names
[GET_COND (insn
)]);
206 fprintf_filtered (stream
, "%s ",
207 unit_cond_names
[GET_COND (insn
)]);
211 fprintf_filtered (stream
, "%s ",
212 shift_cond_names
[GET_FIELD (insn
, 16, 18)]);
215 fput_const (extract_5_store (insn
), stream
);
218 fput_const (extract_11 (insn
), stream
);
221 fput_const (extract_14 (insn
), stream
);
224 fput_const (extract_21 (insn
), stream
);
228 fprintf_filtered (stream
, ",n ");
230 fprintf_filtered (stream
, " ");
233 print_address (memaddr
+ 8 + extract_12 (insn
), stream
);
236 op
= GET_FIELD (insn
, 0, 5);
238 if (op
== 0x38 /* be */ || op
== 0x39 /* ble */)
239 fput_const (extract_17 (insn
), stream
);
241 print_address (memaddr
+ 8 + extract_17 (insn
), stream
);
247 if (space
= GET_FIELD (insn
, 16, 17))
248 fprintf_filtered (stream
, "sr%d,", space
);
249 fput_reg (GET_FIELD (insn
, 6, 10), stream
);
253 fprintf_filtered (stream
, "%d",
254 31 - GET_FIELD (insn
, 22, 26));
257 fprintf_filtered (stream
, "%d",
258 GET_FIELD (insn
, 22, 26));
261 fprintf_filtered (stream
, "%d",
262 GET_FIELD (insn
, 11, 15));
265 fprintf_filtered (stream
, "%d",
266 32 - GET_FIELD (insn
, 27, 31));
269 fput_const (GET_FIELD (insn
, 6, 18), stream
);
272 if (GET_FIELD (insn
, 26, 26))
273 fprintf_filtered (stream
, ",m ");
275 fprintf_filtered (stream
, " ");
278 fput_const (GET_FIELD (insn
, 6, 31), stream
);
281 fprintf_filtered (stream
, ",%d", GET_FIELD (insn
, 23, 25));
284 fput_const ((GET_FIELD (insn
, 6,20) << 5 |
285 GET_FIELD (insn
, 27, 31)), stream
);
288 fput_const (GET_FIELD (insn
, 6, 20), stream
);
291 fput_const ((GET_FIELD (insn
, 6, 22) << 5 |
292 GET_FIELD (insn
, 27, 31)), stream
);
295 fput_const ((GET_FIELD (insn
, 11, 20) << 5 |
296 GET_FIELD (insn
, 27, 31)), stream
);
299 fput_const ((GET_FIELD (insn
, 16, 20) << 5 |
300 GET_FIELD (insn
, 27, 31)), stream
);
303 fprintf_filtered (stream
, "%d", GET_FIELD (insn
, 23, 25));
306 /* if no destination completer, need a space here */
307 if (GET_FIELD (insn
, 21, 22) == 1)
308 fputs_filtered (float_format_names
[GET_FIELD (insn
, 19, 20)],
311 fprintf_filtered (stream
, "%s ",
312 float_format_names
[GET_FIELD
316 fprintf_filtered (stream
, "%s ",
317 float_format_names
[GET_FIELD (insn
,
321 fputs_filtered (float_format_names
[GET_FIELD
322 (insn
, 26, 26)], stream
);
325 fputs_filtered (float_comp_names
[GET_FIELD (insn
, 27, 31)],
329 fprintf_filtered (stream
, "fp%d", GET_FIELD (insn
, 6, 10));
332 fprintf_filtered (stream
, "fp%d", GET_FIELD (insn
, 11, 15));
335 if (GET_FIELD (insn
, 23, 25) == 0)
336 fprintf_filtered (stream
, "fp%d",
337 GET_FIELD (insn
, 27, 31));
339 fprintf_filtered (stream
, "cp%d",
340 GET_FIELD (insn
, 27, 31));
343 fprintf_filtered (stream
, "%c", *s
);
348 /* If this is an external branch, examine the previous instruction and see if
349 it was an ldil that loaded something into the same base reg. If so, then
350 calculate the branch target from the constants in both instructions, and
353 op
= GET_FIELD (insn
, 0, 5);
354 if (op
== 0x38 /* be */ || op
== 0x39 /* ble */)
356 CORE_ADDR target_address
;
357 unsigned int prev_insn
;
358 int basereg
, basereg_prev
;
360 target_address
= extract_17 (insn
);
361 basereg
= GET_FIELD (insn
, 6, 10);
364 read_memory (memaddr
- 4, &prev_insn
, sizeof(prev_insn
));
365 basereg_prev
= GET_FIELD (prev_insn
, 6, 10);
367 if ((prev_insn
& 0xfc000000) == 0x20000000 /* ldil */
368 && basereg
== basereg_prev
)
369 target_address
+= extract_21 (prev_insn
);
371 fprintf_filtered (stream
, "\t! ");
372 print_address (target_address
, stream
);
378 fprintf_filtered (stream
, "%#8x", insn
);
382 /* Utility function to print registers */
385 fput_reg (reg
, stream
)
390 fputs_filtered (reg_names
[reg
], stream
);
392 fputs_filtered ("r0", stream
);
396 fput_reg_r (reg
, stream
)
401 fputs_filtered (reg_names
[reg
], stream
);
403 fputs_filtered ("r0", stream
);
404 fputs_filtered ("R", stream
);
408 fput_creg (reg
, stream
)
412 fputs_filtered (control_reg
[reg
], stream
);
415 /* print constants with sign */
418 fput_const (num
, stream
)
423 fprintf_filtered (stream
, "-%x", -(int)num
);
425 fprintf_filtered (stream
, "%x", num
);
This page took 0.038828 seconds and 4 git commands to generate.