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