Automatic date update in version.in
[deliverable/binutils-gdb.git] / opcodes / arc-dis.c
CommitLineData
252b5132 1/* Instruction printing code for the ARC.
b90efa5b 2 Copyright (C) 1994-2015 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
NC
84 const struct arc_flag_special *flg_spec;
85 size_t len;
86 unsigned i, j, flgidx;
0d2bcfaf 87
886a2506 88 for (i = 0; i < arc_num_flag_special; i++)
252b5132 89 {
886a2506
NC
90 flg_spec = &arc_flag_special_cases[i];
91 len = strlen (flg_spec->name);
279a96ca 92
886a2506
NC
93 if (strncmp (opname, flg_spec->name, len) != 0)
94 continue;
279a96ca 95
886a2506
NC
96 /* Found potential special case instruction. */
97 for (j=0;; ++j)
0d2bcfaf 98 {
886a2506
NC
99 flgidx = flg_spec->flags[j];
100 if (flgidx == 0)
101 break; /* End of the array. */
0d2bcfaf 102
886a2506
NC
103 if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0)
104 return 1;
252b5132 105 }
0d2bcfaf 106 }
886a2506 107 return 0;
0d2bcfaf 108}
252b5132 109
886a2506 110/* Disassemble ARC instructions. */
0d2bcfaf 111
886a2506
NC
112static int
113print_insn_arc (bfd_vma memaddr,
114 struct disassemble_info *info)
0d2bcfaf 115{
886a2506
NC
116 bfd_byte buffer[4];
117 unsigned int lowbyte, highbyte;
118 int status;
119 unsigned int i;
120 int insnLen = 0;
3f94e60d
NC
121 unsigned insn[2] = { 0, 0 };
122 unsigned isa_mask;
886a2506
NC
123 const unsigned char *opidx;
124 const unsigned char *flgidx;
125 const struct arc_opcode *opcode;
126 const char *instrName;
127 int flags;
128 bfd_boolean need_comma;
129 bfd_boolean open_braket;
0d2bcfaf 130
0d2bcfaf 131
886a2506
NC
132 lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
133 highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
0d2bcfaf 134
886a2506
NC
135 switch (info->mach)
136 {
137 case bfd_mach_arc_arc700:
138 isa_mask = ARC_OPCODE_ARC700;
139 break;
0d2bcfaf 140
886a2506
NC
141 case bfd_mach_arc_arc600:
142 isa_mask = ARC_OPCODE_ARC600;
143 break;
0d2bcfaf 144
886a2506
NC
145 case bfd_mach_arc_arcv2:
146 default:
147 isa_mask = ARC_OPCODE_ARCv2HS | ARC_OPCODE_ARCv2EM;
148 break;
0d2bcfaf
NC
149 }
150
886a2506
NC
151 /* Read the insn into a host word. */
152 status = (*info->read_memory_func) (memaddr, buffer, 2, info);
153 if (status != 0)
0d2bcfaf 154 {
886a2506
NC
155 (*info->memory_error_func) (status, memaddr, info);
156 return -1;
0d2bcfaf
NC
157 }
158
886a2506
NC
159 if (info->section
160 && !(info->section->flags & SEC_CODE))
0d2bcfaf 161 {
886a2506
NC
162 /* Sort of data section, just print a 32 bit number. */
163 insnLen = 4;
164 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
165 if (status != 0)
0d2bcfaf 166 {
886a2506
NC
167 (*info->memory_error_func) (status, memaddr + 2, info);
168 return -1;
0d2bcfaf 169 }
886a2506
NC
170 insn[0] = ARRANGE_ENDIAN (info, buffer);
171 (*info->fprintf_func) (info->stream, ".long %#08x", insn[0]);
172 return insnLen;
173 }
279a96ca 174
886a2506
NC
175 if ((((buffer[lowbyte] & 0xf8) > 0x38)
176 && ((buffer[lowbyte] & 0xf8) != 0x48))
177 || ((info->mach == bfd_mach_arc_arcv2)
178 && ((buffer[lowbyte] & 0xF8) == 0x48)) /* FIXME! ugly. */
179 )
180 {
181 /* This is a short instruction. */
182 insnLen = 2;
183 insn[0] = (buffer[lowbyte] << 8) | buffer[highbyte];
184 }
185 else
186 {
187 insnLen = 4;
188
189 /* This is a long instruction: Read the remaning 2 bytes. */
190 status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
191 if (status != 0)
0d2bcfaf 192 {
886a2506
NC
193 (*info->memory_error_func) (status, memaddr + 2, info);
194 return -1;
0d2bcfaf 195 }
886a2506
NC
196 insn[0] = ARRANGE_ENDIAN (info, buffer);
197 }
198
199 /* This variable may be set by the instruction decoder. It suggests
200 the number of bytes objdump should display on a single line. If
201 the instruction decoder sets this, it should always set it to
202 the same value in order to get reasonable looking output. */
203 info->bytes_per_line = 8;
204
205 /* The next two variables control the way objdump displays the raw data.
206 For example, if bytes_per_line is 8 and bytes_per_chunk is 4, the
207 output will look like this:
208 00: 00000000 00000000
209 with the chunks displayed according to "display_endian". */
210 info->bytes_per_chunk = 2;
211 info->display_endian = info->endian;
212
213 /* Set some defaults for the insn info. */
214 info->insn_info_valid = 1;
215 info->branch_delay_insns = 0;
216 info->data_size = 0;
217 info->insn_type = dis_nonbranch;
218 info->target = 0;
219 info->target2 = 0;
220
221 /* FIXME to be moved in dissasemble_init_for_target. */
222 info->disassembler_needs_relocs = TRUE;
223
224 /* Find the first match in the opcode table. */
225 for (i = 0; i < arc_num_opcodes; i++)
226 {
227 bfd_boolean invalid = FALSE;
228
229 opcode = &arc_opcodes[i];
279a96ca 230
886a2506 231 if (ARC_SHORT (opcode->mask) && (insnLen == 2))
0d2bcfaf 232 {
886a2506
NC
233 if (OPCODE_AC (opcode->opcode) != OPCODE_AC (insn[0]))
234 continue;
0d2bcfaf 235 }
886a2506 236 else if (!ARC_SHORT (opcode->mask) && (insnLen == 4))
0d2bcfaf 237 {
886a2506
NC
238 if (OPCODE (opcode->opcode) != OPCODE (insn[0]))
239 continue;
0d2bcfaf 240 }
886a2506
NC
241 else
242 continue;
243
244 if ((insn[0] ^ opcode->opcode) & opcode->mask)
245 continue;
279a96ca 246
886a2506
NC
247 if (!(opcode->cpu & isa_mask))
248 continue;
249
250 /* Possible candidate, check the operands. */
251 for (opidx = opcode->operands; *opidx; opidx++)
0d2bcfaf 252 {
886a2506
NC
253 int value;
254 const struct arc_operand *operand = &arc_operands[*opidx];
255
256 if (operand->flags & ARC_OPERAND_FAKE)
257 continue;
258
259 if (operand->extract)
260 value = (*operand->extract) (insn[0], &invalid);
261 else
262 value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
263
264 /* Check for LIMM indicator. If it is there, then make sure
265 we pick the right format. */
266 if (operand->flags & ARC_OPERAND_IR
267 && !(operand->flags & ARC_OPERAND_LIMM))
252b5132 268 {
886a2506
NC
269 if ((value == 0x3E && insnLen == 4)
270 || (value == 0x1E && insnLen == 2))
271 {
272 invalid = TRUE;
273 break;
274 }
252b5132 275 }
0d2bcfaf 276 }
252b5132 277
886a2506
NC
278 /* Check the flags. */
279 for (flgidx = opcode->flags; *flgidx; flgidx++)
0d2bcfaf 280 {
886a2506
NC
281 /* Get a valid flag class. */
282 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
283 const unsigned *flgopridx;
284 int foundA = 0, foundB = 0;
285
286 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
252b5132 287 {
886a2506
NC
288 const struct arc_flag_operand *flg_operand = &arc_flag_operands[*flgopridx];
289 unsigned int value;
290
291 value = (insn[0] >> flg_operand->shift) & ((1 << flg_operand->bits) - 1);
292 if (value == flg_operand->code)
293 foundA = 1;
294 if (value)
295 foundB = 1;
252b5132 296 }
886a2506 297 if (!foundA && foundB)
252b5132 298 {
886a2506
NC
299 invalid = TRUE;
300 break;
252b5132 301 }
0d2bcfaf 302 }
279a96ca 303
886a2506
NC
304 if (invalid)
305 continue;
252b5132 306
886a2506
NC
307 /* The instruction is valid. */
308 goto found;
309 }
279a96ca 310
886a2506
NC
311 /* No instruction found. Try the extenssions. */
312 instrName = arcExtMap_instName (OPCODE (insn[0]), insn[0], &flags);
313 if (instrName)
314 {
315 opcode = &arc_opcodes[0];
316 (*info->fprintf_func) (info->stream, "%s", instrName);
317 goto print_flags;
318 }
252b5132 319
886a2506
NC
320 if (insnLen == 2)
321 (*info->fprintf_func) (info->stream, ".long %#04x", insn[0]);
322 else
323 (*info->fprintf_func) (info->stream, ".long %#08x", insn[0]);
324
325 info->insn_type = dis_noninsn;
326 return insnLen;
327
328 found:
329 /* Print the mnemonic. */
330 (*info->fprintf_func) (info->stream, "%s", opcode->name);
331
332 /* Preselect the insn class. */
333 switch (opcode->class)
334 {
335 case BRANCH:
336 case JUMP:
337 if (!strncmp (opcode->name, "bl", 2)
338 || !strncmp (opcode->name, "jl", 2))
339 info->insn_type = dis_jsr;
279a96ca 340 else
886a2506
NC
341 info->insn_type = dis_branch;
342 break;
343 case MEMORY:
344 info->insn_type = dis_dref; /* FIXME! DB indicates mov as memory! */
0d2bcfaf 345 break;
0d2bcfaf 346 default:
886a2506 347 info->insn_type = dis_nonbranch;
0d2bcfaf
NC
348 break;
349 }
279a96ca 350
886a2506 351 pr_debug ("%s: 0x%08x\n", opcode->name, opcode->opcode);
279a96ca 352
886a2506
NC
353 print_flags:
354 /* Now extract and print the flags. */
355 for (flgidx = opcode->flags; *flgidx; flgidx++)
0d2bcfaf 356 {
886a2506
NC
357 /* Get a valid flag class. */
358 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
359 const unsigned *flgopridx;
279a96ca 360
886a2506 361 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
0d2bcfaf 362 {
886a2506
NC
363 const struct arc_flag_operand *flg_operand = &arc_flag_operands[*flgopridx];
364 unsigned int value;
279a96ca 365
886a2506
NC
366 if (!flg_operand->favail)
367 continue;
279a96ca 368
886a2506
NC
369 value = (insn[0] >> flg_operand->shift) & ((1 << flg_operand->bits) - 1);
370 if (value == flg_operand->code)
371 {
372 /* FIXME!: print correctly nt/t flag. */
373 if (!special_flag_p (opcode->name, flg_operand->name))
374 (*info->fprintf_func) (info->stream, ".");
375 else if (info->insn_type == dis_dref)
376 {
377 switch (flg_operand->name[0])
378 {
379 case 'b':
380 info->data_size = 1;
381 break;
382 case 'h':
383 case 'w':
384 info->data_size = 2;
385 break;
386 default:
387 info->data_size = 4;
388 break;
389 }
390 }
391 (*info->fprintf_func) (info->stream, "%s", flg_operand->name);
392 }
279a96ca 393
886a2506
NC
394 if (flg_operand->name[0] == 'd'
395 && flg_operand->name[1] == 0)
396 info->branch_delay_insns = 1;
279a96ca 397 }
886a2506 398 }
279a96ca 399
886a2506
NC
400 if (opcode->operands[0] != 0)
401 (*info->fprintf_func) (info->stream, "\t");
279a96ca 402
886a2506
NC
403 need_comma = FALSE;
404 open_braket = FALSE;
279a96ca 405
886a2506
NC
406 /* Now extract and print the operands. */
407 for (opidx = opcode->operands; *opidx; opidx++)
408 {
409 const struct arc_operand *operand = &arc_operands[*opidx];
410 int value;
279a96ca 411
886a2506 412 if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
0d2bcfaf 413 {
886a2506
NC
414 (*info->fprintf_func) (info->stream, "]");
415 open_braket = FALSE;
416 continue;
0d2bcfaf 417 }
279a96ca 418
886a2506
NC
419 /* Only take input from real operands. */
420 if ((operand->flags & ARC_OPERAND_FAKE)
421 && !(operand->flags & ARC_OPERAND_BRAKET))
422 continue;
279a96ca 423
886a2506
NC
424 if (operand->extract)
425 value = (*operand->extract) (insn[0], (int *) NULL);
0d2bcfaf 426 else
0d2bcfaf 427 {
886a2506 428 if (operand->flags & ARC_OPERAND_ALIGNED32)
0d2bcfaf 429 {
886a2506
NC
430 value = (insn[0] >> operand->shift)
431 & ((1 << (operand->bits - 2)) - 1);
432 value = value << 2;
252b5132 433 }
252b5132 434 else
886a2506
NC
435 {
436 value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
437 }
438 if (operand->flags & ARC_OPERAND_SIGNED)
439 {
440 int signbit = 1 << (operand->bits - 1);
441 value = (value ^ signbit) - signbit;
442 }
252b5132 443 }
279a96ca 444
886a2506
NC
445 if (operand->flags & ARC_OPERAND_IGNORE
446 && (operand->flags & ARC_OPERAND_IR
447 && value == -1))
448 continue;
279a96ca 449
886a2506
NC
450 if (need_comma)
451 (*info->fprintf_func) (info->stream, ",");
279a96ca 452
886a2506 453 if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
0d2bcfaf 454 {
886a2506
NC
455 (*info->fprintf_func) (info->stream, "[");
456 open_braket = TRUE;
457 need_comma = FALSE;
458 continue;
0d2bcfaf 459 }
886a2506
NC
460
461 /* Read the limm operand, if required. */
462 if (operand->flags & ARC_OPERAND_LIMM
463 && !(operand->flags & ARC_OPERAND_DUPLICATE))
0d2bcfaf 464 {
886a2506
NC
465 status = (*info->read_memory_func) (memaddr + insnLen, buffer,
466 4, info);
467 if (status != 0)
0d2bcfaf 468 {
886a2506
NC
469 (*info->memory_error_func) (status, memaddr + insnLen, info);
470 return -1;
0d2bcfaf 471 }
886a2506 472 insn[1] = ARRANGE_ENDIAN (info, buffer);
0d2bcfaf 473 }
279a96ca 474
886a2506
NC
475 /* Print the operand as directed by the flags. */
476 if (operand->flags & ARC_OPERAND_IR)
477 {
478 assert (value >=0 && value < 64);
479 (*info->fprintf_func) (info->stream, "%s", regnames[value]);
480 if (operand->flags & ARC_OPERAND_TRUNCATE)
481 (*info->fprintf_func) (info->stream, "%s", regnames[value+1]);
482 }
483 else if (operand->flags & ARC_OPERAND_LIMM)
484 {
485 (*info->fprintf_func) (info->stream, "%#x", insn[1]);
486 if (info->insn_type == dis_branch
487 || info->insn_type == dis_jsr)
488 info->target = (bfd_vma) insn[1];
489 }
490 else if (operand->flags & ARC_OPERAND_PCREL)
491 {
492 /* PCL relative. */
493 if (info->flags & INSN_HAS_RELOC)
494 memaddr = 0;
495 (*info->print_address_func) ((memaddr & ~3) + value, info);
279a96ca 496
886a2506
NC
497 info->target = (bfd_vma) (memaddr & ~3) + value;
498 }
499 else if (operand->flags & ARC_OPERAND_SIGNED)
500 (*info->fprintf_func) (info->stream, "%d", value);
501 else
502 if (operand->flags & ARC_OPERAND_TRUNCATE
503 && !(operand->flags & ARC_OPERAND_ALIGNED32)
504 && !(operand->flags & ARC_OPERAND_ALIGNED16)
505 && value > 0 && value <= 14)
506 (*info->fprintf_func) (info->stream, "r13-%s",
507 regnames[13 + value - 1]);
508 else
509 (*info->fprintf_func) (info->stream, "%#x", value);
510
511 need_comma = TRUE;
512
513 /* Adjust insn len. */
514 if (operand->flags & ARC_OPERAND_LIMM
515 && !(operand->flags & ARC_OPERAND_DUPLICATE))
516 insnLen += 4;
252b5132 517 }
279a96ca 518
886a2506 519 return insnLen;
252b5132
RH
520}
521
47b0e7ad 522
886a2506
NC
523disassembler_ftype
524arc_get_disassembler (bfd *abfd)
252b5132 525{
886a2506
NC
526 /* Read the extenssion insns and registers, if any. */
527 build_ARC_extmap (abfd);
528 dump_ARC_extmap ();
252b5132 529
886a2506 530 return print_insn_arc;
252b5132
RH
531}
532
886a2506 533/* Disassemble ARC instructions. Used by debugger. */
47b0e7ad 534
886a2506
NC
535struct arcDisState
536arcAnalyzeInstr (bfd_vma memaddr,
537 struct disassemble_info *info)
0d2bcfaf 538{
886a2506
NC
539 struct arcDisState ret;
540 memset (&ret, 0, sizeof (struct arcDisState));
541
542 ret.instructionLen = print_insn_arc (memaddr, info);
543
544#if 0
545 ret.words[0] = insn[0];
546 ret.words[1] = insn[1];
547 ret._this = &ret;
548 ret.coreRegName = _coreRegName;
549 ret.auxRegName = _auxRegName;
550 ret.condCodeName = _condCodeName;
551 ret.instName = _instName;
552#endif
47b0e7ad 553
886a2506 554 return ret;
0d2bcfaf
NC
555}
556
886a2506
NC
557/* Local variables:
558 eval: (c-set-style "gnu")
559 indent-tabs-mode: t
560 End: */
This page took 0.961431 seconds and 4 git commands to generate.