summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGalen Williamson <galen@vector35.com>2024-03-08 15:00:02 -0500
committerGalen Williamson <galen@vector35.com>2024-03-26 15:08:13 -0400
commit661f5c4cfb60f36a57b5d05ec7883af821abd046 (patch)
treed1f57e539f0d69a32c4b1ce657c341cae9fd88f6
parentcc22a52907a052f37dad319f843f218fe69e1b9a (diff)
added lifting for EXTSW LD LDU LDUX LDX SLD SRAD SRADI SRD STD STDU STDUX STDX
-rw-r--r--arch/powerpc/arch_ppc.cpp16
-rw-r--r--arch/powerpc/disassembler.cpp2
-rw-r--r--arch/powerpc/disassembler.h2
-rw-r--r--arch/powerpc/il.cpp134
4 files changed, 132 insertions, 22 deletions
diff --git a/arch/powerpc/arch_ppc.cpp b/arch/powerpc/arch_ppc.cpp
index 2f657b7a..e44564c4 100644
--- a/arch/powerpc/arch_ppc.cpp
+++ b/arch/powerpc/arch_ppc.cpp
@@ -281,6 +281,7 @@ class PowerpcArchitecture: public Architecture
{
private:
BNEndianness endian;
+ size_t addressSize;
/* this can maybe be moved to the API later */
BNRegisterInfo RegisterInfo(uint32_t fullWidthReg, size_t offset, size_t size, bool zeroExtend = false)
@@ -296,9 +297,10 @@ class PowerpcArchitecture: public Architecture
public:
/* initialization list */
- PowerpcArchitecture(const char* name, BNEndianness endian_): Architecture(name)
+ PowerpcArchitecture(const char* name, BNEndianness endian_, size_t addressSize_=4): Architecture(name)
{
endian = endian_;
+ addressSize = addressSize_;
}
/*************************************************************************/
@@ -312,7 +314,7 @@ class PowerpcArchitecture: public Architecture
virtual size_t GetAddressSize() const override
{
//MYLOG("%s()\n", __func__);
- return 4;
+ return addressSize;
}
virtual size_t GetDefaultIntegerSize() const override
@@ -360,7 +362,7 @@ class PowerpcArchitecture: public Architecture
}
/* decompose the instruction to get branch info */
- if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res)) {
+ if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res, GetAddressSize() == 8)) {
MYLOG("ERROR: powerpc_decompose()\n");
return false;
}
@@ -622,7 +624,7 @@ class PowerpcArchitecture: public Architecture
if (DoesQualifyForLocalDisassembly(data))
return PerformLocalDisassembly(data, addr, len, result);
- if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res)) {
+ if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res, GetAddressSize() == 8)) {
MYLOG("ERROR: powerpc_decompose()\n");
goto cleanup;
}
@@ -748,7 +750,7 @@ class PowerpcArchitecture: public Architecture
goto cleanup;
}
- if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res)) {
+ if(powerpc_decompose(data, 4, (uint32_t)addr, endian == LittleEndian, &res, GetAddressSize() == 8)) {
MYLOG("ERROR: powerpc_decompose()\n");
il.AddInstruction(il.Undefined());
goto cleanup;
@@ -2471,13 +2473,13 @@ extern "C"
Architecture* ppc = new PowerpcArchitecture("ppc", BigEndian);
Architecture::Register(ppc);
- Architecture* ppc64 = new PowerpcArchitecture("ppc64", BigEndian);
+ Architecture* ppc64 = new PowerpcArchitecture("ppc64", BigEndian, 8);
Architecture::Register(ppc64);
Architecture* ppc_le = new PowerpcArchitecture("ppc_le", LittleEndian);
Architecture::Register(ppc_le);
- Architecture* ppc64_le = new PowerpcArchitecture("ppc64_le", LittleEndian);
+ Architecture* ppc64_le = new PowerpcArchitecture("ppc64_le", LittleEndian, 8);
Architecture::Register(ppc64_le);
/* calling conventions */
diff --git a/arch/powerpc/disassembler.cpp b/arch/powerpc/disassembler.cpp
index 66a8b36d..480ab658 100644
--- a/arch/powerpc/disassembler.cpp
+++ b/arch/powerpc/disassembler.cpp
@@ -69,7 +69,7 @@ powerpc_release(void)
extern "C" int
powerpc_decompose(const uint8_t *data, int size, uint32_t addr, bool lil_end,
- struct decomp_result *res)
+ struct decomp_result *res, bool is_64bit)
{
int rc = -1;
res->status = STATUS_ERROR_UNSPEC;
diff --git a/arch/powerpc/disassembler.h b/arch/powerpc/disassembler.h
index e1701687..e1d3ca55 100644
--- a/arch/powerpc/disassembler.h
+++ b/arch/powerpc/disassembler.h
@@ -62,7 +62,7 @@ struct decomp_result
extern "C" int powerpc_init(void);
extern "C" void powerpc_release(void);
extern "C" int powerpc_decompose(const uint8_t *data, int size, uint32_t addr,
- bool lil_end, struct decomp_result *result);
+ bool lil_end, struct decomp_result *result, bool is_64bit);
extern "C" int powerpc_disassemble(struct decomp_result *, char *buf, size_t len);
extern "C" const char *powerpc_reg_to_str(uint32_t rid);
diff --git a/arch/powerpc/il.cpp b/arch/powerpc/il.cpp
index 1de2c5c0..76cf7419 100644
--- a/arch/powerpc/il.cpp
+++ b/arch/powerpc/il.cpp
@@ -845,6 +845,17 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il,
il.AddInstruction(ei0);
break;
+ case PPC_INS_EXTSW:
+ REQUIRE2OPS
+ ei0 = il.Register(8, oper1->reg);
+ ei0 = il.LowPart(4, ei0);
+ ei0 = il.SignExtend(8, ei0);
+ ei0 = il.SetRegister(8, oper0->reg, ei0,
+ ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0
+ );
+ il.AddInstruction(ei0);
+ break;
+
case PPC_INS_ISEL:
REQUIRE4OPS
{
@@ -1030,6 +1041,44 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il,
break;
+ /*
+ load doubleword [and update]
+ */
+ case PPC_INS_LD:
+ case PPC_INS_LDU:
+ REQUIRE2OPS
+ ei0 = operToIL(il, oper1, OTI_GPR0_ZERO); // d(rA) or 0
+ ei0 = il.Load(8, ei0); // [d(rA)]
+ ei0 = il.SetRegister(8, oper0->reg, ei0); // rD = [d(rA)]
+ il.AddInstruction(ei0);
+
+ // if update, rA is set to effective address (d(rA))
+ if(insn->id == PPC_INS_LWZU) {
+ ei0 = il.SetRegister(8, oper1->mem.base, operToIL(il, oper1));
+ il.AddInstruction(ei0);
+ }
+
+ break;
+
+ /*
+ load doubleword [and update]
+ */
+ case PPC_INS_LDX:
+ case PPC_INS_LDUX:
+ REQUIRE3OPS
+ ei0 = operToIL(il, oper1, OTI_GPR0_ZERO); // d(rA) or 0
+ ei0 = il.Load(8, il.Add(8, ei0, operToIL(il, oper2))); // [d(rA) + d(rB)]
+ ei0 = il.SetRegister(8, oper0->reg, ei0); // rD = [d(rA)]
+ il.AddInstruction(ei0);
+
+ // if update, rA is set to effective address (d(rA))
+ if(insn->id == PPC_INS_LWZUX && oper1->reg != oper0->reg && oper1->reg != PPC_REG_R0) {
+ ei0 = il.SetRegister(8, oper1->reg, operToIL(il, oper1));
+ il.AddInstruction(ei0);
+ }
+
+ break;
+
case PPC_INS_LHBRX:
REQUIRE3OPS
ByteReversedLoad(il, ppc, 2);
@@ -1331,6 +1380,44 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il,
break;
+ /* store double word [with update] */
+ case PPC_INS_STD:
+ case PPC_INS_STDU: /* store(size, addr, val) */
+ REQUIRE2OPS
+ ei0 = il.Store(8,
+ operToIL(il, oper1, OTI_GPR0_ZERO),
+ operToIL(il, oper0)
+ );
+ il.AddInstruction(ei0);
+
+ // if update, then rA gets updated address
+ if(insn->id == PPC_INS_STWU) {
+ ei0 = il.SetRegister(8, oper1->mem.base, operToIL(il, oper1));
+ il.AddInstruction(ei0);
+ }
+
+ break;
+
+ /* store word indexed [with update] */
+ case PPC_INS_STDX:
+ case PPC_INS_STDUX: /* store(size, addr, val) */
+ REQUIRE3OPS
+ ei0 = il.Store(8,
+ il.Add(8, operToIL(il, oper1, OTI_GPR0_ZERO), operToIL(il, oper2)),
+ operToIL(il, oper0)
+ );
+ il.AddInstruction(ei0);
+
+ // if update, then rA gets updated address
+ if(insn->id == PPC_INS_STDUX) {
+ ei0 = il.SetRegister(8, oper1->reg,
+ il.Add(8, operToIL(il, oper1), operToIL(il, oper2))
+ );
+ il.AddInstruction(ei0);
+ }
+
+ break;
+
case PPC_INS_RLWIMI:
REQUIRE5OPS
{
@@ -1484,6 +1571,21 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il,
));
break;
+ case PPC_INS_SLD:
+ case PPC_INS_SRD:
+ REQUIRE3OPS
+ ei0 = il.Register(8, oper1->reg);
+ // permit bit 25 to survive to enable clearing the whole register
+ ei1 = il.And(8, il.Register(8, oper2->reg), il.Const(8, 0x7f));
+ if (insn->id == PPC_INS_SLD)
+ ei0 = il.ShiftLeft(8, ei0, ei1);
+ else
+ ei0 = il.LogicalShiftRight(8, ei0, ei1);
+ il.AddInstruction(il.SetRegister(8, oper0->reg, ei0,
+ ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0
+ ));
+ break;
+
case PPC_INS_SRAW:
REQUIRE3OPS
ei0 = il.Register(4, oper1->reg);
@@ -1503,6 +1605,25 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il,
));
break;
+ case PPC_INS_SRAD:
+ REQUIRE3OPS
+ ei0 = il.Register(8, oper1->reg);
+ ei1 = il.And(8, il.Register(8, oper2->reg), il.Const(8, 0x3f));
+ ei0 = il.ArithShiftRight(8, ei0, ei1, IL_FLAGWRITE_XER_CA);
+ il.AddInstruction(il.SetRegister(8, oper0->reg, ei0,
+ ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0
+ ));
+ break;
+
+ case PPC_INS_SRADI:
+ REQUIRE3OPS
+ ei0 = il.Register(8, oper1->reg);
+ ei0 = il.ArithShiftRight(8, ei0, il.Const(8, oper2->imm), IL_FLAGWRITE_XER_CA);
+ il.AddInstruction(il.SetRegister(8, oper0->reg, ei0,
+ ppc->update_cr0 ? IL_FLAGWRITE_CR0_S : 0
+ ));
+ break;
+
case PPC_INS_MULLW:
REQUIRE3OPS
ei0 = il.Register(4, oper1->reg);
@@ -1768,7 +1889,6 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il,
case PPC_INS_EVSUBFW:
case PPC_INS_EVSUBIFW:
case PPC_INS_EVXOR:
- case PPC_INS_EXTSW:
case PPC_INS_FABS:
case PPC_INS_FADD:
case PPC_INS_FADDS:
@@ -1815,12 +1935,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il,
case PPC_INS_ICBI:
case PPC_INS_ICCCI:
case PPC_INS_ISYNC:
- case PPC_INS_LD:
case PPC_INS_LDARX:
case PPC_INS_LDBRX:
- case PPC_INS_LDU:
- case PPC_INS_LDUX:
- case PPC_INS_LDX:
case PPC_INS_LFD:
case PPC_INS_LFDU:
case PPC_INS_LFDUX:
@@ -1889,16 +2005,8 @@ bool GetLowLevelILForPPCInstruction(Architecture *arch, LowLevelILFunction &il,
case PPC_INS_SLBIE:
case PPC_INS_SLBMFEE:
case PPC_INS_SLBMTE:
- case PPC_INS_SLD:
- case PPC_INS_SRAD:
- case PPC_INS_SRADI:
- case PPC_INS_SRD:
- case PPC_INS_STD:
case PPC_INS_STDBRX:
case PPC_INS_STDCX:
- case PPC_INS_STDU:
- case PPC_INS_STDUX:
- case PPC_INS_STDX:
case PPC_INS_STFD:
case PPC_INS_STFDU:
case PPC_INS_STFDUX: