Setting up register fill/spill.

This commit is contained in:
Ben Vanik 2013-05-22 13:37:44 -07:00
parent 16d2b73a73
commit 7227ba2693
3 changed files with 134 additions and 138 deletions

View File

@ -676,28 +676,21 @@ int LibjitEmitter::branch_to_return_if_not(jit_value_t value) {
//
// return 0;
//}
//
//jit_value_t LibjitEmitter::LoadStateValue(uint32_t offset, jit_type_t type,
// const char* name) {
// IRBuilder<>& b = *builder_;
// PointerType* pointerTy = PointerType::getUnqual(type);
// Function::arg_iterator args = fn_->arg_begin();
// jit_value_t state_ptr = args;
// jit_value_t address = b.CreateInBoundsGEP(state_ptr, b.getInt32(offset));
// jit_value_t ptr = b.CreatePointerCast(address, pointerTy);
// return b.CreateLoad(ptr, name);
//}
//
//void LibjitEmitter::StoreStateValue(uint32_t offset, jit_type_t type,
// jit_value_t value) {
// IRBuilder<>& b = *builder_;
// PointerType* pointerTy = PointerType::getUnqual(type);
// Function::arg_iterator args = fn_->arg_begin();
// jit_value_t state_ptr = args;
// jit_value_t address = b.CreateInBoundsGEP(state_ptr, b.getInt32(offset));
// jit_value_t ptr = b.CreatePointerCast(address, pointerTy);
// b.CreateStore(value, ptr);
//}
jit_value_t LibjitEmitter::LoadStateValue(size_t offset, jit_type_t type,
const char* name) {
// Load from ppc_state[offset].
// TODO(benvanik): tag with debug info?
return jit_insn_load_relative(
fn_, jit_value_get_param(fn_, 0), offset, type);
}
void LibjitEmitter::StoreStateValue(size_t offset, jit_type_t type,
jit_value_t value) {
// Store to ppc_state[offset].
jit_insn_store_relative(
fn_, jit_value_get_param(fn_, 0), offset, value);
}
void LibjitEmitter::SetupLocals() {
uint64_t spr_t = access_bits_.spr;
@ -753,10 +746,6 @@ jit_value_t LibjitEmitter::SetupLocal(jit_type_t type, const char* name) {
return value;
}
//jit_value_t LibjitEmitter::cia_value() {
// return builder_->getInt32(cia_);
//}
void LibjitEmitter::FillRegisters() {
// 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
@ -764,58 +753,63 @@ void LibjitEmitter::FillRegisters() {
// TODO(benvanik): use access flags to see if we need to do reads/writes.
// if (locals_.xer) {
// b.CreateStore(LoadStateValue(
// offsetof(xe_ppc_state_t, xer),
// jit_type_nint), locals_.xer);
// }
if (locals_.xer) {
jit_insn_store(fn_,
locals_.xer,
LoadStateValue(offsetof(xe_ppc_state_t, xer), jit_type_nint));
}
// if (locals_.lr) {
// b.CreateStore(LoadStateValue(
// offsetof(xe_ppc_state_t, lr),
// jit_type_nint), locals_.lr);
// }
if (locals_.lr) {
jit_insn_store(fn_,
locals_.lr,
LoadStateValue(offsetof(xe_ppc_state_t, lr), jit_type_nint));
}
// if (locals_.ctr) {
// b.CreateStore(LoadStateValue(
// offsetof(xe_ppc_state_t, ctr),
// jit_type_nint), locals_.ctr);
// }
if (locals_.ctr) {
jit_insn_store(fn_,
locals_.ctr,
LoadStateValue(offsetof(xe_ppc_state_t, ctr), jit_type_nint));
}
// // Fill the split CR values by extracting each one from the CR.
// // This could probably be done faster via an extractvalues or something.
// // Perhaps we could also change it to be a vector<8*i8>.
// jit_value_t cr = NULL;
// for (size_t n = 0; n < XECOUNT(locals_.cr); n++) {
// jit_value_t cr_n = locals_.cr[n];
// if (!cr_n) {
// continue;
// }
// if (!cr) {
// cr = LoadStateValue(
// offsetof(xe_ppc_state_t, cr),
// jit_type_nint);
// }
// b.CreateStore(
// b.CreateTrunc(b.CreateAnd(b.CreateLShr(cr, (28 - n * 4)), 0xF),
// b.getInt8Ty()), cr_n);
// }
// Fill the split CR values by extracting each one from the CR.
// This could probably be done faster via an extractvalues or something.
// Perhaps we could also change it to be a vector<8*i8>.
jit_value_t cr = NULL;
for (size_t n = 0; n < XECOUNT(locals_.cr); n++) {
jit_value_t cr_n = locals_.cr[n];
if (!cr_n) {
continue;
}
if (!cr) {
// Only fetch once. Doing this in here prevents us from having to
// always fetch even if unused.
cr = LoadStateValue(offsetof(xe_ppc_state_t, cr), jit_type_nint);
}
// (cr >> 28 - n * 4) & 0xF
jit_value_t shamt = jit_value_create_nint_constant(
fn_, jit_type_nuint, 28 - n * 4);
jit_insn_store(fn_, cr_n,
jit_insn_and(fn_,
jit_insn_ushr(fn_, cr, shamt),
jit_value_create_nint_constant(fn_, jit_type_ubyte, 0xF)));
}
// for (size_t n = 0; n < XECOUNT(locals_.gpr); n++) {
// if (locals_.gpr[n]) {
// b.CreateStore(LoadStateValue(
// (uint32_t)offsetof(xe_ppc_state_t, r) + 8 * n,
// jit_type_nint), locals_.gpr[n]);
// }
// }
for (size_t n = 0; n < XECOUNT(locals_.gpr); n++) {
if (locals_.gpr[n]) {
jit_insn_store(fn_,
locals_.gpr[n],
LoadStateValue(offsetof(xe_ppc_state_t, r) + 8 * n, jit_type_nint));
}
}
// for (size_t n = 0; n < XECOUNT(locals_.fpr); n++) {
// if (locals_.fpr[n]) {
// b.CreateStore(LoadStateValue(
// (uint32_t)offsetof(xe_ppc_state_t, f) + 8 * n,
// jit_type_float64), locals_.fpr[n]);
// }
// }
for (size_t n = 0; n < XECOUNT(locals_.fpr); n++) {
if (locals_.fpr[n]) {
jit_insn_store(fn_,
locals_.fpr[n],
LoadStateValue(offsetof(xe_ppc_state_t, f) + 8 * n,
jit_type_float64));
}
}
}
void LibjitEmitter::SpillRegisters() {
@ -824,68 +818,72 @@ void LibjitEmitter::SpillRegisters() {
// TODO(benvanik): only flush if actually required, or selective flushes.
// if (locals_.xer) {
// StoreStateValue(
// offsetof(xe_ppc_state_t, xer),
// jit_type_nint,
// b.CreateLoad(locals_.xer));
// }
if (locals_.xer) {
StoreStateValue(
offsetof(xe_ppc_state_t, xer),
jit_type_nint,
jit_insn_load(fn_, locals_.xer));
}
// if (locals_.lr) {
// StoreStateValue(
// offsetof(xe_ppc_state_t, lr),
// jit_type_nint,
// b.CreateLoad(locals_.lr));
// }
if (locals_.lr) {
StoreStateValue(
offsetof(xe_ppc_state_t, lr),
jit_type_nint,
jit_insn_load(fn_, locals_.lr));
}
// if (locals_.ctr) {
// StoreStateValue(
// offsetof(xe_ppc_state_t, ctr),
// jit_type_nint,
// b.CreateLoad(locals_.ctr));
// }
if (locals_.ctr) {
StoreStateValue(
offsetof(xe_ppc_state_t, ctr),
jit_type_nint,
jit_insn_load(fn_, locals_.ctr));
}
// // Stitch together all split CR values.
// // TODO(benvanik): don't flush across calls?
// jit_value_t cr = NULL;
// for (size_t n = 0; n < XECOUNT(locals_.cr); n++) {
// jit_value_t cr_n = locals_.cr[n];
// if (!cr_n) {
// continue;
// }
// cr_n = b.CreateZExt(b.CreateLoad(cr_n), jit_type_nint);
// if (!cr) {
// cr = b.CreateShl(cr_n, n * 4);
// } else {
// cr = b.CreateOr(cr, b.CreateShl(cr_n, n * 4));
// }
// }
// if (cr) {
// StoreStateValue(
// offsetof(xe_ppc_state_t, cr),
// jit_type_nint,
// cr);
// }
// Stitch together all split CR values.
// TODO(benvanik): don't flush across calls?
jit_value_t cr = NULL;
for (size_t n = 0; n < XECOUNT(locals_.cr); n++) {
jit_value_t cr_n = locals_.cr[n];
if (!cr_n) {
continue;
}
// cr |= (cr_n << n * 4)
jit_value_t shamt = jit_value_create_nint_constant(
fn_, jit_type_nuint, n * 4);
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);
if (!cr) {
cr = cr_n;
} else {
cr = jit_insn_or(fn_, cr, cr_n);
}
}
if (cr) {
StoreStateValue(
offsetof(xe_ppc_state_t, cr),
jit_type_nint,
cr);
}
// for (uint32_t n = 0; n < XECOUNT(locals_.gpr); n++) {
// jit_value_t v = locals_.gpr[n];
// if (v) {
// StoreStateValue(
// offsetof(xe_ppc_state_t, r) + 8 * n,
// jit_type_nint,
// b.CreateLoad(locals_.gpr[n]));
// }
// }
for (uint32_t n = 0; n < XECOUNT(locals_.gpr); n++) {
jit_value_t v = locals_.gpr[n];
if (v) {
StoreStateValue(
offsetof(xe_ppc_state_t, r) + 8 * n,
jit_type_nint,
jit_insn_load(fn_, v));
}
}
// for (uint32_t n = 0; n < XECOUNT(locals_.fpr); n++) {
// jit_value_t v = locals_.fpr[n];
// if (v) {
// StoreStateValue(
// offsetof(xe_ppc_state_t, f) + 8 * n,
// jit_type_float64,
// b.CreateLoad(locals_.fpr[n]));
// }
// }
for (uint32_t n = 0; n < XECOUNT(locals_.fpr); n++) {
jit_value_t v = locals_.fpr[n];
if (v) {
StoreStateValue(
offsetof(xe_ppc_state_t, f) + 8 * n,
jit_type_float64,
jit_insn_load(fn_, v));
}
}
}
//jit_value_t LibjitEmitter::xer_value() {

View File

@ -46,11 +46,9 @@ public:
int GenerateIndirectionBranch(uint32_t cia, jit_value_t target,
bool lk, bool likely_local);
jit_value_t LoadStateValue(uint32_t offset, jit_type_t type,
jit_value_t LoadStateValue(size_t offset, jit_type_t type,
const char* name = "");
void StoreStateValue(uint32_t offset, jit_type_t type, jit_value_t value);
jit_value_t cia_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();

View File

@ -56,10 +56,6 @@ typedef struct XECACHEALIGN64 xe_ppc_state {
uint64_t lr; // Link register
uint64_t ctr; // Count register
uint64_t r[32]; // General purpose registers
xe_float4_t v[128]; // VMX128 vector registers
double f[32]; // Floating-point registers
union {
uint32_t value;
struct {
@ -134,6 +130,10 @@ typedef struct XECACHEALIGN64 xe_ppc_state {
} bits;
} fpscr; // Floating-point status and control register
uint64_t r[32]; // General purpose registers
xe_float4_t v[128]; // VMX128 vector registers
double f[32]; // Floating-point registers
// uint32_t get_fprf() {
// return fpscr.value & 0x000F8000;
// }