Utility to dump instruction translation counts.

This commit is contained in:
Ben Vanik 2015-01-11 00:44:17 -08:00
parent b6b27e621a
commit 5827f5f5d8
5 changed files with 37 additions and 23 deletions

View File

@ -122,6 +122,7 @@ int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, uint32_t flags) {
// TraceInvalidInstruction(i); // TraceInvalidInstruction(i);
continue; continue;
} }
++i.type->translation_count;
typedef int (*InstrEmitter)(PPCHIRBuilder& f, InstrData& i); typedef int (*InstrEmitter)(PPCHIRBuilder& f, InstrData& i);
InstrEmitter emit = (InstrEmitter)i.type->emit; InstrEmitter emit = (InstrEmitter)i.type->emit;

View File

@ -10,14 +10,30 @@
#include <alloy/frontend/ppc/ppc_instr.h> #include <alloy/frontend/ppc/ppc_instr.h>
#include <sstream> #include <sstream>
#include <vector>
#include <alloy/frontend/ppc/ppc_instr_tables.h> #include <alloy/frontend/ppc/ppc_instr_tables.h>
#include <alloy/string_buffer.h>
#include <poly/poly.h> #include <poly/poly.h>
namespace alloy { namespace alloy {
namespace frontend { namespace frontend {
namespace ppc { namespace ppc {
std::vector<InstrType*> all_instrs_;
void DumpAllInstrCounts() {
StringBuffer sb;
sb.Append("Instruction translation counts:\n");
for (auto instr_type : all_instrs_) {
if (instr_type->translation_count) {
sb.Append("%8d : %s\n", instr_type->translation_count, instr_type->name);
}
}
fprintf(stdout, sb.GetString());
fflush(stdout);
}
void InstrOperand::Dump(std::string& out_str) { void InstrOperand::Dump(std::string& out_str) {
if (display) { if (display) {
out_str += display; out_str += display;
@ -322,48 +338,39 @@ InstrType* GetInstrType(uint32_t code) {
switch (code >> 26) { switch (code >> 26) {
case 4: case 4:
// Opcode = 4, index = bits 10-0 (10) // Opcode = 4, index = bits 10-0 (10)
slot = slot = tables::instr_table_4[select_bits(code, 0, 10)];
alloy::frontend::ppc::tables::instr_table_4[select_bits(code, 0, 10)];
break; break;
case 19: case 19:
// Opcode = 19, index = bits 10-1 (10) // Opcode = 19, index = bits 10-1 (10)
slot = alloy::frontend::ppc::tables::instr_table_19[select_bits(code, 1, slot = tables::instr_table_19[select_bits(code, 1, 10)];
10)];
break; break;
case 30: case 30:
// Opcode = 30, index = bits 4-1 (4) // Opcode = 30, index = bits 4-1 (4)
// Special cased to an uber instruction. // Special cased to an uber instruction.
slot = slot = tables::instr_table_30[select_bits(code, 0, 0)];
alloy::frontend::ppc::tables::instr_table_30[select_bits(code, 0, 0)];
break; break;
case 31: case 31:
// Opcode = 31, index = bits 10-1 (10) // Opcode = 31, index = bits 10-1 (10)
slot = alloy::frontend::ppc::tables::instr_table_31[select_bits(code, 1, slot = tables::instr_table_31[select_bits(code, 1, 10)];
10)];
break; break;
case 58: case 58:
// Opcode = 58, index = bits 1-0 (2) // Opcode = 58, index = bits 1-0 (2)
slot = slot = tables::instr_table_58[select_bits(code, 0, 1)];
alloy::frontend::ppc::tables::instr_table_58[select_bits(code, 0, 1)];
break; break;
case 59: case 59:
// Opcode = 59, index = bits 5-1 (5) // Opcode = 59, index = bits 5-1 (5)
slot = slot = tables::instr_table_59[select_bits(code, 1, 5)];
alloy::frontend::ppc::tables::instr_table_59[select_bits(code, 1, 5)];
break; break;
case 62: case 62:
// Opcode = 62, index = bits 1-0 (2) // Opcode = 62, index = bits 1-0 (2)
slot = slot = tables::instr_table_62[select_bits(code, 0, 1)];
alloy::frontend::ppc::tables::instr_table_62[select_bits(code, 0, 1)];
break; break;
case 63: case 63:
// Opcode = 63, index = bits 10-1 (10) // Opcode = 63, index = bits 10-1 (10)
slot = alloy::frontend::ppc::tables::instr_table_63[select_bits(code, 1, slot = tables::instr_table_63[select_bits(code, 1, 10)];
10)];
break; break;
default: default:
slot = slot = tables::instr_table[select_bits(code, 26, 31)];
alloy::frontend::ppc::tables::instr_table[select_bits(code, 26, 31)];
break; break;
} }
if (slot && slot->opcode) { if (slot && slot->opcode) {
@ -372,9 +379,8 @@ InstrType* GetInstrType(uint32_t code) {
// Slow lookup via linear scan. // Slow lookup via linear scan.
// This is primarily due to laziness. It could be made fast like the others. // This is primarily due to laziness. It could be made fast like the others.
for (size_t n = 0; for (size_t n = 0; n < poly::countof(tables::instr_table_scan); n++) {
n < poly::countof(alloy::frontend::ppc::tables::instr_table_scan); n++) { slot = &(tables::instr_table_scan[n]);
slot = &(alloy::frontend::ppc::tables::instr_table_scan[n]);
if (slot->opcode == (code & slot->opcode_mask)) { if (slot->opcode == (code & slot->opcode_mask)) {
return slot; return slot;
} }
@ -389,6 +395,7 @@ int RegisterInstrEmit(uint32_t code, InstrEmitFn emit) {
if (!instr_type) { if (!instr_type) {
return 1; return 1;
} }
all_instrs_.push_back(instr_type);
assert_null(instr_type->emit); assert_null(instr_type->emit);
instr_type->emit = emit; instr_type->emit = emit;
return 0; return 0;

View File

@ -561,10 +561,12 @@ class InstrType {
uint32_t flags; // xe_ppc_instr_flag_e uint32_t flags; // xe_ppc_instr_flag_e
InstrDisasmFn disasm; InstrDisasmFn disasm;
char name[16]; char name[16];
uint32_t translation_count;
InstrEmitFn emit; InstrEmitFn emit;
}; };
void DumpAllInstrCounts();
InstrType* GetInstrType(uint32_t code); InstrType* GetInstrType(uint32_t code);
int RegisterInstrEmit(uint32_t code, InstrEmitFn emit); int RegisterInstrEmit(uint32_t code, InstrEmitFn emit);

View File

@ -127,7 +127,7 @@ static InstrType** instr_table_prep_63(InstrType* unprep, size_t unprep_count,
#define INSTRUCTION(name, opcode, format, type, disasm_fn, descr) \ #define INSTRUCTION(name, opcode, format, type, disasm_fn, descr) \
{ \ { \
opcode, 0, kXEPPCInstrFormat##format, kXEPPCInstrType##type, 0, \ opcode, 0, kXEPPCInstrFormat##format, kXEPPCInstrType##type, 0, \
Disasm_##disasm_fn, #name, \ Disasm_##disasm_fn, #name, 0, \
} }
#define FLAG(t) kXEPPCInstrFlag##t #define FLAG(t) kXEPPCInstrFlag##t
@ -844,7 +844,7 @@ static InstrType** instr_table = instr_table_prep(
#define SCAN_INSTRUCTION(name, opcode, format, type, disasm_fn, descr) \ #define SCAN_INSTRUCTION(name, opcode, format, type, disasm_fn, descr) \
{ \ { \
opcode, kXEPPCInstrMask##format, kXEPPCInstrFormat##format, \ opcode, kXEPPCInstrMask##format, kXEPPCInstrFormat##format, \
kXEPPCInstrType##type, 0, Disasm_##disasm_fn, #name, \ kXEPPCInstrType##type, 0, Disasm_##disasm_fn, #name, 0, \
} }
#define OP(x) ((((uint32_t)(x)) & 0x3f) << 26) #define OP(x) ((((uint32_t)(x)) & 0x3f) << 26)
#define VX128(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x3d0)) #define VX128(op, xop) (OP(op) | (((uint32_t)(xop)) & 0x3d0))

View File

@ -124,6 +124,10 @@ int PPCTranslator::Translate(FunctionInfo* symbol_info,
string_buffer_.Reset(); string_buffer_.Reset();
} }
if (false) {
alloy::frontend::ppc::DumpAllInstrCounts();
}
// Emit function. // Emit function.
uint32_t emit_flags = 0; uint32_t emit_flags = 0;
if (debug_info) { if (debug_info) {