source: vendor/binutils/current/opcodes/fr30-dis.c

Last change on this file was 609, checked in by bird, 22 years ago

binutils v2.14 - offical sources.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 22.2 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, 2002
8Free Software Foundation, Inc.
9
10This file is part of the GNU Binutils and GDB, the GNU debugger.
11
12This program is free software; you can redistribute it and/or modify
13it under the terms of the GNU General Public License as published by
14the Free Software Foundation; either version 2, or (at your option)
15any later version.
16
17This program is distributed in the hope that it will be useful,
18but WITHOUT ANY WARRANTY; without even the implied warranty of
19MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20GNU General Public License for more details.
21
22You should have received a copy of the GNU General Public License
23along with this program; if not, write to the Free Software Foundation, Inc.,
2459 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
25
26/* ??? Eventually more and more of this stuff can go to cpu-independent files.
27 Keep that in mind. */
28
29#include "sysdep.h"
30#include <stdio.h>
31#include "ansidecl.h"
32#include "dis-asm.h"
33#include "bfd.h"
34#include "symcat.h"
35#include "libiberty.h"
36#include "fr30-desc.h"
37#include "fr30-opc.h"
38#include "opintl.h"
39
40/* Default text to print if an instruction isn't recognized. */
41#define UNKNOWN_INSN_MSG _("*unknown*")
42
43static void print_normal
44 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned int, bfd_vma, int));
45static void print_address
46 PARAMS ((CGEN_CPU_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int));
47static void print_keyword
48 PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int));
49static void print_insn_normal
50 PARAMS ((CGEN_CPU_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *,
51 bfd_vma, int));
52static int print_insn
53 PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *, char *, unsigned));
54static int default_print_insn
55 PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *));
56static int read_insn
57 PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *, char *, int,
58 CGEN_EXTRACT_INFO *, unsigned long *));
59
60
61/* -- disassembler routines inserted here */
62
63/* -- dis.c */
64static void print_register_list
65 PARAMS ((PTR, long, long, int));
66static void print_hi_register_list_ld
67 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
68static void print_low_register_list_ld
69 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
70static void print_hi_register_list_st
71 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
72static void print_low_register_list_st
73 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
74static void print_m4
75 PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
76
77static void
78print_register_list (dis_info, value, offset, load_store)
79 PTR dis_info;
80 long value;
81 long offset;
82 int load_store; /* 0 == load, 1 == store */
83{
84 disassemble_info *info = dis_info;
85 int mask;
86 int index = 0;
87 char* comma = "";
88
89 if (load_store)
90 mask = 0x80;
91 else
92 mask = 1;
93
94 if (value & mask)
95 {
96 (*info->fprintf_func) (info->stream, "r%i", index + offset);
97 comma = ",";
98 }
99
100 for (index = 1; index <= 7; ++index)
101 {
102 if (load_store)
103 mask >>= 1;
104 else
105 mask <<= 1;
106
107 if (value & mask)
108 {
109 (*info->fprintf_func) (info->stream, "%sr%i", comma, index + offset);
110 comma = ",";
111 }
112 }
113}
114
115static void
116print_hi_register_list_ld (cd, dis_info, value, attrs, pc, length)
117 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
118 PTR dis_info;
119 long value;
120 unsigned int attrs ATTRIBUTE_UNUSED;
121 bfd_vma pc ATTRIBUTE_UNUSED;
122 int length ATTRIBUTE_UNUSED;
123{
124 print_register_list (dis_info, value, 8, 0/*load*/);
125}
126
127static void
128print_low_register_list_ld (cd, dis_info, value, attrs, pc, length)
129 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
130 PTR dis_info;
131 long value;
132 unsigned int attrs ATTRIBUTE_UNUSED;
133 bfd_vma pc ATTRIBUTE_UNUSED;
134 int length ATTRIBUTE_UNUSED;
135{
136 print_register_list (dis_info, value, 0, 0/*load*/);
137}
138
139static void
140print_hi_register_list_st (cd, dis_info, value, attrs, pc, length)
141 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
142 PTR dis_info;
143 long value;
144 unsigned int attrs ATTRIBUTE_UNUSED;
145 bfd_vma pc ATTRIBUTE_UNUSED;
146 int length ATTRIBUTE_UNUSED;
147{
148 print_register_list (dis_info, value, 8, 1/*store*/);
149}
150
151static void
152print_low_register_list_st (cd, dis_info, value, attrs, pc, length)
153 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
154 PTR dis_info;
155 long value;
156 unsigned int attrs ATTRIBUTE_UNUSED;
157 bfd_vma pc ATTRIBUTE_UNUSED;
158 int length ATTRIBUTE_UNUSED;
159{
160 print_register_list (dis_info, value, 0, 1/*store*/);
161}
162
163static void
164print_m4 (cd, dis_info, value, attrs, pc, length)
165 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
166 PTR dis_info;
167 long value;
168 unsigned int attrs ATTRIBUTE_UNUSED;
169 bfd_vma pc ATTRIBUTE_UNUSED;
170 int length ATTRIBUTE_UNUSED;
171{
172 disassemble_info *info = (disassemble_info *) dis_info;
173 (*info->fprintf_func) (info->stream, "%ld", value);
174}
175/* -- */
176
177void fr30_cgen_print_operand
178 PARAMS ((CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *,
179 void const *, bfd_vma, int));
180
181/* Main entry point for printing operands.
182 XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
183 of dis-asm.h on cgen.h.
184
185 This function is basically just a big switch statement. Earlier versions
186 used tables to look up the function to use, but
187 - if the table contains both assembler and disassembler functions then
188 the disassembler contains much of the assembler and vice-versa,
189 - there's a lot of inlining possibilities as things grow,
190 - using a switch statement avoids the function call overhead.
191
192 This function could be moved into `print_insn_normal', but keeping it
193 separate makes clear the interface between `print_insn_normal' and each of
194 the handlers. */
195
196void
197fr30_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length)
198 CGEN_CPU_DESC cd;
199 int opindex;
200 PTR xinfo;
201 CGEN_FIELDS *fields;
202 void const *attrs ATTRIBUTE_UNUSED;
203 bfd_vma pc;
204 int length;
205{
206 disassemble_info *info = (disassemble_info *) xinfo;
207
208 switch (opindex)
209 {
210 case FR30_OPERAND_CRI :
211 print_keyword (cd, info, & fr30_cgen_opval_cr_names, fields->f_CRi, 0);
212 break;
213 case FR30_OPERAND_CRJ :
214 print_keyword (cd, info, & fr30_cgen_opval_cr_names, fields->f_CRj, 0);
215 break;
216 case FR30_OPERAND_R13 :
217 print_keyword (cd, info, & fr30_cgen_opval_h_r13, 0, 0);
218 break;
219 case FR30_OPERAND_R14 :
220 print_keyword (cd, info, & fr30_cgen_opval_h_r14, 0, 0);
221 break;
222 case FR30_OPERAND_R15 :
223 print_keyword (cd, info, & fr30_cgen_opval_h_r15, 0, 0);
224 break;
225 case FR30_OPERAND_RI :
226 print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Ri, 0);
227 break;
228 case FR30_OPERAND_RIC :
229 print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Ric, 0);
230 break;
231 case FR30_OPERAND_RJ :
232 print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Rj, 0);
233 break;
234 case FR30_OPERAND_RJC :
235 print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Rjc, 0);
236 break;
237 case FR30_OPERAND_RS1 :
238 print_keyword (cd, info, & fr30_cgen_opval_dr_names, fields->f_Rs1, 0);
239 break;
240 case FR30_OPERAND_RS2 :
241 print_keyword (cd, info, & fr30_cgen_opval_dr_names, fields->f_Rs2, 0);
242 break;
243 case FR30_OPERAND_CC :
244 print_normal (cd, info, fields->f_cc, 0, pc, length);
245 break;
246 case FR30_OPERAND_CCC :
247 print_normal (cd, info, fields->f_ccc, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
248 break;
249 case FR30_OPERAND_DIR10 :
250 print_normal (cd, info, fields->f_dir10, 0, pc, length);
251 break;
252 case FR30_OPERAND_DIR8 :
253 print_normal (cd, info, fields->f_dir8, 0, pc, length);
254 break;
255 case FR30_OPERAND_DIR9 :
256 print_normal (cd, info, fields->f_dir9, 0, pc, length);
257 break;
258 case FR30_OPERAND_DISP10 :
259 print_normal (cd, info, fields->f_disp10, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
260 break;
261 case FR30_OPERAND_DISP8 :
262 print_normal (cd, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
263 break;
264 case FR30_OPERAND_DISP9 :
265 print_normal (cd, info, fields->f_disp9, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
266 break;
267 case FR30_OPERAND_I20 :
268 print_normal (cd, info, fields->f_i20, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
269 break;
270 case FR30_OPERAND_I32 :
271 print_normal (cd, info, fields->f_i32, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGN_OPT), pc, length);
272 break;
273 case FR30_OPERAND_I8 :
274 print_normal (cd, info, fields->f_i8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
275 break;
276 case FR30_OPERAND_LABEL12 :
277 print_address (cd, info, fields->f_rel12, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
278 break;
279 case FR30_OPERAND_LABEL9 :
280 print_address (cd, info, fields->f_rel9, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
281 break;
282 case FR30_OPERAND_M4 :
283 print_m4 (cd, info, fields->f_m4, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
284 break;
285 case FR30_OPERAND_PS :
286 print_keyword (cd, info, & fr30_cgen_opval_h_ps, 0, 0);
287 break;
288 case FR30_OPERAND_REGLIST_HI_LD :
289 print_hi_register_list_ld (cd, info, fields->f_reglist_hi_ld, 0, pc, length);
290 break;
291 case FR30_OPERAND_REGLIST_HI_ST :
292 print_hi_register_list_st (cd, info, fields->f_reglist_hi_st, 0, pc, length);
293 break;
294 case FR30_OPERAND_REGLIST_LOW_LD :
295 print_low_register_list_ld (cd, info, fields->f_reglist_low_ld, 0, pc, length);
296 break;
297 case FR30_OPERAND_REGLIST_LOW_ST :
298 print_low_register_list_st (cd, info, fields->f_reglist_low_st, 0, pc, length);
299 break;
300 case FR30_OPERAND_S10 :
301 print_normal (cd, info, fields->f_s10, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
302 break;
303 case FR30_OPERAND_U10 :
304 print_normal (cd, info, fields->f_u10, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
305 break;
306 case FR30_OPERAND_U4 :
307 print_normal (cd, info, fields->f_u4, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
308 break;
309 case FR30_OPERAND_U4C :
310 print_normal (cd, info, fields->f_u4c, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
311 break;
312 case FR30_OPERAND_U8 :
313 print_normal (cd, info, fields->f_u8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
314 break;
315 case FR30_OPERAND_UDISP6 :
316 print_normal (cd, info, fields->f_udisp6, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
317 break;
318
319 default :
320 /* xgettext:c-format */
321 fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
322 opindex);
323 abort ();
324 }
325}
326
327cgen_print_fn * const fr30_cgen_print_handlers[] =
328{
329 print_insn_normal,
330};
331
332
333void
334fr30_cgen_init_dis (cd)
335 CGEN_CPU_DESC cd;
336{
337 fr30_cgen_init_opcode_table (cd);
338 fr30_cgen_init_ibld_table (cd);
339 cd->print_handlers = & fr30_cgen_print_handlers[0];
340 cd->print_operand = fr30_cgen_print_operand;
341}
342
343
344
345/* Default print handler. */
346
347static void
348print_normal (cd, dis_info, value, attrs, pc, length)
349 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
350 PTR dis_info;
351 long value;
352 unsigned int attrs;
353 bfd_vma pc ATTRIBUTE_UNUSED;
354 int length ATTRIBUTE_UNUSED;
355{
356 disassemble_info *info = (disassemble_info *) dis_info;
357
358#ifdef CGEN_PRINT_NORMAL
359 CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
360#endif
361
362 /* Print the operand as directed by the attributes. */
363 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
364 ; /* nothing to do */
365 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
366 (*info->fprintf_func) (info->stream, "%ld", value);
367 else
368 (*info->fprintf_func) (info->stream, "0x%lx", value);
369}
370
371/* Default address handler. */
372
373static void
374print_address (cd, dis_info, value, attrs, pc, length)
375 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
376 PTR dis_info;
377 bfd_vma value;
378 unsigned int attrs;
379 bfd_vma pc ATTRIBUTE_UNUSED;
380 int length ATTRIBUTE_UNUSED;
381{
382 disassemble_info *info = (disassemble_info *) dis_info;
383
384#ifdef CGEN_PRINT_ADDRESS
385 CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
386#endif
387
388 /* Print the operand as directed by the attributes. */
389 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
390 ; /* nothing to do */
391 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
392 (*info->print_address_func) (value, info);
393 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
394 (*info->print_address_func) (value, info);
395 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
396 (*info->fprintf_func) (info->stream, "%ld", (long) value);
397 else
398 (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
399}
400
401/* Keyword print handler. */
402
403static void
404print_keyword (cd, dis_info, keyword_table, value, attrs)
405 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
406 PTR dis_info;
407 CGEN_KEYWORD *keyword_table;
408 long value;
409 unsigned int attrs ATTRIBUTE_UNUSED;
410{
411 disassemble_info *info = (disassemble_info *) dis_info;
412 const CGEN_KEYWORD_ENTRY *ke;
413
414 ke = cgen_keyword_lookup_value (keyword_table, value);
415 if (ke != NULL)
416 (*info->fprintf_func) (info->stream, "%s", ke->name);
417 else
418 (*info->fprintf_func) (info->stream, "???");
419}
420
421
422/* Default insn printer.
423
424 DIS_INFO is defined as `PTR' so the disassembler needn't know anything
425 about disassemble_info. */
426
427static void
428print_insn_normal (cd, dis_info, insn, fields, pc, length)
429 CGEN_CPU_DESC cd;
430 PTR dis_info;
431 const CGEN_INSN *insn;
432 CGEN_FIELDS *fields;
433 bfd_vma pc;
434 int length;
435{
436 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
437 disassemble_info *info = (disassemble_info *) dis_info;
438 const CGEN_SYNTAX_CHAR_TYPE *syn;
439
440 CGEN_INIT_PRINT (cd);
441
442 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
443 {
444 if (CGEN_SYNTAX_MNEMONIC_P (*syn))
445 {
446 (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
447 continue;
448 }
449 if (CGEN_SYNTAX_CHAR_P (*syn))
450 {
451 (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
452 continue;
453 }
454
455 /* We have an operand. */
456 fr30_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
457 fields, CGEN_INSN_ATTRS (insn), pc, length);
458 }
459}
460
461
462/* Subroutine of print_insn. Reads an insn into the given buffers and updates
463 the extract info.
464 Returns 0 if all is well, non-zero otherwise. */
465
466static int
467read_insn (cd, pc, info, buf, buflen, ex_info, insn_value)
468 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
469 bfd_vma pc;
470 disassemble_info *info;
471 char *buf;
472 int buflen;
473 CGEN_EXTRACT_INFO *ex_info;
474 unsigned long *insn_value;
475{
476 int status = (*info->read_memory_func) (pc, buf, buflen, info);
477 if (status != 0)
478 {
479 (*info->memory_error_func) (status, pc, info);
480 return -1;
481 }
482
483 ex_info->dis_info = info;
484 ex_info->valid = (1 << buflen) - 1;
485 ex_info->insn_bytes = buf;
486
487 *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
488 return 0;
489}
490
491/* Utility to print an insn.
492 BUF is the base part of the insn, target byte order, BUFLEN bytes long.
493 The result is the size of the insn in bytes or zero for an unknown insn
494 or -1 if an error occurs fetching data (memory_error_func will have
495 been called). */
496
497static int
498print_insn (cd, pc, info, buf, buflen)
499 CGEN_CPU_DESC cd;
500 bfd_vma pc;
501 disassemble_info *info;
502 char *buf;
503 unsigned int buflen;
504{
505 CGEN_INSN_INT insn_value;
506 const CGEN_INSN_LIST *insn_list;
507 CGEN_EXTRACT_INFO ex_info;
508 int basesize;
509
510 /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
511 basesize = cd->base_insn_bitsize < buflen * 8 ?
512 cd->base_insn_bitsize : buflen * 8;
513 insn_value = cgen_get_insn_value (cd, buf, basesize);
514
515
516 /* Fill in ex_info fields like read_insn would. Don't actually call
517 read_insn, since the incoming buffer is already read (and possibly
518 modified a la m32r). */
519 ex_info.valid = (1 << buflen) - 1;
520 ex_info.dis_info = info;
521 ex_info.insn_bytes = buf;
522
523 /* The instructions are stored in hash lists.
524 Pick the first one and keep trying until we find the right one. */
525
526 insn_list = CGEN_DIS_LOOKUP_INSN (cd, buf, insn_value);
527 while (insn_list != NULL)
528 {
529 const CGEN_INSN *insn = insn_list->insn;
530 CGEN_FIELDS fields;
531 int length;
532 unsigned long insn_value_cropped;
533
534#ifdef CGEN_VALIDATE_INSN_SUPPORTED
535 /* Not needed as insn shouldn't be in hash lists if not supported. */
536 /* Supported by this cpu? */
537 if (! fr30_cgen_insn_supported (cd, insn))
538 {
539 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
540 continue;
541 }
542#endif
543
544 /* Basic bit mask must be correct. */
545 /* ??? May wish to allow target to defer this check until the extract
546 handler. */
547
548 /* Base size may exceed this instruction's size. Extract the
549 relevant part from the buffer. */
550 if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
551 (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
552 insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
553 info->endian == BFD_ENDIAN_BIG);
554 else
555 insn_value_cropped = insn_value;
556
557 if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
558 == CGEN_INSN_BASE_VALUE (insn))
559 {
560 /* Printing is handled in two passes. The first pass parses the
561 machine insn and extracts the fields. The second pass prints
562 them. */
563
564 /* Make sure the entire insn is loaded into insn_value, if it
565 can fit. */
566 if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
567 (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
568 {
569 unsigned long full_insn_value;
570 int rc = read_insn (cd, pc, info, buf,
571 CGEN_INSN_BITSIZE (insn) / 8,
572 & ex_info, & full_insn_value);
573 if (rc != 0)
574 return rc;
575 length = CGEN_EXTRACT_FN (cd, insn)
576 (cd, insn, &ex_info, full_insn_value, &fields, pc);
577 }
578 else
579 length = CGEN_EXTRACT_FN (cd, insn)
580 (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
581
582 /* length < 0 -> error */
583 if (length < 0)
584 return length;
585 if (length > 0)
586 {
587 CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
588 /* length is in bits, result is in bytes */
589 return length / 8;
590 }
591 }
592
593 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
594 }
595
596 return 0;
597}
598
599/* Default value for CGEN_PRINT_INSN.
600 The result is the size of the insn in bytes or zero for an unknown insn
601 or -1 if an error occured fetching bytes. */
602
603#ifndef CGEN_PRINT_INSN
604#define CGEN_PRINT_INSN default_print_insn
605#endif
606
607static int
608default_print_insn (cd, pc, info)
609 CGEN_CPU_DESC cd;
610 bfd_vma pc;
611 disassemble_info *info;
612{
613 char buf[CGEN_MAX_INSN_SIZE];
614 int buflen;
615 int status;
616
617 /* Attempt to read the base part of the insn. */
618 buflen = cd->base_insn_bitsize / 8;
619 status = (*info->read_memory_func) (pc, buf, buflen, info);
620
621 /* Try again with the minimum part, if min < base. */
622 if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
623 {
624 buflen = cd->min_insn_bitsize / 8;
625 status = (*info->read_memory_func) (pc, buf, buflen, info);
626 }
627
628 if (status != 0)
629 {
630 (*info->memory_error_func) (status, pc, info);
631 return -1;
632 }
633
634 return print_insn (cd, pc, info, buf, buflen);
635}
636
637/* Main entry point.
638 Print one instruction from PC on INFO->STREAM.
639 Return the size of the instruction (in bytes). */
640
641typedef struct cpu_desc_list {
642 struct cpu_desc_list *next;
643 int isa;
644 int mach;
645 int endian;
646 CGEN_CPU_DESC cd;
647} cpu_desc_list;
648
649int
650print_insn_fr30 (pc, info)
651 bfd_vma pc;
652 disassemble_info *info;
653{
654 static cpu_desc_list *cd_list = 0;
655 cpu_desc_list *cl = 0;
656 static CGEN_CPU_DESC cd = 0;
657 static int prev_isa;
658 static int prev_mach;
659 static int prev_endian;
660 int length;
661 int isa,mach;
662 int endian = (info->endian == BFD_ENDIAN_BIG
663 ? CGEN_ENDIAN_BIG
664 : CGEN_ENDIAN_LITTLE);
665 enum bfd_architecture arch;
666
667 /* ??? gdb will set mach but leave the architecture as "unknown" */
668#ifndef CGEN_BFD_ARCH
669#define CGEN_BFD_ARCH bfd_arch_fr30
670#endif
671 arch = info->arch;
672 if (arch == bfd_arch_unknown)
673 arch = CGEN_BFD_ARCH;
674
675 /* There's no standard way to compute the machine or isa number
676 so we leave it to the target. */
677#ifdef CGEN_COMPUTE_MACH
678 mach = CGEN_COMPUTE_MACH (info);
679#else
680 mach = info->mach;
681#endif
682
683#ifdef CGEN_COMPUTE_ISA
684 isa = CGEN_COMPUTE_ISA (info);
685#else
686 isa = info->insn_sets;
687#endif
688
689 /* If we've switched cpu's, try to find a handle we've used before */
690 if (cd
691 && (isa != prev_isa
692 || mach != prev_mach
693 || endian != prev_endian))
694 {
695 cd = 0;
696 for (cl = cd_list; cl; cl = cl->next)
697 {
698 if (cl->isa == isa &&
699 cl->mach == mach &&
700 cl->endian == endian)
701 {
702 cd = cl->cd;
703 break;
704 }
705 }
706 }
707
708 /* If we haven't initialized yet, initialize the opcode table. */
709 if (! cd)
710 {
711 const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
712 const char *mach_name;
713
714 if (!arch_type)
715 abort ();
716 mach_name = arch_type->printable_name;
717
718 prev_isa = isa;
719 prev_mach = mach;
720 prev_endian = endian;
721 cd = fr30_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
722 CGEN_CPU_OPEN_BFDMACH, mach_name,
723 CGEN_CPU_OPEN_ENDIAN, prev_endian,
724 CGEN_CPU_OPEN_END);
725 if (!cd)
726 abort ();
727
728 /* save this away for future reference */
729 cl = xmalloc (sizeof (struct cpu_desc_list));
730 cl->cd = cd;
731 cl->isa = isa;
732 cl->mach = mach;
733 cl->endian = endian;
734 cl->next = cd_list;
735 cd_list = cl;
736
737 fr30_cgen_init_dis (cd);
738 }
739
740 /* We try to have as much common code as possible.
741 But at this point some targets need to take over. */
742 /* ??? Some targets may need a hook elsewhere. Try to avoid this,
743 but if not possible try to move this hook elsewhere rather than
744 have two hooks. */
745 length = CGEN_PRINT_INSN (cd, pc, info);
746 if (length > 0)
747 return length;
748 if (length < 0)
749 return -1;
750
751 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
752 return cd->default_insn_bitsize / 8;
753}
Note: See TracBrowser for help on using the repository browser.