]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - opcodes/fr30-dis.c
Mon Nov 23 18:28:48 1998 Dave Brolley <brolley@cygnus.com>
[thirdparty/binutils-gdb.git] / opcodes / fr30-dis.c
1 /* Disassembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
4 THIS FILE IS USED TO GENERATE fr30-dis.c.
5
6 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
7
8 This file is part of the GNU Binutils and GDB, the GNU debugger.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software Foundation, Inc.,
22 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23
24 #include "sysdep.h"
25 #include <stdio.h>
26 #include "ansidecl.h"
27 #include "dis-asm.h"
28 #include "bfd.h"
29 #include "symcat.h"
30 #include "fr30-opc.h"
31 #include "opintl.h"
32
33 #undef INLINE
34 #ifdef __GNUC__
35 #define INLINE __inline__
36 #else
37 #define INLINE
38 #endif
39
40 /* Default text to print if an instruction isn't recognized. */
41 #define UNKNOWN_INSN_MSG _("*unknown*")
42
43 static int extract_normal
44 PARAMS ((CGEN_OPCODE_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
45 unsigned int, int, int, int, bfd_vma, long *));
46 static void print_normal
47 PARAMS ((CGEN_OPCODE_DESC, PTR, long, unsigned int, bfd_vma, int));
48 static void print_address
49 PARAMS ((CGEN_OPCODE_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int));
50 static void print_keyword
51 PARAMS ((CGEN_OPCODE_DESC, PTR, CGEN_KEYWORD *, long, unsigned int));
52 static int extract_insn_normal
53 PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
54 CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma));
55 static void print_insn_normal
56 PARAMS ((CGEN_OPCODE_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *,
57 bfd_vma, int));
58 static int print_insn PARAMS ((CGEN_OPCODE_DESC, bfd_vma,
59 disassemble_info *, char *, int));
60 static int default_print_insn
61 PARAMS ((CGEN_OPCODE_DESC, bfd_vma, disassemble_info *));
62 \f
63 /* -- disassembler routines inserted here */
64 /* -- dis.c */
65
66 static void
67 print_register_list (dis_info, value, offset)
68 PTR dis_info;
69 long value;
70 long offset;
71 {
72 disassemble_info *info = dis_info;
73 int mask = 1;
74 int index;
75
76 if (value & mask)
77 (*info->fprintf_func) (info->stream, "r%i", index + offset);
78
79 for (index = 1; index <= 7; ++index)
80 {
81 mask <<= 1;
82 if (value & mask)
83 (*info->fprintf_func) (info->stream, ",r%i", index + offset);
84 }
85 }
86
87 static void
88 print_reglist_hi (od, dis_info, value, attrs, pc, length)
89 CGEN_OPCODE_DESC od;
90 PTR dis_info;
91 long value;
92 unsigned int attrs;
93 bfd_vma pc;
94 int length;
95 {
96 print_register_list (dis_info, value, 8);
97 }
98
99 static void
100 print_reglist_low (od, dis_info, value, attrs, pc, length)
101 CGEN_OPCODE_DESC od;
102 PTR dis_info;
103 long value;
104 unsigned int attrs;
105 bfd_vma pc;
106 int length;
107 {
108 print_register_list (dis_info, value, 0);
109 }
110
111 /* -- */
112
113 /* Main entry point for operand extraction.
114
115 This function is basically just a big switch statement. Earlier versions
116 used tables to look up the function to use, but
117 - if the table contains both assembler and disassembler functions then
118 the disassembler contains much of the assembler and vice-versa,
119 - there's a lot of inlining possibilities as things grow,
120 - using a switch statement avoids the function call overhead.
121
122 This function could be moved into `print_insn_normal', but keeping it
123 separate makes clear the interface between `print_insn_normal' and each of
124 the handlers.
125 */
126
127 int
128 fr30_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc)
129 CGEN_OPCODE_DESC od;
130 int opindex;
131 CGEN_EXTRACT_INFO *ex_info;
132 CGEN_INSN_INT insn_value;
133 CGEN_FIELDS * fields;
134 bfd_vma pc;
135 {
136 int length;
137
138 switch (opindex)
139 {
140 case FR30_OPERAND_RI :
141 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_Ri);
142 break;
143 case FR30_OPERAND_RJ :
144 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_Rj);
145 break;
146 case FR30_OPERAND_RIC :
147 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 28, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_Ric);
148 break;
149 case FR30_OPERAND_RJC :
150 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 24, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_Rjc);
151 break;
152 case FR30_OPERAND_CRI :
153 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 28, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_CRi);
154 break;
155 case FR30_OPERAND_CRJ :
156 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 24, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_CRj);
157 break;
158 case FR30_OPERAND_RS1 :
159 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_Rs1);
160 break;
161 case FR30_OPERAND_RS2 :
162 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_Rs2);
163 break;
164 case FR30_OPERAND_R13 :
165 length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_nil);
166 break;
167 case FR30_OPERAND_R14 :
168 length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_nil);
169 break;
170 case FR30_OPERAND_R15 :
171 length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_nil);
172 break;
173 case FR30_OPERAND_PS :
174 length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_nil);
175 break;
176 case FR30_OPERAND_U4 :
177 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_u4);
178 break;
179 case FR30_OPERAND_U4C :
180 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_u4c);
181 break;
182 case FR30_OPERAND_M4 :
183 {
184 long value;
185 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), pc, & value);
186 value = ((value) | ((! (15))));
187 fields->f_m4 = value;
188 }
189 break;
190 case FR30_OPERAND_U8 :
191 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_u8);
192 break;
193 case FR30_OPERAND_I8 :
194 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_i8);
195 break;
196 case FR30_OPERAND_UDISP6 :
197 {
198 long value;
199 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), pc, & value);
200 value = ((value) << (2));
201 fields->f_udisp6 = value;
202 }
203 break;
204 case FR30_OPERAND_DISP8 :
205 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_disp8);
206 break;
207 case FR30_OPERAND_DISP9 :
208 {
209 long value;
210 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), pc, & value);
211 value = ((value) << (1));
212 fields->f_disp9 = value;
213 }
214 break;
215 case FR30_OPERAND_DISP10 :
216 {
217 long value;
218 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), pc, & value);
219 value = ((value) << (2));
220 fields->f_disp10 = value;
221 }
222 break;
223 case FR30_OPERAND_S10 :
224 {
225 long value;
226 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), pc, & value);
227 value = ((value) << (2));
228 fields->f_s10 = value;
229 }
230 break;
231 case FR30_OPERAND_U10 :
232 {
233 long value;
234 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), pc, & value);
235 value = ((value) << (2));
236 fields->f_u10 = value;
237 }
238 break;
239 case FR30_OPERAND_I32 :
240 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 32, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_i32);
241 break;
242 case FR30_OPERAND_DIR8 :
243 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_dir8);
244 break;
245 case FR30_OPERAND_DIR9 :
246 {
247 long value;
248 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), pc, & value);
249 value = ((value) << (1));
250 fields->f_dir9 = value;
251 }
252 break;
253 case FR30_OPERAND_DIR10 :
254 {
255 long value;
256 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), pc, & value);
257 value = ((value) << (2));
258 fields->f_dir10 = value;
259 }
260 break;
261 case FR30_OPERAND_LABEL9 :
262 {
263 long value;
264 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_SIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), pc, & value);
265 value = ((((value) << (1))) + (((pc) & (-2))));
266 fields->f_rel9 = value;
267 }
268 break;
269 case FR30_OPERAND_LABEL12 :
270 {
271 long value;
272 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_SIGNED), 5, 11, CGEN_FIELDS_BITSIZE (fields), pc, & value);
273 value = ((((value) << (1))) + (((pc) & (-2))));
274 fields->f_rel12 = value;
275 }
276 break;
277 case FR30_OPERAND_REGLIST_LOW :
278 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_reglist_low);
279 break;
280 case FR30_OPERAND_REGLIST_HI :
281 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_reglist_hi);
282 break;
283 case FR30_OPERAND_CC :
284 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_cc);
285 break;
286 case FR30_OPERAND_CCC :
287 length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 16, 8, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_ccc);
288 break;
289
290 default :
291 /* xgettext:c-format */
292 fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
293 opindex);
294 abort ();
295 }
296
297 return length;
298 }
299
300 /* Main entry point for printing operands.
301
302 This function is basically just a big switch statement. Earlier versions
303 used tables to look up the function to use, but
304 - if the table contains both assembler and disassembler functions then
305 the disassembler contains much of the assembler and vice-versa,
306 - there's a lot of inlining possibilities as things grow,
307 - using a switch statement avoids the function call overhead.
308
309 This function could be moved into `print_insn_normal', but keeping it
310 separate makes clear the interface between `print_insn_normal' and each of
311 the handlers.
312 */
313
314 void
315 fr30_cgen_print_operand (od, opindex, info, fields, attrs, pc, length)
316 CGEN_OPCODE_DESC od;
317 int opindex;
318 disassemble_info * info;
319 CGEN_FIELDS * fields;
320 void const * attrs;
321 bfd_vma pc;
322 int length;
323 {
324 switch (opindex)
325 {
326 case FR30_OPERAND_RI :
327 print_keyword (od, info, & fr30_cgen_opval_h_gr, fields->f_Ri, 0|(1<<CGEN_OPERAND_UNSIGNED));
328 break;
329 case FR30_OPERAND_RJ :
330 print_keyword (od, info, & fr30_cgen_opval_h_gr, fields->f_Rj, 0|(1<<CGEN_OPERAND_UNSIGNED));
331 break;
332 case FR30_OPERAND_RIC :
333 print_keyword (od, info, & fr30_cgen_opval_h_gr, fields->f_Ric, 0|(1<<CGEN_OPERAND_UNSIGNED));
334 break;
335 case FR30_OPERAND_RJC :
336 print_keyword (od, info, & fr30_cgen_opval_h_gr, fields->f_Rjc, 0|(1<<CGEN_OPERAND_UNSIGNED));
337 break;
338 case FR30_OPERAND_CRI :
339 print_keyword (od, info, & fr30_cgen_opval_h_cr, fields->f_CRi, 0|(1<<CGEN_OPERAND_UNSIGNED));
340 break;
341 case FR30_OPERAND_CRJ :
342 print_keyword (od, info, & fr30_cgen_opval_h_cr, fields->f_CRj, 0|(1<<CGEN_OPERAND_UNSIGNED));
343 break;
344 case FR30_OPERAND_RS1 :
345 print_keyword (od, info, & fr30_cgen_opval_h_dr, fields->f_Rs1, 0|(1<<CGEN_OPERAND_UNSIGNED));
346 break;
347 case FR30_OPERAND_RS2 :
348 print_keyword (od, info, & fr30_cgen_opval_h_dr, fields->f_Rs2, 0|(1<<CGEN_OPERAND_UNSIGNED));
349 break;
350 case FR30_OPERAND_R13 :
351 print_keyword (od, info, & fr30_cgen_opval_h_r13, fields->f_nil, 0);
352 break;
353 case FR30_OPERAND_R14 :
354 print_keyword (od, info, & fr30_cgen_opval_h_r14, fields->f_nil, 0);
355 break;
356 case FR30_OPERAND_R15 :
357 print_keyword (od, info, & fr30_cgen_opval_h_r15, fields->f_nil, 0);
358 break;
359 case FR30_OPERAND_PS :
360 print_keyword (od, info, & fr30_cgen_opval_h_ps, fields->f_nil, 0);
361 break;
362 case FR30_OPERAND_U4 :
363 print_normal (od, info, fields->f_u4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
364 break;
365 case FR30_OPERAND_U4C :
366 print_normal (od, info, fields->f_u4c, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
367 break;
368 case FR30_OPERAND_M4 :
369 print_normal (od, info, fields->f_m4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
370 break;
371 case FR30_OPERAND_U8 :
372 print_normal (od, info, fields->f_u8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
373 break;
374 case FR30_OPERAND_I8 :
375 print_normal (od, info, fields->f_i8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
376 break;
377 case FR30_OPERAND_UDISP6 :
378 print_normal (od, info, fields->f_udisp6, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
379 break;
380 case FR30_OPERAND_DISP8 :
381 print_normal (od, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), pc, length);
382 break;
383 case FR30_OPERAND_DISP9 :
384 print_normal (od, info, fields->f_disp9, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), pc, length);
385 break;
386 case FR30_OPERAND_DISP10 :
387 print_normal (od, info, fields->f_disp10, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), pc, length);
388 break;
389 case FR30_OPERAND_S10 :
390 print_normal (od, info, fields->f_s10, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), pc, length);
391 break;
392 case FR30_OPERAND_U10 :
393 print_normal (od, info, fields->f_u10, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
394 break;
395 case FR30_OPERAND_I32 :
396 print_normal (od, info, fields->f_i32, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
397 break;
398 case FR30_OPERAND_DIR8 :
399 print_normal (od, info, fields->f_dir8, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
400 break;
401 case FR30_OPERAND_DIR9 :
402 print_normal (od, info, fields->f_dir9, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
403 break;
404 case FR30_OPERAND_DIR10 :
405 print_normal (od, info, fields->f_dir10, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
406 break;
407 case FR30_OPERAND_LABEL9 :
408 print_normal (od, info, fields->f_rel9, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_SIGNED), pc, length);
409 break;
410 case FR30_OPERAND_LABEL12 :
411 print_normal (od, info, fields->f_rel12, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR)|(1<<CGEN_OPERAND_SIGNED), pc, length);
412 break;
413 case FR30_OPERAND_REGLIST_LOW :
414 print_reglist_low (od, info, fields->f_reglist_low, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
415 break;
416 case FR30_OPERAND_REGLIST_HI :
417 print_reglist_hi (od, info, fields->f_reglist_hi, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
418 break;
419 case FR30_OPERAND_CC :
420 print_normal (od, info, fields->f_cc, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
421 break;
422 case FR30_OPERAND_CCC :
423 print_normal (od, info, fields->f_ccc, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
424 break;
425
426 default :
427 /* xgettext:c-format */
428 fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
429 opindex);
430 abort ();
431 }
432 }
433
434 cgen_extract_fn * const fr30_cgen_extract_handlers[] =
435 {
436 0, /* default */
437 extract_insn_normal,
438 };
439
440 cgen_print_fn * const fr30_cgen_print_handlers[] =
441 {
442 0, /* default */
443 print_insn_normal,
444 };
445
446
447 void
448 fr30_cgen_init_dis (od)
449 CGEN_OPCODE_DESC od;
450 {
451 }
452
453 \f
454 #if ! CGEN_INT_INSN_P
455
456 /* Subroutine of extract_normal.
457 Ensure sufficient bytes are cached in EX_INFO.
458 Returns 1 for success, 0 for failure. */
459
460 static INLINE int
461 fill_cache (od, ex_info, offset, bytes, pc)
462 CGEN_OPCODE_DESC od;
463 CGEN_EXTRACT_INFO *ex_info;
464 int offset, bytes;
465 bfd_vma pc;
466 {
467 /* It's doubtful that the middle part has already been fetched so
468 we don't optimize that case. kiss. */
469 int mask;
470 disassemble_info *info = (disassemble_info *) ex_info->dis_info;
471
472 /* First do a quick check. */
473 mask = (1 << bytes) - 1;
474 if (((ex_info->valid >> offset) & mask) == mask)
475 return 1;
476
477 /* Search for the first byte we need to read. */
478 for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
479 if (! (mask & ex_info->valid))
480 break;
481
482 if (bytes)
483 {
484 int status;
485
486 pc += offset;
487 status = (*info->read_memory_func)
488 (pc, ex_info->insn_bytes + offset, bytes, info);
489
490 if (status != 0)
491 {
492 (*info->memory_error_func) (status, pc, info);
493 return 0;
494 }
495
496 ex_info->valid |= ((1 << bytes) - 1) << offset;
497 }
498
499 return 1;
500 }
501
502 /* Subroutine of extract_normal. */
503
504 static INLINE long
505 extract_1 (od, ex_info, start, length, word_length, bufp, pc)
506 CGEN_OPCODE_DESC od;
507 CGEN_EXTRACT_INFO *ex_info;
508 int start,length,word_length;
509 unsigned char *bufp;
510 bfd_vma pc;
511 {
512 unsigned long x,mask;
513 int shift;
514 int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
515
516 switch (word_length)
517 {
518 case 8:
519 x = *bufp;
520 break;
521 case 16:
522 if (big_p)
523 x = bfd_getb16 (bufp);
524 else
525 x = bfd_getl16 (bufp);
526 break;
527 case 24:
528 /* ??? This may need reworking as these cases don't necessarily
529 want the first byte and the last two bytes handled like this. */
530 if (big_p)
531 x = (bufp[0] << 16) | bfd_getb16 (bufp + 1);
532 else
533 x = bfd_getl16 (bufp) | (bufp[2] << 16);
534 break;
535 case 32:
536 if (big_p)
537 x = bfd_getb32 (bufp);
538 else
539 x = bfd_getl32 (bufp);
540 break;
541 default :
542 abort ();
543 }
544
545 /* Written this way to avoid undefined behaviour. */
546 mask = (((1L << (length - 1)) - 1) << 1) | 1;
547 if (CGEN_INSN_LSB0_P)
548 shift = start;
549 else
550 shift = (word_length - (start + length));
551 return (x >> shift) & mask;
552 }
553
554 #endif /* ! CGEN_INT_INSN_P */
555
556 /* Default extraction routine.
557
558 INSN_VALUE is the first CGEN_BASE_INSN_SIZE bits of the insn in host order,
559 or sometimes less for cases like the m32r where the base insn size is 32
560 but some insns are 16 bits.
561 ATTRS is a mask of the boolean attributes. We only need `unsigned',
562 but for generality we take a bitmask of all of them.
563 TOTAL_LENGTH is the length of the insn in bits.
564
565 Returns 1 for success, 0 for failure. */
566
567 /* ??? This doesn't handle bfd_vma's. Create another function when
568 necessary. */
569
570 static int
571 extract_normal (od, ex_info, insn_value, attrs, start, length, total_length, pc, valuep)
572 CGEN_OPCODE_DESC od;
573 CGEN_EXTRACT_INFO *ex_info;
574 CGEN_INSN_INT insn_value;
575 unsigned int attrs;
576 int start, length, total_length;
577 bfd_vma pc;
578 long *valuep;
579 {
580 unsigned long value;
581
582 /* If LENGTH is zero, this operand doesn't contribute to the value
583 so give it a standard value of zero. */
584 if (length == 0)
585 {
586 *valuep = 0;
587 return 1;
588 }
589
590 if (CGEN_INT_INSN_P
591 || (CGEN_INSN_LSB0_P
592 ? ((total_length - start) <= CGEN_BASE_INSN_BITSIZE)
593 : ((start + length) <= CGEN_BASE_INSN_BITSIZE)))
594 {
595 /* Written this way to avoid undefined behaviour. */
596 unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
597
598 if (CGEN_INSN_LSB0_P)
599 value = insn_value >> start;
600 else
601 value = insn_value >> (total_length - (start + length));
602 value &= mask;
603 /* sign extend? */
604 if (! (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED))
605 && (value & (1L << (length - 1))))
606 value |= ~mask;
607 }
608
609 #if ! CGEN_INT_INSN_P
610
611 /* The hard case is probably too slow for the normal cases.
612 It's certainly more difficult to understand than the normal case.
613 Thus this is split into two. The hard case is defined
614 to be when a field straddles a (loosely defined) word boundary
615 (??? which may require target specific help to determine). */
616
617 #define HARD_CASE_P 0 /* FIXME:wip */
618
619 else if (HARD_CASE_P)
620 {
621 }
622
623 else
624 {
625 unsigned char *bufp = ex_info->insn_bytes;
626 int offset = 0;
627
628 if (length > 32)
629 abort ();
630
631 /* Adjust start,total_length,bufp to point to the pseudo-word that holds
632 the value. For example in a 48 bit insn where the value to insert
633 (say an immediate value) is the last 16 bits then fetch_length here
634 would be 16. To handle a 24 bit insn with an 18 bit immediate,
635 extract_1 handles 24 bits. */
636
637 if (total_length > 32)
638 {
639 int needed_width = start % 8 + length;
640 int fetch_length = (needed_width <= 8 ? 8
641 : needed_width <= 16 ? 16
642 : 32);
643
644 if (CGEN_INSN_LSB0_P)
645 {
646 if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
647 {
648 abort (); /* wip */
649 }
650 else
651 {
652 offset = start & ~7;
653
654 bufp += offset / 8;
655 start -= offset;
656 total_length = fetch_length;
657 }
658 }
659 else
660 {
661 if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
662 {
663 offset = start & ~7;
664
665 bufp += offset / 8;
666 start -= offset;
667 total_length = fetch_length;
668 }
669 else
670 {
671 abort (); /* wip */
672 }
673 }
674 }
675
676 if (fill_cache (od, ex_info, offset / 8, total_length / 8, pc) == 0)
677 return 0;
678
679 value = extract_1 (od, ex_info, start, length, total_length, bufp, pc);
680 }
681
682 #endif /* ! CGEN_INT_INSN_P */
683
684 *valuep = value;
685
686 return 1;
687 }
688
689 /* Default print handler. */
690
691 static void
692 print_normal (od, dis_info, value, attrs, pc, length)
693 CGEN_OPCODE_DESC od;
694 PTR dis_info;
695 long value;
696 unsigned int attrs;
697 bfd_vma pc;
698 int length;
699 {
700 disassemble_info *info = (disassemble_info *) dis_info;
701
702 #ifdef CGEN_PRINT_NORMAL
703 CGEN_PRINT_NORMAL (od, info, value, attrs, pc, length);
704 #endif
705
706 /* Print the operand as directed by the attributes. */
707 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
708 ; /* nothing to do */
709 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
710 (*info->fprintf_func) (info->stream, "0x%lx", value);
711 else
712 (*info->fprintf_func) (info->stream, "%ld", value);
713 }
714
715 /* Default address handler. */
716
717 static void
718 print_address (od, dis_info, value, attrs, pc, length)
719 CGEN_OPCODE_DESC od;
720 PTR dis_info;
721 bfd_vma value;
722 unsigned int attrs;
723 bfd_vma pc;
724 int length;
725 {
726 disassemble_info *info = (disassemble_info *) dis_info;
727
728 #ifdef CGEN_PRINT_ADDRESS
729 CGEN_PRINT_ADDRESS (od, info, value, attrs, pc, length);
730 #endif
731
732 /* Print the operand as directed by the attributes. */
733 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
734 ; /* nothing to do */
735 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
736 (*info->print_address_func) (value, info);
737 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
738 (*info->print_address_func) (value, info);
739 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
740 (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
741 else
742 (*info->fprintf_func) (info->stream, "%ld", (long) value);
743 }
744
745 /* Keyword print handler. */
746
747 static void
748 print_keyword (od, dis_info, keyword_table, value, attrs)
749 CGEN_OPCODE_DESC od;
750 PTR dis_info;
751 CGEN_KEYWORD *keyword_table;
752 long value;
753 unsigned int attrs;
754 {
755 disassemble_info *info = (disassemble_info *) dis_info;
756 const CGEN_KEYWORD_ENTRY *ke;
757
758 ke = cgen_keyword_lookup_value (keyword_table, value);
759 if (ke != NULL)
760 (*info->fprintf_func) (info->stream, "%s", ke->name);
761 else
762 (*info->fprintf_func) (info->stream, "???");
763 }
764 \f
765 /* Default insn extractor.
766
767 INSN_VALUE is the first CGEN_BASE_INSN_SIZE bytes, translated to host order.
768 The extracted fields are stored in FIELDS.
769 EX_INFO is used to handle reading variable length insns.
770 Return the length of the insn in bits, or 0 if no match,
771 or -1 if an error occurs fetching data (memory_error_func will have
772 been called). */
773
774 static int
775 extract_insn_normal (od, insn, ex_info, insn_value, fields, pc)
776 CGEN_OPCODE_DESC od;
777 const CGEN_INSN *insn;
778 CGEN_EXTRACT_INFO *ex_info;
779 CGEN_INSN_INT insn_value;
780 CGEN_FIELDS *fields;
781 bfd_vma pc;
782 {
783 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
784 const unsigned char *syn;
785
786 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
787
788 CGEN_INIT_EXTRACT (od);
789
790 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
791 {
792 int length;
793
794 if (CGEN_SYNTAX_CHAR_P (*syn))
795 continue;
796
797 length = fr30_cgen_extract_operand (od, CGEN_SYNTAX_FIELD (*syn),
798 ex_info, insn_value, fields, pc);
799 if (length <= 0)
800 return length;
801 }
802
803 /* We recognized and successfully extracted this insn. */
804 return CGEN_INSN_BITSIZE (insn);
805 }
806
807 /* Default insn printer.
808
809 DIS_INFO is defined as `PTR' so the disassembler needn't know anything
810 about disassemble_info. */
811
812 static void
813 print_insn_normal (od, dis_info, insn, fields, pc, length)
814 CGEN_OPCODE_DESC od;
815 PTR dis_info;
816 const CGEN_INSN *insn;
817 CGEN_FIELDS *fields;
818 bfd_vma pc;
819 int length;
820 {
821 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
822 disassemble_info *info = (disassemble_info *) dis_info;
823 const unsigned char *syn;
824
825 CGEN_INIT_PRINT (od);
826
827 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
828 {
829 if (CGEN_SYNTAX_MNEMONIC_P (*syn))
830 {
831 (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
832 continue;
833 }
834 if (CGEN_SYNTAX_CHAR_P (*syn))
835 {
836 (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
837 continue;
838 }
839
840 /* We have an operand. */
841 fr30_cgen_print_operand (od, CGEN_SYNTAX_FIELD (*syn), info,
842 fields, CGEN_INSN_ATTRS (insn), pc, length);
843 }
844 }
845 \f
846 /* Utility to print an insn.
847 BUF is the base part of the insn, target byte order, BUFLEN bytes long.
848 The result is the size of the insn in bytes or zero for an unknown insn
849 or -1 if an error occurs fetching data (memory_error_func will have
850 been called). */
851
852 static int
853 print_insn (od, pc, info, buf, buflen)
854 CGEN_OPCODE_DESC od;
855 bfd_vma pc;
856 disassemble_info *info;
857 char *buf;
858 int buflen;
859 {
860 unsigned long insn_value;
861 const CGEN_INSN_LIST *insn_list;
862 CGEN_EXTRACT_INFO ex_info;
863
864 ex_info.dis_info = info;
865 ex_info.valid = (1 << CGEN_BASE_INSN_SIZE) - 1;
866 ex_info.insn_bytes = buf;
867
868 switch (buflen)
869 {
870 case 1:
871 insn_value = buf[0];
872 break;
873 case 2:
874 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf);
875 break;
876 case 4:
877 insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf);
878 break;
879 default:
880 abort ();
881 }
882
883 /* The instructions are stored in hash lists.
884 Pick the first one and keep trying until we find the right one. */
885
886 insn_list = CGEN_DIS_LOOKUP_INSN (od, buf, insn_value);
887 while (insn_list != NULL)
888 {
889 const CGEN_INSN *insn = insn_list->insn;
890 CGEN_FIELDS fields;
891 int length;
892
893 #if 0 /* not needed as insn shouldn't be in hash lists if not supported */
894 /* Supported by this cpu? */
895 if (! fr30_cgen_insn_supported (od, insn))
896 continue;
897 #endif
898
899 /* Basic bit mask must be correct. */
900 /* ??? May wish to allow target to defer this check until the extract
901 handler. */
902 if ((insn_value & CGEN_INSN_MASK (insn)) == CGEN_INSN_VALUE (insn))
903 {
904 /* Printing is handled in two passes. The first pass parses the
905 machine insn and extracts the fields. The second pass prints
906 them. */
907
908 length = (*CGEN_EXTRACT_FN (insn)) (od, insn, &ex_info, insn_value,
909 &fields, pc);
910 /* length < 0 -> error */
911 if (length < 0)
912 return length;
913 if (length > 0)
914 {
915 (*CGEN_PRINT_FN (insn)) (od, info, insn, &fields, pc, length);
916 /* length is in bits, result is in bytes */
917 return length / 8;
918 }
919 }
920
921 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
922 }
923
924 return 0;
925 }
926
927 /* Default value for CGEN_PRINT_INSN.
928 The result is the size of the insn in bytes or zero for an unknown insn
929 or -1 if an error occured fetching bytes. */
930
931 #ifndef CGEN_PRINT_INSN
932 #define CGEN_PRINT_INSN default_print_insn
933 #endif
934
935 static int
936 default_print_insn (od, pc, info)
937 CGEN_OPCODE_DESC od;
938 bfd_vma pc;
939 disassemble_info *info;
940 {
941 char buf[CGEN_MAX_INSN_SIZE];
942 int status;
943
944 /* Read the base part of the insn. */
945
946 status = (*info->read_memory_func) (pc, buf, CGEN_BASE_INSN_SIZE, info);
947 if (status != 0)
948 {
949 (*info->memory_error_func) (status, pc, info);
950 return -1;
951 }
952
953 return print_insn (od, pc, info, buf, CGEN_BASE_INSN_SIZE);
954 }
955
956 /* Main entry point.
957 Print one instruction from PC on INFO->STREAM.
958 Return the size of the instruction (in bytes). */
959
960 int
961 print_insn_fr30 (pc, info)
962 bfd_vma pc;
963 disassemble_info *info;
964 {
965 int length;
966 static CGEN_OPCODE_DESC od = 0;
967 int mach = info->mach;
968 int big_p = info->endian == BFD_ENDIAN_BIG;
969
970 /* If we haven't initialized yet, initialize the opcode table. */
971 if (! od)
972 {
973 od = fr30_cgen_opcode_open (mach,
974 big_p ?
975 CGEN_ENDIAN_BIG
976 : CGEN_ENDIAN_LITTLE);
977 fr30_cgen_init_dis (od);
978 }
979 /* If we've switched cpu's, re-initialize. */
980 /* ??? Perhaps we should use BFD_ENDIAN. */
981 else if (mach != CGEN_OPCODE_MACH (od)
982 || (CGEN_OPCODE_ENDIAN (od)
983 != (big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE)))
984 {
985 cgen_set_cpu (od, mach, big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE);
986 }
987
988 /* We try to have as much common code as possible.
989 But at this point some targets need to take over. */
990 /* ??? Some targets may need a hook elsewhere. Try to avoid this,
991 but if not possible try to move this hook elsewhere rather than
992 have two hooks. */
993 length = CGEN_PRINT_INSN (od, pc, info);
994 if (length > 0)
995 return length;
996 if (length < 0)
997 return -1;
998
999 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1000 return CGEN_DEFAULT_INSN_SIZE;
1001 }