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