forked from OSchip/llvm-project
Add a utility class ITSession to maintain the ITState for the Thumb ISA.
llvm-svn: 124906
This commit is contained in:
parent
79042b3e93
commit
ea745e86c8
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue