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 "ARMUtils.h"
|
||||||
#include "ARM_DWARF_Registers.h"
|
#include "ARM_DWARF_Registers.h"
|
||||||
#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
|
#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
|
||||||
|
// and CountTrailingZeros_32 function
|
||||||
|
|
||||||
using namespace lldb;
|
using namespace lldb;
|
||||||
using namespace lldb_private;
|
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
|
// ARM constants used during decoding
|
||||||
#define REG_RD 0
|
#define REG_RD 0
|
||||||
#define LDM_REGLIST 1
|
#define LDM_REGLIST 1
|
||||||
|
|
|
@ -15,6 +15,30 @@
|
||||||
|
|
||||||
namespace lldb_private {
|
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
|
class EmulateInstructionARM : public EmulateInstruction
|
||||||
{
|
{
|
||||||
public:
|
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);
|
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"
|
// Create a mask that starts at bit zero and includes "bit"
|
||||||
static inline uint64_t
|
static inline uint64_t
|
||||||
MaskUpToBit (const uint64_t bit)
|
MaskUpToBit (const uint64_t bit)
|
||||||
|
|
Loading…
Reference in New Issue