From d1333db404d68b6fa355ea3c37a80d26da23a9a4 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Tue, 29 Jan 2013 01:55:03 -0800 Subject: [PATCH] Disassembly for implemented control/memory instructions. --- include/xenia/cpu/ppc/instr.h | 4 +- src/cpu/codegen/emit_control.cc | 100 +++++++++++++- src/cpu/codegen/emit_memory.cc | 228 +++++++++++++++++++++++++++++--- src/cpu/ppc/instr.cc | 27 +++- 4 files changed, 328 insertions(+), 31 deletions(-) diff --git a/include/xenia/cpu/ppc/instr.h b/include/xenia/cpu/ppc/instr.h index 728642dad..ac0200e56 100644 --- a/include/xenia/cpu/ppc/instr.h +++ b/include/xenia/cpu/ppc/instr.h @@ -256,7 +256,7 @@ public: kOE = 1 << 0, kRc = 1 << 1, kCA = 1 << 2, - kCR = 1 << 3, + kLR = 1 << 4, }; char name[16]; @@ -265,6 +265,8 @@ public: std::vector special_registers; void Init(std::string name, std::string info, uint32_t flags); + void AddLR(InstrRegister::Access access); + void AddCTR(InstrRegister::Access access); void AddCR(uint32_t bf, InstrRegister::Access access); void AddRegOperand(InstrRegister::RegisterSet set, uint32_t ordinal, InstrRegister::Access access, std::string display = ""); diff --git a/src/cpu/codegen/emit_control.cc b/src/cpu/codegen/emit_control.cc index d8f8ee981..339045b4d 100644 --- a/src/cpu/codegen/emit_control.cc +++ b/src/cpu/codegen/emit_control.cc @@ -127,6 +127,18 @@ int XeEmitBranchTo( return 0; } + +XEDISASMR(bx, 0x48000000, I )(InstrData& i, InstrDisasm& d) { + d.Init("b", "Branch", i.I.LK ? InstrDisasm::kLR : 0); + uint32_t nia; + if (i.I.AA) { + nia = XEEXTS26(i.I.LI << 2); + } else { + nia = i.address + XEEXTS26(i.I.LI << 2); + } + d.AddUImmOperand(nia, 4); + return d.Finish(); +} XEEMITTER(bx, 0x48000000, I )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // if AA then // NIA <- EXTS(LI || 0b00) @@ -148,6 +160,19 @@ XEEMITTER(bx, 0x48000000, I )(FunctionGenerator& g, IRBuilder<>& b, I return XeEmitBranchTo(g, b, "bx", i.address, i.I.LK); } +XEDISASMR(bcx, 0x40000000, B )(InstrData& i, InstrDisasm& d) { + // TODO(benvanik): mnemonics + d.Init("bc", "Branch Conditional", i.B.LK ? InstrDisasm::kLR : 0); + if (!XESELECTBITS(i.B.BO, 2, 2)) { + d.AddCTR(InstrRegister::kReadWrite); + } + if (!XESELECTBITS(i.B.BO, 4, 4)) { + d.AddCR(i.B.BI >> 2, InstrRegister::kRead); + } + d.AddUImmOperand(i.B.BO, 1); + d.AddUImmOperand(i.B.BI, 1); + return d.Finish(); +} XEEMITTER(bcx, 0x40000000, B )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // if ¬BO[2] then // CTR <- CTR - 1 @@ -240,6 +265,18 @@ XEEMITTER(bcx, 0x40000000, B )(FunctionGenerator& g, IRBuilder<>& b, I return 0; } + +XEDISASMR(bcctrx, 0x4C000420, XL )(InstrData& i, InstrDisasm& d) { + // TODO(benvanik): mnemonics + d.Init("bcctr", "Branch Conditional to Count Register", + i.XL.LK ? InstrDisasm::kLR : 0); + if (!XESELECTBITS(i.XL.BO, 4, 4)) { + d.AddCR(i.XL.BI >> 2, InstrRegister::kRead); + } + d.AddUImmOperand(i.XL.BO, 1); + d.AddUImmOperand(i.XL.BI, 1); + return d.Finish(); +} XEEMITTER(bcctrx, 0x4C000420, XL )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // cond_ok <- BO[0] | (CR[BI+32] ≡ BO[1]) // if cond_ok then @@ -300,6 +337,23 @@ XEEMITTER(bcctrx, 0x4C000420, XL )(FunctionGenerator& g, IRBuilder<>& b, I return 0; } +XEDISASMR(bclrx, 0x4C000020, XL )(InstrData& i, InstrDisasm& d) { + std::string name = "bclr"; + if (i.code == 0x4E800020) { + name = "blr"; + } + d.Init(name, "Branch Conditional to Link Register", + i.XL.LK ? InstrDisasm::kLR : 0); + if (!XESELECTBITS(i.B.BO, 2, 2)) { + d.AddCTR(InstrRegister::kReadWrite); + } + if (!XESELECTBITS(i.B.BO, 4, 4)) { + d.AddCR(i.B.BI >> 2, InstrRegister::kRead); + } + d.AddUImmOperand(i.XL.BO, 1); + d.AddUImmOperand(i.XL.BI, 1); + return d.Finish(); +} XEEMITTER(bclrx, 0x4C000020, XL )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // if ¬BO[2] then // CTR <- CTR - 1 @@ -605,6 +659,23 @@ XEEMITTER(mfcr, 0x7C000026, X )(FunctionGenerator& g, IRBuilder<>& b, I return 1; } +XEDISASMR(mfspr, 0x7C0002A6, XFX)(InstrData& i, InstrDisasm& d) { + d.Init("mfspr", "Move From Special Purpose Register", 0); + d.AddRegOperand(InstrRegister::kGPR, i.XFX.RT, InstrRegister::kWrite); + const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F); + switch (n) { + case 1: + d.AddRegOperand(InstrRegister::kXER, 0, InstrRegister::kRead); + break; + case 8: + d.AddRegOperand(InstrRegister::kLR, 0, InstrRegister::kRead); + break; + case 9: + d.AddRegOperand(InstrRegister::kCTR, 0, InstrRegister::kRead); + break; + } + return d.Finish(); +} XEEMITTER(mfspr, 0x7C0002A6, XFX)(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // n <- spr[5:9] || spr[0:4] // if length(SPR(n)) = 64 then @@ -647,6 +718,23 @@ XEEMITTER(mtcrf, 0x7C000120, XFX)(FunctionGenerator& g, IRBuilder<>& b, I return 1; } +XEDISASMR(mtspr, 0x7C0003A6, XFX)(InstrData& i, InstrDisasm& d) { + d.Init("mtspr", "Move To Special Purpose Register", 0); + const uint32_t n = ((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F); + switch (n) { + case 1: + d.AddRegOperand(InstrRegister::kXER, 0, InstrRegister::kWrite); + break; + case 8: + d.AddRegOperand(InstrRegister::kLR, 0, InstrRegister::kWrite); + break; + case 9: + d.AddRegOperand(InstrRegister::kCTR, 0, InstrRegister::kWrite); + break; + } + d.AddRegOperand(InstrRegister::kGPR, i.XFX.RT, InstrRegister::kRead); + return d.Finish(); +} XEEMITTER(mtspr, 0x7C0003A6, XFX)(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // n <- spr[5:9] || spr[0:4] // if length(SPR(n)) = 64 then @@ -680,10 +768,10 @@ XEEMITTER(mtspr, 0x7C0003A6, XFX)(FunctionGenerator& g, IRBuilder<>& b, I void RegisterEmitCategoryControl() { - XEREGISTEREMITTER(bx, 0x48000000); - XEREGISTEREMITTER(bcx, 0x40000000); - XEREGISTEREMITTER(bcctrx, 0x4C000420); - XEREGISTEREMITTER(bclrx, 0x4C000020); + XEREGISTERINSTR(bx, 0x48000000); + XEREGISTERINSTR(bcx, 0x40000000); + XEREGISTERINSTR(bcctrx, 0x4C000420); + XEREGISTERINSTR(bclrx, 0x4C000020); XEREGISTEREMITTER(crand, 0x4C000202); XEREGISTEREMITTER(crandc, 0x4C000102); XEREGISTEREMITTER(creqv, 0x4C000242); @@ -699,10 +787,10 @@ void RegisterEmitCategoryControl() { XEREGISTEREMITTER(tw, 0x7C000008); XEREGISTEREMITTER(twi, 0x0C000000); XEREGISTEREMITTER(mfcr, 0x7C000026); - XEREGISTEREMITTER(mfspr, 0x7C0002A6); + XEREGISTERINSTR(mfspr, 0x7C0002A6); XEREGISTEREMITTER(mftb, 0x7C0002E6); XEREGISTEREMITTER(mtcrf, 0x7C000120); - XEREGISTEREMITTER(mtspr, 0x7C0003A6); + XEREGISTERINSTR(mtspr, 0x7C0003A6); } diff --git a/src/cpu/codegen/emit_memory.cc b/src/cpu/codegen/emit_memory.cc index d329ae42e..dc8b6e119 100644 --- a/src/cpu/codegen/emit_memory.cc +++ b/src/cpu/codegen/emit_memory.cc @@ -24,6 +24,17 @@ namespace codegen { // Integer load (A-13) +XEDISASMR(lbz, 0x88000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("lbz", "Load Byte and Zero", 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(lbz, 0x88000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // if RA = 0 then // b <- 0 @@ -42,6 +53,13 @@ XEEMITTER(lbz, 0x88000000, D )(FunctionGenerator& g, IRBuilder<>& b, I return 0; } +XEDISASMR(lbzu, 0x8C000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("lbzu", "Load Byte 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(lbzu, 0x8C000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // EA <- (RA) + EXTS(D) // RT <- i56.0 || MEM(EA, 1) @@ -55,6 +73,13 @@ XEEMITTER(lbzu, 0x8C000000, D )(FunctionGenerator& g, IRBuilder<>& b, I return 0; } +XEDISASMR(lbzux, 0x7C0000EE, X )(InstrData& i, InstrDisasm& d) { + d.Init("lbzux", "Load Byte 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(lbzux, 0x7C0000EE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // EA <- (RA) + (RB) // RT <- i56.0 || MEM(EA, 1) @@ -68,6 +93,17 @@ XEEMITTER(lbzux, 0x7C0000EE, X )(FunctionGenerator& g, IRBuilder<>& b, I return 0; } +XEDISASMR(lbzx, 0x7C0000AE, X )(InstrData& i, InstrDisasm& d) { + d.Init("lbzx", "Load Byte 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(lbzx, 0x7C0000AE, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // if RA = 0 then // b <- 0 @@ -86,6 +122,17 @@ XEEMITTER(lbzx, 0x7C0000AE, X )(FunctionGenerator& g, IRBuilder<>& b, I return 0; } +XEDISASMR(ld, 0xE8000000, DS )(InstrData& i, InstrDisasm& d) { + d.Init("ld", "Load Doubleword", 0); + d.AddRegOperand(InstrRegister::kGPR, i.DS.RT, InstrRegister::kWrite); + if (i.DS.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(ld, 0xE8000000, DS )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // if RA = 0 then // b <- 0 @@ -104,6 +151,13 @@ XEEMITTER(ld, 0xE8000000, DS )(FunctionGenerator& g, IRBuilder<>& b, I return 0; } +XEDISASMR(ldu, 0xE8000001, DS )(InstrData& i, InstrDisasm& d) { + d.Init("ldu", "Load Doubleword with Update", 0); + d.AddRegOperand(InstrRegister::kGPR, i.DS.RT, InstrRegister::kWrite); + d.AddRegOperand(InstrRegister::kGPR, i.DS.RA, InstrRegister::kReadWrite); + d.AddSImmOperand(XEEXTS16(i.DS.DS << 2), 2); + return d.Finish(); +} XEEMITTER(ldu, 0xE8000001, DS )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // EA <- (RA) + EXTS(DS || 0b00) // RT <- MEM(EA, 8) @@ -148,6 +202,17 @@ XEEMITTER(lhax, 0x7C0002AE, X )(FunctionGenerator& g, IRBuilder<>& b, I return 1; } +XEDISASMR(lhz, 0xA0000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("lhz", "Load Halfword and Zero", 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(lhz, 0xA0000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // if RA = 0 then // b <- 0 @@ -196,6 +261,17 @@ XEEMITTER(lwax, 0x7C0002AA, X )(FunctionGenerator& g, IRBuilder<>& b, I return 1; } +XEDISASMR(lwz, 0x80000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("lwz", "Load Word and Zero", 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(lwz, 0x80000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // if RA = 0 then // b <- 0 @@ -214,6 +290,13 @@ XEEMITTER(lwz, 0x80000000, D )(FunctionGenerator& g, IRBuilder<>& b, I return 0; } +XEDISASMR(lwzu, 0x84000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("lwzu", "Load Word and Zero with Udpate", 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(lwzu, 0x84000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // EA <- (RA) + EXTS(D) // RT <- i32.0 || MEM(EA, 4) @@ -232,6 +315,17 @@ XEEMITTER(lwzux, 0x7C00006E, X )(FunctionGenerator& g, IRBuilder<>& b, I return 1; } +XEDISASMR(lwzx, 0x7C00002E, X )(InstrData& i, InstrDisasm& d) { + d.Init("lwzx", "Load Word 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(lwzx, 0x7C00002E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // if RA = 0 then // b <- 0 @@ -253,6 +347,17 @@ XEEMITTER(lwzx, 0x7C00002E, X )(FunctionGenerator& g, IRBuilder<>& b, I // Integer store (A-14) +XEDISASMR(stb, 0x98000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("stb", "Store Byte", 0); + d.AddRegOperand(InstrRegister::kGPR, 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(stb, 0x98000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // if RA = 0 then // b <- 0 @@ -271,6 +376,13 @@ XEEMITTER(stb, 0x98000000, D )(FunctionGenerator& g, IRBuilder<>& b, I return 0; } +XEDISASMR(stbu, 0x9C000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("stbu", "Store Byte with Update", 0); + d.AddRegOperand(InstrRegister::kGPR, 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(stbu, 0x9C000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // EA <- (RA) + EXTS(D) // MEM(EA, 1) <- (RS)[56:63] @@ -294,6 +406,17 @@ XEEMITTER(stbx, 0x7C0001AE, X )(FunctionGenerator& g, IRBuilder<>& b, I return 1; } +XEDISASMR(std, 0xF8000000, DS )(InstrData& i, InstrDisasm& d) { + d.Init("std", "Store Doubleword", 0); + d.AddRegOperand(InstrRegister::kGPR, i.DS.RT, InstrRegister::kRead); + if (i.DS.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(std, 0xF8000000, DS )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // if RA = 0 then // b <- 0 @@ -312,6 +435,13 @@ XEEMITTER(std, 0xF8000000, DS )(FunctionGenerator& g, IRBuilder<>& b, I return 0; } +XEDISASMR(stdu, 0xF8000001, DS )(InstrData& i, InstrDisasm& d) { + d.Init("stdu", "Store Doubleword with Update", 0); + d.AddRegOperand(InstrRegister::kGPR, i.DS.RT, InstrRegister::kRead); + d.AddRegOperand(InstrRegister::kGPR, i.DS.RA, InstrRegister::kReadWrite); + d.AddSImmOperand(XEEXTS16(i.DS.DS << 2), 2); + return d.Finish(); +} XEEMITTER(stdu, 0xF8000001, DS )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // EA <- (RA) + EXTS(DS || 0b00) // MEM(EA, 8) <- (RS) @@ -336,6 +466,17 @@ XEEMITTER(stdx, 0x7C00012A, X )(FunctionGenerator& g, IRBuilder<>& b, I return 1; } +XEDISASMR(sth, 0xB0000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("sth", "Store Halfword", 0); + d.AddRegOperand(InstrRegister::kGPR, 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(sth, 0xB0000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // if RA = 0 then // b <- 0 @@ -354,6 +495,13 @@ XEEMITTER(sth, 0xB0000000, D )(FunctionGenerator& g, IRBuilder<>& b, I return 0; } +XEDISASMR(sthu, 0xB4000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("sthu", "Store Halfword with Update", 0); + d.AddRegOperand(InstrRegister::kGPR, 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(sthu, 0xB4000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // EA <- (RA) + EXTS(D) // MEM(EA, 2) <- (RS)[48:63] @@ -373,6 +521,17 @@ XEEMITTER(sthux, 0x7C00036E, X )(FunctionGenerator& g, IRBuilder<>& b, I return 1; } +XEDISASMR(sthx, 0x7C00032E, X )(InstrData& i, InstrDisasm& d) { + d.Init("sth", "Store Halfword Indexed", 0); + d.AddRegOperand(InstrRegister::kGPR, 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(sthx, 0x7C00032E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // if RA = 0 then // b <- 0 @@ -391,6 +550,17 @@ XEEMITTER(sthx, 0x7C00032E, X )(FunctionGenerator& g, IRBuilder<>& b, I return 0; } +XEDISASMR(stw, 0x90000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("stw", "Store Word", 0); + d.AddRegOperand(InstrRegister::kGPR, 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(stw, 0x90000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // if RA = 0 then // b <- 0 @@ -409,6 +579,13 @@ XEEMITTER(stw, 0x90000000, D )(FunctionGenerator& g, IRBuilder<>& b, I return 0; } +XEDISASMR(stwu, 0x94000000, D )(InstrData& i, InstrDisasm& d) { + d.Init("stwu", "Store Word with Update", 0); + d.AddRegOperand(InstrRegister::kGPR, 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(stwu, 0x94000000, D )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // EA <- (RA) + EXTS(D) // MEM(EA, 4) <- (RS)[32:63] @@ -428,6 +605,17 @@ XEEMITTER(stwux, 0x7C00016E, X )(FunctionGenerator& g, IRBuilder<>& b, I return 1; } +XEDISASMR(stwx, 0x7C00012E, X )(InstrData& i, InstrDisasm& d) { + d.Init("stwx", "Store Word Indexed", 0); + d.AddRegOperand(InstrRegister::kGPR, 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(stwx, 0x7C00012E, X )(FunctionGenerator& g, IRBuilder<>& b, InstrData& i) { // if RA = 0 then // b <- 0 @@ -682,45 +870,45 @@ XEEMITTER(icbi, 0x7C0007AC, X )(FunctionGenerator& g, IRBuilder<>& b, I void RegisterEmitCategoryMemory() { - XEREGISTEREMITTER(lbz, 0x88000000); - XEREGISTEREMITTER(lbzu, 0x8C000000); - XEREGISTEREMITTER(lbzux, 0x7C0000EE); - XEREGISTEREMITTER(lbzx, 0x7C0000AE); - XEREGISTEREMITTER(ld, 0xE8000000); - XEREGISTEREMITTER(ldu, 0xE8000001); + XEREGISTERINSTR(lbz, 0x88000000); + XEREGISTERINSTR(lbzu, 0x8C000000); + XEREGISTERINSTR(lbzux, 0x7C0000EE); + XEREGISTERINSTR(lbzx, 0x7C0000AE); + XEREGISTERINSTR(ld, 0xE8000000); + XEREGISTERINSTR(ldu, 0xE8000001); XEREGISTEREMITTER(ldux, 0x7C00006A); XEREGISTEREMITTER(ldx, 0x7C00002A); XEREGISTEREMITTER(lha, 0xA8000000); XEREGISTEREMITTER(lhau, 0xAC000000); XEREGISTEREMITTER(lhaux, 0x7C0002EE); XEREGISTEREMITTER(lhax, 0x7C0002AE); - XEREGISTEREMITTER(lhz, 0xA0000000); + XEREGISTERINSTR(lhz, 0xA0000000); XEREGISTEREMITTER(lhzu, 0xA4000000); XEREGISTEREMITTER(lhzux, 0x7C00026E); XEREGISTEREMITTER(lhzx, 0x7C00022E); XEREGISTEREMITTER(lwa, 0xE8000002); XEREGISTEREMITTER(lwaux, 0x7C0002EA); XEREGISTEREMITTER(lwax, 0x7C0002AA); - XEREGISTEREMITTER(lwz, 0x80000000); - XEREGISTEREMITTER(lwzu, 0x84000000); + XEREGISTERINSTR(lwz, 0x80000000); + XEREGISTERINSTR(lwzu, 0x84000000); XEREGISTEREMITTER(lwzux, 0x7C00006E); - XEREGISTEREMITTER(lwzx, 0x7C00002E); - XEREGISTEREMITTER(stb, 0x98000000); - XEREGISTEREMITTER(stbu, 0x9C000000); + XEREGISTERINSTR(lwzx, 0x7C00002E); + XEREGISTERINSTR(stb, 0x98000000); + XEREGISTERINSTR(stbu, 0x9C000000); XEREGISTEREMITTER(stbux, 0x7C0001EE); XEREGISTEREMITTER(stbx, 0x7C0001AE); - XEREGISTEREMITTER(std, 0xF8000000); - XEREGISTEREMITTER(stdu, 0xF8000001); + XEREGISTERINSTR(std, 0xF8000000); + XEREGISTERINSTR(stdu, 0xF8000001); XEREGISTEREMITTER(stdux, 0x7C00016A); XEREGISTEREMITTER(stdx, 0x7C00012A); - XEREGISTEREMITTER(sth, 0xB0000000); - XEREGISTEREMITTER(sthu, 0xB4000000); + XEREGISTERINSTR(sth, 0xB0000000); + XEREGISTERINSTR(sthu, 0xB4000000); XEREGISTEREMITTER(sthux, 0x7C00036E); - XEREGISTEREMITTER(sthx, 0x7C00032E); - XEREGISTEREMITTER(stw, 0x90000000); - XEREGISTEREMITTER(stwu, 0x94000000); + XEREGISTERINSTR(sthx, 0x7C00032E); + XEREGISTERINSTR(stw, 0x90000000); + XEREGISTERINSTR(stwu, 0x94000000); XEREGISTEREMITTER(stwux, 0x7C00016E); - XEREGISTEREMITTER(stwx, 0x7C00012E); + XEREGISTERINSTR(stwx, 0x7C00012E); XEREGISTEREMITTER(lhbrx, 0x7C00062C); XEREGISTEREMITTER(lwbrx, 0x7C00042C); XEREGISTEREMITTER(ldbrx, 0x7C000428); diff --git a/src/cpu/ppc/instr.cc b/src/cpu/ppc/instr.cc index 5327cf679..628af95d7 100644 --- a/src/cpu/ppc/instr.cc +++ b/src/cpu/ppc/instr.cc @@ -38,11 +38,30 @@ void InstrDisasm::Init(std::string name, std::string info, uint32_t flags) { InstrRegister::kXER, 0, InstrRegister::kReadWrite }); } + if (flags & InstrDisasm::kLR) { + name += "l"; + special_registers.push_back((InstrRegister){ + InstrRegister::kLR, 0, InstrRegister::kWrite + }); + } + XEIGNORE(xestrcpya(this->name, XECOUNT(this->name), name.c_str())); XEIGNORE(xestrcpya(this->info, XECOUNT(this->info), info.c_str())); } +void InstrDisasm::AddLR(InstrRegister::Access access) { + special_registers.push_back((InstrRegister){ + InstrRegister::kLR, 0, access + }); +} + +void InstrDisasm::AddCTR(InstrRegister::Access access) { + special_registers.push_back((InstrRegister){ + InstrRegister::kCTR, 0, access + }); +} + void InstrDisasm::AddCR(uint32_t bf, InstrRegister::Access access) { special_registers.push_back((InstrRegister){ InstrRegister::kCR, bf, access @@ -137,16 +156,16 @@ void InstrDisasm::AddUImmOperand(uint64_t value, size_t width, const size_t max_count = XECOUNT(o.display); switch (width) { case 1: - xesnprintfa(o.display, max_count, "%.2X", (uint8_t)value); + xesnprintfa(o.display, max_count, "0x%.2X", (uint8_t)value); break; case 2: - xesnprintfa(o.display, max_count, "%.4X", (uint16_t)value); + xesnprintfa(o.display, max_count, "0x%.4X", (uint16_t)value); break; case 4: - xesnprintfa(o.display, max_count, "%.8X", (uint32_t)value); + xesnprintfa(o.display, max_count, "0x%.8X", (uint32_t)value); break; case 8: - xesnprintfa(o.display, max_count, "%.16llX", value); + xesnprintfa(o.display, max_count, "0x%.16llX", value); break; } }