Hacking on some instructions.

This commit is contained in:
Ben Vanik 2013-01-25 23:32:37 -08:00
parent 2e6db831a5
commit ffdc1e5d4b
4 changed files with 131 additions and 19 deletions

14
TODO.md
View File

@ -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

View File

@ -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

View File

@ -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;
} }

View File

@ -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) {