* elf32-m68k.c (elf_m68k_relocate_section): Allow
[deliverable/binutils-gdb.git] / opcodes / arc-dis.c
CommitLineData
252b5132 1/* Instruction printing code for the ARC.
cdb06235
AM
2 Copyright 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2005, 2007, 2009,
3 2010, 2012 Free Software Foundation, Inc.
252b5132
RH
4 Contributed by Doug Evans (dje@cygnus.com).
5
9b201bb5
NC
6 This file is part of libopcodes.
7
8 This library is free software; you can redistribute it and/or modify
0d2bcfaf 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 17
0d2bcfaf
NC
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
47b0e7ad
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
252b5132 22
19f33eee
AM
23#include "ansidecl.h"
24#include "libiberty.h"
252b5132
RH
25#include "dis-asm.h"
26#include "opcode/arc.h"
27#include "elf-bfd.h"
28#include "elf/arc.h"
0d2bcfaf 29#include <string.h>
252b5132
RH
30#include "opintl.h"
31
0d2bcfaf
NC
32#include <stdarg.h>
33#include "arc-dis.h"
34#include "arc-ext.h"
252b5132 35
0d2bcfaf
NC
36#ifndef dbg
37#define dbg (0)
38#endif
252b5132 39
82b829a7
RR
40/* Classification of the opcodes for the decoder to print
41 the instructions. */
42
47b0e7ad
NC
43typedef enum
44{
82b829a7
RR
45 CLASS_A4_ARITH,
46 CLASS_A4_OP3_GENERAL,
47 CLASS_A4_FLAG,
48 /* All branches other than JC. */
49 CLASS_A4_BRANCH,
50 CLASS_A4_JC ,
51 /* All loads other than immediate
52 indexed loads. */
53 CLASS_A4_LD0,
54 CLASS_A4_LD1,
55 CLASS_A4_ST,
56 CLASS_A4_SR,
57 /* All single operand instructions. */
58 CLASS_A4_OP3_SUBOPC3F,
59 CLASS_A4_LR
60} a4_decoding_class;
61
279a96ca 62#define BIT(word,n) ((word) & (1 << n))
cdb06235 63#define BITS(word,s,e) (((word) >> s) & ((1 << (e + 1 - s)) - 1))
279a96ca
AJ
64#define OPCODE(word) (BITS ((word), 27, 31))
65#define FIELDA(word) (BITS ((word), 21, 26))
66#define FIELDB(word) (BITS ((word), 15, 20))
67#define FIELDC(word) (BITS ((word), 9, 14))
252b5132 68
cdb06235
AM
69/* FIELD D is signed. */
70#define FIELDD(word) ((BITS ((word), 0, 8) ^ 0x100) - 0x100)
0d2bcfaf 71
86caa542
AM
72#define PUT_NEXT_WORD_IN(a) \
73 do \
74 { \
75 if (is_limm == 1 && !NEXT_WORD (1)) \
76 mwerror (state, _("Illegal limm reference in last instruction!\n")); \
77 a = state->words[1]; \
78 } \
0d2bcfaf
NC
79 while (0)
80
81#define CHECK_FLAG_COND_NULLIFY() \
82 do \
83 { \
84 if (is_shimm == 0) \
85 { \
86 flag = BIT (state->words[0], 8); \
87 state->nullifyMode = BITS (state->words[0], 5, 6); \
88 cond = BITS (state->words[0], 0, 4); \
89 } \
90 } \
91 while (0)
92
93#define CHECK_COND() \
94 do \
95 { \
96 if (is_shimm == 0) \
97 cond = BITS (state->words[0], 0, 4); \
98 } \
99 while (0)
100
101#define CHECK_FIELD(field) \
102 do \
103 { \
104 if (field == 62) \
105 { \
106 is_limm++; \
107 field##isReg = 0; \
108 PUT_NEXT_WORD_IN (field); \
109 limm_value = field; \
110 } \
111 else if (field > 60) \
112 { \
113 field##isReg = 0; \
114 is_shimm++; \
115 flag = (field == 61); \
116 field = FIELDD (state->words[0]); \
117 } \
118 } \
119 while (0)
120
121#define CHECK_FIELD_A() \
122 do \
123 { \
86caa542 124 fieldA = FIELDA (state->words[0]); \
0d2bcfaf
NC
125 if (fieldA > 60) \
126 { \
127 fieldAisReg = 0; \
128 fieldA = 0; \
129 } \
130 } \
131 while (0)
132
133#define CHECK_FIELD_B() \
134 do \
135 { \
136 fieldB = FIELDB (state->words[0]); \
137 CHECK_FIELD (fieldB); \
138 } \
139 while (0)
140
141#define CHECK_FIELD_C() \
142 do \
143 { \
144 fieldC = FIELDC (state->words[0]); \
145 CHECK_FIELD (fieldC); \
146 } \
147 while (0)
148
47b0e7ad
NC
149#define IS_SMALL(x) (((field##x) < 256) && ((field##x) > -257))
150#define IS_REG(x) (field##x##isReg)
151#define WRITE_FORMAT_LB_Rx_RB(x) WRITE_FORMAT (x, "[","]","","")
152#define WRITE_FORMAT_x_COMMA_LB(x) WRITE_FORMAT (x, "",",[","",",[")
153#define WRITE_FORMAT_COMMA_x_RB(x) WRITE_FORMAT (x, ",","]",",","]")
154#define WRITE_FORMAT_x_RB(x) WRITE_FORMAT (x, "","]","","]")
155#define WRITE_FORMAT_COMMA_x(x) WRITE_FORMAT (x, ",","",",","")
156#define WRITE_FORMAT_x_COMMA(x) WRITE_FORMAT (x, "",",","",",")
157#define WRITE_FORMAT_x(x) WRITE_FORMAT (x, "","","","")
0d2bcfaf
NC
158#define WRITE_FORMAT(x,cb1,ca1,cb,ca) strcat (formatString, \
159 (IS_REG (x) ? cb1"%r"ca1 : \
160 usesAuxReg ? cb"%a"ca : \
161 IS_SMALL (x) ? cb"%d"ca : cb"%h"ca))
279a96ca 162#define WRITE_FORMAT_RB() strcat (formatString, "]")
0d2bcfaf 163#define WRITE_COMMENT(str) (state->comm[state->commNum++] = (str))
279a96ca 164#define WRITE_NOP_COMMENT() if (!fieldAisReg && !flag) WRITE_COMMENT ("nop");
0d2bcfaf 165
279a96ca 166#define NEXT_WORD(x) (offset += 4, state->words[x])
0d2bcfaf 167
279a96ca 168#define add_target(x) (state->targets[state->tcnt++] = (x))
0d2bcfaf
NC
169
170static char comment_prefix[] = "\t; ";
171
172static const char *
47b0e7ad 173core_reg_name (struct arcDisState * state, int val)
252b5132 174{
0d2bcfaf
NC
175 if (state->coreRegName)
176 return (*state->coreRegName)(state->_this, val);
177 return 0;
178}
252b5132 179
0d2bcfaf 180static const char *
47b0e7ad 181aux_reg_name (struct arcDisState * state, int val)
0d2bcfaf
NC
182{
183 if (state->auxRegName)
184 return (*state->auxRegName)(state->_this, val);
185 return 0;
186}
252b5132 187
0d2bcfaf 188static const char *
47b0e7ad 189cond_code_name (struct arcDisState * state, int val)
0d2bcfaf
NC
190{
191 if (state->condCodeName)
192 return (*state->condCodeName)(state->_this, val);
193 return 0;
194}
195
196static const char *
47b0e7ad
NC
197instruction_name (struct arcDisState * state,
198 int op1,
199 int op2,
200 int * flags)
0d2bcfaf
NC
201{
202 if (state->instName)
203 return (*state->instName)(state->_this, op1, op2, flags);
204 return 0;
205}
206
207static void
47b0e7ad 208mwerror (struct arcDisState * state, const char * msg)
0d2bcfaf
NC
209{
210 if (state->err != 0)
211 (*state->err)(state->_this, (msg));
212}
213
214static const char *
47b0e7ad 215post_address (struct arcDisState * state, int addr)
0d2bcfaf
NC
216{
217 static char id[3 * ARRAY_SIZE (state->addresses)];
218 int j, i = state->acnt;
219
220 if (i < ((int) ARRAY_SIZE (state->addresses)))
252b5132 221 {
0d2bcfaf
NC
222 state->addresses[i] = addr;
223 ++state->acnt;
224 j = i*3;
225 id[j+0] = '@';
226 id[j+1] = '0'+i;
227 id[j+2] = 0;
279a96ca 228
0d2bcfaf 229 return id + j;
252b5132 230 }
0d2bcfaf
NC
231 return "";
232}
252b5132 233
279a96ca 234static void
47b0e7ad 235arc_sprintf (struct arcDisState *state, char *buf, const char *format, ...)
0d2bcfaf 236{
279a96ca 237 char *bp;
0d2bcfaf
NC
238 const char *p;
239 int size, leading_zero, regMap[2];
47b0e7ad 240 va_list ap;
279a96ca 241
47b0e7ad 242 va_start (ap, format);
279a96ca
AJ
243
244 bp = buf;
0d2bcfaf
NC
245 *bp = 0;
246 p = format;
0d2bcfaf
NC
247 regMap[0] = 0;
248 regMap[1] = 0;
279a96ca
AJ
249
250 while (1)
0d2bcfaf
NC
251 switch (*p++)
252 {
86caa542
AM
253 case 0:
254 goto DOCOMM; /* (return) */
279a96ca
AJ
255 default:
256 *bp++ = p[-1];
0d2bcfaf
NC
257 break;
258 case '%':
259 size = 0;
260 leading_zero = 0;
261 RETRY: ;
279a96ca 262 switch (*p++)
0d2bcfaf
NC
263 {
264 case '0':
265 case '1':
266 case '2':
267 case '3':
268 case '4':
269 case '5':
270 case '6':
271 case '7':
272 case '8':
273 case '9':
274 {
275 /* size. */
276 size = p[-1] - '0';
277 if (size == 0)
278 leading_zero = 1; /* e.g. %08x */
279 while (*p >= '0' && *p <= '9')
280 {
281 size = size * 10 + *p - '0';
282 p++;
283 }
284 goto RETRY;
285 }
286#define inc_bp() bp = bp + strlen (bp)
252b5132 287
279a96ca 288 case 'h':
0d2bcfaf
NC
289 {
290 unsigned u = va_arg (ap, int);
252b5132 291
0d2bcfaf
NC
292 /* Hex. We can change the format to 0x%08x in
293 one place, here, if we wish.
294 We add underscores for easy reading. */
279a96ca 295 if (u > 65536)
0d2bcfaf 296 sprintf (bp, "0x%x_%04x", u >> 16, u & 0xffff);
279a96ca 297 else
0d2bcfaf
NC
298 sprintf (bp, "0x%x", u);
299 inc_bp ();
279a96ca 300 }
0d2bcfaf 301 break;
279a96ca 302 case 'X': case 'x':
0d2bcfaf
NC
303 {
304 int val = va_arg (ap, int);
252b5132 305
279a96ca 306 if (size != 0)
0d2bcfaf
NC
307 if (leading_zero)
308 sprintf (bp, "%0*x", size, val);
309 else
310 sprintf (bp, "%*x", size, val);
311 else
312 sprintf (bp, "%x", val);
313 inc_bp ();
314 }
315 break;
279a96ca 316 case 'd':
252b5132 317 {
0d2bcfaf 318 int val = va_arg (ap, int);
279a96ca 319
0d2bcfaf
NC
320 if (size != 0)
321 sprintf (bp, "%*d", size, val);
322 else
323 sprintf (bp, "%d", val);
324 inc_bp ();
252b5132 325 }
0d2bcfaf 326 break;
279a96ca 327 case 'r':
0d2bcfaf
NC
328 {
329 /* Register. */
330 int val = va_arg (ap, int);
279a96ca 331
0d2bcfaf
NC
332#define REG2NAME(num, name) case num: sprintf (bp, ""name); \
333 regMap[(num < 32) ? 0 : 1] |= 1 << (num - ((num < 32) ? 0 : 32)); break;
279a96ca
AJ
334
335 switch (val)
0d2bcfaf
NC
336 {
337 REG2NAME (26, "gp");
338 REG2NAME (27, "fp");
339 REG2NAME (28, "sp");
340 REG2NAME (29, "ilink1");
341 REG2NAME (30, "ilink2");
342 REG2NAME (31, "blink");
343 REG2NAME (60, "lp_count");
344 default:
345 {
346 const char * ext;
347
348 ext = core_reg_name (state, val);
349 if (ext)
350 sprintf (bp, "%s", ext);
351 else
352 sprintf (bp,"r%d",val);
353 }
354 break;
355 }
356 inc_bp ();
357 } break;
279a96ca
AJ
358
359 case 'a':
0d2bcfaf
NC
360 {
361 /* Aux Register. */
362 int val = va_arg (ap, int);
252b5132 363
0d2bcfaf 364#define AUXREG2NAME(num, name) case num: sprintf (bp,name); break;
252b5132 365
279a96ca 366 switch (val)
0d2bcfaf
NC
367 {
368 AUXREG2NAME (0x0, "status");
369 AUXREG2NAME (0x1, "semaphore");
370 AUXREG2NAME (0x2, "lp_start");
371 AUXREG2NAME (0x3, "lp_end");
372 AUXREG2NAME (0x4, "identity");
373 AUXREG2NAME (0x5, "debug");
374 default:
375 {
376 const char *ext;
377
378 ext = aux_reg_name (state, val);
379 if (ext)
380 sprintf (bp, "%s", ext);
381 else
47b0e7ad 382 arc_sprintf (state, bp, "%h", val);
0d2bcfaf
NC
383 }
384 break;
385 }
386 inc_bp ();
387 }
388 break;
279a96ca
AJ
389
390 case 's':
252b5132 391 {
0d2bcfaf
NC
392 sprintf (bp, "%s", va_arg (ap, char *));
393 inc_bp ();
252b5132 394 }
0d2bcfaf 395 break;
279a96ca 396
0d2bcfaf
NC
397 default:
398 fprintf (stderr, "?? format %c\n", p[-1]);
399 break;
400 }
401 }
402
403 DOCOMM: *bp = 0;
47b0e7ad 404 va_end (ap);
0d2bcfaf
NC
405}
406
279a96ca 407static void
47b0e7ad
NC
408write_comments_(struct arcDisState * state,
409 int shimm,
410 int is_limm,
411 long limm_value)
0d2bcfaf 412{
279a96ca 413 if (state->commentBuffer != 0)
0d2bcfaf
NC
414 {
415 int i;
416
279a96ca 417 if (is_limm)
0d2bcfaf
NC
418 {
419 const char *name = post_address (state, limm_value + shimm);
420
421 if (*name != 0)
422 WRITE_COMMENT (name);
423 }
279a96ca 424 for (i = 0; i < state->commNum; i++)
0d2bcfaf
NC
425 {
426 if (i == 0)
427 strcpy (state->commentBuffer, comment_prefix);
252b5132 428 else
279a96ca 429 strcat (state->commentBuffer, ", ");
86caa542
AM
430 strncat (state->commentBuffer, state->comm[i],
431 sizeof (state->commentBuffer));
252b5132 432 }
0d2bcfaf
NC
433 }
434}
252b5132 435
47b0e7ad
NC
436#define write_comments2(x) write_comments_ (state, x, is_limm, limm_value)
437#define write_comments() write_comments2 (0)
0d2bcfaf 438
47b0e7ad
NC
439static const char *condName[] =
440{
0d2bcfaf 441 /* 0..15. */
279a96ca 442 "" , "z" , "nz" , "p" , "n" , "c" , "nc" , "v" ,
0d2bcfaf
NC
443 "nv" , "gt" , "ge" , "lt" , "le" , "hi" , "ls" , "pnz"
444};
445
279a96ca 446static void
47b0e7ad
NC
447write_instr_name_(struct arcDisState * state,
448 const char * instrName,
449 int cond,
450 int condCodeIsPartOfName,
451 int flag,
452 int signExtend,
453 int addrWriteBack,
454 int directMem)
0d2bcfaf
NC
455{
456 strcpy (state->instrBuffer, instrName);
457
279a96ca 458 if (cond > 0)
0d2bcfaf
NC
459 {
460 const char *cc = 0;
461
462 if (!condCodeIsPartOfName)
463 strcat (state->instrBuffer, ".");
464
465 if (cond < 16)
466 cc = condName[cond];
467 else
468 cc = cond_code_name (state, cond);
469
470 if (!cc)
471 cc = "???";
472
473 strcat (state->instrBuffer, cc);
474 }
475
476 if (flag)
477 strcat (state->instrBuffer, ".f");
478
279a96ca 479 switch (state->nullifyMode)
0d2bcfaf
NC
480 {
481 case BR_exec_always:
482 strcat (state->instrBuffer, ".d");
483 break;
484 case BR_exec_when_jump:
485 strcat (state->instrBuffer, ".jd");
486 break;
487 }
488
489 if (signExtend)
490 strcat (state->instrBuffer, ".x");
491
492 if (addrWriteBack)
493 strcat (state->instrBuffer, ".a");
494
495 if (directMem)
496 strcat (state->instrBuffer, ".di");
497}
498
499#define write_instr_name() \
500 do \
501 { \
502 write_instr_name_(state, instrName,cond, condCodeIsPartOfName, \
503 flag, signExtend, addrWriteBack, directMem); \
504 formatString[0] = '\0'; \
505 } \
506 while (0)
507
47b0e7ad
NC
508enum
509{
279a96ca 510 op_LD0 = 0, op_LD1 = 1, op_ST = 2, op_3 = 3,
0d2bcfaf 511 op_BC = 4, op_BLC = 5, op_LPC = 6, op_JC = 7,
279a96ca 512 op_ADD = 8, op_ADC = 9, op_SUB = 10, op_SBC = 11,
0d2bcfaf
NC
513 op_AND = 12, op_OR = 13, op_BIC = 14, op_XOR = 15
514};
515
516extern disassemble_info tm_print_insn_info;
252b5132 517
279a96ca 518static int
47b0e7ad 519dsmOneArcInst (bfd_vma addr, struct arcDisState * state)
0d2bcfaf
NC
520{
521 int condCodeIsPartOfName = 0;
82b829a7 522 a4_decoding_class decodingClass;
0d2bcfaf
NC
523 const char * instrName;
524 int repeatsOp = 0;
525 int fieldAisReg = 1;
526 int fieldBisReg = 1;
527 int fieldCisReg = 1;
528 int fieldA;
529 int fieldB;
530 int fieldC = 0;
531 int flag = 0;
532 int cond = 0;
533 int is_shimm = 0;
534 int is_limm = 0;
535 long limm_value = 0;
536 int signExtend = 0;
537 int addrWriteBack = 0;
538 int directMem = 0;
539 int is_linked = 0;
540 int offset = 0;
541 int usesAuxReg = 0;
542 int flags;
543 int ignoreFirstOpd;
544 char formatString[60];
279a96ca 545
0d2bcfaf
NC
546 state->instructionLen = 4;
547 state->nullifyMode = BR_exec_when_no_jump;
548 state->opWidth = 12;
549 state->isBranch = 0;
279a96ca 550
0d2bcfaf
NC
551 state->_mem_load = 0;
552 state->_ea_present = 0;
553 state->_load_len = 0;
554 state->ea_reg1 = no_reg;
555 state->ea_reg2 = no_reg;
556 state->_offset = 0;
279a96ca 557
0d2bcfaf
NC
558 if (! NEXT_WORD (0))
559 return 0;
279a96ca 560
0d2bcfaf
NC
561 state->_opcode = OPCODE (state->words[0]);
562 instrName = 0;
82b829a7 563 decodingClass = CLASS_A4_ARITH; /* default! */
0d2bcfaf
NC
564 repeatsOp = 0;
565 condCodeIsPartOfName=0;
566 state->commNum = 0;
567 state->tcnt = 0;
568 state->acnt = 0;
569 state->flow = noflow;
570 ignoreFirstOpd = 0;
571
572 if (state->commentBuffer)
573 state->commentBuffer[0] = '\0';
574
279a96ca 575 switch (state->_opcode)
0d2bcfaf 576 {
279a96ca
AJ
577 case op_LD0:
578 switch (BITS (state->words[0],1,2))
0d2bcfaf
NC
579 {
580 case 0:
581 instrName = "ld";
582 state->_load_len = 4;
583 break;
584 case 1:
585 instrName = "ldb";
586 state->_load_len = 1;
587 break;
588 case 2:
589 instrName = "ldw";
590 state->_load_len = 2;
591 break;
592 default:
279a96ca 593 instrName = "??? (0[3])";
0d2bcfaf
NC
594 state->flow = invalid_instr;
595 break;
596 }
82b829a7 597 decodingClass = CLASS_A4_LD0;
0d2bcfaf 598 break;
279a96ca
AJ
599
600 case op_LD1:
601 if (BIT (state->words[0],13))
0d2bcfaf 602 {
279a96ca 603 instrName = "lr";
82b829a7 604 decodingClass = CLASS_A4_LR;
0d2bcfaf 605 }
279a96ca 606 else
0d2bcfaf 607 {
47b0e7ad 608 switch (BITS (state->words[0], 10, 11))
252b5132 609 {
0d2bcfaf
NC
610 case 0:
611 instrName = "ld";
612 state->_load_len = 4;
613 break;
614 case 1:
615 instrName = "ldb";
616 state->_load_len = 1;
617 break;
618 case 2:
619 instrName = "ldw";
620 state->_load_len = 2;
621 break;
622 default:
279a96ca 623 instrName = "??? (1[3])";
0d2bcfaf
NC
624 state->flow = invalid_instr;
625 break;
252b5132 626 }
82b829a7 627 decodingClass = CLASS_A4_LD1;
0d2bcfaf
NC
628 }
629 break;
279a96ca 630
0d2bcfaf 631 case op_ST:
47b0e7ad 632 if (BIT (state->words[0], 25))
0d2bcfaf
NC
633 {
634 instrName = "sr";
82b829a7 635 decodingClass = CLASS_A4_SR;
0d2bcfaf 636 }
279a96ca 637 else
0d2bcfaf 638 {
47b0e7ad 639 switch (BITS (state->words[0], 22, 23))
0d2bcfaf
NC
640 {
641 case 0:
642 instrName = "st";
643 break;
644 case 1:
645 instrName = "stb";
646 break;
647 case 2:
648 instrName = "stw";
649 break;
650 default:
279a96ca 651 instrName = "??? (2[3])";
0d2bcfaf
NC
652 state->flow = invalid_instr;
653 break;
654 }
82b829a7 655 decodingClass = CLASS_A4_ST;
0d2bcfaf
NC
656 }
657 break;
279a96ca 658
0d2bcfaf 659 case op_3:
82b829a7 660 decodingClass = CLASS_A4_OP3_GENERAL; /* default for opcode 3... */
279a96ca 661 switch (FIELDC (state->words[0]))
0d2bcfaf
NC
662 {
663 case 0:
279a96ca 664 instrName = "flag";
82b829a7 665 decodingClass = CLASS_A4_FLAG;
0d2bcfaf
NC
666 break;
667 case 1:
668 instrName = "asr";
669 break;
670 case 2:
671 instrName = "lsr";
672 break;
673 case 3:
674 instrName = "ror";
675 break;
676 case 4:
677 instrName = "rrc";
678 break;
679 case 5:
680 instrName = "sexb";
681 break;
682 case 6:
683 instrName = "sexw";
684 break;
685 case 7:
686 instrName = "extb";
687 break;
688 case 8:
689 instrName = "extw";
690 break;
279a96ca 691 case 0x3f:
0d2bcfaf 692 {
82b829a7 693 decodingClass = CLASS_A4_OP3_SUBOPC3F;
47b0e7ad 694 switch (FIELDD (state->words[0]))
0d2bcfaf
NC
695 {
696 case 0:
697 instrName = "brk";
698 break;
699 case 1:
700 instrName = "sleep";
701 break;
702 case 2:
703 instrName = "swi";
704 break;
705 default:
706 instrName = "???";
707 state->flow=invalid_instr;
708 break;
709 }
710 }
711 break;
279a96ca 712
0d2bcfaf
NC
713 /* ARC Extension Library Instructions
714 NOTE: We assume that extension codes are these instrs. */
715 default:
716 instrName = instruction_name (state,
717 state->_opcode,
718 FIELDC (state->words[0]),
86caa542 719 &flags);
0d2bcfaf 720 if (!instrName)
252b5132 721 {
0d2bcfaf
NC
722 instrName = "???";
723 state->flow = invalid_instr;
252b5132 724 }
0d2bcfaf
NC
725 if (flags & IGNORE_FIRST_OPD)
726 ignoreFirstOpd = 1;
727 break;
728 }
729 break;
252b5132 730
0d2bcfaf 731 case op_BC:
279a96ca 732 instrName = "b";
0d2bcfaf
NC
733 case op_BLC:
734 if (!instrName)
279a96ca 735 instrName = "bl";
0d2bcfaf
NC
736 case op_LPC:
737 if (!instrName)
279a96ca 738 instrName = "lp";
0d2bcfaf
NC
739 case op_JC:
740 if (!instrName)
741 {
279a96ca 742 if (BITS (state->words[0],9,9))
252b5132 743 {
279a96ca 744 instrName = "jl";
0d2bcfaf 745 is_linked = 1;
252b5132 746 }
279a96ca 747 else
252b5132 748 {
279a96ca 749 instrName = "j";
0d2bcfaf 750 is_linked = 0;
252b5132 751 }
0d2bcfaf
NC
752 }
753 condCodeIsPartOfName = 1;
82b829a7 754 decodingClass = ((state->_opcode == op_JC) ? CLASS_A4_JC : CLASS_A4_BRANCH );
0d2bcfaf
NC
755 state->isBranch = 1;
756 break;
279a96ca 757
0d2bcfaf
NC
758 case op_ADD:
759 case op_ADC:
760 case op_AND:
761 repeatsOp = (FIELDC (state->words[0]) == FIELDB (state->words[0]));
252b5132 762
279a96ca 763 switch (state->_opcode)
0d2bcfaf
NC
764 {
765 case op_ADD:
766 instrName = (repeatsOp ? "asl" : "add");
767 break;
768 case op_ADC:
769 instrName = (repeatsOp ? "rlc" : "adc");
770 break;
771 case op_AND:
772 instrName = (repeatsOp ? "mov" : "and");
773 break;
774 }
775 break;
279a96ca 776
0d2bcfaf
NC
777 case op_SUB: instrName = "sub";
778 break;
779 case op_SBC: instrName = "sbc";
780 break;
781 case op_OR: instrName = "or";
782 break;
783 case op_BIC: instrName = "bic";
784 break;
252b5132 785
0d2bcfaf
NC
786 case op_XOR:
787 if (state->words[0] == 0x7fffffff)
788 {
47b0e7ad 789 /* NOP encoded as xor -1, -1, -1. */
0d2bcfaf 790 instrName = "nop";
82b829a7 791 decodingClass = CLASS_A4_OP3_SUBOPC3F;
0d2bcfaf 792 }
279a96ca 793 else
0d2bcfaf
NC
794 instrName = "xor";
795 break;
279a96ca 796
0d2bcfaf
NC
797 default:
798 instrName = instruction_name (state,state->_opcode,0,&flags);
799 /* if (instrName) printf("FLAGS=0x%x\n", flags); */
800 if (!instrName)
801 {
802 instrName = "???";
803 state->flow=invalid_instr;
804 }
805 if (flags & IGNORE_FIRST_OPD)
806 ignoreFirstOpd = 1;
807 break;
808 }
279a96ca 809
0d2bcfaf
NC
810 fieldAisReg = fieldBisReg = fieldCisReg = 1; /* Assume regs for now. */
811 flag = cond = is_shimm = is_limm = 0;
812 state->nullifyMode = BR_exec_when_no_jump; /* 0 */
813 signExtend = addrWriteBack = directMem = 0;
814 usesAuxReg = 0;
279a96ca
AJ
815
816 switch (decodingClass)
0d2bcfaf 817 {
82b829a7 818 case CLASS_A4_ARITH:
0d2bcfaf
NC
819 CHECK_FIELD_A ();
820 CHECK_FIELD_B ();
821 if (!repeatsOp)
822 CHECK_FIELD_C ();
823 CHECK_FLAG_COND_NULLIFY ();
279a96ca 824
0d2bcfaf 825 write_instr_name ();
279a96ca 826 if (!ignoreFirstOpd)
0d2bcfaf
NC
827 {
828 WRITE_FORMAT_x (A);
829 WRITE_FORMAT_COMMA_x (B);
830 if (!repeatsOp)
831 WRITE_FORMAT_COMMA_x (C);
832 WRITE_NOP_COMMENT ();
47b0e7ad 833 arc_sprintf (state, state->operandBuffer, formatString,
86caa542 834 fieldA, fieldB, fieldC);
0d2bcfaf 835 }
279a96ca 836 else
0d2bcfaf
NC
837 {
838 WRITE_FORMAT_x (B);
839 if (!repeatsOp)
840 WRITE_FORMAT_COMMA_x (C);
47b0e7ad 841 arc_sprintf (state, state->operandBuffer, formatString,
86caa542 842 fieldB, fieldC);
0d2bcfaf
NC
843 }
844 write_comments ();
845 break;
279a96ca 846
82b829a7 847 case CLASS_A4_OP3_GENERAL:
0d2bcfaf
NC
848 CHECK_FIELD_A ();
849 CHECK_FIELD_B ();
850 CHECK_FLAG_COND_NULLIFY ();
279a96ca 851
0d2bcfaf 852 write_instr_name ();
279a96ca 853 if (!ignoreFirstOpd)
0d2bcfaf
NC
854 {
855 WRITE_FORMAT_x (A);
856 WRITE_FORMAT_COMMA_x (B);
857 WRITE_NOP_COMMENT ();
47b0e7ad 858 arc_sprintf (state, state->operandBuffer, formatString,
86caa542 859 fieldA, fieldB);
0d2bcfaf 860 }
279a96ca 861 else
0d2bcfaf
NC
862 {
863 WRITE_FORMAT_x (B);
47b0e7ad 864 arc_sprintf (state, state->operandBuffer, formatString, fieldB);
0d2bcfaf
NC
865 }
866 write_comments ();
867 break;
279a96ca 868
82b829a7 869 case CLASS_A4_FLAG:
0d2bcfaf
NC
870 CHECK_FIELD_B ();
871 CHECK_FLAG_COND_NULLIFY ();
47b0e7ad 872 flag = 0; /* This is the FLAG instruction -- it's redundant. */
279a96ca 873
0d2bcfaf
NC
874 write_instr_name ();
875 WRITE_FORMAT_x (B);
47b0e7ad 876 arc_sprintf (state, state->operandBuffer, formatString, fieldB);
0d2bcfaf
NC
877 write_comments ();
878 break;
279a96ca 879
82b829a7 880 case CLASS_A4_BRANCH:
0d2bcfaf 881 fieldA = BITS (state->words[0],7,26) << 2;
47b0e7ad 882 fieldA = (fieldA << 10) >> 10; /* Make it signed. */
0d2bcfaf
NC
883 fieldA += addr + 4;
884 CHECK_FLAG_COND_NULLIFY ();
885 flag = 0;
279a96ca 886
0d2bcfaf
NC
887 write_instr_name ();
888 /* This address could be a label we know. Convert it. */
279a96ca 889 if (state->_opcode != op_LPC /* LP */)
0d2bcfaf 890 {
86caa542
AM
891 add_target (fieldA); /* For debugger. */
892 state->flow = state->_opcode == op_BLC /* BL */
893 ? direct_call
894 : direct_jump;
895 /* indirect calls are achieved by "lr blink,[status];
896 lr dest<- func addr; j [dest]" */
279a96ca
AJ
897 }
898
47b0e7ad
NC
899 strcat (formatString, "%s"); /* Address/label name. */
900 arc_sprintf (state, state->operandBuffer, formatString,
86caa542 901 post_address (state, fieldA));
0d2bcfaf
NC
902 write_comments ();
903 break;
279a96ca 904
82b829a7 905 case CLASS_A4_JC:
0d2bcfaf
NC
906 /* For op_JC -- jump to address specified.
907 Also covers jump and link--bit 9 of the instr. word
908 selects whether linked, thus "is_linked" is set above. */
909 fieldA = 0;
910 CHECK_FIELD_B ();
911 CHECK_FLAG_COND_NULLIFY ();
279a96ca
AJ
912
913 if (!fieldBisReg)
0d2bcfaf
NC
914 {
915 fieldAisReg = 0;
47b0e7ad 916 fieldA = (fieldB >> 25) & 0x7F; /* Flags. */
0d2bcfaf
NC
917 fieldB = (fieldB & 0xFFFFFF) << 2;
918 state->flow = is_linked ? direct_call : direct_jump;
919 add_target (fieldB);
47b0e7ad
NC
920 /* Screwy JLcc requires .jd mode to execute correctly
921 but we pretend it is .nd (no delay slot). */
0d2bcfaf
NC
922 if (is_linked && state->nullifyMode == BR_exec_when_jump)
923 state->nullifyMode = BR_exec_when_no_jump;
924 }
279a96ca 925 else
0d2bcfaf
NC
926 {
927 state->flow = is_linked ? indirect_call : indirect_jump;
928 /* We should also treat this as indirect call if NOT linked
47b0e7ad
NC
929 but the preceding instruction was a "lr blink,[status]"
930 and we have a delay slot with "add blink,blink,2".
931 For now we can't detect such. */
0d2bcfaf
NC
932 state->register_for_indirect_jump = fieldB;
933 }
279a96ca 934
0d2bcfaf 935 write_instr_name ();
279a96ca 936 strcat (formatString,
47b0e7ad 937 IS_REG (B) ? "[%r]" : "%s"); /* Address/label name. */
279a96ca 938 if (fieldA != 0)
0d2bcfaf
NC
939 {
940 fieldAisReg = 0;
941 WRITE_FORMAT_COMMA_x (A);
942 }
943 if (IS_REG (B))
47b0e7ad 944 arc_sprintf (state, state->operandBuffer, formatString, fieldB, fieldA);
0d2bcfaf 945 else
47b0e7ad 946 arc_sprintf (state, state->operandBuffer, formatString,
0d2bcfaf
NC
947 post_address (state, fieldB), fieldA);
948 write_comments ();
949 break;
279a96ca 950
82b829a7 951 case CLASS_A4_LD0:
0d2bcfaf
NC
952 /* LD instruction.
953 B and C can be regs, or one (both?) can be limm. */
954 CHECK_FIELD_A ();
955 CHECK_FIELD_B ();
956 CHECK_FIELD_C ();
957 if (dbg)
958 printf ("5:b reg %d %d c reg %d %d \n",
959 fieldBisReg,fieldB,fieldCisReg,fieldC);
960 state->_offset = 0;
961 state->_ea_present = 1;
962 if (fieldBisReg)
963 state->ea_reg1 = fieldB;
964 else
965 state->_offset += fieldB;
966 if (fieldCisReg)
967 state->ea_reg2 = fieldC;
968 else
969 state->_offset += fieldC;
970 state->_mem_load = 1;
279a96ca 971
47b0e7ad
NC
972 directMem = BIT (state->words[0], 5);
973 addrWriteBack = BIT (state->words[0], 3);
974 signExtend = BIT (state->words[0], 0);
279a96ca 975
0d2bcfaf
NC
976 write_instr_name ();
977 WRITE_FORMAT_x_COMMA_LB(A);
978 if (fieldBisReg || fieldB != 0)
979 WRITE_FORMAT_x_COMMA (B);
980 else
981 fieldB = fieldC;
279a96ca 982
0d2bcfaf 983 WRITE_FORMAT_x_RB (C);
47b0e7ad 984 arc_sprintf (state, state->operandBuffer, formatString,
86caa542 985 fieldA, fieldB, fieldC);
0d2bcfaf
NC
986 write_comments ();
987 break;
279a96ca 988
82b829a7 989 case CLASS_A4_LD1:
0d2bcfaf
NC
990 /* LD instruction. */
991 CHECK_FIELD_B ();
992 CHECK_FIELD_A ();
993 fieldC = FIELDD (state->words[0]);
279a96ca 994
0d2bcfaf
NC
995 if (dbg)
996 printf ("6:b reg %d %d c 0x%x \n",
997 fieldBisReg, fieldB, fieldC);
998 state->_ea_present = 1;
999 state->_offset = fieldC;
1000 state->_mem_load = 1;
1001 if (fieldBisReg)
1002 state->ea_reg1 = fieldB;
47b0e7ad 1003 /* Field B is either a shimm (same as fieldC) or limm (different!)
0d2bcfaf
NC
1004 Say ea is not present, so only one of us will do the name lookup. */
1005 else
1006 state->_offset += fieldB, state->_ea_present = 0;
279a96ca 1007
0d2bcfaf
NC
1008 directMem = BIT (state->words[0],14);
1009 addrWriteBack = BIT (state->words[0],12);
1010 signExtend = BIT (state->words[0],9);
279a96ca 1011
0d2bcfaf
NC
1012 write_instr_name ();
1013 WRITE_FORMAT_x_COMMA_LB (A);
279a96ca 1014 if (!fieldBisReg)
0d2bcfaf
NC
1015 {
1016 fieldB = state->_offset;
1017 WRITE_FORMAT_x_RB (B);
1018 }
279a96ca 1019 else
0d2bcfaf
NC
1020 {
1021 WRITE_FORMAT_x (B);
279a96ca 1022 if (fieldC != 0 && !BIT (state->words[0],13))
0d2bcfaf
NC
1023 {
1024 fieldCisReg = 0;
1025 WRITE_FORMAT_COMMA_x_RB (C);
252b5132 1026 }
252b5132 1027 else
0d2bcfaf 1028 WRITE_FORMAT_RB ();
252b5132 1029 }
47b0e7ad 1030 arc_sprintf (state, state->operandBuffer, formatString,
86caa542 1031 fieldA, fieldB, fieldC);
0d2bcfaf
NC
1032 write_comments ();
1033 break;
279a96ca 1034
82b829a7 1035 case CLASS_A4_ST:
0d2bcfaf
NC
1036 /* ST instruction. */
1037 CHECK_FIELD_B();
1038 CHECK_FIELD_C();
1039 fieldA = FIELDD(state->words[0]); /* shimm */
279a96ca 1040
0d2bcfaf
NC
1041 /* [B,A offset] */
1042 if (dbg) printf("7:b reg %d %x off %x\n",
86caa542 1043 fieldBisReg,fieldB,fieldA);
0d2bcfaf
NC
1044 state->_ea_present = 1;
1045 state->_offset = fieldA;
1046 if (fieldBisReg)
1047 state->ea_reg1 = fieldB;
47b0e7ad 1048 /* Field B is either a shimm (same as fieldA) or limm (different!)
0d2bcfaf
NC
1049 Say ea is not present, so only one of us will do the name lookup.
1050 (for is_limm we do the name translation here). */
279a96ca 1051 else
0d2bcfaf 1052 state->_offset += fieldB, state->_ea_present = 0;
279a96ca 1053
47b0e7ad
NC
1054 directMem = BIT (state->words[0], 26);
1055 addrWriteBack = BIT (state->words[0], 24);
279a96ca 1056
47b0e7ad 1057 write_instr_name ();
0d2bcfaf 1058 WRITE_FORMAT_x_COMMA_LB(C);
279a96ca
AJ
1059
1060 if (!fieldBisReg)
0d2bcfaf
NC
1061 {
1062 fieldB = state->_offset;
47b0e7ad 1063 WRITE_FORMAT_x_RB (B);
0d2bcfaf 1064 }
279a96ca 1065 else
0d2bcfaf 1066 {
47b0e7ad 1067 WRITE_FORMAT_x (B);
279a96ca 1068 if (fieldBisReg && fieldA != 0)
0d2bcfaf
NC
1069 {
1070 fieldAisReg = 0;
1071 WRITE_FORMAT_COMMA_x_RB(A);
1072 }
1073 else
1074 WRITE_FORMAT_RB();
1075 }
47b0e7ad 1076 arc_sprintf (state, state->operandBuffer, formatString,
86caa542 1077 fieldC, fieldB, fieldA);
47b0e7ad 1078 write_comments2 (fieldA);
0d2bcfaf 1079 break;
82b829a7
RR
1080
1081 case CLASS_A4_SR:
0d2bcfaf
NC
1082 /* SR instruction */
1083 CHECK_FIELD_B();
1084 CHECK_FIELD_C();
279a96ca 1085
47b0e7ad 1086 write_instr_name ();
0d2bcfaf
NC
1087 WRITE_FORMAT_x_COMMA_LB(C);
1088 /* Try to print B as an aux reg if it is not a core reg. */
1089 usesAuxReg = 1;
47b0e7ad
NC
1090 WRITE_FORMAT_x (B);
1091 WRITE_FORMAT_RB ();
1092 arc_sprintf (state, state->operandBuffer, formatString, fieldC, fieldB);
1093 write_comments ();
0d2bcfaf 1094 break;
279a96ca 1095
82b829a7 1096 case CLASS_A4_OP3_SUBOPC3F:
47b0e7ad 1097 write_instr_name ();
0d2bcfaf
NC
1098 state->operandBuffer[0] = '\0';
1099 break;
279a96ca 1100
82b829a7 1101 case CLASS_A4_LR:
0d2bcfaf 1102 /* LR instruction */
47b0e7ad
NC
1103 CHECK_FIELD_A ();
1104 CHECK_FIELD_B ();
279a96ca 1105
47b0e7ad
NC
1106 write_instr_name ();
1107 WRITE_FORMAT_x_COMMA_LB (A);
0d2bcfaf
NC
1108 /* Try to print B as an aux reg if it is not a core reg. */
1109 usesAuxReg = 1;
47b0e7ad
NC
1110 WRITE_FORMAT_x (B);
1111 WRITE_FORMAT_RB ();
1112 arc_sprintf (state, state->operandBuffer, formatString, fieldA, fieldB);
1113 write_comments ();
0d2bcfaf 1114 break;
279a96ca 1115
0d2bcfaf
NC
1116 default:
1117 mwerror (state, "Bad decoding class in ARC disassembler");
1118 break;
252b5132 1119 }
279a96ca 1120
0d2bcfaf
NC
1121 state->_cond = cond;
1122 return state->instructionLen = offset;
1123}
1124
252b5132 1125
0d2bcfaf 1126/* Returns the name the user specified core extension register. */
47b0e7ad 1127
0d2bcfaf 1128static const char *
47b0e7ad 1129_coreRegName(void * arg ATTRIBUTE_UNUSED, int regval)
0d2bcfaf
NC
1130{
1131 return arcExtMap_coreRegName (regval);
252b5132
RH
1132}
1133
0d2bcfaf 1134/* Returns the name the user specified AUX extension register. */
47b0e7ad 1135
0d2bcfaf
NC
1136static const char *
1137_auxRegName(void *_this ATTRIBUTE_UNUSED, int regval)
1138{
86caa542 1139 return arcExtMap_auxRegName(regval);
0d2bcfaf 1140}
252b5132 1141
0d2bcfaf 1142/* Returns the name the user specified condition code name. */
47b0e7ad 1143
0d2bcfaf
NC
1144static const char *
1145_condCodeName(void *_this ATTRIBUTE_UNUSED, int regval)
252b5132 1146{
86caa542 1147 return arcExtMap_condCodeName(regval);
252b5132
RH
1148}
1149
0d2bcfaf 1150/* Returns the name the user specified extension instruction. */
47b0e7ad 1151
0d2bcfaf
NC
1152static const char *
1153_instName (void *_this ATTRIBUTE_UNUSED, int majop, int minop, int *flags)
252b5132 1154{
86caa542 1155 return arcExtMap_instName(majop, minop, flags);
252b5132
RH
1156}
1157
0d2bcfaf
NC
1158/* Decode an instruction returning the size of the instruction
1159 in bytes or zero if unrecognized. */
47b0e7ad 1160
252b5132 1161static int
47b0e7ad
NC
1162decodeInstr (bfd_vma address, /* Address of this instruction. */
1163 disassemble_info * info)
0d2bcfaf
NC
1164{
1165 int status;
1166 bfd_byte buffer[4];
47b0e7ad
NC
1167 struct arcDisState s; /* ARC Disassembler state. */
1168 void *stream = info->stream; /* Output stream. */
279a96ca 1169 fprintf_ftype func = info->fprintf_func;
279a96ca 1170
0d2bcfaf 1171 memset (&s, 0, sizeof(struct arcDisState));
279a96ca 1172
0d2bcfaf
NC
1173 /* read first instruction */
1174 status = (*info->read_memory_func) (address, buffer, 4, info);
1175 if (status != 0)
1176 {
1177 (*info->memory_error_func) (status, address, info);
1178 return 0;
1179 }
1180 if (info->endian == BFD_ENDIAN_LITTLE)
1181 s.words[0] = bfd_getl32(buffer);
1182 else
1183 s.words[0] = bfd_getb32(buffer);
47b0e7ad 1184 /* Always read second word in case of limm. */
0d2bcfaf 1185
47b0e7ad 1186 /* We ignore the result since last insn may not have a limm. */
0d2bcfaf
NC
1187 status = (*info->read_memory_func) (address + 4, buffer, 4, info);
1188 if (info->endian == BFD_ENDIAN_LITTLE)
1189 s.words[1] = bfd_getl32(buffer);
1190 else
1191 s.words[1] = bfd_getb32(buffer);
1192
1193 s._this = &s;
1194 s.coreRegName = _coreRegName;
1195 s.auxRegName = _auxRegName;
1196 s.condCodeName = _condCodeName;
1197 s.instName = _instName;
1198
47b0e7ad 1199 /* Disassemble. */
c7e2358a 1200 dsmOneArcInst (address, & s);
0d2bcfaf 1201
47b0e7ad 1202 /* Display the disassembly instruction. */
0fd3a477 1203 (*func) (stream, "%08lx ", s.words[0]);
0d2bcfaf 1204 (*func) (stream, " ");
0d2bcfaf 1205 (*func) (stream, "%-10s ", s.instrBuffer);
279a96ca 1206
47b0e7ad 1207 if (__TRANSLATION_REQUIRED (s))
0d2bcfaf
NC
1208 {
1209 bfd_vma addr = s.addresses[s.operandBuffer[1] - '0'];
47b0e7ad 1210
0d2bcfaf
NC
1211 (*info->print_address_func) ((bfd_vma) addr, info);
1212 (*func) (stream, "\n");
1213 }
1214 else
1215 (*func) (stream, "%s",s.operandBuffer);
47b0e7ad 1216
0d2bcfaf
NC
1217 return s.instructionLen;
1218}
1219
1220/* Return the print_insn function to use.
1221 Side effect: load (possibly empty) extension section */
1222
1223disassembler_ftype
1224arc_get_disassembler (void *ptr)
252b5132 1225{
0d2bcfaf 1226 if (ptr)
21d799b5 1227 build_ARC_extmap ((struct bfd *) ptr);
0d2bcfaf 1228 return decodeInstr;
252b5132 1229}
This page took 0.575321 seconds and 4 git commands to generate.