gdb: Ensure that !(a < a) is true in sort_cmp on obj_section objects
[deliverable/binutils-gdb.git] / opcodes / tic30-dis.c
CommitLineData
252b5132 1/* Disassembly routines for TMS320C30 architecture
82704155 2 Copyright (C) 1998-2019 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 21
df7b86aa 22#include "sysdep.h"
252b5132
RH
23#include <errno.h>
24#include <math.h>
88c1242d 25#include "disassemble.h"
252b5132
RH
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;
d3ce72d0 67 insn_template *tm;
bf830eae
KH
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 {
d3ce72d0 81 insn_template *current_optab = (insn_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 {
d3ce72d0 148 insn_template *current_optab = (insn_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];
f44b758d
NC
256 if (bufcnt > 0
257 && buffer[bufcnt - 1] == 'a'
258 && buffer[bufcnt] == 'r')
47b0e7ad
NC
259 buffer[++bufcnt] = arnum + '0';
260 if (buffer[bufcnt] == '('
261 && current_ind->displacement == DISP_REQUIRED)
262 {
263 sprintf (&buffer[bufcnt + 1], "%u", disp);
264 bufcnt += strlen (&buffer[bufcnt + 1]);
265 }
266 }
267 buffer[bufcnt + 1] = '\0';
268 break;
269 }
270 }
271 }
272 }
273 return 1;
274}
275
276static int
277cnvt_tmsfloat_ieee (unsigned long tmsfloat, int size, float *ieeefloat)
278{
91d6fa6a 279 unsigned long exponent, sign, mant;
47b0e7ad
NC
280 union
281 {
282 unsigned long l;
283 float f;
284 } val;
285
286 if (size == 2)
287 {
288 if ((tmsfloat & 0x0000F000) == 0x00008000)
289 tmsfloat = 0x80000000;
290 else
291 {
292 tmsfloat <<= 16;
293 tmsfloat = (long) tmsfloat >> 4;
294 }
295 }
91d6fa6a
NC
296 exponent = tmsfloat & 0xFF000000;
297 if (exponent == 0x80000000)
47b0e7ad
NC
298 {
299 *ieeefloat = 0.0;
300 return 1;
301 }
91d6fa6a 302 exponent += 0x7F000000;
47b0e7ad
NC
303 sign = (tmsfloat & 0x00800000) << 8;
304 mant = tmsfloat & 0x007FFFFF;
91d6fa6a 305 if (exponent == 0xFF000000)
47b0e7ad
NC
306 {
307 if (mant == 0)
308 *ieeefloat = ERANGE;
b0eec63e
L
309#ifdef HUGE_VALF
310 if (sign == 0)
311 *ieeefloat = HUGE_VALF;
312 else
313 *ieeefloat = -HUGE_VALF;
314#else
47b0e7ad
NC
315 if (sign == 0)
316 *ieeefloat = 1.0 / 0.0;
317 else
318 *ieeefloat = -1.0 / 0.0;
b0eec63e 319#endif
47b0e7ad
NC
320 return 1;
321 }
91d6fa6a 322 exponent >>= 1;
47b0e7ad
NC
323 if (sign)
324 {
325 mant = (~mant) & 0x007FFFFF;
326 mant += 1;
91d6fa6a
NC
327 exponent += mant & 0x00800000;
328 exponent &= 0x7F800000;
47b0e7ad
NC
329 mant &= 0x007FFFFF;
330 }
331 if (tmsfloat == 0x80000000)
91d6fa6a
NC
332 sign = mant = exponent = 0;
333 tmsfloat = sign | exponent | mant;
47b0e7ad
NC
334 val.l = tmsfloat;
335 *ieeefloat = val.f;
336 return 1;
337}
338
339static int
340print_two_operand (disassemble_info *info,
341 unsigned long insn_word,
342 struct instruction *insn)
252b5132
RH
343{
344 char name[12];
345 char operand[2][13] =
346 {
347 {0},
47b0e7ad
NC
348 {0}
349 };
252b5132
RH
350 float f_number;
351
352 if (insn->tm == NULL)
353 return 0;
354 strcpy (name, insn->tm->name);
355 if (insn->tm->opcode_modifier == AddressMode)
356 {
357 int src_op, dest_op;
bf830eae 358 /* Determine whether instruction is a store or a normal instruction. */
47b0e7ad
NC
359 if ((insn->tm->operand_types[1] & (Direct | Indirect))
360 == (Direct | Indirect))
252b5132
RH
361 {
362 src_op = 1;
363 dest_op = 0;
364 }
365 else
366 {
367 src_op = 0;
368 dest_op = 1;
369 }
bf830eae 370 /* Get the destination register. */
252b5132
RH
371 if (insn->tm->operands == 2)
372 get_register_operand ((insn_word & 0x001F0000) >> 16, operand[dest_op]);
bf830eae 373 /* Get the source operand based on addressing mode. */
252b5132
RH
374 switch (insn_word & AddressMode)
375 {
376 case AM_REGISTER:
bf830eae 377 /* Check for the NOP instruction before getting the operand. */
252b5132
RH
378 if ((insn->tm->operand_types[0] & NotReq) == 0)
379 get_register_operand ((insn_word & 0x0000001F), operand[src_op]);
380 break;
381 case AM_DIRECT:
382 sprintf (operand[src_op], "@0x%lX", (insn_word & 0x0000FFFF));
383 break;
384 case AM_INDIRECT:
385 get_indirect_operand ((insn_word & 0x0000FFFF), 2, operand[src_op]);
386 break;
387 case AM_IMM:
bf830eae 388 /* Get the value of the immediate operand based on variable type. */
252b5132
RH
389 switch (insn->tm->imm_arg_type)
390 {
391 case Imm_Float:
392 cnvt_tmsfloat_ieee ((insn_word & 0x0000FFFF), 2, &f_number);
393 sprintf (operand[src_op], "%2.2f", f_number);
394 break;
395 case Imm_SInt:
396 sprintf (operand[src_op], "%d", (short) (insn_word & 0x0000FFFF));
397 break;
398 case Imm_UInt:
399 sprintf (operand[src_op], "%lu", (insn_word & 0x0000FFFF));
400 break;
401 default:
402 return 0;
403 }
bf830eae 404 /* Handle special case for LDP instruction. */
252b5132
RH
405 if ((insn_word & 0xFFFFFF00) == LDP_INSN)
406 {
407 strcpy (name, "ldp");
408 sprintf (operand[0], "0x%06lX", (insn_word & 0x000000FF) << 16);
409 operand[1][0] = '\0';
410 }
411 }
412 }
bf830eae 413 /* Handle case for stack and rotate instructions. */
252b5132
RH
414 else if (insn->tm->operands == 1)
415 {
416 if (insn->tm->opcode_modifier == StackOp)
47b0e7ad 417 get_register_operand ((insn_word & 0x001F0000) >> 16, operand[0]);
252b5132 418 }
bf830eae 419 /* Output instruction to stream. */
252b5132
RH
420 info->fprintf_func (info->stream, " %s %s%c%s", name,
421 operand[0][0] ? operand[0] : "",
422 operand[1][0] ? ',' : ' ',
423 operand[1][0] ? operand[1] : "");
424 return 1;
425}
426
47b0e7ad
NC
427static int
428print_three_operand (disassemble_info *info,
429 unsigned long insn_word,
430 struct instruction *insn)
252b5132
RH
431{
432 char operand[3][13] =
433 {
434 {0},
435 {0},
47b0e7ad
NC
436 {0}
437 };
252b5132
RH
438
439 if (insn->tm == NULL)
440 return 0;
441 switch (insn_word & AddressMode)
442 {
443 case AM_REGISTER:
444 get_register_operand ((insn_word & 0x000000FF), operand[0]);
445 get_register_operand ((insn_word & 0x0000FF00) >> 8, operand[1]);
446 break;
447 case AM_DIRECT:
448 get_register_operand ((insn_word & 0x000000FF), operand[0]);
449 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1]);
450 break;
451 case AM_INDIRECT:
452 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0]);
453 get_register_operand ((insn_word & 0x0000FF00) >> 8, operand[1]);
454 break;
455 case AM_IMM:
456 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0]);
457 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1]);
458 break;
459 default:
460 return 0;
461 }
462 if (insn->tm->operands == 3)
463 get_register_operand ((insn_word & 0x001F0000) >> 16, operand[2]);
464 info->fprintf_func (info->stream, " %s %s,%s%c%s", insn->tm->name,
465 operand[0], operand[1],
466 operand[2][0] ? ',' : ' ',
467 operand[2][0] ? operand[2] : "");
468 return 1;
469}
470
47b0e7ad
NC
471static int
472print_par_insn (disassemble_info *info,
473 unsigned long insn_word,
474 struct instruction *insn)
252b5132
RH
475{
476 size_t i, len;
477 char *name1, *name2;
478 char operand[2][3][13] =
479 {
480 {
481 {0},
482 {0},
47b0e7ad
NC
483 {0}
484 },
252b5132
RH
485 {
486 {0},
487 {0},
47b0e7ad
NC
488 {0}
489 }
490 };
252b5132
RH
491
492 if (insn->ptm == NULL)
493 return 0;
494 /* Parse out the names of each of the parallel instructions from the
bf830eae 495 q_insn1_insn2 format. */
252b5132
RH
496 name1 = (char *) strdup (insn->ptm->name + 2);
497 name2 = "";
498 len = strlen (name1);
499 for (i = 0; i < len; i++)
500 {
501 if (name1[i] == '_')
502 {
503 name2 = &name1[i + 1];
504 name1[i] = '\0';
505 break;
506 }
507 }
bf830eae 508 /* Get the operands of the instruction based on the operand order. */
252b5132
RH
509 switch (insn->ptm->oporder)
510 {
511 case OO_4op1:
512 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
513 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
514 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
515 get_register_operand ((insn_word >> 22) & 0x07, operand[0][1]);
516 break;
517 case OO_4op2:
518 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
519 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][0]);
520 get_register_operand ((insn_word >> 19) & 0x07, operand[1][1]);
521 get_register_operand ((insn_word >> 22) & 0x07, operand[0][1]);
522 break;
523 case OO_4op3:
524 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
525 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
526 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
527 get_register_operand ((insn_word >> 22) & 0x07, operand[0][0]);
528 break;
529 case OO_5op1:
530 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
531 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
532 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
533 get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
534 get_register_operand ((insn_word >> 22) & 0x07, operand[0][2]);
535 break;
536 case OO_5op2:
537 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
538 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
539 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
540 get_register_operand ((insn_word >> 19) & 0x07, operand[0][0]);
541 get_register_operand ((insn_word >> 22) & 0x07, operand[0][2]);
542 break;
543 case OO_PField:
544 if (insn_word & 0x00800000)
545 get_register_operand (0x01, operand[0][2]);
546 else
547 get_register_operand (0x00, operand[0][2]);
548 if (insn_word & 0x00400000)
549 get_register_operand (0x03, operand[1][2]);
550 else
551 get_register_operand (0x02, operand[1][2]);
552 switch (insn_word & P_FIELD)
553 {
554 case 0x00000000:
555 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
556 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
557 get_register_operand ((insn_word >> 16) & 0x07, operand[1][1]);
558 get_register_operand ((insn_word >> 19) & 0x07, operand[1][0]);
559 break;
560 case 0x01000000:
561 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][0]);
562 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
563 get_register_operand ((insn_word >> 16) & 0x07, operand[1][1]);
564 get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
565 break;
566 case 0x02000000:
567 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][1]);
568 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][0]);
569 get_register_operand ((insn_word >> 16) & 0x07, operand[0][1]);
570 get_register_operand ((insn_word >> 19) & 0x07, operand[0][0]);
571 break;
572 case 0x03000000:
573 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][1]);
574 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
575 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
576 get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
577 break;
578 }
579 break;
580 default:
581 return 0;
582 }
583 info->fprintf_func (info->stream, " %s %s,%s%c%s", name1,
584 operand[0][0], operand[0][1],
585 operand[0][2][0] ? ',' : ' ',
586 operand[0][2][0] ? operand[0][2] : "");
587 info->fprintf_func (info->stream, "\n\t\t\t|| %s %s,%s%c%s", name2,
588 operand[1][0], operand[1][1],
589 operand[1][2][0] ? ',' : ' ',
590 operand[1][2][0] ? operand[1][2] : "");
591 free (name1);
592 return 1;
593}
594
47b0e7ad
NC
595static int
596print_branch (disassemble_info *info,
597 unsigned long insn_word,
598 struct instruction *insn)
252b5132
RH
599{
600 char operand[2][13] =
601 {
602 {0},
47b0e7ad
NC
603 {0}
604 };
252b5132
RH
605 unsigned long address;
606 int print_label = 0;
607
608 if (insn->tm == NULL)
609 return 0;
bf830eae 610 /* Get the operands for 24-bit immediate jumps. */
252b5132
RH
611 if (insn->tm->operand_types[0] & Imm24)
612 {
613 address = insn_word & 0x00FFFFFF;
614 sprintf (operand[0], "0x%lX", address);
615 print_label = 1;
616 }
bf830eae 617 /* Get the operand for the trap instruction. */
252b5132
RH
618 else if (insn->tm->operand_types[0] & IVector)
619 {
620 address = insn_word & 0x0000001F;
621 sprintf (operand[0], "0x%lX", address);
622 }
623 else
624 {
625 address = insn_word & 0x0000FFFF;
bf830eae 626 /* Get the operands for the DB instructions. */
252b5132
RH
627 if (insn->tm->operands == 2)
628 {
629 get_register_operand (((insn_word & 0x01C00000) >> 22) + REG_AR0, operand[0]);
630 if (insn_word & PCRel)
631 {
632 sprintf (operand[1], "%d", (short) address);
633 print_label = 1;
634 }
635 else
636 get_register_operand (insn_word & 0x0000001F, operand[1]);
637 }
bf830eae 638 /* Get the operands for the standard branches. */
252b5132
RH
639 else if (insn->tm->operands == 1)
640 {
641 if (insn_word & PCRel)
642 {
643 address = (short) address;
644 sprintf (operand[0], "%ld", address);
645 print_label = 1;
646 }
647 else
648 get_register_operand (insn_word & 0x0000001F, operand[0]);
649 }
650 }
651 info->fprintf_func (info->stream, " %s %s%c%s", insn->tm->name,
652 operand[0][0] ? operand[0] : "",
653 operand[1][0] ? ',' : ' ',
654 operand[1][0] ? operand[1] : "");
bf830eae 655 /* Print destination of branch in relation to current symbol. */
252b5132
RH
656 if (print_label && info->symbols)
657 {
658 asymbol *sym = *info->symbols;
659
660 if ((insn->tm->opcode_modifier == PCRel) && (insn_word & PCRel))
661 {
662 address = (_pc + 1 + (short) address) - ((sym->section->vma + sym->value) / 4);
bf830eae 663 /* Check for delayed instruction, if so adjust destination. */
252b5132
RH
664 if (insn_word & 0x00200000)
665 address += 2;
666 }
667 else
668 {
669 address -= ((sym->section->vma + sym->value) / 4);
670 }
671 if (address == 0)
672 info->fprintf_func (info->stream, " <%s>", sym->name);
673 else
b6518b38 674 info->fprintf_func (info->stream, " <%s %c %lu>", sym->name,
252b5132 675 ((short) address < 0) ? '-' : '+',
b6518b38 676 address);
252b5132
RH
677 }
678 return 1;
679}
680
681int
47b0e7ad 682print_insn_tic30 (bfd_vma pc, disassemble_info *info)
252b5132 683{
47b0e7ad
NC
684 unsigned long insn_word;
685 struct instruction insn = { 0, NULL, NULL };
686 bfd_vma bufaddr = pc - info->buffer_vma;
252b5132 687
47b0e7ad
NC
688 /* Obtain the current instruction word from the buffer. */
689 insn_word = (*(info->buffer + bufaddr) << 24) | (*(info->buffer + bufaddr + 1) << 16) |
690 (*(info->buffer + bufaddr + 2) << 8) | *(info->buffer + bufaddr + 3);
691 _pc = pc / 4;
692 /* Get the instruction refered to by the current instruction word
693 and print it out based on its type. */
694 if (!get_tic30_instruction (insn_word, &insn))
695 return -1;
696 switch (GET_TYPE (insn_word))
252b5132 697 {
47b0e7ad
NC
698 case TWO_OPERAND_1:
699 case TWO_OPERAND_2:
700 if (!print_two_operand (info, insn_word, &insn))
701 return -1;
252b5132 702 break;
47b0e7ad
NC
703 case THREE_OPERAND:
704 if (!print_three_operand (info, insn_word, &insn))
705 return -1;
706 break;
707 case PAR_STORE:
708 case MUL_ADDS:
709 if (!print_par_insn (info, insn_word, &insn))
710 return -1;
711 break;
712 case BRANCHES:
713 if (!print_branch (info, insn_word, &insn))
714 return -1;
252b5132 715 break;
252b5132 716 }
47b0e7ad 717 return 4;
252b5132 718}
This page took 1.387136 seconds and 4 git commands to generate.