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