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