Annotation of src/external/gpl3/binutils/dist/opcodes/mt-dis.c, Revision 1.1.1.5.12.2
1.1.1.5.12.1 pgoyette 1: /* DO NOT EDIT! -*- buffer-read-only: t -*- vi:set ro: */
1.1 skrll 2: /* Disassembler interface for targets using CGEN. -*- C -*-
3: CGEN: Cpu tools GENerator
4:
5: THIS FILE IS MACHINE GENERATED WITH CGEN.
6: - the resultant file is machine generated, cgen-dis.in isn't
7:
1.1.1.5.12.1 pgoyette 8: Copyright (C) 1996-2018 Free Software Foundation, Inc.
1.1 skrll 9:
10: This file is part of libopcodes.
11:
12: This library is free software; you can redistribute it and/or modify
13: it under the terms of the GNU General Public License as published by
14: the Free Software Foundation; either version 3, or (at your option)
15: any later version.
16:
17: It is distributed in the hope that it will be useful, but WITHOUT
18: ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
20: License for more details.
21:
22: You should have received a copy of the GNU General Public License
23: along with this program; if not, write to the Free Software Foundation, Inc.,
24: 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 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"
1.1.1.5.12.1 pgoyette 32: #include "disassemble.h"
1.1 skrll 33: #include "bfd.h"
34: #include "symcat.h"
35: #include "libiberty.h"
36: #include "mt-desc.h"
37: #include "mt-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:
43: static void print_normal
44: (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
45: static void print_address
46: (CGEN_CPU_DESC, void *, bfd_vma, unsigned int, bfd_vma, int) ATTRIBUTE_UNUSED;
47: static void print_keyword
48: (CGEN_CPU_DESC, void *, CGEN_KEYWORD *, long, unsigned int) ATTRIBUTE_UNUSED;
49: static void print_insn_normal
50: (CGEN_CPU_DESC, void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int);
51: static int print_insn
52: (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, unsigned);
53: static int default_print_insn
54: (CGEN_CPU_DESC, bfd_vma, disassemble_info *) ATTRIBUTE_UNUSED;
55: static int read_insn
56: (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, int, CGEN_EXTRACT_INFO *,
57: unsigned long *);
58:
59: /* -- disassembler routines inserted here. */
60:
61: /* -- dis.c */
62: static void print_dollarhex (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
63: static void print_pcrel (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
64:
65: static void
66: print_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
67: void * dis_info,
68: long value,
69: unsigned int attrs ATTRIBUTE_UNUSED,
70: bfd_vma pc ATTRIBUTE_UNUSED,
71: int length ATTRIBUTE_UNUSED)
72: {
73: disassemble_info *info = (disassemble_info *) dis_info;
74:
1.1.1.3 christos 75: info->fprintf_func (info->stream, "$%lx", value & 0xffffffff);
1.1 skrll 76:
77: if (0)
78: print_normal (cd, dis_info, value, attrs, pc, length);
79: }
80:
81: static void
82: print_pcrel (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
83: void * dis_info,
84: long value,
85: unsigned int attrs ATTRIBUTE_UNUSED,
86: bfd_vma pc ATTRIBUTE_UNUSED,
87: int length ATTRIBUTE_UNUSED)
88: {
89: print_address (cd, dis_info, value + pc, attrs, pc, length);
90: }
91:
92: /* -- */
93:
94: void mt_cgen_print_operand
95: (CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *, void const *, bfd_vma, int);
96:
97: /* Main entry point for printing operands.
98: XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
99: of dis-asm.h on cgen.h.
100:
101: This function is basically just a big switch statement. Earlier versions
102: used tables to look up the function to use, but
103: - if the table contains both assembler and disassembler functions then
104: the disassembler contains much of the assembler and vice-versa,
105: - there's a lot of inlining possibilities as things grow,
106: - using a switch statement avoids the function call overhead.
107:
108: This function could be moved into `print_insn_normal', but keeping it
109: separate makes clear the interface between `print_insn_normal' and each of
110: the handlers. */
111:
112: void
113: mt_cgen_print_operand (CGEN_CPU_DESC cd,
114: int opindex,
115: void * xinfo,
116: CGEN_FIELDS *fields,
117: void const *attrs ATTRIBUTE_UNUSED,
118: bfd_vma pc,
119: int length)
120: {
121: disassemble_info *info = (disassemble_info *) xinfo;
122:
123: switch (opindex)
124: {
125: case MT_OPERAND_A23 :
126: print_dollarhex (cd, info, fields->f_a23, 0, pc, length);
127: break;
128: case MT_OPERAND_BALL :
129: print_dollarhex (cd, info, fields->f_ball, 0, pc, length);
130: break;
131: case MT_OPERAND_BALL2 :
132: print_dollarhex (cd, info, fields->f_ball2, 0, pc, length);
133: break;
134: case MT_OPERAND_BANKADDR :
135: print_dollarhex (cd, info, fields->f_bankaddr, 0, pc, length);
136: break;
137: case MT_OPERAND_BRC :
138: print_dollarhex (cd, info, fields->f_brc, 0, pc, length);
139: break;
140: case MT_OPERAND_BRC2 :
141: print_dollarhex (cd, info, fields->f_brc2, 0, pc, length);
142: break;
143: case MT_OPERAND_CB1INCR :
144: print_dollarhex (cd, info, fields->f_cb1incr, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
145: break;
146: case MT_OPERAND_CB1SEL :
147: print_dollarhex (cd, info, fields->f_cb1sel, 0, pc, length);
148: break;
149: case MT_OPERAND_CB2INCR :
150: print_dollarhex (cd, info, fields->f_cb2incr, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
151: break;
152: case MT_OPERAND_CB2SEL :
153: print_dollarhex (cd, info, fields->f_cb2sel, 0, pc, length);
154: break;
155: case MT_OPERAND_CBRB :
156: print_dollarhex (cd, info, fields->f_cbrb, 0, pc, length);
157: break;
158: case MT_OPERAND_CBS :
159: print_dollarhex (cd, info, fields->f_cbs, 0, pc, length);
160: break;
161: case MT_OPERAND_CBX :
162: print_dollarhex (cd, info, fields->f_cbx, 0, pc, length);
163: break;
164: case MT_OPERAND_CCB :
165: print_dollarhex (cd, info, fields->f_ccb, 0, pc, length);
166: break;
167: case MT_OPERAND_CDB :
168: print_dollarhex (cd, info, fields->f_cdb, 0, pc, length);
169: break;
170: case MT_OPERAND_CELL :
171: print_dollarhex (cd, info, fields->f_cell, 0, pc, length);
172: break;
173: case MT_OPERAND_COLNUM :
174: print_dollarhex (cd, info, fields->f_colnum, 0, pc, length);
175: break;
176: case MT_OPERAND_CONTNUM :
177: print_dollarhex (cd, info, fields->f_contnum, 0, pc, length);
178: break;
179: case MT_OPERAND_CR :
180: print_dollarhex (cd, info, fields->f_cr, 0, pc, length);
181: break;
182: case MT_OPERAND_CTXDISP :
183: print_dollarhex (cd, info, fields->f_ctxdisp, 0, pc, length);
184: break;
185: case MT_OPERAND_DUP :
186: print_dollarhex (cd, info, fields->f_dup, 0, pc, length);
187: break;
188: case MT_OPERAND_FBDISP :
189: print_dollarhex (cd, info, fields->f_fbdisp, 0, pc, length);
190: break;
191: case MT_OPERAND_FBINCR :
192: print_dollarhex (cd, info, fields->f_fbincr, 0, pc, length);
193: break;
194: case MT_OPERAND_FRDR :
195: print_keyword (cd, info, & mt_cgen_opval_h_spr, fields->f_dr, 0|(1<<CGEN_OPERAND_ABS_ADDR));
196: break;
197: case MT_OPERAND_FRDRRR :
198: print_keyword (cd, info, & mt_cgen_opval_h_spr, fields->f_drrr, 0|(1<<CGEN_OPERAND_ABS_ADDR));
199: break;
200: case MT_OPERAND_FRSR1 :
201: print_keyword (cd, info, & mt_cgen_opval_h_spr, fields->f_sr1, 0|(1<<CGEN_OPERAND_ABS_ADDR));
202: break;
203: case MT_OPERAND_FRSR2 :
204: print_keyword (cd, info, & mt_cgen_opval_h_spr, fields->f_sr2, 0|(1<<CGEN_OPERAND_ABS_ADDR));
205: break;
206: case MT_OPERAND_ID :
207: print_dollarhex (cd, info, fields->f_id, 0, pc, length);
208: break;
209: case MT_OPERAND_IMM16 :
210: print_dollarhex (cd, info, fields->f_imm16s, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
211: break;
212: case MT_OPERAND_IMM16L :
213: print_dollarhex (cd, info, fields->f_imm16l, 0, pc, length);
214: break;
215: case MT_OPERAND_IMM16O :
216: print_pcrel (cd, info, fields->f_imm16s, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
217: break;
218: case MT_OPERAND_IMM16Z :
219: print_dollarhex (cd, info, fields->f_imm16u, 0, pc, length);
220: break;
221: case MT_OPERAND_INCAMT :
222: print_dollarhex (cd, info, fields->f_incamt, 0, pc, length);
223: break;
224: case MT_OPERAND_INCR :
225: print_dollarhex (cd, info, fields->f_incr, 0, pc, length);
226: break;
227: case MT_OPERAND_LENGTH :
228: print_dollarhex (cd, info, fields->f_length, 0, pc, length);
229: break;
230: case MT_OPERAND_LOOPSIZE :
231: print_pcrel (cd, info, fields->f_loopo, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
232: break;
233: case MT_OPERAND_MASK :
234: print_dollarhex (cd, info, fields->f_mask, 0, pc, length);
235: break;
236: case MT_OPERAND_MASK1 :
237: print_dollarhex (cd, info, fields->f_mask1, 0, pc, length);
238: break;
239: case MT_OPERAND_MODE :
240: print_dollarhex (cd, info, fields->f_mode, 0, pc, length);
241: break;
242: case MT_OPERAND_PERM :
243: print_dollarhex (cd, info, fields->f_perm, 0, pc, length);
244: break;
245: case MT_OPERAND_RBBC :
246: print_dollarhex (cd, info, fields->f_rbbc, 0, pc, length);
247: break;
248: case MT_OPERAND_RC :
249: print_dollarhex (cd, info, fields->f_rc, 0, pc, length);
250: break;
251: case MT_OPERAND_RC1 :
252: print_dollarhex (cd, info, fields->f_rc1, 0, pc, length);
253: break;
254: case MT_OPERAND_RC2 :
255: print_dollarhex (cd, info, fields->f_rc2, 0, pc, length);
256: break;
257: case MT_OPERAND_RC3 :
258: print_dollarhex (cd, info, fields->f_rc3, 0, pc, length);
259: break;
260: case MT_OPERAND_RCNUM :
261: print_dollarhex (cd, info, fields->f_rcnum, 0, pc, length);
262: break;
263: case MT_OPERAND_RDA :
264: print_dollarhex (cd, info, fields->f_rda, 0, pc, length);
265: break;
266: case MT_OPERAND_ROWNUM :
267: print_dollarhex (cd, info, fields->f_rownum, 0, pc, length);
268: break;
269: case MT_OPERAND_ROWNUM1 :
270: print_dollarhex (cd, info, fields->f_rownum1, 0, pc, length);
271: break;
272: case MT_OPERAND_ROWNUM2 :
273: print_dollarhex (cd, info, fields->f_rownum2, 0, pc, length);
274: break;
275: case MT_OPERAND_SIZE :
276: print_dollarhex (cd, info, fields->f_size, 0, pc, length);
277: break;
278: case MT_OPERAND_TYPE :
279: print_dollarhex (cd, info, fields->f_type, 0, pc, length);
280: break;
281: case MT_OPERAND_WR :
282: print_dollarhex (cd, info, fields->f_wr, 0, pc, length);
283: break;
284: case MT_OPERAND_XMODE :
285: print_dollarhex (cd, info, fields->f_xmode, 0, pc, length);
286: break;
287:
288: default :
289: /* xgettext:c-format */
1.1.1.5.12.2! pgoyette 290: opcodes_error_handler
! 291: (_("internal error: unrecognized field %d while printing insn"),
! 292: opindex);
! 293: abort ();
1.1 skrll 294: }
295: }
296:
1.1.1.4 christos 297: cgen_print_fn * const mt_cgen_print_handlers[] =
1.1 skrll 298: {
299: print_insn_normal,
300: };
301:
302:
303: void
304: mt_cgen_init_dis (CGEN_CPU_DESC cd)
305: {
306: mt_cgen_init_opcode_table (cd);
307: mt_cgen_init_ibld_table (cd);
308: cd->print_handlers = & mt_cgen_print_handlers[0];
309: cd->print_operand = mt_cgen_print_operand;
310: }
311:
312:
313: /* Default print handler. */
314:
315: static void
316: print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
317: void *dis_info,
318: long value,
319: unsigned int attrs,
320: bfd_vma pc ATTRIBUTE_UNUSED,
321: int length ATTRIBUTE_UNUSED)
322: {
323: disassemble_info *info = (disassemble_info *) dis_info;
324:
325: /* Print the operand as directed by the attributes. */
326: if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
327: ; /* nothing to do */
328: else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
329: (*info->fprintf_func) (info->stream, "%ld", value);
330: else
331: (*info->fprintf_func) (info->stream, "0x%lx", value);
332: }
333:
334: /* Default address handler. */
335:
336: static void
337: print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
338: void *dis_info,
339: bfd_vma value,
340: unsigned int attrs,
341: bfd_vma pc ATTRIBUTE_UNUSED,
342: int length ATTRIBUTE_UNUSED)
343: {
344: disassemble_info *info = (disassemble_info *) dis_info;
345:
346: /* Print the operand as directed by the attributes. */
347: if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
348: ; /* Nothing to do. */
349: else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
350: (*info->print_address_func) (value, info);
351: else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
352: (*info->print_address_func) (value, info);
353: else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
354: (*info->fprintf_func) (info->stream, "%ld", (long) value);
355: else
356: (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
357: }
358:
359: /* Keyword print handler. */
360:
361: static void
362: print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
363: void *dis_info,
364: CGEN_KEYWORD *keyword_table,
365: long value,
366: unsigned int attrs ATTRIBUTE_UNUSED)
367: {
368: disassemble_info *info = (disassemble_info *) dis_info;
369: const CGEN_KEYWORD_ENTRY *ke;
370:
371: ke = cgen_keyword_lookup_value (keyword_table, value);
372: if (ke != NULL)
373: (*info->fprintf_func) (info->stream, "%s", ke->name);
374: else
375: (*info->fprintf_func) (info->stream, "???");
376: }
377:
378: /* Default insn printer.
379:
380: DIS_INFO is defined as `void *' so the disassembler needn't know anything
381: about disassemble_info. */
382:
383: static void
384: print_insn_normal (CGEN_CPU_DESC cd,
385: void *dis_info,
386: const CGEN_INSN *insn,
387: CGEN_FIELDS *fields,
388: bfd_vma pc,
389: int length)
390: {
391: const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
392: disassemble_info *info = (disassemble_info *) dis_info;
393: const CGEN_SYNTAX_CHAR_TYPE *syn;
394:
395: CGEN_INIT_PRINT (cd);
396:
397: for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
398: {
399: if (CGEN_SYNTAX_MNEMONIC_P (*syn))
400: {
401: (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
402: continue;
403: }
404: if (CGEN_SYNTAX_CHAR_P (*syn))
405: {
406: (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
407: continue;
408: }
409:
410: /* We have an operand. */
411: mt_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
412: fields, CGEN_INSN_ATTRS (insn), pc, length);
413: }
414: }
415:
416: /* Subroutine of print_insn. Reads an insn into the given buffers and updates
417: the extract info.
418: Returns 0 if all is well, non-zero otherwise. */
419:
420: static int
421: read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
422: bfd_vma pc,
423: disassemble_info *info,
424: bfd_byte *buf,
425: int buflen,
426: CGEN_EXTRACT_INFO *ex_info,
427: unsigned long *insn_value)
428: {
429: int status = (*info->read_memory_func) (pc, buf, buflen, info);
430:
431: if (status != 0)
432: {
433: (*info->memory_error_func) (status, pc, info);
434: return -1;
435: }
436:
437: ex_info->dis_info = info;
438: ex_info->valid = (1 << buflen) - 1;
439: ex_info->insn_bytes = buf;
440:
441: *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
442: return 0;
443: }
444:
445: /* Utility to print an insn.
446: BUF is the base part of the insn, target byte order, BUFLEN bytes long.
447: The result is the size of the insn in bytes or zero for an unknown insn
448: or -1 if an error occurs fetching data (memory_error_func will have
449: been called). */
450:
451: static int
452: print_insn (CGEN_CPU_DESC cd,
453: bfd_vma pc,
454: disassemble_info *info,
455: bfd_byte *buf,
456: unsigned int buflen)
457: {
458: CGEN_INSN_INT insn_value;
459: const CGEN_INSN_LIST *insn_list;
460: CGEN_EXTRACT_INFO ex_info;
461: int basesize;
462:
463: /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
464: basesize = cd->base_insn_bitsize < buflen * 8 ?
465: cd->base_insn_bitsize : buflen * 8;
466: insn_value = cgen_get_insn_value (cd, buf, basesize);
467:
468:
469: /* Fill in ex_info fields like read_insn would. Don't actually call
470: read_insn, since the incoming buffer is already read (and possibly
471: modified a la m32r). */
472: ex_info.valid = (1 << buflen) - 1;
473: ex_info.dis_info = info;
474: ex_info.insn_bytes = buf;
475:
476: /* The instructions are stored in hash lists.
477: Pick the first one and keep trying until we find the right one. */
478:
479: insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
480: while (insn_list != NULL)
481: {
482: const CGEN_INSN *insn = insn_list->insn;
483: CGEN_FIELDS fields;
484: int length;
485: unsigned long insn_value_cropped;
486:
1.1.1.4 christos 487: #ifdef CGEN_VALIDATE_INSN_SUPPORTED
1.1 skrll 488: /* Not needed as insn shouldn't be in hash lists if not supported. */
489: /* Supported by this cpu? */
490: if (! mt_cgen_insn_supported (cd, insn))
491: {
492: insn_list = CGEN_DIS_NEXT_INSN (insn_list);
493: continue;
494: }
495: #endif
496:
497: /* Basic bit mask must be correct. */
498: /* ??? May wish to allow target to defer this check until the extract
499: handler. */
500:
501: /* Base size may exceed this instruction's size. Extract the
502: relevant part from the buffer. */
503: if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
504: (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
1.1.1.4 christos 505: insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
1.1 skrll 506: info->endian == BFD_ENDIAN_BIG);
507: else
508: insn_value_cropped = insn_value;
509:
510: if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
511: == CGEN_INSN_BASE_VALUE (insn))
512: {
513: /* Printing is handled in two passes. The first pass parses the
514: machine insn and extracts the fields. The second pass prints
515: them. */
516:
517: /* Make sure the entire insn is loaded into insn_value, if it
518: can fit. */
519: if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
520: (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
521: {
522: unsigned long full_insn_value;
523: int rc = read_insn (cd, pc, info, buf,
524: CGEN_INSN_BITSIZE (insn) / 8,
525: & ex_info, & full_insn_value);
526: if (rc != 0)
527: return rc;
528: length = CGEN_EXTRACT_FN (cd, insn)
529: (cd, insn, &ex_info, full_insn_value, &fields, pc);
530: }
531: else
532: length = CGEN_EXTRACT_FN (cd, insn)
533: (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
534:
535: /* Length < 0 -> error. */
536: if (length < 0)
537: return length;
538: if (length > 0)
539: {
540: CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
541: /* Length is in bits, result is in bytes. */
542: return length / 8;
543: }
544: }
545:
546: insn_list = CGEN_DIS_NEXT_INSN (insn_list);
547: }
548:
549: return 0;
550: }
551:
552: /* Default value for CGEN_PRINT_INSN.
553: The result is the size of the insn in bytes or zero for an unknown insn
554: or -1 if an error occured fetching bytes. */
555:
556: #ifndef CGEN_PRINT_INSN
557: #define CGEN_PRINT_INSN default_print_insn
558: #endif
559:
560: static int
561: default_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
562: {
563: bfd_byte buf[CGEN_MAX_INSN_SIZE];
564: int buflen;
565: int status;
566:
567: /* Attempt to read the base part of the insn. */
568: buflen = cd->base_insn_bitsize / 8;
569: status = (*info->read_memory_func) (pc, buf, buflen, info);
570:
571: /* Try again with the minimum part, if min < base. */
572: if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
573: {
574: buflen = cd->min_insn_bitsize / 8;
575: status = (*info->read_memory_func) (pc, buf, buflen, info);
576: }
577:
578: if (status != 0)
579: {
580: (*info->memory_error_func) (status, pc, info);
581: return -1;
582: }
583:
584: return print_insn (cd, pc, info, buf, buflen);
585: }
586:
587: /* Main entry point.
588: Print one instruction from PC on INFO->STREAM.
589: Return the size of the instruction (in bytes). */
590:
591: typedef struct cpu_desc_list
592: {
593: struct cpu_desc_list *next;
594: CGEN_BITSET *isa;
595: int mach;
596: int endian;
597: CGEN_CPU_DESC cd;
598: } cpu_desc_list;
599:
600: int
601: print_insn_mt (bfd_vma pc, disassemble_info *info)
602: {
603: static cpu_desc_list *cd_list = 0;
604: cpu_desc_list *cl = 0;
605: static CGEN_CPU_DESC cd = 0;
606: static CGEN_BITSET *prev_isa;
607: static int prev_mach;
608: static int prev_endian;
609: int length;
610: CGEN_BITSET *isa;
611: int mach;
612: int endian = (info->endian == BFD_ENDIAN_BIG
613: ? CGEN_ENDIAN_BIG
614: : CGEN_ENDIAN_LITTLE);
615: enum bfd_architecture arch;
616:
617: /* ??? gdb will set mach but leave the architecture as "unknown" */
618: #ifndef CGEN_BFD_ARCH
619: #define CGEN_BFD_ARCH bfd_arch_mt
620: #endif
621: arch = info->arch;
622: if (arch == bfd_arch_unknown)
623: arch = CGEN_BFD_ARCH;
1.1.1.4 christos 624:
1.1 skrll 625: /* There's no standard way to compute the machine or isa number
626: so we leave it to the target. */
627: #ifdef CGEN_COMPUTE_MACH
628: mach = CGEN_COMPUTE_MACH (info);
629: #else
630: mach = info->mach;
631: #endif
632:
633: #ifdef CGEN_COMPUTE_ISA
634: {
635: static CGEN_BITSET *permanent_isa;
636:
637: if (!permanent_isa)
638: permanent_isa = cgen_bitset_create (MAX_ISAS);
639: isa = permanent_isa;
640: cgen_bitset_clear (isa);
641: cgen_bitset_add (isa, CGEN_COMPUTE_ISA (info));
642: }
643: #else
644: isa = info->insn_sets;
645: #endif
646:
647: /* If we've switched cpu's, try to find a handle we've used before */
648: if (cd
649: && (cgen_bitset_compare (isa, prev_isa) != 0
650: || mach != prev_mach
651: || endian != prev_endian))
652: {
653: cd = 0;
654: for (cl = cd_list; cl; cl = cl->next)
655: {
656: if (cgen_bitset_compare (cl->isa, isa) == 0 &&
657: cl->mach == mach &&
658: cl->endian == endian)
659: {
660: cd = cl->cd;
661: prev_isa = cd->isas;
662: break;
663: }
664: }
1.1.1.4 christos 665: }
1.1 skrll 666:
667: /* If we haven't initialized yet, initialize the opcode table. */
668: if (! cd)
669: {
670: const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
671: const char *mach_name;
672:
673: if (!arch_type)
674: abort ();
675: mach_name = arch_type->printable_name;
676:
677: prev_isa = cgen_bitset_copy (isa);
678: prev_mach = mach;
679: prev_endian = endian;
680: cd = mt_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
681: CGEN_CPU_OPEN_BFDMACH, mach_name,
682: CGEN_CPU_OPEN_ENDIAN, prev_endian,
683: CGEN_CPU_OPEN_END);
684: if (!cd)
685: abort ();
686:
687: /* Save this away for future reference. */
688: cl = xmalloc (sizeof (struct cpu_desc_list));
689: cl->cd = cd;
690: cl->isa = prev_isa;
691: cl->mach = mach;
692: cl->endian = endian;
693: cl->next = cd_list;
694: cd_list = cl;
695:
696: mt_cgen_init_dis (cd);
697: }
698:
699: /* We try to have as much common code as possible.
700: But at this point some targets need to take over. */
701: /* ??? Some targets may need a hook elsewhere. Try to avoid this,
702: but if not possible try to move this hook elsewhere rather than
703: have two hooks. */
704: length = CGEN_PRINT_INSN (cd, pc, info);
705: if (length > 0)
706: return length;
707: if (length < 0)
708: return -1;
709:
710: (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
711: return cd->default_insn_bitsize / 8;
712: }
CVSweb <webmaster@jp.NetBSD.org>