Change source files over to GPLv3.
[deliverable/binutils-gdb.git] / opcodes / tic30-dis.c
CommitLineData
252b5132 1/* Disassembly routines for TMS320C30 architecture
9b201bb5 2 Copyright 1998, 1999, 2000, 2002, 2005, 2007 Free Software Foundation, Inc.
252b5132
RH
3 Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au)
4
9b201bb5
NC
5 This file is part of the GNU opcodes library.
6
7 This library is free software; you can redistribute it and/or modify
252b5132 8 it under the terms of the GNU General Public License as published by
9b201bb5
NC
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
252b5132 11
9b201bb5
NC
12 It is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
252b5132
RH
16
17 You should have received a copy of the GNU General Public License
9b201bb5
NC
18 along with this file; see the file COPYING. If not, write to the
19 Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
252b5132
RH
21
22#include <errno.h>
23#include <math.h>
6094e721 24#include "sysdep.h"
252b5132
RH
25#include "dis-asm.h"
26#include "opcode/tic30.h"
27
28#define NORMAL_INSN 1
29#define PARALLEL_INSN 2
30
31/* Gets the type of instruction based on the top 2 or 3 bits of the
bf830eae 32 instruction word. */
252b5132
RH
33#define GET_TYPE(insn) (insn & 0x80000000 ? insn & 0xC0000000 : insn & 0xE0000000)
34
bf830eae 35/* Instruction types. */
252b5132
RH
36#define TWO_OPERAND_1 0x00000000
37#define TWO_OPERAND_2 0x40000000
38#define THREE_OPERAND 0x20000000
39#define PAR_STORE 0xC0000000
40#define MUL_ADDS 0x80000000
41#define BRANCHES 0x60000000
42
bf830eae 43/* Specific instruction id bits. */
252b5132
RH
44#define NORMAL_IDEN 0x1F800000
45#define PAR_STORE_IDEN 0x3E000000
46#define MUL_ADD_IDEN 0x2C000000
47#define BR_IMM_IDEN 0x1F000000
48#define BR_COND_IDEN 0x1C3F0000
49
bf830eae 50/* Addressing modes. */
252b5132
RH
51#define AM_REGISTER 0x00000000
52#define AM_DIRECT 0x00200000
53#define AM_INDIRECT 0x00400000
54#define AM_IMM 0x00600000
55
56#define P_FIELD 0x03000000
57
58#define REG_AR0 0x08
59#define LDP_INSN 0x08700000
60
bf830eae 61/* TMS320C30 program counter for current instruction. */
252b5132
RH
62static unsigned int _pc;
63
64struct instruction
bf830eae
KH
65{
66 int type;
67 template *tm;
68 partemplate *ptm;
69};
252b5132 70
47b0e7ad
NC
71static int
72get_tic30_instruction (unsigned long insn_word, struct instruction *insn)
252b5132
RH
73{
74 switch (GET_TYPE (insn_word))
75 {
76 case TWO_OPERAND_1:
77 case TWO_OPERAND_2:
78 case THREE_OPERAND:
79 insn->type = NORMAL_INSN;
80 {
81 template *current_optab = (template *) tic30_optab;
47b0e7ad 82
252b5132
RH
83 for (; current_optab < tic30_optab_end; current_optab++)
84 {
85 if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
86 {
87 if (current_optab->operands == 0)
88 {
89 if (current_optab->base_opcode == insn_word)
90 {
91 insn->tm = current_optab;
92 break;
93 }
94 }
95 else if ((current_optab->base_opcode & NORMAL_IDEN) == (insn_word & NORMAL_IDEN))
96 {
97 insn->tm = current_optab;
98 break;
99 }
100 }
101 }
102 }
103 break;
47b0e7ad 104
252b5132
RH
105 case PAR_STORE:
106 insn->type = PARALLEL_INSN;
107 {
108 partemplate *current_optab = (partemplate *) tic30_paroptab;
47b0e7ad 109
252b5132
RH
110 for (; current_optab < tic30_paroptab_end; current_optab++)
111 {
112 if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
113 {
47b0e7ad
NC
114 if ((current_optab->base_opcode & PAR_STORE_IDEN)
115 == (insn_word & PAR_STORE_IDEN))
252b5132
RH
116 {
117 insn->ptm = current_optab;
118 break;
119 }
120 }
121 }
122 }
123 break;
47b0e7ad 124
252b5132
RH
125 case MUL_ADDS:
126 insn->type = PARALLEL_INSN;
127 {
128 partemplate *current_optab = (partemplate *) tic30_paroptab;
47b0e7ad 129
252b5132
RH
130 for (; current_optab < tic30_paroptab_end; current_optab++)
131 {
132 if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
133 {
47b0e7ad
NC
134 if ((current_optab->base_opcode & MUL_ADD_IDEN)
135 == (insn_word & MUL_ADD_IDEN))
252b5132
RH
136 {
137 insn->ptm = current_optab;
138 break;
139 }
140 }
141 }
142 }
143 break;
47b0e7ad 144
252b5132
RH
145 case BRANCHES:
146 insn->type = NORMAL_INSN;
147 {
148 template *current_optab = (template *) tic30_optab;
47b0e7ad 149
252b5132
RH
150 for (; current_optab < tic30_optab_end; current_optab++)
151 {
152 if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
153 {
154 if (current_optab->operand_types[0] & Imm24)
155 {
47b0e7ad
NC
156 if ((current_optab->base_opcode & BR_IMM_IDEN)
157 == (insn_word & BR_IMM_IDEN))
252b5132
RH
158 {
159 insn->tm = current_optab;
160 break;
161 }
162 }
163 else if (current_optab->operands > 0)
164 {
47b0e7ad
NC
165 if ((current_optab->base_opcode & BR_COND_IDEN)
166 == (insn_word & BR_COND_IDEN))
252b5132
RH
167 {
168 insn->tm = current_optab;
169 break;
170 }
171 }
172 else
173 {
47b0e7ad
NC
174 if ((current_optab->base_opcode & (BR_COND_IDEN | 0x00800000))
175 == (insn_word & (BR_COND_IDEN | 0x00800000)))
252b5132
RH
176 {
177 insn->tm = current_optab;
178 break;
179 }
180 }
181 }
182 }
183 }
184 break;
185 default:
186 return 0;
187 }
188 return 1;
189}
190
47b0e7ad
NC
191static int
192get_register_operand (unsigned char fragment, char *buffer)
193{
194 const reg *current_reg = tic30_regtab;
195
196 if (buffer == NULL)
197 return 0;
198 for (; current_reg < tic30_regtab_end; current_reg++)
199 {
200 if ((fragment & 0x1F) == current_reg->opcode)
201 {
202 strcpy (buffer, current_reg->name);
203 return 1;
204 }
205 }
206 return 0;
207}
208
209static int
210get_indirect_operand (unsigned short fragment,
211 int size,
212 char *buffer)
213{
214 unsigned char mod;
215 unsigned arnum;
216 unsigned char disp;
217
218 if (buffer == NULL)
219 return 0;
220 /* Determine which bits identify the sections of the indirect
221 operand based on the size in bytes. */
222 switch (size)
223 {
224 case 1:
225 mod = (fragment & 0x00F8) >> 3;
226 arnum = (fragment & 0x0007);
227 disp = 0;
228 break;
229 case 2:
230 mod = (fragment & 0xF800) >> 11;
231 arnum = (fragment & 0x0700) >> 8;
232 disp = (fragment & 0x00FF);
233 break;
234 default:
235 return 0;
236 }
237 {
238 const ind_addr_type *current_ind = tic30_indaddr_tab;
239
240 for (; current_ind < tic30_indaddrtab_end; current_ind++)
241 {
242 if (current_ind->modfield == mod)
243 {
244 if (current_ind->displacement == IMPLIED_DISP && size == 2)
245 continue;
246
247 else
248 {
249 size_t i, len;
250 int bufcnt;
251
252 len = strlen (current_ind->syntax);
253 for (i = 0, bufcnt = 0; i < len; i++, bufcnt++)
254 {
255 buffer[bufcnt] = current_ind->syntax[i];
256 if (buffer[bufcnt - 1] == 'a' && buffer[bufcnt] == 'r')
257 buffer[++bufcnt] = arnum + '0';
258 if (buffer[bufcnt] == '('
259 && current_ind->displacement == DISP_REQUIRED)
260 {
261 sprintf (&buffer[bufcnt + 1], "%u", disp);
262 bufcnt += strlen (&buffer[bufcnt + 1]);
263 }
264 }
265 buffer[bufcnt + 1] = '\0';
266 break;
267 }
268 }
269 }
270 }
271 return 1;
272}
273
274static int
275cnvt_tmsfloat_ieee (unsigned long tmsfloat, int size, float *ieeefloat)
276{
277 unsigned long exp, sign, mant;
278 union
279 {
280 unsigned long l;
281 float f;
282 } val;
283
284 if (size == 2)
285 {
286 if ((tmsfloat & 0x0000F000) == 0x00008000)
287 tmsfloat = 0x80000000;
288 else
289 {
290 tmsfloat <<= 16;
291 tmsfloat = (long) tmsfloat >> 4;
292 }
293 }
294 exp = tmsfloat & 0xFF000000;
295 if (exp == 0x80000000)
296 {
297 *ieeefloat = 0.0;
298 return 1;
299 }
300 exp += 0x7F000000;
301 sign = (tmsfloat & 0x00800000) << 8;
302 mant = tmsfloat & 0x007FFFFF;
303 if (exp == 0xFF000000)
304 {
305 if (mant == 0)
306 *ieeefloat = ERANGE;
b0eec63e
L
307#ifdef HUGE_VALF
308 if (sign == 0)
309 *ieeefloat = HUGE_VALF;
310 else
311 *ieeefloat = -HUGE_VALF;
312#else
47b0e7ad
NC
313 if (sign == 0)
314 *ieeefloat = 1.0 / 0.0;
315 else
316 *ieeefloat = -1.0 / 0.0;
b0eec63e 317#endif
47b0e7ad
NC
318 return 1;
319 }
320 exp >>= 1;
321 if (sign)
322 {
323 mant = (~mant) & 0x007FFFFF;
324 mant += 1;
325 exp += mant & 0x00800000;
326 exp &= 0x7F800000;
327 mant &= 0x007FFFFF;
328 }
329 if (tmsfloat == 0x80000000)
330 sign = mant = exp = 0;
331 tmsfloat = sign | exp | mant;
332 val.l = tmsfloat;
333 *ieeefloat = val.f;
334 return 1;
335}
336
337static int
338print_two_operand (disassemble_info *info,
339 unsigned long insn_word,
340 struct instruction *insn)
252b5132
RH
341{
342 char name[12];
343 char operand[2][13] =
344 {
345 {0},
47b0e7ad
NC
346 {0}
347 };
252b5132
RH
348 float f_number;
349
350 if (insn->tm == NULL)
351 return 0;
352 strcpy (name, insn->tm->name);
353 if (insn->tm->opcode_modifier == AddressMode)
354 {
355 int src_op, dest_op;
bf830eae 356 /* Determine whether instruction is a store or a normal instruction. */
47b0e7ad
NC
357 if ((insn->tm->operand_types[1] & (Direct | Indirect))
358 == (Direct | Indirect))
252b5132
RH
359 {
360 src_op = 1;
361 dest_op = 0;
362 }
363 else
364 {
365 src_op = 0;
366 dest_op = 1;
367 }
bf830eae 368 /* Get the destination register. */
252b5132
RH
369 if (insn->tm->operands == 2)
370 get_register_operand ((insn_word & 0x001F0000) >> 16, operand[dest_op]);
bf830eae 371 /* Get the source operand based on addressing mode. */
252b5132
RH
372 switch (insn_word & AddressMode)
373 {
374 case AM_REGISTER:
bf830eae 375 /* Check for the NOP instruction before getting the operand. */
252b5132
RH
376 if ((insn->tm->operand_types[0] & NotReq) == 0)
377 get_register_operand ((insn_word & 0x0000001F), operand[src_op]);
378 break;
379 case AM_DIRECT:
380 sprintf (operand[src_op], "@0x%lX", (insn_word & 0x0000FFFF));
381 break;
382 case AM_INDIRECT:
383 get_indirect_operand ((insn_word & 0x0000FFFF), 2, operand[src_op]);
384 break;
385 case AM_IMM:
bf830eae 386 /* Get the value of the immediate operand based on variable type. */
252b5132
RH
387 switch (insn->tm->imm_arg_type)
388 {
389 case Imm_Float:
390 cnvt_tmsfloat_ieee ((insn_word & 0x0000FFFF), 2, &f_number);
391 sprintf (operand[src_op], "%2.2f", f_number);
392 break;
393 case Imm_SInt:
394 sprintf (operand[src_op], "%d", (short) (insn_word & 0x0000FFFF));
395 break;
396 case Imm_UInt:
397 sprintf (operand[src_op], "%lu", (insn_word & 0x0000FFFF));
398 break;
399 default:
400 return 0;
401 }
bf830eae 402 /* Handle special case for LDP instruction. */
252b5132
RH
403 if ((insn_word & 0xFFFFFF00) == LDP_INSN)
404 {
405 strcpy (name, "ldp");
406 sprintf (operand[0], "0x%06lX", (insn_word & 0x000000FF) << 16);
407 operand[1][0] = '\0';
408 }
409 }
410 }
bf830eae 411 /* Handle case for stack and rotate instructions. */
252b5132
RH
412 else if (insn->tm->operands == 1)
413 {
414 if (insn->tm->opcode_modifier == StackOp)
47b0e7ad 415 get_register_operand ((insn_word & 0x001F0000) >> 16, operand[0]);
252b5132 416 }
bf830eae 417 /* Output instruction to stream. */
252b5132
RH
418 info->fprintf_func (info->stream, " %s %s%c%s", name,
419 operand[0][0] ? operand[0] : "",
420 operand[1][0] ? ',' : ' ',
421 operand[1][0] ? operand[1] : "");
422 return 1;
423}
424
47b0e7ad
NC
425static int
426print_three_operand (disassemble_info *info,
427 unsigned long insn_word,
428 struct instruction *insn)
252b5132
RH
429{
430 char operand[3][13] =
431 {
432 {0},
433 {0},
47b0e7ad
NC
434 {0}
435 };
252b5132
RH
436
437 if (insn->tm == NULL)
438 return 0;
439 switch (insn_word & AddressMode)
440 {
441 case AM_REGISTER:
442 get_register_operand ((insn_word & 0x000000FF), operand[0]);
443 get_register_operand ((insn_word & 0x0000FF00) >> 8, operand[1]);
444 break;
445 case AM_DIRECT:
446 get_register_operand ((insn_word & 0x000000FF), operand[0]);
447 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1]);
448 break;
449 case AM_INDIRECT:
450 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0]);
451 get_register_operand ((insn_word & 0x0000FF00) >> 8, operand[1]);
452 break;
453 case AM_IMM:
454 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0]);
455 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1]);
456 break;
457 default:
458 return 0;
459 }
460 if (insn->tm->operands == 3)
461 get_register_operand ((insn_word & 0x001F0000) >> 16, operand[2]);
462 info->fprintf_func (info->stream, " %s %s,%s%c%s", insn->tm->name,
463 operand[0], operand[1],
464 operand[2][0] ? ',' : ' ',
465 operand[2][0] ? operand[2] : "");
466 return 1;
467}
468
47b0e7ad
NC
469static int
470print_par_insn (disassemble_info *info,
471 unsigned long insn_word,
472 struct instruction *insn)
252b5132
RH
473{
474 size_t i, len;
475 char *name1, *name2;
476 char operand[2][3][13] =
477 {
478 {
479 {0},
480 {0},
47b0e7ad
NC
481 {0}
482 },
252b5132
RH
483 {
484 {0},
485 {0},
47b0e7ad
NC
486 {0}
487 }
488 };
252b5132
RH
489
490 if (insn->ptm == NULL)
491 return 0;
492 /* Parse out the names of each of the parallel instructions from the
bf830eae 493 q_insn1_insn2 format. */
252b5132
RH
494 name1 = (char *) strdup (insn->ptm->name + 2);
495 name2 = "";
496 len = strlen (name1);
497 for (i = 0; i < len; i++)
498 {
499 if (name1[i] == '_')
500 {
501 name2 = &name1[i + 1];
502 name1[i] = '\0';
503 break;
504 }
505 }
bf830eae 506 /* Get the operands of the instruction based on the operand order. */
252b5132
RH
507 switch (insn->ptm->oporder)
508 {
509 case OO_4op1:
510 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
511 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
512 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
513 get_register_operand ((insn_word >> 22) & 0x07, operand[0][1]);
514 break;
515 case OO_4op2:
516 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
517 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][0]);
518 get_register_operand ((insn_word >> 19) & 0x07, operand[1][1]);
519 get_register_operand ((insn_word >> 22) & 0x07, operand[0][1]);
520 break;
521 case OO_4op3:
522 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
523 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
524 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
525 get_register_operand ((insn_word >> 22) & 0x07, operand[0][0]);
526 break;
527 case OO_5op1:
528 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
529 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
530 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
531 get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
532 get_register_operand ((insn_word >> 22) & 0x07, operand[0][2]);
533 break;
534 case OO_5op2:
535 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
536 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
537 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
538 get_register_operand ((insn_word >> 19) & 0x07, operand[0][0]);
539 get_register_operand ((insn_word >> 22) & 0x07, operand[0][2]);
540 break;
541 case OO_PField:
542 if (insn_word & 0x00800000)
543 get_register_operand (0x01, operand[0][2]);
544 else
545 get_register_operand (0x00, operand[0][2]);
546 if (insn_word & 0x00400000)
547 get_register_operand (0x03, operand[1][2]);
548 else
549 get_register_operand (0x02, operand[1][2]);
550 switch (insn_word & P_FIELD)
551 {
552 case 0x00000000:
553 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
554 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
555 get_register_operand ((insn_word >> 16) & 0x07, operand[1][1]);
556 get_register_operand ((insn_word >> 19) & 0x07, operand[1][0]);
557 break;
558 case 0x01000000:
559 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][0]);
560 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
561 get_register_operand ((insn_word >> 16) & 0x07, operand[1][1]);
562 get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
563 break;
564 case 0x02000000:
565 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][1]);
566 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][0]);
567 get_register_operand ((insn_word >> 16) & 0x07, operand[0][1]);
568 get_register_operand ((insn_word >> 19) & 0x07, operand[0][0]);
569 break;
570 case 0x03000000:
571 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][1]);
572 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
573 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
574 get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
575 break;
576 }
577 break;
578 default:
579 return 0;
580 }
581 info->fprintf_func (info->stream, " %s %s,%s%c%s", name1,
582 operand[0][0], operand[0][1],
583 operand[0][2][0] ? ',' : ' ',
584 operand[0][2][0] ? operand[0][2] : "");
585 info->fprintf_func (info->stream, "\n\t\t\t|| %s %s,%s%c%s", name2,
586 operand[1][0], operand[1][1],
587 operand[1][2][0] ? ',' : ' ',
588 operand[1][2][0] ? operand[1][2] : "");
589 free (name1);
590 return 1;
591}
592
47b0e7ad
NC
593static int
594print_branch (disassemble_info *info,
595 unsigned long insn_word,
596 struct instruction *insn)
252b5132
RH
597{
598 char operand[2][13] =
599 {
600 {0},
47b0e7ad
NC
601 {0}
602 };
252b5132
RH
603 unsigned long address;
604 int print_label = 0;
605
606 if (insn->tm == NULL)
607 return 0;
bf830eae 608 /* Get the operands for 24-bit immediate jumps. */
252b5132
RH
609 if (insn->tm->operand_types[0] & Imm24)
610 {
611 address = insn_word & 0x00FFFFFF;
612 sprintf (operand[0], "0x%lX", address);
613 print_label = 1;
614 }
bf830eae 615 /* Get the operand for the trap instruction. */
252b5132
RH
616 else if (insn->tm->operand_types[0] & IVector)
617 {
618 address = insn_word & 0x0000001F;
619 sprintf (operand[0], "0x%lX", address);
620 }
621 else
622 {
623 address = insn_word & 0x0000FFFF;
bf830eae 624 /* Get the operands for the DB instructions. */
252b5132
RH
625 if (insn->tm->operands == 2)
626 {
627 get_register_operand (((insn_word & 0x01C00000) >> 22) + REG_AR0, operand[0]);
628 if (insn_word & PCRel)
629 {
630 sprintf (operand[1], "%d", (short) address);
631 print_label = 1;
632 }
633 else
634 get_register_operand (insn_word & 0x0000001F, operand[1]);
635 }
bf830eae 636 /* Get the operands for the standard branches. */
252b5132
RH
637 else if (insn->tm->operands == 1)
638 {
639 if (insn_word & PCRel)
640 {
641 address = (short) address;
642 sprintf (operand[0], "%ld", address);
643 print_label = 1;
644 }
645 else
646 get_register_operand (insn_word & 0x0000001F, operand[0]);
647 }
648 }
649 info->fprintf_func (info->stream, " %s %s%c%s", insn->tm->name,
650 operand[0][0] ? operand[0] : "",
651 operand[1][0] ? ',' : ' ',
652 operand[1][0] ? operand[1] : "");
bf830eae 653 /* Print destination of branch in relation to current symbol. */
252b5132
RH
654 if (print_label && info->symbols)
655 {
656 asymbol *sym = *info->symbols;
657
658 if ((insn->tm->opcode_modifier == PCRel) && (insn_word & PCRel))
659 {
660 address = (_pc + 1 + (short) address) - ((sym->section->vma + sym->value) / 4);
bf830eae 661 /* Check for delayed instruction, if so adjust destination. */
252b5132
RH
662 if (insn_word & 0x00200000)
663 address += 2;
664 }
665 else
666 {
667 address -= ((sym->section->vma + sym->value) / 4);
668 }
669 if (address == 0)
670 info->fprintf_func (info->stream, " <%s>", sym->name);
671 else
672 info->fprintf_func (info->stream, " <%s %c %d>", sym->name,
673 ((short) address < 0) ? '-' : '+',
674 abs (address));
675 }
676 return 1;
677}
678
679int
47b0e7ad 680print_insn_tic30 (bfd_vma pc, disassemble_info *info)
252b5132 681{
47b0e7ad
NC
682 unsigned long insn_word;
683 struct instruction insn = { 0, NULL, NULL };
684 bfd_vma bufaddr = pc - info->buffer_vma;
252b5132 685
47b0e7ad
NC
686 /* Obtain the current instruction word from the buffer. */
687 insn_word = (*(info->buffer + bufaddr) << 24) | (*(info->buffer + bufaddr + 1) << 16) |
688 (*(info->buffer + bufaddr + 2) << 8) | *(info->buffer + bufaddr + 3);
689 _pc = pc / 4;
690 /* Get the instruction refered to by the current instruction word
691 and print it out based on its type. */
692 if (!get_tic30_instruction (insn_word, &insn))
693 return -1;
694 switch (GET_TYPE (insn_word))
252b5132 695 {
47b0e7ad
NC
696 case TWO_OPERAND_1:
697 case TWO_OPERAND_2:
698 if (!print_two_operand (info, insn_word, &insn))
699 return -1;
252b5132 700 break;
47b0e7ad
NC
701 case THREE_OPERAND:
702 if (!print_three_operand (info, insn_word, &insn))
703 return -1;
704 break;
705 case PAR_STORE:
706 case MUL_ADDS:
707 if (!print_par_insn (info, insn_word, &insn))
708 return -1;
709 break;
710 case BRANCHES:
711 if (!print_branch (info, insn_word, &insn))
712 return -1;
252b5132 713 break;
252b5132 714 }
47b0e7ad 715 return 4;
252b5132 716}
This page took 0.494398 seconds and 4 git commands to generate.