1 /* Capstone Disassembly Engine */
2 /* TMS320C64x Backend by Fotis Loukos <me@fotisl.com> 2016 */
3 
4 #ifdef CAPSTONE_HAS_TMS320C64X
5 
6 #ifdef _MSC_VER
7 // Disable security warnings for strcpy
8 #ifndef _CRT_SECURE_NO_WARNINGS
9 #define _CRT_SECURE_NO_WARNINGS
10 #endif
11 
12 // Banned API Usage : strcpy is a Banned API as listed in dontuse.h for
13 // security purposes.
14 #pragma warning(disable:28719)
15 #endif
16 
17 #include <ctype.h>
18 #include <string.h>
19 
20 #include "TMS320C64xInstPrinter.h"
21 #include "../../MCInst.h"
22 #include "../../utils.h"
23 #include "../../SStream.h"
24 #include "../../MCRegisterInfo.h"
25 #include "../../MathExtras.h"
26 #include "TMS320C64xMapping.h"
27 
28 #include "capstone/tms320c64x.h"
29 
30 static char *getRegisterName(unsigned RegNo);
31 static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
32 static void printMemOperand(MCInst *MI, unsigned OpNo, SStream *O);
33 static void printMemOperand2(MCInst *MI, unsigned OpNo, SStream *O);
34 static void printRegPair(MCInst *MI, unsigned OpNo, SStream *O);
35 
TMS320C64x_post_printer(csh ud,cs_insn * insn,char * insn_asm,MCInst * mci)36 void TMS320C64x_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci)
37 {
38 	SStream ss;
39 	char *p, *p2, tmp[8];
40 	unsigned int unit = 0;
41 	int i;
42 	cs_tms320c64x *tms320c64x;
43 
44 	if (mci->csh->detail) {
45 		tms320c64x = &mci->flat_insn->detail->tms320c64x;
46 
47 		for (i = 0; i < insn->detail->groups_count; i++) {
48 			switch(insn->detail->groups[i]) {
49 				case TMS320C64X_GRP_FUNIT_D:
50 					unit = TMS320C64X_FUNIT_D;
51 					break;
52 				case TMS320C64X_GRP_FUNIT_L:
53 					unit = TMS320C64X_FUNIT_L;
54 					break;
55 				case TMS320C64X_GRP_FUNIT_M:
56 					unit = TMS320C64X_FUNIT_M;
57 					break;
58 				case TMS320C64X_GRP_FUNIT_S:
59 					unit = TMS320C64X_FUNIT_S;
60 					break;
61 				case TMS320C64X_GRP_FUNIT_NO:
62 					unit = TMS320C64X_FUNIT_NO;
63 					break;
64 			}
65 			if (unit != 0)
66 				break;
67 		}
68 		tms320c64x->funit.unit = unit;
69 
70 		SStream_Init(&ss);
71 		if (tms320c64x->condition.reg != TMS320C64X_REG_INVALID)
72 			SStream_concat(&ss, "[%c%s]|", (tms320c64x->condition.zero == 1) ? '!' : '|', cs_reg_name(ud, tms320c64x->condition.reg));
73 		else
74 			SStream_concat0(&ss, "||||||");
75 
76 		p = strchr(insn_asm, '\t');
77 		if (p != NULL)
78 			*p++ = '\0';
79 
80 		SStream_concat0(&ss, insn_asm);
81 		if ((p != NULL) && (((p2 = strchr(p, '[')) != NULL) || ((p2 = strchr(p, '(')) != NULL))) {
82 			while ((p2 > p) && ((*p2 != 'a') && (*p2 != 'b')))
83 				p2--;
84 			if (p2 == p) {
85 				strcpy(insn_asm, "Invalid!");
86 				return;
87 			}
88 			if (*p2 == 'a')
89 				strcpy(tmp, "1T");
90 			else
91 				strcpy(tmp, "2T");
92 		} else {
93 			tmp[0] = '\0';
94 		}
95 		switch(tms320c64x->funit.unit) {
96 			case TMS320C64X_FUNIT_D:
97 				SStream_concat(&ss, ".D%s%u", tmp, tms320c64x->funit.side);
98 				break;
99 			case TMS320C64X_FUNIT_L:
100 				SStream_concat(&ss, ".L%s%u", tmp, tms320c64x->funit.side);
101 				break;
102 			case TMS320C64X_FUNIT_M:
103 				SStream_concat(&ss, ".M%s%u", tmp, tms320c64x->funit.side);
104 				break;
105 			case TMS320C64X_FUNIT_S:
106 				SStream_concat(&ss, ".S%s%u", tmp, tms320c64x->funit.side);
107 				break;
108 		}
109 		if (tms320c64x->funit.crosspath > 0)
110 			SStream_concat0(&ss, "X");
111 
112 		if (p != NULL)
113 			SStream_concat(&ss, "\t%s", p);
114 
115 		if (tms320c64x->parallel != 0)
116 			SStream_concat(&ss, "\t||");
117 
118 		/* insn_asm is a buffer from an SStream, so there should be enough space */
119 		strcpy(insn_asm, ss.buffer);
120 	}
121 }
122 
123 #define PRINT_ALIAS_INSTR
124 #include "TMS320C64xGenAsmWriter.inc"
125 
126 #define GET_INSTRINFO_ENUM
127 #include "TMS320C64xGenInstrInfo.inc"
128 
printOperand(MCInst * MI,unsigned OpNo,SStream * O)129 static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
130 {
131 	MCOperand *Op = MCInst_getOperand(MI, OpNo);
132 	unsigned reg;
133 
134 	if (MCOperand_isReg(Op)) {
135 		reg = MCOperand_getReg(Op);
136 		if ((MCInst_getOpcode(MI) == TMS320C64x_MVC_s1_rr) && (OpNo == 1)) {
137 			switch(reg) {
138 				case TMS320C64X_REG_EFR:
139 					SStream_concat0(O, "EFR");
140 					break;
141 				case TMS320C64X_REG_IFR:
142 					SStream_concat0(O, "IFR");
143 					break;
144 				default:
145 					SStream_concat0(O, getRegisterName(reg));
146 					break;
147 			}
148 		} else {
149 			SStream_concat0(O, getRegisterName(reg));
150 		}
151 
152 		if (MI->csh->detail) {
153 			MI->flat_insn->detail->tms320c64x.operands[MI->flat_insn->detail->tms320c64x.op_count].type = TMS320C64X_OP_REG;
154 			MI->flat_insn->detail->tms320c64x.operands[MI->flat_insn->detail->tms320c64x.op_count].reg = reg;
155 			MI->flat_insn->detail->tms320c64x.op_count++;
156 		}
157 	} else if (MCOperand_isImm(Op)) {
158 		int64_t Imm = MCOperand_getImm(Op);
159 
160 		if (Imm >= 0) {
161 			if (Imm > HEX_THRESHOLD)
162 				SStream_concat(O, "0x%"PRIx64, Imm);
163 			else
164 				SStream_concat(O, "%"PRIu64, Imm);
165 		} else {
166 			if (Imm < -HEX_THRESHOLD)
167 				SStream_concat(O, "-0x%"PRIx64, -Imm);
168 			else
169 				SStream_concat(O, "-%"PRIu64, -Imm);
170 		}
171 
172 		if (MI->csh->detail) {
173 			MI->flat_insn->detail->tms320c64x.operands[MI->flat_insn->detail->tms320c64x.op_count].type = TMS320C64X_OP_IMM;
174 			MI->flat_insn->detail->tms320c64x.operands[MI->flat_insn->detail->tms320c64x.op_count].imm = Imm;
175 			MI->flat_insn->detail->tms320c64x.op_count++;
176 		}
177 	}
178 }
179 
printMemOperand(MCInst * MI,unsigned OpNo,SStream * O)180 static void printMemOperand(MCInst *MI, unsigned OpNo, SStream *O)
181 {
182 	MCOperand *Op = MCInst_getOperand(MI, OpNo);
183 	int64_t Val = MCOperand_getImm(Op);
184 	unsigned scaled, base, offset, mode, unit;
185 	cs_tms320c64x *tms320c64x;
186 	char st, nd;
187 
188 	scaled = (Val >> 19) & 1;
189 	base = (Val >> 12) & 0x7f;
190 	offset = (Val >> 5) & 0x7f;
191 	mode = (Val >> 1) & 0xf;
192 	unit = Val & 1;
193 
194 	if (scaled) {
195 		st = '[';
196 		nd = ']';
197 	} else {
198 		st = '(';
199 		nd = ')';
200 	}
201 
202 	switch(mode) {
203 		case 0:
204 			SStream_concat(O, "*-%s%c%u%c", getRegisterName(base), st, offset, nd);
205 			break;
206 		case 1:
207 			SStream_concat(O, "*+%s%c%u%c", getRegisterName(base), st, offset, nd);
208 			break;
209 		case 4:
210 			SStream_concat(O, "*-%s%c%s%c", getRegisterName(base), st, getRegisterName(offset), nd);
211 			break;
212 		case 5:
213 			SStream_concat(O, "*+%s%c%s%c", getRegisterName(base), st, getRegisterName(offset), nd);
214 			break;
215 		case 8:
216 			SStream_concat(O, "*--%s%c%u%c", getRegisterName(base), st, offset, nd);
217 			break;
218 		case 9:
219 			SStream_concat(O, "*++%s%c%u%c", getRegisterName(base), st, offset, nd);
220 			break;
221 		case 10:
222 			SStream_concat(O, "*%s--%c%u%c", getRegisterName(base), st, offset, nd);
223 			break;
224 		case 11:
225 			SStream_concat(O, "*%s++%c%u%c", getRegisterName(base), st, offset, nd);
226 			break;
227 		case 12:
228 			SStream_concat(O, "*--%s%c%s%c", getRegisterName(base), st, getRegisterName(offset), nd);
229 			break;
230 		case 13:
231 			SStream_concat(O, "*++%s%c%s%c", getRegisterName(base), st, getRegisterName(offset), nd);
232 			break;
233 		case 14:
234 			SStream_concat(O, "*%s--%c%s%c", getRegisterName(base), st, getRegisterName(offset), nd);
235 			break;
236 		case 15:
237 			SStream_concat(O, "*%s++%c%s%c", getRegisterName(base), st, getRegisterName(offset), nd);
238 			break;
239 	}
240 
241 	if (MI->csh->detail) {
242 		tms320c64x = &MI->flat_insn->detail->tms320c64x;
243 
244 		tms320c64x->operands[tms320c64x->op_count].type = TMS320C64X_OP_MEM;
245 		tms320c64x->operands[tms320c64x->op_count].mem.base = base;
246 		tms320c64x->operands[tms320c64x->op_count].mem.disp = offset;
247 		tms320c64x->operands[tms320c64x->op_count].mem.unit = unit + 1;
248 		tms320c64x->operands[tms320c64x->op_count].mem.scaled = scaled;
249 		switch(mode) {
250 			case 0:
251 				tms320c64x->operands[tms320c64x->op_count].mem.disptype = TMS320C64X_MEM_DISP_CONSTANT;
252 				tms320c64x->operands[tms320c64x->op_count].mem.direction = TMS320C64X_MEM_DIR_BW;
253 				tms320c64x->operands[tms320c64x->op_count].mem.modify = TMS320C64X_MEM_MOD_NO;
254 				break;
255 			case 1:
256 				tms320c64x->operands[tms320c64x->op_count].mem.disptype = TMS320C64X_MEM_DISP_CONSTANT;
257 				tms320c64x->operands[tms320c64x->op_count].mem.direction = TMS320C64X_MEM_DIR_FW;
258 				tms320c64x->operands[tms320c64x->op_count].mem.modify = TMS320C64X_MEM_MOD_NO;
259 				break;
260 			case 4:
261 				tms320c64x->operands[tms320c64x->op_count].mem.disptype = TMS320C64X_MEM_DISP_REGISTER;
262 				tms320c64x->operands[tms320c64x->op_count].mem.direction = TMS320C64X_MEM_DIR_BW;
263 				tms320c64x->operands[tms320c64x->op_count].mem.modify = TMS320C64X_MEM_MOD_NO;
264 				break;
265 			case 5:
266 				tms320c64x->operands[tms320c64x->op_count].mem.disptype = TMS320C64X_MEM_DISP_REGISTER;
267 				tms320c64x->operands[tms320c64x->op_count].mem.direction = TMS320C64X_MEM_DIR_FW;
268 				tms320c64x->operands[tms320c64x->op_count].mem.modify = TMS320C64X_MEM_MOD_NO;
269 				break;
270 			case 8:
271 				tms320c64x->operands[tms320c64x->op_count].mem.disptype = TMS320C64X_MEM_DISP_CONSTANT;
272 				tms320c64x->operands[tms320c64x->op_count].mem.direction = TMS320C64X_MEM_DIR_BW;
273 				tms320c64x->operands[tms320c64x->op_count].mem.modify = TMS320C64X_MEM_MOD_PRE;
274 				break;
275 			case 9:
276 				tms320c64x->operands[tms320c64x->op_count].mem.disptype = TMS320C64X_MEM_DISP_CONSTANT;
277 				tms320c64x->operands[tms320c64x->op_count].mem.direction = TMS320C64X_MEM_DIR_FW;
278 				tms320c64x->operands[tms320c64x->op_count].mem.modify = TMS320C64X_MEM_MOD_PRE;
279 				break;
280 			case 10:
281 				tms320c64x->operands[tms320c64x->op_count].mem.disptype = TMS320C64X_MEM_DISP_CONSTANT;
282 				tms320c64x->operands[tms320c64x->op_count].mem.direction = TMS320C64X_MEM_DIR_BW;
283 				tms320c64x->operands[tms320c64x->op_count].mem.modify = TMS320C64X_MEM_MOD_POST;
284 				break;
285 			case 11:
286 				tms320c64x->operands[tms320c64x->op_count].mem.disptype = TMS320C64X_MEM_DISP_CONSTANT;
287 				tms320c64x->operands[tms320c64x->op_count].mem.direction = TMS320C64X_MEM_DIR_FW;
288 				tms320c64x->operands[tms320c64x->op_count].mem.modify = TMS320C64X_MEM_MOD_POST;
289 				break;
290 			case 12:
291 				tms320c64x->operands[tms320c64x->op_count].mem.disptype = TMS320C64X_MEM_DISP_REGISTER;
292 				tms320c64x->operands[tms320c64x->op_count].mem.direction = TMS320C64X_MEM_DIR_BW;
293 				tms320c64x->operands[tms320c64x->op_count].mem.modify = TMS320C64X_MEM_MOD_PRE;
294 				break;
295 			case 13:
296 				tms320c64x->operands[tms320c64x->op_count].mem.disptype = TMS320C64X_MEM_DISP_REGISTER;
297 				tms320c64x->operands[tms320c64x->op_count].mem.direction = TMS320C64X_MEM_DIR_FW;
298 				tms320c64x->operands[tms320c64x->op_count].mem.modify = TMS320C64X_MEM_MOD_PRE;
299 				break;
300 			case 14:
301 				tms320c64x->operands[tms320c64x->op_count].mem.disptype = TMS320C64X_MEM_DISP_REGISTER;
302 				tms320c64x->operands[tms320c64x->op_count].mem.direction = TMS320C64X_MEM_DIR_BW;
303 				tms320c64x->operands[tms320c64x->op_count].mem.modify = TMS320C64X_MEM_MOD_POST;
304 				break;
305 			case 15:
306 				tms320c64x->operands[tms320c64x->op_count].mem.disptype = TMS320C64X_MEM_DISP_REGISTER;
307 				tms320c64x->operands[tms320c64x->op_count].mem.direction = TMS320C64X_MEM_DIR_FW;
308 				tms320c64x->operands[tms320c64x->op_count].mem.modify = TMS320C64X_MEM_MOD_POST;
309 				break;
310 		}
311 		tms320c64x->op_count++;
312 	}
313 }
314 
printMemOperand2(MCInst * MI,unsigned OpNo,SStream * O)315 static void printMemOperand2(MCInst *MI, unsigned OpNo, SStream *O)
316 {
317 	MCOperand *Op = MCInst_getOperand(MI, OpNo);
318 	int64_t Val = MCOperand_getImm(Op);
319 	uint16_t offset;
320 	unsigned basereg;
321 	cs_tms320c64x *tms320c64x;
322 
323 	basereg = Val & 0x7f;
324 	offset = (Val >> 7) & 0x7fff;
325 	SStream_concat(O, "*+%s[0x%x]", getRegisterName(basereg), offset);
326 
327 	if (MI->csh->detail) {
328 		tms320c64x = &MI->flat_insn->detail->tms320c64x;
329 
330 		tms320c64x->operands[tms320c64x->op_count].type = TMS320C64X_OP_MEM;
331 		tms320c64x->operands[tms320c64x->op_count].mem.base = basereg;
332 		tms320c64x->operands[tms320c64x->op_count].mem.unit = 2;
333 		tms320c64x->operands[tms320c64x->op_count].mem.disp = offset;
334 		tms320c64x->operands[tms320c64x->op_count].mem.disptype = TMS320C64X_MEM_DISP_CONSTANT;
335 		tms320c64x->operands[tms320c64x->op_count].mem.direction = TMS320C64X_MEM_DIR_FW;
336 		tms320c64x->operands[tms320c64x->op_count].mem.modify = TMS320C64X_MEM_MOD_NO;
337 		tms320c64x->op_count++;
338 	}
339 }
340 
printRegPair(MCInst * MI,unsigned OpNo,SStream * O)341 static void printRegPair(MCInst *MI, unsigned OpNo, SStream *O)
342 {
343 	MCOperand *Op = MCInst_getOperand(MI, OpNo);
344 	unsigned reg = MCOperand_getReg(Op);
345 	cs_tms320c64x *tms320c64x;
346 
347 	SStream_concat(O, "%s:%s", getRegisterName(reg + 1), getRegisterName(reg));
348 
349 	if (MI->csh->detail) {
350 		tms320c64x = &MI->flat_insn->detail->tms320c64x;
351 
352 		tms320c64x->operands[tms320c64x->op_count].type = TMS320C64X_OP_REGPAIR;
353 		tms320c64x->operands[tms320c64x->op_count].reg = reg;
354 		tms320c64x->op_count++;
355 	}
356 }
357 
printAliasInstruction(MCInst * MI,SStream * O,MCRegisterInfo * MRI)358 static bool printAliasInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI)
359 {
360 	unsigned opcode = MCInst_getOpcode(MI);
361 	MCOperand *op;
362 
363 	switch(opcode) {
364 		/* ADD.Dx -i, x, y -> SUB.Dx x, i, y */
365 		case TMS320C64x_ADD_d2_rir:
366 		/* ADD.L -i, x, y -> SUB.L x, i, y */
367 		case TMS320C64x_ADD_l1_irr:
368 		case TMS320C64x_ADD_l1_ipp:
369 		/* ADD.S -i, x, y -> SUB.S x, i, y */
370 		case TMS320C64x_ADD_s1_irr:
371 			if ((MCInst_getNumOperands(MI) == 3) &&
372 				MCOperand_isReg(MCInst_getOperand(MI, 0)) &&
373 				MCOperand_isReg(MCInst_getOperand(MI, 1)) &&
374 				MCOperand_isImm(MCInst_getOperand(MI, 2)) &&
375 				(MCOperand_getImm(MCInst_getOperand(MI, 2)) < 0)) {
376 
377 				MCInst_setOpcodePub(MI, TMS320C64X_INS_SUB);
378 				op = MCInst_getOperand(MI, 2);
379 				MCOperand_setImm(op, -MCOperand_getImm(op));
380 
381 				SStream_concat0(O, "SUB\t");
382 				printOperand(MI, 1, O);
383 				SStream_concat0(O, ", ");
384 				printOperand(MI, 2, O);
385 				SStream_concat0(O, ", ");
386 				printOperand(MI, 0, O);
387 
388 				return true;
389 			}
390 			break;
391 	}
392 	switch(opcode) {
393 		/* ADD.D 0, x, y -> MV.D x, y */
394 		case TMS320C64x_ADD_d1_rir:
395 		/* OR.D x, 0, y -> MV.D x, y */
396 		case TMS320C64x_OR_d2_rir:
397 		/* ADD.L 0, x, y -> MV.L x, y */
398 		case TMS320C64x_ADD_l1_irr:
399 		case TMS320C64x_ADD_l1_ipp:
400 		/* OR.L 0, x, y -> MV.L x, y */
401 		case TMS320C64x_OR_l1_irr:
402 		/* ADD.S 0, x, y -> MV.S x, y */
403 		case TMS320C64x_ADD_s1_irr:
404 		/* OR.S 0, x, y -> MV.S x, y */
405 		case TMS320C64x_OR_s1_irr:
406 			if ((MCInst_getNumOperands(MI) == 3) &&
407 				MCOperand_isReg(MCInst_getOperand(MI, 0)) &&
408 				MCOperand_isReg(MCInst_getOperand(MI, 1)) &&
409 				MCOperand_isImm(MCInst_getOperand(MI, 2)) &&
410 				(MCOperand_getImm(MCInst_getOperand(MI, 2)) == 0)) {
411 
412 				MCInst_setOpcodePub(MI, TMS320C64X_INS_MV);
413 				MI->size--;
414 
415 				SStream_concat0(O, "MV\t");
416 				printOperand(MI, 1, O);
417 				SStream_concat0(O, ", ");
418 				printOperand(MI, 0, O);
419 
420 				return true;
421 			}
422 			break;
423 	}
424 	switch(opcode) {
425 		/* XOR.D -1, x, y -> NOT.D x, y */
426 		case TMS320C64x_XOR_d2_rir:
427 		/* XOR.L -1, x, y -> NOT.L x, y */
428 		case TMS320C64x_XOR_l1_irr:
429 		/* XOR.S -1, x, y -> NOT.S x, y */
430 		case TMS320C64x_XOR_s1_irr:
431 			if ((MCInst_getNumOperands(MI) == 3) &&
432 				MCOperand_isReg(MCInst_getOperand(MI, 0)) &&
433 				MCOperand_isReg(MCInst_getOperand(MI, 1)) &&
434 				MCOperand_isImm(MCInst_getOperand(MI, 2)) &&
435 				(MCOperand_getImm(MCInst_getOperand(MI, 2)) == -1)) {
436 
437 				MCInst_setOpcodePub(MI, TMS320C64X_INS_NOT);
438 				MI->size--;
439 
440 				SStream_concat0(O, "NOT\t");
441 				printOperand(MI, 1, O);
442 				SStream_concat0(O, ", ");
443 				printOperand(MI, 0, O);
444 
445 				return true;
446 			}
447 			break;
448 	}
449 	switch(opcode) {
450 		/* MVK.D 0, x -> ZERO.D x */
451 		case TMS320C64x_MVK_d1_rr:
452 		/* MVK.L 0, x -> ZERO.L x */
453 		case TMS320C64x_MVK_l2_ir:
454 			if ((MCInst_getNumOperands(MI) == 2) &&
455 				MCOperand_isReg(MCInst_getOperand(MI, 0)) &&
456 				MCOperand_isImm(MCInst_getOperand(MI, 1)) &&
457 				(MCOperand_getImm(MCInst_getOperand(MI, 1)) == 0)) {
458 
459 				MCInst_setOpcodePub(MI, TMS320C64X_INS_ZERO);
460 				MI->size--;
461 
462 				SStream_concat0(O, "ZERO\t");
463 				printOperand(MI, 0, O);
464 
465 				return true;
466 			}
467 			break;
468 	}
469 	switch(opcode) {
470 		/* SUB.L x, x, y -> ZERO.L y */
471 		case TMS320C64x_SUB_l1_rrp_x1:
472 		/* SUB.S x, x, y -> ZERO.S y */
473 		case TMS320C64x_SUB_s1_rrr:
474 			if ((MCInst_getNumOperands(MI) == 3) &&
475 				MCOperand_isReg(MCInst_getOperand(MI, 0)) &&
476 				MCOperand_isReg(MCInst_getOperand(MI, 1)) &&
477 				MCOperand_isReg(MCInst_getOperand(MI, 2)) &&
478 				(MCOperand_getReg(MCInst_getOperand(MI, 1)) == MCOperand_getReg(MCInst_getOperand(MI, 2)))) {
479 
480 				MCInst_setOpcodePub(MI, TMS320C64X_INS_ZERO);
481 				MI->size -= 2;
482 
483 				SStream_concat0(O, "ZERO\t");
484 				printOperand(MI, 0, O);
485 
486 				return true;
487 			}
488 			break;
489 	}
490 	switch(opcode) {
491 		/* SUB.L 0, x, y -> NEG.L x, y */
492 		case TMS320C64x_SUB_l1_irr:
493 		case TMS320C64x_SUB_l1_ipp:
494 		/* SUB.S 0, x, y -> NEG.S x, y */
495 		case TMS320C64x_SUB_s1_irr:
496 			if ((MCInst_getNumOperands(MI) == 3) &&
497 				MCOperand_isReg(MCInst_getOperand(MI, 0)) &&
498 				MCOperand_isReg(MCInst_getOperand(MI, 1)) &&
499 				MCOperand_isImm(MCInst_getOperand(MI, 2)) &&
500 				(MCOperand_getImm(MCInst_getOperand(MI, 2)) == 0)) {
501 
502 				MCInst_setOpcodePub(MI, TMS320C64X_INS_NEG);
503 				MI->size--;
504 
505 				SStream_concat0(O, "NEG\t");
506 				printOperand(MI, 1, O);
507 				SStream_concat0(O, ", ");
508 				printOperand(MI, 0, O);
509 
510 				return true;
511 			}
512 			break;
513 	}
514 	switch(opcode) {
515 		/* PACKLH2.L x, x, y -> SWAP2.L x, y */
516 		case TMS320C64x_PACKLH2_l1_rrr_x2:
517 		/* PACKLH2.S x, x, y -> SWAP2.S x, y */
518 		case TMS320C64x_PACKLH2_s1_rrr:
519 			if ((MCInst_getNumOperands(MI) == 3) &&
520 				MCOperand_isReg(MCInst_getOperand(MI, 0)) &&
521 				MCOperand_isReg(MCInst_getOperand(MI, 1)) &&
522 				MCOperand_isReg(MCInst_getOperand(MI, 2)) &&
523 				(MCOperand_getReg(MCInst_getOperand(MI, 1)) == MCOperand_getReg(MCInst_getOperand(MI, 2)))) {
524 
525 				MCInst_setOpcodePub(MI, TMS320C64X_INS_SWAP2);
526 				MI->size--;
527 
528 				SStream_concat0(O, "SWAP2\t");
529 				printOperand(MI, 1, O);
530 				SStream_concat0(O, ", ");
531 				printOperand(MI, 0, O);
532 
533 				return true;
534 			}
535 			break;
536 	}
537 	switch(opcode) {
538 		/* NOP 16 -> IDLE */
539 		/* NOP 1 -> NOP */
540 		case TMS320C64x_NOP_n:
541 			if ((MCInst_getNumOperands(MI) == 1) &&
542 				MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
543 				(MCOperand_getReg(MCInst_getOperand(MI, 0)) == 16)) {
544 
545 				MCInst_setOpcodePub(MI, TMS320C64X_INS_IDLE);
546 				MI->size--;
547 
548 				SStream_concat0(O, "IDLE");
549 
550 				return true;
551 			}
552 			if ((MCInst_getNumOperands(MI) == 1) &&
553 				MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
554 				(MCOperand_getReg(MCInst_getOperand(MI, 0)) == 1)) {
555 
556 				MI->size--;
557 
558 				SStream_concat0(O, "NOP");
559 
560 				return true;
561 			}
562 			break;
563 	}
564 
565 	return false;
566 }
567 
TMS320C64x_printInst(MCInst * MI,SStream * O,void * Info)568 void TMS320C64x_printInst(MCInst *MI, SStream *O, void *Info)
569 {
570 	if (!printAliasInstruction(MI, O, Info))
571 		printInstruction(MI, O, Info);
572 }
573 
574 #endif
575