Cleanup and tracing.
This commit is contained in:
parent
d7d0b94aab
commit
74ae66aa0a
|
@ -51,6 +51,9 @@ DEFINE_bool(log_codegen, false,
|
||||||
X64Emitter::X64Emitter(xe_memory_ref memory) {
|
X64Emitter::X64Emitter(xe_memory_ref memory) {
|
||||||
memory_ = memory;
|
memory_ = memory;
|
||||||
|
|
||||||
|
// I don't like doing this, but there's no public access to these members.
|
||||||
|
assembler_._properties = compiler_._properties;
|
||||||
|
|
||||||
// Grab global exports.
|
// Grab global exports.
|
||||||
cpu::GetGlobalExports(&global_exports_);
|
cpu::GetGlobalExports(&global_exports_);
|
||||||
|
|
||||||
|
@ -117,9 +120,11 @@ int X64Emitter::PrepareFunction(FunctionSymbol* symbol) {
|
||||||
// Arguments passed as RCX, RDX, R8, R9
|
// Arguments passed as RCX, RDX, R8, R9
|
||||||
assembler_.push(rcx); // ppc_state
|
assembler_.push(rcx); // ppc_state
|
||||||
assembler_.push(rdx); // lr
|
assembler_.push(rdx); // lr
|
||||||
assembler_.mov(rcx, (uint64_t)this);
|
assembler_.sub(rsp, imm(0x20));
|
||||||
assembler_.mov(rdx, (uint64_t)symbol);
|
assembler_.mov(rcx, imm((uint64_t)this));
|
||||||
|
assembler_.mov(rdx, imm((uint64_t)symbol));
|
||||||
assembler_.call(X64Emitter::OnDemandCompileTrampoline);
|
assembler_.call(X64Emitter::OnDemandCompileTrampoline);
|
||||||
|
assembler_.add(rsp, imm(0x20));
|
||||||
assembler_.pop(rdx); // lr
|
assembler_.pop(rdx); // lr
|
||||||
assembler_.pop(rcx); // ppc_state
|
assembler_.pop(rcx); // ppc_state
|
||||||
assembler_.jmp(rax);
|
assembler_.jmp(rax);
|
||||||
|
@ -128,9 +133,11 @@ int X64Emitter::PrepareFunction(FunctionSymbol* symbol) {
|
||||||
// Arguments passed as RDI, RSI, RDX, RCX, R8, R9
|
// Arguments passed as RDI, RSI, RDX, RCX, R8, R9
|
||||||
assembler_.push(rdi); // ppc_state
|
assembler_.push(rdi); // ppc_state
|
||||||
assembler_.push(rsi); // lr
|
assembler_.push(rsi); // lr
|
||||||
assembler_.mov(rdi, (uint64_t)this);
|
assembler_.sub(rsp, imm(0x20));
|
||||||
assembler_.mov(rsi, (uint64_t)symbol);
|
assembler_.mov(rdi, imm((uint64_t)this));
|
||||||
|
assembler_.mov(rsi, imm((uint64_t)symbol));
|
||||||
assembler_.call(X64Emitter::OnDemandCompileTrampoline);
|
assembler_.call(X64Emitter::OnDemandCompileTrampoline);
|
||||||
|
assembler_.add(rsp, imm(0x20));
|
||||||
assembler_.pop(rsi); // lr
|
assembler_.pop(rsi); // lr
|
||||||
assembler_.pop(rdi); // ppc_state
|
assembler_.pop(rdi); // ppc_state
|
||||||
assembler_.jmp(rax);
|
assembler_.jmp(rax);
|
||||||
|
@ -244,9 +251,6 @@ int X64Emitter::MakeFunction(FunctionSymbol* symbol) {
|
||||||
//compiler_.setPriority(compiler_.getGpArg(0), 100);
|
//compiler_.setPriority(compiler_.getGpArg(0), 100);
|
||||||
|
|
||||||
switch (symbol->type) {
|
switch (symbol->type) {
|
||||||
case FunctionSymbol::User:
|
|
||||||
result_code = MakeUserFunction();
|
|
||||||
break;
|
|
||||||
case FunctionSymbol::Kernel:
|
case FunctionSymbol::Kernel:
|
||||||
if (symbol->kernel_export && symbol->kernel_export->is_implemented) {
|
if (symbol->kernel_export && symbol->kernel_export->is_implemented) {
|
||||||
result_code = MakePresentImportFunction();
|
result_code = MakePresentImportFunction();
|
||||||
|
@ -254,6 +258,9 @@ int X64Emitter::MakeFunction(FunctionSymbol* symbol) {
|
||||||
result_code = MakeMissingImportFunction();
|
result_code = MakeMissingImportFunction();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case FunctionSymbol::User:
|
||||||
|
result_code = MakeUserFunction();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
XEASSERTALWAYS();
|
XEASSERTALWAYS();
|
||||||
result_code = 1;
|
result_code = 1;
|
||||||
|
@ -263,10 +270,6 @@ int X64Emitter::MakeFunction(FunctionSymbol* symbol) {
|
||||||
|
|
||||||
compiler_.endFunc();
|
compiler_.endFunc();
|
||||||
|
|
||||||
// I don't like doing this, but there's no public access to these members.
|
|
||||||
assembler_._properties = compiler_._properties;
|
|
||||||
assembler_.setLogger(compiler_.getLogger());
|
|
||||||
|
|
||||||
// Serialize to the assembler.
|
// Serialize to the assembler.
|
||||||
compiler_.serialize(assembler_);
|
compiler_.serialize(assembler_);
|
||||||
if (compiler_.getError()) {
|
if (compiler_.getError()) {
|
||||||
|
@ -311,48 +314,8 @@ XECLEANUP:
|
||||||
return result_code;
|
return result_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
int X64Emitter::MakeUserFunction() {
|
|
||||||
// if (FLAGS_trace_user_calls) {
|
|
||||||
// jit_value_t trace_args[] = {
|
|
||||||
// jit_value_get_param(fn_, 0),
|
|
||||||
// jit_value_create_long_constant(fn_, jit_type_ulong,
|
|
||||||
// (jit_ulong)symbol_->start_address),
|
|
||||||
// jit_value_get_param(fn_, 1),
|
|
||||||
// jit_value_create_long_constant(fn_, jit_type_ulong,
|
|
||||||
// (jit_ulong)symbol_),
|
|
||||||
// };
|
|
||||||
// jit_insn_call_native(
|
|
||||||
// fn_,
|
|
||||||
// "XeTraceUserCall",
|
|
||||||
// global_exports_.XeTraceUserCall,
|
|
||||||
// global_export_signature_4_,
|
|
||||||
// trace_args, XECOUNT(trace_args),
|
|
||||||
// 0);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Emit.
|
|
||||||
GenerateBasicBlocks();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int X64Emitter::MakePresentImportFunction() {
|
int X64Emitter::MakePresentImportFunction() {
|
||||||
// if (FLAGS_trace_kernel_calls) {
|
TraceKernelCall();
|
||||||
// jit_value_t trace_args[] = {
|
|
||||||
// jit_value_get_param(fn_, 0),
|
|
||||||
// jit_value_create_long_constant(fn_, jit_type_ulong,
|
|
||||||
// (jit_ulong)symbol_->start_address),
|
|
||||||
// jit_value_get_param(fn_, 1),
|
|
||||||
// jit_value_create_long_constant(fn_, jit_type_ulong,
|
|
||||||
// (jit_ulong)symbol_->kernel_export),
|
|
||||||
// };
|
|
||||||
// jit_insn_call_native(
|
|
||||||
// fn_,
|
|
||||||
// "XeTraceKernelCall",
|
|
||||||
// global_exports_.XeTraceKernelCall,
|
|
||||||
// global_export_signature_4_,
|
|
||||||
// trace_args, XECOUNT(trace_args),
|
|
||||||
// 0);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // void shim(ppc_state*, shim_data*)
|
// // void shim(ppc_state*, shim_data*)
|
||||||
// jit_value_t shim_args[] = {
|
// jit_value_t shim_args[] = {
|
||||||
|
@ -374,46 +337,21 @@ int X64Emitter::MakePresentImportFunction() {
|
||||||
}
|
}
|
||||||
|
|
||||||
int X64Emitter::MakeMissingImportFunction() {
|
int X64Emitter::MakeMissingImportFunction() {
|
||||||
// if (FLAGS_trace_kernel_calls) {
|
TraceKernelCall();
|
||||||
// jit_value_t trace_args[] = {
|
|
||||||
// jit_value_get_param(fn_, 0),
|
|
||||||
// jit_value_create_long_constant(fn_, jit_type_ulong,
|
|
||||||
// (jit_ulong)symbol_->start_address),
|
|
||||||
// jit_value_get_param(fn_, 1),
|
|
||||||
// jit_value_create_long_constant(fn_, jit_type_ulong,
|
|
||||||
// (jit_ulong)symbol_->kernel_export),
|
|
||||||
// };
|
|
||||||
// jit_insn_call_native(
|
|
||||||
// fn_,
|
|
||||||
// "XeTraceKernelCall",
|
|
||||||
// global_exports_.XeTraceKernelCall,
|
|
||||||
// global_export_signature_4_,
|
|
||||||
// trace_args, XECOUNT(trace_args),
|
|
||||||
// 0);
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
// TODO(benvanik): log better?
|
||||||
// jit_insn_return(fn_, NULL);
|
// jit_insn_return(fn_, NULL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
X86Compiler& X64Emitter::compiler() {
|
int X64Emitter::MakeUserFunction() {
|
||||||
return compiler_;
|
TraceUserCall();
|
||||||
}
|
|
||||||
|
|
||||||
FunctionSymbol* X64Emitter::symbol() {
|
|
||||||
return symbol_;
|
|
||||||
}
|
|
||||||
|
|
||||||
FunctionBlock* X64Emitter::fn_block() {
|
|
||||||
return fn_block_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void X64Emitter::GenerateBasicBlocks() {
|
|
||||||
// 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);
|
// jit_insn_return(fn_, NULL);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass 1 creates all of the labels - this way we can branch to them.
|
// Pass 1 creates all of the labels - this way we can branch to them.
|
||||||
|
@ -445,6 +383,20 @@ void X64Emitter::GenerateBasicBlocks() {
|
||||||
// Setup the shared return/indirection/etc blocks now that we know all the
|
// Setup the shared return/indirection/etc blocks now that we know all the
|
||||||
// blocks we need and all the registers used.
|
// blocks we need and all the registers used.
|
||||||
GenerateSharedBlocks();
|
GenerateSharedBlocks();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
X86Compiler& X64Emitter::compiler() {
|
||||||
|
return compiler_;
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionSymbol* X64Emitter::symbol() {
|
||||||
|
return symbol_;
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionBlock* X64Emitter::fn_block() {
|
||||||
|
return fn_block_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void X64Emitter::GenerateSharedBlocks() {
|
void X64Emitter::GenerateSharedBlocks() {
|
||||||
|
@ -558,39 +510,15 @@ void X64Emitter::GenerateBasicBlock(FunctionBlock* block) {
|
||||||
i.code = XEGETUINT32BE(p + ia);
|
i.code = XEGETUINT32BE(p + ia);
|
||||||
i.type = ppc::GetInstrType(i.code);
|
i.type = ppc::GetInstrType(i.code);
|
||||||
|
|
||||||
// jit_value_t trace_args[] = {
|
|
||||||
// jit_value_get_param(fn_, 0),
|
|
||||||
// jit_value_create_long_constant(fn_, jit_type_ulong,
|
|
||||||
// (jit_ulong)i.address),
|
|
||||||
// jit_value_create_long_constant(fn_, jit_type_ulong,
|
|
||||||
// (jit_ulong)i.code),
|
|
||||||
// };
|
|
||||||
|
|
||||||
// Add debugging tag.
|
// Add debugging tag.
|
||||||
// TODO(benvanik): mark type.
|
// TODO(benvanik): mark type.
|
||||||
//jit_insn_mark_breakpoint(fn_, 1, ia);
|
//jit_insn_mark_breakpoint(fn_, 1, ia);
|
||||||
|
|
||||||
if (FLAGS_trace_instructions) {
|
TraceInstruction(i);
|
||||||
SpillRegisters();
|
|
||||||
// jit_insn_call_native(
|
|
||||||
// fn_,
|
|
||||||
// "XeTraceInstruction",
|
|
||||||
// global_exports_.XeTraceInstruction,
|
|
||||||
// global_export_signature_3_,
|
|
||||||
// trace_args, XECOUNT(trace_args),
|
|
||||||
// 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!i.type) {
|
if (!i.type) {
|
||||||
XELOGCPU("Invalid instruction %.8X %.8X", ia, i.code);
|
XELOGCPU("Invalid instruction %.8X %.8X", ia, i.code);
|
||||||
SpillRegisters();
|
TraceInvalidInstruction(i);
|
||||||
// jit_insn_call_native(
|
|
||||||
// fn_,
|
|
||||||
// "XeInvalidInstruction",
|
|
||||||
// global_exports_.XeInvalidInstruction,
|
|
||||||
// global_export_signature_3_,
|
|
||||||
// trace_args, XECOUNT(trace_args),
|
|
||||||
// 0);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -614,14 +542,7 @@ void X64Emitter::GenerateBasicBlock(FunctionBlock* block) {
|
||||||
|
|
||||||
XELOGCPU("Unimplemented instr %.8X %.8X %s",
|
XELOGCPU("Unimplemented instr %.8X %.8X %s",
|
||||||
ia, i.code, i.type->name);
|
ia, i.code, i.type->name);
|
||||||
SpillRegisters();
|
TraceInvalidInstruction(i);
|
||||||
// jit_insn_call_native(
|
|
||||||
// fn_,
|
|
||||||
// "XeInvalidInstruction",
|
|
||||||
// global_exports_.XeInvalidInstruction,
|
|
||||||
// global_export_signature_3_,
|
|
||||||
// trace_args, XECOUNT(trace_args),
|
|
||||||
// 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -824,7 +745,99 @@ void X64Emitter::GenerateBasicBlock(FunctionBlock* block) {
|
||||||
// return 1;
|
// return 1;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
void X64Emitter::TraceKernelCall() {
|
||||||
|
X86Compiler& c = compiler_;
|
||||||
|
|
||||||
|
if (!FLAGS_trace_kernel_calls) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpillRegisters();
|
||||||
|
|
||||||
|
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
|
||||||
|
c.mov(arg1, imm((uint64_t)symbol_->start_address));
|
||||||
|
GpVar arg3 = c.newGpVar(kX86VarTypeGpd);
|
||||||
|
c.mov(arg3, imm((uint64_t)symbol_->kernel_export));
|
||||||
|
X86CompilerFuncCall* call = c.call(global_exports_.XeTraceKernelCall);
|
||||||
|
call->setComment("XeTraceKernelCall");
|
||||||
|
call->setPrototype(kX86FuncConvDefault,
|
||||||
|
FuncBuilder4<void, void*, uint64_t, uint64_t, uint64_t>());
|
||||||
|
call->setArgument(0, c.getGpArg(0));
|
||||||
|
call->setArgument(1, arg1);
|
||||||
|
call->setArgument(2, c.getGpArg(1));
|
||||||
|
call->setArgument(3, arg3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void X64Emitter::TraceUserCall() {
|
||||||
|
X86Compiler& c = compiler_;
|
||||||
|
|
||||||
|
if (!FLAGS_trace_user_calls) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpillRegisters();
|
||||||
|
|
||||||
|
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
|
||||||
|
c.mov(arg1, imm((uint64_t)symbol_->start_address));
|
||||||
|
GpVar arg3 = c.newGpVar(kX86VarTypeGpd);
|
||||||
|
c.mov(arg3, imm((uint64_t)symbol_));
|
||||||
|
X86CompilerFuncCall* call = c.call(global_exports_.XeTraceUserCall);
|
||||||
|
call->setComment("XeTraceUserCall");
|
||||||
|
call->setPrototype(kX86FuncConvDefault,
|
||||||
|
FuncBuilder4<void, void*, uint64_t, uint64_t, uint64_t>());
|
||||||
|
call->setArgument(0, c.getGpArg(0));
|
||||||
|
call->setArgument(1, arg1);
|
||||||
|
call->setArgument(2, c.getGpArg(1));
|
||||||
|
call->setArgument(3, arg3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void X64Emitter::TraceInstruction(InstrData& i) {
|
||||||
|
X86Compiler& c = compiler_;
|
||||||
|
|
||||||
|
if (!FLAGS_trace_instructions) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SpillRegisters();
|
||||||
|
|
||||||
|
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
|
||||||
|
c.mov(arg1, imm((uint64_t)i.address));
|
||||||
|
GpVar arg2 = c.newGpVar(kX86VarTypeGpd);
|
||||||
|
c.mov(arg2, imm((uint64_t)i.code));
|
||||||
|
X86CompilerFuncCall* call = c.call(global_exports_.XeTraceInstruction);
|
||||||
|
call->setComment("XeTraceInstruction");
|
||||||
|
call->setPrototype(kX86FuncConvDefault,
|
||||||
|
FuncBuilder3<void, void*, uint64_t, uint64_t>());
|
||||||
|
call->setArgument(0, c.getGpArg(0));
|
||||||
|
call->setArgument(1, arg1);
|
||||||
|
call->setArgument(2, arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void X64Emitter::TraceInvalidInstruction(InstrData& i) {
|
||||||
|
X86Compiler& c = compiler_;
|
||||||
|
|
||||||
|
SpillRegisters();
|
||||||
|
|
||||||
|
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
|
||||||
|
c.mov(arg1, imm((uint64_t)i.address));
|
||||||
|
GpVar arg2 = c.newGpVar(kX86VarTypeGpd);
|
||||||
|
c.mov(arg2, imm((uint64_t)i.code));
|
||||||
|
X86CompilerFuncCall* call = c.call(global_exports_.XeInvalidInstruction);
|
||||||
|
call->setComment("XeInvalidInstruction");
|
||||||
|
call->setPrototype(kX86FuncConvDefault,
|
||||||
|
FuncBuilder3<void, void*, uint64_t, uint64_t>());
|
||||||
|
call->setArgument(0, c.getGpArg(0));
|
||||||
|
call->setArgument(1, arg1);
|
||||||
|
call->setArgument(2, arg2);
|
||||||
|
}
|
||||||
|
|
||||||
void X64Emitter::TraceBranch(uint32_t cia) {
|
void X64Emitter::TraceBranch(uint32_t cia) {
|
||||||
|
X86Compiler& c = compiler_;
|
||||||
|
|
||||||
|
if (!FLAGS_trace_branches) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
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.
|
||||||
|
@ -848,18 +861,17 @@ void X64Emitter::TraceBranch(uint32_t cia) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// jit_value_t trace_args[] = {
|
GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
|
||||||
// jit_value_get_param(fn_, 0),
|
c.mov(arg1, imm((uint64_t)cia));
|
||||||
// jit_value_create_long_constant(fn_, jit_type_ulong, cia),
|
GpVar arg2 = c.newGpVar(kX86VarTypeGpd);
|
||||||
// jit_value_create_long_constant(fn_, jit_type_ulong, target),
|
c.mov(arg2, imm((uint64_t)target));
|
||||||
// };
|
X86CompilerFuncCall* call = c.call(global_exports_.XeTraceBranch);
|
||||||
// jit_insn_call_native(
|
call->setComment("XeTraceBranch");
|
||||||
// fn_,
|
call->setPrototype(kX86FuncConvDefault,
|
||||||
// "XeTraceBranch",
|
FuncBuilder3<void, void*, uint64_t, uint64_t>());
|
||||||
// global_exports_.XeTraceBranch,
|
call->setArgument(0, c.getGpArg(0));
|
||||||
// global_export_signature_3_,
|
call->setArgument(1, arg1);
|
||||||
// trace_args, XECOUNT(trace_args),
|
call->setArgument(2, arg2);
|
||||||
// 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// int X64Emitter::GenerateIndirectionBranch(uint32_t cia, jit_value_t target,
|
// int X64Emitter::GenerateIndirectionBranch(uint32_t cia, jit_value_t target,
|
||||||
|
|
|
@ -63,6 +63,10 @@ public:
|
||||||
// int call_function(sdb::FunctionSymbol* target_symbol, jit_value_t lr,
|
// int call_function(sdb::FunctionSymbol* target_symbol, jit_value_t lr,
|
||||||
// bool tail);
|
// bool tail);
|
||||||
|
|
||||||
|
void TraceKernelCall();
|
||||||
|
void TraceUserCall();
|
||||||
|
void TraceInstruction(ppc::InstrData& i);
|
||||||
|
void TraceInvalidInstruction(ppc::InstrData& i);
|
||||||
void TraceBranch(uint32_t cia);
|
void TraceBranch(uint32_t cia);
|
||||||
|
|
||||||
// int GenerateIndirectionBranch(uint32_t cia, jit_value_t target,
|
// int GenerateIndirectionBranch(uint32_t cia, jit_value_t target,
|
||||||
|
@ -113,7 +117,6 @@ private:
|
||||||
int MakePresentImportFunction();
|
int MakePresentImportFunction();
|
||||||
int MakeMissingImportFunction();
|
int MakeMissingImportFunction();
|
||||||
|
|
||||||
void GenerateBasicBlocks();
|
|
||||||
void GenerateSharedBlocks();
|
void GenerateSharedBlocks();
|
||||||
int PrepareBasicBlock(sdb::FunctionBlock* block);
|
int PrepareBasicBlock(sdb::FunctionBlock* block);
|
||||||
void GenerateBasicBlock(sdb::FunctionBlock* block);
|
void GenerateBasicBlock(sdb::FunctionBlock* block);
|
||||||
|
|
Loading…
Reference in New Issue