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