Fix seg fault in linker when performing garbage collection on COFF based targets.
[external/binutils.git] / opcodes / metag-dis.c
1 /* Disassemble Imagination Technologies Meta instructions.
2    Copyright (C) 2013-2016 Free Software Foundation, Inc.
3    Contributed by Imagination Technologies Ltd.
4
5    This library is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    It is distributed in the hope that it will be useful, but WITHOUT
11    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
13    License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
18    MA 02110-1301, USA.  */
19
20 #include "sysdep.h"
21 #include "dis-asm.h"
22 #include "opintl.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "opcode/metag.h"
29
30 /* Column widths for printing.  */
31 #define PREFIX_WIDTH    "10"
32 #define INSN_NAME_WIDTH "10"
33
34 #define OPERAND_WIDTH   92
35 #define ADDR_WIDTH      20
36 #define REG_WIDTH       64
37 #define DSP_PREFIX_WIDTH 17
38
39 /* Value to print if we fail to parse a register name.  */
40 const char unknown_reg[] = "?";
41
42 /* Return the size of a GET or SET instruction.  */
43 unsigned int
44 metag_get_set_size_bytes (unsigned int opcode)
45 {
46   switch (((opcode) >> 24) & 0x5)
47     {
48     case 0x5:
49       return 8;
50     case 0x4:
51       return 4;
52     case 0x1:
53       return 2;
54     case 0x0:
55       return 1;
56     }
57   return 1;
58 }
59
60 /* Return the size of an extended GET or SET instruction.  */
61 unsigned int
62 metag_get_set_ext_size_bytes (unsigned int opcode)
63 {
64   switch (((opcode) >> 1) & 0x3)
65     {
66     case 0x3:
67       return 8;
68     case 0x2:
69       return 4;
70     case 0x1:
71       return 2;
72     case 0x0:
73       return 1;
74     }
75   return 1;
76 }
77
78 /* Return the size of a conditional SET instruction.  */
79 unsigned int
80 metag_cond_set_size_bytes (unsigned int opcode)
81 {
82   switch (opcode & 0x201)
83     {
84     case 0x201:
85       return 8;
86     case 0x200:
87       return 4;
88     case 0x001:
89       return 2;
90     case 0x000:
91       return 1;
92     }
93   return 1;
94 }
95
96 /* Return a value sign-extended.  */
97 static int
98 sign_extend (int n, unsigned int bits)
99 {
100   int mask = 1 << (bits - 1);
101   return -(n & mask) | n;
102 }
103
104 /* Return the short interpretation of UNIT.  */
105 static unsigned int
106 short_unit (unsigned int unit)
107 {
108   if (unit == UNIT_CT)
109     return UNIT_A1;
110   else
111     return unit;
112 }
113
114 /* Return the register corresponding to UNIT and NUMBER or NULL.  */
115 static const metag_reg *
116 lookup_reg (unsigned int unit, unsigned int number)
117 {
118   size_t i;
119
120   for (i = 0; i < sizeof(metag_regtab)/sizeof(metag_regtab[0]); i++)
121     {
122       const metag_reg *reg = &metag_regtab[i];
123
124       if (reg->unit == unit && reg->no == number)
125         return reg;
126     }
127   return NULL;
128 }
129
130
131 /* Return the register name corresponding to UNIT and NUMBER or NULL.  */
132 static const char *
133 lookup_reg_name (unsigned int unit, unsigned int number)
134 {
135   const metag_reg *reg;
136
137   reg = lookup_reg (unit, number);
138
139   if (reg)
140     return reg->name;
141   else
142     return unknown_reg;
143 }
144
145 /* Return the unit that is the pair of UNIT.  */
146 static unsigned int
147 get_pair_unit (unsigned int unit)
148 {
149   switch (unit)
150     {
151     case UNIT_D0:
152       return UNIT_D1;
153     case UNIT_D1:
154       return UNIT_D0;
155     case UNIT_A0:
156       return UNIT_A1;
157     case UNIT_A1:
158       return UNIT_A0;
159     default:
160       return unit;
161     }
162 }
163
164 /* Return the name of the pair register for UNIT and NUMBER or NULL.  */
165 static const char *
166 lookup_pair_reg_name (unsigned int unit, unsigned int number)
167 {
168   if (unit == UNIT_FX)
169     return lookup_reg_name (unit, number + 1);
170   else
171     return lookup_reg_name (get_pair_unit (unit), number);
172 }
173
174 /* Return the name of the accumulator register for PART.  */
175 static const char *
176 lookup_acf_name (unsigned int part)
177 {
178   size_t i;
179
180   for (i = 0; i < sizeof(metag_acftab)/sizeof(metag_acftab[0]); i++)
181     {
182       const metag_acf *acf = &metag_acftab[i];
183
184       if (acf->part == part)
185         return acf->name;
186     }
187   return "ACF.?";
188 }
189
190 /* Return the register name for the O2R register for UNIT and NUMBER.  */
191 static const char *
192 lookup_o2r (enum metag_unit unit, unsigned int number)
193 {
194   unsigned int o2r_unit;
195   enum metag_unit actual_unit = UNIT_A0;
196   const metag_reg *reg;
197
198   o2r_unit = (number & ~O2R_REG_MASK) >> 3;
199   number = number & O2R_REG_MASK;
200
201   if (unit == UNIT_A0)
202     {
203       switch (o2r_unit)
204         {
205         case 0:
206           actual_unit = UNIT_A1;
207           break;
208         case 1:
209           actual_unit = UNIT_D0;
210           break;
211         case 2:
212           actual_unit = UNIT_RD;
213           break;
214         case 3:
215           actual_unit = UNIT_D1;
216           break;
217         }
218     }
219   else if (unit == UNIT_A1)
220     {
221       switch (o2r_unit)
222         {
223         case 0:
224           actual_unit = UNIT_D1;
225           break;
226         case 1:
227           actual_unit = UNIT_D0;
228           break;
229         case 2:
230           actual_unit = UNIT_RD;
231           break;
232         case 3:
233           actual_unit = UNIT_A0;
234           break;
235         }
236     }
237   else if (unit == UNIT_D0)
238     {
239       switch (o2r_unit)
240         {
241         case 0:
242           actual_unit = UNIT_A1;
243           break;
244         case 1:
245           actual_unit = UNIT_D1;
246           break;
247         case 2:
248           actual_unit = UNIT_RD;
249           break;
250         case 3:
251           actual_unit = UNIT_A0;
252           break;
253         }
254     }
255   else if (unit == UNIT_D1)
256     {
257       switch (o2r_unit)
258         {
259         case 0:
260           actual_unit = UNIT_A1;
261           break;
262         case 1:
263           actual_unit = UNIT_D0;
264           break;
265         case 2:
266           actual_unit = UNIT_RD;
267           break;
268         case 3:
269           actual_unit = UNIT_A0;
270           break;
271         }
272     }
273
274   reg = lookup_reg (actual_unit, number);
275
276   if (reg)
277     return reg->name;
278   else
279     return unknown_reg;
280 }
281
282 /* Return the string for split condition code CODE. */
283 static const char *
284 lookup_scc_flags (unsigned int code)
285 {
286   size_t i;
287
288   for (i = 0; i < sizeof (metag_dsp_scondtab) / sizeof (metag_dsp_scondtab[0]); i++)
289     {
290       if (metag_dsp_scondtab[i].code == code)
291         {
292           return metag_dsp_scondtab[i].name;
293         }
294     }
295   return NULL;
296 }
297
298 /* Return the string for FPU split condition code CODE. */
299 static const char *
300 lookup_fpu_scc_flags (unsigned int code)
301 {
302   size_t i;
303
304   for (i = 0; i < sizeof (metag_fpu_scondtab) / sizeof (metag_fpu_scondtab[0]); i++)
305     {
306       if (metag_fpu_scondtab[i].code == code)
307         {
308           return metag_fpu_scondtab[i].name;
309         }
310     }
311   return NULL;
312 }
313
314 /* Print an instruction with PREFIX, NAME and OPERANDS.  */
315 static void
316 print_insn (disassemble_info *outf, const char *prefix, const char *name,
317             const char *operands)
318 {
319   outf->fprintf_func (outf->stream, "%-" PREFIX_WIDTH "s%-" INSN_NAME_WIDTH "s%s", prefix, name, operands);
320 }
321
322 /* Print an instruction with no operands.  */
323 static void
324 print_none (unsigned int insn_word ATTRIBUTE_UNUSED,
325             bfd_vma pc ATTRIBUTE_UNUSED,
326             const insn_template *template,
327             disassemble_info *outf)
328 {
329   outf->fprintf_func (outf->stream, "%-" PREFIX_WIDTH "s%s", "",
330                       template->name);
331 }
332
333 /* Print a unit to unit MOV instruction.  */
334 static void
335 print_mov_u2u (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
336                const insn_template *template,
337                disassemble_info *outf)
338 {
339   unsigned int dest_unit, dest_no, src_unit, src_no;
340   unsigned int is_kick = (insn_word & 0x1) && !((insn_word >> 9) & 0x1);
341   unsigned int major = MAJOR_OPCODE (insn_word);
342   unsigned int minor = MINOR_OPCODE (insn_word);
343   char buf[OPERAND_WIDTH];
344   const char *dest_reg;
345   const char *src_reg;
346
347   dest_unit = (insn_word >> 5) & UNIT_MASK;
348   dest_no = (insn_word >> 14) & REG_MASK;
349
350   dest_reg = lookup_reg_name (dest_unit, dest_no);
351
352   if (is_kick)
353     src_unit = UNIT_TR;
354   else
355     src_unit = (insn_word >> 10) & UNIT_MASK;
356
357   /* This is really an RTI/RTH. No, really.  */
358   if (major == OPC_MISC &&
359       minor == 0x3 &&
360       src_unit == 0xf)
361     {
362       if (insn_word & 0x800000)
363         outf->fprintf_func (outf->stream, "%-" PREFIX_WIDTH "s%s", "",
364                             "RTI");
365       else
366         outf->fprintf_func (outf->stream, "%-" PREFIX_WIDTH "s%s", "",
367                             "RTH");
368
369       return;
370     }
371
372   src_no = (insn_word >> 19) & REG_MASK;
373
374   src_reg = lookup_reg_name (src_unit, src_no);
375
376   snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
377
378   if (dest_unit == UNIT_FX || src_unit == UNIT_FX)
379     print_insn (outf, "F", template->name, buf);
380   else
381     print_insn (outf, "", template->name, buf);
382 }
383
384 /* Print a MOV to port instruction.  */
385 static void
386 print_mov_port (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
387                 const insn_template *template,
388                 disassemble_info *outf)
389 {
390   unsigned int dest_unit, dest1_no, dest2_no, src_unit, src_no;
391   unsigned int is_movl = MINOR_OPCODE (insn_word) == MOVL_MINOR;
392   char buf[OPERAND_WIDTH];
393   const char *dest_reg;
394   const char *pair_reg;
395   const char *src_reg;
396
397   if (is_movl)
398     dest_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK);
399   else
400     dest_unit = (insn_word >> 5) & UNIT_MASK;
401
402   dest1_no = (insn_word >> 14) & REG_MASK;
403   dest2_no = (insn_word >> 9) & REG_MASK;
404
405   dest_reg = lookup_reg_name (dest_unit, dest1_no);
406   pair_reg = lookup_pair_reg_name (dest_unit, dest2_no);
407
408   src_unit = UNIT_RD;
409   src_no = 0;
410
411   src_reg = lookup_reg_name (src_unit, src_no);
412
413   if (is_movl)
414     snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, pair_reg, src_reg);
415   else
416     snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
417
418   if (dest_unit == UNIT_FX)
419     print_insn (outf, "F", template->name, buf);
420   else
421     print_insn (outf, "", template->name, buf);
422 }
423
424 /* Return the number of bits set in rmask.  */
425 static unsigned int hweight (unsigned int rmask)
426 {
427   unsigned int count;
428
429   for (count = 0; rmask; count++)
430     {
431       rmask &= rmask - 1;
432     }
433
434   return count;
435 }
436
437 /* Print a MOVL to TTREC instruction.  */
438 static void
439 print_movl_ttrec (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
440                   const insn_template *template,
441                   disassemble_info *outf)
442 {
443   unsigned int dest_unit, dest_no, src1_no, src2_no, src_unit;
444   char buf[OPERAND_WIDTH];
445   const char *dest_reg;
446   const char *src_reg;
447   const char *pair_reg;
448
449   dest_unit = UNIT_TT;
450   dest_no = 3;
451
452   dest_reg = lookup_reg_name (dest_unit, dest_no);
453
454   src1_no = (insn_word >> 19) & REG_MASK;
455   src2_no = (insn_word >> 14) & REG_MASK;
456
457   src_unit = short_unit ((insn_word >> 7) & SHORT_UNIT_MASK);
458
459   src_reg = lookup_reg_name (src_unit, src1_no);
460   pair_reg = lookup_pair_reg_name (src_unit, src2_no);
461
462   snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src_reg, pair_reg);
463
464   print_insn (outf, "", template->name, buf);
465 }
466
467 /* Format a GET or SET address mode string from INSN_WORD into BUF.  */
468 static void
469 get_set_addr_str (char *buf, unsigned int buf_size, unsigned int size,
470                   unsigned int insn_word)
471 {
472   const char *base_reg;
473   unsigned int base_unit, base_no;
474   unsigned int imm = (insn_word >> 25) & 1;
475   unsigned int ua = (insn_word >> 7) & 1;
476   unsigned int pp = insn_word & 1;
477
478   base_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK);
479   base_no = (insn_word >> 14) & REG_MASK;
480
481   base_reg = lookup_reg_name (base_unit, base_no);
482
483   if (imm)
484     {
485       int offset = (insn_word >> 8) & GET_SET_IMM_MASK;
486
487       offset = sign_extend (offset, GET_SET_IMM_BITS);
488
489       if (offset == 0)
490         {
491           snprintf (buf, buf_size, "[%s]", base_reg);
492           return;
493         }
494
495       if (offset == 1 && ua)
496         {
497           if (pp)
498             snprintf (buf, buf_size, "[%s++]", base_reg);
499           else
500             snprintf (buf, buf_size, "[++%s]", base_reg);
501
502           return;
503         }
504       else if (offset == -1 && ua)
505         {
506           if (pp)
507             snprintf (buf, buf_size, "[%s--]", base_reg);
508           else
509             snprintf (buf, buf_size, "[--%s]", base_reg);
510
511           return;
512         }
513
514       offset = offset * size;
515
516       if (ua)
517         {
518           if (pp)
519             snprintf (buf, buf_size, "[%s+#%d++]", base_reg, offset);
520           else
521             snprintf (buf, buf_size, "[%s++#%d]", base_reg, offset);
522         }
523       else
524         snprintf (buf, buf_size, "[%s+#%d]", base_reg, offset);
525     }
526   else
527     {
528       const char *offset_reg;
529       unsigned int offset_no;
530
531       offset_no = (insn_word >> 9) & REG_MASK;
532
533       offset_reg = lookup_reg_name (base_unit, offset_no);
534
535       if (ua)
536         {
537           if (pp)
538             snprintf (buf, buf_size, "[%s+%s++]", base_reg, offset_reg);
539           else
540             snprintf (buf, buf_size, "[%s++%s]", base_reg, offset_reg);
541         }
542       else
543         snprintf (buf, buf_size, "[%s+%s]", base_reg, offset_reg);
544     }
545 }
546
547 /* Format an extended GET or SET address mode string from INSN_WORD into BUF. */
548 static void
549 get_set_ext_addr_str (char *buf, unsigned int buf_size, unsigned int size,
550                       unsigned int insn_word)
551 {
552   const char *base_reg;
553   unsigned int base_unit, base_no;
554   int offset;
555
556   base_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK);
557   base_no = insn_word & EXT_BASE_REG_MASK;
558
559   base_reg = lookup_reg_name (base_unit, base_no);
560
561   offset = (insn_word >> 7) & GET_SET_EXT_IMM_MASK;
562
563   offset = sign_extend (offset, GET_SET_EXT_IMM_BITS);
564
565   offset = offset * size;
566
567   if (offset == 0)
568     {
569       snprintf (buf, buf_size, "[%s]", base_reg);
570     }
571   else
572     {
573       snprintf (buf, buf_size, "[%s+#%d]", base_reg, offset);
574     }
575 }
576
577 /* Format an MGET or MSET address mode string from INSN_WORD into BUF.  */
578 static void
579 mget_mset_addr_str (char *buf, unsigned int buf_size,
580                     unsigned int insn_word)
581 {
582   const char *base_reg;
583   unsigned int base_unit, base_no;
584
585   base_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK);
586   base_no = (insn_word >> 14) & REG_MASK;
587
588   base_reg = lookup_reg_name (base_unit, base_no);
589
590   snprintf (buf, buf_size, "[%s++]", base_reg);
591 }
592
593 /* Format a conditional SET address mode string from INSN_WORD into BUF.  */
594 static void
595 cond_set_addr_str (char *buf, unsigned int buf_size,
596                    unsigned int insn_word)
597 {
598   const char *base_reg;
599   unsigned int base_unit, base_no;
600
601   base_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK);
602   base_no = (insn_word >> 14) & REG_MASK;
603
604   base_reg = lookup_reg_name (base_unit, base_no);
605
606   snprintf (buf, buf_size, "[%s]", base_reg);
607 }
608
609 /* Format a cache instruction address mode string from INSN_WORD into BUF.  */
610 static void
611 cache_addr_str (char *buf, unsigned int buf_size, unsigned int insn_word,
612                 int width)
613 {
614   const char *base_reg;
615   unsigned int base_unit, base_no;
616   int offset;
617
618   base_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK);
619   base_no = (insn_word >> 14) & REG_MASK;
620
621   base_reg = lookup_reg_name (base_unit, base_no);
622
623   offset = (insn_word >> 8) & GET_SET_IMM_MASK;
624
625   offset = sign_extend (offset, GET_SET_IMM_BITS);
626
627   offset = offset * width;
628
629   if (offset == 0)
630     {
631       snprintf (buf, buf_size, "[%s]", base_reg);
632     }
633   else
634     {
635       snprintf (buf, buf_size, "[%s+#%d]", base_reg, offset);
636     }
637 }
638
639 /* Format a list of registers starting at REG_UNIT and REG_NO and conforming
640    to RMASK into BUF.  */
641 static void
642 lookup_reg_list (char *reg_buf, size_t buf_len, unsigned int reg_unit,
643                  unsigned int reg_no, unsigned int rmask,
644                  bfd_boolean is_fpu_64bit)
645 {
646   const char *regs[MGET_MSET_MAX_REGS];
647   size_t used_regs = 1, i, remaining;
648
649   regs[0] = lookup_reg_name (reg_unit, reg_no);
650
651   for (i = 1; i < MGET_MSET_MAX_REGS; i++)
652     {
653       if (rmask & 1)
654         {
655           if (is_fpu_64bit)
656             regs[used_regs] = lookup_reg_name (reg_unit, reg_no + (i * 2));
657           else
658             regs[used_regs] = lookup_reg_name (reg_unit, reg_no + i);
659           used_regs++;
660         }
661       rmask = rmask >> 1;
662     }
663
664   remaining = buf_len;
665
666   for (i = 0; i < used_regs; i++)
667     {
668       size_t len;
669       if (i == 0)
670         len = snprintf(reg_buf, remaining, "%s", regs[i]);
671       else
672         len = snprintf(reg_buf, remaining, ",%s", regs[i]);
673
674       reg_buf += len;
675       remaining -= len;
676     }
677 }
678
679 /* Print a GET instruction.  */
680 static void
681 print_get (char *buf, char *addr_buf, unsigned int size,
682            const char *dest_reg, const char *pair_reg, unsigned int reg_unit,
683            const insn_template *template,
684            disassemble_info *outf)
685 {
686   if (size == 8)
687     {
688       snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, pair_reg,
689                 addr_buf);
690     }
691   else
692     {
693       snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, addr_buf);
694     }
695
696   if (reg_unit == UNIT_FX)
697     print_insn (outf, "F", template->name, buf);
698   else
699     print_insn (outf, "", template->name, buf);
700 }
701
702 /* Print a SET instruction.  */
703 static void
704 print_set (char *buf, char *addr_buf, unsigned int size,
705            const char *src_reg, const char *pair_reg, unsigned int reg_unit,
706            const insn_template *template,
707            disassemble_info *outf)
708 {
709   if (size == 8)
710     {
711       snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", addr_buf, src_reg, pair_reg);
712     }
713   else
714     {
715       snprintf (buf, OPERAND_WIDTH, "%s,%s", addr_buf, src_reg);
716     }
717
718   if (reg_unit == UNIT_FX)
719     print_insn (outf, "F", template->name, buf);
720   else
721     print_insn (outf, "", template->name, buf);
722 }
723
724 /* Print a GET or SET instruction.  */
725 static void
726 print_get_set (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
727                const insn_template *template,
728                disassemble_info *outf)
729 {
730   bfd_boolean is_get = MAJOR_OPCODE (template->meta_opcode) == OPC_GET;
731   char buf[OPERAND_WIDTH];
732   char addr_buf[ADDR_WIDTH];
733   unsigned int reg_unit, reg_no;
734   unsigned int size = metag_get_set_size_bytes (insn_word);
735   const char *reg_name;
736   const char *pair_reg;
737
738   reg_unit = (insn_word >> 1) & UNIT_MASK;
739   reg_no = (insn_word >> 19) & REG_MASK;
740
741   /* SETs should always print RD. */
742   if (!is_get && reg_unit == UNIT_RD)
743     reg_no = 0;
744
745   reg_name = lookup_reg_name (reg_unit, reg_no);
746
747   pair_reg = lookup_pair_reg_name (reg_unit, reg_no);
748
749   get_set_addr_str (addr_buf, ADDR_WIDTH, size, insn_word);
750
751   if (is_get)
752     {
753       /* RD regs are 64 bits wide so don't use the pair syntax.  */
754       if (reg_unit == UNIT_RD)
755         print_get (buf, addr_buf, 4, reg_name, pair_reg, reg_unit,
756                    template, outf);
757       else
758         print_get (buf, addr_buf, size, reg_name, pair_reg, reg_unit,
759                    template, outf);
760     }
761   else
762     {
763       /* RD regs are 64 bits wide so don't use the pair syntax.  */
764       if (reg_unit == UNIT_RD)
765         print_set (buf, addr_buf, 4, reg_name, pair_reg, reg_unit,
766                    template, outf);
767       else
768         print_set (buf, addr_buf, size, reg_name, pair_reg, reg_unit,
769                    template, outf);
770     }
771 }
772
773 /* Print an extended GET or SET instruction.  */
774 static void
775 print_get_set_ext (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
776                    const insn_template *template,
777                    disassemble_info *outf)
778 {
779   bfd_boolean is_get = MINOR_OPCODE (template->meta_opcode) == GET_EXT_MINOR;
780   bfd_boolean is_mov = MINOR_OPCODE (template->meta_opcode) == MOV_EXT_MINOR;
781   char buf[OPERAND_WIDTH];
782   char addr_buf[ADDR_WIDTH];
783   unsigned int reg_unit, reg_no;
784   unsigned int size = metag_get_set_ext_size_bytes (insn_word);
785   const char *reg_name;
786   const char *pair_reg;
787
788   if (is_mov)
789     reg_unit = UNIT_RD;
790   else
791     reg_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK);
792
793   reg_no = (insn_word >> 19) & REG_MASK;
794
795   reg_name = lookup_reg_name (reg_unit, reg_no);
796
797   pair_reg = lookup_pair_reg_name (reg_unit, reg_no);
798
799   get_set_ext_addr_str (addr_buf, ADDR_WIDTH, size, insn_word);
800
801   if (is_get)
802     print_get (buf, addr_buf, size, reg_name, pair_reg, reg_unit,
803                template, outf);
804   else if (is_mov)
805     print_get (buf, addr_buf, 4, reg_name, pair_reg, reg_unit,
806                template, outf);
807   else
808     print_set (buf, addr_buf, size, reg_name, pair_reg, reg_unit,
809                template, outf);
810 }
811
812 /* Print an MGET or MSET instruction.  */
813 static void
814 print_mget_mset (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
815                  const insn_template *template,
816                  disassemble_info *outf)
817 {
818   bfd_boolean is_get = MAJOR_OPCODE (template->meta_opcode) == OPC_GET;
819   bfd_boolean is_fpu = (MINOR_OPCODE (template->meta_opcode) & 0x6) == 0x6;
820   bfd_boolean is_64bit = (MINOR_OPCODE (template->meta_opcode) & 0x1) == 0x1;
821   char buf[OPERAND_WIDTH];
822   char addr_buf[ADDR_WIDTH];
823   char reg_buf[REG_WIDTH];
824   unsigned int reg_unit, reg_no, rmask;
825
826   if (is_fpu)
827     reg_unit = UNIT_FX;
828   else
829     reg_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK);
830
831   reg_no = (insn_word >> 19) & REG_MASK;
832   rmask = (insn_word >> 7) & RMASK_MASK;
833
834   lookup_reg_list (reg_buf, REG_WIDTH, reg_unit, reg_no, rmask,
835                    is_fpu && is_64bit);
836
837   mget_mset_addr_str (addr_buf, ADDR_WIDTH, insn_word);
838
839   if (is_get)
840     snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_buf, addr_buf);
841   else
842     snprintf (buf, OPERAND_WIDTH, "%s,%s", addr_buf, reg_buf);
843
844   if (is_fpu)
845     print_insn (outf, "F", template->name, buf);
846   else
847     print_insn (outf, "", template->name, buf);
848 }
849
850 /* Print a conditional SET instruction.  */
851 static void
852 print_cond_set (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
853                 const insn_template *template,
854                 disassemble_info *outf)
855 {
856   char buf[OPERAND_WIDTH];
857   char addr_buf[ADDR_WIDTH];
858   unsigned int src_unit, src_no;
859   unsigned int size = metag_cond_set_size_bytes (insn_word);
860   const char *src_reg;
861   const char *pair_reg;
862
863   src_unit = (insn_word >> 10) & UNIT_MASK;
864   src_no = (insn_word >> 19) & REG_MASK;
865
866   if (src_unit == UNIT_RD)
867     src_no = 0;
868
869   src_reg = lookup_reg_name (src_unit, src_no);
870
871   pair_reg = lookup_pair_reg_name (src_unit, src_no);
872
873   cond_set_addr_str (addr_buf, ADDR_WIDTH, insn_word);
874
875   if (src_unit == UNIT_RD)
876     print_set (buf, addr_buf, 4, src_reg, pair_reg, src_unit,
877                template, outf);
878   else
879     print_set (buf, addr_buf, size, src_reg, pair_reg, src_unit,
880                template, outf);
881 }
882
883 /* Print a MMOV instruction.  */
884 static void
885 print_mmov (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
886             const insn_template *template,
887             disassemble_info *outf)
888 {
889   unsigned int is_fpu = template->insn_type == INSN_FPU;
890   unsigned int is_prime = ((MINOR_OPCODE (template->meta_opcode) & 0x2) &&
891                            !is_fpu);
892   unsigned int is_64bit = MINOR_OPCODE (template->meta_opcode) & 0x1;
893   unsigned int is_dsp = template->meta_opcode & 0x1;
894   unsigned int dest_unit, dest_no, rmask;
895   char buf[OPERAND_WIDTH];
896   char reg_buf[REG_WIDTH];
897   char addr_buf[ADDR_WIDTH];
898
899   if (is_fpu)
900     dest_no = (insn_word >> 14) & REG_MASK;
901   else
902     dest_no = (insn_word >> 19) & REG_MASK;
903
904   rmask = (insn_word >> 7) & RMASK_MASK;
905
906   if (is_prime)
907     {
908       const char *dest_reg;
909       const char *base_reg;
910       unsigned int base_unit, base_no;
911       int i, count = hweight (rmask);
912
913       dest_reg = lookup_reg_name (UNIT_RD, dest_no);
914
915       strcpy (reg_buf, dest_reg);
916
917       for (i = 0; i < count; i++)
918         {
919           strcat (reg_buf, ",");
920           strcat (reg_buf, dest_reg);
921         }
922
923       base_unit = short_unit ((insn_word >> 5) & SHORT_UNIT_MASK);
924       base_no = (insn_word >> 14) & REG_MASK;
925
926       base_reg = lookup_reg_name (base_unit, base_no);
927
928       snprintf (addr_buf, ADDR_WIDTH, "[%s++]", base_reg);
929
930       snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_buf, addr_buf);
931     }
932   else
933     {
934       if (is_fpu)
935         dest_unit = UNIT_FX;
936       else
937         dest_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK);
938
939       lookup_reg_list (reg_buf, REG_WIDTH, dest_unit, dest_no, rmask,
940                        is_fpu && is_64bit);
941
942       snprintf (buf, OPERAND_WIDTH, "%s,RD", reg_buf);
943     }
944
945   if (is_dsp)
946     {
947       char prefix_buf[10] = {0};
948       if (is_prime)
949         {
950           if (dest_no == 22 || dest_no == 23)
951             strcpy (prefix_buf, "DB");
952           else if (dest_no == 24)
953             strcpy (prefix_buf, "DBH");
954           else if (dest_no == 25)
955             strcpy (prefix_buf, "DWH");
956           else if (dest_no == 31)
957             strcpy (prefix_buf, "DW");
958         }
959       else
960         strcpy (prefix_buf, "DW");
961       print_insn (outf, prefix_buf, template->name, buf);
962     }
963   else if (is_fpu)
964     print_insn (outf, "F", template->name, buf);
965   else
966     print_insn (outf, "", template->name, buf);
967 }
968
969 /* Print an MDRD instruction.  */
970 static void
971 print_mdrd (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
972             const insn_template *template,
973             disassemble_info *outf)
974 {
975   unsigned int rmask, count;
976   char buf[OPERAND_WIDTH];
977
978   rmask = (insn_word >> 7) & RMASK_MASK;
979
980   count = hweight (rmask);
981
982   snprintf (buf, OPERAND_WIDTH, "#%#x", count + 1);
983
984   print_insn (outf, "", template->name, buf);
985 }
986
987 /* Print an XFR instruction.  */
988 static void
989 print_xfr (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
990            const insn_template *template,
991            disassemble_info *outf)
992 {
993   char buf[OPERAND_WIDTH];
994   char dest_buf[ADDR_WIDTH];
995   char src_buf[ADDR_WIDTH];
996   unsigned int dest_unit, src_unit;
997   unsigned int dest_no, src_no;
998   unsigned int us, ud, pp;
999   const char *dest_base_reg;
1000   const char *dest_offset_reg;
1001   const char *src_base_reg;
1002   const char *src_offset_reg;
1003
1004   src_unit = short_unit ((insn_word >> 2) & SHORT_UNIT_MASK);
1005   src_no = (insn_word >> 19) & REG_MASK;
1006
1007   src_base_reg = lookup_reg_name (src_unit, src_no);
1008
1009   src_no = (insn_word >> 14) & REG_MASK;
1010
1011   src_offset_reg = lookup_reg_name (src_unit, src_no);
1012
1013   dest_unit = short_unit (insn_word & SHORT_UNIT_MASK);
1014   dest_no = (insn_word >> 9) & REG_MASK;
1015
1016   dest_base_reg = lookup_reg_name (dest_unit, dest_no);
1017
1018   dest_no = (insn_word >> 4) & REG_MASK;
1019
1020   dest_offset_reg = lookup_reg_name (dest_unit, dest_no);
1021
1022   us = (insn_word >> 27) & 0x1;
1023   ud = (insn_word >> 26) & 0x1;
1024   pp = (insn_word >> 24) & 0x1;
1025
1026   if (us)
1027     if (pp)
1028       snprintf (src_buf, ADDR_WIDTH, "[%s+%s++]", src_base_reg,
1029                 src_offset_reg);
1030     else
1031       snprintf (src_buf, ADDR_WIDTH, "[%s++%s]", src_base_reg,
1032                 src_offset_reg);
1033   else
1034     snprintf (src_buf, ADDR_WIDTH, "[%s+%s]", src_base_reg,
1035               src_offset_reg);
1036
1037   if (ud)
1038     if (pp)
1039       snprintf (dest_buf, ADDR_WIDTH, "[%s+%s++]", dest_base_reg,
1040                 dest_offset_reg);
1041     else
1042       snprintf (dest_buf, ADDR_WIDTH, "[%s++%s]", dest_base_reg,
1043                 dest_offset_reg);
1044   else
1045     snprintf (dest_buf, ADDR_WIDTH, "[%s+%s]", dest_base_reg,
1046               dest_offset_reg);
1047
1048   snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_buf, src_buf);
1049
1050   print_insn (outf, "", template->name, buf);
1051 }
1052
1053 /* Print a MOV to control unit instruction.  */
1054 static void
1055 print_mov_ct (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1056               const insn_template *template,
1057               disassemble_info *outf)
1058 {
1059   char buf[OPERAND_WIDTH];
1060   unsigned int reg_no;
1061   unsigned int se = (insn_word >> 1) & 0x1;
1062   unsigned int is_trace = (insn_word >> 2) & 0x1;
1063   int value;
1064   const char *dest_reg;
1065
1066   reg_no = (insn_word >> 19) & REG_MASK;
1067
1068   if (is_trace)
1069     dest_reg = lookup_reg_name (UNIT_TT, reg_no);
1070   else
1071     dest_reg = lookup_reg_name (UNIT_CT, reg_no);
1072
1073   value = (insn_word >> 3) & IMM16_MASK;
1074
1075   if (se)
1076     {
1077       value = sign_extend (value, IMM16_BITS);
1078       snprintf (buf, OPERAND_WIDTH, "%s,#%d", dest_reg, value);
1079     }
1080   else
1081     {
1082       snprintf (buf, OPERAND_WIDTH, "%s,#%#x", dest_reg, value);
1083     }
1084
1085   print_insn (outf, "", template->name, buf);
1086 }
1087
1088 /* Print a SWAP instruction.  */
1089 static void
1090 print_swap (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1091             const insn_template *template,
1092             disassemble_info *outf)
1093 {
1094   char buf[OPERAND_WIDTH];
1095   unsigned int dest_no, src_no;
1096   unsigned int dest_unit, src_unit;
1097   const char *dest_reg;
1098   const char *src_reg;
1099
1100   src_unit = (insn_word >> 10) & UNIT_MASK;
1101   src_no = (insn_word >> 19) & REG_MASK;
1102
1103   src_reg = lookup_reg_name (src_unit, src_no);
1104
1105   dest_unit = (insn_word >> 5) & UNIT_MASK;
1106   dest_no = (insn_word >> 14) & REG_MASK;
1107
1108   dest_reg = lookup_reg_name (dest_unit, dest_no);
1109
1110   snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
1111
1112   if (dest_unit == UNIT_FX || src_unit == UNIT_FX)
1113     print_insn (outf, "F", template->name, buf);
1114   else
1115     print_insn (outf, "", template->name, buf);
1116 }
1117
1118 /* Print a SWAP instruction.  */
1119 static void
1120 print_jump (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1121             const insn_template *template,
1122             disassemble_info *outf)
1123 {
1124   char buf[OPERAND_WIDTH];
1125   unsigned int reg_no, reg_unit;
1126   const char *reg_name;
1127   int value;
1128
1129   reg_unit = short_unit (insn_word & SHORT_UNIT_MASK);
1130   reg_no = (insn_word >> 19) & REG_MASK;
1131
1132   reg_name = lookup_reg_name (reg_unit, reg_no);
1133
1134   value = (insn_word >> 3) & IMM16_MASK;
1135
1136   snprintf (buf, OPERAND_WIDTH, "%s,#%#x", reg_name, value);
1137
1138   print_insn (outf, "", template->name, buf);
1139 }
1140
1141 /* Print a CALLR instruction.  */
1142 static void
1143 print_callr (unsigned int insn_word, bfd_vma pc, const insn_template *template,
1144              disassemble_info *outf)
1145 {
1146   char buf[OPERAND_WIDTH];
1147   unsigned int reg_no, reg_unit;
1148   const char *reg_name;
1149   int value;
1150
1151   reg_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK);
1152   reg_no = insn_word & CALLR_REG_MASK;
1153
1154   reg_name = lookup_reg_name (reg_unit, reg_no);
1155
1156   value = (insn_word >> 5) & IMM19_MASK;
1157
1158   value = sign_extend (value, IMM19_BITS);
1159
1160   value = value * 4;
1161
1162   value += pc;
1163
1164   snprintf (buf, OPERAND_WIDTH, "%s,", reg_name);
1165
1166   print_insn (outf, "", template->name, buf);
1167
1168   outf->print_address_func (value, outf);
1169 }
1170
1171 /* Print a GP ALU instruction.  */
1172 static void
1173 print_alu (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1174            const insn_template *template,
1175            disassemble_info *outf)
1176 {
1177   char buf[OPERAND_WIDTH];
1178   unsigned int is_addr_op = MAJOR_OPCODE (template->meta_opcode) == OPC_ADDR;
1179   unsigned int is_mul = MAJOR_OPCODE (template->meta_opcode) == OPC_MUL;
1180   unsigned int dest_no, src1_no, src2_no;
1181   unsigned int imm = (insn_word >> 25) & 0x1;
1182   unsigned int cond = (insn_word >> 26) & 0x1;
1183   unsigned int o1z = 0;
1184   unsigned int o2r = insn_word & 0x1;
1185   unsigned int unit_bit = (insn_word >> 24) & 0x1;
1186   unsigned int ca = (insn_word >> 5) & 0x1;
1187   unsigned int se = (insn_word >> 1) & 0x1;
1188   bfd_boolean is_quickrot = template->arg_type & GP_ARGS_QR;
1189   enum metag_unit base_unit;
1190   enum metag_unit dest_unit;
1191   const char *dest_reg;
1192   const char *src1_reg;
1193   const char *src2_reg;
1194   int value;
1195
1196   if ((MAJOR_OPCODE (template->meta_opcode) == OPC_ADDR ||
1197       MAJOR_OPCODE (template->meta_opcode) == OPC_ADD ||
1198        MAJOR_OPCODE (template->meta_opcode) == OPC_SUB) &&
1199       ((insn_word >> 2) & 0x1))
1200     o1z = 1;
1201
1202   if (is_addr_op)
1203     {
1204       if (unit_bit)
1205         base_unit = UNIT_A1;
1206       else
1207         base_unit = UNIT_A0;
1208     }
1209   else
1210     {
1211       if (unit_bit)
1212         base_unit = UNIT_D1;
1213       else
1214         base_unit = UNIT_D0;
1215     }
1216
1217   dest_no = (insn_word >> 19) & REG_MASK;
1218   src1_no = (insn_word >> 14) & REG_MASK;
1219   src2_no = (insn_word >> 9) & REG_MASK;
1220
1221   dest_unit = base_unit;
1222
1223   if (imm)
1224     {
1225       if (cond)
1226         {
1227           if (ca)
1228             {
1229               dest_unit = (insn_word >> 1) & UNIT_MASK;
1230               dest_reg = lookup_reg_name (dest_unit, dest_no);
1231             }
1232           else
1233               dest_reg = lookup_reg_name (dest_unit, dest_no);
1234
1235           src1_reg = lookup_reg_name (base_unit, src1_no);
1236
1237           value = (insn_word >> 6) & IMM8_MASK;
1238
1239           if (is_quickrot)
1240             {
1241               unsigned int qr_unit = unit_bit ? UNIT_A1 : UNIT_A0;
1242               unsigned int qr_no = 2;
1243               const char *qr_reg = lookup_reg_name (qr_unit, qr_no);
1244
1245               snprintf (buf, OPERAND_WIDTH, "%s,%s,#%#x,%s", dest_reg,
1246                         src1_reg, value, qr_reg);
1247             }
1248           else
1249             snprintf (buf, OPERAND_WIDTH, "%s,%s,#%#x", dest_reg,
1250                       src1_reg, value);
1251         }
1252       else
1253         {
1254           if (is_addr_op && (dest_no & ~CPC_REG_MASK))
1255             {
1256               dest_reg = lookup_reg_name (dest_unit, dest_no & CPC_REG_MASK);
1257               src1_reg = lookup_reg_name (base_unit, 0x10);
1258             }
1259           else
1260             {
1261               dest_reg = lookup_reg_name (dest_unit, dest_no);
1262               src1_reg = lookup_reg_name (base_unit, dest_no);
1263             }
1264
1265           value = (insn_word >> 3) & IMM16_MASK;
1266
1267           if (se)
1268             {
1269               value = sign_extend (value, IMM16_BITS);
1270               if (o1z)
1271                 {
1272                   snprintf (buf, OPERAND_WIDTH, "%s,#%d", dest_reg, value);
1273                 }
1274               else
1275                 {
1276                   snprintf (buf, OPERAND_WIDTH, "%s,%s,#%d", dest_reg,
1277                             src1_reg, value);
1278                 }
1279             }
1280           else
1281             {
1282               if (o1z)
1283                 {
1284                   snprintf (buf, OPERAND_WIDTH, "%s,#%#x", dest_reg, value);
1285                 }
1286               else
1287                 {
1288                   snprintf (buf, OPERAND_WIDTH, "%s,%s,#%#x", dest_reg,
1289                             src1_reg, value);
1290                 }
1291             }
1292         }
1293     }
1294   else
1295     {
1296       src1_reg = lookup_reg_name (base_unit, src1_no);
1297
1298       if (o2r)
1299         src2_reg = lookup_o2r (base_unit, src2_no);
1300       else
1301         src2_reg = lookup_reg_name (base_unit, src2_no);
1302
1303       if (cond)
1304         {
1305           dest_unit = (insn_word >> 5) & UNIT_MASK;
1306
1307           if (is_mul)
1308             {
1309               if (ca)
1310                 dest_unit = (insn_word >> 1) & UNIT_MASK;
1311               else
1312                 dest_unit = base_unit;
1313             }
1314
1315           dest_reg = lookup_reg_name (dest_unit, dest_no);
1316
1317           snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg,
1318                     src1_reg, src2_reg);
1319         }
1320       else
1321         {
1322           dest_reg = lookup_reg_name (dest_unit, dest_no);
1323
1324           if (is_quickrot)
1325             {
1326               unsigned int qr_unit = unit_bit ? UNIT_A1 : UNIT_A0;
1327               unsigned int qr_no = 2 + ((insn_word >> 7) & 0x1);
1328               const char *qr_reg = lookup_reg_name (qr_unit, qr_no);
1329
1330               snprintf (buf, OPERAND_WIDTH, "%s,%s,%s,%s", dest_reg,
1331                         src1_reg, src2_reg, qr_reg);
1332             }
1333           else if (o1z)
1334             {
1335               snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src2_reg);
1336             }
1337           else
1338             {
1339               snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg,
1340                         src1_reg, src2_reg);
1341             }
1342         }
1343     }
1344
1345   if (dest_unit == UNIT_FX)
1346     print_insn (outf, "F", template->name, buf);
1347   else
1348     print_insn (outf, "", template->name, buf);
1349 }
1350
1351 /* Print a B instruction.  */
1352 static void
1353 print_branch (unsigned int insn_word, bfd_vma pc,
1354               const insn_template *template,
1355               disassemble_info *outf)
1356 {
1357   int value;
1358
1359   value = (insn_word >> 5) & IMM19_MASK;
1360
1361   value = sign_extend (value, IMM19_BITS);
1362
1363   value = value * 4;
1364
1365   value += pc;
1366
1367   print_insn (outf, "", template->name, "");
1368
1369   outf->print_address_func (value, outf);
1370 }
1371
1372 /* Print a SWITCH instruction.  */
1373 static void
1374 print_switch (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1375               const insn_template *template,
1376               disassemble_info *outf)
1377 {
1378   char buf[OPERAND_WIDTH];
1379   unsigned int value;
1380
1381   value = insn_word & IMM24_MASK;
1382
1383   snprintf (buf, OPERAND_WIDTH, "#%#x", value);
1384
1385   print_insn (outf, "", template->name, buf);
1386 }
1387
1388 /* Print a shift instruction.  */
1389 static void
1390 print_shift (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1391              const insn_template *template,
1392              disassemble_info *outf)
1393 {
1394   char buf[OPERAND_WIDTH];
1395   unsigned int dest_no, src1_no, src2_no;
1396   unsigned int imm = (insn_word >> 25) & 0x1;
1397   unsigned int cond = (insn_word >> 26) & 0x1;
1398   unsigned int unit_bit = (insn_word >> 24) & 0x1;
1399   unsigned int ca = (insn_word >> 5) & 0x1;
1400   enum metag_unit base_unit;
1401   unsigned int dest_unit;
1402   const char *dest_reg;
1403   const char *src1_reg;
1404   const char *src2_reg;
1405   int value;
1406
1407   if (unit_bit)
1408     base_unit = UNIT_D1;
1409   else
1410     base_unit = UNIT_D0;
1411
1412   dest_no = (insn_word >> 19) & REG_MASK;
1413   src1_no = (insn_word >> 14) & REG_MASK;
1414   src2_no = (insn_word >> 9) & REG_MASK;
1415
1416   dest_unit = base_unit;
1417
1418   if (imm)
1419     {
1420       if (cond && ca)
1421         dest_unit = (insn_word >> 1) & UNIT_MASK;
1422
1423       dest_reg = lookup_reg_name (dest_unit, dest_no);
1424
1425       src1_reg = lookup_reg_name (base_unit, src1_no);
1426
1427       value = (insn_word >> 9) & IMM5_MASK;
1428
1429       snprintf (buf, OPERAND_WIDTH, "%s,%s,#%#x", dest_reg,
1430                 src1_reg, value);
1431     }
1432   else
1433     {
1434       if (cond && ca)
1435         dest_unit = (insn_word >> 1) & UNIT_MASK;
1436
1437       dest_reg = lookup_reg_name (dest_unit, dest_no);
1438
1439       src1_reg = lookup_reg_name (base_unit, src1_no);
1440       src2_reg = lookup_reg_name (base_unit, src2_no);
1441
1442       snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg,
1443                 src1_reg, src2_reg);
1444     }
1445
1446   if (dest_unit == UNIT_FX)
1447     print_insn (outf, "F", template->name, buf);
1448   else
1449     print_insn (outf, "", template->name, buf);
1450 }
1451
1452 /* Print a MIN or MAX instruction.  */
1453 static void
1454 print_min_max (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1455                const insn_template *template,
1456                disassemble_info *outf)
1457 {
1458   unsigned int base_unit, dest_no, src1_no, src2_no;
1459   char buf[OPERAND_WIDTH];
1460   const char *dest_reg;
1461   const char *src1_reg;
1462   const char *src2_reg;
1463
1464   if ((insn_word >> 24) & UNIT_MASK)
1465     base_unit = UNIT_D1;
1466   else
1467     base_unit = UNIT_D0;
1468
1469   dest_no = (insn_word >> 19) & REG_MASK;
1470   src1_no = (insn_word >> 14) & REG_MASK;
1471   src2_no = (insn_word >> 9) & REG_MASK;
1472
1473   dest_reg = lookup_reg_name (base_unit, dest_no);
1474
1475   src1_reg = lookup_reg_name (base_unit, src1_no);
1476   src2_reg = lookup_reg_name (base_unit, src2_no);
1477
1478   snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg);
1479
1480   print_insn (outf, "", template->name, buf);
1481 }
1482
1483 /* Print a bit operation instruction.  */
1484 static void
1485 print_bitop (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1486              const insn_template *template,
1487              disassemble_info *outf)
1488 {
1489   unsigned int swap_inst = MAJOR_OPCODE (template->meta_opcode) == OPC_MISC;
1490   unsigned int base_unit, src_unit, dest_no, src_no;
1491   unsigned int is_bexl = 0;
1492   char buf[OPERAND_WIDTH];
1493   const char *dest_reg;
1494   const char *src_reg;
1495
1496   if (swap_inst &&
1497       ((insn_word >> 1) & 0xb) == 0xa)
1498     is_bexl = 1;
1499
1500   if (swap_inst)
1501     {
1502       if (insn_word & 0x1)
1503         base_unit = UNIT_D1;
1504       else
1505         base_unit = UNIT_D0;
1506     }
1507   else
1508     {
1509       if ((insn_word >> 24) & 0x1)
1510         base_unit = UNIT_D1;
1511       else
1512         base_unit = UNIT_D0;
1513     }
1514
1515   src_unit = base_unit;
1516
1517   if (is_bexl)
1518     base_unit = get_pair_unit (base_unit);
1519
1520   dest_no = (insn_word >> 19) & REG_MASK;
1521
1522   dest_reg = lookup_reg_name (base_unit, dest_no);
1523
1524   src_no = (insn_word >> 14) & REG_MASK;
1525
1526   src_reg = lookup_reg_name (src_unit, src_no);
1527
1528   snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
1529
1530   print_insn (outf, "", template->name, buf);
1531 }
1532
1533 /* Print a CMP or TST instruction.  */
1534 static void
1535 print_cmp (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1536            const insn_template *template,
1537            disassemble_info *outf)
1538 {
1539   char buf[OPERAND_WIDTH];
1540   unsigned int dest_no, src_no;
1541   unsigned int imm = (insn_word >> 25) & 0x1;
1542   unsigned int cond = (insn_word >> 26) & 0x1;
1543   unsigned int o2r = insn_word & 0x1;
1544   unsigned int unit_bit = (insn_word >> 24) & 0x1;
1545   unsigned int se = (insn_word >> 1) & 0x1;
1546   enum metag_unit base_unit;
1547   const char *dest_reg;
1548   const char *src_reg;
1549   int value;
1550
1551   if (unit_bit)
1552     base_unit = UNIT_D1;
1553   else
1554     base_unit = UNIT_D0;
1555
1556   dest_no = (insn_word >> 14) & REG_MASK;
1557   src_no = (insn_word >> 9) & REG_MASK;
1558
1559   dest_reg = lookup_reg_name (base_unit, dest_no);
1560
1561   if (imm)
1562     {
1563       if (cond)
1564         {
1565           value = (insn_word >> 6) & IMM8_MASK;
1566
1567           snprintf (buf, OPERAND_WIDTH, "%s,#%#x", dest_reg, value);
1568         }
1569       else
1570         {
1571           dest_no = (insn_word >> 19) & REG_MASK;
1572
1573           dest_reg = lookup_reg_name (base_unit, dest_no);
1574
1575           value = (insn_word >> 3) & IMM16_MASK;
1576
1577           if (se)
1578             {
1579               value = sign_extend (value, IMM16_BITS);
1580               snprintf (buf, OPERAND_WIDTH, "%s,#%d", dest_reg, value);
1581             }
1582           else
1583             {
1584               snprintf (buf, OPERAND_WIDTH, "%s,#%#x", dest_reg, value);
1585             }
1586         }
1587     }
1588   else
1589     {
1590       if (o2r)
1591         src_reg = lookup_o2r (base_unit, src_no);
1592       else
1593         src_reg = lookup_reg_name (base_unit, src_no);
1594
1595       snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
1596     }
1597
1598   print_insn (outf, "", template->name, buf);
1599 }
1600
1601 /* Print a CACHER instruction.  */
1602 static void
1603 print_cacher (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1604               const insn_template *template,
1605               disassemble_info *outf)
1606 {
1607   char buf[OPERAND_WIDTH];
1608   char addr_buf[ADDR_WIDTH];
1609   unsigned int reg_unit, reg_no;
1610   unsigned int size = ((insn_word >> 1) & 0x1) ? 8 : 4;
1611   const char *reg_name;
1612   const char *pair_name;
1613
1614   reg_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK);
1615   reg_no = (insn_word >> 19) & REG_MASK;
1616
1617   reg_name = lookup_reg_name (reg_unit, reg_no);
1618   pair_name = lookup_pair_reg_name (reg_unit, reg_no);
1619
1620   cache_addr_str (addr_buf, ADDR_WIDTH, insn_word, size);
1621
1622   if (size == 8)
1623     snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", reg_name, pair_name, addr_buf);
1624   else
1625     snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_name, addr_buf);
1626
1627   print_insn (outf, "", template->name, buf);
1628 }
1629
1630 /* Print a CACHEW instruction.  */
1631 static void
1632 print_cachew (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1633               const insn_template *template,
1634               disassemble_info *outf)
1635 {
1636   char buf[OPERAND_WIDTH];
1637   char addr_buf[ADDR_WIDTH];
1638   unsigned int reg_unit, reg_no;
1639   unsigned int size = ((insn_word >> 1) & 0x1) ? 8 : 4;
1640   const char *reg_name;
1641   const char *pair_name;
1642
1643   reg_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK);
1644   reg_no = (insn_word >> 19) & REG_MASK;
1645
1646   reg_name = lookup_reg_name (reg_unit, reg_no);
1647   pair_name = lookup_pair_reg_name (reg_unit, reg_no);
1648
1649   cache_addr_str (addr_buf, ADDR_WIDTH, insn_word, 64);
1650
1651   if (size == 8)
1652     snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", addr_buf, reg_name, pair_name);
1653   else
1654     snprintf (buf, OPERAND_WIDTH, "%s,%s", addr_buf, reg_name);
1655
1656   print_insn (outf, "", template->name, buf);
1657 }
1658
1659 /* Print an ICACHE instruction.  */
1660 static void
1661 print_icache (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1662               const insn_template *template,
1663               disassemble_info *outf)
1664 {
1665   char buf[OPERAND_WIDTH];
1666   int offset;
1667   int pfcount;
1668
1669   offset = ((insn_word >> 9) & IMM15_MASK);
1670   pfcount = ((insn_word >> 1) & IMM4_MASK);
1671
1672   offset = sign_extend (offset, IMM15_BITS);
1673
1674   if (pfcount)
1675     snprintf (buf, OPERAND_WIDTH, "#%d,#0x%x", offset, pfcount);
1676   else
1677     snprintf (buf, OPERAND_WIDTH, "#%d,#0", offset);
1678   print_insn (outf, "", template->name, buf);
1679 }
1680
1681 /* Print a LNKGET instruction.  */
1682 static void
1683 print_lnkget (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1684               const insn_template *template,
1685               disassemble_info *outf)
1686 {
1687   char buf[OPERAND_WIDTH];
1688   char addr_buf[ADDR_WIDTH];
1689   unsigned int reg_unit, reg_no;
1690   unsigned int size = metag_get_set_ext_size_bytes (insn_word);
1691   const char *reg_name;
1692   const char *pair_name;
1693
1694   reg_unit = short_unit ((insn_word >> 3) & SHORT_UNIT_MASK);
1695   reg_no = (insn_word >> 19) & REG_MASK;
1696
1697   reg_name = lookup_reg_name (reg_unit, reg_no);
1698   pair_name = lookup_pair_reg_name (reg_unit, reg_no);
1699
1700   cache_addr_str (addr_buf, ADDR_WIDTH, insn_word, size);
1701
1702   if (size == 8)
1703     snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", reg_name, pair_name, addr_buf);
1704   else
1705     snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_name, addr_buf);
1706
1707   print_insn (outf, "", template->name, buf);
1708 }
1709
1710 /* Print an FPU MOV instruction.  */
1711 static void
1712 print_fmov (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1713             const insn_template *template,
1714             disassemble_info *outf)
1715 {
1716   char buf[OPERAND_WIDTH];
1717   char prefix_buf[10];
1718   unsigned int src_no, dest_no;
1719   unsigned int p = (insn_word >> 6) & 0x1;
1720   unsigned int d = (insn_word >> 5) & 0x1;
1721   unsigned int cc = (insn_word >> 1) & CC_MASK;
1722   bfd_boolean show_cond = cc != COND_A && cc != COND_NV;
1723   const char *dest_reg;
1724   const char *src_reg;
1725   const char *cc_flags;
1726
1727   dest_no = (insn_word >> 19) & REG_MASK;
1728   src_no = (insn_word >> 14) & REG_MASK;
1729
1730   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
1731   src_reg = lookup_reg_name (UNIT_FX, src_no);
1732
1733   cc_flags = lookup_fpu_scc_flags (cc);
1734
1735   snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
1736
1737   snprintf (prefix_buf, 10, "F%s%s%s", p ? "L" : "",
1738             d ? "D" : "", show_cond ? cc_flags : "");
1739
1740   print_insn (outf, prefix_buf, template->name, buf);
1741 }
1742
1743 /* Convert an FPU rmask into a compatible form. */
1744 static unsigned int
1745 convert_fx_rmask (unsigned int rmask)
1746 {
1747   int num_bits = hweight (rmask), i;
1748   unsigned int ret = 0;
1749
1750   for (i = 0; i < num_bits; i++)
1751     {
1752       ret <<= 1;
1753       ret |= 0x1;
1754     }
1755
1756   return ret;
1757 }
1758
1759 /* Print an FPU MMOV instruction.  */
1760 static void
1761 print_fmmov (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1762             const insn_template *template,
1763             disassemble_info *outf)
1764 {
1765   char buf[OPERAND_WIDTH];
1766   char data_buf[REG_WIDTH];
1767   char fpu_buf[REG_WIDTH];
1768   bfd_boolean to_fpu = MAJOR_OPCODE (insn_word) == OPC_GET;
1769   bfd_boolean is_mmovl = MINOR_OPCODE (insn_word) & 0x1;
1770   unsigned int rmask = (insn_word >> 7) & RMASK_MASK;
1771   unsigned int fpu_no, data_no, data_unit;
1772
1773   data_no = (insn_word >> 19) & REG_MASK;
1774   fpu_no = (insn_word >> 14) & REG_MASK;
1775
1776   if (insn_word & 0x1)
1777     data_unit = UNIT_D1;
1778   else
1779     data_unit = UNIT_D0;
1780
1781   lookup_reg_list (data_buf, REG_WIDTH, data_unit, data_no, rmask, FALSE);
1782   lookup_reg_list (fpu_buf, REG_WIDTH, UNIT_FX, fpu_no,
1783                    convert_fx_rmask (rmask), is_mmovl);
1784
1785   if (to_fpu)
1786     snprintf (buf, OPERAND_WIDTH, "%s,%s", fpu_buf, data_buf);
1787   else
1788     snprintf (buf, OPERAND_WIDTH, "%s,%s", data_buf, fpu_buf);
1789
1790   print_insn (outf, "F", template->name, buf);
1791 }
1792
1793 /* Print an FPU data unit MOV instruction.  */
1794 static void
1795 print_fmov_data (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1796                  const insn_template *template,
1797                  disassemble_info *outf)
1798 {
1799   char buf[OPERAND_WIDTH];
1800   unsigned int src_no, dest_no;
1801   unsigned int to_fpu = ((insn_word >> 7) & 0x1);
1802   unsigned int unit_bit = (insn_word >> 24) & 0x1;
1803   enum metag_unit base_unit;
1804   const char *dest_reg;
1805   const char *src_reg;
1806
1807   dest_no = (insn_word >> 19) & REG_MASK;
1808   src_no = (insn_word >> 9) & REG_MASK;
1809
1810   if (unit_bit)
1811     base_unit = UNIT_D1;
1812   else
1813     base_unit = UNIT_D0;
1814
1815   if (to_fpu)
1816     {
1817       dest_reg = lookup_reg_name (UNIT_FX, dest_no);
1818       src_reg = lookup_reg_name (base_unit, src_no);
1819     }
1820   else
1821     {
1822       dest_reg = lookup_reg_name (base_unit, dest_no);
1823       src_reg = lookup_reg_name (UNIT_FX, src_no);
1824     }
1825
1826   snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
1827
1828   print_insn (outf, "F", template->name, buf);
1829 }
1830
1831 /* Print an FPU MOV immediate instruction.  */
1832 static void
1833 print_fmov_i (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1834               const insn_template *template,
1835               disassemble_info *outf)
1836 {
1837   char buf[OPERAND_WIDTH];
1838   unsigned int dest_no;
1839   unsigned int p = (insn_word >> 2) & 0x1;
1840   unsigned int d = (insn_word >> 1) & 0x1;
1841   const char *dest_reg;
1842   unsigned int value = (insn_word >> 3) & IMM16_MASK;
1843
1844   dest_no = (insn_word >> 19) & REG_MASK;
1845
1846   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
1847
1848   snprintf (buf, OPERAND_WIDTH, "%s,#%#x", dest_reg, value);
1849
1850   if (p)
1851     print_insn (outf, "FL", template->name, buf);
1852   else if (d)
1853     print_insn (outf, "FD", template->name, buf);
1854   else
1855     print_insn (outf, "F", template->name, buf);
1856 }
1857
1858 /* Print an FPU PACK instruction.  */
1859 static void
1860 print_fpack (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1861              const insn_template *template,
1862              disassemble_info *outf)
1863 {
1864   char buf[OPERAND_WIDTH];
1865   unsigned int src1_no, src2_no, dest_no;
1866   const char *dest_reg;
1867   const char *src1_reg;
1868   const char *src2_reg;
1869
1870   dest_no = (insn_word >> 19) & REG_MASK;
1871   src1_no = (insn_word >> 14) & REG_MASK;
1872   src2_no = (insn_word >> 9) & REG_MASK;
1873
1874   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
1875   src1_reg = lookup_reg_name (UNIT_FX, src1_no);
1876   src2_reg = lookup_reg_name (UNIT_FX, src2_no);
1877
1878   snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg);
1879
1880   print_insn (outf, "F", template->name, buf);
1881 }
1882
1883 /* Print an FPU SWAP instruction.  */
1884 static void
1885 print_fswap (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1886              const insn_template *template,
1887              disassemble_info *outf)
1888 {
1889   char buf[OPERAND_WIDTH];
1890   unsigned int src_no, dest_no;
1891   const char *dest_reg;
1892   const char *src_reg;
1893
1894   dest_no = (insn_word >> 19) & REG_MASK;
1895   src_no = (insn_word >> 14) & REG_MASK;
1896
1897   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
1898   src_reg = lookup_reg_name (UNIT_FX, src_no);
1899
1900   snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
1901
1902   print_insn (outf, "FL", template->name, buf);
1903 }
1904
1905 /* Print an FPU CMP instruction.  */
1906 static void
1907 print_fcmp (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1908             const insn_template *template,
1909             disassemble_info *outf)
1910 {
1911   char buf[OPERAND_WIDTH];
1912   char prefix_buf[10];
1913   unsigned int src_no, dest_no;
1914   unsigned int a = (insn_word >> 19) & 0x1;
1915   unsigned int z = (insn_word >> 8) & 0x1;
1916   unsigned int p = (insn_word >> 6) & 0x1;
1917   unsigned int d = (insn_word >> 5) & 0x1;
1918   unsigned int q = (insn_word >> 7) & 0x1;
1919   unsigned int cc = (insn_word >> 1) & CC_MASK;
1920   bfd_boolean show_cond = cc != COND_A && cc != COND_NV;
1921   const char *dest_reg;
1922   const char *src_reg;
1923   const char *cc_flags;
1924
1925   dest_no = (insn_word >> 14) & REG_MASK;
1926   src_no = (insn_word >> 9) & REG_MASK;
1927
1928   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
1929   src_reg = lookup_reg_name (UNIT_FX, src_no);
1930
1931   cc_flags = lookup_fpu_scc_flags (cc);
1932
1933   if (z)
1934     snprintf (buf, OPERAND_WIDTH, "%s,#0", dest_reg);
1935   else
1936     snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
1937
1938   snprintf (prefix_buf, 10, "F%s%s%s%s%s", p ? "L" : "",
1939             d ? "D" : "", a ? "A" : "", q ? "Q" : "",
1940             show_cond ? cc_flags : "");
1941
1942   print_insn (outf, prefix_buf, template->name, buf);
1943 }
1944
1945 /* Print an FPU MIN or MAX instruction.  */
1946 static void
1947 print_fminmax (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1948                const insn_template *template,
1949                disassemble_info *outf)
1950 {
1951   char buf[OPERAND_WIDTH];
1952   char prefix_buf[10];
1953   unsigned int p = (insn_word >> 6) & 0x1;
1954   unsigned int d = (insn_word >> 5) & 0x1;
1955   unsigned int src1_no, src2_no, dest_no;
1956   unsigned int cc = (insn_word >> 1) & CC_MASK;
1957   bfd_boolean show_cond = cc != COND_A && cc != COND_NV;
1958   const char *dest_reg;
1959   const char *src1_reg;
1960   const char *src2_reg;
1961   const char *cc_flags;
1962
1963   dest_no = (insn_word >> 19) & REG_MASK;
1964   src1_no = (insn_word >> 14) & REG_MASK;
1965   src2_no = (insn_word >> 9) & REG_MASK;
1966
1967   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
1968   src1_reg = lookup_reg_name (UNIT_FX, src1_no);
1969   src2_reg = lookup_reg_name (UNIT_FX, src2_no);
1970
1971   cc_flags = lookup_fpu_scc_flags (cc);
1972
1973   snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg);
1974
1975   snprintf (prefix_buf, 10, "F%s%s%s", p ? "L" : "",
1976             d ? "D" : "", show_cond ? cc_flags : "");
1977
1978   print_insn (outf, prefix_buf, template->name, buf);
1979 }
1980
1981 /* Print an FPU data conversion instruction.  */
1982 static void
1983 print_fconv (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1984              const insn_template *template,
1985              disassemble_info *outf)
1986 {
1987   char buf[OPERAND_WIDTH];
1988   char prefix_buf[10];
1989   unsigned int p = (insn_word >> 6) & 0x1;
1990   unsigned int z = (insn_word >> 12) & 0x1;
1991   unsigned int src_no, dest_no;
1992   unsigned int cc = (insn_word >> 1) & CC_MASK;
1993   bfd_boolean show_cond = cc != COND_A && cc != COND_NV;
1994   const char *dest_reg;
1995   const char *src_reg;
1996   const char *cc_flags;
1997
1998   dest_no = (insn_word >> 19) & REG_MASK;
1999   src_no = (insn_word >> 14) & REG_MASK;
2000
2001   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
2002   src_reg = lookup_reg_name (UNIT_FX, src_no);
2003
2004   cc_flags = lookup_fpu_scc_flags (cc);
2005
2006   snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
2007
2008   snprintf (prefix_buf, 10, "F%s%s%s", p ? "L" : "",
2009             z ? "Z" : "", show_cond ? cc_flags : "");
2010
2011   print_insn (outf, prefix_buf, template->name, buf);
2012 }
2013
2014 /* Print an FPU extended data conversion instruction.  */
2015 static void
2016 print_fconvx (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
2017               const insn_template *template,
2018               disassemble_info *outf)
2019 {
2020   char buf[OPERAND_WIDTH];
2021   char prefix_buf[10];
2022   unsigned int p = (insn_word >> 6) & 0x1;
2023   unsigned int xl = (insn_word >> 7) & 0x1;
2024   unsigned int src_no, dest_no, fraction_bits;
2025   unsigned int cc = (insn_word >> 1) & CC_MASK;
2026   bfd_boolean show_cond = cc != COND_A && cc != COND_NV;
2027   const char *dest_reg;
2028   const char *src_reg;
2029   const char *cc_flags;
2030
2031   dest_no = (insn_word >> 19) & REG_MASK;
2032   src_no = (insn_word >> 14) & REG_MASK;
2033
2034   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
2035   src_reg = lookup_reg_name (UNIT_FX, src_no);
2036
2037   cc_flags = lookup_fpu_scc_flags (cc);
2038
2039   if (xl)
2040     fraction_bits = (insn_word >> 8) & IMM6_MASK;
2041   else
2042     fraction_bits = (insn_word >> 9) & IMM5_MASK;
2043
2044   snprintf (buf, OPERAND_WIDTH, "%s,%s,#%#x", dest_reg, src_reg,
2045             fraction_bits);
2046
2047   snprintf (prefix_buf, 10, "F%s%s", p ? "L" : "",
2048             show_cond ? cc_flags : "");
2049
2050   print_insn (outf, prefix_buf, template->name, buf);
2051 }
2052
2053 /* Print an FPU basic arithmetic instruction.  */
2054 static void
2055 print_fbarith (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
2056                const insn_template *template,
2057                disassemble_info *outf)
2058 {
2059   char buf[OPERAND_WIDTH];
2060   char prefix_buf[10];
2061   unsigned int n = (insn_word >> 7) & 0x1;
2062   unsigned int p = (insn_word >> 6) & 0x1;
2063   unsigned int d = (insn_word >> 5) & 0x1;
2064   unsigned int src1_no, src2_no, dest_no;
2065   unsigned int cc = (insn_word >> 1) & CC_MASK;
2066   bfd_boolean show_cond = cc != COND_A && cc != COND_NV;
2067   const char *dest_reg;
2068   const char *src1_reg;
2069   const char *src2_reg;
2070   const char *cc_flags;
2071
2072   dest_no = (insn_word >> 19) & REG_MASK;
2073   src1_no = (insn_word >> 14) & REG_MASK;
2074   src2_no = (insn_word >> 9) & REG_MASK;
2075
2076   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
2077   src1_reg = lookup_reg_name (UNIT_FX, src1_no);
2078   src2_reg = lookup_reg_name (UNIT_FX, src2_no);
2079
2080   cc_flags = lookup_fpu_scc_flags (cc);
2081
2082   snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg);
2083
2084   snprintf (prefix_buf, 10, "F%s%s%s%s", p ? "L" : "",
2085             d ? "D" : "", n ? "I" : "", show_cond ? cc_flags : "");
2086
2087   print_insn (outf, prefix_buf, template->name, buf);
2088 }
2089
2090 /* Print an FPU extended arithmetic instruction.  */
2091 static void
2092 print_fearith (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
2093                const insn_template *template,
2094                disassemble_info *outf)
2095 {
2096   char buf[OPERAND_WIDTH];
2097   char prefix_buf[10];
2098   bfd_boolean is_muz = (MINOR_OPCODE (insn_word) == 0x6 &&
2099                         ((insn_word >> 4) & 0x1));
2100   bfd_boolean is_mac = (MINOR_OPCODE (insn_word) == 0x6 &&
2101                         (insn_word & 0x1f) == 0);
2102   bfd_boolean is_maw = (MINOR_OPCODE (insn_word) == 0x6 &&
2103                         ((insn_word >> 3) & 0x1));
2104   unsigned int o3o = insn_word & 0x1;
2105   unsigned int q = is_muz && ((insn_word >> 1) & 0x1);
2106   unsigned int n = (insn_word >> 7) & 0x1;
2107   unsigned int p = (insn_word >> 6) & 0x1;
2108   unsigned int d = (insn_word >> 5) & 0x1;
2109   unsigned int cc = (insn_word >> 1) & CC_MASK;
2110   bfd_boolean show_cond = (MINOR_OPCODE (insn_word) == 0x5 && cc != COND_A &&
2111                            cc != COND_NV);
2112   unsigned int src1_no, src2_no, dest_no;
2113   const char *dest_reg;
2114   const char *src1_reg;
2115   const char *src2_reg;
2116   const char *cc_flags;
2117
2118   dest_no = (insn_word >> 19) & REG_MASK;
2119   src1_no = (insn_word >> 14) & REG_MASK;
2120   src2_no = (insn_word >> 9) & REG_MASK;
2121
2122   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
2123   src1_reg = lookup_reg_name (UNIT_FX, src1_no);
2124   src2_reg = lookup_reg_name (UNIT_FX, src2_no);
2125
2126   cc_flags = lookup_fpu_scc_flags (cc);
2127
2128   if (is_mac)
2129     snprintf (buf, OPERAND_WIDTH, "ACF.0,%s,%s", src1_reg, src2_reg);
2130   else if (o3o && is_maw)
2131     snprintf (buf, OPERAND_WIDTH, "%s,%s", src1_reg, src2_reg);
2132   else
2133     snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg);
2134
2135   snprintf (prefix_buf, 10, "F%s%s%s%s%s", p ? "L" : "",
2136             d ? "D" : "", n ? "I" : "", q ? "Q" : "",
2137             show_cond ? cc_flags : "");
2138
2139   print_insn (outf, prefix_buf, template->name, buf);
2140 }
2141
2142 /* Print an FPU RCP or RSQ instruction.  */
2143 static void
2144 print_frec (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
2145             const insn_template *template,
2146             disassemble_info *outf)
2147 {
2148   char buf[OPERAND_WIDTH];
2149   char prefix_buf[10];
2150   unsigned int z = (insn_word >> 10) & 0x1;
2151   unsigned int q = (insn_word >> 9) & 0x1;
2152   unsigned int n = (insn_word >> 7) & 0x1;
2153   unsigned int p = (insn_word >> 6) & 0x1;
2154   unsigned int d = (insn_word >> 5) & 0x1;
2155   unsigned int src_no, dest_no;
2156   const char *dest_reg;
2157   const char *src_reg;
2158
2159   dest_no = (insn_word >> 19) & REG_MASK;
2160   src_no = (insn_word >> 14) & REG_MASK;
2161
2162   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
2163   src_reg = lookup_reg_name (UNIT_FX, src_no);
2164
2165   snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
2166
2167   snprintf (prefix_buf, 10, "F%s%s%s%s%s", p ? "L" : "",
2168             d ? "D" : "", n ? "I" : "", q ? "Q" : "", z ? "Z" : "");
2169
2170   print_insn (outf, prefix_buf, template->name, buf);
2171 }
2172
2173 static void
2174 print_fsimd (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
2175              const insn_template *template,
2176              disassemble_info *outf)
2177 {
2178   char buf[OPERAND_WIDTH];
2179   unsigned int n = (insn_word >> 7) & 0x1;
2180   unsigned int src1_no, src2_no, dest_no;
2181   const char *dest_reg;
2182   const char *src1_reg;
2183   const char *src2_reg;
2184
2185   dest_no = (insn_word >> 19) & REG_MASK;
2186   src1_no = (insn_word >> 14) & REG_MASK;
2187   src2_no = (insn_word >> 9) & REG_MASK;
2188
2189   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
2190   src1_reg = lookup_reg_name (UNIT_FX, src1_no);
2191   src2_reg = lookup_reg_name (UNIT_FX, src2_no);
2192
2193   snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg);
2194
2195   if (n)
2196     print_insn (outf, "FLI", template->name, buf);
2197   else
2198     print_insn (outf, "FL", template->name, buf);
2199 }
2200
2201 /* Print an FPU accumulator GET or SET instruction.  */
2202 static void
2203 print_fget_set_acf (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
2204                     const insn_template *template,
2205                     disassemble_info *outf)
2206 {
2207   bfd_boolean is_get = MAJOR_OPCODE (template->meta_opcode) == OPC_GET;
2208   char buf[OPERAND_WIDTH];
2209   char addr_buf[ADDR_WIDTH];
2210   unsigned int part;
2211   const char *reg_name;
2212
2213   part = (insn_word >> 19) & ACF_PART_MASK;
2214
2215   reg_name = lookup_acf_name (part);
2216
2217   mget_mset_addr_str (addr_buf, ADDR_WIDTH, insn_word);
2218
2219   if (is_get)
2220     {
2221       snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_name, addr_buf);
2222     }
2223   else
2224     {
2225       snprintf (buf, OPERAND_WIDTH, "%s,%s", addr_buf, reg_name);
2226     }
2227   print_insn (outf, "F", template->name, buf);
2228 }
2229
2230 /* Return the name of the DSP register or accumulator for NUM and UNIT.  */
2231 static const char *
2232 __lookup_dsp_name (unsigned int num, unsigned int unit)
2233 {
2234   size_t i;
2235
2236   for (i = 0; i < sizeof(metag_dsp_regtab)/sizeof(metag_dsp_regtab[0]); i++)
2237     {
2238       const metag_reg *reg = &metag_dsp_regtab[i];
2239
2240       if (reg->no == num)
2241         {
2242           if ((reg->unit == UNIT_RAM_D0 || reg->unit == UNIT_ACC_D0) &&
2243               unit == UNIT_D0)
2244             return reg->name;
2245
2246           if ((reg->unit == UNIT_RAM_D1 || reg->unit == UNIT_ACC_D1) &&
2247               unit == UNIT_D1)
2248             return reg->name;
2249         }
2250     }
2251   return "?.?";
2252 }
2253
2254 /* Return the name of the DSP register for NUM and UNIT.  */
2255 static const char *
2256 lookup_dsp_name (unsigned int num, unsigned int unit)
2257 {
2258   size_t i;
2259
2260   for (i = 0; i < sizeof(metag_dsp_regtab)/sizeof(metag_dsp_regtab[0]); i++)
2261     {
2262       const metag_reg *reg = &metag_dsp_regtab[i];
2263
2264       if (reg->no == num && reg->unit == unit)
2265         return reg->name;
2266     }
2267   return "?.?";
2268 }
2269
2270 /* Return the name of the DSP RAM register for NUM and UNIT.  */
2271 static const char *
2272 lookup_dspram_name (unsigned int num, unsigned int unit, bfd_boolean load)
2273 {
2274   size_t i, nentries;
2275
2276   nentries = sizeof(metag_dsp_tmpl_regtab[load])/sizeof(metag_dsp_tmpl_regtab[load][0]);
2277
2278   for (i = 0; i < nentries; i++)
2279     {
2280       const metag_reg *reg = &metag_dsp_tmpl_regtab[load][i];
2281
2282       if (reg->no == num && reg->unit == unit)
2283         return reg->name;
2284     }
2285   return "?.?";
2286 }
2287
2288 /* This lookup function looks up the corresponding name for a register
2289    number in a DSP instruction. SOURCE indicates whether this
2290    register is a source or destination operand.  */
2291 static const char *
2292 lookup_any_reg_name (unsigned int unit, unsigned int num, bfd_boolean source)
2293 {
2294   /* A register with the top bit set (5th bit) indicates a DSPRAM
2295      register.  */
2296   if (num > 15)
2297     {
2298       unsigned int dunit = (unit == UNIT_D0) ? UNIT_RAM_D0 : UNIT_RAM_D1;
2299       return lookup_dspram_name (num, dunit, source);
2300     }
2301   else
2302     return lookup_reg_name (unit, num);
2303 }
2304
2305 /* Return the DSP data unit for UNIT.  */
2306 static inline enum metag_unit
2307 dsp_data_unit_to_sym (unsigned int unit)
2308 {
2309   if (unit == 0)
2310     return UNIT_D0;
2311   else
2312     return UNIT_D1;
2313 }
2314
2315 /* Print a DSP GET or SET instruction.  */
2316 static void
2317 print_dget_set (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
2318                 const insn_template *template,
2319                 disassemble_info *outf)
2320 {
2321   bfd_boolean is_get = (template->meta_opcode & 0x100);
2322   char buf[OPERAND_WIDTH];
2323   char addr_buf[ADDR_WIDTH];
2324   char prefix[DSP_PREFIX_WIDTH];
2325   unsigned int part;
2326   const char *reg_name[2];
2327   bfd_boolean is_high = FALSE;
2328   bfd_boolean is_dual = (insn_word & 0x4);
2329   bfd_boolean is_template = (insn_word & 0x2);
2330   const char *base_reg = "?";
2331   unsigned int addr_unit, base_no, unit;
2332
2333   unit = dsp_data_unit_to_sym (insn_word & 0x1);
2334
2335   /* Is this a load/store to a template table?  */
2336   if (is_template)
2337     {
2338       part = (insn_word >> 19) & 0x1f;
2339       reg_name[0] = lookup_dsp_name (part, UNIT_DT);
2340     }
2341   else
2342     {
2343       part = (insn_word >> 19) & REG_MASK;
2344       is_high = ((part & 0x18) == 0x18);
2345
2346       /* Strip bit high indicator.  */
2347       if (is_high)
2348         part &= 0x17;
2349
2350       reg_name[0] = __lookup_dsp_name (part, unit);
2351
2352     }
2353
2354   /* Is this a dual unit DSP operation?  The modulo operator below
2355      makes sure that we print the Rd register in the correct order,
2356      e.g. because there's only one bit in the instruction for the Data
2357      Unit we have to work out what the other data unit number is.
2358      (there's only 2).  */
2359   if (is_dual)
2360     {
2361       unsigned int _unit = insn_word & 0x1;
2362
2363       _unit = ((_unit + 1) % 2);
2364       reg_name[1] = __lookup_dsp_name(part, dsp_data_unit_to_sym (_unit));
2365     }
2366   else
2367     reg_name[1] = NULL;
2368
2369   addr_unit = ((insn_word >> 18) & 0x1);
2370   if (addr_unit == 0)
2371           addr_unit = UNIT_A0;
2372   else
2373           addr_unit = UNIT_A1;
2374
2375   base_no = (insn_word >> 14) & DSP_REG_MASK;
2376
2377   base_reg = lookup_reg_name (addr_unit, base_no);
2378
2379   /* Check if it's a post-increment/post-decrement.  */
2380   if (insn_word & 0x2000)
2381   {
2382           unsigned int imm = (insn_word >> 9) & DGET_SET_IMM_MASK;
2383           const char *post_op;
2384
2385           switch (imm)
2386             {
2387             case 0x1:
2388               post_op = "++";
2389               break;
2390             case 0x3:
2391               post_op = "--";
2392               break;
2393             default:
2394               post_op = "";
2395             }
2396
2397           snprintf (addr_buf, ADDR_WIDTH, "[%s%s]", base_reg, post_op);
2398   }
2399   else
2400   {
2401           unsigned int offset_part = (insn_word >> 9) & DSP_REG_MASK;
2402           const char *offset_reg = lookup_reg_name (addr_unit, offset_part);
2403
2404           snprintf (addr_buf, ADDR_WIDTH, "[%s+%s++]", base_reg, offset_reg);
2405   }
2406
2407   if (is_get)
2408     {
2409       if (is_dual && !is_template)
2410         snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", reg_name[0],
2411                   reg_name[1], addr_buf);
2412       else
2413         snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_name[0], addr_buf);
2414     }
2415   else
2416     {
2417       if (is_dual && !is_template)
2418         snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", addr_buf,
2419                   reg_name[0], reg_name[1]);
2420       else
2421         snprintf (buf, OPERAND_WIDTH, "%s,%s", addr_buf, reg_name[0]);
2422     }
2423
2424   snprintf (prefix, DSP_PREFIX_WIDTH, "D%s", is_high ? "H" : "");
2425   print_insn (outf, prefix, template->name, buf);
2426 }
2427
2428 /* Print a DSP template instruction.  */
2429 static void
2430 print_dtemplate (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
2431                  const insn_template *template,
2432                  disassemble_info *outf)
2433 {
2434   char buf[OPERAND_WIDTH];
2435   char prefix[DSP_PREFIX_WIDTH];
2436   unsigned int offset[4];
2437   bfd_boolean is_half = (MINOR_OPCODE (insn_word) == 0x5);
2438   bfd_boolean daop_only = (MINOR_OPCODE (insn_word) == 0x3);
2439
2440   offset[0] = ((insn_word >> 19) & REG_MASK);
2441   offset[1] = ((insn_word >> 14) & REG_MASK);
2442   offset[2] = ((insn_word >> 9) & REG_MASK);
2443   offset[3] = ((insn_word >> 4) & REG_MASK);
2444
2445   if (daop_only)
2446           snprintf (buf, OPERAND_WIDTH, "#0x%x,#0x%x,#0x%x", offset[0],
2447                     offset[1], offset[2]);
2448   else
2449     {
2450       snprintf (buf, OPERAND_WIDTH, "#0x%x,#0x%x,#0x%x,#0x%x", offset[0],
2451                 offset[1], offset[2], offset[3]);
2452     }
2453
2454   snprintf (prefix, DSP_PREFIX_WIDTH, "D%s", is_half ? "H" : "");
2455   print_insn (outf, prefix, template->name, buf);
2456 }
2457
2458 /* Format template definition from INSN_WORD into BUF.  */
2459 static void
2460 decode_template_definition(unsigned int insn_word, char *buf, size_t len)
2461 {
2462   bfd_boolean load = ((insn_word >> 13) & 0x1);
2463   bfd_boolean dspram = (((insn_word >> 17) & 0x3) == 0x3);
2464   const char *template[1];
2465   unsigned int tidx = ((insn_word >> 9) & TEMPLATE_REGS_MASK);
2466   enum metag_unit au, ram_unit;
2467   unsigned int addr_reg_nums[2];
2468   const char *addr_reg_names[2];
2469   const char *post_op = "";
2470   const char *join_op = "";
2471   enum metag_unit data_unit = ((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0;
2472
2473   template[0] = lookup_dsp_name (tidx, UNIT_DT);
2474
2475   addr_reg_names[1] = "";
2476
2477   if (dspram)
2478     {
2479       ram_unit = (data_unit == UNIT_D0) ? UNIT_RAM_D0 : UNIT_RAM_D1;
2480       addr_reg_nums[0] = ((insn_word >> 19) & REG_MASK);
2481       addr_reg_names[0] = lookup_dspram_name (addr_reg_nums[0],
2482                                               ram_unit, load);
2483     }
2484   else
2485     {
2486       bfd_boolean im = (((insn_word >> 18) & 0x1) != 0);
2487
2488       au = (((insn_word >> 23) & 0x1) == 0) ? UNIT_A0 : UNIT_A1;
2489       addr_reg_nums[0] = ((insn_word >> 19) & DSP_REG_MASK);
2490
2491       addr_reg_names[0] = lookup_reg_name (au, addr_reg_nums[0]);
2492
2493       if (im)
2494         {
2495           unsigned int im_value = ((insn_word >> 14) & 0x3);
2496
2497           switch (im_value)
2498             {
2499             case 0x1:
2500               post_op = "++";
2501               break;
2502             case 0x3:
2503               post_op = "--";
2504               break;
2505             }
2506         }
2507       else
2508         {
2509           addr_reg_nums[1] = ((insn_word >> 14) & DSP_REG_MASK);
2510           addr_reg_names[1] = lookup_reg_name (au, addr_reg_nums[1]);
2511           join_op = "+";
2512           post_op = "++";
2513         }
2514     }
2515
2516   if (load)
2517     {
2518       len = snprintf (buf, len, " %s,[%s%s%s%s]", template[0], addr_reg_names[0],
2519                       join_op, addr_reg_names[1], post_op);
2520     }
2521   else
2522     {
2523       len = snprintf (buf, len, " [%s%s%s%s],%s", addr_reg_names[0], join_op,
2524                       addr_reg_names[1], post_op, template[0]);
2525     }
2526 }
2527
2528 /* Print a DSP ALU instruction.  */
2529 static void
2530 print_dalu (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
2531             const insn_template *template,
2532             disassemble_info *outf)
2533 {
2534   bfd_boolean is_dual = FALSE;
2535   unsigned int data_unit = (((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0);
2536   const char *reg_names[3];
2537   unsigned int reg_nums[3];
2538   bfd_boolean ac = ((insn_word >> 7) & 0x1);
2539   char buf[OPERAND_WIDTH];
2540   char prefix[DSP_PREFIX_WIDTH];
2541   size_t len;
2542   bfd_boolean is_mod = FALSE;
2543   bfd_boolean is_overflow = FALSE;
2544   unsigned int reg_brackets[3];
2545   bfd_boolean is_w_mx = FALSE;
2546   bfd_boolean is_b_mx = FALSE;
2547   bfd_boolean imm = FALSE;
2548   bfd_boolean is_quickrot64 = FALSE;
2549   bfd_boolean conditional = FALSE;
2550   const char *cc_flags = NULL;
2551   bfd_boolean is_unsigned = FALSE;
2552
2553   memset (reg_brackets, 0, sizeof (reg_brackets));
2554
2555   if (template->arg_type & DSP_ARGS_1)
2556     {
2557       bfd_boolean is_template = FALSE;
2558       const char *addr_reg = NULL;
2559       bfd_boolean qr = FALSE;
2560       bfd_boolean is_acc_add = FALSE;
2561       bfd_boolean is_acc_sub = FALSE;
2562       bfd_boolean is_acc_zero = FALSE;
2563       bfd_boolean is_split8 = (template->arg_type & DSP_ARGS_SPLIT8);
2564
2565       /* Read DU bit.  */
2566       data_unit = ((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0;
2567
2568       conditional = ((insn_word >> 24) & 0x4);
2569
2570       /* Templates can't be conditional.  */
2571       is_template = (((insn_word & 0x02000002) == 0x2) && !conditional);
2572
2573       if (is_split8)
2574         is_mod = (insn_word & 0x80);
2575
2576       if (template->arg_type & DSP_ARGS_QR)
2577         {
2578           if (!conditional)
2579             is_quickrot64 = ((insn_word >> 5) & 0x1);
2580         }
2581
2582       if (template->arg_type & DSP_ARGS_DACC)
2583         {
2584           is_mod = (insn_word & 0x8);
2585           is_unsigned = (insn_word & 0x40);
2586         }
2587
2588       if (is_template)
2589         {
2590           is_w_mx = (insn_word & 0x1);
2591           is_dual = ((insn_word >> 0x4) & 0x1);
2592
2593           /* De.r,Dx.r,De.r|ACe.r */
2594           if (template->arg_type & DSP_ARGS_ACC2)
2595             {
2596               is_mod = (insn_word & 0x8);
2597               is_overflow = (insn_word & 0x20);
2598             }
2599
2600           /* ACe.e,ACx.r,ACo.e? */
2601           if ((template->arg_type & DSP_ARGS_XACC) &&
2602               (((insn_word >> 6) & 0x5) == 0x5))
2603             {
2604               enum metag_unit ac_unit, ao_unit;
2605
2606               ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1;
2607
2608               if (ac_unit == UNIT_ACC_D0)
2609                 ao_unit = UNIT_ACC_D1;
2610               else
2611                 ao_unit = UNIT_ACC_D0;
2612
2613               reg_nums[1] = ((insn_word >> 19) & REG_MASK);
2614
2615               /* These are dummy arguments anyway so the register
2616                  number does not matter.  */
2617               reg_names[0] = lookup_dsp_name (16, ac_unit); /* ACe.0 */
2618               reg_names[1] = lookup_dsp_name (16, ac_unit); /* ACx.0 */
2619               reg_names[2] = lookup_dsp_name (16, ao_unit); /* ACo.0 */
2620             }
2621           else
2622             {
2623               /* De.r|ACe.r,Dx.r,De.r */
2624               if (template->arg_type & DSP_ARGS_DACC &&
2625                   ((insn_word & 0x84) != 0))
2626                 {
2627                   enum metag_unit ac_unit;
2628
2629                   ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1;
2630                   reg_names[0] = lookup_dsp_name (16, ac_unit);
2631
2632                   is_acc_zero = ((insn_word & 0x84) == 0x04);
2633                   is_acc_add = ((insn_word & 0x84) == 0x80);
2634                   is_acc_sub = ((insn_word & 0x84) == 0x84);
2635                 }
2636               else
2637                 reg_names[0] = lookup_any_reg_name (data_unit, 0, FALSE);
2638
2639               /* These are dummy arguments anyway so the register
2640                  number does not matter.  */
2641               reg_names[1] = lookup_any_reg_name (data_unit, 0, TRUE);
2642
2643               /* De.r,Dx.r,De.r|ACe.r */
2644               if ((template->arg_type & DSP_ARGS_ACC2) &&
2645                   ((insn_word & 0x80) == 0x80))
2646                 {
2647                   enum metag_unit ac_unit;
2648
2649                   ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1;
2650                   reg_names[2] = lookup_dsp_name (16, ac_unit);
2651                 }
2652               /* Detection of QUICKRoT and accumulator usage uses the
2653                  same bits. They are mutually exclusive.  */
2654               else if (ac && (template->arg_type & DSP_ARGS_ACC2))
2655                 {
2656                   reg_nums[2] = ((insn_word >> 9) & REG_MASK);
2657
2658                   if (data_unit == UNIT_D0)
2659                     reg_names[2] = lookup_dsp_name (reg_nums[2], UNIT_ACC_D0);
2660                   else
2661                     reg_names[2] = lookup_dsp_name (reg_nums[2], UNIT_ACC_D1);
2662                 }
2663               else
2664                 {
2665                   if ((template->arg_type & DSP_ARGS_QR) &&
2666                       ((insn_word & 0x40) == 0x40))
2667                     {
2668                       enum metag_unit aunit;
2669                       int reg_no;
2670
2671                       if (conditional)
2672                         reg_no = ((insn_word >> 5) & 0x1);
2673                       else
2674                         reg_no = ((insn_word >> 7) & 0x1);
2675
2676                       aunit = (data_unit == UNIT_D0) ? UNIT_A0 : UNIT_A1;
2677                       addr_reg = lookup_reg_name (aunit, reg_no + 2);
2678
2679                       qr = TRUE;
2680                     }
2681
2682                   reg_names[2] = lookup_any_reg_name (data_unit, 0, TRUE);
2683                 }
2684             }
2685
2686           if (qr)
2687             {
2688               len = snprintf (buf, OPERAND_WIDTH, "%s,%s,%s,%s",
2689                               reg_names[0], reg_names[1], reg_names[2],
2690                               addr_reg);
2691             }
2692           else
2693             {
2694               len = snprintf (buf, OPERAND_WIDTH, "%s,%s,%s%s%s",
2695                               reg_names[0], reg_names[1],
2696                               reg_brackets[2] ? "[" : "",
2697                               reg_names[2], reg_brackets[2] ? "]" : "");
2698             }
2699
2700           decode_template_definition (insn_word, buf + len,
2701                                       OPERAND_WIDTH - len);
2702         }
2703       else                      /* Not a template definiton.  */
2704         {
2705           reg_nums[0] = ((insn_word >> 19) & REG_MASK);
2706           reg_nums[1] = ((insn_word >> 14) & REG_MASK);
2707           reg_nums[2] = ((insn_word >> 9) & REG_MASK);
2708
2709           imm = (((insn_word >> 24) & 0x2) && (template->arg_type & DSP_ARGS_IMM));
2710
2711           if (imm)
2712             is_dual = (insn_word & 0x4);
2713           else if (!conditional)
2714             is_dual = (insn_word & 0x10);
2715           else
2716             cc_flags = lookup_scc_flags ((insn_word >> 1) & CC_MASK);
2717
2718           /* De.r,Dx.r,De.r|ACe.r */
2719           if (template->arg_type & DSP_ARGS_ACC2)
2720             {
2721               is_mod = (insn_word & 0x8);
2722               is_overflow = (insn_word & 0x20);
2723             }
2724
2725           if (template->arg_type & DSP_ARGS_SPLIT8)
2726             {
2727               is_overflow = (insn_word & 0x20);
2728             }
2729
2730           /* ACe.e,ACx.r,ACo.e? */
2731           if ((template->arg_type & DSP_ARGS_XACC) &&
2732               (((insn_word >> 6) & 0x5) == 0x5))
2733             {
2734               enum metag_unit ac_unit, ao_unit;
2735
2736               ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1;
2737
2738               if (ac_unit == UNIT_ACC_D0)
2739                 ao_unit = UNIT_ACC_D1;
2740               else
2741                 ao_unit = UNIT_ACC_D0;
2742
2743               reg_nums[1] = ((insn_word >> 19) & REG_MASK);
2744               reg_names[0] = lookup_dsp_name (reg_nums[1], ac_unit);
2745               reg_names[1] = lookup_dsp_name (reg_nums[1], ac_unit);
2746               reg_names[2] = lookup_dsp_name (reg_nums[1], ao_unit);
2747             }
2748           else
2749             {
2750               bfd_boolean o2r = (insn_word & 0x1);
2751
2752               /* De.r|ACe.r,Dx.r,De.r */
2753               if ((template->arg_type & DSP_ARGS_DACC) &&
2754                   ((insn_word & 0x84) != 0))
2755                 {
2756                   enum metag_unit ac_unit;
2757
2758                   ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1;
2759                   reg_names[0] = lookup_dsp_name (reg_nums[0], ac_unit);
2760
2761                   is_acc_zero = ((insn_word & 0x84) == 0x04);
2762                   is_acc_add = ((insn_word & 0x84) == 0x80);
2763                   is_acc_sub = ((insn_word & 0x84) == 0x84);
2764                 }
2765               else if (conditional)
2766                 {
2767                   reg_names[0] = lookup_reg_name (data_unit, reg_nums[0]);
2768                 }
2769               else
2770                 {
2771                   reg_names[0] = lookup_any_reg_name (data_unit,
2772                                                       reg_nums[0], FALSE);
2773                   if (reg_nums[0] > 15)
2774                     reg_brackets[0] = 1;
2775                 }
2776
2777               if (imm)
2778                 {
2779                   reg_names[1] = lookup_any_reg_name (data_unit, reg_nums[0], TRUE);
2780
2781                   if (reg_brackets[0])
2782                     reg_brackets[1] = 1;
2783                   }
2784               else
2785                 {
2786                   if (is_split8 && is_mod)
2787                     {
2788                       reg_names[1] = lookup_reg_name (data_unit, reg_nums[1]);
2789                     }
2790                   else
2791                   {
2792                     reg_names[1] = lookup_any_reg_name (data_unit, reg_nums[1], TRUE);
2793
2794                     if (reg_nums[1] > 15)
2795                       reg_brackets[1] = 1;
2796                   }
2797                 }
2798
2799               /* Detection of QUICKRoT and accumulator usage uses the
2800                  same bits. They are mutually exclusive.  */
2801               if (ac && (template->arg_type & DSP_ARGS_ACC2))
2802                 {
2803                   if (data_unit == UNIT_D0)
2804                     reg_names[2] = lookup_dsp_name (reg_nums[2], UNIT_ACC_D0);
2805                   else
2806                     reg_names[2] = lookup_dsp_name (reg_nums[2], UNIT_ACC_D1);
2807                 }
2808
2809               else
2810                 {
2811                   if ((template->arg_type & DSP_ARGS_QR) &&
2812                       ((insn_word & 0x40) == 0x40))
2813                     {
2814                       enum metag_unit aunit;
2815                       int reg_no;
2816
2817                       if (conditional)
2818                         reg_no = ((insn_word >> 5) & 0x1);
2819                       else
2820                         reg_no = ((insn_word >> 7) & 0x1);
2821
2822                       aunit = (data_unit == UNIT_D0) ? UNIT_A0 : UNIT_A1;
2823                       addr_reg = lookup_reg_name (aunit, reg_no + 2);
2824
2825                       qr = TRUE;
2826                     }
2827
2828                   if (o2r)
2829                     reg_names[2] = lookup_o2r (data_unit, reg_nums[2]);
2830                   else
2831                     {
2832                       /* Can't use a DSPRAM reg if both QD and L1 are
2833                          set on a QUICKRoT instruction or if we're a
2834                          split 8.  */
2835                       if (((template->arg_type & DSP_ARGS_QR)
2836                            && ((insn_word & 0x30) == 0x30 && !conditional)) ||
2837                           (is_split8 && is_mod))
2838                         reg_names[2] = lookup_reg_name (data_unit, reg_nums[2]);
2839                       else
2840                         {
2841                           reg_names[2] = lookup_any_reg_name (data_unit,
2842                                                               reg_nums[2], TRUE);
2843                           if (reg_nums[2] > 15)
2844                             reg_brackets[2] = 1;
2845                         }
2846                     }
2847                 }
2848             }
2849
2850           if (qr)
2851             {
2852               len = snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,%s%s%s,%s",
2853                               reg_brackets[0] ? "[" : "",
2854                               reg_names[0], reg_brackets[0] ? "]" : "",
2855                               reg_brackets[1] ? "[" : "",
2856                               reg_names[1], reg_brackets[1] ? "]" : "",
2857                               reg_brackets[2] ? "[" : "",
2858                               reg_names[2], reg_brackets[2] ? "]" : "",
2859                               addr_reg);
2860             }
2861           else
2862             {
2863               if (imm)
2864                 {
2865                   /* Conform to the embedded assembler's policy of
2866                      printing negative numbers as decimal and positive
2867                      as hex.  */
2868                   int value = ((insn_word >> 3) & IMM16_MASK);
2869
2870                   if ((value & 0x8000) || value == 0)
2871                     {
2872                       value = sign_extend (value, IMM16_BITS);
2873                       len = snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,#%d",
2874                                       reg_brackets[0] ? "[" : "",
2875                                       reg_names[0], reg_brackets[0] ? "]" : "",
2876                                       reg_brackets[1] ? "[" : "",
2877                                       reg_names[1], reg_brackets[1] ? "]" : "",
2878                                       value);
2879                     }
2880                   else
2881                     {
2882                       len = snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,#%#x",
2883                                       reg_brackets[0] ? "[" : "",
2884                                       reg_names[0], reg_brackets[0] ? "]" : "",
2885                                       reg_brackets[1] ? "[" : "",
2886                                       reg_names[1], reg_brackets[1] ? "]" : "",
2887                                       value);
2888                     }
2889                 }
2890               else
2891                 {
2892                   len = snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,%s%s%s",
2893                                   reg_brackets[0] ? "[" : "",
2894                                   reg_names[0], reg_brackets[0] ? "]" : "",
2895                                   reg_brackets[1] ? "[" : "", reg_names[1],
2896                                   reg_brackets[1] ? "]" : "",
2897                                   reg_brackets[2] ? "[" : "",
2898                                   reg_names[2], reg_brackets[2] ? "]" : "");
2899                 }
2900             }
2901         }
2902
2903       snprintf (prefix, DSP_PREFIX_WIDTH, "D%s%s%s%s%s%s%s%s%s%s%s%s",
2904                 cc_flags ? cc_flags : "",
2905                 is_dual ? "L" : "",
2906                 is_quickrot64 ? "Q" : "",
2907                 is_unsigned ? "U" : "",
2908                 is_mod ? "M" : "",
2909                 is_acc_zero ? "Z" : "",
2910                 is_acc_add ? "P" : "", is_acc_sub ? "N" : "",
2911                 is_overflow ? "O" : "",
2912                 is_w_mx ? "W" : "",
2913                 is_b_mx ? "B" : "",
2914                 is_template ? "T" : "");
2915     }
2916   else if (template->arg_type & DSP_ARGS_2) /* Group 2.  */
2917     {
2918       bfd_boolean is_template;
2919       bfd_boolean o2r = FALSE;
2920       int major = MAJOR_OPCODE (template->meta_opcode);
2921       bfd_boolean is_neg_or_mov = (major == OPC_ADD || major == OPC_SUB);
2922       bfd_boolean is_cmp_tst = ((major == OPC_CMP) &&
2923                                 ((insn_word & 0x0000002c) == 0));
2924       bfd_boolean is_fpu_mov = template->insn_type == INSN_DSP_FPU;
2925       bfd_boolean to_fpu = (template->meta_opcode >> 7) & 0x1;
2926
2927       if (major == OPC_9)
2928         imm = (insn_word & 0x2);
2929       else if (template->arg_type & DSP_ARGS_IMM)
2930         imm = ((insn_word >> 25) & 0x1);
2931
2932       is_template = (((insn_word & 0x02000002) == 0x2) &&
2933                      major != OPC_9);
2934
2935       if (imm)
2936         is_dual = ((insn_word >> 0x2) & 0x1);
2937       else
2938         is_dual = ((insn_word >> 0x4) & 0x1);
2939
2940       /* MOV and XSD[BW] do not have o2r.  */
2941       if (major != OPC_9 && major != OPC_MISC)
2942         o2r = (insn_word & 0x1);
2943
2944       if (is_neg_or_mov)
2945         {
2946           is_mod = (insn_word & 0x8);
2947           is_overflow = (insn_word & 0x20);
2948         }
2949
2950       /* XSD */
2951       if (major == OPC_MISC)
2952         data_unit = (insn_word & 0x1) ? UNIT_D1 : UNIT_D0;
2953       else
2954         data_unit = ((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0;
2955
2956       /* Check for NEG,MOV,ABS,FFB, etc.  */
2957       if (is_neg_or_mov || !is_cmp_tst || imm ||
2958           MAJOR_OPCODE (insn_word) == OPC_9 ||
2959           MAJOR_OPCODE (insn_word) == OPC_MISC)
2960         reg_nums[0] = ((insn_word >> 19) & REG_MASK);
2961       else
2962         reg_nums[0] = ((insn_word >> 14) & REG_MASK);
2963
2964       if (is_template)
2965         {
2966           is_w_mx = (insn_word & 0x1);
2967
2968           /* These are dummy arguments anyway so the register number
2969              does not matter.  */
2970           if (is_fpu_mov)
2971             {
2972               if (to_fpu)
2973                 {
2974                   reg_names[0] = lookup_reg_name (UNIT_FX, 0);
2975                   reg_names[1] = lookup_reg_name (data_unit, 0);
2976                 }
2977               else
2978                 {
2979                   reg_names[0] = lookup_reg_name (data_unit, 0);
2980                   reg_names[1] = lookup_reg_name (UNIT_FX, 0);
2981                 }
2982             }
2983           else
2984             {
2985               reg_names[0] = lookup_reg_name (data_unit, 0);
2986               reg_names[1] = lookup_reg_name (data_unit, 0);
2987             }
2988
2989           len = snprintf (buf, OPERAND_WIDTH, "%s,%s",
2990                           reg_names[0], reg_names[1]);
2991
2992           decode_template_definition (insn_word, buf + len,
2993                                       OPERAND_WIDTH - len);
2994         }
2995       else
2996         {
2997           if (imm)
2998             {
2999               /* Conform to the embedded assembler's policy of
3000                  printing negative numbers as decimal and positive as
3001                  hex.  */
3002               unsigned int value = ((insn_word >> 3) & IMM16_MASK);
3003
3004               if (major == OPC_9)
3005                 {
3006                   data_unit = (insn_word & 0x1) ? UNIT_D1 : UNIT_D0;
3007                   is_dual = (insn_word & 0x4);
3008
3009                   reg_names[0] = __lookup_dsp_name (reg_nums[0], data_unit);
3010                 }
3011               else
3012                 {
3013                   reg_names[0] = lookup_any_reg_name (data_unit, reg_nums[0], TRUE);
3014                   if (reg_nums[0] > 15)
3015                     reg_brackets[0] = 1;
3016                 }
3017
3018               if ((value & 0x8000) || value == 0)
3019                 {
3020                   value = sign_extend (value, IMM16_BITS);
3021                   snprintf (buf, OPERAND_WIDTH, "%s%s%s,#%d",
3022                             reg_brackets[0] ? "[" : "",
3023                             reg_names[0], reg_brackets[0] ? "]" : "",
3024                             value);
3025                 }
3026               else
3027                 {
3028                   snprintf (buf, OPERAND_WIDTH, "%s%s%s,#0x%x",
3029                             reg_brackets[0] ? "[" : "",
3030                             reg_names[0], reg_brackets[0] ? "]" : "",
3031                             value);
3032                 }
3033             }
3034           else
3035             {
3036               if (is_neg_or_mov || is_cmp_tst)
3037                 reg_nums[1] = ((insn_word >> 9) & REG_MASK);
3038               else
3039                 reg_nums[1] = ((insn_word >> 14) & REG_MASK);
3040
3041               if (major == OPC_9)
3042                 {
3043                   is_dual = (insn_word & 0x4);
3044                   data_unit = (insn_word & 0x1) ? UNIT_D1 : UNIT_D0;
3045
3046                   if (MINOR_OPCODE (template->meta_opcode) == 0x1)
3047                     reg_names[0] = __lookup_dsp_name (reg_nums[0], data_unit);
3048                   else
3049                     reg_names[0] = lookup_reg_name (data_unit, reg_nums[0]);
3050                 }
3051               else
3052                 {
3053                   unsigned int reg0_unit = data_unit;
3054
3055                   if (is_fpu_mov && to_fpu)
3056                     reg0_unit = UNIT_FX;
3057
3058                   reg_names[0] = lookup_any_reg_name (reg0_unit, reg_nums[0],
3059                                                       (!is_neg_or_mov && is_cmp_tst));
3060                   if (reg_nums[0] > 15)
3061                     reg_brackets[0] = 1;
3062                 }
3063
3064               if (o2r)
3065                 reg_names[1] = lookup_o2r (data_unit, reg_nums[1]);
3066               else
3067                 {
3068                   /* Check for accumulator argument.  */
3069                   if (is_neg_or_mov && ((insn_word & 0x80) == 0x80))
3070                     {
3071                       if (data_unit == UNIT_D0)
3072                         reg_names[1] = lookup_dsp_name (reg_nums[1], UNIT_ACC_D0);
3073                       else
3074                         reg_names[1] = lookup_dsp_name (reg_nums[1], UNIT_ACC_D1);
3075                     }
3076                   else
3077                     {
3078                       if (major == OPC_9)
3079                         {
3080                           if (MINOR_OPCODE (template->meta_opcode) == 0x1)
3081                             {
3082                               reg_names[1] = lookup_reg_name (data_unit, reg_nums[1]);
3083                             }
3084                           else
3085                             {
3086                               enum metag_unit u;
3087
3088                               u = (insn_word & 0x1) ? UNIT_RAM_D1 : UNIT_RAM_D0;
3089                               reg_names[1] = lookup_dsp_name (reg_nums[1], u);
3090                             }
3091                         }
3092                       else
3093                         {
3094                           reg_names[1] = lookup_any_reg_name (data_unit,
3095                                                               reg_nums[1], TRUE);
3096                           if (reg_nums[1] > 15)
3097                             reg_brackets[1] = 1;
3098                         }
3099                     }
3100                 }
3101
3102               snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s",
3103                         reg_brackets[0] ? "[" : "", reg_names[0],
3104                         reg_brackets[0] ? "]" : "",
3105                         reg_brackets[1] ? "[" : "", reg_names[1],
3106                         reg_brackets[1] ? "]" : "");
3107             }
3108         }
3109
3110       snprintf (prefix, DSP_PREFIX_WIDTH, "D%s%s%s%s%s%s",
3111                 is_fpu_mov ? "F" : "",
3112                 is_dual ? "L" : "",
3113                 is_mod ? "M" : "", is_overflow ? "O" : "",
3114                 is_w_mx ? "W" : "",
3115                 is_template ? "T" : "");
3116     }
3117   else                          /* Group 3. */
3118     {
3119       /* If both the C and CA bits are set, then the Rd register can
3120          be in any unit. Figure out which unit from the Ud field.  */
3121       bfd_boolean all_units = (((insn_word) & 0x04000020) == 0x04000020);
3122       enum metag_unit ud_unit = ((insn_word >> 1) & UNIT_MASK);
3123       enum metag_unit ram_unit, acc_unit;
3124       bfd_boolean round = FALSE;
3125       bfd_boolean clamp9 = FALSE;
3126       bfd_boolean clamp8 = FALSE;
3127       bfd_boolean is_template = ((insn_word & 0x04000002) == 0x2);
3128
3129       imm = ((insn_word >> 25) & 0x1);
3130       ac = (insn_word & 0x1);
3131
3132       conditional = (MINOR_OPCODE (insn_word) & 0x4);
3133
3134       /* Check for conditional and not Condition Always.  */
3135       if (conditional && !(insn_word & 0x20))
3136         cc_flags = lookup_scc_flags ((insn_word >> 1) & CC_MASK);
3137       else if (!(conditional && (insn_word & 0x20)))
3138         is_dual = ((insn_word >> 0x4) & 0x1);
3139
3140       /* Conditional instructions don't have the L1 or RSPP fields.  */
3141       if ((insn_word & 0x04000000) == 0)
3142         {
3143           round = (((insn_word >> 2) & 0x3) == 0x1);
3144           clamp9 = (((insn_word >> 2) & 0x3) == 0x2);
3145           clamp8 = (((insn_word >> 2) & 0x3) == 0x3);
3146         }
3147
3148       /* Read DU bit.  */
3149       data_unit = ((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0;
3150       reg_nums[0] = ((insn_word >> 19) & REG_MASK);
3151       reg_nums[1] = ((insn_word >> 14) & REG_MASK);
3152
3153       ram_unit = (data_unit == UNIT_D0) ? UNIT_RAM_D0 : UNIT_RAM_D1;
3154       acc_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1;
3155
3156       if (all_units)
3157         reg_names[0] = lookup_reg_name (ud_unit, reg_nums[0]);
3158       else
3159         {
3160           if (conditional)
3161             reg_names[0] = lookup_reg_name (data_unit, reg_nums[0]);
3162           else
3163             {
3164               reg_names[0] = lookup_any_reg_name (data_unit, reg_nums[0], FALSE);
3165               if (reg_nums[0] > 15)
3166                 reg_brackets[0] = 1;
3167             }
3168         }
3169
3170       if (ac)
3171         {
3172           reg_names[1] = lookup_dsp_name (reg_nums[1], acc_unit);
3173         }
3174       else
3175         {
3176           reg_names[1] = lookup_any_reg_name (data_unit, reg_nums[1], TRUE);
3177           if (reg_nums[1] > 15)
3178             reg_brackets[1] = 1;
3179         }
3180
3181       if (imm)
3182         {
3183           snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,#%#x",
3184                     reg_brackets[0] ? "[" : "",
3185                     reg_names[0], reg_brackets[0] ? "]" : "",
3186                     reg_brackets[1] ? "[" : "",
3187                     reg_names[1], reg_brackets[1] ? "]" : "",
3188                     ((insn_word >> 9) & IMM5_MASK));
3189         }
3190       else
3191         {
3192           reg_nums[2] = ((insn_word >> 9) & REG_MASK);
3193
3194           reg_names[2] = lookup_any_reg_name (data_unit, reg_nums[2], TRUE);
3195
3196           if (reg_nums[2] > 15)
3197                   reg_brackets[2] = 1;
3198
3199           if (is_template)
3200             {
3201               bfd_boolean load = ((insn_word >> 13) & 0x1);
3202               bfd_boolean dspram = (((insn_word >> 17) & 0x3) == 0x3);
3203               const char *tname[1];
3204               unsigned int tidx = ((insn_word >> 9) & TEMPLATE_REGS_MASK);
3205               enum metag_unit au;
3206               unsigned int addr_reg_nums[2];
3207               const char *addr_reg_names[2];
3208               const char *post_op = "";
3209               const char *join_op = "";
3210
3211               is_w_mx = ((insn_word >> 5) & 0x1);
3212
3213               tname[0] = lookup_dsp_name (tidx, UNIT_DT);
3214
3215               /* These are dummy arguments anyway */
3216               reg_names[0] = lookup_reg_name (data_unit, 0);
3217               if (ac)
3218                 reg_names[1] = lookup_dsp_name (16, acc_unit);
3219               else
3220                 reg_names[1] = lookup_reg_name (data_unit, 0);
3221               reg_names[2] = lookup_reg_name (data_unit, 0);
3222
3223               addr_reg_names[1] = "";
3224
3225               if (dspram)
3226                 {
3227                   ram_unit = (data_unit == UNIT_D0) ? UNIT_RAM_D0 : UNIT_RAM_D1;
3228                   addr_reg_nums[0] = ((insn_word >> 19) & REG_MASK);
3229                   addr_reg_names[0] = lookup_dspram_name (addr_reg_nums[0],
3230                                                           ram_unit, load);
3231                 }
3232               else
3233                 {
3234                   bfd_boolean im = (((insn_word >> 18) & 0x1) != 0);
3235
3236                   au = (((insn_word >> 23) & 0x1) == 0) ? UNIT_A0 : UNIT_A1;
3237                   addr_reg_nums[0] = ((insn_word >> 19) & DSP_REG_MASK);
3238
3239                   addr_reg_names[0] = lookup_reg_name (au, addr_reg_nums[0]);
3240
3241                   if (im)
3242                     {
3243                       unsigned int im_value = ((insn_word >> 14) & 0x3);
3244
3245                       switch (im_value)
3246                         {
3247                         case 0x1:
3248                           post_op = "++";
3249                           break;
3250                         case 0x3:
3251                           post_op = "--";
3252                           break;
3253                         }
3254                     }
3255                   else
3256                     {
3257                       addr_reg_nums[1] = ((insn_word >> 14) & DSP_REG_MASK);
3258                       addr_reg_names[1] = lookup_reg_name (au, addr_reg_nums[1]);
3259                       join_op = "+";
3260                       post_op = "++";
3261                     }
3262                 }
3263
3264               if (load)
3265                 {
3266                   snprintf (buf, OPERAND_WIDTH, "%s,%s,%s %s,[%s%s%s%s]",
3267                             reg_names[0], reg_names[1], reg_names[2],
3268                             tname[0], addr_reg_names[0], join_op,
3269                             addr_reg_names[1], post_op);
3270                 }
3271               else
3272                 {
3273                   snprintf (buf, OPERAND_WIDTH, "%s,%s,%s [%s%s%s%s],%s",
3274                             reg_names[0], reg_names[1], reg_names[2],
3275                             addr_reg_names[0], join_op, addr_reg_names[1],
3276                             post_op, tname[0]);
3277                 }
3278             }
3279           else
3280             {
3281               snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,%s%s%s",
3282                         reg_brackets[0] ? "[" : "",
3283                         reg_names[0], reg_brackets[0] ? "]" : "",
3284                         reg_brackets[1] ? "[" : "",
3285                         reg_names[1], reg_brackets[1] ? "]" : "",
3286                         reg_brackets[2] ? "[" : "",
3287                         reg_names[2], reg_brackets[2] ? "]" : "");
3288             }
3289         }
3290
3291       snprintf (prefix, DSP_PREFIX_WIDTH, "D%s%s%s%s%s%s%s",
3292                 cc_flags ? cc_flags : "",
3293                 is_dual ? "L" : "", clamp9 ? "G" : "",
3294                 clamp8 ? "B" : "", round ? "R" : "",
3295                 is_w_mx ? "W" : "",
3296                 is_template ? "T" : "");
3297     }
3298
3299   print_insn (outf, prefix, template->name, buf);
3300
3301 }
3302
3303 typedef void (*insn_printer)(unsigned int, bfd_vma, const insn_template *,
3304                              disassemble_info *);
3305
3306 /* Printer table.  */
3307 static const insn_printer insn_printers[ENC_MAX] =
3308   {
3309     [ENC_NONE] = print_none,
3310     [ENC_MOV_U2U] = print_mov_u2u,
3311     [ENC_MOV_PORT] = print_mov_port,
3312     [ENC_MMOV] = print_mmov,
3313     [ENC_MDRD] = print_mdrd,
3314     [ENC_MOVL_TTREC] = print_movl_ttrec,
3315     [ENC_GET_SET] = print_get_set,
3316     [ENC_GET_SET_EXT] = print_get_set_ext,
3317     [ENC_MGET_MSET] = print_mget_mset,
3318     [ENC_COND_SET] = print_cond_set,
3319     [ENC_XFR] = print_xfr,
3320     [ENC_MOV_CT] = print_mov_ct,
3321     [ENC_SWAP] = print_swap,
3322     [ENC_JUMP] = print_jump,
3323     [ENC_CALLR] = print_callr,
3324     [ENC_ALU] = print_alu,
3325     [ENC_SHIFT] = print_shift,
3326     [ENC_MIN_MAX] = print_min_max,
3327     [ENC_BITOP] = print_bitop,
3328     [ENC_CMP] = print_cmp,
3329     [ENC_BRANCH] = print_branch,
3330     [ENC_KICK] = print_mov_u2u,
3331     [ENC_SWITCH] = print_switch,
3332     [ENC_CACHER] = print_cacher,
3333     [ENC_CACHEW] = print_cachew,
3334     [ENC_ICACHE] = print_icache,
3335     [ENC_LNKGET] = print_lnkget,
3336     [ENC_FMOV] = print_fmov,
3337     [ENC_FMMOV] = print_fmmov,
3338     [ENC_FMOV_DATA] = print_fmov_data,
3339     [ENC_FMOV_I] = print_fmov_i,
3340     [ENC_FPACK] = print_fpack,
3341     [ENC_FSWAP] = print_fswap,
3342     [ENC_FCMP] = print_fcmp,
3343     [ENC_FMINMAX] = print_fminmax,
3344     [ENC_FCONV] = print_fconv,
3345     [ENC_FCONVX] = print_fconvx,
3346     [ENC_FBARITH] = print_fbarith,
3347     [ENC_FEARITH] = print_fearith,
3348     [ENC_FREC] = print_frec,
3349     [ENC_FSIMD] = print_fsimd,
3350     [ENC_FGET_SET_ACF] = print_fget_set_acf,
3351     [ENC_DGET_SET] = print_dget_set,
3352     [ENC_DTEMPLATE] = print_dtemplate,
3353     [ENC_DALU] = print_dalu,
3354   };
3355
3356 /* Entry point for instruction printing.  */
3357 int
3358 print_insn_metag (bfd_vma pc, disassemble_info *outf)
3359 {
3360   bfd_byte buf[4];
3361   unsigned int insn_word;
3362   size_t i;
3363   outf->bytes_per_chunk = 4;
3364
3365   (*outf->read_memory_func) (pc & ~0x03, buf, 4, outf);
3366   insn_word = bfd_getl32 (buf);
3367
3368   for (i = 0; i < sizeof(metag_optab)/sizeof(metag_optab[0]); i++)
3369     {
3370       const insn_template *template = &metag_optab[i];
3371
3372       if ((insn_word & template->meta_mask) == template->meta_opcode)
3373         {
3374           enum insn_encoding encoding = template->encoding;
3375           insn_printer printer = insn_printers[encoding];
3376
3377           if (printer)
3378             printer (insn_word, pc, template, outf);
3379
3380           return 4;
3381         }
3382     }
3383
3384   return 4;
3385 }