gas/
[binutils.git] / opcodes / xstormy16-ibld.c
blobcaae89ba34e0109460e753d9bec9a154de79e7ac
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, 2006, 2007,
7 2008, 2010 Free Software Foundation, Inc.
9 This file is part of libopcodes.
11 This library is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3, or (at your option)
14 any later version.
16 It is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19 License for more details.
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 "cgen/basic-modes.h"
37 #include "opintl.h"
38 #include "safe-ctype.h"
40 #undef min
41 #define min(a,b) ((a) < (b) ? (a) : (b))
42 #undef max
43 #define max(a,b) ((a) > (b) ? (a) : (b))
45 /* Used by the ifield rtx function. */
46 #define FLD(f) (fields->f)
48 static const char * insert_normal
49 (CGEN_CPU_DESC, long, unsigned int, unsigned int, unsigned int,
50 unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR);
51 static const char * insert_insn_normal
52 (CGEN_CPU_DESC, const CGEN_INSN *,
53 CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
54 static int extract_normal
55 (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
56 unsigned int, unsigned int, unsigned int, unsigned int,
57 unsigned int, unsigned int, bfd_vma, long *);
58 static int extract_insn_normal
59 (CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
60 CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
61 #if CGEN_INT_INSN_P
62 static void put_insn_int_value
63 (CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT);
64 #endif
65 #if ! CGEN_INT_INSN_P
66 static CGEN_INLINE void insert_1
67 (CGEN_CPU_DESC, unsigned long, int, int, int, unsigned char *);
68 static CGEN_INLINE int fill_cache
69 (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, bfd_vma);
70 static CGEN_INLINE long extract_1
71 (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, int, unsigned char *, bfd_vma);
72 #endif
74 /* Operand insertion. */
76 #if ! CGEN_INT_INSN_P
78 /* Subroutine of insert_normal. */
80 static CGEN_INLINE void
81 insert_1 (CGEN_CPU_DESC cd,
82 unsigned long value,
83 int start,
84 int length,
85 int word_length,
86 unsigned char *bufp)
88 unsigned long x,mask;
89 int shift;
91 x = cgen_get_insn_value (cd, bufp, word_length);
93 /* Written this way to avoid undefined behaviour. */
94 mask = (((1L << (length - 1)) - 1) << 1) | 1;
95 if (CGEN_INSN_LSB0_P)
96 shift = (start + 1) - length;
97 else
98 shift = (word_length - (start + length));
99 x = (x & ~(mask << shift)) | ((value & mask) << shift);
101 cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
104 #endif /* ! CGEN_INT_INSN_P */
106 /* Default insertion routine.
108 ATTRS is a mask of the boolean attributes.
109 WORD_OFFSET is the offset in bits from the start of the insn of the value.
110 WORD_LENGTH is the length of the word in bits in which the value resides.
111 START is the starting bit number in the word, architecture origin.
112 LENGTH is the length of VALUE in bits.
113 TOTAL_LENGTH is the total length of the insn in bits.
115 The result is an error message or NULL if success. */
117 /* ??? This duplicates functionality with bfd's howto table and
118 bfd_install_relocation. */
119 /* ??? This doesn't handle bfd_vma's. Create another function when
120 necessary. */
122 static const char *
123 insert_normal (CGEN_CPU_DESC cd,
124 long value,
125 unsigned int attrs,
126 unsigned int word_offset,
127 unsigned int start,
128 unsigned int length,
129 unsigned int word_length,
130 unsigned int total_length,
131 CGEN_INSN_BYTES_PTR buffer)
133 static char errbuf[100];
134 /* Written this way to avoid undefined behaviour. */
135 unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
137 /* If LENGTH is zero, this operand doesn't contribute to the value. */
138 if (length == 0)
139 return NULL;
141 if (word_length > 8 * sizeof (CGEN_INSN_INT))
142 abort ();
144 /* For architectures with insns smaller than the base-insn-bitsize,
145 word_length may be too big. */
146 if (cd->min_insn_bitsize < cd->base_insn_bitsize)
148 if (word_offset == 0
149 && word_length > total_length)
150 word_length = total_length;
153 /* Ensure VALUE will fit. */
154 if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
156 long minval = - (1L << (length - 1));
157 unsigned long maxval = mask;
159 if ((value > 0 && (unsigned long) value > maxval)
160 || value < minval)
162 /* xgettext:c-format */
163 sprintf (errbuf,
164 _("operand out of range (%ld not between %ld and %lu)"),
165 value, minval, maxval);
166 return errbuf;
169 else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
171 unsigned long maxval = mask;
172 unsigned long val = (unsigned long) value;
174 /* For hosts with a word size > 32 check to see if value has been sign
175 extended beyond 32 bits. If so then ignore these higher sign bits
176 as the user is attempting to store a 32-bit signed value into an
177 unsigned 32-bit field which is allowed. */
178 if (sizeof (unsigned long) > 4 && ((value >> 32) == -1))
179 val &= 0xFFFFFFFF;
181 if (val > maxval)
183 /* xgettext:c-format */
184 sprintf (errbuf,
185 _("operand out of range (0x%lx not between 0 and 0x%lx)"),
186 val, maxval);
187 return errbuf;
190 else
192 if (! cgen_signed_overflow_ok_p (cd))
194 long minval = - (1L << (length - 1));
195 long maxval = (1L << (length - 1)) - 1;
197 if (value < minval || value > maxval)
199 sprintf
200 /* xgettext:c-format */
201 (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
202 value, minval, maxval);
203 return errbuf;
208 #if CGEN_INT_INSN_P
211 int shift;
213 if (CGEN_INSN_LSB0_P)
214 shift = (word_offset + start + 1) - length;
215 else
216 shift = total_length - (word_offset + start + length);
217 *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
220 #else /* ! CGEN_INT_INSN_P */
223 unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
225 insert_1 (cd, value, start, length, word_length, bufp);
228 #endif /* ! CGEN_INT_INSN_P */
230 return NULL;
233 /* Default insn builder (insert handler).
234 The instruction is recorded in CGEN_INT_INSN_P byte order (meaning
235 that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is
236 recorded in host byte order, otherwise BUFFER is an array of bytes
237 and the value is recorded in target byte order).
238 The result is an error message or NULL if success. */
240 static const char *
241 insert_insn_normal (CGEN_CPU_DESC cd,
242 const CGEN_INSN * insn,
243 CGEN_FIELDS * fields,
244 CGEN_INSN_BYTES_PTR buffer,
245 bfd_vma pc)
247 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
248 unsigned long value;
249 const CGEN_SYNTAX_CHAR_TYPE * syn;
251 CGEN_INIT_INSERT (cd);
252 value = CGEN_INSN_BASE_VALUE (insn);
254 /* If we're recording insns as numbers (rather than a string of bytes),
255 target byte order handling is deferred until later. */
257 #if CGEN_INT_INSN_P
259 put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
260 CGEN_FIELDS_BITSIZE (fields), value);
262 #else
264 cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
265 (unsigned) CGEN_FIELDS_BITSIZE (fields)),
266 value);
268 #endif /* ! CGEN_INT_INSN_P */
270 /* ??? It would be better to scan the format's fields.
271 Still need to be able to insert a value based on the operand though;
272 e.g. storing a branch displacement that got resolved later.
273 Needs more thought first. */
275 for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn)
277 const char *errmsg;
279 if (CGEN_SYNTAX_CHAR_P (* syn))
280 continue;
282 errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
283 fields, buffer, pc);
284 if (errmsg)
285 return errmsg;
288 return NULL;
291 #if CGEN_INT_INSN_P
292 /* Cover function to store an insn value into an integral insn. Must go here
293 because it needs <prefix>-desc.h for CGEN_INT_INSN_P. */
295 static void
296 put_insn_int_value (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
297 CGEN_INSN_BYTES_PTR buf,
298 int length,
299 int insn_length,
300 CGEN_INSN_INT value)
302 /* For architectures with insns smaller than the base-insn-bitsize,
303 length may be too big. */
304 if (length > insn_length)
305 *buf = value;
306 else
308 int shift = insn_length - length;
309 /* Written this way to avoid undefined behaviour. */
310 CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
312 *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
315 #endif
317 /* Operand extraction. */
319 #if ! CGEN_INT_INSN_P
321 /* Subroutine of extract_normal.
322 Ensure sufficient bytes are cached in EX_INFO.
323 OFFSET is the offset in bytes from the start of the insn of the value.
324 BYTES is the length of the needed value.
325 Returns 1 for success, 0 for failure. */
327 static CGEN_INLINE int
328 fill_cache (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
329 CGEN_EXTRACT_INFO *ex_info,
330 int offset,
331 int bytes,
332 bfd_vma pc)
334 /* It's doubtful that the middle part has already been fetched so
335 we don't optimize that case. kiss. */
336 unsigned int mask;
337 disassemble_info *info = (disassemble_info *) ex_info->dis_info;
339 /* First do a quick check. */
340 mask = (1 << bytes) - 1;
341 if (((ex_info->valid >> offset) & mask) == mask)
342 return 1;
344 /* Search for the first byte we need to read. */
345 for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
346 if (! (mask & ex_info->valid))
347 break;
349 if (bytes)
351 int status;
353 pc += offset;
354 status = (*info->read_memory_func)
355 (pc, ex_info->insn_bytes + offset, bytes, info);
357 if (status != 0)
359 (*info->memory_error_func) (status, pc, info);
360 return 0;
363 ex_info->valid |= ((1 << bytes) - 1) << offset;
366 return 1;
369 /* Subroutine of extract_normal. */
371 static CGEN_INLINE long
372 extract_1 (CGEN_CPU_DESC cd,
373 CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
374 int start,
375 int length,
376 int word_length,
377 unsigned char *bufp,
378 bfd_vma pc ATTRIBUTE_UNUSED)
380 unsigned long x;
381 int shift;
383 x = cgen_get_insn_value (cd, bufp, word_length);
385 if (CGEN_INSN_LSB0_P)
386 shift = (start + 1) - length;
387 else
388 shift = (word_length - (start + length));
389 return x >> shift;
392 #endif /* ! CGEN_INT_INSN_P */
394 /* Default extraction routine.
396 INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
397 or sometimes less for cases like the m32r where the base insn size is 32
398 but some insns are 16 bits.
399 ATTRS is a mask of the boolean attributes. We only need `SIGNED',
400 but for generality we take a bitmask of all of them.
401 WORD_OFFSET is the offset in bits from the start of the insn of the value.
402 WORD_LENGTH is the length of the word in bits in which the value resides.
403 START is the starting bit number in the word, architecture origin.
404 LENGTH is the length of VALUE in bits.
405 TOTAL_LENGTH is the total length of the insn in bits.
407 Returns 1 for success, 0 for failure. */
409 /* ??? The return code isn't properly used. wip. */
411 /* ??? This doesn't handle bfd_vma's. Create another function when
412 necessary. */
414 static int
415 extract_normal (CGEN_CPU_DESC cd,
416 #if ! CGEN_INT_INSN_P
417 CGEN_EXTRACT_INFO *ex_info,
418 #else
419 CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
420 #endif
421 CGEN_INSN_INT insn_value,
422 unsigned int attrs,
423 unsigned int word_offset,
424 unsigned int start,
425 unsigned int length,
426 unsigned int word_length,
427 unsigned int total_length,
428 #if ! CGEN_INT_INSN_P
429 bfd_vma pc,
430 #else
431 bfd_vma pc ATTRIBUTE_UNUSED,
432 #endif
433 long *valuep)
435 long value, mask;
437 /* If LENGTH is zero, this operand doesn't contribute to the value
438 so give it a standard value of zero. */
439 if (length == 0)
441 *valuep = 0;
442 return 1;
445 if (word_length > 8 * sizeof (CGEN_INSN_INT))
446 abort ();
448 /* For architectures with insns smaller than the insn-base-bitsize,
449 word_length may be too big. */
450 if (cd->min_insn_bitsize < cd->base_insn_bitsize)
452 if (word_offset + word_length > total_length)
453 word_length = total_length - word_offset;
456 /* Does the value reside in INSN_VALUE, and at the right alignment? */
458 if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
460 if (CGEN_INSN_LSB0_P)
461 value = insn_value >> ((word_offset + start + 1) - length);
462 else
463 value = insn_value >> (total_length - ( word_offset + start + length));
466 #if ! CGEN_INT_INSN_P
468 else
470 unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
472 if (word_length > 8 * sizeof (CGEN_INSN_INT))
473 abort ();
475 if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
476 return 0;
478 value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
481 #endif /* ! CGEN_INT_INSN_P */
483 /* Written this way to avoid undefined behaviour. */
484 mask = (((1L << (length - 1)) - 1) << 1) | 1;
486 value &= mask;
487 /* sign extend? */
488 if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
489 && (value & (1L << (length - 1))))
490 value |= ~mask;
492 *valuep = value;
494 return 1;
497 /* Default insn extractor.
499 INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
500 The extracted fields are stored in FIELDS.
501 EX_INFO is used to handle reading variable length insns.
502 Return the length of the insn in bits, or 0 if no match,
503 or -1 if an error occurs fetching data (memory_error_func will have
504 been called). */
506 static int
507 extract_insn_normal (CGEN_CPU_DESC cd,
508 const CGEN_INSN *insn,
509 CGEN_EXTRACT_INFO *ex_info,
510 CGEN_INSN_INT insn_value,
511 CGEN_FIELDS *fields,
512 bfd_vma pc)
514 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
515 const CGEN_SYNTAX_CHAR_TYPE *syn;
517 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
519 CGEN_INIT_EXTRACT (cd);
521 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
523 int length;
525 if (CGEN_SYNTAX_CHAR_P (*syn))
526 continue;
528 length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
529 ex_info, insn_value, fields, pc);
530 if (length <= 0)
531 return length;
534 /* We recognized and successfully extracted this insn. */
535 return CGEN_INSN_BITSIZE (insn);
538 /* Machine generated code added here. */
540 const char * xstormy16_cgen_insert_operand
541 (CGEN_CPU_DESC, int, CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
543 /* Main entry point for operand insertion.
545 This function is basically just a big switch statement. Earlier versions
546 used tables to look up the function to use, but
547 - if the table contains both assembler and disassembler functions then
548 the disassembler contains much of the assembler and vice-versa,
549 - there's a lot of inlining possibilities as things grow,
550 - using a switch statement avoids the function call overhead.
552 This function could be moved into `parse_insn_normal', but keeping it
553 separate makes clear the interface between `parse_insn_normal' and each of
554 the handlers. It's also needed by GAS to insert operands that couldn't be
555 resolved during parsing. */
557 const char *
558 xstormy16_cgen_insert_operand (CGEN_CPU_DESC cd,
559 int opindex,
560 CGEN_FIELDS * fields,
561 CGEN_INSN_BYTES_PTR buffer,
562 bfd_vma pc ATTRIBUTE_UNUSED)
564 const char * errmsg = NULL;
565 unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
567 switch (opindex)
569 case XSTORMY16_OPERAND_RB :
570 errmsg = insert_normal (cd, fields->f_Rb, 0, 0, 17, 3, 32, total_length, buffer);
571 break;
572 case XSTORMY16_OPERAND_RBJ :
573 errmsg = insert_normal (cd, fields->f_Rbj, 0, 0, 11, 1, 32, total_length, buffer);
574 break;
575 case XSTORMY16_OPERAND_RD :
576 errmsg = insert_normal (cd, fields->f_Rd, 0, 0, 12, 4, 32, total_length, buffer);
577 break;
578 case XSTORMY16_OPERAND_RDM :
579 errmsg = insert_normal (cd, fields->f_Rdm, 0, 0, 13, 3, 32, total_length, buffer);
580 break;
581 case XSTORMY16_OPERAND_RM :
582 errmsg = insert_normal (cd, fields->f_Rm, 0, 0, 4, 3, 32, total_length, buffer);
583 break;
584 case XSTORMY16_OPERAND_RS :
585 errmsg = insert_normal (cd, fields->f_Rs, 0, 0, 8, 4, 32, total_length, buffer);
586 break;
587 case XSTORMY16_OPERAND_ABS24 :
590 FLD (f_abs24_1) = ((FLD (f_abs24)) & (255));
591 FLD (f_abs24_2) = ((UINT) (FLD (f_abs24)) >> (8));
593 errmsg = insert_normal (cd, fields->f_abs24_1, 0, 0, 8, 8, 32, total_length, buffer);
594 if (errmsg)
595 break;
596 errmsg = insert_normal (cd, fields->f_abs24_2, 0, 0, 16, 16, 32, total_length, buffer);
597 if (errmsg)
598 break;
600 break;
601 case XSTORMY16_OPERAND_BCOND2 :
602 errmsg = insert_normal (cd, fields->f_op2, 0, 0, 4, 4, 32, total_length, buffer);
603 break;
604 case XSTORMY16_OPERAND_BCOND5 :
605 errmsg = insert_normal (cd, fields->f_op5, 0, 0, 16, 4, 32, total_length, buffer);
606 break;
607 case XSTORMY16_OPERAND_HMEM8 :
609 long value = fields->f_hmem8;
610 value = ((value) - (32512));
611 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, buffer);
613 break;
614 case XSTORMY16_OPERAND_IMM12 :
615 errmsg = insert_normal (cd, fields->f_imm12, 0|(1<<CGEN_IFLD_SIGNED), 0, 20, 12, 32, total_length, buffer);
616 break;
617 case XSTORMY16_OPERAND_IMM16 :
618 errmsg = insert_normal (cd, fields->f_imm16, 0|(1<<CGEN_IFLD_SIGN_OPT), 0, 16, 16, 32, total_length, buffer);
619 break;
620 case XSTORMY16_OPERAND_IMM2 :
621 errmsg = insert_normal (cd, fields->f_imm2, 0, 0, 10, 2, 32, total_length, buffer);
622 break;
623 case XSTORMY16_OPERAND_IMM3 :
624 errmsg = insert_normal (cd, fields->f_imm3, 0, 0, 4, 3, 32, total_length, buffer);
625 break;
626 case XSTORMY16_OPERAND_IMM3B :
627 errmsg = insert_normal (cd, fields->f_imm3b, 0, 0, 17, 3, 32, total_length, buffer);
628 break;
629 case XSTORMY16_OPERAND_IMM4 :
630 errmsg = insert_normal (cd, fields->f_imm4, 0, 0, 8, 4, 32, total_length, buffer);
631 break;
632 case XSTORMY16_OPERAND_IMM8 :
633 errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 8, 8, 32, total_length, buffer);
634 break;
635 case XSTORMY16_OPERAND_IMM8SMALL :
636 errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 8, 8, 32, total_length, buffer);
637 break;
638 case XSTORMY16_OPERAND_LMEM8 :
639 errmsg = insert_normal (cd, fields->f_lmem8, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, buffer);
640 break;
641 case XSTORMY16_OPERAND_REL12 :
643 long value = fields->f_rel12;
644 value = ((value) - (((pc) + (4))));
645 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 20, 12, 32, total_length, buffer);
647 break;
648 case XSTORMY16_OPERAND_REL12A :
650 long value = fields->f_rel12a;
651 value = ((SI) (((value) - (((pc) + (2))))) >> (1));
652 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 4, 11, 32, total_length, buffer);
654 break;
655 case XSTORMY16_OPERAND_REL8_2 :
657 long value = fields->f_rel8_2;
658 value = ((value) - (((pc) + (2))));
659 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, buffer);
661 break;
662 case XSTORMY16_OPERAND_REL8_4 :
664 long value = fields->f_rel8_4;
665 value = ((value) - (((pc) + (4))));
666 errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, buffer);
668 break;
669 case XSTORMY16_OPERAND_WS2 :
670 errmsg = insert_normal (cd, fields->f_op2m, 0, 0, 7, 1, 32, total_length, buffer);
671 break;
673 default :
674 /* xgettext:c-format */
675 fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
676 opindex);
677 abort ();
680 return errmsg;
683 int xstormy16_cgen_extract_operand
684 (CGEN_CPU_DESC, int, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
686 /* Main entry point for operand extraction.
687 The result is <= 0 for error, >0 for success.
688 ??? Actual values aren't well defined right now.
690 This function is basically just a big switch statement. Earlier versions
691 used tables to look up the function to use, but
692 - if the table contains both assembler and disassembler functions then
693 the disassembler contains much of the assembler and vice-versa,
694 - there's a lot of inlining possibilities as things grow,
695 - using a switch statement avoids the function call overhead.
697 This function could be moved into `print_insn_normal', but keeping it
698 separate makes clear the interface between `print_insn_normal' and each of
699 the handlers. */
702 xstormy16_cgen_extract_operand (CGEN_CPU_DESC cd,
703 int opindex,
704 CGEN_EXTRACT_INFO *ex_info,
705 CGEN_INSN_INT insn_value,
706 CGEN_FIELDS * fields,
707 bfd_vma pc)
709 /* Assume success (for those operands that are nops). */
710 int length = 1;
711 unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
713 switch (opindex)
715 case XSTORMY16_OPERAND_RB :
716 length = extract_normal (cd, ex_info, insn_value, 0, 0, 17, 3, 32, total_length, pc, & fields->f_Rb);
717 break;
718 case XSTORMY16_OPERAND_RBJ :
719 length = extract_normal (cd, ex_info, insn_value, 0, 0, 11, 1, 32, total_length, pc, & fields->f_Rbj);
720 break;
721 case XSTORMY16_OPERAND_RD :
722 length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 32, total_length, pc, & fields->f_Rd);
723 break;
724 case XSTORMY16_OPERAND_RDM :
725 length = extract_normal (cd, ex_info, insn_value, 0, 0, 13, 3, 32, total_length, pc, & fields->f_Rdm);
726 break;
727 case XSTORMY16_OPERAND_RM :
728 length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 3, 32, total_length, pc, & fields->f_Rm);
729 break;
730 case XSTORMY16_OPERAND_RS :
731 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 32, total_length, pc, & fields->f_Rs);
732 break;
733 case XSTORMY16_OPERAND_ABS24 :
735 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 32, total_length, pc, & fields->f_abs24_1);
736 if (length <= 0) break;
737 length = extract_normal (cd, ex_info, insn_value, 0, 0, 16, 16, 32, total_length, pc, & fields->f_abs24_2);
738 if (length <= 0) break;
739 FLD (f_abs24) = ((((FLD (f_abs24_2)) << (8))) | (FLD (f_abs24_1)));
741 break;
742 case XSTORMY16_OPERAND_BCOND2 :
743 length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 4, 32, total_length, pc, & fields->f_op2);
744 break;
745 case XSTORMY16_OPERAND_BCOND5 :
746 length = extract_normal (cd, ex_info, insn_value, 0, 0, 16, 4, 32, total_length, pc, & fields->f_op5);
747 break;
748 case XSTORMY16_OPERAND_HMEM8 :
750 long value;
751 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, pc, & value);
752 value = ((value) + (32512));
753 fields->f_hmem8 = value;
755 break;
756 case XSTORMY16_OPERAND_IMM12 :
757 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 20, 12, 32, total_length, pc, & fields->f_imm12);
758 break;
759 case XSTORMY16_OPERAND_IMM16 :
760 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGN_OPT), 0, 16, 16, 32, total_length, pc, & fields->f_imm16);
761 break;
762 case XSTORMY16_OPERAND_IMM2 :
763 length = extract_normal (cd, ex_info, insn_value, 0, 0, 10, 2, 32, total_length, pc, & fields->f_imm2);
764 break;
765 case XSTORMY16_OPERAND_IMM3 :
766 length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 3, 32, total_length, pc, & fields->f_imm3);
767 break;
768 case XSTORMY16_OPERAND_IMM3B :
769 length = extract_normal (cd, ex_info, insn_value, 0, 0, 17, 3, 32, total_length, pc, & fields->f_imm3b);
770 break;
771 case XSTORMY16_OPERAND_IMM4 :
772 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 32, total_length, pc, & fields->f_imm4);
773 break;
774 case XSTORMY16_OPERAND_IMM8 :
775 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 32, total_length, pc, & fields->f_imm8);
776 break;
777 case XSTORMY16_OPERAND_IMM8SMALL :
778 length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 32, total_length, pc, & fields->f_imm8);
779 break;
780 case XSTORMY16_OPERAND_LMEM8 :
781 length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, pc, & fields->f_lmem8);
782 break;
783 case XSTORMY16_OPERAND_REL12 :
785 long value;
786 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);
787 value = ((value) + (((pc) + (4))));
788 fields->f_rel12 = value;
790 break;
791 case XSTORMY16_OPERAND_REL12A :
793 long value;
794 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);
795 value = ((((value) << (1))) + (((pc) + (2))));
796 fields->f_rel12a = value;
798 break;
799 case XSTORMY16_OPERAND_REL8_2 :
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) + (2))));
804 fields->f_rel8_2 = value;
806 break;
807 case XSTORMY16_OPERAND_REL8_4 :
809 long value;
810 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);
811 value = ((value) + (((pc) + (4))));
812 fields->f_rel8_4 = value;
814 break;
815 case XSTORMY16_OPERAND_WS2 :
816 length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 1, 32, total_length, pc, & fields->f_op2m);
817 break;
819 default :
820 /* xgettext:c-format */
821 fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
822 opindex);
823 abort ();
826 return length;
829 cgen_insert_fn * const xstormy16_cgen_insert_handlers[] =
831 insert_insn_normal,
834 cgen_extract_fn * const xstormy16_cgen_extract_handlers[] =
836 extract_insn_normal,
839 int xstormy16_cgen_get_int_operand (CGEN_CPU_DESC, int, const CGEN_FIELDS *);
840 bfd_vma xstormy16_cgen_get_vma_operand (CGEN_CPU_DESC, int, const CGEN_FIELDS *);
842 /* Getting values from cgen_fields is handled by a collection of functions.
843 They are distinguished by the type of the VALUE argument they return.
844 TODO: floating point, inlining support, remove cases where result type
845 not appropriate. */
848 xstormy16_cgen_get_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
849 int opindex,
850 const CGEN_FIELDS * fields)
852 int value;
854 switch (opindex)
856 case XSTORMY16_OPERAND_RB :
857 value = fields->f_Rb;
858 break;
859 case XSTORMY16_OPERAND_RBJ :
860 value = fields->f_Rbj;
861 break;
862 case XSTORMY16_OPERAND_RD :
863 value = fields->f_Rd;
864 break;
865 case XSTORMY16_OPERAND_RDM :
866 value = fields->f_Rdm;
867 break;
868 case XSTORMY16_OPERAND_RM :
869 value = fields->f_Rm;
870 break;
871 case XSTORMY16_OPERAND_RS :
872 value = fields->f_Rs;
873 break;
874 case XSTORMY16_OPERAND_ABS24 :
875 value = fields->f_abs24;
876 break;
877 case XSTORMY16_OPERAND_BCOND2 :
878 value = fields->f_op2;
879 break;
880 case XSTORMY16_OPERAND_BCOND5 :
881 value = fields->f_op5;
882 break;
883 case XSTORMY16_OPERAND_HMEM8 :
884 value = fields->f_hmem8;
885 break;
886 case XSTORMY16_OPERAND_IMM12 :
887 value = fields->f_imm12;
888 break;
889 case XSTORMY16_OPERAND_IMM16 :
890 value = fields->f_imm16;
891 break;
892 case XSTORMY16_OPERAND_IMM2 :
893 value = fields->f_imm2;
894 break;
895 case XSTORMY16_OPERAND_IMM3 :
896 value = fields->f_imm3;
897 break;
898 case XSTORMY16_OPERAND_IMM3B :
899 value = fields->f_imm3b;
900 break;
901 case XSTORMY16_OPERAND_IMM4 :
902 value = fields->f_imm4;
903 break;
904 case XSTORMY16_OPERAND_IMM8 :
905 value = fields->f_imm8;
906 break;
907 case XSTORMY16_OPERAND_IMM8SMALL :
908 value = fields->f_imm8;
909 break;
910 case XSTORMY16_OPERAND_LMEM8 :
911 value = fields->f_lmem8;
912 break;
913 case XSTORMY16_OPERAND_REL12 :
914 value = fields->f_rel12;
915 break;
916 case XSTORMY16_OPERAND_REL12A :
917 value = fields->f_rel12a;
918 break;
919 case XSTORMY16_OPERAND_REL8_2 :
920 value = fields->f_rel8_2;
921 break;
922 case XSTORMY16_OPERAND_REL8_4 :
923 value = fields->f_rel8_4;
924 break;
925 case XSTORMY16_OPERAND_WS2 :
926 value = fields->f_op2m;
927 break;
929 default :
930 /* xgettext:c-format */
931 fprintf (stderr, _("Unrecognized field %d while getting int operand.\n"),
932 opindex);
933 abort ();
936 return value;
939 bfd_vma
940 xstormy16_cgen_get_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
941 int opindex,
942 const CGEN_FIELDS * fields)
944 bfd_vma value;
946 switch (opindex)
948 case XSTORMY16_OPERAND_RB :
949 value = fields->f_Rb;
950 break;
951 case XSTORMY16_OPERAND_RBJ :
952 value = fields->f_Rbj;
953 break;
954 case XSTORMY16_OPERAND_RD :
955 value = fields->f_Rd;
956 break;
957 case XSTORMY16_OPERAND_RDM :
958 value = fields->f_Rdm;
959 break;
960 case XSTORMY16_OPERAND_RM :
961 value = fields->f_Rm;
962 break;
963 case XSTORMY16_OPERAND_RS :
964 value = fields->f_Rs;
965 break;
966 case XSTORMY16_OPERAND_ABS24 :
967 value = fields->f_abs24;
968 break;
969 case XSTORMY16_OPERAND_BCOND2 :
970 value = fields->f_op2;
971 break;
972 case XSTORMY16_OPERAND_BCOND5 :
973 value = fields->f_op5;
974 break;
975 case XSTORMY16_OPERAND_HMEM8 :
976 value = fields->f_hmem8;
977 break;
978 case XSTORMY16_OPERAND_IMM12 :
979 value = fields->f_imm12;
980 break;
981 case XSTORMY16_OPERAND_IMM16 :
982 value = fields->f_imm16;
983 break;
984 case XSTORMY16_OPERAND_IMM2 :
985 value = fields->f_imm2;
986 break;
987 case XSTORMY16_OPERAND_IMM3 :
988 value = fields->f_imm3;
989 break;
990 case XSTORMY16_OPERAND_IMM3B :
991 value = fields->f_imm3b;
992 break;
993 case XSTORMY16_OPERAND_IMM4 :
994 value = fields->f_imm4;
995 break;
996 case XSTORMY16_OPERAND_IMM8 :
997 value = fields->f_imm8;
998 break;
999 case XSTORMY16_OPERAND_IMM8SMALL :
1000 value = fields->f_imm8;
1001 break;
1002 case XSTORMY16_OPERAND_LMEM8 :
1003 value = fields->f_lmem8;
1004 break;
1005 case XSTORMY16_OPERAND_REL12 :
1006 value = fields->f_rel12;
1007 break;
1008 case XSTORMY16_OPERAND_REL12A :
1009 value = fields->f_rel12a;
1010 break;
1011 case XSTORMY16_OPERAND_REL8_2 :
1012 value = fields->f_rel8_2;
1013 break;
1014 case XSTORMY16_OPERAND_REL8_4 :
1015 value = fields->f_rel8_4;
1016 break;
1017 case XSTORMY16_OPERAND_WS2 :
1018 value = fields->f_op2m;
1019 break;
1021 default :
1022 /* xgettext:c-format */
1023 fprintf (stderr, _("Unrecognized field %d while getting vma operand.\n"),
1024 opindex);
1025 abort ();
1028 return value;
1031 void xstormy16_cgen_set_int_operand (CGEN_CPU_DESC, int, CGEN_FIELDS *, int);
1032 void xstormy16_cgen_set_vma_operand (CGEN_CPU_DESC, int, CGEN_FIELDS *, bfd_vma);
1034 /* Stuffing values in cgen_fields is handled by a collection of functions.
1035 They are distinguished by the type of the VALUE argument they accept.
1036 TODO: floating point, inlining support, remove cases where argument type
1037 not appropriate. */
1039 void
1040 xstormy16_cgen_set_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1041 int opindex,
1042 CGEN_FIELDS * fields,
1043 int value)
1045 switch (opindex)
1047 case XSTORMY16_OPERAND_RB :
1048 fields->f_Rb = value;
1049 break;
1050 case XSTORMY16_OPERAND_RBJ :
1051 fields->f_Rbj = value;
1052 break;
1053 case XSTORMY16_OPERAND_RD :
1054 fields->f_Rd = value;
1055 break;
1056 case XSTORMY16_OPERAND_RDM :
1057 fields->f_Rdm = value;
1058 break;
1059 case XSTORMY16_OPERAND_RM :
1060 fields->f_Rm = value;
1061 break;
1062 case XSTORMY16_OPERAND_RS :
1063 fields->f_Rs = value;
1064 break;
1065 case XSTORMY16_OPERAND_ABS24 :
1066 fields->f_abs24 = value;
1067 break;
1068 case XSTORMY16_OPERAND_BCOND2 :
1069 fields->f_op2 = value;
1070 break;
1071 case XSTORMY16_OPERAND_BCOND5 :
1072 fields->f_op5 = value;
1073 break;
1074 case XSTORMY16_OPERAND_HMEM8 :
1075 fields->f_hmem8 = value;
1076 break;
1077 case XSTORMY16_OPERAND_IMM12 :
1078 fields->f_imm12 = value;
1079 break;
1080 case XSTORMY16_OPERAND_IMM16 :
1081 fields->f_imm16 = value;
1082 break;
1083 case XSTORMY16_OPERAND_IMM2 :
1084 fields->f_imm2 = value;
1085 break;
1086 case XSTORMY16_OPERAND_IMM3 :
1087 fields->f_imm3 = value;
1088 break;
1089 case XSTORMY16_OPERAND_IMM3B :
1090 fields->f_imm3b = value;
1091 break;
1092 case XSTORMY16_OPERAND_IMM4 :
1093 fields->f_imm4 = value;
1094 break;
1095 case XSTORMY16_OPERAND_IMM8 :
1096 fields->f_imm8 = value;
1097 break;
1098 case XSTORMY16_OPERAND_IMM8SMALL :
1099 fields->f_imm8 = value;
1100 break;
1101 case XSTORMY16_OPERAND_LMEM8 :
1102 fields->f_lmem8 = value;
1103 break;
1104 case XSTORMY16_OPERAND_REL12 :
1105 fields->f_rel12 = value;
1106 break;
1107 case XSTORMY16_OPERAND_REL12A :
1108 fields->f_rel12a = value;
1109 break;
1110 case XSTORMY16_OPERAND_REL8_2 :
1111 fields->f_rel8_2 = value;
1112 break;
1113 case XSTORMY16_OPERAND_REL8_4 :
1114 fields->f_rel8_4 = value;
1115 break;
1116 case XSTORMY16_OPERAND_WS2 :
1117 fields->f_op2m = value;
1118 break;
1120 default :
1121 /* xgettext:c-format */
1122 fprintf (stderr, _("Unrecognized field %d while setting int operand.\n"),
1123 opindex);
1124 abort ();
1128 void
1129 xstormy16_cgen_set_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1130 int opindex,
1131 CGEN_FIELDS * fields,
1132 bfd_vma value)
1134 switch (opindex)
1136 case XSTORMY16_OPERAND_RB :
1137 fields->f_Rb = value;
1138 break;
1139 case XSTORMY16_OPERAND_RBJ :
1140 fields->f_Rbj = value;
1141 break;
1142 case XSTORMY16_OPERAND_RD :
1143 fields->f_Rd = value;
1144 break;
1145 case XSTORMY16_OPERAND_RDM :
1146 fields->f_Rdm = value;
1147 break;
1148 case XSTORMY16_OPERAND_RM :
1149 fields->f_Rm = value;
1150 break;
1151 case XSTORMY16_OPERAND_RS :
1152 fields->f_Rs = value;
1153 break;
1154 case XSTORMY16_OPERAND_ABS24 :
1155 fields->f_abs24 = value;
1156 break;
1157 case XSTORMY16_OPERAND_BCOND2 :
1158 fields->f_op2 = value;
1159 break;
1160 case XSTORMY16_OPERAND_BCOND5 :
1161 fields->f_op5 = value;
1162 break;
1163 case XSTORMY16_OPERAND_HMEM8 :
1164 fields->f_hmem8 = value;
1165 break;
1166 case XSTORMY16_OPERAND_IMM12 :
1167 fields->f_imm12 = value;
1168 break;
1169 case XSTORMY16_OPERAND_IMM16 :
1170 fields->f_imm16 = value;
1171 break;
1172 case XSTORMY16_OPERAND_IMM2 :
1173 fields->f_imm2 = value;
1174 break;
1175 case XSTORMY16_OPERAND_IMM3 :
1176 fields->f_imm3 = value;
1177 break;
1178 case XSTORMY16_OPERAND_IMM3B :
1179 fields->f_imm3b = value;
1180 break;
1181 case XSTORMY16_OPERAND_IMM4 :
1182 fields->f_imm4 = value;
1183 break;
1184 case XSTORMY16_OPERAND_IMM8 :
1185 fields->f_imm8 = value;
1186 break;
1187 case XSTORMY16_OPERAND_IMM8SMALL :
1188 fields->f_imm8 = value;
1189 break;
1190 case XSTORMY16_OPERAND_LMEM8 :
1191 fields->f_lmem8 = value;
1192 break;
1193 case XSTORMY16_OPERAND_REL12 :
1194 fields->f_rel12 = value;
1195 break;
1196 case XSTORMY16_OPERAND_REL12A :
1197 fields->f_rel12a = value;
1198 break;
1199 case XSTORMY16_OPERAND_REL8_2 :
1200 fields->f_rel8_2 = value;
1201 break;
1202 case XSTORMY16_OPERAND_REL8_4 :
1203 fields->f_rel8_4 = value;
1204 break;
1205 case XSTORMY16_OPERAND_WS2 :
1206 fields->f_op2m = value;
1207 break;
1209 default :
1210 /* xgettext:c-format */
1211 fprintf (stderr, _("Unrecognized field %d while setting vma operand.\n"),
1212 opindex);
1213 abort ();
1217 /* Function to call before using the instruction builder tables. */
1219 void
1220 xstormy16_cgen_init_ibld_table (CGEN_CPU_DESC cd)
1222 cd->insert_handlers = & xstormy16_cgen_insert_handlers[0];
1223 cd->extract_handlers = & xstormy16_cgen_extract_handlers[0];
1225 cd->insert_operand = xstormy16_cgen_insert_operand;
1226 cd->extract_operand = xstormy16_cgen_extract_operand;
1228 cd->get_int_operand = xstormy16_cgen_get_int_operand;
1229 cd->set_int_operand = xstormy16_cgen_set_int_operand;
1230 cd->get_vma_operand = xstormy16_cgen_get_vma_operand;
1231 cd->set_vma_operand = xstormy16_cgen_set_vma_operand;