Fix compile time warning messages
[platform/upstream/binutils.git] / opcodes / fr30-dis.c
1 /* Disassembler interface for targets using CGEN. -*- C -*-
2    CGEN: Cpu tools GENerator
3
4 THIS FILE IS MACHINE GENERATED WITH CGEN.
5 - the resultant file is machine generated, cgen-dis.in isn't
6
7 Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
8
9 This file is part of the GNU Binutils and GDB, the GNU debugger.
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software Foundation, Inc.,
23 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
24
25 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
26    Keep that in mind.  */
27
28 #include "sysdep.h"
29 #include <stdio.h>
30 #include "ansidecl.h"
31 #include "dis-asm.h"
32 #include "bfd.h"
33 #include "symcat.h"
34 #include "fr30-desc.h"
35 #include "fr30-opc.h"
36 #include "opintl.h"
37
38 /* Default text to print if an instruction isn't recognized.  */
39 #define UNKNOWN_INSN_MSG _("*unknown*")
40
41 static void print_normal               PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
42 static void print_address              PARAMS ((CGEN_CPU_DESC, PTR, bfd_vma, unsigned, bfd_vma, int));
43 static void print_keyword              PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned));
44 static void print_insn_normal          PARAMS ((CGEN_CPU_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int));
45 static int  print_insn                 PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *, char *, int));
46 static int  default_print_insn         PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *));
47 static void print_register_list        PARAMS ((PTR, long, long, int));
48 static void print_hi_register_list_ld  PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
49 static void print_low_register_list_ld PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
50 static void print_hi_register_list_st  PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
51 static void print_low_register_list_st PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
52 static void print_m4                   PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
53        void fr30_cgen_print_operand    PARAMS ((CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *, void const *, bfd_vma, int));
54 static int  read_insn                  PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *, char *, int, CGEN_EXTRACT_INFO *, unsigned long *));
55 \f
56 /* -- disassembler routines inserted here */
57
58 /* -- dis.c */
59
60 static void
61 print_register_list (dis_info, value, offset, load_store)
62      PTR dis_info;
63      long value;
64      long offset;
65      int load_store; /* 0 == load, 1 == store */
66 {
67   disassemble_info *info = dis_info;
68   int mask;
69   int index = 0;
70   char* comma = "";
71
72   if (load_store)
73     mask = 0x80;
74   else
75     mask = 1;
76
77   if (value & mask)
78     {
79       (*info->fprintf_func) (info->stream, "r%i", index + offset);
80       comma = ",";
81     }
82     
83   for (index = 1; index <= 7; ++index)
84     {
85       if (load_store)
86         mask >>= 1;
87       else
88         mask <<= 1;
89
90       if (value & mask)
91         {
92           (*info->fprintf_func) (info->stream, "%sr%i", comma, index + offset);
93           comma = ",";
94         }
95     }
96 }
97
98 static void
99 print_hi_register_list_ld (cd, dis_info, value, attrs, pc, length)
100      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
101      PTR dis_info;
102      long value;
103      unsigned int attrs ATTRIBUTE_UNUSED;
104      bfd_vma pc ATTRIBUTE_UNUSED;
105      int length ATTRIBUTE_UNUSED;
106 {
107   print_register_list (dis_info, value, 8, 0/*load*/);
108 }
109
110 static void
111 print_low_register_list_ld (cd, dis_info, value, attrs, pc, length)
112      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
113      PTR dis_info;
114      long value;
115      unsigned int attrs ATTRIBUTE_UNUSED;
116      bfd_vma pc ATTRIBUTE_UNUSED;
117      int length ATTRIBUTE_UNUSED;
118 {
119   print_register_list (dis_info, value, 0, 0/*load*/);
120 }
121
122 static void
123 print_hi_register_list_st (cd, dis_info, value, attrs, pc, length)
124      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
125      PTR dis_info;
126      long value;
127      unsigned int attrs ATTRIBUTE_UNUSED;
128      bfd_vma pc ATTRIBUTE_UNUSED;
129      int length ATTRIBUTE_UNUSED;
130 {
131   print_register_list (dis_info, value, 8, 1/*store*/);
132 }
133
134 static void
135 print_low_register_list_st (cd, dis_info, value, attrs, pc, length)
136      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
137      PTR dis_info;
138      long value;
139      unsigned int attrs ATTRIBUTE_UNUSED;
140      bfd_vma pc ATTRIBUTE_UNUSED;
141      int length ATTRIBUTE_UNUSED;
142 {
143   print_register_list (dis_info, value, 0, 1/*store*/);
144 }
145
146 static void
147 print_m4 (cd, dis_info, value, attrs, pc, length)
148      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
149      PTR dis_info;
150      long value;
151      unsigned int attrs ATTRIBUTE_UNUSED;
152      bfd_vma pc ATTRIBUTE_UNUSED;
153      int length ATTRIBUTE_UNUSED;
154 {
155   disassemble_info *info = (disassemble_info *) dis_info;
156   (*info->fprintf_func) (info->stream, "%ld", value);
157 }
158 /* -- */
159
160 /* Main entry point for printing operands.
161    XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
162    of dis-asm.h on cgen.h.
163
164    This function is basically just a big switch statement.  Earlier versions
165    used tables to look up the function to use, but
166    - if the table contains both assembler and disassembler functions then
167      the disassembler contains much of the assembler and vice-versa,
168    - there's a lot of inlining possibilities as things grow,
169    - using a switch statement avoids the function call overhead.
170
171    This function could be moved into `print_insn_normal', but keeping it
172    separate makes clear the interface between `print_insn_normal' and each of
173    the handlers.
174 */
175
176 void
177 fr30_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length)
178      CGEN_CPU_DESC cd;
179      int opindex;
180      PTR xinfo;
181      CGEN_FIELDS *fields;
182      void const *attrs ATTRIBUTE_UNUSED;
183      bfd_vma pc;
184      int length;
185 {
186  disassemble_info *info = (disassemble_info *) xinfo;
187
188   switch (opindex)
189     {
190     case FR30_OPERAND_CRI :
191       print_keyword (cd, info, & fr30_cgen_opval_cr_names, fields->f_CRi, 0);
192       break;
193     case FR30_OPERAND_CRJ :
194       print_keyword (cd, info, & fr30_cgen_opval_cr_names, fields->f_CRj, 0);
195       break;
196     case FR30_OPERAND_R13 :
197       print_keyword (cd, info, & fr30_cgen_opval_h_r13, 0, 0);
198       break;
199     case FR30_OPERAND_R14 :
200       print_keyword (cd, info, & fr30_cgen_opval_h_r14, 0, 0);
201       break;
202     case FR30_OPERAND_R15 :
203       print_keyword (cd, info, & fr30_cgen_opval_h_r15, 0, 0);
204       break;
205     case FR30_OPERAND_RI :
206       print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Ri, 0);
207       break;
208     case FR30_OPERAND_RIC :
209       print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Ric, 0);
210       break;
211     case FR30_OPERAND_RJ :
212       print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Rj, 0);
213       break;
214     case FR30_OPERAND_RJC :
215       print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Rjc, 0);
216       break;
217     case FR30_OPERAND_RS1 :
218       print_keyword (cd, info, & fr30_cgen_opval_dr_names, fields->f_Rs1, 0);
219       break;
220     case FR30_OPERAND_RS2 :
221       print_keyword (cd, info, & fr30_cgen_opval_dr_names, fields->f_Rs2, 0);
222       break;
223     case FR30_OPERAND_CC :
224       print_normal (cd, info, fields->f_cc, 0, pc, length);
225       break;
226     case FR30_OPERAND_CCC :
227       print_normal (cd, info, fields->f_ccc, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
228       break;
229     case FR30_OPERAND_DIR10 :
230       print_normal (cd, info, fields->f_dir10, 0, pc, length);
231       break;
232     case FR30_OPERAND_DIR8 :
233       print_normal (cd, info, fields->f_dir8, 0, pc, length);
234       break;
235     case FR30_OPERAND_DIR9 :
236       print_normal (cd, info, fields->f_dir9, 0, pc, length);
237       break;
238     case FR30_OPERAND_DISP10 :
239       print_normal (cd, info, fields->f_disp10, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
240       break;
241     case FR30_OPERAND_DISP8 :
242       print_normal (cd, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
243       break;
244     case FR30_OPERAND_DISP9 :
245       print_normal (cd, info, fields->f_disp9, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
246       break;
247     case FR30_OPERAND_I20 :
248       print_normal (cd, info, fields->f_i20, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
249       break;
250     case FR30_OPERAND_I32 :
251       print_normal (cd, info, fields->f_i32, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGN_OPT), pc, length);
252       break;
253     case FR30_OPERAND_I8 :
254       print_normal (cd, info, fields->f_i8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
255       break;
256     case FR30_OPERAND_LABEL12 :
257       print_address (cd, info, fields->f_rel12, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
258       break;
259     case FR30_OPERAND_LABEL9 :
260       print_address (cd, info, fields->f_rel9, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
261       break;
262     case FR30_OPERAND_M4 :
263       print_m4 (cd, info, fields->f_m4, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
264       break;
265     case FR30_OPERAND_PS :
266       print_keyword (cd, info, & fr30_cgen_opval_h_ps, 0, 0);
267       break;
268     case FR30_OPERAND_REGLIST_HI_LD :
269       print_hi_register_list_ld (cd, info, fields->f_reglist_hi_ld, 0, pc, length);
270       break;
271     case FR30_OPERAND_REGLIST_HI_ST :
272       print_hi_register_list_st (cd, info, fields->f_reglist_hi_st, 0, pc, length);
273       break;
274     case FR30_OPERAND_REGLIST_LOW_LD :
275       print_low_register_list_ld (cd, info, fields->f_reglist_low_ld, 0, pc, length);
276       break;
277     case FR30_OPERAND_REGLIST_LOW_ST :
278       print_low_register_list_st (cd, info, fields->f_reglist_low_st, 0, pc, length);
279       break;
280     case FR30_OPERAND_S10 :
281       print_normal (cd, info, fields->f_s10, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
282       break;
283     case FR30_OPERAND_U10 :
284       print_normal (cd, info, fields->f_u10, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
285       break;
286     case FR30_OPERAND_U4 :
287       print_normal (cd, info, fields->f_u4, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
288       break;
289     case FR30_OPERAND_U4C :
290       print_normal (cd, info, fields->f_u4c, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
291       break;
292     case FR30_OPERAND_U8 :
293       print_normal (cd, info, fields->f_u8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
294       break;
295     case FR30_OPERAND_UDISP6 :
296       print_normal (cd, info, fields->f_udisp6, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
297       break;
298
299     default :
300       /* xgettext:c-format */
301       fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
302                opindex);
303     abort ();
304   }
305 }
306
307 cgen_print_fn * const fr30_cgen_print_handlers[] = 
308 {
309   print_insn_normal,
310 };
311
312
313 void
314 fr30_cgen_init_dis (cd)
315      CGEN_CPU_DESC cd;
316 {
317   fr30_cgen_init_opcode_table (cd);
318   fr30_cgen_init_ibld_table (cd);
319   cd->print_handlers = & fr30_cgen_print_handlers[0];
320   cd->print_operand = fr30_cgen_print_operand;
321 }
322
323 \f
324 /* Default print handler.  */
325
326 static void
327 print_normal (cd, dis_info, value, attrs, pc, length)
328 #ifdef CGEN_PRINT_NORMAL
329      CGEN_CPU_DESC cd;
330 #else
331      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
332 #endif
333      PTR dis_info;
334      long value;
335      unsigned int attrs;
336 #ifdef CGEN_PRINT_NORMAL
337      bfd_vma pc;
338      int length;
339 #else
340      bfd_vma pc ATTRIBUTE_UNUSED;
341      int length ATTRIBUTE_UNUSED;
342 #endif
343 {
344   disassemble_info *info = (disassemble_info *) dis_info;
345
346 #ifdef CGEN_PRINT_NORMAL
347   CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
348 #endif
349
350   /* Print the operand as directed by the attributes.  */
351   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
352     ; /* nothing to do */
353   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
354     (*info->fprintf_func) (info->stream, "%ld", value);
355   else
356     (*info->fprintf_func) (info->stream, "0x%lx", value);
357 }
358
359 /* Default address handler.  */
360
361 static void
362 print_address (cd, dis_info, value, attrs, pc, length)
363 #ifdef CGEN_PRINT_NORMAL
364      CGEN_CPU_DESC cd;
365 #else
366      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
367 #endif
368      PTR dis_info;
369      bfd_vma value;
370      unsigned int attrs;
371 #ifdef CGEN_PRINT_NORMAL
372      bfd_vma pc;
373      int length;
374 #else
375      bfd_vma pc ATTRIBUTE_UNUSED;
376      int length ATTRIBUTE_UNUSED;
377 #endif
378 {
379   disassemble_info *info = (disassemble_info *) dis_info;
380
381 #ifdef CGEN_PRINT_ADDRESS
382   CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
383 #endif
384
385   /* Print the operand as directed by the attributes.  */
386   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
387     ; /* nothing to do */
388   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
389     (*info->print_address_func) (value, info);
390   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
391     (*info->print_address_func) (value, info);
392   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
393     (*info->fprintf_func) (info->stream, "%ld", (long) value);
394   else
395     (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
396 }
397
398 /* Keyword print handler.  */
399
400 static void
401 print_keyword (cd, dis_info, keyword_table, value, attrs)
402      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
403      PTR dis_info;
404      CGEN_KEYWORD *keyword_table;
405      long value;
406      unsigned int attrs ATTRIBUTE_UNUSED;
407 {
408   disassemble_info *info = (disassemble_info *) dis_info;
409   const CGEN_KEYWORD_ENTRY *ke;
410
411   ke = cgen_keyword_lookup_value (keyword_table, value);
412   if (ke != NULL)
413     (*info->fprintf_func) (info->stream, "%s", ke->name);
414   else
415     (*info->fprintf_func) (info->stream, "???");
416 }
417 \f
418 /* Default insn printer.
419
420    DIS_INFO is defined as `PTR' so the disassembler needn't know anything
421    about disassemble_info.  */
422
423 static void
424 print_insn_normal (cd, dis_info, insn, fields, pc, length)
425      CGEN_CPU_DESC cd;
426      PTR dis_info;
427      const CGEN_INSN *insn;
428      CGEN_FIELDS *fields;
429      bfd_vma pc;
430      int length;
431 {
432   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
433   disassemble_info *info = (disassemble_info *) dis_info;
434   const CGEN_SYNTAX_CHAR_TYPE *syn;
435
436   CGEN_INIT_PRINT (cd);
437
438   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
439     {
440       if (CGEN_SYNTAX_MNEMONIC_P (*syn))
441         {
442           (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
443           continue;
444         }
445       if (CGEN_SYNTAX_CHAR_P (*syn))
446         {
447           (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
448           continue;
449         }
450
451       /* We have an operand.  */
452       fr30_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
453                                  fields, CGEN_INSN_ATTRS (insn), pc, length);
454     }
455 }
456 \f
457 /* Subroutine of print_insn. Reads an insn into the given buffers and updates
458    the extract info.
459    Returns 0 if all is well, non-zero otherwise.  */
460 static int
461 read_insn (cd, pc, info, buf, buflen, ex_info, insn_value)
462      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
463      bfd_vma pc;
464      disassemble_info *info;
465      char *buf;
466      int buflen;
467      CGEN_EXTRACT_INFO *ex_info;
468      unsigned long *insn_value;
469 {
470   int status = (*info->read_memory_func) (pc, buf, buflen, info);
471   if (status != 0)
472     {
473       (*info->memory_error_func) (status, pc, info);
474       return -1;
475     }
476
477   ex_info->dis_info = info;
478   ex_info->valid = (1 << buflen) - 1;
479   ex_info->insn_bytes = buf;
480
481   *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
482   return 0;
483 }
484
485 /* Utility to print an insn.
486    BUF is the base part of the insn, target byte order, BUFLEN bytes long.
487    The result is the size of the insn in bytes or zero for an unknown insn
488    or -1 if an error occurs fetching data (memory_error_func will have
489    been called).  */
490
491 static int
492 print_insn (cd, pc, info, buf, buflen)
493      CGEN_CPU_DESC cd;
494      bfd_vma pc;
495      disassemble_info *info;
496      char *buf;
497      int buflen;
498 {
499   CGEN_INSN_INT insn_value;
500   const CGEN_INSN_LIST *insn_list;
501   CGEN_EXTRACT_INFO ex_info;
502
503   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
504   insn_value = cgen_get_insn_value (cd, buf, buflen * 8);
505
506   /* Fill in ex_info fields like read_insn would.  Don't actually call
507      read_insn, since the incoming buffer is already read (and possibly
508      modified a la m32r).  */
509   ex_info.valid = (1 << buflen) - 1;
510   ex_info.dis_info = info;
511   ex_info.insn_bytes = buf;
512
513   /* The instructions are stored in hash lists.
514      Pick the first one and keep trying until we find the right one.  */
515
516   insn_list = CGEN_DIS_LOOKUP_INSN (cd, buf, insn_value);
517   while (insn_list != NULL)
518     {
519       const CGEN_INSN *insn = insn_list->insn;
520       CGEN_FIELDS fields;
521       int length;
522       unsigned long insn_value_cropped;
523
524 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
525       /* not needed as insn shouldn't be in hash lists if not supported */
526       /* Supported by this cpu?  */
527       if (! fr30_cgen_insn_supported (cd, insn))
528         {
529           insn_list = CGEN_DIS_NEXT_INSN (insn_list);
530           continue;
531         }
532 #endif
533
534       /* Basic bit mask must be correct.  */
535       /* ??? May wish to allow target to defer this check until the extract
536          handler.  */
537
538       /* Base size may exceed this instruction's size.  Extract the
539          relevant part from the buffer. */
540       if ((CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
541           (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
542         insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn), 
543                                            info->endian == BFD_ENDIAN_BIG);
544       else
545         insn_value_cropped = insn_value;
546
547       if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
548           == CGEN_INSN_BASE_VALUE (insn))
549         {
550           /* Printing is handled in two passes.  The first pass parses the
551              machine insn and extracts the fields.  The second pass prints
552              them.  */
553
554           /* Make sure the entire insn is loaded into insn_value, if it
555              can fit.  */
556           if ((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize &&
557               (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
558             {
559               unsigned long full_insn_value;
560               int rc = read_insn (cd, pc, info, buf,
561                                   CGEN_INSN_BITSIZE (insn) / 8,
562                                   & ex_info, & full_insn_value);
563               if (rc != 0)
564                 return rc;
565               length = CGEN_EXTRACT_FN (cd, insn)
566                 (cd, insn, &ex_info, full_insn_value, &fields, pc);
567             }
568           else
569             length = CGEN_EXTRACT_FN (cd, insn)
570               (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
571
572           /* length < 0 -> error */
573           if (length < 0)
574             return length;
575           if (length > 0)
576             {
577               CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
578               /* length is in bits, result is in bytes */
579               return length / 8;
580             }
581         }
582
583       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
584     }
585
586   return 0;
587 }
588
589 /* Default value for CGEN_PRINT_INSN.
590    The result is the size of the insn in bytes or zero for an unknown insn
591    or -1 if an error occured fetching bytes.  */
592
593 #ifndef CGEN_PRINT_INSN
594 #define CGEN_PRINT_INSN default_print_insn
595 #endif
596
597 static int
598 default_print_insn (cd, pc, info)
599      CGEN_CPU_DESC cd;
600      bfd_vma pc;
601      disassemble_info *info;
602 {
603   char buf[CGEN_MAX_INSN_SIZE];
604   int buflen;
605   int status;
606
607   /* Attempt to read the base part of the insn.  */
608   buflen = cd->base_insn_bitsize / 8;
609   status = (*info->read_memory_func) (pc, buf, buflen, info);
610
611   /* Try again with the minimum part, if min < base.  */
612   if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
613     {
614       buflen = cd->min_insn_bitsize / 8;
615       status = (*info->read_memory_func) (pc, buf, buflen, info);
616     }
617
618   if (status != 0)
619     {
620       (*info->memory_error_func) (status, pc, info);
621       return -1;
622     }
623
624   return print_insn (cd, pc, info, buf, buflen);
625 }
626
627 /* Main entry point.
628    Print one instruction from PC on INFO->STREAM.
629    Return the size of the instruction (in bytes).  */
630
631 int
632 print_insn_fr30 (pc, info)
633      bfd_vma pc;
634      disassemble_info *info;
635 {
636   static CGEN_CPU_DESC cd = 0;
637   static int prev_isa;
638   static int prev_mach;
639   static int prev_endian;
640   int length;
641   int isa,mach;
642   int endian = (info->endian == BFD_ENDIAN_BIG
643                 ? CGEN_ENDIAN_BIG
644                 : CGEN_ENDIAN_LITTLE);
645   enum bfd_architecture arch;
646
647   /* ??? gdb will set mach but leave the architecture as "unknown" */
648 #ifndef CGEN_BFD_ARCH
649 #define CGEN_BFD_ARCH bfd_arch_fr30
650 #endif
651   arch = info->arch;
652   if (arch == bfd_arch_unknown)
653     arch = CGEN_BFD_ARCH;
654    
655   /* There's no standard way to compute the machine or isa number
656      so we leave it to the target.  */
657 #ifdef CGEN_COMPUTE_MACH
658   mach = CGEN_COMPUTE_MACH (info);
659 #else
660   mach = info->mach;
661 #endif
662
663 #ifdef CGEN_COMPUTE_ISA
664   isa = CGEN_COMPUTE_ISA (info);
665 #else
666   isa = 0;
667 #endif
668
669   /* If we've switched cpu's, close the current table and open a new one.  */
670   if (cd
671       && (isa != prev_isa
672           || mach != prev_mach
673           || endian != prev_endian))
674     {
675       fr30_cgen_cpu_close (cd);
676       cd = 0;
677     }
678
679   /* If we haven't initialized yet, initialize the opcode table.  */
680   if (! cd)
681     {
682       const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
683       const char *mach_name;
684
685       if (!arch_type)
686         abort ();
687       mach_name = arch_type->printable_name;
688
689       prev_isa = isa;
690       prev_mach = mach;
691       prev_endian = endian;
692       cd = fr30_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
693                                  CGEN_CPU_OPEN_BFDMACH, mach_name,
694                                  CGEN_CPU_OPEN_ENDIAN, prev_endian,
695                                  CGEN_CPU_OPEN_END);
696       if (!cd)
697         abort ();
698       fr30_cgen_init_dis (cd);
699     }
700
701   /* We try to have as much common code as possible.
702      But at this point some targets need to take over.  */
703   /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
704      but if not possible try to move this hook elsewhere rather than
705      have two hooks.  */
706   length = CGEN_PRINT_INSN (cd, pc, info);
707   if (length > 0)
708     return length;
709   if (length < 0)
710     return -1;
711
712   (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
713   return cd->default_insn_bitsize / 8;
714 }