1 /* Capstone Disassembly Engine */
2 /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */
3 
4 #ifdef CAPSTONE_HAS_SPARC
5 
6 #include <stdio.h>	// debug
7 #include <string.h>
8 
9 #include "../../utils.h"
10 
11 #include "SparcMapping.h"
12 
13 #define GET_INSTRINFO_ENUM
14 #include "SparcGenInstrInfo.inc"
15 
16 #ifndef CAPSTONE_DIET
17 static const name_map reg_name_maps[] = {
18 	{ SPARC_REG_INVALID, NULL },
19 
20 	{ SPARC_REG_F0, "f0"},
21 	{ SPARC_REG_F1, "f1"},
22 	{ SPARC_REG_F2, "f2"},
23 	{ SPARC_REG_F3, "f3"},
24 	{ SPARC_REG_F4, "f4"},
25 	{ SPARC_REG_F5, "f5"},
26 	{ SPARC_REG_F6, "f6"},
27 	{ SPARC_REG_F7, "f7"},
28 	{ SPARC_REG_F8, "f8"},
29 	{ SPARC_REG_F9, "f9"},
30 	{ SPARC_REG_F10, "f10"},
31 	{ SPARC_REG_F11, "f11"},
32 	{ SPARC_REG_F12, "f12"},
33 	{ SPARC_REG_F13, "f13"},
34 	{ SPARC_REG_F14, "f14"},
35 	{ SPARC_REG_F15, "f15"},
36 	{ SPARC_REG_F16, "f16"},
37 	{ SPARC_REG_F17, "f17"},
38 	{ SPARC_REG_F18, "f18"},
39 	{ SPARC_REG_F19, "f19"},
40 	{ SPARC_REG_F20, "f20"},
41 	{ SPARC_REG_F21, "f21"},
42 	{ SPARC_REG_F22, "f22"},
43 	{ SPARC_REG_F23, "f23"},
44 	{ SPARC_REG_F24, "f24"},
45 	{ SPARC_REG_F25, "f25"},
46 	{ SPARC_REG_F26, "f26"},
47 	{ SPARC_REG_F27, "f27"},
48 	{ SPARC_REG_F28, "f28"},
49 	{ SPARC_REG_F29, "f29"},
50 	{ SPARC_REG_F30, "f30"},
51 	{ SPARC_REG_F31, "f31"},
52 	{ SPARC_REG_F32, "f32"},
53 	{ SPARC_REG_F34, "f34"},
54 	{ SPARC_REG_F36, "f36"},
55 	{ SPARC_REG_F38, "f38"},
56 	{ SPARC_REG_F40, "f40"},
57 	{ SPARC_REG_F42, "f42"},
58 	{ SPARC_REG_F44, "f44"},
59 	{ SPARC_REG_F46, "f46"},
60 	{ SPARC_REG_F48, "f48"},
61 	{ SPARC_REG_F50, "f50"},
62 	{ SPARC_REG_F52, "f52"},
63 	{ SPARC_REG_F54, "f54"},
64 	{ SPARC_REG_F56, "f56"},
65 	{ SPARC_REG_F58, "f58"},
66 	{ SPARC_REG_F60, "f60"},
67 	{ SPARC_REG_F62, "f62"},
68 	{ SPARC_REG_FCC0, "fcc0"},
69 	{ SPARC_REG_FCC1, "fcc1"},
70 	{ SPARC_REG_FCC2, "fcc2"},
71 	{ SPARC_REG_FCC3, "fcc3"},
72 	{ SPARC_REG_FP, "fp"},
73 	{ SPARC_REG_G0, "g0"},
74 	{ SPARC_REG_G1, "g1"},
75 	{ SPARC_REG_G2, "g2"},
76 	{ SPARC_REG_G3, "g3"},
77 	{ SPARC_REG_G4, "g4"},
78 	{ SPARC_REG_G5, "g5"},
79 	{ SPARC_REG_G6, "g6"},
80 	{ SPARC_REG_G7, "g7"},
81 	{ SPARC_REG_I0, "i0"},
82 	{ SPARC_REG_I1, "i1"},
83 	{ SPARC_REG_I2, "i2"},
84 	{ SPARC_REG_I3, "i3"},
85 	{ SPARC_REG_I4, "i4"},
86 	{ SPARC_REG_I5, "i5"},
87 	{ SPARC_REG_I7, "i7"},
88 	{ SPARC_REG_ICC, "icc"},
89 	{ SPARC_REG_L0, "l0"},
90 	{ SPARC_REG_L1, "l1"},
91 	{ SPARC_REG_L2, "l2"},
92 	{ SPARC_REG_L3, "l3"},
93 	{ SPARC_REG_L4, "l4"},
94 	{ SPARC_REG_L5, "l5"},
95 	{ SPARC_REG_L6, "l6"},
96 	{ SPARC_REG_L7, "l7"},
97 	{ SPARC_REG_O0, "o0"},
98 	{ SPARC_REG_O1, "o1"},
99 	{ SPARC_REG_O2, "o2"},
100 	{ SPARC_REG_O3, "o3"},
101 	{ SPARC_REG_O4, "o4"},
102 	{ SPARC_REG_O5, "o5"},
103 	{ SPARC_REG_O7, "o7"},
104 	{ SPARC_REG_SP, "sp"},
105 	{ SPARC_REG_Y, "y"},
106 
107 	// special registers
108 	{ SPARC_REG_XCC, "xcc"},
109 };
110 #endif
111 
Sparc_reg_name(csh handle,unsigned int reg)112 const char *Sparc_reg_name(csh handle, unsigned int reg)
113 {
114 #ifndef CAPSTONE_DIET
115 	if (reg >= ARR_SIZE(reg_name_maps))
116 		return NULL;
117 
118 	return reg_name_maps[reg].name;
119 #else
120 	return NULL;
121 #endif
122 }
123 
124 static const insn_map insns[] = {
125 	// dummy item
126 	{
127 		0, 0,
128 #ifndef CAPSTONE_DIET
129 		{ 0 }, { 0 }, { 0 }, 0, 0
130 #endif
131 	},
132 
133 #include "SparcMappingInsn.inc"
134 };
135 
136 static struct hint_map {
137 	unsigned int id;
138 	uint8_t hints;
139 } const insn_hints[] = {
140 	{ SP_BPGEZapn, SPARC_HINT_A | SPARC_HINT_PN },
141 	{ SP_BPGEZapt, SPARC_HINT_A | SPARC_HINT_PT },
142 	{ SP_BPGEZnapn, SPARC_HINT_PN },
143 	{ SP_BPGZapn, SPARC_HINT_A | SPARC_HINT_PN },
144 	{ SP_BPGZapt, SPARC_HINT_A | SPARC_HINT_PT },
145 	{ SP_BPGZnapn, SPARC_HINT_PN },
146 	{ SP_BPLEZapn, SPARC_HINT_A | SPARC_HINT_PN },
147 	{ SP_BPLEZapt, SPARC_HINT_A | SPARC_HINT_PT },
148 	{ SP_BPLEZnapn, SPARC_HINT_PN },
149 	{ SP_BPLZapn, SPARC_HINT_A | SPARC_HINT_PN },
150 	{ SP_BPLZapt, SPARC_HINT_A | SPARC_HINT_PT },
151 	{ SP_BPLZnapn, SPARC_HINT_PN },
152 	{ SP_BPNZapn, SPARC_HINT_A | SPARC_HINT_PN },
153 	{ SP_BPNZapt, SPARC_HINT_A | SPARC_HINT_PT },
154 	{ SP_BPNZnapn, SPARC_HINT_PN },
155 	{ SP_BPZapn, SPARC_HINT_A | SPARC_HINT_PN },
156 	{ SP_BPZapt, SPARC_HINT_A | SPARC_HINT_PT },
157 	{ SP_BPZnapn, SPARC_HINT_PN },
158 };
159 
160 // given internal insn id, return public instruction info
Sparc_get_insn_id(cs_struct * h,cs_insn * insn,unsigned int id)161 void Sparc_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
162 {
163 	unsigned short i;
164 
165 	i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
166 	if (i != 0) {
167 		insn->id = insns[i].mapid;
168 
169 		if (h->detail) {
170 #ifndef CAPSTONE_DIET
171 			memcpy(insn->detail->regs_read, insns[i].regs_use, sizeof(insns[i].regs_use));
172 			insn->detail->regs_read_count = (uint8_t)count_positive(insns[i].regs_use);
173 
174 			memcpy(insn->detail->regs_write, insns[i].regs_mod, sizeof(insns[i].regs_mod));
175 			insn->detail->regs_write_count = (uint8_t)count_positive(insns[i].regs_mod);
176 
177 			memcpy(insn->detail->groups, insns[i].groups, sizeof(insns[i].groups));
178 			insn->detail->groups_count = (uint8_t)count_positive8(insns[i].groups);
179 
180 			if (insns[i].branch || insns[i].indirect_branch) {
181 				// this insn also belongs to JUMP group. add JUMP group
182 				insn->detail->groups[insn->detail->groups_count] = SPARC_GRP_JUMP;
183 				insn->detail->groups_count++;
184 			}
185 #endif
186 			// hint code
187 			for (i = 0; i < ARR_SIZE(insn_hints); i++) {
188 				if (id == insn_hints[i].id) {
189 					insn->detail->sparc.hint = insn_hints[i].hints;
190 					break;
191 				}
192 			}
193 		}
194 	}
195 }
196 
197 static const name_map insn_name_maps[] = {
198 	{ SPARC_INS_INVALID, NULL },
199 
200 	{ SPARC_INS_ADDCC, "addcc" },
201 	{ SPARC_INS_ADDX, "addx" },
202 	{ SPARC_INS_ADDXCC, "addxcc" },
203 	{ SPARC_INS_ADDXC, "addxc" },
204 	{ SPARC_INS_ADDXCCC, "addxccc" },
205 	{ SPARC_INS_ADD, "add" },
206 	{ SPARC_INS_ALIGNADDR, "alignaddr" },
207 	{ SPARC_INS_ALIGNADDRL, "alignaddrl" },
208 	{ SPARC_INS_ANDCC, "andcc" },
209 	{ SPARC_INS_ANDNCC, "andncc" },
210 	{ SPARC_INS_ANDN, "andn" },
211 	{ SPARC_INS_AND, "and" },
212 	{ SPARC_INS_ARRAY16, "array16" },
213 	{ SPARC_INS_ARRAY32, "array32" },
214 	{ SPARC_INS_ARRAY8, "array8" },
215 	{ SPARC_INS_B, "b" },
216 	{ SPARC_INS_JMP, "jmp" },
217 	{ SPARC_INS_BMASK, "bmask" },
218 	{ SPARC_INS_FB, "fb" },
219 	{ SPARC_INS_BRGEZ, "brgez" },
220 	{ SPARC_INS_BRGZ, "brgz" },
221 	{ SPARC_INS_BRLEZ, "brlez" },
222 	{ SPARC_INS_BRLZ, "brlz" },
223 	{ SPARC_INS_BRNZ, "brnz" },
224 	{ SPARC_INS_BRZ, "brz" },
225 	{ SPARC_INS_BSHUFFLE, "bshuffle" },
226 	{ SPARC_INS_CALL, "call" },
227 	{ SPARC_INS_CASX, "casx" },
228 	{ SPARC_INS_CAS, "cas" },
229 	{ SPARC_INS_CMASK16, "cmask16" },
230 	{ SPARC_INS_CMASK32, "cmask32" },
231 	{ SPARC_INS_CMASK8, "cmask8" },
232 	{ SPARC_INS_CMP, "cmp" },
233 	{ SPARC_INS_EDGE16, "edge16" },
234 	{ SPARC_INS_EDGE16L, "edge16l" },
235 	{ SPARC_INS_EDGE16LN, "edge16ln" },
236 	{ SPARC_INS_EDGE16N, "edge16n" },
237 	{ SPARC_INS_EDGE32, "edge32" },
238 	{ SPARC_INS_EDGE32L, "edge32l" },
239 	{ SPARC_INS_EDGE32LN, "edge32ln" },
240 	{ SPARC_INS_EDGE32N, "edge32n" },
241 	{ SPARC_INS_EDGE8, "edge8" },
242 	{ SPARC_INS_EDGE8L, "edge8l" },
243 	{ SPARC_INS_EDGE8LN, "edge8ln" },
244 	{ SPARC_INS_EDGE8N, "edge8n" },
245 	{ SPARC_INS_FABSD, "fabsd" },
246 	{ SPARC_INS_FABSQ, "fabsq" },
247 	{ SPARC_INS_FABSS, "fabss" },
248 	{ SPARC_INS_FADDD, "faddd" },
249 	{ SPARC_INS_FADDQ, "faddq" },
250 	{ SPARC_INS_FADDS, "fadds" },
251 	{ SPARC_INS_FALIGNDATA, "faligndata" },
252 	{ SPARC_INS_FAND, "fand" },
253 	{ SPARC_INS_FANDNOT1, "fandnot1" },
254 	{ SPARC_INS_FANDNOT1S, "fandnot1s" },
255 	{ SPARC_INS_FANDNOT2, "fandnot2" },
256 	{ SPARC_INS_FANDNOT2S, "fandnot2s" },
257 	{ SPARC_INS_FANDS, "fands" },
258 	{ SPARC_INS_FCHKSM16, "fchksm16" },
259 	{ SPARC_INS_FCMPD, "fcmpd" },
260 	{ SPARC_INS_FCMPEQ16, "fcmpeq16" },
261 	{ SPARC_INS_FCMPEQ32, "fcmpeq32" },
262 	{ SPARC_INS_FCMPGT16, "fcmpgt16" },
263 	{ SPARC_INS_FCMPGT32, "fcmpgt32" },
264 	{ SPARC_INS_FCMPLE16, "fcmple16" },
265 	{ SPARC_INS_FCMPLE32, "fcmple32" },
266 	{ SPARC_INS_FCMPNE16, "fcmpne16" },
267 	{ SPARC_INS_FCMPNE32, "fcmpne32" },
268 	{ SPARC_INS_FCMPQ, "fcmpq" },
269 	{ SPARC_INS_FCMPS, "fcmps" },
270 	{ SPARC_INS_FDIVD, "fdivd" },
271 	{ SPARC_INS_FDIVQ, "fdivq" },
272 	{ SPARC_INS_FDIVS, "fdivs" },
273 	{ SPARC_INS_FDMULQ, "fdmulq" },
274 	{ SPARC_INS_FDTOI, "fdtoi" },
275 	{ SPARC_INS_FDTOQ, "fdtoq" },
276 	{ SPARC_INS_FDTOS, "fdtos" },
277 	{ SPARC_INS_FDTOX, "fdtox" },
278 	{ SPARC_INS_FEXPAND, "fexpand" },
279 	{ SPARC_INS_FHADDD, "fhaddd" },
280 	{ SPARC_INS_FHADDS, "fhadds" },
281 	{ SPARC_INS_FHSUBD, "fhsubd" },
282 	{ SPARC_INS_FHSUBS, "fhsubs" },
283 	{ SPARC_INS_FITOD, "fitod" },
284 	{ SPARC_INS_FITOQ, "fitoq" },
285 	{ SPARC_INS_FITOS, "fitos" },
286 	{ SPARC_INS_FLCMPD, "flcmpd" },
287 	{ SPARC_INS_FLCMPS, "flcmps" },
288 	{ SPARC_INS_FLUSHW, "flushw" },
289 	{ SPARC_INS_FMEAN16, "fmean16" },
290 	{ SPARC_INS_FMOVD, "fmovd" },
291 	{ SPARC_INS_FMOVQ, "fmovq" },
292 	{ SPARC_INS_FMOVRDGEZ, "fmovrdgez" },
293 	{ SPARC_INS_FMOVRQGEZ, "fmovrqgez" },
294 	{ SPARC_INS_FMOVRSGEZ, "fmovrsgez" },
295 	{ SPARC_INS_FMOVRDGZ, "fmovrdgz" },
296 	{ SPARC_INS_FMOVRQGZ, "fmovrqgz" },
297 	{ SPARC_INS_FMOVRSGZ, "fmovrsgz" },
298 	{ SPARC_INS_FMOVRDLEZ, "fmovrdlez" },
299 	{ SPARC_INS_FMOVRQLEZ, "fmovrqlez" },
300 	{ SPARC_INS_FMOVRSLEZ, "fmovrslez" },
301 	{ SPARC_INS_FMOVRDLZ, "fmovrdlz" },
302 	{ SPARC_INS_FMOVRQLZ, "fmovrqlz" },
303 	{ SPARC_INS_FMOVRSLZ, "fmovrslz" },
304 	{ SPARC_INS_FMOVRDNZ, "fmovrdnz" },
305 	{ SPARC_INS_FMOVRQNZ, "fmovrqnz" },
306 	{ SPARC_INS_FMOVRSNZ, "fmovrsnz" },
307 	{ SPARC_INS_FMOVRDZ, "fmovrdz" },
308 	{ SPARC_INS_FMOVRQZ, "fmovrqz" },
309 	{ SPARC_INS_FMOVRSZ, "fmovrsz" },
310 	{ SPARC_INS_FMOVS, "fmovs" },
311 	{ SPARC_INS_FMUL8SUX16, "fmul8sux16" },
312 	{ SPARC_INS_FMUL8ULX16, "fmul8ulx16" },
313 	{ SPARC_INS_FMUL8X16, "fmul8x16" },
314 	{ SPARC_INS_FMUL8X16AL, "fmul8x16al" },
315 	{ SPARC_INS_FMUL8X16AU, "fmul8x16au" },
316 	{ SPARC_INS_FMULD, "fmuld" },
317 	{ SPARC_INS_FMULD8SUX16, "fmuld8sux16" },
318 	{ SPARC_INS_FMULD8ULX16, "fmuld8ulx16" },
319 	{ SPARC_INS_FMULQ, "fmulq" },
320 	{ SPARC_INS_FMULS, "fmuls" },
321 	{ SPARC_INS_FNADDD, "fnaddd" },
322 	{ SPARC_INS_FNADDS, "fnadds" },
323 	{ SPARC_INS_FNAND, "fnand" },
324 	{ SPARC_INS_FNANDS, "fnands" },
325 	{ SPARC_INS_FNEGD, "fnegd" },
326 	{ SPARC_INS_FNEGQ, "fnegq" },
327 	{ SPARC_INS_FNEGS, "fnegs" },
328 	{ SPARC_INS_FNHADDD, "fnhaddd" },
329 	{ SPARC_INS_FNHADDS, "fnhadds" },
330 	{ SPARC_INS_FNOR, "fnor" },
331 	{ SPARC_INS_FNORS, "fnors" },
332 	{ SPARC_INS_FNOT1, "fnot1" },
333 	{ SPARC_INS_FNOT1S, "fnot1s" },
334 	{ SPARC_INS_FNOT2, "fnot2" },
335 	{ SPARC_INS_FNOT2S, "fnot2s" },
336 	{ SPARC_INS_FONE, "fone" },
337 	{ SPARC_INS_FONES, "fones" },
338 	{ SPARC_INS_FOR, "for" },
339 	{ SPARC_INS_FORNOT1, "fornot1" },
340 	{ SPARC_INS_FORNOT1S, "fornot1s" },
341 	{ SPARC_INS_FORNOT2, "fornot2" },
342 	{ SPARC_INS_FORNOT2S, "fornot2s" },
343 	{ SPARC_INS_FORS, "fors" },
344 	{ SPARC_INS_FPACK16, "fpack16" },
345 	{ SPARC_INS_FPACK32, "fpack32" },
346 	{ SPARC_INS_FPACKFIX, "fpackfix" },
347 	{ SPARC_INS_FPADD16, "fpadd16" },
348 	{ SPARC_INS_FPADD16S, "fpadd16s" },
349 	{ SPARC_INS_FPADD32, "fpadd32" },
350 	{ SPARC_INS_FPADD32S, "fpadd32s" },
351 	{ SPARC_INS_FPADD64, "fpadd64" },
352 	{ SPARC_INS_FPMERGE, "fpmerge" },
353 	{ SPARC_INS_FPSUB16, "fpsub16" },
354 	{ SPARC_INS_FPSUB16S, "fpsub16s" },
355 	{ SPARC_INS_FPSUB32, "fpsub32" },
356 	{ SPARC_INS_FPSUB32S, "fpsub32s" },
357 	{ SPARC_INS_FQTOD, "fqtod" },
358 	{ SPARC_INS_FQTOI, "fqtoi" },
359 	{ SPARC_INS_FQTOS, "fqtos" },
360 	{ SPARC_INS_FQTOX, "fqtox" },
361 	{ SPARC_INS_FSLAS16, "fslas16" },
362 	{ SPARC_INS_FSLAS32, "fslas32" },
363 	{ SPARC_INS_FSLL16, "fsll16" },
364 	{ SPARC_INS_FSLL32, "fsll32" },
365 	{ SPARC_INS_FSMULD, "fsmuld" },
366 	{ SPARC_INS_FSQRTD, "fsqrtd" },
367 	{ SPARC_INS_FSQRTQ, "fsqrtq" },
368 	{ SPARC_INS_FSQRTS, "fsqrts" },
369 	{ SPARC_INS_FSRA16, "fsra16" },
370 	{ SPARC_INS_FSRA32, "fsra32" },
371 	{ SPARC_INS_FSRC1, "fsrc1" },
372 	{ SPARC_INS_FSRC1S, "fsrc1s" },
373 	{ SPARC_INS_FSRC2, "fsrc2" },
374 	{ SPARC_INS_FSRC2S, "fsrc2s" },
375 	{ SPARC_INS_FSRL16, "fsrl16" },
376 	{ SPARC_INS_FSRL32, "fsrl32" },
377 	{ SPARC_INS_FSTOD, "fstod" },
378 	{ SPARC_INS_FSTOI, "fstoi" },
379 	{ SPARC_INS_FSTOQ, "fstoq" },
380 	{ SPARC_INS_FSTOX, "fstox" },
381 	{ SPARC_INS_FSUBD, "fsubd" },
382 	{ SPARC_INS_FSUBQ, "fsubq" },
383 	{ SPARC_INS_FSUBS, "fsubs" },
384 	{ SPARC_INS_FXNOR, "fxnor" },
385 	{ SPARC_INS_FXNORS, "fxnors" },
386 	{ SPARC_INS_FXOR, "fxor" },
387 	{ SPARC_INS_FXORS, "fxors" },
388 	{ SPARC_INS_FXTOD, "fxtod" },
389 	{ SPARC_INS_FXTOQ, "fxtoq" },
390 	{ SPARC_INS_FXTOS, "fxtos" },
391 	{ SPARC_INS_FZERO, "fzero" },
392 	{ SPARC_INS_FZEROS, "fzeros" },
393 	{ SPARC_INS_JMPL, "jmpl" },
394 	{ SPARC_INS_LDD, "ldd" },
395 	{ SPARC_INS_LD, "ld" },
396 	{ SPARC_INS_LDQ, "ldq" },
397 	{ SPARC_INS_LDSB, "ldsb" },
398 	{ SPARC_INS_LDSH, "ldsh" },
399 	{ SPARC_INS_LDSW, "ldsw" },
400 	{ SPARC_INS_LDUB, "ldub" },
401 	{ SPARC_INS_LDUH, "lduh" },
402 	{ SPARC_INS_LDX, "ldx" },
403 	{ SPARC_INS_LZCNT, "lzcnt" },
404 	{ SPARC_INS_MEMBAR, "membar" },
405 	{ SPARC_INS_MOVDTOX, "movdtox" },
406 	{ SPARC_INS_MOV, "mov" },
407 	{ SPARC_INS_MOVRGEZ, "movrgez" },
408 	{ SPARC_INS_MOVRGZ, "movrgz" },
409 	{ SPARC_INS_MOVRLEZ, "movrlez" },
410 	{ SPARC_INS_MOVRLZ, "movrlz" },
411 	{ SPARC_INS_MOVRNZ, "movrnz" },
412 	{ SPARC_INS_MOVRZ, "movrz" },
413 	{ SPARC_INS_MOVSTOSW, "movstosw" },
414 	{ SPARC_INS_MOVSTOUW, "movstouw" },
415 	{ SPARC_INS_MULX, "mulx" },
416 	{ SPARC_INS_NOP, "nop" },
417 	{ SPARC_INS_ORCC, "orcc" },
418 	{ SPARC_INS_ORNCC, "orncc" },
419 	{ SPARC_INS_ORN, "orn" },
420 	{ SPARC_INS_OR, "or" },
421 	{ SPARC_INS_PDIST, "pdist" },
422 	{ SPARC_INS_PDISTN, "pdistn" },
423 	{ SPARC_INS_POPC, "popc" },
424 	{ SPARC_INS_RD, "rd" },
425 	{ SPARC_INS_RESTORE, "restore" },
426 	{ SPARC_INS_RETT, "rett" },
427 	{ SPARC_INS_SAVE, "save" },
428 	{ SPARC_INS_SDIVCC, "sdivcc" },
429 	{ SPARC_INS_SDIVX, "sdivx" },
430 	{ SPARC_INS_SDIV, "sdiv" },
431 	{ SPARC_INS_SETHI, "sethi" },
432 	{ SPARC_INS_SHUTDOWN, "shutdown" },
433 	{ SPARC_INS_SIAM, "siam" },
434 	{ SPARC_INS_SLLX, "sllx" },
435 	{ SPARC_INS_SLL, "sll" },
436 	{ SPARC_INS_SMULCC, "smulcc" },
437 	{ SPARC_INS_SMUL, "smul" },
438 	{ SPARC_INS_SRAX, "srax" },
439 	{ SPARC_INS_SRA, "sra" },
440 	{ SPARC_INS_SRLX, "srlx" },
441 	{ SPARC_INS_SRL, "srl" },
442 	{ SPARC_INS_STBAR, "stbar" },
443 	{ SPARC_INS_STB, "stb" },
444 	{ SPARC_INS_STD, "std" },
445 	{ SPARC_INS_ST, "st" },
446 	{ SPARC_INS_STH, "sth" },
447 	{ SPARC_INS_STQ, "stq" },
448 	{ SPARC_INS_STX, "stx" },
449 	{ SPARC_INS_SUBCC, "subcc" },
450 	{ SPARC_INS_SUBX, "subx" },
451 	{ SPARC_INS_SUBXCC, "subxcc" },
452 	{ SPARC_INS_SUB, "sub" },
453 	{ SPARC_INS_SWAP, "swap" },
454 	{ SPARC_INS_TADDCCTV, "taddcctv" },
455 	{ SPARC_INS_TADDCC, "taddcc" },
456 	{ SPARC_INS_T, "t" },
457 	{ SPARC_INS_TSUBCCTV, "tsubcctv" },
458 	{ SPARC_INS_TSUBCC, "tsubcc" },
459 	{ SPARC_INS_UDIVCC, "udivcc" },
460 	{ SPARC_INS_UDIVX, "udivx" },
461 	{ SPARC_INS_UDIV, "udiv" },
462 	{ SPARC_INS_UMULCC, "umulcc" },
463 	{ SPARC_INS_UMULXHI, "umulxhi" },
464 	{ SPARC_INS_UMUL, "umul" },
465 	{ SPARC_INS_UNIMP, "unimp" },
466 	{ SPARC_INS_FCMPED, "fcmped" },
467 	{ SPARC_INS_FCMPEQ, "fcmpeq" },
468 	{ SPARC_INS_FCMPES, "fcmpes" },
469 	{ SPARC_INS_WR, "wr" },
470 	{ SPARC_INS_XMULX, "xmulx" },
471 	{ SPARC_INS_XMULXHI, "xmulxhi" },
472 	{ SPARC_INS_XNORCC, "xnorcc" },
473 	{ SPARC_INS_XNOR, "xnor" },
474 	{ SPARC_INS_XORCC, "xorcc" },
475 	{ SPARC_INS_XOR, "xor" },
476 
477 	// alias instructions
478 	{ SPARC_INS_RET, "ret" },
479 	{ SPARC_INS_RETL, "retl" },
480 };
481 
482 #ifndef CAPSTONE_DIET
483 // special alias insn
484 static const name_map alias_insn_names[] = {
485 	{ 0, NULL }
486 };
487 #endif
488 
Sparc_insn_name(csh handle,unsigned int id)489 const char *Sparc_insn_name(csh handle, unsigned int id)
490 {
491 #ifndef CAPSTONE_DIET
492 	unsigned int i;
493 
494 	if (id >= SPARC_INS_ENDING)
495 		return NULL;
496 
497 	// handle special alias first
498 	for (i = 0; i < ARR_SIZE(alias_insn_names); i++) {
499 		if (alias_insn_names[i].id == id)
500 			return alias_insn_names[i].name;
501 	}
502 
503 	return insn_name_maps[id].name;
504 #else
505 	return NULL;
506 #endif
507 }
508 
509 #ifndef CAPSTONE_DIET
510 static const name_map group_name_maps[] = {
511 	// generic groups
512 	{ SPARC_GRP_INVALID, NULL },
513 	{ SPARC_GRP_JUMP, "jump" },
514 
515 	// architecture-specific groups
516 	{ SPARC_GRP_HARDQUAD, "hardquad" },
517 	{ SPARC_GRP_V9, "v9" },
518 	{ SPARC_GRP_VIS, "vis" },
519 	{ SPARC_GRP_VIS2, "vis2" },
520 	{ SPARC_GRP_VIS3,  "vis3" },
521 	{ SPARC_GRP_32BIT, "32bit" },
522 	{ SPARC_GRP_64BIT, "64bit" },
523 };
524 #endif
525 
Sparc_group_name(csh handle,unsigned int id)526 const char *Sparc_group_name(csh handle, unsigned int id)
527 {
528 #ifndef CAPSTONE_DIET
529 	return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
530 #else
531 	return NULL;
532 #endif
533 }
534 
535 // map internal raw register to 'public' register
Sparc_map_register(unsigned int r)536 sparc_reg Sparc_map_register(unsigned int r)
537 {
538 	static const unsigned int map[] = { 0,
539 		SPARC_REG_ICC, SPARC_REG_Y, SPARC_REG_F0, SPARC_REG_F2, SPARC_REG_F4,
540 		SPARC_REG_F6, SPARC_REG_F8, SPARC_REG_F10, SPARC_REG_F12, SPARC_REG_F14,
541 		SPARC_REG_F16, SPARC_REG_F18, SPARC_REG_F20, SPARC_REG_F22, SPARC_REG_F24,
542 		SPARC_REG_F26, SPARC_REG_F28, SPARC_REG_F30, SPARC_REG_F32, SPARC_REG_F34,
543 		SPARC_REG_F36, SPARC_REG_F38, SPARC_REG_F40, SPARC_REG_F42, SPARC_REG_F44,
544 		SPARC_REG_F46, SPARC_REG_F48, SPARC_REG_F50, SPARC_REG_F52, SPARC_REG_F54,
545 		SPARC_REG_F56, SPARC_REG_F58, SPARC_REG_F60, SPARC_REG_F62, SPARC_REG_F0,
546 		SPARC_REG_F1, SPARC_REG_F2, SPARC_REG_F3, SPARC_REG_F4, SPARC_REG_F5,
547 		SPARC_REG_F6, SPARC_REG_F7, SPARC_REG_F8, SPARC_REG_F9, SPARC_REG_F10,
548 		SPARC_REG_F11, SPARC_REG_F12, SPARC_REG_F13, SPARC_REG_F14, SPARC_REG_F15,
549 		SPARC_REG_F16, SPARC_REG_F17, SPARC_REG_F18, SPARC_REG_F19, SPARC_REG_F20,
550 		SPARC_REG_F21, SPARC_REG_F22, SPARC_REG_F23, SPARC_REG_F24, SPARC_REG_F25,
551 		SPARC_REG_F26, SPARC_REG_F27, SPARC_REG_F28, SPARC_REG_F29, SPARC_REG_F30,
552 		SPARC_REG_F31, SPARC_REG_FCC0, SPARC_REG_FCC1, SPARC_REG_FCC2, SPARC_REG_FCC3,
553 		SPARC_REG_G0, SPARC_REG_G1, SPARC_REG_G2, SPARC_REG_G3, SPARC_REG_G4,
554 		SPARC_REG_G5, SPARC_REG_G6, SPARC_REG_G7, SPARC_REG_I0, SPARC_REG_I1,
555 		SPARC_REG_I2, SPARC_REG_I3, SPARC_REG_I4, SPARC_REG_I5, SPARC_REG_FP,
556 		SPARC_REG_I7, SPARC_REG_L0, SPARC_REG_L1, SPARC_REG_L2, SPARC_REG_L3,
557 		SPARC_REG_L4, SPARC_REG_L5, SPARC_REG_L6, SPARC_REG_L7, SPARC_REG_O0,
558 		SPARC_REG_O1, SPARC_REG_O2, SPARC_REG_O3, SPARC_REG_O4, SPARC_REG_O5,
559 		SPARC_REG_SP, SPARC_REG_O7, SPARC_REG_F0, SPARC_REG_F4, SPARC_REG_F8,
560 		SPARC_REG_F12, SPARC_REG_F16, SPARC_REG_F20, SPARC_REG_F24, SPARC_REG_F28,
561 		SPARC_REG_F32, SPARC_REG_F36, SPARC_REG_F40, SPARC_REG_F44, SPARC_REG_F48,
562 		SPARC_REG_F52, SPARC_REG_F56, SPARC_REG_F60,
563 	};
564 
565 	if (r < ARR_SIZE(map))
566 		return map[r];
567 
568 	// cannot find this register
569 	return 0;
570 }
571 
572 // map instruction name to instruction ID (public)
Sparc_map_insn(const char * name)573 sparc_reg Sparc_map_insn(const char *name)
574 {
575 	unsigned int i;
576 
577 	// NOTE: skip first NULL name in insn_name_maps
578 	i = name2id(&insn_name_maps[1], ARR_SIZE(insn_name_maps) - 1, name);
579 
580 	return (i != -1)? i : SPARC_REG_INVALID;
581 }
582 
583 // NOTE: put strings in the order of string length since
584 // we are going to compare with mnemonic to find out CC
585 static const name_map alias_icc_maps[] = {
586 	{ SPARC_CC_ICC_LEU, "leu" },
587 	{ SPARC_CC_ICC_POS, "pos" },
588 	{ SPARC_CC_ICC_NEG, "neg" },
589 	{ SPARC_CC_ICC_NE, "ne" },
590 	{ SPARC_CC_ICC_LE, "le" },
591 	{ SPARC_CC_ICC_GE, "ge" },
592 	{ SPARC_CC_ICC_GU, "gu" },
593 	{ SPARC_CC_ICC_CC, "cc" },
594 	{ SPARC_CC_ICC_CS, "cs" },
595 	{ SPARC_CC_ICC_VC, "vc" },
596 	{ SPARC_CC_ICC_VS, "vs" },
597 	{ SPARC_CC_ICC_A, "a" },
598 	{ SPARC_CC_ICC_N, "n" },
599 	{ SPARC_CC_ICC_E, "e" },
600 	{ SPARC_CC_ICC_G, "g" },
601 	{ SPARC_CC_ICC_L, "l" },
602 };
603 
604 static const name_map alias_fcc_maps[] = {
605 	{ SPARC_CC_FCC_UGE, "uge" },
606 	{ SPARC_CC_FCC_ULE, "ule" },
607 	{ SPARC_CC_FCC_UG, "ug" },
608 	{ SPARC_CC_FCC_UL, "ul" },
609 	{ SPARC_CC_FCC_LG, "lg" },
610 	{ SPARC_CC_FCC_NE, "ne" },
611 	{ SPARC_CC_FCC_UE, "ue" },
612 	{ SPARC_CC_FCC_GE, "ge" },
613 	{ SPARC_CC_FCC_LE, "le" },
614 	{ SPARC_CC_FCC_A, "a" },
615 	{ SPARC_CC_FCC_N, "n" },
616 	{ SPARC_CC_FCC_U, "u" },
617 	{ SPARC_CC_FCC_G, "g" },
618 	{ SPARC_CC_FCC_L, "l" },
619 	{ SPARC_CC_FCC_E, "e" },
620 	{ SPARC_CC_FCC_O, "o" },
621 };
622 
623 // map CC string to CC id
Sparc_map_ICC(const char * name)624 sparc_cc Sparc_map_ICC(const char *name)
625 {
626 	unsigned int i;
627 
628 	i = name2id(alias_icc_maps, ARR_SIZE(alias_icc_maps), name);
629 
630 	return (i != -1)? i : SPARC_CC_INVALID;
631 }
632 
Sparc_map_FCC(const char * name)633 sparc_cc Sparc_map_FCC(const char *name)
634 {
635 	unsigned int i;
636 
637 	i = name2id(alias_fcc_maps, ARR_SIZE(alias_fcc_maps), name);
638 
639 	return (i != -1)? i : SPARC_CC_INVALID;
640 }
641 
642 static const name_map hint_maps[] = {
643 	{ SPARC_HINT_A, ",a" },
644 	{ SPARC_HINT_A | SPARC_HINT_PN, ",a,pn" },
645 	{ SPARC_HINT_PN, ",pn" },
646 };
647 
Sparc_map_hint(const char * name)648 sparc_hint Sparc_map_hint(const char *name)
649 {
650 	size_t i, l1, l2;
651 
652 	l1 = strlen(name);
653 	for(i = 0; i < ARR_SIZE(hint_maps); i++) {
654 		l2 = strlen(hint_maps[i].name);
655 		if (l1 > l2) {
656 			// compare the last part of @name with this hint string
657 			if (!strcmp(hint_maps[i].name, name + (l1 - l2)))
658 				return hint_maps[i].id;
659 		}
660 	}
661 
662 	return SPARC_HINT_INVALID;
663 }
664 
665 #endif
666