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