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