Line 776... |
Line 776... |
insn_or1k_opcode_0x32_get_op_hi(insn));
|
insn_or1k_opcode_0x32_get_op_hi(insn));
|
return 1;
|
return 1;
|
break;
|
break;
|
}
|
}
|
break;
|
break;
|
|
// The l.sx instructions'd rD is actually in the location rA is for
|
|
// every other instruction - so we specify has_rA, but really that's
|
|
// the rD, so it's l.sx imm(rA), rB
|
case 0x34:
|
case 0x34:
|
insn_props->insn_string="l.sd";
|
insn_props->insn_string="l.sd";
|
insn_props->insn_index=81;
|
insn_props->insn_index=81;
|
|
insn_props->has_rA = 1;
|
|
insn_props->has_rB = 1;
|
break;
|
break;
|
|
|
case 0x35:
|
case 0x35:
|
insn_props->insn_string="l.sw";
|
insn_props->insn_string="l.sw";
|
|
insn_props->has_rA = 1;
|
|
insn_props->has_rB = 1;
|
insn_props->has_split_imm = 1;
|
insn_props->has_split_imm = 1;
|
insn_props->insn_index=82;
|
insn_props->insn_index=82;
|
break;
|
break;
|
|
|
case 0x36:
|
case 0x36:
|
insn_props->insn_string="l.sb";
|
insn_props->insn_string="l.sb";
|
|
insn_props->has_rA = 1;
|
|
insn_props->has_rB = 1;
|
insn_props->has_split_imm = 1;
|
insn_props->has_split_imm = 1;
|
insn_props->insn_index=83;
|
insn_props->insn_index=83;
|
break;
|
break;
|
|
|
case 0x37:
|
case 0x37:
|
insn_props->insn_string="l.sh";
|
insn_props->insn_string="l.sh";
|
|
insn_props->has_rA = 1;
|
|
insn_props->has_rB = 1;
|
insn_props->has_split_imm = 1;
|
insn_props->has_split_imm = 1;
|
insn_props->insn_index=84;
|
insn_props->insn_index=84;
|
break;
|
break;
|
|
|
case 0x38:
|
case 0x38:
|
Line 999... |
Line 1009... |
}
|
}
|
|
|
return 0;
|
return 0;
|
}
|
}
|
|
|
|
// Function to track entire instructions, regardless of architecture
|
|
// Storage list:
|
|
// Format: [0] - binary copy of instruction
|
|
// [1] - occurrence count
|
|
uint32_t (*bin_insn_list)[2] = NULL;
|
|
int bin_insn_list_count = -1;
|
|
#define NUM_EXPECTED_UNIQUE_INSNS 50000
|
|
void record_bin_insn(uint32_t insn)
|
|
{
|
|
// Check if the array has been initialised yet
|
|
if (bin_insn_list_count == -1)
|
|
{
|
|
bin_insn_list = calloc((NUM_EXPECTED_UNIQUE_INSNS*2)*sizeof(uint32_t),1);
|
|
bin_insn_list_count = 0;
|
|
}
|
|
|
|
int list_check_itr;
|
|
// Go through the list, check if we've seen this one before
|
|
for(list_check_itr=0;list_check_itr<bin_insn_list_count;list_check_itr++)
|
|
if (bin_insn_list[list_check_itr][0] == insn)
|
|
{
|
|
// Seen it before, just increment count
|
|
bin_insn_list[list_check_itr][1]++;
|
|
return;
|
|
}
|
|
|
|
|
|
// If we're here, we've not seen this one before, it's new
|
|
|
|
// No room left in list to add new ones
|
|
if ( bin_insn_list_count == NUM_EXPECTED_UNIQUE_INSNS )
|
|
return;
|
|
|
|
// Add it to the list
|
|
bin_insn_list[bin_insn_list_count][0] = insn;
|
|
bin_insn_list[bin_insn_list_count][1] = 1;
|
|
|
|
bin_insn_list_count++;
|
|
|
|
// No room left in list to add new ones
|
|
if ( bin_insn_list_count == NUM_EXPECTED_UNIQUE_INSNS )
|
|
fprintf(stderr, "Warning: bin_insn_list[][] full (%d entries)\n",
|
|
NUM_EXPECTED_UNIQUE_INSNS);
|
|
|
|
|
|
}
|
|
|
// Entry point for statistics collection.
|
// Entry point for statistics collection.
|
// Passed binary copy of instruction, and pointer to properties struct
|
// Passed binary copy of instruction, and pointer to properties struct
|
// Each function that can collect staistics is called.
|
// Each function that can collect staistics is called.
|
void or1k_32_collect_stats(uint32_t insn,
|
void or1k_32_collect_stats(uint32_t insn,
|
struct or1k_32_instruction_properties * insn_props)
|
struct or1k_32_instruction_properties * insn_props,
|
|
int record_bin_insns)
|
{
|
{
|
// Add this instruction's occurrence to our data
|
// Add this instruction's occurrence to our data
|
insn_lists_add(insn, insn_props);
|
insn_lists_add(insn, insn_props);
|
|
|
// n-tuple groupings stats recording here!
|
// n-tuple groupings stats recording here!
|
Line 1018... |
Line 1075... |
int n;
|
int n;
|
for(n=2;n<OR1K_MAX_GROUPINGS_ANALYSIS+1;n++)
|
for(n=2;n<OR1K_MAX_GROUPINGS_ANALYSIS+1;n++)
|
insn_lists_group_add(n, insn_props);
|
insn_lists_group_add(n, insn_props);
|
}
|
}
|
|
|
// Finished adding to stats for this instruction
|
if (record_bin_insns)
|
|
record_bin_insn(insn);
|
|
|
|
// Finished adding to stats for this instruction
|
|
|
}
|
}
|
|
|
// Function to add entry to, or increment incidences of, value in the value list
|
// Function to add entry to, or increment incidences of, value in the value list
|
void or1k_add_in_list(struct or1k_value_list * list, int32_t value)
|
void or1k_add_in_list(struct or1k_value_list * list, int32_t value)
|
Line 1798... |
Line 1857... |
return;
|
return;
|
|
|
}
|
}
|
|
|
|
|
|
// Print out the top n seen entire instructions
|
|
void print_top_bin_insn(FILE * stream, int n)
|
|
{
|
|
int largest_indx = 0;
|
|
int bin_insn_list_itr;
|
|
|
|
// Copy the counts, so we can trash them as needed
|
|
int bin_insn_counts[NUM_EXPECTED_UNIQUE_INSNS];
|
|
|
|
// An instruction properties object
|
|
struct or1k_32_instruction_properties insn_props;
|
|
|
|
for(bin_insn_list_itr=0;bin_insn_list_itr<bin_insn_list_count;
|
|
bin_insn_list_itr++)
|
|
bin_insn_counts[bin_insn_list_itr] = bin_insn_list[bin_insn_list_itr][1];
|
|
|
|
#ifdef DISPLAY_STRING
|
|
fprintf(stream, "Top %d seen instructions\n", n);
|
|
fprintf(stream, "Saw %d unique instructions\n", bin_insn_list_count);
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
fprintf(stream, ",\n");
|
|
fprintf(stream,"\"Top %d instructions\",\n\"Total unique instructions\",%d\n",
|
|
n, bin_insn_list_count);
|
|
fprintf(stream,
|
|
"\"Instruction (bin)\",\"Dissassembly\",\"Occurrences\",\"Freq\"\n");
|
|
#endif
|
|
|
|
while (n--)
|
|
{
|
|
// Search for the largest count
|
|
for(bin_insn_list_itr=0;bin_insn_list_itr<bin_insn_list_count;
|
|
bin_insn_list_itr++)
|
|
largest_indx = (bin_insn_counts[bin_insn_list_itr] >
|
|
bin_insn_counts[largest_indx]) ?
|
|
bin_insn_list_itr : largest_indx;
|
|
|
|
// Gone through list, largest_indx is the biggest index
|
|
|
|
// Clear the instruction properties struct
|
|
memset(&insn_props, 0, sizeof(struct or1k_32_instruction_properties));
|
|
|
|
// Get the string for this instruction
|
|
or1k_32_analyse_insn(bin_insn_list[largest_indx][0], &insn_props);
|
|
|
|
// Print out the instruction
|
|
#ifdef DISPLAY_STRING
|
|
fprintf(stream, "Insn:\t0x%.8x\t%s",bin_insn_list[largest_indx][0],
|
|
insn_props.insn_string);
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
fprintf(stream, "\"0x%.8x\",\"%s",bin_insn_list[largest_indx][0],
|
|
insn_props.insn_string);
|
|
#endif
|
|
|
|
if (insn_props.has_jumptarg || insn_props.has_branchtarg)
|
|
#ifdef DISPLAY_STRING
|
|
fprintf(stream, " 0x%x", (bin_insn_list[largest_indx][0] & JUMPTARG_MASK) << 2 );
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
fprintf(stream, " 0x%x", (bin_insn_list[largest_indx][0] & JUMPTARG_MASK) << 2 );
|
|
#endif
|
|
|
|
|
|
if (insn_props.has_rD)
|
|
#ifdef DISPLAY_STRING
|
|
fprintf(stream, " r%d",
|
|
insn_or1k_32_rD(bin_insn_list[largest_indx][0]));
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
fprintf(stream, " r%d",
|
|
insn_or1k_32_rD(bin_insn_list[largest_indx][0]));
|
|
#endif
|
|
|
|
if (insn_props.has_rA)
|
|
#ifdef DISPLAY_STRING
|
|
fprintf(stream, " r%d",
|
|
insn_or1k_32_rA(bin_insn_list[largest_indx][0]));
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
fprintf(stream, " r%d",
|
|
insn_or1k_32_rA(bin_insn_list[largest_indx][0]));
|
|
#endif
|
|
|
|
if (insn_props.has_rB)
|
|
#ifdef DISPLAY_STRING
|
|
fprintf(stream, " r%d",
|
|
insn_or1k_32_rB(bin_insn_list[largest_indx][0]));
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
fprintf(stream, " r%d",
|
|
insn_or1k_32_rB(bin_insn_list[largest_indx][0]));
|
|
#endif
|
|
|
|
|
|
if (insn_props.has_imm)
|
|
#ifdef DISPLAY_STRING
|
|
fprintf(stream, " 0x%x",
|
|
insn_or1k_32_imm(bin_insn_list[largest_indx][0]));
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
fprintf(stream, " 0x%x",
|
|
insn_or1k_32_imm(bin_insn_list[largest_indx][0]));
|
|
#endif
|
|
|
|
if (insn_props.has_split_imm)
|
|
#ifdef DISPLAY_STRING
|
|
fprintf(stream, " 0x%x",
|
|
insn_or1k_32_split_imm(bin_insn_list[largest_indx][0]));
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
fprintf(stream, " 0x%x",
|
|
insn_or1k_32_split_imm(bin_insn_list[largest_indx][0]));
|
|
#endif
|
|
|
|
#ifdef DISPLAY_STRING
|
|
fprintf(stream, "\tcount:\t%d (%f%%)\n",bin_insn_list[largest_indx][1],
|
|
(float)((float)bin_insn_list[largest_indx][1])/
|
|
((float)num_seen_insns));
|
|
#endif
|
|
#ifdef DISPLAY_CSV
|
|
fprintf(stream, "\",%d,%f\n",bin_insn_list[largest_indx][1],
|
|
(float)((float)bin_insn_list[largest_indx][1])/
|
|
((float)num_seen_insns));
|
|
#endif
|
|
|
|
// Finished printing out its instruction
|
|
bin_insn_counts[largest_indx] = -1;
|
|
|
|
}
|
|
}
|
|
|
|
|
// Print out the stats relating to the sequences of instructions most
|
// Print out the stats relating to the sequences of instructions most
|
// common before seeing this instruction
|
// common before seeing this instruction
|
void or1k_32_generate_groupings_stats(struct or1k_insn_info *insn_info,
|
void or1k_32_generate_groupings_stats(struct or1k_insn_info *insn_info,
|
FILE * stream)
|
FILE * stream)
|
{
|
{
|
Line 1865... |
Line 2057... |
#ifdef DISPLAY_STRING
|
#ifdef DISPLAY_STRING
|
fprintf(stream, "Individual instruction frequency:\n");
|
fprintf(stream, "Individual instruction frequency:\n");
|
#endif
|
#endif
|
or1k_32_most_freq_insn(stream);
|
or1k_32_most_freq_insn(stream);
|
|
|
}
|
// If we did the binary instruction frequency counting, print it out
|
|
if (bin_insn_list_count != -1)
|
|
print_top_bin_insn(stream, 20);
|
|
|
|
}
|
|
|
|
|
|
|
// Free up all added instruction statistic tracking structs
|
// Free up all added instruction statistic tracking structs
|
void or1k_32_insn_lists_free(void)
|
void or1k_32_insn_lists_free(void)
|
Line 1880... |
Line 2075... |
for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++)
|
for(insn_index=0;insn_index<OR1K_32_MAX_INSNS;insn_index++)
|
{
|
{
|
if (or1k_32_insns[insn_index] != NULL)
|
if (or1k_32_insns[insn_index] != NULL)
|
free(or1k_32_insns[insn_index]);
|
free(or1k_32_insns[insn_index]);
|
}
|
}
|
|
|
|
if (bin_insn_list_count != -1)
|
|
free(bin_insn_list);
|
}
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|