|
Lines 27-32
Link Here
|
| 27 |
#include "opintl.h" |
27 |
#include "opintl.h" |
| 28 |
#include "opcode/ppc.h" |
28 |
#include "opcode/ppc.h" |
| 29 |
#include "libiberty.h" |
29 |
#include "libiberty.h" |
|
|
30 |
#include "hashtab.h" |
| 30 |
|
31 |
|
| 31 |
/* This file provides several disassembler functions, all of which use |
32 |
/* This file provides several disassembler functions, all of which use |
| 32 |
the disassembler interface defined in dis-asm.h. Several functions |
33 |
the disassembler interface defined in dis-asm.h. Several functions |
|
Lines 36-47
Link Here
|
| 36 |
static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int, |
37 |
static int print_insn_powerpc (bfd_vma, struct disassemble_info *, int, |
| 37 |
ppc_cpu_t); |
38 |
ppc_cpu_t); |
| 38 |
|
39 |
|
|
|
40 |
struct opcode_counter |
| 41 |
{ |
| 42 |
const struct powerpc_opcode *opcode; |
| 43 |
size_t count; |
| 44 |
}; |
| 45 |
|
| 46 |
static hashval_t |
| 47 |
hash_opcode_counter (const void *opcnt) |
| 48 |
{ |
| 49 |
const struct opcode_counter *oc = (const struct opcode_counter *)opcnt; |
| 50 |
return htab_hash_pointer (oc->opcode); |
| 51 |
} |
| 52 |
|
| 53 |
static int |
| 54 |
same_opcode_counter (const void *opcnt1, const void *opcnt2) |
| 55 |
{ |
| 56 |
const struct opcode_counter *oc1 = (const struct opcode_counter *)opcnt1; |
| 57 |
const struct opcode_counter *oc2 = (const struct opcode_counter *)opcnt2; |
| 58 |
return htab_eq_pointer (oc1->opcode, oc2->opcode); |
| 59 |
} |
| 60 |
|
| 39 |
struct dis_private |
61 |
struct dis_private |
| 40 |
{ |
62 |
{ |
| 41 |
/* Stash the result of parsing disassembler_options here. */ |
63 |
/* Stash the result of parsing disassembler_options here. */ |
| 42 |
ppc_cpu_t dialect; |
64 |
ppc_cpu_t dialect; |
|
|
65 |
|
| 66 |
/* Counters for encountered opcodes. */ |
| 67 |
htab_t histogram; |
| 43 |
}; |
68 |
}; |
| 44 |
|
69 |
|
|
|
70 |
static int |
| 71 |
increment_opcode_counter (struct disassemble_info *info, |
| 72 |
const struct powerpc_opcode *opcode) |
| 73 |
{ |
| 74 |
struct dis_private *priv = (struct dis_private *) (info->private_data); |
| 75 |
|
| 76 |
if (!priv->histogram) |
| 77 |
return 0; |
| 78 |
|
| 79 |
struct opcode_counter oc, *ocp; |
| 80 |
oc.opcode = opcode; |
| 81 |
|
| 82 |
void **ret = htab_find_slot (priv->histogram, &oc, INSERT); |
| 83 |
ocp = *ret; |
| 84 |
if (ocp == HTAB_EMPTY_ENTRY) |
| 85 |
{ |
| 86 |
*ret = ocp = calloc (sizeof (oc), 1); |
| 87 |
ocp->opcode = opcode; |
| 88 |
} |
| 89 |
|
| 90 |
ocp->count++; |
| 91 |
|
| 92 |
return 1; |
| 93 |
} |
| 94 |
|
| 45 |
#define POWERPC_DIALECT(INFO) \ |
95 |
#define POWERPC_DIALECT(INFO) \ |
| 46 |
(((struct dis_private *) ((INFO)->private_data))->dialect) |
96 |
(((struct dis_private *) ((INFO)->private_data))->dialect) |
| 47 |
|
97 |
|
|
Lines 381-386
powerpc_init_dialect (struct disassemble_info *info)
Link Here
|
| 381 |
dialect |= PPC_OPCODE_64; |
431 |
dialect |= PPC_OPCODE_64; |
| 382 |
else if ((new_cpu = ppc_parse_cpu (dialect, &sticky, opt)) != 0) |
432 |
else if ((new_cpu = ppc_parse_cpu (dialect, &sticky, opt)) != 0) |
| 383 |
dialect = new_cpu; |
433 |
dialect = new_cpu; |
|
|
434 |
else if (disassembler_options_cmp (opt, "histogram") == 0) |
| 435 |
priv->histogram = htab_create (17, |
| 436 |
hash_opcode_counter, |
| 437 |
same_opcode_counter, |
| 438 |
free); |
| 384 |
else |
439 |
else |
| 385 |
/* xgettext: c-format */ |
440 |
/* xgettext: c-format */ |
| 386 |
opcodes_error_handler (_("warning: ignoring unknown -M%s option"), opt); |
441 |
opcodes_error_handler (_("warning: ignoring unknown -M%s option"), opt); |
|
Lines 864-869
print_insn_powerpc (bfd_vma memaddr,
Link Here
|
| 864 |
bfd_boolean skip_optional; |
919 |
bfd_boolean skip_optional; |
| 865 |
int blanks; |
920 |
int blanks; |
| 866 |
|
921 |
|
|
|
922 |
increment_opcode_counter (info, opcode); |
| 923 |
|
| 867 |
(*info->fprintf_func) (info->stream, "%s", opcode->name); |
924 |
(*info->fprintf_func) (info->stream, "%s", opcode->name); |
| 868 |
/* gdb fprintf_func doesn't return count printed. */ |
925 |
/* gdb fprintf_func doesn't return count printed. */ |
| 869 |
blanks = 8 - strlen (opcode->name); |
926 |
blanks = 8 - strlen (opcode->name); |
|
Lines 1013-1015
the -M switch:\n"));
Link Here
|
| 1013 |
} |
1070 |
} |
| 1014 |
fprintf (stream, "\n"); |
1071 |
fprintf (stream, "\n"); |
| 1015 |
} |
1072 |
} |
|
|
1073 |
|
| 1074 |
static int |
| 1075 |
dump_opcode_histogram (void **ocp, void *info_) |
| 1076 |
{ |
| 1077 |
struct opcode_counter *oc = *ocp; |
| 1078 |
struct disassemble_info *info = info_; |
| 1079 |
|
| 1080 |
(*info->fprintf_func) (info->stream, "%8lu %s (%lx)\n", |
| 1081 |
(unsigned long)oc->count, |
| 1082 |
oc->opcode->name, |
| 1083 |
(unsigned long)oc->opcode->opcode); |
| 1084 |
|
| 1085 |
return 1; |
| 1086 |
} |
| 1087 |
|
| 1088 |
void ppc_disassemble_free_target (struct disassemble_info *info); |
| 1089 |
|
| 1090 |
void |
| 1091 |
ppc_disassemble_free_target (struct disassemble_info *info) |
| 1092 |
{ |
| 1093 |
struct dis_private *priv = (struct dis_private *) (info->private_data); |
| 1094 |
|
| 1095 |
if (priv->histogram) |
| 1096 |
{ |
| 1097 |
if (htab_elements (priv->histogram)) |
| 1098 |
{ |
| 1099 |
(*info->fprintf_func) (info->stream, "\n\nOpcode histogram\n"); |
| 1100 |
htab_traverse (priv->histogram, dump_opcode_histogram, info); |
| 1101 |
} |
| 1102 |
|
| 1103 |
htab_delete (priv->histogram); |
| 1104 |
priv->histogram = NULL; |
| 1105 |
} |
| 1106 |
|
| 1107 |
free (priv); |
| 1108 |
info->private_data = NULL; |
| 1109 |
} |