Add code to handle even-numbered only register operands
[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_FRINTIEVEN :
234       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRi, 0);
235       break;
236     case FRV_OPERAND_FRINTJ :
237       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRj, 0);
238       break;
239     case FRV_OPERAND_FRINTJEVEN :
240       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRj, 0);
241       break;
242     case FRV_OPERAND_FRINTK :
243       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
244       break;
245     case FRV_OPERAND_FRINTKEVEN :
246       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
247       break;
248     case FRV_OPERAND_FRJ :
249       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRj, 0);
250       break;
251     case FRV_OPERAND_FRK :
252       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
253       break;
254     case FRV_OPERAND_FRKHI :
255       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
256       break;
257     case FRV_OPERAND_FRKLO :
258       print_keyword (cd, info, & frv_cgen_opval_fr_names, fields->f_FRk, 0);
259       break;
260     case FRV_OPERAND_GRDOUBLEK :
261       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
262       break;
263     case FRV_OPERAND_GRI :
264       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRi, 0);
265       break;
266     case FRV_OPERAND_GRJ :
267       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRj, 0);
268       break;
269     case FRV_OPERAND_GRK :
270       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
271       break;
272     case FRV_OPERAND_GRKHI :
273       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
274       break;
275     case FRV_OPERAND_GRKLO :
276       print_keyword (cd, info, & frv_cgen_opval_gr_names, fields->f_GRk, 0);
277       break;
278     case FRV_OPERAND_ICCI_1 :
279       print_keyword (cd, info, & frv_cgen_opval_iccr_names, fields->f_ICCi_1, 0);
280       break;
281     case FRV_OPERAND_ICCI_2 :
282       print_keyword (cd, info, & frv_cgen_opval_iccr_names, fields->f_ICCi_2, 0);
283       break;
284     case FRV_OPERAND_ICCI_3 :
285       print_keyword (cd, info, & frv_cgen_opval_iccr_names, fields->f_ICCi_3, 0);
286       break;
287     case FRV_OPERAND_LI :
288       print_normal (cd, info, fields->f_LI, 0, pc, length);
289       break;
290     case FRV_OPERAND_AE :
291       print_normal (cd, info, fields->f_ae, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
292       break;
293     case FRV_OPERAND_CCOND :
294       print_normal (cd, info, fields->f_ccond, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
295       break;
296     case FRV_OPERAND_COND :
297       print_normal (cd, info, fields->f_cond, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
298       break;
299     case FRV_OPERAND_D12 :
300       print_normal (cd, info, fields->f_d12, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
301       break;
302     case FRV_OPERAND_DEBUG :
303       print_normal (cd, info, fields->f_debug, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
304       break;
305     case FRV_OPERAND_EIR :
306       print_normal (cd, info, fields->f_eir, 0, pc, length);
307       break;
308     case FRV_OPERAND_HINT :
309       print_normal (cd, info, fields->f_hint, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
310       break;
311     case FRV_OPERAND_HINT_NOT_TAKEN :
312       print_keyword (cd, info, & frv_cgen_opval_h_hint_not_taken, fields->f_hint, 0);
313       break;
314     case FRV_OPERAND_HINT_TAKEN :
315       print_keyword (cd, info, & frv_cgen_opval_h_hint_taken, fields->f_hint, 0);
316       break;
317     case FRV_OPERAND_LABEL16 :
318       print_address (cd, info, fields->f_label16, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
319       break;
320     case FRV_OPERAND_LABEL24 :
321       print_address (cd, info, fields->f_label24, 0|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
322       break;
323     case FRV_OPERAND_LOCK :
324       print_normal (cd, info, fields->f_lock, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
325       break;
326     case FRV_OPERAND_PACK :
327       print_keyword (cd, info, & frv_cgen_opval_h_pack, fields->f_pack, 0);
328       break;
329     case FRV_OPERAND_S10 :
330       print_normal (cd, info, fields->f_s10, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
331       break;
332     case FRV_OPERAND_S12 :
333       print_normal (cd, info, fields->f_d12, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
334       break;
335     case FRV_OPERAND_S16 :
336       print_normal (cd, info, fields->f_s16, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
337       break;
338     case FRV_OPERAND_S5 :
339       print_normal (cd, info, fields->f_s5, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
340       break;
341     case FRV_OPERAND_S6 :
342       print_normal (cd, info, fields->f_s6, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
343       break;
344     case FRV_OPERAND_S6_1 :
345       print_normal (cd, info, fields->f_s6_1, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
346       break;
347     case FRV_OPERAND_SLO16 :
348       print_lo (cd, info, fields->f_s16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
349       break;
350     case FRV_OPERAND_SPR :
351       print_spr (cd, info, & frv_cgen_opval_spr_names, fields->f_spr, 0|(1<<CGEN_OPERAND_VIRTUAL));
352       break;
353     case FRV_OPERAND_U12 :
354       print_normal (cd, info, fields->f_u12, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
355       break;
356     case FRV_OPERAND_U16 :
357       print_normal (cd, info, fields->f_u16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
358       break;
359     case FRV_OPERAND_U6 :
360       print_normal (cd, info, fields->f_u6, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
361       break;
362     case FRV_OPERAND_UHI16 :
363       print_hi (cd, info, fields->f_u16, 0, pc, length);
364       break;
365     case FRV_OPERAND_ULO16 :
366       print_lo (cd, info, fields->f_u16, 0, pc, length);
367       break;
368
369     default :
370       /* xgettext:c-format */
371       fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
372                opindex);
373     abort ();
374   }
375 }
376
377 cgen_print_fn * const frv_cgen_print_handlers[] = 
378 {
379   print_insn_normal,
380 };
381
382
383 void
384 frv_cgen_init_dis (cd)
385      CGEN_CPU_DESC cd;
386 {
387   frv_cgen_init_opcode_table (cd);
388   frv_cgen_init_ibld_table (cd);
389   cd->print_handlers = & frv_cgen_print_handlers[0];
390   cd->print_operand = frv_cgen_print_operand;
391 }
392
393 \f
394 /* Default print handler.  */
395
396 static void
397 print_normal (cd, dis_info, value, attrs, pc, length)
398      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
399      PTR dis_info;
400      long value;
401      unsigned int attrs;
402      bfd_vma pc ATTRIBUTE_UNUSED;
403      int length ATTRIBUTE_UNUSED;
404 {
405   disassemble_info *info = (disassemble_info *) dis_info;
406
407 #ifdef CGEN_PRINT_NORMAL
408   CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
409 #endif
410
411   /* Print the operand as directed by the attributes.  */
412   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
413     ; /* nothing to do */
414   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
415     (*info->fprintf_func) (info->stream, "%ld", value);
416   else
417     (*info->fprintf_func) (info->stream, "0x%lx", value);
418 }
419
420 /* Default address handler.  */
421
422 static void
423 print_address (cd, dis_info, value, attrs, pc, length)
424      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
425      PTR dis_info;
426      bfd_vma value;
427      unsigned int attrs;
428      bfd_vma pc ATTRIBUTE_UNUSED;
429      int length ATTRIBUTE_UNUSED;
430 {
431   disassemble_info *info = (disassemble_info *) dis_info;
432
433 #ifdef CGEN_PRINT_ADDRESS
434   CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
435 #endif
436
437   /* Print the operand as directed by the attributes.  */
438   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
439     ; /* nothing to do */
440   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
441     (*info->print_address_func) (value, info);
442   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
443     (*info->print_address_func) (value, info);
444   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
445     (*info->fprintf_func) (info->stream, "%ld", (long) value);
446   else
447     (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
448 }
449
450 /* Keyword print handler.  */
451
452 static void
453 print_keyword (cd, dis_info, keyword_table, value, attrs)
454      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
455      PTR dis_info;
456      CGEN_KEYWORD *keyword_table;
457      long value;
458      unsigned int attrs ATTRIBUTE_UNUSED;
459 {
460   disassemble_info *info = (disassemble_info *) dis_info;
461   const CGEN_KEYWORD_ENTRY *ke;
462
463   ke = cgen_keyword_lookup_value (keyword_table, value);
464   if (ke != NULL)
465     (*info->fprintf_func) (info->stream, "%s", ke->name);
466   else
467     (*info->fprintf_func) (info->stream, "???");
468 }
469 \f
470 /* Default insn printer.
471
472    DIS_INFO is defined as `PTR' so the disassembler needn't know anything
473    about disassemble_info.  */
474
475 static void
476 print_insn_normal (cd, dis_info, insn, fields, pc, length)
477      CGEN_CPU_DESC cd;
478      PTR dis_info;
479      const CGEN_INSN *insn;
480      CGEN_FIELDS *fields;
481      bfd_vma pc;
482      int length;
483 {
484   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
485   disassemble_info *info = (disassemble_info *) dis_info;
486   const CGEN_SYNTAX_CHAR_TYPE *syn;
487
488   CGEN_INIT_PRINT (cd);
489
490   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
491     {
492       if (CGEN_SYNTAX_MNEMONIC_P (*syn))
493         {
494           (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
495           continue;
496         }
497       if (CGEN_SYNTAX_CHAR_P (*syn))
498         {
499           (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
500           continue;
501         }
502
503       /* We have an operand.  */
504       frv_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
505                                  fields, CGEN_INSN_ATTRS (insn), pc, length);
506     }
507 }
508 \f
509 /* Subroutine of print_insn. Reads an insn into the given buffers and updates
510    the extract info.
511    Returns 0 if all is well, non-zero otherwise.  */
512
513 static int
514 read_insn (cd, pc, info, buf, buflen, ex_info, insn_value)
515      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
516      bfd_vma pc;
517      disassemble_info *info;
518      char *buf;
519      int buflen;
520      CGEN_EXTRACT_INFO *ex_info;
521      unsigned long *insn_value;
522 {
523   int status = (*info->read_memory_func) (pc, buf, buflen, info);
524   if (status != 0)
525     {
526       (*info->memory_error_func) (status, pc, info);
527       return -1;
528     }
529
530   ex_info->dis_info = info;
531   ex_info->valid = (1 << buflen) - 1;
532   ex_info->insn_bytes = buf;
533
534   *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
535   return 0;
536 }
537
538 /* Utility to print an insn.
539    BUF is the base part of the insn, target byte order, BUFLEN bytes long.
540    The result is the size of the insn in bytes or zero for an unknown insn
541    or -1 if an error occurs fetching data (memory_error_func will have
542    been called).  */
543
544 static int
545 print_insn (cd, pc, info, buf, buflen)
546      CGEN_CPU_DESC cd;
547      bfd_vma pc;
548      disassemble_info *info;
549      char *buf;
550      unsigned int buflen;
551 {
552   CGEN_INSN_INT insn_value;
553   const CGEN_INSN_LIST *insn_list;
554   CGEN_EXTRACT_INFO ex_info;
555   int basesize;
556
557   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
558   basesize = cd->base_insn_bitsize < buflen * 8 ?
559                                      cd->base_insn_bitsize : buflen * 8;
560   insn_value = cgen_get_insn_value (cd, buf, basesize);
561
562
563   /* Fill in ex_info fields like read_insn would.  Don't actually call
564      read_insn, since the incoming buffer is already read (and possibly
565      modified a la m32r).  */
566   ex_info.valid = (1 << buflen) - 1;
567   ex_info.dis_info = info;
568   ex_info.insn_bytes = buf;
569
570   /* The instructions are stored in hash lists.
571      Pick the first one and keep trying until we find the right one.  */
572
573   insn_list = CGEN_DIS_LOOKUP_INSN (cd, buf, insn_value);
574   while (insn_list != NULL)
575     {
576       const CGEN_INSN *insn = insn_list->insn;
577       CGEN_FIELDS fields;
578       int length;
579       unsigned long insn_value_cropped;
580
581 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
582       /* Not needed as insn shouldn't be in hash lists if not supported.  */
583       /* Supported by this cpu?  */
584       if (! frv_cgen_insn_supported (cd, insn))
585         {
586           insn_list = CGEN_DIS_NEXT_INSN (insn_list);
587           continue;
588         }
589 #endif
590
591       /* Basic bit mask must be correct.  */
592       /* ??? May wish to allow target to defer this check until the extract
593          handler.  */
594
595       /* Base size may exceed this instruction's size.  Extract the
596          relevant part from the buffer. */
597       if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
598           (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
599         insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn), 
600                                            info->endian == BFD_ENDIAN_BIG);
601       else
602         insn_value_cropped = insn_value;
603
604       if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
605           == CGEN_INSN_BASE_VALUE (insn))
606         {
607           /* Printing is handled in two passes.  The first pass parses the
608              machine insn and extracts the fields.  The second pass prints
609              them.  */
610
611           /* Make sure the entire insn is loaded into insn_value, if it
612              can fit.  */
613           if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
614               (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
615             {
616               unsigned long full_insn_value;
617               int rc = read_insn (cd, pc, info, buf,
618                                   CGEN_INSN_BITSIZE (insn) / 8,
619                                   & ex_info, & full_insn_value);
620               if (rc != 0)
621                 return rc;
622               length = CGEN_EXTRACT_FN (cd, insn)
623                 (cd, insn, &ex_info, full_insn_value, &fields, pc);
624             }
625           else
626             length = CGEN_EXTRACT_FN (cd, insn)
627               (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
628
629           /* length < 0 -> error */
630           if (length < 0)
631             return length;
632           if (length > 0)
633             {
634               CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
635               /* length is in bits, result is in bytes */
636               return length / 8;
637             }
638         }
639
640       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
641     }
642
643   return 0;
644 }
645
646 /* Default value for CGEN_PRINT_INSN.
647    The result is the size of the insn in bytes or zero for an unknown insn
648    or -1 if an error occured fetching bytes.  */
649
650 #ifndef CGEN_PRINT_INSN
651 #define CGEN_PRINT_INSN default_print_insn
652 #endif
653
654 static int
655 default_print_insn (cd, pc, info)
656      CGEN_CPU_DESC cd;
657      bfd_vma pc;
658      disassemble_info *info;
659 {
660   char buf[CGEN_MAX_INSN_SIZE];
661   int buflen;
662   int status;
663
664   /* Attempt to read the base part of the insn.  */
665   buflen = cd->base_insn_bitsize / 8;
666   status = (*info->read_memory_func) (pc, buf, buflen, info);
667
668   /* Try again with the minimum part, if min < base.  */
669   if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
670     {
671       buflen = cd->min_insn_bitsize / 8;
672       status = (*info->read_memory_func) (pc, buf, buflen, info);
673     }
674
675   if (status != 0)
676     {
677       (*info->memory_error_func) (status, pc, info);
678       return -1;
679     }
680
681   return print_insn (cd, pc, info, buf, buflen);
682 }
683
684 /* Main entry point.
685    Print one instruction from PC on INFO->STREAM.
686    Return the size of the instruction (in bytes).  */
687
688 typedef struct cpu_desc_list {
689   struct cpu_desc_list *next;
690   int isa;
691   int mach;
692   int endian;
693   CGEN_CPU_DESC cd;
694 } cpu_desc_list;
695
696 int
697 print_insn_frv (pc, info)
698      bfd_vma pc;
699      disassemble_info *info;
700 {
701   static cpu_desc_list *cd_list = 0;
702   cpu_desc_list *cl = 0;
703   static CGEN_CPU_DESC cd = 0;
704   static int prev_isa;
705   static int prev_mach;
706   static int prev_endian;
707   int length;
708   int isa,mach;
709   int endian = (info->endian == BFD_ENDIAN_BIG
710                 ? CGEN_ENDIAN_BIG
711                 : CGEN_ENDIAN_LITTLE);
712   enum bfd_architecture arch;
713
714   /* ??? gdb will set mach but leave the architecture as "unknown" */
715 #ifndef CGEN_BFD_ARCH
716 #define CGEN_BFD_ARCH bfd_arch_frv
717 #endif
718   arch = info->arch;
719   if (arch == bfd_arch_unknown)
720     arch = CGEN_BFD_ARCH;
721    
722   /* There's no standard way to compute the machine or isa number
723      so we leave it to the target.  */
724 #ifdef CGEN_COMPUTE_MACH
725   mach = CGEN_COMPUTE_MACH (info);
726 #else
727   mach = info->mach;
728 #endif
729
730 #ifdef CGEN_COMPUTE_ISA
731   isa = CGEN_COMPUTE_ISA (info);
732 #else
733   isa = info->insn_sets;
734 #endif
735
736   /* If we've switched cpu's, try to find a handle we've used before */
737   if (cd
738       && (isa != prev_isa
739           || mach != prev_mach
740           || endian != prev_endian))
741     {
742       cd = 0;
743       for (cl = cd_list; cl; cl = cl->next)
744         {
745           if (cl->isa == isa &&
746               cl->mach == mach &&
747               cl->endian == endian)
748             {
749               cd = cl->cd;
750               break;
751             }
752         }
753     } 
754
755   /* If we haven't initialized yet, initialize the opcode table.  */
756   if (! cd)
757     {
758       const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
759       const char *mach_name;
760
761       if (!arch_type)
762         abort ();
763       mach_name = arch_type->printable_name;
764
765       prev_isa = isa;
766       prev_mach = mach;
767       prev_endian = endian;
768       cd = frv_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
769                                  CGEN_CPU_OPEN_BFDMACH, mach_name,
770                                  CGEN_CPU_OPEN_ENDIAN, prev_endian,
771                                  CGEN_CPU_OPEN_END);
772       if (!cd)
773         abort ();
774
775       /* save this away for future reference */
776       cl = xmalloc (sizeof (struct cpu_desc_list));
777       cl->cd = cd;
778       cl->isa = isa;
779       cl->mach = mach;
780       cl->endian = endian;
781       cl->next = cd_list;
782       cd_list = cl;
783
784       frv_cgen_init_dis (cd);
785     }
786
787   /* We try to have as much common code as possible.
788      But at this point some targets need to take over.  */
789   /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
790      but if not possible try to move this hook elsewhere rather than
791      have two hooks.  */
792   length = CGEN_PRINT_INSN (cd, pc, info);
793   if (length > 0)
794     return length;
795   if (length < 0)
796     return -1;
797
798   (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
799   return cd->default_insn_bitsize / 8;
800 }