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