Add emulation methods for LSL (immediate), LSL (register), LSR (immediate), and LSR (register).
Create two helper methods EmulateShiftImm() and EmulateShiftReg() and have ASR, LSL, and LSR
delegate to the helper methods which take an extra ARM_ShifterType parameter.
The opcodes tables have not been updated yet to reflect these new entries.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@125633 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index b5c29bf..c8755e8 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -2125,6 +2125,136 @@
// APSR.V unchanged
#endif
+ return EmulateShiftImm(encoding, SRType_ASR);
+}
+
+// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
+// shifting in copies of its sign bit, and writes the result to the destination register.
+// The variable number of bits is read from the bottom byte of a register. It can optionally update
+// the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
+{
+#if 0
+ // ARM pseudo code...
+ if ConditionPassed() then
+ EncodingSpecificOperations();
+ shift_n = UInt(R[m]<7:0>);
+ (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
+ R[d] = result;
+ if setflags then
+ APSR.N = result<31>;
+ APSR.Z = IsZeroBit(result);
+ APSR.C = carry;
+ // APSR.V unchanged
+#endif
+
+ return EmulateShiftReg(encoding, SRType_ASR);
+}
+
+// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
+// shifting in zeros, and writes the result to the destination register. It can optionally
+// update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateLSLImm (ARMEncoding encoding)
+{
+#if 0
+ // ARM pseudo code...
+ if ConditionPassed() then
+ EncodingSpecificOperations();
+ (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
+ if d == 15 then // Can only occur for ARM encoding
+ ALUWritePC(result); // setflags is always FALSE here
+ else
+ R[d] = result;
+ if setflags then
+ APSR.N = result<31>;
+ APSR.Z = IsZeroBit(result);
+ APSR.C = carry;
+ // APSR.V unchanged
+#endif
+
+ return EmulateShiftImm(encoding, SRType_LSL);
+}
+
+// Logical Shift Left (register) shifts a register value left by a variable number of bits,
+// shifting in zeros, and writes the result to the destination register. The variable number
+// of bits is read from the bottom byte of a register. It can optionally update the condition
+// flags based on the result.
+bool
+EmulateInstructionARM::EmulateLSLReg (ARMEncoding encoding)
+{
+#if 0
+ // ARM pseudo code...
+ if ConditionPassed() then
+ EncodingSpecificOperations();
+ shift_n = UInt(R[m]<7:0>);
+ (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
+ R[d] = result;
+ if setflags then
+ APSR.N = result<31>;
+ APSR.Z = IsZeroBit(result);
+ APSR.C = carry;
+ // APSR.V unchanged
+#endif
+
+ return EmulateShiftReg(encoding, SRType_LSL);
+}
+
+// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
+// shifting in zeros, and writes the result to the destination register. It can optionally
+// update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateLSRImm (ARMEncoding encoding)
+{
+#if 0
+ // ARM pseudo code...
+ if ConditionPassed() then
+ EncodingSpecificOperations();
+ (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
+ if d == 15 then // Can only occur for ARM encoding
+ ALUWritePC(result); // setflags is always FALSE here
+ else
+ R[d] = result;
+ if setflags then
+ APSR.N = result<31>;
+ APSR.Z = IsZeroBit(result);
+ APSR.C = carry;
+ // APSR.V unchanged
+#endif
+
+ return EmulateShiftImm(encoding, SRType_LSR);
+}
+
+// Logical Shift Right (register) shifts a register value right by a variable number of bits,
+// shifting in zeros, and writes the result to the destination register. The variable number
+// of bits is read from the bottom byte of a register. It can optionally update the condition
+// flags based on the result.
+bool
+EmulateInstructionARM::EmulateLSRReg (ARMEncoding encoding)
+{
+#if 0
+ // ARM pseudo code...
+ if ConditionPassed() then
+ EncodingSpecificOperations();
+ shift_n = UInt(R[m]<7:0>);
+ (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
+ R[d] = result;
+ if setflags then
+ APSR.N = result<31>;
+ APSR.Z = IsZeroBit(result);
+ APSR.C = carry;
+ // APSR.V unchanged
+#endif
+
+ return EmulateShiftReg(encoding, SRType_LSR);
+}
+
+bool
+EmulateInstructionARM::EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type)
+{
+ assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
+
bool success = false;
const uint32_t opcode = OpcodeAsUnsigned (&success);
if (!success)
@@ -2168,9 +2298,9 @@
return false;
// Decode the shift amount.
- uint32_t amt = DecodeImmShift(SRType_ASR, imm5);
+ uint32_t amt = DecodeImmShift(shift_type, imm5);
- uint32_t result = Shift_C(value, SRType_ASR, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
+ uint32_t result = Shift_C(value, shift_type, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
// The context specifies that an immediate is to be moved into Rd.
EmulateInstruction::Context context;
@@ -2203,26 +2333,10 @@
return true;
}
-// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
-// shifting in copies of its sign bit, and writes the result to the destination register.
-// The variable number of bits is read from the bottom byte of a register. It can optionally update
-// the condition flags based on the result.
bool
-EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
+EmulateInstructionARM::EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type)
{
-#if 0
- // ARM pseudo code...
- if ConditionPassed() then
- EncodingSpecificOperations();
- shift_n = UInt(R[m]<7:0>);
- (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
- R[d] = result;
- if setflags then
- APSR.N = result<31>;
- APSR.Z = IsZeroBit(result);
- APSR.C = carry;
- // APSR.V unchanged
-#endif
+ assert(shift_type == SRType_ASR || shift_type == SRType_LSL || shift_type == SRType_LSR);
bool success = false;
const uint32_t opcode = OpcodeAsUnsigned (&success);
@@ -2275,7 +2389,7 @@
// Get the shift amount.
uint32_t amt = Bits32(val, 7, 0);
- uint32_t result = Shift_C(value, SRType_ASR, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
+ uint32_t result = Shift_C(value, shift_type, amt, Bit32(m_inst_cpsr, CPSR_C), carry);
// The context specifies that an immediate is to be moved into Rd.
EmulateInstruction::Context context;
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
index 1ff3643..d19e45a 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
@@ -12,6 +12,7 @@
#include "lldb/Core/EmulateInstruction.h"
#include "lldb/Core/Error.h"
+#include "Plugins/Process/Utility/ARMDefines.h"
namespace lldb_private {
@@ -335,6 +336,30 @@
bool
EmulateASRReg (ARMEncoding encoding);
+ // A8.6.88 LSL (immediate)
+ bool
+ EmulateLSLImm (ARMEncoding encoding);
+
+ // A8.6.89 LSL (register)
+ bool
+ EmulateLSLReg (ARMEncoding encoding);
+
+ // A8.6.90 LSR (immediate)
+ bool
+ EmulateLSRImm (ARMEncoding encoding);
+
+ // A8.6.91 LSR (register)
+ bool
+ EmulateLSRReg (ARMEncoding encoding);
+
+ // Helper method for ASR, LSL, and LSR
+ bool
+ EmulateShiftImm (ARMEncoding encoding, ARM_ShifterType shift_type);
+
+ // Helper method for ASR, LSL, and LSR
+ bool
+ EmulateShiftReg (ARMEncoding encoding, ARM_ShifterType shift_type);
+
// A8.6.53 LDM/LDMIA/LDMFD
bool
EmulateLDM (ARMEncoding encoding);