1 /* Capstone Disassembly Engine */
2 /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */
3 
4 #ifdef CAPSTONE_HAS_XCORE
5 
6 #include <stdio.h>	// debug
7 #include <string.h>
8 
9 #include "../../utils.h"
10 
11 #include "XCoreMapping.h"
12 
13 #define GET_INSTRINFO_ENUM
14 #include "XCoreGenInstrInfo.inc"
15 
16 static const name_map reg_name_maps[] = {
17 	{ XCORE_REG_INVALID, NULL },
18 
19 	{ XCORE_REG_CP, "cp" },
20 	{ XCORE_REG_DP, "dp" },
21 	{ XCORE_REG_LR, "lr" },
22 	{ XCORE_REG_SP, "sp" },
23 	{ XCORE_REG_R0, "r0" },
24 	{ XCORE_REG_R1, "r1" },
25 	{ XCORE_REG_R2, "r2" },
26 	{ XCORE_REG_R3, "r3" },
27 	{ XCORE_REG_R4, "r4" },
28 	{ XCORE_REG_R5, "r5" },
29 	{ XCORE_REG_R6, "r6" },
30 	{ XCORE_REG_R7, "r7" },
31 	{ XCORE_REG_R8, "r8" },
32 	{ XCORE_REG_R9, "r9" },
33 	{ XCORE_REG_R10, "r10" },
34 	{ XCORE_REG_R11, "r11" },
35 
36 	// pseudo registers
37 	{ XCORE_REG_PC, "pc" },
38 
39 	{ XCORE_REG_SCP, "scp" },
40 	{ XCORE_REG_SSR, "ssr" },
41 	{ XCORE_REG_ET, "et" },
42 	{ XCORE_REG_ED, "ed" },
43 	{ XCORE_REG_SED, "sed" },
44 	{ XCORE_REG_KEP, "kep" },
45 	{ XCORE_REG_KSP, "ksp" },
46 	{ XCORE_REG_ID, "id" },
47 };
48 
XCore_reg_name(csh handle,unsigned int reg)49 const char *XCore_reg_name(csh handle, unsigned int reg)
50 {
51 #ifndef CAPSTONE_DIET
52 	if (reg >= ARR_SIZE(reg_name_maps))
53 		return NULL;
54 
55 	return reg_name_maps[reg].name;
56 #else
57 	return NULL;
58 #endif
59 }
60 
XCore_reg_id(char * name)61 xcore_reg XCore_reg_id(char *name)
62 {
63 	int i;
64 
65 	for(i = 1; i < ARR_SIZE(reg_name_maps); i++) {
66 		if (!strcmp(name, reg_name_maps[i].name))
67 			return reg_name_maps[i].id;
68 	}
69 
70 	// not found
71 	return 0;
72 }
73 
74 static const insn_map insns[] = {
75 	// dummy item
76 	{
77 		0, 0,
78 #ifndef CAPSTONE_DIET
79 		{ 0 }, { 0 }, { 0 }, 0, 0
80 #endif
81 	},
82 
83 #include "XCoreMappingInsn.inc"
84 };
85 
86 // given internal insn id, return public instruction info
XCore_get_insn_id(cs_struct * h,cs_insn * insn,unsigned int id)87 void XCore_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
88 {
89 	unsigned short i;
90 
91 	i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
92 	if (i != 0) {
93 		insn->id = insns[i].mapid;
94 
95 		if (h->detail) {
96 #ifndef CAPSTONE_DIET
97 			memcpy(insn->detail->regs_read, insns[i].regs_use, sizeof(insns[i].regs_use));
98 			insn->detail->regs_read_count = (uint8_t)count_positive(insns[i].regs_use);
99 
100 			memcpy(insn->detail->regs_write, insns[i].regs_mod, sizeof(insns[i].regs_mod));
101 			insn->detail->regs_write_count = (uint8_t)count_positive(insns[i].regs_mod);
102 
103 			memcpy(insn->detail->groups, insns[i].groups, sizeof(insns[i].groups));
104 			insn->detail->groups_count = (uint8_t)count_positive8(insns[i].groups);
105 
106 			if (insns[i].branch || insns[i].indirect_branch) {
107 				// this insn also belongs to JUMP group. add JUMP group
108 				insn->detail->groups[insn->detail->groups_count] = XCORE_GRP_JUMP;
109 				insn->detail->groups_count++;
110 			}
111 #endif
112 		}
113 	}
114 }
115 
116 #ifndef CAPSTONE_DIET
117 static const name_map insn_name_maps[] = {
118 	{ XCORE_INS_INVALID, NULL },
119 
120 	{ XCORE_INS_ADD, "add" },
121 	{ XCORE_INS_ANDNOT, "andnot" },
122 	{ XCORE_INS_AND, "and" },
123 	{ XCORE_INS_ASHR, "ashr" },
124 	{ XCORE_INS_BAU, "bau" },
125 	{ XCORE_INS_BITREV, "bitrev" },
126 	{ XCORE_INS_BLA, "bla" },
127 	{ XCORE_INS_BLAT, "blat" },
128 	{ XCORE_INS_BL, "bl" },
129 	{ XCORE_INS_BF, "bf" },
130 	{ XCORE_INS_BT, "bt" },
131 	{ XCORE_INS_BU, "bu" },
132 	{ XCORE_INS_BRU, "bru" },
133 	{ XCORE_INS_BYTEREV, "byterev" },
134 	{ XCORE_INS_CHKCT, "chkct" },
135 	{ XCORE_INS_CLRE, "clre" },
136 	{ XCORE_INS_CLRPT, "clrpt" },
137 	{ XCORE_INS_CLRSR, "clrsr" },
138 	{ XCORE_INS_CLZ, "clz" },
139 	{ XCORE_INS_CRC8, "crc8" },
140 	{ XCORE_INS_CRC32, "crc32" },
141 	{ XCORE_INS_DCALL, "dcall" },
142 	{ XCORE_INS_DENTSP, "dentsp" },
143 	{ XCORE_INS_DGETREG, "dgetreg" },
144 	{ XCORE_INS_DIVS, "divs" },
145 	{ XCORE_INS_DIVU, "divu" },
146 	{ XCORE_INS_DRESTSP, "drestsp" },
147 	{ XCORE_INS_DRET, "dret" },
148 	{ XCORE_INS_ECALLF, "ecallf" },
149 	{ XCORE_INS_ECALLT, "ecallt" },
150 	{ XCORE_INS_EDU, "edu" },
151 	{ XCORE_INS_EEF, "eef" },
152 	{ XCORE_INS_EET, "eet" },
153 	{ XCORE_INS_EEU, "eeu" },
154 	{ XCORE_INS_ENDIN, "endin" },
155 	{ XCORE_INS_ENTSP, "entsp" },
156 	{ XCORE_INS_EQ, "eq" },
157 	{ XCORE_INS_EXTDP, "extdp" },
158 	{ XCORE_INS_EXTSP, "extsp" },
159 	{ XCORE_INS_FREER, "freer" },
160 	{ XCORE_INS_FREET, "freet" },
161 	{ XCORE_INS_GETD, "getd" },
162 	{ XCORE_INS_GET, "get" },
163 	{ XCORE_INS_GETN, "getn" },
164 	{ XCORE_INS_GETR, "getr" },
165 	{ XCORE_INS_GETSR, "getsr" },
166 	{ XCORE_INS_GETST, "getst" },
167 	{ XCORE_INS_GETTS, "getts" },
168 	{ XCORE_INS_INCT, "inct" },
169 	{ XCORE_INS_INIT, "init" },
170 	{ XCORE_INS_INPW, "inpw" },
171 	{ XCORE_INS_INSHR, "inshr" },
172 	{ XCORE_INS_INT, "int" },
173 	{ XCORE_INS_IN, "in" },
174 	{ XCORE_INS_KCALL, "kcall" },
175 	{ XCORE_INS_KENTSP, "kentsp" },
176 	{ XCORE_INS_KRESTSP, "krestsp" },
177 	{ XCORE_INS_KRET, "kret" },
178 	{ XCORE_INS_LADD, "ladd" },
179 	{ XCORE_INS_LD16S, "ld16s" },
180 	{ XCORE_INS_LD8U, "ld8u" },
181 	{ XCORE_INS_LDA16, "lda16" },
182 	{ XCORE_INS_LDAP, "ldap" },
183 	{ XCORE_INS_LDAW, "ldaw" },
184 	{ XCORE_INS_LDC, "ldc" },
185 	{ XCORE_INS_LDW, "ldw" },
186 	{ XCORE_INS_LDIVU, "ldivu" },
187 	{ XCORE_INS_LMUL, "lmul" },
188 	{ XCORE_INS_LSS, "lss" },
189 	{ XCORE_INS_LSUB, "lsub" },
190 	{ XCORE_INS_LSU, "lsu" },
191 	{ XCORE_INS_MACCS, "maccs" },
192 	{ XCORE_INS_MACCU, "maccu" },
193 	{ XCORE_INS_MJOIN, "mjoin" },
194 	{ XCORE_INS_MKMSK, "mkmsk" },
195 	{ XCORE_INS_MSYNC, "msync" },
196 	{ XCORE_INS_MUL, "mul" },
197 	{ XCORE_INS_NEG, "neg" },
198 	{ XCORE_INS_NOT, "not" },
199 	{ XCORE_INS_OR, "or" },
200 	{ XCORE_INS_OUTCT, "outct" },
201 	{ XCORE_INS_OUTPW, "outpw" },
202 	{ XCORE_INS_OUTSHR, "outshr" },
203 	{ XCORE_INS_OUTT, "outt" },
204 	{ XCORE_INS_OUT, "out" },
205 	{ XCORE_INS_PEEK, "peek" },
206 	{ XCORE_INS_REMS, "rems" },
207 	{ XCORE_INS_REMU, "remu" },
208 	{ XCORE_INS_RETSP, "retsp" },
209 	{ XCORE_INS_SETCLK, "setclk" },
210 	{ XCORE_INS_SET, "set" },
211 	{ XCORE_INS_SETC, "setc" },
212 	{ XCORE_INS_SETD, "setd" },
213 	{ XCORE_INS_SETEV, "setev" },
214 	{ XCORE_INS_SETN, "setn" },
215 	{ XCORE_INS_SETPSC, "setpsc" },
216 	{ XCORE_INS_SETPT, "setpt" },
217 	{ XCORE_INS_SETRDY, "setrdy" },
218 	{ XCORE_INS_SETSR, "setsr" },
219 	{ XCORE_INS_SETTW, "settw" },
220 	{ XCORE_INS_SETV, "setv" },
221 	{ XCORE_INS_SEXT, "sext" },
222 	{ XCORE_INS_SHL, "shl" },
223 	{ XCORE_INS_SHR, "shr" },
224 	{ XCORE_INS_SSYNC, "ssync" },
225 	{ XCORE_INS_ST16, "st16" },
226 	{ XCORE_INS_ST8, "st8" },
227 	{ XCORE_INS_STW, "stw" },
228 	{ XCORE_INS_SUB, "sub" },
229 	{ XCORE_INS_SYNCR, "syncr" },
230 	{ XCORE_INS_TESTCT, "testct" },
231 	{ XCORE_INS_TESTLCL, "testlcl" },
232 	{ XCORE_INS_TESTWCT, "testwct" },
233 	{ XCORE_INS_TSETMR, "tsetmr" },
234 	{ XCORE_INS_START, "start" },
235 	{ XCORE_INS_WAITEF, "waitef" },
236 	{ XCORE_INS_WAITET, "waitet" },
237 	{ XCORE_INS_WAITEU, "waiteu" },
238 	{ XCORE_INS_XOR, "xor" },
239 	{ XCORE_INS_ZEXT, "zext" },
240 };
241 
242 // special alias insn
243 static const name_map alias_insn_names[] = {
244 	{ 0, NULL }
245 };
246 #endif
247 
XCore_insn_name(csh handle,unsigned int id)248 const char *XCore_insn_name(csh handle, unsigned int id)
249 {
250 #ifndef CAPSTONE_DIET
251 	unsigned int i;
252 
253 	if (id >= XCORE_INS_ENDING)
254 		return NULL;
255 
256 	// handle special alias first
257 	for (i = 0; i < ARR_SIZE(alias_insn_names); i++) {
258 		if (alias_insn_names[i].id == id)
259 			return alias_insn_names[i].name;
260 	}
261 
262 	return insn_name_maps[id].name;
263 #else
264 	return NULL;
265 #endif
266 }
267 
268 #ifndef CAPSTONE_DIET
269 static const name_map group_name_maps[] = {
270 	{ XCORE_GRP_INVALID, NULL },
271 	{ XCORE_GRP_JUMP, "jump" },
272 };
273 #endif
274 
XCore_group_name(csh handle,unsigned int id)275 const char *XCore_group_name(csh handle, unsigned int id)
276 {
277 #ifndef CAPSTONE_DIET
278 	return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
279 #else
280 	return NULL;
281 #endif
282 }
283 
284 // map internal raw register to 'public' register
XCore_map_register(unsigned int r)285 xcore_reg XCore_map_register(unsigned int r)
286 {
287 	static const unsigned int map[] = { 0,
288 	};
289 
290 	if (r < ARR_SIZE(map))
291 		return map[r];
292 
293 	// cannot find this register
294 	return 0;
295 }
296 
297 #endif
298