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.

llvm-svn: 125633
This commit is contained in:
Johnny Chen
2011-02-16 01:27:54 +00:00
parent 25468059e5
commit 22deaa5a1a
4 changed files with 171 additions and 32 deletions

View File

@@ -2125,6 +2125,136 @@ EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
// 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 @@ EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
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 @@ EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
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 @@ EmulateInstructionARM::EmulateASRReg (ARMEncoding encoding)
// 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;

View File

@@ -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 @@ protected:
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);

View File

@@ -10,12 +10,20 @@
#ifndef lldb_ARMDefines_h_
#define lldb_ARMDefines_h_
#include "InstructionUtils.h"
// Common defintions for the ARM/Thumb Instruction Set Architecture.
namespace lldb_private {
// ARM shifter types
typedef enum
{
SRType_LSL,
SRType_LSR,
SRType_ASR,
SRType_ROR,
SRType_RRX
} ARM_ShifterType;
// ARM conditions // Meaning (integer) Meaning (floating-point) Condition flags
#define COND_EQ 0x0 // Equal Equal Z == 1
#define COND_NE 0x1 // Not equal Not equal, or unordered Z == 0

View File

@@ -10,6 +10,7 @@
#ifndef lldb_ARMUtils_h_
#define lldb_ARMUtils_h_
#include "ARMDefines.h"
#include "InstructionUtils.h"
#include "llvm/Support/MathExtras.h" // for SignExtend64 template function
@@ -17,15 +18,6 @@
namespace lldb_private {
typedef enum
{
SRType_LSL,
SRType_LSR,
SRType_ASR,
SRType_ROR,
SRType_RRX
} ARM_ShifterType;
static inline uint32_t DecodeImmShift(const uint32_t type, const uint32_t imm5, ARM_ShifterType &shift_t)
{
switch (type) {