1//=== MC/MCRegisterInfo.cpp - Target Register Description -------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements MCRegisterInfo functions.
11//
12//===----------------------------------------------------------------------===//
13
14/* Capstone Disassembly Engine */
15/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
16
17#include "MCRegisterInfo.h"
18
19/// DiffListIterator - Base iterator class that can traverse the
20/// differentially encoded register and regunit lists in DiffLists.
21/// Don't use this class directly, use one of the specialized sub-classes
22/// defined below.
23typedef struct DiffListIterator {
24	uint16_t Val;
25	MCPhysReg *List;
26} DiffListIterator;
27
28void MCRegisterInfo_InitMCRegisterInfo(MCRegisterInfo *RI,
29		MCRegisterDesc *D, unsigned NR,
30		unsigned RA, unsigned PC,
31		MCRegisterClass *C, unsigned NC,
32		uint16_t (*RURoots)[2], unsigned NRU,
33		MCPhysReg *DL,
34		char *Strings,
35		uint16_t *SubIndices, unsigned NumIndices,
36		uint16_t *RET)
37{
38	RI->Desc = D;
39	RI->NumRegs = NR;
40	RI->RAReg = RA;
41	RI->PCReg = PC;
42	RI->Classes = C;
43	RI->DiffLists = DL;
44	RI->RegStrings = Strings;
45	RI->NumClasses = NC;
46	RI->RegUnitRoots = RURoots;
47	RI->NumRegUnits = NRU;
48	RI->SubRegIndices = SubIndices;
49	RI->NumSubRegIndices = NumIndices;
50	RI->RegEncodingTable = RET;
51}
52
53static void DiffListIterator_init(DiffListIterator *d, MCPhysReg InitVal, MCPhysReg *DiffList)
54{
55	d->Val = InitVal;
56	d->List = DiffList;
57}
58
59static uint16_t DiffListIterator_getVal(DiffListIterator *d)
60{
61	return d->Val;
62}
63
64static bool DiffListIterator_next(DiffListIterator *d)
65{
66	MCPhysReg D;
67
68	if (d->List == 0)
69		return false;
70
71	D = *d->List;
72	d->List++;
73	d->Val += D;
74
75	if (!D)
76		d->List = 0;
77
78	return (D != 0);
79}
80
81static bool DiffListIterator_isValid(DiffListIterator *d)
82{
83	return (d->List != 0);
84}
85
86unsigned MCRegisterInfo_getMatchingSuperReg(MCRegisterInfo *RI, unsigned Reg, unsigned SubIdx, MCRegisterClass *RC)
87{
88	DiffListIterator iter;
89
90	if (Reg >= RI->NumRegs) {
91		return 0;
92	}
93
94	DiffListIterator_init(&iter, (MCPhysReg)Reg, RI->DiffLists + RI->Desc[Reg].SuperRegs);
95	DiffListIterator_next(&iter);
96
97	while(DiffListIterator_isValid(&iter)) {
98		uint16_t val = DiffListIterator_getVal(&iter);
99		if (MCRegisterClass_contains(RC, val) && Reg ==  MCRegisterInfo_getSubReg(RI, val, SubIdx))
100			return val;
101
102		DiffListIterator_next(&iter);
103	}
104
105	return 0;
106}
107
108unsigned MCRegisterInfo_getSubReg(MCRegisterInfo *RI, unsigned Reg, unsigned Idx)
109{
110	DiffListIterator iter;
111	uint16_t *SRI = RI->SubRegIndices + RI->Desc[Reg].SubRegIndices;
112
113	DiffListIterator_init(&iter, (MCPhysReg)Reg, RI->DiffLists + RI->Desc[Reg].SubRegs);
114	DiffListIterator_next(&iter);
115
116	while(DiffListIterator_isValid(&iter)) {
117		if (*SRI == Idx)
118			return DiffListIterator_getVal(&iter);
119		DiffListIterator_next(&iter);
120		++SRI;
121	}
122
123	return 0;
124}
125
126MCRegisterClass* MCRegisterInfo_getRegClass(MCRegisterInfo *RI, unsigned i)
127{
128	//assert(i < getNumRegClasses() && "Register Class ID out of range");
129	if (i >= RI->NumClasses)
130		return 0;
131	return &(RI->Classes[i]);
132}
133
134bool MCRegisterClass_contains(MCRegisterClass *c, unsigned Reg)
135{
136	unsigned InByte = Reg % 8;
137	unsigned Byte = Reg / 8;
138
139	if (Byte >= c->RegSetSize)
140		return false;
141
142	return (c->RegSet[Byte] & (1 << InByte)) != 0;
143}
144