1/* DO NOT EDIT!  -*- buffer-read-only: t -*- vi:set ro:  */
2/* Instruction building/extraction support for ip2k. -*- C -*-
3
4   THIS FILE IS MACHINE GENERATED WITH CGEN: Cpu tools GENerator.
5   - the resultant file is machine generated, cgen-ibld.in isn't
6
7   Copyright (C) 1996-2020 Free Software Foundation, Inc.
8
9   This file is part of libopcodes.
10
11   This library is free software; you can redistribute it and/or modify
12   it under the terms of the GNU General Public License as published by
13   the Free Software Foundation; either version 3, or (at your option)
14   any later version.
15
16   It is distributed in the hope that it will be useful, but WITHOUT
17   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
19   License for more details.
20
21   You should have received a copy of the GNU General Public License
22   along with this program; if not, write to the Free Software Foundation, Inc.,
23   51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
24
25/* ??? Eventually more and more of this stuff can go to cpu-independent files.
26   Keep that in mind.  */
27
28#include "sysdep.h"
29#include <stdio.h>
30#include "ansidecl.h"
31#include "dis-asm.h"
32#include "bfd.h"
33#include "symcat.h"
34#include "ip2k-desc.h"
35#include "ip2k-opc.h"
36#include "cgen/basic-modes.h"
37#include "opintl.h"
38#include "safe-ctype.h"
39
40#undef  min
41#define min(a,b) ((a) < (b) ? (a) : (b))
42#undef  max
43#define max(a,b) ((a) > (b) ? (a) : (b))
44
45/* Used by the ifield rtx function.  */
46#define FLD(f) (fields->f)
47
48static const char * insert_normal
49  (CGEN_CPU_DESC, long, unsigned int, unsigned int, unsigned int,
50   unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR);
51static const char * insert_insn_normal
52  (CGEN_CPU_DESC, const CGEN_INSN *,
53   CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
54static int extract_normal
55  (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
56   unsigned int, unsigned int, unsigned int, unsigned int,
57   unsigned int, unsigned int, bfd_vma, long *);
58static int extract_insn_normal
59  (CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
60   CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
61#if CGEN_INT_INSN_P
62static void put_insn_int_value
63  (CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT);
64#endif
65#if ! CGEN_INT_INSN_P
66static CGEN_INLINE void insert_1
67  (CGEN_CPU_DESC, unsigned long, int, int, int, unsigned char *);
68static CGEN_INLINE int fill_cache
69  (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *,  int, int, bfd_vma);
70static CGEN_INLINE long extract_1
71  (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, int, unsigned char *, bfd_vma);
72#endif
73
74/* Operand insertion.  */
75
76#if ! CGEN_INT_INSN_P
77
78/* Subroutine of insert_normal.  */
79
80static CGEN_INLINE void
81insert_1 (CGEN_CPU_DESC cd,
82	  unsigned long value,
83	  int start,
84	  int length,
85	  int word_length,
86	  unsigned char *bufp)
87{
88  unsigned long x,mask;
89  int shift;
90
91  x = cgen_get_insn_value (cd, bufp, word_length);
92
93  /* Written this way to avoid undefined behaviour.  */
94  mask = (((1L << (length - 1)) - 1) << 1) | 1;
95  if (CGEN_INSN_LSB0_P)
96    shift = (start + 1) - length;
97  else
98    shift = (word_length - (start + length));
99  x = (x & ~(mask << shift)) | ((value & mask) << shift);
100
101  cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
102}
103
104#endif /* ! CGEN_INT_INSN_P */
105
106/* Default insertion routine.
107
108   ATTRS is a mask of the boolean attributes.
109   WORD_OFFSET is the offset in bits from the start of the insn of the value.
110   WORD_LENGTH is the length of the word in bits in which the value resides.
111   START is the starting bit number in the word, architecture origin.
112   LENGTH is the length of VALUE in bits.
113   TOTAL_LENGTH is the total length of the insn in bits.
114
115   The result is an error message or NULL if success.  */
116
117/* ??? This duplicates functionality with bfd's howto table and
118   bfd_install_relocation.  */
119/* ??? This doesn't handle bfd_vma's.  Create another function when
120   necessary.  */
121
122static const char *
123insert_normal (CGEN_CPU_DESC cd,
124	       long value,
125	       unsigned int attrs,
126	       unsigned int word_offset,
127	       unsigned int start,
128	       unsigned int length,
129	       unsigned int word_length,
130	       unsigned int total_length,
131	       CGEN_INSN_BYTES_PTR buffer)
132{
133  static char errbuf[100];
134  /* Written this way to avoid undefined behaviour.  */
135  unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
136
137  /* If LENGTH is zero, this operand doesn't contribute to the value.  */
138  if (length == 0)
139    return NULL;
140
141  if (word_length > 8 * sizeof (CGEN_INSN_INT))
142    abort ();
143
144  /* For architectures with insns smaller than the base-insn-bitsize,
145     word_length may be too big.  */
146  if (cd->min_insn_bitsize < cd->base_insn_bitsize)
147    {
148      if (word_offset == 0
149	  && word_length > total_length)
150	word_length = total_length;
151    }
152
153  /* Ensure VALUE will fit.  */
154  if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
155    {
156      long minval = - (1L << (length - 1));
157      unsigned long maxval = mask;
158
159      if ((value > 0 && (unsigned long) value > maxval)
160	  || value < minval)
161	{
162	  /* xgettext:c-format */
163	  sprintf (errbuf,
164		   _("operand out of range (%ld not between %ld and %lu)"),
165		   value, minval, maxval);
166	  return errbuf;
167	}
168    }
169  else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
170    {
171      unsigned long maxval = mask;
172      unsigned long val = (unsigned long) value;
173
174      /* For hosts with a word size > 32 check to see if value has been sign
175	 extended beyond 32 bits.  If so then ignore these higher sign bits
176	 as the user is attempting to store a 32-bit signed value into an
177	 unsigned 32-bit field which is allowed.  */
178      if (sizeof (unsigned long) > 4 && ((value >> 32) == -1))
179	val &= 0xFFFFFFFF;
180
181      if (val > maxval)
182	{
183	  /* xgettext:c-format */
184	  sprintf (errbuf,
185		   _("operand out of range (0x%lx not between 0 and 0x%lx)"),
186		   val, maxval);
187	  return errbuf;
188	}
189    }
190  else
191    {
192      if (! cgen_signed_overflow_ok_p (cd))
193	{
194	  long minval = - (1L << (length - 1));
195	  long maxval =   (1L << (length - 1)) - 1;
196
197	  if (value < minval || value > maxval)
198	    {
199	      sprintf
200		/* xgettext:c-format */
201		(errbuf, _("operand out of range (%ld not between %ld and %ld)"),
202		 value, minval, maxval);
203	      return errbuf;
204	    }
205	}
206    }
207
208#if CGEN_INT_INSN_P
209
210  {
211    int shift_within_word, shift_to_word, shift;
212
213    /* How to shift the value to BIT0 of the word.  */
214    shift_to_word = total_length - (word_offset + word_length);
215
216    /* How to shift the value to the field within the word.  */
217    if (CGEN_INSN_LSB0_P)
218      shift_within_word = start + 1 - length;
219    else
220      shift_within_word = word_length - start - length;
221
222    /* The total SHIFT, then mask in the value.  */
223    shift = shift_to_word + shift_within_word;
224    *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
225  }
226
227#else /* ! CGEN_INT_INSN_P */
228
229  {
230    unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
231
232    insert_1 (cd, value, start, length, word_length, bufp);
233  }
234
235#endif /* ! CGEN_INT_INSN_P */
236
237  return NULL;
238}
239
240/* Default insn builder (insert handler).
241   The instruction is recorded in CGEN_INT_INSN_P byte order (meaning
242   that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is
243   recorded in host byte order, otherwise BUFFER is an array of bytes
244   and the value is recorded in target byte order).
245   The result is an error message or NULL if success.  */
246
247static const char *
248insert_insn_normal (CGEN_CPU_DESC cd,
249		    const CGEN_INSN * insn,
250		    CGEN_FIELDS * fields,
251		    CGEN_INSN_BYTES_PTR buffer,
252		    bfd_vma pc)
253{
254  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
255  unsigned long value;
256  const CGEN_SYNTAX_CHAR_TYPE * syn;
257
258  CGEN_INIT_INSERT (cd);
259  value = CGEN_INSN_BASE_VALUE (insn);
260
261  /* If we're recording insns as numbers (rather than a string of bytes),
262     target byte order handling is deferred until later.  */
263
264#if CGEN_INT_INSN_P
265
266  put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
267		      CGEN_FIELDS_BITSIZE (fields), value);
268
269#else
270
271  cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
272					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
273		       value);
274
275#endif /* ! CGEN_INT_INSN_P */
276
277  /* ??? It would be better to scan the format's fields.
278     Still need to be able to insert a value based on the operand though;
279     e.g. storing a branch displacement that got resolved later.
280     Needs more thought first.  */
281
282  for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn)
283    {
284      const char *errmsg;
285
286      if (CGEN_SYNTAX_CHAR_P (* syn))
287	continue;
288
289      errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
290				       fields, buffer, pc);
291      if (errmsg)
292	return errmsg;
293    }
294
295  return NULL;
296}
297
298#if CGEN_INT_INSN_P
299/* Cover function to store an insn value into an integral insn.  Must go here
300   because it needs <prefix>-desc.h for CGEN_INT_INSN_P.  */
301
302static void
303put_insn_int_value (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
304		    CGEN_INSN_BYTES_PTR buf,
305		    int length,
306		    int insn_length,
307		    CGEN_INSN_INT value)
308{
309  /* For architectures with insns smaller than the base-insn-bitsize,
310     length may be too big.  */
311  if (length > insn_length)
312    *buf = value;
313  else
314    {
315      int shift = insn_length - length;
316      /* Written this way to avoid undefined behaviour.  */
317      CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
318
319      *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
320    }
321}
322#endif
323
324/* Operand extraction.  */
325
326#if ! CGEN_INT_INSN_P
327
328/* Subroutine of extract_normal.
329   Ensure sufficient bytes are cached in EX_INFO.
330   OFFSET is the offset in bytes from the start of the insn of the value.
331   BYTES is the length of the needed value.
332   Returns 1 for success, 0 for failure.  */
333
334static CGEN_INLINE int
335fill_cache (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
336	    CGEN_EXTRACT_INFO *ex_info,
337	    int offset,
338	    int bytes,
339	    bfd_vma pc)
340{
341  /* It's doubtful that the middle part has already been fetched so
342     we don't optimize that case.  kiss.  */
343  unsigned int mask;
344  disassemble_info *info = (disassemble_info *) ex_info->dis_info;
345
346  /* First do a quick check.  */
347  mask = (1 << bytes) - 1;
348  if (((ex_info->valid >> offset) & mask) == mask)
349    return 1;
350
351  /* Search for the first byte we need to read.  */
352  for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
353    if (! (mask & ex_info->valid))
354      break;
355
356  if (bytes)
357    {
358      int status;
359
360      pc += offset;
361      status = (*info->read_memory_func)
362	(pc, ex_info->insn_bytes + offset, bytes, info);
363
364      if (status != 0)
365	{
366	  (*info->memory_error_func) (status, pc, info);
367	  return 0;
368	}
369
370      ex_info->valid |= ((1 << bytes) - 1) << offset;
371    }
372
373  return 1;
374}
375
376/* Subroutine of extract_normal.  */
377
378static CGEN_INLINE long
379extract_1 (CGEN_CPU_DESC cd,
380	   CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
381	   int start,
382	   int length,
383	   int word_length,
384	   unsigned char *bufp,
385	   bfd_vma pc ATTRIBUTE_UNUSED)
386{
387  unsigned long x;
388  int shift;
389
390  x = cgen_get_insn_value (cd, bufp, word_length);
391
392  if (CGEN_INSN_LSB0_P)
393    shift = (start + 1) - length;
394  else
395    shift = (word_length - (start + length));
396  return x >> shift;
397}
398
399#endif /* ! CGEN_INT_INSN_P */
400
401/* Default extraction routine.
402
403   INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
404   or sometimes less for cases like the m32r where the base insn size is 32
405   but some insns are 16 bits.
406   ATTRS is a mask of the boolean attributes.  We only need `SIGNED',
407   but for generality we take a bitmask of all of them.
408   WORD_OFFSET is the offset in bits from the start of the insn of the value.
409   WORD_LENGTH is the length of the word in bits in which the value resides.
410   START is the starting bit number in the word, architecture origin.
411   LENGTH is the length of VALUE in bits.
412   TOTAL_LENGTH is the total length of the insn in bits.
413
414   Returns 1 for success, 0 for failure.  */
415
416/* ??? The return code isn't properly used.  wip.  */
417
418/* ??? This doesn't handle bfd_vma's.  Create another function when
419   necessary.  */
420
421static int
422extract_normal (CGEN_CPU_DESC cd,
423#if ! CGEN_INT_INSN_P
424		CGEN_EXTRACT_INFO *ex_info,
425#else
426		CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
427#endif
428		CGEN_INSN_INT insn_value,
429		unsigned int attrs,
430		unsigned int word_offset,
431		unsigned int start,
432		unsigned int length,
433		unsigned int word_length,
434		unsigned int total_length,
435#if ! CGEN_INT_INSN_P
436		bfd_vma pc,
437#else
438		bfd_vma pc ATTRIBUTE_UNUSED,
439#endif
440		long *valuep)
441{
442  long value, mask;
443
444  /* If LENGTH is zero, this operand doesn't contribute to the value
445     so give it a standard value of zero.  */
446  if (length == 0)
447    {
448      *valuep = 0;
449      return 1;
450    }
451
452  if (word_length > 8 * sizeof (CGEN_INSN_INT))
453    abort ();
454
455  /* For architectures with insns smaller than the insn-base-bitsize,
456     word_length may be too big.  */
457  if (cd->min_insn_bitsize < cd->base_insn_bitsize)
458    {
459      if (word_offset + word_length > total_length)
460	word_length = total_length - word_offset;
461    }
462
463  /* Does the value reside in INSN_VALUE, and at the right alignment?  */
464
465  if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
466    {
467      if (CGEN_INSN_LSB0_P)
468	value = insn_value >> ((word_offset + start + 1) - length);
469      else
470	value = insn_value >> (total_length - ( word_offset + start + length));
471    }
472
473#if ! CGEN_INT_INSN_P
474
475  else
476    {
477      unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
478
479      if (word_length > 8 * sizeof (CGEN_INSN_INT))
480	abort ();
481
482      if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
483	return 0;
484
485      value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
486    }
487
488#endif /* ! CGEN_INT_INSN_P */
489
490  /* Written this way to avoid undefined behaviour.  */
491  mask = (((1L << (length - 1)) - 1) << 1) | 1;
492
493  value &= mask;
494  /* sign extend? */
495  if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
496      && (value & (1L << (length - 1))))
497    value |= ~mask;
498
499  *valuep = value;
500
501  return 1;
502}
503
504/* Default insn extractor.
505
506   INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
507   The extracted fields are stored in FIELDS.
508   EX_INFO is used to handle reading variable length insns.
509   Return the length of the insn in bits, or 0 if no match,
510   or -1 if an error occurs fetching data (memory_error_func will have
511   been called).  */
512
513static int
514extract_insn_normal (CGEN_CPU_DESC cd,
515		     const CGEN_INSN *insn,
516		     CGEN_EXTRACT_INFO *ex_info,
517		     CGEN_INSN_INT insn_value,
518		     CGEN_FIELDS *fields,
519		     bfd_vma pc)
520{
521  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
522  const CGEN_SYNTAX_CHAR_TYPE *syn;
523
524  CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
525
526  CGEN_INIT_EXTRACT (cd);
527
528  for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
529    {
530      int length;
531
532      if (CGEN_SYNTAX_CHAR_P (*syn))
533	continue;
534
535      length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
536					ex_info, insn_value, fields, pc);
537      if (length <= 0)
538	return length;
539    }
540
541  /* We recognized and successfully extracted this insn.  */
542  return CGEN_INSN_BITSIZE (insn);
543}
544
545/* Machine generated code added here.  */
546
547const char * ip2k_cgen_insert_operand
548  (CGEN_CPU_DESC, int, CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
549
550/* Main entry point for operand insertion.
551
552   This function is basically just a big switch statement.  Earlier versions
553   used tables to look up the function to use, but
554   - if the table contains both assembler and disassembler functions then
555     the disassembler contains much of the assembler and vice-versa,
556   - there's a lot of inlining possibilities as things grow,
557   - using a switch statement avoids the function call overhead.
558
559   This function could be moved into `parse_insn_normal', but keeping it
560   separate makes clear the interface between `parse_insn_normal' and each of
561   the handlers.  It's also needed by GAS to insert operands that couldn't be
562   resolved during parsing.  */
563
564const char *
565ip2k_cgen_insert_operand (CGEN_CPU_DESC cd,
566			     int opindex,
567			     CGEN_FIELDS * fields,
568			     CGEN_INSN_BYTES_PTR buffer,
569			     bfd_vma pc ATTRIBUTE_UNUSED)
570{
571  const char * errmsg = NULL;
572  unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
573
574  switch (opindex)
575    {
576    case IP2K_OPERAND_ADDR16CJP :
577      errmsg = insert_normal (cd, fields->f_addr16cjp, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 12, 13, 16, total_length, buffer);
578      break;
579    case IP2K_OPERAND_ADDR16H :
580      errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 7, 8, 16, total_length, buffer);
581      break;
582    case IP2K_OPERAND_ADDR16L :
583      errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 7, 8, 16, total_length, buffer);
584      break;
585    case IP2K_OPERAND_ADDR16P :
586      errmsg = insert_normal (cd, fields->f_page3, 0, 0, 2, 3, 16, total_length, buffer);
587      break;
588    case IP2K_OPERAND_BITNO :
589      errmsg = insert_normal (cd, fields->f_bitno, 0, 0, 11, 3, 16, total_length, buffer);
590      break;
591    case IP2K_OPERAND_CBIT :
592      break;
593    case IP2K_OPERAND_DCBIT :
594      break;
595    case IP2K_OPERAND_FR :
596      errmsg = insert_normal (cd, fields->f_reg, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 9, 16, total_length, buffer);
597      break;
598    case IP2K_OPERAND_LIT8 :
599      errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 7, 8, 16, total_length, buffer);
600      break;
601    case IP2K_OPERAND_PABITS :
602      break;
603    case IP2K_OPERAND_RETI3 :
604      errmsg = insert_normal (cd, fields->f_reti3, 0, 0, 2, 3, 16, total_length, buffer);
605      break;
606    case IP2K_OPERAND_ZBIT :
607      break;
608
609    default :
610      /* xgettext:c-format */
611      opcodes_error_handler
612	(_("internal error: unrecognized field %d while building insn"),
613	 opindex);
614      abort ();
615  }
616
617  return errmsg;
618}
619
620int ip2k_cgen_extract_operand
621  (CGEN_CPU_DESC, int, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
622
623/* Main entry point for operand extraction.
624   The result is <= 0 for error, >0 for success.
625   ??? Actual values aren't well defined right now.
626
627   This function is basically just a big switch statement.  Earlier versions
628   used tables to look up the function to use, but
629   - if the table contains both assembler and disassembler functions then
630     the disassembler contains much of the assembler and vice-versa,
631   - there's a lot of inlining possibilities as things grow,
632   - using a switch statement avoids the function call overhead.
633
634   This function could be moved into `print_insn_normal', but keeping it
635   separate makes clear the interface between `print_insn_normal' and each of
636   the handlers.  */
637
638int
639ip2k_cgen_extract_operand (CGEN_CPU_DESC cd,
640			     int opindex,
641			     CGEN_EXTRACT_INFO *ex_info,
642			     CGEN_INSN_INT insn_value,
643			     CGEN_FIELDS * fields,
644			     bfd_vma pc)
645{
646  /* Assume success (for those operands that are nops).  */
647  int length = 1;
648  unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
649
650  switch (opindex)
651    {
652    case IP2K_OPERAND_ADDR16CJP :
653      length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 12, 13, 16, total_length, pc, & fields->f_addr16cjp);
654      break;
655    case IP2K_OPERAND_ADDR16H :
656      length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 8, 16, total_length, pc, & fields->f_imm8);
657      break;
658    case IP2K_OPERAND_ADDR16L :
659      length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 8, 16, total_length, pc, & fields->f_imm8);
660      break;
661    case IP2K_OPERAND_ADDR16P :
662      length = extract_normal (cd, ex_info, insn_value, 0, 0, 2, 3, 16, total_length, pc, & fields->f_page3);
663      break;
664    case IP2K_OPERAND_BITNO :
665      length = extract_normal (cd, ex_info, insn_value, 0, 0, 11, 3, 16, total_length, pc, & fields->f_bitno);
666      break;
667    case IP2K_OPERAND_CBIT :
668      break;
669    case IP2K_OPERAND_DCBIT :
670      break;
671    case IP2K_OPERAND_FR :
672      length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 9, 16, total_length, pc, & fields->f_reg);
673      break;
674    case IP2K_OPERAND_LIT8 :
675      length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 8, 16, total_length, pc, & fields->f_imm8);
676      break;
677    case IP2K_OPERAND_PABITS :
678      break;
679    case IP2K_OPERAND_RETI3 :
680      length = extract_normal (cd, ex_info, insn_value, 0, 0, 2, 3, 16, total_length, pc, & fields->f_reti3);
681      break;
682    case IP2K_OPERAND_ZBIT :
683      break;
684
685    default :
686      /* xgettext:c-format */
687      opcodes_error_handler
688	(_("internal error: unrecognized field %d while decoding insn"),
689	 opindex);
690      abort ();
691    }
692
693  return length;
694}
695
696cgen_insert_fn * const ip2k_cgen_insert_handlers[] =
697{
698  insert_insn_normal,
699};
700
701cgen_extract_fn * const ip2k_cgen_extract_handlers[] =
702{
703  extract_insn_normal,
704};
705
706int ip2k_cgen_get_int_operand     (CGEN_CPU_DESC, int, const CGEN_FIELDS *);
707bfd_vma ip2k_cgen_get_vma_operand (CGEN_CPU_DESC, int, const CGEN_FIELDS *);
708
709/* Getting values from cgen_fields is handled by a collection of functions.
710   They are distinguished by the type of the VALUE argument they return.
711   TODO: floating point, inlining support, remove cases where result type
712   not appropriate.  */
713
714int
715ip2k_cgen_get_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
716			     int opindex,
717			     const CGEN_FIELDS * fields)
718{
719  int value;
720
721  switch (opindex)
722    {
723    case IP2K_OPERAND_ADDR16CJP :
724      value = fields->f_addr16cjp;
725      break;
726    case IP2K_OPERAND_ADDR16H :
727      value = fields->f_imm8;
728      break;
729    case IP2K_OPERAND_ADDR16L :
730      value = fields->f_imm8;
731      break;
732    case IP2K_OPERAND_ADDR16P :
733      value = fields->f_page3;
734      break;
735    case IP2K_OPERAND_BITNO :
736      value = fields->f_bitno;
737      break;
738    case IP2K_OPERAND_CBIT :
739      value = 0;
740      break;
741    case IP2K_OPERAND_DCBIT :
742      value = 0;
743      break;
744    case IP2K_OPERAND_FR :
745      value = fields->f_reg;
746      break;
747    case IP2K_OPERAND_LIT8 :
748      value = fields->f_imm8;
749      break;
750    case IP2K_OPERAND_PABITS :
751      value = 0;
752      break;
753    case IP2K_OPERAND_RETI3 :
754      value = fields->f_reti3;
755      break;
756    case IP2K_OPERAND_ZBIT :
757      value = 0;
758      break;
759
760    default :
761      /* xgettext:c-format */
762      opcodes_error_handler
763	(_("internal error: unrecognized field %d while getting int operand"),
764	 opindex);
765      abort ();
766  }
767
768  return value;
769}
770
771bfd_vma
772ip2k_cgen_get_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
773			     int opindex,
774			     const CGEN_FIELDS * fields)
775{
776  bfd_vma value;
777
778  switch (opindex)
779    {
780    case IP2K_OPERAND_ADDR16CJP :
781      value = fields->f_addr16cjp;
782      break;
783    case IP2K_OPERAND_ADDR16H :
784      value = fields->f_imm8;
785      break;
786    case IP2K_OPERAND_ADDR16L :
787      value = fields->f_imm8;
788      break;
789    case IP2K_OPERAND_ADDR16P :
790      value = fields->f_page3;
791      break;
792    case IP2K_OPERAND_BITNO :
793      value = fields->f_bitno;
794      break;
795    case IP2K_OPERAND_CBIT :
796      value = 0;
797      break;
798    case IP2K_OPERAND_DCBIT :
799      value = 0;
800      break;
801    case IP2K_OPERAND_FR :
802      value = fields->f_reg;
803      break;
804    case IP2K_OPERAND_LIT8 :
805      value = fields->f_imm8;
806      break;
807    case IP2K_OPERAND_PABITS :
808      value = 0;
809      break;
810    case IP2K_OPERAND_RETI3 :
811      value = fields->f_reti3;
812      break;
813    case IP2K_OPERAND_ZBIT :
814      value = 0;
815      break;
816
817    default :
818      /* xgettext:c-format */
819      opcodes_error_handler
820	(_("internal error: unrecognized field %d while getting vma operand"),
821	 opindex);
822      abort ();
823  }
824
825  return value;
826}
827
828void ip2k_cgen_set_int_operand  (CGEN_CPU_DESC, int, CGEN_FIELDS *, int);
829void ip2k_cgen_set_vma_operand  (CGEN_CPU_DESC, int, CGEN_FIELDS *, bfd_vma);
830
831/* Stuffing values in cgen_fields is handled by a collection of functions.
832   They are distinguished by the type of the VALUE argument they accept.
833   TODO: floating point, inlining support, remove cases where argument type
834   not appropriate.  */
835
836void
837ip2k_cgen_set_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
838			     int opindex,
839			     CGEN_FIELDS * fields,
840			     int value)
841{
842  switch (opindex)
843    {
844    case IP2K_OPERAND_ADDR16CJP :
845      fields->f_addr16cjp = value;
846      break;
847    case IP2K_OPERAND_ADDR16H :
848      fields->f_imm8 = value;
849      break;
850    case IP2K_OPERAND_ADDR16L :
851      fields->f_imm8 = value;
852      break;
853    case IP2K_OPERAND_ADDR16P :
854      fields->f_page3 = value;
855      break;
856    case IP2K_OPERAND_BITNO :
857      fields->f_bitno = value;
858      break;
859    case IP2K_OPERAND_CBIT :
860      break;
861    case IP2K_OPERAND_DCBIT :
862      break;
863    case IP2K_OPERAND_FR :
864      fields->f_reg = value;
865      break;
866    case IP2K_OPERAND_LIT8 :
867      fields->f_imm8 = value;
868      break;
869    case IP2K_OPERAND_PABITS :
870      break;
871    case IP2K_OPERAND_RETI3 :
872      fields->f_reti3 = value;
873      break;
874    case IP2K_OPERAND_ZBIT :
875      break;
876
877    default :
878      /* xgettext:c-format */
879      opcodes_error_handler
880	(_("internal error: unrecognized field %d while setting int operand"),
881	 opindex);
882      abort ();
883  }
884}
885
886void
887ip2k_cgen_set_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
888			     int opindex,
889			     CGEN_FIELDS * fields,
890			     bfd_vma value)
891{
892  switch (opindex)
893    {
894    case IP2K_OPERAND_ADDR16CJP :
895      fields->f_addr16cjp = value;
896      break;
897    case IP2K_OPERAND_ADDR16H :
898      fields->f_imm8 = value;
899      break;
900    case IP2K_OPERAND_ADDR16L :
901      fields->f_imm8 = value;
902      break;
903    case IP2K_OPERAND_ADDR16P :
904      fields->f_page3 = value;
905      break;
906    case IP2K_OPERAND_BITNO :
907      fields->f_bitno = value;
908      break;
909    case IP2K_OPERAND_CBIT :
910      break;
911    case IP2K_OPERAND_DCBIT :
912      break;
913    case IP2K_OPERAND_FR :
914      fields->f_reg = value;
915      break;
916    case IP2K_OPERAND_LIT8 :
917      fields->f_imm8 = value;
918      break;
919    case IP2K_OPERAND_PABITS :
920      break;
921    case IP2K_OPERAND_RETI3 :
922      fields->f_reti3 = value;
923      break;
924    case IP2K_OPERAND_ZBIT :
925      break;
926
927    default :
928      /* xgettext:c-format */
929      opcodes_error_handler
930	(_("internal error: unrecognized field %d while setting vma operand"),
931	 opindex);
932      abort ();
933  }
934}
935
936/* Function to call before using the instruction builder tables.  */
937
938void
939ip2k_cgen_init_ibld_table (CGEN_CPU_DESC cd)
940{
941  cd->insert_handlers = & ip2k_cgen_insert_handlers[0];
942  cd->extract_handlers = & ip2k_cgen_extract_handlers[0];
943
944  cd->insert_operand = ip2k_cgen_insert_operand;
945  cd->extract_operand = ip2k_cgen_extract_operand;
946
947  cd->get_int_operand = ip2k_cgen_get_int_operand;
948  cd->set_int_operand = ip2k_cgen_set_int_operand;
949  cd->get_vma_operand = ip2k_cgen_get_vma_operand;
950  cd->set_vma_operand = ip2k_cgen_set_vma_operand;
951}
952