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