xref: /openbsd-src/gnu/usr.bin/binutils/opcodes/m32r-dis.c (revision f7cc78ec694aa42ece3363be499a17e16a4780bc)
1fddef416Sniklas /* Disassembler interface for targets using CGEN. -*- C -*-
2fddef416Sniklas    CGEN: Cpu tools GENerator
3fddef416Sniklas 
4*f7cc78ecSespie THIS FILE IS MACHINE GENERATED WITH CGEN.
5*f7cc78ecSespie - the resultant file is machine generated, cgen-dis.in isn't
6fddef416Sniklas 
7*f7cc78ecSespie Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
8fddef416Sniklas 
9fddef416Sniklas This file is part of the GNU Binutils and GDB, the GNU debugger.
10fddef416Sniklas 
11fddef416Sniklas This program is free software; you can redistribute it and/or modify
12fddef416Sniklas it under the terms of the GNU General Public License as published by
13fddef416Sniklas the Free Software Foundation; either version 2, or (at your option)
14fddef416Sniklas any later version.
15fddef416Sniklas 
16fddef416Sniklas This program is distributed in the hope that it will be useful,
17fddef416Sniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
18fddef416Sniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19fddef416Sniklas GNU General Public License for more details.
20fddef416Sniklas 
21fddef416Sniklas You should have received a copy of the GNU General Public License
22*f7cc78ecSespie along with this program; if not, write to the Free Software Foundation, Inc.,
23*f7cc78ecSespie 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
24*f7cc78ecSespie 
25*f7cc78ecSespie /* ??? Eventually more and more of this stuff can go to cpu-independent files.
26*f7cc78ecSespie    Keep that in mind.  */
27fddef416Sniklas 
28fddef416Sniklas #include "sysdep.h"
29fddef416Sniklas #include <stdio.h>
30fddef416Sniklas #include "ansidecl.h"
31fddef416Sniklas #include "dis-asm.h"
32fddef416Sniklas #include "bfd.h"
33*f7cc78ecSespie #include "symcat.h"
34*f7cc78ecSespie #include "m32r-desc.h"
35*f7cc78ecSespie #include "m32r-opc.h"
36*f7cc78ecSespie #include "opintl.h"
37fddef416Sniklas 
38fddef416Sniklas /* Default text to print if an instruction isn't recognized.  */
39*f7cc78ecSespie #define UNKNOWN_INSN_MSG _("*unknown*")
40fddef416Sniklas 
41*f7cc78ecSespie static void print_normal
42*f7cc78ecSespie      PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned int, bfd_vma, int));
43*f7cc78ecSespie static void print_address
44*f7cc78ecSespie      PARAMS ((CGEN_CPU_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int));
45*f7cc78ecSespie static void print_keyword
46*f7cc78ecSespie      PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int));
47fddef416Sniklas static void print_insn_normal
48*f7cc78ecSespie      PARAMS ((CGEN_CPU_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *,
49*f7cc78ecSespie 	      bfd_vma, int));
50*f7cc78ecSespie static int print_insn PARAMS ((CGEN_CPU_DESC, bfd_vma,
51*f7cc78ecSespie 			       disassemble_info *, char *, int));
52*f7cc78ecSespie static int default_print_insn
53*f7cc78ecSespie      PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *));
54fddef416Sniklas 
55fddef416Sniklas /* -- disassembler routines inserted here */
56*f7cc78ecSespie 
57fddef416Sniklas /* -- dis.c */
58fddef416Sniklas 
59*f7cc78ecSespie /* Immediate values are prefixed with '#'.  */
60*f7cc78ecSespie 
61*f7cc78ecSespie #define CGEN_PRINT_NORMAL(cd, info, value, attrs, pc, length) \
62*f7cc78ecSespie do { \
63*f7cc78ecSespie   if (CGEN_BOOL_ATTR ((attrs), CGEN_OPERAND_HASH_PREFIX)) \
64*f7cc78ecSespie     (*info->fprintf_func) (info->stream, "#"); \
65*f7cc78ecSespie } while (0)
66*f7cc78ecSespie 
67*f7cc78ecSespie /* Handle '#' prefixes as operands.  */
68*f7cc78ecSespie 
69*f7cc78ecSespie static void
70*f7cc78ecSespie print_hash (cd, dis_info, value, attrs, pc, length)
71*f7cc78ecSespie      CGEN_CPU_DESC cd;
72*f7cc78ecSespie      PTR dis_info;
73*f7cc78ecSespie      long value;
74*f7cc78ecSespie      unsigned int attrs;
75*f7cc78ecSespie      bfd_vma pc;
76*f7cc78ecSespie      int length;
77*f7cc78ecSespie {
78*f7cc78ecSespie   disassemble_info *info = (disassemble_info *) dis_info;
79*f7cc78ecSespie   (*info->fprintf_func) (info->stream, "#");
80*f7cc78ecSespie }
81*f7cc78ecSespie 
82fddef416Sniklas #undef CGEN_PRINT_INSN
83fddef416Sniklas #define CGEN_PRINT_INSN my_print_insn
84fddef416Sniklas 
85fddef416Sniklas static int
86*f7cc78ecSespie my_print_insn (cd, pc, info)
87*f7cc78ecSespie      CGEN_CPU_DESC cd;
88fddef416Sniklas      bfd_vma pc;
89fddef416Sniklas      disassemble_info *info;
90fddef416Sniklas {
91*f7cc78ecSespie   char buffer[CGEN_MAX_INSN_SIZE];
92*f7cc78ecSespie   char *buf = buffer;
93*f7cc78ecSespie   int status;
94*f7cc78ecSespie   int buflen = (pc & 3) == 0 ? 4 : 2;
95*f7cc78ecSespie 
96*f7cc78ecSespie   /* Read the base part of the insn.  */
97*f7cc78ecSespie 
98*f7cc78ecSespie   status = (*info->read_memory_func) (pc, buf, buflen, info);
99*f7cc78ecSespie   if (status != 0)
100*f7cc78ecSespie     {
101*f7cc78ecSespie       (*info->memory_error_func) (status, pc, info);
102*f7cc78ecSespie       return -1;
103*f7cc78ecSespie     }
104fddef416Sniklas 
105fddef416Sniklas   /* 32 bit insn?  */
106fddef416Sniklas   if ((pc & 3) == 0 && (buf[0] & 0x80) != 0)
107*f7cc78ecSespie     return print_insn (cd, pc, info, buf, buflen);
108fddef416Sniklas 
109fddef416Sniklas   /* Print the first insn.  */
110fddef416Sniklas   if ((pc & 3) == 0)
111fddef416Sniklas     {
112*f7cc78ecSespie       if (print_insn (cd, pc, info, buf, 2) == 0)
113fddef416Sniklas 	(*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
114fddef416Sniklas       buf += 2;
115fddef416Sniklas     }
116fddef416Sniklas 
117fddef416Sniklas   if (buf[0] & 0x80)
118fddef416Sniklas     {
119fddef416Sniklas       /* Parallel.  */
120fddef416Sniklas       (*info->fprintf_func) (info->stream, " || ");
121fddef416Sniklas       buf[0] &= 0x7f;
122fddef416Sniklas     }
123fddef416Sniklas   else
124fddef416Sniklas     (*info->fprintf_func) (info->stream, " -> ");
125fddef416Sniklas 
126*f7cc78ecSespie   /* The "& 3" is to pass a consistent address.
127*f7cc78ecSespie      Parallel insns arguably both begin on the word boundary.
128*f7cc78ecSespie      Also, branch insns are calculated relative to the word boundary.  */
129*f7cc78ecSespie   if (print_insn (cd, pc & ~ (bfd_vma) 3, info, buf, 2) == 0)
130fddef416Sniklas     (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
131fddef416Sniklas 
132fddef416Sniklas   return (pc & 3) ? 2 : 4;
133fddef416Sniklas }
134fddef416Sniklas 
135fddef416Sniklas /* -- */
136fddef416Sniklas 
137fddef416Sniklas /* Main entry point for printing operands.
138*f7cc78ecSespie    XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
139*f7cc78ecSespie    of dis-asm.h on cgen.h.
140fddef416Sniklas 
141fddef416Sniklas    This function is basically just a big switch statement.  Earlier versions
142fddef416Sniklas    used tables to look up the function to use, but
143fddef416Sniklas    - if the table contains both assembler and disassembler functions then
144fddef416Sniklas      the disassembler contains much of the assembler and vice-versa,
145fddef416Sniklas    - there's a lot of inlining possibilities as things grow,
146fddef416Sniklas    - using a switch statement avoids the function call overhead.
147fddef416Sniklas 
148fddef416Sniklas    This function could be moved into `print_insn_normal', but keeping it
149fddef416Sniklas    separate makes clear the interface between `print_insn_normal' and each of
150fddef416Sniklas    the handlers.
151fddef416Sniklas */
152fddef416Sniklas 
153*f7cc78ecSespie void
154*f7cc78ecSespie m32r_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length)
155*f7cc78ecSespie      CGEN_CPU_DESC cd;
156fddef416Sniklas      int opindex;
157*f7cc78ecSespie      PTR xinfo;
158*f7cc78ecSespie      CGEN_FIELDS *fields;
159*f7cc78ecSespie      void const *attrs;
160fddef416Sniklas      bfd_vma pc;
161fddef416Sniklas      int length;
162fddef416Sniklas {
163*f7cc78ecSespie  disassemble_info *info = (disassemble_info *) xinfo;
164*f7cc78ecSespie 
165fddef416Sniklas   switch (opindex)
166fddef416Sniklas     {
167*f7cc78ecSespie     case M32R_OPERAND_ACC :
168*f7cc78ecSespie       print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_acc, 0);
169fddef416Sniklas       break;
170*f7cc78ecSespie     case M32R_OPERAND_ACCD :
171*f7cc78ecSespie       print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_accd, 0);
172fddef416Sniklas       break;
173*f7cc78ecSespie     case M32R_OPERAND_ACCS :
174*f7cc78ecSespie       print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_accs, 0);
175fddef416Sniklas       break;
176*f7cc78ecSespie     case M32R_OPERAND_DCR :
177*f7cc78ecSespie       print_keyword (cd, info, & m32r_cgen_opval_cr_names, fields->f_r1, 0);
178fddef416Sniklas       break;
179*f7cc78ecSespie     case M32R_OPERAND_DISP16 :
180*f7cc78ecSespie       print_address (cd, info, fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
181fddef416Sniklas       break;
182*f7cc78ecSespie     case M32R_OPERAND_DISP24 :
183*f7cc78ecSespie       print_address (cd, info, fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
184fddef416Sniklas       break;
185*f7cc78ecSespie     case M32R_OPERAND_DISP8 :
186*f7cc78ecSespie       print_address (cd, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
187fddef416Sniklas       break;
188*f7cc78ecSespie     case M32R_OPERAND_DR :
189*f7cc78ecSespie       print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r1, 0);
190fddef416Sniklas       break;
191*f7cc78ecSespie     case M32R_OPERAND_HASH :
192*f7cc78ecSespie       print_hash (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
193fddef416Sniklas       break;
194*f7cc78ecSespie     case M32R_OPERAND_HI16 :
195*f7cc78ecSespie       print_normal (cd, info, fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT), pc, length);
196fddef416Sniklas       break;
197*f7cc78ecSespie     case M32R_OPERAND_IMM1 :
198*f7cc78ecSespie       print_normal (cd, info, fields->f_imm1, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
199fddef416Sniklas       break;
200*f7cc78ecSespie     case M32R_OPERAND_SCR :
201*f7cc78ecSespie       print_keyword (cd, info, & m32r_cgen_opval_cr_names, fields->f_r2, 0);
202fddef416Sniklas       break;
203*f7cc78ecSespie     case M32R_OPERAND_SIMM16 :
204*f7cc78ecSespie       print_normal (cd, info, fields->f_simm16, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
205fddef416Sniklas       break;
206*f7cc78ecSespie     case M32R_OPERAND_SIMM8 :
207*f7cc78ecSespie       print_normal (cd, info, fields->f_simm8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
208fddef416Sniklas       break;
209*f7cc78ecSespie     case M32R_OPERAND_SLO16 :
210*f7cc78ecSespie       print_normal (cd, info, fields->f_simm16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
211fddef416Sniklas       break;
212*f7cc78ecSespie     case M32R_OPERAND_SR :
213*f7cc78ecSespie       print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r2, 0);
214fddef416Sniklas       break;
215*f7cc78ecSespie     case M32R_OPERAND_SRC1 :
216*f7cc78ecSespie       print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r1, 0);
217fddef416Sniklas       break;
218*f7cc78ecSespie     case M32R_OPERAND_SRC2 :
219*f7cc78ecSespie       print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r2, 0);
220*f7cc78ecSespie       break;
221*f7cc78ecSespie     case M32R_OPERAND_UIMM16 :
222*f7cc78ecSespie       print_normal (cd, info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
223*f7cc78ecSespie       break;
224*f7cc78ecSespie     case M32R_OPERAND_UIMM24 :
225*f7cc78ecSespie       print_address (cd, info, fields->f_uimm24, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
226*f7cc78ecSespie       break;
227*f7cc78ecSespie     case M32R_OPERAND_UIMM4 :
228*f7cc78ecSespie       print_normal (cd, info, fields->f_uimm4, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
229*f7cc78ecSespie       break;
230*f7cc78ecSespie     case M32R_OPERAND_UIMM5 :
231*f7cc78ecSespie       print_normal (cd, info, fields->f_uimm5, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
232*f7cc78ecSespie       break;
233*f7cc78ecSespie     case M32R_OPERAND_ULO16 :
234*f7cc78ecSespie       print_normal (cd, info, fields->f_uimm16, 0, pc, length);
235fddef416Sniklas       break;
236fddef416Sniklas 
237fddef416Sniklas     default :
238*f7cc78ecSespie       /* xgettext:c-format */
239*f7cc78ecSespie       fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
240fddef416Sniklas 	       opindex);
241fddef416Sniklas     abort ();
242fddef416Sniklas   }
243fddef416Sniklas }
244fddef416Sniklas 
245*f7cc78ecSespie cgen_print_fn * const m32r_cgen_print_handlers[] =
246*f7cc78ecSespie {
247fddef416Sniklas   print_insn_normal,
248fddef416Sniklas };
249fddef416Sniklas 
250fddef416Sniklas 
251fddef416Sniklas void
252*f7cc78ecSespie m32r_cgen_init_dis (cd)
253*f7cc78ecSespie      CGEN_CPU_DESC cd;
254fddef416Sniklas {
255*f7cc78ecSespie   m32r_cgen_init_opcode_table (cd);
256*f7cc78ecSespie   m32r_cgen_init_ibld_table (cd);
257*f7cc78ecSespie   cd->print_handlers = & m32r_cgen_print_handlers[0];
258*f7cc78ecSespie   cd->print_operand = m32r_cgen_print_operand;
259fddef416Sniklas }
260fddef416Sniklas 
261fddef416Sniklas 
262*f7cc78ecSespie /* Default print handler.  */
263fddef416Sniklas 
264fddef416Sniklas static void
265*f7cc78ecSespie print_normal (cd, dis_info, value, attrs, pc, length)
266*f7cc78ecSespie      CGEN_CPU_DESC cd;
267*f7cc78ecSespie      PTR dis_info;
268*f7cc78ecSespie      long value;
269*f7cc78ecSespie      unsigned int attrs;
270fddef416Sniklas      bfd_vma pc;
271fddef416Sniklas      int length;
272fddef416Sniklas {
273*f7cc78ecSespie   disassemble_info *info = (disassemble_info *) dis_info;
274*f7cc78ecSespie 
275*f7cc78ecSespie #ifdef CGEN_PRINT_NORMAL
276*f7cc78ecSespie   CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
277*f7cc78ecSespie #endif
278*f7cc78ecSespie 
279*f7cc78ecSespie   /* Print the operand as directed by the attributes.  */
280*f7cc78ecSespie   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
281*f7cc78ecSespie     ; /* nothing to do */
282*f7cc78ecSespie   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
283*f7cc78ecSespie     (*info->fprintf_func) (info->stream, "%ld", value);
284*f7cc78ecSespie   else
285*f7cc78ecSespie     (*info->fprintf_func) (info->stream, "0x%lx", value);
286*f7cc78ecSespie }
287*f7cc78ecSespie 
288*f7cc78ecSespie /* Default address handler.  */
289*f7cc78ecSespie 
290*f7cc78ecSespie static void
291*f7cc78ecSespie print_address (cd, dis_info, value, attrs, pc, length)
292*f7cc78ecSespie      CGEN_CPU_DESC cd;
293*f7cc78ecSespie      PTR dis_info;
294*f7cc78ecSespie      bfd_vma value;
295*f7cc78ecSespie      unsigned int attrs;
296*f7cc78ecSespie      bfd_vma pc;
297*f7cc78ecSespie      int length;
298*f7cc78ecSespie {
299*f7cc78ecSespie   disassemble_info *info = (disassemble_info *) dis_info;
300*f7cc78ecSespie 
301*f7cc78ecSespie #ifdef CGEN_PRINT_ADDRESS
302*f7cc78ecSespie   CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
303*f7cc78ecSespie #endif
304*f7cc78ecSespie 
305*f7cc78ecSespie   /* Print the operand as directed by the attributes.  */
306*f7cc78ecSespie   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
307*f7cc78ecSespie     ; /* nothing to do */
308*f7cc78ecSespie   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
309*f7cc78ecSespie     (*info->print_address_func) (value, info);
310*f7cc78ecSespie   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
311*f7cc78ecSespie     (*info->print_address_func) (value, info);
312*f7cc78ecSespie   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
313*f7cc78ecSespie     (*info->fprintf_func) (info->stream, "%ld", (long) value);
314*f7cc78ecSespie   else
315*f7cc78ecSespie     (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
316*f7cc78ecSespie }
317*f7cc78ecSespie 
318*f7cc78ecSespie /* Keyword print handler.  */
319*f7cc78ecSespie 
320*f7cc78ecSespie static void
321*f7cc78ecSespie print_keyword (cd, dis_info, keyword_table, value, attrs)
322*f7cc78ecSespie      CGEN_CPU_DESC cd;
323*f7cc78ecSespie      PTR dis_info;
324*f7cc78ecSespie      CGEN_KEYWORD *keyword_table;
325*f7cc78ecSespie      long value;
326*f7cc78ecSespie      unsigned int attrs;
327*f7cc78ecSespie {
328*f7cc78ecSespie   disassemble_info *info = (disassemble_info *) dis_info;
329*f7cc78ecSespie   const CGEN_KEYWORD_ENTRY *ke;
330*f7cc78ecSespie 
331*f7cc78ecSespie   ke = cgen_keyword_lookup_value (keyword_table, value);
332*f7cc78ecSespie   if (ke != NULL)
333*f7cc78ecSespie     (*info->fprintf_func) (info->stream, "%s", ke->name);
334*f7cc78ecSespie   else
335*f7cc78ecSespie     (*info->fprintf_func) (info->stream, "???");
336*f7cc78ecSespie }
337*f7cc78ecSespie 
338*f7cc78ecSespie /* Default insn printer.
339*f7cc78ecSespie 
340*f7cc78ecSespie    DIS_INFO is defined as `PTR' so the disassembler needn't know anything
341*f7cc78ecSespie    about disassemble_info.  */
342*f7cc78ecSespie 
343*f7cc78ecSespie static void
344*f7cc78ecSespie print_insn_normal (cd, dis_info, insn, fields, pc, length)
345*f7cc78ecSespie      CGEN_CPU_DESC cd;
346*f7cc78ecSespie      PTR dis_info;
347*f7cc78ecSespie      const CGEN_INSN *insn;
348*f7cc78ecSespie      CGEN_FIELDS *fields;
349*f7cc78ecSespie      bfd_vma pc;
350*f7cc78ecSespie      int length;
351*f7cc78ecSespie {
352*f7cc78ecSespie   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
353*f7cc78ecSespie   disassemble_info *info = (disassemble_info *) dis_info;
354fddef416Sniklas   const unsigned char *syn;
355fddef416Sniklas 
356*f7cc78ecSespie   CGEN_INIT_PRINT (cd);
357fddef416Sniklas 
358*f7cc78ecSespie   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
359fddef416Sniklas     {
360*f7cc78ecSespie       if (CGEN_SYNTAX_MNEMONIC_P (*syn))
361*f7cc78ecSespie 	{
362*f7cc78ecSespie 	  (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
363*f7cc78ecSespie 	  continue;
364*f7cc78ecSespie 	}
365fddef416Sniklas       if (CGEN_SYNTAX_CHAR_P (*syn))
366fddef416Sniklas 	{
367fddef416Sniklas 	  (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
368fddef416Sniklas 	  continue;
369fddef416Sniklas 	}
370fddef416Sniklas 
371fddef416Sniklas       /* We have an operand.  */
372*f7cc78ecSespie       m32r_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
373fddef416Sniklas 				 fields, CGEN_INSN_ATTRS (insn), pc, length);
374fddef416Sniklas     }
375fddef416Sniklas }
376fddef416Sniklas 
377*f7cc78ecSespie /* Utility to print an insn.
378*f7cc78ecSespie    BUF is the base part of the insn, target byte order, BUFLEN bytes long.
379*f7cc78ecSespie    The result is the size of the insn in bytes or zero for an unknown insn
380*f7cc78ecSespie    or -1 if an error occurs fetching data (memory_error_func will have
381*f7cc78ecSespie    been called).  */
382fddef416Sniklas 
383fddef416Sniklas static int
384*f7cc78ecSespie print_insn (cd, pc, info, buf, buflen)
385*f7cc78ecSespie      CGEN_CPU_DESC cd;
386fddef416Sniklas      bfd_vma pc;
387fddef416Sniklas      disassemble_info *info;
388fddef416Sniklas      char *buf;
389fddef416Sniklas      int buflen;
390fddef416Sniklas {
391fddef416Sniklas   unsigned long insn_value;
392fddef416Sniklas   const CGEN_INSN_LIST *insn_list;
393*f7cc78ecSespie   CGEN_EXTRACT_INFO ex_info;
394*f7cc78ecSespie 
395*f7cc78ecSespie   ex_info.dis_info = info;
396*f7cc78ecSespie   ex_info.valid = (1 << (cd->base_insn_bitsize / 8)) - 1;
397*f7cc78ecSespie   ex_info.insn_bytes = buf;
398fddef416Sniklas 
399fddef416Sniklas   switch (buflen)
400fddef416Sniklas     {
401*f7cc78ecSespie     case 1:
402fddef416Sniklas       insn_value = buf[0];
403fddef416Sniklas       break;
404*f7cc78ecSespie     case 2:
405fddef416Sniklas       insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf);
406fddef416Sniklas       break;
407*f7cc78ecSespie     case 4:
408fddef416Sniklas       insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf);
409fddef416Sniklas       break;
410fddef416Sniklas     default:
411fddef416Sniklas       abort ();
412fddef416Sniklas     }
413fddef416Sniklas 
414fddef416Sniklas   /* The instructions are stored in hash lists.
415fddef416Sniklas      Pick the first one and keep trying until we find the right one.  */
416fddef416Sniklas 
417*f7cc78ecSespie   insn_list = CGEN_DIS_LOOKUP_INSN (cd, buf, insn_value);
418fddef416Sniklas   while (insn_list != NULL)
419fddef416Sniklas     {
420fddef416Sniklas       const CGEN_INSN *insn = insn_list->insn;
421*f7cc78ecSespie       CGEN_FIELDS fields;
422fddef416Sniklas       int length;
423fddef416Sniklas 
424*f7cc78ecSespie #ifdef CGEN_VALIDATE_INSN_SUPPORTED
425*f7cc78ecSespie       /* not needed as insn shouldn't be in hash lists if not supported */
426fddef416Sniklas       /* Supported by this cpu?  */
427*f7cc78ecSespie       if (! m32r_cgen_insn_supported (cd, insn))
428*f7cc78ecSespie         {
429*f7cc78ecSespie           insn_list = CGEN_DIS_NEXT_INSN (insn_list);
430fddef416Sniklas 	  continue;
431*f7cc78ecSespie         }
432fddef416Sniklas #endif
433fddef416Sniklas 
434fddef416Sniklas       /* Basic bit mask must be correct.  */
435fddef416Sniklas       /* ??? May wish to allow target to defer this check until the extract
436fddef416Sniklas 	 handler.  */
437*f7cc78ecSespie       if ((insn_value & CGEN_INSN_BASE_MASK (insn))
438*f7cc78ecSespie 	  == CGEN_INSN_BASE_VALUE (insn))
439fddef416Sniklas 	{
440fddef416Sniklas 	  /* Printing is handled in two passes.  The first pass parses the
441fddef416Sniklas 	     machine insn and extracts the fields.  The second pass prints
442fddef416Sniklas 	     them.  */
443fddef416Sniklas 
444*f7cc78ecSespie 	  length = CGEN_EXTRACT_FN (cd, insn)
445*f7cc78ecSespie 	    (cd, insn, &ex_info, insn_value, &fields, pc);
446*f7cc78ecSespie 	  /* length < 0 -> error */
447*f7cc78ecSespie 	  if (length < 0)
448*f7cc78ecSespie 	    return length;
449fddef416Sniklas 	  if (length > 0)
450fddef416Sniklas 	    {
451*f7cc78ecSespie 	      CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
452fddef416Sniklas 	      /* length is in bits, result is in bytes */
453fddef416Sniklas 	      return length / 8;
454fddef416Sniklas 	    }
455fddef416Sniklas 	}
456fddef416Sniklas 
457fddef416Sniklas       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
458fddef416Sniklas     }
459fddef416Sniklas 
460fddef416Sniklas   return 0;
461fddef416Sniklas }
462fddef416Sniklas 
463*f7cc78ecSespie /* Default value for CGEN_PRINT_INSN.
464*f7cc78ecSespie    The result is the size of the insn in bytes or zero for an unknown insn
465*f7cc78ecSespie    or -1 if an error occured fetching bytes.  */
466*f7cc78ecSespie 
467*f7cc78ecSespie #ifndef CGEN_PRINT_INSN
468*f7cc78ecSespie #define CGEN_PRINT_INSN default_print_insn
469*f7cc78ecSespie #endif
470*f7cc78ecSespie 
471*f7cc78ecSespie static int
472*f7cc78ecSespie default_print_insn (cd, pc, info)
473*f7cc78ecSespie      CGEN_CPU_DESC cd;
474*f7cc78ecSespie      bfd_vma pc;
475*f7cc78ecSespie      disassemble_info *info;
476*f7cc78ecSespie {
477*f7cc78ecSespie   char buf[CGEN_MAX_INSN_SIZE];
478*f7cc78ecSespie   int status;
479*f7cc78ecSespie 
480*f7cc78ecSespie   /* Read the base part of the insn.  */
481*f7cc78ecSespie 
482*f7cc78ecSespie   status = (*info->read_memory_func) (pc, buf, cd->base_insn_bitsize / 8, info);
483*f7cc78ecSespie   if (status != 0)
484*f7cc78ecSespie     {
485*f7cc78ecSespie       (*info->memory_error_func) (status, pc, info);
486*f7cc78ecSespie       return -1;
487*f7cc78ecSespie     }
488*f7cc78ecSespie 
489*f7cc78ecSespie   return print_insn (cd, pc, info, buf, cd->base_insn_bitsize / 8);
490*f7cc78ecSespie }
491*f7cc78ecSespie 
492fddef416Sniklas /* Main entry point.
493fddef416Sniklas    Print one instruction from PC on INFO->STREAM.
494fddef416Sniklas    Return the size of the instruction (in bytes).  */
495fddef416Sniklas 
496fddef416Sniklas int
497fddef416Sniklas print_insn_m32r (pc, info)
498fddef416Sniklas      bfd_vma pc;
499fddef416Sniklas      disassemble_info *info;
500fddef416Sniklas {
501*f7cc78ecSespie   static CGEN_CPU_DESC cd = 0;
502*f7cc78ecSespie   static prev_isa,prev_mach,prev_endian;
503*f7cc78ecSespie   int length;
504*f7cc78ecSespie   int isa,mach;
505*f7cc78ecSespie   int endian = (info->endian == BFD_ENDIAN_BIG
506*f7cc78ecSespie 		? CGEN_ENDIAN_BIG
507*f7cc78ecSespie 		: CGEN_ENDIAN_LITTLE);
508*f7cc78ecSespie   enum bfd_architecture arch;
509fddef416Sniklas 
510*f7cc78ecSespie   /* ??? gdb will set mach but leave the architecture as "unknown" */
511*f7cc78ecSespie #ifndef CGEN_BFD_ARCH
512*f7cc78ecSespie #define CGEN_BFD_ARCH bfd_arch_m32r
513*f7cc78ecSespie #endif
514*f7cc78ecSespie   arch = info->arch;
515*f7cc78ecSespie   if (arch == bfd_arch_unknown)
516*f7cc78ecSespie     arch = CGEN_BFD_ARCH;
517*f7cc78ecSespie 
518*f7cc78ecSespie   /* There's no standard way to compute the isa number (e.g. for arm thumb)
519*f7cc78ecSespie      so we leave it to the target.  */
520*f7cc78ecSespie #ifdef CGEN_COMPUTE_ISA
521*f7cc78ecSespie   isa = CGEN_COMPUTE_ISA (info);
522*f7cc78ecSespie #else
523*f7cc78ecSespie   isa = 0;
524*f7cc78ecSespie #endif
525*f7cc78ecSespie 
526*f7cc78ecSespie   mach = info->mach;
527*f7cc78ecSespie 
528*f7cc78ecSespie   /* If we've switched cpu's, close the current table and open a new one.  */
529*f7cc78ecSespie   if (cd
530*f7cc78ecSespie       && (isa != prev_isa
531*f7cc78ecSespie 	  || mach != prev_mach
532*f7cc78ecSespie 	  || endian != prev_endian))
533fddef416Sniklas     {
534*f7cc78ecSespie       m32r_cgen_cpu_close (cd);
535*f7cc78ecSespie       cd = 0;
536fddef416Sniklas     }
537fddef416Sniklas 
538*f7cc78ecSespie   /* If we haven't initialized yet, initialize the opcode table.  */
539*f7cc78ecSespie   if (! cd)
540fddef416Sniklas     {
541*f7cc78ecSespie       const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
542*f7cc78ecSespie       const char *mach_name;
543*f7cc78ecSespie 
544*f7cc78ecSespie       if (!arch_type)
545*f7cc78ecSespie 	abort ();
546*f7cc78ecSespie       mach_name = arch_type->printable_name;
547*f7cc78ecSespie 
548*f7cc78ecSespie       prev_isa = isa;
549*f7cc78ecSespie       prev_mach = mach;
550*f7cc78ecSespie       prev_endian = endian;
551*f7cc78ecSespie       cd = m32r_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
552*f7cc78ecSespie 				 CGEN_CPU_OPEN_BFDMACH, mach_name,
553*f7cc78ecSespie 				 CGEN_CPU_OPEN_ENDIAN, prev_endian,
554*f7cc78ecSespie 				 CGEN_CPU_OPEN_END);
555*f7cc78ecSespie       if (!cd)
556*f7cc78ecSespie 	abort ();
557*f7cc78ecSespie       m32r_cgen_init_dis (cd);
558fddef416Sniklas     }
559fddef416Sniklas 
560fddef416Sniklas   /* We try to have as much common code as possible.
561fddef416Sniklas      But at this point some targets need to take over.  */
562fddef416Sniklas   /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
563*f7cc78ecSespie      but if not possible try to move this hook elsewhere rather than
564fddef416Sniklas      have two hooks.  */
565*f7cc78ecSespie   length = CGEN_PRINT_INSN (cd, pc, info);
566*f7cc78ecSespie   if (length > 0)
567fddef416Sniklas     return length;
568*f7cc78ecSespie   if (length < 0)
569*f7cc78ecSespie     return -1;
570fddef416Sniklas 
571fddef416Sniklas   (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
572*f7cc78ecSespie   return cd->default_insn_bitsize / 8;
573fddef416Sniklas }
574