Setting up locals in codegen based on disassembly results.
This commit is contained in:
parent
d3054839b7
commit
9c86c29140
|
@ -93,12 +93,7 @@ private:
|
||||||
void GenerateSharedBlocks();
|
void GenerateSharedBlocks();
|
||||||
void PrepareBasicBlock(sdb::FunctionBlock* block);
|
void PrepareBasicBlock(sdb::FunctionBlock* block);
|
||||||
void GenerateBasicBlock(sdb::FunctionBlock* block);
|
void GenerateBasicBlock(sdb::FunctionBlock* block);
|
||||||
|
void SetupLocals();
|
||||||
void setup_xer();
|
|
||||||
void setup_lr();
|
|
||||||
void setup_ctr();
|
|
||||||
void setup_cr(uint32_t n);
|
|
||||||
void setup_gpr(uint32_t n);
|
|
||||||
|
|
||||||
xe_memory_ref memory_;
|
xe_memory_ref memory_;
|
||||||
sdb::SymbolDatabase* sdb_;
|
sdb::SymbolDatabase* sdb_;
|
||||||
|
|
|
@ -311,7 +311,9 @@ XEEMITTER(divwux, 0x7C000396, XO )(FunctionGenerator& g, IRBuilder<>& b, I
|
||||||
g.update_gpr_value(i.XO.RT, v);
|
g.update_gpr_value(i.XO.RT, v);
|
||||||
|
|
||||||
// If we are OE=1 we need to clear the overflow bit.
|
// If we are OE=1 we need to clear the overflow bit.
|
||||||
g.update_xer_with_overflow(b.getInt1(0));
|
if (i.XO.OE) {
|
||||||
|
g.update_xer_with_overflow(b.getInt1(0));
|
||||||
|
}
|
||||||
|
|
||||||
if (i.XO.Rc) {
|
if (i.XO.Rc) {
|
||||||
// With cr0 update.
|
// With cr0 update.
|
||||||
|
@ -1018,10 +1020,10 @@ XEDISASMR(ori, 0x60000000, D )(InstrData& i, InstrDisasm& d) {
|
||||||
d.Init("no-op", "OR Immediate", 0);
|
d.Init("no-op", "OR Immediate", 0);
|
||||||
} else {
|
} else {
|
||||||
d.Init("ori", "OR Immediate", 0);
|
d.Init("ori", "OR Immediate", 0);
|
||||||
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kWrite);
|
|
||||||
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kRead);
|
|
||||||
d.AddUImmOperand(i.D.DS, 2);
|
|
||||||
}
|
}
|
||||||
|
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kWrite);
|
||||||
|
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kRead);
|
||||||
|
d.AddUImmOperand(i.D.DS, 2);
|
||||||
return d.Finish();
|
return d.Finish();
|
||||||
}
|
}
|
||||||
XEEMITTER(ori, 0x60000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
XEEMITTER(ori, 0x60000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
||||||
|
|
|
@ -275,6 +275,7 @@ XEDISASMR(bcctrx, 0x4C000420, XL )(InstrData& i, InstrDisasm& d) {
|
||||||
}
|
}
|
||||||
d.AddUImmOperand(i.XL.BO, 1);
|
d.AddUImmOperand(i.XL.BO, 1);
|
||||||
d.AddUImmOperand(i.XL.BI, 1);
|
d.AddUImmOperand(i.XL.BI, 1);
|
||||||
|
d.AddCTR(InstrRegister::kRead);
|
||||||
return d.Finish();
|
return d.Finish();
|
||||||
}
|
}
|
||||||
XEEMITTER(bcctrx, 0x4C000420, XL )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
XEEMITTER(bcctrx, 0x4C000420, XL )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
||||||
|
@ -352,6 +353,7 @@ XEDISASMR(bclrx, 0x4C000020, XL )(InstrData& i, InstrDisasm& d) {
|
||||||
}
|
}
|
||||||
d.AddUImmOperand(i.XL.BO, 1);
|
d.AddUImmOperand(i.XL.BO, 1);
|
||||||
d.AddUImmOperand(i.XL.BI, 1);
|
d.AddUImmOperand(i.XL.BI, 1);
|
||||||
|
d.AddLR(InstrRegister::kRead);
|
||||||
return d.Finish();
|
return d.Finish();
|
||||||
}
|
}
|
||||||
XEEMITTER(bclrx, 0x4C000020, XL )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
XEEMITTER(bclrx, 0x4C000020, XL )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
||||||
|
@ -591,6 +593,12 @@ int XeEmitTrap(FunctionGenerator& g, IRBuilder<>& b, InstrData& i,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XEDISASMR(td, 0x7C000088, X )(InstrData& i, InstrDisasm& d) {
|
||||||
|
d.Init("td", "Trap Doubleword", 0);
|
||||||
|
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
|
||||||
|
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
|
||||||
|
return d.Finish();
|
||||||
|
}
|
||||||
XEEMITTER(td, 0x7C000088, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
XEEMITTER(td, 0x7C000088, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
||||||
// a <- (RA)
|
// a <- (RA)
|
||||||
// b <- (RB)
|
// b <- (RB)
|
||||||
|
@ -605,6 +613,11 @@ XEEMITTER(td, 0x7C000088, X )(FunctionGenerator& g, IRBuilder<>& b, I
|
||||||
i.X.RT);
|
i.X.RT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XEDISASMR(tdi, 0x08000000, D )(InstrData& i, InstrDisasm& d) {
|
||||||
|
d.Init("tdi", "Trap Doubleword Immediate", 0);
|
||||||
|
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
|
||||||
|
return d.Finish();
|
||||||
|
}
|
||||||
XEEMITTER(tdi, 0x08000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
XEEMITTER(tdi, 0x08000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
||||||
// a <- (RA)
|
// a <- (RA)
|
||||||
// if (a < EXTS(SI)) & TO[0] then TRAP
|
// if (a < EXTS(SI)) & TO[0] then TRAP
|
||||||
|
@ -618,6 +631,12 @@ XEEMITTER(tdi, 0x08000000, D )(FunctionGenerator& g, IRBuilder<>& b, I
|
||||||
i.D.RT);
|
i.D.RT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XEDISASMR(tw, 0x7C000008, X )(InstrData& i, InstrDisasm& d) {
|
||||||
|
d.Init("tw", "Trap Word", 0);
|
||||||
|
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
|
||||||
|
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
|
||||||
|
return d.Finish();
|
||||||
|
}
|
||||||
XEEMITTER(tw, 0x7C000008, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
XEEMITTER(tw, 0x7C000008, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
||||||
// a <- EXTS((RA)[32:63])
|
// a <- EXTS((RA)[32:63])
|
||||||
// b <- EXTS((RB)[32:63])
|
// b <- EXTS((RB)[32:63])
|
||||||
|
@ -636,6 +655,11 @@ XEEMITTER(tw, 0x7C000008, X )(FunctionGenerator& g, IRBuilder<>& b, I
|
||||||
i.X.RT);
|
i.X.RT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
XEDISASMR(twi, 0x0C000000, D )(InstrData& i, InstrDisasm& d) {
|
||||||
|
d.Init("twi", "Trap Word Immediate", 0);
|
||||||
|
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
|
||||||
|
return d.Finish();
|
||||||
|
}
|
||||||
XEEMITTER(twi, 0x0C000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
XEEMITTER(twi, 0x0C000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
||||||
// a <- EXTS((RA)[32:63])
|
// a <- EXTS((RA)[32:63])
|
||||||
// if (a < EXTS(SI)) & TO[0] then TRAP
|
// if (a < EXTS(SI)) & TO[0] then TRAP
|
||||||
|
@ -782,10 +806,10 @@ void RegisterEmitCategoryControl() {
|
||||||
XEREGISTEREMITTER(crxor, 0x4C000182);
|
XEREGISTEREMITTER(crxor, 0x4C000182);
|
||||||
XEREGISTEREMITTER(mcrf, 0x4C000000);
|
XEREGISTEREMITTER(mcrf, 0x4C000000);
|
||||||
XEREGISTEREMITTER(sc, 0x44000002);
|
XEREGISTEREMITTER(sc, 0x44000002);
|
||||||
XEREGISTEREMITTER(td, 0x7C000088);
|
XEREGISTERINSTR(td, 0x7C000088);
|
||||||
XEREGISTEREMITTER(tdi, 0x08000000);
|
XEREGISTERINSTR(tdi, 0x08000000);
|
||||||
XEREGISTEREMITTER(tw, 0x7C000008);
|
XEREGISTERINSTR(tw, 0x7C000008);
|
||||||
XEREGISTEREMITTER(twi, 0x0C000000);
|
XEREGISTERINSTR(twi, 0x0C000000);
|
||||||
XEREGISTEREMITTER(mfcr, 0x7C000026);
|
XEREGISTEREMITTER(mfcr, 0x7C000026);
|
||||||
XEREGISTERINSTR(mfspr, 0x7C0002A6);
|
XEREGISTERINSTR(mfspr, 0x7C0002A6);
|
||||||
XEREGISTEREMITTER(mftb, 0x7C0002E6);
|
XEREGISTEREMITTER(mftb, 0x7C0002E6);
|
||||||
|
|
|
@ -155,6 +155,9 @@ void FunctionGenerator::GenerateBasicBlocks() {
|
||||||
PrepareBasicBlock(block);
|
PrepareBasicBlock(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Setup all local variables now that we know what we need.
|
||||||
|
SetupLocals();
|
||||||
|
|
||||||
// Pass 2 fills in instructions.
|
// Pass 2 fills in instructions.
|
||||||
for (std::map<uint32_t, FunctionBlock*>::iterator it = fn_->blocks.begin();
|
for (std::map<uint32_t, FunctionBlock*>::iterator it = fn_->blocks.begin();
|
||||||
it != fn_->blocks.end(); ++it) {
|
it != fn_->blocks.end(); ++it) {
|
||||||
|
@ -240,8 +243,11 @@ void FunctionGenerator::PrepareBasicBlock(FunctionBlock* block) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We really need to know the registers modified, so die if we've been lazy
|
||||||
|
// and haven't implemented the disassemble method yet.
|
||||||
ppc::InstrDisasm d;
|
ppc::InstrDisasm d;
|
||||||
i.type->disassemble(i, d);
|
XEASSERTNOTNULL(i.type->disassemble);
|
||||||
|
XEASSERTZERO(i.type->disassemble(i, d));
|
||||||
|
|
||||||
// Accumulate access bits.
|
// Accumulate access bits.
|
||||||
access_bits.Extend(d.access_bits);
|
access_bits.Extend(d.access_bits);
|
||||||
|
@ -488,8 +494,43 @@ void FunctionGenerator::StoreStateValue(uint32_t offset, Type* type,
|
||||||
b.CreateStore(value, ptr);
|
b.CreateStore(value, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* FunctionGenerator::cia_value() {
|
void FunctionGenerator::SetupLocals() {
|
||||||
return builder_->getInt32(cia_);
|
IRBuilder<>& b = *builder_;
|
||||||
|
|
||||||
|
uint64_t spr_t = access_bits_.spr;
|
||||||
|
if (spr_t & 0x3) {
|
||||||
|
locals_.xer = SetupLocal(b.getInt64Ty(), "xer");
|
||||||
|
}
|
||||||
|
spr_t >>= 2;
|
||||||
|
if (spr_t & 0x3) {
|
||||||
|
locals_.lr = SetupLocal(b.getInt64Ty(), "lr");
|
||||||
|
}
|
||||||
|
spr_t >>= 2;
|
||||||
|
if (spr_t & 0x3) {
|
||||||
|
locals_.ctr = SetupLocal(b.getInt64Ty(), "ctr");
|
||||||
|
}
|
||||||
|
spr_t >>= 2;
|
||||||
|
// TODO: FPCSR
|
||||||
|
|
||||||
|
char name[32];
|
||||||
|
|
||||||
|
uint64_t cr_t = access_bits_.cr;
|
||||||
|
for (int n = 0; n < 8; n++) {
|
||||||
|
if (cr_t & 3) {
|
||||||
|
xesnprintfa(name, XECOUNT(name), "cr%d", n);
|
||||||
|
locals_.cr[n] = SetupLocal(b.getInt8Ty(), name);
|
||||||
|
}
|
||||||
|
cr_t >>= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t gpr_t = access_bits_.gpr;
|
||||||
|
for (int n = 0; n < 32; n++) {
|
||||||
|
if (gpr_t & 3) {
|
||||||
|
xesnprintfa(name, XECOUNT(name), "r%d", n);
|
||||||
|
locals_.gpr[n] = SetupLocal(b.getInt64Ty(), name);
|
||||||
|
}
|
||||||
|
gpr_t >>= 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Value* FunctionGenerator::SetupLocal(llvm::Type* type, const char* name) {
|
Value* FunctionGenerator::SetupLocal(llvm::Type* type, const char* name) {
|
||||||
|
@ -502,11 +543,18 @@ Value* FunctionGenerator::SetupLocal(llvm::Type* type, const char* name) {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value* FunctionGenerator::cia_value() {
|
||||||
|
return builder_->getInt32(cia_);
|
||||||
|
}
|
||||||
|
|
||||||
void FunctionGenerator::FillRegisters() {
|
void FunctionGenerator::FillRegisters() {
|
||||||
// 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.
|
||||||
|
// Though LLVM may do a better job than we can, except across calls.
|
||||||
|
|
||||||
IRBuilder<>& b = *builder_;
|
IRBuilder<>& b = *builder_;
|
||||||
|
|
||||||
if (locals_.xer) {
|
if (locals_.xer) {
|
||||||
|
@ -619,29 +667,16 @@ void FunctionGenerator::SpillRegisters() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionGenerator::setup_xer() {
|
|
||||||
IRBuilder<>& b = *builder_;
|
|
||||||
|
|
||||||
if (locals_.xer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
locals_.xer = SetupLocal(b.getInt64Ty(), "xer");
|
|
||||||
}
|
|
||||||
|
|
||||||
Value* FunctionGenerator::xer_value() {
|
Value* FunctionGenerator::xer_value() {
|
||||||
|
XEASSERTNOTNULL(locals_.xer);
|
||||||
IRBuilder<>& b = *builder_;
|
IRBuilder<>& b = *builder_;
|
||||||
|
|
||||||
setup_xer();
|
|
||||||
|
|
||||||
return b.CreateLoad(locals_.xer);
|
return b.CreateLoad(locals_.xer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionGenerator::update_xer_value(Value* value) {
|
void FunctionGenerator::update_xer_value(Value* value) {
|
||||||
|
XEASSERTNOTNULL(locals_.xer);
|
||||||
IRBuilder<>& b = *builder_;
|
IRBuilder<>& b = *builder_;
|
||||||
|
|
||||||
setup_xer();
|
|
||||||
|
|
||||||
// Extend to 64bits if needed.
|
// Extend to 64bits if needed.
|
||||||
if (!value->getType()->isIntegerTy(64)) {
|
if (!value->getType()->isIntegerTy(64)) {
|
||||||
value = b.CreateZExt(value, b.getInt64Ty());
|
value = b.CreateZExt(value, b.getInt64Ty());
|
||||||
|
@ -650,10 +685,9 @@ void FunctionGenerator::update_xer_value(Value* value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionGenerator::update_xer_with_overflow(Value* value) {
|
void FunctionGenerator::update_xer_with_overflow(Value* value) {
|
||||||
|
XEASSERTNOTNULL(locals_.xer);
|
||||||
IRBuilder<>& b = *builder_;
|
IRBuilder<>& b = *builder_;
|
||||||
|
|
||||||
setup_xer();
|
|
||||||
|
|
||||||
// Expects a i1 indicating overflow.
|
// Expects a i1 indicating overflow.
|
||||||
// Trust the caller that if it's larger than that it's already truncated.
|
// Trust the caller that if it's larger than that it's already truncated.
|
||||||
if (!value->getType()->isIntegerTy(64)) {
|
if (!value->getType()->isIntegerTy(64)) {
|
||||||
|
@ -668,10 +702,9 @@ void FunctionGenerator::update_xer_with_overflow(Value* value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionGenerator::update_xer_with_carry(Value* value) {
|
void FunctionGenerator::update_xer_with_carry(Value* value) {
|
||||||
|
XEASSERTNOTNULL(locals_.xer);
|
||||||
IRBuilder<>& b = *builder_;
|
IRBuilder<>& b = *builder_;
|
||||||
|
|
||||||
setup_xer();
|
|
||||||
|
|
||||||
// Expects a i1 indicating carry.
|
// Expects a i1 indicating carry.
|
||||||
// Trust the caller that if it's larger than that it's already truncated.
|
// Trust the caller that if it's larger than that it's already truncated.
|
||||||
if (!value->getType()->isIntegerTy(64)) {
|
if (!value->getType()->isIntegerTy(64)) {
|
||||||
|
@ -685,10 +718,9 @@ void FunctionGenerator::update_xer_with_carry(Value* value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionGenerator::update_xer_with_overflow_and_carry(Value* value) {
|
void FunctionGenerator::update_xer_with_overflow_and_carry(Value* value) {
|
||||||
|
XEASSERTNOTNULL(locals_.xer);
|
||||||
IRBuilder<>& b = *builder_;
|
IRBuilder<>& b = *builder_;
|
||||||
|
|
||||||
setup_xer();
|
|
||||||
|
|
||||||
// Expects a i1 indicating overflow.
|
// Expects a i1 indicating overflow.
|
||||||
// Trust the caller that if it's larger than that it's already truncated.
|
// Trust the caller that if it's larger than that it's already truncated.
|
||||||
if (!value->getType()->isIntegerTy(64)) {
|
if (!value->getType()->isIntegerTy(64)) {
|
||||||
|
@ -705,29 +737,16 @@ void FunctionGenerator::update_xer_with_overflow_and_carry(Value* value) {
|
||||||
b.CreateStore(xer, locals_.xer);
|
b.CreateStore(xer, locals_.xer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionGenerator::setup_lr() {
|
|
||||||
IRBuilder<>& b = *builder_;
|
|
||||||
|
|
||||||
if (locals_.lr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
locals_.lr = SetupLocal(b.getInt64Ty(), "lr");
|
|
||||||
}
|
|
||||||
|
|
||||||
Value* FunctionGenerator::lr_value() {
|
Value* FunctionGenerator::lr_value() {
|
||||||
|
XEASSERTNOTNULL(locals_.lr);
|
||||||
IRBuilder<>& b = *builder_;
|
IRBuilder<>& b = *builder_;
|
||||||
|
|
||||||
setup_lr();
|
|
||||||
|
|
||||||
return b.CreateLoad(locals_.lr);
|
return b.CreateLoad(locals_.lr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionGenerator::update_lr_value(Value* value) {
|
void FunctionGenerator::update_lr_value(Value* value) {
|
||||||
|
XEASSERTNOTNULL(locals_.lr);
|
||||||
IRBuilder<>& b = *builder_;
|
IRBuilder<>& b = *builder_;
|
||||||
|
|
||||||
setup_lr();
|
|
||||||
|
|
||||||
// Extend to 64bits if needed.
|
// Extend to 64bits if needed.
|
||||||
if (!value->getType()->isIntegerTy(64)) {
|
if (!value->getType()->isIntegerTy(64)) {
|
||||||
value = b.CreateZExt(value, b.getInt64Ty());
|
value = b.CreateZExt(value, b.getInt64Ty());
|
||||||
|
@ -735,29 +754,17 @@ void FunctionGenerator::update_lr_value(Value* value) {
|
||||||
b.CreateStore(value, locals_.lr);
|
b.CreateStore(value, locals_.lr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionGenerator::setup_ctr() {
|
|
||||||
IRBuilder<>& b = *builder_;
|
|
||||||
|
|
||||||
if (locals_.ctr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
locals_.ctr = SetupLocal(b.getInt64Ty(), "ctr");
|
|
||||||
}
|
|
||||||
|
|
||||||
Value* FunctionGenerator::ctr_value() {
|
Value* FunctionGenerator::ctr_value() {
|
||||||
|
XEASSERTNOTNULL(locals_.ctr);
|
||||||
IRBuilder<>& b = *builder_;
|
IRBuilder<>& b = *builder_;
|
||||||
|
|
||||||
setup_ctr();
|
|
||||||
|
|
||||||
return b.CreateLoad(locals_.ctr);
|
return b.CreateLoad(locals_.ctr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionGenerator::update_ctr_value(Value* value) {
|
void FunctionGenerator::update_ctr_value(Value* value) {
|
||||||
|
XEASSERTNOTNULL(locals_.ctr);
|
||||||
IRBuilder<>& b = *builder_;
|
IRBuilder<>& b = *builder_;
|
||||||
|
|
||||||
setup_ctr();
|
|
||||||
|
|
||||||
// Extend to 64bits if needed.
|
// Extend to 64bits if needed.
|
||||||
if (!value->getType()->isIntegerTy(64)) {
|
if (!value->getType()->isIntegerTy(64)) {
|
||||||
value = b.CreateZExt(value, b.getInt64Ty());
|
value = b.CreateZExt(value, b.getInt64Ty());
|
||||||
|
@ -765,34 +772,21 @@ void FunctionGenerator::update_ctr_value(Value* value) {
|
||||||
b.CreateStore(value, locals_.ctr);
|
b.CreateStore(value, locals_.ctr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionGenerator::setup_cr(uint32_t n) {
|
|
||||||
IRBuilder<>& b = *builder_;
|
|
||||||
|
|
||||||
XEASSERT(n >= 0 && n < 8);
|
|
||||||
if (locals_.cr[n]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char name[32];
|
|
||||||
xesnprintfa(name, XECOUNT(name), "cr_f%d", n);
|
|
||||||
locals_.cr[n] = SetupLocal(b.getInt8Ty(), name);
|
|
||||||
}
|
|
||||||
|
|
||||||
Value* FunctionGenerator::cr_value(uint32_t n) {
|
Value* FunctionGenerator::cr_value(uint32_t n) {
|
||||||
|
XEASSERT(n >= 0 && n < 8);
|
||||||
|
XEASSERTNOTNULL(locals_.cr[n]);
|
||||||
IRBuilder<>& b = *builder_;
|
IRBuilder<>& b = *builder_;
|
||||||
|
|
||||||
setup_cr(n);
|
|
||||||
|
|
||||||
Value* v = b.CreateLoad(locals_.cr[n]);
|
Value* v = b.CreateLoad(locals_.cr[n]);
|
||||||
v = b.CreateZExt(v, b.getInt64Ty());
|
v = b.CreateZExt(v, b.getInt64Ty());
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionGenerator::update_cr_value(uint32_t n, Value* value) {
|
void FunctionGenerator::update_cr_value(uint32_t n, Value* value) {
|
||||||
|
XEASSERT(n >= 0 && n < 8);
|
||||||
|
XEASSERTNOTNULL(locals_.cr[n]);
|
||||||
IRBuilder<>& b = *builder_;
|
IRBuilder<>& b = *builder_;
|
||||||
|
|
||||||
setup_cr(n);
|
|
||||||
|
|
||||||
// Truncate to 8 bits if needed.
|
// Truncate to 8 bits if needed.
|
||||||
// TODO(benvanik): also widen?
|
// TODO(benvanik): also widen?
|
||||||
if (!value->getType()->isIntegerTy(8)) {
|
if (!value->getType()->isIntegerTy(8)) {
|
||||||
|
@ -834,22 +828,10 @@ void FunctionGenerator::update_cr_with_cond(
|
||||||
update_cr_value(n, c);
|
update_cr_value(n, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionGenerator::setup_gpr(uint32_t n) {
|
|
||||||
IRBuilder<>& b = *builder_;
|
|
||||||
|
|
||||||
if (locals_.gpr[n]) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char name[30];
|
|
||||||
xesnprintfa(name, XECOUNT(name), "gpr_r%d", n);
|
|
||||||
locals_.gpr[n] = SetupLocal(b.getInt64Ty(), name);
|
|
||||||
}
|
|
||||||
|
|
||||||
Value* FunctionGenerator::gpr_value(uint32_t n) {
|
Value* FunctionGenerator::gpr_value(uint32_t n) {
|
||||||
IRBuilder<>& b = *builder_;
|
|
||||||
|
|
||||||
XEASSERT(n >= 0 && n < 32);
|
XEASSERT(n >= 0 && n < 32);
|
||||||
|
XEASSERTNOTNULL(locals_.gpr[n]);
|
||||||
|
IRBuilder<>& b = *builder_;
|
||||||
|
|
||||||
// Actually r0 is writable, even though nobody should ever do that.
|
// Actually r0 is writable, even though nobody should ever do that.
|
||||||
// Perhaps we can check usage and enable this if safe?
|
// Perhaps we can check usage and enable this if safe?
|
||||||
|
@ -858,15 +840,13 @@ Value* FunctionGenerator::gpr_value(uint32_t n) {
|
||||||
// return b.getInt64(0);
|
// return b.getInt64(0);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
setup_gpr(n);
|
|
||||||
|
|
||||||
return b.CreateLoad(locals_.gpr[n]);
|
return b.CreateLoad(locals_.gpr[n]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionGenerator::update_gpr_value(uint32_t n, Value* value) {
|
void FunctionGenerator::update_gpr_value(uint32_t n, Value* value) {
|
||||||
IRBuilder<>& b = *builder_;
|
|
||||||
|
|
||||||
XEASSERT(n >= 0 && n < 32);
|
XEASSERT(n >= 0 && n < 32);
|
||||||
|
XEASSERTNOTNULL(locals_.gpr[n]);
|
||||||
|
IRBuilder<>& b = *builder_;
|
||||||
|
|
||||||
// See above - r0 can be written.
|
// See above - r0 can be written.
|
||||||
// if (n == 0) {
|
// if (n == 0) {
|
||||||
|
@ -874,8 +854,6 @@ void FunctionGenerator::update_gpr_value(uint32_t n, Value* value) {
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
setup_gpr(n);
|
|
||||||
|
|
||||||
// Extend to 64bits if needed.
|
// Extend to 64bits if needed.
|
||||||
if (!value->getType()->isIntegerTy(64)) {
|
if (!value->getType()->isIntegerTy(64)) {
|
||||||
value = b.CreateZExt(value, b.getInt64Ty());
|
value = b.CreateZExt(value, b.getInt64Ty());
|
||||||
|
|
Loading…
Reference in New Issue