Imported Upstream version 7.9
[platform/upstream/gdb.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 (C) 1996-2015 Free Software Foundation, Inc.
8
9    This file is part of libopcodes.
10
11    This library 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 3, or (at your option)
14    any later version.
15
16    It is distributed in the hope that it will be useful, but WITHOUT
17    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
19    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    51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 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 "libiberty.h"
35 #include "frv-desc.h"
36 #include "frv-opc.h"
37 #include "opintl.h"
38
39 /* Default text to print if an instruction isn't recognized.  */
40 #define UNKNOWN_INSN_MSG _("*unknown*")
41
42 static void print_normal
43   (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
44 static void print_address
45   (CGEN_CPU_DESC, void *, bfd_vma, unsigned int, bfd_vma, int) ATTRIBUTE_UNUSED;
46 static void print_keyword
47   (CGEN_CPU_DESC, void *, CGEN_KEYWORD *, long, unsigned int) ATTRIBUTE_UNUSED;
48 static void print_insn_normal
49   (CGEN_CPU_DESC, void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int);
50 static int print_insn
51   (CGEN_CPU_DESC, bfd_vma,  disassemble_info *, bfd_byte *, unsigned);
52 static int default_print_insn
53   (CGEN_CPU_DESC, bfd_vma, disassemble_info *) ATTRIBUTE_UNUSED;
54 static int read_insn
55   (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, int, CGEN_EXTRACT_INFO *,
56    unsigned long *);
57 \f
58 /* -- disassembler routines inserted here.  */
59
60 /* -- dis.c */
61 static void
62 print_at (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
63           void * dis_info,
64           long reloc_ann ATTRIBUTE_UNUSED,
65           long value ATTRIBUTE_UNUSED,
66           bfd_vma pc ATTRIBUTE_UNUSED,
67           int length ATTRIBUTE_UNUSED)
68 {
69   disassemble_info *info = (disassemble_info *) dis_info;
70
71   (*info->fprintf_func) (info->stream, "@");
72 }  
73
74 static void
75 print_spr (CGEN_CPU_DESC cd,
76            void * dis_info,
77            CGEN_KEYWORD *names,
78            long regno,
79            unsigned int attrs)
80 {
81   /* Use the register index format for any unnamed registers.  */
82   if (cgen_keyword_lookup_value (names, regno) == NULL)
83     {
84       disassemble_info *info = (disassemble_info *) dis_info;
85       (*info->fprintf_func) (info->stream, "spr[%ld]", regno);
86     }
87   else
88     print_keyword (cd, dis_info, names, regno, attrs);
89 }
90
91 static void
92 print_hi (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
93           void * dis_info,
94           long value,
95           unsigned int attrs ATTRIBUTE_UNUSED,
96           bfd_vma pc ATTRIBUTE_UNUSED,
97           int length ATTRIBUTE_UNUSED)
98 {
99   disassemble_info *info = (disassemble_info *) dis_info;
100
101   (*info->fprintf_func) (info->stream, value ? "0x%lx" : "hi(0x%lx)", value);
102 }
103
104 static void
105 print_lo (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
106           void * dis_info,
107           long value,
108           unsigned int attrs ATTRIBUTE_UNUSED,
109           bfd_vma pc ATTRIBUTE_UNUSED,
110           int length ATTRIBUTE_UNUSED)
111 {
112   disassemble_info *info = (disassemble_info *) dis_info;
113   if (value)
114     (*info->fprintf_func) (info->stream, "0x%lx", value);
115   else
116     (*info->fprintf_func) (info->stream, "lo(0x%lx)", value);
117 }
118
119 /* -- */
120
121 void frv_cgen_print_operand
122   (CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *, void const *, bfd_vma, int);
123
124 /* Main entry point for printing operands.
125    XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
126    of dis-asm.h on cgen.h.
127
128    This function is basically just a big switch statement.  Earlier versions
129    used tables to look up the function to use, but
130    - if the table contains both assembler and disassembler functions then
131      the disassembler contains much of the assembler and vice-versa,
132    - there's a lot of inlining possibilities as things grow,
133    - using a switch statement avoids the function call overhead.
134
135    This function could be moved into `print_insn_normal', but keeping it
136    separate makes clear the interface between `print_insn_normal' and each of
137    the handlers.  */
138
139 void
140 frv_cgen_print_operand (CGEN_CPU_DESC cd,
141                            int opindex,
142                            void * xinfo,
143                            CGEN_FIELDS *fields,
144                            void const *attrs ATTRIBUTE_UNUSED,
145                            bfd_vma pc,
146                            int length)
147 {
148   disassemble_info *info = (disassemble_info *) xinfo;
149
150   switch (opindex)
151     {
152     case FRV_OPERAND_A0 :
153       print_normal (cd, info, fields->f_A, 0, pc, length);
154       break;
155     case FRV_OPERAND_A1 :
156       print_normal (cd, info, fields->f_A, 0, 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_LRAD :
291       print_normal (cd, info, fields->f_LRAD, 0, pc, length);
292       break;
293     case FRV_OPERAND_LRAE :
294       print_normal (cd, info, fields->f_LRAE, 0, pc, length);
295       break;
296     case FRV_OPERAND_LRAS :
297       print_normal (cd, info, fields->f_LRAS, 0, pc, length);
298       break;
299     case FRV_OPERAND_TLBPRL :
300       print_normal (cd, info, fields->f_TLBPRL, 0, pc, length);
301       break;
302     case FRV_OPERAND_TLBPROPX :
303       print_normal (cd, info, fields->f_TLBPRopx, 0, pc, length);
304       break;
305     case FRV_OPERAND_AE :
306       print_normal (cd, info, fields->f_ae, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
307       break;
308     case FRV_OPERAND_CALLANN :
309       print_at (cd, info, fields->f_reloc_ann, 0, pc, length);
310       break;
311     case FRV_OPERAND_CCOND :
312       print_normal (cd, info, fields->f_ccond, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
313       break;
314     case FRV_OPERAND_COND :
315       print_normal (cd, info, fields->f_cond, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
316       break;
317     case FRV_OPERAND_D12 :
318       print_normal (cd, info, fields->f_d12, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
319       break;
320     case FRV_OPERAND_DEBUG :
321       print_normal (cd, info, fields->f_debug, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
322       break;
323     case FRV_OPERAND_EIR :
324       print_normal (cd, info, fields->f_eir, 0, pc, length);
325       break;
326     case FRV_OPERAND_HINT :
327       print_normal (cd, info, fields->f_hint, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
328       break;
329     case FRV_OPERAND_HINT_NOT_TAKEN :
330       print_keyword (cd, info, & frv_cgen_opval_h_hint_not_taken, fields->f_hint, 0);
331       break;
332     case FRV_OPERAND_HINT_TAKEN :
333       print_keyword (cd, info, & frv_cgen_opval_h_hint_taken, fields->f_hint, 0);
334       break;
335     case FRV_OPERAND_LABEL16 :
336       print_address (cd, info, fields->f_label16, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
337       break;
338     case FRV_OPERAND_LABEL24 :
339       print_address (cd, info, fields->f_label24, 0|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
340       break;
341     case FRV_OPERAND_LDANN :
342       print_at (cd, info, fields->f_reloc_ann, 0, pc, length);
343       break;
344     case FRV_OPERAND_LDDANN :
345       print_at (cd, info, fields->f_reloc_ann, 0, pc, length);
346       break;
347     case FRV_OPERAND_LOCK :
348       print_normal (cd, info, fields->f_lock, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
349       break;
350     case FRV_OPERAND_PACK :
351       print_keyword (cd, info, & frv_cgen_opval_h_pack, fields->f_pack, 0);
352       break;
353     case FRV_OPERAND_S10 :
354       print_normal (cd, info, fields->f_s10, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
355       break;
356     case FRV_OPERAND_S12 :
357       print_normal (cd, info, fields->f_d12, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
358       break;
359     case FRV_OPERAND_S16 :
360       print_normal (cd, info, fields->f_s16, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
361       break;
362     case FRV_OPERAND_S5 :
363       print_normal (cd, info, fields->f_s5, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
364       break;
365     case FRV_OPERAND_S6 :
366       print_normal (cd, info, fields->f_s6, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
367       break;
368     case FRV_OPERAND_S6_1 :
369       print_normal (cd, info, fields->f_s6_1, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
370       break;
371     case FRV_OPERAND_SLO16 :
372       print_lo (cd, info, fields->f_s16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
373       break;
374     case FRV_OPERAND_SPR :
375       print_spr (cd, info, & frv_cgen_opval_spr_names, fields->f_spr, 0|(1<<CGEN_OPERAND_VIRTUAL));
376       break;
377     case FRV_OPERAND_U12 :
378       print_normal (cd, info, fields->f_u12, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
379       break;
380     case FRV_OPERAND_U16 :
381       print_normal (cd, info, fields->f_u16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
382       break;
383     case FRV_OPERAND_U6 :
384       print_normal (cd, info, fields->f_u6, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
385       break;
386     case FRV_OPERAND_UHI16 :
387       print_hi (cd, info, fields->f_u16, 0, pc, length);
388       break;
389     case FRV_OPERAND_ULO16 :
390       print_lo (cd, info, fields->f_u16, 0, pc, length);
391       break;
392
393     default :
394       /* xgettext:c-format */
395       fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
396                opindex);
397     abort ();
398   }
399 }
400
401 cgen_print_fn * const frv_cgen_print_handlers[] = 
402 {
403   print_insn_normal,
404 };
405
406
407 void
408 frv_cgen_init_dis (CGEN_CPU_DESC cd)
409 {
410   frv_cgen_init_opcode_table (cd);
411   frv_cgen_init_ibld_table (cd);
412   cd->print_handlers = & frv_cgen_print_handlers[0];
413   cd->print_operand = frv_cgen_print_operand;
414 }
415
416 \f
417 /* Default print handler.  */
418
419 static void
420 print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
421               void *dis_info,
422               long value,
423               unsigned int attrs,
424               bfd_vma pc ATTRIBUTE_UNUSED,
425               int length ATTRIBUTE_UNUSED)
426 {
427   disassemble_info *info = (disassemble_info *) dis_info;
428
429   /* Print the operand as directed by the attributes.  */
430   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
431     ; /* nothing to do */
432   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
433     (*info->fprintf_func) (info->stream, "%ld", value);
434   else
435     (*info->fprintf_func) (info->stream, "0x%lx", value);
436 }
437
438 /* Default address handler.  */
439
440 static void
441 print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
442                void *dis_info,
443                bfd_vma value,
444                unsigned int attrs,
445                bfd_vma pc ATTRIBUTE_UNUSED,
446                int length ATTRIBUTE_UNUSED)
447 {
448   disassemble_info *info = (disassemble_info *) dis_info;
449
450   /* Print the operand as directed by the attributes.  */
451   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
452     ; /* Nothing to do.  */
453   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
454     (*info->print_address_func) (value, info);
455   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
456     (*info->print_address_func) (value, info);
457   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
458     (*info->fprintf_func) (info->stream, "%ld", (long) value);
459   else
460     (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
461 }
462
463 /* Keyword print handler.  */
464
465 static void
466 print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
467                void *dis_info,
468                CGEN_KEYWORD *keyword_table,
469                long value,
470                unsigned int attrs ATTRIBUTE_UNUSED)
471 {
472   disassemble_info *info = (disassemble_info *) dis_info;
473   const CGEN_KEYWORD_ENTRY *ke;
474
475   ke = cgen_keyword_lookup_value (keyword_table, value);
476   if (ke != NULL)
477     (*info->fprintf_func) (info->stream, "%s", ke->name);
478   else
479     (*info->fprintf_func) (info->stream, "???");
480 }
481 \f
482 /* Default insn printer.
483
484    DIS_INFO is defined as `void *' so the disassembler needn't know anything
485    about disassemble_info.  */
486
487 static void
488 print_insn_normal (CGEN_CPU_DESC cd,
489                    void *dis_info,
490                    const CGEN_INSN *insn,
491                    CGEN_FIELDS *fields,
492                    bfd_vma pc,
493                    int length)
494 {
495   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
496   disassemble_info *info = (disassemble_info *) dis_info;
497   const CGEN_SYNTAX_CHAR_TYPE *syn;
498
499   CGEN_INIT_PRINT (cd);
500
501   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
502     {
503       if (CGEN_SYNTAX_MNEMONIC_P (*syn))
504         {
505           (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
506           continue;
507         }
508       if (CGEN_SYNTAX_CHAR_P (*syn))
509         {
510           (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
511           continue;
512         }
513
514       /* We have an operand.  */
515       frv_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
516                                  fields, CGEN_INSN_ATTRS (insn), pc, length);
517     }
518 }
519 \f
520 /* Subroutine of print_insn. Reads an insn into the given buffers and updates
521    the extract info.
522    Returns 0 if all is well, non-zero otherwise.  */
523
524 static int
525 read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
526            bfd_vma pc,
527            disassemble_info *info,
528            bfd_byte *buf,
529            int buflen,
530            CGEN_EXTRACT_INFO *ex_info,
531            unsigned long *insn_value)
532 {
533   int status = (*info->read_memory_func) (pc, buf, buflen, info);
534
535   if (status != 0)
536     {
537       (*info->memory_error_func) (status, pc, info);
538       return -1;
539     }
540
541   ex_info->dis_info = info;
542   ex_info->valid = (1 << buflen) - 1;
543   ex_info->insn_bytes = buf;
544
545   *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
546   return 0;
547 }
548
549 /* Utility to print an insn.
550    BUF is the base part of the insn, target byte order, BUFLEN bytes long.
551    The result is the size of the insn in bytes or zero for an unknown insn
552    or -1 if an error occurs fetching data (memory_error_func will have
553    been called).  */
554
555 static int
556 print_insn (CGEN_CPU_DESC cd,
557             bfd_vma pc,
558             disassemble_info *info,
559             bfd_byte *buf,
560             unsigned int buflen)
561 {
562   CGEN_INSN_INT insn_value;
563   const CGEN_INSN_LIST *insn_list;
564   CGEN_EXTRACT_INFO ex_info;
565   int basesize;
566
567   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
568   basesize = cd->base_insn_bitsize < buflen * 8 ?
569                                      cd->base_insn_bitsize : buflen * 8;
570   insn_value = cgen_get_insn_value (cd, buf, basesize);
571
572
573   /* Fill in ex_info fields like read_insn would.  Don't actually call
574      read_insn, since the incoming buffer is already read (and possibly
575      modified a la m32r).  */
576   ex_info.valid = (1 << buflen) - 1;
577   ex_info.dis_info = info;
578   ex_info.insn_bytes = buf;
579
580   /* The instructions are stored in hash lists.
581      Pick the first one and keep trying until we find the right one.  */
582
583   insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
584   while (insn_list != NULL)
585     {
586       const CGEN_INSN *insn = insn_list->insn;
587       CGEN_FIELDS fields;
588       int length;
589       unsigned long insn_value_cropped;
590
591 #ifdef CGEN_VALIDATE_INSN_SUPPORTED 
592       /* Not needed as insn shouldn't be in hash lists if not supported.  */
593       /* Supported by this cpu?  */
594       if (! frv_cgen_insn_supported (cd, insn))
595         {
596           insn_list = CGEN_DIS_NEXT_INSN (insn_list);
597           continue;
598         }
599 #endif
600
601       /* Basic bit mask must be correct.  */
602       /* ??? May wish to allow target to defer this check until the extract
603          handler.  */
604
605       /* Base size may exceed this instruction's size.  Extract the
606          relevant part from the buffer. */
607       if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
608           (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
609         insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn), 
610                                            info->endian == BFD_ENDIAN_BIG);
611       else
612         insn_value_cropped = insn_value;
613
614       if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
615           == CGEN_INSN_BASE_VALUE (insn))
616         {
617           /* Printing is handled in two passes.  The first pass parses the
618              machine insn and extracts the fields.  The second pass prints
619              them.  */
620
621           /* Make sure the entire insn is loaded into insn_value, if it
622              can fit.  */
623           if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
624               (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
625             {
626               unsigned long full_insn_value;
627               int rc = read_insn (cd, pc, info, buf,
628                                   CGEN_INSN_BITSIZE (insn) / 8,
629                                   & ex_info, & full_insn_value);
630               if (rc != 0)
631                 return rc;
632               length = CGEN_EXTRACT_FN (cd, insn)
633                 (cd, insn, &ex_info, full_insn_value, &fields, pc);
634             }
635           else
636             length = CGEN_EXTRACT_FN (cd, insn)
637               (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
638
639           /* Length < 0 -> error.  */
640           if (length < 0)
641             return length;
642           if (length > 0)
643             {
644               CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
645               /* Length is in bits, result is in bytes.  */
646               return length / 8;
647             }
648         }
649
650       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
651     }
652
653   return 0;
654 }
655
656 /* Default value for CGEN_PRINT_INSN.
657    The result is the size of the insn in bytes or zero for an unknown insn
658    or -1 if an error occured fetching bytes.  */
659
660 #ifndef CGEN_PRINT_INSN
661 #define CGEN_PRINT_INSN default_print_insn
662 #endif
663
664 static int
665 default_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
666 {
667   bfd_byte buf[CGEN_MAX_INSN_SIZE];
668   int buflen;
669   int status;
670
671   /* Attempt to read the base part of the insn.  */
672   buflen = cd->base_insn_bitsize / 8;
673   status = (*info->read_memory_func) (pc, buf, buflen, info);
674
675   /* Try again with the minimum part, if min < base.  */
676   if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
677     {
678       buflen = cd->min_insn_bitsize / 8;
679       status = (*info->read_memory_func) (pc, buf, buflen, info);
680     }
681
682   if (status != 0)
683     {
684       (*info->memory_error_func) (status, pc, info);
685       return -1;
686     }
687
688   return print_insn (cd, pc, info, buf, buflen);
689 }
690
691 /* Main entry point.
692    Print one instruction from PC on INFO->STREAM.
693    Return the size of the instruction (in bytes).  */
694
695 typedef struct cpu_desc_list
696 {
697   struct cpu_desc_list *next;
698   CGEN_BITSET *isa;
699   int mach;
700   int endian;
701   CGEN_CPU_DESC cd;
702 } cpu_desc_list;
703
704 int
705 print_insn_frv (bfd_vma pc, disassemble_info *info)
706 {
707   static cpu_desc_list *cd_list = 0;
708   cpu_desc_list *cl = 0;
709   static CGEN_CPU_DESC cd = 0;
710   static CGEN_BITSET *prev_isa;
711   static int prev_mach;
712   static int prev_endian;
713   int length;
714   CGEN_BITSET *isa;
715   int mach;
716   int endian = (info->endian == BFD_ENDIAN_BIG
717                 ? CGEN_ENDIAN_BIG
718                 : CGEN_ENDIAN_LITTLE);
719   enum bfd_architecture arch;
720
721   /* ??? gdb will set mach but leave the architecture as "unknown" */
722 #ifndef CGEN_BFD_ARCH
723 #define CGEN_BFD_ARCH bfd_arch_frv
724 #endif
725   arch = info->arch;
726   if (arch == bfd_arch_unknown)
727     arch = CGEN_BFD_ARCH;
728    
729   /* There's no standard way to compute the machine or isa number
730      so we leave it to the target.  */
731 #ifdef CGEN_COMPUTE_MACH
732   mach = CGEN_COMPUTE_MACH (info);
733 #else
734   mach = info->mach;
735 #endif
736
737 #ifdef CGEN_COMPUTE_ISA
738   {
739     static CGEN_BITSET *permanent_isa;
740
741     if (!permanent_isa)
742       permanent_isa = cgen_bitset_create (MAX_ISAS);
743     isa = permanent_isa;
744     cgen_bitset_clear (isa);
745     cgen_bitset_add (isa, CGEN_COMPUTE_ISA (info));
746   }
747 #else
748   isa = info->insn_sets;
749 #endif
750
751   /* If we've switched cpu's, try to find a handle we've used before */
752   if (cd
753       && (cgen_bitset_compare (isa, prev_isa) != 0
754           || mach != prev_mach
755           || endian != prev_endian))
756     {
757       cd = 0;
758       for (cl = cd_list; cl; cl = cl->next)
759         {
760           if (cgen_bitset_compare (cl->isa, isa) == 0 &&
761               cl->mach == mach &&
762               cl->endian == endian)
763             {
764               cd = cl->cd;
765               prev_isa = cd->isas;
766               break;
767             }
768         }
769     } 
770
771   /* If we haven't initialized yet, initialize the opcode table.  */
772   if (! cd)
773     {
774       const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
775       const char *mach_name;
776
777       if (!arch_type)
778         abort ();
779       mach_name = arch_type->printable_name;
780
781       prev_isa = cgen_bitset_copy (isa);
782       prev_mach = mach;
783       prev_endian = endian;
784       cd = frv_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
785                                  CGEN_CPU_OPEN_BFDMACH, mach_name,
786                                  CGEN_CPU_OPEN_ENDIAN, prev_endian,
787                                  CGEN_CPU_OPEN_END);
788       if (!cd)
789         abort ();
790
791       /* Save this away for future reference.  */
792       cl = xmalloc (sizeof (struct cpu_desc_list));
793       cl->cd = cd;
794       cl->isa = prev_isa;
795       cl->mach = mach;
796       cl->endian = endian;
797       cl->next = cd_list;
798       cd_list = cl;
799
800       frv_cgen_init_dis (cd);
801     }
802
803   /* We try to have as much common code as possible.
804      But at this point some targets need to take over.  */
805   /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
806      but if not possible try to move this hook elsewhere rather than
807      have two hooks.  */
808   length = CGEN_PRINT_INSN (cd, pc, info);
809   if (length > 0)
810     return length;
811   if (length < 0)
812     return -1;
813
814   (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
815   return cd->default_insn_bitsize / 8;
816 }