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