Last of the integer memory instructions and a lot of the fp ones.

This commit is contained in:
Ben Vanik 2013-02-03 21:41:38 -08:00
parent 9dcf2d27fb
commit 7fed5cf579
4 changed files with 756 additions and 174 deletions

78
TODO.md
View File

@ -44,92 +44,18 @@ KeBugCheck:
```
rlwimix
rldiclx
addcx
addex
addicx
andisx
cntlzdx
dcbf
dcbz
divdux
divdx
divwx
eieio
eqvx
extshx
extswx
fabsx
faddsx
faddx
fcfidx
fcmpu
fctidzx
fctiwzx
fdivsx
fdivx
fmaddsx
fmaddx
fmrx
fmsubsx
fmsubx
fmulsx
fmulx
fnegx
fnmsubsx
fnmsubx
frspx
fselx
fsqrtx
fsubsx
fsubx
ldarx
ldx
lwarx
stwcx
lfd
lfdx
lfs
lfsu
lfsux
lfsx
lha
lhax
lhzu
lhzx
lwa
lwarx
lwax
lwbrx
lwzux
mftb
mulldx
nandx
negx
orcx
rldiclx
rldicrx
rldimix
rlwnmx
sldx
sradix
sradx
srawx
srdx
srwx
stbx
stdcx
stdx
stfd
stfdu
stfdx
stfiwx
stfs
stfsu
stfsx
stwbrx
stwcx
stwux
subfcx
subfzex
sync
```
### XER CA bit (carry)

View File

@ -83,13 +83,16 @@ public:
llvm::Value* gpr_value(uint32_t n);
void update_gpr_value(uint32_t n, llvm::Value* value);
llvm::Value* fpr_value(uint32_t n);
void update_fpr_value(uint32_t n, llvm::Value* value);
llvm::Value* GetMembase();
llvm::Value* GetMemoryAddress(uint32_t cia, llvm::Value* addr);
llvm::Value* ReadMemory(
uint32_t cia, llvm::Value* addr, uint32_t size, bool extend);
uint32_t cia, llvm::Value* addr, uint32_t size, bool acquire = false);
void WriteMemory(
uint32_t cia, llvm::Value* addr, uint32_t size, llvm::Value* value);
uint32_t cia, llvm::Value* addr, uint32_t size, llvm::Value* value,
bool release = false);
private:
void GenerateSharedBlocks();
@ -128,6 +131,7 @@ private:
llvm::Value* ctr;
llvm::Value* cr[8];
llvm::Value* gpr[32];
llvm::Value* fpr[32];
} locals_;
};

View File

@ -182,9 +182,34 @@ XEEMITTER(ldx, 0x7C00002A, X )(FunctionGenerator& g, IRBuilder<>& b, I
return 1;
}
XEDISASMR(lha, 0xA8000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("lha", "Load Halfword Algebraic", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kWrite);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEEMITTER(lha, 0xA8000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// if RA = 0 then
// b <- 0
// else
// b <- (RA)
// EA <- b + EXTS(D)
// RT <- EXTS(MEM(EA, 2))
Value* ea = b.getInt64(XEEXTS16(i.D.DS));
if (i.D.RA) {
ea = b.CreateAdd(g.gpr_value(i.D.RA), ea);
}
Value* v = b.CreateSExt(g.ReadMemory(i.address, ea, 2, false),
b.getInt64Ty());
g.update_gpr_value(i.D.RT, v);
return 0;
}
XEEMITTER(lhau, 0xAC000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
@ -197,9 +222,34 @@ XEEMITTER(lhaux, 0x7C0002EE, X )(FunctionGenerator& g, IRBuilder<>& b, I
return 1;
}
XEDISASMR(lhax, 0x7C0002AE, X )(InstrData& i, InstrDisasm& d) {
d.Init("lhax", "Load Halfword Algebraic Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEEMITTER(lhax, 0x7C0002AE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// if RA = 0 then
// b <- 0
// else
// b <- (RA)
// EA <- b + (RB)
// RT <- EXTS(MEM(EA, 2))
Value* ea = g.gpr_value(i.X.RB);
if (i.X.RA) {
ea = b.CreateAdd(g.gpr_value(i.X.RA), ea);
}
Value* v = b.CreateSExt(g.ReadMemory(i.address, ea, 2, false),
b.getInt64Ty());
g.update_gpr_value(i.X.RT, v);
return 0;
}
XEDISASMR(lhz, 0xA0000000, D )(InstrData& i, InstrDisasm& d) {
@ -231,24 +281,103 @@ XEEMITTER(lhz, 0xA0000000, D )(FunctionGenerator& g, IRBuilder<>& b, I
return 0;
}
XEDISASMR(lhzu, 0xA4000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("lhzu", "Load Halfword and Zero with Update", 0);
d.AddRegOperand(InstrRegister::kGPR, i.D.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEEMITTER(lhzu, 0xA4000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// EA <- (RA) + EXTS(D)
// RT <- i48.0 || MEM(EA, 2)
// RA <- EA
Value* ea = b.CreateAdd(g.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS)));
Value* v = g.ReadMemory(i.address, ea, 2, false);
g.update_gpr_value(i.D.RT, v);
g.update_gpr_value(i.D.RA, ea);
return 0;
}
XEDISASMR(lhzux, 0x7C00026E, X )(InstrData& i, InstrDisasm& d) {
d.Init("lhzux", "Load Halfword and Zero with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEEMITTER(lhzux, 0x7C00026E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// EA <- (RA) + (RB)
// RT <- i48.0 || MEM(EA, 2)
// RA <- EA
Value* ea = b.CreateAdd(g.gpr_value(i.X.RA), g.gpr_value(i.X.RB));
Value* v = g.ReadMemory(i.address, ea, 2, false);
g.update_gpr_value(i.X.RT, v);
g.update_gpr_value(i.X.RA, ea);
return 0;
}
XEDISASMR(lhzx, 0x7C00022E, X )(InstrData& i, InstrDisasm& d) {
d.Init("lhzx", "Load Halfword and Zero Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEEMITTER(lhzx, 0x7C00022E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// if RA = 0 then
// b <- 0
// else
// b <- (RA)
// EA <- b + (RB)
// RT <- i48.0 || MEM(EA, 2)
Value* ea = g.gpr_value(i.X.RB);
if (i.X.RA) {
ea = b.CreateAdd(g.gpr_value(i.X.RA), ea);
}
Value* v = g.ReadMemory(i.address, ea, 2, false);
g.update_gpr_value(i.X.RT, v);
return 0;
}
XEDISASMR(lwa, 0xE8000002, DS )(InstrData& i, InstrDisasm& d) {
d.Init("lwa", "Load Word Algebraic", 0);
d.AddRegOperand(InstrRegister::kGPR, i.DS.RT, InstrRegister::kWrite);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.DS.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.DS.DS << 2), 2);
return d.Finish();
}
XEEMITTER(lwa, 0xE8000002, DS )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// if RA = 0 then
// b <- 0
// else
// b <- (RA)
// EA <- b + EXTS(D || 00)
// RT <- EXTS(MEM(EA, 4))
Value* ea = b.getInt64(XEEXTS16(i.DS.DS << 2));
if (i.DS.RA) {
ea = b.CreateAdd(g.gpr_value(i.DS.RA), ea);
}
Value* v = b.CreateSExt(g.ReadMemory(i.address, ea, 4, false),
b.getInt64Ty());
g.update_gpr_value(i.DS.RT, v);
return 0;
}
XEDISASMR(lwaux, 0x7C0002EA, X )(InstrData& i, InstrDisasm& d) {
@ -351,9 +480,24 @@ XEEMITTER(lwzu, 0x84000000, D )(FunctionGenerator& g, IRBuilder<>& b, I
return 0;
}
XEDISASMR(lwzux, 0x7C00006E, X )(InstrData& i, InstrDisasm& d) {
d.Init("lwzux", "Load Word and Zero with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEEMITTER(lwzux, 0x7C00006E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// EA <- (RA) + (RB)
// RT <- i32.0 || MEM(EA, 4)
// RA <- EA
Value* ea = b.CreateAdd(g.gpr_value(i.X.RA), g.gpr_value(i.X.RB));
Value* v = g.ReadMemory(i.address, ea, 4, false);
g.update_gpr_value(i.X.RT, v);
g.update_gpr_value(i.X.RA, ea);
return 0;
}
XEDISASMR(lwzx, 0x7C00002E, X )(InstrData& i, InstrDisasm& d) {
@ -536,14 +680,53 @@ XEEMITTER(stdu, 0xF8000001, DS )(FunctionGenerator& g, IRBuilder<>& b, I
return 0;
}
XEDISASMR(stdux, 0x7C00016A, X )(InstrData& i, InstrDisasm& d) {
d.Init("stdux", "Store Doubleword with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
if (i.DS.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEEMITTER(stdux, 0x7C00016A, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// if RA = 0 then
// b <- 0
// else
// b <- (RA)
// EA <- b + (RB)
// MEM(EA, 8) <- (RS)
Value* ea = g.gpr_value(i.X.RB);
if (i.X.RA) {
ea = b.CreateAdd(g.gpr_value(i.X.RA), ea);
}
Value* v = g.gpr_value(i.X.RT);
g.WriteMemory(i.address, ea, 8, v);
return 0;
}
XEDISASMR(stdx, 0x7C00012A, X )(InstrData& i, InstrDisasm& d) {
d.Init("stdx", "Store Doubleword Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEEMITTER(stdx, 0x7C00012A, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// EA <- (RA) + (RB)
// MEM(EA, 8) <- (RS)
// RA <- EA
Value* ea = b.CreateAdd(g.gpr_value(i.X.RA), g.gpr_value(i.X.RB));
Value* v = g.gpr_value(i.X.RT);
g.WriteMemory(i.address, ea, 8, v);
g.update_gpr_value(i.X.RA, ea);
return 0;
}
XEDISASMR(sth, 0xB0000000, D )(InstrData& i, InstrDisasm& d) {
@ -831,9 +1014,38 @@ XEEMITTER(ldarx, 0x7C0000A8, X )(FunctionGenerator& g, IRBuilder<>& b, I
return 1;
}
XEDISASMR(lwarx, 0x7C000028, X )(InstrData& i, InstrDisasm& d) {
d.Init("lwarx", "Load Word And Reserve Indexed", 0);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kWrite);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEEMITTER(lwarx, 0x7C000028, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// if RA = 0 then
// b <- 0
// else
// b <- (RA)
// EA <- b + (RB)
// RESERVE <- 1
// RESERVE_LENGTH <- 4
// RESERVE_ADDR <- real_addr(EA)
// RT <- i32.0 || MEM(EA, 4)
// TODO(benvanik): make this right
Value* ea = g.gpr_value(i.X.RB);
if (i.X.RA) {
ea = b.CreateAdd(g.gpr_value(i.X.RA), ea);
}
Value* v = g.ReadMemory(i.address, ea, 4, /* acquire */ true);
g.update_gpr_value(i.X.RT, v);
return 0;
}
XEEMITTER(stdcx, 0x7C0001AD, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
@ -841,9 +1053,40 @@ XEEMITTER(stdcx, 0x7C0001AD, X )(FunctionGenerator& g, IRBuilder<>& b, I
return 1;
}
XEDISASMR(stwcx, 0x7C00012D, X )(InstrData& i, InstrDisasm& d) {
d.Init("stwcx", "Store Word Conditional Indexed",
InstrDisasm::kRc);
d.AddRegOperand(InstrRegister::kGPR, i.X.RT, InstrRegister::kRead);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEEMITTER(stwcx, 0x7C00012D, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// if RA = 0 then
// b <- 0
// else
// b <- (RA)
// EA <- b + (RB)
// RESERVE stuff...
// MEM(EA, 4) <- (RS)[32:63]
// n <- 1 if store performed
// CR0[LT GT EQ SO] = 0b00 || n || XER[SO]
// TODO(benvanik): make this right
Value* ea = b.getInt64(XEEXTS16(i.D.DS));
if (i.D.RA) {
ea = b.CreateAdd(g.gpr_value(i.D.RA), ea);
}
Value* v = g.gpr_value(i.D.RT);
g.WriteMemory(i.address, ea, 4, v, /* release */ true);
// TODO(benvanik): update CR0
return 0;
}
XEEMITTER(sync, 0x7C0004AC, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
@ -854,92 +1097,447 @@ XEEMITTER(sync, 0x7C0004AC, X )(FunctionGenerator& g, IRBuilder<>& b, I
// Floating-point load (A-19)
XEDISASMR(lfd, 0xC8000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("lfd", "Load Floating-Point Double", 0);
d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kWrite);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEEMITTER(lfd, 0xC8000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// if RA = 0 then
// b <- 0
// else
// b <- (RA)
// EA <- b + EXTS(D)
// FRT <- MEM(EA, 8)
Value* ea = b.getInt64(XEEXTS16(i.D.DS));
if (i.D.RA) {
ea = b.CreateAdd(g.gpr_value(i.D.RA), ea);
}
Value* v = g.ReadMemory(i.address, ea, 8, false);
v = b.CreateBitCast(v, b.getDoubleTy());
g.update_fpr_value(i.D.RT, v);
return 0;
}
XEDISASMR(lfdu, 0xCC000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("lfdu", "Load Floating-Point Double with Update", 0);
d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEEMITTER(lfdu, 0xCC000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// EA <- (RA) + EXTS(D)
// FRT <- MEM(EA, 8)
// RA <- EA
Value* ea = b.CreateAdd(g.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS)));
Value* v = g.ReadMemory(i.address, ea, 8, false);
v = b.CreateBitCast(v, b.getDoubleTy());
g.update_fpr_value(i.D.RT, v);
g.update_gpr_value(i.D.RA, ea);
return 0;
}
XEDISASMR(lfdux, 0x7C0004EE, X )(InstrData& i, InstrDisasm& d) {
d.Init("lfdux", "Load Floating-Point Double with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEEMITTER(lfdux, 0x7C0004EE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// EA <- (RA) + (RB)
// FRT <- MEM(EA, 8)
// RA <- EA
Value* ea = b.CreateAdd(g.gpr_value(i.X.RA), g.gpr_value(i.X.RB));
Value* v = g.ReadMemory(i.address, ea, 8, false);
v = b.CreateBitCast(v, b.getDoubleTy());
g.update_fpr_value(i.X.RT, v);
g.update_gpr_value(i.X.RA, ea);
return 0;
}
XEDISASMR(lfdx, 0x7C0004AE, X )(InstrData& i, InstrDisasm& d) {
d.Init("lfdx", "Load Floating-Point Double Indexed", 0);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEEMITTER(lfdx, 0x7C0004AE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// if RA = 0 then
// b <- 0
// else
// b <- (RA)
// EA <- b + (RB)
// FRT <- MEM(EA, 8)
Value* ea = g.gpr_value(i.X.RB);
if (i.X.RA) {
ea = b.CreateAdd(g.gpr_value(i.X.RA), ea);
}
Value* v = g.ReadMemory(i.address, ea, 8, false);
v = b.CreateBitCast(v, b.getDoubleTy());
g.update_fpr_value(i.X.RT, v);
return 0;
}
XEDISASMR(lfs, 0xC0000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("lfs", "Load Floating-Point Single", 0);
d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kWrite);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEEMITTER(lfs, 0xC0000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// if RA = 0 then
// b <- 0
// else
// b <- (RA)
// EA <- b + EXTS(D)
// FRT <- DOUBLE(MEM(EA, 4))
Value* ea = b.getInt64(XEEXTS16(i.D.DS));
if (i.D.RA) {
ea = b.CreateAdd(g.gpr_value(i.D.RA), ea);
}
Value* v = g.ReadMemory(i.address, ea, 4, false);
v = b.CreateFPExt(b.CreateBitCast(v, b.getFloatTy()), b.getDoubleTy());
g.update_fpr_value(i.D.RT, v);
return 0;
}
XEDISASMR(lfsu, 0xC4000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("lfsu", "Load Floating-Point Single with Update", 0);
d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEEMITTER(lfsu, 0xC4000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// EA <- (RA) + EXTS(D)
// FRT <- DOUBLE(MEM(EA, 4))
// RA <- EA
Value* ea = b.CreateAdd(g.gpr_value(i.D.RA), b.getInt64(XEEXTS16(i.D.DS)));
Value* v = g.ReadMemory(i.address, ea, 4, false);
v = b.CreateFPExt(b.CreateBitCast(v, b.getFloatTy()), b.getDoubleTy());
g.update_fpr_value(i.D.RT, v);
g.update_gpr_value(i.D.RA, ea);
return 0;
}
XEDISASMR(lfsux, 0x7C00046E, X )(InstrData& i, InstrDisasm& d) {
d.Init("lfsux", "Load Floating-Point Single with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEEMITTER(lfsux, 0x7C00046E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// EA <- (RA) + (RB)
// FRT <- DOUBLE(MEM(EA, 4))
// RA <- EA
Value* ea = b.CreateAdd(g.gpr_value(i.X.RA), g.gpr_value(i.X.RB));
Value* v = g.ReadMemory(i.address, ea, 4, false);
v = b.CreateFPExt(b.CreateBitCast(v, b.getFloatTy()), b.getDoubleTy());
g.update_fpr_value(i.X.RT, v);
g.update_gpr_value(i.X.RA, ea);
return 0;
}
XEDISASMR(lfsx, 0x7C00042E, X )(InstrData& i, InstrDisasm& d) {
d.Init("lfsx", "Load Floating-Point Single Indexed", 0);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kWrite);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEEMITTER(lfsx, 0x7C00042E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// if RA = 0 then
// b <- 0
// else
// b <- (RA)
// EA <- b + (RB)
// FRT <- DOUBLE(MEM(EA, 4))
Value* ea = g.gpr_value(i.X.RB);
if (i.X.RA) {
ea = b.CreateAdd(g.gpr_value(i.X.RA), ea);
}
Value* v = g.ReadMemory(i.address, ea, 4, false);
v = b.CreateFPExt(b.CreateBitCast(v, b.getFloatTy()), b.getDoubleTy());
g.update_fpr_value(i.X.RT, v);
return 0;
}
// Floating-point store (A-20)
XEDISASMR(stfd, 0xD8000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("stfd", "Store Floating-Point Double", 0);
d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kRead);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEEMITTER(stfd, 0xD8000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// if RA = 0 then
// b <- 0
// else
// b <- (RA)
// EA <- b + EXTS(D)
// MEM(EA, 8) <- (FRS)
Value* ea = b.getInt64(XEEXTS16(i.D.DS));
if (i.D.RA) {
ea = b.CreateAdd(g.gpr_value(i.D.RA), ea);
}
Value* v = g.fpr_value(i.D.RT);
v = b.CreateBitCast(v, b.getInt64Ty());
g.WriteMemory(i.address, ea, 8, v);
return 0;
}
XEDISASMR(stfdu, 0xDC000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("stfdu", "Store Floating-Point Double with Update", 0);
d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEEMITTER(stfdu, 0xDC000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// EA <- (RA) + EXTS(D)
// MEM(EA, 8) <- (FRS)
// RA <- EA
Value* ea = b.CreateAdd(g.gpr_value(i.D.RA),
b.getInt64(XEEXTS16(i.D.DS)));
Value* v = g.fpr_value(i.D.RT);
v = b.CreateBitCast(v, b.getInt64Ty());
g.WriteMemory(i.address, ea, 8, v);
g.update_gpr_value(i.D.RA, ea);
return 0;
}
XEDISASMR(stfdux, 0x7C0005EE, X )(InstrData& i, InstrDisasm& d) {
d.Init("stfdux", "Store Floating-Point Double with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEEMITTER(stfdux, 0x7C0005EE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// EA <- (RA) + (RB)
// MEM(EA, 8) <- (FRS)
// RA <- EA
Value* ea = b.CreateAdd(g.gpr_value(i.X.RA), g.gpr_value(i.X.RB));
Value* v = g.fpr_value(i.X.RT);
v = b.CreateBitCast(v, b.getInt64Ty());
g.WriteMemory(i.address, ea, 8, v);
g.update_gpr_value(i.X.RA, ea);
return 0;
}
XEDISASMR(stfdx, 0x7C0005AE, X )(InstrData& i, InstrDisasm& d) {
d.Init("stfdx", "Store Floating-Point Double Indexed", 0);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kRead);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEEMITTER(stfdx, 0x7C0005AE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// if RA = 0 then
// b <- 0
// else
// b <- (RA)
// EA <- b + (RB)
// MEM(EA, 8) <- (FRS)
Value* ea = g.gpr_value(i.X.RB);
if (i.X.RA) {
ea = b.CreateAdd(g.gpr_value(i.X.RA), ea);
}
Value* v = g.fpr_value(i.X.RT);
v = b.CreateBitCast(v, b.getInt64Ty());
g.WriteMemory(i.address, ea, 8, v);
return 0;
}
XEDISASMR(stfiwx, 0x7C0007AE, X )(InstrData& i, InstrDisasm& d) {
d.Init("stfiwx", "Store Floating-Point as Integer Word Indexed", 0);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kRead);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEEMITTER(stfiwx, 0x7C0007AE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// if RA = 0 then
// b <- 0
// else
// b <- (RA)
// EA <- b + (RB)
// MEM(EA, 4) <- (FRS)[32:63]
Value* ea = g.gpr_value(i.X.RB);
if (i.X.RA) {
ea = b.CreateAdd(g.gpr_value(i.D.RA), ea);
}
Value* v = g.fpr_value(i.X.RT);
v = b.CreateBitCast(v, b.getInt64Ty());
g.WriteMemory(i.address, ea, 4, v);
return 0;
}
XEDISASMR(stfs, 0xD0000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("stfs", "Store Floating-Point Single", 0);
d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kRead);
if (i.D.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEEMITTER(stfs, 0xD0000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// if RA = 0 then
// b <- 0
// else
// b <- (RA)
// EA <- b + EXTS(D)
// MEM(EA, 4) <- SINGLE(FRS)
Value* ea = b.getInt64(XEEXTS16(i.D.DS));
if (i.D.RA) {
ea = b.CreateAdd(g.gpr_value(i.D.RA), ea);
}
Value* v = g.fpr_value(i.D.RT);
v = b.CreateBitCast(b.CreateFPTrunc(v, b.getFloatTy()), b.getInt32Ty());
g.WriteMemory(i.address, ea, 4, v);
return 0;
}
XEDISASMR(stfsu, 0xD4000000, D )(InstrData& i, InstrDisasm& d) {
d.Init("stfsu", "Store Floating-Point Single with Update", 0);
d.AddRegOperand(InstrRegister::kFPR, i.D.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.D.RA, InstrRegister::kReadWrite);
d.AddSImmOperand(XEEXTS16(i.D.DS), 2);
return d.Finish();
}
XEEMITTER(stfsu, 0xD4000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// EA <- (RA) + EXTS(D)
// MEM(EA, 4) <- SINGLE(FRS)
// RA <- EA
Value* ea = b.CreateAdd(g.gpr_value(i.D.RA),
b.getInt64(XEEXTS16(i.D.DS)));
Value* v = g.fpr_value(i.D.RT);
v = b.CreateBitCast(b.CreateFPTrunc(v, b.getFloatTy()), b.getInt32Ty());
g.WriteMemory(i.address, ea, 4, v);
g.update_gpr_value(i.D.RA, ea);
return 0;
}
XEDISASMR(stfsux, 0x7C00056E, X )(InstrData& i, InstrDisasm& d) {
d.Init("stfsux", "Store Floating-Point Single with Update Indexed", 0);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kRead);
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kReadWrite);
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEEMITTER(stfsux, 0x7C00056E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// EA <- (RA) + (RB)
// MEM(EA, 4) <- SINGLE(FRS)
// RA <- EA
Value* ea = b.CreateAdd(g.gpr_value(i.X.RA), g.gpr_value(i.X.RB));
Value* v = g.fpr_value(i.X.RT);
v = b.CreateBitCast(b.CreateFPTrunc(v, b.getFloatTy()), b.getInt32Ty());
g.WriteMemory(i.address, ea, 4, v);
g.update_gpr_value(i.X.RA, ea);
return 0;
}
XEDISASMR(stfsx, 0x7C00052E, X )(InstrData& i, InstrDisasm& d) {
d.Init("stfsx", "Store Floating-Point Single Indexed", 0);
d.AddRegOperand(InstrRegister::kFPR, i.X.RT, InstrRegister::kRead);
if (i.X.RA) {
d.AddRegOperand(InstrRegister::kGPR, i.X.RA, InstrRegister::kRead);
} else {
d.AddUImmOperand(0, 1);
}
d.AddRegOperand(InstrRegister::kGPR, i.X.RB, InstrRegister::kRead);
return d.Finish();
}
XEEMITTER(stfsx, 0x7C00052E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
// if RA = 0 then
// b <- 0
// else
// b <- (RA)
// EA <- b + (RB)
// MEM(EA, 4) <- SINGLE(FRS)
Value* ea = g.gpr_value(i.X.RB);
if (i.X.RA) {
ea = b.CreateAdd(g.gpr_value(i.X.RA), ea);
}
Value* v = g.fpr_value(i.X.RT);
v = b.CreateBitCast(b.CreateFPTrunc(v, b.getFloatTy()), b.getInt32Ty());
g.WriteMemory(i.address, ea, 4, v);
return 0;
}
@ -998,36 +1596,36 @@ void RegisterEmitCategoryMemory() {
XEREGISTERINSTR(ldu, 0xE8000001);
XEREGISTEREMITTER(ldux, 0x7C00006A);
XEREGISTEREMITTER(ldx, 0x7C00002A);
XEREGISTEREMITTER(lha, 0xA8000000);
XEREGISTERINSTR(lha, 0xA8000000);
XEREGISTEREMITTER(lhau, 0xAC000000);
XEREGISTEREMITTER(lhaux, 0x7C0002EE);
XEREGISTEREMITTER(lhax, 0x7C0002AE);
XEREGISTERINSTR(lhax, 0x7C0002AE);
XEREGISTERINSTR(lhz, 0xA0000000);
XEREGISTEREMITTER(lhzu, 0xA4000000);
XEREGISTEREMITTER(lhzux, 0x7C00026E);
XEREGISTEREMITTER(lhzx, 0x7C00022E);
XEREGISTEREMITTER(lwa, 0xE8000002);
XEREGISTEREMITTER(lwaux, 0x7C0002EA);
XEREGISTEREMITTER(lwax, 0x7C0002AA);
XEREGISTERINSTR(lhzu, 0xA4000000);
XEREGISTERINSTR(lhzux, 0x7C00026E);
XEREGISTERINSTR(lhzx, 0x7C00022E);
XEREGISTERINSTR(lwa, 0xE8000002);
XEREGISTERINSTR(lwaux, 0x7C0002EA);
XEREGISTERINSTR(lwax, 0x7C0002AA);
XEREGISTERINSTR(lwz, 0x80000000);
XEREGISTERINSTR(lwzu, 0x84000000);
XEREGISTEREMITTER(lwzux, 0x7C00006E);
XEREGISTERINSTR(lwzux, 0x7C00006E);
XEREGISTERINSTR(lwzx, 0x7C00002E);
XEREGISTERINSTR(stb, 0x98000000);
XEREGISTERINSTR(stbu, 0x9C000000);
XEREGISTEREMITTER(stbux, 0x7C0001EE);
XEREGISTEREMITTER(stbx, 0x7C0001AE);
XEREGISTERINSTR(stbux, 0x7C0001EE);
XEREGISTERINSTR(stbx, 0x7C0001AE);
XEREGISTERINSTR(std, 0xF8000000);
XEREGISTERINSTR(stdu, 0xF8000001);
XEREGISTEREMITTER(stdux, 0x7C00016A);
XEREGISTEREMITTER(stdx, 0x7C00012A);
XEREGISTERINSTR(stdux, 0x7C00016A);
XEREGISTERINSTR(stdx, 0x7C00012A);
XEREGISTERINSTR(sth, 0xB0000000);
XEREGISTERINSTR(sthu, 0xB4000000);
XEREGISTEREMITTER(sthux, 0x7C00036E);
XEREGISTERINSTR(sthux, 0x7C00036E);
XEREGISTERINSTR(sthx, 0x7C00032E);
XEREGISTERINSTR(stw, 0x90000000);
XEREGISTERINSTR(stwu, 0x94000000);
XEREGISTEREMITTER(stwux, 0x7C00016E);
XEREGISTERINSTR(stwux, 0x7C00016E);
XEREGISTERINSTR(stwx, 0x7C00012E);
XEREGISTEREMITTER(lhbrx, 0x7C00062C);
XEREGISTEREMITTER(lwbrx, 0x7C00042C);
@ -1044,27 +1642,27 @@ void RegisterEmitCategoryMemory() {
XEREGISTEREMITTER(eieio, 0x7C0006AC);
XEREGISTEREMITTER(isync, 0x4C00012C);
XEREGISTEREMITTER(ldarx, 0x7C0000A8);
XEREGISTEREMITTER(lwarx, 0x7C000028);
XEREGISTERINSTR(lwarx, 0x7C000028);
XEREGISTEREMITTER(stdcx, 0x7C0001AD);
XEREGISTEREMITTER(stwcx, 0x7C00012D);
XEREGISTERINSTR(stwcx, 0x7C00012D);
XEREGISTEREMITTER(sync, 0x7C0004AC);
XEREGISTEREMITTER(lfd, 0xC8000000);
XEREGISTEREMITTER(lfdu, 0xCC000000);
XEREGISTEREMITTER(lfdux, 0x7C0004EE);
XEREGISTEREMITTER(lfdx, 0x7C0004AE);
XEREGISTEREMITTER(lfs, 0xC0000000);
XEREGISTEREMITTER(lfsu, 0xC4000000);
XEREGISTEREMITTER(lfsux, 0x7C00046E);
XEREGISTEREMITTER(lfsx, 0x7C00042E);
XEREGISTEREMITTER(stfd, 0xD8000000);
XEREGISTEREMITTER(stfdu, 0xDC000000);
XEREGISTEREMITTER(stfdux, 0x7C0005EE);
XEREGISTEREMITTER(stfdx, 0x7C0005AE);
XEREGISTEREMITTER(stfiwx, 0x7C0007AE);
XEREGISTEREMITTER(stfs, 0xD0000000);
XEREGISTEREMITTER(stfsu, 0xD4000000);
XEREGISTEREMITTER(stfsux, 0x7C00056E);
XEREGISTEREMITTER(stfsx, 0x7C00052E);
XEREGISTERINSTR(lfd, 0xC8000000);
XEREGISTERINSTR(lfdu, 0xCC000000);
XEREGISTERINSTR(lfdux, 0x7C0004EE);
XEREGISTERINSTR(lfdx, 0x7C0004AE);
XEREGISTERINSTR(lfs, 0xC0000000);
XEREGISTERINSTR(lfsu, 0xC4000000);
XEREGISTERINSTR(lfsux, 0x7C00046E);
XEREGISTERINSTR(lfsx, 0x7C00042E);
XEREGISTERINSTR(stfd, 0xD8000000);
XEREGISTERINSTR(stfdu, 0xDC000000);
XEREGISTERINSTR(stfdux, 0x7C0005EE);
XEREGISTERINSTR(stfdx, 0x7C0005AE);
XEREGISTERINSTR(stfiwx, 0x7C0007AE);
XEREGISTERINSTR(stfs, 0xD0000000);
XEREGISTERINSTR(stfsu, 0xD4000000);
XEREGISTERINSTR(stfsux, 0x7C00056E);
XEREGISTERINSTR(stfsx, 0x7C00052E);
XEREGISTEREMITTER(dcbf, 0x7C0000AC);
XEREGISTEREMITTER(dcbst, 0x7C00006C);
XEREGISTERINSTR(dcbt, 0x7C00022C);

View File

@ -77,6 +77,9 @@ FunctionGenerator::FunctionGenerator(
for (size_t n = 0; n < XECOUNT(locals_.gpr); n++) {
locals_.gpr[n] = NULL;
}
for (size_t n = 0; n < XECOUNT(locals_.fpr); n++) {
locals_.fpr[n] = NULL;
}
if (FLAGS_log_codegen) {
printf("%s:\n", fn->name());
@ -548,6 +551,15 @@ void FunctionGenerator::SetupLocals() {
}
gpr_t >>= 2;
}
uint64_t fpr_t = access_bits_.fpr;
for (int n = 0; n < 32; n++) {
if (fpr_t & 3) {
xesnprintfa(name, XECOUNT(name), "f%d", n);
locals_.fpr[n] = SetupLocal(b.getDoubleTy(), name);
}
fpr_t >>= 2;
}
}
Value* FunctionGenerator::SetupLocal(llvm::Type* type, const char* name) {
@ -611,7 +623,6 @@ void FunctionGenerator::FillRegisters() {
b.getInt8Ty()), cr_n);
}
// Note that we skip zero.
for (size_t n = 0; n < XECOUNT(locals_.gpr); n++) {
if (locals_.gpr[n]) {
b.CreateStore(LoadStateValue(
@ -619,6 +630,14 @@ void FunctionGenerator::FillRegisters() {
b.getInt64Ty()), locals_.gpr[n]);
}
}
for (size_t n = 0; n < XECOUNT(locals_.fpr); n++) {
if (locals_.fpr[n]) {
b.CreateStore(LoadStateValue(
offsetof(xe_ppc_state_t, f) + 8 * n,
b.getDoubleTy()), locals_.fpr[n]);
}
}
}
void FunctionGenerator::SpillRegisters() {
@ -672,7 +691,6 @@ void FunctionGenerator::SpillRegisters() {
cr);
}
// Note that we skip zero.
for (uint32_t n = 0; n < XECOUNT(locals_.gpr); n++) {
Value* v = locals_.gpr[n];
if (v) {
@ -682,6 +700,16 @@ void FunctionGenerator::SpillRegisters() {
b.CreateLoad(locals_.gpr[n]));
}
}
for (uint32_t n = 0; n < XECOUNT(locals_.fpr); n++) {
Value* v = locals_.fpr[n];
if (v) {
StoreStateValue(
offsetof(xe_ppc_state_t, f) + 8 * n,
b.getDoubleTy(),
b.CreateLoad(locals_.fpr[n]));
}
}
}
Value* FunctionGenerator::xer_value() {
@ -879,6 +907,21 @@ void FunctionGenerator::update_gpr_value(uint32_t n, Value* value) {
b.CreateStore(value, locals_.gpr[n]);
}
Value* FunctionGenerator::fpr_value(uint32_t n) {
XEASSERT(n >= 0 && n < 32);
XEASSERTNOTNULL(locals_.fpr[n]);
IRBuilder<>& b = *builder_;
return b.CreateLoad(locals_.fpr[n]);
}
void FunctionGenerator::update_fpr_value(uint32_t n, Value* value) {
XEASSERT(n >= 0 && n < 32);
XEASSERTNOTNULL(locals_.fpr[n]);
IRBuilder<>& b = *builder_;
value = b.CreateFPExtOrFPTrunc(value, b.getDoubleTy());
b.CreateStore(value, locals_.fpr[n]);
}
Value* FunctionGenerator::GetMembase() {
Value* v = gen_module_->getGlobalVariable("xe_memory_base");
return builder_->CreateLoad(v);
@ -916,7 +959,7 @@ Value* FunctionGenerator::GetMemoryAddress(uint32_t cia, Value* addr) {
}
Value* FunctionGenerator::ReadMemory(
uint32_t cia, Value* addr, uint32_t size, bool extend) {
uint32_t cia, Value* addr, uint32_t size, bool acquire) {
IRBuilder<>& b = *builder_;
Type* dataTy = NULL;
@ -945,7 +988,13 @@ Value* FunctionGenerator::ReadMemory(
Value* address = GetMemoryAddress(cia, addr);
Value* ptr = b.CreatePointerCast(address, pointerTy);
Value* value = b.CreateLoad(ptr);
LoadInst* load_value = b.CreateLoad(ptr);
if (acquire) {
load_value->setAlignment(size);
load_value->setVolatile(true);
load_value->setAtomic(Acquire);
}
Value* value = load_value;
// Swap after loading.
// TODO(benvanik): find a way to avoid this!
@ -959,7 +1008,7 @@ Value* FunctionGenerator::ReadMemory(
}
void FunctionGenerator::WriteMemory(
uint32_t cia, Value* addr, uint32_t size, Value* value) {
uint32_t cia, Value* addr, uint32_t size, Value* value, bool release) {
IRBuilder<>& b = *builder_;
Type* dataTy = NULL;
@ -1002,5 +1051,10 @@ void FunctionGenerator::WriteMemory(
value = b.CreateCall(bswap, value);
}
b.CreateStore(value, ptr);
StoreInst* store_value = b.CreateStore(value, ptr);
if (release) {
store_value->setAlignment(size);
store_value->setVolatile(true);
store_value->setAtomic(Release);
}
}