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