Release 2.33.1
[external/binutils.git] / opcodes / arc-dis.c
1 /* Instruction printing code for the ARC.
2    Copyright (C) 1994-2019 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 "elf/arc.h"
29 #include "arc-dis.h"
30 #include "arc-ext.h"
31 #include "elf-bfd.h"
32 #include "libiberty.h"
33 #include "opintl.h"
34
35 /* Structure used to iterate over, and extract the values for, operands of
36    an opcode.  */
37
38 struct arc_operand_iterator
39 {
40   /* The complete instruction value to extract operands from.  */
41   unsigned long long insn;
42
43   /* The LIMM if this is being tracked separately.  This field is only
44      valid if we find the LIMM operand in the operand list.  */
45   unsigned limm;
46
47   /* The opcode this iterator is operating on.  */
48   const struct arc_opcode *opcode;
49
50   /* The index into the opcodes operand index list.  */
51   const unsigned char *opidx;
52 };
53
54 /* A private data used by ARC decoder.  */
55 struct arc_disassemble_info
56 {
57   /* The current disassembled arc opcode.  */
58   const struct arc_opcode *opcode;
59
60   /* Instruction length w/o limm field.  */
61   unsigned insn_len;
62
63   /* TRUE if we have limm.  */
64   bfd_boolean limm_p;
65
66   /* LIMM value, if exists.  */
67   unsigned limm;
68
69   /* Condition code, if exists.  */
70   unsigned condition_code;
71
72   /* Writeback mode.  */
73   unsigned writeback_mode;
74
75   /* Number of operands.  */
76   unsigned operands_count;
77
78   struct arc_insn_operand operands[MAX_INSN_ARGS];
79 };
80
81 /* Globals variables.  */
82
83 static const char * const regnames[64] =
84 {
85   "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
86   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
87   "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
88   "r24", "r25", "gp", "fp", "sp", "ilink", "r30", "blink",
89
90   "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
91   "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
92   "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",
93   "r56", "r57", "ACCL", "ACCH", "lp_count", "rezerved", "LIMM", "pcl"
94 };
95
96 static const char * const addrtypenames[ARC_NUM_ADDRTYPES] =
97 {
98   "bd", "jid", "lbd", "mbd", "sd", "sm", "xa", "xd",
99   "cd", "cbd", "cjid", "clbd", "cm", "csd", "cxa", "cxd"
100 };
101
102 static int addrtypenames_max = ARC_NUM_ADDRTYPES - 1;
103
104 static const char * const addrtypeunknown = "unknown";
105
106 /* This structure keeps track which instruction class(es)
107    should be ignored durring disassembling.  */
108
109 typedef struct skipclass
110 {
111   insn_class_t     insn_class;
112   insn_subclass_t  subclass;
113   struct skipclass *nxt;
114 } skipclass_t, *linkclass;
115
116 /* Intial classes of instructions to be consider first when
117    disassembling.  */
118 static linkclass decodelist = NULL;
119
120 /* ISA mask value enforced via disassembler info options.  ARC_OPCODE_NONE
121    value means that no CPU is enforced.  */
122
123 static unsigned enforced_isa_mask = ARC_OPCODE_NONE;
124
125 /* True if we want to print using only hex numbers.  */
126 static bfd_boolean print_hex = FALSE;
127
128 /* Macros section.  */
129
130 #ifdef DEBUG
131 # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
132 #else
133 # define pr_debug(fmt, args...)
134 #endif
135
136 #define ARRANGE_ENDIAN(info, buf)                                       \
137   (info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf))    \
138    : bfd_getb32 (buf))
139
140 #define BITS(word,s,e)  (((word) << (sizeof (word) * 8 - 1 - e)) >>     \
141                          (s + (sizeof (word) * 8 - 1 - e)))
142 #define OPCODE_32BIT_INSN(word) (BITS ((word), 27, 31))
143
144 /* Functions implementation.  */
145
146 /* Initialize private data.  */
147 static bfd_boolean
148 init_arc_disasm_info (struct disassemble_info *info)
149 {
150   struct arc_disassemble_info *arc_infop
151     = calloc (sizeof (*arc_infop), 1);
152
153   if (arc_infop == NULL)
154     return FALSE;
155
156   info->private_data = arc_infop;
157   return TRUE;
158 }
159
160 /* Add a new element to the decode list.  */
161
162 static void
163 add_to_decodelist (insn_class_t     insn_class,
164                    insn_subclass_t  subclass)
165 {
166   linkclass t = (linkclass) xmalloc (sizeof (skipclass_t));
167
168   t->insn_class = insn_class;
169   t->subclass = subclass;
170   t->nxt = decodelist;
171   decodelist = t;
172 }
173
174 /* Return TRUE if we need to skip the opcode from being
175    disassembled.  */
176
177 static bfd_boolean
178 skip_this_opcode (const struct arc_opcode *opcode)
179 {
180   linkclass t = decodelist;
181
182   /* Check opcode for major 0x06, return if it is not in.  */
183   if (arc_opcode_len (opcode) == 4
184       && (OPCODE_32BIT_INSN (opcode->opcode) != 0x06
185           /* Can be an APEX extensions.  */
186           && OPCODE_32BIT_INSN (opcode->opcode) != 0x07))
187     return FALSE;
188
189   /* or not a known truble class.  */
190   switch (opcode->insn_class)
191     {
192     case FLOAT:
193     case DSP:
194     case ARITH:
195     case MPY:
196       break;
197     default:
198       return FALSE;
199     }
200
201   while (t != NULL)
202     {
203       if ((t->insn_class == opcode->insn_class)
204           && (t->subclass == opcode->subclass))
205         return FALSE;
206       t = t->nxt;
207     }
208
209   return TRUE;
210 }
211
212 static bfd_vma
213 bfd_getm32 (unsigned int data)
214 {
215   bfd_vma value = 0;
216
217   value = ((data & 0xff00) | (data & 0xff)) << 16;
218   value |= ((data & 0xff0000) | (data & 0xff000000)) >> 16;
219   return value;
220 }
221
222 static bfd_boolean
223 special_flag_p (const char *opname,
224                 const char *flgname)
225 {
226   const struct arc_flag_special *flg_spec;
227   unsigned i, j, flgidx;
228
229   for (i = 0; i < arc_num_flag_special; i++)
230     {
231       flg_spec = &arc_flag_special_cases[i];
232
233       if (strcmp (opname, flg_spec->name))
234         continue;
235
236       /* Found potential special case instruction.  */
237       for (j=0;; ++j)
238         {
239           flgidx = flg_spec->flags[j];
240           if (flgidx == 0)
241             break; /* End of the array.  */
242
243           if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0)
244             return TRUE;
245         }
246     }
247   return FALSE;
248 }
249
250 /* Find opcode from ARC_TABLE given the instruction described by INSN and
251    INSNLEN.  The ISA_MASK restricts the possible matches in ARC_TABLE.  */
252
253 static const struct arc_opcode *
254 find_format_from_table (struct disassemble_info *info,
255                         const struct arc_opcode *arc_table,
256                         unsigned long long insn,
257                         unsigned int insn_len,
258                         unsigned isa_mask,
259                         bfd_boolean *has_limm,
260                         bfd_boolean overlaps)
261 {
262   unsigned int i = 0;
263   const struct arc_opcode *opcode = NULL;
264   const struct arc_opcode *t_op = NULL;
265   const unsigned char *opidx;
266   const unsigned char *flgidx;
267   bfd_boolean warn_p = FALSE;
268
269   do
270     {
271       bfd_boolean invalid = FALSE;
272
273       opcode = &arc_table[i++];
274
275       if (!(opcode->cpu & isa_mask))
276         continue;
277
278       if (arc_opcode_len (opcode) != (int) insn_len)
279         continue;
280
281       if ((insn & opcode->mask) != opcode->opcode)
282         continue;
283
284       *has_limm = FALSE;
285
286       /* Possible candidate, check the operands.  */
287       for (opidx = opcode->operands; *opidx; opidx++)
288         {
289           int value, limmind;
290           const struct arc_operand *operand = &arc_operands[*opidx];
291
292           if (operand->flags & ARC_OPERAND_FAKE)
293             continue;
294
295           if (operand->extract)
296             value = (*operand->extract) (insn, &invalid);
297           else
298             value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
299
300           /* Check for LIMM indicator.  If it is there, then make sure
301              we pick the right format.  */
302           limmind = (isa_mask & ARC_OPCODE_ARCV2) ? 0x1E : 0x3E;
303           if (operand->flags & ARC_OPERAND_IR
304               && !(operand->flags & ARC_OPERAND_LIMM))
305             {
306               if ((value == 0x3E && insn_len == 4)
307                   || (value == limmind && insn_len == 2))
308                 {
309                   invalid = TRUE;
310                   break;
311                 }
312             }
313
314           if (operand->flags & ARC_OPERAND_LIMM
315               && !(operand->flags & ARC_OPERAND_DUPLICATE))
316             *has_limm = TRUE;
317         }
318
319       /* Check the flags.  */
320       for (flgidx = opcode->flags; *flgidx; flgidx++)
321         {
322           /* Get a valid flag class.  */
323           const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
324           const unsigned *flgopridx;
325           int foundA = 0, foundB = 0;
326           unsigned int value;
327
328           /* Check first the extensions.  */
329           if (cl_flags->flag_class & F_CLASS_EXTEND)
330             {
331               value = (insn & 0x1F);
332               if (arcExtMap_condCodeName (value))
333                 continue;
334             }
335
336           /* Check for the implicit flags.  */
337           if (cl_flags->flag_class & F_CLASS_IMPLICIT)
338             continue;
339
340           for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
341             {
342               const struct arc_flag_operand *flg_operand =
343                 &arc_flag_operands[*flgopridx];
344
345               value = (insn >> flg_operand->shift)
346                 & ((1 << flg_operand->bits) - 1);
347               if (value == flg_operand->code)
348                 foundA = 1;
349               if (value)
350                 foundB = 1;
351             }
352
353           if (!foundA && foundB)
354             {
355               invalid = TRUE;
356               break;
357             }
358         }
359
360       if (invalid)
361         continue;
362
363       if (insn_len == 4
364           && overlaps)
365         {
366           warn_p = TRUE;
367           t_op = opcode;
368           if (skip_this_opcode (opcode))
369             continue;
370         }
371
372       /* The instruction is valid.  */
373       return opcode;
374     }
375   while (opcode->mask);
376
377   if (warn_p)
378     {
379       info->fprintf_func (info->stream,
380                           _("\nWarning: disassembly may be wrong due to "
381                             "guessed opcode class choice.\n"
382                             "Use -M<class[,class]> to select the correct "
383                             "opcode class(es).\n\t\t\t\t"));
384       return t_op;
385     }
386
387   return NULL;
388 }
389
390 /* Find opcode for INSN, trying various different sources.  The instruction
391    length in INSN_LEN will be updated if the instruction requires a LIMM
392    extension.
393
394    A pointer to the opcode is placed into OPCODE_RESULT, and ITER is
395    initialised, ready to iterate over the operands of the found opcode.  If
396    the found opcode requires a LIMM then the LIMM value will be loaded into a
397    field of ITER.
398
399    This function returns TRUE in almost all cases, FALSE is reserved to
400    indicate an error (failing to find an opcode is not an error) a returned
401    result of FALSE would indicate that the disassembler can't continue.
402
403    If no matching opcode is found then the returned result will be TRUE, the
404    value placed into OPCODE_RESULT will be NULL, ITER will be undefined, and
405    INSN_LEN will be unchanged.
406
407    If a matching opcode is found, then the returned result will be TRUE, the
408    opcode pointer is placed into OPCODE_RESULT, INSN_LEN will be increased by
409    4 if the instruction requires a LIMM, and the LIMM value will have been
410    loaded into a field of ITER.  Finally, ITER will have been initialised so
411    that calls to OPERAND_ITERATOR_NEXT will iterate over the opcode's
412    operands.  */
413
414 static bfd_boolean
415 find_format (bfd_vma                       memaddr,
416              unsigned long long            insn,
417              unsigned int *                insn_len,
418              unsigned                      isa_mask,
419              struct disassemble_info *     info,
420              const struct arc_opcode **    opcode_result,
421              struct arc_operand_iterator * iter)
422 {
423   const struct arc_opcode *opcode = NULL;
424   bfd_boolean needs_limm;
425   const extInstruction_t *einsn, *i;
426   unsigned limm = 0;
427   struct arc_disassemble_info *arc_infop = info->private_data;
428
429   /* First, try the extension instructions.  */
430   if (*insn_len == 4)
431     {
432       einsn = arcExtMap_insn (OPCODE_32BIT_INSN (insn), insn);
433       for (i = einsn; (i != NULL) && (opcode == NULL); i = i->next)
434         {
435           const char *errmsg = NULL;
436
437           opcode = arcExtMap_genOpcode (i, isa_mask, &errmsg);
438           if (opcode == NULL)
439             {
440               (*info->fprintf_func) (info->stream, "\
441 An error occured while generating the extension instruction operations");
442               *opcode_result = NULL;
443               return FALSE;
444             }
445
446           opcode = find_format_from_table (info, opcode, insn, *insn_len,
447                                            isa_mask, &needs_limm, FALSE);
448         }
449     }
450
451   /* Then, try finding the first match in the opcode table.  */
452   if (opcode == NULL)
453     opcode = find_format_from_table (info, arc_opcodes, insn, *insn_len,
454                                      isa_mask, &needs_limm, TRUE);
455
456   if (needs_limm && opcode != NULL)
457     {
458       bfd_byte buffer[4];
459       int status;
460
461       status = (*info->read_memory_func) (memaddr + *insn_len, buffer,
462                                           4, info);
463       if (status != 0)
464         {
465           opcode = NULL;
466         }
467       else
468         {
469           limm = ARRANGE_ENDIAN (info, buffer);
470           *insn_len += 4;
471         }
472     }
473
474   if (opcode != NULL)
475     {
476       iter->insn = insn;
477       iter->limm = limm;
478       iter->opcode = opcode;
479       iter->opidx = opcode->operands;
480     }
481
482   *opcode_result = opcode;
483
484   /* Update private data.  */
485   arc_infop->opcode = opcode;
486   arc_infop->limm = (needs_limm) ? limm : 0;
487   arc_infop->limm_p = needs_limm;
488
489   return TRUE;
490 }
491
492 static void
493 print_flags (const struct arc_opcode *opcode,
494              unsigned long long *insn,
495              struct disassemble_info *info)
496 {
497   const unsigned char *flgidx;
498   unsigned int value;
499   struct arc_disassemble_info *arc_infop = info->private_data;
500
501   /* Now extract and print the flags.  */
502   for (flgidx = opcode->flags; *flgidx; flgidx++)
503     {
504       /* Get a valid flag class.  */
505       const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
506       const unsigned *flgopridx;
507
508       /* Check first the extensions.  */
509       if (cl_flags->flag_class & F_CLASS_EXTEND)
510         {
511           const char *name;
512           value = (insn[0] & 0x1F);
513
514           name = arcExtMap_condCodeName (value);
515           if (name)
516             {
517               (*info->fprintf_func) (info->stream, ".%s", name);
518               continue;
519             }
520         }
521
522       for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
523         {
524           const struct arc_flag_operand *flg_operand =
525             &arc_flag_operands[*flgopridx];
526
527           /* Implicit flags are only used for the insn decoder.  */
528           if (cl_flags->flag_class & F_CLASS_IMPLICIT)
529             {
530               if (cl_flags->flag_class & F_CLASS_COND)
531                 arc_infop->condition_code = flg_operand->code;
532               else if (cl_flags->flag_class & F_CLASS_WB)
533                 arc_infop->writeback_mode = flg_operand->code;
534               else if (cl_flags->flag_class & F_CLASS_ZZ)
535                 info->data_size = flg_operand->code;
536               continue;
537             }
538
539           if (!flg_operand->favail)
540             continue;
541
542           value = (insn[0] >> flg_operand->shift)
543             & ((1 << flg_operand->bits) - 1);
544           if (value == flg_operand->code)
545             {
546                /* FIXME!: print correctly nt/t flag.  */
547               if (!special_flag_p (opcode->name, flg_operand->name))
548                 (*info->fprintf_func) (info->stream, ".");
549               else if (info->insn_type == dis_dref)
550                 {
551                   switch (flg_operand->name[0])
552                     {
553                     case 'b':
554                       info->data_size = 1;
555                       break;
556                     case 'h':
557                     case 'w':
558                       info->data_size = 2;
559                       break;
560                     default:
561                       info->data_size = 4;
562                       break;
563                     }
564                 }
565               if (flg_operand->name[0] == 'd'
566                   && flg_operand->name[1] == 0)
567                 info->branch_delay_insns = 1;
568
569               /* Check if it is a conditional flag.  */
570               if (cl_flags->flag_class & F_CLASS_COND)
571                 {
572                   if (info->insn_type == dis_jsr)
573                     info->insn_type = dis_condjsr;
574                   else if (info->insn_type == dis_branch)
575                     info->insn_type = dis_condbranch;
576                   arc_infop->condition_code = flg_operand->code;
577                 }
578
579               /* Check for the write back modes.  */
580               if (cl_flags->flag_class & F_CLASS_WB)
581                 arc_infop->writeback_mode = flg_operand->code;
582
583               (*info->fprintf_func) (info->stream, "%s", flg_operand->name);
584             }
585         }
586     }
587 }
588
589 static const char *
590 get_auxreg (const struct arc_opcode *opcode,
591             int value,
592             unsigned isa_mask)
593 {
594   const char *name;
595   unsigned int i;
596   const struct arc_aux_reg *auxr = &arc_aux_regs[0];
597
598   if (opcode->insn_class != AUXREG)
599     return NULL;
600
601   name = arcExtMap_auxRegName (value);
602   if (name)
603     return name;
604
605   for (i = 0; i < arc_num_aux_regs; i++, auxr++)
606     {
607       if (!(auxr->cpu & isa_mask))
608         continue;
609
610       if (auxr->subclass != NONE)
611         return NULL;
612
613       if (auxr->address == value)
614         return auxr->name;
615     }
616   return NULL;
617 }
618
619 /* Convert a value representing an address type to a string used to refer to
620    the address type in assembly code.  */
621
622 static const char *
623 get_addrtype (int value)
624 {
625   if (value < 0 || value > addrtypenames_max)
626     return addrtypeunknown;
627
628   return addrtypenames[value];
629 }
630
631 /* Calculate the instruction length for an instruction starting with MSB
632    and LSB, the most and least significant byte.  The ISA_MASK is used to
633    filter the instructions considered to only those that are part of the
634    current architecture.
635
636    The instruction lengths are calculated from the ARC_OPCODE table, and
637    cached for later use.  */
638
639 static unsigned int
640 arc_insn_length (bfd_byte msb, bfd_byte lsb, struct disassemble_info *info)
641 {
642   bfd_byte major_opcode = msb >> 3;
643
644   switch (info->mach)
645     {
646     case bfd_mach_arc_arc700:
647       /* The nps400 extension set requires this special casing of the
648          instruction length calculation.  Right now this is not causing any
649          problems as none of the known extensions overlap in opcode space,
650          but, if they ever do then we might need to start carrying
651          information around in the elf about which extensions are in use.  */
652       if (major_opcode == 0xb)
653         {
654           bfd_byte minor_opcode = lsb & 0x1f;
655
656           if (minor_opcode < 4)
657             return 6;
658           else if (minor_opcode == 0x10 || minor_opcode == 0x11)
659             return 8;
660         }
661       if (major_opcode == 0xa)
662         {
663           return 8;
664         }
665       /* Fall through.  */
666     case bfd_mach_arc_arc600:
667       return (major_opcode > 0xb) ? 2 : 4;
668       break;
669
670     case bfd_mach_arc_arcv2:
671       return (major_opcode > 0x7) ? 2 : 4;
672       break;
673
674     default:
675       return 0;
676     }
677 }
678
679 /* Extract and return the value of OPERAND from the instruction whose value
680    is held in the array INSN.  */
681
682 static int
683 extract_operand_value (const struct arc_operand *operand,
684                        unsigned long long insn,
685                        unsigned limm)
686 {
687   int value;
688
689   /* Read the limm operand, if required.  */
690   if (operand->flags & ARC_OPERAND_LIMM)
691     /* The second part of the instruction value will have been loaded as
692        part of the find_format call made earlier.  */
693     value = limm;
694   else
695     {
696       if (operand->extract)
697         value = (*operand->extract) (insn, (int *) NULL);
698       else
699         {
700           if (operand->flags & ARC_OPERAND_ALIGNED32)
701             {
702               value = (insn >> operand->shift)
703                 & ((1 << (operand->bits - 2)) - 1);
704               value = value << 2;
705             }
706           else
707             {
708               value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
709             }
710           if (operand->flags & ARC_OPERAND_SIGNED)
711             {
712               int signbit = 1 << (operand->bits - 1);
713               value = (value ^ signbit) - signbit;
714             }
715         }
716     }
717
718   return value;
719 }
720
721 /* Find the next operand, and the operands value from ITER.  Return TRUE if
722    there is another operand, otherwise return FALSE.  If there is an
723    operand returned then the operand is placed into OPERAND, and the value
724    into VALUE.  If there is no operand returned then OPERAND and VALUE are
725    unchanged.  */
726
727 static bfd_boolean
728 operand_iterator_next (struct arc_operand_iterator *iter,
729                        const struct arc_operand **operand,
730                        int *value)
731 {
732   if (*iter->opidx == 0)
733     {
734       *operand = NULL;
735       return FALSE;
736     }
737
738   *operand = &arc_operands[*iter->opidx];
739   *value = extract_operand_value (*operand, iter->insn, iter->limm);
740   iter->opidx++;
741
742   return TRUE;
743 }
744
745 /* Helper for parsing the options.  */
746
747 static void
748 parse_option (const char *option)
749 {
750   if (disassembler_options_cmp (option, "dsp") == 0)
751     add_to_decodelist (DSP, NONE);
752
753   else if (disassembler_options_cmp (option, "spfp") == 0)
754     add_to_decodelist (FLOAT, SPX);
755
756   else if (disassembler_options_cmp (option, "dpfp") == 0)
757     add_to_decodelist (FLOAT, DPX);
758
759   else if (disassembler_options_cmp (option, "quarkse_em") == 0)
760     {
761       add_to_decodelist (FLOAT, DPX);
762       add_to_decodelist (FLOAT, SPX);
763       add_to_decodelist (FLOAT, QUARKSE1);
764       add_to_decodelist (FLOAT, QUARKSE2);
765     }
766
767   else if (disassembler_options_cmp (option, "fpuda") == 0)
768     add_to_decodelist (FLOAT, DPA);
769
770   else if (disassembler_options_cmp (option, "nps400") == 0)
771     {
772       add_to_decodelist (ACL, NPS400);
773       add_to_decodelist (ARITH, NPS400);
774       add_to_decodelist (BITOP, NPS400);
775       add_to_decodelist (BMU, NPS400);
776       add_to_decodelist (CONTROL, NPS400);
777       add_to_decodelist (DMA, NPS400);
778       add_to_decodelist (DPI, NPS400);
779       add_to_decodelist (MEMORY, NPS400);
780       add_to_decodelist (MISC, NPS400);
781       add_to_decodelist (NET, NPS400);
782       add_to_decodelist (PMU, NPS400);
783       add_to_decodelist (PROTOCOL_DECODE, NPS400);
784       add_to_decodelist (ULTRAIP, NPS400);
785     }
786
787   else if (disassembler_options_cmp (option, "fpus") == 0)
788     {
789       add_to_decodelist (FLOAT, SP);
790       add_to_decodelist (FLOAT, CVT);
791     }
792
793   else if (disassembler_options_cmp (option, "fpud") == 0)
794     {
795       add_to_decodelist (FLOAT, DP);
796       add_to_decodelist (FLOAT, CVT);
797     }
798   else if (CONST_STRNEQ (option, "hex"))
799     print_hex = TRUE;
800   else
801     /* xgettext:c-format */
802     opcodes_error_handler (_("unrecognised disassembler option: %s"), option);
803 }
804
805 #define ARC_CPU_TYPE_A6xx(NAME,EXTRA)                   \
806   { #NAME, ARC_OPCODE_ARC600, "ARC600" }
807 #define ARC_CPU_TYPE_A7xx(NAME,EXTRA)                   \
808   { #NAME, ARC_OPCODE_ARC700, "ARC700" }
809 #define ARC_CPU_TYPE_AV2EM(NAME,EXTRA)                  \
810   { #NAME,  ARC_OPCODE_ARCv2EM, "ARC EM" }
811 #define ARC_CPU_TYPE_AV2HS(NAME,EXTRA)                  \
812   { #NAME,  ARC_OPCODE_ARCv2HS, "ARC HS" }
813 #define ARC_CPU_TYPE_NONE                               \
814   { 0, 0, 0 }
815
816 /* A table of CPU names and opcode sets.  */
817 static const struct cpu_type
818 {
819   const char *name;
820   unsigned flags;
821   const char *isa;
822 }
823   cpu_types[] =
824 {
825   #include "elf/arc-cpu.def"
826 };
827
828 /* Helper for parsing the CPU options.  Accept any of the ARC architectures
829    values.  OPTION should be a value passed to cpu=.  */
830
831 static unsigned
832 parse_cpu_option (const char *option)
833 {
834   int i;
835
836   for (i = 0; cpu_types[i].name; ++i)
837     {
838       if (!disassembler_options_cmp (cpu_types[i].name, option))
839         {
840           return cpu_types[i].flags;
841         }
842     }
843
844   /* xgettext:c-format */
845   opcodes_error_handler (_("unrecognised disassembler CPU option: %s"), option);
846   return ARC_OPCODE_NONE;
847 }
848
849 /* Go over the options list and parse it.  */
850
851 static void
852 parse_disassembler_options (const char *options)
853 {
854   const char *option;
855
856   if (options == NULL)
857     return;
858
859   /* Disassembler might be reused for difference CPU's, and cpu option set for
860      the first one shouldn't be applied to second (which might not have
861      explicit cpu in its options.  Therefore it is required to reset enforced
862      CPU when new options are being parsed.  */
863   enforced_isa_mask = ARC_OPCODE_NONE;
864
865   FOR_EACH_DISASSEMBLER_OPTION (option, options)
866     {
867       /* A CPU option?  Cannot use STRING_COMMA_LEN because strncmp is also a
868          preprocessor macro.  */
869       if (strncmp (option, "cpu=", 4) == 0)
870         /* Strip leading `cpu=`.  */
871         enforced_isa_mask = parse_cpu_option (option + 4);
872       else
873         parse_option (option);
874     }
875 }
876
877 /* Return the instruction type for an instruction described by OPCODE.  */
878
879 static enum dis_insn_type
880 arc_opcode_to_insn_type (const struct arc_opcode *opcode)
881 {
882   enum dis_insn_type insn_type;
883
884   switch (opcode->insn_class)
885     {
886     case BRANCH:
887     case BBIT0:
888     case BBIT1:
889     case BI:
890     case BIH:
891     case BRCC:
892     case EI:
893     case JLI:
894     case JUMP:
895     case LOOP:
896       if (!strncmp (opcode->name, "bl", 2)
897           || !strncmp (opcode->name, "jl", 2))
898         {
899           if (opcode->subclass == COND)
900             insn_type = dis_condjsr;
901           else
902             insn_type = dis_jsr;
903         }
904       else
905         {
906           if (opcode->subclass == COND)
907             insn_type = dis_condbranch;
908           else
909             insn_type = dis_branch;
910         }
911       break;
912     case LOAD:
913     case STORE:
914     case MEMORY:
915     case ENTER:
916     case PUSH:
917     case POP:
918       insn_type = dis_dref;
919       break;
920     case LEAVE:
921       insn_type = dis_branch;
922       break;
923     default:
924       insn_type = dis_nonbranch;
925       break;
926     }
927
928   return insn_type;
929 }
930
931 /* Disassemble ARC instructions.  */
932
933 static int
934 print_insn_arc (bfd_vma memaddr,
935                 struct disassemble_info *info)
936 {
937   bfd_byte buffer[8];
938   unsigned int highbyte, lowbyte;
939   int status;
940   unsigned int insn_len;
941   unsigned long long insn = 0;
942   unsigned isa_mask = ARC_OPCODE_NONE;
943   const struct arc_opcode *opcode;
944   bfd_boolean need_comma;
945   bfd_boolean open_braket;
946   int size;
947   const struct arc_operand *operand;
948   int value, vpcl;
949   struct arc_operand_iterator iter;
950   struct arc_disassemble_info *arc_infop;
951   bfd_boolean rpcl = FALSE, rset = FALSE;
952
953   if (info->disassembler_options)
954     {
955       parse_disassembler_options (info->disassembler_options);
956
957       /* Avoid repeated parsing of the options.  */
958       info->disassembler_options = NULL;
959     }
960
961   if (info->private_data == NULL && !init_arc_disasm_info (info))
962     return -1;
963
964   memset (&iter, 0, sizeof (iter));
965   highbyte  = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
966   lowbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
967
968   /* Figure out CPU type, unless it was enforced via disassembler options.  */
969   if (enforced_isa_mask == ARC_OPCODE_NONE)
970     {
971       Elf_Internal_Ehdr *header = NULL;
972
973       if (info->section && info->section->owner)
974         header = elf_elfheader (info->section->owner);
975
976       switch (info->mach)
977         {
978         case bfd_mach_arc_arc700:
979           isa_mask = ARC_OPCODE_ARC700;
980           break;
981
982         case bfd_mach_arc_arc600:
983           isa_mask = ARC_OPCODE_ARC600;
984           break;
985
986         case bfd_mach_arc_arcv2:
987         default:
988           isa_mask = ARC_OPCODE_ARCv2EM;
989           /* TODO: Perhaps remove definition of header since it is only used at
990              this location.  */
991           if (header != NULL
992               && (header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS)
993             isa_mask = ARC_OPCODE_ARCv2HS;
994           break;
995         }
996     }
997   else
998     isa_mask = enforced_isa_mask;
999
1000   if (isa_mask == ARC_OPCODE_ARCv2HS)
1001     {
1002       /* FPU instructions are not extensions for HS.  */
1003       add_to_decodelist (FLOAT, SP);
1004       add_to_decodelist (FLOAT, DP);
1005       add_to_decodelist (FLOAT, CVT);
1006     }
1007
1008   /* This variable may be set by the instruction decoder.  It suggests
1009      the number of bytes objdump should display on a single line.  If
1010      the instruction decoder sets this, it should always set it to
1011      the same value in order to get reasonable looking output.  */
1012   info->bytes_per_line  = 8;
1013
1014   /* In the next lines, we set two info variables control the way
1015      objdump displays the raw data.  For example, if bytes_per_line is
1016      8 and bytes_per_chunk is 4, the output will look like this:
1017      00:   00000000 00000000
1018      with the chunks displayed according to "display_endian".  */
1019   if (info->section
1020       && !(info->section->flags & SEC_CODE))
1021     {
1022       /* This is not a CODE section.  */
1023       switch (info->section->size)
1024         {
1025         case 1:
1026         case 2:
1027         case 4:
1028           size = info->section->size;
1029           break;
1030         default:
1031           size = (info->section->size & 0x01) ? 1 : 4;
1032           break;
1033         }
1034       info->bytes_per_chunk = 1;
1035       info->display_endian = info->endian;
1036     }
1037   else
1038     {
1039       size = 2;
1040       info->bytes_per_chunk = 2;
1041       info->display_endian = info->endian;
1042     }
1043
1044   /* Read the insn into a host word.  */
1045   status = (*info->read_memory_func) (memaddr, buffer, size, info);
1046
1047   if (status != 0)
1048     {
1049       (*info->memory_error_func) (status, memaddr, info);
1050       return -1;
1051     }
1052
1053   if (info->section
1054       && !(info->section->flags & SEC_CODE))
1055     {
1056       /* Data section.  */
1057       unsigned long data;
1058
1059       data = bfd_get_bits (buffer, size * 8,
1060                            info->display_endian == BFD_ENDIAN_BIG);
1061       switch (size)
1062         {
1063         case 1:
1064           (*info->fprintf_func) (info->stream, ".byte\t0x%02lx", data);
1065           break;
1066         case 2:
1067           (*info->fprintf_func) (info->stream, ".short\t0x%04lx", data);
1068           break;
1069         case 4:
1070           (*info->fprintf_func) (info->stream, ".word\t0x%08lx", data);
1071           break;
1072         default:
1073           return -1;
1074         }
1075       return size;
1076     }
1077
1078   insn_len = arc_insn_length (buffer[highbyte], buffer[lowbyte], info);
1079   pr_debug ("instruction length = %d bytes\n", insn_len);
1080   if (insn_len == 0)
1081     return -1;
1082
1083   arc_infop = info->private_data;
1084   arc_infop->insn_len = insn_len;
1085
1086   switch (insn_len)
1087     {
1088     case 2:
1089       insn = (buffer[highbyte] << 8) | buffer[lowbyte];
1090       break;
1091
1092     case 4:
1093       {
1094         /* This is a long instruction: Read the remaning 2 bytes.  */
1095         status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 2, info);
1096         if (status != 0)
1097           {
1098             (*info->memory_error_func) (status, memaddr + 2, info);
1099             return -1;
1100           }
1101         insn = (unsigned long long) ARRANGE_ENDIAN (info, buffer);
1102       }
1103       break;
1104
1105     case 6:
1106       {
1107         status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 4, info);
1108         if (status != 0)
1109           {
1110             (*info->memory_error_func) (status, memaddr + 2, info);
1111             return -1;
1112           }
1113         insn = (unsigned long long) ARRANGE_ENDIAN (info, &buffer[2]);
1114         insn |= ((unsigned long long) buffer[highbyte] << 40)
1115           | ((unsigned long long) buffer[lowbyte] << 32);
1116       }
1117       break;
1118
1119     case 8:
1120       {
1121         status = (*info->read_memory_func) (memaddr + 2, &buffer[2], 6, info);
1122         if (status != 0)
1123           {
1124             (*info->memory_error_func) (status, memaddr + 2, info);
1125             return -1;
1126           }
1127         insn =
1128           ((((unsigned long long) ARRANGE_ENDIAN (info, buffer)) << 32)
1129            | ((unsigned long long) ARRANGE_ENDIAN (info, &buffer[4])));
1130       }
1131       break;
1132
1133     default:
1134       /* There is no instruction whose length is not 2, 4, 6, or 8.  */
1135       return -1;
1136     }
1137
1138   pr_debug ("instruction value = %llx\n", insn);
1139
1140   /* Set some defaults for the insn info.  */
1141   info->insn_info_valid    = 1;
1142   info->branch_delay_insns = 0;
1143   info->data_size          = 4;
1144   info->insn_type          = dis_nonbranch;
1145   info->target             = 0;
1146   info->target2            = 0;
1147
1148   /* FIXME to be moved in dissasemble_init_for_target.  */
1149   info->disassembler_needs_relocs = TRUE;
1150
1151   /* Find the first match in the opcode table.  */
1152   if (!find_format (memaddr, insn, &insn_len, isa_mask, info, &opcode, &iter))
1153     return -1;
1154
1155   if (!opcode)
1156     {
1157       switch (insn_len)
1158         {
1159         case 2:
1160           (*info->fprintf_func) (info->stream, ".shor\t%#04llx",
1161                                  insn & 0xffff);
1162           break;
1163
1164         case 4:
1165           (*info->fprintf_func) (info->stream, ".word\t%#08llx",
1166                                  insn & 0xffffffff);
1167           break;
1168
1169         case 6:
1170           (*info->fprintf_func) (info->stream, ".long\t%#08llx",
1171                                  insn & 0xffffffff);
1172           (*info->fprintf_func) (info->stream, ".long\t%#04llx",
1173                                  (insn >> 32) & 0xffff);
1174           break;
1175
1176         case 8:
1177           (*info->fprintf_func) (info->stream, ".long\t%#08llx",
1178                                  insn & 0xffffffff);
1179           (*info->fprintf_func) (info->stream, ".long\t%#08llx",
1180                                  insn >> 32);
1181           break;
1182
1183         default:
1184           return -1;
1185         }
1186
1187       info->insn_type = dis_noninsn;
1188       return insn_len;
1189     }
1190
1191   /* Print the mnemonic.  */
1192   (*info->fprintf_func) (info->stream, "%s", opcode->name);
1193
1194   /* Preselect the insn class.  */
1195   info->insn_type = arc_opcode_to_insn_type (opcode);
1196
1197   pr_debug ("%s: 0x%08llx\n", opcode->name, opcode->opcode);
1198
1199   print_flags (opcode, &insn, info);
1200
1201   if (opcode->operands[0] != 0)
1202     (*info->fprintf_func) (info->stream, "\t");
1203
1204   need_comma = FALSE;
1205   open_braket = FALSE;
1206   arc_infop->operands_count = 0;
1207
1208   /* Now extract and print the operands.  */
1209   operand = NULL;
1210   vpcl = 0;
1211   while (operand_iterator_next (&iter, &operand, &value))
1212     {
1213       if (open_braket && (operand->flags & ARC_OPERAND_BRAKET))
1214         {
1215           (*info->fprintf_func) (info->stream, "]");
1216           open_braket = FALSE;
1217           continue;
1218         }
1219
1220       /* Only take input from real operands.  */
1221       if (ARC_OPERAND_IS_FAKE (operand))
1222         continue;
1223
1224       if ((operand->flags & ARC_OPERAND_IGNORE)
1225           && (operand->flags & ARC_OPERAND_IR)
1226           && value == -1)
1227         continue;
1228
1229       if (operand->flags & ARC_OPERAND_COLON)
1230         {
1231           (*info->fprintf_func) (info->stream, ":");
1232           continue;
1233         }
1234
1235       if (need_comma)
1236         (*info->fprintf_func) (info->stream, ",");
1237
1238       if (!open_braket && (operand->flags & ARC_OPERAND_BRAKET))
1239         {
1240           (*info->fprintf_func) (info->stream, "[");
1241           open_braket = TRUE;
1242           need_comma = FALSE;
1243           continue;
1244         }
1245
1246       need_comma = TRUE;
1247
1248       if (operand->flags & ARC_OPERAND_PCREL)
1249         {
1250           rpcl = TRUE;
1251           vpcl = value;
1252           rset = TRUE;
1253
1254           info->target = (bfd_vma) (memaddr & ~3) + value;
1255         }
1256       else if (!(operand->flags & ARC_OPERAND_IR))
1257         {
1258           vpcl = value;
1259           rset = TRUE;
1260         }
1261
1262       /* Print the operand as directed by the flags.  */
1263       if (operand->flags & ARC_OPERAND_IR)
1264         {
1265           const char *rname;
1266
1267           assert (value >=0 && value < 64);
1268           rname = arcExtMap_coreRegName (value);
1269           if (!rname)
1270             rname = regnames[value];
1271           (*info->fprintf_func) (info->stream, "%s", rname);
1272           if (operand->flags & ARC_OPERAND_TRUNCATE)
1273             {
1274               rname = arcExtMap_coreRegName (value + 1);
1275               if (!rname)
1276                 rname = regnames[value + 1];
1277               (*info->fprintf_func) (info->stream, "%s", rname);
1278             }
1279           if (value == 63)
1280             rpcl = TRUE;
1281           else
1282             rpcl = FALSE;
1283         }
1284       else if (operand->flags & ARC_OPERAND_LIMM)
1285         {
1286           const char *rname = get_auxreg (opcode, value, isa_mask);
1287
1288           if (rname && open_braket)
1289             (*info->fprintf_func) (info->stream, "%s", rname);
1290           else
1291             {
1292               (*info->fprintf_func) (info->stream, "%#x", value);
1293               if (info->insn_type == dis_branch
1294                   || info->insn_type == dis_jsr)
1295                 info->target = (bfd_vma) value;
1296             }
1297         }
1298       else if (operand->flags & ARC_OPERAND_SIGNED)
1299         {
1300           const char *rname = get_auxreg (opcode, value, isa_mask);
1301           if (rname && open_braket)
1302             (*info->fprintf_func) (info->stream, "%s", rname);
1303           else
1304             {
1305               if (print_hex)
1306                 (*info->fprintf_func) (info->stream, "%#x", value);
1307               else
1308                 (*info->fprintf_func) (info->stream, "%d", value);
1309             }
1310         }
1311       else if (operand->flags & ARC_OPERAND_ADDRTYPE)
1312         {
1313           const char *addrtype = get_addrtype (value);
1314           (*info->fprintf_func) (info->stream, "%s", addrtype);
1315           /* A colon follow an address type.  */
1316           need_comma = FALSE;
1317         }
1318       else
1319         {
1320           if (operand->flags & ARC_OPERAND_TRUNCATE
1321               && !(operand->flags & ARC_OPERAND_ALIGNED32)
1322               && !(operand->flags & ARC_OPERAND_ALIGNED16)
1323               && value >= 0 && value <= 14)
1324             {
1325               /* Leave/Enter mnemonics.  */
1326               switch (value)
1327                 {
1328                 case 0:
1329                   need_comma = FALSE;
1330                   break;
1331                 case 1:
1332                   (*info->fprintf_func) (info->stream, "r13");
1333                   break;
1334                 default:
1335                   (*info->fprintf_func) (info->stream, "r13-%s",
1336                                          regnames[13 + value - 1]);
1337                   break;
1338                 }
1339               rpcl = FALSE;
1340               rset = FALSE;
1341             }
1342           else
1343             {
1344               const char *rname = get_auxreg (opcode, value, isa_mask);
1345               if (rname && open_braket)
1346                 (*info->fprintf_func) (info->stream, "%s", rname);
1347               else
1348                 (*info->fprintf_func) (info->stream, "%#x", value);
1349             }
1350         }
1351
1352       if (operand->flags & ARC_OPERAND_LIMM)
1353         {
1354           arc_infop->operands[arc_infop->operands_count].kind
1355             = ARC_OPERAND_KIND_LIMM;
1356           /* It is not important to have exactly the LIMM indicator
1357              here.  */
1358           arc_infop->operands[arc_infop->operands_count].value = 63;
1359         }
1360       else
1361         {
1362           arc_infop->operands[arc_infop->operands_count].value = value;
1363           arc_infop->operands[arc_infop->operands_count].kind
1364             = (operand->flags & ARC_OPERAND_IR
1365                ? ARC_OPERAND_KIND_REG
1366                : ARC_OPERAND_KIND_SHIMM);
1367         }
1368       arc_infop->operands_count ++;
1369     }
1370
1371   /* Pretty print extra info for pc-relative operands.  */
1372   if (rpcl && rset)
1373     {
1374       if (info->flags & INSN_HAS_RELOC)
1375         /* If the instruction has a reloc associated with it, then the
1376            offset field in the instruction will actually be the addend
1377            for the reloc.  (We are using REL type relocs).  In such
1378            cases, we can ignore the pc when computing addresses, since
1379            the addend is not currently pc-relative.  */
1380         memaddr = 0;
1381
1382       (*info->fprintf_func) (info->stream, "\t;");
1383       (*info->print_address_func) ((memaddr & ~3) + vpcl, info);
1384     }
1385
1386   return insn_len;
1387 }
1388
1389
1390 disassembler_ftype
1391 arc_get_disassembler (bfd *abfd)
1392 {
1393   /* BFD my be absent, if opcodes is invoked from the debugger that
1394      has connected to remote target and doesn't have an ELF file.  */
1395   if (abfd != NULL)
1396     {
1397       /* Read the extension insns and registers, if any.  */
1398       build_ARC_extmap (abfd);
1399 #ifdef DEBUG
1400       dump_ARC_extmap ();
1401 #endif
1402     }
1403
1404   return print_insn_arc;
1405 }
1406
1407 void
1408 print_arc_disassembler_options (FILE *stream)
1409 {
1410   int i;
1411
1412   fprintf (stream, _("\n\
1413 The following ARC specific disassembler options are supported for use \n\
1414 with -M switch (multiple options should be separated by commas):\n"));
1415
1416   /* cpu=... options.  */
1417   for (i = 0; cpu_types[i].name; ++i)
1418     {
1419       /* As of now all value CPU values are less than 16 characters.  */
1420       fprintf (stream, "  cpu=%-16s\tEnforce %s ISA.\n",
1421                cpu_types[i].name, cpu_types[i].isa);
1422     }
1423
1424   fprintf (stream, _("\
1425   dsp             Recognize DSP instructions.\n"));
1426   fprintf (stream, _("\
1427   spfp            Recognize FPX SP instructions.\n"));
1428   fprintf (stream, _("\
1429   dpfp            Recognize FPX DP instructions.\n"));
1430   fprintf (stream, _("\
1431   quarkse_em      Recognize FPU QuarkSE-EM instructions.\n"));
1432   fprintf (stream, _("\
1433   fpuda           Recognize double assist FPU instructions.\n"));
1434   fprintf (stream, _("\
1435   fpus            Recognize single precision FPU instructions.\n"));
1436   fprintf (stream, _("\
1437   fpud            Recognize double precision FPU instructions.\n"));
1438   fprintf (stream, _("\
1439   nps400          Recognize NPS400 instructions.\n"));
1440   fprintf (stream, _("\
1441   hex             Use only hexadecimal number to print immediates.\n"));
1442 }
1443
1444 void arc_insn_decode (bfd_vma addr,
1445                       struct disassemble_info *info,
1446                       disassembler_ftype disasm_func,
1447                       struct arc_instruction *insn)
1448 {
1449   const struct arc_opcode *opcode;
1450   struct arc_disassemble_info *arc_infop;
1451
1452   /* Ensure that insn would be in the reset state.  */
1453   memset (insn, 0, sizeof (struct arc_instruction));
1454
1455   /* There was an error when disassembling, for example memory read error.  */
1456   if (disasm_func (addr, info) < 0)
1457     {
1458       insn->valid = FALSE;
1459       return;
1460     }
1461
1462   assert (info->private_data != NULL);
1463   arc_infop = info->private_data;
1464
1465   insn->length  = arc_infop->insn_len;;
1466   insn->address = addr;
1467
1468   /* Quick exit if memory at this address is not an instruction.  */
1469   if (info->insn_type == dis_noninsn)
1470     {
1471       insn->valid = FALSE;
1472       return;
1473     }
1474
1475   insn->valid = TRUE;
1476
1477   opcode = (const struct arc_opcode *) arc_infop->opcode;
1478   insn->insn_class = opcode->insn_class;
1479   insn->limm_value = arc_infop->limm;
1480   insn->limm_p     = arc_infop->limm_p;
1481
1482   insn->is_control_flow = (info->insn_type == dis_branch
1483                            || info->insn_type == dis_condbranch
1484                            || info->insn_type == dis_jsr
1485                            || info->insn_type == dis_condjsr);
1486
1487   insn->has_delay_slot = info->branch_delay_insns;
1488   insn->writeback_mode
1489     = (enum arc_ldst_writeback_mode) arc_infop->writeback_mode;
1490   insn->data_size_mode = info->data_size;
1491   insn->condition_code = arc_infop->condition_code;
1492   memcpy (insn->operands, arc_infop->operands,
1493           sizeof (struct arc_insn_operand) * MAX_INSN_ARGS);
1494   insn->operands_count = arc_infop->operands_count;
1495 }
1496
1497 /* Local variables:
1498    eval: (c-set-style "gnu")
1499    indent-tabs-mode: t
1500    End:  */