Making disassembly much faster by moving string processing to only the

dump path.
This commit is contained in:
Ben Vanik 2013-05-19 19:32:55 -07:00
parent d78f045123
commit 94e3e592dd
3 changed files with 116 additions and 102 deletions

View File

@ -58,7 +58,7 @@ XEDISASMR(bcctrx, 0x4C000420, XL )(InstrData& i, InstrDisasm& d) {
} }
XEDISASMR(bclrx, 0x4C000020, XL )(InstrData& i, InstrDisasm& d) { XEDISASMR(bclrx, 0x4C000020, XL )(InstrData& i, InstrDisasm& d) {
std::string name = "bclr"; const char* name = "bclr";
if (i.code == 0x4E800020) { if (i.code == 0x4E800020) {
name = "blr"; name = "blr";
} }

View File

@ -17,6 +17,80 @@
using namespace xe::cpu::ppc; using namespace xe::cpu::ppc;
void InstrOperand::Dump(std::string& out_str) {
if (display) {
out_str += display;
return;
}
char buffer[32];
const size_t max_count = XECOUNT(buffer);
switch (type) {
case InstrOperand::kRegister:
switch (reg.set) {
case InstrRegister::kXER:
xesnprintfa(buffer, max_count, "XER");
break;
case InstrRegister::kLR:
xesnprintfa(buffer, max_count, "LR");
break;
case InstrRegister::kCTR:
xesnprintfa(buffer, max_count, "CTR");
break;
case InstrRegister::kCR:
xesnprintfa(buffer, max_count, "CR%d", reg.ordinal);
break;
case InstrRegister::kFPSCR:
xesnprintfa(buffer, max_count, "FPSCR");
break;
case InstrRegister::kGPR:
xesnprintfa(buffer, max_count, "r%d", reg.ordinal);
break;
case InstrRegister::kFPR:
xesnprintfa(buffer, max_count, "f%d", reg.ordinal);
break;
case InstrRegister::kVMX:
xesnprintfa(buffer, max_count, "v%d", reg.ordinal);
break;
}
break;
case InstrOperand::kImmediate:
switch (imm.width) {
case 1:
if (imm.is_signed) {
xesnprintfa(buffer, max_count, "%d", (int32_t)(int8_t)imm.value);
} else {
xesnprintfa(buffer, max_count, "0x%.2X", (uint8_t)imm.value);
}
break;
case 2:
if (imm.is_signed) {
xesnprintfa(buffer, max_count, "%d", (int32_t)(int16_t)imm.value);
} else {
xesnprintfa(buffer, max_count, "0x%.4X", (uint16_t)imm.value);
}
break;
case 4:
if (imm.is_signed) {
xesnprintfa(buffer, max_count, "%d", (int32_t)imm.value);
} else {
xesnprintfa(buffer, max_count, "0x%.8X", (uint32_t)imm.value);
}
break;
case 8:
if (imm.is_signed) {
xesnprintfa(buffer, max_count, "%lld", (int64_t)imm.value);
} else {
xesnprintfa(buffer, max_count, "0x%.16llX", imm.value);
}
break;
}
break;
}
out_str += buffer;
}
void InstrAccessBits::Clear() { void InstrAccessBits::Clear() {
spr = cr = gpr = fpr = 0; spr = cr = gpr = fpr = 0;
} }
@ -143,20 +217,22 @@ void InstrAccessBits::Dump(std::string& out_str) {
} }
void InstrDisasm::Init(std::string name, std::string info, uint32_t flags) { void InstrDisasm::Init(const char* name, const char* info, uint32_t flags) {
operands.clear(); operands.clear();
special_registers.clear(); special_registers.clear();
access_bits.Clear(); access_bits.Clear();
this->name = name;
this->info = info;
this->flags = flags;
if (flags & InstrDisasm::kOE) { if (flags & InstrDisasm::kOE) {
name += "o";
InstrRegister i = { InstrRegister i = {
InstrRegister::kXER, 0, InstrRegister::kReadWrite InstrRegister::kXER, 0, InstrRegister::kReadWrite
}; };
special_registers.push_back(i); special_registers.push_back(i);
} }
if (flags & InstrDisasm::kRc) { if (flags & InstrDisasm::kRc) {
name += ".";
InstrRegister i = { InstrRegister i = {
InstrRegister::kCR, 0, InstrRegister::kWrite InstrRegister::kCR, 0, InstrRegister::kWrite
}; };
@ -169,16 +245,11 @@ void InstrDisasm::Init(std::string name, std::string info, uint32_t flags) {
special_registers.push_back(i); special_registers.push_back(i);
} }
if (flags & InstrDisasm::kLR) { if (flags & InstrDisasm::kLR) {
name += "l";
InstrRegister i = { InstrRegister i = {
InstrRegister::kLR, 0, InstrRegister::kWrite InstrRegister::kLR, 0, InstrRegister::kWrite
}; };
special_registers.push_back(i); special_registers.push_back(i);
} }
XEIGNORE(xestrcpya(this->name, XECOUNT(this->name), name.c_str()));
XEIGNORE(xestrcpya(this->info, XECOUNT(this->info), info.c_str()));
} }
void InstrDisasm::AddLR(InstrRegister::Access access) { void InstrDisasm::AddLR(InstrRegister::Access access) {
@ -204,106 +275,36 @@ void InstrDisasm::AddCR(uint32_t bf, InstrRegister::Access access) {
void InstrDisasm::AddRegOperand( void InstrDisasm::AddRegOperand(
InstrRegister::RegisterSet set, uint32_t ordinal, InstrRegister::RegisterSet set, uint32_t ordinal,
InstrRegister::Access access, std::string display) { InstrRegister::Access access, const char* display) {
InstrRegister i = { InstrRegister i = {
set, ordinal, access set, ordinal, access
}; };
InstrOperand o; InstrOperand o;
o.type = InstrOperand::kRegister; o.type = InstrOperand::kRegister;
o.reg = i; o.reg = i;
if (!display.size()) { o.display = display;
std::stringstream display_out;
switch (set) {
case InstrRegister::kXER:
display_out << "XER";
break;
case InstrRegister::kLR:
display_out << "LR";
break;
case InstrRegister::kCTR:
display_out << "CTR";
break;
case InstrRegister::kCR:
display_out << "CR";
display_out << ordinal;
break;
case InstrRegister::kFPSCR:
display_out << "FPSCR";
break;
case InstrRegister::kGPR:
display_out << "r";
display_out << ordinal;
break;
case InstrRegister::kFPR:
display_out << "f";
display_out << ordinal;
break;
case InstrRegister::kVMX:
display_out << "v";
display_out << ordinal;
break;
}
display = display_out.str();
}
XEIGNORE(xestrcpya(o.display, XECOUNT(o.display), display.c_str()));
operands.push_back(o); operands.push_back(o);
} }
void InstrDisasm::AddSImmOperand(uint64_t value, size_t width, void InstrDisasm::AddSImmOperand(uint64_t value, size_t width,
std::string display) { const char* display) {
InstrOperand o; InstrOperand o;
o.type = InstrOperand::kImmediate; o.type = InstrOperand::kImmediate;
o.imm.is_signed = true; o.imm.is_signed = true;
o.imm.value = value; o.imm.value = value;
o.imm.width = value; o.imm.width = value;
if (display.size()) { o.display = display;
XEIGNORE(xestrcpya(o.display, XECOUNT(o.display), display.c_str()));
} else {
const size_t max_count = XECOUNT(o.display);
switch (width) {
case 1:
xesnprintfa(o.display, max_count, "%d", (int32_t)(int8_t)value);
break;
case 2:
xesnprintfa(o.display, max_count, "%d", (int32_t)(int16_t)value);
break;
case 4:
xesnprintfa(o.display, max_count, "%d", (int32_t)value);
break;
case 8:
xesnprintfa(o.display, max_count, "%lld", (int64_t)value);
break;
}
}
operands.push_back(o); operands.push_back(o);
} }
void InstrDisasm::AddUImmOperand(uint64_t value, size_t width, void InstrDisasm::AddUImmOperand(uint64_t value, size_t width,
std::string display) { const char* display) {
InstrOperand o; InstrOperand o;
o.type = InstrOperand::kImmediate; o.type = InstrOperand::kImmediate;
o.imm.is_signed = false; o.imm.is_signed = false;
o.imm.value = value; o.imm.value = value;
o.imm.width = value; o.imm.width = value;
if (display.size()) { o.display = display;
XEIGNORE(xestrcpya(o.display, XECOUNT(o.display), display.c_str()));
} else {
const size_t max_count = XECOUNT(o.display);
switch (width) {
case 1:
xesnprintfa(o.display, max_count, "0x%.2X", (uint8_t)value);
break;
case 2:
xesnprintfa(o.display, max_count, "0x%.4X", (uint16_t)value);
break;
case 4:
xesnprintfa(o.display, max_count, "0x%.8X", (uint32_t)value);
break;
case 8:
xesnprintfa(o.display, max_count, "0x%.16llX", value);
break;
}
}
operands.push_back(o); operands.push_back(o);
} }
@ -321,23 +322,33 @@ int InstrDisasm::Finish() {
return 0; return 0;
} }
void InstrDisasm::Dump(std::string& str, size_t pad) { void InstrDisasm::Dump(std::string& out_str, size_t pad) {
str = name; out_str = name;
if (flags & InstrDisasm::kOE) {
out_str += "o";
}
if (flags & InstrDisasm::kRc) {
out_str += ".";
}
if (flags & InstrDisasm::kLR) {
out_str += "l";
}
if (operands.size()) { if (operands.size()) {
if (pad && str.size() < pad) { if (pad && out_str.size() < pad) {
str += std::string(pad - str.size(), ' '); out_str += std::string(pad - out_str.size(), ' ');
} }
for (std::vector<InstrOperand>::iterator it = operands.begin(); for (std::vector<InstrOperand>::iterator it = operands.begin();
it != operands.end(); ++it) { it != operands.end(); ++it) {
str += it->display; it->Dump(out_str);
if (it + 1 != operands.end()) { if (it + 1 != operands.end()) {
str += ", "; out_str += ", ";
} }
} }
} }
} }
InstrType* xe::cpu::ppc::GetInstrType(uint32_t code) { InstrType* xe::cpu::ppc::GetInstrType(uint32_t code) {
InstrType* slot = NULL; InstrType* slot = NULL;
switch (code >> 26) { switch (code >> 26) {

View File

@ -238,6 +238,7 @@ typedef struct {
}; };
OperandType type; OperandType type;
const char* display;
union { union {
InstrRegister reg; InstrRegister reg;
struct { struct {
@ -246,7 +247,8 @@ typedef struct {
size_t width; size_t width;
} imm; } imm;
}; };
char display[32];
void Dump(std::string& out_str);
} InstrOperand; } InstrOperand;
@ -278,23 +280,24 @@ public:
kLR = 1 << 4, kLR = 1 << 4,
}; };
char name[16]; const char* name;
char info[64]; const char* info;
uint32_t flags;
std::vector<InstrOperand> operands; std::vector<InstrOperand> operands;
std::vector<InstrRegister> special_registers; std::vector<InstrRegister> special_registers;
InstrAccessBits access_bits; InstrAccessBits access_bits;
void Init(std::string name, std::string info, uint32_t flags); void Init(const char* name, const char* info, uint32_t flags);
void AddLR(InstrRegister::Access access); void AddLR(InstrRegister::Access access);
void AddCTR(InstrRegister::Access access); void AddCTR(InstrRegister::Access access);
void AddCR(uint32_t bf, InstrRegister::Access access); void AddCR(uint32_t bf, InstrRegister::Access access);
void AddRegOperand(InstrRegister::RegisterSet set, uint32_t ordinal, void AddRegOperand(InstrRegister::RegisterSet set, uint32_t ordinal,
InstrRegister::Access access, std::string display = ""); InstrRegister::Access access, const char* display = NULL);
void AddSImmOperand(uint64_t value, size_t width, std::string display = ""); void AddSImmOperand(uint64_t value, size_t width, const char* display = NULL);
void AddUImmOperand(uint64_t value, size_t width, std::string display = ""); void AddUImmOperand(uint64_t value, size_t width, const char* display = NULL);
int Finish(); int Finish();
void Dump(std::string& str, size_t pad = 8); void Dump(std::string& out_str, size_t pad = 8);
}; };