/src/capstonenext/arch/TMS320C64x/TMS320C64xInstPrinter.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Capstone Disassembly Engine */ |
2 | | /* TMS320C64x Backend by Fotis Loukos <me@fotisl.com> 2016 */ |
3 | | |
4 | | #ifdef CAPSTONE_HAS_TMS320C64X |
5 | | |
6 | | #include <ctype.h> |
7 | | #include <string.h> |
8 | | |
9 | | #include "TMS320C64xInstPrinter.h" |
10 | | #include "../../MCInst.h" |
11 | | #include "../../utils.h" |
12 | | #include "../../SStream.h" |
13 | | #include "../../MCRegisterInfo.h" |
14 | | #include "../../MathExtras.h" |
15 | | #include "TMS320C64xMapping.h" |
16 | | |
17 | | #include "capstone/tms320c64x.h" |
18 | | |
19 | | static const char *getRegisterName(unsigned RegNo); |
20 | | static void printOperand(MCInst *MI, unsigned OpNo, SStream *O); |
21 | | static void printMemOperand(MCInst *MI, unsigned OpNo, SStream *O); |
22 | | static void printMemOperand2(MCInst *MI, unsigned OpNo, SStream *O); |
23 | | static void printRegPair(MCInst *MI, unsigned OpNo, SStream *O); |
24 | | |
25 | | void TMS320C64x_post_printer(csh ud, cs_insn *insn, SStream *insn_asm, |
26 | | MCInst *mci) |
27 | 32.3k | { |
28 | 32.3k | SStream ss; |
29 | 32.3k | const char *op_str_ptr, *p2; |
30 | 32.3k | char tmp[8] = { 0 }; |
31 | 32.3k | unsigned int unit = 0; |
32 | 32.3k | int i; |
33 | 32.3k | cs_tms320c64x *tms320c64x; |
34 | | |
35 | 32.3k | if (mci->csh->detail_opt) { |
36 | 32.3k | tms320c64x = &mci->flat_insn->detail->tms320c64x; |
37 | | |
38 | 32.3k | for (i = 0; i < insn->detail->groups_count; i++) { |
39 | 32.3k | switch (insn->detail->groups[i]) { |
40 | 8.90k | case TMS320C64X_GRP_FUNIT_D: |
41 | 8.90k | unit = TMS320C64X_FUNIT_D; |
42 | 8.90k | break; |
43 | 7.12k | case TMS320C64X_GRP_FUNIT_L: |
44 | 7.12k | unit = TMS320C64X_FUNIT_L; |
45 | 7.12k | break; |
46 | 2.29k | case TMS320C64X_GRP_FUNIT_M: |
47 | 2.29k | unit = TMS320C64X_FUNIT_M; |
48 | 2.29k | break; |
49 | 13.5k | case TMS320C64X_GRP_FUNIT_S: |
50 | 13.5k | unit = TMS320C64X_FUNIT_S; |
51 | 13.5k | break; |
52 | 527 | case TMS320C64X_GRP_FUNIT_NO: |
53 | 527 | unit = TMS320C64X_FUNIT_NO; |
54 | 527 | break; |
55 | 32.3k | } |
56 | 32.3k | if (unit != 0) |
57 | 32.3k | break; |
58 | 32.3k | } |
59 | 32.3k | tms320c64x->funit.unit = unit; |
60 | | |
61 | 32.3k | SStream_Init(&ss); |
62 | 32.3k | if (tms320c64x->condition.reg != TMS320C64X_REG_INVALID) |
63 | 20.9k | SStream_concat( |
64 | 20.9k | &ss, "[%c%s]|", |
65 | 20.9k | (tms320c64x->condition.zero == 1) ? '!' : '|', |
66 | 20.9k | cs_reg_name(ud, tms320c64x->condition.reg)); |
67 | | |
68 | | // Sorry for all the fixes below. I don't have time to add more helper SStream functions. |
69 | | // Before that they messed around with the private buffer of the stream. |
70 | | // So it is better now. But still not efficient. |
71 | 32.3k | op_str_ptr = strchr(SStream_rbuf(insn_asm), '\t'); |
72 | | |
73 | 32.3k | if ((op_str_ptr != NULL) && |
74 | 32.3k | (((p2 = strchr(op_str_ptr, '[')) != NULL) || |
75 | 31.8k | ((p2 = strchr(op_str_ptr, '(')) != NULL))) { |
76 | 28.9k | while ((p2 > op_str_ptr) && |
77 | 28.9k | ((*p2 != 'a') && (*p2 != 'b'))) |
78 | 21.9k | p2--; |
79 | 6.97k | if (p2 == op_str_ptr) { |
80 | 0 | SStream_Flush(insn_asm, NULL); |
81 | 0 | SStream_concat0(insn_asm, "Invalid!"); |
82 | 0 | return; |
83 | 0 | } |
84 | 6.97k | if (*p2 == 'a') |
85 | 4.27k | strncpy(tmp, "1T", sizeof(tmp)); |
86 | 2.70k | else |
87 | 2.70k | strncpy(tmp, "2T", sizeof(tmp)); |
88 | 25.3k | } else { |
89 | 25.3k | tmp[0] = '\0'; |
90 | 25.3k | } |
91 | 32.3k | SStream mnem_post = { 0 }; |
92 | 32.3k | SStream_Init(&mnem_post); |
93 | 32.3k | switch (tms320c64x->funit.unit) { |
94 | 8.90k | case TMS320C64X_FUNIT_D: |
95 | 8.90k | SStream_concat(&mnem_post, ".D%s%u", tmp, |
96 | 8.90k | tms320c64x->funit.side); |
97 | 8.90k | break; |
98 | 7.12k | case TMS320C64X_FUNIT_L: |
99 | 7.12k | SStream_concat(&mnem_post, ".L%s%u", tmp, |
100 | 7.12k | tms320c64x->funit.side); |
101 | 7.12k | break; |
102 | 2.29k | case TMS320C64X_FUNIT_M: |
103 | 2.29k | SStream_concat(&mnem_post, ".M%s%u", tmp, |
104 | 2.29k | tms320c64x->funit.side); |
105 | 2.29k | break; |
106 | 13.5k | case TMS320C64X_FUNIT_S: |
107 | 13.5k | SStream_concat(&mnem_post, ".S%s%u", tmp, |
108 | 13.5k | tms320c64x->funit.side); |
109 | 13.5k | break; |
110 | 32.3k | } |
111 | 32.3k | if (tms320c64x->funit.crosspath > 0) |
112 | 8.18k | SStream_concat0(&mnem_post, "X"); |
113 | | |
114 | 32.3k | if (op_str_ptr != NULL) { |
115 | | // There is an op_str |
116 | 31.8k | SStream_concat1(&mnem_post, '\t'); |
117 | 31.8k | SStream_replc_str(insn_asm, '\t', |
118 | 31.8k | SStream_rbuf(&mnem_post)); |
119 | 31.8k | } |
120 | | |
121 | 32.3k | if (tms320c64x->parallel != 0) |
122 | 14.3k | SStream_concat0(insn_asm, "\t||"); |
123 | 32.3k | SStream_concat0(&ss, SStream_rbuf(insn_asm)); |
124 | 32.3k | SStream_Flush(insn_asm, NULL); |
125 | 32.3k | SStream_concat0(insn_asm, SStream_rbuf(&ss)); |
126 | 32.3k | } |
127 | 32.3k | } |
128 | | |
129 | | #define PRINT_ALIAS_INSTR |
130 | | #include "TMS320C64xGenAsmWriter.inc" |
131 | | |
132 | | #define GET_INSTRINFO_ENUM |
133 | | #include "TMS320C64xGenInstrInfo.inc" |
134 | | |
135 | | static void printOperand(MCInst *MI, unsigned OpNo, SStream *O) |
136 | 129k | { |
137 | 129k | MCOperand *Op = MCInst_getOperand(MI, OpNo); |
138 | 129k | unsigned reg; |
139 | | |
140 | 129k | if (MCOperand_isReg(Op)) { |
141 | 90.7k | reg = MCOperand_getReg(Op); |
142 | 90.7k | if ((MCInst_getOpcode(MI) == TMS320C64x_MVC_s1_rr) && |
143 | 90.7k | (OpNo == 1)) { |
144 | 1.62k | switch (reg) { |
145 | 926 | case TMS320C64X_REG_EFR: |
146 | 926 | SStream_concat0(O, "EFR"); |
147 | 926 | break; |
148 | 363 | case TMS320C64X_REG_IFR: |
149 | 363 | SStream_concat0(O, "IFR"); |
150 | 363 | break; |
151 | 340 | default: |
152 | 340 | SStream_concat0(O, getRegisterName(reg)); |
153 | 340 | break; |
154 | 1.62k | } |
155 | 89.0k | } else { |
156 | 89.0k | SStream_concat0(O, getRegisterName(reg)); |
157 | 89.0k | } |
158 | | |
159 | 90.7k | if (MI->csh->detail_opt) { |
160 | 90.7k | MI->flat_insn->detail->tms320c64x |
161 | 90.7k | .operands[MI->flat_insn->detail->tms320c64x |
162 | 90.7k | .op_count] |
163 | 90.7k | .type = TMS320C64X_OP_REG; |
164 | 90.7k | MI->flat_insn->detail->tms320c64x |
165 | 90.7k | .operands[MI->flat_insn->detail->tms320c64x |
166 | 90.7k | .op_count] |
167 | 90.7k | .reg = reg; |
168 | 90.7k | MI->flat_insn->detail->tms320c64x.op_count++; |
169 | 90.7k | } |
170 | 90.7k | } else if (MCOperand_isImm(Op)) { |
171 | 38.8k | int64_t Imm = MCOperand_getImm(Op); |
172 | | |
173 | 38.8k | if (Imm >= 0) { |
174 | 30.5k | if (Imm > HEX_THRESHOLD) |
175 | 18.0k | SStream_concat(O, "0x%" PRIx64, Imm); |
176 | 12.4k | else |
177 | 12.4k | SStream_concat(O, "%" PRIu64, Imm); |
178 | 30.5k | } else { |
179 | 8.26k | if (Imm < -HEX_THRESHOLD) |
180 | 6.86k | SStream_concat(O, "-0x%" PRIx64, -Imm); |
181 | 1.39k | else |
182 | 1.39k | SStream_concat(O, "-%" PRIu64, -Imm); |
183 | 8.26k | } |
184 | | |
185 | 38.8k | if (MI->csh->detail_opt) { |
186 | 38.8k | MI->flat_insn->detail->tms320c64x |
187 | 38.8k | .operands[MI->flat_insn->detail->tms320c64x |
188 | 38.8k | .op_count] |
189 | 38.8k | .type = TMS320C64X_OP_IMM; |
190 | 38.8k | MI->flat_insn->detail->tms320c64x |
191 | 38.8k | .operands[MI->flat_insn->detail->tms320c64x |
192 | 38.8k | .op_count] |
193 | 38.8k | .imm = Imm; |
194 | 38.8k | MI->flat_insn->detail->tms320c64x.op_count++; |
195 | 38.8k | } |
196 | 38.8k | } |
197 | 129k | } |
198 | | |
199 | | static void printMemOperand(MCInst *MI, unsigned OpNo, SStream *O) |
200 | 9.02k | { |
201 | 9.02k | MCOperand *Op = MCInst_getOperand(MI, OpNo); |
202 | 9.02k | int64_t Val = MCOperand_getImm(Op); |
203 | 9.02k | unsigned scaled, base, offset, mode, unit; |
204 | 9.02k | cs_tms320c64x *tms320c64x; |
205 | 9.02k | char st, nd; |
206 | | |
207 | 9.02k | scaled = (Val >> 19) & 1; |
208 | 9.02k | base = (Val >> 12) & 0x7f; |
209 | 9.02k | offset = (Val >> 5) & 0x7f; |
210 | 9.02k | mode = (Val >> 1) & 0xf; |
211 | 9.02k | unit = Val & 1; |
212 | | |
213 | 9.02k | if (scaled) { |
214 | 8.08k | st = '['; |
215 | 8.08k | nd = ']'; |
216 | 8.08k | } else { |
217 | 941 | st = '('; |
218 | 941 | nd = ')'; |
219 | 941 | } |
220 | | |
221 | 9.02k | switch (mode) { |
222 | 1.59k | case 0: |
223 | 1.59k | SStream_concat(O, "*-%s%c%u%c", getRegisterName(base), st, |
224 | 1.59k | offset, nd); |
225 | 1.59k | break; |
226 | 604 | case 1: |
227 | 604 | SStream_concat(O, "*+%s%c%u%c", getRegisterName(base), st, |
228 | 604 | offset, nd); |
229 | 604 | break; |
230 | 518 | case 4: |
231 | 518 | SStream_concat(O, "*-%s%c%s%c", getRegisterName(base), st, |
232 | 518 | getRegisterName(offset), nd); |
233 | 518 | break; |
234 | 598 | case 5: |
235 | 598 | SStream_concat(O, "*+%s%c%s%c", getRegisterName(base), st, |
236 | 598 | getRegisterName(offset), nd); |
237 | 598 | break; |
238 | 674 | case 8: |
239 | 674 | SStream_concat(O, "*--%s%c%u%c", getRegisterName(base), st, |
240 | 674 | offset, nd); |
241 | 674 | break; |
242 | 976 | case 9: |
243 | 976 | SStream_concat(O, "*++%s%c%u%c", getRegisterName(base), st, |
244 | 976 | offset, nd); |
245 | 976 | break; |
246 | 760 | case 10: |
247 | 760 | SStream_concat(O, "*%s--%c%u%c", getRegisterName(base), st, |
248 | 760 | offset, nd); |
249 | 760 | break; |
250 | 767 | case 11: |
251 | 767 | SStream_concat(O, "*%s++%c%u%c", getRegisterName(base), st, |
252 | 767 | offset, nd); |
253 | 767 | break; |
254 | 736 | case 12: |
255 | 736 | SStream_concat(O, "*--%s%c%s%c", getRegisterName(base), st, |
256 | 736 | getRegisterName(offset), nd); |
257 | 736 | break; |
258 | 659 | case 13: |
259 | 659 | SStream_concat(O, "*++%s%c%s%c", getRegisterName(base), st, |
260 | 659 | getRegisterName(offset), nd); |
261 | 659 | break; |
262 | 573 | case 14: |
263 | 573 | SStream_concat(O, "*%s--%c%s%c", getRegisterName(base), st, |
264 | 573 | getRegisterName(offset), nd); |
265 | 573 | break; |
266 | 566 | case 15: |
267 | 566 | SStream_concat(O, "*%s++%c%s%c", getRegisterName(base), st, |
268 | 566 | getRegisterName(offset), nd); |
269 | 566 | break; |
270 | 9.02k | } |
271 | | |
272 | 9.02k | if (MI->csh->detail_opt) { |
273 | 9.02k | tms320c64x = &MI->flat_insn->detail->tms320c64x; |
274 | | |
275 | 9.02k | tms320c64x->operands[tms320c64x->op_count].type = |
276 | 9.02k | TMS320C64X_OP_MEM; |
277 | 9.02k | tms320c64x->operands[tms320c64x->op_count].mem.base = base; |
278 | 9.02k | tms320c64x->operands[tms320c64x->op_count].mem.disp = offset; |
279 | 9.02k | tms320c64x->operands[tms320c64x->op_count].mem.unit = unit + 1; |
280 | 9.02k | tms320c64x->operands[tms320c64x->op_count].mem.scaled = scaled; |
281 | 9.02k | switch (mode) { |
282 | 1.59k | case 0: |
283 | 1.59k | tms320c64x->operands[tms320c64x->op_count].mem.disptype = |
284 | 1.59k | TMS320C64X_MEM_DISP_CONSTANT; |
285 | 1.59k | tms320c64x->operands[tms320c64x->op_count] |
286 | 1.59k | .mem.direction = TMS320C64X_MEM_DIR_BW; |
287 | 1.59k | tms320c64x->operands[tms320c64x->op_count].mem.modify = |
288 | 1.59k | TMS320C64X_MEM_MOD_NO; |
289 | 1.59k | break; |
290 | 604 | case 1: |
291 | 604 | tms320c64x->operands[tms320c64x->op_count].mem.disptype = |
292 | 604 | TMS320C64X_MEM_DISP_CONSTANT; |
293 | 604 | tms320c64x->operands[tms320c64x->op_count] |
294 | 604 | .mem.direction = TMS320C64X_MEM_DIR_FW; |
295 | 604 | tms320c64x->operands[tms320c64x->op_count].mem.modify = |
296 | 604 | TMS320C64X_MEM_MOD_NO; |
297 | 604 | break; |
298 | 518 | case 4: |
299 | 518 | tms320c64x->operands[tms320c64x->op_count].mem.disptype = |
300 | 518 | TMS320C64X_MEM_DISP_REGISTER; |
301 | 518 | tms320c64x->operands[tms320c64x->op_count] |
302 | 518 | .mem.direction = TMS320C64X_MEM_DIR_BW; |
303 | 518 | tms320c64x->operands[tms320c64x->op_count].mem.modify = |
304 | 518 | TMS320C64X_MEM_MOD_NO; |
305 | 518 | break; |
306 | 598 | case 5: |
307 | 598 | tms320c64x->operands[tms320c64x->op_count].mem.disptype = |
308 | 598 | TMS320C64X_MEM_DISP_REGISTER; |
309 | 598 | tms320c64x->operands[tms320c64x->op_count] |
310 | 598 | .mem.direction = TMS320C64X_MEM_DIR_FW; |
311 | 598 | tms320c64x->operands[tms320c64x->op_count].mem.modify = |
312 | 598 | TMS320C64X_MEM_MOD_NO; |
313 | 598 | break; |
314 | 674 | case 8: |
315 | 674 | tms320c64x->operands[tms320c64x->op_count].mem.disptype = |
316 | 674 | TMS320C64X_MEM_DISP_CONSTANT; |
317 | 674 | tms320c64x->operands[tms320c64x->op_count] |
318 | 674 | .mem.direction = TMS320C64X_MEM_DIR_BW; |
319 | 674 | tms320c64x->operands[tms320c64x->op_count].mem.modify = |
320 | 674 | TMS320C64X_MEM_MOD_PRE; |
321 | 674 | break; |
322 | 976 | case 9: |
323 | 976 | tms320c64x->operands[tms320c64x->op_count].mem.disptype = |
324 | 976 | TMS320C64X_MEM_DISP_CONSTANT; |
325 | 976 | tms320c64x->operands[tms320c64x->op_count] |
326 | 976 | .mem.direction = TMS320C64X_MEM_DIR_FW; |
327 | 976 | tms320c64x->operands[tms320c64x->op_count].mem.modify = |
328 | 976 | TMS320C64X_MEM_MOD_PRE; |
329 | 976 | break; |
330 | 760 | case 10: |
331 | 760 | tms320c64x->operands[tms320c64x->op_count].mem.disptype = |
332 | 760 | TMS320C64X_MEM_DISP_CONSTANT; |
333 | 760 | tms320c64x->operands[tms320c64x->op_count] |
334 | 760 | .mem.direction = TMS320C64X_MEM_DIR_BW; |
335 | 760 | tms320c64x->operands[tms320c64x->op_count].mem.modify = |
336 | 760 | TMS320C64X_MEM_MOD_POST; |
337 | 760 | break; |
338 | 767 | case 11: |
339 | 767 | tms320c64x->operands[tms320c64x->op_count].mem.disptype = |
340 | 767 | TMS320C64X_MEM_DISP_CONSTANT; |
341 | 767 | tms320c64x->operands[tms320c64x->op_count] |
342 | 767 | .mem.direction = TMS320C64X_MEM_DIR_FW; |
343 | 767 | tms320c64x->operands[tms320c64x->op_count].mem.modify = |
344 | 767 | TMS320C64X_MEM_MOD_POST; |
345 | 767 | break; |
346 | 736 | case 12: |
347 | 736 | tms320c64x->operands[tms320c64x->op_count].mem.disptype = |
348 | 736 | TMS320C64X_MEM_DISP_REGISTER; |
349 | 736 | tms320c64x->operands[tms320c64x->op_count] |
350 | 736 | .mem.direction = TMS320C64X_MEM_DIR_BW; |
351 | 736 | tms320c64x->operands[tms320c64x->op_count].mem.modify = |
352 | 736 | TMS320C64X_MEM_MOD_PRE; |
353 | 736 | break; |
354 | 659 | case 13: |
355 | 659 | tms320c64x->operands[tms320c64x->op_count].mem.disptype = |
356 | 659 | TMS320C64X_MEM_DISP_REGISTER; |
357 | 659 | tms320c64x->operands[tms320c64x->op_count] |
358 | 659 | .mem.direction = TMS320C64X_MEM_DIR_FW; |
359 | 659 | tms320c64x->operands[tms320c64x->op_count].mem.modify = |
360 | 659 | TMS320C64X_MEM_MOD_PRE; |
361 | 659 | break; |
362 | 573 | case 14: |
363 | 573 | tms320c64x->operands[tms320c64x->op_count].mem.disptype = |
364 | 573 | TMS320C64X_MEM_DISP_REGISTER; |
365 | 573 | tms320c64x->operands[tms320c64x->op_count] |
366 | 573 | .mem.direction = TMS320C64X_MEM_DIR_BW; |
367 | 573 | tms320c64x->operands[tms320c64x->op_count].mem.modify = |
368 | 573 | TMS320C64X_MEM_MOD_POST; |
369 | 573 | break; |
370 | 566 | case 15: |
371 | 566 | tms320c64x->operands[tms320c64x->op_count].mem.disptype = |
372 | 566 | TMS320C64X_MEM_DISP_REGISTER; |
373 | 566 | tms320c64x->operands[tms320c64x->op_count] |
374 | 566 | .mem.direction = TMS320C64X_MEM_DIR_FW; |
375 | 566 | tms320c64x->operands[tms320c64x->op_count].mem.modify = |
376 | 566 | TMS320C64X_MEM_MOD_POST; |
377 | 566 | break; |
378 | 9.02k | } |
379 | 9.02k | tms320c64x->op_count++; |
380 | 9.02k | } |
381 | 9.02k | } |
382 | | |
383 | | static void printMemOperand2(MCInst *MI, unsigned OpNo, SStream *O) |
384 | 5.00k | { |
385 | 5.00k | MCOperand *Op = MCInst_getOperand(MI, OpNo); |
386 | 5.00k | int64_t Val = MCOperand_getImm(Op); |
387 | 5.00k | uint16_t offset; |
388 | 5.00k | unsigned basereg; |
389 | 5.00k | cs_tms320c64x *tms320c64x; |
390 | | |
391 | 5.00k | basereg = Val & 0x7f; |
392 | 5.00k | offset = (Val >> 7) & 0x7fff; |
393 | 5.00k | SStream_concat(O, "*+%s[0x%x]", getRegisterName(basereg), offset); |
394 | | |
395 | 5.00k | if (MI->csh->detail_opt) { |
396 | 5.00k | tms320c64x = &MI->flat_insn->detail->tms320c64x; |
397 | | |
398 | 5.00k | tms320c64x->operands[tms320c64x->op_count].type = |
399 | 5.00k | TMS320C64X_OP_MEM; |
400 | 5.00k | tms320c64x->operands[tms320c64x->op_count].mem.base = basereg; |
401 | 5.00k | tms320c64x->operands[tms320c64x->op_count].mem.unit = 2; |
402 | 5.00k | tms320c64x->operands[tms320c64x->op_count].mem.disp = offset; |
403 | 5.00k | tms320c64x->operands[tms320c64x->op_count].mem.disptype = |
404 | 5.00k | TMS320C64X_MEM_DISP_CONSTANT; |
405 | 5.00k | tms320c64x->operands[tms320c64x->op_count].mem.direction = |
406 | 5.00k | TMS320C64X_MEM_DIR_FW; |
407 | 5.00k | tms320c64x->operands[tms320c64x->op_count].mem.modify = |
408 | 5.00k | TMS320C64X_MEM_MOD_NO; |
409 | 5.00k | tms320c64x->op_count++; |
410 | 5.00k | } |
411 | 5.00k | } |
412 | | |
413 | | static void printRegPair(MCInst *MI, unsigned OpNo, SStream *O) |
414 | 22.5k | { |
415 | 22.5k | MCOperand *Op = MCInst_getOperand(MI, OpNo); |
416 | 22.5k | unsigned reg = MCOperand_getReg(Op); |
417 | 22.5k | cs_tms320c64x *tms320c64x; |
418 | | |
419 | 22.5k | SStream_concat(O, "%s:%s", getRegisterName(reg + 1), |
420 | 22.5k | getRegisterName(reg)); |
421 | | |
422 | 22.5k | if (MI->csh->detail_opt) { |
423 | 22.5k | tms320c64x = &MI->flat_insn->detail->tms320c64x; |
424 | | |
425 | 22.5k | tms320c64x->operands[tms320c64x->op_count].type = |
426 | 22.5k | TMS320C64X_OP_REGPAIR; |
427 | 22.5k | tms320c64x->operands[tms320c64x->op_count].reg = reg; |
428 | 22.5k | tms320c64x->op_count++; |
429 | 22.5k | } |
430 | 22.5k | } |
431 | | |
432 | | static bool printAliasInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) |
433 | 68.3k | { |
434 | 68.3k | unsigned opcode = MCInst_getOpcode(MI); |
435 | 68.3k | MCOperand *op; |
436 | | |
437 | 68.3k | switch (opcode) { |
438 | | /* ADD.Dx -i, x, y -> SUB.Dx x, i, y */ |
439 | 360 | case TMS320C64x_ADD_d2_rir: |
440 | | /* ADD.L -i, x, y -> SUB.L x, i, y */ |
441 | 816 | case TMS320C64x_ADD_l1_irr: |
442 | 1.17k | case TMS320C64x_ADD_l1_ipp: |
443 | | /* ADD.S -i, x, y -> SUB.S x, i, y */ |
444 | 1.78k | case TMS320C64x_ADD_s1_irr: |
445 | 1.78k | if ((MCInst_getNumOperands(MI) == 3) && |
446 | 1.78k | MCOperand_isReg(MCInst_getOperand(MI, 0)) && |
447 | 1.78k | MCOperand_isReg(MCInst_getOperand(MI, 1)) && |
448 | 1.78k | MCOperand_isImm(MCInst_getOperand(MI, 2)) && |
449 | 1.78k | (MCOperand_getImm(MCInst_getOperand(MI, 2)) < 0)) { |
450 | 384 | MCInst_setOpcodePub(MI, TMS320C64X_INS_SUB); |
451 | 384 | op = MCInst_getOperand(MI, 2); |
452 | 384 | MCOperand_setImm(op, -MCOperand_getImm(op)); |
453 | | |
454 | 384 | SStream_concat0(O, "SUB\t"); |
455 | 384 | printOperand(MI, 1, O); |
456 | 384 | SStream_concat0(O, ", "); |
457 | 384 | printOperand(MI, 2, O); |
458 | 384 | SStream_concat0(O, ", "); |
459 | 384 | printOperand(MI, 0, O); |
460 | | |
461 | 384 | return true; |
462 | 384 | } |
463 | 1.39k | break; |
464 | 68.3k | } |
465 | 67.9k | switch (opcode) { |
466 | | /* ADD.D 0, x, y -> MV.D x, y */ |
467 | 145 | case TMS320C64x_ADD_d1_rir: |
468 | | /* OR.D x, 0, y -> MV.D x, y */ |
469 | 556 | case TMS320C64x_OR_d2_rir: |
470 | | /* ADD.L 0, x, y -> MV.L x, y */ |
471 | 966 | case TMS320C64x_ADD_l1_irr: |
472 | 1.25k | case TMS320C64x_ADD_l1_ipp: |
473 | | /* OR.L 0, x, y -> MV.L x, y */ |
474 | 1.41k | case TMS320C64x_OR_l1_irr: |
475 | | /* ADD.S 0, x, y -> MV.S x, y */ |
476 | 1.83k | case TMS320C64x_ADD_s1_irr: |
477 | | /* OR.S 0, x, y -> MV.S x, y */ |
478 | 2.12k | case TMS320C64x_OR_s1_irr: |
479 | 2.12k | if ((MCInst_getNumOperands(MI) == 3) && |
480 | 2.12k | MCOperand_isReg(MCInst_getOperand(MI, 0)) && |
481 | 2.12k | MCOperand_isReg(MCInst_getOperand(MI, 1)) && |
482 | 2.12k | MCOperand_isImm(MCInst_getOperand(MI, 2)) && |
483 | 2.12k | (MCOperand_getImm(MCInst_getOperand(MI, 2)) == 0)) { |
484 | 309 | MCInst_setOpcodePub(MI, TMS320C64X_INS_MV); |
485 | 309 | MI->size--; |
486 | | |
487 | 309 | SStream_concat0(O, "MV\t"); |
488 | 309 | printOperand(MI, 1, O); |
489 | 309 | SStream_concat0(O, ", "); |
490 | 309 | printOperand(MI, 0, O); |
491 | | |
492 | 309 | return true; |
493 | 309 | } |
494 | 1.81k | break; |
495 | 67.9k | } |
496 | 67.6k | switch (opcode) { |
497 | | /* XOR.D -1, x, y -> NOT.D x, y */ |
498 | 441 | case TMS320C64x_XOR_d2_rir: |
499 | | /* XOR.L -1, x, y -> NOT.L x, y */ |
500 | 608 | case TMS320C64x_XOR_l1_irr: |
501 | | /* XOR.S -1, x, y -> NOT.S x, y */ |
502 | 1.07k | case TMS320C64x_XOR_s1_irr: |
503 | 1.07k | if ((MCInst_getNumOperands(MI) == 3) && |
504 | 1.07k | MCOperand_isReg(MCInst_getOperand(MI, 0)) && |
505 | 1.07k | MCOperand_isReg(MCInst_getOperand(MI, 1)) && |
506 | 1.07k | MCOperand_isImm(MCInst_getOperand(MI, 2)) && |
507 | 1.07k | (MCOperand_getImm(MCInst_getOperand(MI, 2)) == -1)) { |
508 | 139 | MCInst_setOpcodePub(MI, TMS320C64X_INS_NOT); |
509 | 139 | MI->size--; |
510 | | |
511 | 139 | SStream_concat0(O, "NOT\t"); |
512 | 139 | printOperand(MI, 1, O); |
513 | 139 | SStream_concat0(O, ", "); |
514 | 139 | printOperand(MI, 0, O); |
515 | | |
516 | 139 | return true; |
517 | 139 | } |
518 | 935 | break; |
519 | 67.6k | } |
520 | 67.5k | switch (opcode) { |
521 | | /* MVK.D 0, x -> ZERO.D x */ |
522 | 1.21k | case TMS320C64x_MVK_d1_rr: |
523 | | /* MVK.L 0, x -> ZERO.L x */ |
524 | 2.55k | case TMS320C64x_MVK_l2_ir: |
525 | 2.55k | if ((MCInst_getNumOperands(MI) == 2) && |
526 | 2.55k | MCOperand_isReg(MCInst_getOperand(MI, 0)) && |
527 | 2.55k | MCOperand_isImm(MCInst_getOperand(MI, 1)) && |
528 | 2.55k | (MCOperand_getImm(MCInst_getOperand(MI, 1)) == 0)) { |
529 | 291 | MCInst_setOpcodePub(MI, TMS320C64X_INS_ZERO); |
530 | 291 | MI->size--; |
531 | | |
532 | 291 | SStream_concat0(O, "ZERO\t"); |
533 | 291 | printOperand(MI, 0, O); |
534 | | |
535 | 291 | return true; |
536 | 291 | } |
537 | 2.25k | break; |
538 | 67.5k | } |
539 | 67.2k | switch (opcode) { |
540 | | /* SUB.L x, x, y -> ZERO.L y */ |
541 | 495 | case TMS320C64x_SUB_l1_rrp_x1: |
542 | | /* SUB.S x, x, y -> ZERO.S y */ |
543 | 876 | case TMS320C64x_SUB_s1_rrr: |
544 | 876 | if ((MCInst_getNumOperands(MI) == 3) && |
545 | 876 | MCOperand_isReg(MCInst_getOperand(MI, 0)) && |
546 | 876 | MCOperand_isReg(MCInst_getOperand(MI, 1)) && |
547 | 876 | MCOperand_isReg(MCInst_getOperand(MI, 2)) && |
548 | 876 | (MCOperand_getReg(MCInst_getOperand(MI, 1)) == |
549 | 876 | MCOperand_getReg(MCInst_getOperand(MI, 2)))) { |
550 | 145 | MCInst_setOpcodePub(MI, TMS320C64X_INS_ZERO); |
551 | 145 | MI->size -= 2; |
552 | | |
553 | 145 | SStream_concat0(O, "ZERO\t"); |
554 | 145 | printOperand(MI, 0, O); |
555 | | |
556 | 145 | return true; |
557 | 145 | } |
558 | 731 | break; |
559 | 67.2k | } |
560 | 67.0k | switch (opcode) { |
561 | | /* SUB.L 0, x, y -> NEG.L x, y */ |
562 | 314 | case TMS320C64x_SUB_l1_irr: |
563 | 873 | case TMS320C64x_SUB_l1_ipp: |
564 | | /* SUB.S 0, x, y -> NEG.S x, y */ |
565 | 1.28k | case TMS320C64x_SUB_s1_irr: |
566 | 1.28k | if ((MCInst_getNumOperands(MI) == 3) && |
567 | 1.28k | MCOperand_isReg(MCInst_getOperand(MI, 0)) && |
568 | 1.28k | MCOperand_isReg(MCInst_getOperand(MI, 1)) && |
569 | 1.28k | MCOperand_isImm(MCInst_getOperand(MI, 2)) && |
570 | 1.28k | (MCOperand_getImm(MCInst_getOperand(MI, 2)) == 0)) { |
571 | 362 | MCInst_setOpcodePub(MI, TMS320C64X_INS_NEG); |
572 | 362 | MI->size--; |
573 | | |
574 | 362 | SStream_concat0(O, "NEG\t"); |
575 | 362 | printOperand(MI, 1, O); |
576 | 362 | SStream_concat0(O, ", "); |
577 | 362 | printOperand(MI, 0, O); |
578 | | |
579 | 362 | return true; |
580 | 362 | } |
581 | 923 | break; |
582 | 67.0k | } |
583 | 66.7k | switch (opcode) { |
584 | | /* PACKLH2.L x, x, y -> SWAP2.L x, y */ |
585 | 319 | case TMS320C64x_PACKLH2_l1_rrr_x2: |
586 | | /* PACKLH2.S x, x, y -> SWAP2.S x, y */ |
587 | 1.06k | case TMS320C64x_PACKLH2_s1_rrr: |
588 | 1.06k | if ((MCInst_getNumOperands(MI) == 3) && |
589 | 1.06k | MCOperand_isReg(MCInst_getOperand(MI, 0)) && |
590 | 1.06k | MCOperand_isReg(MCInst_getOperand(MI, 1)) && |
591 | 1.06k | MCOperand_isReg(MCInst_getOperand(MI, 2)) && |
592 | 1.06k | (MCOperand_getReg(MCInst_getOperand(MI, 1)) == |
593 | 1.06k | MCOperand_getReg(MCInst_getOperand(MI, 2)))) { |
594 | 230 | MCInst_setOpcodePub(MI, TMS320C64X_INS_SWAP2); |
595 | 230 | MI->size--; |
596 | | |
597 | 230 | SStream_concat0(O, "SWAP2\t"); |
598 | 230 | printOperand(MI, 1, O); |
599 | 230 | SStream_concat0(O, ", "); |
600 | 230 | printOperand(MI, 0, O); |
601 | | |
602 | 230 | return true; |
603 | 230 | } |
604 | 836 | break; |
605 | 66.7k | } |
606 | 66.4k | switch (opcode) { |
607 | | /* NOP 16 -> IDLE */ |
608 | | /* NOP 1 -> NOP */ |
609 | 1.74k | case TMS320C64x_NOP_n: |
610 | 1.74k | if ((MCInst_getNumOperands(MI) == 1) && |
611 | 1.74k | MCOperand_isImm(MCInst_getOperand(MI, 0)) && |
612 | 1.74k | (MCOperand_getReg(MCInst_getOperand(MI, 0)) == 16)) { |
613 | 400 | MCInst_setOpcodePub(MI, TMS320C64X_INS_IDLE); |
614 | 400 | MI->size--; |
615 | | |
616 | 400 | SStream_concat0(O, "IDLE"); |
617 | | |
618 | 400 | return true; |
619 | 400 | } |
620 | 1.34k | if ((MCInst_getNumOperands(MI) == 1) && |
621 | 1.34k | MCOperand_isImm(MCInst_getOperand(MI, 0)) && |
622 | 1.34k | (MCOperand_getReg(MCInst_getOperand(MI, 0)) == 1)) { |
623 | 793 | MI->size--; |
624 | | |
625 | 793 | SStream_concat0(O, "NOP"); |
626 | | |
627 | 793 | return true; |
628 | 793 | } |
629 | 550 | break; |
630 | 66.4k | } |
631 | | |
632 | 65.3k | return false; |
633 | 66.4k | } |
634 | | |
635 | | void TMS320C64x_printInst(MCInst *MI, SStream *O, void *Info) |
636 | 68.3k | { |
637 | 68.3k | if (!printAliasInstruction(MI, O, Info)) |
638 | 65.3k | printInstruction(MI, O, Info); |
639 | 68.3k | } |
640 | | |
641 | | #endif |