1 /* Instruction printing code for the ARC.
2    Copyright (C) 1994-2016 Free Software Foundation, Inc.
3 
4    Contributed by Claudiu Zissulescu (claziss@synopsys.com)
5 
6    This file is part of libopcodes.
7 
8    This library is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3, or (at your option)
11    any later version.
12 
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.
17 
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
20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21    MA 02110-1301, USA.  */
22 
23 #include "sysdep.h"
24 #include <stdio.h>
25 #include <assert.h>
26 #include "dis-asm.h"
27 #include "opcode/arc.h"
28 #include "arc-dis.h"
29 #include "arc-ext.h"
30 
31 /* Structure used to iterate over, and extract the values for, operands of
32    an opcode.  */
33 
34 struct arc_operand_iterator
35 {
36   enum
37     {
38       OPERAND_ITERATOR_STANDARD,
39       OPERAND_ITERATOR_LONG
40     } mode;
41 
42   /* The array of 32-bit values that make up this instruction.  All
43      required values have been pre-loaded into this array during the
44      find_format call.  */
45   unsigned *insn;
46 
47   union
48   {
49     struct
50     {
51       /* The opcode this iterator is operating on.  */
52       const struct arc_opcode *opcode;
53 
54       /* The index into the opcodes operand index list.  */
55       const unsigned char *opidx;
56     } standard;
57 
58     struct
59     {
60       /* The long instruction opcode this iterator is operating on.  */
61       const struct arc_long_opcode *long_opcode;
62 
63       /* Two indexes into the opcodes operand index lists.  */
64       const unsigned char *opidx_base, *opidx_limm;
65     } long_insn;
66   } state;
67 };
68 
69 /* Globals variables.  */
70 
71 static const char * const regnames[64] =
72 {
73   "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
74   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
75   "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
76   "r24", "r25", "gp", "fp", "sp", "ilink", "r30", "blink",
77 
78   "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
79   "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
80   "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",
81   "r56", "r57", "ACCL", "ACCH", "lp_count", "rezerved", "LIMM", "pcl"
82 };
83 
84 /* Macros section.  */
85 
86 #ifdef DEBUG
87 # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
88 #else
89 # define pr_debug(fmt, args...)
90 #endif
91 
92 #define ARRANGE_ENDIAN(info, buf)					\
93   (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf))	\
94    : bfd_getb32 (buf))
95 
96 #define BITS(word,s,e)  (((word) << (sizeof (word) * 8 - 1 - e)) >>	\
97 			 (s + (sizeof (word) * 8 - 1 - e)))
98 #define OPCODE(word)	(BITS ((word), 27, 31))
99 
100 #define OPCODE_AC(word)   (BITS ((word), 11, 15))
101 
102 /* Functions implementation.  */
103 
104 static bfd_vma
bfd_getm32(unsigned int data)105 bfd_getm32 (unsigned int data)
106 {
107   bfd_vma value = 0;
108 
109   value = ((data & 0xff00) | (data & 0xff)) << 16;
110   value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16;
111   return value;
112 }
113 
114 static int
special_flag_p(const char * opname,const char * flgname)115 special_flag_p (const char *opname,
116 		const char *flgname)
117 {
118   const struct arc_flag_special *flg_spec;
119   unsigned i, j, flgidx;
120 
121   for (i = 0; i < arc_num_flag_special; i++)
122     {
123       flg_spec = &arc_flag_special_cases[i];
124 
125       if (strcmp (opname, flg_spec->name))
126 	continue;
127 
128       /* Found potential special case instruction.  */
129       for (j=0;; ++j)
130 	{
131 	  flgidx = flg_spec->flags[j];
132 	  if (flgidx == 0)
133 	    break; /* End of the array.  */
134 
135 	  if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0)
136 	    return 1;
137 	}
138     }
139   return 0;
140 }
141 
142 /* Find opcode from ARC_TABLE given the instruction described by INSN and
143    INSNLEN.  The ISA_MASK restricts the possible matches in ARC_TABLE.  */
144 
145 static const struct arc_opcode *
find_format_from_table(const struct arc_opcode * arc_table,unsigned * insn,unsigned int insn_len,unsigned isa_mask,bfd_boolean * has_limm)146 find_format_from_table (const struct arc_opcode *arc_table,
147                         unsigned *insn, unsigned int insn_len,
148                         unsigned isa_mask, bfd_boolean *has_limm)
149 {
150   unsigned int i = 0;
151   const struct arc_opcode *opcode = NULL;
152   const unsigned char *opidx;
153   const unsigned char *flgidx;
154 
155   do {
156     bfd_boolean invalid = FALSE;
157 
158     opcode = &arc_table[i++];
159 
160     if (ARC_SHORT (opcode->mask) && (insn_len == 2))
161       {
162 	if (OPCODE_AC (opcode->opcode) != OPCODE_AC (insn[0]))
163 	  continue;
164       }
165     else if (!ARC_SHORT (opcode->mask) && (insn_len == 4))
166       {
167 	if (OPCODE (opcode->opcode) != OPCODE (insn[0]))
168 	  continue;
169       }
170     else
171       continue;
172 
173     if ((insn[0] ^ opcode->opcode) & opcode->mask)
174       continue;
175 
176     if (!(opcode->cpu & isa_mask))
177       continue;
178 
179     *has_limm = FALSE;
180 
181     /* Possible candidate, check the operands.  */
182     for (opidx = opcode->operands; *opidx; opidx++)
183       {
184 	int value;
185 	const struct arc_operand *operand = &arc_operands[*opidx];
186 
187 	if (operand->flags & ARC_OPERAND_FAKE)
188 	  continue;
189 
190 	if (operand->extract)
191 	  value = (*operand->extract) (insn[0], &invalid);
192 	else
193 	  value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
194 
195 	/* Check for LIMM indicator.  If it is there, then make sure
196 	   we pick the right format.  */
197 	if (operand->flags & ARC_OPERAND_IR
198 	    && !(operand->flags & ARC_OPERAND_LIMM))
199 	  {
200 	    if ((value == 0x3E && insn_len == 4)
201 		|| (value == 0x1E && insn_len == 2))
202 	      {
203 		invalid = TRUE;
204 		break;
205 	      }
206 	  }
207 
208         if (operand->flags & ARC_OPERAND_LIMM
209             && !(operand->flags & ARC_OPERAND_DUPLICATE))
210           *has_limm = TRUE;
211       }
212 
213     /* Check the flags.  */
214     for (flgidx = opcode->flags; *flgidx; flgidx++)
215       {
216 	/* Get a valid flag class.  */
217 	const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
218 	const unsigned *flgopridx;
219 	int foundA = 0, foundB = 0;
220 	unsigned int value;
221 
222 	/* Check first the extensions.  */
223 	if (cl_flags->flag_class & F_CLASS_EXTEND)
224 	  {
225 	    value = (insn[0] & 0x1F);
226 	    if (arcExtMap_condCodeName (value))
227 	      continue;
228 	  }
229 	for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
230 	  {
231 	    const struct arc_flag_operand *flg_operand =
232 	      &arc_flag_operands[*flgopridx];
233 
234 	    value = (insn[0] >> flg_operand->shift)
235 	      & ((1 << flg_operand->bits) - 1);
236 	    if (value == flg_operand->code)
237 	      foundA = 1;
238 	    if (value)
239 	      foundB = 1;
240 	  }
241 	if (!foundA && foundB)
242 	  {
243 	    invalid = TRUE;
244 	    break;
245 	  }
246       }
247 
248     if (invalid)
249       continue;
250 
251     /* The instruction is valid.  */
252     return opcode;
253   } while (opcode->mask);
254 
255   return NULL;
256 }
257 
258 /* Find long instructions matching values in INSN array.  */
259 
260 static const struct arc_long_opcode *
find_format_long_instructions(unsigned * insn,unsigned int * insn_len,unsigned isa_mask,bfd_vma memaddr,struct disassemble_info * info)261 find_format_long_instructions (unsigned *insn,
262                                unsigned int *insn_len,
263                                unsigned isa_mask,
264                                bfd_vma memaddr,
265                                struct disassemble_info *info)
266 {
267   unsigned int i;
268   unsigned limm = 0;
269   bfd_boolean limm_loaded = FALSE;
270 
271   for (i = 0; i < arc_num_long_opcodes; ++i)
272     {
273       bfd_byte buffer[4];
274       int status;
275       const struct arc_opcode *opcode;
276 
277       opcode = &arc_long_opcodes[i].base_opcode;
278 
279       if (ARC_SHORT (opcode->mask) && (*insn_len == 2))
280         {
281           if (OPCODE_AC (opcode->opcode) != OPCODE_AC (insn[0]))
282             continue;
283         }
284       else if (!ARC_SHORT (opcode->mask) && (*insn_len == 4))
285         {
286           if (OPCODE (opcode->opcode) != OPCODE (insn[0]))
287             continue;
288         }
289       else
290         continue;
291 
292       if ((insn[0] ^ opcode->opcode) & opcode->mask)
293         continue;
294 
295       if (!(opcode->cpu & isa_mask))
296         continue;
297 
298       if (!limm_loaded)
299         {
300           status = (*info->read_memory_func) (memaddr + *insn_len, buffer,
301                                               4, info);
302           if (status != 0)
303             return NULL;
304 
305           limm = ARRANGE_ENDIAN (info, buffer);
306           limm_loaded = TRUE;
307         }
308 
309       /* Check the second word using the mask and template.  */
310       if ((limm & arc_long_opcodes[i].limm_mask)
311           != arc_long_opcodes[i].limm_template)
312         continue;
313 
314       (*insn_len) += 4;
315       insn[1] = limm;
316       return &arc_long_opcodes[i];
317     }
318 
319   return NULL;
320 }
321 
322 /* Find opcode for INSN, trying various different sources.  The instruction
323    length in INSN_LEN will be updated if the instruction requires a LIMM
324    extension, and the additional values loaded into the INSN array (which
325    must be big enough).
326 
327    A pointer to the opcode is placed into OPCODE_RESULT, and ITER is
328    initialised, ready to iterate over the operands of the found opcode.
329 
330    This function returns TRUE in almost all cases, FALSE is reserved to
331    indicate an error (failing to find an opcode is not an error) a
332    returned result of FALSE would indicate that the disassembler can't
333    continue.
334 
335    If no matching opcode is found then the returned result will be TRUE,
336    the value placed into OPCODE_RESULT will be NULL, ITER will be
337    undefined, and INSN_LEN will be unchanged.
338 
339    If a matching opcode is found, then the returned result will be TRUE,
340    the opcode pointer is placed into OPCODE_RESULT, INSN_LEN will be
341    increased by 4 if the instruction requires a LIMM, and the LIMM value
342    will have been loaded into the INSN[1].  Finally, ITER will have been
343    initialised so that calls to OPERAND_ITERATOR_NEXT will iterate over
344    the opcode's operands.  */
345 
346 static bfd_boolean
find_format(bfd_vma memaddr,unsigned * insn,unsigned int * insn_len,unsigned isa_mask,struct disassemble_info * info,const struct arc_opcode ** opcode_result,struct arc_operand_iterator * iter)347 find_format (bfd_vma memaddr, unsigned *insn, unsigned int *insn_len,
348              unsigned isa_mask, struct disassemble_info *info,
349              const struct arc_opcode **opcode_result,
350              struct arc_operand_iterator *iter)
351 {
352   const struct arc_opcode *opcode;
353   bfd_boolean needs_limm;
354 
355   /* Find the first match in the opcode table.  */
356   opcode = find_format_from_table (arc_opcodes, insn, *insn_len,
357                                    isa_mask, &needs_limm);
358 
359   if (opcode == NULL)
360     {
361       const extInstruction_t *einsn;
362 
363       /* No instruction found.  Try the extensions.  */
364       einsn = arcExtMap_insn (OPCODE (insn[0]), insn[0]);
365       if (einsn != NULL)
366 	{
367 	  const char *errmsg = NULL;
368 	  opcode = arcExtMap_genOpcode (einsn, isa_mask, &errmsg);
369 	  if (opcode == NULL)
370 	    {
371 	      (*info->fprintf_func) (info->stream,
372 				     "An error occured while "
373 				     "generating the extension instruction "
374 				     "operations");
375               *opcode_result = NULL;
376 	      return FALSE;
377 	    }
378 
379 	  opcode = find_format_from_table (opcode, insn, *insn_len,
380                                            isa_mask, &needs_limm);
381 	  assert (opcode != NULL);
382 	}
383     }
384 
385   if (needs_limm && opcode != NULL)
386     {
387       bfd_byte buffer[4];
388       int status;
389 
390       status = (*info->read_memory_func) (memaddr + *insn_len, buffer,
391                                           4, info);
392       if (status != 0)
393         {
394           opcode = NULL;
395         }
396       else
397         {
398           insn[1] = ARRANGE_ENDIAN (info, buffer);
399           *insn_len += 4;
400         }
401     }
402 
403   if (opcode == NULL)
404     {
405       const struct arc_long_opcode *long_opcode;
406 
407       /* No instruction found yet, try the long instructions.  */
408       long_opcode =
409         find_format_long_instructions (insn, insn_len, isa_mask,
410                                        memaddr, info);
411 
412       if (long_opcode != NULL)
413         {
414           iter->mode = OPERAND_ITERATOR_LONG;
415           iter->insn = insn;
416           iter->state.long_insn.long_opcode = long_opcode;
417           iter->state.long_insn.opidx_base =
418             long_opcode->base_opcode.operands;
419           iter->state.long_insn.opidx_limm =
420             long_opcode->operands;
421           opcode = &long_opcode->base_opcode;
422         }
423     }
424   else
425     {
426       iter->mode = OPERAND_ITERATOR_STANDARD;
427       iter->insn = insn;
428       iter->state.standard.opcode = opcode;
429       iter->state.standard.opidx = opcode->operands;
430     }
431 
432   *opcode_result = opcode;
433   return TRUE;
434 }
435 
436 static void
print_flags(const struct arc_opcode * opcode,unsigned * insn,struct disassemble_info * info)437 print_flags (const struct arc_opcode *opcode,
438 	     unsigned *insn,
439 	     struct disassemble_info *info)
440 {
441   const unsigned char *flgidx;
442   unsigned int value;
443 
444   /* Now extract and print the flags.  */
445   for (flgidx = opcode->flags; *flgidx; flgidx++)
446     {
447       /* Get a valid flag class.  */
448       const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
449       const unsigned *flgopridx;
450 
451       /* Check first the extensions.  */
452       if (cl_flags->flag_class & F_CLASS_EXTEND)
453 	{
454 	  const char *name;
455 	  value = (insn[0] & 0x1F);
456 
457 	  name = arcExtMap_condCodeName (value);
458 	  if (name)
459 	    {
460 	      (*info->fprintf_func) (info->stream, ".%s", name);
461 	      continue;
462 	    }
463 	}
464 
465       for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
466 	{
467 	  const struct arc_flag_operand *flg_operand =
468 	    &arc_flag_operands[*flgopridx];
469 
470 	  if (!flg_operand->favail)
471 	    continue;
472 
473 	  value = (insn[0] >> flg_operand->shift)
474 	    & ((1 << flg_operand->bits) - 1);
475 	  if (value == flg_operand->code)
476 	    {
477 	       /* FIXME!: print correctly nt/t flag.  */
478 	      if (!special_flag_p (opcode->name, flg_operand->name))
479 		(*info->fprintf_func) (info->stream, ".");
480 	      else if (info->insn_type == dis_dref)
481 		{
482 		  switch (flg_operand->name[0])
483 		    {
484 		    case 'b':
485 		      info->data_size = 1;
486 		      break;
487 		    case 'h':
488 		    case 'w':
489 		      info->data_size = 2;
490 		      break;
491 		    default:
492 		      info->data_size = 4;
493 		      break;
494 		    }
495 		}
496 	      if (flg_operand->name[0] == 'd'
497 		  && flg_operand->name[1] == 0)
498 		info->branch_delay_insns = 1;
499 
500 	      /* Check if it is a conditional flag.  */
501 	      if (cl_flags->flag_class & F_CLASS_COND)
502 		{
503 		  if (info->insn_type == dis_jsr)
504 		    info->insn_type = dis_condjsr;
505 		  else if (info->insn_type == dis_branch)
506 		    info->insn_type = dis_condbranch;
507 		}
508 
509 	      (*info->fprintf_func) (info->stream, "%s", flg_operand->name);
510 	    }
511 	}
512     }
513 }
514 
515 static const char *
get_auxreg(const struct arc_opcode * opcode,int value,unsigned isa_mask)516 get_auxreg (const struct arc_opcode *opcode,
517 	    int value,
518 	    unsigned isa_mask)
519 {
520   const char *name;
521   unsigned int i;
522   const struct arc_aux_reg *auxr = &arc_aux_regs[0];
523 
524   if (opcode->insn_class != AUXREG)
525     return NULL;
526 
527   name = arcExtMap_auxRegName (value);
528   if (name)
529     return name;
530 
531   for (i = 0; i < arc_num_aux_regs; i++, auxr++)
532     {
533       if (!(auxr->cpu & isa_mask))
534 	continue;
535 
536       if (auxr->subclass != NONE)
537 	return NULL;
538 
539       if (auxr->address == value)
540 	return auxr->name;
541     }
542   return NULL;
543 }
544 
545 /* Calculate the instruction length for an instruction starting with MSB
546    and LSB, the most and least significant byte.  The ISA_MASK is used to
547    filter the instructions considered to only those that are part of the
548    current architecture.
549 
550    The instruction lengths are calculated from the ARC_OPCODE table, and
551    cached for later use.  */
552 
553 static unsigned int
arc_insn_length(bfd_byte msb,bfd_byte lsb,struct disassemble_info * info)554 arc_insn_length (bfd_byte msb, bfd_byte lsb, struct disassemble_info *info)
555 {
556   bfd_byte major_opcode = msb >> 3;
557 
558   switch (info->mach)
559     {
560     case bfd_mach_arc_arc700:
561       /* The nps400 extension set requires this special casing of the
562 	 instruction length calculation.  Right now this is not causing any
563 	 problems as none of the known extensions overlap in opcode space,
564 	 but, if they ever do then we might need to start carrying
565 	 information around in the elf about which extensions are in use.  */
566       if (major_opcode == 0xb)
567         {
568           bfd_byte minor_opcode = lsb & 0x1f;
569 
570           if (minor_opcode < 4)
571             return 2;
572         }
573     case bfd_mach_arc_arc600:
574       return (major_opcode > 0xb) ? 2 : 4;
575       break;
576 
577     case bfd_mach_arc_arcv2:
578       return (major_opcode > 0x7) ? 2 : 4;
579       break;
580 
581     default:
582       abort ();
583     }
584 }
585 
586 /* Extract and return the value of OPERAND from the instruction whose value
587    is held in the array INSN.  */
588 
589 static int
extract_operand_value(const struct arc_operand * operand,unsigned * insn)590 extract_operand_value (const struct arc_operand *operand, unsigned *insn)
591 {
592   int value;
593 
594   /* Read the limm operand, if required.  */
595   if (operand->flags & ARC_OPERAND_LIMM)
596     /* The second part of the instruction value will have been loaded as
597        part of the find_format call made earlier.  */
598     value = insn[1];
599   else
600     {
601       if (operand->extract)
602         value = (*operand->extract) (insn[0], (int *) NULL);
603       else
604         {
605           if (operand->flags & ARC_OPERAND_ALIGNED32)
606             {
607               value = (insn[0] >> operand->shift)
608                 & ((1 << (operand->bits - 2)) - 1);
609               value = value << 2;
610             }
611           else
612             {
613               value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
614             }
615           if (operand->flags & ARC_OPERAND_SIGNED)
616             {
617               int signbit = 1 << (operand->bits - 1);
618               value = (value ^ signbit) - signbit;
619             }
620         }
621     }
622 
623   return value;
624 }
625 
626 /* Find the next operand, and the operands value from ITER.  Return TRUE if
627    there is another operand, otherwise return FALSE.  If there is an
628    operand returned then the operand is placed into OPERAND, and the value
629    into VALUE.  If there is no operand returned then OPERAND and VALUE are
630    unchanged.  */
631 
632 static bfd_boolean
operand_iterator_next(struct arc_operand_iterator * iter,const struct arc_operand ** operand,int * value)633 operand_iterator_next (struct arc_operand_iterator *iter,
634                        const struct arc_operand **operand,
635                        int *value)
636 {
637   if (iter->mode == OPERAND_ITERATOR_STANDARD)
638     {
639       if (*iter->state.standard.opidx == 0)
640         {
641           *operand = NULL;
642           return FALSE;
643         }
644 
645       *operand = &arc_operands[*iter->state.standard.opidx];
646       *value = extract_operand_value (*operand, iter->insn);
647       iter->state.standard.opidx++;
648     }
649   else
650     {
651       const struct arc_operand *operand_base, *operand_limm;
652       int value_base, value_limm;
653 
654       if (*iter->state.long_insn.opidx_limm == 0)
655         {
656           *operand = NULL;
657           return FALSE;
658         }
659 
660       operand_base = &arc_operands[*iter->state.long_insn.opidx_base];
661       operand_limm = &arc_operands[*iter->state.long_insn.opidx_limm];
662 
663       if (operand_base->flags & ARC_OPERAND_LIMM)
664         {
665           /* We've reached the end of the operand list.  */
666           *operand = NULL;
667           return FALSE;
668         }
669 
670       value_base = value_limm = 0;
671       if (!(operand_limm->flags & ARC_OPERAND_IGNORE))
672         {
673           /* This should never happen.  If it does then the use of
674              extract_operand_value below will access memory beyond
675              the insn array.  */
676           assert ((operand_limm->flags & ARC_OPERAND_LIMM) == 0);
677 
678           *operand = operand_limm;
679           value_limm = extract_operand_value (*operand, &iter->insn[1]);
680         }
681 
682       if (!(operand_base->flags & ARC_OPERAND_IGNORE))
683         {
684           *operand = operand_base;
685           value_base = extract_operand_value (*operand, iter->insn);
686         }
687 
688       /* This is a bit of a fudge.  There's no reason why simply ORing
689          together the two values is the right thing to do, however, for all
690          the cases we currently have, it is the right thing, so, for now,
691          I've put off solving the more complex problem.  */
692       *value = value_base | value_limm;
693 
694       iter->state.long_insn.opidx_base++;
695       iter->state.long_insn.opidx_limm++;
696     }
697   return TRUE;
698 }
699 
700 /* Disassemble ARC instructions.  */
701 
702 static int
print_insn_arc(bfd_vma memaddr,struct disassemble_info * info)703 print_insn_arc (bfd_vma memaddr,
704 		struct disassemble_info *info)
705 {
706   bfd_byte buffer[4];
707   unsigned int lowbyte, highbyte;
708   int status;
709   unsigned int insn_len;
710   unsigned insn[2] = { 0, 0 };
711   unsigned isa_mask;
712   const struct arc_opcode *opcode;
713   bfd_boolean need_comma;
714   bfd_boolean open_braket;
715   int size;
716   const struct arc_operand *operand;
717   int value;
718   struct arc_operand_iterator iter;
719 
720   memset (&iter, 0, sizeof (iter));
721   lowbyte  = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
722   highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
723 
724   switch (info->mach)
725     {
726     case bfd_mach_arc_arc700:
727       isa_mask = ARC_OPCODE_ARC700;
728       break;
729 
730     case bfd_mach_arc_arc600:
731       isa_mask = ARC_OPCODE_ARC600;
732       break;
733 
734     case bfd_mach_arc_arcv2:
735     default:
736       isa_mask = ARC_OPCODE_ARCv2HS | ARC_OPCODE_ARCv2EM;
737       break;
738     }
739 
740   /* This variable may be set by the instruction decoder.  It suggests
741      the number of bytes objdump should display on a single line.  If
742      the instruction decoder sets this, it should always set it to
743      the same value in order to get reasonable looking output.  */
744 
745   info->bytes_per_line  = 8;
746 
747   /* In the next lines, we set two info variables control the way
748      objdump displays the raw data.  For example, if bytes_per_line is
749      8 and bytes_per_chunk is 4, the output will look like this:
750      00:   00000000 00000000
751      with the chunks displayed according to "display_endian".  */
752 
753   if (info->section
754       && !(info->section->flags & SEC_CODE))
755     {
756       /* This is not a CODE section.  */
757       switch (info->section->size)
758 	{
759 	case 1:
760 	case 2:
761 	case 4:
762 	  size = info->section->size;
763 	  break;
764 	default:
765 	  size = (info->section->size & 0x01) ? 1 : 4;
766 	  break;
767 	}
768       info->bytes_per_chunk = 1;
769       info->display_endian = info->endian;
770     }
771   else
772     {
773       size = 2;
774       info->bytes_per_chunk = 2;
775       info->display_endian = info->endian;
776     }
777 
778   /* Read the insn into a host word.  */
779   status = (*info->read_memory_func) (memaddr, buffer, size, info);
780   if (status != 0)
781     {
782       (*info->memory_error_func) (status, memaddr, info);
783       return -1;
784     }
785 
786   if (info->section
787       && !(info->section->flags & SEC_CODE))
788     {
789       /* Data section.  */
790       unsigned long data;
791 
792       data = bfd_get_bits (buffer, size * 8,
793 			   info->display_endian == BFD_ENDIAN_BIG);
794       switch (size)
795 	{
796 	case 1:
797 	  (*info->fprintf_func) (info->stream, ".byte\t0x%02lx", data);
798 	  break;
799 	case 2:
800 	  (*info->fprintf_func) (info->stream, ".short\t0x%04lx", data);
801 	  break;
802 	case 4:
803 	  (*info->fprintf_func) (info->stream, ".word\t0x%08lx", data);
804 	  break;
805 	default:
806 	  abort ();
807 	}
808       return size;
809     }
810 
811   insn_len = arc_insn_length (buffer[lowbyte], buffer[highbyte], info);
812   pr_debug ("instruction length = %d bytes\n", insn_len);
813   switch (insn_len)
814     {
815     case 2:
816       insn[0] = (buffer[lowbyte] << 8) | buffer[highbyte];
817       break;
818 
819     default:
820       /* An unknown instruction is treated as being length 4.  This is
821          possibly not the best solution, but matches the behaviour that was
822          in place before the table based instruction length look-up was
823          introduced.  */
824     case 4:
825       /* This is a long instruction: Read the remaning 2 bytes.  */
826       status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
827       if (status != 0)
828 	{
829 	  (*info->memory_error_func) (status, memaddr + 2, info);
830 	  return -1;
831 	}
832       insn[0] = ARRANGE_ENDIAN (info, buffer);
833       break;
834     }
835 
836   /* Set some defaults for the insn info.  */
837   info->insn_info_valid    = 1;
838   info->branch_delay_insns = 0;
839   info->data_size	   = 0;
840   info->insn_type	   = dis_nonbranch;
841   info->target		   = 0;
842   info->target2		   = 0;
843 
844   /* FIXME to be moved in dissasemble_init_for_target.  */
845   info->disassembler_needs_relocs = TRUE;
846 
847   /* Find the first match in the opcode table.  */
848   if (!find_format (memaddr, insn, &insn_len, isa_mask, info, &opcode, &iter))
849     return -1;
850 
851   if (!opcode)
852     {
853       if (insn_len == 2)
854         (*info->fprintf_func) (info->stream, ".long %#04x", insn[0]);
855       else
856         (*info->fprintf_func) (info->stream, ".long %#08x", insn[0]);
857 
858       info->insn_type = dis_noninsn;
859       return insn_len;
860     }
861 
862   /* Print the mnemonic.  */
863   (*info->fprintf_func) (info->stream, "%s", opcode->name);
864 
865   /* Preselect the insn class.  */
866   switch (opcode->insn_class)
867     {
868     case BRANCH:
869     case JUMP:
870       if (!strncmp (opcode->name, "bl", 2)
871 	  || !strncmp (opcode->name, "jl", 2))
872 	{
873 	  if (opcode->subclass == COND)
874 	    info->insn_type = dis_condjsr;
875 	  else
876 	    info->insn_type = dis_jsr;
877 	}
878       else
879 	{
880 	  if (opcode->subclass == COND)
881 	    info->insn_type = dis_condbranch;
882 	  else
883 	    info->insn_type = dis_branch;
884 	}
885       break;
886     case MEMORY:
887       info->insn_type = dis_dref; /* FIXME! DB indicates mov as memory! */
888       break;
889     default:
890       info->insn_type = dis_nonbranch;
891       break;
892     }
893 
894   pr_debug ("%s: 0x%08x\n", opcode->name, opcode->opcode);
895 
896   print_flags (opcode, insn, info);
897 
898   if (opcode->operands[0] != 0)
899     (*info->fprintf_func) (info->stream, "\t");
900 
901   need_comma = FALSE;
902   open_braket = FALSE;
903 
904   /* Now extract and print the operands.  */
905   operand = NULL;
906   while (operand_iterator_next (&iter, &operand, &value))
907     {
908       if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
909 	{
910 	  (*info->fprintf_func) (info->stream, "]");
911 	  open_braket = FALSE;
912 	  continue;
913 	}
914 
915       /* Only take input from real operands.  */
916       if ((operand->flags & ARC_OPERAND_FAKE)
917 	  && !(operand->flags & ARC_OPERAND_BRAKET))
918 	continue;
919 
920       if ((operand->flags & ARC_OPERAND_IGNORE)
921 	  && (operand->flags & ARC_OPERAND_IR)
922           && value == -1)
923 	continue;
924 
925       if (need_comma)
926 	(*info->fprintf_func) (info->stream, ",");
927 
928       if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
929 	{
930 	  (*info->fprintf_func) (info->stream, "[");
931 	  open_braket = TRUE;
932 	  need_comma = FALSE;
933 	  continue;
934 	}
935 
936       /* Print the operand as directed by the flags.  */
937       if (operand->flags & ARC_OPERAND_IR)
938 	{
939 	  const char *rname;
940 
941 	  assert (value >=0 && value < 64);
942 	  rname = arcExtMap_coreRegName (value);
943 	  if (!rname)
944 	    rname = regnames[value];
945 	  (*info->fprintf_func) (info->stream, "%s", rname);
946 	  if (operand->flags & ARC_OPERAND_TRUNCATE)
947 	    {
948 	      rname = arcExtMap_coreRegName (value + 1);
949 	      if (!rname)
950 		rname = regnames[value + 1];
951 	      (*info->fprintf_func) (info->stream, "%s", rname);
952 	    }
953 	}
954       else if (operand->flags & ARC_OPERAND_LIMM)
955 	{
956 	  const char *rname = get_auxreg (opcode, value, isa_mask);
957 	  if (rname && open_braket)
958 	    (*info->fprintf_func) (info->stream, "%s", rname);
959 	  else
960 	    {
961 	      (*info->fprintf_func) (info->stream, "%#x", value);
962 	      if (info->insn_type == dis_branch
963 		  || info->insn_type == dis_jsr)
964 		info->target = (bfd_vma) value;
965 	    }
966 	}
967       else if (operand->flags & ARC_OPERAND_PCREL)
968 	{
969 	   /* PCL relative.  */
970 	  if (info->flags & INSN_HAS_RELOC)
971 	    memaddr = 0;
972 	  (*info->print_address_func) ((memaddr & ~3) + value, info);
973 
974 	  info->target = (bfd_vma) (memaddr & ~3) + value;
975 	}
976       else if (operand->flags & ARC_OPERAND_SIGNED)
977 	{
978 	  const char *rname = get_auxreg (opcode, value, isa_mask);
979 	  if (rname && open_braket)
980 	    (*info->fprintf_func) (info->stream, "%s", rname);
981 	  else
982 	    (*info->fprintf_func) (info->stream, "%d", value);
983 	}
984       else
985 	{
986 	  if (operand->flags & ARC_OPERAND_TRUNCATE
987 	      && !(operand->flags & ARC_OPERAND_ALIGNED32)
988 	      && !(operand->flags & ARC_OPERAND_ALIGNED16)
989 	      && value > 0 && value <= 14)
990 	    (*info->fprintf_func) (info->stream, "r13-%s",
991 				   regnames[13 + value - 1]);
992 	  else
993 	    {
994 	      const char *rname = get_auxreg (opcode, value, isa_mask);
995 	      if (rname && open_braket)
996 		(*info->fprintf_func) (info->stream, "%s", rname);
997 	      else
998 		(*info->fprintf_func) (info->stream, "%#x", value);
999 	    }
1000 	}
1001 
1002       need_comma = TRUE;
1003     }
1004 
1005   return insn_len;
1006 }
1007 
1008 
1009 disassembler_ftype
arc_get_disassembler(bfd * abfd)1010 arc_get_disassembler (bfd *abfd)
1011 {
1012   /* Read the extenssion insns and registers, if any.  */
1013   build_ARC_extmap (abfd);
1014 #ifdef DEBUG
1015   dump_ARC_extmap ();
1016 #endif
1017 
1018   return print_insn_arc;
1019 }
1020 
1021 /* Disassemble ARC instructions.  Used by debugger.  */
1022 
1023 struct arcDisState
arcAnalyzeInstr(bfd_vma memaddr,struct disassemble_info * info)1024 arcAnalyzeInstr (bfd_vma memaddr,
1025 		 struct disassemble_info *info)
1026 {
1027   struct arcDisState ret;
1028   memset (&ret, 0, sizeof (struct arcDisState));
1029 
1030   ret.instructionLen = print_insn_arc (memaddr, info);
1031 
1032 #if 0
1033   ret.words[0] = insn[0];
1034   ret.words[1] = insn[1];
1035   ret._this = &ret;
1036   ret.coreRegName = _coreRegName;
1037   ret.auxRegName = _auxRegName;
1038   ret.condCodeName = _condCodeName;
1039   ret.instName = _instName;
1040 #endif
1041 
1042   return ret;
1043 }
1044 
1045 /* Local variables:
1046    eval: (c-set-style "gnu")
1047    indent-tabs-mode: t
1048    End:  */
1049