Making disassembly much faster by moving string processing to only the
dump path.
This commit is contained in:
parent
d78f045123
commit
94e3e592dd
|
@ -58,7 +58,7 @@ XEDISASMR(bcctrx, 0x4C000420, 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) {
|
||||
name = "blr";
|
||||
}
|
||||
|
|
|
@ -17,6 +17,80 @@
|
|||
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() {
|
||||
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();
|
||||
special_registers.clear();
|
||||
access_bits.Clear();
|
||||
|
||||
this->name = name;
|
||||
this->info = info;
|
||||
this->flags = flags;
|
||||
|
||||
if (flags & InstrDisasm::kOE) {
|
||||
name += "o";
|
||||
InstrRegister i = {
|
||||
InstrRegister::kXER, 0, InstrRegister::kReadWrite
|
||||
};
|
||||
special_registers.push_back(i);
|
||||
}
|
||||
if (flags & InstrDisasm::kRc) {
|
||||
name += ".";
|
||||
InstrRegister i = {
|
||||
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);
|
||||
}
|
||||
if (flags & InstrDisasm::kLR) {
|
||||
name += "l";
|
||||
InstrRegister i = {
|
||||
InstrRegister::kLR, 0, InstrRegister::kWrite
|
||||
};
|
||||
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) {
|
||||
|
@ -204,106 +275,36 @@ void InstrDisasm::AddCR(uint32_t bf, InstrRegister::Access access) {
|
|||
|
||||
void InstrDisasm::AddRegOperand(
|
||||
InstrRegister::RegisterSet set, uint32_t ordinal,
|
||||
InstrRegister::Access access, std::string display) {
|
||||
InstrRegister::Access access, const char* display) {
|
||||
InstrRegister i = {
|
||||
set, ordinal, access
|
||||
};
|
||||
InstrOperand o;
|
||||
o.type = InstrOperand::kRegister;
|
||||
o.reg = i;
|
||||
if (!display.size()) {
|
||||
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()));
|
||||
o.display = display;
|
||||
operands.push_back(o);
|
||||
}
|
||||
|
||||
void InstrDisasm::AddSImmOperand(uint64_t value, size_t width,
|
||||
std::string display) {
|
||||
const char* display) {
|
||||
InstrOperand o;
|
||||
o.type = InstrOperand::kImmediate;
|
||||
o.imm.is_signed = true;
|
||||
o.imm.value = value;
|
||||
o.imm.width = value;
|
||||
if (display.size()) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
o.display = display;
|
||||
operands.push_back(o);
|
||||
}
|
||||
|
||||
void InstrDisasm::AddUImmOperand(uint64_t value, size_t width,
|
||||
std::string display) {
|
||||
const char* display) {
|
||||
InstrOperand o;
|
||||
o.type = InstrOperand::kImmediate;
|
||||
o.imm.is_signed = false;
|
||||
o.imm.value = value;
|
||||
o.imm.width = value;
|
||||
if (display.size()) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
o.display = display;
|
||||
operands.push_back(o);
|
||||
}
|
||||
|
||||
|
@ -321,23 +322,33 @@ int InstrDisasm::Finish() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void InstrDisasm::Dump(std::string& str, size_t pad) {
|
||||
str = name;
|
||||
void InstrDisasm::Dump(std::string& out_str, size_t pad) {
|
||||
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 (pad && str.size() < pad) {
|
||||
str += std::string(pad - str.size(), ' ');
|
||||
if (pad && out_str.size() < pad) {
|
||||
out_str += std::string(pad - out_str.size(), ' ');
|
||||
}
|
||||
for (std::vector<InstrOperand>::iterator it = operands.begin();
|
||||
it != operands.end(); ++it) {
|
||||
str += it->display;
|
||||
|
||||
it->Dump(out_str);
|
||||
if (it + 1 != operands.end()) {
|
||||
str += ", ";
|
||||
out_str += ", ";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
InstrType* xe::cpu::ppc::GetInstrType(uint32_t code) {
|
||||
InstrType* slot = NULL;
|
||||
switch (code >> 26) {
|
||||
|
|
|
@ -238,6 +238,7 @@ typedef struct {
|
|||
};
|
||||
|
||||
OperandType type;
|
||||
const char* display;
|
||||
union {
|
||||
InstrRegister reg;
|
||||
struct {
|
||||
|
@ -246,7 +247,8 @@ typedef struct {
|
|||
size_t width;
|
||||
} imm;
|
||||
};
|
||||
char display[32];
|
||||
|
||||
void Dump(std::string& out_str);
|
||||
} InstrOperand;
|
||||
|
||||
|
||||
|
@ -278,23 +280,24 @@ public:
|
|||
kLR = 1 << 4,
|
||||
};
|
||||
|
||||
char name[16];
|
||||
char info[64];
|
||||
const char* name;
|
||||
const char* info;
|
||||
uint32_t flags;
|
||||
std::vector<InstrOperand> operands;
|
||||
std::vector<InstrRegister> special_registers;
|
||||
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 AddCTR(InstrRegister::Access access);
|
||||
void AddCR(uint32_t bf, InstrRegister::Access access);
|
||||
void AddRegOperand(InstrRegister::RegisterSet set, uint32_t ordinal,
|
||||
InstrRegister::Access access, std::string display = "");
|
||||
void AddSImmOperand(uint64_t value, size_t width, std::string display = "");
|
||||
void AddUImmOperand(uint64_t value, size_t width, std::string display = "");
|
||||
InstrRegister::Access access, const char* display = NULL);
|
||||
void AddSImmOperand(uint64_t value, size_t width, const char* display = NULL);
|
||||
void AddUImmOperand(uint64_t value, size_t width, const char* display = NULL);
|
||||
int Finish();
|
||||
|
||||
void Dump(std::string& str, size_t pad = 8);
|
||||
void Dump(std::string& out_str, size_t pad = 8);
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue