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. */
26 #include "opcode/hppa.h"
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"
36 static char *compare_cond_names
[] =
37 { "", ",=", ",<", ",<=", ",<<", ",<<=", ",sv",
38 ",od", ",tr", ",<>", ",>=", ",>", ",>>=",
42 static char *add_cond_names
[] =
43 { "", ",=", ",<", ",<=", ",nuv", ",znv", ",sv",
44 ",od", ",tr", ",<>", ",>=", ",>", ",uv",
48 static char *logical_cond_names
[] =
49 { "", ",=", ",<", ",<=", 0, 0, 0, ",od",
50 ",tr", ",<>", ",>=", ",>", 0, 0, 0, ",ev"
53 static char *unit_cond_names
[] =
54 { "", 0, ",sbz", ",shz", ",sdc", 0, ",sbc", ",shc",
55 ",tr", 0, ",nbz", ",nhz", ",ndc", 0, ",nbc", ",nhc"
58 static char *shift_cond_names
[] =
59 {"", ",=", ",<", ",od", ",tr", ",<>", ",>=", ",ev"};
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"
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)
77 #define GET_COND(insn) (GET_FIELD ((insn), 16, 18) + \
78 (GET_FIELD ((insn), 19, 19) ? 8 : 0))
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
));
85 /* Print one instruction from MEMADDR on STREAM. */
87 print_insn (memaddr
, stream
)
94 insn
= read_memory_integer (memaddr
, sizeof (insn
));
96 for (i
= 0; i
< NUMOPCODES
; ++i
)
98 const struct pa_opcode
*opcode
= &pa_opcodes
[i
];
99 if ((insn
& opcode
->mask
) == opcode
->match
)
101 register const char *s
;
103 fputs_filtered (opcode
->name
, stream
);
105 if (!index ("cCY<?!@-+&U>~nZFIM", opcode
->args
[0]))
106 fputs_filtered (" ", stream
);
107 for (s
= opcode
->args
; *s
!= '\0'; ++s
)
112 fput_reg (GET_FIELD (insn
, 11, 15), stream
);
115 if (GET_FIELD (insn
, 25, 25))
116 fput_reg_r (GET_FIELD (insn
, 11, 15), stream
);
118 fput_reg (GET_FIELD (insn
, 11, 15), stream
);
121 fput_reg (GET_FIELD (insn
, 6, 10), stream
);
124 fput_creg (GET_FIELD (insn
, 6, 10), stream
);
127 if (GET_FIELD (insn
, 25, 25))
128 fput_reg_r (GET_FIELD (insn
, 6, 10), stream
);
130 fput_reg (GET_FIELD (insn
, 6, 10), stream
);
133 fput_reg (GET_FIELD (insn
, 27, 31), stream
);
136 if (GET_FIELD (insn
, 25, 25))
137 fput_reg_r (GET_FIELD (insn
, 27, 31), stream
);
139 fput_reg (GET_FIELD (insn
, 27, 31), stream
);
142 fput_creg (GET_FIELD (insn
, 6, 10), stream
);
145 fput_reg (GET_FIELD (insn
, 11, 15), stream
);
148 fput_reg (GET_FIELD (insn
, 27, 31), stream
);
151 fput_reg (GET_FIELD (insn
, 16, 20), stream
);
154 fput_reg (GET_FIELD (insn
, 21, 25), stream
);
157 fput_const (extract_5_load (insn
), stream
);
161 fprintf_filtered (stream
, "sr%d", extract_3 (insn
));
164 fprintf_filtered (stream
, "%s ",
165 index_compl_names
[GET_COMPL (insn
)]);
168 fprintf_filtered (stream
, "%s ",
169 short_ldst_compl_names
[GET_COMPL (insn
)]);
172 fprintf_filtered (stream
, "%s ",
173 short_bytes_compl_names
[GET_COMPL (insn
)]);
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 */
179 fputs_filtered (compare_cond_names
[GET_FIELD (insn
, 16, 18)],
183 fputs_filtered (compare_cond_names
[GET_FIELD (insn
, 16, 18) + 8],
187 fputs_filtered (add_cond_names
[GET_FIELD (insn
, 16, 18)],
191 fputs_filtered (add_cond_names
[GET_FIELD (insn
, 16, 18) + 8],
195 fprintf_filtered (stream
, "%s ",
196 compare_cond_names
[GET_COND (insn
)]);
199 fprintf_filtered (stream
, "%s ",
200 add_cond_names
[GET_FIELD (insn
, 16, 18)]);
204 fprintf_filtered (stream
, "%s ",
205 logical_cond_names
[GET_COND (insn
)]);
208 fprintf_filtered (stream
, "%s ",
209 unit_cond_names
[GET_COND (insn
)]);
213 fprintf_filtered (stream
, "%s ",
214 shift_cond_names
[GET_FIELD (insn
, 16, 18)]);
217 fput_const (extract_5_store (insn
), stream
);
220 fput_const (extract_5r_store (insn
), stream
);
223 fput_const (extract_5R_store (insn
), stream
);
226 fput_const (extract_11 (insn
), stream
);
229 fput_const (extract_14 (insn
), stream
);
232 fput_const (extract_21 (insn
), stream
);
236 fprintf_filtered (stream
, ",n ");
238 fprintf_filtered (stream
, " ");
241 print_address (memaddr
+ 8 + extract_12 (insn
), stream
);
244 op
= GET_FIELD (insn
, 0, 5);
246 if (op
== 0x38 /* be */ || op
== 0x39 /* ble */)
247 fput_const (extract_17 (insn
), stream
);
249 print_address (memaddr
+ 8 + extract_17 (insn
), stream
);
255 if (space
= GET_FIELD (insn
, 16, 17))
256 fprintf_filtered (stream
, "sr%d,", space
);
257 fput_reg (GET_FIELD (insn
, 6, 10), stream
);
261 fprintf_filtered (stream
, "%d",
262 31 - GET_FIELD (insn
, 22, 26));
265 fprintf_filtered (stream
, "%d",
266 GET_FIELD (insn
, 22, 26));
269 fprintf_filtered (stream
, "%d",
270 GET_FIELD (insn
, 11, 15));
273 fprintf_filtered (stream
, "%d",
274 32 - GET_FIELD (insn
, 27, 31));
277 fput_const (GET_FIELD (insn
, 6, 18), stream
);
280 if (GET_FIELD (insn
, 26, 26))
281 fprintf_filtered (stream
, ",m ");
283 fprintf_filtered (stream
, " ");
286 fput_const (GET_FIELD (insn
, 6, 31), stream
);
289 fprintf_filtered (stream
, ",%d", GET_FIELD (insn
, 23, 25));
292 fput_const ((GET_FIELD (insn
, 6,20) << 5 |
293 GET_FIELD (insn
, 27, 31)), stream
);
296 fput_const (GET_FIELD (insn
, 6, 20), stream
);
299 fput_const ((GET_FIELD (insn
, 6, 22) << 5 |
300 GET_FIELD (insn
, 27, 31)), stream
);
303 fput_const ((GET_FIELD (insn
, 11, 20) << 5 |
304 GET_FIELD (insn
, 27, 31)), stream
);
307 fput_const ((GET_FIELD (insn
, 16, 20) << 5 |
308 GET_FIELD (insn
, 27, 31)), stream
);
311 fprintf_filtered (stream
, "%d", GET_FIELD (insn
, 23, 25));
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)],
319 fprintf_filtered (stream
, "%s ",
320 float_format_names
[GET_FIELD
324 fprintf_filtered (stream
, "%s ",
325 float_format_names
[GET_FIELD (insn
,
329 fputs_filtered (float_format_names
[GET_FIELD
330 (insn
, 26, 26)], stream
);
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)],
338 fprintf_filtered (stream
, "%s ",
339 float_format_names
[GET_FIELD
343 if (GET_FIELD (insn
, 24, 24))
344 fput_reg_r (GET_FIELD (insn
, 6, 10), stream
);
346 fput_reg (GET_FIELD (insn
, 6, 10), stream
);
350 if (GET_FIELD (insn
, 19, 19))
351 fput_reg_r (GET_FIELD (insn
, 11, 15), stream
);
353 fput_reg (GET_FIELD (insn
, 11, 15), stream
);
356 fputs_filtered (float_comp_names
[GET_FIELD (insn
, 27, 31)],
360 fprintf_filtered (stream
, "fp%d", GET_FIELD (insn
, 6, 10));
363 fprintf_filtered (stream
, "fp%d", GET_FIELD (insn
, 11, 15));
366 if (GET_FIELD (insn
, 23, 25) == 0)
367 fprintf_filtered (stream
, "fp%d",
368 GET_FIELD (insn
, 27, 31));
370 fprintf_filtered (stream
, "cp%d",
371 GET_FIELD (insn
, 27, 31));
374 fprintf_filtered (stream
, "%c", *s
);
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
384 op
= GET_FIELD (insn
, 0, 5);
385 if (op
== 0x38 /* be */ || op
== 0x39 /* ble */)
387 CORE_ADDR target_address
;
389 int basereg
, basereg_prev
;
391 target_address
= extract_17 (insn
);
392 basereg
= GET_FIELD (insn
, 6, 10);
395 prev_insn
= read_memory_integer (memaddr
- 4,
397 basereg_prev
= GET_FIELD (prev_insn
, 6, 10);
399 if ((prev_insn
& 0xfc000000) == 0x20000000 /* ldil */
400 && basereg
== basereg_prev
)
401 target_address
+= extract_21 (prev_insn
);
403 fprintf_filtered (stream
, "\t! ");
404 print_address (target_address
, stream
);
410 fprintf_filtered (stream
, "%#8x", insn
);
414 /* Utility function to print registers */
417 fput_reg (reg
, stream
)
422 fputs_filtered (reg_names
[reg
], stream
);
424 fputs_filtered ("r0", stream
);
428 fput_reg_r (reg
, stream
)
433 fputs_filtered (reg_names
[reg
], stream
);
435 fputs_filtered ("r0", stream
);
436 fputs_filtered ("R", stream
);
440 fput_creg (reg
, stream
)
444 fputs_filtered (control_reg
[reg
], stream
);
447 /* print constants with sign */
450 fput_const (num
, stream
)
455 fprintf_filtered (stream
, "-%x", -(int)num
);
457 fprintf_filtered (stream
, "%x", num
);
This page took 0.039055 seconds and 4 git commands to generate.