Local variables setup and spilling/filling.

This commit is contained in:
Ben Vanik 2013-05-24 00:50:56 -07:00
parent 376226c59a
commit 71bd3c799f
2 changed files with 179 additions and 155 deletions

View File

@ -230,21 +230,21 @@ int X64Emitter::MakeFunction(FunctionSymbol* symbol) {
access_bits_.Clear(); access_bits_.Clear();
// locals_.indirection_target = NULL; locals_.indirection_target = GpVar();
// locals_.indirection_cia = NULL; locals_.indirection_cia = GpVar();
// locals_.xer = NULL; locals_.xer = GpVar();
// locals_.lr = NULL; locals_.lr = GpVar();
// locals_.ctr = NULL; locals_.ctr = GpVar();
// for (size_t n = 0; n < XECOUNT(locals_.cr); n++) { for (size_t n = 0; n < XECOUNT(locals_.cr); n++) {
// locals_.cr[n] = NULL; locals_.cr[n] = GpVar();
// } }
// for (size_t n = 0; n < XECOUNT(locals_.gpr); n++) { for (size_t n = 0; n < XECOUNT(locals_.gpr); n++) {
// locals_.gpr[n] = NULL; locals_.gpr[n] = GpVar();
// } }
// for (size_t n = 0; n < XECOUNT(locals_.fpr); n++) { for (size_t n = 0; n < XECOUNT(locals_.fpr); n++) {
// locals_.fpr[n] = NULL; locals_.fpr[n] = GpVar();
// } }
// Setup function. All share the same signature. // Setup function. All share the same signature.
compiler_.newFunc(kX86FuncConvDefault, compiler_.newFunc(kX86FuncConvDefault,
@ -331,6 +331,7 @@ int X64Emitter::MakePresentImportFunction() {
void* shim_data = symbol_->kernel_export->function_data.shim_data; void* shim_data = symbol_->kernel_export->function_data.shim_data;
// void shim(ppc_state*, shim_data*) // void shim(ppc_state*, shim_data*)
// TODO(benvanik): remove once fixed: https://code.google.com/p/asmjit/issues/detail?id=86
GpVar arg1 = c.newGpVar(kX86VarTypeGpd); GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
c.mov(arg1, imm((uint64_t)shim_data)); c.mov(arg1, imm((uint64_t)shim_data));
X86CompilerFuncCall* call = c.call(shim); X86CompilerFuncCall* call = c.call(shim);
@ -794,6 +795,7 @@ void X64Emitter::TraceKernelCall() {
SpillRegisters(); SpillRegisters();
// TODO(benvanik): remove once fixed: https://code.google.com/p/asmjit/issues/detail?id=86
GpVar arg1 = c.newGpVar(kX86VarTypeGpd); GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
c.mov(arg1, imm((uint64_t)symbol_->start_address)); c.mov(arg1, imm((uint64_t)symbol_->start_address));
GpVar arg3 = c.newGpVar(kX86VarTypeGpd); GpVar arg3 = c.newGpVar(kX86VarTypeGpd);
@ -820,6 +822,7 @@ void X64Emitter::TraceUserCall() {
SpillRegisters(); SpillRegisters();
// TODO(benvanik): remove once fixed: https://code.google.com/p/asmjit/issues/detail?id=86
GpVar arg1 = c.newGpVar(kX86VarTypeGpd); GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
c.mov(arg1, imm((uint64_t)symbol_->start_address)); c.mov(arg1, imm((uint64_t)symbol_->start_address));
GpVar arg3 = c.newGpVar(kX86VarTypeGpd); GpVar arg3 = c.newGpVar(kX86VarTypeGpd);
@ -846,6 +849,7 @@ void X64Emitter::TraceInstruction(InstrData& i) {
SpillRegisters(); SpillRegisters();
// TODO(benvanik): remove once fixed: https://code.google.com/p/asmjit/issues/detail?id=86
GpVar arg1 = c.newGpVar(kX86VarTypeGpd); GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
c.mov(arg1, imm((uint64_t)i.address)); c.mov(arg1, imm((uint64_t)i.address));
GpVar arg2 = c.newGpVar(kX86VarTypeGpd); GpVar arg2 = c.newGpVar(kX86VarTypeGpd);
@ -867,6 +871,7 @@ void X64Emitter::TraceInvalidInstruction(InstrData& i) {
SpillRegisters(); SpillRegisters();
// TODO(benvanik): remove once fixed: https://code.google.com/p/asmjit/issues/detail?id=86
GpVar arg1 = c.newGpVar(kX86VarTypeGpd); GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
c.mov(arg1, imm((uint64_t)i.address)); c.mov(arg1, imm((uint64_t)i.address));
GpVar arg2 = c.newGpVar(kX86VarTypeGpd); GpVar arg2 = c.newGpVar(kX86VarTypeGpd);
@ -913,6 +918,7 @@ void X64Emitter::TraceBranch(uint32_t cia) {
break; break;
} }
// TODO(benvanik): remove once fixed: https://code.google.com/p/asmjit/issues/detail?id=86
GpVar arg1 = c.newGpVar(kX86VarTypeGpd); GpVar arg1 = c.newGpVar(kX86VarTypeGpd);
c.mov(arg1, imm((uint64_t)cia)); c.mov(arg1, imm((uint64_t)cia));
GpVar arg2 = c.newGpVar(kX86VarTypeGpd); GpVar arg2 = c.newGpVar(kX86VarTypeGpd);
@ -1037,26 +1043,30 @@ void X64Emitter::TraceBranch(uint32_t cia) {
// } // }
void X64Emitter::SetupLocals() { void X64Emitter::SetupLocals() {
X86Compiler& c = compiler_;
uint64_t spr_t = access_bits_.spr; uint64_t spr_t = access_bits_.spr;
if (spr_t & 0x3) { if (spr_t & 0x3) {
// locals_.xer = SetupLocal(jit_type_nuint, "xer"); locals_.xer = c.newGpVar(kX86VarTypeGpq, "xer");
} }
spr_t >>= 2; spr_t >>= 2;
if (spr_t & 0x3) { if (spr_t & 0x3) {
// locals_.lr = SetupLocal(jit_type_nuint, "lr"); locals_.lr = c.newGpVar(kX86VarTypeGpq, "lr");
} }
spr_t >>= 2; spr_t >>= 2;
if (spr_t & 0x3) { if (spr_t & 0x3) {
// locals_.ctr = SetupLocal(jit_type_nuint, "ctr"); locals_.ctr = c.newGpVar(kX86VarTypeGpq, "ctr");
} }
spr_t >>= 2; spr_t >>= 2;
// TODO: FPCSR // TODO: FPCSR
char name[8];
uint64_t cr_t = access_bits_.cr; uint64_t cr_t = access_bits_.cr;
for (int n = 0; n < 8; n++) { for (int n = 0; n < 8; n++) {
if (cr_t & 3) { if (cr_t & 3) {
//xesnprintfa(name, XECOUNT(name), "cr%d", n); xesnprintfa(name, XECOUNT(name), "cr%d", n);
// locals_.cr[n] = SetupLocal(jit_type_ubyte, name); locals_.cr[n] = c.newGpVar(kX86VarTypeGpd, name);
} }
cr_t >>= 2; cr_t >>= 2;
} }
@ -1064,8 +1074,8 @@ void X64Emitter::SetupLocals() {
uint64_t gpr_t = access_bits_.gpr; uint64_t gpr_t = access_bits_.gpr;
for (int n = 0; n < 32; n++) { for (int n = 0; n < 32; n++) {
if (gpr_t & 3) { if (gpr_t & 3) {
//xesnprintfa(name, XECOUNT(name), "r%d", n); xesnprintfa(name, XECOUNT(name), "r%d", n);
// locals_.gpr[n] = SetupLocal(jit_type_nuint, name); locals_.gpr[n] = c.newGpVar(kX86VarTypeGpq, name);
} }
gpr_t >>= 2; gpr_t >>= 2;
} }
@ -1073,159 +1083,174 @@ void X64Emitter::SetupLocals() {
uint64_t fpr_t = access_bits_.fpr; uint64_t fpr_t = access_bits_.fpr;
for (int n = 0; n < 32; n++) { for (int n = 0; n < 32; n++) {
if (fpr_t & 3) { if (fpr_t & 3) {
//xesnprintfa(name, XECOUNT(name), "f%d", n); xesnprintfa(name, XECOUNT(name), "f%d", n);
// locals_.fpr[n] = SetupLocal(jit_type_float64, name); locals_.fpr[n] = c.newGpVar(kX86VarTypeXmmSD, name);
} }
fpr_t >>= 2; fpr_t >>= 2;
} }
} }
// jit_value_t X64Emitter::SetupLocal(jit_type_t type, const char* name) {
// // Note that the value is created in the current block, but will be pushed
// // up to function level if used in another block.
// jit_value_t value = jit_value_create(fn_, type);
// // TODO(benvanik): set a name?
// return value;
// }
void X64Emitter::FillRegisters() { void X64Emitter::FillRegisters() {
X86Compiler& c = compiler_;
// This updates all of the local register values from the state memory. // This updates all of the local register values from the state memory.
// It should be called on function entry for initial setup and after any // It should be called on function entry for initial setup and after any
// calls that may modify the registers. // calls that may modify the registers.
// TODO(benvanik): use access flags to see if we need to do reads/writes. // TODO(benvanik): use access flags to see if we need to do reads/writes.
// if (locals_.xer) { if (locals_.xer.getId() != kInvalidValue) {
// jit_insn_store(fn_, if (FLAGS_annotate_disassembly) {
// locals_.xer, c.comment("Filling XER");
// LoadStateValue(offsetof(xe_ppc_state_t, xer), jit_type_nuint)); }
// } c.mov(locals_.xer, ptr(c.getGpArg(0), offsetof(xe_ppc_state_t, xer), 8));
}
// if (locals_.lr) { if (locals_.lr.getId() != kInvalidValue) {
// jit_insn_store(fn_, if (FLAGS_annotate_disassembly) {
// locals_.lr, c.comment("Filling LR");
// LoadStateValue(offsetof(xe_ppc_state_t, lr), jit_type_nuint)); }
// } c.mov(locals_.lr, ptr(c.getGpArg(0), offsetof(xe_ppc_state_t, lr), 8));
}
// if (locals_.ctr) { if (locals_.ctr.getId() != kInvalidValue) {
// jit_insn_store(fn_, if (FLAGS_annotate_disassembly) {
// locals_.ctr, c.comment("Filling CTR");
// LoadStateValue(offsetof(xe_ppc_state_t, ctr), jit_type_nuint)); }
// } c.mov(locals_.ctr, ptr(c.getGpArg(0), offsetof(xe_ppc_state_t, ctr), 8));
}
// // Fill the split CR values by extracting each one from the CR. // Fill the split CR values by extracting each one from the CR.
// // This could probably be done faster via an extractvalues or something. // This could probably be done faster via an extractvalues or something.
// // Perhaps we could also change it to be a vector<8*i8>. // Perhaps we could also change it to be a vector<8*i8>.
// jit_value_t cr = NULL; GpVar cr;
// for (size_t n = 0; n < XECOUNT(locals_.cr); n++) { GpVar cr_tmp;
// jit_value_t cr_n = locals_.cr[n]; for (size_t n = 0; n < XECOUNT(locals_.cr); n++) {
// if (!cr_n) { GpVar& cr_n = locals_.cr[n];
// continue; if (cr_n.getId() == kInvalidValue) {
// } continue;
// if (!cr) { }
// // Only fetch once. Doing this in here prevents us from having to if (cr.getId() == kInvalidValue) {
// // always fetch even if unused. // Only fetch once. Doing this in here prevents us from having to
// cr = LoadStateValue(offsetof(xe_ppc_state_t, cr), jit_type_nuint); // always fetch even if unused.
// } if (FLAGS_annotate_disassembly) {
// // (cr >> 28 - n * 4) & 0xF c.comment("Filling CR");
// jit_value_t shamt = jit_value_create_nint_constant( }
// fn_, jit_type_nuint, 28 - n * 4); cr = c.newGpVar();
// jit_insn_store(fn_, cr_n, c.mov(cr, ptr(c.getGpArg(0), offsetof(xe_ppc_state_t, cr), 8));
// jit_insn_and(fn_, cr_tmp = c.newGpVar();
// jit_insn_ushr(fn_, cr, shamt), }
// jit_value_create_nint_constant(fn_, jit_type_ubyte, 0xF))); // (cr >> 28 - n * 4) & 0xF
// } c.mov(cr_tmp, cr);
c.shr(cr_tmp, imm(28 - n * 4));
c.and_(cr_tmp, imm(0xF));
c.mov(cr_n, cr_tmp);
}
// for (size_t n = 0; n < XECOUNT(locals_.gpr); n++) { for (size_t n = 0; n < XECOUNT(locals_.gpr); n++) {
// if (locals_.gpr[n]) { if (locals_.gpr[n].getId() != kInvalidValue) {
// jit_insn_store(fn_, if (FLAGS_annotate_disassembly) {
// locals_.gpr[n], c.comment("Filling r%d", n);
// LoadStateValue(offsetof(xe_ppc_state_t, r) + 8 * n, jit_type_nuint)); }
// } c.mov(locals_.gpr[n],
// } ptr(c.getGpArg(0), offsetof(xe_ppc_state_t, r) + 8 * n, 8));
}
}
// for (size_t n = 0; n < XECOUNT(locals_.fpr); n++) { for (size_t n = 0; n < XECOUNT(locals_.fpr); n++) {
// if (locals_.fpr[n]) { if (locals_.fpr[n].getId() != kInvalidValue) {
// jit_insn_store(fn_, if (FLAGS_annotate_disassembly) {
// locals_.fpr[n], c.comment("Filling f%d", n);
// LoadStateValue(offsetof(xe_ppc_state_t, f) + 8 * n, }
// jit_type_float64)); c.mov(locals_.fpr[n],
// } ptr(c.getGpArg(0), offsetof(xe_ppc_state_t, f) + 8 * n, 8));
// } }
}
} }
void X64Emitter::SpillRegisters() { void X64Emitter::SpillRegisters() {
X86Compiler& c = compiler_;
// This flushes all local registers (if written) to the register bank and // This flushes all local registers (if written) to the register bank and
// resets their values. // resets their values.
// TODO(benvanik): only flush if actually required, or selective flushes. // TODO(benvanik): only flush if actually required, or selective flushes.
// if (locals_.xer) { if (locals_.xer.getId() != kInvalidValue) {
// StoreStateValue( if (FLAGS_annotate_disassembly) {
// offsetof(xe_ppc_state_t, xer), c.comment("Spilling XER");
// jit_type_nuint, }
// jit_insn_load(fn_, locals_.xer)); c.mov(ptr(c.getGpArg(0), offsetof(xe_ppc_state_t, xer)),
// } locals_.xer);
}
// if (locals_.lr) { if (locals_.lr.getId() != kInvalidValue) {
// StoreStateValue( if (FLAGS_annotate_disassembly) {
// offsetof(xe_ppc_state_t, lr), c.comment("Spilling LR");
// jit_type_nuint, }
// jit_insn_load(fn_, locals_.lr)); c.mov(ptr(c.getGpArg(0), offsetof(xe_ppc_state_t, lr)),
// } locals_.lr);
}
// if (locals_.ctr) { if (locals_.ctr.getId() != kInvalidValue) {
// StoreStateValue( if (FLAGS_annotate_disassembly) {
// offsetof(xe_ppc_state_t, ctr), c.comment("Spilling CTR");
// jit_type_nuint, }
// jit_insn_load(fn_, locals_.ctr)); c.mov(ptr(c.getGpArg(0), offsetof(xe_ppc_state_t, ctr)),
// } locals_.ctr);
}
// // Stitch together all split CR values. // Stitch together all split CR values.
// // TODO(benvanik): don't flush across calls? // TODO(benvanik): don't flush across calls?
// jit_value_t cr = NULL; GpVar cr;
// for (size_t n = 0; n < XECOUNT(locals_.cr); n++) { GpVar cr_tmp;
// jit_value_t cr_n = locals_.cr[n]; for (size_t n = 0; n < XECOUNT(locals_.cr); n++) {
// if (!cr_n) { GpVar& cr_n = locals_.cr[n];
// continue; if (cr_n.getId() == kInvalidValue) {
// } continue;
// // cr |= (cr_n << n * 4) }
// jit_value_t shamt = jit_value_create_nint_constant( if (cr_tmp.getId() == kInvalidValue) {
// fn_, jit_type_nuint, n * 4); cr_tmp = c.newGpVar();
// cr_n = jit_insn_convert(fn_, jit_insn_load(fn_, cr_n), jit_type_nuint, 0); }
// cr_n = jit_insn_shl(fn_, cr_n, shamt); // cr |= (cr_n << n * 4)
// if (!cr) { c.mov(cr_tmp, cr_n);
// cr = cr_n; c.shl(cr_tmp, imm(n * 4));
// } else { if (cr.getId() == kInvalidValue) {
// cr = jit_insn_or(fn_, cr, cr_n); cr = c.newGpVar();
// } c.mov(cr, cr_tmp);
// } } else {
// if (cr) { c.or_(cr, cr_tmp);
// StoreStateValue( }
// offsetof(xe_ppc_state_t, cr), }
// jit_type_nuint, if (cr.getId() != kInvalidValue) {
// cr); if (FLAGS_annotate_disassembly) {
// } c.comment("Spilling CR");
}
c.mov(ptr(c.getGpArg(0), offsetof(xe_ppc_state_t, cr)),
cr);
}
// for (uint32_t n = 0; n < XECOUNT(locals_.gpr); n++) { for (uint32_t n = 0; n < XECOUNT(locals_.gpr); n++) {
// jit_value_t v = locals_.gpr[n]; GpVar& v = locals_.gpr[n];
// if (v) { if (v.getId() != kInvalidValue) {
// StoreStateValue( if (FLAGS_annotate_disassembly) {
// offsetof(xe_ppc_state_t, r) + 8 * n, c.comment("Spilling r%d", n);
// jit_type_nuint, }
// jit_insn_load(fn_, v)); c.mov(ptr(c.getGpArg(0), offsetof(xe_ppc_state_t, r) + 8 * n),
// } v);
// } }
}
// for (uint32_t n = 0; n < XECOUNT(locals_.fpr); n++) { for (uint32_t n = 0; n < XECOUNT(locals_.fpr); n++) {
// jit_value_t v = locals_.fpr[n]; GpVar& v = locals_.fpr[n];
// if (v) { if (v.getId() != kInvalidValue) {
// StoreStateValue( if (FLAGS_annotate_disassembly) {
// offsetof(xe_ppc_state_t, f) + 8 * n, c.comment("Spilling f%d", n);
// jit_type_float64, }
// jit_insn_load(fn_, v)); c.mov(ptr(c.getGpArg(0), offsetof(xe_ppc_state_t, f) + 8 * n),
// } v);
// } }
}
} }
// jit_value_t X64Emitter::xer_value() { // jit_value_t X64Emitter::xer_value() {

View File

@ -76,7 +76,6 @@ public:
// const char* name = ""); // const char* name = "");
// void StoreStateValue(size_t offset, jit_type_t type, jit_value_t value); // void StoreStateValue(size_t offset, jit_type_t type, jit_value_t value);
// jit_value_t SetupLocal(jit_type_t type, const char* name);
void FillRegisters(); void FillRegisters();
void SpillRegisters(); void SpillRegisters();
@ -139,17 +138,17 @@ private:
std::map<uint32_t, AsmJit::Label> bbs_; std::map<uint32_t, AsmJit::Label> bbs_;
ppc::InstrAccessBits access_bits_; ppc::InstrAccessBits access_bits_;
// struct { struct {
// jit_value_t indirection_target; AsmJit::GpVar indirection_target;
// jit_value_t indirection_cia; AsmJit::GpVar indirection_cia;
// jit_value_t xer; AsmJit::GpVar xer;
// jit_value_t lr; AsmJit::GpVar lr;
// jit_value_t ctr; AsmJit::GpVar ctr;
// jit_value_t cr[8]; AsmJit::GpVar cr[8];
// jit_value_t gpr[32]; AsmJit::GpVar gpr[32];
// jit_value_t fpr[32]; AsmJit::GpVar fpr[32];
// } locals_; } locals_;
}; };