198f124a6Schristos /* DO NOT EDIT!  -*- buffer-read-only: t -*- vi:set ro:  */
22a6b7db3Sskrll /* Disassembler interface for targets using CGEN. -*- C -*-
32a6b7db3Sskrll    CGEN: Cpu tools GENerator
42a6b7db3Sskrll 
52a6b7db3Sskrll    THIS FILE IS MACHINE GENERATED WITH CGEN.
62a6b7db3Sskrll    - the resultant file is machine generated, cgen-dis.in isn't
72a6b7db3Sskrll 
8*f22f0ef4Schristos    Copyright (C) 1996-2022 Free Software Foundation, Inc.
92a6b7db3Sskrll 
102a6b7db3Sskrll    This file is part of libopcodes.
112a6b7db3Sskrll 
122a6b7db3Sskrll    This library is free software; you can redistribute it and/or modify
132a6b7db3Sskrll    it under the terms of the GNU General Public License as published by
142a6b7db3Sskrll    the Free Software Foundation; either version 3, or (at your option)
152a6b7db3Sskrll    any later version.
162a6b7db3Sskrll 
172a6b7db3Sskrll    It is distributed in the hope that it will be useful, but WITHOUT
182a6b7db3Sskrll    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
192a6b7db3Sskrll    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
202a6b7db3Sskrll    License for more details.
212a6b7db3Sskrll 
222a6b7db3Sskrll    You should have received a copy of the GNU General Public License
232a6b7db3Sskrll    along with this program; if not, write to the Free Software Foundation, Inc.,
242a6b7db3Sskrll    51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
252a6b7db3Sskrll 
262a6b7db3Sskrll /* ??? Eventually more and more of this stuff can go to cpu-independent files.
272a6b7db3Sskrll    Keep that in mind.  */
282a6b7db3Sskrll 
292a6b7db3Sskrll #include "sysdep.h"
302a6b7db3Sskrll #include <stdio.h>
312a6b7db3Sskrll #include "ansidecl.h"
3298f124a6Schristos #include "disassemble.h"
332a6b7db3Sskrll #include "bfd.h"
342a6b7db3Sskrll #include "symcat.h"
352a6b7db3Sskrll #include "libiberty.h"
362a6b7db3Sskrll #include "fr30-desc.h"
372a6b7db3Sskrll #include "fr30-opc.h"
382a6b7db3Sskrll #include "opintl.h"
392a6b7db3Sskrll 
402a6b7db3Sskrll /* Default text to print if an instruction isn't recognized.  */
412a6b7db3Sskrll #define UNKNOWN_INSN_MSG _("*unknown*")
422a6b7db3Sskrll 
432a6b7db3Sskrll static void print_normal
442a6b7db3Sskrll   (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
452a6b7db3Sskrll static void print_address
462a6b7db3Sskrll   (CGEN_CPU_DESC, void *, bfd_vma, unsigned int, bfd_vma, int) ATTRIBUTE_UNUSED;
472a6b7db3Sskrll static void print_keyword
482a6b7db3Sskrll   (CGEN_CPU_DESC, void *, CGEN_KEYWORD *, long, unsigned int) ATTRIBUTE_UNUSED;
492a6b7db3Sskrll static void print_insn_normal
502a6b7db3Sskrll   (CGEN_CPU_DESC, void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int);
512a6b7db3Sskrll static int print_insn
522a6b7db3Sskrll   (CGEN_CPU_DESC, bfd_vma,  disassemble_info *, bfd_byte *, unsigned);
532a6b7db3Sskrll static int default_print_insn
542a6b7db3Sskrll   (CGEN_CPU_DESC, bfd_vma, disassemble_info *) ATTRIBUTE_UNUSED;
552a6b7db3Sskrll static int read_insn
562a6b7db3Sskrll   (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, int, CGEN_EXTRACT_INFO *,
572a6b7db3Sskrll    unsigned long *);
582a6b7db3Sskrll 
592a6b7db3Sskrll /* -- disassembler routines inserted here.  */
602a6b7db3Sskrll 
612a6b7db3Sskrll /* -- dis.c */
622a6b7db3Sskrll static void
print_register_list(void * dis_info,long value,long offset,int load_store)632a6b7db3Sskrll print_register_list (void * dis_info,
642a6b7db3Sskrll 		     long value,
652a6b7db3Sskrll 		     long offset,
662a6b7db3Sskrll 		     int load_store) /* 0 == load, 1 == store.  */
672a6b7db3Sskrll {
682a6b7db3Sskrll   disassemble_info *info = dis_info;
692a6b7db3Sskrll   int mask;
70b3ac4aedSchristos   int reg_index = 0;
712a6b7db3Sskrll   char * comma = "";
722a6b7db3Sskrll 
732a6b7db3Sskrll   if (load_store)
742a6b7db3Sskrll     mask = 0x80;
752a6b7db3Sskrll   else
762a6b7db3Sskrll     mask = 1;
772a6b7db3Sskrll 
782a6b7db3Sskrll   if (value & mask)
792a6b7db3Sskrll     {
80b3ac4aedSchristos       (*info->fprintf_func) (info->stream, "r%li", reg_index + offset);
812a6b7db3Sskrll       comma = ",";
822a6b7db3Sskrll     }
832a6b7db3Sskrll 
84b3ac4aedSchristos   for (reg_index = 1; reg_index <= 7; ++reg_index)
852a6b7db3Sskrll     {
862a6b7db3Sskrll       if (load_store)
872a6b7db3Sskrll 	mask >>= 1;
882a6b7db3Sskrll       else
892a6b7db3Sskrll 	mask <<= 1;
902a6b7db3Sskrll 
912a6b7db3Sskrll       if (value & mask)
922a6b7db3Sskrll 	{
93b3ac4aedSchristos 	  (*info->fprintf_func) (info->stream, "%sr%li", comma, reg_index + offset);
942a6b7db3Sskrll 	  comma = ",";
952a6b7db3Sskrll 	}
962a6b7db3Sskrll     }
972a6b7db3Sskrll }
982a6b7db3Sskrll 
992a6b7db3Sskrll static void
print_hi_register_list_ld(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,long value,unsigned int attrs ATTRIBUTE_UNUSED,bfd_vma pc ATTRIBUTE_UNUSED,int length ATTRIBUTE_UNUSED)1002a6b7db3Sskrll print_hi_register_list_ld (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1012a6b7db3Sskrll 			   void * dis_info,
1022a6b7db3Sskrll 			   long value,
1032a6b7db3Sskrll 			   unsigned int attrs ATTRIBUTE_UNUSED,
1042a6b7db3Sskrll 			   bfd_vma pc ATTRIBUTE_UNUSED,
1052a6b7db3Sskrll 			   int length ATTRIBUTE_UNUSED)
1062a6b7db3Sskrll {
1072a6b7db3Sskrll   print_register_list (dis_info, value, 8, 0 /* Load.  */);
1082a6b7db3Sskrll }
1092a6b7db3Sskrll 
1102a6b7db3Sskrll static void
print_low_register_list_ld(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,long value,unsigned int attrs ATTRIBUTE_UNUSED,bfd_vma pc ATTRIBUTE_UNUSED,int length ATTRIBUTE_UNUSED)1112a6b7db3Sskrll print_low_register_list_ld (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1122a6b7db3Sskrll 			    void * dis_info,
1132a6b7db3Sskrll 			    long value,
1142a6b7db3Sskrll 			    unsigned int attrs ATTRIBUTE_UNUSED,
1152a6b7db3Sskrll 			    bfd_vma pc ATTRIBUTE_UNUSED,
1162a6b7db3Sskrll 			    int length ATTRIBUTE_UNUSED)
1172a6b7db3Sskrll {
1182a6b7db3Sskrll   print_register_list (dis_info, value, 0, 0 /* Load.  */);
1192a6b7db3Sskrll }
1202a6b7db3Sskrll 
1212a6b7db3Sskrll static void
print_hi_register_list_st(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,long value,unsigned int attrs ATTRIBUTE_UNUSED,bfd_vma pc ATTRIBUTE_UNUSED,int length ATTRIBUTE_UNUSED)1222a6b7db3Sskrll print_hi_register_list_st (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1232a6b7db3Sskrll 			   void * dis_info,
1242a6b7db3Sskrll 			   long value,
1252a6b7db3Sskrll 			   unsigned int attrs ATTRIBUTE_UNUSED,
1262a6b7db3Sskrll 			   bfd_vma pc ATTRIBUTE_UNUSED,
1272a6b7db3Sskrll 			   int length ATTRIBUTE_UNUSED)
1282a6b7db3Sskrll {
1292a6b7db3Sskrll   print_register_list (dis_info, value, 8, 1 /* Store.  */);
1302a6b7db3Sskrll }
1312a6b7db3Sskrll 
1322a6b7db3Sskrll static void
print_low_register_list_st(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,long value,unsigned int attrs ATTRIBUTE_UNUSED,bfd_vma pc ATTRIBUTE_UNUSED,int length ATTRIBUTE_UNUSED)1332a6b7db3Sskrll print_low_register_list_st (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1342a6b7db3Sskrll 			    void * dis_info,
1352a6b7db3Sskrll 			    long value,
1362a6b7db3Sskrll 			    unsigned int attrs ATTRIBUTE_UNUSED,
1372a6b7db3Sskrll 			    bfd_vma pc ATTRIBUTE_UNUSED,
1382a6b7db3Sskrll 			    int length ATTRIBUTE_UNUSED)
1392a6b7db3Sskrll {
1402a6b7db3Sskrll   print_register_list (dis_info, value, 0, 1 /* Store.  */);
1412a6b7db3Sskrll }
1422a6b7db3Sskrll 
1432a6b7db3Sskrll static void
print_m4(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,long value,unsigned int attrs ATTRIBUTE_UNUSED,bfd_vma pc ATTRIBUTE_UNUSED,int length ATTRIBUTE_UNUSED)1442a6b7db3Sskrll print_m4 (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1452a6b7db3Sskrll 	  void * dis_info,
1462a6b7db3Sskrll 	  long value,
1472a6b7db3Sskrll 	  unsigned int attrs ATTRIBUTE_UNUSED,
1482a6b7db3Sskrll 	  bfd_vma pc ATTRIBUTE_UNUSED,
1492a6b7db3Sskrll 	  int length ATTRIBUTE_UNUSED)
1502a6b7db3Sskrll {
1512a6b7db3Sskrll   disassemble_info *info = (disassemble_info *) dis_info;
1522a6b7db3Sskrll 
1532a6b7db3Sskrll   (*info->fprintf_func) (info->stream, "%ld", value);
1542a6b7db3Sskrll }
1552a6b7db3Sskrll /* -- */
1562a6b7db3Sskrll 
1572a6b7db3Sskrll void fr30_cgen_print_operand
158*f22f0ef4Schristos   (CGEN_CPU_DESC, int, void *, CGEN_FIELDS *, void const *, bfd_vma, int);
1592a6b7db3Sskrll 
1602a6b7db3Sskrll /* Main entry point for printing operands.
1612a6b7db3Sskrll    XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
1622a6b7db3Sskrll    of dis-asm.h on cgen.h.
1632a6b7db3Sskrll 
1642a6b7db3Sskrll    This function is basically just a big switch statement.  Earlier versions
1652a6b7db3Sskrll    used tables to look up the function to use, but
1662a6b7db3Sskrll    - if the table contains both assembler and disassembler functions then
1672a6b7db3Sskrll      the disassembler contains much of the assembler and vice-versa,
1682a6b7db3Sskrll    - there's a lot of inlining possibilities as things grow,
1692a6b7db3Sskrll    - using a switch statement avoids the function call overhead.
1702a6b7db3Sskrll 
1712a6b7db3Sskrll    This function could be moved into `print_insn_normal', but keeping it
1722a6b7db3Sskrll    separate makes clear the interface between `print_insn_normal' and each of
1732a6b7db3Sskrll    the handlers.  */
1742a6b7db3Sskrll 
1752a6b7db3Sskrll void
fr30_cgen_print_operand(CGEN_CPU_DESC cd,int opindex,void * xinfo,CGEN_FIELDS * fields,void const * attrs ATTRIBUTE_UNUSED,bfd_vma pc,int length)1762a6b7db3Sskrll fr30_cgen_print_operand (CGEN_CPU_DESC cd,
1772a6b7db3Sskrll 			   int opindex,
1782a6b7db3Sskrll 			   void * xinfo,
1792a6b7db3Sskrll 			   CGEN_FIELDS *fields,
1802a6b7db3Sskrll 			   void const *attrs ATTRIBUTE_UNUSED,
1812a6b7db3Sskrll 			   bfd_vma pc,
1822a6b7db3Sskrll 			   int length)
1832a6b7db3Sskrll {
1842a6b7db3Sskrll   disassemble_info *info = (disassemble_info *) xinfo;
1852a6b7db3Sskrll 
1862a6b7db3Sskrll   switch (opindex)
1872a6b7db3Sskrll     {
1882a6b7db3Sskrll     case FR30_OPERAND_CRI :
1892a6b7db3Sskrll       print_keyword (cd, info, & fr30_cgen_opval_cr_names, fields->f_CRi, 0);
1902a6b7db3Sskrll       break;
1912a6b7db3Sskrll     case FR30_OPERAND_CRJ :
1922a6b7db3Sskrll       print_keyword (cd, info, & fr30_cgen_opval_cr_names, fields->f_CRj, 0);
1932a6b7db3Sskrll       break;
1942a6b7db3Sskrll     case FR30_OPERAND_R13 :
1952a6b7db3Sskrll       print_keyword (cd, info, & fr30_cgen_opval_h_r13, 0, 0);
1962a6b7db3Sskrll       break;
1972a6b7db3Sskrll     case FR30_OPERAND_R14 :
1982a6b7db3Sskrll       print_keyword (cd, info, & fr30_cgen_opval_h_r14, 0, 0);
1992a6b7db3Sskrll       break;
2002a6b7db3Sskrll     case FR30_OPERAND_R15 :
2012a6b7db3Sskrll       print_keyword (cd, info, & fr30_cgen_opval_h_r15, 0, 0);
2022a6b7db3Sskrll       break;
2032a6b7db3Sskrll     case FR30_OPERAND_RI :
2042a6b7db3Sskrll       print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Ri, 0);
2052a6b7db3Sskrll       break;
2062a6b7db3Sskrll     case FR30_OPERAND_RIC :
2072a6b7db3Sskrll       print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Ric, 0);
2082a6b7db3Sskrll       break;
2092a6b7db3Sskrll     case FR30_OPERAND_RJ :
2102a6b7db3Sskrll       print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Rj, 0);
2112a6b7db3Sskrll       break;
2122a6b7db3Sskrll     case FR30_OPERAND_RJC :
2132a6b7db3Sskrll       print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Rjc, 0);
2142a6b7db3Sskrll       break;
2152a6b7db3Sskrll     case FR30_OPERAND_RS1 :
2162a6b7db3Sskrll       print_keyword (cd, info, & fr30_cgen_opval_dr_names, fields->f_Rs1, 0);
2172a6b7db3Sskrll       break;
2182a6b7db3Sskrll     case FR30_OPERAND_RS2 :
2192a6b7db3Sskrll       print_keyword (cd, info, & fr30_cgen_opval_dr_names, fields->f_Rs2, 0);
2202a6b7db3Sskrll       break;
2212a6b7db3Sskrll     case FR30_OPERAND_CC :
2222a6b7db3Sskrll       print_normal (cd, info, fields->f_cc, 0, pc, length);
2232a6b7db3Sskrll       break;
2242a6b7db3Sskrll     case FR30_OPERAND_CCC :
2252a6b7db3Sskrll       print_normal (cd, info, fields->f_ccc, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
2262a6b7db3Sskrll       break;
2272a6b7db3Sskrll     case FR30_OPERAND_DIR10 :
2282a6b7db3Sskrll       print_normal (cd, info, fields->f_dir10, 0, pc, length);
2292a6b7db3Sskrll       break;
2302a6b7db3Sskrll     case FR30_OPERAND_DIR8 :
2312a6b7db3Sskrll       print_normal (cd, info, fields->f_dir8, 0, pc, length);
2322a6b7db3Sskrll       break;
2332a6b7db3Sskrll     case FR30_OPERAND_DIR9 :
2342a6b7db3Sskrll       print_normal (cd, info, fields->f_dir9, 0, pc, length);
2352a6b7db3Sskrll       break;
2362a6b7db3Sskrll     case FR30_OPERAND_DISP10 :
2372a6b7db3Sskrll       print_normal (cd, info, fields->f_disp10, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
2382a6b7db3Sskrll       break;
2392a6b7db3Sskrll     case FR30_OPERAND_DISP8 :
2402a6b7db3Sskrll       print_normal (cd, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
2412a6b7db3Sskrll       break;
2422a6b7db3Sskrll     case FR30_OPERAND_DISP9 :
2432a6b7db3Sskrll       print_normal (cd, info, fields->f_disp9, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
2442a6b7db3Sskrll       break;
2452a6b7db3Sskrll     case FR30_OPERAND_I20 :
2462a6b7db3Sskrll       print_normal (cd, info, fields->f_i20, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
2472a6b7db3Sskrll       break;
2482a6b7db3Sskrll     case FR30_OPERAND_I32 :
2492a6b7db3Sskrll       print_normal (cd, info, fields->f_i32, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGN_OPT), pc, length);
2502a6b7db3Sskrll       break;
2512a6b7db3Sskrll     case FR30_OPERAND_I8 :
2522a6b7db3Sskrll       print_normal (cd, info, fields->f_i8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
2532a6b7db3Sskrll       break;
2542a6b7db3Sskrll     case FR30_OPERAND_LABEL12 :
2552a6b7db3Sskrll       print_address (cd, info, fields->f_rel12, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
2562a6b7db3Sskrll       break;
2572a6b7db3Sskrll     case FR30_OPERAND_LABEL9 :
2582a6b7db3Sskrll       print_address (cd, info, fields->f_rel9, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
2592a6b7db3Sskrll       break;
2602a6b7db3Sskrll     case FR30_OPERAND_M4 :
2612a6b7db3Sskrll       print_m4 (cd, info, fields->f_m4, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
2622a6b7db3Sskrll       break;
2632a6b7db3Sskrll     case FR30_OPERAND_PS :
2642a6b7db3Sskrll       print_keyword (cd, info, & fr30_cgen_opval_h_ps, 0, 0);
2652a6b7db3Sskrll       break;
2662a6b7db3Sskrll     case FR30_OPERAND_REGLIST_HI_LD :
2672a6b7db3Sskrll       print_hi_register_list_ld (cd, info, fields->f_reglist_hi_ld, 0, pc, length);
2682a6b7db3Sskrll       break;
2692a6b7db3Sskrll     case FR30_OPERAND_REGLIST_HI_ST :
2702a6b7db3Sskrll       print_hi_register_list_st (cd, info, fields->f_reglist_hi_st, 0, pc, length);
2712a6b7db3Sskrll       break;
2722a6b7db3Sskrll     case FR30_OPERAND_REGLIST_LOW_LD :
2732a6b7db3Sskrll       print_low_register_list_ld (cd, info, fields->f_reglist_low_ld, 0, pc, length);
2742a6b7db3Sskrll       break;
2752a6b7db3Sskrll     case FR30_OPERAND_REGLIST_LOW_ST :
2762a6b7db3Sskrll       print_low_register_list_st (cd, info, fields->f_reglist_low_st, 0, pc, length);
2772a6b7db3Sskrll       break;
2782a6b7db3Sskrll     case FR30_OPERAND_S10 :
2792a6b7db3Sskrll       print_normal (cd, info, fields->f_s10, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
2802a6b7db3Sskrll       break;
2812a6b7db3Sskrll     case FR30_OPERAND_U10 :
2822a6b7db3Sskrll       print_normal (cd, info, fields->f_u10, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
2832a6b7db3Sskrll       break;
2842a6b7db3Sskrll     case FR30_OPERAND_U4 :
2852a6b7db3Sskrll       print_normal (cd, info, fields->f_u4, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
2862a6b7db3Sskrll       break;
2872a6b7db3Sskrll     case FR30_OPERAND_U4C :
2882a6b7db3Sskrll       print_normal (cd, info, fields->f_u4c, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
2892a6b7db3Sskrll       break;
2902a6b7db3Sskrll     case FR30_OPERAND_U8 :
2912a6b7db3Sskrll       print_normal (cd, info, fields->f_u8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
2922a6b7db3Sskrll       break;
2932a6b7db3Sskrll     case FR30_OPERAND_UDISP6 :
2942a6b7db3Sskrll       print_normal (cd, info, fields->f_udisp6, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
2952a6b7db3Sskrll       break;
2962a6b7db3Sskrll 
2972a6b7db3Sskrll     default :
2982a6b7db3Sskrll       /* xgettext:c-format */
299fa2c2dd3Schristos       opcodes_error_handler
300fa2c2dd3Schristos 	(_("internal error: unrecognized field %d while printing insn"),
3012a6b7db3Sskrll 	 opindex);
3022a6b7db3Sskrll       abort ();
3032a6b7db3Sskrll   }
3042a6b7db3Sskrll }
3052a6b7db3Sskrll 
3062a6b7db3Sskrll cgen_print_fn * const fr30_cgen_print_handlers[] =
3072a6b7db3Sskrll {
3082a6b7db3Sskrll   print_insn_normal,
3092a6b7db3Sskrll };
3102a6b7db3Sskrll 
3112a6b7db3Sskrll 
3122a6b7db3Sskrll void
fr30_cgen_init_dis(CGEN_CPU_DESC cd)3132a6b7db3Sskrll fr30_cgen_init_dis (CGEN_CPU_DESC cd)
3142a6b7db3Sskrll {
3152a6b7db3Sskrll   fr30_cgen_init_opcode_table (cd);
3162a6b7db3Sskrll   fr30_cgen_init_ibld_table (cd);
3172a6b7db3Sskrll   cd->print_handlers = & fr30_cgen_print_handlers[0];
3182a6b7db3Sskrll   cd->print_operand = fr30_cgen_print_operand;
3192a6b7db3Sskrll }
3202a6b7db3Sskrll 
3212a6b7db3Sskrll 
3222a6b7db3Sskrll /* Default print handler.  */
3232a6b7db3Sskrll 
3242a6b7db3Sskrll static void
print_normal(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,long value,unsigned int attrs,bfd_vma pc ATTRIBUTE_UNUSED,int length ATTRIBUTE_UNUSED)3252a6b7db3Sskrll print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
3262a6b7db3Sskrll 	      void *dis_info,
3272a6b7db3Sskrll 	      long value,
3282a6b7db3Sskrll 	      unsigned int attrs,
3292a6b7db3Sskrll 	      bfd_vma pc ATTRIBUTE_UNUSED,
3302a6b7db3Sskrll 	      int length ATTRIBUTE_UNUSED)
3312a6b7db3Sskrll {
3322a6b7db3Sskrll   disassemble_info *info = (disassemble_info *) dis_info;
3332a6b7db3Sskrll 
3342a6b7db3Sskrll   /* Print the operand as directed by the attributes.  */
3352a6b7db3Sskrll   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
3362a6b7db3Sskrll     ; /* nothing to do */
3372a6b7db3Sskrll   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
3382a6b7db3Sskrll     (*info->fprintf_func) (info->stream, "%ld", value);
3392a6b7db3Sskrll   else
3402a6b7db3Sskrll     (*info->fprintf_func) (info->stream, "0x%lx", value);
3412a6b7db3Sskrll }
3422a6b7db3Sskrll 
3432a6b7db3Sskrll /* Default address handler.  */
3442a6b7db3Sskrll 
3452a6b7db3Sskrll static void
print_address(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,bfd_vma value,unsigned int attrs,bfd_vma pc ATTRIBUTE_UNUSED,int length ATTRIBUTE_UNUSED)3462a6b7db3Sskrll print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
3472a6b7db3Sskrll 	       void *dis_info,
3482a6b7db3Sskrll 	       bfd_vma value,
3492a6b7db3Sskrll 	       unsigned int attrs,
3502a6b7db3Sskrll 	       bfd_vma pc ATTRIBUTE_UNUSED,
3512a6b7db3Sskrll 	       int length ATTRIBUTE_UNUSED)
3522a6b7db3Sskrll {
3532a6b7db3Sskrll   disassemble_info *info = (disassemble_info *) dis_info;
3542a6b7db3Sskrll 
3552a6b7db3Sskrll   /* Print the operand as directed by the attributes.  */
3562a6b7db3Sskrll   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
3572a6b7db3Sskrll     ; /* Nothing to do.  */
3582a6b7db3Sskrll   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
3592a6b7db3Sskrll     (*info->print_address_func) (value, info);
3602a6b7db3Sskrll   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
3612a6b7db3Sskrll     (*info->print_address_func) (value, info);
3622a6b7db3Sskrll   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
3632a6b7db3Sskrll     (*info->fprintf_func) (info->stream, "%ld", (long) value);
3642a6b7db3Sskrll   else
3652a6b7db3Sskrll     (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
3662a6b7db3Sskrll }
3672a6b7db3Sskrll 
3682a6b7db3Sskrll /* Keyword print handler.  */
3692a6b7db3Sskrll 
3702a6b7db3Sskrll static void
print_keyword(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,CGEN_KEYWORD * keyword_table,long value,unsigned int attrs ATTRIBUTE_UNUSED)3712a6b7db3Sskrll print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
3722a6b7db3Sskrll 	       void *dis_info,
3732a6b7db3Sskrll 	       CGEN_KEYWORD *keyword_table,
3742a6b7db3Sskrll 	       long value,
3752a6b7db3Sskrll 	       unsigned int attrs ATTRIBUTE_UNUSED)
3762a6b7db3Sskrll {
3772a6b7db3Sskrll   disassemble_info *info = (disassemble_info *) dis_info;
3782a6b7db3Sskrll   const CGEN_KEYWORD_ENTRY *ke;
3792a6b7db3Sskrll 
3802a6b7db3Sskrll   ke = cgen_keyword_lookup_value (keyword_table, value);
3812a6b7db3Sskrll   if (ke != NULL)
3822a6b7db3Sskrll     (*info->fprintf_func) (info->stream, "%s", ke->name);
3832a6b7db3Sskrll   else
3842a6b7db3Sskrll     (*info->fprintf_func) (info->stream, "???");
3852a6b7db3Sskrll }
3862a6b7db3Sskrll 
3872a6b7db3Sskrll /* Default insn printer.
3882a6b7db3Sskrll 
3892a6b7db3Sskrll    DIS_INFO is defined as `void *' so the disassembler needn't know anything
3902a6b7db3Sskrll    about disassemble_info.  */
3912a6b7db3Sskrll 
3922a6b7db3Sskrll static void
print_insn_normal(CGEN_CPU_DESC cd,void * dis_info,const CGEN_INSN * insn,CGEN_FIELDS * fields,bfd_vma pc,int length)3932a6b7db3Sskrll print_insn_normal (CGEN_CPU_DESC cd,
3942a6b7db3Sskrll 		   void *dis_info,
3952a6b7db3Sskrll 		   const CGEN_INSN *insn,
3962a6b7db3Sskrll 		   CGEN_FIELDS *fields,
3972a6b7db3Sskrll 		   bfd_vma pc,
3982a6b7db3Sskrll 		   int length)
3992a6b7db3Sskrll {
4002a6b7db3Sskrll   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
4012a6b7db3Sskrll   disassemble_info *info = (disassemble_info *) dis_info;
4022a6b7db3Sskrll   const CGEN_SYNTAX_CHAR_TYPE *syn;
4032a6b7db3Sskrll 
4042a6b7db3Sskrll   CGEN_INIT_PRINT (cd);
4052a6b7db3Sskrll 
4062a6b7db3Sskrll   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
4072a6b7db3Sskrll     {
4082a6b7db3Sskrll       if (CGEN_SYNTAX_MNEMONIC_P (*syn))
4092a6b7db3Sskrll 	{
4102a6b7db3Sskrll 	  (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
4112a6b7db3Sskrll 	  continue;
4122a6b7db3Sskrll 	}
4132a6b7db3Sskrll       if (CGEN_SYNTAX_CHAR_P (*syn))
4142a6b7db3Sskrll 	{
4152a6b7db3Sskrll 	  (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
4162a6b7db3Sskrll 	  continue;
4172a6b7db3Sskrll 	}
4182a6b7db3Sskrll 
4192a6b7db3Sskrll       /* We have an operand.  */
4202a6b7db3Sskrll       fr30_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
4212a6b7db3Sskrll 				 fields, CGEN_INSN_ATTRS (insn), pc, length);
4222a6b7db3Sskrll     }
4232a6b7db3Sskrll }
4242a6b7db3Sskrll 
4252a6b7db3Sskrll /* Subroutine of print_insn. Reads an insn into the given buffers and updates
4262a6b7db3Sskrll    the extract info.
4272a6b7db3Sskrll    Returns 0 if all is well, non-zero otherwise.  */
4282a6b7db3Sskrll 
4292a6b7db3Sskrll static int
read_insn(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,bfd_vma pc,disassemble_info * info,bfd_byte * buf,int buflen,CGEN_EXTRACT_INFO * ex_info,unsigned long * insn_value)4302a6b7db3Sskrll read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
4312a6b7db3Sskrll 	   bfd_vma pc,
4322a6b7db3Sskrll 	   disassemble_info *info,
4332a6b7db3Sskrll 	   bfd_byte *buf,
4342a6b7db3Sskrll 	   int buflen,
4352a6b7db3Sskrll 	   CGEN_EXTRACT_INFO *ex_info,
4362a6b7db3Sskrll 	   unsigned long *insn_value)
4372a6b7db3Sskrll {
4382a6b7db3Sskrll   int status = (*info->read_memory_func) (pc, buf, buflen, info);
4392a6b7db3Sskrll 
4402a6b7db3Sskrll   if (status != 0)
4412a6b7db3Sskrll     {
4422a6b7db3Sskrll       (*info->memory_error_func) (status, pc, info);
4432a6b7db3Sskrll       return -1;
4442a6b7db3Sskrll     }
4452a6b7db3Sskrll 
4462a6b7db3Sskrll   ex_info->dis_info = info;
4472a6b7db3Sskrll   ex_info->valid = (1 << buflen) - 1;
4482a6b7db3Sskrll   ex_info->insn_bytes = buf;
4492a6b7db3Sskrll 
4502a6b7db3Sskrll   *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
4512a6b7db3Sskrll   return 0;
4522a6b7db3Sskrll }
4532a6b7db3Sskrll 
4542a6b7db3Sskrll /* Utility to print an insn.
4552a6b7db3Sskrll    BUF is the base part of the insn, target byte order, BUFLEN bytes long.
4562a6b7db3Sskrll    The result is the size of the insn in bytes or zero for an unknown insn
4572a6b7db3Sskrll    or -1 if an error occurs fetching data (memory_error_func will have
4582a6b7db3Sskrll    been called).  */
4592a6b7db3Sskrll 
4602a6b7db3Sskrll static int
print_insn(CGEN_CPU_DESC cd,bfd_vma pc,disassemble_info * info,bfd_byte * buf,unsigned int buflen)4612a6b7db3Sskrll print_insn (CGEN_CPU_DESC cd,
4622a6b7db3Sskrll 	    bfd_vma pc,
4632a6b7db3Sskrll 	    disassemble_info *info,
4642a6b7db3Sskrll 	    bfd_byte *buf,
4652a6b7db3Sskrll 	    unsigned int buflen)
4662a6b7db3Sskrll {
4672a6b7db3Sskrll   CGEN_INSN_INT insn_value;
4682a6b7db3Sskrll   const CGEN_INSN_LIST *insn_list;
4692a6b7db3Sskrll   CGEN_EXTRACT_INFO ex_info;
4702a6b7db3Sskrll   int basesize;
4712a6b7db3Sskrll 
4722a6b7db3Sskrll   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
4732a6b7db3Sskrll   basesize = cd->base_insn_bitsize < buflen * 8 ?
4742a6b7db3Sskrll                                      cd->base_insn_bitsize : buflen * 8;
475*f22f0ef4Schristos   insn_value = cgen_get_insn_value (cd, buf, basesize, cd->insn_endian);
4762a6b7db3Sskrll 
4772a6b7db3Sskrll 
4782a6b7db3Sskrll   /* Fill in ex_info fields like read_insn would.  Don't actually call
4792a6b7db3Sskrll      read_insn, since the incoming buffer is already read (and possibly
4802a6b7db3Sskrll      modified a la m32r).  */
4812a6b7db3Sskrll   ex_info.valid = (1 << buflen) - 1;
4822a6b7db3Sskrll   ex_info.dis_info = info;
4832a6b7db3Sskrll   ex_info.insn_bytes = buf;
4842a6b7db3Sskrll 
4852a6b7db3Sskrll   /* The instructions are stored in hash lists.
4862a6b7db3Sskrll      Pick the first one and keep trying until we find the right one.  */
4872a6b7db3Sskrll 
4882a6b7db3Sskrll   insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
4892a6b7db3Sskrll   while (insn_list != NULL)
4902a6b7db3Sskrll     {
4912a6b7db3Sskrll       const CGEN_INSN *insn = insn_list->insn;
4922a6b7db3Sskrll       CGEN_FIELDS fields;
4932a6b7db3Sskrll       int length;
4942a6b7db3Sskrll       unsigned long insn_value_cropped;
4952a6b7db3Sskrll 
4962a6b7db3Sskrll #ifdef CGEN_VALIDATE_INSN_SUPPORTED
4972a6b7db3Sskrll       /* Not needed as insn shouldn't be in hash lists if not supported.  */
4982a6b7db3Sskrll       /* Supported by this cpu?  */
4992a6b7db3Sskrll       if (! fr30_cgen_insn_supported (cd, insn))
5002a6b7db3Sskrll         {
5012a6b7db3Sskrll           insn_list = CGEN_DIS_NEXT_INSN (insn_list);
5022a6b7db3Sskrll 	  continue;
5032a6b7db3Sskrll         }
5042a6b7db3Sskrll #endif
5052a6b7db3Sskrll 
5062a6b7db3Sskrll       /* Basic bit mask must be correct.  */
5072a6b7db3Sskrll       /* ??? May wish to allow target to defer this check until the extract
5082a6b7db3Sskrll 	 handler.  */
5092a6b7db3Sskrll 
5102a6b7db3Sskrll       /* Base size may exceed this instruction's size.  Extract the
5112a6b7db3Sskrll          relevant part from the buffer. */
5122a6b7db3Sskrll       if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
5132a6b7db3Sskrll 	  (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
5142a6b7db3Sskrll 	insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
5152a6b7db3Sskrll 					   info->endian == BFD_ENDIAN_BIG);
5162a6b7db3Sskrll       else
5172a6b7db3Sskrll 	insn_value_cropped = insn_value;
5182a6b7db3Sskrll 
5192a6b7db3Sskrll       if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
5202a6b7db3Sskrll 	  == CGEN_INSN_BASE_VALUE (insn))
5212a6b7db3Sskrll 	{
5222a6b7db3Sskrll 	  /* Printing is handled in two passes.  The first pass parses the
5232a6b7db3Sskrll 	     machine insn and extracts the fields.  The second pass prints
5242a6b7db3Sskrll 	     them.  */
5252a6b7db3Sskrll 
5262a6b7db3Sskrll 	  /* Make sure the entire insn is loaded into insn_value, if it
5272a6b7db3Sskrll 	     can fit.  */
5282a6b7db3Sskrll 	  if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
5292a6b7db3Sskrll 	      (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
5302a6b7db3Sskrll 	    {
5312a6b7db3Sskrll 	      unsigned long full_insn_value;
5322a6b7db3Sskrll 	      int rc = read_insn (cd, pc, info, buf,
5332a6b7db3Sskrll 				  CGEN_INSN_BITSIZE (insn) / 8,
5342a6b7db3Sskrll 				  & ex_info, & full_insn_value);
5352a6b7db3Sskrll 	      if (rc != 0)
5362a6b7db3Sskrll 		return rc;
5372a6b7db3Sskrll 	      length = CGEN_EXTRACT_FN (cd, insn)
5382a6b7db3Sskrll 		(cd, insn, &ex_info, full_insn_value, &fields, pc);
5392a6b7db3Sskrll 	    }
5402a6b7db3Sskrll 	  else
5412a6b7db3Sskrll 	    length = CGEN_EXTRACT_FN (cd, insn)
5422a6b7db3Sskrll 	      (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
5432a6b7db3Sskrll 
5442a6b7db3Sskrll 	  /* Length < 0 -> error.  */
5452a6b7db3Sskrll 	  if (length < 0)
5462a6b7db3Sskrll 	    return length;
5472a6b7db3Sskrll 	  if (length > 0)
5482a6b7db3Sskrll 	    {
5492a6b7db3Sskrll 	      CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
5502a6b7db3Sskrll 	      /* Length is in bits, result is in bytes.  */
5512a6b7db3Sskrll 	      return length / 8;
5522a6b7db3Sskrll 	    }
5532a6b7db3Sskrll 	}
5542a6b7db3Sskrll 
5552a6b7db3Sskrll       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
5562a6b7db3Sskrll     }
5572a6b7db3Sskrll 
5582a6b7db3Sskrll   return 0;
5592a6b7db3Sskrll }
5602a6b7db3Sskrll 
5612a6b7db3Sskrll /* Default value for CGEN_PRINT_INSN.
5622a6b7db3Sskrll    The result is the size of the insn in bytes or zero for an unknown insn
5632a6b7db3Sskrll    or -1 if an error occured fetching bytes.  */
5642a6b7db3Sskrll 
5652a6b7db3Sskrll #ifndef CGEN_PRINT_INSN
5662a6b7db3Sskrll #define CGEN_PRINT_INSN default_print_insn
5672a6b7db3Sskrll #endif
5682a6b7db3Sskrll 
5692a6b7db3Sskrll static int
default_print_insn(CGEN_CPU_DESC cd,bfd_vma pc,disassemble_info * info)5702a6b7db3Sskrll default_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
5712a6b7db3Sskrll {
5722a6b7db3Sskrll   bfd_byte buf[CGEN_MAX_INSN_SIZE];
5732a6b7db3Sskrll   int buflen;
5742a6b7db3Sskrll   int status;
5752a6b7db3Sskrll 
5762a6b7db3Sskrll   /* Attempt to read the base part of the insn.  */
5772a6b7db3Sskrll   buflen = cd->base_insn_bitsize / 8;
5782a6b7db3Sskrll   status = (*info->read_memory_func) (pc, buf, buflen, info);
5792a6b7db3Sskrll 
5802a6b7db3Sskrll   /* Try again with the minimum part, if min < base.  */
5812a6b7db3Sskrll   if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
5822a6b7db3Sskrll     {
5832a6b7db3Sskrll       buflen = cd->min_insn_bitsize / 8;
5842a6b7db3Sskrll       status = (*info->read_memory_func) (pc, buf, buflen, info);
5852a6b7db3Sskrll     }
5862a6b7db3Sskrll 
5872a6b7db3Sskrll   if (status != 0)
5882a6b7db3Sskrll     {
5892a6b7db3Sskrll       (*info->memory_error_func) (status, pc, info);
5902a6b7db3Sskrll       return -1;
5912a6b7db3Sskrll     }
5922a6b7db3Sskrll 
5932a6b7db3Sskrll   return print_insn (cd, pc, info, buf, buflen);
5942a6b7db3Sskrll }
5952a6b7db3Sskrll 
5962a6b7db3Sskrll /* Main entry point.
5972a6b7db3Sskrll    Print one instruction from PC on INFO->STREAM.
5982a6b7db3Sskrll    Return the size of the instruction (in bytes).  */
5992a6b7db3Sskrll 
6002a6b7db3Sskrll typedef struct cpu_desc_list
6012a6b7db3Sskrll {
6022a6b7db3Sskrll   struct cpu_desc_list *next;
6032a6b7db3Sskrll   CGEN_BITSET *isa;
6042a6b7db3Sskrll   int mach;
6052a6b7db3Sskrll   int endian;
606*f22f0ef4Schristos   int insn_endian;
6072a6b7db3Sskrll   CGEN_CPU_DESC cd;
6082a6b7db3Sskrll } cpu_desc_list;
6092a6b7db3Sskrll 
6102a6b7db3Sskrll int
print_insn_fr30(bfd_vma pc,disassemble_info * info)6112a6b7db3Sskrll print_insn_fr30 (bfd_vma pc, disassemble_info *info)
6122a6b7db3Sskrll {
6132a6b7db3Sskrll   static cpu_desc_list *cd_list = 0;
6142a6b7db3Sskrll   cpu_desc_list *cl = 0;
6152a6b7db3Sskrll   static CGEN_CPU_DESC cd = 0;
6162a6b7db3Sskrll   static CGEN_BITSET *prev_isa;
6172a6b7db3Sskrll   static int prev_mach;
6182a6b7db3Sskrll   static int prev_endian;
619*f22f0ef4Schristos   static int prev_insn_endian;
6202a6b7db3Sskrll   int length;
6212a6b7db3Sskrll   CGEN_BITSET *isa;
6222a6b7db3Sskrll   int mach;
6232a6b7db3Sskrll   int endian = (info->endian == BFD_ENDIAN_BIG
6242a6b7db3Sskrll 		? CGEN_ENDIAN_BIG
6252a6b7db3Sskrll 		: CGEN_ENDIAN_LITTLE);
626*f22f0ef4Schristos   int insn_endian = (info->endian_code == BFD_ENDIAN_BIG
627*f22f0ef4Schristos                      ? CGEN_ENDIAN_BIG
628*f22f0ef4Schristos                      : CGEN_ENDIAN_LITTLE);
6292a6b7db3Sskrll   enum bfd_architecture arch;
6302a6b7db3Sskrll 
6312a6b7db3Sskrll   /* ??? gdb will set mach but leave the architecture as "unknown" */
6322a6b7db3Sskrll #ifndef CGEN_BFD_ARCH
6332a6b7db3Sskrll #define CGEN_BFD_ARCH bfd_arch_fr30
6342a6b7db3Sskrll #endif
6352a6b7db3Sskrll   arch = info->arch;
6362a6b7db3Sskrll   if (arch == bfd_arch_unknown)
6372a6b7db3Sskrll     arch = CGEN_BFD_ARCH;
6382a6b7db3Sskrll 
6392a6b7db3Sskrll   /* There's no standard way to compute the machine or isa number
6402a6b7db3Sskrll      so we leave it to the target.  */
6412a6b7db3Sskrll #ifdef CGEN_COMPUTE_MACH
6422a6b7db3Sskrll   mach = CGEN_COMPUTE_MACH (info);
6432a6b7db3Sskrll #else
6442a6b7db3Sskrll   mach = info->mach;
6452a6b7db3Sskrll #endif
6462a6b7db3Sskrll 
6472a6b7db3Sskrll #ifdef CGEN_COMPUTE_ISA
6482a6b7db3Sskrll   {
6492a6b7db3Sskrll     static CGEN_BITSET *permanent_isa;
6502a6b7db3Sskrll 
6512a6b7db3Sskrll     if (!permanent_isa)
6522a6b7db3Sskrll       permanent_isa = cgen_bitset_create (MAX_ISAS);
6532a6b7db3Sskrll     isa = permanent_isa;
6542a6b7db3Sskrll     cgen_bitset_clear (isa);
6552a6b7db3Sskrll     cgen_bitset_add (isa, CGEN_COMPUTE_ISA (info));
6562a6b7db3Sskrll   }
6572a6b7db3Sskrll #else
658f7172901Schristos   isa = info->private_data;
6592a6b7db3Sskrll #endif
6602a6b7db3Sskrll 
6612a6b7db3Sskrll   /* If we've switched cpu's, try to find a handle we've used before */
6622a6b7db3Sskrll   if (cd
6632a6b7db3Sskrll       && (cgen_bitset_compare (isa, prev_isa) != 0
6642a6b7db3Sskrll 	  || mach != prev_mach
6652a6b7db3Sskrll 	  || endian != prev_endian))
6662a6b7db3Sskrll     {
6672a6b7db3Sskrll       cd = 0;
6682a6b7db3Sskrll       for (cl = cd_list; cl; cl = cl->next)
6692a6b7db3Sskrll 	{
6702a6b7db3Sskrll 	  if (cgen_bitset_compare (cl->isa, isa) == 0 &&
6712a6b7db3Sskrll 	      cl->mach == mach &&
6722a6b7db3Sskrll 	      cl->endian == endian)
6732a6b7db3Sskrll 	    {
6742a6b7db3Sskrll 	      cd = cl->cd;
6752a6b7db3Sskrll  	      prev_isa = cd->isas;
6762a6b7db3Sskrll 	      break;
6772a6b7db3Sskrll 	    }
6782a6b7db3Sskrll 	}
6792a6b7db3Sskrll     }
6802a6b7db3Sskrll 
6812a6b7db3Sskrll   /* If we haven't initialized yet, initialize the opcode table.  */
6822a6b7db3Sskrll   if (! cd)
6832a6b7db3Sskrll     {
6842a6b7db3Sskrll       const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
6852a6b7db3Sskrll       const char *mach_name;
6862a6b7db3Sskrll 
6872a6b7db3Sskrll       if (!arch_type)
6882a6b7db3Sskrll 	abort ();
6892a6b7db3Sskrll       mach_name = arch_type->printable_name;
6902a6b7db3Sskrll 
6912a6b7db3Sskrll       prev_isa = cgen_bitset_copy (isa);
6922a6b7db3Sskrll       prev_mach = mach;
6932a6b7db3Sskrll       prev_endian = endian;
694*f22f0ef4Schristos       prev_insn_endian = insn_endian;
6952a6b7db3Sskrll       cd = fr30_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
6962a6b7db3Sskrll 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
6972a6b7db3Sskrll 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
698*f22f0ef4Schristos                                  CGEN_CPU_OPEN_INSN_ENDIAN, prev_insn_endian,
6992a6b7db3Sskrll 				 CGEN_CPU_OPEN_END);
7002a6b7db3Sskrll       if (!cd)
7012a6b7db3Sskrll 	abort ();
7022a6b7db3Sskrll 
7032a6b7db3Sskrll       /* Save this away for future reference.  */
7042a6b7db3Sskrll       cl = xmalloc (sizeof (struct cpu_desc_list));
7052a6b7db3Sskrll       cl->cd = cd;
7062a6b7db3Sskrll       cl->isa = prev_isa;
7072a6b7db3Sskrll       cl->mach = mach;
7082a6b7db3Sskrll       cl->endian = endian;
7092a6b7db3Sskrll       cl->next = cd_list;
7102a6b7db3Sskrll       cd_list = cl;
7112a6b7db3Sskrll 
7122a6b7db3Sskrll       fr30_cgen_init_dis (cd);
7132a6b7db3Sskrll     }
7142a6b7db3Sskrll 
7152a6b7db3Sskrll   /* We try to have as much common code as possible.
7162a6b7db3Sskrll      But at this point some targets need to take over.  */
7172a6b7db3Sskrll   /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
7182a6b7db3Sskrll      but if not possible try to move this hook elsewhere rather than
7192a6b7db3Sskrll      have two hooks.  */
7202a6b7db3Sskrll   length = CGEN_PRINT_INSN (cd, pc, info);
7212a6b7db3Sskrll   if (length > 0)
7222a6b7db3Sskrll     return length;
7232a6b7db3Sskrll   if (length < 0)
7242a6b7db3Sskrll     return -1;
7252a6b7db3Sskrll 
7262a6b7db3Sskrll   (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
7272a6b7db3Sskrll   return cd->default_insn_bitsize / 8;
7282a6b7db3Sskrll }
729