* cgen-dis.in (print_normal): CGEN_OPERAND_FAKE renamed to
[platform/upstream/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 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 "m32r-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 /* -- dis.c */
65
66 /* Immediate values are prefixed with '#'.  */
67
68 #define CGEN_PRINT_NORMAL(od, info, value, attrs, pc, length) \
69 do { \
70   if ((attrs) & (1 << CGEN_OPERAND_HASH_PREFIX)) \
71     (*info->fprintf_func) (info->stream, "#"); \
72 } while (0)
73
74 /* Handle '#' prefixes as operands.  */
75
76 static void
77 print_hash (od, dis_info, value, attrs, pc, length)
78      CGEN_OPCODE_DESC od;
79      PTR dis_info;
80      long value;
81      unsigned int attrs;
82      bfd_vma pc;
83      int length;
84 {
85   disassemble_info *info = dis_info;
86   (*info->fprintf_func) (info->stream, "#");
87 }
88
89 #undef CGEN_PRINT_INSN
90 #define CGEN_PRINT_INSN my_print_insn
91
92 static int
93 my_print_insn (od, pc, info)
94      CGEN_OPCODE_DESC od;
95      bfd_vma pc;
96      disassemble_info *info;
97 {
98   char buffer[CGEN_MAX_INSN_SIZE];
99   char *buf = buffer;
100   int status;
101   int buflen = (pc & 3) == 0 ? 4 : 2;
102
103   /* Read the base part of the insn.  */
104
105   status = (*info->read_memory_func) (pc, buf, buflen, info);
106   if (status != 0)
107     {
108       (*info->memory_error_func) (status, pc, info);
109       return -1;
110     }
111
112   /* 32 bit insn?  */
113   if ((pc & 3) == 0 && (buf[0] & 0x80) != 0)
114     return print_insn (od, pc, info, buf, buflen);
115
116   /* Print the first insn.  */
117   if ((pc & 3) == 0)
118     {
119       if (print_insn (od, pc, info, buf, 2) == 0)
120         (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
121       buf += 2;
122     }
123
124   if (buf[0] & 0x80)
125     {
126       /* Parallel.  */
127       (*info->fprintf_func) (info->stream, " || ");
128       buf[0] &= 0x7f;
129     }
130   else
131     (*info->fprintf_func) (info->stream, " -> ");
132
133   /* The "& 3" is to pass a consistent address.
134      Parallel insns arguably both begin on the word boundary.
135      Also, branch insns are calculated relative to the word boundary.  */
136   if (print_insn (od, pc & ~ (bfd_vma) 3, info, buf, 2) == 0)
137     (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
138
139   return (pc & 3) ? 2 : 4;
140 }
141
142 /* -- */
143
144 /* Main entry point for operand extraction.
145
146    This function is basically just a big switch statement.  Earlier versions
147    used tables to look up the function to use, but
148    - if the table contains both assembler and disassembler functions then
149      the disassembler contains much of the assembler and vice-versa,
150    - there's a lot of inlining possibilities as things grow,
151    - using a switch statement avoids the function call overhead.
152
153    This function could be moved into `print_insn_normal', but keeping it
154    separate makes clear the interface between `print_insn_normal' and each of
155    the handlers.
156 */
157
158 int
159 m32r_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc)
160      CGEN_OPCODE_DESC od;
161      int opindex;
162      CGEN_EXTRACT_INFO *ex_info;
163      CGEN_INSN_BYTES insn_value;
164      CGEN_FIELDS * fields;
165      bfd_vma pc;
166 {
167   int length;
168
169   switch (opindex)
170     {
171     case M32R_OPERAND_SR :
172       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_r2);
173       break;
174     case M32R_OPERAND_DR :
175       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_r1);
176       break;
177     case M32R_OPERAND_SRC1 :
178       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_r1);
179       break;
180     case M32R_OPERAND_SRC2 :
181       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_r2);
182       break;
183     case M32R_OPERAND_SCR :
184       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_r2);
185       break;
186     case M32R_OPERAND_DCR :
187       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_r1);
188       break;
189     case M32R_OPERAND_SIMM8 :
190       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 8, 8, CGEN_FIELDS_BITSIZE (fields), & fields->f_simm8);
191       break;
192     case M32R_OPERAND_SIMM16 :
193       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX), 16, 16, CGEN_FIELDS_BITSIZE (fields), & fields->f_simm16);
194       break;
195     case M32R_OPERAND_UIMM4 :
196       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm4);
197       break;
198     case M32R_OPERAND_UIMM5 :
199       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 11, 5, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm5);
200       break;
201     case M32R_OPERAND_UIMM16 :
202       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm16);
203       break;
204 /* start-sanitize-m32rx */
205     case M32R_OPERAND_IMM1 :
206       {
207         long value;
208         length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), 15, 1, CGEN_FIELDS_BITSIZE (fields), & value);
209         value = ((value) + (1));
210         fields->f_imm1 = value;
211       }
212       break;
213 /* end-sanitize-m32rx */
214 /* start-sanitize-m32rx */
215     case M32R_OPERAND_ACCD :
216       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 2, CGEN_FIELDS_BITSIZE (fields), & fields->f_accd);
217       break;
218 /* end-sanitize-m32rx */
219 /* start-sanitize-m32rx */
220     case M32R_OPERAND_ACCS :
221       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 2, CGEN_FIELDS_BITSIZE (fields), & fields->f_accs);
222       break;
223 /* end-sanitize-m32rx */
224 /* start-sanitize-m32rx */
225     case M32R_OPERAND_ACC :
226       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 8, 1, CGEN_FIELDS_BITSIZE (fields), & fields->f_acc);
227       break;
228 /* end-sanitize-m32rx */
229     case M32R_OPERAND_HASH :
230       length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_nil);
231       break;
232     case M32R_OPERAND_HI16 :
233       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, CGEN_FIELDS_BITSIZE (fields), & fields->f_hi16);
234       break;
235     case M32R_OPERAND_SLO16 :
236       length = extract_normal (od, ex_info, insn_value, 0, 16, 16, CGEN_FIELDS_BITSIZE (fields), & fields->f_simm16);
237       break;
238     case M32R_OPERAND_ULO16 :
239       length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, CGEN_FIELDS_BITSIZE (fields), & fields->f_uimm16);
240       break;
241     case M32R_OPERAND_UIMM24 :
242       length = extract_normal (od, ex_info, 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);
243       break;
244     case M32R_OPERAND_DISP8 :
245       {
246         long value;
247         length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 8, CGEN_FIELDS_BITSIZE (fields), & value);
248         value = ((((value) << (2))) + (((pc) & (-4))));
249         fields->f_disp8 = value;
250       }
251       break;
252     case M32R_OPERAND_DISP16 :
253       {
254         long value;
255         length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 16, 16, CGEN_FIELDS_BITSIZE (fields), & value);
256         value = ((((value) << (2))) + (pc));
257         fields->f_disp16 = value;
258       }
259       break;
260     case M32R_OPERAND_DISP24 :
261       {
262         long value;
263         length = extract_normal (od, ex_info, insn_value, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 24, CGEN_FIELDS_BITSIZE (fields), & value);
264         value = ((((value) << (2))) + (pc));
265         fields->f_disp24 = value;
266       }
267       break;
268
269     default :
270       /* xgettext:c-format */
271       fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
272                opindex);
273       abort ();
274     }
275
276   return length;
277 }
278
279 /* Main entry point for printing operands.
280
281    This function is basically just a big switch statement.  Earlier versions
282    used tables to look up the function to use, but
283    - if the table contains both assembler and disassembler functions then
284      the disassembler contains much of the assembler and vice-versa,
285    - there's a lot of inlining possibilities as things grow,
286    - using a switch statement avoids the function call overhead.
287
288    This function could be moved into `print_insn_normal', but keeping it
289    separate makes clear the interface between `print_insn_normal' and each of
290    the handlers.
291 */
292
293 void
294 m32r_cgen_print_operand (od, opindex, info, fields, attrs, pc, length)
295      CGEN_OPCODE_DESC od;
296      int opindex;
297      disassemble_info * info;
298      CGEN_FIELDS * fields;
299      void const * attrs;
300      bfd_vma pc;
301      int length;
302 {
303   switch (opindex)
304     {
305     case M32R_OPERAND_SR :
306       print_keyword (od, info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
307       break;
308     case M32R_OPERAND_DR :
309       print_keyword (od, info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
310       break;
311     case M32R_OPERAND_SRC1 :
312       print_keyword (od, info, & m32r_cgen_opval_h_gr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
313       break;
314     case M32R_OPERAND_SRC2 :
315       print_keyword (od, info, & m32r_cgen_opval_h_gr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
316       break;
317     case M32R_OPERAND_SCR :
318       print_keyword (od, info, & m32r_cgen_opval_h_cr, fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED));
319       break;
320     case M32R_OPERAND_DCR :
321       print_keyword (od, info, & m32r_cgen_opval_h_cr, fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED));
322       break;
323     case M32R_OPERAND_SIMM8 :
324       print_normal (od, info, fields->f_simm8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
325       break;
326     case M32R_OPERAND_SIMM16 :
327       print_normal (od, info, fields->f_simm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
328       break;
329     case M32R_OPERAND_UIMM4 :
330       print_normal (od, info, fields->f_uimm4, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
331       break;
332     case M32R_OPERAND_UIMM5 :
333       print_normal (od, info, fields->f_uimm5, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
334       break;
335     case M32R_OPERAND_UIMM16 :
336       print_normal (od, info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
337       break;
338 /* start-sanitize-m32rx */
339     case M32R_OPERAND_IMM1 :
340       print_normal (od, info, fields->f_imm1, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
341       break;
342 /* end-sanitize-m32rx */
343 /* start-sanitize-m32rx */
344     case M32R_OPERAND_ACCD :
345       print_keyword (od, info, & m32r_cgen_opval_h_accums, fields->f_accd, 0|(1<<CGEN_OPERAND_UNSIGNED));
346       break;
347 /* end-sanitize-m32rx */
348 /* start-sanitize-m32rx */
349     case M32R_OPERAND_ACCS :
350       print_keyword (od, info, & m32r_cgen_opval_h_accums, fields->f_accs, 0|(1<<CGEN_OPERAND_UNSIGNED));
351       break;
352 /* end-sanitize-m32rx */
353 /* start-sanitize-m32rx */
354     case M32R_OPERAND_ACC :
355       print_keyword (od, info, & m32r_cgen_opval_h_accums, fields->f_acc, 0|(1<<CGEN_OPERAND_UNSIGNED));
356       break;
357 /* end-sanitize-m32rx */
358     case M32R_OPERAND_HASH :
359       print_hash (od, info, fields->f_nil, 0, pc, length);
360       break;
361     case M32R_OPERAND_HI16 :
362       print_normal (od, info, fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
363       break;
364     case M32R_OPERAND_SLO16 :
365       print_normal (od, info, fields->f_simm16, 0, pc, length);
366       break;
367     case M32R_OPERAND_ULO16 :
368       print_normal (od, info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), pc, length);
369       break;
370     case M32R_OPERAND_UIMM24 :
371       print_address (od, 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);
372       break;
373     case M32R_OPERAND_DISP8 :
374       print_address (od, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
375       break;
376     case M32R_OPERAND_DISP16 :
377       print_address (od, info, fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
378       break;
379     case M32R_OPERAND_DISP24 :
380       print_address (od, info, fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
381       break;
382
383     default :
384       /* xgettext:c-format */
385       fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
386                opindex);
387     abort ();
388   }
389 }
390
391 cgen_extract_fn * const m32r_cgen_extract_handlers[] = 
392 {
393   0, /* default */
394   extract_insn_normal,
395 };
396
397 cgen_print_fn * const m32r_cgen_print_handlers[] = 
398 {
399   0, /* default */
400   print_insn_normal,
401 };
402
403
404 void
405 m32r_cgen_init_dis (od)
406      CGEN_OPCODE_DESC od;
407 {
408 }
409
410 \f
411 #if ! CGEN_INT_INSN_P
412
413 /* Subroutine of extract_normal.  */
414
415 static INLINE long
416 extract_1 (od, ex_info, start, length, word_length, bufp)
417      CGEN_OPCODE_DESC od;
418      CGEN_EXTRACT_INFO *info;
419      int start,length,word_length;
420      unsigned char *bufp;
421 {
422   unsigned long x,mask;
423   int shift;
424   int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG;
425
426   /* FIXME: Need to use ex_info to ensure bytes have been fetched.  */
427
428   switch (word_length)
429     {
430     case 8:
431       x = *bufp;
432       break;
433     case 16:
434       if (big_p)
435         x = bfd_getb16 (bufp);
436       else
437         x = bfd_getl16 (bufp);
438       break;
439     case 24:
440       /* ??? This may need reworking as these cases don't necessarily
441          want the first byte and the last two bytes handled like this.  */
442       if (big_p)
443         x = (bfd_getb8 (bufp) << 16) | bfd_getb16 (bufp + 1);
444       else
445         x = bfd_getl16 (bufp) | (bfd_getb8 (bufp + 2) << 16);
446       break;
447     case 32:
448       if (big_p)
449         x = bfd_getb32 (bufp);
450       else
451         x = bfd_getl32 (bufp);
452       break;
453     default :
454       abort ();
455     }
456
457   /* Written this way to avoid undefined behaviour.  */
458   mask = (((1L << (length - 1)) - 1) << 1) | 1;
459   if (CGEN_INSN_LSB0_P)
460     shift = start;
461   else
462     shift = (word_length - (start + length));
463   return (x >> shift) & mask;
464 }
465
466 #endif /* ! CGEN_INT_INSN_P */
467
468 /* Default extraction routine.
469
470    ATTRS is a mask of the boolean attributes.  We only need `unsigned',
471    but for generality we take a bitmask of all of them.  */
472
473 /* ??? This doesn't handle bfd_vma's.  Create another function when
474    necessary.  */
475
476 static int
477 extract_normal (od, ex_info, insn_value, attrs, start, length, total_length, valuep)
478      CGEN_OPCODE_DESC od;
479      CGEN_EXTRACT_INFO *ex_info;
480      CGEN_INSN_BYTES insn_value;
481      unsigned int attrs;
482      int start, length, total_length;
483      long *valuep;
484 {
485   unsigned long value;
486
487   /* If LENGTH is zero, this operand doesn't contribute to the value
488      so give it a standard value of zero.  */
489   if (length == 0)
490     {
491       *valuep = 0;
492       return 1;
493     }
494
495 #if CGEN_INT_INSN_P
496
497   {
498     /* Written this way to avoid undefined behaviour.  */
499     unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
500
501     if (CGEN_INSN_LSB0_P)
502       value = insn_value >> start;
503     else
504       value = insn_value >> (total_length - (start + length));
505     value &= mask;
506     /* sign extend? */
507     if (! (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED))
508         && (value & (1L << (length - 1))))
509       value |= ~mask;
510   }
511
512 #else
513
514   /* The hard case is probably too slow for the normal cases.
515      It's certainly more difficult to understand than the normal case.
516      Thus this is split into two.  Keep it that way.  The hard case is defined
517      to be when a field straddles a (loosely defined) word boundary
518      (??? which may require target specific help to determine).  */
519
520 #if 0 /*wip*/
521
522 #define HARD_CASE_P 0 /* FIXME:wip */
523
524   if (HARD_CASE_P)
525     {
526     }
527 #endif
528   else
529     {
530       unsigned char *bufp = (unsigned char *) insn_value;
531
532       if (length > 32)
533         abort ();
534
535       /* Adjust start,total_length,bufp to point to the pseudo-word that holds
536          the value.  For example in a 48 bit insn where the value to insert
537          (say an immediate value) is the last 16 bits then word_length here
538          would be 16.  To handle a 24 bit insn with an 18 bit immediate,
539          extract_1 handles 24 bits (using a combination of bfd_get8,16).  */
540
541       if (total_length > 32)
542         {
543           int needed_width = start % 8 + length;
544           int fetch_length = (needed_width <= 8 ? 8
545                               : needed_width <= 16 ? 16
546                               : 32);
547
548           if (CGEN_INSN_LSB0_P)
549             {
550               if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
551                 {
552                   abort (); /* wip */
553                 }
554               else
555                 {
556                   int offset = start & ~7;
557
558                   bufp += offset / 8;
559                   start -= offset;
560                   total_length -= offset;
561                 }
562             }
563           else
564             {
565               if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG)
566                 {
567                   int offset = start & ~7;
568
569                   bufp += offset / 8;
570                   start -= offset;
571                   total_length -= offset;
572                 }
573               else
574                 {
575                   abort (); /* wip */
576                 }
577             }
578         }
579
580       /* FIXME: which bytes are being extracted have been lost.  */
581       value = extract_1 (od, ex_info, start, length, total_length, bufp);
582     }
583
584 #endif /* ! CGEN_INT_INSN_P */
585
586   *valuep = value;
587
588   /* FIXME: for now */
589   return 1;
590 }
591
592 /* Default print handler.  */
593
594 static void
595 print_normal (od, dis_info, value, attrs, pc, length)
596      CGEN_OPCODE_DESC od;
597      PTR dis_info;
598      long value;
599      unsigned int attrs;
600      bfd_vma pc;
601      int length;
602 {
603   disassemble_info *info = (disassemble_info *) dis_info;
604
605 #ifdef CGEN_PRINT_NORMAL
606   CGEN_PRINT_NORMAL (od, info, value, attrs, pc, length);
607 #endif
608
609   /* Print the operand as directed by the attributes.  */
610   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
611     ; /* nothing to do */
612   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
613     (*info->fprintf_func) (info->stream, "0x%lx", value);
614   else
615     (*info->fprintf_func) (info->stream, "%ld", value);
616 }
617
618 /* Default address handler.  */
619
620 static void
621 print_address (od, dis_info, value, attrs, pc, length)
622      CGEN_OPCODE_DESC od;
623      PTR dis_info;
624      bfd_vma value;
625      unsigned int attrs;
626      bfd_vma pc;
627      int length;
628 {
629   disassemble_info *info = (disassemble_info *) dis_info;
630
631 #ifdef CGEN_PRINT_ADDRESS
632   CGEN_PRINT_ADDRESS (od, info, value, attrs, pc, length);
633 #endif
634
635   /* Print the operand as directed by the attributes.  */
636   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
637     ; /* nothing to do */
638   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
639     (*info->print_address_func) (value, info);
640   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
641     (*info->print_address_func) (value, info);
642   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED))
643     (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
644   else
645     (*info->fprintf_func) (info->stream, "%ld", (long) value);
646 }
647
648 /* Keyword print handler.  */
649
650 static void
651 print_keyword (od, dis_info, keyword_table, value, attrs)
652      CGEN_OPCODE_DESC od;
653      PTR dis_info;
654      CGEN_KEYWORD *keyword_table;
655      long value;
656      unsigned int attrs;
657 {
658   disassemble_info *info = (disassemble_info *) dis_info;
659   const CGEN_KEYWORD_ENTRY *ke;
660
661   ke = cgen_keyword_lookup_value (keyword_table, value);
662   if (ke != NULL)
663     (*info->fprintf_func) (info->stream, "%s", ke->name);
664   else
665     (*info->fprintf_func) (info->stream, "???");
666 }
667 \f
668 /* Default insn extractor.
669
670    INSN_VALUE is the first CGEN_BASE_INSN_SIZE bytes, translated to host order.
671    The extracted fields are stored in FIELDS.
672    EX_INFO is used to handle reading variable length insns.
673    Return the length of the insn in bits, or 0 if no match,
674    or -1 if an error occurs fetching data (memory_error_func will have
675    been called).  */
676
677 static int
678 extract_insn_normal (od, insn, ex_info, insn_value, fields, pc)
679      CGEN_OPCODE_DESC od;
680      const CGEN_INSN *insn;
681      CGEN_EXTRACT_INFO *ex_info;
682      unsigned long insn_value;
683      CGEN_FIELDS *fields;
684      bfd_vma pc;
685 {
686   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
687   const unsigned char *syn;
688
689   CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
690
691   CGEN_INIT_EXTRACT (od);
692
693   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
694     {
695       int length;
696
697       if (CGEN_SYNTAX_CHAR_P (*syn))
698         continue;
699
700       length = m32r_cgen_extract_operand (od, CGEN_SYNTAX_FIELD (*syn),
701                                             ex_info, insn_value, fields, pc);
702       if (length <= 0)
703         return length;
704     }
705
706   /* We recognized and successfully extracted this insn.  */
707   return CGEN_INSN_BITSIZE (insn);
708 }
709
710 /* Default insn printer.
711
712    DIS_INFO is defined as `PTR' so the disassembler needn't know anything
713    about disassemble_info.  */
714
715 static void
716 print_insn_normal (od, dis_info, insn, fields, pc, length)
717      CGEN_OPCODE_DESC od;
718      PTR dis_info;
719      const CGEN_INSN *insn;
720      CGEN_FIELDS *fields;
721      bfd_vma pc;
722      int length;
723 {
724   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
725   disassemble_info *info = (disassemble_info *) dis_info;
726   const unsigned char *syn;
727
728   CGEN_INIT_PRINT (od);
729
730   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
731     {
732       if (CGEN_SYNTAX_MNEMONIC_P (*syn))
733         {
734           (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
735           continue;
736         }
737       if (CGEN_SYNTAX_CHAR_P (*syn))
738         {
739           (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
740           continue;
741         }
742
743       /* We have an operand.  */
744       m32r_cgen_print_operand (od, CGEN_SYNTAX_FIELD (*syn), info,
745                                  fields, CGEN_INSN_ATTRS (insn), pc, length);
746     }
747 }
748 \f
749 /* Utility to print an insn.
750    BUF is the base part of the insn, target byte order, BUFLEN bytes long.
751    The result is the size of the insn in bytes or zero for an unknown insn
752    or -1 if an error occurs fetching data (memory_error_func will have
753    been called).  */
754
755 static int
756 print_insn (od, pc, info, buf, buflen)
757      CGEN_OPCODE_DESC od;
758      bfd_vma pc;
759      disassemble_info *info;
760      char *buf;
761      int buflen;
762 {
763   unsigned long insn_value;
764   const CGEN_INSN_LIST *insn_list;
765   CGEN_EXTRACT_INFO ex_info;
766
767   ex_info.dis_info = info;
768   ex_info.valid = (1 << CGEN_BASE_INSN_SIZE) - 1;
769   ex_info.bytes = buf;
770
771   switch (buflen)
772     {
773     case 1:
774       insn_value = buf[0];
775       break;
776     case 2:
777       insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb16 (buf) : bfd_getl16 (buf);
778       break;
779     case 4:
780       insn_value = info->endian == BFD_ENDIAN_BIG ? bfd_getb32 (buf) : bfd_getl32 (buf);
781       break;
782     default:
783       abort ();
784     }
785
786   /* The instructions are stored in hash lists.
787      Pick the first one and keep trying until we find the right one.  */
788
789   insn_list = CGEN_DIS_LOOKUP_INSN (od, buf, insn_value);
790   while (insn_list != NULL)
791     {
792       const CGEN_INSN *insn = insn_list->insn;
793       CGEN_FIELDS fields;
794       int length;
795
796 #if 0 /* not needed as insn shouldn't be in hash lists if not supported */
797       /* Supported by this cpu?  */
798       if (! m32r_cgen_insn_supported (od, insn))
799         continue;
800 #endif
801
802       /* Basic bit mask must be correct.  */
803       /* ??? May wish to allow target to defer this check until the extract
804          handler.  */
805       if ((insn_value & CGEN_INSN_MASK (insn)) == CGEN_INSN_VALUE (insn))
806         {
807           /* Printing is handled in two passes.  The first pass parses the
808              machine insn and extracts the fields.  The second pass prints
809              them.  */
810
811           length = (*CGEN_EXTRACT_FN (insn)) (od, insn, &ex_info, insn_value,
812                                               &fields, pc);
813           /* length < 0 -> error */
814           if (length < 0)
815             return length;
816           if (length > 0)
817             {
818               (*CGEN_PRINT_FN (insn)) (od, info, insn, &fields, pc, length);
819               /* length is in bits, result is in bytes */
820               return length / 8;
821             }
822         }
823
824       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
825     }
826
827   return 0;
828 }
829
830 /* Default value for CGEN_PRINT_INSN.
831    The result is the size of the insn in bytes or zero for an unknown insn
832    or -1 if an error occured fetching bytes.  */
833
834 #ifndef CGEN_PRINT_INSN
835 #define CGEN_PRINT_INSN default_print_insn
836 #endif
837
838 static int
839 default_print_insn (od, pc, info)
840      CGEN_OPCODE_DESC od;
841      bfd_vma pc;
842      disassemble_info *info;
843 {
844   char buf[CGEN_MAX_INSN_SIZE];
845   int status;
846
847   /* Read the base part of the insn.  */
848
849   status = (*info->read_memory_func) (pc, buf, CGEN_BASE_INSN_SIZE, info);
850   if (status != 0)
851     {
852       (*info->memory_error_func) (status, pc, info);
853       return -1;
854     }
855
856   return print_insn (od, pc, info, buf, CGEN_BASE_INSN_SIZE);
857 }
858
859 /* Main entry point.
860    Print one instruction from PC on INFO->STREAM.
861    Return the size of the instruction (in bytes).  */
862
863 int
864 print_insn_m32r (pc, info)
865      bfd_vma pc;
866      disassemble_info *info;
867 {
868   int length;
869   static CGEN_OPCODE_DESC od = 0;
870   int mach = info->mach;
871   int big_p = info->endian == BFD_ENDIAN_BIG;
872
873   /* If we haven't initialized yet, initialize the opcode table.  */
874   if (! od)
875     {
876       od = m32r_cgen_opcode_open (mach,
877                                     big_p ?
878                                     CGEN_ENDIAN_BIG
879                                     : CGEN_ENDIAN_LITTLE);
880       m32r_cgen_init_dis (od);
881     }
882   /* If we've switched cpu's, re-initialize.  */
883   /* ??? Perhaps we should use BFD_ENDIAN.  */
884   else if (mach != CGEN_OPCODE_MACH (od)
885            || (CGEN_OPCODE_ENDIAN (od)
886                != (big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE)))
887     {
888       cgen_set_cpu (od, mach, big_p ? CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE);
889     }
890
891   /* We try to have as much common code as possible.
892      But at this point some targets need to take over.  */
893   /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
894      but if not possible try to move this hook elsewhere rather than
895      have two hooks.  */
896   length = CGEN_PRINT_INSN (od, pc, info);
897   if (length > 0)
898     return length;
899   if (length < 0)
900     return -1;
901
902   (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
903   return CGEN_DEFAULT_INSN_SIZE;
904 }