Rizin
unix-like reverse engineering framework and cli tools
hppa-dis.c
Go to the documentation of this file.
1 /* Disassembler for the PA-RISC. Somewhat derived from sparc-pinsn.c.
2  Copyright (C) 1989-2014 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 the GNU opcodes library.
8 
9  This library 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 3, or (at your option)
12  any later version.
13 
14  It is distributed in the hope that it will be useful, but WITHOUT
15  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17  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., 51 Franklin Street - Fifth Floor, Boston,
22  MA 02110-1301, USA. */
23 
24 #include "sysdep.h"
25 #include "disas-asm.h"
26 #include "libhppa.h"
27 #include "opcode/hppa.h"
28 #include <string.h>
29 #include <rz_types_base.h>
30 
31 /* Integer register names, indexed by the numbers which appear in the
32  opcodes. */
33 static const char *const reg_names[] =
34 {
35  "flags", "r1", "rp", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
36  "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19",
37  "r20", "r21", "r22", "r23", "r24", "r25", "r26", "dp", "ret0", "ret1",
38  "sp", "r31"
39 };
40 
41 /* Floating point register names, indexed by the numbers which appear in the
42  opcodes. */
43 static const char *const fp_reg_names[] =
44 {
45  "fpsr", "fpe2", "fpe4", "fpe6",
46  "fr4", "fr5", "fr6", "fr7", "fr8",
47  "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
48  "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23",
49  "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31"
50 };
51 
52 typedef unsigned int CORE_ADDR;
53 
54 /* Get at various relevant fields of an instruction word. */
55 
56 #define MASK_5 0x1f
57 #define MASK_10 0x3ff
58 #define MASK_11 0x7ff
59 #define MASK_14 0x3fff
60 #define MASK_16 0xffff
61 #define MASK_21 0x1fffff
62 
63 /* These macros get bit fields using HP's numbering (MSB = 0). */
64 
65 #define GET_FIELD(X, FROM, TO) \
66  ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
67 
68 #define GET_BIT(X, WHICH) \
69  GET_FIELD (X, WHICH, WHICH)
70 
71 /* Some of these have been converted to 2-d arrays because they
72  consume less storage this way. If the maintenance becomes a
73  problem, convert them back to const 1-d pointer arrays. */
74 static const char *const control_reg[] =
75 {
76  "rctr", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
77  "pidr1", "pidr2", "ccr", "sar", "pidr3", "pidr4",
78  "iva", "eiem", "itmr", "pcsq", "pcoq", "iir", "isr",
79  "ior", "ipsw", "eirr", "tr0", "tr1", "tr2", "tr3",
80  "tr4", "tr5", "tr6", "tr7"
81 };
82 
83 static const char *const compare_cond_names[] =
84 {
85  "", ",=", ",<", ",<=", ",<<", ",<<=", ",sv", ",od",
86  ",tr", ",<>", ",>=", ",>", ",>>=", ",>>", ",nsv", ",ev"
87 };
88 static const char *const compare_cond_64_names[] =
89 {
90  ",*", ",*=", ",*<", ",*<=", ",*<<", ",*<<=", ",*sv", ",*od",
91  ",*tr", ",*<>", ",*>=", ",*>", ",*>>=", ",*>>", ",*nsv", ",*ev"
92 };
93 static const char *const cmpib_cond_64_names[] =
94 {
95  ",*<<", ",*=", ",*<", ",*<=", ",*>>=", ",*<>", ",*>=", ",*>"
96 };
97 static const char *const add_cond_names[] =
98 {
99  "", ",=", ",<", ",<=", ",nuv", ",znv", ",sv", ",od",
100  ",tr", ",<>", ",>=", ",>", ",uv", ",vnz", ",nsv", ",ev"
101 };
102 static const char *const add_cond_64_names[] =
103 {
104  ",*", ",*=", ",*<", ",*<=", ",*nuv", ",*znv", ",*sv", ",*od",
105  ",*tr", ",*<>", ",*>=", ",*>", ",*uv", ",*vnz", ",*nsv", ",*ev"
106 };
107 static const char *const wide_add_cond_names[] =
108 {
109  "", ",=", ",<", ",<=", ",nuv", ",*=", ",*<", ",*<=",
110  ",tr", ",<>", ",>=", ",>", ",uv", ",*<>", ",*>=", ",*>"
111 };
112 static const char *const logical_cond_names[] =
113 {
114  "", ",=", ",<", ",<=", 0, 0, 0, ",od",
115  ",tr", ",<>", ",>=", ",>", 0, 0, 0, ",ev"};
116 static const char *const logical_cond_64_names[] =
117 {
118  ",*", ",*=", ",*<", ",*<=", 0, 0, 0, ",*od",
119  ",*tr", ",*<>", ",*>=", ",*>", 0, 0, 0, ",*ev"};
120 static const char *const unit_cond_names[] =
121 {
122  "", ",swz", ",sbz", ",shz", ",sdc", ",swc", ",sbc", ",shc",
123  ",tr", ",nwz", ",nbz", ",nhz", ",ndc", ",nwc", ",nbc", ",nhc"
124 };
125 static const char *const unit_cond_64_names[] =
126 {
127  ",*", ",*swz", ",*sbz", ",*shz", ",*sdc", ",*swc", ",*sbc", ",*shc",
128  ",*tr", ",*nwz", ",*nbz", ",*nhz", ",*ndc", ",*nwc", ",*nbc", ",*nhc"
129 };
130 static const char *const shift_cond_names[] =
131 {
132  "", ",=", ",<", ",od", ",tr", ",<>", ",>=", ",ev"
133 };
134 static const char *const shift_cond_64_names[] =
135 {
136  ",*", ",*=", ",*<", ",*od", ",*tr", ",*<>", ",*>=", ",*ev"
137 };
138 static const char *const bb_cond_64_names[] =
139 {
140  ",*<", ",*>="
141 };
142 static const char *const index_compl_names[] = {"", ",m", ",s", ",sm"};
143 static const char *const short_ldst_compl_names[] = {"", ",ma", "", ",mb"};
144 static const char *const short_bytes_compl_names[] =
145 {
146  "", ",b,m", ",e", ",e,m"
147 };
148 static const char *const float_format_names[] = {",sgl", ",dbl", "", ",quad"};
149 static const char *const fcnv_fixed_names[] = {",w", ",dw", "", ",qw"};
150 static const char *const fcnv_ufixed_names[] = {",uw", ",udw", "", ",uqw"};
151 static const char *const float_comp_names[] =
152 {
153  ",false?", ",false", ",?", ",!<=>", ",=", ",=t", ",?=", ",!<>",
154  ",!?>=", ",<", ",?<", ",!>=", ",!?>", ",<=", ",?<=", ",!>",
155  ",!?<=", ",>", ",?>", ",!<=", ",!?<", ",>=", ",?>=", ",!<",
156  ",!?=", ",<>", ",!=", ",!=t", ",!?", ",<=>", ",true?", ",true"
157 };
158 static const char *const signed_unsigned_names[] = {",u", ",s"};
159 static const char *const mix_half_names[] = {",l", ",r"};
160 static const char *const saturation_names[] = {",us", ",ss", 0, ""};
161 static const char *const read_write_names[] = {",r", ",w"};
162 static const char *const add_compl_names[] = { 0, "", ",l", ",tsv" };
163 
164 /* For a bunch of different instructions form an index into a
165  completer name table. */
166 #define GET_COMPL(insn) (GET_FIELD (insn, 26, 26) | \
167  GET_FIELD (insn, 18, 18) << 1)
168 
169 #define GET_COND(insn) (GET_FIELD ((insn), 16, 18) + \
170  (GET_FIELD ((insn), 19, 19) ? 8 : 0))
171 
172 /* Utility function to print registers. Put these first, so gcc's function
173  inlining can do its stuff. */
174 
175 #define fputs_filtered(STR,F) (*info->fprintf_func) (info->stream, "%s", STR)
176 
177 static void
179 {
180  (*info->fprintf_func) (info->stream, "%s", reg ? reg_names[reg] : "r0");
181 }
182 
183 static void
185 {
186  (*info->fprintf_func) (info->stream, "%s", reg ? fp_reg_names[reg] : "fr0");
187 }
188 
189 static void
191 {
192  /* Special case floating point exception registers. */
193  if (reg < 4) {
194  (*info->fprintf_func) (info->stream, "fpe%d", reg * 2 + 1);
195  } else {
196  (*info->fprintf_func) (info->stream, "%sR", fp_reg_names[reg]);
197  }
198 }
199 
200 static void
202 {
203  (*info->fprintf_func) (info->stream, "%s", control_reg[reg]);
204 }
205 
206 /* Print constants with sign. */
207 
208 static void
210 {
211  if ((int)num < 0) {
212  (*info->fprintf_func) (info->stream, "-%x", -(int)num);
213  } else {
214  (*info->fprintf_func) (info->stream, "%x", num);
215  }
216 }
217 
218 /* Routines to extract various sized constants out of hppa
219  instructions. */
220 
221 /* Extract a 3-bit space register number from a be, ble, mtsp or mfsp. */
222 static int
223 extract_3 (unsigned word)
224 {
225  return GET_FIELD (word, 18, 18) << 2 | GET_FIELD (word, 16, 17);
226 }
227 
228 static int
229 extract_5_load (unsigned word)
230 {
231  return low_sign_extend (word >> 16 & MASK_5, 5);
232 }
233 
234 /* Extract the immediate field from a st{bhw}s instruction. */
235 
236 static int
237 extract_5_store (unsigned word)
238 {
239  return low_sign_extend (word & MASK_5, 5);
240 }
241 
242 /* Extract the immediate field from a break instruction. */
243 
244 static unsigned
245 extract_5r_store (unsigned word)
246 {
247  return (word & MASK_5);
248 }
249 
250 /* Extract the immediate field from a {sr}sm instruction. */
251 
252 static unsigned
253 extract_5R_store (unsigned word)
254 {
255  return (word >> 16 & MASK_5);
256 }
257 
258 /* Extract the 10 bit immediate field from a {sr}sm instruction. */
259 
260 static unsigned
261 extract_10U_store (unsigned word)
262 {
263  return (word >> 16 & MASK_10);
264 }
265 
266 /* Extract the immediate field from a bb instruction. */
267 
268 static unsigned
269 extract_5Q_store (unsigned word)
270 {
271  return (word >> 21 & MASK_5);
272 }
273 
274 /* Extract an 11 bit immediate field. */
275 
276 static int
277 extract_11 (unsigned word)
278 {
279  return low_sign_extend (word & MASK_11, 11);
280 }
281 
282 /* Extract a 14 bit immediate field. */
283 
284 static int
285 extract_14 (unsigned word)
286 {
287  return low_sign_extend (word & MASK_14, 14);
288 }
289 
290 /* Extract a 16 bit immediate field (PA2.0 wide only). */
291 
292 static int
293 extract_16 (unsigned word)
294 {
295  int m15, m0, m1;
296 
297  m0 = GET_BIT (word, 16);
298  m1 = GET_BIT (word, 17);
299  m15 = GET_BIT (word, 31);
300  word = (word >> 1) & 0x1fff;
301  word = word | (m15 << 15) | ((m15 ^ m0) << 14) | ((m15 ^ m1) << 13);
302  return sign_extend (word, 16);
303 }
304 
305 /* Extract a 21 bit constant. */
306 
307 static int
308 extract_21 (unsigned word)
309 {
310  int val;
311 
312  word &= MASK_21;
313  word <<= 11;
314  val = GET_FIELD (word, 20, 20);
315  val <<= 11;
316  val |= GET_FIELD (word, 9, 19);
317  val <<= 2;
318  val |= GET_FIELD (word, 5, 6);
319  val <<= 5;
320  val |= GET_FIELD (word, 0, 4);
321  val <<= 2;
322  val |= GET_FIELD (word, 7, 8);
323  return sign_extend (val, 21) << 11;
324 }
325 
326 /* Extract a 12 bit constant from branch instructions. */
327 
328 static int
329 extract_12 (unsigned word)
330 {
331  return sign_extend (GET_FIELD (word, 19, 28)
332  | GET_FIELD (word, 29, 29) << 10
333  | (word & 0x1) << 11, 12) << 2;
334 }
335 
336 /* Extract a 17 bit constant from branch instructions, returning the
337  19 bit signed value. */
338 
339 static int
340 extract_17 (unsigned word)
341 {
342  return sign_extend (GET_FIELD (word, 19, 28)
343  | GET_FIELD (word, 29, 29) << 10
344  | GET_FIELD (word, 11, 15) << 11
345  | (word & 0x1) << 16, 17) << 2;
346 }
347 
348 static int
349 extract_22 (unsigned word)
350 {
351  return sign_extend (GET_FIELD (word, 19, 28)
352  | GET_FIELD (word, 29, 29) << 10
353  | GET_FIELD (word, 11, 15) << 11
354  | GET_FIELD (word, 6, 10) << 16
355  | (word & 0x1) << 21, 22) << 2;
356 }
357 
358 /* Print one instruction. */
359 
360 int
362 {
363  bfd_byte buffer[4];
364  unsigned int insn, i;
365 
366  {
367  int status =
368  (*info->read_memory_func) (memaddr, buffer, sizeof (buffer), info);
369  if (status != 0)
370  {
371  (*info->memory_error_func) (status, memaddr, info);
372  return -1;
373  }
374  }
375 
376  insn = bfd_getb32 (buffer);
377 
378  for (i = 0; i < NUMOPCODES; ++i)
379  {
380  const struct pa_opcode *opcode = &pa_opcodes[i];
381 
382  if ((insn & opcode->mask) == opcode->match)
383  {
384  const char *s;
385 #ifndef BFD64
386  if (opcode->arch == pa20w)
387  continue;
388 #endif
389  (*info->fprintf_func) (info->stream, "%s", opcode->name);
390 
391  if (!strchr ("cfCY?-+nHNZFIuv{", opcode->args[0])) {
392  (*info->fprintf_func) (info->stream, " ");
393  }
394  for (s = opcode->args; *s != '\0'; ++s)
395  {
396  switch (*s)
397  {
398  case 'x':
399  fput_reg (GET_FIELD (insn, 11, 15), info);
400  break;
401  case 'a':
402  case 'b':
403  fput_reg (GET_FIELD (insn, 6, 10), info);
404  break;
405  case '^':
406  fput_creg (GET_FIELD (insn, 6, 10), info);
407  break;
408  case 't':
409  fput_reg (GET_FIELD (insn, 27, 31), info);
410  break;
411 
412  /* Handle floating point registers. */
413  case 'f':
414  switch (*++s)
415  {
416  case 't':
417  fput_fp_reg (GET_FIELD (insn, 27, 31), info);
418  break;
419  case 'T':
420  if (GET_FIELD (insn, 25, 25)) {
421  fput_fp_reg_r (GET_FIELD (insn, 27, 31), info);
422  } else {
423  fput_fp_reg (GET_FIELD (insn, 27, 31), info);
424  }
425  break;
426  case 'a':
427  if (GET_FIELD (insn, 25, 25)) {
428  fput_fp_reg_r (GET_FIELD (insn, 6, 10), info);
429  } else {
430  fput_fp_reg (GET_FIELD (insn, 6, 10), info);
431  }
432  break;
433 
434  /* 'fA' will not generate a space before the register
435  name. Normally that is fine. Except that it
436  causes problems with xmpyu which has no FP format
437  completer. */
438  case 'X':
439  fputs_filtered (" ", info);
440  /* FALLTHRU */
441 
442  case 'A':
443  if (GET_FIELD (insn, 24, 24)) {
444  fput_fp_reg_r (GET_FIELD (insn, 6, 10), info);
445  } else {
446  fput_fp_reg (GET_FIELD (insn, 6, 10), info);
447  }
448  break;
449  case 'b':
450  if (GET_FIELD (insn, 25, 25)) {
451  fput_fp_reg_r (GET_FIELD (insn, 11, 15), info);
452  } else {
453  fput_fp_reg (GET_FIELD (insn, 11, 15), info);
454  }
455  break;
456  case 'B':
457  if (GET_FIELD (insn, 19, 19)) {
458  fput_fp_reg_r (GET_FIELD (insn, 11, 15), info);
459  } else {
460  fput_fp_reg (GET_FIELD (insn, 11, 15), info);
461  }
462  break;
463  case 'C':
464  {
465  int reg = GET_FIELD (insn, 21, 22);
466  reg |= GET_FIELD (insn, 16, 18) << 2;
467  if (GET_FIELD (insn, 23, 23) != 0) {
469  } else {
470  fput_fp_reg (reg, info);
471  }
472  break;
473  }
474  case 'i':
475  {
476  int reg = GET_FIELD (insn, 6, 10);
477 
478  reg |= (GET_FIELD (insn, 26, 26) << 4);
479  fput_fp_reg (reg, info);
480  break;
481  }
482  case 'j':
483  {
484  int reg = GET_FIELD (insn, 11, 15);
485 
486  reg |= (GET_FIELD (insn, 26, 26) << 4);
487  fput_fp_reg (reg, info);
488  break;
489  }
490  case 'k':
491  {
492  int reg = GET_FIELD (insn, 27, 31);
493 
494  reg |= (GET_FIELD (insn, 26, 26) << 4);
495  fput_fp_reg (reg, info);
496  break;
497  }
498  case 'l':
499  {
500  int reg = GET_FIELD (insn, 21, 25);
501 
502  reg |= (GET_FIELD (insn, 26, 26) << 4);
503  fput_fp_reg (reg, info);
504  break;
505  }
506  case 'm':
507  {
508  int reg = GET_FIELD (insn, 16, 20);
509 
510  reg |= (GET_FIELD (insn, 26, 26) << 4);
511  fput_fp_reg (reg, info);
512  break;
513  }
514 
515  /* 'fe' will not generate a space before the register
516  name. Normally that is fine. Except that it
517  causes problems with fstw fe,y(b) which has no FP
518  format completer. */
519  case 'E':
520  fputs_filtered (" ", info);
521  /* FALLTHRU */
522 
523  case 'e':
524  if (GET_FIELD (insn, 30, 30)) {
525  fput_fp_reg_r (GET_FIELD (insn, 11, 15), info);
526  } else {
527  fput_fp_reg (GET_FIELD (insn, 11, 15), info);
528  }
529  break;
530  case 'x':
531  fput_fp_reg (GET_FIELD (insn, 11, 15), info);
532  break;
533  }
534  break;
535 
536  case '5':
537  fput_const (extract_5_load (insn), info);
538  break;
539  case 's':
540  {
541  int space = GET_FIELD (insn, 16, 17);
542  /* Zero means implicit addressing, not use of sr0. */
543  if (space != 0) {
544  (*info->fprintf_func) (info->stream, "sr%d", space);
545  }
546  }
547  break;
548 
549  case 'S':
550  (*info->fprintf_func) (info->stream, "sr%d",
551  extract_3 (insn));
552  break;
553 
554  /* Handle completers. */
555  case 'c':
556  switch (*++s)
557  {
558  case 'x':
559  (*info->fprintf_func)
560  (info->stream, "%s",
561  index_compl_names[GET_COMPL (insn)]);
562  break;
563  case 'X':
564  (*info->fprintf_func)
565  (info->stream, "%s ",
566  index_compl_names[GET_COMPL (insn)]);
567  break;
568  case 'm':
569  (*info->fprintf_func)
570  (info->stream, "%s",
572  break;
573  case 'M':
574  (*info->fprintf_func)
575  (info->stream, "%s ",
577  break;
578  case 'A':
579  (*info->fprintf_func)
580  (info->stream, "%s ",
582  break;
583  case 's':
584  (*info->fprintf_func)
585  (info->stream, "%s",
587  break;
588  case 'c':
589  case 'C':
590  switch (GET_FIELD (insn, 20, 21))
591  {
592  case 1:
593  (*info->fprintf_func) (info->stream, ",bc ");
594  break;
595  case 2:
596  (*info->fprintf_func) (info->stream, ",sl ");
597  break;
598  default:
599  (*info->fprintf_func) (info->stream, " ");
600  }
601  break;
602  case 'd':
603  switch (GET_FIELD (insn, 20, 21))
604  {
605  case 1:
606  (*info->fprintf_func) (info->stream, ",co ");
607  break;
608  default:
609  (*info->fprintf_func) (info->stream, " ");
610  }
611  break;
612  case 'o':
613  (*info->fprintf_func) (info->stream, ",o");
614  break;
615  case 'g':
616  (*info->fprintf_func) (info->stream, ",gate");
617  break;
618  case 'p':
619  (*info->fprintf_func) (info->stream, ",l,push");
620  break;
621  case 'P':
622  (*info->fprintf_func) (info->stream, ",pop");
623  break;
624  case 'l':
625  case 'L':
626  (*info->fprintf_func) (info->stream, ",l");
627  break;
628  case 'w':
629  (*info->fprintf_func)
630  (info->stream, "%s ",
631  read_write_names[GET_FIELD (insn, 25, 25)]);
632  break;
633  case 'W':
634  (*info->fprintf_func) (info->stream, ",w ");
635  break;
636  case 'r':
637  if (GET_FIELD (insn, 23, 26) == 5) {
638  (*info->fprintf_func) (info->stream, ",r");
639  }
640  break;
641  case 'Z':
642  if (GET_FIELD (insn, 26, 26)) {
643  (*info->fprintf_func) (info->stream, ",m ");
644  } else {
645  (*info->fprintf_func) (info->stream, " ");
646  }
647  break;
648  case 'i':
649  if (GET_FIELD (insn, 25, 25)) {
650  (*info->fprintf_func) (info->stream, ",i");
651  }
652  break;
653  case 'z':
654  if (!GET_FIELD (insn, 21, 21)) {
655  (*info->fprintf_func) (info->stream, ",z");
656  }
657  break;
658  case 'a':
659  (*info->fprintf_func)
660  (info->stream, "%s",
661  add_compl_names[GET_FIELD (insn, 20, 21)]);
662  break;
663  case 'Y':
664  (*info->fprintf_func)
665  (info->stream, ",dc%s",
666  add_compl_names[GET_FIELD (insn, 20, 21)]);
667  break;
668  case 'y':
669  (*info->fprintf_func)
670  (info->stream, ",c%s",
671  add_compl_names[GET_FIELD (insn, 20, 21)]);
672  break;
673  case 'v':
674  if (GET_FIELD (insn, 20, 20)) {
675  (*info->fprintf_func) (info->stream, ",tsv");
676  }
677  break;
678  case 't':
679  (*info->fprintf_func) (info->stream, ",tc");
680  if (GET_FIELD (insn, 20, 20)) {
681  (*info->fprintf_func) (info->stream, ",tsv");
682  }
683  break;
684  case 'B':
685  (*info->fprintf_func) (info->stream, ",db");
686  if (GET_FIELD (insn, 20, 20)) {
687  (*info->fprintf_func) (info->stream, ",tsv");
688  }
689  break;
690  case 'b':
691  (*info->fprintf_func) (info->stream, ",b");
692  if (GET_FIELD (insn, 20, 20)) {
693  (*info->fprintf_func) (info->stream, ",tsv");
694  }
695  break;
696  case 'T':
697  if (GET_FIELD (insn, 25, 25)) {
698  (*info->fprintf_func) (info->stream, ",tc");
699  }
700  break;
701  case 'S':
702  /* EXTRD/W has a following condition. */
703  if (*(s + 1) == '?') {
704  (*info->fprintf_func) (info->stream, "%s",
705  signed_unsigned_names[GET_FIELD (insn, 21, 21)]);
706  } else {
707  (*info->fprintf_func) (info->stream, "%s ",
708  signed_unsigned_names[GET_FIELD (insn, 21, 21)]);
709  }
710  break;
711  case 'h':
712  (*info->fprintf_func)
713  (info->stream, "%s",
714  mix_half_names[GET_FIELD (insn, 17, 17)]);
715  break;
716  case 'H':
717  (*info->fprintf_func)
718  (info->stream, "%s ",
719  saturation_names[GET_FIELD (insn, 24, 25)]);
720  break;
721  case '*':
722  (*info->fprintf_func)
723  (info->stream, ",%d%d%d%d ",
724  GET_FIELD (insn, 17, 18), GET_FIELD (insn, 20, 21),
725  GET_FIELD (insn, 22, 23), GET_FIELD (insn, 24, 25));
726  break;
727 
728  case 'q':
729  {
730  int m, a;
731 
732  m = GET_FIELD (insn, 28, 28);
733  a = GET_FIELD (insn, 29, 29);
734 
735  if (m && !a) {
736  fputs_filtered (",ma ", info);
737  } else if (m && a) {
738  fputs_filtered (",mb ", info);
739  } else {
740  fputs_filtered (" ", info);
741  }
742  break;
743  }
744 
745  case 'J':
746  {
747  int opc = GET_FIELD (insn, 0, 5);
748 
749  if (opc == 0x16 || opc == 0x1e)
750  {
751  if (GET_FIELD (insn, 29, 29) == 0) {
752  fputs_filtered (",ma ", info);
753  } else {
754  fputs_filtered (",mb ", info);
755  }
756  } else {
757  fputs_filtered (" ", info);
758  }
759  break;
760  }
761 
762  case 'e':
763  {
764  int opc = GET_FIELD (insn, 0, 5);
765 
766  if (opc == 0x13 || opc == 0x1b)
767  {
768  if (GET_FIELD (insn, 18, 18) == 1) {
769  fputs_filtered (",mb ", info);
770  } else {
771  fputs_filtered (",ma ", info);
772  }
773  }
774  else if (opc == 0x17 || opc == 0x1f)
775  {
776  if (GET_FIELD (insn, 31, 31) == 1) {
777  fputs_filtered (",ma ", info);
778  } else {
779  fputs_filtered (",mb ", info);
780  }
781  } else {
782  fputs_filtered (" ", info);
783  }
784 
785  break;
786  }
787  }
788  break;
789 
790  /* Handle conditions. */
791  case '?':
792  {
793  s++;
794  switch (*s)
795  {
796  case 'f':
797  (*info->fprintf_func)
798  (info->stream, "%s ",
799  float_comp_names[GET_FIELD (insn, 27, 31)]);
800  break;
801 
802  /* These four conditions are for the set of instructions
803  which distinguish true/false conditions by opcode
804  rather than by the 'f' bit (sigh): comb, comib,
805  addb, addib. */
806  case 't':
808  (compare_cond_names[GET_FIELD (insn, 16, 18)], info);
809  break;
810  case 'n':
812  (compare_cond_names[GET_FIELD (insn, 16, 18)
813  + GET_FIELD (insn, 4, 4) * 8],
814  info);
815  break;
816  case 'N':
818  (compare_cond_64_names[GET_FIELD (insn, 16, 18)
819  + GET_FIELD (insn, 2, 2) * 8],
820  info);
821  break;
822  case 'Q':
824  (cmpib_cond_64_names[GET_FIELD (insn, 16, 18)],
825  info);
826  break;
827  case '@':
829  (add_cond_names[GET_FIELD (insn, 16, 18)
830  + GET_FIELD (insn, 4, 4) * 8],
831  info);
832  break;
833  case 's':
834  (*info->fprintf_func)
835  (info->stream, "%s ",
836  compare_cond_names[GET_COND (insn)]);
837  break;
838  case 'S':
839  (*info->fprintf_func)
840  (info->stream, "%s ",
842  break;
843  case 'a':
844  (*info->fprintf_func)
845  (info->stream, "%s ",
846  add_cond_names[GET_COND (insn)]);
847  break;
848  case 'A':
849  (*info->fprintf_func)
850  (info->stream, "%s ",
851  add_cond_64_names[GET_COND (insn)]);
852  break;
853  case 'd':
854  (*info->fprintf_func)
855  (info->stream, "%s",
856  add_cond_names[GET_FIELD (insn, 16, 18)]);
857  break;
858 
859  case 'W':
860  (*info->fprintf_func)
861  (info->stream, "%s",
862  wide_add_cond_names[GET_FIELD (insn, 16, 18) +
863  GET_FIELD (insn, 4, 4) * 8]);
864  break;
865 
866  case 'l':
867  (*info->fprintf_func)
868  (info->stream, "%s ",
869  logical_cond_names[GET_COND (insn)]);
870  break;
871  case 'L':
872  (*info->fprintf_func)
873  (info->stream, "%s ",
875  break;
876  case 'u':
877  (*info->fprintf_func)
878  (info->stream, "%s ",
879  unit_cond_names[GET_COND (insn)]);
880  break;
881  case 'U':
882  (*info->fprintf_func)
883  (info->stream, "%s ",
884  unit_cond_64_names[GET_COND (insn)]);
885  break;
886  case 'y':
887  case 'x':
888  case 'b':
889  (*info->fprintf_func)
890  (info->stream, "%s",
891  shift_cond_names[GET_FIELD (insn, 16, 18)]);
892 
893  /* If the next character in args is 'n', it will handle
894  putting out the space. */
895  if (s[1] != 'n') {
896  (*info->fprintf_func) (info->stream, " ");
897  }
898  break;
899  case 'X':
900  (*info->fprintf_func)
901  (info->stream, "%s ",
902  shift_cond_64_names[GET_FIELD (insn, 16, 18)]);
903  break;
904  case 'B':
905  (*info->fprintf_func)
906  (info->stream, "%s",
907  bb_cond_64_names[GET_FIELD (insn, 16, 16)]);
908 
909  /* If the next character in args is 'n', it will handle
910  putting out the space. */
911  if (s[1] != 'n') {
912  (*info->fprintf_func) (info->stream, " ");
913  }
914  break;
915  }
916  break;
917  }
918 
919  case 'V':
920  fput_const (extract_5_store (insn), info);
921  break;
922  case 'r':
923  fput_const (extract_5r_store (insn), info);
924  break;
925  case 'R':
926  fput_const (extract_5R_store (insn), info);
927  break;
928  case 'U':
930  break;
931  case 'B':
932  case 'Q':
933  fput_const (extract_5Q_store (insn), info);
934  break;
935  case 'i':
936  fput_const (extract_11 (insn), info);
937  break;
938  case 'j':
939  fput_const (extract_14 (insn), info);
940  break;
941  case 'k':
942  fputs_filtered ("L%", info);
943  fput_const (extract_21 (insn), info);
944  break;
945  case '<':
946  case 'l':
947  /* 16-bit long disp., PA2.0 wide only. */
948  fput_const (extract_16 (insn), info);
949  break;
950  case 'n':
951  if (insn & 0x2) {
952  (*info->fprintf_func) (info->stream, ",n ");
953  } else {
954  (*info->fprintf_func) (info->stream, " ");
955  }
956  break;
957  case 'N':
958  if ((insn & 0x20) && s[1]) {
959  (*info->fprintf_func) (info->stream, ",n ");
960  } else if (insn & 0x20) {
961  (*info->fprintf_func) (info->stream, ",n");
962  } else if (s[1]) {
963  (*info->fprintf_func) (info->stream, " ");
964  }
965  break;
966  case 'w':
967  (*info->print_address_func)
968  (memaddr + 8 + extract_12 (insn), info);
969  break;
970  case 'W':
971  /* 17 bit PC-relative branch. */
972  (*info->print_address_func)
973  ((memaddr + 8 + extract_17 (insn)), info);
974  break;
975  case 'z':
976  /* 17 bit displacement. This is an offset from a register
977  so it gets disasssembled as just a number, not any sort
978  of address. */
979  fput_const (extract_17 (insn), info);
980  break;
981 
982  case 'Z':
983  /* addil %r1 implicit output. */
984  fputs_filtered ("r1", info);
985  break;
986 
987  case 'Y':
988  /* be,l %sr0,%r31 implicit output. */
989  fputs_filtered ("sr0,r31", info);
990  break;
991 
992  case '@':
993  (*info->fprintf_func) (info->stream, "0");
994  break;
995 
996  case '.':
997  (*info->fprintf_func) (info->stream, "%d",
998  GET_FIELD (insn, 24, 25));
999  break;
1000  case '*':
1001  (*info->fprintf_func) (info->stream, "%d",
1002  GET_FIELD (insn, 22, 25));
1003  break;
1004  case '!':
1005  fputs_filtered ("sar", info);
1006  break;
1007  case 'p':
1008  (*info->fprintf_func) (info->stream, "%d",
1009  31 - GET_FIELD (insn, 22, 26));
1010  break;
1011  case '~':
1012  {
1013  int num;
1014  num = GET_FIELD (insn, 20, 20) << 5;
1015  num |= GET_FIELD (insn, 22, 26);
1016  (*info->fprintf_func) (info->stream, "%d", 63 - num);
1017  break;
1018  }
1019  case 'P':
1020  (*info->fprintf_func) (info->stream, "%d",
1021  GET_FIELD (insn, 22, 26));
1022  break;
1023  case 'q':
1024  {
1025  int num;
1026  num = GET_FIELD (insn, 20, 20) << 5;
1027  num |= GET_FIELD (insn, 22, 26);
1028  (*info->fprintf_func) (info->stream, "%d", num);
1029  break;
1030  }
1031  case 'T':
1032  (*info->fprintf_func) (info->stream, "%d",
1033  32 - GET_FIELD (insn, 27, 31));
1034  break;
1035  case '%':
1036  {
1037  int num;
1038  num = (GET_FIELD (insn, 23, 23) + 1) * 32;
1039  num -= GET_FIELD (insn, 27, 31);
1040  (*info->fprintf_func) (info->stream, "%d", num);
1041  break;
1042  }
1043  case '|':
1044  {
1045  int num;
1046  num = (GET_FIELD (insn, 19, 19) + 1) * 32;
1047  num -= GET_FIELD (insn, 27, 31);
1048  (*info->fprintf_func) (info->stream, "%d", num);
1049  break;
1050  }
1051  case '$':
1052  fput_const (GET_FIELD (insn, 20, 28), info);
1053  break;
1054  case 'A':
1055  fput_const (GET_FIELD (insn, 6, 18), info);
1056  break;
1057  case 'D':
1058  fput_const (GET_FIELD (insn, 6, 31), info);
1059  break;
1060  case 'v':
1061  (*info->fprintf_func) (info->stream, ",%d",
1062  GET_FIELD (insn, 23, 25));
1063  break;
1064  case 'O':
1065  fput_const ((GET_FIELD (insn, 6,20) << 5 |
1066  GET_FIELD (insn, 27, 31)), info);
1067  break;
1068  case 'o':
1069  fput_const (GET_FIELD (insn, 6, 20), info);
1070  break;
1071  case '2':
1072  fput_const ((GET_FIELD (insn, 6, 22) << 5 |
1073  GET_FIELD (insn, 27, 31)), info);
1074  break;
1075  case '1':
1076  fput_const ((GET_FIELD (insn, 11, 20) << 5 |
1077  GET_FIELD (insn, 27, 31)), info);
1078  break;
1079  case '0':
1080  fput_const ((GET_FIELD (insn, 16, 20) << 5 |
1081  GET_FIELD (insn, 27, 31)), info);
1082  break;
1083  case 'u':
1084  (*info->fprintf_func) (info->stream, ",%d",
1085  GET_FIELD (insn, 23, 25));
1086  break;
1087  case 'F':
1088  /* If no destination completer and not before a completer
1089  for fcmp, need a space here. */
1090  if (s[1] == 'G' || s[1] == '?') {
1091  fputs_filtered (float_format_names[GET_FIELD (insn, 19, 20)], info);
1092  } else {
1093  (*info->fprintf_func) (info->stream, "%s ",
1094  float_format_names[GET_FIELD (insn, 19, 20)]);
1095  }
1096  break;
1097  case 'G':
1098  (*info->fprintf_func)
1099  (info->stream, "%s ",
1100  float_format_names[GET_FIELD (insn, 17, 18)]);
1101  break;
1102  case 'H':
1103  if (GET_FIELD (insn, 26, 26) == 1) {
1104  (*info->fprintf_func) (info->stream, "%s ",
1105  float_format_names[0]);
1106  } else {
1107  (*info->fprintf_func) (info->stream, "%s ",
1108  float_format_names[1]);
1109  }
1110  break;
1111  case 'I':
1112  /* If no destination completer and not before a completer
1113  for fcmp, need a space here. */
1114  if (s[1] == '?') {
1115  fputs_filtered (float_format_names[GET_FIELD (insn, 20, 20)], info);
1116  } else {
1117  (*info->fprintf_func) (info->stream, "%s ",
1118  float_format_names[GET_FIELD (insn, 20, 20)]);
1119  }
1120  break;
1121 
1122  case 'J':
1123  fput_const (extract_14 (insn), info);
1124  break;
1125 
1126  case '#':
1127  {
1128  int sign = GET_FIELD (insn, 31, 31);
1129  int imm10 = GET_FIELD (insn, 18, 27);
1130  int disp;
1131 
1132  if (sign) {
1133  disp = (UT64_MAX << 10) | imm10;
1134  } else {
1135  disp = imm10;
1136  }
1137 
1138  disp <<= 3;
1139  fput_const (disp, info);
1140  break;
1141  }
1142  case 'K':
1143  case 'd':
1144  {
1145  int sign = GET_FIELD (insn, 31, 31);
1146  int imm11 = GET_FIELD (insn, 18, 28);
1147  int disp;
1148 
1149  if (sign) {
1150  disp = (UT64_MAX << 11) | imm11;
1151  } else {
1152  disp = imm11;
1153  }
1154 
1155  disp <<= 2;
1156  fput_const (disp, info);
1157  break;
1158  }
1159 
1160  case '>':
1161  case 'y':
1162  {
1163  /* 16-bit long disp., PA2.0 wide only. */
1164  int disp = extract_16 (insn);
1165  disp &= ~3;
1166  fput_const (disp, info);
1167  break;
1168  }
1169 
1170  case '&':
1171  {
1172  /* 16-bit long disp., PA2.0 wide only. */
1173  int disp = extract_16 (insn);
1174  disp &= ~7;
1175  fput_const (disp, info);
1176  break;
1177  }
1178 
1179  case '_':
1180  break; /* Dealt with by '{' */
1181 
1182  case '{':
1183  {
1184  int sub = GET_FIELD (insn, 14, 16);
1185  int df = GET_FIELD (insn, 17, 18);
1186  int sf = GET_FIELD (insn, 19, 20);
1187  const char * const * source = float_format_names;
1188  const char * const * dest = float_format_names;
1189  char *t = "";
1190 
1191  if (sub == 4)
1192  {
1193  fputs_filtered (",UND ", info);
1194  break;
1195  }
1196  if ((sub & 3) == 3) {
1197  t = ",t";
1198  }
1199  if ((sub & 3) == 1) {
1201  }
1202  if (sub & 2) {
1203  dest = sub & 4 ? fcnv_ufixed_names : fcnv_fixed_names;
1204  }
1205 
1206  (*info->fprintf_func) (info->stream, "%s%s%s ",
1207  t, source[sf], dest[df]);
1208  break;
1209  }
1210 
1211  case 'm':
1212  {
1213  int y = GET_FIELD (insn, 16, 18);
1214 
1215  if (y != 1) {
1216  fput_const ((y ^ 1) - 1, info);
1217  }
1218  }
1219  break;
1220 
1221  case 'h':
1222  {
1223  int cbit;
1224 
1225  cbit = GET_FIELD (insn, 16, 18);
1226 
1227  if (cbit > 0) {
1228  (*info->fprintf_func) (info->stream, ",%d", cbit - 1);
1229  }
1230  break;
1231  }
1232 
1233  case '=':
1234  {
1235  int cond = GET_FIELD (insn, 27, 31);
1236 
1237  switch (cond)
1238  {
1239  case 0: fputs_filtered (" ", info); break;
1240  case 1: fputs_filtered ("acc ", info); break;
1241  case 2: fputs_filtered ("rej ", info); break;
1242  case 5: fputs_filtered ("acc8 ", info); break;
1243  case 6: fputs_filtered ("rej8 ", info); break;
1244  case 9: fputs_filtered ("acc6 ", info); break;
1245  case 13: fputs_filtered ("acc4 ", info); break;
1246  case 17: fputs_filtered ("acc2 ", info); break;
1247  default: break;
1248  }
1249  break;
1250  }
1251 
1252  case 'X':
1253  (*info->print_address_func)
1254  (memaddr + 8 + extract_22 (insn), info);
1255  break;
1256  case 'L':
1257  fputs_filtered (",rp", info);
1258  break;
1259  default:
1260  (*info->fprintf_func) (info->stream, "%c", *s);
1261  break;
1262  }
1263  }
1264  return sizeof (insn);
1265  }
1266  }
1267  (*info->fprintf_func) (info->stream, "#%8x", insn);
1268  return sizeof (insn);
1269 }
static void sign_extend(st32 *value, ut8 bit)
lzma_index ** i
Definition: index.h:629
ut16 val
Definition: armass64_const.h:6
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
static ut64 opc
Definition: desil.c:33
static unsigned extract_5R_store(unsigned word)
Definition: hppa-dis.c:253
static void fput_fp_reg_r(unsigned reg, disassemble_info *info)
Definition: hppa-dis.c:190
int print_insn_hppa(bfd_vma memaddr, disassemble_info *info)
Definition: hppa-dis.c:361
static const char *const control_reg[]
Definition: hppa-dis.c:74
static void fput_creg(unsigned reg, disassemble_info *info)
Definition: hppa-dis.c:201
static const char *const logical_cond_names[]
Definition: hppa-dis.c:112
static unsigned extract_10U_store(unsigned word)
Definition: hppa-dis.c:261
static int extract_5_store(unsigned word)
Definition: hppa-dis.c:237
static const char *const wide_add_cond_names[]
Definition: hppa-dis.c:107
static int extract_12(unsigned word)
Definition: hppa-dis.c:329
static const char *const compare_cond_64_names[]
Definition: hppa-dis.c:88
static const char *const short_ldst_compl_names[]
Definition: hppa-dis.c:143
static const char *const float_format_names[]
Definition: hppa-dis.c:148
static const char *const add_compl_names[]
Definition: hppa-dis.c:162
static int extract_5_load(unsigned word)
Definition: hppa-dis.c:229
static const char *const mix_half_names[]
Definition: hppa-dis.c:159
#define MASK_14
Definition: hppa-dis.c:59
static int extract_3(unsigned word)
Definition: hppa-dis.c:223
static const char *const logical_cond_64_names[]
Definition: hppa-dis.c:116
static const char *const reg_names[]
Definition: hppa-dis.c:33
#define GET_BIT(X, WHICH)
Definition: hppa-dis.c:68
#define MASK_11
Definition: hppa-dis.c:58
#define GET_FIELD(X, FROM, TO)
Definition: hppa-dis.c:65
static const char *const fp_reg_names[]
Definition: hppa-dis.c:43
static int extract_16(unsigned word)
Definition: hppa-dis.c:293
#define MASK_5
Definition: hppa-dis.c:56
static void fput_reg(unsigned reg, disassemble_info *info)
Definition: hppa-dis.c:178
static const char *const saturation_names[]
Definition: hppa-dis.c:160
static const char *const signed_unsigned_names[]
Definition: hppa-dis.c:158
static const char *const compare_cond_names[]
Definition: hppa-dis.c:83
static const char *const read_write_names[]
Definition: hppa-dis.c:161
static const char *const index_compl_names[]
Definition: hppa-dis.c:142
static const char *const fcnv_ufixed_names[]
Definition: hppa-dis.c:150
static const char *const fcnv_fixed_names[]
Definition: hppa-dis.c:149
#define MASK_21
Definition: hppa-dis.c:61
static const char *const add_cond_64_names[]
Definition: hppa-dis.c:102
static int extract_11(unsigned word)
Definition: hppa-dis.c:277
static int extract_21(unsigned word)
Definition: hppa-dis.c:308
static void fput_const(unsigned num, disassemble_info *info)
Definition: hppa-dis.c:209
static const char *const bb_cond_64_names[]
Definition: hppa-dis.c:138
static int extract_22(unsigned word)
Definition: hppa-dis.c:349
#define fputs_filtered(STR, F)
Definition: hppa-dis.c:175
#define GET_COND(insn)
Definition: hppa-dis.c:169
static int extract_17(unsigned word)
Definition: hppa-dis.c:340
static int extract_14(unsigned word)
Definition: hppa-dis.c:285
static const char *const unit_cond_names[]
Definition: hppa-dis.c:120
#define GET_COMPL(insn)
Definition: hppa-dis.c:166
static const char *const shift_cond_64_names[]
Definition: hppa-dis.c:134
static const char *const shift_cond_names[]
Definition: hppa-dis.c:130
static unsigned extract_5Q_store(unsigned word)
Definition: hppa-dis.c:269
static const char *const unit_cond_64_names[]
Definition: hppa-dis.c:125
static const char *const cmpib_cond_64_names[]
Definition: hppa-dis.c:93
unsigned int CORE_ADDR
Definition: hppa-dis.c:52
static void fput_fp_reg(unsigned reg, disassemble_info *info)
Definition: hppa-dis.c:184
static const char *const float_comp_names[]
Definition: hppa-dis.c:151
static const char *const short_bytes_compl_names[]
Definition: hppa-dis.c:144
static const char *const add_cond_names[]
Definition: hppa-dis.c:97
#define MASK_10
Definition: hppa-dis.c:57
static unsigned extract_5r_store(unsigned word)
Definition: hppa-dis.c:245
static const struct pa_opcode pa_opcodes[]
Definition: hppa.h:312
#define NUMOPCODES
Definition: hppa.h:1079
#define reg(n)
@ pa20w
Definition: libhppa.h:37
static int low_sign_extend(int, int) ATTRIBUTE_UNUSED
Definition: libhppa.h:187
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags void static offset const char static length static mode static who const char struct statfs static buf unsigned unsigned num
Definition: sflib.h:126
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
const char * source
Definition: lz4.h:699
char * dest
Definition: lz4.h:697
unsigned char bfd_byte
Definition: mybfd.h:176
BFD_HOST_U_64_BIT bfd_vma
Definition: mybfd.h:111
static bfd_vma bfd_getb32(const void *p)
Definition: mybfd.h:4979
static RzSocket * s
Definition: rtr.c:28
#define UT64_MAX
Definition: rz_types_base.h:86
#define a(i)
Definition: sha256.c:41
#define cond(bop, top, mask, flags)
Definition: buffer.h:15
Definition: hppa.h:43
enum pa_arch arch
Definition: hppa.h:48
char * args
Definition: hppa.h:47
unsigned long int mask
Definition: hppa.h:46
unsigned long int match
Definition: hppa.h:45
const char * name
Definition: hppa.h:44