mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 13:30:02 +00:00
unittest: Have the JIT harness print disassembly, to make it easy to inspect results.
This commit is contained in:
parent
450227b2c6
commit
5bcdecc26b
@ -15,8 +15,67 @@
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "JitCommon.h"
|
||||
|
||||
#include "ext/disarm.h"
|
||||
#include "ext/udis86/udis86.h"
|
||||
|
||||
namespace MIPSComp {
|
||||
Jit *jit;
|
||||
}
|
||||
|
||||
// We compile this for x86 as well because it may be useful when developing the ARM JIT on a PC.
|
||||
std::vector<std::string> DisassembleArm2(const u8 *data, int size) {
|
||||
std::vector<std::string> lines;
|
||||
|
||||
char temp[256];
|
||||
for (int i = 0; i < size; i += 4) {
|
||||
const u32 *codePtr = (const u32 *)(data + i);
|
||||
u32 inst = codePtr[0];
|
||||
u32 next = (i < size - 4) ? codePtr[1] : 0;
|
||||
// MAGIC SPECIAL CASE for MOVW/MOVT readability!
|
||||
if ((inst & 0x0FF00000) == 0x03000000 && (next & 0x0FF00000) == 0x03400000) {
|
||||
u32 low = ((inst & 0x000F0000) >> 4) | (inst & 0x0FFF);
|
||||
u32 hi = ((next & 0x000F0000) >> 4) | (next & 0x0FFF);
|
||||
int reg0 = (inst & 0x0000F000) >> 12;
|
||||
int reg1 = (next & 0x0000F000) >> 12;
|
||||
if (reg0 == reg1) {
|
||||
sprintf(temp, "MOV32 %s, %04x%04x", ArmRegName(reg0), hi, low);
|
||||
// sprintf(temp, "%08x MOV32? %s, %04x%04x", (u32)inst, ArmRegName(reg0), hi, low);
|
||||
lines.push_back(temp);
|
||||
i += 4;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ArmDis((u32)(intptr_t)codePtr, inst, temp, sizeof(temp), false);
|
||||
std::string buf = temp;
|
||||
lines.push_back(buf);
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
#ifndef ARM
|
||||
|
||||
std::vector<std::string> DisassembleX86(const u8 *data, int size) {
|
||||
std::vector<std::string> lines;
|
||||
ud_t ud_obj;
|
||||
ud_init(&ud_obj);
|
||||
#ifdef _M_X64
|
||||
ud_set_mode(&ud_obj, 64);
|
||||
#else
|
||||
ud_set_mode(&ud_obj, 32);
|
||||
#endif
|
||||
ud_set_pc(&ud_obj, (intptr_t)data);
|
||||
ud_set_vendor(&ud_obj, UD_VENDOR_ANY);
|
||||
ud_set_syntax(&ud_obj, UD_SYN_INTEL);
|
||||
|
||||
ud_set_input_buffer(&ud_obj, data, size);
|
||||
while (ud_disassemble(&ud_obj) != 0) {
|
||||
lines.push_back(ud_insn_asm(&ud_obj));
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
#endif
|
@ -17,6 +17,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "Common/Common.h"
|
||||
|
||||
struct JitBlock;
|
||||
@ -56,3 +59,6 @@ struct JitBlock;
|
||||
namespace MIPSComp {
|
||||
extern Jit *jit;
|
||||
}
|
||||
|
||||
std::vector<std::string> DisassembleArm2(const u8 *data, int size);
|
||||
std::vector<std::string> DisassembleX86(const u8 *data, int size);
|
||||
|
@ -24,8 +24,6 @@
|
||||
#include "ui/view.h"
|
||||
#include "ui/viewgroup.h"
|
||||
#include "ui/ui.h"
|
||||
#include "ext/disarm.h"
|
||||
#include "ext/udis86/udis86.h"
|
||||
|
||||
#include "Common/LogManager.h"
|
||||
#include "Common/CPUDetect.h"
|
||||
@ -432,37 +430,6 @@ void JitCompareScreen::CreateViews() {
|
||||
OnCurrentBlock(ignore);
|
||||
}
|
||||
|
||||
#ifdef ARM
|
||||
std::vector<std::string> DisassembleArm2(const u8 *data, int size) {
|
||||
std::vector<std::string> lines;
|
||||
|
||||
char temp[256];
|
||||
for (int i = 0; i < size; i += 4) {
|
||||
const u32 *codePtr = (const u32 *)(data + i);
|
||||
u32 inst = codePtr[0];
|
||||
u32 next = (i < size - 4) ? codePtr[1] : 0;
|
||||
// MAGIC SPECIAL CASE for MOVW/MOVT readability!
|
||||
if ((inst & 0x0FF00000) == 0x03000000 && (next & 0x0FF00000) == 0x03400000) {
|
||||
u32 low = ((inst & 0x000F0000) >> 4) | (inst & 0x0FFF);
|
||||
u32 hi = ((next & 0x000F0000) >> 4) | (next & 0x0FFF);
|
||||
int reg0 = (inst & 0x0000F000) >> 12;
|
||||
int reg1 = (next & 0x0000F000) >> 12;
|
||||
if (reg0 == reg1) {
|
||||
sprintf(temp, "MOV32 %s, %04x%04x", ArmRegName(reg0), hi, low);
|
||||
// sprintf(temp, "%08x MOV32? %s, %04x%04x", (u32)inst, ArmRegName(reg0), hi, low);
|
||||
lines.push_back(temp);
|
||||
i += 4;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ArmDis((u32)(intptr_t)codePtr, inst, temp, sizeof(temp), false);
|
||||
std::string buf = temp;
|
||||
lines.push_back(buf);
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
#endif
|
||||
|
||||
void JitCompareScreen::UpdateDisasm() {
|
||||
leftDisasm_->Clear();
|
||||
rightDisasm_->Clear();
|
||||
@ -494,26 +461,12 @@ void JitCompareScreen::UpdateDisasm() {
|
||||
|
||||
#if defined(ARM)
|
||||
std::vector<std::string> targetDis = DisassembleArm2(block->normalEntry, block->codeSize);
|
||||
#else
|
||||
std::vector<std::string> targetDis = DisassembleX86(block->normalEntry, block->codeSize);
|
||||
#endif
|
||||
for (size_t i = 0; i < targetDis.size(); i++) {
|
||||
rightDisasm_->Add(new TextView(targetDis[i]));
|
||||
}
|
||||
#else
|
||||
ud_t ud_obj;
|
||||
ud_init(&ud_obj);
|
||||
#ifdef _M_X64
|
||||
ud_set_mode(&ud_obj, 64);
|
||||
#else
|
||||
ud_set_mode(&ud_obj, 32);
|
||||
#endif
|
||||
ud_set_pc(&ud_obj, (intptr_t)block->normalEntry);
|
||||
ud_set_vendor(&ud_obj, UD_VENDOR_ANY);
|
||||
ud_set_syntax(&ud_obj, UD_SYN_INTEL);
|
||||
|
||||
ud_set_input_buffer(&ud_obj, block->normalEntry, block->codeSize);
|
||||
while (ud_disassemble(&ud_obj) != 0) {
|
||||
rightDisasm_->Add(new TextView(ud_insn_asm(&ud_obj)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
UI::EventReturn JitCompareScreen::OnSelectBlock(UI::EventParams &e) {
|
||||
|
@ -138,6 +138,10 @@ static std::vector<PendingMessage> pendingMessages;
|
||||
static Thin3DContext *thin3d;
|
||||
static UIContext *uiContext;
|
||||
|
||||
Thin3DContext *GetThin3D() {
|
||||
return thin3d;
|
||||
}
|
||||
|
||||
std::thread *graphicsLoadThread;
|
||||
|
||||
class AndroidLogger : public LogListener {
|
||||
|
@ -15,6 +15,8 @@
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "base/timeutil.h"
|
||||
#include "Core/MIPS/JitCommon/JitCommon.h"
|
||||
#include "Core/MIPS/MIPSCodeUtils.h"
|
||||
@ -128,6 +130,7 @@ bool TestJit() {
|
||||
*p++ = 0xD03C0000 | (1 << 7) | (1 << 15) | (7 << 8);
|
||||
*/
|
||||
for (size_t j = 0; j < ARRAY_SIZE(lines); ++j) {
|
||||
if (i == 0) printf("%s\n", lines[j]);
|
||||
if (!MIPSAsm::MipsAssembleOpcode(lines[j], currentDebugMIPS, addr, *p++)) {
|
||||
printf("ERROR: %s\n", MIPSAsm::GetAssembleError());
|
||||
compileSuccess = false;
|
||||
@ -139,15 +142,34 @@ bool TestJit() {
|
||||
*p++ = MIPS_MAKE_SYSCALL("UnitTestFakeSyscalls", "UnitTestTerminator");
|
||||
*p++ = MIPS_MAKE_BREAK(1);
|
||||
|
||||
printf("\n");
|
||||
|
||||
double jit_speed, interp_speed;
|
||||
if (compileSuccess) {
|
||||
interp_speed = ExecCPUTest();
|
||||
mipsr4k.UpdateCore(CPU_JIT);
|
||||
jit_speed = ExecCPUTest();
|
||||
|
||||
printf("Jit was %fx faster than interp.\n", jit_speed / interp_speed);
|
||||
// Disassemble
|
||||
JitBlockCache *cache = MIPSComp::jit->GetBlockCache();
|
||||
JitBlock *block = cache->GetBlock(0); // Should only be one block.
|
||||
#ifdef ARM
|
||||
std::vector<std::string> lines = DisassembleArm2(block->normalEntry, block->codeSize);
|
||||
#else
|
||||
std::vector<std::string> lines = DisassembleX86(block->normalEntry, block->codeSize);
|
||||
#endif
|
||||
printf("Jit was %fx faster than interp.\n\n", jit_speed / interp_speed);
|
||||
// Cut off at 25 due to the repetition above. Might need tweaking for large instructions.
|
||||
const int cutoff = 25;
|
||||
for (int i = 0; i < std::min((int)lines.size(), cutoff); i++) {
|
||||
printf("%s\n", lines[i].c_str());
|
||||
}
|
||||
if (lines.size() > cutoff)
|
||||
printf("...\n");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
DestroyJitHarness();
|
||||
|
||||
return jit_speed >= interp_speed;
|
||||
|
Loading…
Reference in New Issue
Block a user