Last of the integer memory instructions and a lot of the fp ones.
This commit is contained in:
parent
9dcf2d27fb
commit
7fed5cf579
78
TODO.md
78
TODO.md
|
@ -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)
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue