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