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 rlwimix
rldiclx rldiclx
addcx lwarx
addex stwcx
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
lfd lfd
lfdx lfdx
lfs lfs
lfsu lfsu
lfsux
lfsx 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 stfd
stfdu
stfdx
stfiwx stfiwx
stfs stfs
stfsu stfsu
stfsx stfsx
stwbrx
stwcx
stwux
subfcx
subfzex
sync
``` ```
### XER CA bit (carry) ### XER CA bit (carry)

View File

@ -83,13 +83,16 @@ public:
llvm::Value* gpr_value(uint32_t n); llvm::Value* gpr_value(uint32_t n);
void update_gpr_value(uint32_t n, llvm::Value* value); 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* GetMembase();
llvm::Value* GetMemoryAddress(uint32_t cia, llvm::Value* addr); llvm::Value* GetMemoryAddress(uint32_t cia, llvm::Value* addr);
llvm::Value* ReadMemory( 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( 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: private:
void GenerateSharedBlocks(); void GenerateSharedBlocks();
@ -128,6 +131,7 @@ private:
llvm::Value* ctr; llvm::Value* ctr;
llvm::Value* cr[8]; llvm::Value* cr[8];
llvm::Value* gpr[32]; llvm::Value* gpr[32];
llvm::Value* fpr[32];
} locals_; } locals_;
}; };

View File

@ -182,9 +182,34 @@ XEEMITTER(ldx, 0x7C00002A, X )(FunctionGenerator& g, IRBuilder<>& b, I
return 1; 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) { XEEMITTER(lha, 0xA8000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { 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; 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) { XEEMITTER(lhax, 0x7C0002AE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { XEDISASMR(lhz, 0xA0000000, D )(InstrData& i, InstrDisasm& d) {
@ -231,24 +281,103 @@ XEEMITTER(lhz, 0xA0000000, D )(FunctionGenerator& g, IRBuilder<>& b, I
return 0; 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) { XEEMITTER(lhzu, 0xA4000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // EA <- (RA) + EXTS(D)
return 1; // 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) { XEEMITTER(lhzux, 0x7C00026E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // EA <- (RA) + (RB)
return 1; // 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) { XEEMITTER(lhzx, 0x7C00022E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { XEEMITTER(lwa, 0xE8000002, DS )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { XEDISASMR(lwaux, 0x7C0002EA, X )(InstrData& i, InstrDisasm& d) {
@ -351,9 +480,24 @@ XEEMITTER(lwzu, 0x84000000, D )(FunctionGenerator& g, IRBuilder<>& b, I
return 0; 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) { XEEMITTER(lwzux, 0x7C00006E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // EA <- (RA) + (RB)
return 1; // 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) { XEDISASMR(lwzx, 0x7C00002E, X )(InstrData& i, InstrDisasm& d) {
@ -536,14 +680,53 @@ XEEMITTER(stdu, 0xF8000001, DS )(FunctionGenerator& g, IRBuilder<>& b, I
return 0; 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) { XEEMITTER(stdux, 0x7C00016A, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { XEEMITTER(stdx, 0x7C00012A, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // EA <- (RA) + (RB)
return 1; // 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) { XEDISASMR(sth, 0xB0000000, D )(InstrData& i, InstrDisasm& d) {
@ -831,9 +1014,38 @@ XEEMITTER(ldarx, 0x7C0000A8, X )(FunctionGenerator& g, IRBuilder<>& b, I
return 1; 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) { XEEMITTER(lwarx, 0x7C000028, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { 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; 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) { XEEMITTER(stwcx, 0x7C00012D, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { 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) // 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) { XEEMITTER(lfd, 0xC8000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { XEEMITTER(lfdu, 0xCC000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // EA <- (RA) + EXTS(D)
return 1; // 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) { XEEMITTER(lfdux, 0x7C0004EE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // EA <- (RA) + (RB)
return 1; // 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) { XEEMITTER(lfdx, 0x7C0004AE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { XEEMITTER(lfs, 0xC0000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { XEEMITTER(lfsu, 0xC4000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // EA <- (RA) + EXTS(D)
return 1; // 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) { XEEMITTER(lfsux, 0x7C00046E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // EA <- (RA) + (RB)
return 1; // 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) { XEEMITTER(lfsx, 0x7C00042E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) // 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) { XEEMITTER(stfd, 0xD8000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { XEEMITTER(stfdu, 0xDC000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // EA <- (RA) + EXTS(D)
return 1; // 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) { XEEMITTER(stfdux, 0x7C0005EE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // EA <- (RA) + (RB)
return 1; // 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) { XEEMITTER(stfdx, 0x7C0005AE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { XEEMITTER(stfiwx, 0x7C0007AE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { XEEMITTER(stfs, 0xD0000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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) { XEEMITTER(stfsu, 0xD4000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // EA <- (RA) + EXTS(D)
return 1; // 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) { XEEMITTER(stfsux, 0x7C00056E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // EA <- (RA) + (RB)
return 1; // 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) { XEEMITTER(stfsx, 0x7C00052E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
XEINSTRNOTIMPLEMENTED(); // if RA = 0 then
return 1; // 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); XEREGISTERINSTR(ldu, 0xE8000001);
XEREGISTEREMITTER(ldux, 0x7C00006A); XEREGISTEREMITTER(ldux, 0x7C00006A);
XEREGISTEREMITTER(ldx, 0x7C00002A); XEREGISTEREMITTER(ldx, 0x7C00002A);
XEREGISTEREMITTER(lha, 0xA8000000); XEREGISTERINSTR(lha, 0xA8000000);
XEREGISTEREMITTER(lhau, 0xAC000000); XEREGISTEREMITTER(lhau, 0xAC000000);
XEREGISTEREMITTER(lhaux, 0x7C0002EE); XEREGISTEREMITTER(lhaux, 0x7C0002EE);
XEREGISTEREMITTER(lhax, 0x7C0002AE); XEREGISTERINSTR(lhax, 0x7C0002AE);
XEREGISTERINSTR(lhz, 0xA0000000); XEREGISTERINSTR(lhz, 0xA0000000);
XEREGISTEREMITTER(lhzu, 0xA4000000); XEREGISTERINSTR(lhzu, 0xA4000000);
XEREGISTEREMITTER(lhzux, 0x7C00026E); XEREGISTERINSTR(lhzux, 0x7C00026E);
XEREGISTEREMITTER(lhzx, 0x7C00022E); XEREGISTERINSTR(lhzx, 0x7C00022E);
XEREGISTEREMITTER(lwa, 0xE8000002); XEREGISTERINSTR(lwa, 0xE8000002);
XEREGISTEREMITTER(lwaux, 0x7C0002EA); XEREGISTERINSTR(lwaux, 0x7C0002EA);
XEREGISTEREMITTER(lwax, 0x7C0002AA); XEREGISTERINSTR(lwax, 0x7C0002AA);
XEREGISTERINSTR(lwz, 0x80000000); XEREGISTERINSTR(lwz, 0x80000000);
XEREGISTERINSTR(lwzu, 0x84000000); XEREGISTERINSTR(lwzu, 0x84000000);
XEREGISTEREMITTER(lwzux, 0x7C00006E); XEREGISTERINSTR(lwzux, 0x7C00006E);
XEREGISTERINSTR(lwzx, 0x7C00002E); XEREGISTERINSTR(lwzx, 0x7C00002E);
XEREGISTERINSTR(stb, 0x98000000); XEREGISTERINSTR(stb, 0x98000000);
XEREGISTERINSTR(stbu, 0x9C000000); XEREGISTERINSTR(stbu, 0x9C000000);
XEREGISTEREMITTER(stbux, 0x7C0001EE); XEREGISTERINSTR(stbux, 0x7C0001EE);
XEREGISTEREMITTER(stbx, 0x7C0001AE); XEREGISTERINSTR(stbx, 0x7C0001AE);
XEREGISTERINSTR(std, 0xF8000000); XEREGISTERINSTR(std, 0xF8000000);
XEREGISTERINSTR(stdu, 0xF8000001); XEREGISTERINSTR(stdu, 0xF8000001);
XEREGISTEREMITTER(stdux, 0x7C00016A); XEREGISTERINSTR(stdux, 0x7C00016A);
XEREGISTEREMITTER(stdx, 0x7C00012A); XEREGISTERINSTR(stdx, 0x7C00012A);
XEREGISTERINSTR(sth, 0xB0000000); XEREGISTERINSTR(sth, 0xB0000000);
XEREGISTERINSTR(sthu, 0xB4000000); XEREGISTERINSTR(sthu, 0xB4000000);
XEREGISTEREMITTER(sthux, 0x7C00036E); XEREGISTERINSTR(sthux, 0x7C00036E);
XEREGISTERINSTR(sthx, 0x7C00032E); XEREGISTERINSTR(sthx, 0x7C00032E);
XEREGISTERINSTR(stw, 0x90000000); XEREGISTERINSTR(stw, 0x90000000);
XEREGISTERINSTR(stwu, 0x94000000); XEREGISTERINSTR(stwu, 0x94000000);
XEREGISTEREMITTER(stwux, 0x7C00016E); XEREGISTERINSTR(stwux, 0x7C00016E);
XEREGISTERINSTR(stwx, 0x7C00012E); XEREGISTERINSTR(stwx, 0x7C00012E);
XEREGISTEREMITTER(lhbrx, 0x7C00062C); XEREGISTEREMITTER(lhbrx, 0x7C00062C);
XEREGISTEREMITTER(lwbrx, 0x7C00042C); XEREGISTEREMITTER(lwbrx, 0x7C00042C);
@ -1044,27 +1642,27 @@ void RegisterEmitCategoryMemory() {
XEREGISTEREMITTER(eieio, 0x7C0006AC); XEREGISTEREMITTER(eieio, 0x7C0006AC);
XEREGISTEREMITTER(isync, 0x4C00012C); XEREGISTEREMITTER(isync, 0x4C00012C);
XEREGISTEREMITTER(ldarx, 0x7C0000A8); XEREGISTEREMITTER(ldarx, 0x7C0000A8);
XEREGISTEREMITTER(lwarx, 0x7C000028); XEREGISTERINSTR(lwarx, 0x7C000028);
XEREGISTEREMITTER(stdcx, 0x7C0001AD); XEREGISTEREMITTER(stdcx, 0x7C0001AD);
XEREGISTEREMITTER(stwcx, 0x7C00012D); XEREGISTERINSTR(stwcx, 0x7C00012D);
XEREGISTEREMITTER(sync, 0x7C0004AC); XEREGISTEREMITTER(sync, 0x7C0004AC);
XEREGISTEREMITTER(lfd, 0xC8000000); XEREGISTERINSTR(lfd, 0xC8000000);
XEREGISTEREMITTER(lfdu, 0xCC000000); XEREGISTERINSTR(lfdu, 0xCC000000);
XEREGISTEREMITTER(lfdux, 0x7C0004EE); XEREGISTERINSTR(lfdux, 0x7C0004EE);
XEREGISTEREMITTER(lfdx, 0x7C0004AE); XEREGISTERINSTR(lfdx, 0x7C0004AE);
XEREGISTEREMITTER(lfs, 0xC0000000); XEREGISTERINSTR(lfs, 0xC0000000);
XEREGISTEREMITTER(lfsu, 0xC4000000); XEREGISTERINSTR(lfsu, 0xC4000000);
XEREGISTEREMITTER(lfsux, 0x7C00046E); XEREGISTERINSTR(lfsux, 0x7C00046E);
XEREGISTEREMITTER(lfsx, 0x7C00042E); XEREGISTERINSTR(lfsx, 0x7C00042E);
XEREGISTEREMITTER(stfd, 0xD8000000); XEREGISTERINSTR(stfd, 0xD8000000);
XEREGISTEREMITTER(stfdu, 0xDC000000); XEREGISTERINSTR(stfdu, 0xDC000000);
XEREGISTEREMITTER(stfdux, 0x7C0005EE); XEREGISTERINSTR(stfdux, 0x7C0005EE);
XEREGISTEREMITTER(stfdx, 0x7C0005AE); XEREGISTERINSTR(stfdx, 0x7C0005AE);
XEREGISTEREMITTER(stfiwx, 0x7C0007AE); XEREGISTERINSTR(stfiwx, 0x7C0007AE);
XEREGISTEREMITTER(stfs, 0xD0000000); XEREGISTERINSTR(stfs, 0xD0000000);
XEREGISTEREMITTER(stfsu, 0xD4000000); XEREGISTERINSTR(stfsu, 0xD4000000);
XEREGISTEREMITTER(stfsux, 0x7C00056E); XEREGISTERINSTR(stfsux, 0x7C00056E);
XEREGISTEREMITTER(stfsx, 0x7C00052E); XEREGISTERINSTR(stfsx, 0x7C00052E);
XEREGISTEREMITTER(dcbf, 0x7C0000AC); XEREGISTEREMITTER(dcbf, 0x7C0000AC);
XEREGISTEREMITTER(dcbst, 0x7C00006C); XEREGISTEREMITTER(dcbst, 0x7C00006C);
XEREGISTERINSTR(dcbt, 0x7C00022C); XEREGISTERINSTR(dcbt, 0x7C00022C);

View File

@ -77,6 +77,9 @@ FunctionGenerator::FunctionGenerator(
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] = NULL;
} }
for (size_t n = 0; n < XECOUNT(locals_.fpr); n++) {
locals_.fpr[n] = NULL;
}
if (FLAGS_log_codegen) { if (FLAGS_log_codegen) {
printf("%s:\n", fn->name()); printf("%s:\n", fn->name());
@ -548,6 +551,15 @@ void FunctionGenerator::SetupLocals() {
} }
gpr_t >>= 2; 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) { Value* FunctionGenerator::SetupLocal(llvm::Type* type, const char* name) {
@ -611,7 +623,6 @@ void FunctionGenerator::FillRegisters() {
b.getInt8Ty()), cr_n); b.getInt8Ty()), cr_n);
} }
// Note that we skip zero.
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]) {
b.CreateStore(LoadStateValue( b.CreateStore(LoadStateValue(
@ -619,6 +630,14 @@ void FunctionGenerator::FillRegisters() {
b.getInt64Ty()), locals_.gpr[n]); 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() { void FunctionGenerator::SpillRegisters() {
@ -672,7 +691,6 @@ void FunctionGenerator::SpillRegisters() {
cr); cr);
} }
// Note that we skip zero.
for (uint32_t n = 0; n < XECOUNT(locals_.gpr); n++) { for (uint32_t n = 0; n < XECOUNT(locals_.gpr); n++) {
Value* v = locals_.gpr[n]; Value* v = locals_.gpr[n];
if (v) { if (v) {
@ -682,6 +700,16 @@ void FunctionGenerator::SpillRegisters() {
b.CreateLoad(locals_.gpr[n])); 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() { Value* FunctionGenerator::xer_value() {
@ -879,6 +907,21 @@ void FunctionGenerator::update_gpr_value(uint32_t n, Value* value) {
b.CreateStore(value, locals_.gpr[n]); 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* FunctionGenerator::GetMembase() {
Value* v = gen_module_->getGlobalVariable("xe_memory_base"); Value* v = gen_module_->getGlobalVariable("xe_memory_base");
return builder_->CreateLoad(v); return builder_->CreateLoad(v);
@ -916,7 +959,7 @@ Value* FunctionGenerator::GetMemoryAddress(uint32_t cia, Value* addr) {
} }
Value* FunctionGenerator::ReadMemory( 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_; IRBuilder<>& b = *builder_;
Type* dataTy = NULL; Type* dataTy = NULL;
@ -945,7 +988,13 @@ Value* FunctionGenerator::ReadMemory(
Value* address = GetMemoryAddress(cia, addr); Value* address = GetMemoryAddress(cia, addr);
Value* ptr = b.CreatePointerCast(address, pointerTy); 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. // Swap after loading.
// TODO(benvanik): find a way to avoid this! // TODO(benvanik): find a way to avoid this!
@ -959,7 +1008,7 @@ Value* FunctionGenerator::ReadMemory(
} }
void FunctionGenerator::WriteMemory( 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_; IRBuilder<>& b = *builder_;
Type* dataTy = NULL; Type* dataTy = NULL;
@ -1002,5 +1051,10 @@ void FunctionGenerator::WriteMemory(
value = b.CreateCall(bswap, value); 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);
}
} }