source: trunk/src/binutils/opcodes/m32r-dis.c@ 167

Last change on this file since 167 was 10, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 18.4 KB
Line 
1/* Disassembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
4THIS FILE IS MACHINE GENERATED WITH CGEN.
5- the resultant file is machine generated, cgen-dis.in isn't
6
7Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
8
9This file is part of the GNU Binutils and GDB, the GNU debugger.
10
11This program is free software; you can redistribute it and/or modify
12it under the terms of the GNU General Public License as published by
13the Free Software Foundation; either version 2, or (at your option)
14any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License
22along with this program; if not, write to the Free Software Foundation, Inc.,
2359 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24
25/* ??? Eventually more and more of this stuff can go to cpu-independent files.
26 Keep that in mind. */
27
28#include "sysdep.h"
29#include <stdio.h>
30#include "ansidecl.h"
31#include "dis-asm.h"
32#include "bfd.h"
33#include "symcat.h"
34#include "m32r-desc.h"
35#include "m32r-opc.h"
36#include "opintl.h"
37
38/* Default text to print if an instruction isn't recognized. */
39#define UNKNOWN_INSN_MSG _("*unknown*")
40
41static void print_normal
42 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned int, bfd_vma, int));
43static void print_address
44 PARAMS ((CGEN_CPU_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int));
45static void print_keyword
46 PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int));
47static void print_insn_normal
48 PARAMS ((CGEN_CPU_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *,
49 bfd_vma, int));
50static int print_insn PARAMS ((CGEN_CPU_DESC, bfd_vma,
51 disassemble_info *, char *, int));
52static int default_print_insn
53 PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *));
54
55
56/* -- disassembler routines inserted here */
57
58/* -- dis.c */
59
60/* Immediate values are prefixed with '#'. */
61
62#define CGEN_PRINT_NORMAL(cd, info, value, attrs, pc, length) \
63do { \
64 if (CGEN_BOOL_ATTR ((attrs), CGEN_OPERAND_HASH_PREFIX)) \
65 (*info->fprintf_func) (info->stream, "#"); \
66} while (0)
67
68/* Handle '#' prefixes as operands. */
69
70static void
71print_hash (cd, dis_info, value, attrs, pc, length)
72 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
73 PTR dis_info;
74 long value ATTRIBUTE_UNUSED;
75 unsigned int attrs ATTRIBUTE_UNUSED;
76 bfd_vma pc ATTRIBUTE_UNUSED;
77 int length ATTRIBUTE_UNUSED;
78{
79 disassemble_info *info = (disassemble_info *) dis_info;
80 (*info->fprintf_func) (info->stream, "#");
81}
82
83#undef CGEN_PRINT_INSN
84#define CGEN_PRINT_INSN my_print_insn
85
86static int
87my_print_insn (cd, pc, info)
88 CGEN_CPU_DESC cd;
89 bfd_vma pc;
90 disassemble_info *info;
91{
92 char buffer[CGEN_MAX_INSN_SIZE];
93 char *buf = buffer;
94 int status;
95 int buflen = (pc & 3) == 0 ? 4 : 2;
96
97 /* Read the base part of the insn. */
98
99 status = (*info->read_memory_func) (pc, buf, buflen, info);
100 if (status != 0)
101 {
102 (*info->memory_error_func) (status, pc, info);
103 return -1;
104 }
105
106 /* 32 bit insn? */
107 if ((pc & 3) == 0 && (buf[0] & 0x80) != 0)
108 return print_insn (cd, pc, info, buf, buflen);
109
110 /* Print the first insn. */
111 if ((pc & 3) == 0)
112 {
113 if (print_insn (cd, pc, info, buf, 2) == 0)
114 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
115 buf += 2;
116 }
117
118 if (buf[0] & 0x80)
119 {
120 /* Parallel. */
121 (*info->fprintf_func) (info->stream, " || ");
122 buf[0] &= 0x7f;
123 }
124 else
125 (*info->fprintf_func) (info->stream, " -> ");
126
127 /* The "& 3" is to pass a consistent address.
128 Parallel insns arguably both begin on the word boundary.
129 Also, branch insns are calculated relative to the word boundary. */
130 if (print_insn (cd, pc & ~ (bfd_vma) 3, info, buf, 2) == 0)
131 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
132
133 return (pc & 3) ? 2 : 4;
134}
135
136/* -- */
137
138/* Main entry point for printing operands.
139 XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
140 of dis-asm.h on cgen.h.
141
142 This function is basically just a big switch statement. Earlier versions
143 used tables to look up the function to use, but
144 - if the table contains both assembler and disassembler functions then
145 the disassembler contains much of the assembler and vice-versa,
146 - there's a lot of inlining possibilities as things grow,
147 - using a switch statement avoids the function call overhead.
148
149 This function could be moved into `print_insn_normal', but keeping it
150 separate makes clear the interface between `print_insn_normal' and each of
151 the handlers.
152*/
153
154void
155m32r_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length)
156 CGEN_CPU_DESC cd;
157 int opindex;
158 PTR xinfo;
159 CGEN_FIELDS *fields;
160 void const *attrs ATTRIBUTE_UNUSED;
161 bfd_vma pc;
162 int length;
163{
164 disassemble_info *info = (disassemble_info *) xinfo;
165
166 switch (opindex)
167 {
168 case M32R_OPERAND_ACC :
169 print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_acc, 0);
170 break;
171 case M32R_OPERAND_ACCD :
172 print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_accd, 0);
173 break;
174 case M32R_OPERAND_ACCS :
175 print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_accs, 0);
176 break;
177 case M32R_OPERAND_DCR :
178 print_keyword (cd, info, & m32r_cgen_opval_cr_names, fields->f_r1, 0);
179 break;
180 case M32R_OPERAND_DISP16 :
181 print_address (cd, info, fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
182 break;
183 case M32R_OPERAND_DISP24 :
184 print_address (cd, info, fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
185 break;
186 case M32R_OPERAND_DISP8 :
187 print_address (cd, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
188 break;
189 case M32R_OPERAND_DR :
190 print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r1, 0);
191 break;
192 case M32R_OPERAND_HASH :
193 print_hash (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
194 break;
195 case M32R_OPERAND_HI16 :
196 print_normal (cd, info, fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT), pc, length);
197 break;
198 case M32R_OPERAND_IMM1 :
199 print_normal (cd, info, fields->f_imm1, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
200 break;
201 case M32R_OPERAND_SCR :
202 print_keyword (cd, info, & m32r_cgen_opval_cr_names, fields->f_r2, 0);
203 break;
204 case M32R_OPERAND_SIMM16 :
205 print_normal (cd, info, fields->f_simm16, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
206 break;
207 case M32R_OPERAND_SIMM8 :
208 print_normal (cd, info, fields->f_simm8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
209 break;
210 case M32R_OPERAND_SLO16 :
211 print_normal (cd, info, fields->f_simm16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
212 break;
213 case M32R_OPERAND_SR :
214 print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r2, 0);
215 break;
216 case M32R_OPERAND_SRC1 :
217 print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r1, 0);
218 break;
219 case M32R_OPERAND_SRC2 :
220 print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r2, 0);
221 break;
222 case M32R_OPERAND_UIMM16 :
223 print_normal (cd, info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
224 break;
225 case M32R_OPERAND_UIMM24 :
226 print_address (cd, info, fields->f_uimm24, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
227 break;
228 case M32R_OPERAND_UIMM4 :
229 print_normal (cd, info, fields->f_uimm4, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
230 break;
231 case M32R_OPERAND_UIMM5 :
232 print_normal (cd, info, fields->f_uimm5, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
233 break;
234 case M32R_OPERAND_ULO16 :
235 print_normal (cd, info, fields->f_uimm16, 0, pc, length);
236 break;
237
238 default :
239 /* xgettext:c-format */
240 fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
241 opindex);
242 abort ();
243 }
244}
245
246cgen_print_fn * const m32r_cgen_print_handlers[] =
247{
248 print_insn_normal,
249};
250
251
252void
253m32r_cgen_init_dis (cd)
254 CGEN_CPU_DESC cd;
255{
256 m32r_cgen_init_opcode_table (cd);
257 m32r_cgen_init_ibld_table (cd);
258 cd->print_handlers = & m32r_cgen_print_handlers[0];
259 cd->print_operand = m32r_cgen_print_operand;
260}
261
262
263
264/* Default print handler. */
265
266static void
267print_normal (cd, dis_info, value, attrs, pc, length)
268 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
269 PTR dis_info;
270 long value;
271 unsigned int attrs;
272 bfd_vma pc ATTRIBUTE_UNUSED;
273 int length ATTRIBUTE_UNUSED;
274{
275 disassemble_info *info = (disassemble_info *) dis_info;
276
277#ifdef CGEN_PRINT_NORMAL
278 CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
279#endif
280
281 /* Print the operand as directed by the attributes. */
282 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
283 ; /* nothing to do */
284 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
285 (*info->fprintf_func) (info->stream, "%ld", value);
286 else
287 (*info->fprintf_func) (info->stream, "0x%lx", value);
288}
289
290/* Default address handler. */
291
292static void
293print_address (cd, dis_info, value, attrs, pc, length)
294 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
295 PTR dis_info;
296 bfd_vma value;
297 unsigned int attrs;
298 bfd_vma pc ATTRIBUTE_UNUSED;
299 int length ATTRIBUTE_UNUSED;
300{
301 disassemble_info *info = (disassemble_info *) dis_info;
302
303#ifdef CGEN_PRINT_ADDRESS
304 CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
305#endif
306
307 /* Print the operand as directed by the attributes. */
308 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
309 ; /* nothing to do */
310 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
311 (*info->print_address_func) (value, info);
312 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
313 (*info->print_address_func) (value, info);
314 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
315 (*info->fprintf_func) (info->stream, "%ld", (long) value);
316 else
317 (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
318}
319
320/* Keyword print handler. */
321
322static void
323print_keyword (cd, dis_info, keyword_table, value, attrs)
324 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
325 PTR dis_info;
326 CGEN_KEYWORD *keyword_table;