summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohnny Chen <johnny.chen@apple.com>2011-02-15 23:22:46 +0000
committerJohnny Chen <johnny.chen@apple.com>2011-02-15 23:22:46 +0000
commit531dbfa5d8d21a63fafc765a20c67d9142f55be8 (patch)
tree8f7ff3502a9deab0c44fddb9bec7a3dced7b445c
parent038124b6712b37ba27d2b375fb6544294c5fc3ed (diff)
downloadbcm5719-llvm-531dbfa5d8d21a63fafc765a20c67d9142f55be8.tar.gz
bcm5719-llvm-531dbfa5d8d21a63fafc765a20c67d9142f55be8.zip
A8.6.14 ASR (register)
Add EmulateASRReg() Encodings T1, T2, and A1 to the opcodes tables. llvm-svn: 125614
-rw-r--r--lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp108
-rw-r--r--lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h4
2 files changed, 109 insertions, 3 deletions
diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index 1797bc15294..15c4df3434a 100644
--- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -2132,9 +2132,9 @@ EmulateInstructionARM::EmulateASRImm (ARMEncoding encoding)
if (ConditionPassed())
{
- uint32_t Rd; // the destination register
- uint32_t Rm; // the first operand register
- uint32_t imm5; // encoding for the shift amount
+ uint32_t Rd; // the destination register
+ uint32_t Rm; // the first operand register
+ uint32_t imm5; // encoding for the shift amount
uint32_t carry; // the carry bit after the shift operation
bool setflags;
switch (encoding) {
@@ -2203,6 +2203,103 @@ 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)
+{
+#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
+
+ bool success = false;
+ const uint32_t opcode = OpcodeAsUnsigned (&success);
+ if (!success)
+ return false;
+
+ if (ConditionPassed())
+ {
+ uint32_t Rd; // the destination register
+ uint32_t Rn; // the first operand register
+ uint32_t Rm; // the register whose bottom byte contains the amount to shift by
+ uint32_t carry; // the carry bit after the shift operation
+ bool setflags;
+ switch (encoding) {
+ case eEncodingT1:
+ Rd = Bits32(opcode, 2, 0);
+ Rn = Rd;
+ Rm = Bits32(opcode, 5, 3);
+ setflags = !InITBlock();
+ break;
+ case eEncodingT2:
+ Rd = Bits32(opcode, 11, 8);
+ Rn = Bits32(opcode, 19, 16);
+ Rm = Bits32(opcode, 3, 0);
+ setflags = BitIsSet(opcode, 20);
+ if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
+ return false;
+ break;
+ case eEncodingA1:
+ Rd = Bits32(opcode, 15, 12);
+ Rn = Bits32(opcode, 3, 0);
+ Rm = Bits32(opcode, 11, 8);
+ setflags = BitIsSet(opcode, 20);
+ if (Rd == 15 || Rn == 15 || Rm == 15)
+ return false;
+ break;
+ default:
+ return false;
+ }
+
+ // Get the first operand.
+ uint32_t value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
+ if (!success)
+ return false;
+ // Get the Rm register content.
+ uint32_t val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
+ if (!success)
+ return false;
+
+ // 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);
+
+ // The context specifies that an immediate is to be moved into Rd.
+ EmulateInstruction::Context context;
+ context.type = EmulateInstruction::eContextImmediate;
+ context.SetNoArgs ();
+
+ if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, result))
+ return false;
+ if (setflags)
+ {
+ m_new_inst_cpsr = m_inst_cpsr;
+ SetBit32(m_new_inst_cpsr, CPSR_N, Bit32(result, CPSR_N));
+ SetBit32(m_new_inst_cpsr, CPSR_Z, result == 0 ? 1 : 0);
+ SetBit32(m_new_inst_cpsr, CPSR_C, carry);
+ if (m_new_inst_cpsr != m_inst_cpsr)
+ {
+ if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
// LDM loads multiple registers from consecutive memory locations, using an
// address from a base register. Optionally the address just above the highest of those locations
// can be written back to the base register.
@@ -3625,6 +3722,8 @@ EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode)
{ 0x0fef0000, 0x03e00000, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateMvnRdImm, "mvn{s} <Rd>, #<const>"},
// asr (immediate)
{ 0x0fef0070, 0x01a00040, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
+ // asr (immediate)
+ { 0x0fef00f0, 0x01a00050, ARMvAll, eEncodingA1, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
//----------------------------------------------------------------------
// Load instructions
@@ -3753,6 +3852,9 @@ EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
// asr (immediate)
{ 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
{ 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
+ // asr (register)
+ { 0xffffffc0, 0x00004100, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
+ { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
//----------------------------------------------------------------------
// Load instructions
diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
index 7ea87252c64..08ce5297353 100644
--- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
+++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
@@ -308,6 +308,10 @@ protected:
bool
EmulateASRImm (ARMEncoding encoding);
+ // A8.6.15 ASR (register)
+ bool
+ EmulateASRReg (ARMEncoding encoding);
+
bool
EmulateLDM (ARMEncoding encoding);
OpenPOWER on IntegriCloud