Adding comments to the disasm and implementing kernel calls.
This commit is contained in:
parent
74ae66aa0a
commit
a81babac1e
|
@ -26,6 +26,8 @@ DEFINE_bool(memory_address_verification, false,
|
||||||
"Whether to add additional checks to generated memory load/stores.");
|
"Whether to add additional checks to generated memory load/stores.");
|
||||||
DEFINE_bool(log_codegen, false,
|
DEFINE_bool(log_codegen, false,
|
||||||
"Log codegen to stdout.");
|
"Log codegen to stdout.");
|
||||||
|
DEFINE_bool(annotate_disassembly, true,
|
||||||
|
"Annotate disassembled x64 code with comments.");
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -288,6 +290,9 @@ int X64Emitter::MakeFunction(FunctionSymbol* symbol) {
|
||||||
assembler_.getCode(), assembler_.getCodeSize());
|
assembler_.getCode(), assembler_.getCodeSize());
|
||||||
|
|
||||||
// Dump x64 assembly.
|
// Dump x64 assembly.
|
||||||
|
// This is not currently used as we are dumping from asmjit.
|
||||||
|
// This format is more concise and prettier (though it lacks comments).
|
||||||
|
#if 0
|
||||||
DISASM MyDisasm;
|
DISASM MyDisasm;
|
||||||
memset(&MyDisasm, 0, sizeof(MyDisasm));
|
memset(&MyDisasm, 0, sizeof(MyDisasm));
|
||||||
MyDisasm.Archi = 64;
|
MyDisasm.Archi = 64;
|
||||||
|
@ -302,6 +307,7 @@ int X64Emitter::MakeFunction(FunctionSymbol* symbol) {
|
||||||
XELOGCPU("%p %s", MyDisasm.EIP, MyDisasm.CompleteInstr);
|
XELOGCPU("%p %s", MyDisasm.EIP, MyDisasm.CompleteInstr);
|
||||||
MyDisasm.EIP += len;
|
MyDisasm.EIP += len;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
result_code = 0;
|
result_code = 0;
|
||||||
|
@ -315,42 +321,47 @@ XECLEANUP:
|
||||||
}
|
}
|
||||||
|
|
||||||
int X64Emitter::MakePresentImportFunction() {
|
int X64Emitter::MakePresentImportFunction() {
|
||||||
|
X86Compiler& c = compiler_;
|
||||||
|
|
||||||
TraceKernelCall();
|
TraceKernelCall();
|
||||||
|
|
||||||
// // void shim(ppc_state*, shim_data*)
|
void* shim = symbol_->kernel_export->function_data.shim;
|
||||||
// jit_value_t shim_args[] = {
|
void* shim_data = symbol_->kernel_export->function_data.shim_data;
|
||||||
// jit_value_get_param(fn_, 0),
|
|
||||||
// jit_value_create_long_constant(fn_, jit_type_ulong,
|
|
||||||
// (jit_ulong)symbol_->kernel_export->function_data.shim_data),
|
|
||||||
// };
|
|
||||||
// jit_insn_call_native(
|
|
||||||
// fn_,
|
|
||||||
// symbol_->kernel_export->name,
|
|
||||||
// symbol_->kernel_export->function_data.shim,
|
|
||||||
// shim_signature_,
|
|
||||||
// shim_args, XECOUNT(shim_args),
|
|
||||||
// 0);
|
|
||||||
|
|
||||||
// jit_insn_return(fn_, NULL);
|
// void shim(ppc_state*, shim_data*)
|
||||||
|
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
|
||||||
|
c.mov(arg1, imm((uint64_t)shim_data));
|
||||||
|
X86CompilerFuncCall* call = c.call(shim);
|
||||||
|
call->setComment(symbol_->kernel_export->name);
|
||||||
|
call->setPrototype(kX86FuncConvDefault,
|
||||||
|
FuncBuilder2<void, void*, uint64_t>());
|
||||||
|
call->setArgument(0, c.getGpArg(0));
|
||||||
|
call->setArgument(1, arg1);
|
||||||
|
|
||||||
|
c.ret();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int X64Emitter::MakeMissingImportFunction() {
|
int X64Emitter::MakeMissingImportFunction() {
|
||||||
|
X86Compiler& c = compiler_;
|
||||||
|
|
||||||
TraceKernelCall();
|
TraceKernelCall();
|
||||||
|
|
||||||
// TODO(benvanik): log better?
|
// TODO(benvanik): log better?
|
||||||
// jit_insn_return(fn_, NULL);
|
c.ret();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int X64Emitter::MakeUserFunction() {
|
int X64Emitter::MakeUserFunction() {
|
||||||
|
X86Compiler& c = compiler_;
|
||||||
|
|
||||||
TraceUserCall();
|
TraceUserCall();
|
||||||
|
|
||||||
// If this function is empty, abort!
|
// If this function is empty, abort!
|
||||||
if (!symbol_->blocks.size()) {
|
if (!symbol_->blocks.size()) {
|
||||||
// jit_insn_return(fn_, NULL);
|
c.ret();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,6 +500,8 @@ int X64Emitter::PrepareBasicBlock(FunctionBlock* block) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void X64Emitter::GenerateBasicBlock(FunctionBlock* block) {
|
void X64Emitter::GenerateBasicBlock(FunctionBlock* block) {
|
||||||
|
X86Compiler& c = compiler_;
|
||||||
|
|
||||||
fn_block_ = block;
|
fn_block_ = block;
|
||||||
|
|
||||||
// Create new block.
|
// Create new block.
|
||||||
|
@ -511,8 +524,36 @@ void X64Emitter::GenerateBasicBlock(FunctionBlock* block) {
|
||||||
i.type = ppc::GetInstrType(i.code);
|
i.type = ppc::GetInstrType(i.code);
|
||||||
|
|
||||||
// Add debugging tag.
|
// Add debugging tag.
|
||||||
// TODO(benvanik): mark type.
|
// TODO(benvanik): add debugging info?
|
||||||
//jit_insn_mark_breakpoint(fn_, 1, ia);
|
|
||||||
|
if (FLAGS_log_codegen || FLAGS_annotate_disassembly) {
|
||||||
|
if (!i.type) {
|
||||||
|
if (FLAGS_log_codegen) {
|
||||||
|
printf("%.8X: %.8X ???", ia, i.code);
|
||||||
|
}
|
||||||
|
if (FLAGS_annotate_disassembly) {
|
||||||
|
c.comment("%.8X: %.8X ???", ia, i.code);
|
||||||
|
}
|
||||||
|
} else if (i.type->disassemble) {
|
||||||
|
ppc::InstrDisasm d;
|
||||||
|
i.type->disassemble(i, d);
|
||||||
|
std::string disasm;
|
||||||
|
d.Dump(disasm);
|
||||||
|
if (FLAGS_log_codegen) {
|
||||||
|
printf(" %.8X: %.8X %s\n", ia, i.code, disasm.c_str());
|
||||||
|
}
|
||||||
|
if (FLAGS_annotate_disassembly) {
|
||||||
|
c.comment("%.8X: %.8X %s", ia, i.code, disasm.c_str());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (FLAGS_log_codegen) {
|
||||||
|
printf(" %.8X: %.8X %s ???\n", ia, i.code, i.type->name);
|
||||||
|
}
|
||||||
|
if (FLAGS_annotate_disassembly) {
|
||||||
|
c.comment("%.8X: %.8X %s ???", ia, i.code, i.type->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TraceInstruction(i);
|
TraceInstruction(i);
|
||||||
|
|
||||||
|
@ -522,18 +563,6 @@ void X64Emitter::GenerateBasicBlock(FunctionBlock* block) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FLAGS_log_codegen) {
|
|
||||||
if (i.type->disassemble) {
|
|
||||||
ppc::InstrDisasm d;
|
|
||||||
i.type->disassemble(i, d);
|
|
||||||
std::string disasm;
|
|
||||||
d.Dump(disasm);
|
|
||||||
printf(" %.8X: %.8X %s\n", ia, i.code, disasm.c_str());
|
|
||||||
} else {
|
|
||||||
printf(" %.8X: %.8X %s ???\n", ia, i.code, i.type->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef int (*InstrEmitter)(X64Emitter& g, Compiler& c, InstrData& i);
|
typedef int (*InstrEmitter)(X64Emitter& g, Compiler& c, InstrData& i);
|
||||||
InstrEmitter emit = (InstrEmitter)i.type->emit;
|
InstrEmitter emit = (InstrEmitter)i.type->emit;
|
||||||
if (!i.type->emit || emit(*this, compiler_, i)) {
|
if (!i.type->emit || emit(*this, compiler_, i)) {
|
||||||
|
@ -556,7 +585,7 @@ void X64Emitter::GenerateBasicBlock(FunctionBlock* block) {
|
||||||
// TODO(benvanik): assert this doesn't occur - means a bad sdb run!
|
// TODO(benvanik): assert this doesn't occur - means a bad sdb run!
|
||||||
XELOGCPU("SDB function scan error in %.8X: bb %.8X has unknown exit",
|
XELOGCPU("SDB function scan error in %.8X: bb %.8X has unknown exit",
|
||||||
symbol_->start_address, block->start_address);
|
symbol_->start_address, block->start_address);
|
||||||
// jit_insn_return(fn_, NULL);
|
c.ret();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(benvanik): finish up BB
|
// TODO(benvanik): finish up BB
|
||||||
|
@ -752,6 +781,10 @@ void X64Emitter::TraceKernelCall() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FLAGS_annotate_disassembly) {
|
||||||
|
c.comment("XeTraceKernelCall (+spill)");
|
||||||
|
}
|
||||||
|
|
||||||
SpillRegisters();
|
SpillRegisters();
|
||||||
|
|
||||||
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
|
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
|
||||||
|
@ -759,7 +792,6 @@ void X64Emitter::TraceKernelCall() {
|
||||||
GpVar arg3 = c.newGpVar(kX86VarTypeGpd);
|
GpVar arg3 = c.newGpVar(kX86VarTypeGpd);
|
||||||
c.mov(arg3, imm((uint64_t)symbol_->kernel_export));
|
c.mov(arg3, imm((uint64_t)symbol_->kernel_export));
|
||||||
X86CompilerFuncCall* call = c.call(global_exports_.XeTraceKernelCall);
|
X86CompilerFuncCall* call = c.call(global_exports_.XeTraceKernelCall);
|
||||||
call->setComment("XeTraceKernelCall");
|
|
||||||
call->setPrototype(kX86FuncConvDefault,
|
call->setPrototype(kX86FuncConvDefault,
|
||||||
FuncBuilder4<void, void*, uint64_t, uint64_t, uint64_t>());
|
FuncBuilder4<void, void*, uint64_t, uint64_t, uint64_t>());
|
||||||
call->setArgument(0, c.getGpArg(0));
|
call->setArgument(0, c.getGpArg(0));
|
||||||
|
@ -775,6 +807,10 @@ void X64Emitter::TraceUserCall() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FLAGS_annotate_disassembly) {
|
||||||
|
c.comment("XeTraceUserCall (+spill)");
|
||||||
|
}
|
||||||
|
|
||||||
SpillRegisters();
|
SpillRegisters();
|
||||||
|
|
||||||
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
|
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
|
||||||
|
@ -782,7 +818,6 @@ void X64Emitter::TraceUserCall() {
|
||||||
GpVar arg3 = c.newGpVar(kX86VarTypeGpd);
|
GpVar arg3 = c.newGpVar(kX86VarTypeGpd);
|
||||||
c.mov(arg3, imm((uint64_t)symbol_));
|
c.mov(arg3, imm((uint64_t)symbol_));
|
||||||
X86CompilerFuncCall* call = c.call(global_exports_.XeTraceUserCall);
|
X86CompilerFuncCall* call = c.call(global_exports_.XeTraceUserCall);
|
||||||
call->setComment("XeTraceUserCall");
|
|
||||||
call->setPrototype(kX86FuncConvDefault,
|
call->setPrototype(kX86FuncConvDefault,
|
||||||
FuncBuilder4<void, void*, uint64_t, uint64_t, uint64_t>());
|
FuncBuilder4<void, void*, uint64_t, uint64_t, uint64_t>());
|
||||||
call->setArgument(0, c.getGpArg(0));
|
call->setArgument(0, c.getGpArg(0));
|
||||||
|
@ -798,6 +833,10 @@ void X64Emitter::TraceInstruction(InstrData& i) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FLAGS_annotate_disassembly) {
|
||||||
|
c.comment("XeTraceInstruction (+spill)");
|
||||||
|
}
|
||||||
|
|
||||||
SpillRegisters();
|
SpillRegisters();
|
||||||
|
|
||||||
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
|
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
|
||||||
|
@ -805,7 +844,6 @@ void X64Emitter::TraceInstruction(InstrData& i) {
|
||||||
GpVar arg2 = c.newGpVar(kX86VarTypeGpd);
|
GpVar arg2 = c.newGpVar(kX86VarTypeGpd);
|
||||||
c.mov(arg2, imm((uint64_t)i.code));
|
c.mov(arg2, imm((uint64_t)i.code));
|
||||||
X86CompilerFuncCall* call = c.call(global_exports_.XeTraceInstruction);
|
X86CompilerFuncCall* call = c.call(global_exports_.XeTraceInstruction);
|
||||||
call->setComment("XeTraceInstruction");
|
|
||||||
call->setPrototype(kX86FuncConvDefault,
|
call->setPrototype(kX86FuncConvDefault,
|
||||||
FuncBuilder3<void, void*, uint64_t, uint64_t>());
|
FuncBuilder3<void, void*, uint64_t, uint64_t>());
|
||||||
call->setArgument(0, c.getGpArg(0));
|
call->setArgument(0, c.getGpArg(0));
|
||||||
|
@ -816,6 +854,10 @@ void X64Emitter::TraceInstruction(InstrData& i) {
|
||||||
void X64Emitter::TraceInvalidInstruction(InstrData& i) {
|
void X64Emitter::TraceInvalidInstruction(InstrData& i) {
|
||||||
X86Compiler& c = compiler_;
|
X86Compiler& c = compiler_;
|
||||||
|
|
||||||
|
if (FLAGS_annotate_disassembly) {
|
||||||
|
c.comment("XeInvalidInstruction (+spill)");
|
||||||
|
}
|
||||||
|
|
||||||
SpillRegisters();
|
SpillRegisters();
|
||||||
|
|
||||||
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
|
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
|
||||||
|
@ -823,7 +865,6 @@ void X64Emitter::TraceInvalidInstruction(InstrData& i) {
|
||||||
GpVar arg2 = c.newGpVar(kX86VarTypeGpd);
|
GpVar arg2 = c.newGpVar(kX86VarTypeGpd);
|
||||||
c.mov(arg2, imm((uint64_t)i.code));
|
c.mov(arg2, imm((uint64_t)i.code));
|
||||||
X86CompilerFuncCall* call = c.call(global_exports_.XeInvalidInstruction);
|
X86CompilerFuncCall* call = c.call(global_exports_.XeInvalidInstruction);
|
||||||
call->setComment("XeInvalidInstruction");
|
|
||||||
call->setPrototype(kX86FuncConvDefault,
|
call->setPrototype(kX86FuncConvDefault,
|
||||||
FuncBuilder3<void, void*, uint64_t, uint64_t>());
|
FuncBuilder3<void, void*, uint64_t, uint64_t>());
|
||||||
call->setArgument(0, c.getGpArg(0));
|
call->setArgument(0, c.getGpArg(0));
|
||||||
|
@ -838,6 +879,10 @@ void X64Emitter::TraceBranch(uint32_t cia) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FLAGS_annotate_disassembly) {
|
||||||
|
c.comment("XeTraceBranch (+spill)");
|
||||||
|
}
|
||||||
|
|
||||||
SpillRegisters();
|
SpillRegisters();
|
||||||
|
|
||||||
// Pick target. If it's an indirection the tracing function will handle it.
|
// Pick target. If it's an indirection the tracing function will handle it.
|
||||||
|
|
Loading…
Reference in New Issue