| //=== 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-2014 */ |
| |
| #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; |
| MCPhysReg *List; |
| } DiffListIterator; |
| |
| void MCRegisterInfo_InitMCRegisterInfo(MCRegisterInfo *RI, |
| MCRegisterDesc *D, unsigned NR, |
| unsigned RA, unsigned PC, |
| MCRegisterClass *C, unsigned NC, |
| uint16_t (*RURoots)[2], unsigned NRU, |
| MCPhysReg *DL, |
| char *Strings, |
| uint16_t *SubIndices, unsigned NumIndices, |
| 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, 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(MCRegisterInfo *RI, unsigned Reg, unsigned SubIdx, 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(MCRegisterInfo *RI, unsigned Reg, unsigned Idx) |
| { |
| DiffListIterator iter; |
| 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; |
| } |
| |
| MCRegisterClass* MCRegisterInfo_getRegClass(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(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; |
| } |