1 /* Disassemble Imagination Technologies Meta instructions.
2 Copyright (C) 2013-2021 Free Software Foundation, Inc.
3 Contributed by Imagination Technologies Ltd.
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.
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.
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. */
21 #include "disassemble.h"
28 #include "opcode/metag.h"
30 /* Column widths for printing. */
31 #define PREFIX_WIDTH "10"
32 #define INSN_NAME_WIDTH "10"
34 #define OPERAND_WIDTH 92
37 #define DSP_PREFIX_WIDTH 17
39 /* Value to print if we fail to parse a register name. */
40 const char unknown_reg
[] = "?";
42 /* Return the size of a GET or SET instruction. */
44 metag_get_set_size_bytes (unsigned int opcode
)
46 switch (((opcode
) >> 24) & 0x5)
60 /* Return the size of an extended GET or SET instruction. */
62 metag_get_set_ext_size_bytes (unsigned int opcode
)
64 switch (((opcode
) >> 1) & 0x3)
78 /* Return the size of a conditional SET instruction. */
80 metag_cond_set_size_bytes (unsigned int opcode
)
82 switch (opcode
& 0x201)
96 /* Return a value sign-extended. */
98 sign_extend (int n
, unsigned int bits
)
100 int mask
= 1 << (bits
- 1);
101 return -(n
& mask
) | n
;
104 /* Return the short interpretation of UNIT. */
106 short_unit (unsigned int unit
)
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
)
120 for (i
= 0; i
< sizeof(metag_regtab
)/sizeof(metag_regtab
[0]); i
++)
122 const metag_reg
*reg
= &metag_regtab
[i
];
124 if (reg
->unit
== unit
&& reg
->no
== number
)
131 /* Return the register name corresponding to UNIT and NUMBER or NULL. */
133 lookup_reg_name (unsigned int unit
, unsigned int number
)
135 const metag_reg
*reg
;
137 reg
= lookup_reg (unit
, number
);
145 /* Return the unit that is the pair of UNIT. */
147 get_pair_unit (unsigned int unit
)
164 /* Return the name of the pair register for UNIT and NUMBER or NULL. */
166 lookup_pair_reg_name (unsigned int unit
, unsigned int number
)
169 return lookup_reg_name (unit
, number
+ 1);
171 return lookup_reg_name (get_pair_unit (unit
), number
);
174 /* Return the name of the accumulator register for PART. */
176 lookup_acf_name (unsigned int part
)
180 for (i
= 0; i
< sizeof(metag_acftab
)/sizeof(metag_acftab
[0]); i
++)
182 const metag_acf
*acf
= &metag_acftab
[i
];
184 if (acf
->part
== part
)
190 /* Return the register name for the O2R register for UNIT and NUMBER. */
192 lookup_o2r (enum metag_unit unit
, unsigned int number
)
194 unsigned int o2r_unit
;
195 enum metag_unit actual_unit
= UNIT_A0
;
196 const metag_reg
*reg
;
198 o2r_unit
= (number
& ~O2R_REG_MASK
) >> 3;
199 number
= number
& O2R_REG_MASK
;
206 actual_unit
= UNIT_A1
;
209 actual_unit
= UNIT_D0
;
212 actual_unit
= UNIT_RD
;
215 actual_unit
= UNIT_D1
;
219 else if (unit
== UNIT_A1
)
224 actual_unit
= UNIT_D1
;
227 actual_unit
= UNIT_D0
;
230 actual_unit
= UNIT_RD
;
233 actual_unit
= UNIT_A0
;
237 else if (unit
== UNIT_D0
)
242 actual_unit
= UNIT_A1
;
245 actual_unit
= UNIT_D1
;
248 actual_unit
= UNIT_RD
;
251 actual_unit
= UNIT_A0
;
255 else if (unit
== UNIT_D1
)
260 actual_unit
= UNIT_A1
;
263 actual_unit
= UNIT_D0
;
266 actual_unit
= UNIT_RD
;
269 actual_unit
= UNIT_A0
;
274 reg
= lookup_reg (actual_unit
, number
);
282 /* Return the string for split condition code CODE. */
284 lookup_scc_flags (unsigned int code
)
288 for (i
= 0; i
< sizeof (metag_dsp_scondtab
) / sizeof (metag_dsp_scondtab
[0]); i
++)
290 if (metag_dsp_scondtab
[i
].code
== code
)
292 return metag_dsp_scondtab
[i
].name
;
298 /* Return the string for FPU split condition code CODE. */
300 lookup_fpu_scc_flags (unsigned int code
)
304 for (i
= 0; i
< sizeof (metag_fpu_scondtab
) / sizeof (metag_fpu_scondtab
[0]); i
++)
306 if (metag_fpu_scondtab
[i
].code
== code
)
308 return metag_fpu_scondtab
[i
].name
;
314 /* Print an instruction with PREFIX, NAME and OPERANDS. */
316 print_insn (disassemble_info
*outf
, const char *prefix
, const char *name
,
317 const char *operands
)
319 outf
->fprintf_func (outf
->stream
, "%-" PREFIX_WIDTH
"s%-" INSN_NAME_WIDTH
"s%s", prefix
, name
, operands
);
322 /* Print an instruction with no operands. */
324 print_none (unsigned int insn_word ATTRIBUTE_UNUSED
,
325 bfd_vma pc ATTRIBUTE_UNUSED
,
326 const insn_template
*template,
327 disassemble_info
*outf
)
329 outf
->fprintf_func (outf
->stream
, "%-" PREFIX_WIDTH
"s%s", "",
333 /* Print a unit to unit MOV instruction. */
335 print_mov_u2u (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
336 const insn_template
*template,
337 disassemble_info
*outf
)
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
;
347 dest_unit
= (insn_word
>> 5) & UNIT_MASK
;
348 dest_no
= (insn_word
>> 14) & REG_MASK
;
350 dest_reg
= lookup_reg_name (dest_unit
, dest_no
);
355 src_unit
= (insn_word
>> 10) & UNIT_MASK
;
357 /* This is really an RTI/RTH. No, really. */
358 if (major
== OPC_MISC
&&
362 if (insn_word
& 0x800000)
363 outf
->fprintf_func (outf
->stream
, "%-" PREFIX_WIDTH
"s%s", "",
366 outf
->fprintf_func (outf
->stream
, "%-" PREFIX_WIDTH
"s%s", "",
372 src_no
= (insn_word
>> 19) & REG_MASK
;
374 src_reg
= lookup_reg_name (src_unit
, src_no
);
376 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", dest_reg
, src_reg
);
378 if (dest_unit
== UNIT_FX
|| src_unit
== UNIT_FX
)
379 print_insn (outf
, "F", template->name
, buf
);
381 print_insn (outf
, "", template->name
, buf
);
384 /* Print a MOV to port instruction. */
386 print_mov_port (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
387 const insn_template
*template,
388 disassemble_info
*outf
)
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
;
398 dest_unit
= short_unit ((insn_word
>> 5) & SHORT_UNIT_MASK
);
400 dest_unit
= (insn_word
>> 5) & UNIT_MASK
;
402 dest1_no
= (insn_word
>> 14) & REG_MASK
;
403 dest2_no
= (insn_word
>> 9) & REG_MASK
;
405 dest_reg
= lookup_reg_name (dest_unit
, dest1_no
);
406 pair_reg
= lookup_pair_reg_name (dest_unit
, dest2_no
);
411 src_reg
= lookup_reg_name (src_unit
, src_no
);
414 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s", dest_reg
, pair_reg
, src_reg
);
416 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", dest_reg
, src_reg
);
418 if (dest_unit
== UNIT_FX
)
419 print_insn (outf
, "F", template->name
, buf
);
421 print_insn (outf
, "", template->name
, buf
);
424 /* Return the number of bits set in rmask. */
425 static unsigned int hweight (unsigned int rmask
)
429 for (count
= 0; rmask
; count
++)
437 /* Print a MOVL to TTREC instruction. */
439 print_movl_ttrec (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
440 const insn_template
*template,
441 disassemble_info
*outf
)
443 unsigned int dest_unit
, dest_no
, src1_no
, src2_no
, src_unit
;
444 char buf
[OPERAND_WIDTH
];
445 const char *dest_reg
;
447 const char *pair_reg
;
452 dest_reg
= lookup_reg_name (dest_unit
, dest_no
);
454 src1_no
= (insn_word
>> 19) & REG_MASK
;
455 src2_no
= (insn_word
>> 14) & REG_MASK
;
457 src_unit
= short_unit ((insn_word
>> 7) & SHORT_UNIT_MASK
);
459 src_reg
= lookup_reg_name (src_unit
, src1_no
);
460 pair_reg
= lookup_pair_reg_name (src_unit
, src2_no
);
462 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s", dest_reg
, src_reg
, pair_reg
);
464 print_insn (outf
, "", template->name
, buf
);
467 /* Format a GET or SET address mode string from INSN_WORD into BUF. */
469 get_set_addr_str (char *buf
, unsigned int buf_size
, unsigned int size
,
470 unsigned int insn_word
)
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;
478 base_unit
= short_unit ((insn_word
>> 5) & SHORT_UNIT_MASK
);
479 base_no
= (insn_word
>> 14) & REG_MASK
;
481 base_reg
= lookup_reg_name (base_unit
, base_no
);
485 int offset
= (insn_word
>> 8) & GET_SET_IMM_MASK
;
487 offset
= sign_extend (offset
, GET_SET_IMM_BITS
);
491 snprintf (buf
, buf_size
, "[%s]", base_reg
);
495 if (offset
== 1 && ua
)
498 snprintf (buf
, buf_size
, "[%s++]", base_reg
);
500 snprintf (buf
, buf_size
, "[++%s]", base_reg
);
504 else if (offset
== -1 && ua
)
507 snprintf (buf
, buf_size
, "[%s--]", base_reg
);
509 snprintf (buf
, buf_size
, "[--%s]", base_reg
);
514 offset
= offset
* size
;
519 snprintf (buf
, buf_size
, "[%s+#%d++]", base_reg
, offset
);
521 snprintf (buf
, buf_size
, "[%s++#%d]", base_reg
, offset
);
524 snprintf (buf
, buf_size
, "[%s+#%d]", base_reg
, offset
);
528 const char *offset_reg
;
529 unsigned int offset_no
;
531 offset_no
= (insn_word
>> 9) & REG_MASK
;
533 offset_reg
= lookup_reg_name (base_unit
, offset_no
);
538 snprintf (buf
, buf_size
, "[%s+%s++]", base_reg
, offset_reg
);
540 snprintf (buf
, buf_size
, "[%s++%s]", base_reg
, offset_reg
);
543 snprintf (buf
, buf_size
, "[%s+%s]", base_reg
, offset_reg
);
547 /* Format an extended GET or SET address mode string from INSN_WORD into BUF. */
549 get_set_ext_addr_str (char *buf
, unsigned int buf_size
, unsigned int size
,
550 unsigned int insn_word
)
552 const char *base_reg
;
553 unsigned int base_unit
, base_no
;
556 base_unit
= short_unit ((insn_word
>> 5) & SHORT_UNIT_MASK
);
557 base_no
= insn_word
& EXT_BASE_REG_MASK
;
559 base_reg
= lookup_reg_name (base_unit
, base_no
);
561 offset
= (insn_word
>> 7) & GET_SET_EXT_IMM_MASK
;
563 offset
= sign_extend (offset
, GET_SET_EXT_IMM_BITS
);
565 offset
= offset
* size
;
569 snprintf (buf
, buf_size
, "[%s]", base_reg
);
573 snprintf (buf
, buf_size
, "[%s+#%d]", base_reg
, offset
);
577 /* Format an MGET or MSET address mode string from INSN_WORD into BUF. */
579 mget_mset_addr_str (char *buf
, unsigned int buf_size
,
580 unsigned int insn_word
)
582 const char *base_reg
;
583 unsigned int base_unit
, base_no
;
585 base_unit
= short_unit ((insn_word
>> 5) & SHORT_UNIT_MASK
);
586 base_no
= (insn_word
>> 14) & REG_MASK
;
588 base_reg
= lookup_reg_name (base_unit
, base_no
);
590 snprintf (buf
, buf_size
, "[%s++]", base_reg
);
593 /* Format a conditional SET address mode string from INSN_WORD into BUF. */
595 cond_set_addr_str (char *buf
, unsigned int buf_size
,
596 unsigned int insn_word
)
598 const char *base_reg
;
599 unsigned int base_unit
, base_no
;
601 base_unit
= short_unit ((insn_word
>> 5) & SHORT_UNIT_MASK
);
602 base_no
= (insn_word
>> 14) & REG_MASK
;
604 base_reg
= lookup_reg_name (base_unit
, base_no
);
606 snprintf (buf
, buf_size
, "[%s]", base_reg
);
609 /* Format a cache instruction address mode string from INSN_WORD into BUF. */
611 cache_addr_str (char *buf
, unsigned int buf_size
, unsigned int insn_word
,
614 const char *base_reg
;
615 unsigned int base_unit
, base_no
;
618 base_unit
= short_unit ((insn_word
>> 5) & SHORT_UNIT_MASK
);
619 base_no
= (insn_word
>> 14) & REG_MASK
;
621 base_reg
= lookup_reg_name (base_unit
, base_no
);
623 offset
= (insn_word
>> 8) & GET_SET_IMM_MASK
;
625 offset
= sign_extend (offset
, GET_SET_IMM_BITS
);
627 offset
= offset
* width
;
631 snprintf (buf
, buf_size
, "[%s]", base_reg
);
635 snprintf (buf
, buf_size
, "[%s+#%d]", base_reg
, offset
);
639 /* Format a list of registers starting at REG_UNIT and REG_NO and conforming
640 to RMASK into BUF. */
642 lookup_reg_list (char *reg_buf
, size_t buf_len
, unsigned int reg_unit
,
643 unsigned int reg_no
, unsigned int rmask
,
646 const char *regs
[MGET_MSET_MAX_REGS
];
647 size_t used_regs
= 1, i
, remaining
;
649 regs
[0] = lookup_reg_name (reg_unit
, reg_no
);
651 for (i
= 1; i
< MGET_MSET_MAX_REGS
; i
++)
656 regs
[used_regs
] = lookup_reg_name (reg_unit
, reg_no
+ (i
* 2));
658 regs
[used_regs
] = lookup_reg_name (reg_unit
, reg_no
+ i
);
666 for (i
= 0; i
< used_regs
; i
++)
670 len
= snprintf(reg_buf
, remaining
, "%s", regs
[i
]);
672 len
= snprintf(reg_buf
, remaining
, ",%s", regs
[i
]);
679 /* Print a GET instruction. */
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
)
688 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s", dest_reg
, pair_reg
,
693 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", dest_reg
, addr_buf
);
696 if (reg_unit
== UNIT_FX
)
697 print_insn (outf
, "F", template->name
, buf
);
699 print_insn (outf
, "", template->name
, buf
);
702 /* Print a SET instruction. */
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
)
711 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s", addr_buf
, src_reg
, pair_reg
);
715 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", addr_buf
, src_reg
);
718 if (reg_unit
== UNIT_FX
)
719 print_insn (outf
, "F", template->name
, buf
);
721 print_insn (outf
, "", template->name
, buf
);
724 /* Print a GET or SET instruction. */
726 print_get_set (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
727 const insn_template
*template,
728 disassemble_info
*outf
)
730 bool 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
;
738 reg_unit
= (insn_word
>> 1) & UNIT_MASK
;
739 reg_no
= (insn_word
>> 19) & REG_MASK
;
741 /* SETs should always print RD. */
742 if (!is_get
&& reg_unit
== UNIT_RD
)
745 reg_name
= lookup_reg_name (reg_unit
, reg_no
);
747 pair_reg
= lookup_pair_reg_name (reg_unit
, reg_no
);
749 get_set_addr_str (addr_buf
, ADDR_WIDTH
, size
, insn_word
);
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
,
758 print_get (buf
, addr_buf
, size
, reg_name
, pair_reg
, reg_unit
,
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
,
768 print_set (buf
, addr_buf
, size
, reg_name
, pair_reg
, reg_unit
,
773 /* Print an extended GET or SET instruction. */
775 print_get_set_ext (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
776 const insn_template
*template,
777 disassemble_info
*outf
)
779 bool is_get
= MINOR_OPCODE (template->meta_opcode
) == GET_EXT_MINOR
;
780 bool 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
;
791 reg_unit
= short_unit ((insn_word
>> 3) & SHORT_UNIT_MASK
);
793 reg_no
= (insn_word
>> 19) & REG_MASK
;
795 reg_name
= lookup_reg_name (reg_unit
, reg_no
);
797 pair_reg
= lookup_pair_reg_name (reg_unit
, reg_no
);
799 get_set_ext_addr_str (addr_buf
, ADDR_WIDTH
, size
, insn_word
);
802 print_get (buf
, addr_buf
, size
, reg_name
, pair_reg
, reg_unit
,
805 print_get (buf
, addr_buf
, 4, reg_name
, pair_reg
, reg_unit
,
808 print_set (buf
, addr_buf
, size
, reg_name
, pair_reg
, reg_unit
,
812 /* Print an MGET or MSET instruction. */
814 print_mget_mset (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
815 const insn_template
*template,
816 disassemble_info
*outf
)
818 bool is_get
= MAJOR_OPCODE (template->meta_opcode
) == OPC_GET
;
819 bool is_fpu
= (MINOR_OPCODE (template->meta_opcode
) & 0x6) == 0x6;
820 bool 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
;
829 reg_unit
= short_unit ((insn_word
>> 3) & SHORT_UNIT_MASK
);
831 reg_no
= (insn_word
>> 19) & REG_MASK
;
832 rmask
= (insn_word
>> 7) & RMASK_MASK
;
834 lookup_reg_list (reg_buf
, REG_WIDTH
, reg_unit
, reg_no
, rmask
,
837 mget_mset_addr_str (addr_buf
, ADDR_WIDTH
, insn_word
);
840 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", reg_buf
, addr_buf
);
842 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", addr_buf
, reg_buf
);
845 print_insn (outf
, "F", template->name
, buf
);
847 print_insn (outf
, "", template->name
, buf
);
850 /* Print a conditional SET instruction. */
852 print_cond_set (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
853 const insn_template
*template,
854 disassemble_info
*outf
)
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
);
861 const char *pair_reg
;
863 src_unit
= (insn_word
>> 10) & UNIT_MASK
;
864 src_no
= (insn_word
>> 19) & REG_MASK
;
866 if (src_unit
== UNIT_RD
)
869 src_reg
= lookup_reg_name (src_unit
, src_no
);
871 pair_reg
= lookup_pair_reg_name (src_unit
, src_no
);
873 cond_set_addr_str (addr_buf
, ADDR_WIDTH
, insn_word
);
875 if (src_unit
== UNIT_RD
)
876 print_set (buf
, addr_buf
, 4, src_reg
, pair_reg
, src_unit
,
879 print_set (buf
, addr_buf
, size
, src_reg
, pair_reg
, src_unit
,
883 /* Print a MMOV instruction. */
885 print_mmov (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
886 const insn_template
*template,
887 disassemble_info
*outf
)
889 unsigned int is_fpu
= template->insn_type
== INSN_FPU
;
890 unsigned int is_prime
= ((MINOR_OPCODE (template->meta_opcode
) & 0x2) &&
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
];
900 dest_no
= (insn_word
>> 14) & REG_MASK
;
902 dest_no
= (insn_word
>> 19) & REG_MASK
;
904 rmask
= (insn_word
>> 7) & RMASK_MASK
;
908 const char *dest_reg
;
909 const char *base_reg
;
910 unsigned int base_unit
, base_no
;
911 int i
, count
= hweight (rmask
);
913 dest_reg
= lookup_reg_name (UNIT_RD
, dest_no
);
915 strcpy (reg_buf
, dest_reg
);
917 for (i
= 0; i
< count
; i
++)
919 strcat (reg_buf
, ",");
920 strcat (reg_buf
, dest_reg
);
923 base_unit
= short_unit ((insn_word
>> 5) & SHORT_UNIT_MASK
);
924 base_no
= (insn_word
>> 14) & REG_MASK
;
926 base_reg
= lookup_reg_name (base_unit
, base_no
);
928 snprintf (addr_buf
, ADDR_WIDTH
, "[%s++]", base_reg
);
930 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", reg_buf
, addr_buf
);
937 dest_unit
= short_unit ((insn_word
>> 3) & SHORT_UNIT_MASK
);
939 lookup_reg_list (reg_buf
, REG_WIDTH
, dest_unit
, dest_no
, rmask
,
942 snprintf (buf
, OPERAND_WIDTH
, "%s,RD", reg_buf
);
947 char prefix_buf
[10] = {0};
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");
960 strcpy (prefix_buf
, "DW");
961 print_insn (outf
, prefix_buf
, template->name
, buf
);
964 print_insn (outf
, "F", template->name
, buf
);
966 print_insn (outf
, "", template->name
, buf
);
969 /* Print an MDRD instruction. */
971 print_mdrd (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
972 const insn_template
*template,
973 disassemble_info
*outf
)
975 unsigned int rmask
, count
;
976 char buf
[OPERAND_WIDTH
];
978 rmask
= (insn_word
>> 7) & RMASK_MASK
;
980 count
= hweight (rmask
);
982 snprintf (buf
, OPERAND_WIDTH
, "#%#x", count
+ 1);
984 print_insn (outf
, "", template->name
, buf
);
987 /* Print an XFR instruction. */
989 print_xfr (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
990 const insn_template
*template,
991 disassemble_info
*outf
)
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
;
1004 src_unit
= short_unit ((insn_word
>> 2) & SHORT_UNIT_MASK
);
1005 src_no
= (insn_word
>> 19) & REG_MASK
;
1007 src_base_reg
= lookup_reg_name (src_unit
, src_no
);
1009 src_no
= (insn_word
>> 14) & REG_MASK
;
1011 src_offset_reg
= lookup_reg_name (src_unit
, src_no
);
1013 dest_unit
= short_unit (insn_word
& SHORT_UNIT_MASK
);
1014 dest_no
= (insn_word
>> 9) & REG_MASK
;
1016 dest_base_reg
= lookup_reg_name (dest_unit
, dest_no
);
1018 dest_no
= (insn_word
>> 4) & REG_MASK
;
1020 dest_offset_reg
= lookup_reg_name (dest_unit
, dest_no
);
1022 us
= (insn_word
>> 27) & 0x1;
1023 ud
= (insn_word
>> 26) & 0x1;
1024 pp
= (insn_word
>> 24) & 0x1;
1028 snprintf (src_buf
, ADDR_WIDTH
, "[%s+%s++]", src_base_reg
,
1031 snprintf (src_buf
, ADDR_WIDTH
, "[%s++%s]", src_base_reg
,
1034 snprintf (src_buf
, ADDR_WIDTH
, "[%s+%s]", src_base_reg
,
1039 snprintf (dest_buf
, ADDR_WIDTH
, "[%s+%s++]", dest_base_reg
,
1042 snprintf (dest_buf
, ADDR_WIDTH
, "[%s++%s]", dest_base_reg
,
1045 snprintf (dest_buf
, ADDR_WIDTH
, "[%s+%s]", dest_base_reg
,
1048 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", dest_buf
, src_buf
);
1050 print_insn (outf
, "", template->name
, buf
);
1053 /* Print a MOV to control unit instruction. */
1055 print_mov_ct (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1056 const insn_template
*template,
1057 disassemble_info
*outf
)
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;
1064 const char *dest_reg
;
1066 reg_no
= (insn_word
>> 19) & REG_MASK
;
1069 dest_reg
= lookup_reg_name (UNIT_TT
, reg_no
);
1071 dest_reg
= lookup_reg_name (UNIT_CT
, reg_no
);
1073 value
= (insn_word
>> 3) & IMM16_MASK
;
1077 value
= sign_extend (value
, IMM16_BITS
);
1078 snprintf (buf
, OPERAND_WIDTH
, "%s,#%d", dest_reg
, value
);
1082 snprintf (buf
, OPERAND_WIDTH
, "%s,#%#x", dest_reg
, value
);
1085 print_insn (outf
, "", template->name
, buf
);
1088 /* Print a SWAP instruction. */
1090 print_swap (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1091 const insn_template
*template,
1092 disassemble_info
*outf
)
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
;
1100 src_unit
= (insn_word
>> 10) & UNIT_MASK
;
1101 src_no
= (insn_word
>> 19) & REG_MASK
;
1103 src_reg
= lookup_reg_name (src_unit
, src_no
);
1105 dest_unit
= (insn_word
>> 5) & UNIT_MASK
;
1106 dest_no
= (insn_word
>> 14) & REG_MASK
;
1108 dest_reg
= lookup_reg_name (dest_unit
, dest_no
);
1110 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", dest_reg
, src_reg
);
1112 if (dest_unit
== UNIT_FX
|| src_unit
== UNIT_FX
)
1113 print_insn (outf
, "F", template->name
, buf
);
1115 print_insn (outf
, "", template->name
, buf
);
1118 /* Print a SWAP instruction. */
1120 print_jump (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1121 const insn_template
*template,
1122 disassemble_info
*outf
)
1124 char buf
[OPERAND_WIDTH
];
1125 unsigned int reg_no
, reg_unit
;
1126 const char *reg_name
;
1129 reg_unit
= short_unit (insn_word
& SHORT_UNIT_MASK
);
1130 reg_no
= (insn_word
>> 19) & REG_MASK
;
1132 reg_name
= lookup_reg_name (reg_unit
, reg_no
);
1134 value
= (insn_word
>> 3) & IMM16_MASK
;
1136 snprintf (buf
, OPERAND_WIDTH
, "%s,#%#x", reg_name
, value
);
1138 print_insn (outf
, "", template->name
, buf
);
1141 /* Print a CALLR instruction. */
1143 print_callr (unsigned int insn_word
, bfd_vma pc
, const insn_template
*template,
1144 disassemble_info
*outf
)
1146 char buf
[OPERAND_WIDTH
];
1147 unsigned int reg_no
, reg_unit
;
1148 const char *reg_name
;
1151 reg_unit
= short_unit ((insn_word
>> 3) & SHORT_UNIT_MASK
);
1152 reg_no
= insn_word
& CALLR_REG_MASK
;
1154 reg_name
= lookup_reg_name (reg_unit
, reg_no
);
1156 value
= (insn_word
>> 5) & IMM19_MASK
;
1158 value
= sign_extend (value
, IMM19_BITS
);
1164 snprintf (buf
, OPERAND_WIDTH
, "%s,", reg_name
);
1166 print_insn (outf
, "", template->name
, buf
);
1168 outf
->print_address_func (value
, outf
);
1171 /* Print a GP ALU instruction. */
1173 print_alu (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1174 const insn_template
*template,
1175 disassemble_info
*outf
)
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 bool 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
;
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))
1205 base_unit
= UNIT_A1
;
1207 base_unit
= UNIT_A0
;
1212 base_unit
= UNIT_D1
;
1214 base_unit
= UNIT_D0
;
1217 dest_no
= (insn_word
>> 19) & REG_MASK
;
1218 src1_no
= (insn_word
>> 14) & REG_MASK
;
1219 src2_no
= (insn_word
>> 9) & REG_MASK
;
1221 dest_unit
= base_unit
;
1229 dest_unit
= (insn_word
>> 1) & UNIT_MASK
;
1230 dest_reg
= lookup_reg_name (dest_unit
, dest_no
);
1233 dest_reg
= lookup_reg_name (dest_unit
, dest_no
);
1235 src1_reg
= lookup_reg_name (base_unit
, src1_no
);
1237 value
= (insn_word
>> 6) & IMM8_MASK
;
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
);
1245 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,#%#x,%s", dest_reg
,
1246 src1_reg
, value
, qr_reg
);
1249 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,#%#x", dest_reg
,
1254 if (is_addr_op
&& (dest_no
& ~CPC_REG_MASK
))
1256 dest_reg
= lookup_reg_name (dest_unit
, dest_no
& CPC_REG_MASK
);
1257 src1_reg
= lookup_reg_name (base_unit
, 0x10);
1261 dest_reg
= lookup_reg_name (dest_unit
, dest_no
);
1262 src1_reg
= lookup_reg_name (base_unit
, dest_no
);
1265 value
= (insn_word
>> 3) & IMM16_MASK
;
1269 value
= sign_extend (value
, IMM16_BITS
);
1272 snprintf (buf
, OPERAND_WIDTH
, "%s,#%d", dest_reg
, value
);
1276 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,#%d", dest_reg
,
1284 snprintf (buf
, OPERAND_WIDTH
, "%s,#%#x", dest_reg
, value
);
1288 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,#%#x", dest_reg
,
1296 src1_reg
= lookup_reg_name (base_unit
, src1_no
);
1299 src2_reg
= lookup_o2r (base_unit
, src2_no
);
1301 src2_reg
= lookup_reg_name (base_unit
, src2_no
);
1305 dest_unit
= (insn_word
>> 5) & UNIT_MASK
;
1310 dest_unit
= (insn_word
>> 1) & UNIT_MASK
;
1312 dest_unit
= base_unit
;
1315 dest_reg
= lookup_reg_name (dest_unit
, dest_no
);
1317 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s", dest_reg
,
1318 src1_reg
, src2_reg
);
1322 dest_reg
= lookup_reg_name (dest_unit
, dest_no
);
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
);
1330 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s,%s", dest_reg
,
1331 src1_reg
, src2_reg
, qr_reg
);
1335 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", dest_reg
, src2_reg
);
1339 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s", dest_reg
,
1340 src1_reg
, src2_reg
);
1345 if (dest_unit
== UNIT_FX
)
1346 print_insn (outf
, "F", template->name
, buf
);
1348 print_insn (outf
, "", template->name
, buf
);
1351 /* Print a B instruction. */
1353 print_branch (unsigned int insn_word
, bfd_vma pc
,
1354 const insn_template
*template,
1355 disassemble_info
*outf
)
1359 value
= (insn_word
>> 5) & IMM19_MASK
;
1361 value
= sign_extend (value
, IMM19_BITS
);
1367 print_insn (outf
, "", template->name
, "");
1369 outf
->print_address_func (value
, outf
);
1372 /* Print a SWITCH instruction. */
1374 print_switch (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1375 const insn_template
*template,
1376 disassemble_info
*outf
)
1378 char buf
[OPERAND_WIDTH
];
1381 value
= insn_word
& IMM24_MASK
;
1383 snprintf (buf
, OPERAND_WIDTH
, "#%#x", value
);
1385 print_insn (outf
, "", template->name
, buf
);
1388 /* Print a shift instruction. */
1390 print_shift (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1391 const insn_template
*template,
1392 disassemble_info
*outf
)
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
;
1408 base_unit
= UNIT_D1
;
1410 base_unit
= UNIT_D0
;
1412 dest_no
= (insn_word
>> 19) & REG_MASK
;
1413 src1_no
= (insn_word
>> 14) & REG_MASK
;
1414 src2_no
= (insn_word
>> 9) & REG_MASK
;
1416 dest_unit
= base_unit
;
1421 dest_unit
= (insn_word
>> 1) & UNIT_MASK
;
1423 dest_reg
= lookup_reg_name (dest_unit
, dest_no
);
1425 src1_reg
= lookup_reg_name (base_unit
, src1_no
);
1427 value
= (insn_word
>> 9) & IMM5_MASK
;
1429 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,#%#x", dest_reg
,
1435 dest_unit
= (insn_word
>> 1) & UNIT_MASK
;
1437 dest_reg
= lookup_reg_name (dest_unit
, dest_no
);
1439 src1_reg
= lookup_reg_name (base_unit
, src1_no
);
1440 src2_reg
= lookup_reg_name (base_unit
, src2_no
);
1442 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s", dest_reg
,
1443 src1_reg
, src2_reg
);
1446 if (dest_unit
== UNIT_FX
)
1447 print_insn (outf
, "F", template->name
, buf
);
1449 print_insn (outf
, "", template->name
, buf
);
1452 /* Print a MIN or MAX instruction. */
1454 print_min_max (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1455 const insn_template
*template,
1456 disassemble_info
*outf
)
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
;
1464 if ((insn_word
>> 24) & UNIT_MASK
)
1465 base_unit
= UNIT_D1
;
1467 base_unit
= UNIT_D0
;
1469 dest_no
= (insn_word
>> 19) & REG_MASK
;
1470 src1_no
= (insn_word
>> 14) & REG_MASK
;
1471 src2_no
= (insn_word
>> 9) & REG_MASK
;
1473 dest_reg
= lookup_reg_name (base_unit
, dest_no
);
1475 src1_reg
= lookup_reg_name (base_unit
, src1_no
);
1476 src2_reg
= lookup_reg_name (base_unit
, src2_no
);
1478 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s", dest_reg
, src1_reg
, src2_reg
);
1480 print_insn (outf
, "", template->name
, buf
);
1483 /* Print a bit operation instruction. */
1485 print_bitop (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1486 const insn_template
*template,
1487 disassemble_info
*outf
)
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
;
1497 ((insn_word
>> 1) & 0xb) == 0xa)
1502 if (insn_word
& 0x1)
1503 base_unit
= UNIT_D1
;
1505 base_unit
= UNIT_D0
;
1509 if ((insn_word
>> 24) & 0x1)
1510 base_unit
= UNIT_D1
;
1512 base_unit
= UNIT_D0
;
1515 src_unit
= base_unit
;
1518 base_unit
= get_pair_unit (base_unit
);
1520 dest_no
= (insn_word
>> 19) & REG_MASK
;
1522 dest_reg
= lookup_reg_name (base_unit
, dest_no
);
1524 src_no
= (insn_word
>> 14) & REG_MASK
;
1526 src_reg
= lookup_reg_name (src_unit
, src_no
);
1528 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", dest_reg
, src_reg
);
1530 print_insn (outf
, "", template->name
, buf
);
1533 /* Print a CMP or TST instruction. */
1535 print_cmp (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1536 const insn_template
*template,
1537 disassemble_info
*outf
)
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
;
1552 base_unit
= UNIT_D1
;
1554 base_unit
= UNIT_D0
;
1556 dest_no
= (insn_word
>> 14) & REG_MASK
;
1557 src_no
= (insn_word
>> 9) & REG_MASK
;
1559 dest_reg
= lookup_reg_name (base_unit
, dest_no
);
1565 value
= (insn_word
>> 6) & IMM8_MASK
;
1567 snprintf (buf
, OPERAND_WIDTH
, "%s,#%#x", dest_reg
, value
);
1571 dest_no
= (insn_word
>> 19) & REG_MASK
;
1573 dest_reg
= lookup_reg_name (base_unit
, dest_no
);
1575 value
= (insn_word
>> 3) & IMM16_MASK
;
1579 value
= sign_extend (value
, IMM16_BITS
);
1580 snprintf (buf
, OPERAND_WIDTH
, "%s,#%d", dest_reg
, value
);
1584 snprintf (buf
, OPERAND_WIDTH
, "%s,#%#x", dest_reg
, value
);
1591 src_reg
= lookup_o2r (base_unit
, src_no
);
1593 src_reg
= lookup_reg_name (base_unit
, src_no
);
1595 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", dest_reg
, src_reg
);
1598 print_insn (outf
, "", template->name
, buf
);
1601 /* Print a CACHER instruction. */
1603 print_cacher (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1604 const insn_template
*template,
1605 disassemble_info
*outf
)
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
;
1614 reg_unit
= short_unit ((insn_word
>> 3) & SHORT_UNIT_MASK
);
1615 reg_no
= (insn_word
>> 19) & REG_MASK
;
1617 reg_name
= lookup_reg_name (reg_unit
, reg_no
);
1618 pair_name
= lookup_pair_reg_name (reg_unit
, reg_no
);
1620 cache_addr_str (addr_buf
, ADDR_WIDTH
, insn_word
, size
);
1623 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s", reg_name
, pair_name
, addr_buf
);
1625 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", reg_name
, addr_buf
);
1627 print_insn (outf
, "", template->name
, buf
);
1630 /* Print a CACHEW instruction. */
1632 print_cachew (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1633 const insn_template
*template,
1634 disassemble_info
*outf
)
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
;
1643 reg_unit
= short_unit ((insn_word
>> 3) & SHORT_UNIT_MASK
);
1644 reg_no
= (insn_word
>> 19) & REG_MASK
;
1646 reg_name
= lookup_reg_name (reg_unit
, reg_no
);
1647 pair_name
= lookup_pair_reg_name (reg_unit
, reg_no
);
1649 cache_addr_str (addr_buf
, ADDR_WIDTH
, insn_word
, 64);
1652 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s", addr_buf
, reg_name
, pair_name
);
1654 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", addr_buf
, reg_name
);
1656 print_insn (outf
, "", template->name
, buf
);
1659 /* Print an ICACHE instruction. */
1661 print_icache (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1662 const insn_template
*template,
1663 disassemble_info
*outf
)
1665 char buf
[OPERAND_WIDTH
];
1669 offset
= ((insn_word
>> 9) & IMM15_MASK
);
1670 pfcount
= ((insn_word
>> 1) & IMM4_MASK
);
1672 offset
= sign_extend (offset
, IMM15_BITS
);
1675 snprintf (buf
, OPERAND_WIDTH
, "#%d,#0x%x", offset
, pfcount
);
1677 snprintf (buf
, OPERAND_WIDTH
, "#%d,#0", offset
);
1678 print_insn (outf
, "", template->name
, buf
);
1681 /* Print a LNKGET instruction. */
1683 print_lnkget (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1684 const insn_template
*template,
1685 disassemble_info
*outf
)
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
;
1694 reg_unit
= short_unit ((insn_word
>> 3) & SHORT_UNIT_MASK
);
1695 reg_no
= (insn_word
>> 19) & REG_MASK
;
1697 reg_name
= lookup_reg_name (reg_unit
, reg_no
);
1698 pair_name
= lookup_pair_reg_name (reg_unit
, reg_no
);
1700 cache_addr_str (addr_buf
, ADDR_WIDTH
, insn_word
, size
);
1703 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s", reg_name
, pair_name
, addr_buf
);
1705 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", reg_name
, addr_buf
);
1707 print_insn (outf
, "", template->name
, buf
);
1710 /* Print an FPU MOV instruction. */
1712 print_fmov (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1713 const insn_template
*template,
1714 disassemble_info
*outf
)
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 bool show_cond
= cc
!= COND_A
&& cc
!= COND_NV
;
1723 const char *dest_reg
;
1724 const char *src_reg
;
1725 const char *cc_flags
;
1727 dest_no
= (insn_word
>> 19) & REG_MASK
;
1728 src_no
= (insn_word
>> 14) & REG_MASK
;
1730 dest_reg
= lookup_reg_name (UNIT_FX
, dest_no
);
1731 src_reg
= lookup_reg_name (UNIT_FX
, src_no
);
1733 cc_flags
= lookup_fpu_scc_flags (cc
);
1735 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", dest_reg
, src_reg
);
1737 snprintf (prefix_buf
, 10, "F%s%s%s", p
? "L" : "",
1738 d
? "D" : "", show_cond
? cc_flags
: "");
1740 print_insn (outf
, prefix_buf
, template->name
, buf
);
1743 /* Convert an FPU rmask into a compatible form. */
1745 convert_fx_rmask (unsigned int rmask
)
1747 int num_bits
= hweight (rmask
), i
;
1748 unsigned int ret
= 0;
1750 for (i
= 0; i
< num_bits
; i
++)
1759 /* Print an FPU MMOV instruction. */
1761 print_fmmov (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1762 const insn_template
*template,
1763 disassemble_info
*outf
)
1765 /* We used to have buf[OPERAND_WIDTH] here, but gcc v8 complains
1766 about the snprintf()s below possibly truncating the output.
1767 (There is no way to tell gcc that this truncation is intentional).
1768 So now we use an extra wide buffer. */
1769 char buf
[OPERAND_WIDTH
* 2];
1770 char data_buf
[REG_WIDTH
];
1771 char fpu_buf
[REG_WIDTH
];
1772 bool to_fpu
= MAJOR_OPCODE (insn_word
) == OPC_GET
;
1773 bool is_mmovl
= MINOR_OPCODE (insn_word
) & 0x1;
1774 unsigned int rmask
= (insn_word
>> 7) & RMASK_MASK
;
1775 unsigned int fpu_no
, data_no
, data_unit
;
1777 data_no
= (insn_word
>> 19) & REG_MASK
;
1778 fpu_no
= (insn_word
>> 14) & REG_MASK
;
1780 if (insn_word
& 0x1)
1781 data_unit
= UNIT_D1
;
1783 data_unit
= UNIT_D0
;
1785 lookup_reg_list (data_buf
, REG_WIDTH
, data_unit
, data_no
, rmask
, false);
1786 lookup_reg_list (fpu_buf
, REG_WIDTH
, UNIT_FX
, fpu_no
,
1787 convert_fx_rmask (rmask
), is_mmovl
);
1790 snprintf (buf
, sizeof buf
, "%s,%s", fpu_buf
, data_buf
);
1792 snprintf (buf
, sizeof buf
, "%s,%s", data_buf
, fpu_buf
);
1794 print_insn (outf
, "F", template->name
, buf
);
1797 /* Print an FPU data unit MOV instruction. */
1799 print_fmov_data (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1800 const insn_template
*template,
1801 disassemble_info
*outf
)
1803 char buf
[OPERAND_WIDTH
];
1804 unsigned int src_no
, dest_no
;
1805 unsigned int to_fpu
= ((insn_word
>> 7) & 0x1);
1806 unsigned int unit_bit
= (insn_word
>> 24) & 0x1;
1807 enum metag_unit base_unit
;
1808 const char *dest_reg
;
1809 const char *src_reg
;
1811 dest_no
= (insn_word
>> 19) & REG_MASK
;
1812 src_no
= (insn_word
>> 9) & REG_MASK
;
1815 base_unit
= UNIT_D1
;
1817 base_unit
= UNIT_D0
;
1821 dest_reg
= lookup_reg_name (UNIT_FX
, dest_no
);
1822 src_reg
= lookup_reg_name (base_unit
, src_no
);
1826 dest_reg
= lookup_reg_name (base_unit
, dest_no
);
1827 src_reg
= lookup_reg_name (UNIT_FX
, src_no
);
1830 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", dest_reg
, src_reg
);
1832 print_insn (outf
, "F", template->name
, buf
);
1835 /* Print an FPU MOV immediate instruction. */
1837 print_fmov_i (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1838 const insn_template
*template,
1839 disassemble_info
*outf
)
1841 char buf
[OPERAND_WIDTH
];
1842 unsigned int dest_no
;
1843 unsigned int p
= (insn_word
>> 2) & 0x1;
1844 unsigned int d
= (insn_word
>> 1) & 0x1;
1845 const char *dest_reg
;
1846 unsigned int value
= (insn_word
>> 3) & IMM16_MASK
;
1848 dest_no
= (insn_word
>> 19) & REG_MASK
;
1850 dest_reg
= lookup_reg_name (UNIT_FX
, dest_no
);
1852 snprintf (buf
, OPERAND_WIDTH
, "%s,#%#x", dest_reg
, value
);
1855 print_insn (outf
, "FL", template->name
, buf
);
1857 print_insn (outf
, "FD", template->name
, buf
);
1859 print_insn (outf
, "F", template->name
, buf
);
1862 /* Print an FPU PACK instruction. */
1864 print_fpack (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1865 const insn_template
*template,
1866 disassemble_info
*outf
)
1868 char buf
[OPERAND_WIDTH
];
1869 unsigned int src1_no
, src2_no
, dest_no
;
1870 const char *dest_reg
;
1871 const char *src1_reg
;
1872 const char *src2_reg
;
1874 dest_no
= (insn_word
>> 19) & REG_MASK
;
1875 src1_no
= (insn_word
>> 14) & REG_MASK
;
1876 src2_no
= (insn_word
>> 9) & REG_MASK
;
1878 dest_reg
= lookup_reg_name (UNIT_FX
, dest_no
);
1879 src1_reg
= lookup_reg_name (UNIT_FX
, src1_no
);
1880 src2_reg
= lookup_reg_name (UNIT_FX
, src2_no
);
1882 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s", dest_reg
, src1_reg
, src2_reg
);
1884 print_insn (outf
, "F", template->name
, buf
);
1887 /* Print an FPU SWAP instruction. */
1889 print_fswap (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1890 const insn_template
*template,
1891 disassemble_info
*outf
)
1893 char buf
[OPERAND_WIDTH
];
1894 unsigned int src_no
, dest_no
;
1895 const char *dest_reg
;
1896 const char *src_reg
;
1898 dest_no
= (insn_word
>> 19) & REG_MASK
;
1899 src_no
= (insn_word
>> 14) & REG_MASK
;
1901 dest_reg
= lookup_reg_name (UNIT_FX
, dest_no
);
1902 src_reg
= lookup_reg_name (UNIT_FX
, src_no
);
1904 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", dest_reg
, src_reg
);
1906 print_insn (outf
, "FL", template->name
, buf
);
1909 /* Print an FPU CMP instruction. */
1911 print_fcmp (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1912 const insn_template
*template,
1913 disassemble_info
*outf
)
1915 char buf
[OPERAND_WIDTH
];
1916 char prefix_buf
[10];
1917 unsigned int src_no
, dest_no
;
1918 unsigned int a
= (insn_word
>> 19) & 0x1;
1919 unsigned int z
= (insn_word
>> 8) & 0x1;
1920 unsigned int p
= (insn_word
>> 6) & 0x1;
1921 unsigned int d
= (insn_word
>> 5) & 0x1;
1922 unsigned int q
= (insn_word
>> 7) & 0x1;
1923 unsigned int cc
= (insn_word
>> 1) & CC_MASK
;
1924 bool show_cond
= cc
!= COND_A
&& cc
!= COND_NV
;
1925 const char *dest_reg
;
1926 const char *src_reg
;
1927 const char *cc_flags
;
1929 dest_no
= (insn_word
>> 14) & REG_MASK
;
1930 src_no
= (insn_word
>> 9) & REG_MASK
;
1932 dest_reg
= lookup_reg_name (UNIT_FX
, dest_no
);
1933 src_reg
= lookup_reg_name (UNIT_FX
, src_no
);
1935 cc_flags
= lookup_fpu_scc_flags (cc
);
1938 snprintf (buf
, OPERAND_WIDTH
, "%s,#0", dest_reg
);
1940 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", dest_reg
, src_reg
);
1942 snprintf (prefix_buf
, 10, "F%s%s%s%s%s", p
? "L" : "",
1943 d
? "D" : "", a
? "A" : "", q
? "Q" : "",
1944 show_cond
? cc_flags
: "");
1946 print_insn (outf
, prefix_buf
, template->name
, buf
);
1949 /* Print an FPU MIN or MAX instruction. */
1951 print_fminmax (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1952 const insn_template
*template,
1953 disassemble_info
*outf
)
1955 char buf
[OPERAND_WIDTH
];
1956 char prefix_buf
[10];
1957 unsigned int p
= (insn_word
>> 6) & 0x1;
1958 unsigned int d
= (insn_word
>> 5) & 0x1;
1959 unsigned int src1_no
, src2_no
, dest_no
;
1960 unsigned int cc
= (insn_word
>> 1) & CC_MASK
;
1961 bool show_cond
= cc
!= COND_A
&& cc
!= COND_NV
;
1962 const char *dest_reg
;
1963 const char *src1_reg
;
1964 const char *src2_reg
;
1965 const char *cc_flags
;
1967 dest_no
= (insn_word
>> 19) & REG_MASK
;
1968 src1_no
= (insn_word
>> 14) & REG_MASK
;
1969 src2_no
= (insn_word
>> 9) & REG_MASK
;
1971 dest_reg
= lookup_reg_name (UNIT_FX
, dest_no
);
1972 src1_reg
= lookup_reg_name (UNIT_FX
, src1_no
);
1973 src2_reg
= lookup_reg_name (UNIT_FX
, src2_no
);
1975 cc_flags
= lookup_fpu_scc_flags (cc
);
1977 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s", dest_reg
, src1_reg
, src2_reg
);
1979 snprintf (prefix_buf
, 10, "F%s%s%s", p
? "L" : "",
1980 d
? "D" : "", show_cond
? cc_flags
: "");
1982 print_insn (outf
, prefix_buf
, template->name
, buf
);
1985 /* Print an FPU data conversion instruction. */
1987 print_fconv (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
1988 const insn_template
*template,
1989 disassemble_info
*outf
)
1991 char buf
[OPERAND_WIDTH
];
1992 char prefix_buf
[10];
1993 unsigned int p
= (insn_word
>> 6) & 0x1;
1994 unsigned int z
= (insn_word
>> 12) & 0x1;
1995 unsigned int src_no
, dest_no
;
1996 unsigned int cc
= (insn_word
>> 1) & CC_MASK
;
1997 bool show_cond
= cc
!= COND_A
&& cc
!= COND_NV
;
1998 const char *dest_reg
;
1999 const char *src_reg
;
2000 const char *cc_flags
;
2002 dest_no
= (insn_word
>> 19) & REG_MASK
;
2003 src_no
= (insn_word
>> 14) & REG_MASK
;
2005 dest_reg
= lookup_reg_name (UNIT_FX
, dest_no
);
2006 src_reg
= lookup_reg_name (UNIT_FX
, src_no
);
2008 cc_flags
= lookup_fpu_scc_flags (cc
);
2010 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", dest_reg
, src_reg
);
2012 snprintf (prefix_buf
, 10, "F%s%s%s", p
? "L" : "",
2013 z
? "Z" : "", show_cond
? cc_flags
: "");
2015 print_insn (outf
, prefix_buf
, template->name
, buf
);
2018 /* Print an FPU extended data conversion instruction. */
2020 print_fconvx (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
2021 const insn_template
*template,
2022 disassemble_info
*outf
)
2024 char buf
[OPERAND_WIDTH
];
2025 char prefix_buf
[10];
2026 unsigned int p
= (insn_word
>> 6) & 0x1;
2027 unsigned int xl
= (insn_word
>> 7) & 0x1;
2028 unsigned int src_no
, dest_no
, fraction_bits
;
2029 unsigned int cc
= (insn_word
>> 1) & CC_MASK
;
2030 bool show_cond
= cc
!= COND_A
&& cc
!= COND_NV
;
2031 const char *dest_reg
;
2032 const char *src_reg
;
2033 const char *cc_flags
;
2035 dest_no
= (insn_word
>> 19) & REG_MASK
;
2036 src_no
= (insn_word
>> 14) & REG_MASK
;
2038 dest_reg
= lookup_reg_name (UNIT_FX
, dest_no
);
2039 src_reg
= lookup_reg_name (UNIT_FX
, src_no
);
2041 cc_flags
= lookup_fpu_scc_flags (cc
);
2044 fraction_bits
= (insn_word
>> 8) & IMM6_MASK
;
2046 fraction_bits
= (insn_word
>> 9) & IMM5_MASK
;
2048 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,#%#x", dest_reg
, src_reg
,
2051 snprintf (prefix_buf
, 10, "F%s%s", p
? "L" : "",
2052 show_cond
? cc_flags
: "");
2054 print_insn (outf
, prefix_buf
, template->name
, buf
);
2057 /* Print an FPU basic arithmetic instruction. */
2059 print_fbarith (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
2060 const insn_template
*template,
2061 disassemble_info
*outf
)
2063 char buf
[OPERAND_WIDTH
];
2064 char prefix_buf
[10];
2065 unsigned int n
= (insn_word
>> 7) & 0x1;
2066 unsigned int p
= (insn_word
>> 6) & 0x1;
2067 unsigned int d
= (insn_word
>> 5) & 0x1;
2068 unsigned int src1_no
, src2_no
, dest_no
;
2069 unsigned int cc
= (insn_word
>> 1) & CC_MASK
;
2070 bool show_cond
= cc
!= COND_A
&& cc
!= COND_NV
;
2071 const char *dest_reg
;
2072 const char *src1_reg
;
2073 const char *src2_reg
;
2074 const char *cc_flags
;
2076 dest_no
= (insn_word
>> 19) & REG_MASK
;
2077 src1_no
= (insn_word
>> 14) & REG_MASK
;
2078 src2_no
= (insn_word
>> 9) & REG_MASK
;
2080 dest_reg
= lookup_reg_name (UNIT_FX
, dest_no
);
2081 src1_reg
= lookup_reg_name (UNIT_FX
, src1_no
);
2082 src2_reg
= lookup_reg_name (UNIT_FX
, src2_no
);
2084 cc_flags
= lookup_fpu_scc_flags (cc
);
2086 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s", dest_reg
, src1_reg
, src2_reg
);
2088 snprintf (prefix_buf
, 10, "F%s%s%s%s", p
? "L" : "",
2089 d
? "D" : "", n
? "I" : "", show_cond
? cc_flags
: "");
2091 print_insn (outf
, prefix_buf
, template->name
, buf
);
2094 /* Print an FPU extended arithmetic instruction. */
2096 print_fearith (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
2097 const insn_template
*template,
2098 disassemble_info
*outf
)
2100 char buf
[OPERAND_WIDTH
];
2101 char prefix_buf
[10];
2102 bool is_muz
= MINOR_OPCODE (insn_word
) == 0x6 && ((insn_word
>> 4) & 0x1);
2103 bool is_mac
= MINOR_OPCODE (insn_word
) == 0x6 && (insn_word
& 0x1f) == 0;
2104 bool is_maw
= MINOR_OPCODE (insn_word
) == 0x6 && ((insn_word
>> 3) & 0x1);
2105 unsigned int o3o
= insn_word
& 0x1;
2106 unsigned int q
= is_muz
&& ((insn_word
>> 1) & 0x1);
2107 unsigned int n
= (insn_word
>> 7) & 0x1;
2108 unsigned int p
= (insn_word
>> 6) & 0x1;
2109 unsigned int d
= (insn_word
>> 5) & 0x1;
2110 unsigned int cc
= (insn_word
>> 1) & CC_MASK
;
2111 bool show_cond
= (MINOR_OPCODE (insn_word
) == 0x5 && cc
!= COND_A
2113 unsigned int src1_no
, src2_no
, dest_no
;
2114 const char *dest_reg
;
2115 const char *src1_reg
;
2116 const char *src2_reg
;
2117 const char *cc_flags
;
2119 dest_no
= (insn_word
>> 19) & REG_MASK
;
2120 src1_no
= (insn_word
>> 14) & REG_MASK
;
2121 src2_no
= (insn_word
>> 9) & REG_MASK
;
2123 dest_reg
= lookup_reg_name (UNIT_FX
, dest_no
);
2124 src1_reg
= lookup_reg_name (UNIT_FX
, src1_no
);
2125 src2_reg
= lookup_reg_name (UNIT_FX
, src2_no
);
2127 cc_flags
= lookup_fpu_scc_flags (cc
);
2130 snprintf (buf
, OPERAND_WIDTH
, "ACF.0,%s,%s", src1_reg
, src2_reg
);
2131 else if (o3o
&& is_maw
)
2132 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", src1_reg
, src2_reg
);
2134 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s", dest_reg
, src1_reg
, src2_reg
);
2136 snprintf (prefix_buf
, 10, "F%s%s%s%s%s", p
? "L" : "",
2137 d
? "D" : "", n
? "I" : "", q
? "Q" : "",
2138 show_cond
? cc_flags
: "");
2140 print_insn (outf
, prefix_buf
, template->name
, buf
);
2143 /* Print an FPU RCP or RSQ instruction. */
2145 print_frec (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
2146 const insn_template
*template,
2147 disassemble_info
*outf
)
2149 char buf
[OPERAND_WIDTH
];
2150 char prefix_buf
[10];
2151 unsigned int z
= (insn_word
>> 10) & 0x1;
2152 unsigned int q
= (insn_word
>> 9) & 0x1;
2153 unsigned int n
= (insn_word
>> 7) & 0x1;
2154 unsigned int p
= (insn_word
>> 6) & 0x1;
2155 unsigned int d
= (insn_word
>> 5) & 0x1;
2156 unsigned int src_no
, dest_no
;
2157 const char *dest_reg
;
2158 const char *src_reg
;
2160 dest_no
= (insn_word
>> 19) & REG_MASK
;
2161 src_no
= (insn_word
>> 14) & REG_MASK
;
2163 dest_reg
= lookup_reg_name (UNIT_FX
, dest_no
);
2164 src_reg
= lookup_reg_name (UNIT_FX
, src_no
);
2166 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", dest_reg
, src_reg
);
2168 snprintf (prefix_buf
, 10, "F%s%s%s%s%s", p
? "L" : "",
2169 d
? "D" : "", n
? "I" : "", q
? "Q" : "", z
? "Z" : "");
2171 print_insn (outf
, prefix_buf
, template->name
, buf
);
2175 print_fsimd (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
2176 const insn_template
*template,
2177 disassemble_info
*outf
)
2179 char buf
[OPERAND_WIDTH
];
2180 unsigned int n
= (insn_word
>> 7) & 0x1;
2181 unsigned int src1_no
, src2_no
, dest_no
;
2182 const char *dest_reg
;
2183 const char *src1_reg
;
2184 const char *src2_reg
;
2186 dest_no
= (insn_word
>> 19) & REG_MASK
;
2187 src1_no
= (insn_word
>> 14) & REG_MASK
;
2188 src2_no
= (insn_word
>> 9) & REG_MASK
;
2190 dest_reg
= lookup_reg_name (UNIT_FX
, dest_no
);
2191 src1_reg
= lookup_reg_name (UNIT_FX
, src1_no
);
2192 src2_reg
= lookup_reg_name (UNIT_FX
, src2_no
);
2194 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s", dest_reg
, src1_reg
, src2_reg
);
2197 print_insn (outf
, "FLI", template->name
, buf
);
2199 print_insn (outf
, "FL", template->name
, buf
);
2202 /* Print an FPU accumulator GET or SET instruction. */
2204 print_fget_set_acf (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
2205 const insn_template
*template,
2206 disassemble_info
*outf
)
2208 bool is_get
= MAJOR_OPCODE (template->meta_opcode
) == OPC_GET
;
2209 char buf
[OPERAND_WIDTH
];
2210 char addr_buf
[ADDR_WIDTH
];
2212 const char *reg_name
;
2214 part
= (insn_word
>> 19) & ACF_PART_MASK
;
2216 reg_name
= lookup_acf_name (part
);
2218 mget_mset_addr_str (addr_buf
, ADDR_WIDTH
, insn_word
);
2222 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", reg_name
, addr_buf
);
2226 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", addr_buf
, reg_name
);
2228 print_insn (outf
, "F", template->name
, buf
);
2231 /* Return the name of the DSP register or accumulator for NUM and UNIT. */
2233 __lookup_dsp_name (unsigned int num
, unsigned int unit
)
2237 for (i
= 0; i
< sizeof(metag_dsp_regtab
)/sizeof(metag_dsp_regtab
[0]); i
++)
2239 const metag_reg
*reg
= &metag_dsp_regtab
[i
];
2243 if ((reg
->unit
== UNIT_RAM_D0
|| reg
->unit
== UNIT_ACC_D0
) &&
2247 if ((reg
->unit
== UNIT_RAM_D1
|| reg
->unit
== UNIT_ACC_D1
) &&
2255 /* Return the name of the DSP register for NUM and UNIT. */
2257 lookup_dsp_name (unsigned int num
, unsigned int unit
)
2261 for (i
= 0; i
< sizeof(metag_dsp_regtab
)/sizeof(metag_dsp_regtab
[0]); i
++)
2263 const metag_reg
*reg
= &metag_dsp_regtab
[i
];
2265 if (reg
->no
== num
&& reg
->unit
== unit
)
2271 /* Return the name of the DSP RAM register for NUM and UNIT. */
2273 lookup_dspram_name (unsigned int num
, unsigned int unit
, bool load
)
2277 nentries
= sizeof(metag_dsp_tmpl_regtab
[load
])/sizeof(metag_dsp_tmpl_regtab
[load
][0]);
2279 for (i
= 0; i
< nentries
; i
++)
2281 const metag_reg
*reg
= &metag_dsp_tmpl_regtab
[load
][i
];
2283 if (reg
->no
== num
&& reg
->unit
== unit
)
2289 /* This lookup function looks up the corresponding name for a register
2290 number in a DSP instruction. SOURCE indicates whether this
2291 register is a source or destination operand. */
2293 lookup_any_reg_name (unsigned int unit
, unsigned int num
, bool source
)
2295 /* A register with the top bit set (5th bit) indicates a DSPRAM
2299 unsigned int dunit
= (unit
== UNIT_D0
) ? UNIT_RAM_D0
: UNIT_RAM_D1
;
2300 return lookup_dspram_name (num
, dunit
, source
);
2303 return lookup_reg_name (unit
, num
);
2306 /* Return the DSP data unit for UNIT. */
2307 static inline enum metag_unit
2308 dsp_data_unit_to_sym (unsigned int unit
)
2316 /* Print a DSP GET or SET instruction. */
2318 print_dget_set (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
2319 const insn_template
*template,
2320 disassemble_info
*outf
)
2322 bool is_get
= (template->meta_opcode
& 0x100);
2323 char buf
[OPERAND_WIDTH
];
2324 char addr_buf
[ADDR_WIDTH
];
2325 char prefix
[DSP_PREFIX_WIDTH
];
2327 const char *reg_name
[2];
2328 bool is_high
= false;
2329 bool is_dual
= (insn_word
& 0x4);
2330 bool is_template
= (insn_word
& 0x2);
2331 const char *base_reg
= "?";
2332 unsigned int addr_unit
, base_no
, unit
;
2334 unit
= dsp_data_unit_to_sym (insn_word
& 0x1);
2336 /* Is this a load/store to a template table? */
2339 part
= (insn_word
>> 19) & 0x1f;
2340 reg_name
[0] = lookup_dsp_name (part
, UNIT_DT
);
2344 part
= (insn_word
>> 19) & REG_MASK
;
2345 is_high
= ((part
& 0x18) == 0x18);
2347 /* Strip bit high indicator. */
2351 reg_name
[0] = __lookup_dsp_name (part
, unit
);
2355 /* Is this a dual unit DSP operation? The modulo operator below
2356 makes sure that we print the Rd register in the correct order,
2357 e.g. because there's only one bit in the instruction for the Data
2358 Unit we have to work out what the other data unit number is.
2359 (there's only 2). */
2362 unsigned int _unit
= insn_word
& 0x1;
2364 _unit
= ((_unit
+ 1) % 2);
2365 reg_name
[1] = __lookup_dsp_name(part
, dsp_data_unit_to_sym (_unit
));
2370 addr_unit
= ((insn_word
>> 18) & 0x1);
2372 addr_unit
= UNIT_A0
;
2374 addr_unit
= UNIT_A1
;
2376 base_no
= (insn_word
>> 14) & DSP_REG_MASK
;
2378 base_reg
= lookup_reg_name (addr_unit
, base_no
);
2380 /* Check if it's a post-increment/post-decrement. */
2381 if (insn_word
& 0x2000)
2383 unsigned int imm
= (insn_word
>> 9) & DGET_SET_IMM_MASK
;
2384 const char *post_op
;
2398 snprintf (addr_buf
, ADDR_WIDTH
, "[%s%s]", base_reg
, post_op
);
2402 unsigned int offset_part
= (insn_word
>> 9) & DSP_REG_MASK
;
2403 const char *offset_reg
= lookup_reg_name (addr_unit
, offset_part
);
2405 snprintf (addr_buf
, ADDR_WIDTH
, "[%s+%s++]", base_reg
, offset_reg
);
2410 if (is_dual
&& !is_template
)
2411 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s", reg_name
[0],
2412 reg_name
[1], addr_buf
);
2414 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", reg_name
[0], addr_buf
);
2418 if (is_dual
&& !is_template
)
2419 snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s", addr_buf
,
2420 reg_name
[0], reg_name
[1]);
2422 snprintf (buf
, OPERAND_WIDTH
, "%s,%s", addr_buf
, reg_name
[0]);
2425 snprintf (prefix
, DSP_PREFIX_WIDTH
, "D%s", is_high
? "H" : "");
2426 print_insn (outf
, prefix
, template->name
, buf
);
2429 /* Print a DSP template instruction. */
2431 print_dtemplate (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
2432 const insn_template
*template,
2433 disassemble_info
*outf
)
2435 char buf
[OPERAND_WIDTH
];
2436 char prefix
[DSP_PREFIX_WIDTH
];
2437 unsigned int offset
[4];
2438 bool is_half
= (MINOR_OPCODE (insn_word
) == 0x5);
2439 bool daop_only
= (MINOR_OPCODE (insn_word
) == 0x3);
2441 offset
[0] = ((insn_word
>> 19) & REG_MASK
);
2442 offset
[1] = ((insn_word
>> 14) & REG_MASK
);
2443 offset
[2] = ((insn_word
>> 9) & REG_MASK
);
2444 offset
[3] = ((insn_word
>> 4) & REG_MASK
);
2447 snprintf (buf
, OPERAND_WIDTH
, "#0x%x,#0x%x,#0x%x", offset
[0],
2448 offset
[1], offset
[2]);
2451 snprintf (buf
, OPERAND_WIDTH
, "#0x%x,#0x%x,#0x%x,#0x%x", offset
[0],
2452 offset
[1], offset
[2], offset
[3]);
2455 snprintf (prefix
, DSP_PREFIX_WIDTH
, "D%s", is_half
? "H" : "");
2456 print_insn (outf
, prefix
, template->name
, buf
);
2459 /* Format template definition from INSN_WORD into BUF. */
2461 decode_template_definition(unsigned int insn_word
, char *buf
, size_t len
)
2463 bool load
= ((insn_word
>> 13) & 0x1);
2464 bool dspram
= (((insn_word
>> 17) & 0x3) == 0x3);
2465 const char *template[1];
2466 unsigned int tidx
= ((insn_word
>> 9) & TEMPLATE_REGS_MASK
);
2467 enum metag_unit au
, ram_unit
;
2468 unsigned int addr_reg_nums
[2];
2469 const char *addr_reg_names
[2];
2470 const char *post_op
= "";
2471 const char *join_op
= "";
2472 enum metag_unit data_unit
= ((insn_word
>> 24) & 0x1) ? UNIT_D1
: UNIT_D0
;
2474 template[0] = lookup_dsp_name (tidx
, UNIT_DT
);
2476 addr_reg_names
[1] = "";
2480 ram_unit
= (data_unit
== UNIT_D0
) ? UNIT_RAM_D0
: UNIT_RAM_D1
;
2481 addr_reg_nums
[0] = ((insn_word
>> 19) & REG_MASK
);
2482 addr_reg_names
[0] = lookup_dspram_name (addr_reg_nums
[0],
2487 bool im
= (((insn_word
>> 18) & 0x1) != 0);
2489 au
= (((insn_word
>> 23) & 0x1) == 0) ? UNIT_A0
: UNIT_A1
;
2490 addr_reg_nums
[0] = ((insn_word
>> 19) & DSP_REG_MASK
);
2492 addr_reg_names
[0] = lookup_reg_name (au
, addr_reg_nums
[0]);
2496 unsigned int im_value
= ((insn_word
>> 14) & 0x3);
2510 addr_reg_nums
[1] = ((insn_word
>> 14) & DSP_REG_MASK
);
2511 addr_reg_names
[1] = lookup_reg_name (au
, addr_reg_nums
[1]);
2519 len
= snprintf (buf
, len
, " %s,[%s%s%s%s]", template[0], addr_reg_names
[0],
2520 join_op
, addr_reg_names
[1], post_op
);
2524 len
= snprintf (buf
, len
, " [%s%s%s%s],%s", addr_reg_names
[0], join_op
,
2525 addr_reg_names
[1], post_op
, template[0]);
2529 /* Print a DSP ALU instruction. */
2531 print_dalu (unsigned int insn_word
, bfd_vma pc ATTRIBUTE_UNUSED
,
2532 const insn_template
*template,
2533 disassemble_info
*outf
)
2535 bool is_dual
= false;
2536 unsigned int data_unit
= (((insn_word
>> 24) & 0x1) ? UNIT_D1
: UNIT_D0
);
2537 const char *reg_names
[3];
2538 unsigned int reg_nums
[3];
2539 bool ac
= ((insn_word
>> 7) & 0x1);
2540 char buf
[OPERAND_WIDTH
];
2541 char prefix
[DSP_PREFIX_WIDTH
];
2543 bool is_mod
= false;
2544 bool is_overflow
= false;
2545 unsigned int reg_brackets
[3];
2546 bool is_w_mx
= false;
2547 bool is_b_mx
= false;
2549 bool is_quickrot64
= false;
2550 bool conditional
= false;
2551 const char *cc_flags
= NULL
;
2552 bool is_unsigned
= false;
2554 memset (reg_brackets
, 0, sizeof (reg_brackets
));
2556 if (template->arg_type
& DSP_ARGS_1
)
2558 bool is_template
= false;
2559 const char *addr_reg
= NULL
;
2561 bool is_acc_add
= false;
2562 bool is_acc_sub
= false;
2563 bool is_acc_zero
= false;
2564 bool is_split8
= (template->arg_type
& DSP_ARGS_SPLIT8
);
2567 data_unit
= ((insn_word
>> 24) & 0x1) ? UNIT_D1
: UNIT_D0
;
2569 conditional
= ((insn_word
>> 24) & 0x4);
2571 /* Templates can't be conditional. */
2572 is_template
= (((insn_word
& 0x02000002) == 0x2) && !conditional
);
2575 is_mod
= (insn_word
& 0x80);
2577 if (template->arg_type
& DSP_ARGS_QR
)
2580 is_quickrot64
= ((insn_word
>> 5) & 0x1);
2583 if (template->arg_type
& DSP_ARGS_DACC
)
2585 is_mod
= (insn_word
& 0x8);
2586 is_unsigned
= (insn_word
& 0x40);
2591 is_w_mx
= (insn_word
& 0x1);
2592 is_dual
= ((insn_word
>> 0x4) & 0x1);
2594 /* De.r,Dx.r,De.r|ACe.r */
2595 if (template->arg_type
& DSP_ARGS_ACC2
)
2597 is_mod
= (insn_word
& 0x8);
2598 is_overflow
= (insn_word
& 0x20);
2601 /* ACe.e,ACx.r,ACo.e? */
2602 if ((template->arg_type
& DSP_ARGS_XACC
) &&
2603 (((insn_word
>> 6) & 0x5) == 0x5))
2605 enum metag_unit ac_unit
, ao_unit
;
2607 ac_unit
= (data_unit
== UNIT_D0
) ? UNIT_ACC_D0
: UNIT_ACC_D1
;
2609 if (ac_unit
== UNIT_ACC_D0
)
2610 ao_unit
= UNIT_ACC_D1
;
2612 ao_unit
= UNIT_ACC_D0
;
2614 reg_nums
[1] = ((insn_word
>> 19) & REG_MASK
);
2616 /* These are dummy arguments anyway so the register
2617 number does not matter. */
2618 reg_names
[0] = lookup_dsp_name (16, ac_unit
); /* ACe.0 */
2619 reg_names
[1] = lookup_dsp_name (16, ac_unit
); /* ACx.0 */
2620 reg_names
[2] = lookup_dsp_name (16, ao_unit
); /* ACo.0 */
2624 /* De.r|ACe.r,Dx.r,De.r */
2625 if (template->arg_type
& DSP_ARGS_DACC
&&
2626 ((insn_word
& 0x84) != 0))
2628 enum metag_unit ac_unit
;
2630 ac_unit
= (data_unit
== UNIT_D0
) ? UNIT_ACC_D0
: UNIT_ACC_D1
;
2631 reg_names
[0] = lookup_dsp_name (16, ac_unit
);
2633 is_acc_zero
= ((insn_word
& 0x84) == 0x04);
2634 is_acc_add
= ((insn_word
& 0x84) == 0x80);
2635 is_acc_sub
= ((insn_word
& 0x84) == 0x84);
2638 reg_names
[0] = lookup_any_reg_name (data_unit
, 0, false);
2640 /* These are dummy arguments anyway so the register
2641 number does not matter. */
2642 reg_names
[1] = lookup_any_reg_name (data_unit
, 0, true);
2644 /* De.r,Dx.r,De.r|ACe.r */
2645 if ((template->arg_type
& DSP_ARGS_ACC2
) &&
2646 ((insn_word
& 0x80) == 0x80))
2648 enum metag_unit ac_unit
;
2650 ac_unit
= (data_unit
== UNIT_D0
) ? UNIT_ACC_D0
: UNIT_ACC_D1
;
2651 reg_names
[2] = lookup_dsp_name (16, ac_unit
);
2653 /* Detection of QUICKRoT and accumulator usage uses the
2654 same bits. They are mutually exclusive. */
2655 else if (ac
&& (template->arg_type
& DSP_ARGS_ACC2
))
2657 reg_nums
[2] = ((insn_word
>> 9) & REG_MASK
);
2659 if (data_unit
== UNIT_D0
)
2660 reg_names
[2] = lookup_dsp_name (reg_nums
[2], UNIT_ACC_D0
);
2662 reg_names
[2] = lookup_dsp_name (reg_nums
[2], UNIT_ACC_D1
);
2666 if ((template->arg_type
& DSP_ARGS_QR
) &&
2667 ((insn_word
& 0x40) == 0x40))
2669 enum metag_unit aunit
;
2673 reg_no
= ((insn_word
>> 5) & 0x1);
2675 reg_no
= ((insn_word
>> 7) & 0x1);
2677 aunit
= (data_unit
== UNIT_D0
) ? UNIT_A0
: UNIT_A1
;
2678 addr_reg
= lookup_reg_name (aunit
, reg_no
+ 2);
2683 reg_names
[2] = lookup_any_reg_name (data_unit
, 0, true);
2689 len
= snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s,%s",
2690 reg_names
[0], reg_names
[1], reg_names
[2],
2695 len
= snprintf (buf
, OPERAND_WIDTH
, "%s,%s,%s%s%s",
2696 reg_names
[0], reg_names
[1],
2697 reg_brackets
[2] ? "[" : "",
2698 reg_names
[2], reg_brackets
[2] ? "]" : "");
2701 decode_template_definition (insn_word
, buf
+ len
,
2702 OPERAND_WIDTH
- len
);
2704 else /* Not a template definiton. */
2706 reg_nums
[0] = ((insn_word
>> 19) & REG_MASK
);
2707 reg_nums
[1] = ((insn_word
>> 14) & REG_MASK
);
2708 reg_nums
[2] = ((insn_word
>> 9) & REG_MASK
);
2710 imm
= (((insn_word
>> 24) & 0x2) && (template->arg_type
& DSP_ARGS_IMM
));
2713 is_dual
= (insn_word
& 0x4);
2714 else if (!conditional
)
2715 is_dual
= (insn_word
& 0x10);
2717 cc_flags
= lookup_scc_flags ((insn_word
>> 1) & CC_MASK
);
2719 /* De.r,Dx.r,De.r|ACe.r */
2720 if (template->arg_type
& DSP_ARGS_ACC2
)
2722 is_mod
= (insn_word
& 0x8);
2723 is_overflow
= (insn_word
& 0x20);
2726 if (template->arg_type
& DSP_ARGS_SPLIT8
)
2728 is_overflow
= (insn_word
& 0x20);
2731 /* ACe.e,ACx.r,ACo.e? */
2732 if ((template->arg_type
& DSP_ARGS_XACC
) &&
2733 (((insn_word
>> 6) & 0x5) == 0x5))
2735 enum metag_unit ac_unit
, ao_unit
;
2737 ac_unit
= (data_unit
== UNIT_D0
) ? UNIT_ACC_D0
: UNIT_ACC_D1
;
2739 if (ac_unit
== UNIT_ACC_D0
)
2740 ao_unit
= UNIT_ACC_D1
;
2742 ao_unit
= UNIT_ACC_D0
;
2744 reg_nums
[1] = ((insn_word
>> 19) & REG_MASK
);
2745 reg_names
[0] = lookup_dsp_name (reg_nums
[1], ac_unit
);
2746 reg_names
[1] = lookup_dsp_name (reg_nums
[1], ac_unit
);
2747 reg_names
[2] = lookup_dsp_name (reg_nums
[1], ao_unit
);
2751 bool o2r
= (insn_word
& 0x1);
2753 /* De.r|ACe.r,Dx.r,De.r */
2754 if ((template->arg_type
& DSP_ARGS_DACC
) &&
2755 ((insn_word
& 0x84) != 0))
2757 enum metag_unit ac_unit
;
2759 ac_unit
= (data_unit
== UNIT_D0
) ? UNIT_ACC_D0
: UNIT_ACC_D1
;
2760 reg_names
[0] = lookup_dsp_name (reg_nums
[0], ac_unit
);
2762 is_acc_zero
= ((insn_word
& 0x84) == 0x04);
2763 is_acc_add
= ((insn_word
& 0x84) == 0x80);
2764 is_acc_sub
= ((insn_word
& 0x84) == 0x84);
2766 else if (conditional
)
2768 reg_names
[0] = lookup_reg_name (data_unit
, reg_nums
[0]);
2772 reg_names
[0] = lookup_any_reg_name (data_unit
,
2773 reg_nums
[0], false);
2774 if (reg_nums
[0] > 15)
2775 reg_brackets
[0] = 1;
2780 reg_names
[1] = lookup_any_reg_name (data_unit
, reg_nums
[0], true);
2782 if (reg_brackets
[0])
2783 reg_brackets
[1] = 1;
2787 if (is_split8
&& is_mod
)
2789 reg_names
[1] = lookup_reg_name (data_unit
, reg_nums
[1]);
2793 reg_names
[1] = lookup_any_reg_name (data_unit
, reg_nums
[1], true);
2795 if (reg_nums
[1] > 15)
2796 reg_brackets
[1] = 1;
2800 /* Detection of QUICKRoT and accumulator usage uses the
2801 same bits. They are mutually exclusive. */
2802 if (ac
&& (template->arg_type
& DSP_ARGS_ACC2
))
2804 if (data_unit
== UNIT_D0
)
2805 reg_names
[2] = lookup_dsp_name (reg_nums
[2], UNIT_ACC_D0
);
2807 reg_names
[2] = lookup_dsp_name (reg_nums
[2], UNIT_ACC_D1
);
2812 if ((template->arg_type
& DSP_ARGS_QR
) &&
2813 ((insn_word
& 0x40) == 0x40))
2815 enum metag_unit aunit
;
2819 reg_no
= ((insn_word
>> 5) & 0x1);
2821 reg_no
= ((insn_word
>> 7) & 0x1);
2823 aunit
= (data_unit
== UNIT_D0
) ? UNIT_A0
: UNIT_A1
;
2824 addr_reg
= lookup_reg_name (aunit
, reg_no
+ 2);
2830 reg_names
[2] = lookup_o2r (data_unit
, reg_nums
[2]);
2833 /* Can't use a DSPRAM reg if both QD and L1 are
2834 set on a QUICKRoT instruction or if we're a
2836 if (((template->arg_type
& DSP_ARGS_QR
)
2837 && ((insn_word
& 0x30) == 0x30 && !conditional
)) ||
2838 (is_split8
&& is_mod
))
2839 reg_names
[2] = lookup_reg_name (data_unit
, reg_nums
[2]);
2842 reg_names
[2] = lookup_any_reg_name (data_unit
,
2844 if (reg_nums
[2] > 15)
2845 reg_brackets
[2] = 1;
2853 len
= snprintf (buf
, OPERAND_WIDTH
, "%s%s%s,%s%s%s,%s%s%s,%s",
2854 reg_brackets
[0] ? "[" : "",
2855 reg_names
[0], reg_brackets
[0] ? "]" : "",
2856 reg_brackets
[1] ? "[" : "",
2857 reg_names
[1], reg_brackets
[1] ? "]" : "",
2858 reg_brackets
[2] ? "[" : "",
2859 reg_names
[2], reg_brackets
[2] ? "]" : "",
2866 /* Conform to the embedded assembler's policy of
2867 printing negative numbers as decimal and positive
2869 int value
= ((insn_word
>> 3) & IMM16_MASK
);
2871 if ((value
& 0x8000) || value
== 0)
2873 value
= sign_extend (value
, IMM16_BITS
);
2874 len
= snprintf (buf
, OPERAND_WIDTH
, "%s%s%s,%s%s%s,#%d",
2875 reg_brackets
[0] ? "[" : "",
2876 reg_names
[0], reg_brackets
[0] ? "]" : "",
2877 reg_brackets
[1] ? "[" : "",
2878 reg_names
[1], reg_brackets
[1] ? "]" : "",
2883 len
= snprintf (buf
, OPERAND_WIDTH
, "%s%s%s,%s%s%s,#%#x",
2884 reg_brackets
[0] ? "[" : "",
2885 reg_names
[0], reg_brackets
[0] ? "]" : "",
2886 reg_brackets
[1] ? "[" : "",
2887 reg_names
[1], reg_brackets
[1] ? "]" : "",
2893 len
= snprintf (buf
, OPERAND_WIDTH
, "%s%s%s,%s%s%s,%s%s%s",
2894 reg_brackets
[0] ? "[" : "",
2895 reg_names
[0], reg_brackets
[0] ? "]" : "",
2896 reg_brackets
[1] ? "[" : "", reg_names
[1],
2897 reg_brackets
[1] ? "]" : "",
2898 reg_brackets
[2] ? "[" : "",
2899 reg_names
[2], reg_brackets
[2] ? "]" : "");
2904 snprintf (prefix
, DSP_PREFIX_WIDTH
, "D%s%s%s%s%s%s%s%s%s%s%s%s",
2905 cc_flags
? cc_flags
: "",
2907 is_quickrot64
? "Q" : "",
2908 is_unsigned
? "U" : "",
2910 is_acc_zero
? "Z" : "",
2911 is_acc_add
? "P" : "", is_acc_sub
? "N" : "",
2912 is_overflow
? "O" : "",
2915 is_template
? "T" : "");
2917 else if (template->arg_type
& DSP_ARGS_2
) /* Group 2. */
2921 int major
= MAJOR_OPCODE (template->meta_opcode
);
2922 bool is_neg_or_mov
= (major
== OPC_ADD
|| major
== OPC_SUB
);
2923 bool is_cmp_tst
= major
== OPC_CMP
&& (insn_word
& 0x0000002c) == 0;
2924 bool is_fpu_mov
= template->insn_type
== INSN_DSP_FPU
;
2925 bool to_fpu
= (template->meta_opcode
>> 7) & 0x1;
2928 imm
= (insn_word
& 0x2);
2929 else if (template->arg_type
& DSP_ARGS_IMM
)
2930 imm
= ((insn_word
>> 25) & 0x1);
2932 is_template
= (((insn_word
& 0x02000002) == 0x2) &&
2936 is_dual
= ((insn_word
>> 0x2) & 0x1);
2938 is_dual
= ((insn_word
>> 0x4) & 0x1);
2940 /* MOV and XSD[BW] do not have o2r. */
2941 if (major
!= OPC_9
&& major
!= OPC_MISC
)
2942 o2r
= (insn_word
& 0x1);
2946 is_mod
= (insn_word
& 0x8);
2947 is_overflow
= (insn_word
& 0x20);
2951 if (major
== OPC_MISC
)
2952 data_unit
= (insn_word
& 0x1) ? UNIT_D1
: UNIT_D0
;
2954 data_unit
= ((insn_word
>> 24) & 0x1) ? UNIT_D1
: UNIT_D0
;
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
);
2962 reg_nums
[0] = ((insn_word
>> 14) & REG_MASK
);
2966 is_w_mx
= (insn_word
& 0x1);
2968 /* These are dummy arguments anyway so the register number
2974 reg_names
[0] = lookup_reg_name (UNIT_FX
, 0);
2975 reg_names
[1] = lookup_reg_name (data_unit
, 0);
2979 reg_names
[0] = lookup_reg_name (data_unit
, 0);
2980 reg_names
[1] = lookup_reg_name (UNIT_FX
, 0);
2985 reg_names
[0] = lookup_reg_name (data_unit
, 0);
2986 reg_names
[1] = lookup_reg_name (data_unit
, 0);
2989 len
= snprintf (buf
, OPERAND_WIDTH
, "%s,%s",
2990 reg_names
[0], reg_names
[1]);
2992 decode_template_definition (insn_word
, buf
+ len
,
2993 OPERAND_WIDTH
- len
);
2999 /* Conform to the embedded assembler's policy of
3000 printing negative numbers as decimal and positive as
3002 unsigned int value
= ((insn_word
>> 3) & IMM16_MASK
);
3006 data_unit
= (insn_word
& 0x1) ? UNIT_D1
: UNIT_D0
;
3007 is_dual
= (insn_word
& 0x4);
3009 reg_names
[0] = __lookup_dsp_name (reg_nums
[0], data_unit
);
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;
3018 if ((value
& 0x8000) || value
== 0)
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] ? "]" : "",
3028 snprintf (buf
, OPERAND_WIDTH
, "%s%s%s,#0x%x",
3029 reg_brackets
[0] ? "[" : "",
3030 reg_names
[0], reg_brackets
[0] ? "]" : "",
3036 if (is_neg_or_mov
|| is_cmp_tst
)
3037 reg_nums
[1] = ((insn_word
>> 9) & REG_MASK
);
3039 reg_nums
[1] = ((insn_word
>> 14) & REG_MASK
);
3043 is_dual
= (insn_word
& 0x4);
3044 data_unit
= (insn_word
& 0x1) ? UNIT_D1
: UNIT_D0
;
3046 if (MINOR_OPCODE (template->meta_opcode
) == 0x1)
3047 reg_names
[0] = __lookup_dsp_name (reg_nums
[0], data_unit
);
3049 reg_names
[0] = lookup_reg_name (data_unit
, reg_nums
[0]);
3053 unsigned int reg0_unit
= data_unit
;
3055 if (is_fpu_mov
&& to_fpu
)
3056 reg0_unit
= UNIT_FX
;
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;
3065 reg_names
[1] = lookup_o2r (data_unit
, reg_nums
[1]);
3068 /* Check for accumulator argument. */
3069 if (is_neg_or_mov
&& ((insn_word
& 0x80) == 0x80))
3071 if (data_unit
== UNIT_D0
)
3072 reg_names
[1] = lookup_dsp_name (reg_nums
[1], UNIT_ACC_D0
);
3074 reg_names
[1] = lookup_dsp_name (reg_nums
[1], UNIT_ACC_D1
);
3080 if (MINOR_OPCODE (template->meta_opcode
) == 0x1)
3082 reg_names
[1] = lookup_reg_name (data_unit
, reg_nums
[1]);
3088 u
= (insn_word
& 0x1) ? UNIT_RAM_D1
: UNIT_RAM_D0
;
3089 reg_names
[1] = lookup_dsp_name (reg_nums
[1], u
);
3094 reg_names
[1] = lookup_any_reg_name (data_unit
,
3096 if (reg_nums
[1] > 15)
3097 reg_brackets
[1] = 1;
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] ? "]" : "");
3110 snprintf (prefix
, DSP_PREFIX_WIDTH
, "D%s%s%s%s%s%s",
3111 is_fpu_mov
? "F" : "",
3113 is_mod
? "M" : "", is_overflow
? "O" : "",
3115 is_template
? "T" : "");
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 bool 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
;
3125 bool clamp9
= false;
3126 bool clamp8
= false;
3127 bool is_template
= ((insn_word
& 0x04000002) == 0x2);
3129 imm
= ((insn_word
>> 25) & 0x1);
3130 ac
= (insn_word
& 0x1);
3132 conditional
= (MINOR_OPCODE (insn_word
) & 0x4);
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);
3140 /* Conditional instructions don't have the L1 or RSPP fields. */
3141 if ((insn_word
& 0x04000000) == 0)
3143 round
= (((insn_word
>> 2) & 0x3) == 0x1);
3144 clamp9
= (((insn_word
>> 2) & 0x3) == 0x2);
3145 clamp8
= (((insn_word
>> 2) & 0x3) == 0x3);
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
);
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
;
3157 reg_names
[0] = lookup_reg_name (ud_unit
, reg_nums
[0]);
3161 reg_names
[0] = lookup_reg_name (data_unit
, reg_nums
[0]);
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;
3172 reg_names
[1] = lookup_dsp_name (reg_nums
[1], acc_unit
);
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;
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
));
3192 reg_nums
[2] = ((insn_word
>> 9) & REG_MASK
);
3194 reg_names
[2] = lookup_any_reg_name (data_unit
, reg_nums
[2], true);
3196 if (reg_nums
[2] > 15)
3197 reg_brackets
[2] = 1;
3201 bool load
= ((insn_word
>> 13) & 0x1);
3202 bool dspram
= (((insn_word
>> 17) & 0x3) == 0x3);
3203 const char *tname
[1];
3204 unsigned int tidx
= ((insn_word
>> 9) & TEMPLATE_REGS_MASK
);
3206 unsigned int addr_reg_nums
[2];
3207 const char *addr_reg_names
[2];
3208 const char *post_op
= "";
3209 const char *join_op
= "";
3211 is_w_mx
= ((insn_word
>> 5) & 0x1);
3213 tname
[0] = lookup_dsp_name (tidx
, UNIT_DT
);
3215 /* These are dummy arguments anyway */
3216 reg_names
[0] = lookup_reg_name (data_unit
, 0);
3218 reg_names
[1] = lookup_dsp_name (16, acc_unit
);
3220 reg_names
[1] = lookup_reg_name (data_unit
, 0);
3221 reg_names
[2] = lookup_reg_name (data_unit
, 0);
3223 addr_reg_names
[1] = "";
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],
3234 bool im
= (((insn_word
>> 18) & 0x1) != 0);
3236 au
= (((insn_word
>> 23) & 0x1) == 0) ? UNIT_A0
: UNIT_A1
;
3237 addr_reg_nums
[0] = ((insn_word
>> 19) & DSP_REG_MASK
);
3239 addr_reg_names
[0] = lookup_reg_name (au
, addr_reg_nums
[0]);
3243 unsigned int im_value
= ((insn_word
>> 14) & 0x3);
3257 addr_reg_nums
[1] = ((insn_word
>> 14) & DSP_REG_MASK
);
3258 addr_reg_names
[1] = lookup_reg_name (au
, addr_reg_nums
[1]);
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
);
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],
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] ? "]" : "");
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" : "",
3296 is_template
? "T" : "");
3299 print_insn (outf
, prefix
, template->name
, buf
);
3303 typedef void (*insn_printer
)(unsigned int, bfd_vma
, const insn_template
*,
3304 disassemble_info
*);
3306 /* Printer table. */
3307 static const insn_printer insn_printers
[ENC_MAX
] =
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
,
3356 /* Entry point for instruction printing. */
3358 print_insn_metag (bfd_vma pc
, disassemble_info
*outf
)
3361 unsigned int insn_word
;
3365 outf
->bytes_per_chunk
= 4;
3366 status
= (*outf
->read_memory_func
) (pc
& ~0x03, buf
, 4, outf
);
3369 (*outf
->memory_error_func
) (status
, pc
, outf
);
3372 insn_word
= bfd_getl32 (buf
);
3374 for (i
= 0; i
< sizeof(metag_optab
)/sizeof(metag_optab
[0]); i
++)
3376 const insn_template
*template = &metag_optab
[i
];
3378 if ((insn_word
& template->meta_mask
) == template->meta_opcode
)
3380 enum insn_encoding encoding
= template->encoding
;
3381 insn_printer printer
= insn_printers
[encoding
];
3384 printer (insn_word
, pc
, template, outf
);