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