2005-09-01 Dmitry Diky <diwil@spec.ru>
[binutils.git] / opcodes / xstormy16-ibld.c
blob57ef85cdf0c02f5c2a6589bbe50e080e6c7cd0ad
1 /* Instruction building/extraction support for xstormy16. -*- 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 "xstormy16-desc.h"
35 #include "xstormy16-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 * xstormy16_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 xstormy16_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 XSTORMY16_OPERAND_RB :
562 errmsg = insert_normal (cd, fields->f_Rb, 0, 0, 17, 3, 32, total_length, buffer);
563 break;
564 case XSTORMY16_OPERAND_RBJ :
565 errmsg = insert_normal (cd, fields->f_Rbj, 0, 0, 11, 1, 32, total_length, buffer);
566 break;
567 case XSTORMY16_OPERAND_RD :
568 errmsg = insert_normal (cd, fields->f_Rd, 0, 0, 12, 4, 32, total_length, buffer);
569 break;
570 case XSTORMY16_OPERAND_RDM :
571 errmsg = insert_normal (cd, fields->f_Rdm, 0, 0, 13, 3, 32, total_length, buffer);
572 break;
573 case XSTORMY16_OPERAND_RM :
574 errmsg = insert_normal (cd, fields->f_Rm, 0, 0, 4, 3, 32, total_length, buffer);
575 break;
576 case XSTORMY16_OPERAND_RS :
577 errmsg = insert_normal (cd, fields->f_Rs, 0, 0, 8, 4, 32, total_length, buffer);
578 break;
579 case XSTORMY16_OPERAND_ABS24 :
582 FLD (f_abs24_1) = ((FLD (f_abs24)) & (255));
583 FLD (f_abs24_2) = ((unsigned int) (FLD (f_abs24)) >> (8));
585 errmsg = insert_normal (cd, fields->f_abs24_1, 0, 0, 8, 8, 32, total_length, buffer);
586 if (errmsg)
587 break;
588 errmsg = insert_normal (cd, fields->f_abs24_2, 0, 0, 16, 16, 32, total_length, buffer);
589 if (errmsg)
590 break;
592 break;
593 case XSTORMY16_OPERAND_BCOND2 :
594 errmsg = insert_normal (cd, fields->f_op2, 0, 0, 4, 4, 32, total_length, buffer);
595 break;
596 case XSTORMY16_OPERAND_BCOND5 :
597 errmsg = insert_normal (cd, fields->f_op5, 0, 0, 16, 4, 32, total_length, buffer);
598 break;
599 case XSTORMY16_OPERAND_HMEM8 :
601 long value = fields->f_hmem8;
602 value = ((value) - (32512));
603 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, buffer);
605 break;
606 case XSTORMY16_OPERAND_IMM12 :
607 errmsg = insert_normal (cd, fields->f_imm12, 0|(1<<CGEN_IFLD_SIGNED), 0, 20, 12, 32, total_length, buffer);
608 break;
609 case XSTORMY16_OPERAND_IMM16 :
610 errmsg = insert_normal (cd, fields->f_imm16, 0|(1<<CGEN_IFLD_SIGN_OPT), 0, 16, 16, 32, total_length, buffer);
611 break;
612 case XSTORMY16_OPERAND_IMM2 :
613 errmsg = insert_normal (cd, fields->f_imm2, 0, 0, 10, 2, 32, total_length, buffer);
614 break;
615 case XSTORMY16_OPERAND_IMM3 :
616 errmsg = insert_normal (cd, fields->f_imm3, 0, 0, 4, 3, 32, total_length, buffer);
617 break;
618 case XSTORMY16_OPERAND_IMM3B :
619 errmsg = insert_normal (cd, fields->f_imm3b, 0, 0, 17, 3, 32, total_length, buffer);
620 break;
621 case XSTORMY16_OPERAND_IMM4 :
622 errmsg = insert_normal (cd, fields->f_imm4, 0, 0, 8, 4, 32, total_length, buffer);
623 break;
624 case XSTORMY16_OPERAND_IMM8 :
625 errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 8, 8, 32, total_length, buffer);
626 break;
627 case XSTORMY16_OPERAND_IMM8SMALL :
628 errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 8, 8, 32, total_length, buffer);
629 break;
630 case XSTORMY16_OPERAND_LMEM8 :
631 errmsg = insert_normal (cd, fields->f_lmem8, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, buffer);
632 break;
633 case XSTORMY16_OPERAND_REL12 :
635 long value = fields->f_rel12;
636 value = ((value) - (((pc) + (4))));
637 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 20, 12, 32, total_length, buffer);
639 break;
640 case XSTORMY16_OPERAND_REL12A :
642 long value = fields->f_rel12a;
643 value = ((int) (((value) - (((pc) + (2))))) >> (1));
644 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 4, 11, 32, total_length, buffer);
646 break;
647 case XSTORMY16_OPERAND_REL8_2 :
649 long value = fields->f_rel8_2;
650 value = ((value) - (((pc) + (2))));
651 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, buffer);
653 break;
654 case XSTORMY16_OPERAND_REL8_4 :
656 long value = fields->f_rel8_4;
657 value = ((value) - (((pc) + (4))));
658 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, buffer);
660 break;
661 case XSTORMY16_OPERAND_WS2 :
662 errmsg = insert_normal (cd, fields->f_op2m, 0, 0, 7, 1, 32, total_length, buffer);
663 break;
665 default :
666 /* xgettext:c-format */
667 fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
668 opindex);
669 abort ();
672 return errmsg;
675 int xstormy16_cgen_extract_operand
676 (CGEN_CPU_DESC, int, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
678 /* Main entry point for operand extraction.
679 The result is <= 0 for error, >0 for success.
680 ??? Actual values aren't well defined right now.
682 This function is basically just a big switch statement. Earlier versions
683 used tables to look up the function to use, but
684 - if the table contains both assembler and disassembler functions then
685 the disassembler contains much of the assembler and vice-versa,
686 - there's a lot of inlining possibilities as things grow,
687 - using a switch statement avoids the function call overhead.
689 This function could be moved into `print_insn_normal', but keeping it
690 separate makes clear the interface between `print_insn_normal' and each of
691 the handlers. */
694 xstormy16_cgen_extract_operand (CGEN_CPU_DESC cd,
695 int opindex,
696 CGEN_EXTRACT_INFO *ex_info,
697 CGEN_INSN_INT insn_value,
698 CGEN_FIELDS * fields,
699 bfd_vma pc)
701 /* Assume success (for those operands that are nops). */
702 int length = 1;
703 unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
705 switch (opindex)
707 case XSTORMY16_OPERAND_RB :
708 length = extract_normal (cd, ex_info, insn_value, 0, 0, 17, 3, 32, total_length, pc, & fields->f_Rb);
709 break;
710 case XSTORMY16_OPERAND_RBJ :
711 length = extract_normal (cd, ex_info, insn_value, 0, 0, 11, 1, 32, total_length, pc, & fields->f_Rbj);
712 break;
713 case XSTORMY16_OPERAND_RD :
714 length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 32, total_length, pc, & fields->f_Rd);
715 break;
716 case XSTORMY16_OPERAND_RDM :
717 length = extract_normal (cd, ex_info, insn_value, 0, 0, 13, 3, 32, total_length, pc, & fields->f_Rdm);
718 break;
719 case XSTORMY16_OPERAND_RM :
720 length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 3, 32, total_length, pc, & fields->f_Rm);
721 break;
722 case XSTORMY16_OPERAND_RS :
723 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 32, total_length, pc, & fields->f_Rs);
724 break;
725 case XSTORMY16_OPERAND_ABS24 :
727 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 32, total_length, pc, & fields->f_abs24_1);
728 if (length <= 0) break;
729 length = extract_normal (cd, ex_info, insn_value, 0, 0, 16, 16, 32, total_length, pc, & fields->f_abs24_2);
730 if (length <= 0) break;
731 FLD (f_abs24) = ((((FLD (f_abs24_2)) << (8))) | (FLD (f_abs24_1)));
733 break;
734 case XSTORMY16_OPERAND_BCOND2 :
735 length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 4, 32, total_length, pc, & fields->f_op2);
736 break;
737 case XSTORMY16_OPERAND_BCOND5 :
738 length = extract_normal (cd, ex_info, insn_value, 0, 0, 16, 4, 32, total_length, pc, & fields->f_op5);
739 break;
740 case XSTORMY16_OPERAND_HMEM8 :
742 long value;
743 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, pc, & value);
744 value = ((value) + (32512));
745 fields->f_hmem8 = value;
747 break;
748 case XSTORMY16_OPERAND_IMM12 :
749 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 20, 12, 32, total_length, pc, & fields->f_imm12);
750 break;
751 case XSTORMY16_OPERAND_IMM16 :
752 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGN_OPT), 0, 16, 16, 32, total_length, pc, & fields->f_imm16);
753 break;
754 case XSTORMY16_OPERAND_IMM2 :
755 length = extract_normal (cd, ex_info, insn_value, 0, 0, 10, 2, 32, total_length, pc, & fields->f_imm2);
756 break;
757 case XSTORMY16_OPERAND_IMM3 :
758 length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 3, 32, total_length, pc, & fields->f_imm3);
759 break;
760 case XSTORMY16_OPERAND_IMM3B :
761 length = extract_normal (cd, ex_info, insn_value, 0, 0, 17, 3, 32, total_length, pc, & fields->f_imm3b);
762 break;
763 case XSTORMY16_OPERAND_IMM4 :
764 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 32, total_length, pc, & fields->f_imm4);
765 break;
766 case XSTORMY16_OPERAND_IMM8 :
767 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 32, total_length, pc, & fields->f_imm8);
768 break;
769 case XSTORMY16_OPERAND_IMM8SMALL :
770 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 32, total_length, pc, & fields->f_imm8);
771 break;
772 case XSTORMY16_OPERAND_LMEM8 :
773 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, pc, & fields->f_lmem8);
774 break;
775 case XSTORMY16_OPERAND_REL12 :
777 long value;
778 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 20, 12, 32, total_length, pc, & value);
779 value = ((value) + (((pc) + (4))));
780 fields->f_rel12 = value;
782 break;
783 case XSTORMY16_OPERAND_REL12A :
785 long value;
786 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 4, 11, 32, total_length, pc, & value);
787 value = ((((value) << (1))) + (((pc) + (2))));
788 fields->f_rel12a = value;
790 break;
791 case XSTORMY16_OPERAND_REL8_2 :
793 long value;
794 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, pc, & value);
795 value = ((value) + (((pc) + (2))));
796 fields->f_rel8_2 = value;
798 break;
799 case XSTORMY16_OPERAND_REL8_4 :
801 long value;
802 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, pc, & value);
803 value = ((value) + (((pc) + (4))));
804 fields->f_rel8_4 = value;
806 break;
807 case XSTORMY16_OPERAND_WS2 :
808 length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 1, 32, total_length, pc, & fields->f_op2m);
809 break;
811 default :
812 /* xgettext:c-format */
813 fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
814 opindex);
815 abort ();
818 return length;
821 cgen_insert_fn * const xstormy16_cgen_insert_handlers[] =
823 insert_insn_normal,
826 cgen_extract_fn * const xstormy16_cgen_extract_handlers[] =
828 extract_insn_normal,
831 int xstormy16_cgen_get_int_operand (CGEN_CPU_DESC, int, const CGEN_FIELDS *);
832 bfd_vma xstormy16_cgen_get_vma_operand (CGEN_CPU_DESC, int, const CGEN_FIELDS *);
834 /* Getting values from cgen_fields is handled by a collection of functions.
835 They are distinguished by the type of the VALUE argument they return.
836 TODO: floating point, inlining support, remove cases where result type
837 not appropriate. */
840 xstormy16_cgen_get_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
841 int opindex,
842 const CGEN_FIELDS * fields)
844 int value;
846 switch (opindex)
848 case XSTORMY16_OPERAND_RB :
849 value = fields->f_Rb;
850 break;
851 case XSTORMY16_OPERAND_RBJ :
852 value = fields->f_Rbj;
853 break;
854 case XSTORMY16_OPERAND_RD :
855 value = fields->f_Rd;
856 break;
857 case XSTORMY16_OPERAND_RDM :
858 value = fields->f_Rdm;
859 break;
860 case XSTORMY16_OPERAND_RM :
861 value = fields->f_Rm;
862 break;
863 case XSTORMY16_OPERAND_RS :
864 value = fields->f_Rs;
865 break;
866 case XSTORMY16_OPERAND_ABS24 :
867 value = fields->f_abs24;
868 break;
869 case XSTORMY16_OPERAND_BCOND2 :
870 value = fields->f_op2;
871 break;
872 case XSTORMY16_OPERAND_BCOND5 :
873 value = fields->f_op5;
874 break;
875 case XSTORMY16_OPERAND_HMEM8 :
876 value = fields->f_hmem8;
877 break;
878 case XSTORMY16_OPERAND_IMM12 :
879 value = fields->f_imm12;
880 break;
881 case XSTORMY16_OPERAND_IMM16 :
882 value = fields->f_imm16;
883 break;
884 case XSTORMY16_OPERAND_IMM2 :
885 value = fields->f_imm2;
886 break;
887 case XSTORMY16_OPERAND_IMM3 :
888 value = fields->f_imm3;
889 break;
890 case XSTORMY16_OPERAND_IMM3B :
891 value = fields->f_imm3b;
892 break;
893 case XSTORMY16_OPERAND_IMM4 :
894 value = fields->f_imm4;
895 break;
896 case XSTORMY16_OPERAND_IMM8 :
897 value = fields->f_imm8;
898 break;
899 case XSTORMY16_OPERAND_IMM8SMALL :
900 value = fields->f_imm8;
901 break;
902 case XSTORMY16_OPERAND_LMEM8 :
903 value = fields->f_lmem8;
904 break;
905 case XSTORMY16_OPERAND_REL12 :
906 value = fields->f_rel12;
907 break;
908 case XSTORMY16_OPERAND_REL12A :
909 value = fields->f_rel12a;
910 break;
911 case XSTORMY16_OPERAND_REL8_2 :
912 value = fields->f_rel8_2;
913 break;
914 case XSTORMY16_OPERAND_REL8_4 :
915 value = fields->f_rel8_4;
916 break;
917 case XSTORMY16_OPERAND_WS2 :
918 value = fields->f_op2m;
919 break;
921 default :
922 /* xgettext:c-format */
923 fprintf (stderr, _("Unrecognized field %d while getting int operand.\n"),
924 opindex);
925 abort ();
928 return value;
931 bfd_vma
932 xstormy16_cgen_get_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
933 int opindex,
934 const CGEN_FIELDS * fields)
936 bfd_vma value;
938 switch (opindex)
940 case XSTORMY16_OPERAND_RB :
941 value = fields->f_Rb;
942 break;
943 case XSTORMY16_OPERAND_RBJ :
944 value = fields->f_Rbj;
945 break;
946 case XSTORMY16_OPERAND_RD :
947 value = fields->f_Rd;
948 break;
949 case XSTORMY16_OPERAND_RDM :
950 value = fields->f_Rdm;
951 break;
952 case XSTORMY16_OPERAND_RM :
953 value = fields->f_Rm;
954 break;
955 case XSTORMY16_OPERAND_RS :
956 value = fields->f_Rs;
957 break;
958 case XSTORMY16_OPERAND_ABS24 :
959 value = fields->f_abs24;
960 break;
961 case XSTORMY16_OPERAND_BCOND2 :
962 value = fields->f_op2;
963 break;
964 case XSTORMY16_OPERAND_BCOND5 :
965 value = fields->f_op5;
966 break;
967 case XSTORMY16_OPERAND_HMEM8 :
968 value = fields->f_hmem8;
969 break;
970 case XSTORMY16_OPERAND_IMM12 :
971 value = fields->f_imm12;
972 break;
973 case XSTORMY16_OPERAND_IMM16 :
974 value = fields->f_imm16;
975 break;
976 case XSTORMY16_OPERAND_IMM2 :
977 value = fields->f_imm2;
978 break;
979 case XSTORMY16_OPERAND_IMM3 :
980 value = fields->f_imm3;
981 break;
982 case XSTORMY16_OPERAND_IMM3B :
983 value = fields->f_imm3b;
984 break;
985 case XSTORMY16_OPERAND_IMM4 :
986 value = fields->f_imm4;
987 break;
988 case XSTORMY16_OPERAND_IMM8 :
989 value = fields->f_imm8;
990 break;
991 case XSTORMY16_OPERAND_IMM8SMALL :
992 value = fields->f_imm8;
993 break;
994 case XSTORMY16_OPERAND_LMEM8 :
995 value = fields->f_lmem8;
996 break;
997 case XSTORMY16_OPERAND_REL12 :
998 value = fields->f_rel12;
999 break;
1000 case XSTORMY16_OPERAND_REL12A :
1001 value = fields->f_rel12a;
1002 break;
1003 case XSTORMY16_OPERAND_REL8_2 :
1004 value = fields->f_rel8_2;
1005 break;
1006 case XSTORMY16_OPERAND_REL8_4 :
1007 value = fields->f_rel8_4;
1008 break;
1009 case XSTORMY16_OPERAND_WS2 :
1010 value = fields->f_op2m;
1011 break;
1013 default :
1014 /* xgettext:c-format */
1015 fprintf (stderr, _("Unrecognized field %d while getting vma operand.\n"),
1016 opindex);
1017 abort ();
1020 return value;
1023 void xstormy16_cgen_set_int_operand (CGEN_CPU_DESC, int, CGEN_FIELDS *, int);
1024 void xstormy16_cgen_set_vma_operand (CGEN_CPU_DESC, int, CGEN_FIELDS *, bfd_vma);
1026 /* Stuffing values in cgen_fields is handled by a collection of functions.
1027 They are distinguished by the type of the VALUE argument they accept.
1028 TODO: floating point, inlining support, remove cases where argument type
1029 not appropriate. */
1031 void
1032 xstormy16_cgen_set_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1033 int opindex,
1034 CGEN_FIELDS * fields,
1035 int value)
1037 switch (opindex)
1039 case XSTORMY16_OPERAND_RB :
1040 fields->f_Rb = value;
1041 break;
1042 case XSTORMY16_OPERAND_RBJ :
1043 fields->f_Rbj = value;
1044 break;
1045 case XSTORMY16_OPERAND_RD :
1046 fields->f_Rd = value;
1047 break;
1048 case XSTORMY16_OPERAND_RDM :
1049 fields->f_Rdm = value;
1050 break;
1051 case XSTORMY16_OPERAND_RM :
1052 fields->f_Rm = value;
1053 break;
1054 case XSTORMY16_OPERAND_RS :
1055 fields->f_Rs = value;
1056 break;
1057 case XSTORMY16_OPERAND_ABS24 :
1058 fields->f_abs24 = value;
1059 break;
1060 case XSTORMY16_OPERAND_BCOND2 :
1061 fields->f_op2 = value;
1062 break;
1063 case XSTORMY16_OPERAND_BCOND5 :
1064 fields->f_op5 = value;
1065 break;
1066 case XSTORMY16_OPERAND_HMEM8 :
1067 fields->f_hmem8 = value;
1068 break;
1069 case XSTORMY16_OPERAND_IMM12 :
1070 fields->f_imm12 = value;
1071 break;
1072 case XSTORMY16_OPERAND_IMM16 :
1073 fields->f_imm16 = value;
1074 break;
1075 case XSTORMY16_OPERAND_IMM2 :
1076 fields->f_imm2 = value;
1077 break;
1078 case XSTORMY16_OPERAND_IMM3 :
1079 fields->f_imm3 = value;
1080 break;
1081 case XSTORMY16_OPERAND_IMM3B :
1082 fields->f_imm3b = value;
1083 break;
1084 case XSTORMY16_OPERAND_IMM4 :
1085 fields->f_imm4 = value;
1086 break;
1087 case XSTORMY16_OPERAND_IMM8 :
1088 fields->f_imm8 = value;
1089 break;
1090 case XSTORMY16_OPERAND_IMM8SMALL :
1091 fields->f_imm8 = value;
1092 break;
1093 case XSTORMY16_OPERAND_LMEM8 :
1094 fields->f_lmem8 = value;
1095 break;
1096 case XSTORMY16_OPERAND_REL12 :
1097 fields->f_rel12 = value;
1098 break;
1099 case XSTORMY16_OPERAND_REL12A :
1100 fields->f_rel12a = value;
1101 break;
1102 case XSTORMY16_OPERAND_REL8_2 :
1103 fields->f_rel8_2 = value;
1104 break;
1105 case XSTORMY16_OPERAND_REL8_4 :
1106 fields->f_rel8_4 = value;
1107 break;
1108 case XSTORMY16_OPERAND_WS2 :
1109 fields->f_op2m = value;
1110 break;
1112 default :
1113 /* xgettext:c-format */
1114 fprintf (stderr, _("Unrecognized field %d while setting int operand.\n"),
1115 opindex);
1116 abort ();
1120 void
1121 xstormy16_cgen_set_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1122 int opindex,
1123 CGEN_FIELDS * fields,
1124 bfd_vma value)
1126 switch (opindex)
1128 case XSTORMY16_OPERAND_RB :
1129 fields->f_Rb = value;
1130 break;
1131 case XSTORMY16_OPERAND_RBJ :
1132 fields->f_Rbj = value;
1133 break;
1134 case XSTORMY16_OPERAND_RD :
1135 fields->f_Rd = value;
1136 break;
1137 case XSTORMY16_OPERAND_RDM :
1138 fields->f_Rdm = value;
1139 break;
1140 case XSTORMY16_OPERAND_RM :
1141 fields->f_Rm = value;
1142 break;
1143 case XSTORMY16_OPERAND_RS :
1144 fields->f_Rs = value;
1145 break;
1146 case XSTORMY16_OPERAND_ABS24 :
1147 fields->f_abs24 = value;
1148 break;
1149 case XSTORMY16_OPERAND_BCOND2 :
1150 fields->f_op2 = value;
1151 break;
1152 case XSTORMY16_OPERAND_BCOND5 :
1153 fields->f_op5 = value;
1154 break;
1155 case XSTORMY16_OPERAND_HMEM8 :
1156 fields->f_hmem8 = value;
1157 break;
1158 case XSTORMY16_OPERAND_IMM12 :
1159 fields->f_imm12 = value;
1160 break;
1161 case XSTORMY16_OPERAND_IMM16 :
1162 fields->f_imm16 = value;
1163 break;
1164 case XSTORMY16_OPERAND_IMM2 :
1165 fields->f_imm2 = value;
1166 break;
1167 case XSTORMY16_OPERAND_IMM3 :
1168 fields->f_imm3 = value;
1169 break;
1170 case XSTORMY16_OPERAND_IMM3B :
1171 fields->f_imm3b = value;
1172 break;
1173 case XSTORMY16_OPERAND_IMM4 :
1174 fields->f_imm4 = value;
1175 break;
1176 case XSTORMY16_OPERAND_IMM8 :
1177 fields->f_imm8 = value;
1178 break;
1179 case XSTORMY16_OPERAND_IMM8SMALL :
1180 fields->f_imm8 = value;
1181 break;
1182 case XSTORMY16_OPERAND_LMEM8 :
1183 fields->f_lmem8 = value;
1184 break;
1185 case XSTORMY16_OPERAND_REL12 :
1186 fields->f_rel12 = value;
1187 break;
1188 case XSTORMY16_OPERAND_REL12A :
1189 fields->f_rel12a = value;
1190 break;
1191 case XSTORMY16_OPERAND_REL8_2 :
1192 fields->f_rel8_2 = value;
1193 break;
1194 case XSTORMY16_OPERAND_REL8_4 :
1195 fields->f_rel8_4 = value;
1196 break;
1197 case XSTORMY16_OPERAND_WS2 :
1198 fields->f_op2m = value;
1199 break;
1201 default :
1202 /* xgettext:c-format */
1203 fprintf (stderr, _("Unrecognized field %d while setting vma operand.\n"),
1204 opindex);
1205 abort ();
1209 /* Function to call before using the instruction builder tables. */
1211 void
1212 xstormy16_cgen_init_ibld_table (CGEN_CPU_DESC cd)
1214 cd->insert_handlers = & xstormy16_cgen_insert_handlers[0];
1215 cd->extract_handlers = & xstormy16_cgen_extract_handlers[0];
1217 cd->insert_operand = xstormy16_cgen_insert_operand;
1218 cd->extract_operand = xstormy16_cgen_extract_operand;
1220 cd->get_int_operand = xstormy16_cgen_get_int_operand;
1221 cd->set_int_operand = xstormy16_cgen_set_int_operand;
1222 cd->get_vma_operand = xstormy16_cgen_get_vma_operand;
1223 cd->set_vma_operand = xstormy16_cgen_set_vma_operand;