* m32r-opc.h,m32r-opc.c,m32r-asm.c,m32r-dis.c: Regenerate.
[external/binutils.git] / opcodes / m32r-dis.c
1 /* Disassembler interface for targets using CGEN. -*- C -*-
2    CGEN: Cpu tools GENerator
3
4 This file is used to generate m32r-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
22 Foundation, Inc., 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 "m32r-opc.h"
31
32 /* ??? The layout of this stuff is still work in progress.
33    For speed in assembly/disassembly, we use inline functions.  That of course
34    will only work for GCC.  When this stuff is finished, we can decide whether
35    to keep the inline functions (and only get the performance increase when
36    compiled with GCC), or switch to macros, or use something else.
37 */
38
39 /* Default text to print if an instruction isn't recognized.  */
40 #define UNKNOWN_INSN_MSG "*unknown*"
41
42 /* FIXME: Machine generate.  */
43 #ifndef CGEN_PCREL_OFFSET
44 #define CGEN_PCREL_OFFSET 0
45 #endif
46
47 static int print_insn PARAMS ((bfd_vma, disassemble_info *, char *, int));
48
49 static int extract_normal
50      PARAMS ((PTR, cgen_insn_t, unsigned int, int, int, int, long *));
51 static void print_normal
52      PARAMS ((PTR, long, unsigned int, unsigned long, int));
53 static void print_keyword
54      PARAMS ((PTR, CGEN_KEYWORD *, long, unsigned int));
55 static int extract_insn_normal
56      PARAMS ((const CGEN_INSN *, void *, cgen_insn_t, CGEN_FIELDS *));
57 static void print_insn_normal
58      PARAMS ((void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int));
59 \f
60 /* -- disassembler routines inserted here */
61 /* -- dis.c */
62
63 /* Immediate values are prefixed with '#'.  */
64
65 #define CGEN_PRINT_NORMAL(info, value, attrs, pc, length) \
66 do { \
67   if ((attrs) & (1 << CGEN_OPERAND_HASH_PREFIX)) \
68     (*info->fprintf_func) (info->stream, "#"); \
69 } while (0)
70
71 /* Handle '#' prefixes as operands.  */
72
73 static void
74 print_hash (dis_info, value, attrs, pc, length)
75      PTR dis_info;
76      long value;
77      unsigned int attrs;
78      unsigned long pc; /* FIXME: should be bfd_vma */
79      int length;
80 {
81   disassemble_info *info = dis_info;
82   (*info->fprintf_func) (info->stream, "#");
83 }
84
85 #undef CGEN_PRINT_INSN
86 #define CGEN_PRINT_INSN my_print_insn
87
88 static int
89 my_print_insn (pc, info, buf, buflen)
90      bfd_vma pc;
91      disassemble_info *info;
92      char *buf;
93      int buflen;
94 {
95   /* 32 bit insn?  */
96   if ((pc & 3) == 0 && (buf[0] & 0x80) != 0)
97     return print_insn (pc, info, buf, buflen);
98
99   /* Print the first insn.  */
100   if ((pc & 3) == 0)
101     {
102       if (print_insn (pc, info, buf, 16) == 0)
103         (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
104       buf += 2;
105     }
106
107   if (buf[0] & 0x80)
108     {
109       /* Parallel.  */
110       (*info->fprintf_func) (info->stream, " || ");
111       buf[0] &= 0x7f;
112     }
113   else
114     (*info->fprintf_func) (info->stream, " -> ");
115
116   /* The "& 3" is to ensure the branch address is computed correctly
117      [if it is a branch].  */
118   if (print_insn (pc & ~ (bfd_vma) 3, info, buf, 16) == 0)
119     (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
120
121   return (pc & 3) ? 2 : 4;
122 }
123
124 /* -- */
125
126 /* Main entry point for operand extraction.
127
128    This function is basically just a big switch statement.  Earlier versions
129    used tables to look up the function to use, but
130    - if the table contains both assembler and disassembler functions then
131      the disassembler contains much of the assembler and vice-versa,
132    - there's a lot of inlining possibilities as things grow,
133    - using a switch statement avoids the function call overhead.
134
135    This function could be moved into `print_insn_normal', but keeping it
136    separate makes clear the interface between `print_insn_normal' and each of
137    the handlers.
138 */
139
140 int
141 m32r_cgen_extract_operand (opindex, buf_ctrl, insn_value, fields)
142      int opindex;
143      PTR buf_ctrl;
144      cgen_insn_t insn_value;
145      CGEN_FIELDS * fields;
146 {
147   int length;
148
149   switch (opindex)
150     {
151     case M32R_OPERAND_SR :
152       length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_r2);
153       break;
154     case M32R_OPERAND_DR :
155       length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_r1);
156       break;
157     case M32R_OPERAND_SRC1 :
158       length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_r1);
159       break;
160     case M32R_OPERAND_SRC2 :
161       length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_r2);
162       break;
163     case M32R_OPERAND_SCR :
164       length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_r2);
165       break;
166     case M32R_OPERAND_DCR :
167       length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_r1);
168       break;
169     case M32R_OPERAND_SIMM8 :
170       length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 8, 8, CGEN_FIELDS_BITSIZE (fields), & fields->f_simm8);
171       break;
172     case M32R_OPERAND_SIMM16 :
173       length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 16, 16, CGEN_FIELDS_BITSIZE (fields), & fields->f_simm16);
174       break;
175     case M32R_OPERAND_UIMM4 :
176       length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm4);
177       break;
178     case M32R_OPERAND_UIMM5 :
179       length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 11, 5, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm5);
180       break;
181     case M32R_OPERAND_UIMM16 :
182       length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm16);
183       break;
184 /* start-sanitize-m32rx */
185     case M32R_OPERAND_IMM1 :
186       {
187         long value;
188         length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 15, 1, CGEN_FIELDS_BITSIZE (fields), & value);
189         fields->f_imm1 = ((value) + (1));
190       }
191       break;
192 /* end-sanitize-m32rx */
193 /* start-sanitize-m32rx */
194     case M32R_OPERAND_ACCD :
195       length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 2, CGEN_FIELDS_BITSIZE (fields), & fields->f_accd);
196       break;
197 /* end-sanitize-m32rx */
198 /* start-sanitize-m32rx */
199     case M32R_OPERAND_ACCS :
200       length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 2, CGEN_FIELDS_BITSIZE (fields), & fields->f_accs);
201       break;
202 /* end-sanitize-m32rx */
203 /* start-sanitize-m32rx */
204     case M32R_OPERAND_ACC :
205       length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 1, CGEN_FIELDS_BITSIZE (fields), & fields->f_acc);
206       break;
207 /* end-sanitize-m32rx */
208     case M32R_OPERAND_HASH :
209       length = extract_normal (NULL /*FIXME*/, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_nil);
210       break;
211     case M32R_OPERAND_HI16 :
212       length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, CGEN_FIELDS_BITSIZE (fields), & fields->f_hi16);
213       break;
214     case M32R_OPERAND_SLO16 :
215       length = extract_normal (NULL /*FIXME*/, insn_value, 0, 16, 16, CGEN_FIELDS_BITSIZE (fields), & fields->f_simm16);
216       break;
217     case M32R_OPERAND_ULO16 :
218       length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm16);
219       break;
220     case M32R_OPERAND_UIMM24 :
221       length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), 8, 24, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm24);
222       break;
223     case M32R_OPERAND_DISP8 :
224       {
225         long value;
226         length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 8, CGEN_FIELDS_BITSIZE (fields), & value);
227         fields->f_disp8 = ((value) << (2));
228       }
229       break;
230     case M32R_OPERAND_DISP16 :
231       {
232         long value;
233         length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 16, 16, CGEN_FIELDS_BITSIZE (fields), & value);
234         fields->f_disp16 = ((value) << (2));
235       }
236       break;
237     case M32R_OPERAND_DISP24 :
238       {
239         long value;
240         length = extract_normal (NULL /*FIXME*/, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 24, CGEN_FIELDS_BITSIZE (fields), & value);
241         fields->f_disp24 = ((value) << (2));
242       }
243       break;
244
245     default :
246       fprintf (stderr, "Unrecognized field %d while decoding insn.\n",
247                opindex);
248       abort ();
249     }
250
251   return length;
252 }
253
254 /* Main entry point for printing operands.
255
256    This function is basically just a big switch statement.  Earlier versions
257    used tables to look up the function to use, but
258    - if the table contains both assembler and disassembler functions then
259      the disassembler contains much of the assembler and vice-versa,
260    - there's a lot of inlining possibilities as things grow,
261    - using a switch statement avoids the function call overhead.
262
263    This function could be moved into `print_insn_normal', but keeping it
264    separate makes clear the interface between `print_insn_normal' and each of
265    the handlers.
266 */
267
268 void
269 m32r_cgen_print_operand (opindex, info, fields, attrs, pc, length)
270      int opindex;
271      disassemble_info * info;
272      CGEN_FIELDS * fields;
273      void const * attrs;
274      bfd_vma pc;
275      int length;
276 {
277   switch (opindex)
278     {
279     case M32R_OPERAND_SR :
280       print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
281       break;
282     case M32R_OPERAND_DR :
283       print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
284       break;
285     case M32R_OPERAND_SRC1 :
286       print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
287       break;
288     case M32R_OPERAND_SRC2 :
289       print_keyword (info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
290       break;
291     case M32R_OPERAND_SCR :
292       print_keyword (info, & m32r_cgen_opval_h_cr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
293       break;
294     case M32R_OPERAND_DCR :
295       print_keyword (info, & m32r_cgen_opval_h_cr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
296       break;
297     case M32R_OPERAND_SIMM8 :
298       print_normal (info, fields->f_simm8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
299       break;
300     case M32R_OPERAND_SIMM16 :
301       print_normal (info, fields->f_simm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
302       break;
303     case M32R_OPERAND_UIMM4 :
304       print_normal (info, fields->f_uimm4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
305       break;
306     case M32R_OPERAND_UIMM5 :
307       print_normal (info, fields->f_uimm5, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
308       break;
309     case M32R_OPERAND_UIMM16 :
310       print_normal (info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
311       break;
312 /* start-sanitize-m32rx */
313     case M32R_OPERAND_IMM1 :
314       print_normal (info, fields->f_imm1, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
315       break;
316 /* end-sanitize-m32rx */
317 /* start-sanitize-m32rx */
318     case M32R_OPERAND_ACCD :
319       print_keyword (info, & m32r_cgen_opval_h_accums, fields->f_accd, 0|(1<<CGEN_OPERAND_UNSIGNED));
320       break;
321 /* end-sanitize-m32rx */
322 /* start-sanitize-m32rx */
323     case M32R_OPERAND_ACCS :
324       print_keyword (info, & m32r_cgen_opval_h_accums, fields->f_accs, 0|(1<<CGEN_OPERAND_UNSIGNED));
325       break;
326 /* end-sanitize-m32rx */
327 /* start-sanitize-m32rx */
328     case M32R_OPERAND_ACC :
329       print_keyword (info, & m32r_cgen_opval_h_accums, fields->f_acc, 0|(1<<CGEN_OPERAND_UNSIGNED));
330       break;
331 /* end-sanitize-m32rx */
332     case M32R_OPERAND_HASH :
333       print_hash (info, fields->f_nil, 0, pc, length);
334       break;
335     case M32R_OPERAND_HI16 :
336       print_normal (info, fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
337       break;
338     case M32R_OPERAND_SLO16 :
339       print_normal (info, fields->f_simm16, 0, pc, length);
340       break;
341     case M32R_OPERAND_ULO16 :
342       print_normal (info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
343       break;
344     case M32R_OPERAND_UIMM24 :
345       print_normal (info, fields->f_uimm24, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
346       break;
347     case M32R_OPERAND_DISP8 :
348       print_normal (info, fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
349       break;
350     case M32R_OPERAND_DISP16 :
351       print_normal (info, fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
352       break;
353     case M32R_OPERAND_DISP24 :
354       print_normal (info, fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
355       break;
356
357     default :
358       fprintf (stderr, "Unrecognized field %d while printing insn.\n",
359                opindex);
360     abort ();
361   }
362 }
363
364 cgen_extract_fn * m32r_cgen_extract_handlers[] = 
365 {
366   0, /* default */
367   extract_insn_normal,
368 };
369
370 cgen_print_fn * m32r_cgen_print_handlers[] = 
371 {
372   0, /* default */
373   print_insn_normal,
374 };
375
376
377 void
378 m32r_cgen_init_dis (mach, endian)
379      int mach;
380      enum cgen_endian endian;
381 {
382   m32r_cgen_init_tables (mach);
383   cgen_set_cpu (& m32r_cgen_opcode_table, mach, endian);
384   cgen_dis_init ();
385 }
386
387 \f
388 /* Default extraction routine.
389
390    ATTRS is a mask of the boolean attributes.  We only need `unsigned',
391    but for generality we take a bitmask of all of them.  */
392
393 static int
394 extract_normal (buf_ctrl, insn_value, attrs, start, length, total_length, valuep)
395      PTR buf_ctrl;
396      cgen_insn_t insn_value;
397      unsigned int attrs;
398      int start, length, total_length;
399      long *valuep;
400 {
401   long value;
402
403 #ifdef CGEN_INT_INSN
404 #if 0
405   value = ((insn_value >> (CGEN_BASE_INSN_BITSIZE - (start + length)))
406            & ((1 << length) - 1));
407 #else
408   value = ((insn_value >> (total_length - (start + length)))
409            & ((1 << length) - 1));
410 #endif
411   if (! (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED))
412       && (value & (1 << (length - 1))))
413     value -= 1 << length;
414 #else
415   /* FIXME: unfinished */
416 #endif
417
418   *valuep = value;
419
420   /* FIXME: for now */
421   return 1;
422 }
423
424 /* Default print handler.  */
425
426 static void
427 print_normal (dis_info, value, attrs, pc, length)
428      PTR dis_info;
429      long value;
430      unsigned int attrs;
431      unsigned long pc; /* FIXME: should be bfd_vma */
432      int length;
433 {
434   disassemble_info *info = dis_info;
435
436 #ifdef CGEN_PRINT_NORMAL
437   CGEN_PRINT_NORMAL (info, value, attrs, pc, length);
438 #endif
439
440   /* Print the operand as directed by the attributes.  */
441   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_FAKE))
442     ; /* nothing to do (??? at least not yet) */
443   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
444     (*info->print_address_func) (pc + CGEN_PCREL_OFFSET + value, info);
445   /* ??? Not all cases of this are currently caught.  */
446   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
447     /* FIXME: Why & 0xffffffff?  */
448     (*info->print_address_func) ((bfd_vma) value & 0xffffffff, info);
449   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
450     (*info->fprintf_func) (info->stream, "0x%lx", value);
451   else
452     (*info->fprintf_func) (info->stream, "%ld", value);
453 }
454
455 /* Keyword print handler.  */
456
457 static void
458 print_keyword (dis_info, keyword_table, value, attrs)
459      PTR dis_info;
460      CGEN_KEYWORD *keyword_table;
461      long value;
462      unsigned int attrs;
463 {
464   disassemble_info *info = dis_info;
465   const CGEN_KEYWORD_ENTRY *ke;
466
467   ke = cgen_keyword_lookup_value (keyword_table, value);
468   if (ke != NULL)
469     (*info->fprintf_func) (info->stream, "%s", ke->name);
470   else
471     (*info->fprintf_func) (info->stream, "???");
472 }
473 \f
474 /* Default insn extractor.
475
476    The extracted fields are stored in DIS_FLDS.
477    BUF_CTRL is used to handle reading variable length insns (FIXME: not done).
478    Return the length of the insn in bits, or 0 if no match.  */
479
480 static int
481 extract_insn_normal (insn, buf_ctrl, insn_value, fields)
482      const CGEN_INSN *insn;
483      PTR buf_ctrl;
484      cgen_insn_t insn_value;
485      CGEN_FIELDS *fields;
486 {
487   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
488   const unsigned char *syn;
489
490   CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
491
492   CGEN_INIT_EXTRACT ();
493
494   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
495     {
496       int length;
497
498       if (CGEN_SYNTAX_CHAR_P (*syn))
499         continue;
500
501       length = m32r_cgen_extract_operand (CGEN_SYNTAX_FIELD (*syn),
502                                             buf_ctrl, insn_value, fields);
503       if (length == 0)
504         return 0;
505     }
506
507   /* We recognized and successfully extracted this insn.  */
508   return CGEN_INSN_BITSIZE (insn);
509 }
510
511 /* Default insn printer.
512
513    DIS_INFO is defined as `PTR' so the disassembler needn't know anything
514    about disassemble_info.
515 */
516
517 static void
518 print_insn_normal (dis_info, insn, fields, pc, length)
519      PTR dis_info;
520      const CGEN_INSN *insn;
521      CGEN_FIELDS *fields;
522      bfd_vma pc;
523      int length;
524 {
525   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
526   disassemble_info *info = dis_info;
527   const unsigned char *syn;
528
529   CGEN_INIT_PRINT ();
530
531   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
532     {
533       if (CGEN_SYNTAX_MNEMONIC_P (*syn))
534         {
535           (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
536           continue;
537         }
538       if (CGEN_SYNTAX_CHAR_P (*syn))
539         {
540           (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
541           continue;
542         }
543
544       /* We have an operand.  */
545       m32r_cgen_print_operand (CGEN_SYNTAX_FIELD (*syn), info,
546                                 fields, CGEN_INSN_ATTRS (insn), pc, length);
547     }
548 }
549 \f
550 /* Default value for CGEN_PRINT_INSN.
551    Given BUFLEN bits (target byte order) read into BUF, look up the
552    insn in the instruction table and disassemble it.
553
554    The result is the size of the insn in bytes.  */
555
556 #ifndef CGEN_PRINT_INSN
557 #define CGEN_PRINT_INSN print_insn
558 #endif
559
560 static int
561 print_insn (pc, info, buf, buflen)
562      bfd_vma pc;
563      disassemble_info *info;
564      char *buf;
565      int buflen;
566 {
567   unsigned long insn_value;
568   const CGEN_INSN_LIST *insn_list;
569
570   switch (buflen)
571     {
572     case 8:
573       insn_value = buf[0];
574       break;
575     case 16:
576       insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf);
577       break;
578     case 32:
579       insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf);
580       break;
581     default:
582       abort ();
583     }
584
585   /* The instructions are stored in hash lists.
586      Pick the first one and keep trying until we find the right one.  */
587
588   insn_list = CGEN_DIS_LOOKUP_INSN (buf, insn_value);
589   while (insn_list != NULL)
590     {
591       const CGEN_INSN *insn = insn_list->insn;
592       CGEN_FIELDS fields;
593       int length;
594
595 #if 0 /* not needed as insn shouldn't be in hash lists if not supported */
596       /* Supported by this cpu?  */
597       if (! m32r_cgen_insn_supported (insn))
598         continue;
599 #endif
600
601       /* Basic bit mask must be correct.  */
602       /* ??? May wish to allow target to defer this check until the extract
603          handler.  */
604       if ((insn_value & CGEN_INSN_MASK (insn)) == CGEN_INSN_VALUE (insn))
605         {
606           /* Printing is handled in two passes.  The first pass parses the
607              machine insn and extracts the fields.  The second pass prints
608              them.  */
609
610           length = (*CGEN_EXTRACT_FN (insn)) (insn, NULL, insn_value, &fields);
611           if (length > 0)
612             {
613               (*CGEN_PRINT_FN (insn)) (info, insn, &fields, pc, length);
614               /* length is in bits, result is in bytes */
615               return length / 8;
616             }
617         }
618
619       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
620     }
621
622   return 0;
623 }
624
625 /* Main entry point.
626    Print one instruction from PC on INFO->STREAM.
627    Return the size of the instruction (in bytes).  */
628
629 int
630 print_insn_m32r (pc, info)
631      bfd_vma pc;
632      disassemble_info *info;
633 {
634   char buffer[CGEN_MAX_INSN_SIZE];
635   int status, length;
636   static int initialized = 0;
637   static int current_mach = 0;
638   static int current_big_p = 0;
639   int mach = info->mach;
640   int big_p = info->endian == BFD_ENDIAN_BIG;
641
642   /* If we haven't initialized yet, or if we've switched cpu's, initialize.  */
643   if (!initialized || mach != current_mach || big_p != current_big_p)
644     {
645       initialized = 1;
646       current_mach = mach;
647       current_big_p = big_p;
648       m32r_cgen_init_dis (mach, big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE);
649     }
650
651   /* Read enough of the insn so we can look it up in the hash lists.  */
652
653   status = (*info->read_memory_func) (pc, buffer, CGEN_BASE_INSN_SIZE, info);
654   if (status != 0)
655     {
656       (*info->memory_error_func) (status, pc, info);
657       return -1;
658     }
659
660   /* We try to have as much common code as possible.
661      But at this point some targets need to take over.  */
662   /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
663      but if not possible try to move this hook elsewhere rather than
664      have two hooks.  */
665   length = CGEN_PRINT_INSN (pc, info, buffer, CGEN_BASE_INSN_BITSIZE);
666   if (length)
667     return length;
668
669   (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
670   return CGEN_DEFAULT_INSN_SIZE;
671 }