S12Z: Make disassebler work for --enable-targets=all config.
[external/binutils.git] / opcodes / or1k-dis.c
1 /* DO NOT EDIT!  -*- buffer-read-only: t -*- vi:set ro:  */
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
8    Copyright (C) 1996-2018 Free Software Foundation, Inc.
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"
32 #include "disassemble.h"
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 \f
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 */
141       opcodes_error_handler
142         (_("internal error: unrecognized field %d while printing insn"),
143          opindex);
144       abort ();
145   }
146 }
147
148 cgen_print_fn * const or1k_cgen_print_handlers[] =
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 \f
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 \f
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 \f
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
338 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
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))
356         insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
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;
475
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         }
516     }
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 }