arc: Remove EF_ARC_CPU_GENERIC constant.
[deliverable/binutils-gdb.git] / opcodes / arc-dis.c
CommitLineData
252b5132 1/* Instruction printing code for the ARC.
6f2750fe 2 Copyright (C) 1994-2016 Free Software Foundation, Inc.
886a2506
NC
3
4 Contributed by Claudiu Zissulescu (claziss@synopsys.com)
252b5132 5
9b201bb5
NC
6 This file is part of libopcodes.
7
8 This library is free software; you can redistribute it and/or modify
0d2bcfaf 9 it under the terms of the GNU General Public License as published by
9b201bb5
NC
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
252b5132 12
9b201bb5
NC
13 It is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16 License for more details.
252b5132 17
0d2bcfaf
NC
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
47b0e7ad
NC
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
252b5132 22
5eb3690e 23#include "sysdep.h"
886a2506
NC
24#include <stdio.h>
25#include <assert.h>
252b5132
RH
26#include "dis-asm.h"
27#include "opcode/arc.h"
0d2bcfaf
NC
28#include "arc-dis.h"
29#include "arc-ext.h"
252b5132 30
252b5132 31
886a2506 32/* Globals variables. */
82b829a7 33
886a2506 34static const char * const regnames[64] =
47b0e7ad 35{
886a2506
NC
36 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
37 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
38 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
39 "r24", "r25", "gp", "fp", "sp", "ilink", "r30", "blink",
40
41 "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
42 "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
43 "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",
44 "r56", "r57", "ACCL", "ACCH", "lp_count", "rezerved", "LIMM", "pcl"
45};
46
47/* Macros section. */
48
49#ifdef DEBUG
50# define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
51#else
52# define pr_debug(fmt, args...)
53#endif
54
55#define ARRANGE_ENDIAN(info, buf) \
56 (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf)) \
57 : bfd_getb32 (buf))
58
59#define BITS(word,s,e) (((word) << (sizeof (word) * 8 - 1 - e)) >> \
60 (s + (sizeof (word) * 8 - 1 - e)))
279a96ca
AJ
61#define OPCODE(word) (BITS ((word), 27, 31))
62#define FIELDA(word) (BITS ((word), 21, 26))
63#define FIELDB(word) (BITS ((word), 15, 20))
64#define FIELDC(word) (BITS ((word), 9, 14))
252b5132 65
886a2506 66#define OPCODE_AC(word) (BITS ((word), 11, 15))
252b5132 67
886a2506 68/* Functions implementation. */
252b5132 69
886a2506
NC
70static bfd_vma
71bfd_getm32 (unsigned int data)
0d2bcfaf 72{
886a2506 73 bfd_vma value = 0;
0d2bcfaf 74
886a2506
NC
75 value = ((data & 0xff00) | (data & 0xff)) << 16;
76 value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16;
77 return value;
0d2bcfaf
NC
78}
79
886a2506
NC
80static int
81special_flag_p (const char *opname,
82 const char *flgname)
0d2bcfaf 83{
886a2506 84 const struct arc_flag_special *flg_spec;
886a2506 85 unsigned i, j, flgidx;
0d2bcfaf 86
886a2506 87 for (i = 0; i < arc_num_flag_special; i++)
252b5132 88 {
886a2506 89 flg_spec = &arc_flag_special_cases[i];
279a96ca 90
24b368f8 91 if (strcmp (opname, flg_spec->name))
886a2506 92 continue;
279a96ca 93
886a2506
NC
94 /* Found potential special case instruction. */
95 for (j=0;; ++j)
0d2bcfaf 96 {
886a2506
NC
97 flgidx = flg_spec->flags[j];
98 if (flgidx == 0)
99 break; /* End of the array. */
0d2bcfaf 100
886a2506
NC
101 if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0)
102 return 1;
252b5132 103 }
0d2bcfaf 104 }
886a2506 105 return 0;
0d2bcfaf 106}
252b5132 107
886a2506 108/* Disassemble ARC instructions. */
0d2bcfaf 109
886a2506
NC
110static int
111print_insn_arc (bfd_vma memaddr,
112 struct disassemble_info *info)
0d2bcfaf 113{
886a2506
NC
114 bfd_byte buffer[4];
115 unsigned int lowbyte, highbyte;
116 int status;
117 unsigned int i;
118 int insnLen = 0;
3f94e60d
NC
119 unsigned insn[2] = { 0, 0 };
120 unsigned isa_mask;
886a2506
NC
121 const unsigned char *opidx;
122 const unsigned char *flgidx;
123 const struct arc_opcode *opcode;
124 const char *instrName;
125 int flags;
126 bfd_boolean need_comma;
127 bfd_boolean open_braket;
24b368f8 128 int size;
0d2bcfaf 129
886a2506
NC
130 lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
131 highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
0d2bcfaf 132
886a2506
NC
133 switch (info->mach)
134 {
135 case bfd_mach_arc_arc700:
136 isa_mask = ARC_OPCODE_ARC700;
137 break;
0d2bcfaf 138
886a2506
NC
139 case bfd_mach_arc_arc600:
140 isa_mask = ARC_OPCODE_ARC600;
141 break;
0d2bcfaf 142
886a2506
NC
143 case bfd_mach_arc_arcv2:
144 default:
145 isa_mask = ARC_OPCODE_ARCv2HS | ARC_OPCODE_ARCv2EM;
146 break;
0d2bcfaf
NC
147 }
148
24b368f8
CZ
149 /* This variable may be set by the instruction decoder. It suggests
150 the number of bytes objdump should display on a single line. If
151 the instruction decoder sets this, it should always set it to
152 the same value in order to get reasonable looking output. */
153
154 info->bytes_per_line = 8;
155
156 /* In the next lines, we set two info variables control the way
157 objdump displays the raw data. For example, if bytes_per_line is
158 8 and bytes_per_chunk is 4, the output will look like this:
159 00: 00000000 00000000
160 with the chunks displayed according to "display_endian". */
161
162 if (info->section
163 && !(info->section->flags & SEC_CODE))
164 {
165 /* This is not a CODE section. */
166 switch (info->section->size)
167 {
168 case 1:
169 case 2:
170 case 4:
171 size = info->section->size;
172 break;
173 default:
174 size = (info->section->size & 0x01) ? 1 : 4;
175 break;
176 }
177 info->bytes_per_chunk = 1;
178 info->display_endian = info->endian;
179 }
180 else
181 {
182 size = 2;
183 info->bytes_per_chunk = 2;
184 info->display_endian = info->endian;
185 }
186
886a2506 187 /* Read the insn into a host word. */
24b368f8 188 status = (*info->read_memory_func) (memaddr, buffer, size, info);
886a2506 189 if (status != 0)
0d2bcfaf 190 {
886a2506
NC
191 (*info->memory_error_func) (status, memaddr, info);
192 return -1;
0d2bcfaf
NC
193 }
194
886a2506
NC
195 if (info->section
196 && !(info->section->flags & SEC_CODE))
0d2bcfaf 197 {
24b368f8
CZ
198 /* Data section. */
199 unsigned long data;
200
201 data = bfd_get_bits (buffer, size * 8,
202 info->display_endian == BFD_ENDIAN_BIG);
203 switch (size)
0d2bcfaf 204 {
24b368f8
CZ
205 case 1:
206 (*info->fprintf_func) (info->stream, ".byte\t0x%02lx", data);
207 break;
208 case 2:
209 (*info->fprintf_func) (info->stream, ".short\t0x%04lx", data);
210 break;
211 case 4:
212 (*info->fprintf_func) (info->stream, ".word\t0x%08lx", data);
213 break;
214 default:
215 abort ();
0d2bcfaf 216 }
24b368f8 217 return size;
886a2506 218 }
279a96ca 219
24b368f8 220 if ( (((buffer[lowbyte] & 0xf8) > 0x38)
886a2506
NC
221 && ((buffer[lowbyte] & 0xf8) != 0x48))
222 || ((info->mach == bfd_mach_arc_arcv2)
223 && ((buffer[lowbyte] & 0xF8) == 0x48)) /* FIXME! ugly. */
224 )
225 {
226 /* This is a short instruction. */
227 insnLen = 2;
228 insn[0] = (buffer[lowbyte] << 8) | buffer[highbyte];
229 }
230 else
231 {
232 insnLen = 4;
233
234 /* This is a long instruction: Read the remaning 2 bytes. */
235 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
236 if (status != 0)
0d2bcfaf 237 {
886a2506
NC
238 (*info->memory_error_func) (status, memaddr + 2, info);
239 return -1;
0d2bcfaf 240 }
886a2506
NC
241 insn[0] = ARRANGE_ENDIAN (info, buffer);
242 }
243
886a2506
NC
244 /* Set some defaults for the insn info. */
245 info->insn_info_valid = 1;
246 info->branch_delay_insns = 0;
247 info->data_size = 0;
248 info->insn_type = dis_nonbranch;
249 info->target = 0;
250 info->target2 = 0;
251
252 /* FIXME to be moved in dissasemble_init_for_target. */
253 info->disassembler_needs_relocs = TRUE;
254
255 /* Find the first match in the opcode table. */
256 for (i = 0; i < arc_num_opcodes; i++)
257 {
258 bfd_boolean invalid = FALSE;
259
260 opcode = &arc_opcodes[i];
279a96ca 261
886a2506 262 if (ARC_SHORT (opcode->mask) && (insnLen == 2))
0d2bcfaf 263 {
886a2506
NC
264 if (OPCODE_AC (opcode->opcode) != OPCODE_AC (insn[0]))
265 continue;
0d2bcfaf 266 }
886a2506 267 else if (!ARC_SHORT (opcode->mask) && (insnLen == 4))
0d2bcfaf 268 {
886a2506
NC
269 if (OPCODE (opcode->opcode) != OPCODE (insn[0]))
270 continue;
0d2bcfaf 271 }
886a2506
NC
272 else
273 continue;
274
275 if ((insn[0] ^ opcode->opcode) & opcode->mask)
276 continue;
279a96ca 277
886a2506
NC
278 if (!(opcode->cpu & isa_mask))
279 continue;
280
281 /* Possible candidate, check the operands. */
282 for (opidx = opcode->operands; *opidx; opidx++)
0d2bcfaf 283 {
886a2506
NC
284 int value;
285 const struct arc_operand *operand = &arc_operands[*opidx];
286
287 if (operand->flags & ARC_OPERAND_FAKE)
288 continue;
289
290 if (operand->extract)
291 value = (*operand->extract) (insn[0], &invalid);
292 else
293 value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
294
295 /* Check for LIMM indicator. If it is there, then make sure
296 we pick the right format. */
297 if (operand->flags & ARC_OPERAND_IR
298 && !(operand->flags & ARC_OPERAND_LIMM))
252b5132 299 {
886a2506
NC
300 if ((value == 0x3E && insnLen == 4)
301 || (value == 0x1E && insnLen == 2))
302 {
303 invalid = TRUE;
304 break;
305 }
252b5132 306 }
0d2bcfaf 307 }
252b5132 308
886a2506
NC
309 /* Check the flags. */
310 for (flgidx = opcode->flags; *flgidx; flgidx++)
0d2bcfaf 311 {
886a2506
NC
312 /* Get a valid flag class. */
313 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
314 const unsigned *flgopridx;
315 int foundA = 0, foundB = 0;
316
317 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
252b5132 318 {
886a2506
NC
319 const struct arc_flag_operand *flg_operand = &arc_flag_operands[*flgopridx];
320 unsigned int value;
321
322 value = (insn[0] >> flg_operand->shift) & ((1 << flg_operand->bits) - 1);
323 if (value == flg_operand->code)
324 foundA = 1;
325 if (value)
326 foundB = 1;
252b5132 327 }
886a2506 328 if (!foundA && foundB)
252b5132 329 {
886a2506
NC
330 invalid = TRUE;
331 break;
252b5132 332 }
0d2bcfaf 333 }
279a96ca 334
886a2506
NC
335 if (invalid)
336 continue;
252b5132 337
886a2506
NC
338 /* The instruction is valid. */
339 goto found;
340 }
279a96ca 341
886a2506
NC
342 /* No instruction found. Try the extenssions. */
343 instrName = arcExtMap_instName (OPCODE (insn[0]), insn[0], &flags);
344 if (instrName)
345 {
346 opcode = &arc_opcodes[0];
347 (*info->fprintf_func) (info->stream, "%s", instrName);
348 goto print_flags;
349 }
252b5132 350
886a2506
NC
351 if (insnLen == 2)
352 (*info->fprintf_func) (info->stream, ".long %#04x", insn[0]);
353 else
354 (*info->fprintf_func) (info->stream, ".long %#08x", insn[0]);
355
356 info->insn_type = dis_noninsn;
357 return insnLen;
358
359 found:
360 /* Print the mnemonic. */
361 (*info->fprintf_func) (info->stream, "%s", opcode->name);
362
363 /* Preselect the insn class. */
364 switch (opcode->class)
365 {
366 case BRANCH:
367 case JUMP:
368 if (!strncmp (opcode->name, "bl", 2)
369 || !strncmp (opcode->name, "jl", 2))
370 info->insn_type = dis_jsr;
279a96ca 371 else
886a2506
NC
372 info->insn_type = dis_branch;
373 break;
374 case MEMORY:
375 info->insn_type = dis_dref; /* FIXME! DB indicates mov as memory! */
0d2bcfaf 376 break;
0d2bcfaf 377 default:
886a2506 378 info->insn_type = dis_nonbranch;
0d2bcfaf
NC
379 break;
380 }
279a96ca 381
886a2506 382 pr_debug ("%s: 0x%08x\n", opcode->name, opcode->opcode);
279a96ca 383
886a2506
NC
384 print_flags:
385 /* Now extract and print the flags. */
386 for (flgidx = opcode->flags; *flgidx; flgidx++)
0d2bcfaf 387 {
886a2506
NC
388 /* Get a valid flag class. */
389 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
390 const unsigned *flgopridx;
279a96ca 391
886a2506 392 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
0d2bcfaf 393 {
886a2506
NC
394 const struct arc_flag_operand *flg_operand = &arc_flag_operands[*flgopridx];
395 unsigned int value;
279a96ca 396
886a2506
NC
397 if (!flg_operand->favail)
398 continue;
279a96ca 399
886a2506
NC
400 value = (insn[0] >> flg_operand->shift) & ((1 << flg_operand->bits) - 1);
401 if (value == flg_operand->code)
402 {
403 /* FIXME!: print correctly nt/t flag. */
404 if (!special_flag_p (opcode->name, flg_operand->name))
405 (*info->fprintf_func) (info->stream, ".");
406 else if (info->insn_type == dis_dref)
407 {
408 switch (flg_operand->name[0])
409 {
410 case 'b':
411 info->data_size = 1;
412 break;
413 case 'h':
414 case 'w':
415 info->data_size = 2;
416 break;
417 default:
418 info->data_size = 4;
419 break;
420 }
421 }
422 (*info->fprintf_func) (info->stream, "%s", flg_operand->name);
423 }
279a96ca 424
886a2506
NC
425 if (flg_operand->name[0] == 'd'
426 && flg_operand->name[1] == 0)
427 info->branch_delay_insns = 1;
279a96ca 428 }
886a2506 429 }
279a96ca 430
886a2506
NC
431 if (opcode->operands[0] != 0)
432 (*info->fprintf_func) (info->stream, "\t");
279a96ca 433
886a2506
NC
434 need_comma = FALSE;
435 open_braket = FALSE;
279a96ca 436
886a2506
NC
437 /* Now extract and print the operands. */
438 for (opidx = opcode->operands; *opidx; opidx++)
439 {
440 const struct arc_operand *operand = &arc_operands[*opidx];
441 int value;
279a96ca 442
886a2506 443 if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
0d2bcfaf 444 {
886a2506
NC
445 (*info->fprintf_func) (info->stream, "]");
446 open_braket = FALSE;
447 continue;
0d2bcfaf 448 }
279a96ca 449
886a2506
NC
450 /* Only take input from real operands. */
451 if ((operand->flags & ARC_OPERAND_FAKE)
452 && !(operand->flags & ARC_OPERAND_BRAKET))
453 continue;
279a96ca 454
886a2506
NC
455 if (operand->extract)
456 value = (*operand->extract) (insn[0], (int *) NULL);
0d2bcfaf 457 else
0d2bcfaf 458 {
886a2506 459 if (operand->flags & ARC_OPERAND_ALIGNED32)
0d2bcfaf 460 {
886a2506
NC
461 value = (insn[0] >> operand->shift)
462 & ((1 << (operand->bits - 2)) - 1);
463 value = value << 2;
252b5132 464 }
252b5132 465 else
886a2506
NC
466 {
467 value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
468 }
469 if (operand->flags & ARC_OPERAND_SIGNED)
470 {
471 int signbit = 1 << (operand->bits - 1);
472 value = (value ^ signbit) - signbit;
473 }
252b5132 474 }
279a96ca 475
886a2506
NC
476 if (operand->flags & ARC_OPERAND_IGNORE
477 && (operand->flags & ARC_OPERAND_IR
478 && value == -1))
479 continue;
279a96ca 480
886a2506
NC
481 if (need_comma)
482 (*info->fprintf_func) (info->stream, ",");
279a96ca 483
886a2506 484 if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
0d2bcfaf 485 {
886a2506
NC
486 (*info->fprintf_func) (info->stream, "[");
487 open_braket = TRUE;
488 need_comma = FALSE;
489 continue;
0d2bcfaf 490 }
886a2506
NC
491
492 /* Read the limm operand, if required. */
493 if (operand->flags & ARC_OPERAND_LIMM
494 && !(operand->flags & ARC_OPERAND_DUPLICATE))
0d2bcfaf 495 {
886a2506
NC
496 status = (*info->read_memory_func) (memaddr + insnLen, buffer,
497 4, info);
498 if (status != 0)
0d2bcfaf 499 {
886a2506
NC
500 (*info->memory_error_func) (status, memaddr + insnLen, info);
501 return -1;
0d2bcfaf 502 }
886a2506 503 insn[1] = ARRANGE_ENDIAN (info, buffer);
0d2bcfaf 504 }
279a96ca 505
886a2506
NC
506 /* Print the operand as directed by the flags. */
507 if (operand->flags & ARC_OPERAND_IR)
508 {
509 assert (value >=0 && value < 64);
510 (*info->fprintf_func) (info->stream, "%s", regnames[value]);
511 if (operand->flags & ARC_OPERAND_TRUNCATE)
512 (*info->fprintf_func) (info->stream, "%s", regnames[value+1]);
513 }
514 else if (operand->flags & ARC_OPERAND_LIMM)
515 {
516 (*info->fprintf_func) (info->stream, "%#x", insn[1]);
517 if (info->insn_type == dis_branch
518 || info->insn_type == dis_jsr)
519 info->target = (bfd_vma) insn[1];
520 }
521 else if (operand->flags & ARC_OPERAND_PCREL)
522 {
523 /* PCL relative. */
524 if (info->flags & INSN_HAS_RELOC)
525 memaddr = 0;
526 (*info->print_address_func) ((memaddr & ~3) + value, info);
279a96ca 527
886a2506
NC
528 info->target = (bfd_vma) (memaddr & ~3) + value;
529 }
530 else if (operand->flags & ARC_OPERAND_SIGNED)
531 (*info->fprintf_func) (info->stream, "%d", value);
532 else
533 if (operand->flags & ARC_OPERAND_TRUNCATE
534 && !(operand->flags & ARC_OPERAND_ALIGNED32)
535 && !(operand->flags & ARC_OPERAND_ALIGNED16)
536 && value > 0 && value <= 14)
537 (*info->fprintf_func) (info->stream, "r13-%s",
538 regnames[13 + value - 1]);
539 else
540 (*info->fprintf_func) (info->stream, "%#x", value);
541
542 need_comma = TRUE;
543
544 /* Adjust insn len. */
545 if (operand->flags & ARC_OPERAND_LIMM
546 && !(operand->flags & ARC_OPERAND_DUPLICATE))
547 insnLen += 4;
252b5132 548 }
279a96ca 549
886a2506 550 return insnLen;
252b5132
RH
551}
552
47b0e7ad 553
886a2506
NC
554disassembler_ftype
555arc_get_disassembler (bfd *abfd)
252b5132 556{
886a2506
NC
557 /* Read the extenssion insns and registers, if any. */
558 build_ARC_extmap (abfd);
559 dump_ARC_extmap ();
252b5132 560
886a2506 561 return print_insn_arc;
252b5132
RH
562}
563
886a2506 564/* Disassemble ARC instructions. Used by debugger. */
47b0e7ad 565
886a2506
NC
566struct arcDisState
567arcAnalyzeInstr (bfd_vma memaddr,
568 struct disassemble_info *info)
0d2bcfaf 569{
886a2506
NC
570 struct arcDisState ret;
571 memset (&ret, 0, sizeof (struct arcDisState));
572
573 ret.instructionLen = print_insn_arc (memaddr, info);
574
575#if 0
576 ret.words[0] = insn[0];
577 ret.words[1] = insn[1];
578 ret._this = &ret;
579 ret.coreRegName = _coreRegName;
580 ret.auxRegName = _auxRegName;
581 ret.condCodeName = _condCodeName;
582 ret.instName = _instName;
583#endif
47b0e7ad 584
886a2506 585 return ret;
0d2bcfaf
NC
586}
587
886a2506
NC
588/* Local variables:
589 eval: (c-set-style "gnu")
590 indent-tabs-mode: t
591 End: */
This page took 0.928145 seconds and 4 git commands to generate.