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