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 "xstormy16-desc.h"
37d2201f2fSdrahn #include "xstormy16-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
62d2201f2fSdrahn void xstormy16_cgen_print_operand
63d2201f2fSdrahn PARAMS ((CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *,
64d2201f2fSdrahn void const *, bfd_vma, int));
65d2201f2fSdrahn
66d2201f2fSdrahn /* Main entry point for printing operands.
67d2201f2fSdrahn XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
68d2201f2fSdrahn of dis-asm.h on cgen.h.
69d2201f2fSdrahn
70d2201f2fSdrahn This function is basically just a big switch statement. Earlier versions
71d2201f2fSdrahn used tables to look up the function to use, but
72d2201f2fSdrahn - if the table contains both assembler and disassembler functions then
73d2201f2fSdrahn the disassembler contains much of the assembler and vice-versa,
74d2201f2fSdrahn - there's a lot of inlining possibilities as things grow,
75d2201f2fSdrahn - using a switch statement avoids the function call overhead.
76d2201f2fSdrahn
77d2201f2fSdrahn This function could be moved into `print_insn_normal', but keeping it
78d2201f2fSdrahn separate makes clear the interface between `print_insn_normal' and each of
79d2201f2fSdrahn the handlers. */
80d2201f2fSdrahn
81d2201f2fSdrahn void
xstormy16_cgen_print_operand(cd,opindex,xinfo,fields,attrs,pc,length)82d2201f2fSdrahn xstormy16_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length)
83d2201f2fSdrahn CGEN_CPU_DESC cd;
84d2201f2fSdrahn int opindex;
85d2201f2fSdrahn PTR xinfo;
86d2201f2fSdrahn CGEN_FIELDS *fields;
87d2201f2fSdrahn void const *attrs ATTRIBUTE_UNUSED;
88d2201f2fSdrahn bfd_vma pc;
89d2201f2fSdrahn int length;
90d2201f2fSdrahn {
91d2201f2fSdrahn disassemble_info *info = (disassemble_info *) xinfo;
92d2201f2fSdrahn
93d2201f2fSdrahn switch (opindex)
94d2201f2fSdrahn {
95d2201f2fSdrahn case XSTORMY16_OPERAND_RB :
96d2201f2fSdrahn print_keyword (cd, info, & xstormy16_cgen_opval_gr_Rb_names, fields->f_Rb, 0);
97d2201f2fSdrahn break;
98d2201f2fSdrahn case XSTORMY16_OPERAND_RBJ :
99d2201f2fSdrahn print_keyword (cd, info, & xstormy16_cgen_opval_gr_Rb_names, fields->f_Rbj, 0);
100d2201f2fSdrahn break;
101d2201f2fSdrahn case XSTORMY16_OPERAND_RD :
102d2201f2fSdrahn print_keyword (cd, info, & xstormy16_cgen_opval_gr_names, fields->f_Rd, 0);
103d2201f2fSdrahn break;
104d2201f2fSdrahn case XSTORMY16_OPERAND_RDM :
105d2201f2fSdrahn print_keyword (cd, info, & xstormy16_cgen_opval_gr_names, fields->f_Rdm, 0);
106d2201f2fSdrahn break;
107d2201f2fSdrahn case XSTORMY16_OPERAND_RM :
108d2201f2fSdrahn print_keyword (cd, info, & xstormy16_cgen_opval_gr_names, fields->f_Rm, 0);
109d2201f2fSdrahn break;
110d2201f2fSdrahn case XSTORMY16_OPERAND_RS :
111d2201f2fSdrahn print_keyword (cd, info, & xstormy16_cgen_opval_gr_names, fields->f_Rs, 0);
112d2201f2fSdrahn break;
113d2201f2fSdrahn case XSTORMY16_OPERAND_ABS24 :
114d2201f2fSdrahn print_normal (cd, info, fields->f_abs24, 0|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
115d2201f2fSdrahn break;
116d2201f2fSdrahn case XSTORMY16_OPERAND_BCOND2 :
117d2201f2fSdrahn print_keyword (cd, info, & xstormy16_cgen_opval_h_branchcond, fields->f_op2, 0);
118d2201f2fSdrahn break;
119d2201f2fSdrahn case XSTORMY16_OPERAND_BCOND5 :
120d2201f2fSdrahn print_keyword (cd, info, & xstormy16_cgen_opval_h_branchcond, fields->f_op5, 0);
121d2201f2fSdrahn break;
122d2201f2fSdrahn case XSTORMY16_OPERAND_HMEM8 :
123d2201f2fSdrahn print_normal (cd, info, fields->f_hmem8, 0|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
124d2201f2fSdrahn break;
125d2201f2fSdrahn case XSTORMY16_OPERAND_IMM12 :
126d2201f2fSdrahn print_normal (cd, info, fields->f_imm12, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
127d2201f2fSdrahn break;
128d2201f2fSdrahn case XSTORMY16_OPERAND_IMM16 :
129d2201f2fSdrahn print_normal (cd, info, fields->f_imm16, 0|(1<<CGEN_OPERAND_SIGN_OPT), pc, length);
130d2201f2fSdrahn break;
131d2201f2fSdrahn case XSTORMY16_OPERAND_IMM2 :
132d2201f2fSdrahn print_normal (cd, info, fields->f_imm2, 0, pc, length);
133d2201f2fSdrahn break;
134d2201f2fSdrahn case XSTORMY16_OPERAND_IMM3 :
135d2201f2fSdrahn print_normal (cd, info, fields->f_imm3, 0, pc, length);
136d2201f2fSdrahn break;
137d2201f2fSdrahn case XSTORMY16_OPERAND_IMM3B :
138d2201f2fSdrahn print_normal (cd, info, fields->f_imm3b, 0, pc, length);
139d2201f2fSdrahn break;
140d2201f2fSdrahn case XSTORMY16_OPERAND_IMM4 :
141d2201f2fSdrahn print_normal (cd, info, fields->f_imm4, 0, pc, length);
142d2201f2fSdrahn break;
143d2201f2fSdrahn case XSTORMY16_OPERAND_IMM8 :
144d2201f2fSdrahn print_normal (cd, info, fields->f_imm8, 0, pc, length);
145d2201f2fSdrahn break;
146d2201f2fSdrahn case XSTORMY16_OPERAND_IMM8SMALL :
147d2201f2fSdrahn print_normal (cd, info, fields->f_imm8, 0, pc, length);
148d2201f2fSdrahn break;
149d2201f2fSdrahn case XSTORMY16_OPERAND_LMEM8 :
150d2201f2fSdrahn print_normal (cd, info, fields->f_lmem8, 0|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
151d2201f2fSdrahn break;
152d2201f2fSdrahn case XSTORMY16_OPERAND_REL12 :
153d2201f2fSdrahn print_normal (cd, info, fields->f_rel12, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
154d2201f2fSdrahn break;
155d2201f2fSdrahn case XSTORMY16_OPERAND_REL12A :
156d2201f2fSdrahn print_normal (cd, info, fields->f_rel12a, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
157d2201f2fSdrahn break;
158d2201f2fSdrahn case XSTORMY16_OPERAND_REL8_2 :
159d2201f2fSdrahn print_normal (cd, info, fields->f_rel8_2, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
160d2201f2fSdrahn break;
161d2201f2fSdrahn case XSTORMY16_OPERAND_REL8_4 :
162d2201f2fSdrahn print_normal (cd, info, fields->f_rel8_4, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
163d2201f2fSdrahn break;
164d2201f2fSdrahn case XSTORMY16_OPERAND_WS2 :
165d2201f2fSdrahn print_keyword (cd, info, & xstormy16_cgen_opval_h_wordsize, fields->f_op2m, 0);
166d2201f2fSdrahn break;
167d2201f2fSdrahn
168d2201f2fSdrahn default :
169d2201f2fSdrahn /* xgettext:c-format */
170d2201f2fSdrahn fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
171d2201f2fSdrahn opindex);
172d2201f2fSdrahn abort ();
173d2201f2fSdrahn }
174d2201f2fSdrahn }
175d2201f2fSdrahn
176d2201f2fSdrahn cgen_print_fn * const xstormy16_cgen_print_handlers[] =
177d2201f2fSdrahn {
178d2201f2fSdrahn print_insn_normal,
179d2201f2fSdrahn };
180d2201f2fSdrahn
181d2201f2fSdrahn
182d2201f2fSdrahn void
xstormy16_cgen_init_dis(cd)183d2201f2fSdrahn xstormy16_cgen_init_dis (cd)
184d2201f2fSdrahn CGEN_CPU_DESC cd;
185d2201f2fSdrahn {
186d2201f2fSdrahn xstormy16_cgen_init_opcode_table (cd);
187d2201f2fSdrahn xstormy16_cgen_init_ibld_table (cd);
188d2201f2fSdrahn cd->print_handlers = & xstormy16_cgen_print_handlers[0];
189d2201f2fSdrahn cd->print_operand = xstormy16_cgen_print_operand;
190d2201f2fSdrahn }
191d2201f2fSdrahn
192d2201f2fSdrahn
193d2201f2fSdrahn /* Default print handler. */
194d2201f2fSdrahn
195d2201f2fSdrahn 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)196*cf2f2c56Smiod print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
197*cf2f2c56Smiod void *dis_info,
198*cf2f2c56Smiod long value,
199*cf2f2c56Smiod unsigned int attrs,
200*cf2f2c56Smiod bfd_vma pc ATTRIBUTE_UNUSED,
201*cf2f2c56Smiod int length ATTRIBUTE_UNUSED)
202d2201f2fSdrahn {
203d2201f2fSdrahn disassemble_info *info = (disassemble_info *) dis_info;
204d2201f2fSdrahn
205d2201f2fSdrahn #ifdef CGEN_PRINT_NORMAL
206d2201f2fSdrahn CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
207d2201f2fSdrahn #endif
208d2201f2fSdrahn
209d2201f2fSdrahn /* Print the operand as directed by the attributes. */
210d2201f2fSdrahn if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
211d2201f2fSdrahn ; /* nothing to do */
212d2201f2fSdrahn else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
213d2201f2fSdrahn (*info->fprintf_func) (info->stream, "%ld", value);
214d2201f2fSdrahn else
215d2201f2fSdrahn (*info->fprintf_func) (info->stream, "0x%lx", value);
216d2201f2fSdrahn }
217d2201f2fSdrahn
218d2201f2fSdrahn /* Default address handler. */
219d2201f2fSdrahn
220d2201f2fSdrahn 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)221*cf2f2c56Smiod print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
222*cf2f2c56Smiod void *dis_info,
223*cf2f2c56Smiod bfd_vma value,
224*cf2f2c56Smiod unsigned int attrs,
225*cf2f2c56Smiod bfd_vma pc ATTRIBUTE_UNUSED,
226*cf2f2c56Smiod int length ATTRIBUTE_UNUSED)
227d2201f2fSdrahn {
228d2201f2fSdrahn disassemble_info *info = (disassemble_info *) dis_info;
229d2201f2fSdrahn
230d2201f2fSdrahn #ifdef CGEN_PRINT_ADDRESS
231d2201f2fSdrahn CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
232d2201f2fSdrahn #endif
233d2201f2fSdrahn
234d2201f2fSdrahn /* Print the operand as directed by the attributes. */
235d2201f2fSdrahn if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
236d2201f2fSdrahn ; /* nothing to do */
237d2201f2fSdrahn else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
238d2201f2fSdrahn (*info->print_address_func) (value, info);
239d2201f2fSdrahn else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
240d2201f2fSdrahn (*info->print_address_func) (value, info);
241d2201f2fSdrahn else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
242d2201f2fSdrahn (*info->fprintf_func) (info->stream, "%ld", (long) value);
243d2201f2fSdrahn else
244d2201f2fSdrahn (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
245d2201f2fSdrahn }
246d2201f2fSdrahn
247d2201f2fSdrahn /* Keyword print handler. */
248d2201f2fSdrahn
249d2201f2fSdrahn static void
print_keyword(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,void * dis_info,CGEN_KEYWORD * keyword_table,long value,unsigned int attrs ATTRIBUTE_UNUSED)250*cf2f2c56Smiod print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
251*cf2f2c56Smiod void *dis_info,
252*cf2f2c56Smiod CGEN_KEYWORD *keyword_table,
253*cf2f2c56Smiod long value,
254*cf2f2c56Smiod unsigned int attrs ATTRIBUTE_UNUSED)
255d2201f2fSdrahn {
256d2201f2fSdrahn disassemble_info *info = (disassemble_info *) dis_info;
257d2201f2fSdrahn const CGEN_KEYWORD_ENTRY *ke;
258d2201f2fSdrahn
259d2201f2fSdrahn ke = cgen_keyword_lookup_value (keyword_table, value);
260d2201f2fSdrahn if (ke != NULL)
261d2201f2fSdrahn (*info->fprintf_func) (info->stream, "%s", ke->name);
262d2201f2fSdrahn else
263d2201f2fSdrahn (*info->fprintf_func) (info->stream, "???");
264d2201f2fSdrahn }
265d2201f2fSdrahn
266d2201f2fSdrahn /* Default insn printer.
267d2201f2fSdrahn
268*cf2f2c56Smiod DIS_INFO is defined as `void *' so the disassembler needn't know anything
269d2201f2fSdrahn about disassemble_info. */
270d2201f2fSdrahn
271d2201f2fSdrahn static void
print_insn_normal(CGEN_CPU_DESC cd,void * dis_info,const CGEN_INSN * insn,CGEN_FIELDS * fields,bfd_vma pc,int length)272*cf2f2c56Smiod print_insn_normal (CGEN_CPU_DESC cd,
273*cf2f2c56Smiod void *dis_info,
274*cf2f2c56Smiod const CGEN_INSN *insn,
275*cf2f2c56Smiod CGEN_FIELDS *fields,
276*cf2f2c56Smiod bfd_vma pc,
277*cf2f2c56Smiod int length)
278d2201f2fSdrahn {
279d2201f2fSdrahn const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
280d2201f2fSdrahn disassemble_info *info = (disassemble_info *) dis_info;
281d2201f2fSdrahn const CGEN_SYNTAX_CHAR_TYPE *syn;
282d2201f2fSdrahn
283d2201f2fSdrahn CGEN_INIT_PRINT (cd);
284d2201f2fSdrahn
285d2201f2fSdrahn for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
286d2201f2fSdrahn {
287d2201f2fSdrahn if (CGEN_SYNTAX_MNEMONIC_P (*syn))
288d2201f2fSdrahn {
289d2201f2fSdrahn (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
290d2201f2fSdrahn continue;
291d2201f2fSdrahn }
292d2201f2fSdrahn if (CGEN_SYNTAX_CHAR_P (*syn))
293d2201f2fSdrahn {
294d2201f2fSdrahn (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
295d2201f2fSdrahn continue;
296d2201f2fSdrahn }
297d2201f2fSdrahn
298d2201f2fSdrahn /* We have an operand. */
299d2201f2fSdrahn xstormy16_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
300d2201f2fSdrahn fields, CGEN_INSN_ATTRS (insn), pc, length);
301d2201f2fSdrahn }
302d2201f2fSdrahn }
303d2201f2fSdrahn
304d2201f2fSdrahn /* Subroutine of print_insn. Reads an insn into the given buffers and updates
305d2201f2fSdrahn the extract info.
306d2201f2fSdrahn Returns 0 if all is well, non-zero otherwise. */
307d2201f2fSdrahn
308d2201f2fSdrahn 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)309*cf2f2c56Smiod read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
310*cf2f2c56Smiod bfd_vma pc,
311*cf2f2c56Smiod disassemble_info *info,
312*cf2f2c56Smiod char *buf,
313*cf2f2c56Smiod int buflen,
314*cf2f2c56Smiod CGEN_EXTRACT_INFO *ex_info,
315*cf2f2c56Smiod unsigned long *insn_value)
316d2201f2fSdrahn {
317d2201f2fSdrahn int status = (*info->read_memory_func) (pc, buf, buflen, info);
318d2201f2fSdrahn if (status != 0)
319d2201f2fSdrahn {
320d2201f2fSdrahn (*info->memory_error_func) (status, pc, info);
321d2201f2fSdrahn return -1;
322d2201f2fSdrahn }
323d2201f2fSdrahn
324d2201f2fSdrahn ex_info->dis_info = info;
325d2201f2fSdrahn ex_info->valid = (1 << buflen) - 1;
326d2201f2fSdrahn ex_info->insn_bytes = buf;
327d2201f2fSdrahn
328d2201f2fSdrahn *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
329d2201f2fSdrahn return 0;
330d2201f2fSdrahn }
331d2201f2fSdrahn
332d2201f2fSdrahn /* Utility to print an insn.
333d2201f2fSdrahn BUF is the base part of the insn, target byte order, BUFLEN bytes long.
334d2201f2fSdrahn The result is the size of the insn in bytes or zero for an unknown insn
335d2201f2fSdrahn or -1 if an error occurs fetching data (memory_error_func will have
336d2201f2fSdrahn been called). */
337d2201f2fSdrahn
338d2201f2fSdrahn static int
print_insn(CGEN_CPU_DESC cd,bfd_vma pc,disassemble_info * info,char * buf,unsigned int buflen)339*cf2f2c56Smiod print_insn (CGEN_CPU_DESC cd,
340*cf2f2c56Smiod bfd_vma pc,
341*cf2f2c56Smiod disassemble_info *info,
342*cf2f2c56Smiod char *buf,
343*cf2f2c56Smiod unsigned int buflen)
344d2201f2fSdrahn {
345d2201f2fSdrahn CGEN_INSN_INT insn_value;
346d2201f2fSdrahn const CGEN_INSN_LIST *insn_list;
347d2201f2fSdrahn CGEN_EXTRACT_INFO ex_info;
348d2201f2fSdrahn int basesize;
349d2201f2fSdrahn
350d2201f2fSdrahn /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
351d2201f2fSdrahn basesize = cd->base_insn_bitsize < buflen * 8 ?
352d2201f2fSdrahn cd->base_insn_bitsize : buflen * 8;
353d2201f2fSdrahn insn_value = cgen_get_insn_value (cd, buf, basesize);
354d2201f2fSdrahn
355d2201f2fSdrahn
356d2201f2fSdrahn /* Fill in ex_info fields like read_insn would. Don't actually call
357d2201f2fSdrahn read_insn, since the incoming buffer is already read (and possibly
358d2201f2fSdrahn modified a la m32r). */
359d2201f2fSdrahn ex_info.valid = (1 << buflen) - 1;
360d2201f2fSdrahn ex_info.dis_info = info;
361d2201f2fSdrahn ex_info.insn_bytes = buf;
362d2201f2fSdrahn
363d2201f2fSdrahn /* The instructions are stored in hash lists.
364d2201f2fSdrahn Pick the first one and keep trying until we find the right one. */
365d2201f2fSdrahn
366d2201f2fSdrahn insn_list = CGEN_DIS_LOOKUP_INSN (cd, buf, insn_value);
367d2201f2fSdrahn while (insn_list != NULL)
368d2201f2fSdrahn {
369d2201f2fSdrahn const CGEN_INSN *insn = insn_list->insn;
370d2201f2fSdrahn CGEN_FIELDS fields;
371d2201f2fSdrahn int length;
372d2201f2fSdrahn unsigned long insn_value_cropped;
373d2201f2fSdrahn
374d2201f2fSdrahn #ifdef CGEN_VALIDATE_INSN_SUPPORTED
375d2201f2fSdrahn /* Not needed as insn shouldn't be in hash lists if not supported. */
376d2201f2fSdrahn /* Supported by this cpu? */
377d2201f2fSdrahn if (! xstormy16_cgen_insn_supported (cd, insn))
378d2201f2fSdrahn {
379d2201f2fSdrahn insn_list = CGEN_DIS_NEXT_INSN (insn_list);
380d2201f2fSdrahn continue;
381d2201f2fSdrahn }
382d2201f2fSdrahn #endif
383d2201f2fSdrahn
384d2201f2fSdrahn /* Basic bit mask must be correct. */
385d2201f2fSdrahn /* ??? May wish to allow target to defer this check until the extract
386d2201f2fSdrahn handler. */
387d2201f2fSdrahn
388d2201f2fSdrahn /* Base size may exceed this instruction's size. Extract the
389d2201f2fSdrahn relevant part from the buffer. */
390d2201f2fSdrahn if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
391d2201f2fSdrahn (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
392d2201f2fSdrahn insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
393d2201f2fSdrahn info->endian == BFD_ENDIAN_BIG);
394d2201f2fSdrahn else
395d2201f2fSdrahn insn_value_cropped = insn_value;
396d2201f2fSdrahn
397d2201f2fSdrahn if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
398d2201f2fSdrahn == CGEN_INSN_BASE_VALUE (insn))
399d2201f2fSdrahn {
400d2201f2fSdrahn /* Printing is handled in two passes. The first pass parses the
401d2201f2fSdrahn machine insn and extracts the fields. The second pass prints
402d2201f2fSdrahn them. */
403d2201f2fSdrahn
404d2201f2fSdrahn /* Make sure the entire insn is loaded into insn_value, if it
405d2201f2fSdrahn can fit. */
406d2201f2fSdrahn if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
407d2201f2fSdrahn (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
408d2201f2fSdrahn {
409d2201f2fSdrahn unsigned long full_insn_value;
410d2201f2fSdrahn int rc = read_insn (cd, pc, info, buf,
411d2201f2fSdrahn CGEN_INSN_BITSIZE (insn) / 8,
412d2201f2fSdrahn & ex_info, & full_insn_value);
413d2201f2fSdrahn if (rc != 0)
414d2201f2fSdrahn return rc;
415d2201f2fSdrahn length = CGEN_EXTRACT_FN (cd, insn)
416d2201f2fSdrahn (cd, insn, &ex_info, full_insn_value, &fields, pc);
417d2201f2fSdrahn }
418d2201f2fSdrahn else
419d2201f2fSdrahn length = CGEN_EXTRACT_FN (cd, insn)
420d2201f2fSdrahn (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
421d2201f2fSdrahn
422d2201f2fSdrahn /* length < 0 -> error */
423d2201f2fSdrahn if (length < 0)
424d2201f2fSdrahn return length;
425d2201f2fSdrahn if (length > 0)
426d2201f2fSdrahn {
427d2201f2fSdrahn CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
428d2201f2fSdrahn /* length is in bits, result is in bytes */
429d2201f2fSdrahn return length / 8;
430d2201f2fSdrahn }
431d2201f2fSdrahn }
432d2201f2fSdrahn
433d2201f2fSdrahn insn_list = CGEN_DIS_NEXT_INSN (insn_list);
434d2201f2fSdrahn }
435d2201f2fSdrahn
436d2201f2fSdrahn return 0;
437d2201f2fSdrahn }
438d2201f2fSdrahn
439d2201f2fSdrahn /* Default value for CGEN_PRINT_INSN.
440d2201f2fSdrahn The result is the size of the insn in bytes or zero for an unknown insn
441d2201f2fSdrahn or -1 if an error occured fetching bytes. */
442d2201f2fSdrahn
443d2201f2fSdrahn #ifndef CGEN_PRINT_INSN
444d2201f2fSdrahn #define CGEN_PRINT_INSN default_print_insn
445d2201f2fSdrahn #endif
446d2201f2fSdrahn
447d2201f2fSdrahn static int
default_print_insn(CGEN_CPU_DESC cd,bfd_vma pc,disassemble_info * info)448*cf2f2c56Smiod default_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
449d2201f2fSdrahn {
450d2201f2fSdrahn char buf[CGEN_MAX_INSN_SIZE];
451d2201f2fSdrahn int buflen;
452d2201f2fSdrahn int status;
453d2201f2fSdrahn
454d2201f2fSdrahn /* Attempt to read the base part of the insn. */
455d2201f2fSdrahn buflen = cd->base_insn_bitsize / 8;
456d2201f2fSdrahn status = (*info->read_memory_func) (pc, buf, buflen, info);
457d2201f2fSdrahn
458d2201f2fSdrahn /* Try again with the minimum part, if min < base. */
459d2201f2fSdrahn if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
460d2201f2fSdrahn {
461d2201f2fSdrahn buflen = cd->min_insn_bitsize / 8;
462d2201f2fSdrahn status = (*info->read_memory_func) (pc, buf, buflen, info);
463d2201f2fSdrahn }
464d2201f2fSdrahn
465d2201f2fSdrahn if (status != 0)
466d2201f2fSdrahn {
467d2201f2fSdrahn (*info->memory_error_func) (status, pc, info);
468d2201f2fSdrahn return -1;
469d2201f2fSdrahn }
470d2201f2fSdrahn
471d2201f2fSdrahn return print_insn (cd, pc, info, buf, buflen);
472d2201f2fSdrahn }
473d2201f2fSdrahn
474d2201f2fSdrahn /* Main entry point.
475d2201f2fSdrahn Print one instruction from PC on INFO->STREAM.
476d2201f2fSdrahn Return the size of the instruction (in bytes). */
477d2201f2fSdrahn
478d2201f2fSdrahn typedef struct cpu_desc_list {
479d2201f2fSdrahn struct cpu_desc_list *next;
480d2201f2fSdrahn int isa;
481d2201f2fSdrahn int mach;
482d2201f2fSdrahn int endian;
483d2201f2fSdrahn CGEN_CPU_DESC cd;
484d2201f2fSdrahn } cpu_desc_list;
485d2201f2fSdrahn
486d2201f2fSdrahn int
print_insn_xstormy16(bfd_vma pc,disassemble_info * info)487*cf2f2c56Smiod print_insn_xstormy16 (bfd_vma pc, disassemble_info *info)
488d2201f2fSdrahn {
489d2201f2fSdrahn static cpu_desc_list *cd_list = 0;
490d2201f2fSdrahn cpu_desc_list *cl = 0;
491d2201f2fSdrahn static CGEN_CPU_DESC cd = 0;
492d2201f2fSdrahn static int prev_isa;
493d2201f2fSdrahn static int prev_mach;
494d2201f2fSdrahn static int prev_endian;
495d2201f2fSdrahn int length;
496d2201f2fSdrahn int isa,mach;
497d2201f2fSdrahn int endian = (info->endian == BFD_ENDIAN_BIG
498d2201f2fSdrahn ? CGEN_ENDIAN_BIG
499d2201f2fSdrahn : CGEN_ENDIAN_LITTLE);
500d2201f2fSdrahn enum bfd_architecture arch;
501d2201f2fSdrahn
502d2201f2fSdrahn /* ??? gdb will set mach but leave the architecture as "unknown" */
503d2201f2fSdrahn #ifndef CGEN_BFD_ARCH
504d2201f2fSdrahn #define CGEN_BFD_ARCH bfd_arch_xstormy16
505d2201f2fSdrahn #endif
506d2201f2fSdrahn arch = info->arch;
507d2201f2fSdrahn if (arch == bfd_arch_unknown)
508d2201f2fSdrahn arch = CGEN_BFD_ARCH;
509d2201f2fSdrahn
510d2201f2fSdrahn /* There's no standard way to compute the machine or isa number
511d2201f2fSdrahn so we leave it to the target. */
512d2201f2fSdrahn #ifdef CGEN_COMPUTE_MACH
513d2201f2fSdrahn mach = CGEN_COMPUTE_MACH (info);
514d2201f2fSdrahn #else
515d2201f2fSdrahn mach = info->mach;
516d2201f2fSdrahn #endif
517d2201f2fSdrahn
518d2201f2fSdrahn #ifdef CGEN_COMPUTE_ISA
519d2201f2fSdrahn isa = CGEN_COMPUTE_ISA (info);
520d2201f2fSdrahn #else
521d2201f2fSdrahn isa = info->insn_sets;
522d2201f2fSdrahn #endif
523d2201f2fSdrahn
524d2201f2fSdrahn /* If we've switched cpu's, try to find a handle we've used before */
525d2201f2fSdrahn if (cd
526d2201f2fSdrahn && (isa != prev_isa
527d2201f2fSdrahn || mach != prev_mach
528d2201f2fSdrahn || endian != prev_endian))
529d2201f2fSdrahn {
530d2201f2fSdrahn cd = 0;
531d2201f2fSdrahn for (cl = cd_list; cl; cl = cl->next)
532d2201f2fSdrahn {
533d2201f2fSdrahn if (cl->isa == isa &&
534d2201f2fSdrahn cl->mach == mach &&
535d2201f2fSdrahn cl->endian == endian)
536d2201f2fSdrahn {
537d2201f2fSdrahn cd = cl->cd;
538d2201f2fSdrahn break;
539d2201f2fSdrahn }
540d2201f2fSdrahn }
541d2201f2fSdrahn }
542d2201f2fSdrahn
543d2201f2fSdrahn /* If we haven't initialized yet, initialize the opcode table. */
544d2201f2fSdrahn if (! cd)
545d2201f2fSdrahn {
546d2201f2fSdrahn const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
547d2201f2fSdrahn const char *mach_name;
548d2201f2fSdrahn
549d2201f2fSdrahn if (!arch_type)
550d2201f2fSdrahn abort ();
551d2201f2fSdrahn mach_name = arch_type->printable_name;
552d2201f2fSdrahn
553d2201f2fSdrahn prev_isa = isa;
554d2201f2fSdrahn prev_mach = mach;
555d2201f2fSdrahn prev_endian = endian;
556d2201f2fSdrahn cd = xstormy16_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
557d2201f2fSdrahn CGEN_CPU_OPEN_BFDMACH, mach_name,
558d2201f2fSdrahn CGEN_CPU_OPEN_ENDIAN, prev_endian,
559d2201f2fSdrahn CGEN_CPU_OPEN_END);
560d2201f2fSdrahn if (!cd)
561d2201f2fSdrahn abort ();
562d2201f2fSdrahn
563d2201f2fSdrahn /* save this away for future reference */
564d2201f2fSdrahn cl = xmalloc (sizeof (struct cpu_desc_list));
565d2201f2fSdrahn cl->cd = cd;
566d2201f2fSdrahn cl->isa = isa;
567d2201f2fSdrahn cl->mach = mach;
568d2201f2fSdrahn cl->endian = endian;
569d2201f2fSdrahn cl->next = cd_list;
570d2201f2fSdrahn cd_list = cl;
571d2201f2fSdrahn
572d2201f2fSdrahn xstormy16_cgen_init_dis (cd);
573d2201f2fSdrahn }
574d2201f2fSdrahn
575d2201f2fSdrahn /* We try to have as much common code as possible.
576d2201f2fSdrahn But at this point some targets need to take over. */
577d2201f2fSdrahn /* ??? Some targets may need a hook elsewhere. Try to avoid this,
578d2201f2fSdrahn but if not possible try to move this hook elsewhere rather than
579d2201f2fSdrahn have two hooks. */
580d2201f2fSdrahn length = CGEN_PRINT_INSN (cd, pc, info);
581d2201f2fSdrahn if (length > 0)
582d2201f2fSdrahn return length;
583d2201f2fSdrahn if (length < 0)
584d2201f2fSdrahn return -1;
585d2201f2fSdrahn
586d2201f2fSdrahn (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
587d2201f2fSdrahn return cd->default_insn_bitsize / 8;
588d2201f2fSdrahn }
589