A8.6.6 ADD (register)

Renamed EmulateAddRdnRm() to EmulateAddReg(), and added Encoding T1 to it.
Where Encoding T2 can potentially modify the PC, causing a brnach.

llvm-svn: 125782
This commit is contained in:
Johnny Chen 2011-02-17 22:03:29 +00:00
parent 48d9626055
commit fc5c19dec5
2 changed files with 34 additions and 8 deletions

View File

@ -1912,11 +1912,10 @@ EmulateInstructionARM::EmulateTB (ARMEncoding encoding)
return true;
}
// ADD <Rdn>, <Rm>
// where <Rdn> the destination register is also the first operand register
// and <Rm> is the second operand register.
// This instruction adds a register value and an optionally-shifted register value, and writes the result
// to the destination register. It can optionally update the condition flags based on the result.
bool
EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
EmulateInstructionARM::EmulateAddReg (ARMEncoding encoding)
{
#if 0
// ARM pseudo code...
@ -1943,15 +1942,28 @@ EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
if (ConditionPassed())
{
uint32_t Rd, Rn, Rm;
ARM_ShifterType shift_t;
uint32_t shift_n; // the shift applied to the value read from Rm
bool setflags;
switch (encoding)
{
case eEncodingT1:
Rd = Bits32(opcode, 2, 0);
Rn = Bits32(opcode, 5, 3);
Rm = Bits32(opcode, 8, 6);
setflags = !InITBlock();
shift_t = SRType_LSL;
shift_n = 0;
case eEncodingT2:
Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
Rm = Bits32(opcode, 6, 3);
setflags = false;
shift_t = SRType_LSL;
shift_n = 0;
if (Rn == 15 && Rm == 15)
return false;
if (Rd == 15 && InITBlock() && !LastInITBlock())
return false;
break;
default:
return false;
@ -1960,7 +1972,13 @@ EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
int32_t result, val1, val2;
// Read the first operand.
if (Rn == 15)
{
val1 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
if (encoding == eEncodingT1 || encoding == eEncodingT2)
val1 += 4;
else
val1 += 8;
}
else
val1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rn, 0, &success);
if (!success)
@ -1968,13 +1986,19 @@ EmulateInstructionARM::EmulateAddRdnRm (ARMEncoding encoding)
// Read the second operand.
if (Rm == 15)
{
val2 = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, 0, &success);
if (encoding == eEncodingT1 || encoding == eEncodingT2)
val1 += 4;
else
val1 += 8;
}
else
val2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + Rm, 0, &success);
if (!success)
return false;
// TODO: Handle the case where Rm needs to be shifted properly.
val2 = Shift(val2, shift_t, shift_n, Bit32(m_inst_cpsr, CPSR_C));
AddWithCarryResult res = AddWithCarry(val1, val2, 0);
result = val1 + val2;
@ -4371,8 +4395,10 @@ EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode)
//----------------------------------------------------------------------
// Data-processing instructions
//----------------------------------------------------------------------
{ 0xfffffe00, 0x00001800, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
// Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
{ 0xffffff00, 0x00004400, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateAddRdnRm, "add <Rdn>, <Rm>"},
// Can update PC!
{ 0xffffff00, 0x00004400, ARMvAll, eEncodingT2, eSize16, &EmulateInstructionARM::EmulateAddReg, "add<c> <Rdn>, <Rm>"},
// move from high register to high register
{ 0xffffff00, 0x00004600, ARMvAll, eEncodingT1, eSize16, &EmulateInstructionARM::EmulateMovRdRm, "mov<c> <Rd>, <Rm>"},
// move from low register to low register

View File

@ -388,9 +388,9 @@ protected:
bool
EmulateTB (ARMEncoding encoding);
// A8.6.6 ADD (register) -- Encoding T2
// A8.6.6 ADD (register)
bool
EmulateAddRdnRm (ARMEncoding encoding);
EmulateAddReg (ARMEncoding encoding);
// A8.6.97 MOV (register)
bool