Sync dlang demangling tests from upstream libiberty testsuite.
[deliverable/binutils-gdb.git] / opcodes / xc16x-dis.c
... / ...
CommitLineData
1/* Disassembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
4 THIS FILE IS MACHINE GENERATED WITH CGEN.
5 - the resultant file is machine generated, cgen-dis.in isn't
6
7 Copyright (C) 1996-2017 Free Software Foundation, Inc.
8
9 This file is part of libopcodes.
10
11 This library is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3, or (at your option)
14 any later version.
15
16 It is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19 License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
24
25/* ??? Eventually more and more of this stuff can go to cpu-independent files.
26 Keep that in mind. */
27
28#include "sysdep.h"
29#include <stdio.h>
30#include "ansidecl.h"
31#include "disassemble.h"
32#include "bfd.h"
33#include "symcat.h"
34#include "libiberty.h"
35#include "xc16x-desc.h"
36#include "xc16x-opc.h"
37#include "opintl.h"
38
39/* Default text to print if an instruction isn't recognized. */
40#define UNKNOWN_INSN_MSG _("*unknown*")
41
42static void print_normal
43 (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
44static void print_address
45 (CGEN_CPU_DESC, void *, bfd_vma, unsigned int, bfd_vma, int) ATTRIBUTE_UNUSED;
46static void print_keyword
47 (CGEN_CPU_DESC, void *, CGEN_KEYWORD *, long, unsigned int) ATTRIBUTE_UNUSED;
48static void print_insn_normal
49 (CGEN_CPU_DESC, void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int);
50static int print_insn
51 (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, unsigned);
52static int default_print_insn
53 (CGEN_CPU_DESC, bfd_vma, disassemble_info *) ATTRIBUTE_UNUSED;
54static int read_insn
55 (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, int, CGEN_EXTRACT_INFO *,
56 unsigned long *);
57\f
58/* -- disassembler routines inserted here. */
59
60/* -- dis.c */
61
62/* Print an operand with a "." prefix.
63 NOTE: This prints the operand in hex.
64 ??? This exists to maintain disassembler compatibility with previous
65 versions. Ideally we'd print the "." in print_dot. */
66
67static void
68print_with_dot_prefix (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
69 void * dis_info,
70 long value,
71 unsigned attrs ATTRIBUTE_UNUSED,
72 bfd_vma pc ATTRIBUTE_UNUSED,
73 int length ATTRIBUTE_UNUSED)
74{
75 disassemble_info *info = (disassemble_info *) dis_info;
76
77 info->fprintf_func (info->stream, ".");
78 info->fprintf_func (info->stream, "0x%lx", value);
79}
80
81/* Print an operand with a "#pof:" prefix.
82 NOTE: This prints the operand as an address.
83 ??? This exists to maintain disassembler compatibility with previous
84 versions. Ideally we'd print "#pof:" in print_pof. */
85
86static void
87print_with_pof_prefix (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
88 void * dis_info,
89 bfd_vma value,
90 unsigned attrs ATTRIBUTE_UNUSED,
91 bfd_vma pc ATTRIBUTE_UNUSED,
92 int length ATTRIBUTE_UNUSED)
93{
94 disassemble_info *info = (disassemble_info *) dis_info;
95
96 info->fprintf_func (info->stream, "#pof:");
97 info->fprintf_func (info->stream, "0x%lx", (long) value);
98}
99
100/* Print an operand with a "#pag:" prefix.
101 NOTE: This prints the operand in hex.
102 ??? This exists to maintain disassembler compatibility with previous
103 versions. Ideally we'd print "#pag:" in print_pag. */
104
105static void
106print_with_pag_prefix (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
107 void * dis_info,
108 long value,
109 unsigned attrs ATTRIBUTE_UNUSED,
110 bfd_vma pc ATTRIBUTE_UNUSED,
111 int length ATTRIBUTE_UNUSED)
112{
113 disassemble_info *info = (disassemble_info *) dis_info;
114
115 info->fprintf_func (info->stream, "#pag:");
116 info->fprintf_func (info->stream, "0x%lx", value);
117}
118
119/* Print a 'pof:' prefix to an operand. */
120
121static void
122print_pof (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
123 void * dis_info ATTRIBUTE_UNUSED,
124 long value ATTRIBUTE_UNUSED,
125 unsigned int attrs ATTRIBUTE_UNUSED,
126 bfd_vma pc ATTRIBUTE_UNUSED,
127 int length ATTRIBUTE_UNUSED)
128{
129}
130
131/* Print a 'pag:' prefix to an operand. */
132
133static void
134print_pag (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
135 void * dis_info ATTRIBUTE_UNUSED,
136 long value ATTRIBUTE_UNUSED,
137 unsigned int attrs ATTRIBUTE_UNUSED,
138 bfd_vma pc ATTRIBUTE_UNUSED,
139 int length ATTRIBUTE_UNUSED)
140{
141}
142
143/* Print a 'sof:' prefix to an operand. */
144
145static void
146print_sof (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
147 void * dis_info,
148 long value ATTRIBUTE_UNUSED,
149 unsigned int attrs ATTRIBUTE_UNUSED,
150 bfd_vma pc ATTRIBUTE_UNUSED,
151 int length ATTRIBUTE_UNUSED)
152{
153 disassemble_info *info = (disassemble_info *) dis_info;
154
155 info->fprintf_func (info->stream, "sof:");
156}
157
158/* Print a 'seg:' prefix to an operand. */
159
160static void
161print_seg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
162 void * dis_info,
163 long value ATTRIBUTE_UNUSED,
164 unsigned int attrs ATTRIBUTE_UNUSED,
165 bfd_vma pc ATTRIBUTE_UNUSED,
166 int length ATTRIBUTE_UNUSED)
167{
168 disassemble_info *info = (disassemble_info *) dis_info;
169
170 info->fprintf_func (info->stream, "seg:");
171}
172
173/* Print a '#' prefix to an operand. */
174
175static void
176print_hash (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
177 void * dis_info,
178 long value ATTRIBUTE_UNUSED,
179 unsigned int attrs ATTRIBUTE_UNUSED,
180 bfd_vma pc ATTRIBUTE_UNUSED,
181 int length ATTRIBUTE_UNUSED)
182{
183 disassemble_info *info = (disassemble_info *) dis_info;
184
185 info->fprintf_func (info->stream, "#");
186}
187
188/* Print a '.' prefix to an operand. */
189
190static void
191print_dot (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
192 void * dis_info ATTRIBUTE_UNUSED,
193 long value ATTRIBUTE_UNUSED,
194 unsigned int attrs ATTRIBUTE_UNUSED,
195 bfd_vma pc ATTRIBUTE_UNUSED,
196 int length ATTRIBUTE_UNUSED)
197{
198}
199
200/* -- */
201
202void xc16x_cgen_print_operand
203 (CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *, void const *, bfd_vma, int);
204
205/* Main entry point for printing operands.
206 XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
207 of dis-asm.h on cgen.h.
208
209 This function is basically just a big switch statement. Earlier versions
210 used tables to look up the function to use, but
211 - if the table contains both assembler and disassembler functions then
212 the disassembler contains much of the assembler and vice-versa,
213 - there's a lot of inlining possibilities as things grow,
214 - using a switch statement avoids the function call overhead.
215
216 This function could be moved into `print_insn_normal', but keeping it
217 separate makes clear the interface between `print_insn_normal' and each of
218 the handlers. */
219
220void
221xc16x_cgen_print_operand (CGEN_CPU_DESC cd,
222 int opindex,
223 void * xinfo,
224 CGEN_FIELDS *fields,
225 void const *attrs ATTRIBUTE_UNUSED,
226 bfd_vma pc,
227 int length)
228{
229 disassemble_info *info = (disassemble_info *) xinfo;
230
231 switch (opindex)
232 {
233 case XC16X_OPERAND_REGNAM :
234 print_keyword (cd, info, & xc16x_cgen_opval_psw_names, fields->f_reg8, 0);
235 break;
236 case XC16X_OPERAND_BIT01 :
237 print_normal (cd, info, fields->f_op_1bit, 0, pc, length);
238 break;
239 case XC16X_OPERAND_BIT1 :
240 print_normal (cd, info, fields->f_op_bit1, 0, pc, length);
241 break;
242 case XC16X_OPERAND_BIT2 :
243 print_normal (cd, info, fields->f_op_bit2, 0, pc, length);
244 break;
245 case XC16X_OPERAND_BIT4 :
246 print_normal (cd, info, fields->f_op_bit4, 0, pc, length);
247 break;
248 case XC16X_OPERAND_BIT8 :
249 print_normal (cd, info, fields->f_op_bit8, 0, pc, length);
250 break;
251 case XC16X_OPERAND_BITONE :
252 print_normal (cd, info, fields->f_op_onebit, 0, pc, length);
253 break;
254 case XC16X_OPERAND_CADDR :
255 print_address (cd, info, fields->f_offset16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
256 break;
257 case XC16X_OPERAND_COND :
258 print_keyword (cd, info, & xc16x_cgen_opval_conditioncode_names, fields->f_condcode, 0);
259 break;
260 case XC16X_OPERAND_DATA8 :
261 print_normal (cd, info, fields->f_data8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
262 break;
263 case XC16X_OPERAND_DATAHI8 :
264 print_normal (cd, info, fields->f_datahi8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
265 break;
266 case XC16X_OPERAND_DOT :
267 print_dot (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
268 break;
269 case XC16X_OPERAND_DR :
270 print_keyword (cd, info, & xc16x_cgen_opval_gr_names, fields->f_r1, 0);
271 break;
272 case XC16X_OPERAND_DRB :
273 print_keyword (cd, info, & xc16x_cgen_opval_grb_names, fields->f_r1, 0);
274 break;
275 case XC16X_OPERAND_DRI :
276 print_keyword (cd, info, & xc16x_cgen_opval_gr_names, fields->f_r4, 0);
277 break;
278 case XC16X_OPERAND_EXTCOND :
279 print_keyword (cd, info, & xc16x_cgen_opval_extconditioncode_names, fields->f_extccode, 0);
280 break;
281 case XC16X_OPERAND_GENREG :
282 print_keyword (cd, info, & xc16x_cgen_opval_r8_names, fields->f_regb8, 0);
283 break;
284 case XC16X_OPERAND_HASH :
285 print_hash (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
286 break;
287 case XC16X_OPERAND_ICOND :
288 print_keyword (cd, info, & xc16x_cgen_opval_conditioncode_names, fields->f_icondcode, 0);
289 break;
290 case XC16X_OPERAND_LBIT2 :
291 print_normal (cd, info, fields->f_op_lbit2, 0, pc, length);
292 break;
293 case XC16X_OPERAND_LBIT4 :
294 print_normal (cd, info, fields->f_op_lbit4, 0, pc, length);
295 break;
296 case XC16X_OPERAND_MASK8 :
297 print_normal (cd, info, fields->f_mask8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
298 break;
299 case XC16X_OPERAND_MASKLO8 :
300 print_normal (cd, info, fields->f_datahi8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
301 break;
302 case XC16X_OPERAND_MEMGR8 :
303 print_keyword (cd, info, & xc16x_cgen_opval_memgr8_names, fields->f_memgr8, 0);
304 break;
305 case XC16X_OPERAND_MEMORY :
306 print_address (cd, info, fields->f_memory, 0, pc, length);
307 break;
308 case XC16X_OPERAND_PAG :
309 print_pag (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
310 break;
311 case XC16X_OPERAND_PAGENUM :
312 print_normal (cd, info, fields->f_pagenum, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
313 break;
314 case XC16X_OPERAND_POF :
315 print_pof (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
316 break;
317 case XC16X_OPERAND_QBIT :
318 print_with_dot_prefix (cd, info, fields->f_qbit, 0|(1<<CGEN_OPERAND_DOT_PREFIX), pc, length);
319 break;
320 case XC16X_OPERAND_QHIBIT :
321 print_with_dot_prefix (cd, info, fields->f_qhibit, 0|(1<<CGEN_OPERAND_DOT_PREFIX), pc, length);
322 break;
323 case XC16X_OPERAND_QLOBIT :
324 print_with_dot_prefix (cd, info, fields->f_qlobit, 0|(1<<CGEN_OPERAND_DOT_PREFIX), pc, length);
325 break;
326 case XC16X_OPERAND_REG8 :
327 print_keyword (cd, info, & xc16x_cgen_opval_r8_names, fields->f_reg8, 0);
328 break;
329 case XC16X_OPERAND_REGB8 :
330 print_keyword (cd, info, & xc16x_cgen_opval_grb8_names, fields->f_regb8, 0);
331 break;
332 case XC16X_OPERAND_REGBMEM8 :
333 print_keyword (cd, info, & xc16x_cgen_opval_regbmem8_names, fields->f_regmem8, 0);
334 break;
335 case XC16X_OPERAND_REGHI8 :
336 print_keyword (cd, info, & xc16x_cgen_opval_r8_names, fields->f_reghi8, 0);
337 break;
338 case XC16X_OPERAND_REGMEM8 :
339 print_keyword (cd, info, & xc16x_cgen_opval_regmem8_names, fields->f_regmem8, 0);
340 break;
341 case XC16X_OPERAND_REGOFF8 :
342 print_keyword (cd, info, & xc16x_cgen_opval_r8_names, fields->f_regoff8, 0);
343 break;
344 case XC16X_OPERAND_REL :
345 print_normal (cd, info, fields->f_rel8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
346 break;
347 case XC16X_OPERAND_RELHI :
348 print_normal (cd, info, fields->f_relhi8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
349 break;
350 case XC16X_OPERAND_SEG :
351 print_normal (cd, info, fields->f_seg8, 0, pc, length);
352 break;
353 case XC16X_OPERAND_SEGHI8 :
354 print_normal (cd, info, fields->f_segnum8, 0, pc, length);
355 break;
356 case XC16X_OPERAND_SEGM :
357 print_seg (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
358 break;
359 case XC16X_OPERAND_SOF :
360 print_sof (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
361 break;
362 case XC16X_OPERAND_SR :
363 print_keyword (cd, info, & xc16x_cgen_opval_gr_names, fields->f_r2, 0);
364 break;
365 case XC16X_OPERAND_SR2 :
366 print_keyword (cd, info, & xc16x_cgen_opval_gr_names, fields->f_r0, 0);
367 break;
368 case XC16X_OPERAND_SRB :
369 print_keyword (cd, info, & xc16x_cgen_opval_grb_names, fields->f_r2, 0);
370 break;
371 case XC16X_OPERAND_SRC1 :
372 print_keyword (cd, info, & xc16x_cgen_opval_gr_names, fields->f_r1, 0);
373 break;
374 case XC16X_OPERAND_SRC2 :
375 print_keyword (cd, info, & xc16x_cgen_opval_gr_names, fields->f_r2, 0);
376 break;
377 case XC16X_OPERAND_SRDIV :
378 print_keyword (cd, info, & xc16x_cgen_opval_regdiv8_names, fields->f_reg8, 0);
379 break;
380 case XC16X_OPERAND_U4 :
381 print_keyword (cd, info, & xc16x_cgen_opval_reg0_name, fields->f_uimm4, 0);
382 break;
383 case XC16X_OPERAND_UIMM16 :
384 print_normal (cd, info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
385 break;
386 case XC16X_OPERAND_UIMM2 :
387 print_keyword (cd, info, & xc16x_cgen_opval_ext_names, fields->f_uimm2, 0|(1<<CGEN_OPERAND_HASH_PREFIX));
388 break;
389 case XC16X_OPERAND_UIMM3 :
390 print_keyword (cd, info, & xc16x_cgen_opval_reg0_name1, fields->f_uimm3, 0|(1<<CGEN_OPERAND_HASH_PREFIX));
391 break;
392 case XC16X_OPERAND_UIMM4 :
393 print_normal (cd, info, fields->f_uimm4, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
394 break;
395 case XC16X_OPERAND_UIMM7 :
396 print_normal (cd, info, fields->f_uimm7, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
397 break;
398 case XC16X_OPERAND_UIMM8 :
399 print_normal (cd, info, fields->f_uimm8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
400 break;
401 case XC16X_OPERAND_UPAG16 :
402 print_with_pag_prefix (cd, info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_PAG_PREFIX), pc, length);
403 break;
404 case XC16X_OPERAND_UPOF16 :
405 print_with_pof_prefix (cd, info, fields->f_memory, 0|(1<<CGEN_OPERAND_POF_PREFIX), pc, length);
406 break;
407 case XC16X_OPERAND_USEG16 :
408 print_normal (cd, info, fields->f_offset16, 0|(1<<CGEN_OPERAND_SEG_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
409 break;
410 case XC16X_OPERAND_USEG8 :
411 print_normal (cd, info, fields->f_seg8, 0|(1<<CGEN_OPERAND_SEG_PREFIX), pc, length);
412 break;
413 case XC16X_OPERAND_USOF16 :
414 print_normal (cd, info, fields->f_offset16, 0|(1<<CGEN_OPERAND_SOF_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
415 break;
416
417 default :
418 /* xgettext:c-format */
419 fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
420 opindex);
421 abort ();
422 }
423}
424
425cgen_print_fn * const xc16x_cgen_print_handlers[] =
426{
427 print_insn_normal,
428};
429
430
431void
432xc16x_cgen_init_dis (CGEN_CPU_DESC cd)
433{
434 xc16x_cgen_init_opcode_table (cd);
435 xc16x_cgen_init_ibld_table (cd);
436 cd->print_handlers = & xc16x_cgen_print_handlers[0];
437 cd->print_operand = xc16x_cgen_print_operand;
438}
439
440\f
441/* Default print handler. */
442
443static void
444print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
445 void *dis_info,
446 long value,
447 unsigned int attrs,
448 bfd_vma pc ATTRIBUTE_UNUSED,
449 int length ATTRIBUTE_UNUSED)
450{
451 disassemble_info *info = (disassemble_info *) dis_info;
452
453 /* Print the operand as directed by the attributes. */
454 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
455 ; /* nothing to do */
456 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
457 (*info->fprintf_func) (info->stream, "%ld", value);
458 else
459 (*info->fprintf_func) (info->stream, "0x%lx", value);
460}
461
462/* Default address handler. */
463
464static void
465print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
466 void *dis_info,
467 bfd_vma value,
468 unsigned int attrs,
469 bfd_vma pc ATTRIBUTE_UNUSED,
470 int length ATTRIBUTE_UNUSED)
471{
472 disassemble_info *info = (disassemble_info *) dis_info;
473
474 /* Print the operand as directed by the attributes. */
475 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
476 ; /* Nothing to do. */
477 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
478 (*info->print_address_func) (value, info);
479 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
480 (*info->print_address_func) (value, info);
481 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
482 (*info->fprintf_func) (info->stream, "%ld", (long) value);
483 else
484 (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
485}
486
487/* Keyword print handler. */
488
489static void
490print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
491 void *dis_info,
492 CGEN_KEYWORD *keyword_table,
493 long value,
494 unsigned int attrs ATTRIBUTE_UNUSED)
495{
496 disassemble_info *info = (disassemble_info *) dis_info;
497 const CGEN_KEYWORD_ENTRY *ke;
498
499 ke = cgen_keyword_lookup_value (keyword_table, value);
500 if (ke != NULL)
501 (*info->fprintf_func) (info->stream, "%s", ke->name);
502 else
503 (*info->fprintf_func) (info->stream, "???");
504}
505\f
506/* Default insn printer.
507
508 DIS_INFO is defined as `void *' so the disassembler needn't know anything
509 about disassemble_info. */
510
511static void
512print_insn_normal (CGEN_CPU_DESC cd,
513 void *dis_info,
514 const CGEN_INSN *insn,
515 CGEN_FIELDS *fields,
516 bfd_vma pc,
517 int length)
518{
519 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
520 disassemble_info *info = (disassemble_info *) dis_info;
521 const CGEN_SYNTAX_CHAR_TYPE *syn;
522
523 CGEN_INIT_PRINT (cd);
524
525 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
526 {
527 if (CGEN_SYNTAX_MNEMONIC_P (*syn))
528 {
529 (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
530 continue;
531 }
532 if (CGEN_SYNTAX_CHAR_P (*syn))
533 {
534 (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
535 continue;
536 }
537
538 /* We have an operand. */
539 xc16x_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
540 fields, CGEN_INSN_ATTRS (insn), pc, length);
541 }
542}
543\f
544/* Subroutine of print_insn. Reads an insn into the given buffers and updates
545 the extract info.
546 Returns 0 if all is well, non-zero otherwise. */
547
548static int
549read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
550 bfd_vma pc,
551 disassemble_info *info,
552 bfd_byte *buf,
553 int buflen,
554 CGEN_EXTRACT_INFO *ex_info,
555 unsigned long *insn_value)
556{
557 int status = (*info->read_memory_func) (pc, buf, buflen, info);
558
559 if (status != 0)
560 {
561 (*info->memory_error_func) (status, pc, info);
562 return -1;
563 }
564
565 ex_info->dis_info = info;
566 ex_info->valid = (1 << buflen) - 1;
567 ex_info->insn_bytes = buf;
568
569 *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
570 return 0;
571}
572
573/* Utility to print an insn.
574 BUF is the base part of the insn, target byte order, BUFLEN bytes long.
575 The result is the size of the insn in bytes or zero for an unknown insn
576 or -1 if an error occurs fetching data (memory_error_func will have
577 been called). */
578
579static int
580print_insn (CGEN_CPU_DESC cd,
581 bfd_vma pc,
582 disassemble_info *info,
583 bfd_byte *buf,
584 unsigned int buflen)
585{
586 CGEN_INSN_INT insn_value;
587 const CGEN_INSN_LIST *insn_list;
588 CGEN_EXTRACT_INFO ex_info;
589 int basesize;
590
591 /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
592 basesize = cd->base_insn_bitsize < buflen * 8 ?
593 cd->base_insn_bitsize : buflen * 8;
594 insn_value = cgen_get_insn_value (cd, buf, basesize);
595
596
597 /* Fill in ex_info fields like read_insn would. Don't actually call
598 read_insn, since the incoming buffer is already read (and possibly
599 modified a la m32r). */
600 ex_info.valid = (1 << buflen) - 1;
601 ex_info.dis_info = info;
602 ex_info.insn_bytes = buf;
603
604 /* The instructions are stored in hash lists.
605 Pick the first one and keep trying until we find the right one. */
606
607 insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
608 while (insn_list != NULL)
609 {
610 const CGEN_INSN *insn = insn_list->insn;
611 CGEN_FIELDS fields;
612 int length;
613 unsigned long insn_value_cropped;
614
615#ifdef CGEN_VALIDATE_INSN_SUPPORTED
616 /* Not needed as insn shouldn't be in hash lists if not supported. */
617 /* Supported by this cpu? */
618 if (! xc16x_cgen_insn_supported (cd, insn))
619 {
620 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
621 continue;
622 }
623#endif
624
625 /* Basic bit mask must be correct. */
626 /* ??? May wish to allow target to defer this check until the extract
627 handler. */
628
629 /* Base size may exceed this instruction's size. Extract the
630 relevant part from the buffer. */
631 if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
632 (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
633 insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
634 info->endian == BFD_ENDIAN_BIG);
635 else
636 insn_value_cropped = insn_value;
637
638 if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
639 == CGEN_INSN_BASE_VALUE (insn))
640 {
641 /* Printing is handled in two passes. The first pass parses the
642 machine insn and extracts the fields. The second pass prints
643 them. */
644
645 /* Make sure the entire insn is loaded into insn_value, if it
646 can fit. */
647 if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
648 (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
649 {
650 unsigned long full_insn_value;
651 int rc = read_insn (cd, pc, info, buf,
652 CGEN_INSN_BITSIZE (insn) / 8,
653 & ex_info, & full_insn_value);
654 if (rc != 0)
655 return rc;
656 length = CGEN_EXTRACT_FN (cd, insn)
657 (cd, insn, &ex_info, full_insn_value, &fields, pc);
658 }
659 else
660 length = CGEN_EXTRACT_FN (cd, insn)
661 (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
662
663 /* Length < 0 -> error. */
664 if (length < 0)
665 return length;
666 if (length > 0)
667 {
668 CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
669 /* Length is in bits, result is in bytes. */
670 return length / 8;
671 }
672 }
673
674 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
675 }
676
677 return 0;
678}
679
680/* Default value for CGEN_PRINT_INSN.
681 The result is the size of the insn in bytes or zero for an unknown insn
682 or -1 if an error occured fetching bytes. */
683
684#ifndef CGEN_PRINT_INSN
685#define CGEN_PRINT_INSN default_print_insn
686#endif
687
688static int
689default_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
690{
691 bfd_byte buf[CGEN_MAX_INSN_SIZE];
692 int buflen;
693 int status;
694
695 /* Attempt to read the base part of the insn. */
696 buflen = cd->base_insn_bitsize / 8;
697 status = (*info->read_memory_func) (pc, buf, buflen, info);
698
699 /* Try again with the minimum part, if min < base. */
700 if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
701 {
702 buflen = cd->min_insn_bitsize / 8;
703 status = (*info->read_memory_func) (pc, buf, buflen, info);
704 }
705
706 if (status != 0)
707 {
708 (*info->memory_error_func) (status, pc, info);
709 return -1;
710 }
711
712 return print_insn (cd, pc, info, buf, buflen);
713}
714
715/* Main entry point.
716 Print one instruction from PC on INFO->STREAM.
717 Return the size of the instruction (in bytes). */
718
719typedef struct cpu_desc_list
720{
721 struct cpu_desc_list *next;
722 CGEN_BITSET *isa;
723 int mach;
724 int endian;
725 CGEN_CPU_DESC cd;
726} cpu_desc_list;
727
728int
729print_insn_xc16x (bfd_vma pc, disassemble_info *info)
730{
731 static cpu_desc_list *cd_list = 0;
732 cpu_desc_list *cl = 0;
733 static CGEN_CPU_DESC cd = 0;
734 static CGEN_BITSET *prev_isa;
735 static int prev_mach;
736 static int prev_endian;
737 int length;
738 CGEN_BITSET *isa;
739 int mach;
740 int endian = (info->endian == BFD_ENDIAN_BIG
741 ? CGEN_ENDIAN_BIG
742 : CGEN_ENDIAN_LITTLE);
743 enum bfd_architecture arch;
744
745 /* ??? gdb will set mach but leave the architecture as "unknown" */
746#ifndef CGEN_BFD_ARCH
747#define CGEN_BFD_ARCH bfd_arch_xc16x
748#endif
749 arch = info->arch;
750 if (arch == bfd_arch_unknown)
751 arch = CGEN_BFD_ARCH;
752
753 /* There's no standard way to compute the machine or isa number
754 so we leave it to the target. */
755#ifdef CGEN_COMPUTE_MACH
756 mach = CGEN_COMPUTE_MACH (info);
757#else
758 mach = info->mach;
759#endif
760
761#ifdef CGEN_COMPUTE_ISA
762 {
763 static CGEN_BITSET *permanent_isa;
764
765 if (!permanent_isa)
766 permanent_isa = cgen_bitset_create (MAX_ISAS);
767 isa = permanent_isa;
768 cgen_bitset_clear (isa);
769 cgen_bitset_add (isa, CGEN_COMPUTE_ISA (info));
770 }
771#else
772 isa = info->insn_sets;
773#endif
774
775 /* If we've switched cpu's, try to find a handle we've used before */
776 if (cd
777 && (cgen_bitset_compare (isa, prev_isa) != 0
778 || mach != prev_mach
779 || endian != prev_endian))
780 {
781 cd = 0;
782 for (cl = cd_list; cl; cl = cl->next)
783 {
784 if (cgen_bitset_compare (cl->isa, isa) == 0 &&
785 cl->mach == mach &&
786 cl->endian == endian)
787 {
788 cd = cl->cd;
789 prev_isa = cd->isas;
790 break;
791 }
792 }
793 }
794
795 /* If we haven't initialized yet, initialize the opcode table. */
796 if (! cd)
797 {
798 const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
799 const char *mach_name;
800
801 if (!arch_type)
802 abort ();
803 mach_name = arch_type->printable_name;
804
805 prev_isa = cgen_bitset_copy (isa);
806 prev_mach = mach;
807 prev_endian = endian;
808 cd = xc16x_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
809 CGEN_CPU_OPEN_BFDMACH, mach_name,
810 CGEN_CPU_OPEN_ENDIAN, prev_endian,
811 CGEN_CPU_OPEN_END);
812 if (!cd)
813 abort ();
814
815 /* Save this away for future reference. */
816 cl = xmalloc (sizeof (struct cpu_desc_list));
817 cl->cd = cd;
818 cl->isa = prev_isa;
819 cl->mach = mach;
820 cl->endian = endian;
821 cl->next = cd_list;
822 cd_list = cl;
823
824 xc16x_cgen_init_dis (cd);
825 }
826
827 /* We try to have as much common code as possible.
828 But at this point some targets need to take over. */
829 /* ??? Some targets may need a hook elsewhere. Try to avoid this,
830 but if not possible try to move this hook elsewhere rather than
831 have two hooks. */
832 length = CGEN_PRINT_INSN (cd, pc, info);
833 if (length > 0)
834 return length;
835 if (length < 0)
836 return -1;
837
838 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
839 return cd->default_insn_bitsize / 8;
840}
This page took 0.024718 seconds and 4 git commands to generate.