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) {
|
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";
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue