Hacking on some instructions.
This commit is contained in:
parent
2e6db831a5
commit
ffdc1e5d4b
14
TODO.md
14
TODO.md
|
@ -1,8 +1,11 @@
|
||||||
## Instructions
|
## Instructions
|
||||||
|
|
||||||
```
|
```
|
||||||
stbu
|
need cr0:
|
||||||
lwzu
|
andix
|
||||||
|
orx
|
||||||
|
mullwx
|
||||||
|
divwux
|
||||||
|
|
||||||
addx
|
addx
|
||||||
addix
|
addix
|
||||||
|
@ -12,13 +15,6 @@ subfx
|
||||||
subfex
|
subfex
|
||||||
subficx
|
subficx
|
||||||
|
|
||||||
mulli
|
|
||||||
mullwx
|
|
||||||
divwux
|
|
||||||
|
|
||||||
andix
|
|
||||||
orx
|
|
||||||
|
|
||||||
rlwinmx
|
rlwinmx
|
||||||
rlwimix
|
rlwimix
|
||||||
rldiclx
|
rldiclx
|
||||||
|
|
|
@ -73,6 +73,7 @@ typedef struct {
|
||||||
|
|
||||||
// kXEPPCInstrFormatI
|
// kXEPPCInstrFormatI
|
||||||
struct {
|
struct {
|
||||||
|
// TODO(benvanik): doc format update
|
||||||
uint32_t LK : 1;
|
uint32_t LK : 1;
|
||||||
uint32_t AA : 1;
|
uint32_t AA : 1;
|
||||||
uint32_t LI : 24;
|
uint32_t LI : 24;
|
||||||
|
@ -80,6 +81,7 @@ typedef struct {
|
||||||
} I;
|
} I;
|
||||||
// kXEPPCInstrFormatB
|
// kXEPPCInstrFormatB
|
||||||
struct {
|
struct {
|
||||||
|
// TODO(benvanik): doc format update
|
||||||
uint32_t LK : 1;
|
uint32_t LK : 1;
|
||||||
uint32_t AA : 1;
|
uint32_t AA : 1;
|
||||||
uint32_t BD : 14;
|
uint32_t BD : 14;
|
||||||
|
@ -89,7 +91,9 @@ typedef struct {
|
||||||
} B;
|
} B;
|
||||||
|
|
||||||
// kXEPPCInstrFormatSC
|
// kXEPPCInstrFormatSC
|
||||||
|
// kXEPPCInstrFormatD
|
||||||
struct {
|
struct {
|
||||||
|
// TODO(benvanik): doc format update
|
||||||
uint32_t SIMM : 16;
|
uint32_t SIMM : 16;
|
||||||
uint32_t A : 5;
|
uint32_t A : 5;
|
||||||
uint32_t D : 5;
|
uint32_t D : 5;
|
||||||
|
@ -97,6 +101,7 @@ typedef struct {
|
||||||
} D;
|
} D;
|
||||||
// kXEPPCInstrFormatDS
|
// kXEPPCInstrFormatDS
|
||||||
struct {
|
struct {
|
||||||
|
// TODO(benvanik): doc format update
|
||||||
uint32_t : 2;
|
uint32_t : 2;
|
||||||
uint32_t ds : 14;
|
uint32_t ds : 14;
|
||||||
uint32_t A : 5;
|
uint32_t A : 5;
|
||||||
|
@ -105,6 +110,7 @@ typedef struct {
|
||||||
} DS;
|
} DS;
|
||||||
// kXEPPCInstrFormatX
|
// kXEPPCInstrFormatX
|
||||||
struct {
|
struct {
|
||||||
|
// TODO(benvanik): doc format update
|
||||||
uint32_t Rc : 1;
|
uint32_t Rc : 1;
|
||||||
uint32_t : 10;
|
uint32_t : 10;
|
||||||
uint32_t B : 5;
|
uint32_t B : 5;
|
||||||
|
@ -114,6 +120,7 @@ typedef struct {
|
||||||
} X;
|
} X;
|
||||||
// kXEPPCInstrFormatXL
|
// kXEPPCInstrFormatXL
|
||||||
struct {
|
struct {
|
||||||
|
// TODO(benvanik): doc format update
|
||||||
uint32_t LK : 1;
|
uint32_t LK : 1;
|
||||||
uint32_t : 10;
|
uint32_t : 10;
|
||||||
uint32_t BB : 5;
|
uint32_t BB : 5;
|
||||||
|
@ -121,7 +128,9 @@ typedef struct {
|
||||||
uint32_t BO : 5;
|
uint32_t BO : 5;
|
||||||
uint32_t OPCD : 6;
|
uint32_t OPCD : 6;
|
||||||
} XL;
|
} XL;
|
||||||
|
// kXEPPCInstrFormatXFX
|
||||||
struct {
|
struct {
|
||||||
|
// TODO(benvanik): doc format update
|
||||||
uint32_t : 1;
|
uint32_t : 1;
|
||||||
uint32_t : 10;
|
uint32_t : 10;
|
||||||
uint32_t spr : 10;
|
uint32_t spr : 10;
|
||||||
|
@ -132,6 +141,7 @@ typedef struct {
|
||||||
// kXEPPCInstrFormatXS
|
// kXEPPCInstrFormatXS
|
||||||
// kXEPPCInstrFormatXO
|
// kXEPPCInstrFormatXO
|
||||||
struct {
|
struct {
|
||||||
|
// TODO(benvanik): doc format update
|
||||||
uint32_t Rc : 1;
|
uint32_t Rc : 1;
|
||||||
uint32_t : 8;
|
uint32_t : 8;
|
||||||
uint32_t OE : 1;
|
uint32_t OE : 1;
|
||||||
|
@ -142,6 +152,15 @@ typedef struct {
|
||||||
} XO;
|
} XO;
|
||||||
// kXEPPCInstrFormatA
|
// kXEPPCInstrFormatA
|
||||||
// kXEPPCInstrFormatM
|
// kXEPPCInstrFormatM
|
||||||
|
struct {
|
||||||
|
uint32_t Rc : 1;
|
||||||
|
uint32_t ME : 5;
|
||||||
|
uint32_t MB : 5;
|
||||||
|
uint32_t SH : 5;
|
||||||
|
uint32_t RA : 5;
|
||||||
|
uint32_t RS : 5;
|
||||||
|
uint32_t OPCD : 6;
|
||||||
|
} M;
|
||||||
// kXEPPCInstrFormatMD
|
// kXEPPCInstrFormatMD
|
||||||
// kXEPPCInstrFormatMDS
|
// kXEPPCInstrFormatMDS
|
||||||
// kXEPPCInstrFormatVA
|
// kXEPPCInstrFormatVA
|
||||||
|
|
|
@ -118,8 +118,28 @@ XEEMITTER(divwx, 0x7C0003D6, XO )(FunctionGenerator& g, IRBuilder<>& b, I
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(divwux, 0x7C000396, XO )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
XEEMITTER(divwux, 0x7C000396, XO )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
// dividend[0:31] <- (RA)[32:63]
|
||||||
return 1;
|
// divisor[0:31] <- (RB)[32:63]
|
||||||
|
// RT[32:63] <- dividend ÷ divisor
|
||||||
|
// RT[0:31] <- undefined
|
||||||
|
|
||||||
|
if (i.XO.Rc) {
|
||||||
|
// With cr0 update.
|
||||||
|
XEINSTRNOTIMPLEMENTED();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (i.XO.OE) {
|
||||||
|
// With XER update.
|
||||||
|
XEINSTRNOTIMPLEMENTED();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* dividend = b.CreateTrunc(g.gpr_value(i.XO.A), b.getInt32Ty());
|
||||||
|
Value* divisor = b.CreateTrunc(g.gpr_value(i.XO.B), b.getInt32Ty());
|
||||||
|
Value* v = b.CreateUDiv(dividend, divisor);
|
||||||
|
v = b.CreateZExt(v, b.getInt64Ty());
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(mulhdx, 0x7C000092, XO )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
XEEMITTER(mulhdx, 0x7C000092, XO )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
||||||
|
@ -148,13 +168,38 @@ XEEMITTER(mulldx, 0x7C0001D2, XO )(FunctionGenerator& g, IRBuilder<>& b, I
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(mulli, 0x1C000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
XEEMITTER(mulli, 0x1C000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
// prod[0:127] <- (RA) × EXTS(SI)
|
||||||
return 1;
|
// RT <- prod[64:127]
|
||||||
|
|
||||||
|
// TODO(benvanik): ensure this has the right behavior when the value
|
||||||
|
// overflows. It should be truncating the result, but I'm not sure what LLVM
|
||||||
|
// does.
|
||||||
|
|
||||||
|
Value* v = b.CreateMul(g.gpr_value(i.D.A), b.getInt64(XEEXTS16(i.D.SIMM)));
|
||||||
|
g.update_gpr_value(i.D.D, b.CreateTrunc(v, b.getInt64Ty()));
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(mullwx, 0x7C0001D6, XO )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
XEEMITTER(mullwx, 0x7C0001D6, XO )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
// RT <- (RA)[32:63] × (RB)[32:63]
|
||||||
return 1;
|
|
||||||
|
if (i.XO.Rc) {
|
||||||
|
// With cr0 update.
|
||||||
|
XEINSTRNOTIMPLEMENTED();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (i.XO.OE) {
|
||||||
|
// With XER update.
|
||||||
|
XEINSTRNOTIMPLEMENTED();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* v = b.CreateMul(b.CreateSExt(g.gpr_value(i.XO.A), b.getInt64Ty()),
|
||||||
|
b.CreateSExt(g.gpr_value(i.XO.B), b.getInt64Ty()));
|
||||||
|
g.update_gpr_value(i.XO.D, v);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(negx, 0x7C0000D0, XO )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
XEEMITTER(negx, 0x7C0000D0, XO )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
||||||
|
@ -594,6 +639,42 @@ XEEMITTER(rlwimix, 0x50000000, M )(FunctionGenerator& g, IRBuilder<>& b, I
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(rlwinmx, 0x54000000, M )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
XEEMITTER(rlwinmx, 0x54000000, M )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
||||||
|
// n <- SH
|
||||||
|
// r <- ROTL32((RS)[32:63], n)
|
||||||
|
// m <- MASK(MB+32, ME+32)
|
||||||
|
// RA <- r & m
|
||||||
|
|
||||||
|
if (i.M.Rc) {
|
||||||
|
// With cr0 update.
|
||||||
|
XEINSTRNOTIMPLEMENTED();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The compiler will generate a bunch of these for the special case of
|
||||||
|
// SH=0, MB=ME
|
||||||
|
// Which seems to just select a single bit and set cr0 for use with a branch.
|
||||||
|
// We can detect this and do less work.
|
||||||
|
if (!i.M.SH && i.M.MB == i.M.ME) {
|
||||||
|
Value* v = b.CreateAnd(g.gpr_value(i.M.RS), 1 << i.M.MB);
|
||||||
|
g.update_gpr_value(i.M.RS, v);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if mstart ≤ mstop then
|
||||||
|
// mask[mstart:mstop] = ones
|
||||||
|
// mask[all other bits] = zeros
|
||||||
|
// else
|
||||||
|
// mask[mstart:63] = ones
|
||||||
|
// mask[0:mstop] = ones
|
||||||
|
// mask[all other bits] = zeros
|
||||||
|
|
||||||
|
// // ROTL32(x, y) = rotl(i64.(x||x), y)
|
||||||
|
// Value* v = b.CreateZExt(b.CreateTrunc(g.gpr_value(i.M.RS)), b.getInt64Ty());
|
||||||
|
// v = b.CreateOr(b.CreateLShr(v, 32), v);
|
||||||
|
// // (v << shift) | (v >> (64 - shift));
|
||||||
|
// v = b.CreateOr(b.CreateShl(v, i.M.SH), b.CreateLShr(v, 32 - i.M.SH));
|
||||||
|
// v = b.CreateAnd(v, XEMASK(i.M.MB + 32, i.M.ME + 32));
|
||||||
|
|
||||||
XEINSTRNOTIMPLEMENTED();
|
XEINSTRNOTIMPLEMENTED();
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,8 +215,16 @@ XEEMITTER(lwz, 0x80000000, D )(FunctionGenerator& g, IRBuilder<>& b, I
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lwzu, 0x84000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
XEEMITTER(lwzu, 0x84000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
// EA <- (RA) + EXTS(D)
|
||||||
return 1;
|
// RT <- i32.0 || MEM(EA, 4)
|
||||||
|
// RA <- EA
|
||||||
|
|
||||||
|
Value* ea = b.CreateAdd(g.gpr_value(i.D.A), b.getInt64(XEEXTS16(i.D.SIMM)));
|
||||||
|
Value* v = g.ReadMemory(ea, 4, false);
|
||||||
|
g.update_gpr_value(i.D.D, v);
|
||||||
|
g.update_gpr_value(i.D.A, ea);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(lwzux, 0x7C00006E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
XEEMITTER(lwzux, 0x7C00006E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
||||||
|
@ -264,8 +272,16 @@ XEEMITTER(stb, 0x98000000, D )(FunctionGenerator& g, IRBuilder<>& b, I
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stbu, 0x9C000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
XEEMITTER(stbu, 0x9C000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
||||||
XEINSTRNOTIMPLEMENTED();
|
// EA <- (RA) + EXTS(D)
|
||||||
return 1;
|
// MEM(EA, 1) <- (RS)[56:63]
|
||||||
|
// RA <- EA
|
||||||
|
|
||||||
|
Value* ea = b.CreateAdd(g.gpr_value(i.D.A), b.getInt64(XEEXTS16(i.D.SIMM)));
|
||||||
|
Value* v = g.gpr_value(i.D.D);
|
||||||
|
g.WriteMemory(ea, 1, v);
|
||||||
|
g.update_gpr_value(i.D.A, ea);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
XEEMITTER(stbux, 0x7C0001EE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
XEEMITTER(stbux, 0x7C0001EE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) {
|
||||||
|
|
Loading…
Reference in New Issue