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