Add a utility class ITSession to maintain the ITState for the Thumb ISA.

llvm-svn: 124906
This commit is contained in:
Johnny Chen 2011-02-04 23:02:47 +00:00
parent 79042b3e93
commit ea745e86c8
3 changed files with 97 additions and 0 deletions

View File

@ -14,10 +14,74 @@
#include "ARMUtils.h"
#include "ARM_DWARF_Registers.h"
#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
// and CountTrailingZeros_32 function
using namespace lldb;
using namespace lldb_private;
// A8.6.50
// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
static unsigned short CountITSize(unsigned ITMask) {
// First count the trailing zeros of the IT mask.
unsigned TZ = llvm::CountTrailingZeros_32(ITMask);
if (TZ > 3)
{
printf("Encoding error: IT Mask '0000'\n");
return 0;
}
return (4 - TZ);
}
// Init ITState. Note that at least one bit is always 1 in mask.
bool ITSession::InitIT(unsigned short bits7_0)
{
ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
if (ITCounter == 0)
return false;
// A8.6.50 IT
unsigned short FirstCond = Bits32(bits7_0, 7, 4);
if (FirstCond == 0xF)
{
printf("Encoding error: IT FirstCond '1111'\n");
return false;
}
if (FirstCond == 0xE && ITCounter != 1)
{
printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
return false;
}
ITState = bits7_0;
return true;
}
// Update ITState if necessary.
void ITSession::ITAdvance()
{
assert(ITCounter);
--ITCounter;
if (ITCounter == 0)
ITState = 0;
else
{
unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
SetBits32(ITState, 4, 0, NewITState4_0);
}
}
// Return true if we're inside an IT Block.
bool ITSession::InITBlock()
{
return ITCounter != 0;
}
// Get condition bits for the current thumb instruction.
uint32_t ITSession::GetCond()
{
return Bits32(ITState, 7, 4);
}
// ARM constants used during decoding
#define REG_RD 0
#define LDM_REGLIST 1

View File

@ -15,6 +15,30 @@
namespace lldb_private {
// ITSession - Keep track of the IT Block progression.
class ITSession
{
public:
ITSession() : ITCounter(0), ITState(0) {}
~ITSession() {}
// InitIT - Initializes ITCounter/ITState.
bool InitIT(unsigned short bits7_0);
// ITAdvance - Updates ITCounter/ITState as IT Block progresses.
void ITAdvance();
// InITBlock - Returns true if we're inside an IT Block.
bool InITBlock();
// GetCond - Gets condition bits for the current thumb instruction.
uint32_t GetCond();
private:
uint32_t ITCounter; // Possible values: 0, 1, 2, 3, 4.
uint32_t ITState; // A2.5.2 Consists of IT[7:5] and IT[4:0] initially.
};
class EmulateInstructionARM : public EmulateInstruction
{
public:

View File

@ -21,6 +21,15 @@ Bits32 (const uint32_t value, const uint32_t msbit, const uint32_t lsbit)
return (value >> lsbit) & ((1u << (msbit - lsbit + 1)) - 1);
}
static inline void
SetBits32(uint32_t &bits, unsigned msbit, unsigned lsbit, unsigned val)
{
assert(msbit < 32 && lsbit < 32 && msbit >= lsbit);
uint32_t mask = ((1 << (msbit - lsbit + 1)) - 1);
bits &= ~(mask << lsbit);
bits |= (val & mask) << lsbit;
}
// Create a mask that starts at bit zero and includes "bit"
static inline uint64_t
MaskUpToBit (const uint64_t bit)