merge from gcc
[binutils.git] / opcodes / ip2k-ibld.c
blobcd39392c98a94acb8695bdc073c8f4bf3b142467
1 /* Instruction building/extraction support for ip2k. -*- C -*-
3 THIS FILE IS MACHINE GENERATED WITH CGEN: Cpu tools GENerator.
4 - the resultant file is machine generated, cgen-ibld.in isn't
6 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2005
7 Free Software Foundation, Inc.
9 This file is part of the GNU Binutils and GDB, the GNU debugger.
11 This program 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 2, or (at your option)
14 any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
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. */
25 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
26 Keep that in mind. */
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 "opintl.h"
37 #include "safe-ctype.h"
39 #undef min
40 #define min(a,b) ((a) < (b) ? (a) : (b))
41 #undef max
42 #define max(a,b) ((a) > (b) ? (a) : (b))
44 /* Used by the ifield rtx function. */
45 #define FLD(f) (fields->f)
47 static const char * insert_normal
48 (CGEN_CPU_DESC, long, unsigned int, unsigned int, unsigned int,
49 unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR);
50 static const char * insert_insn_normal
51 (CGEN_CPU_DESC, const CGEN_INSN *,
52 CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
53 static int extract_normal
54 (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
55 unsigned int, unsigned int, unsigned int, unsigned int,
56 unsigned int, unsigned int, bfd_vma, long *);
57 static int extract_insn_normal
58 (CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
59 CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
60 #if CGEN_INT_INSN_P
61 static void put_insn_int_value
62 (CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT);
63 #endif
64 #if ! CGEN_INT_INSN_P
65 static CGEN_INLINE void insert_1
66 (CGEN_CPU_DESC, unsigned long, int, int, int, unsigned char *);
67 static CGEN_INLINE int fill_cache
68 (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, bfd_vma);
69 static CGEN_INLINE long extract_1
70 (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, int, unsigned char *, bfd_vma);
71 #endif
73 /* Operand insertion. */
75 #if ! CGEN_INT_INSN_P
77 /* Subroutine of insert_normal. */
79 static CGEN_INLINE void
80 insert_1 (CGEN_CPU_DESC cd,
81 unsigned long value,
82 int start,
83 int length,
84 int word_length,
85 unsigned char *bufp)
87 unsigned long x,mask;
88 int shift;
90 x = cgen_get_insn_value (cd, bufp, word_length);
92 /* Written this way to avoid undefined behaviour. */
93 mask = (((1L << (length - 1)) - 1) << 1) | 1;
94 if (CGEN_INSN_LSB0_P)
95 shift = (start + 1) - length;
96 else
97 shift = (word_length - (start + length));
98 x = (x & ~(mask << shift)) | ((value & mask) << shift);
100 cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
103 #endif /* ! CGEN_INT_INSN_P */
105 /* Default insertion routine.
107 ATTRS is a mask of the boolean attributes.
108 WORD_OFFSET is the offset in bits from the start of the insn of the value.
109 WORD_LENGTH is the length of the word in bits in which the value resides.
110 START is the starting bit number in the word, architecture origin.
111 LENGTH is the length of VALUE in bits.
112 TOTAL_LENGTH is the total length of the insn in bits.
114 The result is an error message or NULL if success. */
116 /* ??? This duplicates functionality with bfd's howto table and
117 bfd_install_relocation. */
118 /* ??? This doesn't handle bfd_vma's. Create another function when
119 necessary. */
121 static const char *
122 insert_normal (CGEN_CPU_DESC cd,
123 long value,
124 unsigned int attrs,
125 unsigned int word_offset,
126 unsigned int start,
127 unsigned int length,
128 unsigned int word_length,
129 unsigned int total_length,
130 CGEN_INSN_BYTES_PTR buffer)
132 static char errbuf[100];
133 /* Written this way to avoid undefined behaviour. */
134 unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
136 /* If LENGTH is zero, this operand doesn't contribute to the value. */
137 if (length == 0)
138 return NULL;
140 if (word_length > 32)
141 abort ();
143 /* For architectures with insns smaller than the base-insn-bitsize,
144 word_length may be too big. */
145 if (cd->min_insn_bitsize < cd->base_insn_bitsize)
147 if (word_offset == 0
148 && word_length > total_length)
149 word_length = total_length;
152 /* Ensure VALUE will fit. */
153 if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
155 long minval = - (1L << (length - 1));
156 unsigned long maxval = mask;
158 if ((value > 0 && (unsigned long) value > maxval)
159 || value < minval)
161 /* xgettext:c-format */
162 sprintf (errbuf,
163 _("operand out of range (%ld not between %ld and %lu)"),
164 value, minval, maxval);
165 return errbuf;
168 else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
170 unsigned long maxval = mask;
172 if ((unsigned long) value > maxval)
174 /* xgettext:c-format */
175 sprintf (errbuf,
176 _("operand out of range (%lu not between 0 and %lu)"),
177 value, maxval);
178 return errbuf;
181 else
183 if (! cgen_signed_overflow_ok_p (cd))
185 long minval = - (1L << (length - 1));
186 long maxval = (1L << (length - 1)) - 1;
188 if (value < minval || value > maxval)
190 sprintf
191 /* xgettext:c-format */
192 (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
193 value, minval, maxval);
194 return errbuf;
199 #if CGEN_INT_INSN_P
202 int shift;
204 if (CGEN_INSN_LSB0_P)
205 shift = (word_offset + start + 1) - length;
206 else
207 shift = total_length - (word_offset + start + length);
208 *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
211 #else /* ! CGEN_INT_INSN_P */
214 unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
216 insert_1 (cd, value, start, length, word_length, bufp);
219 #endif /* ! CGEN_INT_INSN_P */
221 return NULL;
224 /* Default insn builder (insert handler).
225 The instruction is recorded in CGEN_INT_INSN_P byte order (meaning
226 that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is
227 recorded in host byte order, otherwise BUFFER is an array of bytes
228 and the value is recorded in target byte order).
229 The result is an error message or NULL if success. */
231 static const char *
232 insert_insn_normal (CGEN_CPU_DESC cd,
233 const CGEN_INSN * insn,
234 CGEN_FIELDS * fields,
235 CGEN_INSN_BYTES_PTR buffer,
236 bfd_vma pc)
238 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
239 unsigned long value;
240 const CGEN_SYNTAX_CHAR_TYPE * syn;
242 CGEN_INIT_INSERT (cd);
243 value = CGEN_INSN_BASE_VALUE (insn);
245 /* If we're recording insns as numbers (rather than a string of bytes),
246 target byte order handling is deferred until later. */
248 #if CGEN_INT_INSN_P
250 put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
251 CGEN_FIELDS_BITSIZE (fields), value);
253 #else
255 cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
256 (unsigned) CGEN_FIELDS_BITSIZE (fields)),
257 value);
259 #endif /* ! CGEN_INT_INSN_P */
261 /* ??? It would be better to scan the format's fields.
262 Still need to be able to insert a value based on the operand though;
263 e.g. storing a branch displacement that got resolved later.
264 Needs more thought first. */
266 for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn)
268 const char *errmsg;
270 if (CGEN_SYNTAX_CHAR_P (* syn))
271 continue;
273 errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
274 fields, buffer, pc);
275 if (errmsg)
276 return errmsg;
279 return NULL;
282 #if CGEN_INT_INSN_P
283 /* Cover function to store an insn value into an integral insn. Must go here
284 because it needs <prefix>-desc.h for CGEN_INT_INSN_P. */
286 static void
287 put_insn_int_value (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
288 CGEN_INSN_BYTES_PTR buf,
289 int length,
290 int insn_length,
291 CGEN_INSN_INT value)
293 /* For architectures with insns smaller than the base-insn-bitsize,
294 length may be too big. */
295 if (length > insn_length)
296 *buf = value;
297 else
299 int shift = insn_length - length;
300 /* Written this way to avoid undefined behaviour. */
301 CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
303 *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
306 #endif
308 /* Operand extraction. */
310 #if ! CGEN_INT_INSN_P
312 /* Subroutine of extract_normal.
313 Ensure sufficient bytes are cached in EX_INFO.
314 OFFSET is the offset in bytes from the start of the insn of the value.
315 BYTES is the length of the needed value.
316 Returns 1 for success, 0 for failure. */
318 static CGEN_INLINE int
319 fill_cache (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
320 CGEN_EXTRACT_INFO *ex_info,
321 int offset,
322 int bytes,
323 bfd_vma pc)
325 /* It's doubtful that the middle part has already been fetched so
326 we don't optimize that case. kiss. */
327 unsigned int mask;
328 disassemble_info *info = (disassemble_info *) ex_info->dis_info;
330 /* First do a quick check. */
331 mask = (1 << bytes) - 1;
332 if (((ex_info->valid >> offset) & mask) == mask)
333 return 1;
335 /* Search for the first byte we need to read. */
336 for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
337 if (! (mask & ex_info->valid))
338 break;
340 if (bytes)
342 int status;
344 pc += offset;
345 status = (*info->read_memory_func)
346 (pc, ex_info->insn_bytes + offset, bytes, info);
348 if (status != 0)
350 (*info->memory_error_func) (status, pc, info);
351 return 0;
354 ex_info->valid |= ((1 << bytes) - 1) << offset;
357 return 1;
360 /* Subroutine of extract_normal. */
362 static CGEN_INLINE long
363 extract_1 (CGEN_CPU_DESC cd,
364 CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
365 int start,
366 int length,
367 int word_length,
368 unsigned char *bufp,
369 bfd_vma pc ATTRIBUTE_UNUSED)
371 unsigned long x;
372 int shift;
374 x = cgen_get_insn_value (cd, bufp, word_length);
376 if (CGEN_INSN_LSB0_P)
377 shift = (start + 1) - length;
378 else
379 shift = (word_length - (start + length));
380 return x >> shift;
383 #endif /* ! CGEN_INT_INSN_P */
385 /* Default extraction routine.
387 INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
388 or sometimes less for cases like the m32r where the base insn size is 32
389 but some insns are 16 bits.
390 ATTRS is a mask of the boolean attributes. We only need `SIGNED',
391 but for generality we take a bitmask of all of them.
392 WORD_OFFSET is the offset in bits from the start of the insn of the value.
393 WORD_LENGTH is the length of the word in bits in which the value resides.
394 START is the starting bit number in the word, architecture origin.
395 LENGTH is the length of VALUE in bits.
396 TOTAL_LENGTH is the total length of the insn in bits.
398 Returns 1 for success, 0 for failure. */
400 /* ??? The return code isn't properly used. wip. */
402 /* ??? This doesn't handle bfd_vma's. Create another function when
403 necessary. */
405 static int
406 extract_normal (CGEN_CPU_DESC cd,
407 #if ! CGEN_INT_INSN_P
408 CGEN_EXTRACT_INFO *ex_info,
409 #else
410 CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
411 #endif
412 CGEN_INSN_INT insn_value,
413 unsigned int attrs,
414 unsigned int word_offset,
415 unsigned int start,
416 unsigned int length,
417 unsigned int word_length,
418 unsigned int total_length,
419 #if ! CGEN_INT_INSN_P
420 bfd_vma pc,
421 #else
422 bfd_vma pc ATTRIBUTE_UNUSED,
423 #endif
424 long *valuep)
426 long value, mask;
428 /* If LENGTH is zero, this operand doesn't contribute to the value
429 so give it a standard value of zero. */
430 if (length == 0)
432 *valuep = 0;
433 return 1;
436 if (word_length > 32)
437 abort ();
439 /* For architectures with insns smaller than the insn-base-bitsize,
440 word_length may be too big. */
441 if (cd->min_insn_bitsize < cd->base_insn_bitsize)
443 if (word_offset == 0
444 && word_length > total_length)
445 word_length = total_length;
448 /* Does the value reside in INSN_VALUE, and at the right alignment? */
450 if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
452 if (CGEN_INSN_LSB0_P)
453 value = insn_value >> ((word_offset + start + 1) - length);
454 else
455 value = insn_value >> (total_length - ( word_offset + start + length));
458 #if ! CGEN_INT_INSN_P
460 else
462 unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
464 if (word_length > 32)
465 abort ();
467 if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
468 return 0;
470 value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
473 #endif /* ! CGEN_INT_INSN_P */
475 /* Written this way to avoid undefined behaviour. */
476 mask = (((1L << (length - 1)) - 1) << 1) | 1;
478 value &= mask;
479 /* sign extend? */
480 if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
481 && (value & (1L << (length - 1))))
482 value |= ~mask;
484 *valuep = value;
486 return 1;
489 /* Default insn extractor.
491 INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
492 The extracted fields are stored in FIELDS.
493 EX_INFO is used to handle reading variable length insns.
494 Return the length of the insn in bits, or 0 if no match,
495 or -1 if an error occurs fetching data (memory_error_func will have
496 been called). */
498 static int
499 extract_insn_normal (CGEN_CPU_DESC cd,
500 const CGEN_INSN *insn,
501 CGEN_EXTRACT_INFO *ex_info,
502 CGEN_INSN_INT insn_value,
503 CGEN_FIELDS *fields,
504 bfd_vma pc)
506 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
507 const CGEN_SYNTAX_CHAR_TYPE *syn;
509 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
511 CGEN_INIT_EXTRACT (cd);
513 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
515 int length;
517 if (CGEN_SYNTAX_CHAR_P (*syn))
518 continue;
520 length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
521 ex_info, insn_value, fields, pc);
522 if (length <= 0)
523 return length;
526 /* We recognized and successfully extracted this insn. */
527 return CGEN_INSN_BITSIZE (insn);
530 /* Machine generated code added here. */
532 const char * ip2k_cgen_insert_operand
533 (CGEN_CPU_DESC, int, CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
535 /* Main entry point for operand insertion.
537 This function is basically just a big switch statement. Earlier versions
538 used tables to look up the function to use, but
539 - if the table contains both assembler and disassembler functions then
540 the disassembler contains much of the assembler and vice-versa,
541 - there's a lot of inlining possibilities as things grow,
542 - using a switch statement avoids the function call overhead.
544 This function could be moved into `parse_insn_normal', but keeping it
545 separate makes clear the interface between `parse_insn_normal' and each of
546 the handlers. It's also needed by GAS to insert operands that couldn't be
547 resolved during parsing. */
549 const char *
550 ip2k_cgen_insert_operand (CGEN_CPU_DESC cd,
551 int opindex,
552 CGEN_FIELDS * fields,
553 CGEN_INSN_BYTES_PTR buffer,
554 bfd_vma pc ATTRIBUTE_UNUSED)
556 const char * errmsg = NULL;
557 unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
559 switch (opindex)
561 case IP2K_OPERAND_ADDR16CJP :
562 errmsg = insert_normal (cd, fields->f_addr16cjp, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 12, 13, 16, total_length, buffer);
563 break;
564 case IP2K_OPERAND_ADDR16H :
565 errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 7, 8, 16, total_length, buffer);
566 break;
567 case IP2K_OPERAND_ADDR16L :
568 errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 7, 8, 16, total_length, buffer);
569 break;
570 case IP2K_OPERAND_ADDR16P :
571 errmsg = insert_normal (cd, fields->f_page3, 0, 0, 2, 3, 16, total_length, buffer);
572 break;
573 case IP2K_OPERAND_BITNO :
574 errmsg = insert_normal (cd, fields->f_bitno, 0, 0, 11, 3, 16, total_length, buffer);
575 break;
576 case IP2K_OPERAND_CBIT :
577 break;
578 case IP2K_OPERAND_DCBIT :
579 break;
580 case IP2K_OPERAND_FR :
581 errmsg = insert_normal (cd, fields->f_reg, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 9, 16, total_length, buffer);
582 break;
583 case IP2K_OPERAND_LIT8 :
584 errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 7, 8, 16, total_length, buffer);
585 break;
586 case IP2K_OPERAND_PABITS :
587 break;
588 case IP2K_OPERAND_RETI3 :
589 errmsg = insert_normal (cd, fields->f_reti3, 0, 0, 2, 3, 16, total_length, buffer);
590 break;
591 case IP2K_OPERAND_ZBIT :
592 break;
594 default :
595 /* xgettext:c-format */
596 fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
597 opindex);
598 abort ();
601 return errmsg;
604 int ip2k_cgen_extract_operand
605 (CGEN_CPU_DESC, int, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
607 /* Main entry point for operand extraction.
608 The result is <= 0 for error, >0 for success.
609 ??? Actual values aren't well defined right now.
611 This function is basically just a big switch statement. Earlier versions
612 used tables to look up the function to use, but
613 - if the table contains both assembler and disassembler functions then
614 the disassembler contains much of the assembler and vice-versa,
615 - there's a lot of inlining possibilities as things grow,
616 - using a switch statement avoids the function call overhead.
618 This function could be moved into `print_insn_normal', but keeping it
619 separate makes clear the interface between `print_insn_normal' and each of
620 the handlers. */
623 ip2k_cgen_extract_operand (CGEN_CPU_DESC cd,
624 int opindex,
625 CGEN_EXTRACT_INFO *ex_info,
626 CGEN_INSN_INT insn_value,
627 CGEN_FIELDS * fields,
628 bfd_vma pc)
630 /* Assume success (for those operands that are nops). */
631 int length = 1;
632 unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
634 switch (opindex)
636 case IP2K_OPERAND_ADDR16CJP :
637 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 12, 13, 16, total_length, pc, & fields->f_addr16cjp);
638 break;
639 case IP2K_OPERAND_ADDR16H :
640 length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 8, 16, total_length, pc, & fields->f_imm8);
641 break;
642 case IP2K_OPERAND_ADDR16L :
643 length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 8, 16, total_length, pc, & fields->f_imm8);
644 break;
645 case IP2K_OPERAND_ADDR16P :
646 length = extract_normal (cd, ex_info, insn_value, 0, 0, 2, 3, 16, total_length, pc, & fields->f_page3);
647 break;
648 case IP2K_OPERAND_BITNO :
649 length = extract_normal (cd, ex_info, insn_value, 0, 0, 11, 3, 16, total_length, pc, & fields->f_bitno);
650 break;
651 case IP2K_OPERAND_CBIT :
652 break;
653 case IP2K_OPERAND_DCBIT :
654 break;
655 case IP2K_OPERAND_FR :
656 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 9, 16, total_length, pc, & fields->f_reg);
657 break;
658 case IP2K_OPERAND_LIT8 :
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_PABITS :
662 break;
663 case IP2K_OPERAND_RETI3 :
664 length = extract_normal (cd, ex_info, insn_value, 0, 0, 2, 3, 16, total_length, pc, & fields->f_reti3);
665 break;
666 case IP2K_OPERAND_ZBIT :
667 break;
669 default :
670 /* xgettext:c-format */
671 fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
672 opindex);
673 abort ();
676 return length;
679 cgen_insert_fn * const ip2k_cgen_insert_handlers[] =
681 insert_insn_normal,
684 cgen_extract_fn * const ip2k_cgen_extract_handlers[] =
686 extract_insn_normal,
689 int ip2k_cgen_get_int_operand (CGEN_CPU_DESC, int, const CGEN_FIELDS *);
690 bfd_vma ip2k_cgen_get_vma_operand (CGEN_CPU_DESC, int, const CGEN_FIELDS *);
692 /* Getting values from cgen_fields is handled by a collection of functions.
693 They are distinguished by the type of the VALUE argument they return.
694 TODO: floating point, inlining support, remove cases where result type
695 not appropriate. */
698 ip2k_cgen_get_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
699 int opindex,
700 const CGEN_FIELDS * fields)
702 int value;
704 switch (opindex)
706 case IP2K_OPERAND_ADDR16CJP :
707 value = fields->f_addr16cjp;
708 break;
709 case IP2K_OPERAND_ADDR16H :
710 value = fields->f_imm8;
711 break;
712 case IP2K_OPERAND_ADDR16L :
713 value = fields->f_imm8;
714 break;
715 case IP2K_OPERAND_ADDR16P :
716 value = fields->f_page3;
717 break;
718 case IP2K_OPERAND_BITNO :
719 value = fields->f_bitno;
720 break;
721 case IP2K_OPERAND_CBIT :
722 value = 0;
723 break;
724 case IP2K_OPERAND_DCBIT :
725 value = 0;
726 break;
727 case IP2K_OPERAND_FR :
728 value = fields->f_reg;
729 break;
730 case IP2K_OPERAND_LIT8 :
731 value = fields->f_imm8;
732 break;
733 case IP2K_OPERAND_PABITS :
734 value = 0;
735 break;
736 case IP2K_OPERAND_RETI3 :
737 value = fields->f_reti3;
738 break;
739 case IP2K_OPERAND_ZBIT :
740 value = 0;
741 break;
743 default :
744 /* xgettext:c-format */
745 fprintf (stderr, _("Unrecognized field %d while getting int operand.\n"),
746 opindex);
747 abort ();
750 return value;
753 bfd_vma
754 ip2k_cgen_get_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
755 int opindex,
756 const CGEN_FIELDS * fields)
758 bfd_vma value;
760 switch (opindex)
762 case IP2K_OPERAND_ADDR16CJP :
763 value = fields->f_addr16cjp;
764 break;
765 case IP2K_OPERAND_ADDR16H :
766 value = fields->f_imm8;
767 break;
768 case IP2K_OPERAND_ADDR16L :
769 value = fields->f_imm8;
770 break;
771 case IP2K_OPERAND_ADDR16P :
772 value = fields->f_page3;
773 break;
774 case IP2K_OPERAND_BITNO :
775 value = fields->f_bitno;
776 break;
777 case IP2K_OPERAND_CBIT :
778 value = 0;
779 break;
780 case IP2K_OPERAND_DCBIT :
781 value = 0;
782 break;
783 case IP2K_OPERAND_FR :
784 value = fields->f_reg;
785 break;
786 case IP2K_OPERAND_LIT8 :
787 value = fields->f_imm8;
788 break;
789 case IP2K_OPERAND_PABITS :
790 value = 0;
791 break;
792 case IP2K_OPERAND_RETI3 :
793 value = fields->f_reti3;
794 break;
795 case IP2K_OPERAND_ZBIT :
796 value = 0;
797 break;
799 default :
800 /* xgettext:c-format */
801 fprintf (stderr, _("Unrecognized field %d while getting vma operand.\n"),
802 opindex);
803 abort ();
806 return value;
809 void ip2k_cgen_set_int_operand (CGEN_CPU_DESC, int, CGEN_FIELDS *, int);
810 void ip2k_cgen_set_vma_operand (CGEN_CPU_DESC, int, CGEN_FIELDS *, bfd_vma);
812 /* Stuffing values in cgen_fields is handled by a collection of functions.
813 They are distinguished by the type of the VALUE argument they accept.
814 TODO: floating point, inlining support, remove cases where argument type
815 not appropriate. */
817 void
818 ip2k_cgen_set_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
819 int opindex,
820 CGEN_FIELDS * fields,
821 int value)
823 switch (opindex)
825 case IP2K_OPERAND_ADDR16CJP :
826 fields->f_addr16cjp = value;
827 break;
828 case IP2K_OPERAND_ADDR16H :
829 fields->f_imm8 = value;
830 break;
831 case IP2K_OPERAND_ADDR16L :
832 fields->f_imm8 = value;
833 break;
834 case IP2K_OPERAND_ADDR16P :
835 fields->f_page3 = value;
836 break;
837 case IP2K_OPERAND_BITNO :
838 fields->f_bitno = value;
839 break;
840 case IP2K_OPERAND_CBIT :
841 break;
842 case IP2K_OPERAND_DCBIT :
843 break;
844 case IP2K_OPERAND_FR :
845 fields->f_reg = value;
846 break;
847 case IP2K_OPERAND_LIT8 :
848 fields->f_imm8 = value;
849 break;
850 case IP2K_OPERAND_PABITS :
851 break;
852 case IP2K_OPERAND_RETI3 :
853 fields->f_reti3 = value;
854 break;
855 case IP2K_OPERAND_ZBIT :
856 break;
858 default :
859 /* xgettext:c-format */
860 fprintf (stderr, _("Unrecognized field %d while setting int operand.\n"),
861 opindex);
862 abort ();
866 void
867 ip2k_cgen_set_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
868 int opindex,
869 CGEN_FIELDS * fields,
870 bfd_vma value)
872 switch (opindex)
874 case IP2K_OPERAND_ADDR16CJP :
875 fields->f_addr16cjp = value;
876 break;
877 case IP2K_OPERAND_ADDR16H :
878 fields->f_imm8 = value;
879 break;
880 case IP2K_OPERAND_ADDR16L :
881 fields->f_imm8 = value;
882 break;
883 case IP2K_OPERAND_ADDR16P :
884 fields->f_page3 = value;
885 break;
886 case IP2K_OPERAND_BITNO :
887 fields->f_bitno = value;
888 break;
889 case IP2K_OPERAND_CBIT :
890 break;
891 case IP2K_OPERAND_DCBIT :
892 break;
893 case IP2K_OPERAND_FR :
894 fields->f_reg = value;
895 break;
896 case IP2K_OPERAND_LIT8 :
897 fields->f_imm8 = value;
898 break;
899 case IP2K_OPERAND_PABITS :
900 break;
901 case IP2K_OPERAND_RETI3 :
902 fields->f_reti3 = value;
903 break;
904 case IP2K_OPERAND_ZBIT :
905 break;
907 default :
908 /* xgettext:c-format */
909 fprintf (stderr, _("Unrecognized field %d while setting vma operand.\n"),
910 opindex);
911 abort ();
915 /* Function to call before using the instruction builder tables. */
917 void
918 ip2k_cgen_init_ibld_table (CGEN_CPU_DESC cd)
920 cd->insert_handlers = & ip2k_cgen_insert_handlers[0];
921 cd->extract_handlers = & ip2k_cgen_extract_handlers[0];
923 cd->insert_operand = ip2k_cgen_insert_operand;
924 cd->extract_operand = ip2k_cgen_extract_operand;
926 cd->get_int_operand = ip2k_cgen_get_int_operand;
927 cd->set_int_operand = ip2k_cgen_set_int_operand;
928 cd->get_vma_operand = ip2k_cgen_get_vma_operand;
929 cd->set_vma_operand = ip2k_cgen_set_vma_operand;