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