aboutsummaryrefslogtreecommitdiff
path: root/opcodes/disassemble.c
blob: d5b17be325318277a8eca3555d2ffe1c55ab7904 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
/* Select disassembly routine for specified architecture.
   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
   Free Software Foundation, Inc.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */

#include "sysdep.h"
#include "dis-asm.h"

#ifdef ARCH_all
#define ARCH_a29k
#define ARCH_alpha
#define ARCH_arc
#define ARCH_arm
#define ARCH_avr
#define ARCH_cris
#define ARCH_d10v
#define ARCH_d30v
#define ARCH_dlx
#define ARCH_h8300
#define ARCH_h8500
#define ARCH_hppa
#define ARCH_i370
#define ARCH_i386
#define ARCH_i860
#define ARCH_i960
#define ARCH_ip2k
#define ARCH_ia64
#define ARCH_fr30
#define ARCH_m32r
#define ARCH_m68k
#define ARCH_m68hc11
#define ARCH_m68hc12
#define ARCH_m88k
#define ARCH_mcore
#define ARCH_mips
#define ARCH_mmix
#define ARCH_mn10200
#define ARCH_mn10300
#define ARCH_msp430
#define ARCH_ns32k
#define ARCH_openrisc
#define ARCH_or32
#define ARCH_pdp11
#define ARCH_pj
#define ARCH_powerpc
#define ARCH_rs6000
#define ARCH_s390
#define ARCH_sh
#define ARCH_sparc
#define ARCH_tic30
#define ARCH_tic4x
#define ARCH_tic54x
#define ARCH_tic80
#define ARCH_v850
#define ARCH_vax
#define ARCH_w65
#define ARCH_xstormy16
#define ARCH_xtensa
#define ARCH_z8k
#define ARCH_frv
#define ARCH_iq2000
#define INCLUDE_SHMEDIA
#endif


disassembler_ftype
disassembler (abfd)
     bfd *abfd;
{
  enum bfd_architecture a = bfd_get_arch (abfd);
  disassembler_ftype disassemble;

  switch (a)
    {
      /* If you add a case to this table, also add it to the
	 ARCH_all definition right above this function.  */
#ifdef ARCH_a29k
    case bfd_arch_a29k:
      /* As far as I know we only handle big-endian 29k objects.  */
      disassemble = print_insn_big_a29k;
      break;
#endif
#ifdef ARCH_alpha
    case bfd_arch_alpha:
      disassemble = print_insn_alpha;
      break;
#endif
#ifdef ARCH_arc
    case bfd_arch_arc:
      {
	disassemble = arc_get_disassembler (abfd);
	break;
      }
#endif
#ifdef ARCH_arm
    case bfd_arch_arm:
      if (bfd_big_endian (abfd))
	disassemble = print_insn_big_arm;
      else
	disassemble = print_insn_little_arm;
      break;
#endif
#ifdef ARCH_avr
    case bfd_arch_avr:
      disassemble = print_insn_avr;
      break;
#endif
#ifdef ARCH_cris
    case bfd_arch_cris:
      disassemble = cris_get_disassembler (abfd);
      break;
#endif
#ifdef ARCH_d10v
    case bfd_arch_d10v:
      disassemble = print_insn_d10v;
      break;
#endif
#ifdef ARCH_d30v
    case bfd_arch_d30v:
      disassemble = print_insn_d30v;
      break;
#endif
#ifdef ARCH_dlx
    case bfd_arch_dlx:
      /* As far as I know we only handle big-endian DLX objects.  */
      disassemble = print_insn_dlx;
      break;
#endif
#ifdef ARCH_h8300
    case bfd_arch_h8300:
      if (bfd_get_mach (abfd) == bfd_mach_h8300h
	  || bfd_get_mach (abfd) == bfd_mach_h8300hn)
	disassemble = print_insn_h8300h;
      else if (bfd_get_mach (abfd) == bfd_mach_h8300s
	       || bfd_get_mach (abfd) == bfd_mach_h8300sn
	       || bfd_get_mach (abfd) == bfd_mach_h8300sx)
	disassemble = print_insn_h8300s;
      else
	disassemble = print_insn_h8300;
      break;
#endif
#ifdef ARCH_h8500
    case bfd_arch_h8500:
      disassemble = print_insn_h8500;
      break;
#endif
#ifdef ARCH_hppa
    case bfd_arch_hppa:
      disassemble = print_insn_hppa;
      break;
#endif
#ifdef ARCH_i370
    case bfd_arch_i370:
      disassemble = print_insn_i370;
      break;
#endif
#ifdef ARCH_i386
    case bfd_arch_i386:
      disassemble = print_insn_i386;
      break;
#endif
#ifdef ARCH_i860
    case bfd_arch_i860:
      disassemble = print_insn_i860;
      break;
#endif
#ifdef ARCH_i960
    case bfd_arch_i960:
      disassemble = print_insn_i960;
      break;
#endif
#ifdef ARCH_ia64
    case bfd_arch_ia64:
      disassemble = print_insn_ia64;
      break;
#endif
#ifdef ARCH_ip2k
    case bfd_arch_ip2k:
      disassemble = print_insn_ip2k;
      break;
#endif
#ifdef ARCH_fr30
    case bfd_arch_fr30:
      disassemble = print_insn_fr30;
      break;
#endif
#ifdef ARCH_m32r
    case bfd_arch_m32r:
      disassemble = print_insn_m32r;
      break;
#endif
#if defined(ARCH_m68hc11) || defined(ARCH_m68hc12)
    case bfd_arch_m68hc11:
      disassemble = print_insn_m68hc11;
      break;
    case bfd_arch_m68hc12:
      disassemble = print_insn_m68hc12;
      break;
#endif
#ifdef ARCH_m68k
    case bfd_arch_m68k:
      disassemble = print_insn_m68k;
      break;
#endif
#ifdef ARCH_m88k
    case bfd_arch_m88k:
      disassemble = print_insn_m88k;
      break;
#endif
#ifdef ARCH_msp430
    case bfd_arch_msp430:
      disassemble = print_insn_msp430;
      break;
#endif
#ifdef ARCH_ns32k
    case bfd_arch_ns32k:
      disassemble = print_insn_ns32k;
      break;
#endif
#ifdef ARCH_mcore
    case bfd_arch_mcore:
      disassemble = print_insn_mcore;
      break;
#endif
#ifdef ARCH_mips
    case bfd_arch_mips:
      if (bfd_big_endian (abfd))
	disassemble = print_insn_big_mips;
      else
	disassemble = print_insn_little_mips;
      break;
#endif
#ifdef ARCH_mmix
    case bfd_arch_mmix:
      disassemble = print_insn_mmix;
      break;
#endif
#ifdef ARCH_mn10200
    case bfd_arch_mn10200:
      disassemble = print_insn_mn10200;
      break;
#endif
#ifdef ARCH_mn10300
    case bfd_arch_mn10300:
      disassemble = print_insn_mn10300;
      break;
#endif
#ifdef ARCH_openrisc
    case bfd_arch_openrisc:
      disassemble = print_insn_openrisc;
      break;
#endif
#ifdef ARCH_or32
    case bfd_arch_or32:
      if (bfd_big_endian (abfd))
        disassemble = print_insn_big_or32;
      else
        disassemble = print_insn_little_or32;
      break;
#endif
#ifdef ARCH_pdp11
    case bfd_arch_pdp11:
      disassemble = print_insn_pdp11;
      break;
#endif
#ifdef ARCH_pj
    case bfd_arch_pj:
      disassemble = print_insn_pj;
      break;
#endif
#ifdef ARCH_powerpc
    case bfd_arch_powerpc:
      if (bfd_big_endian (abfd))
	disassemble = print_insn_big_powerpc;
      else
	disassemble = print_insn_little_powerpc;
      break;
#endif
#ifdef ARCH_rs6000
    case bfd_arch_rs6000:
      if (bfd_get_mach (abfd) == bfd_mach_ppc_620)
	disassemble = print_insn_big_powerpc;
      else
	disassemble = print_insn_rs6000;
      break;
#endif
#ifdef ARCH_s390
    case bfd_arch_s390:
      disassemble = print_insn_s390;
      break;
#endif
#ifdef ARCH_sh
    case bfd_arch_sh:
      disassemble = print_insn_sh;
      break;
#endif
#ifdef ARCH_sparc
    case bfd_arch_sparc:
      disassemble = print_insn_sparc;
      break;
#endif
#ifdef ARCH_tic30
    case bfd_arch_tic30:
      disassemble = print_insn_tic30;
      break;
#endif
#ifdef ARCH_tic4x
    case bfd_arch_tic4x:
      disassemble = print_insn_tic4x;
      break;
#endif
#ifdef ARCH_tic54x
    case bfd_arch_tic54x:
      disassemble = print_insn_tic54x;
      break;
#endif
#ifdef ARCH_tic80
    case bfd_arch_tic80:
      disassemble = print_insn_tic80;
      break;
#endif
#ifdef ARCH_v850
    case bfd_arch_v850:
      disassemble = print_insn_v850;
      break;
#endif
#ifdef ARCH_w65
    case bfd_arch_w65:
      disassemble = print_insn_w65;
      break;
#endif
#ifdef ARCH_xstormy16
    case bfd_arch_xstormy16:
      disassemble = print_insn_xstormy16;
      break;
#endif
#ifdef ARCH_xtensa
    case bfd_arch_xtensa:
      disassemble = print_insn_xtensa;
      break;
#endif
#ifdef ARCH_z8k
    case bfd_arch_z8k:
      if (bfd_get_mach(abfd) == bfd_mach_z8001)
	disassemble = print_insn_z8001;
      else
	disassemble = print_insn_z8002;
      break;
#endif
#ifdef ARCH_vax
    case bfd_arch_vax:
      disassemble = print_insn_vax;
      break;
#endif
#ifdef ARCH_frv
    case bfd_arch_frv:
      disassemble = print_insn_frv;
      break;
#endif
#ifdef ARCH_iq2000
    case bfd_arch_iq2000:
      disassemble = print_insn_iq2000;
      break;
#endif
    default:
      return 0;
    }
  return disassemble;
}

void
disassembler_usage (stream)
     FILE * stream ATTRIBUTE_UNUSED;
{
#ifdef ARCH_arm
  print_arm_disassembler_options (stream);
#endif
#ifdef ARCH_mips
  print_mips_disassembler_options (stream);
#endif
#ifdef ARCH_powerpc
  print_ppc_disassembler_options (stream);
#endif

  return;
}

void
disassemble_init_for_target (struct disassemble_info * info)
{
  if (info == NULL)
    return;

  switch (info->arch)
    {
#ifdef ARCH_arm
    case bfd_arch_arm:
      info->symbol_is_valid = arm_symbol_is_valid;
      break;
#endif
    default:
      break;
    }
}
1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236
/* Instruction building/extraction support for m32r. -*- C -*-

THIS FILE IS MACHINE GENERATED WITH CGEN: Cpu tools GENerator.
- the resultant file is machine generated, cgen-ibld.in isn't

Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.

This file is part of the GNU Binutils and GDB, the GNU debugger.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */

/* ??? Eventually more and more of this stuff can go to cpu-independent files.
   Keep that in mind.  */

#include "sysdep.h"
#include <stdio.h>
#include "ansidecl.h"
#include "dis-asm.h"
#include "bfd.h"
#include "symcat.h"
#include "m32r-desc.h"
#include "m32r-opc.h"
#include "opintl.h"
#include "safe-ctype.h"

#undef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#undef max
#define max(a,b) ((a) > (b) ? (a) : (b))

/* Used by the ifield rtx function.  */
#define FLD(f) (fields->f)

static const char * insert_normal
  (CGEN_CPU_DESC, long, unsigned int, unsigned int, unsigned int,
   unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR);
static const char * insert_insn_normal
  (CGEN_CPU_DESC, const CGEN_INSN *,
   CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
static int extract_normal
  (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
   unsigned int, unsigned int, unsigned int, unsigned int,
   unsigned int, unsigned int, bfd_vma, long *);
static int extract_insn_normal
  (CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
   CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
#if CGEN_INT_INSN_P
static void put_insn_int_value
  (CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT);
#endif
#if ! CGEN_INT_INSN_P
static CGEN_INLINE void insert_1
  (CGEN_CPU_DESC, unsigned long, int, int, int, unsigned char *);
static CGEN_INLINE int fill_cache
  (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *,  int, int, bfd_vma);
static CGEN_INLINE long extract_1
  (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, int, unsigned char *, bfd_vma);
#endif

/* Operand insertion.  */

#if ! CGEN_INT_INSN_P

/* Subroutine of insert_normal.  */

static CGEN_INLINE void
insert_1 (CGEN_CPU_DESC cd,
	  unsigned long value,
	  int start,
	  int length,
	  int word_length,
	  unsigned char *bufp)
{
  unsigned long x,mask;
  int shift;

  x = cgen_get_insn_value (cd, bufp, word_length);

  /* Written this way to avoid undefined behaviour.  */
  mask = (((1L << (length - 1)) - 1) << 1) | 1;
  if (CGEN_INSN_LSB0_P)
    shift = (start + 1) - length;
  else
    shift = (word_length - (start + length));
  x = (x & ~(mask << shift)) | ((value & mask) << shift);

  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
}

#endif /* ! CGEN_INT_INSN_P */

/* Default insertion routine.

   ATTRS is a mask of the boolean attributes.
   WORD_OFFSET is the offset in bits from the start of the insn of the value.
   WORD_LENGTH is the length of the word in bits in which the value resides.
   START is the starting bit number in the word, architecture origin.
   LENGTH is the length of VALUE in bits.
   TOTAL_LENGTH is the total length of the insn in bits.

   The result is an error message or NULL if success.  */

/* ??? This duplicates functionality with bfd's howto table and
   bfd_install_relocation.  */
/* ??? This doesn't handle bfd_vma's.  Create another function when
   necessary.  */

static const char *
insert_normal (CGEN_CPU_DESC cd,
	       long value,
	       unsigned int attrs,
	       unsigned int word_offset,
	       unsigned int start,
	       unsigned int length,
	       unsigned int word_length,
	       unsigned int total_length,
	       CGEN_INSN_BYTES_PTR buffer)
{
  static char errbuf[100];
  /* Written this way to avoid undefined behaviour.  */
  unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;

  /* If LENGTH is zero, this operand doesn't contribute to the value.  */
  if (length == 0)
    return NULL;

#if 0
  if (CGEN_INT_INSN_P
      && word_offset != 0)
    abort ();
#endif

  if (word_length > 32)
    abort ();

  /* For architectures with insns smaller than the base-insn-bitsize,
     word_length may be too big.  */
  if (cd->min_insn_bitsize < cd->base_insn_bitsize)
    {
      if (word_offset == 0
	  && word_length > total_length)
	word_length = total_length;
    }

  /* Ensure VALUE will fit.  */
  if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
    {
      long minval = - (1L << (length - 1));
      unsigned long maxval = mask;
      
      if ((value > 0 && (unsigned long) value > maxval)
	  || value < minval)
	{
	  /* xgettext:c-format */
	  sprintf (errbuf,
		   _("operand out of range (%ld not between %ld and %lu)"),
		   value, minval, maxval);
	  return errbuf;
	}
    }
  else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
    {
      unsigned long maxval = mask;
      
      if ((unsigned long) value > maxval)
	{
	  /* xgettext:c-format */
	  sprintf (errbuf,
		   _("operand out of range (%lu not between 0 and %lu)"),
		   value, maxval);
	  return errbuf;
	}
    }
  else
    {
      if (! cgen_signed_overflow_ok_p (cd))
	{
	  long minval = - (1L << (length - 1));
	  long maxval =   (1L << (length - 1)) - 1;
	  
	  if (value < minval || value > maxval)
	    {
	      sprintf
		/* xgettext:c-format */
		(errbuf, _("operand out of range (%ld not between %ld and %ld)"),
		 value, minval, maxval);
	      return errbuf;
	    }
	}
    }

#if CGEN_INT_INSN_P

  {
    int shift;

    if (CGEN_INSN_LSB0_P)
      shift = (word_offset + start + 1) - length;
    else
      shift = total_length - (word_offset + start + length);
    *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
  }

#else /* ! CGEN_INT_INSN_P */

  {
    unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;

    insert_1 (cd, value, start, length, word_length, bufp);
  }

#endif /* ! CGEN_INT_INSN_P */

  return NULL;
}

/* Default insn builder (insert handler).
   The instruction is recorded in CGEN_INT_INSN_P byte order (meaning
   that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is
   recorded in host byte order, otherwise BUFFER is an array of bytes
   and the value is recorded in target byte order).
   The result is an error message or NULL if success.  */

static const char *
insert_insn_normal (CGEN_CPU_DESC cd,
		    const CGEN_INSN * insn,
		    CGEN_FIELDS * fields,
		    CGEN_INSN_BYTES_PTR buffer,
		    bfd_vma pc)
{
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
  unsigned long value;
  const CGEN_SYNTAX_CHAR_TYPE * syn;

  CGEN_INIT_INSERT (cd);
  value = CGEN_INSN_BASE_VALUE (insn);

  /* If we're recording insns as numbers (rather than a string of bytes),
     target byte order handling is deferred until later.  */

#if CGEN_INT_INSN_P

  put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
		      CGEN_FIELDS_BITSIZE (fields), value);

#else

  cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
		       value);

#endif /* ! CGEN_INT_INSN_P */

  /* ??? It would be better to scan the format's fields.
     Still need to be able to insert a value based on the operand though;
     e.g. storing a branch displacement that got resolved later.
     Needs more thought first.  */

  for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn)
    {
      const char *errmsg;

      if (CGEN_SYNTAX_CHAR_P (* syn))
	continue;

      errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
				       fields, buffer, pc);
      if (errmsg)
	return errmsg;
    }

  return NULL;
}

#if CGEN_INT_INSN_P
/* Cover function to store an insn value into an integral insn.  Must go here
 because it needs <prefix>-desc.h for CGEN_INT_INSN_P.  */

static void
put_insn_int_value (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
		    CGEN_INSN_BYTES_PTR buf,
		    int length,
		    int insn_length,
		    CGEN_INSN_INT value)
{
  /* For architectures with insns smaller than the base-insn-bitsize,
     length may be too big.  */
  if (length > insn_length)
    *buf = value;
  else
    {
      int shift = insn_length - length;
      /* Written this way to avoid undefined behaviour.  */
      CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
      *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
    }
}
#endif

/* Operand extraction.  */

#if ! CGEN_INT_INSN_P

/* Subroutine of extract_normal.
   Ensure sufficient bytes are cached in EX_INFO.
   OFFSET is the offset in bytes from the start of the insn of the value.
   BYTES is the length of the needed value.
   Returns 1 for success, 0 for failure.  */

static CGEN_INLINE int
fill_cache (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
	    CGEN_EXTRACT_INFO *ex_info,
	    int offset,
	    int bytes,
	    bfd_vma pc)
{
  /* It's doubtful that the middle part has already been fetched so
     we don't optimize that case.  kiss.  */
  unsigned int mask;
  disassemble_info *info = (disassemble_info *) ex_info->dis_info;

  /* First do a quick check.  */
  mask = (1 << bytes) - 1;
  if (((ex_info->valid >> offset) & mask) == mask)
    return 1;

  /* Search for the first byte we need to read.  */
  for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
    if (! (mask & ex_info->valid))
      break;

  if (bytes)
    {
      int status;

      pc += offset;
      status = (*info->read_memory_func)
	(pc, ex_info->insn_bytes + offset, bytes, info);

      if (status != 0)
	{
	  (*info->memory_error_func) (status, pc, info);
	  return 0;
	}

      ex_info->valid |= ((1 << bytes) - 1) << offset;
    }

  return 1;
}

/* Subroutine of extract_normal.  */

static CGEN_INLINE long
extract_1 (CGEN_CPU_DESC cd,
	   CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
	   int start,
	   int length,
	   int word_length,
	   unsigned char *bufp,
	   bfd_vma pc ATTRIBUTE_UNUSED)
{
  unsigned long x;
  int shift;
#if 0
  int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
#endif
  x = cgen_get_insn_value (cd, bufp, word_length);

  if (CGEN_INSN_LSB0_P)
    shift = (start + 1) - length;
  else
    shift = (word_length - (start + length));
  return x >> shift;
}

#endif /* ! CGEN_INT_INSN_P */

/* Default extraction routine.

   INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
   or sometimes less for cases like the m32r where the base insn size is 32
   but some insns are 16 bits.
   ATTRS is a mask of the boolean attributes.  We only need `SIGNED',
   but for generality we take a bitmask of all of them.
   WORD_OFFSET is the offset in bits from the start of the insn of the value.
   WORD_LENGTH is the length of the word in bits in which the value resides.
   START is the starting bit number in the word, architecture origin.
   LENGTH is the length of VALUE in bits.
   TOTAL_LENGTH is the total length of the insn in bits.

   Returns 1 for success, 0 for failure.  */

/* ??? The return code isn't properly used.  wip.  */

/* ??? This doesn't handle bfd_vma's.  Create another function when
   necessary.  */

static int
extract_normal (CGEN_CPU_DESC cd,
#if ! CGEN_INT_INSN_P
		CGEN_EXTRACT_INFO *ex_info,
#else
		CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
#endif
		CGEN_INSN_INT insn_value,
		unsigned int attrs,
		unsigned int word_offset,
		unsigned int start,
		unsigned int length,
		unsigned int word_length,
		unsigned int total_length,
#if ! CGEN_INT_INSN_P
		bfd_vma pc,
#else
		bfd_vma pc ATTRIBUTE_UNUSED,
#endif
		long *valuep)
{
  long value, mask;

  /* If LENGTH is zero, this operand doesn't contribute to the value
     so give it a standard value of zero.  */
  if (length == 0)
    {
      *valuep = 0;
      return 1;
    }

#if 0
  if (CGEN_INT_INSN_P
      && word_offset != 0)
    abort ();
#endif

  if (word_length > 32)
    abort ();

  /* For architectures with insns smaller than the insn-base-bitsize,
     word_length may be too big.  */
  if (cd->min_insn_bitsize < cd->base_insn_bitsize)
    {
      if (word_offset == 0
	  && word_length > total_length)
	word_length = total_length;
    }

  /* Does the value reside in INSN_VALUE, and at the right alignment?  */

  if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
    {
      if (CGEN_INSN_LSB0_P)
	value = insn_value >> ((word_offset + start + 1) - length);
      else
	value = insn_value >> (total_length - ( word_offset + start + length));
    }

#if ! CGEN_INT_INSN_P

  else
    {
      unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;

      if (word_length > 32)
	abort ();

      if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
	return 0;

      value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
    }

#endif /* ! CGEN_INT_INSN_P */

  /* Written this way to avoid undefined behaviour.  */
  mask = (((1L << (length - 1)) - 1) << 1) | 1;

  value &= mask;
  /* sign extend? */
  if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
      && (value & (1L << (length - 1))))
    value |= ~mask;

  *valuep = value;

  return 1;
}

/* Default insn extractor.

   INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
   The extracted fields are stored in FIELDS.
   EX_INFO is used to handle reading variable length insns.
   Return the length of the insn in bits, or 0 if no match,
   or -1 if an error occurs fetching data (memory_error_func will have
   been called).  */

static int
extract_insn_normal (CGEN_CPU_DESC cd,
		     const CGEN_INSN *insn,
		     CGEN_EXTRACT_INFO *ex_info,
		     CGEN_INSN_INT insn_value,
		     CGEN_FIELDS *fields,
		     bfd_vma pc)
{
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
  const CGEN_SYNTAX_CHAR_TYPE *syn;

  CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);

  CGEN_INIT_EXTRACT (cd);

  for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
    {
      int length;

      if (CGEN_SYNTAX_CHAR_P (*syn))
	continue;

      length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
					ex_info, insn_value, fields, pc);
      if (length <= 0)
	return length;
    }

  /* We recognized and successfully extracted this insn.  */
  return CGEN_INSN_BITSIZE (insn);
}

/* machine generated code added here */

const char * m32r_cgen_insert_operand
  PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma));

/* Main entry point for operand insertion.

   This function is basically just a big switch statement.  Earlier versions
   used tables to look up the function to use, but
   - if the table contains both assembler and disassembler functions then
     the disassembler contains much of the assembler and vice-versa,
   - there's a lot of inlining possibilities as things grow,
   - using a switch statement avoids the function call overhead.

   This function could be moved into `parse_insn_normal', but keeping it
   separate makes clear the interface between `parse_insn_normal' and each of
   the handlers.  It's also needed by GAS to insert operands that couldn't be
   resolved during parsing.  */

const char *
m32r_cgen_insert_operand (cd, opindex, fields, buffer, pc)
     CGEN_CPU_DESC cd;
     int opindex;
     CGEN_FIELDS * fields;
     CGEN_INSN_BYTES_PTR buffer;
     bfd_vma pc ATTRIBUTE_UNUSED;
{
  const char * errmsg = NULL;
  unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);

  switch (opindex)
    {
    case M32R_OPERAND_ACC :
      errmsg = insert_normal (cd, fields->f_acc, 0, 0, 8, 1, 32, total_length, buffer);
      break;
    case M32R_OPERAND_ACCD :
      errmsg = insert_normal (cd, fields->f_accd, 0, 0, 4, 2, 32, total_length, buffer);
      break;
    case M32R_OPERAND_ACCS :
      errmsg = insert_normal (cd, fields->f_accs, 0, 0, 12, 2, 32, total_length, buffer);
      break;
    case M32R_OPERAND_DCR :
      errmsg = insert_normal (cd, fields->f_r1, 0, 0, 4, 4, 32, total_length, buffer);
      break;
    case M32R_OPERAND_DISP16 :
      {
        long value = fields->f_disp16;
        value = ((int) (((value) - (pc))) >> (2));
        errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 16, 16, 32, total_length, buffer);
      }
      break;
    case M32R_OPERAND_DISP24 :
      {
        long value = fields->f_disp24;
        value = ((int) (((value) - (pc))) >> (2));
        errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 24, 32, total_length, buffer);
      }
      break;
    case M32R_OPERAND_DISP8 :
      {
        long value = fields->f_disp8;
        value = ((int) (((value) - (((pc) & (-4))))) >> (2));
        errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, buffer);
      }
      break;
    case M32R_OPERAND_DR :
      errmsg = insert_normal (cd, fields->f_r1, 0, 0, 4, 4, 32, total_length, buffer);
      break;
    case M32R_OPERAND_HASH :
      break;
    case M32R_OPERAND_HI16 :
      errmsg = insert_normal (cd, fields->f_hi16, 0|(1<<CGEN_IFLD_SIGN_OPT), 0, 16, 16, 32, total_length, buffer);
      break;
    case M32R_OPERAND_IMM1 :
      {
        long value = fields->f_imm1;
        value = ((value) - (1));
        errmsg = insert_normal (cd, value, 0, 0, 15, 1, 32, total_length, buffer);
      }
      break;
    case M32R_OPERAND_SCR :
      errmsg = insert_normal (cd, fields->f_r2, 0, 0, 12, 4, 32, total_length, buffer);
      break;
    case M32R_OPERAND_SIMM16 :
      errmsg = insert_normal (cd, fields->f_simm16, 0|(1<<CGEN_IFLD_SIGNED), 0, 16, 16, 32, total_length, buffer);
      break;
    case M32R_OPERAND_SIMM8 :
      errmsg = insert_normal (cd, fields->f_simm8, 0|(1<<CGEN_IFLD_SIGNED), 0, 8, 8, 32, total_length, buffer);
      break;
    case M32R_OPERAND_SLO16 :
      errmsg = insert_normal (cd, fields->f_simm16, 0|(1<<CGEN_IFLD_SIGNED), 0, 16, 16, 32, total_length, buffer);
      break;
    case M32R_OPERAND_SR :
      errmsg = insert_normal (cd, fields->f_r2, 0, 0, 12, 4, 32, total_length, buffer);
      break;
    case M32R_OPERAND_SRC1 :
      errmsg = insert_normal (cd, fields->f_r1, 0, 0, 4, 4, 32, total_length, buffer);
      break;
    case M32R_OPERAND_SRC2 :
      errmsg = insert_normal (cd, fields->f_r2, 0, 0, 12, 4, 32, total_length, buffer);
      break;
    case M32R_OPERAND_UIMM16 :
      errmsg = insert_normal (cd, fields->f_uimm16, 0, 0, 16, 16, 32, total_length, buffer);
      break;
    case M32R_OPERAND_UIMM24 :
      errmsg = insert_normal (cd, fields->f_uimm24, 0|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 24, 32, total_length, buffer);
      break;
    case M32R_OPERAND_UIMM3 :
      errmsg = insert_normal (cd, fields->f_uimm3, 0, 0, 5, 3, 32, total_length, buffer);
      break;
    case M32R_OPERAND_UIMM4 :
      errmsg = insert_normal (cd, fields->f_uimm4, 0, 0, 12, 4, 32, total_length, buffer);
      break;
    case M32R_OPERAND_UIMM5 :
      errmsg = insert_normal (cd, fields->f_uimm5, 0, 0, 11, 5, 32, total_length, buffer);
      break;
    case M32R_OPERAND_UIMM8 :
      errmsg = insert_normal (cd, fields->f_uimm8, 0, 0, 8, 8, 32, total_length, buffer);
      break;
    case M32R_OPERAND_ULO16 :
      errmsg = insert_normal (cd, fields->f_uimm16, 0, 0, 16, 16, 32, total_length, buffer);
      break;

    default :
      /* xgettext:c-format */
      fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
	       opindex);
      abort ();
  }

  return errmsg;
}

int m32r_cgen_extract_operand
  PARAMS ((CGEN_CPU_DESC, int, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
           CGEN_FIELDS *, bfd_vma));

/* Main entry point for operand extraction.
   The result is <= 0 for error, >0 for success.
   ??? Actual values aren't well defined right now.

   This function is basically just a big switch statement.  Earlier versions
   used tables to look up the function to use, but
   - if the table contains both assembler and disassembler functions then
     the disassembler contains much of the assembler and vice-versa,
   - there's a lot of inlining possibilities as things grow,
   - using a switch statement avoids the function call overhead.

   This function could be moved into `print_insn_normal', but keeping it
   separate makes clear the interface between `print_insn_normal' and each of
   the handlers.  */

int
m32r_cgen_extract_operand (cd, opindex, ex_info, insn_value, fields, pc)
     CGEN_CPU_DESC cd;
     int opindex;
     CGEN_EXTRACT_INFO *ex_info;
     CGEN_INSN_INT insn_value;
     CGEN_FIELDS * fields;
     bfd_vma pc;
{
  /* Assume success (for those operands that are nops).  */
  int length = 1;
  unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);

  switch (opindex)
    {
    case M32R_OPERAND_ACC :
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 1, 32, total_length, pc, & fields->f_acc);
      break;
    case M32R_OPERAND_ACCD :
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 2, 32, total_length, pc, & fields->f_accd);
      break;
    case M32R_OPERAND_ACCS :
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 2, 32, total_length, pc, & fields->f_accs);
      break;
    case M32R_OPERAND_DCR :
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 4, 32, total_length, pc, & fields->f_r1);
      break;
    case M32R_OPERAND_DISP16 :
      {
        long value;
        length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 16, 16, 32, total_length, pc, & value);
        value = ((((value) << (2))) + (pc));
        fields->f_disp16 = value;
      }
      break;
    case M32R_OPERAND_DISP24 :
      {
        long value;
        length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 24, 32, total_length, pc, & value);
        value = ((((value) << (2))) + (pc));
        fields->f_disp24 = value;
      }
      break;
    case M32R_OPERAND_DISP8 :
      {
        long value;
        length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, pc, & value);
        value = ((((value) << (2))) + (((pc) & (-4))));
        fields->f_disp8 = value;
      }
      break;
    case M32R_OPERAND_DR :
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 4, 32, total_length, pc, & fields->f_r1);
      break;
    case M32R_OPERAND_HASH :
      break;
    case M32R_OPERAND_HI16 :
      length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGN_OPT), 0, 16, 16, 32, total_length, pc, & fields->f_hi16);
      break;
    case M32R_OPERAND_IMM1 :
      {
        long value;
        length = extract_normal (cd, ex_info, insn_value, 0, 0, 15, 1, 32, total_length, pc, & value);
        value = ((value) + (1));
        fields->f_imm1 = value;
      }
      break;
    case M32R_OPERAND_SCR :
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 32, total_length, pc, & fields->f_r2);
      break;
    case M32R_OPERAND_SIMM16 :
      length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 16, 16, 32, total_length, pc, & fields->f_simm16);
      break;
    case M32R_OPERAND_SIMM8 :
      length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 8, 8, 32, total_length, pc, & fields->f_simm8);
      break;
    case M32R_OPERAND_SLO16 :
      length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 16, 16, 32, total_length, pc, & fields->f_simm16);
      break;
    case M32R_OPERAND_SR :
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 32, total_length, pc, & fields->f_r2);
      break;
    case M32R_OPERAND_SRC1 :
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 4, 32, total_length, pc, & fields->f_r1);
      break;
    case M32R_OPERAND_SRC2 :
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 32, total_length, pc, & fields->f_r2);
      break;
    case M32R_OPERAND_UIMM16 :
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 16, 16, 32, total_length, pc, & fields->f_uimm16);
      break;
    case M32R_OPERAND_UIMM24 :
      length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_RELOC)|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 24, 32, total_length, pc, & fields->f_uimm24);
      break;
    case M32R_OPERAND_UIMM3 :
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 5, 3, 32, total_length, pc, & fields->f_uimm3);
      break;
    case M32R_OPERAND_UIMM4 :
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 32, total_length, pc, & fields->f_uimm4);
      break;
    case M32R_OPERAND_UIMM5 :
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 11, 5, 32, total_length, pc, & fields->f_uimm5);
      break;
    case M32R_OPERAND_UIMM8 :
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 32, total_length, pc, & fields->f_uimm8);
      break;
    case M32R_OPERAND_ULO16 :
      length = extract_normal (cd, ex_info, insn_value, 0, 0, 16, 16, 32, total_length, pc, & fields->f_uimm16);
      break;

    default :
      /* xgettext:c-format */
      fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
	       opindex);
      abort ();
    }

  return length;
}

cgen_insert_fn * const m32r_cgen_insert_handlers[] = 
{
  insert_insn_normal,
};

cgen_extract_fn * const m32r_cgen_extract_handlers[] = 
{
  extract_insn_normal,
};

int m32r_cgen_get_int_operand
  PARAMS ((CGEN_CPU_DESC, int, const CGEN_FIELDS *));
bfd_vma m32r_cgen_get_vma_operand
  PARAMS ((CGEN_CPU_DESC, int, const CGEN_FIELDS *));

/* Getting values from cgen_fields is handled by a collection of functions.
   They are distinguished by the type of the VALUE argument they return.
   TODO: floating point, inlining support, remove cases where result type
   not appropriate.  */

int
m32r_cgen_get_int_operand (cd, opindex, fields)
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
     int opindex;
     const CGEN_FIELDS * fields;
{
  int value;

  switch (opindex)
    {
    case M32R_OPERAND_ACC :
      value = fields->f_acc;
      break;
    case M32R_OPERAND_ACCD :
      value = fields->f_accd;
      break;
    case M32R_OPERAND_ACCS :
      value = fields->f_accs;
      break;
    case M32R_OPERAND_DCR :
      value = fields->f_r1;
      break;
    case M32R_OPERAND_DISP16 :
      value = fields->f_disp16;
      break;
    case M32R_OPERAND_DISP24 :
      value = fields->f_disp24;
      break;
    case M32R_OPERAND_DISP8 :
      value = fields->f_disp8;
      break;
    case M32R_OPERAND_DR :
      value = fields->f_r1;
      break;
    case M32R_OPERAND_HASH :
      value = 0;
      break;
    case M32R_OPERAND_HI16 :
      value = fields->f_hi16;
      break;
    case M32R_OPERAND_IMM1 :
      value = fields->f_imm1;
      break;
    case M32R_OPERAND_SCR :
      value = fields->f_r2;
      break;
    case M32R_OPERAND_SIMM16 :
      value = fields->f_simm16;
      break;
    case M32R_OPERAND_SIMM8 :
      value = fields->f_simm8;
      break;
    case M32R_OPERAND_SLO16 :
      value = fields->f_simm16;
      break;
    case M32R_OPERAND_SR :
      value = fields->f_r2;
      break;
    case M32R_OPERAND_SRC1 :
      value = fields->f_r1;
      break;
    case M32R_OPERAND_SRC2 :
      value = fields->f_r2;
      break;
    case M32R_OPERAND_UIMM16 :
      value = fields->f_uimm16;
      break;
    case M32R_OPERAND_UIMM24 :
      value = fields->f_uimm24;
      break;
    case M32R_OPERAND_UIMM3 :
      value = fields->f_uimm3;
      break;
    case M32R_OPERAND_UIMM4 :
      value = fields->f_uimm4;
      break;
    case M32R_OPERAND_UIMM5 :
      value = fields->f_uimm5;
      break;
    case M32R_OPERAND_UIMM8 :
      value = fields->f_uimm8;
      break;
    case M32R_OPERAND_ULO16 :
      value = fields->f_uimm16;
      break;

    default :
      /* xgettext:c-format */
      fprintf (stderr, _("Unrecognized field %d while getting int operand.\n"),
		       opindex);
      abort ();
  }

  return value;
}

bfd_vma
m32r_cgen_get_vma_operand (cd, opindex, fields)
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
     int opindex;
     const CGEN_FIELDS * fields;
{
  bfd_vma value;

  switch (opindex)
    {
    case M32R_OPERAND_ACC :
      value = fields->f_acc;
      break;
    case M32R_OPERAND_ACCD :
      value = fields->f_accd;
      break;
    case M32R_OPERAND_ACCS :
      value = fields->f_accs;
      break;
    case M32R_OPERAND_DCR :
      value = fields->f_r1;
      break;
    case M32R_OPERAND_DISP16 :
      value = fields->f_disp16;
      break;
    case M32R_OPERAND_DISP24 :
      value = fields->f_disp24;
      break;
    case M32R_OPERAND_DISP8 :
      value = fields->f_disp8;
      break;
    case M32R_OPERAND_DR :
      value = fields->f_r1;
      break;
    case M32R_OPERAND_HASH :
      value = 0;
      break;
    case M32R_OPERAND_HI16 :
      value = fields->f_hi16;
      break;
    case M32R_OPERAND_IMM1 :
      value = fields->f_imm1;
      break;
    case M32R_OPERAND_SCR :
      value = fields->f_r2;
      break;
    case M32R_OPERAND_SIMM16 :
      value = fields->f_simm16;
      break;
    case M32R_OPERAND_SIMM8 :
      value = fields->f_simm8;
      break;
    case M32R_OPERAND_SLO16 :
      value = fields->f_simm16;
      break;
    case M32R_OPERAND_SR :
      value = fields->f_r2;
      break;
    case M32R_OPERAND_SRC1 :
      value = fields->f_r1;
      break;
    case M32R_OPERAND_SRC2 :
      value = fields->f_r2;
      break;
    case M32R_OPERAND_UIMM16 :
      value = fields->f_uimm16;
      break;
    case M32R_OPERAND_UIMM24 :
      value = fields->f_uimm24;
      break;
    case M32R_OPERAND_UIMM3 :
      value = fields->f_uimm3;
      break;
    case M32R_OPERAND_UIMM4 :
      value = fields->f_uimm4;
      break;
    case M32R_OPERAND_UIMM5 :
      value = fields->f_uimm5;
      break;
    case M32R_OPERAND_UIMM8 :
      value = fields->f_uimm8;
      break;
    case M32R_OPERAND_ULO16 :
      value = fields->f_uimm16;
      break;

    default :
      /* xgettext:c-format */
      fprintf (stderr, _("Unrecognized field %d while getting vma operand.\n"),
		       opindex);
      abort ();
  }

  return value;
}

void m32r_cgen_set_int_operand
  PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, int));
void m32r_cgen_set_vma_operand
  PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, bfd_vma));

/* Stuffing values in cgen_fields is handled by a collection of functions.
   They are distinguished by the type of the VALUE argument they accept.
   TODO: floating point, inlining support, remove cases where argument type
   not appropriate.  */

void
m32r_cgen_set_int_operand (cd, opindex, fields, value)
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
     int opindex;
     CGEN_FIELDS * fields;
     int value;
{
  switch (opindex)
    {
    case M32R_OPERAND_ACC :
      fields->f_acc = value;
      break;
    case M32R_OPERAND_ACCD :
      fields->f_accd = value;
      break;
    case M32R_OPERAND_ACCS :
      fields->f_accs = value;
      break;
    case M32R_OPERAND_DCR :
      fields->f_r1 = value;
      break;
    case M32R_OPERAND_DISP16 :
      fields->f_disp16 = value;
      break;
    case M32R_OPERAND_DISP24 :
      fields->f_disp24 = value;
      break;
    case M32R_OPERAND_DISP8 :
      fields->f_disp8 = value;
      break;
    case M32R_OPERAND_DR :
      fields->f_r1 = value;
      break;
    case M32R_OPERAND_HASH :
      break;
    case M32R_OPERAND_HI16 :
      fields->f_hi16 = value;
      break;
    case M32R_OPERAND_IMM1 :
      fields->f_imm1 = value;
      break;
    case M32R_OPERAND_SCR :
      fields->f_r2 = value;
      break;
    case M32R_OPERAND_SIMM16 :
      fields->f_simm16 = value;
      break;
    case M32R_OPERAND_SIMM8 :
      fields->f_simm8 = value;
      break;
    case M32R_OPERAND_SLO16 :
      fields->f_simm16 = value;
      break;
    case M32R_OPERAND_SR :
      fields->f_r2 = value;
      break;
    case M32R_OPERAND_SRC1 :
      fields->f_r1 = value;
      break;
    case M32R_OPERAND_SRC2 :
      fields->f_r2 = value;
      break;
    case M32R_OPERAND_UIMM16 :
      fields->f_uimm16 = value;
      break;
    case M32R_OPERAND_UIMM24 :
      fields->f_uimm24 = value;
      break;
    case M32R_OPERAND_UIMM3 :
      fields->f_uimm3 = value;
      break;
    case M32R_OPERAND_UIMM4 :
      fields->f_uimm4 = value;
      break;
    case M32R_OPERAND_UIMM5 :
      fields->f_uimm5 = value;
      break;
    case M32R_OPERAND_UIMM8 :
      fields->f_uimm8 = value;
      break;
    case M32R_OPERAND_ULO16 :
      fields->f_uimm16 = value;
      break;

    default :
      /* xgettext:c-format */
      fprintf (stderr, _("Unrecognized field %d while setting int operand.\n"),
		       opindex);
      abort ();
  }
}

void
m32r_cgen_set_vma_operand (cd, opindex, fields, value)
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
     int opindex;
     CGEN_FIELDS * fields;
     bfd_vma value;
{
  switch (opindex)
    {
    case M32R_OPERAND_ACC :
      fields->f_acc = value;
      break;
    case M32R_OPERAND_ACCD :
      fields->f_accd = value;
      break;
    case M32R_OPERAND_ACCS :
      fields->f_accs = value;
      break;
    case M32R_OPERAND_DCR :
      fields->f_r1 = value;
      break;
    case M32R_OPERAND_DISP16 :
      fields->f_disp16 = value;
      break;
    case M32R_OPERAND_DISP24 :
      fields->f_disp24 = value;
      break;
    case M32R_OPERAND_DISP8 :
      fields->f_disp8 = value;
      break;
    case M32R_OPERAND_DR :
      fields->f_r1 = value;
      break;
    case M32R_OPERAND_HASH :
      break;
    case M32R_OPERAND_HI16 :
      fields->f_hi16 = value;
      break;
    case M32R_OPERAND_IMM1 :
      fields->f_imm1 = value;
      break;
    case M32R_OPERAND_SCR :
      fields->f_r2 = value;
      break;
    case M32R_OPERAND_SIMM16 :
      fields->f_simm16 = value;
      break;
    case M32R_OPERAND_SIMM8 :
      fields->f_simm8 = value;
      break;
    case M32R_OPERAND_SLO16 :
      fields->f_simm16 = value;
      break;
    case M32R_OPERAND_SR :
      fields->f_r2 = value;
      break;
    case M32R_OPERAND_SRC1 :
      fields->f_r1 = value;
      break;
    case M32R_OPERAND_SRC2 :
      fields->f_r2 = value;
      break;
    case M32R_OPERAND_UIMM16 :
      fields->f_uimm16 = value;
      break;
    case M32R_OPERAND_UIMM24 :
      fields->f_uimm24 = value;
      break;
    case M32R_OPERAND_UIMM3 :
      fields->f_uimm3 = value;
      break;
    case M32R_OPERAND_UIMM4 :
      fields->f_uimm4 = value;
      break;
    case M32R_OPERAND_UIMM5 :
      fields->f_uimm5 = value;
      break;
    case M32R_OPERAND_UIMM8 :
      fields->f_uimm8 = value;
      break;
    case M32R_OPERAND_ULO16 :
      fields->f_uimm16 = value;
      break;

    default :
      /* xgettext:c-format */