You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
144 lines
3.5 KiB
144 lines
3.5 KiB
//=== MC/MCRegisterInfo.cpp - Target Register Description -------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements MCRegisterInfo functions.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/* Capstone Disassembly Engine */
|
|
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */
|
|
|
|
#include "MCRegisterInfo.h"
|
|
|
|
/// DiffListIterator - Base iterator class that can traverse the
|
|
/// differentially encoded register and regunit lists in DiffLists.
|
|
/// Don't use this class directly, use one of the specialized sub-classes
|
|
/// defined below.
|
|
typedef struct DiffListIterator {
|
|
uint16_t Val;
|
|
const MCPhysReg *List;
|
|
} DiffListIterator;
|
|
|
|
void MCRegisterInfo_InitMCRegisterInfo(MCRegisterInfo *RI,
|
|
const MCRegisterDesc *D, unsigned NR,
|
|
unsigned RA, unsigned PC,
|
|
const MCRegisterClass *C, unsigned NC,
|
|
uint16_t (*RURoots)[2], unsigned NRU,
|
|
const MCPhysReg *DL,
|
|
const char *Strings,
|
|
const uint16_t *SubIndices, unsigned NumIndices,
|
|
const uint16_t *RET)
|
|
{
|
|
RI->Desc = D;
|
|
RI->NumRegs = NR;
|
|
RI->RAReg = RA;
|
|
RI->PCReg = PC;
|
|
RI->Classes = C;
|
|
RI->DiffLists = DL;
|
|
RI->RegStrings = Strings;
|
|
RI->NumClasses = NC;
|
|
RI->RegUnitRoots = RURoots;
|
|
RI->NumRegUnits = NRU;
|
|
RI->SubRegIndices = SubIndices;
|
|
RI->NumSubRegIndices = NumIndices;
|
|
RI->RegEncodingTable = RET;
|
|
}
|
|
|
|
static void DiffListIterator_init(DiffListIterator *d, MCPhysReg InitVal, const MCPhysReg *DiffList)
|
|
{
|
|
d->Val = InitVal;
|
|
d->List = DiffList;
|
|
}
|
|
|
|
static uint16_t DiffListIterator_getVal(DiffListIterator *d)
|
|
{
|
|
return d->Val;
|
|
}
|
|
|
|
static bool DiffListIterator_next(DiffListIterator *d)
|
|
{
|
|
MCPhysReg D;
|
|
|
|
if (d->List == 0)
|
|
return false;
|
|
|
|
D = *d->List;
|
|
d->List++;
|
|
d->Val += D;
|
|
|
|
if (!D)
|
|
d->List = 0;
|
|
|
|
return (D != 0);
|
|
}
|
|
|
|
static bool DiffListIterator_isValid(DiffListIterator *d)
|
|
{
|
|
return (d->List != 0);
|
|
}
|
|
|
|
unsigned MCRegisterInfo_getMatchingSuperReg(const MCRegisterInfo *RI, unsigned Reg, unsigned SubIdx, const MCRegisterClass *RC)
|
|
{
|
|
DiffListIterator iter;
|
|
|
|
if (Reg >= RI->NumRegs) {
|
|
return 0;
|
|
}
|
|
|
|
DiffListIterator_init(&iter, (MCPhysReg)Reg, RI->DiffLists + RI->Desc[Reg].SuperRegs);
|
|
DiffListIterator_next(&iter);
|
|
|
|
while(DiffListIterator_isValid(&iter)) {
|
|
uint16_t val = DiffListIterator_getVal(&iter);
|
|
if (MCRegisterClass_contains(RC, val) && Reg == MCRegisterInfo_getSubReg(RI, val, SubIdx))
|
|
return val;
|
|
|
|
DiffListIterator_next(&iter);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
unsigned MCRegisterInfo_getSubReg(const MCRegisterInfo *RI, unsigned Reg, unsigned Idx)
|
|
{
|
|
DiffListIterator iter;
|
|
const uint16_t *SRI = RI->SubRegIndices + RI->Desc[Reg].SubRegIndices;
|
|
|
|
DiffListIterator_init(&iter, (MCPhysReg)Reg, RI->DiffLists + RI->Desc[Reg].SubRegs);
|
|
DiffListIterator_next(&iter);
|
|
|
|
while(DiffListIterator_isValid(&iter)) {
|
|
if (*SRI == Idx)
|
|
return DiffListIterator_getVal(&iter);
|
|
DiffListIterator_next(&iter);
|
|
++SRI;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
const MCRegisterClass* MCRegisterInfo_getRegClass(const MCRegisterInfo *RI, unsigned i)
|
|
{
|
|
//assert(i < getNumRegClasses() && "Register Class ID out of range");
|
|
if (i >= RI->NumClasses)
|
|
return 0;
|
|
return &(RI->Classes[i]);
|
|
}
|
|
|
|
bool MCRegisterClass_contains(const MCRegisterClass *c, unsigned Reg)
|
|
{
|
|
unsigned InByte = Reg % 8;
|
|
unsigned Byte = Reg / 8;
|
|
|
|
if (Byte >= c->RegSetSize)
|
|
return false;
|
|
|
|
return (c->RegSet[Byte] & (1 << InByte)) != 0;
|
|
}
|