Thu Nov 12 19:24:18 1998 Dave Brolley <brolley@cygnus.com>
[platform/upstream/binutils.git] / opcodes / fr30-dis.c
1 /* Disassembler interface for targets using CGEN. -*- C -*-
2    CGEN: Cpu tools GENerator
3
4 THIS FILE IS USED TO GENERATE fr30-dis.c.
5
6 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
7
8 This file is part of the GNU Binutils and GDB, the GNU debugger.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software Foundation, Inc.,
22 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
23
24 #include "sysdep.h"
25 #include <stdio.h>
26 #include "ansidecl.h"
27 #include "dis-asm.h"
28 #include "bfd.h"
29 #include "symcat.h"
30 #include "fr30-opc.h"
31 #include "opintl.h"
32
33 #undef INLINE
34 #ifdef __GNUC__
35 #define INLINE __inline__
36 #else
37 #define INLINE
38 #endif
39
40 /* Default text to print if an instruction isn't recognized.  */
41 #define UNKNOWN_INSN_MSG _("*unknown*")
42
43 static int extract_normal
44      PARAMS ((CGEN_OPCODE_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_BYTES,
45               unsigned int, int, int, int, long *));
46 static void print_normal
47      PARAMS ((CGEN_OPCODE_DESC, PTR, long, unsigned int, bfd_vma, int));
48 static void print_address
49      PARAMS ((CGEN_OPCODE_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int));
50 static void print_keyword
51      PARAMS ((CGEN_OPCODE_DESC, PTR, CGEN_KEYWORD *, long, unsigned int));
52 static int extract_insn_normal
53      PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
54               unsigned long, CGEN_FIELDS *, bfd_vma));
55 static void print_insn_normal
56      PARAMS ((CGEN_OPCODE_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *,
57               bfd_vma, int));
58 static int print_insn PARAMS ((CGEN_OPCODE_DESC, bfd_vma,
59                                disassemble_info *, char *, int));
60 static int default_print_insn
61      PARAMS ((CGEN_OPCODE_DESC, bfd_vma, disassemble_info *));
62 \f
63 /* -- disassembler routines inserted here */
64
65 /* Main entry point for operand extraction.
66
67    This function is basically just a big switch statement.  Earlier versions
68    used tables to look up the function to use, but
69    - if the table contains both assembler and disassembler functions then
70      the disassembler contains much of the assembler and vice-versa,
71    - there's a lot of inlining possibilities as things grow,
72    - using a switch statement avoids the function call overhead.
73
74    This function could be moved into `print_insn_normal', but keeping it
75    separate makes clear the interface between `print_insn_normal' and each of
76    the handlers.
77 */
78
79 int
80 fr30_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc)
81      CGEN_OPCODE_DESC od;
82      int opindex;
83      CGEN_EXTRACT_INFO *ex_info;
84      CGEN_INSN_BYTES insn_value;
85      CGEN_FIELDS * fields;
86      bfd_vma pc;
87 {
88   int length;
89
90   switch (opindex)
91     {
92     case FR30_OPERAND_RI :
93       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_Ri);
94       break;
95     case FR30_OPERAND_RJ :
96       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_Rj);
97       break;
98     case FR30_OPERAND_RS1 :
99       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_Rs1);
100       break;
101     case FR30_OPERAND_RS2 :
102       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_Rs2);
103       break;
104     case FR30_OPERAND_U4 :
105       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_u4);
106       break;
107     case FR30_OPERAND_M4 :
108       {
109         long value;
110         length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 4, CGEN_FIELDS_BITSIZE (fields), & value);
111         value = ((value) | ((! (15))));
112         fields->f_m4 = value;
113       }
114       break;
115     case FR30_OPERAND_I8 :
116       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), & fields->f_i8);
117       break;
118     case FR30_OPERAND_U8 :
119       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), & fields->f_u8);
120       break;
121     case FR30_OPERAND_O8 :
122       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 4, 8, CGEN_FIELDS_BITSIZE (fields), & fields->f_o8);
123       break;
124     case FR30_OPERAND_S10 :
125       {
126         long value;
127         length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), & value);
128         value = ((value) << (2));
129         fields->f_s10 = value;
130       }
131       break;
132     case FR30_OPERAND_U10 :
133       {
134         long value;
135         length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), & value);
136         value = ((value) << (2));
137         fields->f_u10 = value;
138       }
139       break;
140     case FR30_OPERAND_DIR8 :
141       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), & fields->f_dir8);
142       break;
143     case FR30_OPERAND_DIR9 :
144       {
145         long value;
146         length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), & value);
147         value = ((value) << (1));
148         fields->f_dir9 = value;
149       }
150       break;
151     case FR30_OPERAND_DIR10 :
152       {
153         long value;
154         length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), & value);
155         value = ((value) << (2));
156         fields->f_dir10 = value;
157       }
158       break;
159     case FR30_OPERAND_LABEL9 :
160       {
161         long value;
162         length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_SIGNED), 8, 8, CGEN_FIELDS_BITSIZE (fields), & value);
163         value = ((value) << (1));
164         fields->f_rel8 = value;
165       }
166       break;
167     case FR30_OPERAND_LABEL12 :
168       {
169         long value;
170         length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_SIGNED), 5, 11, CGEN_FIELDS_BITSIZE (fields), & value);
171         value = ((value) << (1));
172         fields->f_rel11 = value;
173       }
174       break;
175     case FR30_OPERAND_CC :
176       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_cc);
177       break;
178
179     default :
180       /* xgettext:c-format */
181       fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
182                opindex);
183       abort ();
184     }
185
186   return length;
187 }
188
189 /* Main entry point for printing operands.
190
191    This function is basically just a big switch statement.  Earlier versions
192    used tables to look up the function to use, but
193    - if the table contains both assembler and disassembler functions then
194      the disassembler contains much of the assembler and vice-versa,
195    - there's a lot of inlining possibilities as things grow,
196    - using a switch statement avoids the function call overhead.
197
198    This function could be moved into `print_insn_normal', but keeping it
199    separate makes clear the interface between `print_insn_normal' and each of
200    the handlers.
201 */
202
203 void
204 fr30_cgen_print_operand (od, opindex, info, fields, attrs, pc, length)
205      CGEN_OPCODE_DESC od;
206      int opindex;
207      disassemble_info * info;
208      CGEN_FIELDS * fields;
209      void const * attrs;
210      bfd_vma pc;
211      int length;
212 {
213   switch (opindex)
214     {
215     case FR30_OPERAND_RI :
216       print_keyword (od, info, & fr30_cgen_opval_h_gr, fields->f_Ri, 0|(1<<CGEN_OPERAND_UNSIGNED));
217       break;
218     case FR30_OPERAND_RJ :
219       print_keyword (od, info, & fr30_cgen_opval_h_gr, fields->f_Rj, 0|(1<<CGEN_OPERAND_UNSIGNED));
220       break;
221     case FR30_OPERAND_RS1 :
222       print_keyword (od, info, & fr30_cgen_opval_h_dr, fields->f_Rs1, 0|(1<<CGEN_OPERAND_UNSIGNED));
223       break;
224     case FR30_OPERAND_RS2 :
225       print_keyword (od, info, & fr30_cgen_opval_h_dr, fields->f_Rs2, 0|(1<<CGEN_OPERAND_UNSIGNED));
226       break;
227     case FR30_OPERAND_U4 :
228       print_normal (od, info, fields->f_u4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
229       break;
230     case FR30_OPERAND_M4 :
231       print_normal (od, info, fields->f_m4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
232       break;
233     case FR30_OPERAND_I8 :
234       print_normal (od, info, fields->f_i8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
235       break;
236     case FR30_OPERAND_U8 :
237       print_normal (od, info, fields->f_u8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
238       break;
239     case FR30_OPERAND_O8 :
240       print_normal (od, info, fields->f_o8, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
241       break;
242     case FR30_OPERAND_S10 :
243       print_normal (od, info, fields->f_s10, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGNED), pc, length);
244       break;
245     case FR30_OPERAND_U10 :
246       print_normal (od, info, fields->f_u10, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
247       break;
248     case FR30_OPERAND_DIR8 :
249       print_normal (od, info, fields->f_dir8, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
250       break;
251     case FR30_OPERAND_DIR9 :
252       print_normal (od, info, fields->f_dir9, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
253       break;
254     case FR30_OPERAND_DIR10 :
255       print_normal (od, info, fields->f_dir10, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
256       break;
257     case FR30_OPERAND_LABEL9 :
258       print_normal (od, info, fields->f_rel8, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
259       break;
260     case FR30_OPERAND_LABEL12 :
261       print_normal (od, info, fields->f_rel11, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
262       break;
263     case FR30_OPERAND_CC :
264       print_normal (od, info, fields->f_cc, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
265       break;
266
267     default :
268       /* xgettext:c-format */
269       fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
270                opindex);
271     abort ();
272   }
273 }
274
275 cgen_extract_fn * const fr30_cgen_extract_handlers[] = 
276 {
277   0, /* default */
278   extract_insn_normal,
279 };
280
281 cgen_print_fn * const fr30_cgen_print_handlers[] = 
282 {
283   0, /* default */
284   print_insn_normal,
285 };
286
287
288 void
289 fr30_cgen_init_dis (od)
290      CGEN_OPCODE_DESC od;
291 {
292 }
293
294 \f
295 #if ! CGEN_INT_INSN_P
296
297 /* Subroutine of extract_normal.  */
298
299 static INLINE long
300 extract_1 (od, ex_info, start, length, word_length, bufp)
301      CGEN_OPCODE_DESC od;
302      CGEN_EXTRACT_INFO *info;
303      int start,length,word_length;
304      unsigned char *bufp;
305 {
306   unsigned long x,mask;
307   int shift;
308   int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
309
310   /* FIXME: Need to use ex_info to ensure bytes have been fetched.  */
311
312   switch (word_length)
313     {
314     case 8:
315       x = *bufp;
316       break;
317     case 16:
318       if (big_p)
319         x = bfd_getb16 (bufp);
320       else
321         x = bfd_getl16 (bufp);
322       break;
323     case 24:
324       /* ??? This may need reworking as these cases don't necessarily
325          want the first byte and the last two bytes handled like this.  */
326       if (big_p)
327         x = (bfd_getb8 (bufp) << 16) | bfd_getb16 (bufp + 1);
328       else
329         x = bfd_getl16 (bufp) | (bfd_getb8 (bufp + 2) << 16);
330       break;
331     case 32:
332       if (big_p)
333         x = bfd_getb32 (bufp);
334       else
335         x = bfd_getl32 (bufp);
336       break;
337     default :
338       abort ();
339     }
340
341   /* Written this way to avoid undefined behaviour.  */
342   mask = (((1L << (length - 1)) - 1) << 1) | 1;
343   if (CGEN_INSN_LSB0_P)
344     shift = start;
345   else
346     shift = (word_length - (start + length));
347   return (x >> shift) & mask;
348 }
349
350 #endif /* ! CGEN_INT_INSN_P */
351
352 /* Default extraction routine.
353
354    ATTRS is a mask of the boolean attributes.  We only need `unsigned',
355    but for generality we take a bitmask of all of them.  */
356
357 /* ??? This doesn't handle bfd_vma's.  Create another function when
358    necessary.  */
359
360 static int
361 extract_normal (od, ex_info, insn_value, attrs, start, length, total_length, valuep)
362      CGEN_OPCODE_DESC od;
363      CGEN_EXTRACT_INFO *ex_info;
364      CGEN_INSN_BYTES insn_value;
365      unsigned int attrs;
366      int start, length, total_length;
367      long *valuep;
368 {
369   unsigned long value;
370
371   /* If LENGTH is zero, this operand doesn't contribute to the value
372      so give it a standard value of zero.  */
373   if (length == 0)
374     {
375       *valuep = 0;
376       return 1;
377     }
378
379 #if CGEN_INT_INSN_P
380
381   {
382     /* Written this way to avoid undefined behaviour.  */
383     unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
384
385     if (CGEN_INSN_LSB0_P)
386       value = insn_value >> start;
387     else
388       value = insn_value >> (total_length - (start + length));
389     value &= mask;
390     /* sign extend? */
391     if (! (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED))
392         && (value & (1L << (length - 1))))
393       value |= ~mask;
394   }
395
396 #else
397
398   /* The hard case is probably too slow for the normal cases.
399      It's certainly more difficult to understand than the normal case.
400      Thus this is split into two.  Keep it that way.  The hard case is defined
401      to be when a field straddles a (loosely defined) word boundary
402      (??? which may require target specific help to determine).  */
403
404 #if 0 /*wip*/
405
406 #define HARD_CASE_P 0 /* FIXME:wip */
407
408   if (HARD_CASE_P)
409     {
410     }
411 #endif
412   else
413     {
414       unsigned char *bufp = (unsigned char *) insn_value;
415
416       if (length > 32)
417         abort ();
418
419       /* Adjust start,total_length,bufp to point to the pseudo-word that holds
420          the value.  For example in a 48 bit insn where the value to insert
421          (say an immediate value) is the last 16 bits then word_length here
422          would be 16.  To handle a 24 bit insn with an 18 bit immediate,
423          extract_1 handles 24 bits (using a combination of bfd_get8,16).  */
424
425       if (total_length > 32)
426         {
427           int needed_width = start % 8 + length;
428           int fetch_length = (needed_width <= 8 ? 8
429                               : needed_width <= 16 ? 16
430                               : 32);
431
432           if (CGEN_INSN_LSB0_P)
433             {
434               if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
435                 {
436                   abort (); /* wip */
437                 }
438               else
439                 {
440                   int offset = start & ~7;
441
442                   bufp += offset / 8;
443                   start -= offset;
444                   total_length -= offset;
445                 }
446             }
447           else
448             {
449               if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
450                 {
451                   int offset = start & ~7;
452
453                   bufp += offset / 8;
454                   start -= offset;
455                   total_length -= offset;
456                 }
457               else
458                 {
459                   abort (); /* wip */
460                 }
461             }
462         }
463
464       /* FIXME: which bytes are being extracted have been lost.  */
465       value = extract_1 (od, ex_info, start, length, total_length, bufp);
466     }
467
468 #endif /* ! CGEN_INT_INSN_P */
469
470   *valuep = value;
471
472   /* FIXME: for now */
473   return 1;
474 }
475
476 /* Default print handler.  */
477
478 static void
479 print_normal (od, dis_info, value, attrs, pc, length)
480      CGEN_OPCODE_DESC od;
481      PTR dis_info;
482      long value;
483      unsigned int attrs;
484      bfd_vma pc;
485      int length;
486 {
487   disassemble_info *info = (disassemble_info *) dis_info;
488
489 #ifdef CGEN_PRINT_NORMAL
490   CGEN_PRINT_NORMAL (od, info, value, attrs, pc, length);
491 #endif
492
493   /* Print the operand as directed by the attributes.  */
494   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
495     ; /* nothing to do */
496   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
497     (*info->fprintf_func) (info->stream, "0x%lx", value);
498   else
499     (*info->fprintf_func) (info->stream, "%ld", value);
500 }
501
502 /* Default address handler.  */
503
504 static void
505 print_address (od, dis_info, value, attrs, pc, length)
506      CGEN_OPCODE_DESC od;
507      PTR dis_info;
508      bfd_vma value;
509      unsigned int attrs;
510      bfd_vma pc;
511      int length;
512 {
513   disassemble_info *info = (disassemble_info *) dis_info;
514
515 #ifdef CGEN_PRINT_ADDRESS
516   CGEN_PRINT_ADDRESS (od, info, value, attrs, pc, length);
517 #endif
518
519   /* Print the operand as directed by the attributes.  */
520   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
521     ; /* nothing to do */
522   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
523     (*info->print_address_func) (value, info);
524   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
525     (*info->print_address_func) (value, info);
526   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
527     (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
528   else
529     (*info->fprintf_func) (info->stream, "%ld", (long) value);
530 }
531
532 /* Keyword print handler.  */
533
534 static void
535 print_keyword (od, dis_info, keyword_table, value, attrs)
536      CGEN_OPCODE_DESC od;
537      PTR dis_info;
538      CGEN_KEYWORD *keyword_table;
539      long value;
540      unsigned int attrs;
541 {
542   disassemble_info *info = (disassemble_info *) dis_info;
543   const CGEN_KEYWORD_ENTRY *ke;
544
545   ke = cgen_keyword_lookup_value (keyword_table, value);
546   if (ke != NULL)
547     (*info->fprintf_func) (info->stream, "%s", ke->name);
548   else
549     (*info->fprintf_func) (info->stream, "???");
550 }
551 \f
552 /* Default insn extractor.
553
554    INSN_VALUE is the first CGEN_BASE_INSN_SIZE bytes, translated to host order.
555    The extracted fields are stored in FIELDS.
556    EX_INFO is used to handle reading variable length insns.
557    Return the length of the insn in bits, or 0 if no match,
558    or -1 if an error occurs fetching data (memory_error_func will have
559    been called).  */
560
561 static int
562 extract_insn_normal (od, insn, ex_info, insn_value, fields, pc)
563      CGEN_OPCODE_DESC od;
564      const CGEN_INSN *insn;
565      CGEN_EXTRACT_INFO *ex_info;
566      unsigned long insn_value;
567      CGEN_FIELDS *fields;
568      bfd_vma pc;
569 {
570   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
571   const unsigned char *syn;
572
573   CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
574
575   CGEN_INIT_EXTRACT (od);
576
577   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
578     {
579       int length;
580
581       if (CGEN_SYNTAX_CHAR_P (*syn))
582         continue;
583
584       length = fr30_cgen_extract_operand (od, CGEN_SYNTAX_FIELD (*syn),
585                                             ex_info, insn_value, fields, pc);
586       if (length <= 0)
587         return length;
588     }
589
590   /* We recognized and successfully extracted this insn.  */
591   return CGEN_INSN_BITSIZE (insn);
592 }
593
594 /* Default insn printer.
595
596    DIS_INFO is defined as `PTR' so the disassembler needn't know anything
597    about disassemble_info.  */
598
599 static void
600 print_insn_normal (od, dis_info, insn, fields, pc, length)
601      CGEN_OPCODE_DESC od;
602      PTR dis_info;
603      const CGEN_INSN *insn;
604      CGEN_FIELDS *fields;
605      bfd_vma pc;
606      int length;
607 {
608   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
609   disassemble_info *info = (disassemble_info *) dis_info;
610   const unsigned char *syn;
611
612   CGEN_INIT_PRINT (od);
613
614   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
615     {
616       if (CGEN_SYNTAX_MNEMONIC_P (*syn))
617         {
618           (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
619           continue;
620         }
621       if (CGEN_SYNTAX_CHAR_P (*syn))
622         {
623           (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
624           continue;
625         }
626
627       /* We have an operand.  */
628       fr30_cgen_print_operand (od, CGEN_SYNTAX_FIELD (*syn), info,
629                                  fields, CGEN_INSN_ATTRS (insn), pc, length);
630     }
631 }
632 \f
633 /* Utility to print an insn.
634    BUF is the base part of the insn, target byte order, BUFLEN bytes long.
635    The result is the size of the insn in bytes or zero for an unknown insn
636    or -1 if an error occurs fetching data (memory_error_func will have
637    been called).  */
638
639 static int
640 print_insn (od, pc, info, buf, buflen)
641      CGEN_OPCODE_DESC od;
642      bfd_vma pc;
643      disassemble_info *info;
644      char *buf;
645      int buflen;
646 {
647   unsigned long insn_value;
648   const CGEN_INSN_LIST *insn_list;
649   CGEN_EXTRACT_INFO ex_info;
650
651   ex_info.dis_info = info;
652   ex_info.valid = (1 << CGEN_BASE_INSN_SIZE) - 1;
653   ex_info.bytes = buf;
654
655   switch (buflen)
656     {
657     case 1:
658       insn_value = buf[0];
659       break;
660     case 2:
661       insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf);
662       break;
663     case 4:
664       insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf);
665       break;
666     default:
667       abort ();
668     }
669
670   /* The instructions are stored in hash lists.
671      Pick the first one and keep trying until we find the right one.  */
672
673   insn_list = CGEN_DIS_LOOKUP_INSN (od, buf, insn_value);
674   while (insn_list != NULL)
675     {
676       const CGEN_INSN *insn = insn_list->insn;
677       CGEN_FIELDS fields;
678       int length;
679
680 #if 0 /* not needed as insn shouldn't be in hash lists if not supported */
681       /* Supported by this cpu?  */
682       if (! fr30_cgen_insn_supported (od, insn))
683         continue;
684 #endif
685
686       /* Basic bit mask must be correct.  */
687       /* ??? May wish to allow target to defer this check until the extract
688          handler.  */
689       if ((insn_value & CGEN_INSN_MASK (insn)) == CGEN_INSN_VALUE (insn))
690         {
691           /* Printing is handled in two passes.  The first pass parses the
692              machine insn and extracts the fields.  The second pass prints
693              them.  */
694
695           length = (*CGEN_EXTRACT_FN (insn)) (od, insn, &ex_info, insn_value,
696                                               &fields, pc);
697           /* length < 0 -> error */
698           if (length < 0)
699             return length;
700           if (length > 0)
701             {
702               (*CGEN_PRINT_FN (insn)) (od, info, insn, &fields, pc, length);
703               /* length is in bits, result is in bytes */
704               return length / 8;
705             }
706         }
707
708       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
709     }
710
711   return 0;
712 }
713
714 /* Default value for CGEN_PRINT_INSN.
715    The result is the size of the insn in bytes or zero for an unknown insn
716    or -1 if an error occured fetching bytes.  */
717
718 #ifndef CGEN_PRINT_INSN
719 #define CGEN_PRINT_INSN default_print_insn
720 #endif
721
722 static int
723 default_print_insn (od, pc, info)
724      CGEN_OPCODE_DESC od;
725      bfd_vma pc;
726      disassemble_info *info;
727 {
728   char buf[CGEN_MAX_INSN_SIZE];
729   int status;
730
731   /* Read the base part of the insn.  */
732
733   status = (*info->read_memory_func) (pc, buf, CGEN_BASE_INSN_SIZE, info);
734   if (status != 0)
735     {
736       (*info->memory_error_func) (status, pc, info);
737       return -1;
738     }
739
740   return print_insn (od, pc, info, buf, CGEN_BASE_INSN_SIZE);
741 }
742
743 /* Main entry point.
744    Print one instruction from PC on INFO->STREAM.
745    Return the size of the instruction (in bytes).  */
746
747 int
748 print_insn_fr30 (pc, info)
749      bfd_vma pc;
750      disassemble_info *info;
751 {
752   int length;
753   static CGEN_OPCODE_DESC od = 0;
754   int mach = info->mach;
755   int big_p = info->endian == BFD_ENDIAN_BIG;
756
757   /* If we haven't initialized yet, initialize the opcode table.  */
758   if (! od)
759     {
760       od = fr30_cgen_opcode_open (mach,
761                                     big_p ?
762                                     CGEN_ENDIAN_BIG
763                                     : CGEN_ENDIAN_LITTLE);
764       fr30_cgen_init_dis (od);
765     }
766   /* If we've switched cpu's, re-initialize.  */
767   /* ??? Perhaps we should use BFD_ENDIAN.  */
768   else if (mach != CGEN_OPCODE_MACH (od)
769            || (CGEN_OPCODE_ENDIAN (od)
770                != (big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE)))
771     {
772       cgen_set_cpu (od, mach, big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE);
773     }
774
775   /* We try to have as much common code as possible.
776      But at this point some targets need to take over.  */
777   /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
778      but if not possible try to move this hook elsewhere rather than
779      have two hooks.  */
780   length = CGEN_PRINT_INSN (od, pc, info);
781   if (length > 0)
782     return length;
783   if (length < 0)
784     return -1;
785
786   (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
787   return CGEN_DEFAULT_INSN_SIZE;
788 }