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-2016 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 
58 /* -- disassembler routines inserted here.  */
59 
60 /* -- dis.c */
61 static void
print_at(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,long reloc_ann ATTRIBUTE_UNUSED,long value ATTRIBUTE_UNUSED,bfd_vma pc ATTRIBUTE_UNUSED,int length ATTRIBUTE_UNUSED)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
print_spr(CGEN_CPU_DESC cd,void * dis_info,CGEN_KEYWORD * names,long regno,unsigned int attrs)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
print_hi(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,long value,unsigned int attrs ATTRIBUTE_UNUSED,bfd_vma pc ATTRIBUTE_UNUSED,int length ATTRIBUTE_UNUSED)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
print_lo(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,long value,unsigned int attrs ATTRIBUTE_UNUSED,bfd_vma pc ATTRIBUTE_UNUSED,int length ATTRIBUTE_UNUSED)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
frv_cgen_print_operand(CGEN_CPU_DESC cd,int opindex,void * xinfo,CGEN_FIELDS * fields,void const * attrs ATTRIBUTE_UNUSED,bfd_vma pc,int length)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
frv_cgen_init_dis(CGEN_CPU_DESC cd)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 
417 /* Default print handler.  */
418 
419 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)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
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)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
print_keyword(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,CGEN_KEYWORD * keyword_table,long value,unsigned int attrs ATTRIBUTE_UNUSED)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 
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
print_insn_normal(CGEN_CPU_DESC cd,void * dis_info,const CGEN_INSN * insn,CGEN_FIELDS * fields,bfd_vma pc,int length)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 
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
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)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
print_insn(CGEN_CPU_DESC cd,bfd_vma pc,disassemble_info * info,bfd_byte * buf,unsigned int buflen)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
default_print_insn(CGEN_CPU_DESC cd,bfd_vma pc,disassemble_info * info)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
print_insn_frv(bfd_vma pc,disassemble_info * info)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 }
817