Rizin
unix-like reverse engineering framework and cli tools
arc-dis.c
Go to the documentation of this file.
1 /* Instruction printing code for the ARC.
2  Copyright 1994, 1995, 1997, 1998, 2000, 2001, 2002, 2005, 2006, 2007, 2008, 2009
3  Free Software Foundation, Inc.
4  Contributed by Doug Evans (dje@cygnus.com).
5 
6  Copyright 2008-2012 Synopsys Inc.
7 
8  This file is part of libopcodes.
9 
10  This library is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 3, or (at your option)
13  any later version.
14 
15  It is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
18  License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program; if not, write to the Free Software
22  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
23  MA 02110-1301, USA. */
24 
25 #include "ansidecl.h"
26 #include "libiberty.h"
27 #include "disas-asm.h"
28 //#include "opcode/arc.h"
29 #include "elf-bfd.h"
30 #include "arc.h"
31 #include <string.h>
32 #include "opintl.h"
33 
34 #include <stdarg.h>
35 #include "arc-dis.h"
36 #include "arc-ext.h"
37 #include "arcompact-dis.h"
38 
39 #include <stdlib.h>
40 
41 /* Classification of the opcodes for the decoder to print
42  the instructions. */
43 
44 typedef enum {
48  /* All branches other than JC. */
51  /* All loads other than immediate
52  indexed loads. */
57  /* All single operand instructions. */
61 
62 #define BIT(word, n) ((word) & (1 << (n)))
63 /* START ARC LOCAL */
64 #define BITS(word, s, e) (((word) << (sizeof(word) * 8 - 1 - (e))) >> ((s) + (sizeof(word) * 8 - 1 - (e))))
65 /* END ARC LOCAL */
66 #define OPCODE(word) (BITS((word), 27, 31))
67 #define FIELDA(word) (BITS((word), 21, 26))
68 #define FIELDB(word) (BITS((word), 15, 20))
69 #define FIELDC(word) (BITS((word), 9, 14))
70 
71 /* FIELD D is signed in all of its uses, so we make sure argument is
72  treated as signed for bit shifting purposes: */
73 #define FIELDD(word) (BITS(((signed int)(word)), 0, 8))
74 
75 #define PUT_NEXT_WORD_IN(a) \
76  do { \
77  if (is_limm == 1 && !NEXT_WORD(1)) { \
78  mwerror(state, _("Illegal limm reference in last instruction!\n")); \
79  } \
80  (a) = state->words[1]; \
81  } while (0)
82 
83 #define CHECK_FLAG_COND_NULLIFY() \
84  do { \
85  if (is_shimm == 0) { \
86  flag = BIT(state->words[0], 8); \
87  state->nullifyMode = BITS(state->words[0], 5, 6); \
88  cond = BITS(state->words[0], 0, 4); \
89  } \
90  } while (0)
91 
92 #define CHECK_COND() \
93  do { \
94  if (is_shimm == 0) \
95  cond = BITS(state->words[0], 0, 4); \
96  } while (0)
97 
98 #define CHECK_FIELD(field) \
99  do { \
100  if ((field) == 62) { \
101  is_limm++; \
102  field##isReg = 0; \
103  PUT_NEXT_WORD_IN(field); \
104  } else if ((field) > 60) { \
105  field##isReg = 0; \
106  is_shimm++; \
107  flag = ((field) == 61); \
108  (field) = FIELDD(state->words[0]); \
109  } \
110  } while (0)
111 
112 #define CHECK_FIELD_A() \
113  do { \
114  fieldA = FIELDA(state->words[0]); \
115  if (fieldA > 60) { \
116  fieldAisReg = 0; \
117  fieldA = 0; \
118  } \
119  } while (0)
120 
121 #define CHECK_FIELD_B() \
122  do { \
123  fieldB = FIELDB(state->words[0]); \
124  CHECK_FIELD(fieldB); \
125  } while (0)
126 
127 #define CHECK_FIELD_C() \
128  do { \
129  fieldC = FIELDC(state->words[0]); \
130  CHECK_FIELD(fieldC); \
131  } while (0)
132 
133 #define IS_SMALL(x) (((field##x) < 10) && ((field##x) >= 0))
134 #define IS_REG(x) (field##x##isReg)
135 #define WRITE_FORMAT_LB_Rx_RB(x) WRITE_FORMAT(x, "[", "]", "", "")
136 #define WRITE_FORMAT_x_COMMA_LB(x) WRITE_FORMAT(x, "", ", [", "", ", [")
137 #define WRITE_FORMAT_COMMA_x_RB(x) WRITE_FORMAT(x, ", ", "]", ", ", "]")
138 #define WRITE_FORMAT_x_RB(x) WRITE_FORMAT(x, "", "]", "", "]")
139 #define WRITE_FORMAT_COMMA_x(x) WRITE_FORMAT(x, ", ", "", ", ", "")
140 #define WRITE_FORMAT_x_COMMA(x) WRITE_FORMAT(x, "", ", ", "", ", ")
141 #define WRITE_FORMAT_x(x) WRITE_FORMAT(x, "", "", "", "")
142 #define WRITE_FORMAT(x, cb1, ca1, cb, ca) strcat(formatString, \
143  (IS_REG(x) ? cb1 "%r" ca1 : usesAuxReg ? cb "%a" ca \
144  : IS_SMALL(x) ? cb "%d" ca \
145  : cb "%h" ca))
146 #define WRITE_FORMAT_RB() strcat(formatString, "]")
147 #define WRITE_COMMENT(str) (state->comm[state->commNum++] = (str))
148 #define WRITE_NOP_COMMENT() \
149  if (!fieldAisReg && !flag) \
150  WRITE_COMMENT("nop");
151 
152 #define NEXT_WORD(x) (offset += 4, state->words[x])
153 
154 #define add_target(x) (state->targets[state->tcnt++] = (x))
155 
156 static const char *
158  if (state->coreRegName) {
159  return (*state->coreRegName)(state->_this, val);
160  }
161  return 0;
162 }
163 
164 static const char *
166  if (state->auxRegName) {
167  return (*state->auxRegName)(state->_this, val);
168  }
169  return 0;
170 }
171 
172 static const char *
174  if (state->condCodeName) {
175  return (*state->condCodeName)(state->_this, val);
176  }
177  return 0;
178 }
179 
180 static const char *
182  int op1,
183  int op2,
184  int *flags) {
185  if (state->instName) {
186  return (*state->instName)(state->_this, op1, op2, flags);
187  }
188  return 0;
189 }
190 
191 static void
192 mwerror(struct arcDisState *state, const char *msg) {
193  if (state->err != 0) {
194  (*state->err)(state->_this, (msg));
195  }
196 }
197 
198 static const char *
200  static char id[3 * ARRAY_SIZE(state->addresses)];
201  unsigned int j, i = state->acnt;
202 
203  if (i < ARRAY_SIZE(state->addresses)) {
204  state->addresses[i] = addr;
205  ++state->acnt;
206  j = i * 3;
207  id[j + 0] = '@';
208  id[j + 1] = '0' + i;
209  id[j + 2] = 0;
210 
211  return id + j;
212  }
213  return "";
214 }
215 
216 static void
217 arc_sprintf(struct arcDisState *state, char *buf, const char *format, ...) {
218  char *bp;
219  const char *p;
220  int size, leading_zero, regMap[2];
221  va_list ap;
222 
223  va_start(ap, format);
224 
225  if (!buf || !format) {
226  va_end(ap);
227  return;
228  }
229 
230  bp = buf;
231  *bp = 0;
232  p = format;
233  regMap[0] = 0;
234  regMap[1] = 0;
235 
236  while (1) {
237  switch (*p++) {
238  case 0:
239  goto DOCOMM; /* Return. */
240  default:
241  *bp++ = p[-1];
242  break;
243  case '%':
244  size = 0;
245  leading_zero = 0;
246  RETRY:;
247  switch (*p++) {
248  case '0':
249  case '1':
250  case '2':
251  case '3':
252  case '4':
253  case '5':
254  case '6':
255  case '7':
256  case '8':
257  case '9': {
258  /* size. */
259  size = p[-1] - '0';
260  if (size == 0) {
261  leading_zero = 1; /* e.g. %08x */
262  }
263  while (*p >= '0' && *p <= '9') {
264  size = size * 10 + *p - '0';
265  p++;
266  }
267  goto RETRY;
268  }
269 #define inc_bp() bp = bp + strlen(bp)
270 
271  case 'h': {
272  unsigned u = va_arg(ap, int);
273  sprintf(bp, "0x%x", u);
274  inc_bp();
275  } break;
276  case 'X':
277  case 'x': {
278  int val = va_arg(ap, int);
279 
280  if (size != 0) {
281  if (leading_zero) {
282  sprintf(bp, "%0*x", size, val);
283  } else {
284  sprintf(bp, "%*x", size, val);
285  }
286  } else {
287  sprintf(bp, "%x", val);
288  }
289  inc_bp();
290  } break;
291  case 'd': {
292  int val = va_arg(ap, int);
293 
294  if (size != 0) {
295  sprintf(bp, "%*d", size, val);
296  } else {
297  sprintf(bp, "%d", val);
298  }
299  inc_bp();
300  } break;
301  case 'r': {
302  /* Register. */
303  int val = va_arg(ap, int);
304 
305 #define REG2NAME(num, name) \
306  case num: \
307  sprintf(bp, "" name); \
308  regMap[((num) < 32) ? 0 : 1] |= 1 << ((num) - (((num) < 32) ? 0 : 32)); \
309  break;
310  switch (val) {
311  REG2NAME(26, "gp");
312  REG2NAME(27, "fp");
313  REG2NAME(28, "sp");
314  REG2NAME(29, "ilink1");
315  REG2NAME(30, "ilink2");
316  REG2NAME(31, "blink");
317  REG2NAME(60, "lp_count");
318  default: {
319  const char *ext;
320 
322  if (ext) {
323  sprintf(bp, "%s", ext);
324  } else {
325  sprintf(bp, "r%d", val);
326  }
327  } break;
328  }
329  inc_bp();
330  } break;
331 
332  case 'a': {
333  /* Aux Register. */
334  int val = va_arg(ap, int);
335 #define AUXREG2NAME(num, name) \
336  case num: sprintf(bp, "" name); break;
337  switch (val) {
338  AUXREG2NAME(0x0, "status");
339  AUXREG2NAME(0x1, "semaphore");
340  AUXREG2NAME(0x2, "lp_start");
341  AUXREG2NAME(0x3, "lp_end");
342  AUXREG2NAME(0x4, "identity");
343  AUXREG2NAME(0x5, "debug");
344 
345  default: {
346  const char *ext;
347 
349  if (ext) {
350  sprintf(bp, "%s", ext);
351  } else {
352  arc_sprintf(state, bp, "%h", val);
353  }
354  } break;
355  }
356  inc_bp();
357  } break;
358  case 's': {
359  sprintf(bp, "%s", va_arg(ap, char *));
360  inc_bp();
361  } break;
362  default:
363  fprintf(stderr, "?? format %c\n", p[-1]);
364  break;
365  }
366  }
367  }
368 
369 DOCOMM:
370  *bp = 0;
371  va_end(ap);
372 }
373 
374 static const char *condName[] = {
375  /* 0..15. */
376  "", "z", "nz", "p", "n", "c", "nc", "v",
377  "nv", "gt", "ge", "lt", "le", "hi", "ls", "pnz"
378 };
379 
380 static void
382  const char *instrName,
383  int cond,
384  int condCodeIsPartOfName,
385  int flag,
386  int signExtend,
387  int addrWriteBack,
388  int directMem) {
389  strncpy(state->instrBuffer, instrName, sizeof(state->instrBuffer) - 1);
390  if (cond > 0) {
391  const char *cc = 0;
392 
393  if (!condCodeIsPartOfName) {
394  strcat(state->instrBuffer, ".");
395  }
396  if (cond < 16) {
397  cc = condName[cond];
398  } else {
399  cc = cond_code_name(state, cond);
400  }
401  if (!cc) {
402  cc = "???";
403  }
404  strcat(state->instrBuffer, cc);
405  }
406  if (flag) {
407  strcat(state->instrBuffer, ".f");
408  }
409  switch (state->nullifyMode) {
410  case BR_exec_always:
411  strcat(state->instrBuffer, ".d");
412  break;
413  case BR_exec_when_jump:
414  strcat(state->instrBuffer, ".jd");
415  break;
417  break;
418  }
419  if (signExtend) {
420  strcat(state->instrBuffer, ".x");
421  }
422  if (addrWriteBack) {
423  strcat(state->instrBuffer, ".a");
424  }
425  if (directMem) {
426  strcat(state->instrBuffer, ".di");
427  }
428 }
429 
430 #define write_instr_name() \
431  do { \
432  write_instr_name_(state, instrName, cond, condCodeIsPartOfName, \
433  flag, signExtend, addrWriteBack, directMem); \
434  formatString[0] = '\0'; \
435  } while (0)
436 
437 enum {
438  op_LD0 = 0,
439  op_LD1 = 1,
440  op_ST = 2,
441  op_3 = 3,
442  op_BC = 4,
443  op_BLC = 5,
444  op_LPC = 6,
445  op_JC = 7,
446  op_ADD = 8,
447  op_ADC = 9,
448  op_SUB = 10,
449  op_SBC = 11,
450  op_AND = 12,
451  op_OR = 13,
452  op_BIC = 14,
453  op_XOR = 15
454 };
455 
457 
458 static int
460  int condCodeIsPartOfName = 0;
461  a4_decoding_class decodingClass;
462  const char *instrName;
463  int repeatsOp = 0;
464  int fieldAisReg = 1, fieldBisReg = 1, fieldCisReg = 1;
465  int fieldA, fieldB, fieldC = 0;
466  int flag = 0, cond = 0, is_shimm = 0, is_limm = 0;
467  int signExtend = 0, addrWriteBack = 0, directMem = 0;
468  int is_linked = 0;
469  int offset = 0;
470  int usesAuxReg = 0;
471  int ignoreFirstOpd;
472  char formatString[60];
473  int flags = E_ARC_MACH_A4;
474 
475  state->instructionLen = 4;
476  state->nullifyMode = BR_exec_when_no_jump;
477  state->opWidth = 12;
478  state->isBranch = 0;
479 
480  state->_mem_load = 0;
481  state->_ea_present = 0;
482  state->_load_len = 0;
483  state->ea_reg1 = no_reg;
484  state->ea_reg2 = no_reg;
485  state->_offset = 0;
486 
487  if (!NEXT_WORD(0)) {
488  return 0;
489  }
490 
491  state->_opcode = OPCODE(state->words[0]);
492  instrName = 0;
493  decodingClass = CLASS_A4_ARITH; /* default! */
494  repeatsOp = 0;
495  condCodeIsPartOfName = 0;
496  state->commNum = 0;
497  state->tcnt = 0;
498  state->acnt = 0;
499  state->flow = noflow;
500  ignoreFirstOpd = 0;
501 
502  switch (state->_opcode) {
503  case op_LD0:
504  switch (BITS(state->words[0], 1, 2)) {
505  case 0:
506  instrName = "ld";
507  state->_load_len = 4;
508  break;
509  case 1:
510  instrName = "ldb";
511  state->_load_len = 1;
512  break;
513  case 2:
514  instrName = "ldw";
515  state->_load_len = 2;
516  break;
517  default:
518  instrName = "??? (0[3])";
519  state->flow = invalid_instr;
520  break;
521  }
522  decodingClass = CLASS_A4_LD0;
523  break;
524 
525  case op_LD1:
526  if (BIT(state->words[0], 13)) {
527  instrName = "lr";
528  decodingClass = CLASS_A4_LR;
529  } else {
530  switch (BITS(state->words[0], 10, 11)) {
531  case 0:
532  instrName = "ld";
533  state->_load_len = 4;
534  break;
535  case 1:
536  instrName = "ldb";
537  state->_load_len = 1;
538  break;
539  case 2:
540  instrName = "ldw";
541  state->_load_len = 2;
542  break;
543  default:
544  instrName = "??? (1[3])";
545  state->flow = invalid_instr;
546  break;
547  }
548  decodingClass = CLASS_A4_LD1;
549  }
550  break;
551 
552  case op_ST:
553  if (BIT(state->words[0], 25)) {
554  instrName = "sr";
555  decodingClass = CLASS_A4_SR;
556  } else {
557  switch (BITS(state->words[0], 22, 23)) {
558  case 0: instrName = "st"; break;
559  case 1: instrName = "stb"; break;
560  case 2: instrName = "stw"; break;
561  default:
562  instrName = "??? (2[3])";
563  state->flow = invalid_instr;
564  break;
565  }
566  decodingClass = CLASS_A4_ST;
567  }
568  break;
569 
570  case op_3:
571  decodingClass = CLASS_A4_OP3_GENERAL; /* default for opcode 3... */
572  switch (FIELDC(state->words[0])) {
573  case 0:
574  instrName = "flag";
575  decodingClass = CLASS_A4_FLAG;
576  break;
577  case 1:
578  instrName = "asr";
579  break;
580  case 2:
581  instrName = "lsr";
582  break;
583  case 3:
584  instrName = "ror";
585  break;
586  case 4:
587  instrName = "rrc";
588  break;
589  case 5:
590  instrName = "sexb";
591  break;
592  case 6:
593  instrName = "sexw";
594  break;
595  case 7:
596  instrName = "extb";
597  break;
598  case 8:
599  instrName = "extw";
600  break;
601  case 0x3f: {
602  decodingClass = CLASS_A4_OP3_SUBOPC3F;
603  switch (FIELDD(state->words[0])) {
604  case 0:
605  instrName = "brk";
606  break;
607  case 1:
608  instrName = "sleep";
609  break;
610  case 2:
611  instrName = "swi";
612  break;
613  default:
614  instrName = "???";
615  state->flow = invalid_instr;
616  break;
617  }
618  } break;
619 
620  /* ARC Extension Library Instructions
621  NOTE: We assume that extension codes are these instrs. */
622  default:
623  instrName = instruction_name(state,
624  state->_opcode,
625  FIELDC(state->words[0]),
626  &flags);
627  if (!instrName) {
628  instrName = "???";
629  state->flow = invalid_instr;
630  }
631  if (flags & IGNORE_FIRST_OPD) {
632  ignoreFirstOpd = 1;
633  }
634  break;
635  }
636  break;
637 
638  case op_BC: instrName = "b"; // fallthrough
639  case op_BLC:
640  if (!instrName) {
641  instrName = "bl";
642  }
643  // fallthrough
644  case op_LPC:
645  if (!instrName) {
646  instrName = "lp";
647  }
648  // fallthrough
649  case op_JC:
650  if (!instrName) {
651  if (BITS(state->words[0], 9, 9)) {
652  instrName = "jl";
653  is_linked = 1;
654  } else {
655  instrName = "j";
656  is_linked = 0;
657  }
658  }
659  condCodeIsPartOfName = 1;
660  decodingClass = ((state->_opcode == op_JC) ? CLASS_A4_JC : CLASS_A4_BRANCH);
661  state->isBranch = 1;
662  break;
663 
664  case op_ADD:
665  case op_ADC:
666  case op_AND:
667  repeatsOp = (FIELDC(state->words[0]) == FIELDB(state->words[0]));
668  switch (state->_opcode) {
669  case op_ADD: instrName = (repeatsOp ? "asl" : "add"); break;
670  case op_ADC: instrName = (repeatsOp ? "rlc" : "adc"); break;
671  case op_AND: instrName = (repeatsOp ? "mov" : "and"); break;
672  }
673  break;
674 
675  case op_SUB: instrName = "sub"; break;
676  case op_SBC: instrName = "sbc"; break;
677  case op_OR: instrName = "or"; break;
678  case op_BIC: instrName = "bic"; break;
679 
680  case op_XOR:
681  if (state->words[0] == 0x7fffffff) {
682  /*
683  * Official encoding for NOP (there are many possibilities
684  with ARC). This encoding says: xor -1, -1, -1. */
685  instrName = "nop";
686  decodingClass = CLASS_A4_OP3_SUBOPC3F;
687  } else {
688  instrName = "xor";
689  }
690  break;
691 
692  default:
693  instrName = instruction_name(state, state->_opcode, 0, &flags);
694  /* if (instrName) printf ("FLAGS=0x%x\n", flags); */
695  if (!instrName) {
696  instrName = "???";
697  state->flow = invalid_instr;
698  }
699  if (flags & IGNORE_FIRST_OPD) {
700  ignoreFirstOpd = 1;
701  }
702  break;
703  }
704 
705  fieldAisReg = fieldBisReg = fieldCisReg = 1; /* Assume regs for now. */
706  flag = cond = is_shimm = is_limm = 0;
707  state->nullifyMode = BR_exec_when_no_jump; /* 0 */
708  signExtend = addrWriteBack = directMem = 0;
709  usesAuxReg = 0;
710 
711  switch (decodingClass) {
712  case CLASS_A4_ARITH:
713  CHECK_FIELD_A();
714  CHECK_FIELD_B();
715  if (!repeatsOp) {
716  CHECK_FIELD_C();
717  }
719 
721  if (!ignoreFirstOpd) {
722  WRITE_FORMAT_x(A);
724  if (!repeatsOp) {
726  }
728  arc_sprintf(state, state->operandBuffer, formatString,
729  fieldA, fieldB, fieldC);
730  } else {
731  WRITE_FORMAT_x(B);
732  if (!repeatsOp) {
734  }
735  arc_sprintf(state, state->operandBuffer, formatString,
736  fieldB, fieldC);
737  }
738  break;
739 
741  CHECK_FIELD_A();
742  CHECK_FIELD_B();
744 
746  if (!ignoreFirstOpd) {
747  WRITE_FORMAT_x(A);
750  arc_sprintf(state, state->operandBuffer, formatString,
751  fieldA, fieldB);
752  } else {
753  WRITE_FORMAT_x(B);
754  arc_sprintf(state, state->operandBuffer, formatString, fieldB);
755  }
756  break;
757 
758  case CLASS_A4_FLAG:
759  CHECK_FIELD_B();
761  flag = 0; /* This is the FLAG instruction -- it's redundant. */
762 
764  WRITE_FORMAT_x(B);
765  arc_sprintf(state, state->operandBuffer, formatString, fieldB);
766  break;
767 
768  case CLASS_A4_BRANCH:
769  fieldA = BITS(state->words[0], 7, 26) << 2;
770  fieldA = (fieldA << 10) >> 10; /* Make it signed. */
771  fieldA += addr + 4;
773  flag = 0;
774 
776  /* This address could be a label we know. Convert it. */
777  if (state->_opcode != op_LPC /* LP */) {
778  add_target(fieldA); /* For debugger. */
779  state->flow = state->_opcode == op_BLC /* BL */ ? direct_call : direct_jump;
780  /* indirect calls are achieved by "lr blink,[status];
781  lr dest<- func addr; j [dest]" */
782  }
783 
784  strcat(formatString, "%s"); /* Address/label name. */
785  arc_sprintf(state, state->operandBuffer, formatString,
786  post_address(state, fieldA));
787  break;
788 
789  case CLASS_A4_JC:
790  /* For op_JC -- jump to address specified.
791  Also covers jump and link--bit 9 of the instr. word
792  selects whether linked, thus "is_linked" is set above. */
793  fieldA = 0;
794  CHECK_FIELD_B();
796 
797  if (!fieldBisReg) {
798  fieldA = (fieldB >> 25) & 0x7F; /* Flags. */
799  fieldB = (fieldB & 0xFFFFFF) << 2;
800  state->flow = is_linked ? direct_call : direct_jump;
801  add_target(fieldB);
802  /* Screwy JLcc requires .jd mode to execute correctly
803  but we pretend it is .nd (no delay slot). */
804  if (is_linked && state->nullifyMode == BR_exec_when_jump) {
805  state->nullifyMode = BR_exec_when_no_jump;
806  }
807  } else {
808  state->flow = is_linked ? indirect_call : indirect_jump;
809  /* We should also treat this as indirect call if NOT linked
810  but the preceding instruction was a "lr blink,[status]"
811  and we have a delay slot with "add blink,blink,2".
812  For now we can't detect such. */
813  state->register_for_indirect_jump = fieldB;
814  }
815 
817  strcat(formatString,
818  IS_REG(B) ? "[%r]" : "%s"); /* Address/label name. */
819  if (fieldA != 0) {
821  }
822  if (IS_REG(B)) {
823  arc_sprintf(state, state->operandBuffer, formatString, fieldB, fieldA);
824  } else {
825  arc_sprintf(state, state->operandBuffer, formatString,
826  post_address(state, fieldB), fieldA);
827  }
828  break;
829 
830  case CLASS_A4_LD0:
831  /* LD instruction. B and C can be regs, or one (both?) can be limm. */
832  CHECK_FIELD_A();
833  CHECK_FIELD_B();
834  CHECK_FIELD_C();
835  state->_offset = 0;
836  state->_ea_present = 1;
837  if (fieldBisReg) {
838  state->ea_reg1 = fieldB;
839  } else {
840  state->_offset += fieldB;
841  }
842  if (fieldCisReg) {
843  state->ea_reg2 = fieldC;
844  } else {
845  state->_offset += fieldC;
846  }
847  state->_mem_load = 1;
848 
849  directMem = BIT(state->words[0], 5);
850  addrWriteBack = BIT(state->words[0], 3);
851  signExtend = BIT(state->words[0], 0);
852 
855  if (fieldBisReg || fieldB != 0) {
857  } else {
858  fieldB = fieldC;
859  }
860 
862  arc_sprintf(state, state->operandBuffer, formatString,
863  fieldA, fieldB, fieldC);
864  break;
865 
866  case CLASS_A4_LD1:
867  /* LD instruction. */
868  CHECK_FIELD_B();
869  CHECK_FIELD_A();
870  fieldC = FIELDD(state->words[0]);
871 
872  state->_ea_present = 1;
873  state->_offset = fieldC;
874  state->_mem_load = 1;
875  if (fieldBisReg) {
876  state->ea_reg1 = fieldB;
877  /* Field B is either a shimm (same as fieldC) or limm (different!)
878  Say ea is not present, so only one of us will do the name lookup. */
879  } else {
880  state->_offset += fieldB, state->_ea_present = 0;
881  }
882 
883  directMem = BIT(state->words[0], 14);
884  addrWriteBack = BIT(state->words[0], 12);
885  signExtend = BIT(state->words[0], 9);
886 
889  if (!fieldBisReg) {
890  fieldB = state->_offset;
892  } else {
893  WRITE_FORMAT_x(B);
894  if (fieldC != 0 && !BIT(state->words[0], 13)) {
895  fieldCisReg = 0;
897  } else {
898  WRITE_FORMAT_RB();
899  }
900  }
901  arc_sprintf(state, state->operandBuffer, formatString,
902  fieldA, fieldB, fieldC);
903  break;
904 
905  case CLASS_A4_ST:
906  /* ST instruction. */
907  CHECK_FIELD_B();
908  CHECK_FIELD_C();
909  fieldA = FIELDD(state->words[0]); /* shimm */
910 
911  /* [B,A offset] */
912  state->_ea_present = 1;
913  state->_offset = fieldA;
914  if (fieldBisReg) {
915  state->ea_reg1 = fieldB;
916  /* Field B is either a shimm (same as fieldA) or limm (different!)
917  Say ea is not present, so only one of us will do the name lookup.
918  (for is_limm we do the name translation here). */
919  } else {
920  state->_offset += fieldB, state->_ea_present = 0;
921  }
922 
923  directMem = BIT(state->words[0], 26);
924  addrWriteBack = BIT(state->words[0], 24);
925 
928 
929  if (!fieldBisReg) {
930  fieldB = state->_offset;
932  } else {
933  WRITE_FORMAT_x(B);
934  if (fieldBisReg && fieldA != 0) {
935  fieldAisReg = 0;
937  } else {
938  WRITE_FORMAT_RB();
939  }
940  }
941  arc_sprintf(state, state->operandBuffer, formatString,
942  fieldC, fieldB, fieldA);
943  break;
944 
945  case CLASS_A4_SR:
946  /* SR instruction */
947  CHECK_FIELD_B();
948  CHECK_FIELD_C();
949 
952  /* Try to print B as an aux reg if it is not a core reg. */
953  usesAuxReg = 1;
954  WRITE_FORMAT_x(B);
955  WRITE_FORMAT_RB();
956  arc_sprintf(state, state->operandBuffer, formatString, fieldC, fieldB);
957  break;
958 
961  state->operandBuffer[0] = '\0';
962  break;
963 
964  case CLASS_A4_LR:
965  /* LR instruction */
966  CHECK_FIELD_A();
967  CHECK_FIELD_B();
968 
971  /* Try to print B as an aux reg if it is not a core reg. */
972  usesAuxReg = 1;
973  WRITE_FORMAT_x(B);
974  WRITE_FORMAT_RB();
975  arc_sprintf(state, state->operandBuffer, formatString, fieldA, fieldB);
976  break;
977 
978  default:
979  mwerror(state, "Bad decoding class in ARC disassembler");
980  break;
981  }
982 
983  state->_cond = cond;
984  return state->instructionLen = offset;
985 }
986 
987 /* Return the name of the user specified core extension register REGNUM.
988  CPP_THIS is the C++ this pointer. */
989 
990 static const char *
991 _coreRegName(void *cpp_this ATTRIBUTE_UNUSED, int regnum) {
992  return arcExtMap_coreRegName(regnum);
993 }
994 
995 /* Return the name of the user specified AUX extension register REGNUM.
996  CPP_THIS is the C++ this pointer. */
997 
998 static const char *
999 _auxRegName(void *cpp_this ATTRIBUTE_UNUSED, int regnum) {
1000  return arcExtMap_auxRegName(regnum);
1001 }
1002 
1003 /* Return the name of the user specified condition code with encoding NUM.
1004  CPP_THIS is the C++ this pointer. */
1005 
1006 static const char *
1007 _condCodeName(void *cpp_this ATTRIBUTE_UNUSED, int num) {
1008  return arcExtMap_condCodeName(num);
1009 }
1010 
1011 /* Return the name of the user specified extension instruction
1012  with major opcode MAJOP and minor opcode MINOP.
1013  CPP_THIS is the C++ this pointer.
1014  FLAGS are the instruction flags. */
1015 
1016 static const char *
1017 _instName(void *_this ATTRIBUTE_UNUSED, int majop, int minop, int *flags) {
1018  return arcExtMap_instName(majop, minop, flags);
1019 }
1020 
1021 /* Decode an ARCtangent instruction returning the size of the instruction
1022  in bytes or zero if unrecognized.
1023  ADDRESS is the address of this instruction. */
1024 
1026  int status;
1027  bfd_byte buffer[4];
1028  struct arcDisState s; /* ARC Disassembler state. */
1029  void *stream = info->stream; /* Output stream. */
1030  fprintf_ftype func = info->fprintf_func;
1031 
1032  memset(&s, 0, sizeof(struct arcDisState));
1033 
1034  /* Read first instruction. */
1035  status = (*info->read_memory_func)(address, buffer, 4, info);
1036  if (status != 0) {
1037  (*info->memory_error_func)(status, address, info);
1038  return -1;
1039  }
1040  if (info->endian == BFD_ENDIAN_LITTLE) {
1041  s.words[0] = bfd_getl32(buffer);
1042  } else {
1043  s.words[0] = bfd_getb32(buffer);
1044  }
1045  /* Always read second word in case of limm. */
1046  /* We ignore the result since last insn may not have a limm. */
1047  (*info->read_memory_func)(address + 4, buffer, 4, info);
1048  if (info->endian == BFD_ENDIAN_LITTLE) {
1049  s.words[1] = bfd_getl32(buffer);
1050  } else {
1051  s.words[1] = bfd_getb32(buffer);
1052  }
1053 
1054  s._this = &s;
1055  s.coreRegName = _coreRegName;
1056  s.auxRegName = _auxRegName;
1057  s.condCodeName = _condCodeName;
1058  s.instName = _instName;
1059 
1060  /* Disassemble. */
1061  dsmOneArcInst(address, (void *)&s);
1062 
1063  /* Display the disassembly instruction. */
1064  /*
1065  (*func) (stream, "%08lx ", s.words[0]);
1066  (*func) (stream, " ");
1067  */
1068  (*func)(stream, "%s ", s.instrBuffer);
1069 
1070  if (__TRANSLATION_REQUIRED(s)) {
1071  bfd_vma addr = s.addresses[s.operandBuffer[1] - '0'];
1072 
1073  (*info->print_address_func)((bfd_vma)addr, info);
1074  //(*func) (stream, "\n");
1075  } else {
1076  (*func)(stream, "%s", s.operandBuffer);
1077  }
1078 
1079  return s.instructionLen;
1080 }
#define ARRAY_SIZE(a)
lzma_index ** i
Definition: index.h:629
static const char ext[]
Definition: apprentice.c:1981
#define CHECK_FIELD_A()
Definition: arc-dis.c:112
#define IS_REG(x)
Definition: arc-dis.c:134
@ op_ADD
Definition: arc-dis.c:446
@ op_SUB
Definition: arc-dis.c:448
@ op_3
Definition: arc-dis.c:441
@ op_BIC
Definition: arc-dis.c:452
@ op_SBC
Definition: arc-dis.c:449
@ op_LD1
Definition: arc-dis.c:439
@ op_AND
Definition: arc-dis.c:450
@ op_LPC
Definition: arc-dis.c:444
@ op_OR
Definition: arc-dis.c:451
@ op_XOR
Definition: arc-dis.c:453
@ op_BLC
Definition: arc-dis.c:443
@ op_JC
Definition: arc-dis.c:445
@ op_BC
Definition: arc-dis.c:442
@ op_LD0
Definition: arc-dis.c:438
@ op_ST
Definition: arc-dis.c:440
@ op_ADC
Definition: arc-dis.c:447
#define OPCODE(word)
Definition: arc-dis.c:66
#define FIELDC(word)
Definition: arc-dis.c:69
disassemble_info tm_print_insn_info
#define WRITE_FORMAT_COMMA_x(x)
Definition: arc-dis.c:139
static const char * cond_code_name(struct arcDisState *state, int val)
Definition: arc-dis.c:173
#define inc_bp()
#define CHECK_FIELD_B()
Definition: arc-dis.c:121
#define write_instr_name()
Definition: arc-dis.c:430
#define REG2NAME(num, name)
#define FIELDB(word)
Definition: arc-dis.c:68
a4_decoding_class
Definition: arc-dis.c:44
@ CLASS_A4_SR
Definition: arc-dis.c:56
@ CLASS_A4_JC
Definition: arc-dis.c:50
@ CLASS_A4_OP3_GENERAL
Definition: arc-dis.c:46
@ CLASS_A4_BRANCH
Definition: arc-dis.c:49
@ CLASS_A4_OP3_SUBOPC3F
Definition: arc-dis.c:58
@ CLASS_A4_LD0
Definition: arc-dis.c:53
@ CLASS_A4_LR
Definition: arc-dis.c:59
@ CLASS_A4_ARITH
Definition: arc-dis.c:45
@ CLASS_A4_FLAG
Definition: arc-dis.c:47
@ CLASS_A4_ST
Definition: arc-dis.c:55
@ CLASS_A4_LD1
Definition: arc-dis.c:54
static const char * _condCodeName(void *cpp_this ATTRIBUTE_UNUSED, int num)
Definition: arc-dis.c:1007
#define BITS(word, s, e)
Definition: arc-dis.c:64
#define FIELDD(word)
Definition: arc-dis.c:73
static void arc_sprintf(struct arcDisState *state, char *buf, const char *format,...)
Definition: arc-dis.c:217
static const char * condName[]
Definition: arc-dis.c:374
#define CHECK_FLAG_COND_NULLIFY()
Definition: arc-dis.c:83
#define WRITE_FORMAT_x(x)
Definition: arc-dis.c:141
static const char * _auxRegName(void *cpp_this ATTRIBUTE_UNUSED, int regnum)
Definition: arc-dis.c:999
#define WRITE_FORMAT_COMMA_x_RB(x)
Definition: arc-dis.c:137
#define WRITE_FORMAT_RB()
Definition: arc-dis.c:146
#define add_target(x)
Definition: arc-dis.c:154
static const char * _instName(void *_this ATTRIBUTE_UNUSED, int majop, int minop, int *flags)
Definition: arc-dis.c:1017
#define BIT(word, n)
Definition: arc-dis.c:62
static int dsmOneArcInst(bfd_vma addr, struct arcDisState *state)
Definition: arc-dis.c:459
#define AUXREG2NAME(num, name)
static void mwerror(struct arcDisState *state, const char *msg)
Definition: arc-dis.c:192
#define WRITE_FORMAT_x_COMMA_LB(x)
Definition: arc-dis.c:136
#define NEXT_WORD(x)
Definition: arc-dis.c:152
int ARCTangent_decodeInstr(bfd_vma address, disassemble_info *info)
Definition: arc-dis.c:1025
#define WRITE_NOP_COMMENT()
Definition: arc-dis.c:148
static const char * post_address(struct arcDisState *state, int addr)
Definition: arc-dis.c:199
static const char * instruction_name(struct arcDisState *state, int op1, int op2, int *flags)
Definition: arc-dis.c:181
static const char * _coreRegName(void *cpp_this ATTRIBUTE_UNUSED, int regnum)
Definition: arc-dis.c:991
#define WRITE_FORMAT_x_COMMA(x)
Definition: arc-dis.c:140
static const char * core_reg_name(struct arcDisState *state, int val)
Definition: arc-dis.c:157
static const char * aux_reg_name(struct arcDisState *state, int val)
Definition: arc-dis.c:165
#define WRITE_FORMAT_x_RB(x)
Definition: arc-dis.c:138
static void write_instr_name_(struct arcDisState *state, const char *instrName, int cond, int condCodeIsPartOfName, int flag, int signExtend, int addrWriteBack, int directMem)
Definition: arc-dis.c:381
#define CHECK_FIELD_C()
Definition: arc-dis.c:127
@ no_reg
Definition: arc-dis.h:55
#define __TRANSLATION_REQUIRED(state)
Definition: arc-dis.h:110
@ invalid_instr
Definition: arc-dis.h:52
@ indirect_jump
Definition: arc-dis.h:50
@ direct_jump
Definition: arc-dis.h:48
@ indirect_call
Definition: arc-dis.h:51
@ direct_call
Definition: arc-dis.h:49
@ noflow
Definition: arc-dis.h:47
@ BR_exec_when_jump
Definition: arc-dis.h:31
@ BR_exec_when_no_jump
Definition: arc-dis.h:29
@ BR_exec_always
Definition: arc-dis.h:30
const char * arcExtMap_auxRegName(long address)
Definition: arc-ext.c:435
const char * arcExtMap_instName(int opcode, int insn, int *flags)
Definition: arc-ext.c:300
const char * arcExtMap_condCodeName(int code)
Definition: arc-ext.c:424
const char * arcExtMap_coreRegName(int regnum)
Definition: arc-ext.c:402
#define IGNORE_FIRST_OPD
Definition: arc-ext.h:50
#define A(x)
Definition: arc.h:165
#define E_ARC_MACH_A4
Definition: arc.h:47
#define B(x)
Definition: arc.h:166
#define C(x)
Definition: arc.h:167
ut16 val
Definition: armass64_const.h:6
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
int(* fprintf_ftype)(void *, const char *,...) ATTRIBUTE_FPTR_PRINTF_2
Definition: disas-asm.h:45
voidpf void uLong size
Definition: ioapi.h:138
voidpf stream
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
sprintf
Definition: kernel.h:365
return memset(p, 0, total)
void * p
Definition: libc.cpp:67
#define ATTRIBUTE_UNUSED
Definition: ansidecl.h:288
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags void static offset const char static length static mode static who const char struct statfs static buf unsigned unsigned num
Definition: sflib.h:126
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
unsigned char bfd_byte
Definition: mybfd.h:176
BFD_HOST_U_64_BIT bfd_vma
Definition: mybfd.h:111
static bfd_vma bfd_getb32(const void *p)
Definition: mybfd.h:4979
@ BFD_ENDIAN_LITTLE
Definition: mybfd.h:4618
static bfd_vma bfd_getl32(const void *p)
Definition: mybfd.h:4990
static RzSocket * s
Definition: rtr.c:28
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
static struct sockaddr static addrlen static backlog const void msg
Definition: sfsocketcall.h:119
#define cond(bop, top, mask, flags)
Definition: buffer.h:15
Definition: dis.h:43
static int addr
Definition: z80asm.c:58