StringBuffer cleanup.
This commit is contained in:
parent
da6edbe1d7
commit
d816d80190
|
@ -32,11 +32,19 @@ void StringBuffer::Grow(size_t additional_length) {
|
|||
buffer_.reserve(new_capacity);
|
||||
}
|
||||
|
||||
void StringBuffer::Append(char c) {
|
||||
AppendBytes(reinterpret_cast<const uint8_t*>(&c), 1);
|
||||
}
|
||||
|
||||
void StringBuffer::Append(const char* value) {
|
||||
AppendBytes(reinterpret_cast<const uint8_t*>(value), std::strlen(value));
|
||||
}
|
||||
|
||||
void StringBuffer::Append(const std::string& value) {
|
||||
AppendBytes(reinterpret_cast<const uint8_t*>(value.data()), value.size());
|
||||
}
|
||||
|
||||
void StringBuffer::Append(const char* format, ...) {
|
||||
void StringBuffer::AppendFormat(const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
AppendVarargs(format, args);
|
||||
|
|
|
@ -25,8 +25,10 @@ class StringBuffer {
|
|||
|
||||
void Reset();
|
||||
|
||||
void Append(char c);
|
||||
void Append(const char* value);
|
||||
void Append(const std::string& value);
|
||||
void Append(const char* format, ...);
|
||||
void AppendFormat(const char* format, ...);
|
||||
void AppendVarargs(const char* format, va_list args);
|
||||
void AppendBytes(const uint8_t* buffer, size_t length);
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ void X64Assembler::DumpMachineCode(DebugInfo* debug_info, void* machine_code,
|
|||
if (map_entry->source_offset == prev_source_offset) {
|
||||
str->Append(" ");
|
||||
} else {
|
||||
str->Append("%.8X ", map_entry->source_offset);
|
||||
str->AppendFormat("%.8X ", map_entry->source_offset);
|
||||
prev_source_offset = map_entry->source_offset;
|
||||
}
|
||||
} else {
|
||||
|
@ -128,7 +128,7 @@ void X64Assembler::DumpMachineCode(DebugInfo* debug_info, void* machine_code,
|
|||
if (len == BE::UNKNOWN_OPCODE) {
|
||||
break;
|
||||
}
|
||||
str->Append("%p %s\n", disasm.EIP, disasm.CompleteInstr);
|
||||
str->AppendFormat("%p %s\n", disasm.EIP, disasm.CompleteInstr);
|
||||
disasm.EIP += len;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,113 +18,116 @@ namespace cpu {
|
|||
namespace frontend {
|
||||
|
||||
void Disasm_0(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s ???", i.type->name);
|
||||
str->AppendFormat("%-8s ???", i.type->name);
|
||||
}
|
||||
|
||||
void Disasm__(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s", i.type->name);
|
||||
str->AppendFormat("%-8s", i.type->name);
|
||||
}
|
||||
|
||||
void Disasm_X_FRT_FRB(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s f%d, f%d", i.X.Rc ? -7 : -8, i.type->name,
|
||||
i.X.Rc ? "." : "", i.X.RT, i.X.RB);
|
||||
str->AppendFormat("%*s%s f%d, f%d", i.X.Rc ? -7 : -8, i.type->name,
|
||||
i.X.Rc ? "." : "", i.X.RT, i.X.RB);
|
||||
}
|
||||
void Disasm_A_FRT_FRB(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s f%d, f%d", i.A.Rc ? -7 : -8, i.type->name,
|
||||
i.A.Rc ? "." : "", i.A.FRT, i.A.FRB);
|
||||
str->AppendFormat("%*s%s f%d, f%d", i.A.Rc ? -7 : -8, i.type->name,
|
||||
i.A.Rc ? "." : "", i.A.FRT, i.A.FRB);
|
||||
}
|
||||
void Disasm_A_FRT_FRA_FRB(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s f%d, f%d, f%d", i.A.Rc ? -7 : -8, i.type->name,
|
||||
i.A.Rc ? "." : "", i.A.FRT, i.A.FRA, i.A.FRB);
|
||||
str->AppendFormat("%*s%s f%d, f%d, f%d", i.A.Rc ? -7 : -8, i.type->name,
|
||||
i.A.Rc ? "." : "", i.A.FRT, i.A.FRA, i.A.FRB);
|
||||
}
|
||||
void Disasm_A_FRT_FRA_FRB_FRC(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s f%d, f%d, f%d, f%d", i.A.Rc ? -7 : -8, i.type->name,
|
||||
i.A.Rc ? "." : "", i.A.FRT, i.A.FRA, i.A.FRB, i.A.FRC);
|
||||
str->AppendFormat("%*s%s f%d, f%d, f%d, f%d", i.A.Rc ? -7 : -8, i.type->name,
|
||||
i.A.Rc ? "." : "", i.A.FRT, i.A.FRA, i.A.FRB, i.A.FRC);
|
||||
}
|
||||
void Disasm_X_RT_RA_RB(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s r%d, r%d, r%d", i.type->name, i.X.RT, i.X.RA, i.X.RB);
|
||||
str->AppendFormat("%-8s r%d, r%d, r%d", i.type->name, i.X.RT, i.X.RA, i.X.RB);
|
||||
}
|
||||
void Disasm_X_RT_RA0_RB(InstrData& i, StringBuffer* str) {
|
||||
if (i.X.RA) {
|
||||
str->Append("%-8s r%d, r%d, r%d", i.type->name, i.X.RT, i.X.RA, i.X.RB);
|
||||
str->AppendFormat("%-8s r%d, r%d, r%d", i.type->name, i.X.RT, i.X.RA,
|
||||
i.X.RB);
|
||||
} else {
|
||||
str->Append("%-8s r%d, 0, r%d", i.type->name, i.X.RT, i.X.RB);
|
||||
str->AppendFormat("%-8s r%d, 0, r%d", i.type->name, i.X.RT, i.X.RB);
|
||||
}
|
||||
}
|
||||
void Disasm_X_FRT_RA_RB(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s f%d, r%d, r%d", i.type->name, i.X.RT, i.X.RA, i.X.RB);
|
||||
str->AppendFormat("%-8s f%d, r%d, r%d", i.type->name, i.X.RT, i.X.RA, i.X.RB);
|
||||
}
|
||||
void Disasm_X_FRT_RA0_RB(InstrData& i, StringBuffer* str) {
|
||||
if (i.X.RA) {
|
||||
str->Append("%-8s f%d, r%d, r%d", i.type->name, i.X.RT, i.X.RA, i.X.RB);
|
||||
str->AppendFormat("%-8s f%d, r%d, r%d", i.type->name, i.X.RT, i.X.RA,
|
||||
i.X.RB);
|
||||
} else {
|
||||
str->Append("%-8s f%d, 0, r%d", i.type->name, i.X.RT, i.X.RB);
|
||||
str->AppendFormat("%-8s f%d, 0, r%d", i.type->name, i.X.RT, i.X.RB);
|
||||
}
|
||||
}
|
||||
void Disasm_D_RT_RA_I(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s r%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
str->AppendFormat("%-8s r%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
}
|
||||
void Disasm_D_RT_RA0_I(InstrData& i, StringBuffer* str) {
|
||||
if (i.D.RA) {
|
||||
str->Append("%-8s r%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
str->AppendFormat("%-8s r%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
} else {
|
||||
str->Append("%-8s r%d, 0, %d", i.type->name, i.D.RT,
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
str->AppendFormat("%-8s r%d, 0, %d", i.type->name, i.D.RT,
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
}
|
||||
}
|
||||
void Disasm_D_FRT_RA_I(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s f%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
str->AppendFormat("%-8s f%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
}
|
||||
void Disasm_D_FRT_RA0_I(InstrData& i, StringBuffer* str) {
|
||||
if (i.D.RA) {
|
||||
str->Append("%-8s f%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
str->AppendFormat("%-8s f%d, r%d, %d", i.type->name, i.D.RT, i.D.RA,
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
} else {
|
||||
str->Append("%-8s f%d, 0, %d", i.type->name, i.D.RT,
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
str->AppendFormat("%-8s f%d, 0, %d", i.type->name, i.D.RT,
|
||||
(int32_t)(int16_t) XEEXTS16(i.D.DS));
|
||||
}
|
||||
}
|
||||
void Disasm_DS_RT_RA_I(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s r%d, r%d, %d", i.type->name, i.DS.RT, i.DS.RA,
|
||||
(int32_t)(int16_t) XEEXTS16(i.DS.DS << 2));
|
||||
str->AppendFormat("%-8s r%d, r%d, %d", i.type->name, i.DS.RT, i.DS.RA,
|
||||
(int32_t)(int16_t) XEEXTS16(i.DS.DS << 2));
|
||||
}
|
||||
void Disasm_DS_RT_RA0_I(InstrData& i, StringBuffer* str) {
|
||||
if (i.DS.RA) {
|
||||
str->Append("%-8s r%d, r%d, %d", i.type->name, i.DS.RT, i.DS.RA,
|
||||
(int32_t)(int16_t) XEEXTS16(i.DS.DS << 2));
|
||||
str->AppendFormat("%-8s r%d, r%d, %d", i.type->name, i.DS.RT, i.DS.RA,
|
||||
(int32_t)(int16_t) XEEXTS16(i.DS.DS << 2));
|
||||
} else {
|
||||
str->Append("%-8s r%d, 0, %d", i.type->name, i.DS.RT,
|
||||
(int32_t)(int16_t) XEEXTS16(i.DS.DS << 2));
|
||||
str->AppendFormat("%-8s r%d, 0, %d", i.type->name, i.DS.RT,
|
||||
(int32_t)(int16_t) XEEXTS16(i.DS.DS << 2));
|
||||
}
|
||||
}
|
||||
void Disasm_D_RA(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s r%d", i.type->name, i.D.RA);
|
||||
str->AppendFormat("%-8s r%d", i.type->name, i.D.RA);
|
||||
}
|
||||
void Disasm_X_RA_RB(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s r%d, r%d", i.type->name, i.X.RA, i.X.RB);
|
||||
str->AppendFormat("%-8s r%d, r%d", i.type->name, i.X.RA, i.X.RB);
|
||||
}
|
||||
void Disasm_XO_RT_RA_RB(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s%s r%d, r%d, r%d", i.XO.Rc ? -7 : -8, i.type->name,
|
||||
i.XO.OE ? "o" : "", i.XO.Rc ? "." : "", i.XO.RT, i.XO.RA,
|
||||
i.XO.RB);
|
||||
str->AppendFormat("%*s%s%s r%d, r%d, r%d", i.XO.Rc ? -7 : -8, i.type->name,
|
||||
i.XO.OE ? "o" : "", i.XO.Rc ? "." : "", i.XO.RT, i.XO.RA,
|
||||
i.XO.RB);
|
||||
}
|
||||
void Disasm_XO_RT_RA(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s%s r%d, r%d", i.XO.Rc ? -7 : -8, i.type->name,
|
||||
i.XO.OE ? "o" : "", i.XO.Rc ? "." : "", i.XO.RT, i.XO.RA);
|
||||
str->AppendFormat("%*s%s%s r%d, r%d", i.XO.Rc ? -7 : -8, i.type->name,
|
||||
i.XO.OE ? "o" : "", i.XO.Rc ? "." : "", i.XO.RT, i.XO.RA);
|
||||
}
|
||||
void Disasm_X_RA_RT_RB(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s r%d, r%d, r%d", i.X.Rc ? -7 : -8, i.type->name,
|
||||
i.X.Rc ? "." : "", i.X.RA, i.X.RT, i.X.RB);
|
||||
str->AppendFormat("%*s%s r%d, r%d, r%d", i.X.Rc ? -7 : -8, i.type->name,
|
||||
i.X.Rc ? "." : "", i.X.RA, i.X.RT, i.X.RB);
|
||||
}
|
||||
void Disasm_D_RA_RT_I(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-7s. r%d, r%d, %.4Xh", i.type->name, i.D.RA, i.D.RT, i.D.DS);
|
||||
str->AppendFormat("%-7s. r%d, r%d, %.4Xh", i.type->name, i.D.RA, i.D.RT,
|
||||
i.D.DS);
|
||||
}
|
||||
void Disasm_X_RA_RT(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s r%d, r%d", i.X.Rc ? -7 : -8, i.type->name,
|
||||
i.X.Rc ? "." : "", i.X.RA, i.X.RT);
|
||||
str->AppendFormat("%*s%s r%d, r%d", i.X.Rc ? -7 : -8, i.type->name,
|
||||
i.X.Rc ? "." : "", i.X.RA, i.X.RT);
|
||||
}
|
||||
|
||||
#define OP(x) ((((uint32_t)(x)) & 0x3f) << 26)
|
||||
|
@ -163,56 +166,58 @@ void Disasm_X_RA_RT(InstrData& i, StringBuffer* str) {
|
|||
|
||||
void Disasm_X_VX_RA0_RB(InstrData& i, StringBuffer* str) {
|
||||
if (i.X.RA) {
|
||||
str->Append("%-8s v%d, r%d, r%d", i.type->name, i.X.RT, i.X.RA, i.X.RB);
|
||||
str->AppendFormat("%-8s v%d, r%d, r%d", i.type->name, i.X.RT, i.X.RA,
|
||||
i.X.RB);
|
||||
} else {
|
||||
str->Append("%-8s v%d, 0, r%d", i.type->name, i.X.RT, i.X.RB);
|
||||
str->AppendFormat("%-8s v%d, 0, r%d", i.type->name, i.X.RT, i.X.RB);
|
||||
}
|
||||
}
|
||||
void Disasm_VX1281_VD_RA0_RB(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = VX128_1_VD128;
|
||||
if (i.VX128_1.RA) {
|
||||
str->Append("%-8s v%d, r%d, r%d", i.type->name, vd, i.VX128_1.RA,
|
||||
i.VX128_1.RB);
|
||||
str->AppendFormat("%-8s v%d, r%d, r%d", i.type->name, vd, i.VX128_1.RA,
|
||||
i.VX128_1.RB);
|
||||
} else {
|
||||
str->Append("%-8s v%d, 0, r%d", i.type->name, vd, i.VX128_1.RB);
|
||||
str->AppendFormat("%-8s v%d, 0, r%d", i.type->name, vd, i.VX128_1.RB);
|
||||
}
|
||||
}
|
||||
void Disasm_VX1283_VD_VB(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = VX128_3_VD128;
|
||||
const uint32_t vb = VX128_3_VB128;
|
||||
str->Append("%-8s v%d, v%d", i.type->name, vd, vb);
|
||||
str->AppendFormat("%-8s v%d, v%d", i.type->name, vd, vb);
|
||||
}
|
||||
void Disasm_VX1283_VD_VB_I(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = VX128_VD128;
|
||||
const uint32_t va = VX128_VA128;
|
||||
const uint32_t uimm = i.VX128_3.IMM;
|
||||
str->Append("%-8s v%d, v%d, %.2Xh", i.type->name, vd, va, uimm);
|
||||
str->AppendFormat("%-8s v%d, v%d, %.2Xh", i.type->name, vd, va, uimm);
|
||||
}
|
||||
void Disasm_VX_VD_VA_VB(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s v%d, v%d, v%d", i.type->name, i.VX.VD, i.VX.VA, i.VX.VB);
|
||||
str->AppendFormat("%-8s v%d, v%d, v%d", i.type->name, i.VX.VD, i.VX.VA,
|
||||
i.VX.VB);
|
||||
}
|
||||
void Disasm_VX128_VD_VA_VB(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = VX128_VD128;
|
||||
const uint32_t va = VX128_VA128;
|
||||
const uint32_t vb = VX128_VB128;
|
||||
str->Append("%-8s v%d, v%d, v%d", i.type->name, vd, va, vb);
|
||||
str->AppendFormat("%-8s v%d, v%d, v%d", i.type->name, vd, va, vb);
|
||||
}
|
||||
void Disasm_VX128_VD_VA_VD_VB(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = VX128_VD128;
|
||||
const uint32_t va = VX128_VA128;
|
||||
const uint32_t vb = VX128_VB128;
|
||||
str->Append("%-8s v%d, v%d, v%d, v%d", i.type->name, vd, va, vd, vb);
|
||||
str->AppendFormat("%-8s v%d, v%d, v%d, v%d", i.type->name, vd, va, vd, vb);
|
||||
}
|
||||
void Disasm_VX1282_VD_VA_VB_VC(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = VX128_2_VD128;
|
||||
const uint32_t va = VX128_2_VA128;
|
||||
const uint32_t vb = VX128_2_VB128;
|
||||
const uint32_t vc = i.VX128_2.VC;
|
||||
str->Append("%-8s v%d, v%d, v%d, v%d", i.type->name, vd, va, vb, vc);
|
||||
str->AppendFormat("%-8s v%d, v%d, v%d, v%d", i.type->name, vd, va, vb, vc);
|
||||
}
|
||||
void Disasm_VXA_VD_VA_VB_VC(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s v%d, v%d, v%d, v%d", i.type->name, i.VXA.VD, i.VXA.VA,
|
||||
i.VXA.VB, i.VXA.VC);
|
||||
str->AppendFormat("%-8s v%d, v%d, v%d, v%d", i.type->name, i.VXA.VD, i.VXA.VA,
|
||||
i.VXA.VB, i.VXA.VC);
|
||||
}
|
||||
|
||||
void Disasm_sync(InstrData& i, StringBuffer* str) {
|
||||
|
@ -231,7 +236,7 @@ void Disasm_sync(InstrData& i, StringBuffer* str) {
|
|||
name = "sync";
|
||||
break;
|
||||
}
|
||||
str->Append("%-8s %.2X", name, L);
|
||||
str->AppendFormat("%-8s %.2X", name, L);
|
||||
}
|
||||
|
||||
void Disasm_dcbf(InstrData& i, StringBuffer* str) {
|
||||
|
@ -253,25 +258,26 @@ void Disasm_dcbf(InstrData& i, StringBuffer* str) {
|
|||
name = "dcbf.??";
|
||||
break;
|
||||
}
|
||||
str->Append("%-8s r%d, r%d", name, i.X.RA, i.X.RB);
|
||||
str->AppendFormat("%-8s r%d, r%d", name, i.X.RA, i.X.RB);
|
||||
}
|
||||
|
||||
void Disasm_dcbz(InstrData& i, StringBuffer* str) {
|
||||
// or dcbz128 0x7C2007EC
|
||||
if (i.X.RA) {
|
||||
str->Append("%-8s r%d, r%d", i.type->name, i.X.RA, i.X.RB);
|
||||
str->AppendFormat("%-8s r%d, r%d", i.type->name, i.X.RA, i.X.RB);
|
||||
} else {
|
||||
str->Append("%-8s 0, r%d", i.type->name, i.X.RB);
|
||||
str->AppendFormat("%-8s 0, r%d", i.type->name, i.X.RB);
|
||||
}
|
||||
}
|
||||
|
||||
void Disasm_fcmp(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s cr%d, f%d, f%d", i.type->name, i.X.RT >> 2, i.X.RA, i.X.RB);
|
||||
str->AppendFormat("%-8s cr%d, f%d, f%d", i.type->name, i.X.RT >> 2, i.X.RA,
|
||||
i.X.RB);
|
||||
}
|
||||
|
||||
void Disasm_mffsx(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s f%d, FPSCR", i.X.Rc ? -7 : -8, i.type->name,
|
||||
i.X.Rc ? "." : "", i.X.RT);
|
||||
str->AppendFormat("%*s%s f%d, FPSCR", i.X.Rc ? -7 : -8, i.type->name,
|
||||
i.X.Rc ? "." : "", i.X.RT);
|
||||
}
|
||||
|
||||
void Disasm_bx(InstrData& i, StringBuffer* str) {
|
||||
|
@ -282,7 +288,7 @@ void Disasm_bx(InstrData& i, StringBuffer* str) {
|
|||
} else {
|
||||
nia = (uint32_t)(i.address + XEEXTS26(i.I.LI << 2));
|
||||
}
|
||||
str->Append("%-8s %.8X", name, nia);
|
||||
str->AppendFormat("%-8s %.8X", name, nia);
|
||||
// TODO(benvanik): resolve target name?
|
||||
}
|
||||
void Disasm_bcx(InstrData& i, StringBuffer* str) {
|
||||
|
@ -303,7 +309,7 @@ void Disasm_bcx(InstrData& i, StringBuffer* str) {
|
|||
} else {
|
||||
nia = (uint32_t)(i.address + XEEXTS16(i.B.BD << 2));
|
||||
}
|
||||
str->Append("%-8s %s%s%s%.8X", i.type->name, s0, s1, s2, nia);
|
||||
str->AppendFormat("%-8s %s%s%s%.8X", i.type->name, s0, s1, s2, nia);
|
||||
// TODO(benvanik): resolve target name?
|
||||
}
|
||||
void Disasm_bcctrx(InstrData& i, StringBuffer* str) {
|
||||
|
@ -313,7 +319,7 @@ void Disasm_bcctrx(InstrData& i, StringBuffer* str) {
|
|||
if (!select_bits(i.XL.BO, 4, 4)) {
|
||||
snprintf(s2, xe::countof(s2), "cr%d, ", i.XL.BI >> 2);
|
||||
}
|
||||
str->Append("%-8s %s%sctr", i.type->name, s0, s2);
|
||||
str->AppendFormat("%-8s %s%sctr", i.type->name, s0, s2);
|
||||
// TODO(benvanik): resolve target name?
|
||||
}
|
||||
void Disasm_bclrx(InstrData& i, StringBuffer* str) {
|
||||
|
@ -331,11 +337,11 @@ void Disasm_bclrx(InstrData& i, StringBuffer* str) {
|
|||
if (!select_bits(i.XL.BO, 4, 4)) {
|
||||
snprintf(s2, xe::countof(s2), "cr%d, ", i.XL.BI >> 2);
|
||||
}
|
||||
str->Append("%-8s %s%s", name, s1, s2);
|
||||
str->AppendFormat("%-8s %s%s", name, s1, s2);
|
||||
}
|
||||
|
||||
void Disasm_mfcr(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s r%d, cr", i.type->name, i.X.RT);
|
||||
str->AppendFormat("%-8s r%d, cr", i.type->name, i.X.RT);
|
||||
}
|
||||
const char* Disasm_spr_name(uint32_t n) {
|
||||
const char* reg = "???";
|
||||
|
@ -355,139 +361,144 @@ const char* Disasm_spr_name(uint32_t n) {
|
|||
void Disasm_mfspr(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F);
|
||||
const char* reg = Disasm_spr_name(n);
|
||||
str->Append("%-8s r%d, %s", i.type->name, i.XFX.RT, reg);
|
||||
str->AppendFormat("%-8s r%d, %s", i.type->name, i.XFX.RT, reg);
|
||||
}
|
||||
void Disasm_mtspr(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F);
|
||||
const char* reg = Disasm_spr_name(n);
|
||||
str->Append("%-8s %s, r%d", i.type->name, reg, i.XFX.RT);
|
||||
str->AppendFormat("%-8s %s, r%d", i.type->name, reg, i.XFX.RT);
|
||||
}
|
||||
void Disasm_mftb(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s r%d, tb", i.type->name, i.XFX.RT);
|
||||
str->AppendFormat("%-8s r%d, tb", i.type->name, i.XFX.RT);
|
||||
}
|
||||
void Disasm_mfmsr(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s r%d", i.type->name, i.X.RT);
|
||||
str->AppendFormat("%-8s r%d", i.type->name, i.X.RT);
|
||||
}
|
||||
void Disasm_mtmsr(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s r%d, %d", i.type->name, i.X.RT, (i.X.RA & 16) ? 1 : 0);
|
||||
str->AppendFormat("%-8s r%d, %d", i.type->name, i.X.RT,
|
||||
(i.X.RA & 16) ? 1 : 0);
|
||||
}
|
||||
|
||||
void Disasm_cmp(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s cr%d, %.2X, r%d, r%d", i.type->name, i.X.RT >> 2,
|
||||
i.X.RT & 1, i.X.RA, i.X.RB);
|
||||
str->AppendFormat("%-8s cr%d, %.2X, r%d, r%d", i.type->name, i.X.RT >> 2,
|
||||
i.X.RT & 1, i.X.RA, i.X.RB);
|
||||
}
|
||||
void Disasm_cmpi(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s cr%d, %.2X, r%d, %d", i.type->name, i.D.RT >> 2, i.D.RT & 1,
|
||||
i.D.RA, XEEXTS16(i.D.DS));
|
||||
str->AppendFormat("%-8s cr%d, %.2X, r%d, %d", i.type->name, i.D.RT >> 2,
|
||||
i.D.RT & 1, i.D.RA, XEEXTS16(i.D.DS));
|
||||
}
|
||||
void Disasm_cmpli(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s cr%d, %.2X, r%d, %.2X", i.type->name, i.D.RT >> 2,
|
||||
i.D.RT & 1, i.D.RA, XEEXTS16(i.D.DS));
|
||||
str->AppendFormat("%-8s cr%d, %.2X, r%d, %.2X", i.type->name, i.D.RT >> 2,
|
||||
i.D.RT & 1, i.D.RA, XEEXTS16(i.D.DS));
|
||||
}
|
||||
|
||||
void Disasm_rld(InstrData& i, StringBuffer* str) {
|
||||
if (i.MD.idx == 0) {
|
||||
// XEDISASMR(rldiclx, 0x78000000, MD )
|
||||
str->Append("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, "rldicl",
|
||||
i.MD.Rc ? "." : "", i.MD.RA, i.MD.RT, (i.MD.SH5 << 5) | i.MD.SH,
|
||||
(i.MD.MB5 << 5) | i.MD.MB);
|
||||
str->AppendFormat("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, "rldicl",
|
||||
i.MD.Rc ? "." : "", i.MD.RA, i.MD.RT,
|
||||
(i.MD.SH5 << 5) | i.MD.SH, (i.MD.MB5 << 5) | i.MD.MB);
|
||||
} else if (i.MD.idx == 1) {
|
||||
// XEDISASMR(rldicrx, 0x78000004, MD )
|
||||
str->Append("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, "rldicr",
|
||||
i.MD.Rc ? "." : "", i.MD.RA, i.MD.RT, (i.MD.SH5 << 5) | i.MD.SH,
|
||||
(i.MD.MB5 << 5) | i.MD.MB);
|
||||
str->AppendFormat("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, "rldicr",
|
||||
i.MD.Rc ? "." : "", i.MD.RA, i.MD.RT,
|
||||
(i.MD.SH5 << 5) | i.MD.SH, (i.MD.MB5 << 5) | i.MD.MB);
|
||||
} else if (i.MD.idx == 2) {
|
||||
// XEDISASMR(rldicx, 0x78000008, MD )
|
||||
uint32_t sh = (i.MD.SH5 << 5) | i.MD.SH;
|
||||
uint32_t mb = (i.MD.MB5 << 5) | i.MD.MB;
|
||||
const char* name = (mb == 0x3E) ? "sldi" : "rldic";
|
||||
str->Append("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, name,
|
||||
i.MD.Rc ? "." : "", i.MD.RA, i.MD.RT, sh, mb);
|
||||
str->AppendFormat("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, name,
|
||||
i.MD.Rc ? "." : "", i.MD.RA, i.MD.RT, sh, mb);
|
||||
} else if (i.MDS.idx == 8) {
|
||||
// XEDISASMR(rldclx, 0x78000010, MDS)
|
||||
str->Append("%*s%s r%d, r%d, %d, %d", i.MDS.Rc ? -7 : -8, "rldcl",
|
||||
i.MDS.Rc ? "." : "", i.MDS.RA, i.MDS.RT, i.MDS.RB,
|
||||
(i.MDS.MB5 << 5) | i.MDS.MB);
|
||||
str->AppendFormat("%*s%s r%d, r%d, %d, %d", i.MDS.Rc ? -7 : -8, "rldcl",
|
||||
i.MDS.Rc ? "." : "", i.MDS.RA, i.MDS.RT, i.MDS.RB,
|
||||
(i.MDS.MB5 << 5) | i.MDS.MB);
|
||||
} else if (i.MDS.idx == 9) {
|
||||
// XEDISASMR(rldcrx, 0x78000012, MDS)
|
||||
str->Append("%*s%s r%d, r%d, %d, %d", i.MDS.Rc ? -7 : -8, "rldcr",
|
||||
i.MDS.Rc ? "." : "", i.MDS.RA, i.MDS.RT, i.MDS.RB,
|
||||
(i.MDS.MB5 << 5) | i.MDS.MB);
|
||||
str->AppendFormat("%*s%s r%d, r%d, %d, %d", i.MDS.Rc ? -7 : -8, "rldcr",
|
||||
i.MDS.Rc ? "." : "", i.MDS.RA, i.MDS.RT, i.MDS.RB,
|
||||
(i.MDS.MB5 << 5) | i.MDS.MB);
|
||||
} else if (i.MD.idx == 3) {
|
||||
// XEDISASMR(rldimix, 0x7800000C, MD )
|
||||
str->Append("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, "rldimi",
|
||||
i.MD.Rc ? "." : "", i.MD.RA, i.MD.RT, (i.MD.SH5 << 5) | i.MD.SH,
|
||||
(i.MD.MB5 << 5) | i.MD.MB);
|
||||
str->AppendFormat("%*s%s r%d, r%d, %d, %d", i.MD.Rc ? -7 : -8, "rldimi",
|
||||
i.MD.Rc ? "." : "", i.MD.RA, i.MD.RT,
|
||||
(i.MD.SH5 << 5) | i.MD.SH, (i.MD.MB5 << 5) | i.MD.MB);
|
||||
} else {
|
||||
assert_always();
|
||||
}
|
||||
}
|
||||
void Disasm_rlwim(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s r%d, r%d, %d, %d, %d", i.M.Rc ? -7 : -8, i.type->name,
|
||||
i.M.Rc ? "." : "", i.M.RA, i.M.RT, i.M.SH, i.M.MB, i.M.ME);
|
||||
str->AppendFormat("%*s%s r%d, r%d, %d, %d, %d", i.M.Rc ? -7 : -8,
|
||||
i.type->name, i.M.Rc ? "." : "", i.M.RA, i.M.RT, i.M.SH,
|
||||
i.M.MB, i.M.ME);
|
||||
}
|
||||
void Disasm_rlwnmx(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s r%d, r%d, r%d, %d, %d", i.M.Rc ? -7 : -8, i.type->name,
|
||||
i.M.Rc ? "." : "", i.M.RA, i.M.RT, i.M.SH, i.M.MB, i.M.ME);
|
||||
str->AppendFormat("%*s%s r%d, r%d, r%d, %d, %d", i.M.Rc ? -7 : -8,
|
||||
i.type->name, i.M.Rc ? "." : "", i.M.RA, i.M.RT, i.M.SH,
|
||||
i.M.MB, i.M.ME);
|
||||
}
|
||||
void Disasm_srawix(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s r%d, r%d, %d", i.X.Rc ? -7 : -8, i.type->name,
|
||||
i.X.Rc ? "." : "", i.X.RA, i.X.RT, i.X.RB);
|
||||
str->AppendFormat("%*s%s r%d, r%d, %d", i.X.Rc ? -7 : -8, i.type->name,
|
||||
i.X.Rc ? "." : "", i.X.RA, i.X.RT, i.X.RB);
|
||||
}
|
||||
void Disasm_sradix(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%*s%s r%d, r%d, %d", i.XS.Rc ? -7 : -8, i.type->name,
|
||||
i.XS.Rc ? "." : "", i.XS.RA, i.XS.RT, (i.XS.SH5 << 5) | i.XS.SH);
|
||||
str->AppendFormat("%*s%s r%d, r%d, %d", i.XS.Rc ? -7 : -8, i.type->name,
|
||||
i.XS.Rc ? "." : "", i.XS.RA, i.XS.RT,
|
||||
(i.XS.SH5 << 5) | i.XS.SH);
|
||||
}
|
||||
|
||||
void Disasm_vpermwi128(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = i.VX128_P.VD128l | (i.VX128_P.VD128h << 5);
|
||||
const uint32_t vb = i.VX128_P.VB128l | (i.VX128_P.VB128h << 5);
|
||||
str->Append("%-8s v%d, v%d, %.2X", i.type->name, vd, vb,
|
||||
i.VX128_P.PERMl | (i.VX128_P.PERMh << 5));
|
||||
str->AppendFormat("%-8s v%d, v%d, %.2X", i.type->name, vd, vb,
|
||||
i.VX128_P.PERMl | (i.VX128_P.PERMh << 5));
|
||||
}
|
||||
void Disasm_vrfin128(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = VX128_3_VD128;
|
||||
const uint32_t vb = VX128_3_VB128;
|
||||
str->Append("%-8s v%d, v%d", i.type->name, vd, vb);
|
||||
str->AppendFormat("%-8s v%d, v%d", i.type->name, vd, vb);
|
||||
}
|
||||
void Disasm_vrlimi128(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = VX128_4_VD128;
|
||||
const uint32_t vb = VX128_4_VB128;
|
||||
str->Append("%-8s v%d, v%d, %.2X, %.2X", i.type->name, vd, vb, i.VX128_4.IMM,
|
||||
i.VX128_4.z);
|
||||
str->AppendFormat("%-8s v%d, v%d, %.2X, %.2X", i.type->name, vd, vb,
|
||||
i.VX128_4.IMM, i.VX128_4.z);
|
||||
}
|
||||
void Disasm_vsldoi128(InstrData& i, StringBuffer* str) {
|
||||
const uint32_t vd = VX128_5_VD128;
|
||||
const uint32_t va = VX128_5_VA128;
|
||||
const uint32_t vb = VX128_5_VB128;
|
||||
const uint32_t sh = i.VX128_5.SH;
|
||||
str->Append("%-8s v%d, v%d, v%d, %.2X", i.type->name, vd, va, vb, sh);
|
||||
str->AppendFormat("%-8s v%d, v%d, v%d, %.2X", i.type->name, vd, va, vb, sh);
|
||||
}
|
||||
void Disasm_vspltb(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s v%d, v%d, %.2X", i.type->name, i.VX.VD, i.VX.VB,
|
||||
i.VX.VA & 0xF);
|
||||
str->AppendFormat("%-8s v%d, v%d, %.2X", i.type->name, i.VX.VD, i.VX.VB,
|
||||
i.VX.VA & 0xF);
|
||||
}
|
||||
void Disasm_vsplth(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s v%d, v%d, %.2X", i.type->name, i.VX.VD, i.VX.VB,
|
||||
i.VX.VA & 0x7);
|
||||
str->AppendFormat("%-8s v%d, v%d, %.2X", i.type->name, i.VX.VD, i.VX.VB,
|
||||
i.VX.VA & 0x7);
|
||||
}
|
||||
void Disasm_vspltw(InstrData& i, StringBuffer* str) {
|
||||
str->Append("%-8s v%d, v%d, %.2X", i.type->name, i.VX.VD, i.VX.VB, i.VX.VA);
|
||||
str->AppendFormat("%-8s v%d, v%d, %.2X", i.type->name, i.VX.VD, i.VX.VB,
|
||||
i.VX.VA);
|
||||
}
|
||||
void Disasm_vspltisb(InstrData& i, StringBuffer* str) {
|
||||
// 5bit -> 8bit sign extend
|
||||
int8_t simm = (i.VX.VA & 0x10) ? (i.VX.VA | 0xF0) : i.VX.VA;
|
||||
str->Append("%-8s v%d, %.2X", i.type->name, i.VX.VD, simm);
|
||||
str->AppendFormat("%-8s v%d, %.2X", i.type->name, i.VX.VD, simm);
|
||||
}
|
||||
void Disasm_vspltish(InstrData& i, StringBuffer* str) {
|
||||
// 5bit -> 16bit sign extend
|
||||
int16_t simm = (i.VX.VA & 0x10) ? (i.VX.VA | 0xFFF0) : i.VX.VA;
|
||||
str->Append("%-8s v%d, %.4X", i.type->name, i.VX.VD, simm);
|
||||
str->AppendFormat("%-8s v%d, %.4X", i.type->name, i.VX.VD, simm);
|
||||
}
|
||||
void Disasm_vspltisw(InstrData& i, StringBuffer* str) {
|
||||
// 5bit -> 32bit sign extend
|
||||
int32_t simm = (i.VX.VA & 0x10) ? (i.VX.VA | 0xFFFFFFF0) : i.VX.VA;
|
||||
str->Append("%-8s v%d, %.8X", i.type->name, i.VX.VD, simm);
|
||||
str->AppendFormat("%-8s v%d, %.8X", i.type->name, i.VX.VD, simm);
|
||||
}
|
||||
|
||||
int DisasmPPC(InstrData& i, StringBuffer* str) {
|
||||
|
|
|
@ -28,7 +28,8 @@ void DumpAllInstrCounts() {
|
|||
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);
|
||||
sb.AppendFormat("%8d : %s\n", instr_type->translation_count,
|
||||
instr_type->name);
|
||||
}
|
||||
}
|
||||
fprintf(stdout, sb.GetString());
|
||||
|
|
|
@ -195,10 +195,10 @@ void PPCTranslator::DumpSource(FunctionInfo* symbol_info,
|
|||
StringBuffer* string_buffer) {
|
||||
Memory* memory = frontend_->memory();
|
||||
|
||||
string_buffer->Append("%s fn %.8X-%.8X %s\n",
|
||||
symbol_info->module()->name().c_str(),
|
||||
symbol_info->address(), symbol_info->end_address(),
|
||||
symbol_info->name().c_str());
|
||||
string_buffer->AppendFormat(
|
||||
"%s fn %.8X-%.8X %s\n", symbol_info->module()->name().c_str(),
|
||||
symbol_info->address(), symbol_info->end_address(),
|
||||
symbol_info->name().c_str());
|
||||
|
||||
auto blocks = scanner_->FindBlocks(symbol_info);
|
||||
|
||||
|
@ -215,13 +215,14 @@ void PPCTranslator::DumpSource(FunctionInfo* symbol_info,
|
|||
|
||||
// Check labels.
|
||||
if (block_it != blocks.end() && block_it->start_address == address) {
|
||||
string_buffer->Append("%.8X loc_%.8X:\n", address, address);
|
||||
string_buffer->AppendFormat("%.8X loc_%.8X:\n", address,
|
||||
address);
|
||||
++block_it;
|
||||
}
|
||||
|
||||
string_buffer->Append("%.8X %.8X ", address, i.code);
|
||||
string_buffer->AppendFormat("%.8X %.8X ", address, i.code);
|
||||
DisasmPPC(i, string_buffer);
|
||||
string_buffer->Append("\n");
|
||||
string_buffer->Append('\n');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ assert_true((value->type) != FLOAT32_TYPE && (value->type) != FLOAT64_TYPE)
|
|||
#define ASSERT_TYPES_EQUAL(value1, value2) \
|
||||
assert_true((value1->type) == (value2->type))
|
||||
|
||||
HIRBuilder::HIRBuilder() {
|
||||
HIRBuilder::HIRBuilder() {
|
||||
arena_ = new Arena();
|
||||
Reset();
|
||||
}
|
||||
|
@ -103,27 +103,27 @@ void HIRBuilder::DumpValue(StringBuffer* str, Value* value) {
|
|||
if (value->IsConstant()) {
|
||||
switch (value->type) {
|
||||
case INT8_TYPE:
|
||||
str->Append("%X", value->constant.i8);
|
||||
str->AppendFormat("%X", value->constant.i8);
|
||||
break;
|
||||
case INT16_TYPE:
|
||||
str->Append("%X", value->constant.i16);
|
||||
str->AppendFormat("%X", value->constant.i16);
|
||||
break;
|
||||
case INT32_TYPE:
|
||||
str->Append("%X", value->constant.i32);
|
||||
str->AppendFormat("%X", value->constant.i32);
|
||||
break;
|
||||
case INT64_TYPE:
|
||||
str->Append("%llX", value->constant.i64);
|
||||
str->AppendFormat("%llX", value->constant.i64);
|
||||
break;
|
||||
case FLOAT32_TYPE:
|
||||
str->Append("%F", value->constant.f32);
|
||||
str->AppendFormat("%F", value->constant.f32);
|
||||
break;
|
||||
case FLOAT64_TYPE:
|
||||
str->Append("%F", value->constant.f64);
|
||||
str->AppendFormat("%F", value->constant.f64);
|
||||
break;
|
||||
case VEC128_TYPE:
|
||||
str->Append("(%F,%F,%F,%F)", value->constant.v128.x,
|
||||
value->constant.v128.y, value->constant.v128.z,
|
||||
value->constant.v128.w);
|
||||
str->AppendFormat("(%F,%F,%F,%F)", value->constant.v128.x,
|
||||
value->constant.v128.y, value->constant.v128.z,
|
||||
value->constant.v128.w);
|
||||
break;
|
||||
default:
|
||||
assert_always();
|
||||
|
@ -133,10 +133,10 @@ void HIRBuilder::DumpValue(StringBuffer* str, Value* value) {
|
|||
static const char* type_names[] = {
|
||||
"i8", "i16", "i32", "i64", "f32", "f64", "v128",
|
||||
};
|
||||
str->Append("v%d.%s", value->ordinal, type_names[value->type]);
|
||||
str->AppendFormat("v%d.%s", value->ordinal, type_names[value->type]);
|
||||
}
|
||||
if (value->reg.index != -1) {
|
||||
str->Append("<%s%d>", value->reg.set->name, value->reg.index);
|
||||
str->AppendFormat("<%s%d>", value->reg.set->name, value->reg.index);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,11 +149,11 @@ void HIRBuilder::DumpOp(StringBuffer* str, OpcodeSignatureType sig_type,
|
|||
if (op->label->name) {
|
||||
str->Append(op->label->name);
|
||||
} else {
|
||||
str->Append("label%d", op->label->id);
|
||||
str->AppendFormat("label%d", op->label->id);
|
||||
}
|
||||
break;
|
||||
case OPCODE_SIG_TYPE_O:
|
||||
str->Append("+%lld", op->offset);
|
||||
str->AppendFormat("+%lld", op->offset);
|
||||
break;
|
||||
case OPCODE_SIG_TYPE_S:
|
||||
if (true) {
|
||||
|
@ -169,14 +169,14 @@ void HIRBuilder::DumpOp(StringBuffer* str, OpcodeSignatureType sig_type,
|
|||
|
||||
void HIRBuilder::Dump(StringBuffer* str) {
|
||||
if (attributes_) {
|
||||
str->Append("; attributes = %.8X\n", attributes_);
|
||||
str->AppendFormat("; attributes = %.8X\n", attributes_);
|
||||
}
|
||||
|
||||
for (auto it = locals_.begin(); it != locals_.end(); ++it) {
|
||||
auto local = *it;
|
||||
str->Append(" ; local ");
|
||||
DumpValue(str, local);
|
||||
str->Append("\n");
|
||||
str->Append('\n');
|
||||
}
|
||||
|
||||
uint32_t block_ordinal = 0;
|
||||
|
@ -185,16 +185,16 @@ void HIRBuilder::Dump(StringBuffer* str) {
|
|||
if (block == block_head_) {
|
||||
str->Append("<entry>:\n");
|
||||
} else if (!block->label_head) {
|
||||
str->Append("<block%d>:\n", block_ordinal);
|
||||
str->AppendFormat("<block%d>:\n", block_ordinal);
|
||||
}
|
||||
block_ordinal++;
|
||||
|
||||
Label* label = block->label_head;
|
||||
while (label) {
|
||||
if (label->name) {
|
||||
str->Append("%s:\n", label->name);
|
||||
str->AppendFormat("%s:\n", label->name);
|
||||
} else {
|
||||
str->Append("label%d:\n", label->id);
|
||||
str->AppendFormat("label%d:\n", label->id);
|
||||
}
|
||||
label = label->next;
|
||||
}
|
||||
|
@ -203,30 +203,30 @@ void HIRBuilder::Dump(StringBuffer* str) {
|
|||
while (incoming_edge) {
|
||||
auto src_label = incoming_edge->src->label_head;
|
||||
if (src_label && src_label->name) {
|
||||
str->Append(" ; in: %s", src_label->name);
|
||||
str->AppendFormat(" ; in: %s", src_label->name);
|
||||
} else if (src_label) {
|
||||
str->Append(" ; in: label%d", src_label->id);
|
||||
str->AppendFormat(" ; in: label%d", src_label->id);
|
||||
} else {
|
||||
str->Append(" ; in: <block%d>", incoming_edge->src->ordinal);
|
||||
str->AppendFormat(" ; in: <block%d>", incoming_edge->src->ordinal);
|
||||
}
|
||||
str->Append(", dom:%d, uncond:%d\n",
|
||||
(incoming_edge->flags & Edge::DOMINATES) ? 1 : 0,
|
||||
(incoming_edge->flags & Edge::UNCONDITIONAL) ? 1 : 0);
|
||||
str->AppendFormat(", dom:%d, uncond:%d\n",
|
||||
(incoming_edge->flags & Edge::DOMINATES) ? 1 : 0,
|
||||
(incoming_edge->flags & Edge::UNCONDITIONAL) ? 1 : 0);
|
||||
incoming_edge = incoming_edge->incoming_next;
|
||||
}
|
||||
Edge* outgoing_edge = block->outgoing_edge_head;
|
||||
while (outgoing_edge) {
|
||||
auto dest_label = outgoing_edge->dest->label_head;
|
||||
if (dest_label && dest_label->name) {
|
||||
str->Append(" ; out: %s", dest_label->name);
|
||||
str->AppendFormat(" ; out: %s", dest_label->name);
|
||||
} else if (dest_label) {
|
||||
str->Append(" ; out: label%d", dest_label->id);
|
||||
str->AppendFormat(" ; out: label%d", dest_label->id);
|
||||
} else {
|
||||
str->Append(" ; out: <block%d>", outgoing_edge->dest->ordinal);
|
||||
str->AppendFormat(" ; out: <block%d>", outgoing_edge->dest->ordinal);
|
||||
}
|
||||
str->Append(", dom:%d, uncond:%d\n",
|
||||
(outgoing_edge->flags & Edge::DOMINATES) ? 1 : 0,
|
||||
(outgoing_edge->flags & Edge::UNCONDITIONAL) ? 1 : 0);
|
||||
str->AppendFormat(", dom:%d, uncond:%d\n",
|
||||
(outgoing_edge->flags & Edge::DOMINATES) ? 1 : 0,
|
||||
(outgoing_edge->flags & Edge::UNCONDITIONAL) ? 1 : 0);
|
||||
outgoing_edge = outgoing_edge->outgoing_next;
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,7 @@ void HIRBuilder::Dump(StringBuffer* str) {
|
|||
continue;
|
||||
}
|
||||
if (i->opcode == &OPCODE_COMMENT_info) {
|
||||
str->Append(" ; %s\n", (char*)i->src1.offset);
|
||||
str->AppendFormat(" ; %s\n", (char*)i->src1.offset);
|
||||
i = i->next;
|
||||
continue;
|
||||
}
|
||||
|
@ -253,12 +253,12 @@ void HIRBuilder::Dump(StringBuffer* str) {
|
|||
str->Append(" = ");
|
||||
}
|
||||
if (i->flags) {
|
||||
str->Append("%s.%d", info->name, i->flags);
|
||||
str->AppendFormat("%s.%d", info->name, i->flags);
|
||||
} else {
|
||||
str->Append("%s", info->name);
|
||||
str->Append(info->name);
|
||||
}
|
||||
if (src1_type) {
|
||||
str->Append(" ");
|
||||
str->Append(' ');
|
||||
DumpOp(str, src1_type, &i->src1);
|
||||
}
|
||||
if (src2_type) {
|
||||
|
@ -269,7 +269,7 @@ void HIRBuilder::Dump(StringBuffer* str) {
|
|||
str->Append(", ");
|
||||
DumpOp(str, src3_type, &i->src3);
|
||||
}
|
||||
str->Append("\n");
|
||||
str->Append('\n');
|
||||
i = i->next;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "xenia/base/assert.h"
|
||||
#include "xenia/base/string_buffer.h"
|
||||
|
||||
namespace xe {
|
||||
namespace gpu {
|
||||
|
@ -45,28 +46,10 @@ namespace gpu {
|
|||
using namespace xe::gpu::ucode;
|
||||
using namespace xe::gpu::xenos;
|
||||
|
||||
const int OUTPUT_CAPACITY = 256 * 1024;
|
||||
struct Output {
|
||||
char buffer[OUTPUT_CAPACITY];
|
||||
size_t capacity;
|
||||
size_t offset;
|
||||
Output() : capacity(OUTPUT_CAPACITY), offset(0) { buffer[0] = 0; }
|
||||
void append(const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int len = vsnprintf(buffer + offset, capacity - offset, format, args);
|
||||
va_end(args);
|
||||
assert_true(offset + len < capacity);
|
||||
offset += len;
|
||||
buffer[offset] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
static const char* levels[] = {
|
||||
"", "\t", "\t\t", "\t\t\t",
|
||||
"\t\t\t\t", "\t\t\t\t\t", "\t\t\t\t\t\t", "\t\t\t\t\t\t\t",
|
||||
"\t\t\t\t\t\t\t\t", "\t\t\t\t\t\t\t\t\t", "x", "x",
|
||||
"x", "x", "x", "x",
|
||||
"", "\t", "\t\t", "\t\t\t", "\t\t\t\t", "\t\t\t\t\t", "\t\t\t\t\t\t",
|
||||
"\t\t\t\t\t\t\t", "\t\t\t\t\t\t\t\t", "\t\t\t\t\t\t\t\t\t", "x", "x", "x",
|
||||
"x", "x", "x",
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -79,52 +62,52 @@ static const char chan_names[] = {
|
|||
'0', '1', '?', '_',
|
||||
};
|
||||
|
||||
void print_srcreg(Output* output, uint32_t num, uint32_t type, uint32_t swiz,
|
||||
uint32_t negate, uint32_t abs_constants,
|
||||
void print_srcreg(StringBuffer* output, uint32_t num, uint32_t type,
|
||||
uint32_t swiz, uint32_t negate, uint32_t abs_constants,
|
||||
ShaderType shader_type) {
|
||||
if (negate) {
|
||||
output->append("-");
|
||||
output->Append('-');
|
||||
}
|
||||
if (type) {
|
||||
if (num & 0x80) {
|
||||
output->append("abs(");
|
||||
output->Append("abs(");
|
||||
}
|
||||
output->append("R%u", num & 0x7F);
|
||||
output->AppendFormat("R%u", num & 0x7F);
|
||||
if (num & 0x80) {
|
||||
output->append(")");
|
||||
output->Append(')');
|
||||
}
|
||||
} else {
|
||||
if (abs_constants) {
|
||||
output->append("|");
|
||||
output->Append('|');
|
||||
}
|
||||
num += shader_type == ShaderType::kPixel ? 256 : 0;
|
||||
output->append("C%u", num);
|
||||
output->AppendFormat("C%u", num);
|
||||
if (abs_constants) {
|
||||
output->append("|");
|
||||
output->Append('|');
|
||||
}
|
||||
}
|
||||
if (swiz) {
|
||||
output->append(".");
|
||||
output->Append('.');
|
||||
for (int i = 0; i < 4; i++) {
|
||||
output->append("%c", chan_names[(swiz + i) & 0x3]);
|
||||
output->Append(chan_names[(swiz + i) & 0x3]);
|
||||
swiz >>= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void print_dstreg(Output* output, uint32_t num, uint32_t mask,
|
||||
void print_dstreg(StringBuffer* output, uint32_t num, uint32_t mask,
|
||||
uint32_t dst_exp) {
|
||||
output->append("%s%u", dst_exp ? "export" : "R", num);
|
||||
output->AppendFormat("%s%u", dst_exp ? "export" : "R", num);
|
||||
if (mask != 0xf) {
|
||||
output->append(".");
|
||||
output->Append('.');
|
||||
for (int i = 0; i < 4; i++) {
|
||||
output->append("%c", (mask & 0x1) ? chan_names[i] : '_');
|
||||
output->Append((mask & 0x1) ? chan_names[i] : '_');
|
||||
mask >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void print_export_comment(Output* output, uint32_t num, ShaderType type) {
|
||||
void print_export_comment(StringBuffer* output, uint32_t num, ShaderType type) {
|
||||
const char* name = NULL;
|
||||
switch (type) {
|
||||
case ShaderType::kVertex:
|
||||
|
@ -149,46 +132,47 @@ void print_export_comment(Output* output, uint32_t num, ShaderType type) {
|
|||
* up the name of the varying..
|
||||
*/
|
||||
if (name) {
|
||||
output->append("\t; %s", name);
|
||||
output->AppendFormat("\t; %s", name);
|
||||
}
|
||||
}
|
||||
|
||||
struct {
|
||||
uint32_t num_srcs;
|
||||
const char* name;
|
||||
} vector_instructions[0x20] = {
|
||||
} vector_instructions[0x20] =
|
||||
{
|
||||
#define INSTR(opc, num_srcs) \
|
||||
{ num_srcs, #opc }
|
||||
INSTR(ADDv, 2), // 0
|
||||
INSTR(MULv, 2), // 1
|
||||
INSTR(MAXv, 2), // 2
|
||||
INSTR(MINv, 2), // 3
|
||||
INSTR(SETEv, 2), // 4
|
||||
INSTR(SETGTv, 2), // 5
|
||||
INSTR(SETGTEv, 2), // 6
|
||||
INSTR(SETNEv, 2), // 7
|
||||
INSTR(FRACv, 1), // 8
|
||||
INSTR(TRUNCv, 1), // 9
|
||||
INSTR(FLOORv, 1), // 10
|
||||
INSTR(MULADDv, 3), // 111
|
||||
INSTR(CNDEv, 3), // 12
|
||||
INSTR(CNDGTEv, 3), // 13
|
||||
INSTR(CNDGTv, 3), // 14
|
||||
INSTR(DOT4v, 2), // 15
|
||||
INSTR(DOT3v, 2), // 16
|
||||
INSTR(DOT2ADDv, 3), // 17 -- ???
|
||||
INSTR(CUBEv, 2), // 18
|
||||
INSTR(MAX4v, 1), // 19
|
||||
INSTR(PRED_SETE_PUSHv, 2), // 20
|
||||
INSTR(PRED_SETNE_PUSHv, 2), // 21
|
||||
INSTR(PRED_SETGT_PUSHv, 2), // 22
|
||||
INSTR(PRED_SETGTE_PUSHv, 2), // 23
|
||||
INSTR(KILLEv, 2), // 24
|
||||
INSTR(KILLGTv, 2), // 25
|
||||
INSTR(KILLGTEv, 2), // 26
|
||||
INSTR(KILLNEv, 2), // 27
|
||||
INSTR(DSTv, 2), // 28
|
||||
INSTR(MOVAv, 1), // 29
|
||||
INSTR(ADDv, 2), // 0
|
||||
INSTR(MULv, 2), // 1
|
||||
INSTR(MAXv, 2), // 2
|
||||
INSTR(MINv, 2), // 3
|
||||
INSTR(SETEv, 2), // 4
|
||||
INSTR(SETGTv, 2), // 5
|
||||
INSTR(SETGTEv, 2), // 6
|
||||
INSTR(SETNEv, 2), // 7
|
||||
INSTR(FRACv, 1), // 8
|
||||
INSTR(TRUNCv, 1), // 9
|
||||
INSTR(FLOORv, 1), // 10
|
||||
INSTR(MULADDv, 3), // 111
|
||||
INSTR(CNDEv, 3), // 12
|
||||
INSTR(CNDGTEv, 3), // 13
|
||||
INSTR(CNDGTv, 3), // 14
|
||||
INSTR(DOT4v, 2), // 15
|
||||
INSTR(DOT3v, 2), // 16
|
||||
INSTR(DOT2ADDv, 3), // 17 -- ???
|
||||
INSTR(CUBEv, 2), // 18
|
||||
INSTR(MAX4v, 1), // 19
|
||||
INSTR(PRED_SETE_PUSHv, 2), // 20
|
||||
INSTR(PRED_SETNE_PUSHv, 2), // 21
|
||||
INSTR(PRED_SETGT_PUSHv, 2), // 22
|
||||
INSTR(PRED_SETGTE_PUSHv, 2), // 23
|
||||
INSTR(KILLEv, 2), // 24
|
||||
INSTR(KILLGTv, 2), // 25
|
||||
INSTR(KILLGTEv, 2), // 26
|
||||
INSTR(KILLNEv, 2), // 27
|
||||
INSTR(DSTv, 2), // 28
|
||||
INSTR(MOVAv, 1), // 29
|
||||
},
|
||||
scalar_instructions[0x40] = {
|
||||
INSTR(ADDs, 1), // 0
|
||||
|
@ -245,77 +229,77 @@ struct {
|
|||
#undef INSTR
|
||||
};
|
||||
|
||||
int disasm_alu(Output* output, const uint32_t* dwords, uint32_t alu_off,
|
||||
int disasm_alu(StringBuffer* output, const uint32_t* dwords, uint32_t alu_off,
|
||||
int level, int sync, ShaderType type) {
|
||||
const instr_alu_t* alu = (const instr_alu_t*)dwords;
|
||||
|
||||
output->append("%s", levels[level]);
|
||||
output->append("%02x: %08x %08x %08x\t", alu_off, dwords[0], dwords[1],
|
||||
dwords[2]);
|
||||
output->Append(levels[level]);
|
||||
output->AppendFormat("%02x: %08x %08x %08x\t", alu_off, dwords[0], dwords[1],
|
||||
dwords[2]);
|
||||
|
||||
output->append(" %sALU:\t", sync ? "(S)" : " ");
|
||||
output->AppendFormat(" %sALU:\t", sync ? "(S)" : " ");
|
||||
|
||||
if (!alu->scalar_write_mask && !alu->vector_write_mask) {
|
||||
output->append(" <nop>\n");
|
||||
output->Append(" <nop>\n");
|
||||
}
|
||||
|
||||
if (alu->vector_write_mask) {
|
||||
output->append("%s", vector_instructions[alu->vector_opc].name);
|
||||
output->Append(vector_instructions[alu->vector_opc].name);
|
||||
|
||||
if (alu->pred_select & 0x2) {
|
||||
// seems to work similar to conditional execution in ARM instruction
|
||||
// set, so let's use a similar syntax for now:
|
||||
output->append((alu->pred_select & 0x1) ? "EQ" : "NE");
|
||||
output->Append((alu->pred_select & 0x1) ? "EQ" : "NE");
|
||||
}
|
||||
|
||||
output->append("\t");
|
||||
output->Append("\t");
|
||||
|
||||
print_dstreg(output, alu->vector_dest, alu->vector_write_mask,
|
||||
alu->export_data);
|
||||
output->append(" = ");
|
||||
output->Append(" = ");
|
||||
if (vector_instructions[alu->vector_opc].num_srcs == 3) {
|
||||
print_srcreg(output, alu->src3_reg, alu->src3_sel, alu->src3_swiz,
|
||||
alu->src3_reg_negate, alu->abs_constants, type);
|
||||
output->append(", ");
|
||||
output->Append(", ");
|
||||
}
|
||||
print_srcreg(output, alu->src1_reg, alu->src1_sel, alu->src1_swiz,
|
||||
alu->src1_reg_negate, alu->abs_constants, type);
|
||||
if (vector_instructions[alu->vector_opc].num_srcs > 1) {
|
||||
output->append(", ");
|
||||
output->Append(", ");
|
||||
print_srcreg(output, alu->src2_reg, alu->src2_sel, alu->src2_swiz,
|
||||
alu->src2_reg_negate, alu->abs_constants, type);
|
||||
}
|
||||
|
||||
if (alu->vector_clamp) {
|
||||
output->append(" CLAMP");
|
||||
output->Append(" CLAMP");
|
||||
}
|
||||
if (alu->pred_select) {
|
||||
output->append(" COND(%d)", alu->pred_condition);
|
||||
output->AppendFormat(" COND(%d)", alu->pred_condition);
|
||||
}
|
||||
if (alu->export_data) {
|
||||
print_export_comment(output, alu->vector_dest, type);
|
||||
}
|
||||
|
||||
output->append("\n");
|
||||
output->Append('\n');
|
||||
}
|
||||
|
||||
if (alu->scalar_write_mask || !alu->vector_write_mask) {
|
||||
// 2nd optional scalar op:
|
||||
|
||||
if (alu->vector_write_mask) {
|
||||
output->append("%s", levels[level]);
|
||||
output->append(" \t\t\t\t\t\t \t");
|
||||
output->Append(levels[level]);
|
||||
output->AppendFormat(" \t\t\t\t\t\t \t");
|
||||
}
|
||||
|
||||
if (scalar_instructions[alu->scalar_opc].name) {
|
||||
output->append("%s\t", scalar_instructions[alu->scalar_opc].name);
|
||||
output->AppendFormat("%s\t", scalar_instructions[alu->scalar_opc].name);
|
||||
} else {
|
||||
output->append("OP(%u)\t", alu->scalar_opc);
|
||||
output->AppendFormat("OP(%u)\t", alu->scalar_opc);
|
||||
}
|
||||
|
||||
print_dstreg(output, alu->scalar_dest, alu->scalar_write_mask,
|
||||
alu->export_data);
|
||||
output->append(" = ");
|
||||
output->Append(" = ");
|
||||
if (scalar_instructions[alu->scalar_opc].num_srcs == 2) {
|
||||
// MUL/ADD/etc
|
||||
// Clever, CONST_0 and CONST_1 are just an extra storage bit.
|
||||
|
@ -325,24 +309,24 @@ int disasm_alu(Output* output, const uint32_t* dwords, uint32_t alu_off,
|
|||
uint32_t swiz_b = (src3_swiz & 0x3);
|
||||
print_srcreg(output, alu->src3_reg, 0, 0, alu->src3_reg_negate,
|
||||
alu->abs_constants, type);
|
||||
output->append(".%c", chan_names[swiz_a]);
|
||||
output->append(", ");
|
||||
output->AppendFormat(".%c", chan_names[swiz_a]);
|
||||
output->Append(", ");
|
||||
uint32_t reg2 = (alu->scalar_opc & 1) | (alu->src3_swiz & 0x3C) |
|
||||
(alu->src3_sel << 1);
|
||||
print_srcreg(output, reg2, 1, 0, alu->src3_reg_negate, alu->abs_constants,
|
||||
type);
|
||||
output->append(".%c", chan_names[swiz_b]);
|
||||
output->AppendFormat(".%c", chan_names[swiz_b]);
|
||||
} else {
|
||||
print_srcreg(output, alu->src3_reg, alu->src3_sel, alu->src3_swiz,
|
||||
alu->src3_reg_negate, alu->abs_constants, type);
|
||||
}
|
||||
if (alu->scalar_clamp) {
|
||||
output->append(" CLAMP");
|
||||
output->Append(" CLAMP");
|
||||
}
|
||||
if (alu->export_data) {
|
||||
print_export_comment(output, alu->scalar_dest, type);
|
||||
}
|
||||
output->append("\n");
|
||||
output->Append('\n');
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -353,115 +337,117 @@ struct {
|
|||
} fetch_types[0xff] = {
|
||||
#define TYPE(id) \
|
||||
{ #id }
|
||||
TYPE(FMT_1_REVERSE), // 0
|
||||
{0},
|
||||
TYPE(FMT_8), // 2
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
TYPE(FMT_8_8_8_8), // 6
|
||||
TYPE(FMT_2_10_10_10), // 7
|
||||
{0},
|
||||
{0},
|
||||
TYPE(FMT_8_8), // 10
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
TYPE(FMT_16), // 24
|
||||
TYPE(FMT_16_16), // 25
|
||||
TYPE(FMT_16_16_16_16), // 26
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
TYPE(FMT_32), // 33
|
||||
TYPE(FMT_32_32), // 34
|
||||
TYPE(FMT_32_32_32_32), // 35
|
||||
TYPE(FMT_32_FLOAT), // 36
|
||||
TYPE(FMT_32_32_FLOAT), // 37
|
||||
TYPE(FMT_32_32_32_32_FLOAT), // 38
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
TYPE(FMT_32_32_32_FLOAT), // 57
|
||||
TYPE(FMT_1_REVERSE), // 0
|
||||
{0},
|
||||
TYPE(FMT_8), // 2
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
TYPE(FMT_8_8_8_8), // 6
|
||||
TYPE(FMT_2_10_10_10), // 7
|
||||
{0},
|
||||
{0},
|
||||
TYPE(FMT_8_8), // 10
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
TYPE(FMT_16), // 24
|
||||
TYPE(FMT_16_16), // 25
|
||||
TYPE(FMT_16_16_16_16), // 26
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
TYPE(FMT_32), // 33
|
||||
TYPE(FMT_32_32), // 34
|
||||
TYPE(FMT_32_32_32_32), // 35
|
||||
TYPE(FMT_32_FLOAT), // 36
|
||||
TYPE(FMT_32_32_FLOAT), // 37
|
||||
TYPE(FMT_32_32_32_32_FLOAT), // 38
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
{0},
|
||||
TYPE(FMT_32_32_32_FLOAT), // 57
|
||||
#undef TYPE
|
||||
};
|
||||
|
||||
void print_fetch_dst(Output* output, uint32_t dst_reg, uint32_t dst_swiz) {
|
||||
output->append("\tR%u.", dst_reg);
|
||||
void print_fetch_dst(StringBuffer* output, uint32_t dst_reg,
|
||||
uint32_t dst_swiz) {
|
||||
output->AppendFormat("\tR%u.", dst_reg);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
output->append("%c", chan_names[dst_swiz & 0x7]);
|
||||
output->Append(chan_names[dst_swiz & 0x7]);
|
||||
dst_swiz >>= 3;
|
||||
}
|
||||
}
|
||||
|
||||
void print_fetch_vtx(Output* output, const instr_fetch_t* fetch) {
|
||||
void print_fetch_vtx(StringBuffer* output, const instr_fetch_t* fetch) {
|
||||
const instr_fetch_vtx_t* vtx = &fetch->vtx;
|
||||
|
||||
if (vtx->pred_select) {
|
||||
// seems to work similar to conditional execution in ARM instruction
|
||||
// set, so let's use a similar syntax for now:
|
||||
output->append(vtx->pred_condition ? "EQ" : "NE");
|
||||
output->Append(vtx->pred_condition ? "EQ" : "NE");
|
||||
}
|
||||
|
||||
print_fetch_dst(output, vtx->dst_reg, vtx->dst_swiz);
|
||||
output->append(" = R%u.", vtx->src_reg);
|
||||
output->append("%c", chan_names[vtx->src_swiz & 0x3]);
|
||||
output->AppendFormat(" = R%u.", vtx->src_reg);
|
||||
output->Append(chan_names[vtx->src_swiz & 0x3]);
|
||||
if (fetch_types[vtx->format].name) {
|
||||
output->append(" %s", fetch_types[vtx->format].name);
|
||||
output->AppendFormat(" %s", fetch_types[vtx->format].name);
|
||||
} else {
|
||||
output->append(" TYPE(0x%x)", vtx->format);
|
||||
output->AppendFormat(" TYPE(0x%x)", vtx->format);
|
||||
}
|
||||
output->append(" %s", vtx->format_comp_all ? "SIGNED" : "UNSIGNED");
|
||||
output->AppendFormat(" %s", vtx->format_comp_all ? "SIGNED" : "UNSIGNED");
|
||||
if (!vtx->num_format_all) {
|
||||
output->append(" NORMALIZED");
|
||||
output->Append(" NORMALIZED");
|
||||
}
|
||||
output->append(" STRIDE(%u)", vtx->stride);
|
||||
output->AppendFormat(" STRIDE(%u)", vtx->stride);
|
||||
if (vtx->offset) {
|
||||
output->append(" OFFSET(%u)", vtx->offset);
|
||||
output->AppendFormat(" OFFSET(%u)", vtx->offset);
|
||||
}
|
||||
output->append(" CONST(%u, %u)", vtx->const_index, vtx->const_index_sel);
|
||||
output->AppendFormat(" CONST(%u, %u)", vtx->const_index,
|
||||
vtx->const_index_sel);
|
||||
if (vtx->pred_select) {
|
||||
output->append(" COND(%d)", vtx->pred_condition);
|
||||
output->AppendFormat(" COND(%d)", vtx->pred_condition);
|
||||
}
|
||||
if (1) {
|
||||
// XXX
|
||||
output->append(" src_reg_am=%u", vtx->src_reg_am);
|
||||
output->append(" dst_reg_am=%u", vtx->dst_reg_am);
|
||||
output->append(" num_format_all=%u", vtx->num_format_all);
|
||||
output->append(" signed_rf_mode_all=%u", vtx->signed_rf_mode_all);
|
||||
output->append(" exp_adjust_all=%u", vtx->exp_adjust_all);
|
||||
output->AppendFormat(" src_reg_am=%u", vtx->src_reg_am);
|
||||
output->AppendFormat(" dst_reg_am=%u", vtx->dst_reg_am);
|
||||
output->AppendFormat(" num_format_all=%u", vtx->num_format_all);
|
||||
output->AppendFormat(" signed_rf_mode_all=%u", vtx->signed_rf_mode_all);
|
||||
output->AppendFormat(" exp_adjust_all=%u", vtx->exp_adjust_all);
|
||||
}
|
||||
}
|
||||
|
||||
void print_fetch_tex(Output* output, const instr_fetch_t* fetch) {
|
||||
void print_fetch_tex(StringBuffer* output, const instr_fetch_t* fetch) {
|
||||
static const char* filter[] = {
|
||||
"POINT", // TEX_FILTER_POINT
|
||||
"LINEAR", // TEX_FILTER_LINEAR
|
||||
|
@ -493,219 +479,215 @@ void print_fetch_tex(Output* output, const instr_fetch_t* fetch) {
|
|||
if (tex->pred_select) {
|
||||
// seems to work similar to conditional execution in ARM instruction
|
||||
// set, so let's use a similar syntax for now:
|
||||
output->append(tex->pred_condition ? "EQ" : "NE");
|
||||
output->Append(tex->pred_condition ? "EQ" : "NE");
|
||||
}
|
||||
|
||||
print_fetch_dst(output, tex->dst_reg, tex->dst_swiz);
|
||||
output->append(" = R%u.", tex->src_reg);
|
||||
output->AppendFormat(" = R%u.", tex->src_reg);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
output->append("%c", chan_names[src_swiz & 0x3]);
|
||||
output->Append(chan_names[src_swiz & 0x3]);
|
||||
src_swiz >>= 2;
|
||||
}
|
||||
output->append(" CONST(%u)", tex->const_idx);
|
||||
output->AppendFormat(" CONST(%u)", tex->const_idx);
|
||||
if (tex->fetch_valid_only) {
|
||||
output->append(" VALID_ONLY");
|
||||
output->Append(" VALID_ONLY");
|
||||
}
|
||||
if (tex->tx_coord_denorm) {
|
||||
output->append(" DENORM");
|
||||
output->Append(" DENORM");
|
||||
}
|
||||
if (tex->mag_filter != TEX_FILTER_USE_FETCH_CONST) {
|
||||
output->append(" MAG(%s)", filter[tex->mag_filter]);
|
||||
output->AppendFormat(" MAG(%s)", filter[tex->mag_filter]);
|
||||
}
|
||||
if (tex->min_filter != TEX_FILTER_USE_FETCH_CONST) {
|
||||
output->append(" MIN(%s)", filter[tex->min_filter]);
|
||||
output->AppendFormat(" MIN(%s)", filter[tex->min_filter]);
|
||||
}
|
||||
if (tex->mip_filter != TEX_FILTER_USE_FETCH_CONST) {
|
||||
output->append(" MIP(%s)", filter[tex->mip_filter]);
|
||||
output->AppendFormat(" MIP(%s)", filter[tex->mip_filter]);
|
||||
}
|
||||
if (tex->aniso_filter != ANISO_FILTER_USE_FETCH_CONST) {
|
||||
output->append(" ANISO(%s)", aniso_filter[tex->aniso_filter]);
|
||||
output->AppendFormat(" ANISO(%s)", aniso_filter[tex->aniso_filter]);
|
||||
}
|
||||
if (tex->arbitrary_filter != ARBITRARY_FILTER_USE_FETCH_CONST) {
|
||||
output->append(" ARBITRARY(%s)", arbitrary_filter[tex->arbitrary_filter]);
|
||||
output->AppendFormat(" ARBITRARY(%s)",
|
||||
arbitrary_filter[tex->arbitrary_filter]);
|
||||
}
|
||||
if (tex->vol_mag_filter != TEX_FILTER_USE_FETCH_CONST) {
|
||||
output->append(" VOL_MAG(%s)", filter[tex->vol_mag_filter]);
|
||||
output->AppendFormat(" VOL_MAG(%s)", filter[tex->vol_mag_filter]);
|
||||
}
|
||||
if (tex->vol_min_filter != TEX_FILTER_USE_FETCH_CONST) {
|
||||
output->append(" VOL_MIN(%s)", filter[tex->vol_min_filter]);
|
||||
output->AppendFormat(" VOL_MIN(%s)", filter[tex->vol_min_filter]);
|
||||
}
|
||||
if (!tex->use_comp_lod) {
|
||||
output->append(" LOD(%u)", tex->use_comp_lod);
|
||||
output->append(" LOD_BIAS(%u)", tex->lod_bias);
|
||||
output->AppendFormat(" LOD(%u)", tex->use_comp_lod);
|
||||
output->AppendFormat(" LOD_BIAS(%u)", tex->lod_bias);
|
||||
}
|
||||
if (tex->use_reg_lod) {
|
||||
output->append(" REG_LOD(%u)", tex->use_reg_lod);
|
||||
output->AppendFormat(" REG_LOD(%u)", tex->use_reg_lod);
|
||||
}
|
||||
if (tex->use_reg_gradients) {
|
||||
output->append(" USE_REG_GRADIENTS");
|
||||
output->Append(" USE_REG_GRADIENTS");
|
||||
}
|
||||
output->append(" LOCATION(%s)", sample_loc[tex->sample_location]);
|
||||
output->AppendFormat(" LOCATION(%s)", sample_loc[tex->sample_location]);
|
||||
if (tex->offset_x || tex->offset_y || tex->offset_z) {
|
||||
output->append(" OFFSET(%u,%u,%u)", tex->offset_x, tex->offset_y,
|
||||
tex->offset_z);
|
||||
output->AppendFormat(" OFFSET(%u,%u,%u)", tex->offset_x, tex->offset_y,
|
||||
tex->offset_z);
|
||||
}
|
||||
if (tex->pred_select) {
|
||||
output->append(" COND(%d)", tex->pred_condition);
|
||||
output->AppendFormat(" COND(%d)", tex->pred_condition);
|
||||
}
|
||||
}
|
||||
|
||||
struct {
|
||||
const char* name;
|
||||
void (*fxn)(Output* output, const instr_fetch_t* cf);
|
||||
void (*fxn)(StringBuffer* output, const instr_fetch_t* cf);
|
||||
} fetch_instructions[] = {
|
||||
#define INSTR(opc, name, fxn) \
|
||||
{ name, fxn }
|
||||
INSTR(VTX_FETCH, "VERTEX", print_fetch_vtx), // 0
|
||||
INSTR(TEX_FETCH, "SAMPLE", print_fetch_tex), // 1
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
INSTR(TEX_GET_BORDER_COLOR_FRAC, "?", print_fetch_tex), // 16
|
||||
INSTR(TEX_GET_COMP_TEX_LOD, "?", print_fetch_tex), // 17
|
||||
INSTR(TEX_GET_GRADIENTS, "?", print_fetch_tex), // 18
|
||||
INSTR(TEX_GET_WEIGHTS, "?", print_fetch_tex), // 19
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
INSTR(TEX_SET_TEX_LOD, "SET_TEX_LOD", print_fetch_tex), // 24
|
||||
INSTR(TEX_SET_GRADIENTS_H, "?", print_fetch_tex), // 25
|
||||
INSTR(TEX_SET_GRADIENTS_V, "?", print_fetch_tex), // 26
|
||||
INSTR(TEX_RESERVED_4, "?", print_fetch_tex), // 27
|
||||
INSTR(VTX_FETCH, "VERTEX", print_fetch_vtx), // 0
|
||||
INSTR(TEX_FETCH, "SAMPLE", print_fetch_tex), // 1
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
INSTR(TEX_GET_BORDER_COLOR_FRAC, "?", print_fetch_tex), // 16
|
||||
INSTR(TEX_GET_COMP_TEX_LOD, "?", print_fetch_tex), // 17
|
||||
INSTR(TEX_GET_GRADIENTS, "?", print_fetch_tex), // 18
|
||||
INSTR(TEX_GET_WEIGHTS, "?", print_fetch_tex), // 19
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
INSTR(TEX_SET_TEX_LOD, "SET_TEX_LOD", print_fetch_tex), // 24
|
||||
INSTR(TEX_SET_GRADIENTS_H, "?", print_fetch_tex), // 25
|
||||
INSTR(TEX_SET_GRADIENTS_V, "?", print_fetch_tex), // 26
|
||||
INSTR(TEX_RESERVED_4, "?", print_fetch_tex), // 27
|
||||
#undef INSTR
|
||||
};
|
||||
|
||||
int disasm_fetch(Output* output, const uint32_t* dwords, uint32_t alu_off,
|
||||
int disasm_fetch(StringBuffer* output, const uint32_t* dwords, uint32_t alu_off,
|
||||
int level, int sync) {
|
||||
const instr_fetch_t* fetch = (const instr_fetch_t*)dwords;
|
||||
|
||||
output->append("%s", levels[level]);
|
||||
output->append("%02x: %08x %08x %08x\t", alu_off, dwords[0], dwords[1],
|
||||
dwords[2]);
|
||||
output->Append(levels[level]);
|
||||
output->AppendFormat("%02x: %08x %08x %08x\t", alu_off, dwords[0], dwords[1],
|
||||
dwords[2]);
|
||||
|
||||
output->append(" %sFETCH:\t", sync ? "(S)" : " ");
|
||||
output->AppendFormat(" %sFETCH:\t", sync ? "(S)" : " ");
|
||||
if (fetch_instructions[fetch->opc].fxn) {
|
||||
output->append("%s", fetch_instructions[fetch->opc].name);
|
||||
output->Append(fetch_instructions[fetch->opc].name);
|
||||
fetch_instructions[fetch->opc].fxn(output, fetch);
|
||||
} else {
|
||||
output->append("???");
|
||||
output->Append("???");
|
||||
}
|
||||
output->append("\n");
|
||||
output->Append('\n');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void print_cf_nop(Output* output, const instr_cf_t* cf) {}
|
||||
void print_cf_nop(StringBuffer* output, const instr_cf_t* cf) {}
|
||||
|
||||
void print_cf_exec(Output* output, const instr_cf_t* cf) {
|
||||
output->append(" ADDR(0x%x) CNT(0x%x)", cf->exec.address, cf->exec.count);
|
||||
void print_cf_exec(StringBuffer* output, const instr_cf_t* cf) {
|
||||
output->AppendFormat(" ADDR(0x%x) CNT(0x%x)", cf->exec.address,
|
||||
cf->exec.count);
|
||||
if (cf->exec.yeild) {
|
||||
output->append(" YIELD");
|
||||
output->Append(" YIELD");
|
||||
}
|
||||
uint8_t vc = cf->exec.vc_hi | (cf->exec.vc_lo << 2);
|
||||
if (vc) {
|
||||
output->append(" VC(0x%x)", vc);
|
||||
output->AppendFormat(" VC(0x%x)", vc);
|
||||
}
|
||||
if (cf->exec.bool_addr) {
|
||||
output->append(" BOOL_ADDR(0x%x)", cf->exec.bool_addr);
|
||||
output->AppendFormat(" BOOL_ADDR(0x%x)", cf->exec.bool_addr);
|
||||
}
|
||||
if (cf->exec.address_mode == ABSOLUTE_ADDR) {
|
||||
output->append(" ABSOLUTE_ADDR");
|
||||
output->Append(" ABSOLUTE_ADDR");
|
||||
}
|
||||
if (cf->is_cond_exec()) {
|
||||
output->append(" COND(%d)", cf->exec.pred_condition);
|
||||
output->AppendFormat(" COND(%d)", cf->exec.pred_condition);
|
||||
}
|
||||
}
|
||||
|
||||
void print_cf_loop(Output* output, const instr_cf_t* cf) {
|
||||
output->append(" ADDR(0x%x) LOOP_ID(%d)", cf->loop.address, cf->loop.loop_id);
|
||||
void print_cf_loop(StringBuffer* output, const instr_cf_t* cf) {
|
||||
output->AppendFormat(" ADDR(0x%x) LOOP_ID(%d)", cf->loop.address,
|
||||
cf->loop.loop_id);
|
||||
if (cf->loop.address_mode == ABSOLUTE_ADDR) {
|
||||
output->append(" ABSOLUTE_ADDR");
|
||||
output->Append(" ABSOLUTE_ADDR");
|
||||
}
|
||||
}
|
||||
|
||||
void print_cf_jmp_call(Output* output, const instr_cf_t* cf) {
|
||||
output->append(" ADDR(0x%x) DIR(%d)", cf->jmp_call.address,
|
||||
cf->jmp_call.direction);
|
||||
void print_cf_jmp_call(StringBuffer* output, const instr_cf_t* cf) {
|
||||
output->AppendFormat(" ADDR(0x%x) DIR(%d)", cf->jmp_call.address,
|
||||
cf->jmp_call.direction);
|
||||
if (cf->jmp_call.force_call) {
|
||||
output->append(" FORCE_CALL");
|
||||
output->Append(" FORCE_CALL");
|
||||
}
|
||||
if (cf->jmp_call.predicated_jmp) {
|
||||
output->append(" COND(%d)", cf->jmp_call.condition);
|
||||
output->AppendFormat(" COND(%d)", cf->jmp_call.condition);
|
||||
}
|
||||
if (cf->jmp_call.bool_addr) {
|
||||
output->append(" BOOL_ADDR(0x%x)", cf->jmp_call.bool_addr);
|
||||
output->AppendFormat(" BOOL_ADDR(0x%x)", cf->jmp_call.bool_addr);
|
||||
}
|
||||
if (cf->jmp_call.address_mode == ABSOLUTE_ADDR) {
|
||||
output->append(" ABSOLUTE_ADDR");
|
||||
output->Append(" ABSOLUTE_ADDR");
|
||||
}
|
||||
}
|
||||
|
||||
void print_cf_alloc(Output* output, const instr_cf_t* cf) {
|
||||
void print_cf_alloc(StringBuffer* output, const instr_cf_t* cf) {
|
||||
static const char* bufname[] = {
|
||||
"NO ALLOC", // SQ_NO_ALLOC
|
||||
"POSITION", // SQ_POSITION
|
||||
"PARAM/PIXEL", // SQ_PARAMETER_PIXEL
|
||||
"MEMORY", // SQ_MEMORY
|
||||
};
|
||||
output->append(" %s SIZE(0x%x)", bufname[cf->alloc.buffer_select],
|
||||
cf->alloc.size);
|
||||
output->AppendFormat(" %s SIZE(0x%x)", bufname[cf->alloc.buffer_select],
|
||||
cf->alloc.size);
|
||||
if (cf->alloc.no_serial) {
|
||||
output->append(" NO_SERIAL");
|
||||
output->Append(" NO_SERIAL");
|
||||
}
|
||||
if (cf->alloc.alloc_mode) {
|
||||
// ???
|
||||
output->append(" ALLOC_MODE");
|
||||
output->Append(" ALLOC_MODE");
|
||||
}
|
||||
}
|
||||
|
||||
struct {
|
||||
const char* name;
|
||||
void (*fxn)(Output* output, const instr_cf_t* cf);
|
||||
void (*fxn)(StringBuffer* output, const instr_cf_t* cf);
|
||||
} cf_instructions[] = {
|
||||
#define INSTR(opc, fxn) \
|
||||
{ #opc, fxn }
|
||||
INSTR(NOP, print_cf_nop),
|
||||
INSTR(EXEC, print_cf_exec),
|
||||
INSTR(EXEC_END, print_cf_exec),
|
||||
INSTR(COND_EXEC, print_cf_exec),
|
||||
INSTR(COND_EXEC_END, print_cf_exec),
|
||||
INSTR(COND_PRED_EXEC, print_cf_exec),
|
||||
INSTR(COND_PRED_EXEC_END, print_cf_exec),
|
||||
INSTR(LOOP_START, print_cf_loop),
|
||||
INSTR(LOOP_END, print_cf_loop),
|
||||
INSTR(COND_CALL, print_cf_jmp_call),
|
||||
INSTR(RETURN, print_cf_jmp_call),
|
||||
INSTR(COND_JMP, print_cf_jmp_call),
|
||||
INSTR(ALLOC, print_cf_alloc),
|
||||
INSTR(COND_EXEC_PRED_CLEAN, print_cf_exec),
|
||||
INSTR(COND_EXEC_PRED_CLEAN_END, print_cf_exec),
|
||||
INSTR(MARK_VS_FETCH_DONE, print_cf_nop), // ??
|
||||
INSTR(NOP, print_cf_nop), INSTR(EXEC, print_cf_exec),
|
||||
INSTR(EXEC_END, print_cf_exec), INSTR(COND_EXEC, print_cf_exec),
|
||||
INSTR(COND_EXEC_END, print_cf_exec), INSTR(COND_PRED_EXEC, print_cf_exec),
|
||||
INSTR(COND_PRED_EXEC_END, print_cf_exec), INSTR(LOOP_START, print_cf_loop),
|
||||
INSTR(LOOP_END, print_cf_loop), INSTR(COND_CALL, print_cf_jmp_call),
|
||||
INSTR(RETURN, print_cf_jmp_call), INSTR(COND_JMP, print_cf_jmp_call),
|
||||
INSTR(ALLOC, print_cf_alloc), INSTR(COND_EXEC_PRED_CLEAN, print_cf_exec),
|
||||
INSTR(COND_EXEC_PRED_CLEAN_END, print_cf_exec),
|
||||
INSTR(MARK_VS_FETCH_DONE, print_cf_nop), // ??
|
||||
#undef INSTR
|
||||
};
|
||||
|
||||
static void print_cf(Output* output, const instr_cf_t* cf, int level) {
|
||||
output->append("%s", levels[level]);
|
||||
static void print_cf(StringBuffer* output, const instr_cf_t* cf, int level) {
|
||||
output->Append(levels[level]);
|
||||
|
||||
const uint16_t* words = (uint16_t*)cf;
|
||||
output->append(" %04x %04x %04x \t", words[0], words[1],
|
||||
words[2]);
|
||||
output->AppendFormat(" %04x %04x %04x \t", words[0], words[1],
|
||||
words[2]);
|
||||
|
||||
output->append("%s", cf_instructions[cf->opc].name);
|
||||
output->AppendFormat(cf_instructions[cf->opc].name);
|
||||
cf_instructions[cf->opc].fxn(output, cf);
|
||||
output->append("\n");
|
||||
output->Append('\n');
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -714,8 +696,9 @@ static void print_cf(Output* output, const instr_cf_t* cf, int level) {
|
|||
* which refers to ALU/FETCH instructions that follow it by address.
|
||||
* 2) ALU and FETCH instructions
|
||||
*/
|
||||
void disasm_exec(Output* output, const uint32_t* dwords, size_t dword_count,
|
||||
int level, ShaderType type, const instr_cf_t* cf) {
|
||||
void disasm_exec(StringBuffer* output, const uint32_t* dwords,
|
||||
size_t dword_count, int level, ShaderType type,
|
||||
const instr_cf_t* cf) {
|
||||
uint32_t sequence = cf->exec.serialize;
|
||||
for (uint32_t i = 0; i < cf->exec.count; i++) {
|
||||
uint32_t alu_off = (cf->exec.address + i);
|
||||
|
@ -732,7 +715,7 @@ void disasm_exec(Output* output, const uint32_t* dwords, size_t dword_count,
|
|||
|
||||
std::string DisassembleShader(ShaderType type, const uint32_t* dwords,
|
||||
size_t dword_count) {
|
||||
Output* output = new Output();
|
||||
StringBuffer string_buffer(256 * 1024);
|
||||
|
||||
instr_cf_t cfa;
|
||||
instr_cf_t cfb;
|
||||
|
@ -744,22 +727,20 @@ std::string DisassembleShader(ShaderType type, const uint32_t* dwords,
|
|||
cfa.dword_1 = dword_1 & 0xFFFF;
|
||||
cfb.dword_0 = (dword_1 >> 16) | (dword_2 << 16);
|
||||
cfb.dword_1 = dword_2 >> 16;
|
||||
print_cf(output, &cfa, 0);
|
||||
print_cf(&string_buffer, &cfa, 0);
|
||||
if (cfa.is_exec()) {
|
||||
disasm_exec(output, dwords, dword_count, 0, type, &cfa);
|
||||
disasm_exec(&string_buffer, dwords, dword_count, 0, type, &cfa);
|
||||
}
|
||||
print_cf(output, &cfb, 0);
|
||||
print_cf(&string_buffer, &cfb, 0);
|
||||
if (cfb.is_exec()) {
|
||||
disasm_exec(output, dwords, dword_count, 0, type, &cfb);
|
||||
disasm_exec(&string_buffer, dwords, dword_count, 0, type, &cfb);
|
||||
}
|
||||
if (cfa.opc == EXEC_END || cfb.opc == EXEC_END) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto result = std::string(output->buffer);
|
||||
delete output;
|
||||
return result;
|
||||
return string_buffer.to_string();
|
||||
}
|
||||
|
||||
} // namespace gpu
|
||||
|
|
Loading…
Reference in New Issue