Replace "the the" with "the"
[external/binutils.git] / opcodes / metag-dis.c
1 /* Disassemble Imagination Technologies Meta instructions.
2    Copyright (C) 2013-2019 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 "disassemble.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   /* We used to have buf[OPERAND_WIDTH] here, but gcc v8 complains
1766      about the snprintf()s below possibly truncating the output.
1767      (There is no way to tell gcc that this truncation is intentional).
1768      So now we use an extra wide buffer.  */
1769   char buf[OPERAND_WIDTH * 2];
1770   char data_buf[REG_WIDTH];
1771   char fpu_buf[REG_WIDTH];
1772   bfd_boolean to_fpu = MAJOR_OPCODE (insn_word) == OPC_GET;
1773   bfd_boolean is_mmovl = MINOR_OPCODE (insn_word) & 0x1;
1774   unsigned int rmask = (insn_word >> 7) & RMASK_MASK;
1775   unsigned int fpu_no, data_no, data_unit;
1776
1777   data_no = (insn_word >> 19) & REG_MASK;
1778   fpu_no = (insn_word >> 14) & REG_MASK;
1779
1780   if (insn_word & 0x1)
1781     data_unit = UNIT_D1;
1782   else
1783     data_unit = UNIT_D0;
1784
1785   lookup_reg_list (data_buf, REG_WIDTH, data_unit, data_no, rmask, FALSE);
1786   lookup_reg_list (fpu_buf, REG_WIDTH, UNIT_FX, fpu_no,
1787                    convert_fx_rmask (rmask), is_mmovl);
1788
1789   if (to_fpu)
1790     snprintf (buf, sizeof buf, "%s,%s", fpu_buf, data_buf);
1791   else
1792     snprintf (buf, sizeof buf, "%s,%s", data_buf, fpu_buf);
1793
1794   print_insn (outf, "F", template->name, buf);
1795 }
1796
1797 /* Print an FPU data unit MOV instruction.  */
1798 static void
1799 print_fmov_data (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1800                  const insn_template *template,
1801                  disassemble_info *outf)
1802 {
1803   char buf[OPERAND_WIDTH];
1804   unsigned int src_no, dest_no;
1805   unsigned int to_fpu = ((insn_word >> 7) & 0x1);
1806   unsigned int unit_bit = (insn_word >> 24) & 0x1;
1807   enum metag_unit base_unit;
1808   const char *dest_reg;
1809   const char *src_reg;
1810
1811   dest_no = (insn_word >> 19) & REG_MASK;
1812   src_no = (insn_word >> 9) & REG_MASK;
1813
1814   if (unit_bit)
1815     base_unit = UNIT_D1;
1816   else
1817     base_unit = UNIT_D0;
1818
1819   if (to_fpu)
1820     {
1821       dest_reg = lookup_reg_name (UNIT_FX, dest_no);
1822       src_reg = lookup_reg_name (base_unit, src_no);
1823     }
1824   else
1825     {
1826       dest_reg = lookup_reg_name (base_unit, dest_no);
1827       src_reg = lookup_reg_name (UNIT_FX, src_no);
1828     }
1829
1830   snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
1831
1832   print_insn (outf, "F", template->name, buf);
1833 }
1834
1835 /* Print an FPU MOV immediate instruction.  */
1836 static void
1837 print_fmov_i (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1838               const insn_template *template,
1839               disassemble_info *outf)
1840 {
1841   char buf[OPERAND_WIDTH];
1842   unsigned int dest_no;
1843   unsigned int p = (insn_word >> 2) & 0x1;
1844   unsigned int d = (insn_word >> 1) & 0x1;
1845   const char *dest_reg;
1846   unsigned int value = (insn_word >> 3) & IMM16_MASK;
1847
1848   dest_no = (insn_word >> 19) & REG_MASK;
1849
1850   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
1851
1852   snprintf (buf, OPERAND_WIDTH, "%s,#%#x", dest_reg, value);
1853
1854   if (p)
1855     print_insn (outf, "FL", template->name, buf);
1856   else if (d)
1857     print_insn (outf, "FD", template->name, buf);
1858   else
1859     print_insn (outf, "F", template->name, buf);
1860 }
1861
1862 /* Print an FPU PACK instruction.  */
1863 static void
1864 print_fpack (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1865              const insn_template *template,
1866              disassemble_info *outf)
1867 {
1868   char buf[OPERAND_WIDTH];
1869   unsigned int src1_no, src2_no, dest_no;
1870   const char *dest_reg;
1871   const char *src1_reg;
1872   const char *src2_reg;
1873
1874   dest_no = (insn_word >> 19) & REG_MASK;
1875   src1_no = (insn_word >> 14) & REG_MASK;
1876   src2_no = (insn_word >> 9) & REG_MASK;
1877
1878   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
1879   src1_reg = lookup_reg_name (UNIT_FX, src1_no);
1880   src2_reg = lookup_reg_name (UNIT_FX, src2_no);
1881
1882   snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg);
1883
1884   print_insn (outf, "F", template->name, buf);
1885 }
1886
1887 /* Print an FPU SWAP instruction.  */
1888 static void
1889 print_fswap (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1890              const insn_template *template,
1891              disassemble_info *outf)
1892 {
1893   char buf[OPERAND_WIDTH];
1894   unsigned int src_no, dest_no;
1895   const char *dest_reg;
1896   const char *src_reg;
1897
1898   dest_no = (insn_word >> 19) & REG_MASK;
1899   src_no = (insn_word >> 14) & REG_MASK;
1900
1901   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
1902   src_reg = lookup_reg_name (UNIT_FX, src_no);
1903
1904   snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
1905
1906   print_insn (outf, "FL", template->name, buf);
1907 }
1908
1909 /* Print an FPU CMP instruction.  */
1910 static void
1911 print_fcmp (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1912             const insn_template *template,
1913             disassemble_info *outf)
1914 {
1915   char buf[OPERAND_WIDTH];
1916   char prefix_buf[10];
1917   unsigned int src_no, dest_no;
1918   unsigned int a = (insn_word >> 19) & 0x1;
1919   unsigned int z = (insn_word >> 8) & 0x1;
1920   unsigned int p = (insn_word >> 6) & 0x1;
1921   unsigned int d = (insn_word >> 5) & 0x1;
1922   unsigned int q = (insn_word >> 7) & 0x1;
1923   unsigned int cc = (insn_word >> 1) & CC_MASK;
1924   bfd_boolean show_cond = cc != COND_A && cc != COND_NV;
1925   const char *dest_reg;
1926   const char *src_reg;
1927   const char *cc_flags;
1928
1929   dest_no = (insn_word >> 14) & REG_MASK;
1930   src_no = (insn_word >> 9) & REG_MASK;
1931
1932   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
1933   src_reg = lookup_reg_name (UNIT_FX, src_no);
1934
1935   cc_flags = lookup_fpu_scc_flags (cc);
1936
1937   if (z)
1938     snprintf (buf, OPERAND_WIDTH, "%s,#0", dest_reg);
1939   else
1940     snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
1941
1942   snprintf (prefix_buf, 10, "F%s%s%s%s%s", p ? "L" : "",
1943             d ? "D" : "", a ? "A" : "", q ? "Q" : "",
1944             show_cond ? cc_flags : "");
1945
1946   print_insn (outf, prefix_buf, template->name, buf);
1947 }
1948
1949 /* Print an FPU MIN or MAX instruction.  */
1950 static void
1951 print_fminmax (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1952                const insn_template *template,
1953                disassemble_info *outf)
1954 {
1955   char buf[OPERAND_WIDTH];
1956   char prefix_buf[10];
1957   unsigned int p = (insn_word >> 6) & 0x1;
1958   unsigned int d = (insn_word >> 5) & 0x1;
1959   unsigned int src1_no, src2_no, dest_no;
1960   unsigned int cc = (insn_word >> 1) & CC_MASK;
1961   bfd_boolean show_cond = cc != COND_A && cc != COND_NV;
1962   const char *dest_reg;
1963   const char *src1_reg;
1964   const char *src2_reg;
1965   const char *cc_flags;
1966
1967   dest_no = (insn_word >> 19) & REG_MASK;
1968   src1_no = (insn_word >> 14) & REG_MASK;
1969   src2_no = (insn_word >> 9) & REG_MASK;
1970
1971   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
1972   src1_reg = lookup_reg_name (UNIT_FX, src1_no);
1973   src2_reg = lookup_reg_name (UNIT_FX, src2_no);
1974
1975   cc_flags = lookup_fpu_scc_flags (cc);
1976
1977   snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg);
1978
1979   snprintf (prefix_buf, 10, "F%s%s%s", p ? "L" : "",
1980             d ? "D" : "", show_cond ? cc_flags : "");
1981
1982   print_insn (outf, prefix_buf, template->name, buf);
1983 }
1984
1985 /* Print an FPU data conversion instruction.  */
1986 static void
1987 print_fconv (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
1988              const insn_template *template,
1989              disassemble_info *outf)
1990 {
1991   char buf[OPERAND_WIDTH];
1992   char prefix_buf[10];
1993   unsigned int p = (insn_word >> 6) & 0x1;
1994   unsigned int z = (insn_word >> 12) & 0x1;
1995   unsigned int src_no, dest_no;
1996   unsigned int cc = (insn_word >> 1) & CC_MASK;
1997   bfd_boolean show_cond = cc != COND_A && cc != COND_NV;
1998   const char *dest_reg;
1999   const char *src_reg;
2000   const char *cc_flags;
2001
2002   dest_no = (insn_word >> 19) & REG_MASK;
2003   src_no = (insn_word >> 14) & REG_MASK;
2004
2005   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
2006   src_reg = lookup_reg_name (UNIT_FX, src_no);
2007
2008   cc_flags = lookup_fpu_scc_flags (cc);
2009
2010   snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
2011
2012   snprintf (prefix_buf, 10, "F%s%s%s", p ? "L" : "",
2013             z ? "Z" : "", show_cond ? cc_flags : "");
2014
2015   print_insn (outf, prefix_buf, template->name, buf);
2016 }
2017
2018 /* Print an FPU extended data conversion instruction.  */
2019 static void
2020 print_fconvx (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
2021               const insn_template *template,
2022               disassemble_info *outf)
2023 {
2024   char buf[OPERAND_WIDTH];
2025   char prefix_buf[10];
2026   unsigned int p = (insn_word >> 6) & 0x1;
2027   unsigned int xl = (insn_word >> 7) & 0x1;
2028   unsigned int src_no, dest_no, fraction_bits;
2029   unsigned int cc = (insn_word >> 1) & CC_MASK;
2030   bfd_boolean show_cond = cc != COND_A && cc != COND_NV;
2031   const char *dest_reg;
2032   const char *src_reg;
2033   const char *cc_flags;
2034
2035   dest_no = (insn_word >> 19) & REG_MASK;
2036   src_no = (insn_word >> 14) & REG_MASK;
2037
2038   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
2039   src_reg = lookup_reg_name (UNIT_FX, src_no);
2040
2041   cc_flags = lookup_fpu_scc_flags (cc);
2042
2043   if (xl)
2044     fraction_bits = (insn_word >> 8) & IMM6_MASK;
2045   else
2046     fraction_bits = (insn_word >> 9) & IMM5_MASK;
2047
2048   snprintf (buf, OPERAND_WIDTH, "%s,%s,#%#x", dest_reg, src_reg,
2049             fraction_bits);
2050
2051   snprintf (prefix_buf, 10, "F%s%s", p ? "L" : "",
2052             show_cond ? cc_flags : "");
2053
2054   print_insn (outf, prefix_buf, template->name, buf);
2055 }
2056
2057 /* Print an FPU basic arithmetic instruction.  */
2058 static void
2059 print_fbarith (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
2060                const insn_template *template,
2061                disassemble_info *outf)
2062 {
2063   char buf[OPERAND_WIDTH];
2064   char prefix_buf[10];
2065   unsigned int n = (insn_word >> 7) & 0x1;
2066   unsigned int p = (insn_word >> 6) & 0x1;
2067   unsigned int d = (insn_word >> 5) & 0x1;
2068   unsigned int src1_no, src2_no, dest_no;
2069   unsigned int cc = (insn_word >> 1) & CC_MASK;
2070   bfd_boolean show_cond = cc != COND_A && cc != COND_NV;
2071   const char *dest_reg;
2072   const char *src1_reg;
2073   const char *src2_reg;
2074   const char *cc_flags;
2075
2076   dest_no = (insn_word >> 19) & REG_MASK;
2077   src1_no = (insn_word >> 14) & REG_MASK;
2078   src2_no = (insn_word >> 9) & REG_MASK;
2079
2080   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
2081   src1_reg = lookup_reg_name (UNIT_FX, src1_no);
2082   src2_reg = lookup_reg_name (UNIT_FX, src2_no);
2083
2084   cc_flags = lookup_fpu_scc_flags (cc);
2085
2086   snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg);
2087
2088   snprintf (prefix_buf, 10, "F%s%s%s%s", p ? "L" : "",
2089             d ? "D" : "", n ? "I" : "", show_cond ? cc_flags : "");
2090
2091   print_insn (outf, prefix_buf, template->name, buf);
2092 }
2093
2094 /* Print an FPU extended arithmetic instruction.  */
2095 static void
2096 print_fearith (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
2097                const insn_template *template,
2098                disassemble_info *outf)
2099 {
2100   char buf[OPERAND_WIDTH];
2101   char prefix_buf[10];
2102   bfd_boolean is_muz = (MINOR_OPCODE (insn_word) == 0x6 &&
2103                         ((insn_word >> 4) & 0x1));
2104   bfd_boolean is_mac = (MINOR_OPCODE (insn_word) == 0x6 &&
2105                         (insn_word & 0x1f) == 0);
2106   bfd_boolean is_maw = (MINOR_OPCODE (insn_word) == 0x6 &&
2107                         ((insn_word >> 3) & 0x1));
2108   unsigned int o3o = insn_word & 0x1;
2109   unsigned int q = is_muz && ((insn_word >> 1) & 0x1);
2110   unsigned int n = (insn_word >> 7) & 0x1;
2111   unsigned int p = (insn_word >> 6) & 0x1;
2112   unsigned int d = (insn_word >> 5) & 0x1;
2113   unsigned int cc = (insn_word >> 1) & CC_MASK;
2114   bfd_boolean show_cond = (MINOR_OPCODE (insn_word) == 0x5 && cc != COND_A &&
2115                            cc != COND_NV);
2116   unsigned int src1_no, src2_no, dest_no;
2117   const char *dest_reg;
2118   const char *src1_reg;
2119   const char *src2_reg;
2120   const char *cc_flags;
2121
2122   dest_no = (insn_word >> 19) & REG_MASK;
2123   src1_no = (insn_word >> 14) & REG_MASK;
2124   src2_no = (insn_word >> 9) & REG_MASK;
2125
2126   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
2127   src1_reg = lookup_reg_name (UNIT_FX, src1_no);
2128   src2_reg = lookup_reg_name (UNIT_FX, src2_no);
2129
2130   cc_flags = lookup_fpu_scc_flags (cc);
2131
2132   if (is_mac)
2133     snprintf (buf, OPERAND_WIDTH, "ACF.0,%s,%s", src1_reg, src2_reg);
2134   else if (o3o && is_maw)
2135     snprintf (buf, OPERAND_WIDTH, "%s,%s", src1_reg, src2_reg);
2136   else
2137     snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg);
2138
2139   snprintf (prefix_buf, 10, "F%s%s%s%s%s", p ? "L" : "",
2140             d ? "D" : "", n ? "I" : "", q ? "Q" : "",
2141             show_cond ? cc_flags : "");
2142
2143   print_insn (outf, prefix_buf, template->name, buf);
2144 }
2145
2146 /* Print an FPU RCP or RSQ instruction.  */
2147 static void
2148 print_frec (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
2149             const insn_template *template,
2150             disassemble_info *outf)
2151 {
2152   char buf[OPERAND_WIDTH];
2153   char prefix_buf[10];
2154   unsigned int z = (insn_word >> 10) & 0x1;
2155   unsigned int q = (insn_word >> 9) & 0x1;
2156   unsigned int n = (insn_word >> 7) & 0x1;
2157   unsigned int p = (insn_word >> 6) & 0x1;
2158   unsigned int d = (insn_word >> 5) & 0x1;
2159   unsigned int src_no, dest_no;
2160   const char *dest_reg;
2161   const char *src_reg;
2162
2163   dest_no = (insn_word >> 19) & REG_MASK;
2164   src_no = (insn_word >> 14) & REG_MASK;
2165
2166   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
2167   src_reg = lookup_reg_name (UNIT_FX, src_no);
2168
2169   snprintf (buf, OPERAND_WIDTH, "%s,%s", dest_reg, src_reg);
2170
2171   snprintf (prefix_buf, 10, "F%s%s%s%s%s", p ? "L" : "",
2172             d ? "D" : "", n ? "I" : "", q ? "Q" : "", z ? "Z" : "");
2173
2174   print_insn (outf, prefix_buf, template->name, buf);
2175 }
2176
2177 static void
2178 print_fsimd (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
2179              const insn_template *template,
2180              disassemble_info *outf)
2181 {
2182   char buf[OPERAND_WIDTH];
2183   unsigned int n = (insn_word >> 7) & 0x1;
2184   unsigned int src1_no, src2_no, dest_no;
2185   const char *dest_reg;
2186   const char *src1_reg;
2187   const char *src2_reg;
2188
2189   dest_no = (insn_word >> 19) & REG_MASK;
2190   src1_no = (insn_word >> 14) & REG_MASK;
2191   src2_no = (insn_word >> 9) & REG_MASK;
2192
2193   dest_reg = lookup_reg_name (UNIT_FX, dest_no);
2194   src1_reg = lookup_reg_name (UNIT_FX, src1_no);
2195   src2_reg = lookup_reg_name (UNIT_FX, src2_no);
2196
2197   snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", dest_reg, src1_reg, src2_reg);
2198
2199   if (n)
2200     print_insn (outf, "FLI", template->name, buf);
2201   else
2202     print_insn (outf, "FL", template->name, buf);
2203 }
2204
2205 /* Print an FPU accumulator GET or SET instruction.  */
2206 static void
2207 print_fget_set_acf (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
2208                     const insn_template *template,
2209                     disassemble_info *outf)
2210 {
2211   bfd_boolean is_get = MAJOR_OPCODE (template->meta_opcode) == OPC_GET;
2212   char buf[OPERAND_WIDTH];
2213   char addr_buf[ADDR_WIDTH];
2214   unsigned int part;
2215   const char *reg_name;
2216
2217   part = (insn_word >> 19) & ACF_PART_MASK;
2218
2219   reg_name = lookup_acf_name (part);
2220
2221   mget_mset_addr_str (addr_buf, ADDR_WIDTH, insn_word);
2222
2223   if (is_get)
2224     {
2225       snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_name, addr_buf);
2226     }
2227   else
2228     {
2229       snprintf (buf, OPERAND_WIDTH, "%s,%s", addr_buf, reg_name);
2230     }
2231   print_insn (outf, "F", template->name, buf);
2232 }
2233
2234 /* Return the name of the DSP register or accumulator for NUM and UNIT.  */
2235 static const char *
2236 __lookup_dsp_name (unsigned int num, unsigned int unit)
2237 {
2238   size_t i;
2239
2240   for (i = 0; i < sizeof(metag_dsp_regtab)/sizeof(metag_dsp_regtab[0]); i++)
2241     {
2242       const metag_reg *reg = &metag_dsp_regtab[i];
2243
2244       if (reg->no == num)
2245         {
2246           if ((reg->unit == UNIT_RAM_D0 || reg->unit == UNIT_ACC_D0) &&
2247               unit == UNIT_D0)
2248             return reg->name;
2249
2250           if ((reg->unit == UNIT_RAM_D1 || reg->unit == UNIT_ACC_D1) &&
2251               unit == UNIT_D1)
2252             return reg->name;
2253         }
2254     }
2255   return "?.?";
2256 }
2257
2258 /* Return the name of the DSP register for NUM and UNIT.  */
2259 static const char *
2260 lookup_dsp_name (unsigned int num, unsigned int unit)
2261 {
2262   size_t i;
2263
2264   for (i = 0; i < sizeof(metag_dsp_regtab)/sizeof(metag_dsp_regtab[0]); i++)
2265     {
2266       const metag_reg *reg = &metag_dsp_regtab[i];
2267
2268       if (reg->no == num && reg->unit == unit)
2269         return reg->name;
2270     }
2271   return "?.?";
2272 }
2273
2274 /* Return the name of the DSP RAM register for NUM and UNIT.  */
2275 static const char *
2276 lookup_dspram_name (unsigned int num, unsigned int unit, bfd_boolean load)
2277 {
2278   size_t i, nentries;
2279
2280   nentries = sizeof(metag_dsp_tmpl_regtab[load])/sizeof(metag_dsp_tmpl_regtab[load][0]);
2281
2282   for (i = 0; i < nentries; i++)
2283     {
2284       const metag_reg *reg = &metag_dsp_tmpl_regtab[load][i];
2285
2286       if (reg->no == num && reg->unit == unit)
2287         return reg->name;
2288     }
2289   return "?.?";
2290 }
2291
2292 /* This lookup function looks up the corresponding name for a register
2293    number in a DSP instruction. SOURCE indicates whether this
2294    register is a source or destination operand.  */
2295 static const char *
2296 lookup_any_reg_name (unsigned int unit, unsigned int num, bfd_boolean source)
2297 {
2298   /* A register with the top bit set (5th bit) indicates a DSPRAM
2299      register.  */
2300   if (num > 15)
2301     {
2302       unsigned int dunit = (unit == UNIT_D0) ? UNIT_RAM_D0 : UNIT_RAM_D1;
2303       return lookup_dspram_name (num, dunit, source);
2304     }
2305   else
2306     return lookup_reg_name (unit, num);
2307 }
2308
2309 /* Return the DSP data unit for UNIT.  */
2310 static inline enum metag_unit
2311 dsp_data_unit_to_sym (unsigned int unit)
2312 {
2313   if (unit == 0)
2314     return UNIT_D0;
2315   else
2316     return UNIT_D1;
2317 }
2318
2319 /* Print a DSP GET or SET instruction.  */
2320 static void
2321 print_dget_set (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
2322                 const insn_template *template,
2323                 disassemble_info *outf)
2324 {
2325   bfd_boolean is_get = (template->meta_opcode & 0x100);
2326   char buf[OPERAND_WIDTH];
2327   char addr_buf[ADDR_WIDTH];
2328   char prefix[DSP_PREFIX_WIDTH];
2329   unsigned int part;
2330   const char *reg_name[2];
2331   bfd_boolean is_high = FALSE;
2332   bfd_boolean is_dual = (insn_word & 0x4);
2333   bfd_boolean is_template = (insn_word & 0x2);
2334   const char *base_reg = "?";
2335   unsigned int addr_unit, base_no, unit;
2336
2337   unit = dsp_data_unit_to_sym (insn_word & 0x1);
2338
2339   /* Is this a load/store to a template table?  */
2340   if (is_template)
2341     {
2342       part = (insn_word >> 19) & 0x1f;
2343       reg_name[0] = lookup_dsp_name (part, UNIT_DT);
2344     }
2345   else
2346     {
2347       part = (insn_word >> 19) & REG_MASK;
2348       is_high = ((part & 0x18) == 0x18);
2349
2350       /* Strip bit high indicator.  */
2351       if (is_high)
2352         part &= 0x17;
2353
2354       reg_name[0] = __lookup_dsp_name (part, unit);
2355
2356     }
2357
2358   /* Is this a dual unit DSP operation?  The modulo operator below
2359      makes sure that we print the Rd register in the correct order,
2360      e.g. because there's only one bit in the instruction for the Data
2361      Unit we have to work out what the other data unit number is.
2362      (there's only 2).  */
2363   if (is_dual)
2364     {
2365       unsigned int _unit = insn_word & 0x1;
2366
2367       _unit = ((_unit + 1) % 2);
2368       reg_name[1] = __lookup_dsp_name(part, dsp_data_unit_to_sym (_unit));
2369     }
2370   else
2371     reg_name[1] = NULL;
2372
2373   addr_unit = ((insn_word >> 18) & 0x1);
2374   if (addr_unit == 0)
2375           addr_unit = UNIT_A0;
2376   else
2377           addr_unit = UNIT_A1;
2378
2379   base_no = (insn_word >> 14) & DSP_REG_MASK;
2380
2381   base_reg = lookup_reg_name (addr_unit, base_no);
2382
2383   /* Check if it's a post-increment/post-decrement.  */
2384   if (insn_word & 0x2000)
2385   {
2386           unsigned int imm = (insn_word >> 9) & DGET_SET_IMM_MASK;
2387           const char *post_op;
2388
2389           switch (imm)
2390             {
2391             case 0x1:
2392               post_op = "++";
2393               break;
2394             case 0x3:
2395               post_op = "--";
2396               break;
2397             default:
2398               post_op = "";
2399             }
2400
2401           snprintf (addr_buf, ADDR_WIDTH, "[%s%s]", base_reg, post_op);
2402   }
2403   else
2404   {
2405           unsigned int offset_part = (insn_word >> 9) & DSP_REG_MASK;
2406           const char *offset_reg = lookup_reg_name (addr_unit, offset_part);
2407
2408           snprintf (addr_buf, ADDR_WIDTH, "[%s+%s++]", base_reg, offset_reg);
2409   }
2410
2411   if (is_get)
2412     {
2413       if (is_dual && !is_template)
2414         snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", reg_name[0],
2415                   reg_name[1], addr_buf);
2416       else
2417         snprintf (buf, OPERAND_WIDTH, "%s,%s", reg_name[0], addr_buf);
2418     }
2419   else
2420     {
2421       if (is_dual && !is_template)
2422         snprintf (buf, OPERAND_WIDTH, "%s,%s,%s", addr_buf,
2423                   reg_name[0], reg_name[1]);
2424       else
2425         snprintf (buf, OPERAND_WIDTH, "%s,%s", addr_buf, reg_name[0]);
2426     }
2427
2428   snprintf (prefix, DSP_PREFIX_WIDTH, "D%s", is_high ? "H" : "");
2429   print_insn (outf, prefix, template->name, buf);
2430 }
2431
2432 /* Print a DSP template instruction.  */
2433 static void
2434 print_dtemplate (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
2435                  const insn_template *template,
2436                  disassemble_info *outf)
2437 {
2438   char buf[OPERAND_WIDTH];
2439   char prefix[DSP_PREFIX_WIDTH];
2440   unsigned int offset[4];
2441   bfd_boolean is_half = (MINOR_OPCODE (insn_word) == 0x5);
2442   bfd_boolean daop_only = (MINOR_OPCODE (insn_word) == 0x3);
2443
2444   offset[0] = ((insn_word >> 19) & REG_MASK);
2445   offset[1] = ((insn_word >> 14) & REG_MASK);
2446   offset[2] = ((insn_word >> 9) & REG_MASK);
2447   offset[3] = ((insn_word >> 4) & REG_MASK);
2448
2449   if (daop_only)
2450           snprintf (buf, OPERAND_WIDTH, "#0x%x,#0x%x,#0x%x", offset[0],
2451                     offset[1], offset[2]);
2452   else
2453     {
2454       snprintf (buf, OPERAND_WIDTH, "#0x%x,#0x%x,#0x%x,#0x%x", offset[0],
2455                 offset[1], offset[2], offset[3]);
2456     }
2457
2458   snprintf (prefix, DSP_PREFIX_WIDTH, "D%s", is_half ? "H" : "");
2459   print_insn (outf, prefix, template->name, buf);
2460 }
2461
2462 /* Format template definition from INSN_WORD into BUF.  */
2463 static void
2464 decode_template_definition(unsigned int insn_word, char *buf, size_t len)
2465 {
2466   bfd_boolean load = ((insn_word >> 13) & 0x1);
2467   bfd_boolean dspram = (((insn_word >> 17) & 0x3) == 0x3);
2468   const char *template[1];
2469   unsigned int tidx = ((insn_word >> 9) & TEMPLATE_REGS_MASK);
2470   enum metag_unit au, ram_unit;
2471   unsigned int addr_reg_nums[2];
2472   const char *addr_reg_names[2];
2473   const char *post_op = "";
2474   const char *join_op = "";
2475   enum metag_unit data_unit = ((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0;
2476
2477   template[0] = lookup_dsp_name (tidx, UNIT_DT);
2478
2479   addr_reg_names[1] = "";
2480
2481   if (dspram)
2482     {
2483       ram_unit = (data_unit == UNIT_D0) ? UNIT_RAM_D0 : UNIT_RAM_D1;
2484       addr_reg_nums[0] = ((insn_word >> 19) & REG_MASK);
2485       addr_reg_names[0] = lookup_dspram_name (addr_reg_nums[0],
2486                                               ram_unit, load);
2487     }
2488   else
2489     {
2490       bfd_boolean im = (((insn_word >> 18) & 0x1) != 0);
2491
2492       au = (((insn_word >> 23) & 0x1) == 0) ? UNIT_A0 : UNIT_A1;
2493       addr_reg_nums[0] = ((insn_word >> 19) & DSP_REG_MASK);
2494
2495       addr_reg_names[0] = lookup_reg_name (au, addr_reg_nums[0]);
2496
2497       if (im)
2498         {
2499           unsigned int im_value = ((insn_word >> 14) & 0x3);
2500
2501           switch (im_value)
2502             {
2503             case 0x1:
2504               post_op = "++";
2505               break;
2506             case 0x3:
2507               post_op = "--";
2508               break;
2509             }
2510         }
2511       else
2512         {
2513           addr_reg_nums[1] = ((insn_word >> 14) & DSP_REG_MASK);
2514           addr_reg_names[1] = lookup_reg_name (au, addr_reg_nums[1]);
2515           join_op = "+";
2516           post_op = "++";
2517         }
2518     }
2519
2520   if (load)
2521     {
2522       len = snprintf (buf, len, " %s,[%s%s%s%s]", template[0], addr_reg_names[0],
2523                       join_op, addr_reg_names[1], post_op);
2524     }
2525   else
2526     {
2527       len = snprintf (buf, len, " [%s%s%s%s],%s", addr_reg_names[0], join_op,
2528                       addr_reg_names[1], post_op, template[0]);
2529     }
2530 }
2531
2532 /* Print a DSP ALU instruction.  */
2533 static void
2534 print_dalu (unsigned int insn_word, bfd_vma pc ATTRIBUTE_UNUSED,
2535             const insn_template *template,
2536             disassemble_info *outf)
2537 {
2538   bfd_boolean is_dual = FALSE;
2539   unsigned int data_unit = (((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0);
2540   const char *reg_names[3];
2541   unsigned int reg_nums[3];
2542   bfd_boolean ac = ((insn_word >> 7) & 0x1);
2543   char buf[OPERAND_WIDTH];
2544   char prefix[DSP_PREFIX_WIDTH];
2545   size_t len;
2546   bfd_boolean is_mod = FALSE;
2547   bfd_boolean is_overflow = FALSE;
2548   unsigned int reg_brackets[3];
2549   bfd_boolean is_w_mx = FALSE;
2550   bfd_boolean is_b_mx = FALSE;
2551   bfd_boolean imm = FALSE;
2552   bfd_boolean is_quickrot64 = FALSE;
2553   bfd_boolean conditional = FALSE;
2554   const char *cc_flags = NULL;
2555   bfd_boolean is_unsigned = FALSE;
2556
2557   memset (reg_brackets, 0, sizeof (reg_brackets));
2558
2559   if (template->arg_type & DSP_ARGS_1)
2560     {
2561       bfd_boolean is_template = FALSE;
2562       const char *addr_reg = NULL;
2563       bfd_boolean qr = FALSE;
2564       bfd_boolean is_acc_add = FALSE;
2565       bfd_boolean is_acc_sub = FALSE;
2566       bfd_boolean is_acc_zero = FALSE;
2567       bfd_boolean is_split8 = (template->arg_type & DSP_ARGS_SPLIT8);
2568
2569       /* Read DU bit.  */
2570       data_unit = ((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0;
2571
2572       conditional = ((insn_word >> 24) & 0x4);
2573
2574       /* Templates can't be conditional.  */
2575       is_template = (((insn_word & 0x02000002) == 0x2) && !conditional);
2576
2577       if (is_split8)
2578         is_mod = (insn_word & 0x80);
2579
2580       if (template->arg_type & DSP_ARGS_QR)
2581         {
2582           if (!conditional)
2583             is_quickrot64 = ((insn_word >> 5) & 0x1);
2584         }
2585
2586       if (template->arg_type & DSP_ARGS_DACC)
2587         {
2588           is_mod = (insn_word & 0x8);
2589           is_unsigned = (insn_word & 0x40);
2590         }
2591
2592       if (is_template)
2593         {
2594           is_w_mx = (insn_word & 0x1);
2595           is_dual = ((insn_word >> 0x4) & 0x1);
2596
2597           /* De.r,Dx.r,De.r|ACe.r */
2598           if (template->arg_type & DSP_ARGS_ACC2)
2599             {
2600               is_mod = (insn_word & 0x8);
2601               is_overflow = (insn_word & 0x20);
2602             }
2603
2604           /* ACe.e,ACx.r,ACo.e? */
2605           if ((template->arg_type & DSP_ARGS_XACC) &&
2606               (((insn_word >> 6) & 0x5) == 0x5))
2607             {
2608               enum metag_unit ac_unit, ao_unit;
2609
2610               ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1;
2611
2612               if (ac_unit == UNIT_ACC_D0)
2613                 ao_unit = UNIT_ACC_D1;
2614               else
2615                 ao_unit = UNIT_ACC_D0;
2616
2617               reg_nums[1] = ((insn_word >> 19) & REG_MASK);
2618
2619               /* These are dummy arguments anyway so the register
2620                  number does not matter.  */
2621               reg_names[0] = lookup_dsp_name (16, ac_unit); /* ACe.0 */
2622               reg_names[1] = lookup_dsp_name (16, ac_unit); /* ACx.0 */
2623               reg_names[2] = lookup_dsp_name (16, ao_unit); /* ACo.0 */
2624             }
2625           else
2626             {
2627               /* De.r|ACe.r,Dx.r,De.r */
2628               if (template->arg_type & DSP_ARGS_DACC &&
2629                   ((insn_word & 0x84) != 0))
2630                 {
2631                   enum metag_unit ac_unit;
2632
2633                   ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1;
2634                   reg_names[0] = lookup_dsp_name (16, ac_unit);
2635
2636                   is_acc_zero = ((insn_word & 0x84) == 0x04);
2637                   is_acc_add = ((insn_word & 0x84) == 0x80);
2638                   is_acc_sub = ((insn_word & 0x84) == 0x84);
2639                 }
2640               else
2641                 reg_names[0] = lookup_any_reg_name (data_unit, 0, FALSE);
2642
2643               /* These are dummy arguments anyway so the register
2644                  number does not matter.  */
2645               reg_names[1] = lookup_any_reg_name (data_unit, 0, TRUE);
2646
2647               /* De.r,Dx.r,De.r|ACe.r */
2648               if ((template->arg_type & DSP_ARGS_ACC2) &&
2649                   ((insn_word & 0x80) == 0x80))
2650                 {
2651                   enum metag_unit ac_unit;
2652
2653                   ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1;
2654                   reg_names[2] = lookup_dsp_name (16, ac_unit);
2655                 }
2656               /* Detection of QUICKRoT and accumulator usage uses the
2657                  same bits. They are mutually exclusive.  */
2658               else if (ac && (template->arg_type & DSP_ARGS_ACC2))
2659                 {
2660                   reg_nums[2] = ((insn_word >> 9) & REG_MASK);
2661
2662                   if (data_unit == UNIT_D0)
2663                     reg_names[2] = lookup_dsp_name (reg_nums[2], UNIT_ACC_D0);
2664                   else
2665                     reg_names[2] = lookup_dsp_name (reg_nums[2], UNIT_ACC_D1);
2666                 }
2667               else
2668                 {
2669                   if ((template->arg_type & DSP_ARGS_QR) &&
2670                       ((insn_word & 0x40) == 0x40))
2671                     {
2672                       enum metag_unit aunit;
2673                       int reg_no;
2674
2675                       if (conditional)
2676                         reg_no = ((insn_word >> 5) & 0x1);
2677                       else
2678                         reg_no = ((insn_word >> 7) & 0x1);
2679
2680                       aunit = (data_unit == UNIT_D0) ? UNIT_A0 : UNIT_A1;
2681                       addr_reg = lookup_reg_name (aunit, reg_no + 2);
2682
2683                       qr = TRUE;
2684                     }
2685
2686                   reg_names[2] = lookup_any_reg_name (data_unit, 0, TRUE);
2687                 }
2688             }
2689
2690           if (qr)
2691             {
2692               len = snprintf (buf, OPERAND_WIDTH, "%s,%s,%s,%s",
2693                               reg_names[0], reg_names[1], reg_names[2],
2694                               addr_reg);
2695             }
2696           else
2697             {
2698               len = snprintf (buf, OPERAND_WIDTH, "%s,%s,%s%s%s",
2699                               reg_names[0], reg_names[1],
2700                               reg_brackets[2] ? "[" : "",
2701                               reg_names[2], reg_brackets[2] ? "]" : "");
2702             }
2703
2704           decode_template_definition (insn_word, buf + len,
2705                                       OPERAND_WIDTH - len);
2706         }
2707       else                      /* Not a template definiton.  */
2708         {
2709           reg_nums[0] = ((insn_word >> 19) & REG_MASK);
2710           reg_nums[1] = ((insn_word >> 14) & REG_MASK);
2711           reg_nums[2] = ((insn_word >> 9) & REG_MASK);
2712
2713           imm = (((insn_word >> 24) & 0x2) && (template->arg_type & DSP_ARGS_IMM));
2714
2715           if (imm)
2716             is_dual = (insn_word & 0x4);
2717           else if (!conditional)
2718             is_dual = (insn_word & 0x10);
2719           else
2720             cc_flags = lookup_scc_flags ((insn_word >> 1) & CC_MASK);
2721
2722           /* De.r,Dx.r,De.r|ACe.r */
2723           if (template->arg_type & DSP_ARGS_ACC2)
2724             {
2725               is_mod = (insn_word & 0x8);
2726               is_overflow = (insn_word & 0x20);
2727             }
2728
2729           if (template->arg_type & DSP_ARGS_SPLIT8)
2730             {
2731               is_overflow = (insn_word & 0x20);
2732             }
2733
2734           /* ACe.e,ACx.r,ACo.e? */
2735           if ((template->arg_type & DSP_ARGS_XACC) &&
2736               (((insn_word >> 6) & 0x5) == 0x5))
2737             {
2738               enum metag_unit ac_unit, ao_unit;
2739
2740               ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1;
2741
2742               if (ac_unit == UNIT_ACC_D0)
2743                 ao_unit = UNIT_ACC_D1;
2744               else
2745                 ao_unit = UNIT_ACC_D0;
2746
2747               reg_nums[1] = ((insn_word >> 19) & REG_MASK);
2748               reg_names[0] = lookup_dsp_name (reg_nums[1], ac_unit);
2749               reg_names[1] = lookup_dsp_name (reg_nums[1], ac_unit);
2750               reg_names[2] = lookup_dsp_name (reg_nums[1], ao_unit);
2751             }
2752           else
2753             {
2754               bfd_boolean o2r = (insn_word & 0x1);
2755
2756               /* De.r|ACe.r,Dx.r,De.r */
2757               if ((template->arg_type & DSP_ARGS_DACC) &&
2758                   ((insn_word & 0x84) != 0))
2759                 {
2760                   enum metag_unit ac_unit;
2761
2762                   ac_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1;
2763                   reg_names[0] = lookup_dsp_name (reg_nums[0], ac_unit);
2764
2765                   is_acc_zero = ((insn_word & 0x84) == 0x04);
2766                   is_acc_add = ((insn_word & 0x84) == 0x80);
2767                   is_acc_sub = ((insn_word & 0x84) == 0x84);
2768                 }
2769               else if (conditional)
2770                 {
2771                   reg_names[0] = lookup_reg_name (data_unit, reg_nums[0]);
2772                 }
2773               else
2774                 {
2775                   reg_names[0] = lookup_any_reg_name (data_unit,
2776                                                       reg_nums[0], FALSE);
2777                   if (reg_nums[0] > 15)
2778                     reg_brackets[0] = 1;
2779                 }
2780
2781               if (imm)
2782                 {
2783                   reg_names[1] = lookup_any_reg_name (data_unit, reg_nums[0], TRUE);
2784
2785                   if (reg_brackets[0])
2786                     reg_brackets[1] = 1;
2787                   }
2788               else
2789                 {
2790                   if (is_split8 && is_mod)
2791                     {
2792                       reg_names[1] = lookup_reg_name (data_unit, reg_nums[1]);
2793                     }
2794                   else
2795                   {
2796                     reg_names[1] = lookup_any_reg_name (data_unit, reg_nums[1], TRUE);
2797
2798                     if (reg_nums[1] > 15)
2799                       reg_brackets[1] = 1;
2800                   }
2801                 }
2802
2803               /* Detection of QUICKRoT and accumulator usage uses the
2804                  same bits. They are mutually exclusive.  */
2805               if (ac && (template->arg_type & DSP_ARGS_ACC2))
2806                 {
2807                   if (data_unit == UNIT_D0)
2808                     reg_names[2] = lookup_dsp_name (reg_nums[2], UNIT_ACC_D0);
2809                   else
2810                     reg_names[2] = lookup_dsp_name (reg_nums[2], UNIT_ACC_D1);
2811                 }
2812
2813               else
2814                 {
2815                   if ((template->arg_type & DSP_ARGS_QR) &&
2816                       ((insn_word & 0x40) == 0x40))
2817                     {
2818                       enum metag_unit aunit;
2819                       int reg_no;
2820
2821                       if (conditional)
2822                         reg_no = ((insn_word >> 5) & 0x1);
2823                       else
2824                         reg_no = ((insn_word >> 7) & 0x1);
2825
2826                       aunit = (data_unit == UNIT_D0) ? UNIT_A0 : UNIT_A1;
2827                       addr_reg = lookup_reg_name (aunit, reg_no + 2);
2828
2829                       qr = TRUE;
2830                     }
2831
2832                   if (o2r)
2833                     reg_names[2] = lookup_o2r (data_unit, reg_nums[2]);
2834                   else
2835                     {
2836                       /* Can't use a DSPRAM reg if both QD and L1 are
2837                          set on a QUICKRoT instruction or if we're a
2838                          split 8.  */
2839                       if (((template->arg_type & DSP_ARGS_QR)
2840                            && ((insn_word & 0x30) == 0x30 && !conditional)) ||
2841                           (is_split8 && is_mod))
2842                         reg_names[2] = lookup_reg_name (data_unit, reg_nums[2]);
2843                       else
2844                         {
2845                           reg_names[2] = lookup_any_reg_name (data_unit,
2846                                                               reg_nums[2], TRUE);
2847                           if (reg_nums[2] > 15)
2848                             reg_brackets[2] = 1;
2849                         }
2850                     }
2851                 }
2852             }
2853
2854           if (qr)
2855             {
2856               len = snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,%s%s%s,%s",
2857                               reg_brackets[0] ? "[" : "",
2858                               reg_names[0], reg_brackets[0] ? "]" : "",
2859                               reg_brackets[1] ? "[" : "",
2860                               reg_names[1], reg_brackets[1] ? "]" : "",
2861                               reg_brackets[2] ? "[" : "",
2862                               reg_names[2], reg_brackets[2] ? "]" : "",
2863                               addr_reg);
2864             }
2865           else
2866             {
2867               if (imm)
2868                 {
2869                   /* Conform to the embedded assembler's policy of
2870                      printing negative numbers as decimal and positive
2871                      as hex.  */
2872                   int value = ((insn_word >> 3) & IMM16_MASK);
2873
2874                   if ((value & 0x8000) || value == 0)
2875                     {
2876                       value = sign_extend (value, IMM16_BITS);
2877                       len = snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,#%d",
2878                                       reg_brackets[0] ? "[" : "",
2879                                       reg_names[0], reg_brackets[0] ? "]" : "",
2880                                       reg_brackets[1] ? "[" : "",
2881                                       reg_names[1], reg_brackets[1] ? "]" : "",
2882                                       value);
2883                     }
2884                   else
2885                     {
2886                       len = snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,#%#x",
2887                                       reg_brackets[0] ? "[" : "",
2888                                       reg_names[0], reg_brackets[0] ? "]" : "",
2889                                       reg_brackets[1] ? "[" : "",
2890                                       reg_names[1], reg_brackets[1] ? "]" : "",
2891                                       value);
2892                     }
2893                 }
2894               else
2895                 {
2896                   len = snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,%s%s%s",
2897                                   reg_brackets[0] ? "[" : "",
2898                                   reg_names[0], reg_brackets[0] ? "]" : "",
2899                                   reg_brackets[1] ? "[" : "", reg_names[1],
2900                                   reg_brackets[1] ? "]" : "",
2901                                   reg_brackets[2] ? "[" : "",
2902                                   reg_names[2], reg_brackets[2] ? "]" : "");
2903                 }
2904             }
2905         }
2906
2907       snprintf (prefix, DSP_PREFIX_WIDTH, "D%s%s%s%s%s%s%s%s%s%s%s%s",
2908                 cc_flags ? cc_flags : "",
2909                 is_dual ? "L" : "",
2910                 is_quickrot64 ? "Q" : "",
2911                 is_unsigned ? "U" : "",
2912                 is_mod ? "M" : "",
2913                 is_acc_zero ? "Z" : "",
2914                 is_acc_add ? "P" : "", is_acc_sub ? "N" : "",
2915                 is_overflow ? "O" : "",
2916                 is_w_mx ? "W" : "",
2917                 is_b_mx ? "B" : "",
2918                 is_template ? "T" : "");
2919     }
2920   else if (template->arg_type & DSP_ARGS_2) /* Group 2.  */
2921     {
2922       bfd_boolean is_template;
2923       bfd_boolean o2r = FALSE;
2924       int major = MAJOR_OPCODE (template->meta_opcode);
2925       bfd_boolean is_neg_or_mov = (major == OPC_ADD || major == OPC_SUB);
2926       bfd_boolean is_cmp_tst = ((major == OPC_CMP) &&
2927                                 ((insn_word & 0x0000002c) == 0));
2928       bfd_boolean is_fpu_mov = template->insn_type == INSN_DSP_FPU;
2929       bfd_boolean to_fpu = (template->meta_opcode >> 7) & 0x1;
2930
2931       if (major == OPC_9)
2932         imm = (insn_word & 0x2);
2933       else if (template->arg_type & DSP_ARGS_IMM)
2934         imm = ((insn_word >> 25) & 0x1);
2935
2936       is_template = (((insn_word & 0x02000002) == 0x2) &&
2937                      major != OPC_9);
2938
2939       if (imm)
2940         is_dual = ((insn_word >> 0x2) & 0x1);
2941       else
2942         is_dual = ((insn_word >> 0x4) & 0x1);
2943
2944       /* MOV and XSD[BW] do not have o2r.  */
2945       if (major != OPC_9 && major != OPC_MISC)
2946         o2r = (insn_word & 0x1);
2947
2948       if (is_neg_or_mov)
2949         {
2950           is_mod = (insn_word & 0x8);
2951           is_overflow = (insn_word & 0x20);
2952         }
2953
2954       /* XSD */
2955       if (major == OPC_MISC)
2956         data_unit = (insn_word & 0x1) ? UNIT_D1 : UNIT_D0;
2957       else
2958         data_unit = ((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0;
2959
2960       /* Check for NEG,MOV,ABS,FFB, etc.  */
2961       if (is_neg_or_mov || !is_cmp_tst || imm ||
2962           MAJOR_OPCODE (insn_word) == OPC_9 ||
2963           MAJOR_OPCODE (insn_word) == OPC_MISC)
2964         reg_nums[0] = ((insn_word >> 19) & REG_MASK);
2965       else
2966         reg_nums[0] = ((insn_word >> 14) & REG_MASK);
2967
2968       if (is_template)
2969         {
2970           is_w_mx = (insn_word & 0x1);
2971
2972           /* These are dummy arguments anyway so the register number
2973              does not matter.  */
2974           if (is_fpu_mov)
2975             {
2976               if (to_fpu)
2977                 {
2978                   reg_names[0] = lookup_reg_name (UNIT_FX, 0);
2979                   reg_names[1] = lookup_reg_name (data_unit, 0);
2980                 }
2981               else
2982                 {
2983                   reg_names[0] = lookup_reg_name (data_unit, 0);
2984                   reg_names[1] = lookup_reg_name (UNIT_FX, 0);
2985                 }
2986             }
2987           else
2988             {
2989               reg_names[0] = lookup_reg_name (data_unit, 0);
2990               reg_names[1] = lookup_reg_name (data_unit, 0);
2991             }
2992
2993           len = snprintf (buf, OPERAND_WIDTH, "%s,%s",
2994                           reg_names[0], reg_names[1]);
2995
2996           decode_template_definition (insn_word, buf + len,
2997                                       OPERAND_WIDTH - len);
2998         }
2999       else
3000         {
3001           if (imm)
3002             {
3003               /* Conform to the embedded assembler's policy of
3004                  printing negative numbers as decimal and positive as
3005                  hex.  */
3006               unsigned int value = ((insn_word >> 3) & IMM16_MASK);
3007
3008               if (major == OPC_9)
3009                 {
3010                   data_unit = (insn_word & 0x1) ? UNIT_D1 : UNIT_D0;
3011                   is_dual = (insn_word & 0x4);
3012
3013                   reg_names[0] = __lookup_dsp_name (reg_nums[0], data_unit);
3014                 }
3015               else
3016                 {
3017                   reg_names[0] = lookup_any_reg_name (data_unit, reg_nums[0], TRUE);
3018                   if (reg_nums[0] > 15)
3019                     reg_brackets[0] = 1;
3020                 }
3021
3022               if ((value & 0x8000) || value == 0)
3023                 {
3024                   value = sign_extend (value, IMM16_BITS);
3025                   snprintf (buf, OPERAND_WIDTH, "%s%s%s,#%d",
3026                             reg_brackets[0] ? "[" : "",
3027                             reg_names[0], reg_brackets[0] ? "]" : "",
3028                             value);
3029                 }
3030               else
3031                 {
3032                   snprintf (buf, OPERAND_WIDTH, "%s%s%s,#0x%x",
3033                             reg_brackets[0] ? "[" : "",
3034                             reg_names[0], reg_brackets[0] ? "]" : "",
3035                             value);
3036                 }
3037             }
3038           else
3039             {
3040               if (is_neg_or_mov || is_cmp_tst)
3041                 reg_nums[1] = ((insn_word >> 9) & REG_MASK);
3042               else
3043                 reg_nums[1] = ((insn_word >> 14) & REG_MASK);
3044
3045               if (major == OPC_9)
3046                 {
3047                   is_dual = (insn_word & 0x4);
3048                   data_unit = (insn_word & 0x1) ? UNIT_D1 : UNIT_D0;
3049
3050                   if (MINOR_OPCODE (template->meta_opcode) == 0x1)
3051                     reg_names[0] = __lookup_dsp_name (reg_nums[0], data_unit);
3052                   else
3053                     reg_names[0] = lookup_reg_name (data_unit, reg_nums[0]);
3054                 }
3055               else
3056                 {
3057                   unsigned int reg0_unit = data_unit;
3058
3059                   if (is_fpu_mov && to_fpu)
3060                     reg0_unit = UNIT_FX;
3061
3062                   reg_names[0] = lookup_any_reg_name (reg0_unit, reg_nums[0],
3063                                                       (!is_neg_or_mov && is_cmp_tst));
3064                   if (reg_nums[0] > 15)
3065                     reg_brackets[0] = 1;
3066                 }
3067
3068               if (o2r)
3069                 reg_names[1] = lookup_o2r (data_unit, reg_nums[1]);
3070               else
3071                 {
3072                   /* Check for accumulator argument.  */
3073                   if (is_neg_or_mov && ((insn_word & 0x80) == 0x80))
3074                     {
3075                       if (data_unit == UNIT_D0)
3076                         reg_names[1] = lookup_dsp_name (reg_nums[1], UNIT_ACC_D0);
3077                       else
3078                         reg_names[1] = lookup_dsp_name (reg_nums[1], UNIT_ACC_D1);
3079                     }
3080                   else
3081                     {
3082                       if (major == OPC_9)
3083                         {
3084                           if (MINOR_OPCODE (template->meta_opcode) == 0x1)
3085                             {
3086                               reg_names[1] = lookup_reg_name (data_unit, reg_nums[1]);
3087                             }
3088                           else
3089                             {
3090                               enum metag_unit u;
3091
3092                               u = (insn_word & 0x1) ? UNIT_RAM_D1 : UNIT_RAM_D0;
3093                               reg_names[1] = lookup_dsp_name (reg_nums[1], u);
3094                             }
3095                         }
3096                       else
3097                         {
3098                           reg_names[1] = lookup_any_reg_name (data_unit,
3099                                                               reg_nums[1], TRUE);
3100                           if (reg_nums[1] > 15)
3101                             reg_brackets[1] = 1;
3102                         }
3103                     }
3104                 }
3105
3106               snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s",
3107                         reg_brackets[0] ? "[" : "", reg_names[0],
3108                         reg_brackets[0] ? "]" : "",
3109                         reg_brackets[1] ? "[" : "", reg_names[1],
3110                         reg_brackets[1] ? "]" : "");
3111             }
3112         }
3113
3114       snprintf (prefix, DSP_PREFIX_WIDTH, "D%s%s%s%s%s%s",
3115                 is_fpu_mov ? "F" : "",
3116                 is_dual ? "L" : "",
3117                 is_mod ? "M" : "", is_overflow ? "O" : "",
3118                 is_w_mx ? "W" : "",
3119                 is_template ? "T" : "");
3120     }
3121   else                          /* Group 3. */
3122     {
3123       /* If both the C and CA bits are set, then the Rd register can
3124          be in any unit. Figure out which unit from the Ud field.  */
3125       bfd_boolean all_units = (((insn_word) & 0x04000020) == 0x04000020);
3126       enum metag_unit ud_unit = ((insn_word >> 1) & UNIT_MASK);
3127       enum metag_unit ram_unit, acc_unit;
3128       bfd_boolean round = FALSE;
3129       bfd_boolean clamp9 = FALSE;
3130       bfd_boolean clamp8 = FALSE;
3131       bfd_boolean is_template = ((insn_word & 0x04000002) == 0x2);
3132
3133       imm = ((insn_word >> 25) & 0x1);
3134       ac = (insn_word & 0x1);
3135
3136       conditional = (MINOR_OPCODE (insn_word) & 0x4);
3137
3138       /* Check for conditional and not Condition Always.  */
3139       if (conditional && !(insn_word & 0x20))
3140         cc_flags = lookup_scc_flags ((insn_word >> 1) & CC_MASK);
3141       else if (!(conditional && (insn_word & 0x20)))
3142         is_dual = ((insn_word >> 0x4) & 0x1);
3143
3144       /* Conditional instructions don't have the L1 or RSPP fields.  */
3145       if ((insn_word & 0x04000000) == 0)
3146         {
3147           round = (((insn_word >> 2) & 0x3) == 0x1);
3148           clamp9 = (((insn_word >> 2) & 0x3) == 0x2);
3149           clamp8 = (((insn_word >> 2) & 0x3) == 0x3);
3150         }
3151
3152       /* Read DU bit.  */
3153       data_unit = ((insn_word >> 24) & 0x1) ? UNIT_D1 : UNIT_D0;
3154       reg_nums[0] = ((insn_word >> 19) & REG_MASK);
3155       reg_nums[1] = ((insn_word >> 14) & REG_MASK);
3156
3157       ram_unit = (data_unit == UNIT_D0) ? UNIT_RAM_D0 : UNIT_RAM_D1;
3158       acc_unit = (data_unit == UNIT_D0) ? UNIT_ACC_D0 : UNIT_ACC_D1;
3159
3160       if (all_units)
3161         reg_names[0] = lookup_reg_name (ud_unit, reg_nums[0]);
3162       else
3163         {
3164           if (conditional)
3165             reg_names[0] = lookup_reg_name (data_unit, reg_nums[0]);
3166           else
3167             {
3168               reg_names[0] = lookup_any_reg_name (data_unit, reg_nums[0], FALSE);
3169               if (reg_nums[0] > 15)
3170                 reg_brackets[0] = 1;
3171             }
3172         }
3173
3174       if (ac)
3175         {
3176           reg_names[1] = lookup_dsp_name (reg_nums[1], acc_unit);
3177         }
3178       else
3179         {
3180           reg_names[1] = lookup_any_reg_name (data_unit, reg_nums[1], TRUE);
3181           if (reg_nums[1] > 15)
3182             reg_brackets[1] = 1;
3183         }
3184
3185       if (imm)
3186         {
3187           snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,#%#x",
3188                     reg_brackets[0] ? "[" : "",
3189                     reg_names[0], reg_brackets[0] ? "]" : "",
3190                     reg_brackets[1] ? "[" : "",
3191                     reg_names[1], reg_brackets[1] ? "]" : "",
3192                     ((insn_word >> 9) & IMM5_MASK));
3193         }
3194       else
3195         {
3196           reg_nums[2] = ((insn_word >> 9) & REG_MASK);
3197
3198           reg_names[2] = lookup_any_reg_name (data_unit, reg_nums[2], TRUE);
3199
3200           if (reg_nums[2] > 15)
3201                   reg_brackets[2] = 1;
3202
3203           if (is_template)
3204             {
3205               bfd_boolean load = ((insn_word >> 13) & 0x1);
3206               bfd_boolean dspram = (((insn_word >> 17) & 0x3) == 0x3);
3207               const char *tname[1];
3208               unsigned int tidx = ((insn_word >> 9) & TEMPLATE_REGS_MASK);
3209               enum metag_unit au;
3210               unsigned int addr_reg_nums[2];
3211               const char *addr_reg_names[2];
3212               const char *post_op = "";
3213               const char *join_op = "";
3214
3215               is_w_mx = ((insn_word >> 5) & 0x1);
3216
3217               tname[0] = lookup_dsp_name (tidx, UNIT_DT);
3218
3219               /* These are dummy arguments anyway */
3220               reg_names[0] = lookup_reg_name (data_unit, 0);
3221               if (ac)
3222                 reg_names[1] = lookup_dsp_name (16, acc_unit);
3223               else
3224                 reg_names[1] = lookup_reg_name (data_unit, 0);
3225               reg_names[2] = lookup_reg_name (data_unit, 0);
3226
3227               addr_reg_names[1] = "";
3228
3229               if (dspram)
3230                 {
3231                   ram_unit = (data_unit == UNIT_D0) ? UNIT_RAM_D0 : UNIT_RAM_D1;
3232                   addr_reg_nums[0] = ((insn_word >> 19) & REG_MASK);
3233                   addr_reg_names[0] = lookup_dspram_name (addr_reg_nums[0],
3234                                                           ram_unit, load);
3235                 }
3236               else
3237                 {
3238                   bfd_boolean im = (((insn_word >> 18) & 0x1) != 0);
3239
3240                   au = (((insn_word >> 23) & 0x1) == 0) ? UNIT_A0 : UNIT_A1;
3241                   addr_reg_nums[0] = ((insn_word >> 19) & DSP_REG_MASK);
3242
3243                   addr_reg_names[0] = lookup_reg_name (au, addr_reg_nums[0]);
3244
3245                   if (im)
3246                     {
3247                       unsigned int im_value = ((insn_word >> 14) & 0x3);
3248
3249                       switch (im_value)
3250                         {
3251                         case 0x1:
3252                           post_op = "++";
3253                           break;
3254                         case 0x3:
3255                           post_op = "--";
3256                           break;
3257                         }
3258                     }
3259                   else
3260                     {
3261                       addr_reg_nums[1] = ((insn_word >> 14) & DSP_REG_MASK);
3262                       addr_reg_names[1] = lookup_reg_name (au, addr_reg_nums[1]);
3263                       join_op = "+";
3264                       post_op = "++";
3265                     }
3266                 }
3267
3268               if (load)
3269                 {
3270                   snprintf (buf, OPERAND_WIDTH, "%s,%s,%s %s,[%s%s%s%s]",
3271                             reg_names[0], reg_names[1], reg_names[2],
3272                             tname[0], addr_reg_names[0], join_op,
3273                             addr_reg_names[1], post_op);
3274                 }
3275               else
3276                 {
3277                   snprintf (buf, OPERAND_WIDTH, "%s,%s,%s [%s%s%s%s],%s",
3278                             reg_names[0], reg_names[1], reg_names[2],
3279                             addr_reg_names[0], join_op, addr_reg_names[1],
3280                             post_op, tname[0]);
3281                 }
3282             }
3283           else
3284             {
3285               snprintf (buf, OPERAND_WIDTH, "%s%s%s,%s%s%s,%s%s%s",
3286                         reg_brackets[0] ? "[" : "",
3287                         reg_names[0], reg_brackets[0] ? "]" : "",
3288                         reg_brackets[1] ? "[" : "",
3289                         reg_names[1], reg_brackets[1] ? "]" : "",
3290                         reg_brackets[2] ? "[" : "",
3291                         reg_names[2], reg_brackets[2] ? "]" : "");
3292             }
3293         }
3294
3295       snprintf (prefix, DSP_PREFIX_WIDTH, "D%s%s%s%s%s%s%s",
3296                 cc_flags ? cc_flags : "",
3297                 is_dual ? "L" : "", clamp9 ? "G" : "",
3298                 clamp8 ? "B" : "", round ? "R" : "",
3299                 is_w_mx ? "W" : "",
3300                 is_template ? "T" : "");
3301     }
3302
3303   print_insn (outf, prefix, template->name, buf);
3304
3305 }
3306
3307 typedef void (*insn_printer)(unsigned int, bfd_vma, const insn_template *,
3308                              disassemble_info *);
3309
3310 /* Printer table.  */
3311 static const insn_printer insn_printers[ENC_MAX] =
3312   {
3313     [ENC_NONE] = print_none,
3314     [ENC_MOV_U2U] = print_mov_u2u,
3315     [ENC_MOV_PORT] = print_mov_port,
3316     [ENC_MMOV] = print_mmov,
3317     [ENC_MDRD] = print_mdrd,
3318     [ENC_MOVL_TTREC] = print_movl_ttrec,
3319     [ENC_GET_SET] = print_get_set,
3320     [ENC_GET_SET_EXT] = print_get_set_ext,
3321     [ENC_MGET_MSET] = print_mget_mset,
3322     [ENC_COND_SET] = print_cond_set,
3323     [ENC_XFR] = print_xfr,
3324     [ENC_MOV_CT] = print_mov_ct,
3325     [ENC_SWAP] = print_swap,
3326     [ENC_JUMP] = print_jump,
3327     [ENC_CALLR] = print_callr,
3328     [ENC_ALU] = print_alu,
3329     [ENC_SHIFT] = print_shift,
3330     [ENC_MIN_MAX] = print_min_max,
3331     [ENC_BITOP] = print_bitop,
3332     [ENC_CMP] = print_cmp,
3333     [ENC_BRANCH] = print_branch,
3334     [ENC_KICK] = print_mov_u2u,
3335     [ENC_SWITCH] = print_switch,
3336     [ENC_CACHER] = print_cacher,
3337     [ENC_CACHEW] = print_cachew,
3338     [ENC_ICACHE] = print_icache,
3339     [ENC_LNKGET] = print_lnkget,
3340     [ENC_FMOV] = print_fmov,
3341     [ENC_FMMOV] = print_fmmov,
3342     [ENC_FMOV_DATA] = print_fmov_data,
3343     [ENC_FMOV_I] = print_fmov_i,
3344     [ENC_FPACK] = print_fpack,
3345     [ENC_FSWAP] = print_fswap,
3346     [ENC_FCMP] = print_fcmp,
3347     [ENC_FMINMAX] = print_fminmax,
3348     [ENC_FCONV] = print_fconv,
3349     [ENC_FCONVX] = print_fconvx,
3350     [ENC_FBARITH] = print_fbarith,
3351     [ENC_FEARITH] = print_fearith,
3352     [ENC_FREC] = print_frec,
3353     [ENC_FSIMD] = print_fsimd,
3354     [ENC_FGET_SET_ACF] = print_fget_set_acf,
3355     [ENC_DGET_SET] = print_dget_set,
3356     [ENC_DTEMPLATE] = print_dtemplate,
3357     [ENC_DALU] = print_dalu,
3358   };
3359
3360 /* Entry point for instruction printing.  */
3361 int
3362 print_insn_metag (bfd_vma pc, disassemble_info *outf)
3363 {
3364   bfd_byte buf[4];
3365   unsigned int insn_word;
3366   size_t i;
3367   outf->bytes_per_chunk = 4;
3368
3369   (*outf->read_memory_func) (pc & ~0x03, buf, 4, outf);
3370   insn_word = bfd_getl32 (buf);
3371
3372   for (i = 0; i < sizeof(metag_optab)/sizeof(metag_optab[0]); i++)
3373     {
3374       const insn_template *template = &metag_optab[i];
3375
3376       if ((insn_word & template->meta_mask) == template->meta_opcode)
3377         {
3378           enum insn_encoding encoding = template->encoding;
3379           insn_printer printer = insn_printers[encoding];
3380
3381           if (printer)
3382             printer (insn_word, pc, template, outf);
3383
3384           return 4;
3385         }
3386     }
3387
3388   return 4;
3389 }