* cgen-dis.in: Include libiberty.h.
[external/binutils.git] / opcodes / frv-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, 2002
8 Free Software Foundation, Inc.
9
10 This file is part of the GNU Binutils and GDB, the GNU debugger.
11
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2, or (at your option)
15 any later version.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software Foundation, Inc.,
24 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
25
26 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
27    Keep that in mind.  */
28
29 #include "sysdep.h"
30 #include <stdio.h>
31 #include "ansidecl.h"
32 #include "dis-asm.h"
33 #include "bfd.h"
34 #include "symcat.h"
35 #include "libiberty.h"
36 #include "frv-desc.h"
37 #include "frv-opc.h"
38 #include "opintl.h"
39
40 /* Default text to print if an instruction isn't recognized.  */
41 #define UNKNOWN_INSN_MSG _("*unknown*")
42
43 static void print_normal
44      PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned int, bfd_vma, int));
45 static void print_address
46      PARAMS ((CGEN_CPU_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int));
47 static void print_keyword
48      PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int));
49 static void print_insn_normal
50      PARAMS ((CGEN_CPU_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *,
51               bfd_vma, int));
52 static int print_insn
53      PARAMS ((CGEN_CPU_DESC, bfd_vma,  disassemble_info *, char *, unsigned));
54 static int default_print_insn
55      PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *));
56 static int read_insn
57      PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *, char *, int,
58               CGEN_EXTRACT_INFO *, unsigned long *));
59 \f
60 /* -- disassembler routines inserted here */
61
62 /* -- dis.c */
63 static void print_spr
64   PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned));
65 static void print_hi
66   PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
67 static void print_lo
68   PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
69
70 static void
71 print_spr (cd, dis_info, names, regno, attrs)
72      CGEN_CPU_DESC cd;
73      PTR dis_info;
74      CGEN_KEYWORD *names;
75      long regno;
76      unsigned int attrs;
77 {
78   /* Use the register index format for any unnamed registers.  */
79   if (cgen_keyword_lookup_value (names, regno) == NULL)
80     {
81       disassemble_info *info = (disassemble_info *) dis_info;
82       (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
83     }
84   else
85     print_keyword (cd, dis_info, names, regno, attrs);
86 }
87
88 static void
89 print_hi (cd, dis_info, value, attrs, pc, length)
90      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
91      PTR dis_info;
92      long value;
93      unsigned int attrs ATTRIBUTE_UNUSED;
94      bfd_vma pc ATTRIBUTE_UNUSED;
95      int length ATTRIBUTE_UNUSED;
96 {
97   disassemble_info *info = (disassemble_info *) dis_info;
98   if (value)
99     (*info->fprintf_func) (info->stream, "0x%lx", value);
100   else
101     (*info->fprintf_func) (info->stream, "hi(0x%lx)", value);
102 }
103
104 static void
105 print_lo (cd, dis_info, value, attrs, pc, length)
106      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
107      PTR dis_info;
108      long value;
109      unsigned int attrs ATTRIBUTE_UNUSED;
110      bfd_vma pc ATTRIBUTE_UNUSED;
111      int length ATTRIBUTE_UNUSED;
112 {
113   disassemble_info *info = (disassemble_info *) dis_info;
114   if (value)
115     (*info->fprintf_func) (info->stream, "0x%lx", value);
116   else
117     (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
118 }
119
120 /* -- */
121
122 void frv_cgen_print_operand
123   PARAMS ((CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *,
124            void const *, bfd_vma, int));
125
126 /* Main entry point for printing operands.
127    XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
128    of dis-asm.h on cgen.h.
129
130    This function is basically just a big switch statement.  Earlier versions
131    used tables to look up the function to use, but
132    - if the table contains both assembler and disassembler functions then
133      the disassembler contains much of the assembler and vice-versa,
134    - there's a lot of inlining possibilities as things grow,
135    - using a switch statement avoids the function call overhead.
136
137    This function could be moved into `print_insn_normal', but keeping it
138    separate makes clear the interface between `print_insn_normal' and each of
139    the handlers.  */
140
141 void
142 frv_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length)
143      CGEN_CPU_DESC cd;
144      int opindex;
145      PTR xinfo;
146      CGEN_FIELDS *fields;
147      void const *attrs ATTRIBUTE_UNUSED;
148      bfd_vma pc;
149      int length;
150 {
151  disassemble_info *info = (disassemble_info *) xinfo;
152
153   switch (opindex)
154     {
155     case FRV_OPERAND_A :
156       print_normal (cd, info, fields->f_A, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
157       break;
158     case FRV_OPERAND_ACC40SI :
159       print_keyword (cd, info, & frv_cgen_opval_acc_names, fields->f_ACC40Si, 0);
160       break;
161     case FRV_OPERAND_ACC40SK :
162       print_keyword (cd, info, & frv_cgen_opval_acc_names, fields->f_ACC40Sk, 0);
163       break;
164     case FRV_OPERAND_ACC40UI :
165       print_keyword (cd, info, & frv_cgen_opval_acc_names, fields->f_ACC40Ui, 0);
166       break;
167     case FRV_OPERAND_ACC40UK :
168       print_keyword (cd, info, & frv_cgen_opval_acc_names, fields->f_ACC40Uk, 0);
169       break;
170     case FRV_OPERAND_ACCGI :
171       print_keyword (cd, info, & frv_cgen_opval_accg_names, fields->f_ACCGi, 0);
172       break;
173     case FRV_OPERAND_ACCGK :
174       print_keyword (cd, info, & frv_cgen_opval_accg_names, fields->f_ACCGk, 0);
175       break;
176     case FRV_OPERAND_CCI :
177       print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CCi, 0);
178       break;
179     case FRV_OPERAND_CPRDOUBLEK :
180       print_keyword (cd, info, & frv_cgen_opval_cpr_names, fields->f_CPRk, 0);
181       break;
182     case FRV_OPERAND_CPRI :
183       print_keyword (cd, info, & frv_cgen_opval_cpr_names, fields->f_CPRi, 0);
184       break;
185     case FRV_OPERAND_CPRJ :
186       print_keyword (cd, info, & frv_cgen_opval_cpr_names, fields->f_CPRj, 0);
187       break;
188     case FRV_OPERAND_CPRK :
189       print_keyword (cd, info, & frv_cgen_opval_cpr_names, fields->f_CPRk, 0);
190       break;
191     case FRV_OPERAND_CRI :
192       print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRi, 0);
193       break;
194     case FRV_OPERAND_CRJ :
195       print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRj, 0);
196       break;
197     case FRV_OPERAND_CRJ_FLOAT :
198       print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRj_float, 0);
199       break;
200     case FRV_OPERAND_CRJ_INT :
201       print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRj_int, 0);
202       break;
203     case FRV_OPERAND_CRK :
204       print_keyword (cd, info, & frv_cgen_opval_cccr_names, fields->f_CRk, 0);
205       break;
206     case FRV_OPERAND_FCCI_1 :
207       print_keyword (cd, info, & frv_cgen_opval_fccr_names, fields->f_FCCi_1, 0);
208       break;
209     case FRV_OPERAND_FCCI_2 :
210       print_keyword (cd, info, & frv_cgen_opval_fccr_names, fields->f_FCCi_2, 0);
211       break;
212     case FRV_OPERAND_FCCI_3 :
213       print_keyword (cd, info, & frv_cgen_opval_fccr_names, fields->f_FCCi_3, 0);
214       break;
215     case FRV_OPERAND_FCCK :
216       print_keyword (cd, info, & frv_cgen_opval_fccr_names, fields->f_FCCk, 0);
217       break;
218     case FRV_OPERAND_FRDOUBLEI :
219       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRi, 0);
220       break;
221     case FRV_OPERAND_FRDOUBLEJ :
222       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRj, 0);
223       break;
224     case FRV_OPERAND_FRDOUBLEK :
225       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
226       break;
227     case FRV_OPERAND_FRI :
228       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRi, 0);
229       break;
230     case FRV_OPERAND_FRINTI :
231       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRi, 0);
232       break;
233     case FRV_OPERAND_FRINTJ :
234       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRj, 0);
235       break;
236     case FRV_OPERAND_FRINTK :
237       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
238       break;
239     case FRV_OPERAND_FRJ :
240       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRj, 0);
241       break;
242     case FRV_OPERAND_FRK :
243       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
244       break;
245     case FRV_OPERAND_FRKHI :
246       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
247       break;
248     case FRV_OPERAND_FRKLO :
249       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
250       break;
251     case FRV_OPERAND_GRDOUBLEK :
252       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
253       break;
254     case FRV_OPERAND_GRI :
255       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRi, 0);
256       break;
257     case FRV_OPERAND_GRJ :
258       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRj, 0);
259       break;
260     case FRV_OPERAND_GRK :
261       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
262       break;
263     case FRV_OPERAND_GRKHI :
264       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
265       break;
266     case FRV_OPERAND_GRKLO :
267       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
268       break;
269     case FRV_OPERAND_ICCI_1 :
270       print_keyword (cd, info, & frv_cgen_opval_iccr_names, fields->f_ICCi_1, 0);
271       break;
272     case FRV_OPERAND_ICCI_2 :
273       print_keyword (cd, info, & frv_cgen_opval_iccr_names, fields->f_ICCi_2, 0);
274       break;
275     case FRV_OPERAND_ICCI_3 :
276       print_keyword (cd, info, & frv_cgen_opval_iccr_names, fields->f_ICCi_3, 0);
277       break;
278     case FRV_OPERAND_LI :
279       print_normal (cd, info, fields->f_LI, 0, pc, length);
280       break;
281     case FRV_OPERAND_AE :
282       print_normal (cd, info, fields->f_ae, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
283       break;
284     case FRV_OPERAND_CCOND :
285       print_normal (cd, info, fields->f_ccond, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
286       break;
287     case FRV_OPERAND_COND :
288       print_normal (cd, info, fields->f_cond, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
289       break;
290     case FRV_OPERAND_D12 :
291       print_normal (cd, info, fields->f_d12, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
292       break;
293     case FRV_OPERAND_DEBUG :
294       print_normal (cd, info, fields->f_debug, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
295       break;
296     case FRV_OPERAND_EIR :
297       print_normal (cd, info, fields->f_eir, 0, pc, length);
298       break;
299     case FRV_OPERAND_HINT :
300       print_normal (cd, info, fields->f_hint, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
301       break;
302     case FRV_OPERAND_HINT_NOT_TAKEN :
303       print_keyword (cd, info, & frv_cgen_opval_h_hint_not_taken, fields->f_hint, 0);
304       break;
305     case FRV_OPERAND_HINT_TAKEN :
306       print_keyword (cd, info, & frv_cgen_opval_h_hint_taken, fields->f_hint, 0);
307       break;
308     case FRV_OPERAND_LABEL16 :
309       print_address (cd, info, fields->f_label16, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
310       break;
311     case FRV_OPERAND_LABEL24 :
312       print_address (cd, info, fields->f_label24, 0|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
313       break;
314     case FRV_OPERAND_LOCK :
315       print_normal (cd, info, fields->f_lock, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
316       break;
317     case FRV_OPERAND_PACK :
318       print_keyword (cd, info, & frv_cgen_opval_h_pack, fields->f_pack, 0);
319       break;
320     case FRV_OPERAND_S10 :
321       print_normal (cd, info, fields->f_s10, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
322       break;
323     case FRV_OPERAND_S12 :
324       print_normal (cd, info, fields->f_d12, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
325       break;
326     case FRV_OPERAND_S16 :
327       print_normal (cd, info, fields->f_s16, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
328       break;
329     case FRV_OPERAND_S5 :
330       print_normal (cd, info, fields->f_s5, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
331       break;
332     case FRV_OPERAND_S6 :
333       print_normal (cd, info, fields->f_s6, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
334       break;
335     case FRV_OPERAND_S6_1 :
336       print_normal (cd, info, fields->f_s6_1, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
337       break;
338     case FRV_OPERAND_SLO16 :
339       print_lo (cd, info, fields->f_s16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
340       break;
341     case FRV_OPERAND_SPR :
342       print_spr (cd, info, & frv_cgen_opval_spr_names, fields->f_spr, 0|(1<<CGEN_OPERAND_VIRTUAL));
343       break;
344     case FRV_OPERAND_U12 :
345       print_normal (cd, info, fields->f_u12, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
346       break;
347     case FRV_OPERAND_U16 :
348       print_normal (cd, info, fields->f_u16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
349       break;
350     case FRV_OPERAND_U6 :
351       print_normal (cd, info, fields->f_u6, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
352       break;
353     case FRV_OPERAND_UHI16 :
354       print_hi (cd, info, fields->f_u16, 0, pc, length);
355       break;
356     case FRV_OPERAND_ULO16 :
357       print_lo (cd, info, fields->f_u16, 0, pc, length);
358       break;
359
360     default :
361       /* xgettext:c-format */
362       fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
363                opindex);
364     abort ();
365   }
366 }
367
368 cgen_print_fn * const frv_cgen_print_handlers[] = 
369 {
370   print_insn_normal,
371 };
372
373
374 void
375 frv_cgen_init_dis (cd)
376      CGEN_CPU_DESC cd;
377 {
378   frv_cgen_init_opcode_table (cd);
379   frv_cgen_init_ibld_table (cd);
380   cd->print_handlers = & frv_cgen_print_handlers[0];
381   cd->print_operand = frv_cgen_print_operand;
382 }
383
384 \f
385 /* Default print handler.  */
386
387 static void
388 print_normal (cd, dis_info, value, attrs, pc, length)
389      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
390      PTR dis_info;
391      long value;
392      unsigned int attrs;
393      bfd_vma pc ATTRIBUTE_UNUSED;
394      int length ATTRIBUTE_UNUSED;
395 {
396   disassemble_info *info = (disassemble_info *) dis_info;
397
398 #ifdef CGEN_PRINT_NORMAL
399   CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
400 #endif
401
402   /* Print the operand as directed by the attributes.  */
403   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
404     ; /* nothing to do */
405   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
406     (*info->fprintf_func) (info->stream, "%ld", value);
407   else
408     (*info->fprintf_func) (info->stream, "0x%lx", value);
409 }
410
411 /* Default address handler.  */
412
413 static void
414 print_address (cd, dis_info, value, attrs, pc, length)
415      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
416      PTR dis_info;
417      bfd_vma value;
418      unsigned int attrs;
419      bfd_vma pc ATTRIBUTE_UNUSED;
420      int length ATTRIBUTE_UNUSED;
421 {
422   disassemble_info *info = (disassemble_info *) dis_info;
423
424 #ifdef CGEN_PRINT_ADDRESS
425   CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
426 #endif
427
428   /* Print the operand as directed by the attributes.  */
429   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
430     ; /* nothing to do */
431   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
432     (*info->print_address_func) (value, info);
433   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
434     (*info->print_address_func) (value, info);
435   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
436     (*info->fprintf_func) (info->stream, "%ld", (long) value);
437   else
438     (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
439 }
440
441 /* Keyword print handler.  */
442
443 static void
444 print_keyword (cd, dis_info, keyword_table, value, attrs)
445      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
446      PTR dis_info;
447      CGEN_KEYWORD *keyword_table;
448      long value;
449      unsigned int attrs ATTRIBUTE_UNUSED;
450 {
451   disassemble_info *info = (disassemble_info *) dis_info;
452   const CGEN_KEYWORD_ENTRY *ke;
453
454   ke = cgen_keyword_lookup_value (keyword_table, value);
455   if (ke != NULL)
456     (*info->fprintf_func) (info->stream, "%s", ke->name);
457   else
458     (*info->fprintf_func) (info->stream, "???");
459 }
460 \f
461 /* Default insn printer.
462
463    DIS_INFO is defined as `PTR' so the disassembler needn't know anything
464    about disassemble_info.  */
465
466 static void
467 print_insn_normal (cd, dis_info, insn, fields, pc, length)
468      CGEN_CPU_DESC cd;
469      PTR dis_info;
470      const CGEN_INSN *insn;
471      CGEN_FIELDS *fields;
472      bfd_vma pc;
473      int length;
474 {
475   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
476   disassemble_info *info = (disassemble_info *) dis_info;
477   const CGEN_SYNTAX_CHAR_TYPE *syn;
478
479   CGEN_INIT_PRINT (cd);
480
481   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
482     {
483       if (CGEN_SYNTAX_MNEMONIC_P (*syn))
484         {
485           (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
486           continue;
487         }
488       if (CGEN_SYNTAX_CHAR_P (*syn))
489         {
490           (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
491           continue;
492         }
493
494       /* We have an operand.  */
495       frv_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
496                                  fields, CGEN_INSN_ATTRS (insn), pc, length);
497     }
498 }
499 \f
500 /* Subroutine of print_insn. Reads an insn into the given buffers and updates
501    the extract info.
502    Returns 0 if all is well, non-zero otherwise.  */
503
504 static int
505 read_insn (cd, pc, info, buf, buflen, ex_info, insn_value)
506      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
507      bfd_vma pc;
508      disassemble_info *info;
509      char *buf;
510      int buflen;
511      CGEN_EXTRACT_INFO *ex_info;
512      unsigned long *insn_value;
513 {
514   int status = (*info->read_memory_func) (pc, buf, buflen, info);
515   if (status != 0)
516     {
517       (*info->memory_error_func) (status, pc, info);
518       return -1;
519     }
520
521   ex_info->dis_info = info;
522   ex_info->valid = (1 << buflen) - 1;
523   ex_info->insn_bytes = buf;
524
525   *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
526   return 0;
527 }
528
529 /* Utility to print an insn.
530    BUF is the base part of the insn, target byte order, BUFLEN bytes long.
531    The result is the size of the insn in bytes or zero for an unknown insn
532    or -1 if an error occurs fetching data (memory_error_func will have
533    been called).  */
534
535 static int
536 print_insn (cd, pc, info, buf, buflen)
537      CGEN_CPU_DESC cd;
538      bfd_vma pc;
539      disassemble_info *info;
540      char *buf;
541      unsigned int buflen;
542 {
543   CGEN_INSN_INT insn_value;
544   const CGEN_INSN_LIST *insn_list;
545   CGEN_EXTRACT_INFO ex_info;
546   int basesize;
547
548   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
549   basesize = cd->base_insn_bitsize < buflen * 8 ?
550                                      cd->base_insn_bitsize : buflen * 8;
551   insn_value = cgen_get_insn_value (cd, buf, basesize);
552
553
554   /* Fill in ex_info fields like read_insn would.  Don't actually call
555      read_insn, since the incoming buffer is already read (and possibly
556      modified a la m32r).  */
557   ex_info.valid = (1 << buflen) - 1;
558   ex_info.dis_info = info;
559   ex_info.insn_bytes = buf;
560
561   /* The instructions are stored in hash lists.
562      Pick the first one and keep trying until we find the right one.  */
563
564   insn_list = CGEN_DIS_LOOKUP_INSN (cd, buf, insn_value);
565   while (insn_list != NULL)
566     {
567       const CGEN_INSN *insn = insn_list->insn;
568       CGEN_FIELDS fields;
569       int length;
570       unsigned long insn_value_cropped;
571
572 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
573       /* Not needed as insn shouldn't be in hash lists if not supported.  */
574       /* Supported by this cpu?  */
575       if (! frv_cgen_insn_supported (cd, insn))
576         {
577           insn_list = CGEN_DIS_NEXT_INSN (insn_list);
578           continue;
579         }
580 #endif
581
582       /* Basic bit mask must be correct.  */
583       /* ??? May wish to allow target to defer this check until the extract
584          handler.  */
585
586       /* Base size may exceed this instruction's size.  Extract the
587          relevant part from the buffer. */
588       if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
589           (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
590         insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn), 
591                                            info->endian == BFD_ENDIAN_BIG);
592       else
593         insn_value_cropped = insn_value;
594
595       if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
596           == CGEN_INSN_BASE_VALUE (insn))
597         {
598           /* Printing is handled in two passes.  The first pass parses the
599              machine insn and extracts the fields.  The second pass prints
600              them.  */
601
602           /* Make sure the entire insn is loaded into insn_value, if it
603              can fit.  */
604           if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
605               (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
606             {
607               unsigned long full_insn_value;
608               int rc = read_insn (cd, pc, info, buf,
609                                   CGEN_INSN_BITSIZE (insn) / 8,
610                                   & ex_info, & full_insn_value);
611               if (rc != 0)
612                 return rc;
613               length = CGEN_EXTRACT_FN (cd, insn)
614                 (cd, insn, &ex_info, full_insn_value, &fields, pc);
615             }
616           else
617             length = CGEN_EXTRACT_FN (cd, insn)
618               (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
619
620           /* length < 0 -> error */
621           if (length < 0)
622             return length;
623           if (length > 0)
624             {
625               CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
626               /* length is in bits, result is in bytes */
627               return length / 8;
628             }
629         }
630
631       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
632     }
633
634   return 0;
635 }
636
637 /* Default value for CGEN_PRINT_INSN.
638    The result is the size of the insn in bytes or zero for an unknown insn
639    or -1 if an error occured fetching bytes.  */
640
641 #ifndef CGEN_PRINT_INSN
642 #define CGEN_PRINT_INSN default_print_insn
643 #endif
644
645 static int
646 default_print_insn (cd, pc, info)
647      CGEN_CPU_DESC cd;
648      bfd_vma pc;
649      disassemble_info *info;
650 {
651   char buf[CGEN_MAX_INSN_SIZE];
652   int buflen;
653   int status;
654
655   /* Attempt to read the base part of the insn.  */
656   buflen = cd->base_insn_bitsize / 8;
657   status = (*info->read_memory_func) (pc, buf, buflen, info);
658
659   /* Try again with the minimum part, if min < base.  */
660   if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
661     {
662       buflen = cd->min_insn_bitsize / 8;
663       status = (*info->read_memory_func) (pc, buf, buflen, info);
664     }
665
666   if (status != 0)
667     {
668       (*info->memory_error_func) (status, pc, info);
669       return -1;
670     }
671
672   return print_insn (cd, pc, info, buf, buflen);
673 }
674
675 /* Main entry point.
676    Print one instruction from PC on INFO->STREAM.
677    Return the size of the instruction (in bytes).  */
678
679 typedef struct cpu_desc_list {
680   struct cpu_desc_list *next;
681   int isa;
682   int mach;
683   int endian;
684   CGEN_CPU_DESC cd;
685 } cpu_desc_list;
686
687 int
688 print_insn_frv (pc, info)
689      bfd_vma pc;
690      disassemble_info *info;
691 {
692   static cpu_desc_list *cd_list = 0;
693   cpu_desc_list *cl = 0;
694   static CGEN_CPU_DESC cd = 0;
695   static int prev_isa;
696   static int prev_mach;
697   static int prev_endian;
698   int length;
699   int isa,mach;
700   int endian = (info->endian == BFD_ENDIAN_BIG
701                 ? CGEN_ENDIAN_BIG
702                 : CGEN_ENDIAN_LITTLE);
703   enum bfd_architecture arch;
704
705   /* ??? gdb will set mach but leave the architecture as "unknown" */
706 #ifndef CGEN_BFD_ARCH
707 #define CGEN_BFD_ARCH bfd_arch_frv
708 #endif
709   arch = info->arch;
710   if (arch == bfd_arch_unknown)
711     arch = CGEN_BFD_ARCH;
712    
713   /* There's no standard way to compute the machine or isa number
714      so we leave it to the target.  */
715 #ifdef CGEN_COMPUTE_MACH
716   mach = CGEN_COMPUTE_MACH (info);
717 #else
718   mach = info->mach;
719 #endif
720
721 #ifdef CGEN_COMPUTE_ISA
722   isa = CGEN_COMPUTE_ISA (info);
723 #else
724   isa = info->insn_sets;
725 #endif
726
727   /* If we've switched cpu's, try to find a handle we've used before */
728   if (cd
729       && (isa != prev_isa
730           || mach != prev_mach
731           || endian != prev_endian))
732     {
733       cd = 0;
734       for (cl = cd_list; cl; cl = cl->next)
735         {
736           if (cl->isa == isa &&
737               cl->mach == mach &&
738               cl->endian == endian)
739             {
740               cd = cl->cd;
741               break;
742             }
743         }
744     } 
745
746   /* If we haven't initialized yet, initialize the opcode table.  */
747   if (! cd)
748     {
749       const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
750       const char *mach_name;
751
752       if (!arch_type)
753         abort ();
754       mach_name = arch_type->printable_name;
755
756       prev_isa = isa;
757       prev_mach = mach;
758       prev_endian = endian;
759       cd = frv_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
760                                  CGEN_CPU_OPEN_BFDMACH, mach_name,
761                                  CGEN_CPU_OPEN_ENDIAN, prev_endian,
762                                  CGEN_CPU_OPEN_END);
763       if (!cd)
764         abort ();
765
766       /* save this away for future reference */
767       cl = xmalloc (sizeof (struct cpu_desc_list));
768       cl->cd = cd;
769       cl->isa = isa;
770       cl->mach = mach;
771       cl->endian = endian;
772       cl->next = cd_list;
773       cd_list = cl;
774
775       frv_cgen_init_dis (cd);
776     }
777
778   /* We try to have as much common code as possible.
779      But at this point some targets need to take over.  */
780   /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
781      but if not possible try to move this hook elsewhere rather than
782      have two hooks.  */
783   length = CGEN_PRINT_INSN (cd, pc, info);
784   if (length > 0)
785     return length;
786   if (length < 0)
787     return -1;
788
789   (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
790   return cd->default_insn_bitsize / 8;
791 }