From b44355f367a3a7df09b33c290c60ffc16dbd3163 Mon Sep 17 00:00:00 2001 From: Alessandro Gatti Date: Wed, 8 Jun 2022 20:36:33 +0200 Subject: [PATCH] Use pcodeops for `bitrev` and `byterev`. --- .../68000/data/languages/68000.sinc | 16 ++---- .../m68kEmulateInstructionStateModifier.java | 56 +++++++++++++++++++ 2 files changed, 62 insertions(+), 10 deletions(-) diff --git a/Ghidra/Processors/68000/data/languages/68000.sinc b/Ghidra/Processors/68000/data/languages/68000.sinc index 5c6ffba27b..f361d129c0 100644 --- a/Ghidra/Processors/68000/data/languages/68000.sinc +++ b/Ghidra/Processors/68000/data/languages/68000.sinc @@ -860,20 +860,16 @@ define pcodeop countLeadingZeros; @ifdef COLDFIRE +define pcodeop bitReverse; + :bitrev regdn is reg315=0x18 & regdn { - local dword = regdn; - regdn[31,1] = dword[0,1]; regdn[30,1] = dword[1,1]; regdn[29,1] = dword[2,1]; regdn[28,1] = dword[3,1]; - regdn[27,1] = dword[4,1]; regdn[26,1] = dword[5,1]; regdn[25,1] = dword[6,1]; regdn[24,1] = dword[7,1]; - regdn[23,1] = dword[8,1]; regdn[22,1] = dword[9,1]; regdn[21,1] = dword[10,1]; regdn[20,1] = dword[11,1]; - regdn[19,1] = dword[12,1]; regdn[18,1] = dword[13,1]; regdn[17,1] = dword[14,1]; regdn[16,1] = dword[15,1]; - regdn[15,1] = dword[16,1]; regdn[14,1] = dword[17,1]; regdn[13,1] = dword[18,1]; regdn[12,1] = dword[19,1]; - regdn[11,1] = dword[20,1]; regdn[10,1] = dword[21,1]; regdn[9,1] = dword[22,1]; regdn[8,1] = dword[23,1]; - regdn[7,1] = dword[24,1]; regdn[6,1] = dword[25,1]; regdn[5,1] = dword[26,1]; regdn[4,1] = dword[27,1]; - regdn[3,1] = dword[28,1]; regdn[2,1] = dword[29,1]; regdn[1,1] = dword[30,1]; regdn[0,1] = dword[31,1]; + regdn = bitReverse(regdn); } +define pcodeop byteReverse; + :byterev regdn is reg315=0x58 & regdn { - regdn = ((regdn & 0x000000FF) << 24) | ((regdn & 0x0000FF00) << 8) | ((regdn & 0x00FF0000) >> 8) | ((regdn & 0xFF000000) >> 24); + regdn = byteReverse(regdn); } @endif # COLDFIRE diff --git a/Ghidra/Processors/68000/src/main/java/ghidra/program/emulation/m68kEmulateInstructionStateModifier.java b/Ghidra/Processors/68000/src/main/java/ghidra/program/emulation/m68kEmulateInstructionStateModifier.java index 98a56cd986..04536687ef 100644 --- a/Ghidra/Processors/68000/src/main/java/ghidra/program/emulation/m68kEmulateInstructionStateModifier.java +++ b/Ghidra/Processors/68000/src/main/java/ghidra/program/emulation/m68kEmulateInstructionStateModifier.java @@ -50,6 +50,8 @@ public class m68kEmulateInstructionStateModifier extends EmulateInstructionState registerPcodeOpBehavior("countLeadingZeros", new CountLeadingZerosOpBehavior()); registerPcodeOpBehavior("findFirstOne", new FindFirstOneOpBehavior()); + registerPcodeOpBehavior("bitReverse", new BitReverseOpBehavior()); + registerPcodeOpBehavior("byteReverse", new ByteReverseOpBehavior()); } /** @@ -142,4 +144,58 @@ public class m68kEmulateInstructionStateModifier extends EmulateInstructionState } } + + private static class BitReverseOpBehavior implements OpBehaviorOther { + + @Override + public void evaluate(Emulate emu, Varnode out, Varnode[] inputs) { + if (out == null) { + throw new LowlevelError("CALLOTHER: Bit Reverse op missing required output"); + } + + if (inputs.length != 2 || inputs[1].getSize() == 0 || !inputs[1].isRegister()) { + throw new LowlevelError( + "CALLOTHER: Bit Reverse op requires one register varnode input"); + } + + Varnode in = inputs[1]; + MemoryState memoryState = emu.getMemoryState(); + + long value = memoryState.getValue(in); + long size = in.getSize() * 8; + long bitFrom = size - 1; + long bitTo = 0; + long reversed = 0; + while (bitFrom >= 0) { + reversed |= ((value >> bitFrom) & 1L) << bitTo; + bitTo++; + } + + memoryState.setValue(out, reversed); + } + + } + + private static class ByteReverseOpBehavior implements OpBehaviorOther { + + @Override + public void evaluate(Emulate emu, Varnode out, Varnode[] inputs) { + if (out == null) { + throw new LowlevelError("CALLOTHER: Byte Reverse op missing required output"); + } + + if (inputs.length != 2 || inputs[1].getSize() == 0 || !inputs[1].isRegister()) { + throw new LowlevelError( + "CALLOTHER: Byte Reverse op requires one register varnode input"); + } + + Varnode in = inputs[1]; + MemoryState memoryState = emu.getMemoryState(); + + long value = memoryState.getValue(in); + memoryState.setValue(out, ((value & 0x000000FF) << 24) | ((value & 0x0000FF00) << 8) | + ((value & 0x00FF0000) >> 8) | ((value & 0xFF000000) >> 24)); + } + + } }