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
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)
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.
34 #include "xstormy16-desc.h"
35 #include "xstormy16-opc.h"
37 #include "safe-ctype.h"
40 #define min(a,b) ((a) < (b) ? (a) : (b))
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
);
61 static void put_insn_int_value
62 (CGEN_CPU_DESC
, CGEN_INSN_BYTES_PTR
, int, int, CGEN_INSN_INT
);
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
);
73 /* Operand insertion. */
77 /* Subroutine of insert_normal. */
79 static CGEN_INLINE
void
80 insert_1 (CGEN_CPU_DESC cd
,
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;
95 shift
= (start
+ 1) - length
;
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
122 insert_normal (CGEN_CPU_DESC cd
,
125 unsigned int word_offset
,
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. */
140 if (word_length
> 32)
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
)
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
)
161 /* xgettext:c-format */
163 _("operand out of range (%ld not between %ld and %lu)"),
164 value
, minval
, maxval
);
168 else if (! CGEN_BOOL_ATTR (attrs
, CGEN_IFLD_SIGNED
))
170 unsigned long maxval
= mask
;
171 unsigned long val
= (unsigned long) value
;
173 /* For hosts with a word size > 32 check to see if value has been sign
174 extended beyond 32 bits. If so then ignore these higher sign bits
175 as the user is attempting to store a 32-bit signed value into an
176 unsigned 32-bit field which is allowed. */
177 if (sizeof (unsigned long) > 4 && ((value
>> 32) == -1))
182 /* xgettext:c-format */
184 _("operand out of range (0x%lx not between 0 and 0x%lx)"),
191 if (! cgen_signed_overflow_ok_p (cd
))
193 long minval
= - (1L << (length
- 1));
194 long maxval
= (1L << (length
- 1)) - 1;
196 if (value
< minval
|| value
> maxval
)
199 /* xgettext:c-format */
200 (errbuf
, _("operand out of range (%ld not between %ld and %ld)"),
201 value
, minval
, maxval
);
212 if (CGEN_INSN_LSB0_P
)
213 shift
= (word_offset
+ start
+ 1) - length
;
215 shift
= total_length
- (word_offset
+ start
+ length
);
216 *buffer
= (*buffer
& ~(mask
<< shift
)) | ((value
& mask
) << shift
);
219 #else /* ! CGEN_INT_INSN_P */
222 unsigned char *bufp
= (unsigned char *) buffer
+ word_offset
/ 8;
224 insert_1 (cd
, value
, start
, length
, word_length
, bufp
);
227 #endif /* ! CGEN_INT_INSN_P */
232 /* Default insn builder (insert handler).
233 The instruction is recorded in CGEN_INT_INSN_P byte order (meaning
234 that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is
235 recorded in host byte order, otherwise BUFFER is an array of bytes
236 and the value is recorded in target byte order).
237 The result is an error message or NULL if success. */
240 insert_insn_normal (CGEN_CPU_DESC cd
,
241 const CGEN_INSN
* insn
,
242 CGEN_FIELDS
* fields
,
243 CGEN_INSN_BYTES_PTR buffer
,
246 const CGEN_SYNTAX
*syntax
= CGEN_INSN_SYNTAX (insn
);
248 const CGEN_SYNTAX_CHAR_TYPE
* syn
;
250 CGEN_INIT_INSERT (cd
);
251 value
= CGEN_INSN_BASE_VALUE (insn
);
253 /* If we're recording insns as numbers (rather than a string of bytes),
254 target byte order handling is deferred until later. */
258 put_insn_int_value (cd
, buffer
, cd
->base_insn_bitsize
,
259 CGEN_FIELDS_BITSIZE (fields
), value
);
263 cgen_put_insn_value (cd
, buffer
, min ((unsigned) cd
->base_insn_bitsize
,
264 (unsigned) CGEN_FIELDS_BITSIZE (fields
)),
267 #endif /* ! CGEN_INT_INSN_P */
269 /* ??? It would be better to scan the format's fields.
270 Still need to be able to insert a value based on the operand though;
271 e.g. storing a branch displacement that got resolved later.
272 Needs more thought first. */
274 for (syn
= CGEN_SYNTAX_STRING (syntax
); * syn
; ++ syn
)
278 if (CGEN_SYNTAX_CHAR_P (* syn
))
281 errmsg
= (* cd
->insert_operand
) (cd
, CGEN_SYNTAX_FIELD (*syn
),
291 /* Cover function to store an insn value into an integral insn. Must go here
292 because it needs <prefix>-desc.h for CGEN_INT_INSN_P. */
295 put_insn_int_value (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED
,
296 CGEN_INSN_BYTES_PTR buf
,
301 /* For architectures with insns smaller than the base-insn-bitsize,
302 length may be too big. */
303 if (length
> insn_length
)
307 int shift
= insn_length
- length
;
308 /* Written this way to avoid undefined behaviour. */
309 CGEN_INSN_INT mask
= (((1L << (length
- 1)) - 1) << 1) | 1;
311 *buf
= (*buf
& ~(mask
<< shift
)) | ((value
& mask
) << shift
);
316 /* Operand extraction. */
318 #if ! CGEN_INT_INSN_P
320 /* Subroutine of extract_normal.
321 Ensure sufficient bytes are cached in EX_INFO.
322 OFFSET is the offset in bytes from the start of the insn of the value.
323 BYTES is the length of the needed value.
324 Returns 1 for success, 0 for failure. */
326 static CGEN_INLINE
int
327 fill_cache (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED
,
328 CGEN_EXTRACT_INFO
*ex_info
,
333 /* It's doubtful that the middle part has already been fetched so
334 we don't optimize that case. kiss. */
336 disassemble_info
*info
= (disassemble_info
*) ex_info
->dis_info
;
338 /* First do a quick check. */
339 mask
= (1 << bytes
) - 1;
340 if (((ex_info
->valid
>> offset
) & mask
) == mask
)
343 /* Search for the first byte we need to read. */
344 for (mask
= 1 << offset
; bytes
> 0; --bytes
, ++offset
, mask
<<= 1)
345 if (! (mask
& ex_info
->valid
))
353 status
= (*info
->read_memory_func
)
354 (pc
, ex_info
->insn_bytes
+ offset
, bytes
, info
);
358 (*info
->memory_error_func
) (status
, pc
, info
);
362 ex_info
->valid
|= ((1 << bytes
) - 1) << offset
;
368 /* Subroutine of extract_normal. */
370 static CGEN_INLINE
long
371 extract_1 (CGEN_CPU_DESC cd
,
372 CGEN_EXTRACT_INFO
*ex_info ATTRIBUTE_UNUSED
,
377 bfd_vma pc ATTRIBUTE_UNUSED
)
382 x
= cgen_get_insn_value (cd
, bufp
, word_length
);
384 if (CGEN_INSN_LSB0_P
)
385 shift
= (start
+ 1) - length
;
387 shift
= (word_length
- (start
+ length
));
391 #endif /* ! CGEN_INT_INSN_P */
393 /* Default extraction routine.
395 INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
396 or sometimes less for cases like the m32r where the base insn size is 32
397 but some insns are 16 bits.
398 ATTRS is a mask of the boolean attributes. We only need `SIGNED',
399 but for generality we take a bitmask of all of them.
400 WORD_OFFSET is the offset in bits from the start of the insn of the value.
401 WORD_LENGTH is the length of the word in bits in which the value resides.
402 START is the starting bit number in the word, architecture origin.
403 LENGTH is the length of VALUE in bits.
404 TOTAL_LENGTH is the total length of the insn in bits.
406 Returns 1 for success, 0 for failure. */
408 /* ??? The return code isn't properly used. wip. */
410 /* ??? This doesn't handle bfd_vma's. Create another function when
414 extract_normal (CGEN_CPU_DESC cd
,
415 #if ! CGEN_INT_INSN_P
416 CGEN_EXTRACT_INFO
*ex_info
,
418 CGEN_EXTRACT_INFO
*ex_info ATTRIBUTE_UNUSED
,
420 CGEN_INSN_INT insn_value
,
422 unsigned int word_offset
,
425 unsigned int word_length
,
426 unsigned int total_length
,
427 #if ! CGEN_INT_INSN_P
430 bfd_vma pc ATTRIBUTE_UNUSED
,
436 /* If LENGTH is zero, this operand doesn't contribute to the value
437 so give it a standard value of zero. */
444 if (word_length
> 32)
447 /* For architectures with insns smaller than the insn-base-bitsize,
448 word_length may be too big. */
449 if (cd
->min_insn_bitsize
< cd
->base_insn_bitsize
)
451 if (word_offset
+ word_length
> total_length
)
452 word_length
= total_length
- word_offset
;
455 /* Does the value reside in INSN_VALUE, and at the right alignment? */
457 if (CGEN_INT_INSN_P
|| (word_offset
== 0 && word_length
== total_length
))
459 if (CGEN_INSN_LSB0_P
)
460 value
= insn_value
>> ((word_offset
+ start
+ 1) - length
);
462 value
= insn_value
>> (total_length
- ( word_offset
+ start
+ length
));
465 #if ! CGEN_INT_INSN_P
469 unsigned char *bufp
= ex_info
->insn_bytes
+ word_offset
/ 8;
471 if (word_length
> 32)
474 if (fill_cache (cd
, ex_info
, word_offset
/ 8, word_length
/ 8, pc
) == 0)
477 value
= extract_1 (cd
, ex_info
, start
, length
, word_length
, bufp
, pc
);
480 #endif /* ! CGEN_INT_INSN_P */
482 /* Written this way to avoid undefined behaviour. */
483 mask
= (((1L << (length
- 1)) - 1) << 1) | 1;
487 if (CGEN_BOOL_ATTR (attrs
, CGEN_IFLD_SIGNED
)
488 && (value
& (1L << (length
- 1))))
496 /* Default insn extractor.
498 INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
499 The extracted fields are stored in FIELDS.
500 EX_INFO is used to handle reading variable length insns.
501 Return the length of the insn in bits, or 0 if no match,
502 or -1 if an error occurs fetching data (memory_error_func will have
506 extract_insn_normal (CGEN_CPU_DESC cd
,
507 const CGEN_INSN
*insn
,
508 CGEN_EXTRACT_INFO
*ex_info
,
509 CGEN_INSN_INT insn_value
,
513 const CGEN_SYNTAX
*syntax
= CGEN_INSN_SYNTAX (insn
);
514 const CGEN_SYNTAX_CHAR_TYPE
*syn
;
516 CGEN_FIELDS_BITSIZE (fields
) = CGEN_INSN_BITSIZE (insn
);
518 CGEN_INIT_EXTRACT (cd
);
520 for (syn
= CGEN_SYNTAX_STRING (syntax
); *syn
; ++syn
)
524 if (CGEN_SYNTAX_CHAR_P (*syn
))
527 length
= (* cd
->extract_operand
) (cd
, CGEN_SYNTAX_FIELD (*syn
),
528 ex_info
, insn_value
, fields
, pc
);
533 /* We recognized and successfully extracted this insn. */
534 return CGEN_INSN_BITSIZE (insn
);
537 /* Machine generated code added here. */
539 const char * xstormy16_cgen_insert_operand
540 (CGEN_CPU_DESC
, int, CGEN_FIELDS
*, CGEN_INSN_BYTES_PTR
, bfd_vma
);
542 /* Main entry point for operand insertion.
544 This function is basically just a big switch statement. Earlier versions
545 used tables to look up the function to use, but
546 - if the table contains both assembler and disassembler functions then
547 the disassembler contains much of the assembler and vice-versa,
548 - there's a lot of inlining possibilities as things grow,
549 - using a switch statement avoids the function call overhead.
551 This function could be moved into `parse_insn_normal', but keeping it
552 separate makes clear the interface between `parse_insn_normal' and each of
553 the handlers. It's also needed by GAS to insert operands that couldn't be
554 resolved during parsing. */
557 xstormy16_cgen_insert_operand (CGEN_CPU_DESC cd
,
559 CGEN_FIELDS
* fields
,
560 CGEN_INSN_BYTES_PTR buffer
,
561 bfd_vma pc ATTRIBUTE_UNUSED
)
563 const char * errmsg
= NULL
;
564 unsigned int total_length
= CGEN_FIELDS_BITSIZE (fields
);
568 case XSTORMY16_OPERAND_RB
:
569 errmsg
= insert_normal (cd
, fields
->f_Rb
, 0, 0, 17, 3, 32, total_length
, buffer
);
571 case XSTORMY16_OPERAND_RBJ
:
572 errmsg
= insert_normal (cd
, fields
->f_Rbj
, 0, 0, 11, 1, 32, total_length
, buffer
);
574 case XSTORMY16_OPERAND_RD
:
575 errmsg
= insert_normal (cd
, fields
->f_Rd
, 0, 0, 12, 4, 32, total_length
, buffer
);
577 case XSTORMY16_OPERAND_RDM
:
578 errmsg
= insert_normal (cd
, fields
->f_Rdm
, 0, 0, 13, 3, 32, total_length
, buffer
);
580 case XSTORMY16_OPERAND_RM
:
581 errmsg
= insert_normal (cd
, fields
->f_Rm
, 0, 0, 4, 3, 32, total_length
, buffer
);
583 case XSTORMY16_OPERAND_RS
:
584 errmsg
= insert_normal (cd
, fields
->f_Rs
, 0, 0, 8, 4, 32, total_length
, buffer
);
586 case XSTORMY16_OPERAND_ABS24
:
589 FLD (f_abs24_1
) = ((FLD (f_abs24
)) & (255));
590 FLD (f_abs24_2
) = ((unsigned int) (FLD (f_abs24
)) >> (8));
592 errmsg
= insert_normal (cd
, fields
->f_abs24_1
, 0, 0, 8, 8, 32, total_length
, buffer
);
595 errmsg
= insert_normal (cd
, fields
->f_abs24_2
, 0, 0, 16, 16, 32, total_length
, buffer
);
600 case XSTORMY16_OPERAND_BCOND2
:
601 errmsg
= insert_normal (cd
, fields
->f_op2
, 0, 0, 4, 4, 32, total_length
, buffer
);
603 case XSTORMY16_OPERAND_BCOND5
:
604 errmsg
= insert_normal (cd
, fields
->f_op5
, 0, 0, 16, 4, 32, total_length
, buffer
);
606 case XSTORMY16_OPERAND_HMEM8
:
608 long value
= fields
->f_hmem8
;
609 value
= ((value
) - (32512));
610 errmsg
= insert_normal (cd
, value
, 0|(1<<CGEN_IFLD_ABS_ADDR
), 0, 8, 8, 32, total_length
, buffer
);
613 case XSTORMY16_OPERAND_IMM12
:
614 errmsg
= insert_normal (cd
, fields
->f_imm12
, 0|(1<<CGEN_IFLD_SIGNED
), 0, 20, 12, 32, total_length
, buffer
);
616 case XSTORMY16_OPERAND_IMM16
:
617 errmsg
= insert_normal (cd
, fields
->f_imm16
, 0|(1<<CGEN_IFLD_SIGN_OPT
), 0, 16, 16, 32, total_length
, buffer
);
619 case XSTORMY16_OPERAND_IMM2
:
620 errmsg
= insert_normal (cd
, fields
->f_imm2
, 0, 0, 10, 2, 32, total_length
, buffer
);
622 case XSTORMY16_OPERAND_IMM3
:
623 errmsg
= insert_normal (cd
, fields
->f_imm3
, 0, 0, 4, 3, 32, total_length
, buffer
);
625 case XSTORMY16_OPERAND_IMM3B
:
626 errmsg
= insert_normal (cd
, fields
->f_imm3b
, 0, 0, 17, 3, 32, total_length
, buffer
);
628 case XSTORMY16_OPERAND_IMM4
:
629 errmsg
= insert_normal (cd
, fields
->f_imm4
, 0, 0, 8, 4, 32, total_length
, buffer
);
631 case XSTORMY16_OPERAND_IMM8
:
632 errmsg
= insert_normal (cd
, fields
->f_imm8
, 0, 0, 8, 8, 32, total_length
, buffer
);
634 case XSTORMY16_OPERAND_IMM8SMALL
:
635 errmsg
= insert_normal (cd
, fields
->f_imm8
, 0, 0, 8, 8, 32, total_length
, buffer
);
637 case XSTORMY16_OPERAND_LMEM8
:
638 errmsg
= insert_normal (cd
, fields
->f_lmem8
, 0|(1<<CGEN_IFLD_ABS_ADDR
), 0, 8, 8, 32, total_length
, buffer
);
640 case XSTORMY16_OPERAND_REL12
:
642 long value
= fields
->f_rel12
;
643 value
= ((value
) - (((pc
) + (4))));
644 errmsg
= insert_normal (cd
, value
, 0|(1<<CGEN_IFLD_SIGNED
)|(1<<CGEN_IFLD_PCREL_ADDR
), 0, 20, 12, 32, total_length
, buffer
);
647 case XSTORMY16_OPERAND_REL12A
:
649 long value
= fields
->f_rel12a
;
650 value
= ((int) (((value
) - (((pc
) + (2))))) >> (1));
651 errmsg
= insert_normal (cd
, value
, 0|(1<<CGEN_IFLD_SIGNED
)|(1<<CGEN_IFLD_PCREL_ADDR
), 0, 4, 11, 32, total_length
, buffer
);
654 case XSTORMY16_OPERAND_REL8_2
:
656 long value
= fields
->f_rel8_2
;
657 value
= ((value
) - (((pc
) + (2))));
658 errmsg
= insert_normal (cd
, value
, 0|(1<<CGEN_IFLD_SIGNED
)|(1<<CGEN_IFLD_PCREL_ADDR
), 0, 8, 8, 32, total_length
, buffer
);
661 case XSTORMY16_OPERAND_REL8_4
:
663 long value
= fields
->f_rel8_4
;
664 value
= ((value
) - (((pc
) + (4))));
665 errmsg
= insert_normal (cd
, value
, 0|(1<<CGEN_IFLD_SIGNED
)|(1<<CGEN_IFLD_PCREL_ADDR
), 0, 8, 8, 32, total_length
, buffer
);
668 case XSTORMY16_OPERAND_WS2
:
669 errmsg
= insert_normal (cd
, fields
->f_op2m
, 0, 0, 7, 1, 32, total_length
, buffer
);
673 /* xgettext:c-format */
674 fprintf (stderr
, _("Unrecognized field %d while building insn.\n"),
682 int xstormy16_cgen_extract_operand
683 (CGEN_CPU_DESC
, int, CGEN_EXTRACT_INFO
*, CGEN_INSN_INT
, CGEN_FIELDS
*, bfd_vma
);
685 /* Main entry point for operand extraction.
686 The result is <= 0 for error, >0 for success.
687 ??? Actual values aren't well defined right now.
689 This function is basically just a big switch statement. Earlier versions
690 used tables to look up the function to use, but
691 - if the table contains both assembler and disassembler functions then
692 the disassembler contains much of the assembler and vice-versa,
693 - there's a lot of inlining possibilities as things grow,
694 - using a switch statement avoids the function call overhead.
696 This function could be moved into `print_insn_normal', but keeping it
697 separate makes clear the interface between `print_insn_normal' and each of
701 xstormy16_cgen_extract_operand (CGEN_CPU_DESC cd
,
703 CGEN_EXTRACT_INFO
*ex_info
,
704 CGEN_INSN_INT insn_value
,
705 CGEN_FIELDS
* fields
,
708 /* Assume success (for those operands that are nops). */
710 unsigned int total_length
= CGEN_FIELDS_BITSIZE (fields
);
714 case XSTORMY16_OPERAND_RB
:
715 length
= extract_normal (cd
, ex_info
, insn_value
, 0, 0, 17, 3, 32, total_length
, pc
, & fields
->f_Rb
);
717 case XSTORMY16_OPERAND_RBJ
:
718 length
= extract_normal (cd
, ex_info
, insn_value
, 0, 0, 11, 1, 32, total_length
, pc
, & fields
->f_Rbj
);
720 case XSTORMY16_OPERAND_RD
:
721 length
= extract_normal (cd
, ex_info
, insn_value
, 0, 0, 12, 4, 32, total_length
, pc
, & fields
->f_Rd
);
723 case XSTORMY16_OPERAND_RDM
:
724 length
= extract_normal (cd
, ex_info
, insn_value
, 0, 0, 13, 3, 32, total_length
, pc
, & fields
->f_Rdm
);
726 case XSTORMY16_OPERAND_RM
:
727 length
= extract_normal (cd
, ex_info
, insn_value
, 0, 0, 4, 3, 32, total_length
, pc
, & fields
->f_Rm
);
729 case XSTORMY16_OPERAND_RS
:
730 length
= extract_normal (cd
, ex_info
, insn_value
, 0, 0, 8, 4, 32, total_length
, pc
, & fields
->f_Rs
);
732 case XSTORMY16_OPERAND_ABS24
:
734 length
= extract_normal (cd
, ex_info
, insn_value
, 0, 0, 8, 8, 32, total_length
, pc
, & fields
->f_abs24_1
);
735 if (length
<= 0) break;
736 length
= extract_normal (cd
, ex_info
, insn_value
, 0, 0, 16, 16, 32, total_length
, pc
, & fields
->f_abs24_2
);
737 if (length
<= 0) break;
738 FLD (f_abs24
) = ((((FLD (f_abs24_2
)) << (8))) | (FLD (f_abs24_1
)));
741 case XSTORMY16_OPERAND_BCOND2
:
742 length
= extract_normal (cd
, ex_info
, insn_value
, 0, 0, 4, 4, 32, total_length
, pc
, & fields
->f_op2
);
744 case XSTORMY16_OPERAND_BCOND5
:
745 length
= extract_normal (cd
, ex_info
, insn_value
, 0, 0, 16, 4, 32, total_length
, pc
, & fields
->f_op5
);
747 case XSTORMY16_OPERAND_HMEM8
:
750 length
= extract_normal (cd
, ex_info
, insn_value
, 0|(1<<CGEN_IFLD_ABS_ADDR
), 0, 8, 8, 32, total_length
, pc
, & value
);
751 value
= ((value
) + (32512));
752 fields
->f_hmem8
= value
;
755 case XSTORMY16_OPERAND_IMM12
:
756 length
= extract_normal (cd
, ex_info
, insn_value
, 0|(1<<CGEN_IFLD_SIGNED
), 0, 20, 12, 32, total_length
, pc
, & fields
->f_imm12
);
758 case XSTORMY16_OPERAND_IMM16
:
759 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 case XSTORMY16_OPERAND_IMM2
:
762 length
= extract_normal (cd
, ex_info
, insn_value
, 0, 0, 10, 2, 32, total_length
, pc
, & fields
->f_imm2
);
764 case XSTORMY16_OPERAND_IMM3
:
765 length
= extract_normal (cd
, ex_info
, insn_value
, 0, 0, 4, 3, 32, total_length
, pc
, & fields
->f_imm3
);
767 case XSTORMY16_OPERAND_IMM3B
:
768 length
= extract_normal (cd
, ex_info
, insn_value
, 0, 0, 17, 3, 32, total_length
, pc
, & fields
->f_imm3b
);
770 case XSTORMY16_OPERAND_IMM4
:
771 length
= extract_normal (cd
, ex_info
, insn_value
, 0, 0, 8, 4, 32, total_length
, pc
, & fields
->f_imm4
);
773 case XSTORMY16_OPERAND_IMM8
:
774 length
= extract_normal (cd
, ex_info
, insn_value
, 0, 0, 8, 8, 32, total_length
, pc
, & fields
->f_imm8
);
776 case XSTORMY16_OPERAND_IMM8SMALL
:
777 length
= extract_normal (cd
, ex_info
, insn_value
, 0, 0, 8, 8, 32, total_length
, pc
, & fields
->f_imm8
);
779 case XSTORMY16_OPERAND_LMEM8
:
780 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 case XSTORMY16_OPERAND_REL12
:
785 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
);
786 value
= ((value
) + (((pc
) + (4))));
787 fields
->f_rel12
= value
;
790 case XSTORMY16_OPERAND_REL12A
:
793 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
);
794 value
= ((((value
) << (1))) + (((pc
) + (2))));
795 fields
->f_rel12a
= value
;
798 case XSTORMY16_OPERAND_REL8_2
:
801 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
);
802 value
= ((value
) + (((pc
) + (2))));
803 fields
->f_rel8_2
= value
;
806 case XSTORMY16_OPERAND_REL8_4
:
809 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
);
810 value
= ((value
) + (((pc
) + (4))));
811 fields
->f_rel8_4
= value
;
814 case XSTORMY16_OPERAND_WS2
:
815 length
= extract_normal (cd
, ex_info
, insn_value
, 0, 0, 7, 1, 32, total_length
, pc
, & fields
->f_op2m
);
819 /* xgettext:c-format */
820 fprintf (stderr
, _("Unrecognized field %d while decoding insn.\n"),
828 cgen_insert_fn
* const xstormy16_cgen_insert_handlers
[] =
833 cgen_extract_fn
* const xstormy16_cgen_extract_handlers
[] =
838 int xstormy16_cgen_get_int_operand (CGEN_CPU_DESC
, int, const CGEN_FIELDS
*);
839 bfd_vma
xstormy16_cgen_get_vma_operand (CGEN_CPU_DESC
, int, const CGEN_FIELDS
*);
841 /* Getting values from cgen_fields is handled by a collection of functions.
842 They are distinguished by the type of the VALUE argument they return.
843 TODO: floating point, inlining support, remove cases where result type
847 xstormy16_cgen_get_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED
,
849 const CGEN_FIELDS
* fields
)
855 case XSTORMY16_OPERAND_RB
:
856 value
= fields
->f_Rb
;
858 case XSTORMY16_OPERAND_RBJ
:
859 value
= fields
->f_Rbj
;
861 case XSTORMY16_OPERAND_RD
:
862 value
= fields
->f_Rd
;
864 case XSTORMY16_OPERAND_RDM
:
865 value
= fields
->f_Rdm
;
867 case XSTORMY16_OPERAND_RM
:
868 value
= fields
->f_Rm
;
870 case XSTORMY16_OPERAND_RS
:
871 value
= fields
->f_Rs
;
873 case XSTORMY16_OPERAND_ABS24
:
874 value
= fields
->f_abs24
;
876 case XSTORMY16_OPERAND_BCOND2
:
877 value
= fields
->f_op2
;
879 case XSTORMY16_OPERAND_BCOND5
:
880 value
= fields
->f_op5
;
882 case XSTORMY16_OPERAND_HMEM8
:
883 value
= fields
->f_hmem8
;
885 case XSTORMY16_OPERAND_IMM12
:
886 value
= fields
->f_imm12
;
888 case XSTORMY16_OPERAND_IMM16
:
889 value
= fields
->f_imm16
;
891 case XSTORMY16_OPERAND_IMM2
:
892 value
= fields
->f_imm2
;
894 case XSTORMY16_OPERAND_IMM3
:
895 value
= fields
->f_imm3
;
897 case XSTORMY16_OPERAND_IMM3B
:
898 value
= fields
->f_imm3b
;
900 case XSTORMY16_OPERAND_IMM4
:
901 value
= fields
->f_imm4
;
903 case XSTORMY16_OPERAND_IMM8
:
904 value
= fields
->f_imm8
;
906 case XSTORMY16_OPERAND_IMM8SMALL
:
907 value
= fields
->f_imm8
;
909 case XSTORMY16_OPERAND_LMEM8
:
910 value
= fields
->f_lmem8
;
912 case XSTORMY16_OPERAND_REL12
:
913 value
= fields
->f_rel12
;
915 case XSTORMY16_OPERAND_REL12A
:
916 value
= fields
->f_rel12a
;
918 case XSTORMY16_OPERAND_REL8_2
:
919 value
= fields
->f_rel8_2
;
921 case XSTORMY16_OPERAND_REL8_4
:
922 value
= fields
->f_rel8_4
;
924 case XSTORMY16_OPERAND_WS2
:
925 value
= fields
->f_op2m
;
929 /* xgettext:c-format */
930 fprintf (stderr
, _("Unrecognized field %d while getting int operand.\n"),
939 xstormy16_cgen_get_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED
,
941 const CGEN_FIELDS
* fields
)
947 case XSTORMY16_OPERAND_RB
:
948 value
= fields
->f_Rb
;
950 case XSTORMY16_OPERAND_RBJ
:
951 value
= fields
->f_Rbj
;
953 case XSTORMY16_OPERAND_RD
:
954 value
= fields
->f_Rd
;
956 case XSTORMY16_OPERAND_RDM
:
957 value
= fields
->f_Rdm
;
959 case XSTORMY16_OPERAND_RM
:
960 value
= fields
->f_Rm
;
962 case XSTORMY16_OPERAND_RS
:
963 value
= fields
->f_Rs
;
965 case XSTORMY16_OPERAND_ABS24
:
966 value
= fields
->f_abs24
;
968 case XSTORMY16_OPERAND_BCOND2
:
969 value
= fields
->f_op2
;
971 case XSTORMY16_OPERAND_BCOND5
:
972 value
= fields
->f_op5
;
974 case XSTORMY16_OPERAND_HMEM8
:
975 value
= fields
->f_hmem8
;
977 case XSTORMY16_OPERAND_IMM12
:
978 value
= fields
->f_imm12
;
980 case XSTORMY16_OPERAND_IMM16
:
981 value
= fields
->f_imm16
;
983 case XSTORMY16_OPERAND_IMM2
:
984 value
= fields
->f_imm2
;
986 case XSTORMY16_OPERAND_IMM3
:
987 value
= fields
->f_imm3
;
989 case XSTORMY16_OPERAND_IMM3B
:
990 value
= fields
->f_imm3b
;
992 case XSTORMY16_OPERAND_IMM4
:
993 value
= fields
->f_imm4
;
995 case XSTORMY16_OPERAND_IMM8
:
996 value
= fields
->f_imm8
;
998 case XSTORMY16_OPERAND_IMM8SMALL
:
999 value
= fields
->f_imm8
;
1001 case XSTORMY16_OPERAND_LMEM8
:
1002 value
= fields
->f_lmem8
;
1004 case XSTORMY16_OPERAND_REL12
:
1005 value
= fields
->f_rel12
;
1007 case XSTORMY16_OPERAND_REL12A
:
1008 value
= fields
->f_rel12a
;
1010 case XSTORMY16_OPERAND_REL8_2
:
1011 value
= fields
->f_rel8_2
;
1013 case XSTORMY16_OPERAND_REL8_4
:
1014 value
= fields
->f_rel8_4
;
1016 case XSTORMY16_OPERAND_WS2
:
1017 value
= fields
->f_op2m
;
1021 /* xgettext:c-format */
1022 fprintf (stderr
, _("Unrecognized field %d while getting vma operand.\n"),
1030 void xstormy16_cgen_set_int_operand (CGEN_CPU_DESC
, int, CGEN_FIELDS
*, int);
1031 void xstormy16_cgen_set_vma_operand (CGEN_CPU_DESC
, int, CGEN_FIELDS
*, bfd_vma
);
1033 /* Stuffing values in cgen_fields is handled by a collection of functions.
1034 They are distinguished by the type of the VALUE argument they accept.
1035 TODO: floating point, inlining support, remove cases where argument type
1039 xstormy16_cgen_set_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED
,
1041 CGEN_FIELDS
* fields
,
1046 case XSTORMY16_OPERAND_RB
:
1047 fields
->f_Rb
= value
;
1049 case XSTORMY16_OPERAND_RBJ
:
1050 fields
->f_Rbj
= value
;
1052 case XSTORMY16_OPERAND_RD
:
1053 fields
->f_Rd
= value
;
1055 case XSTORMY16_OPERAND_RDM
:
1056 fields
->f_Rdm
= value
;
1058 case XSTORMY16_OPERAND_RM
:
1059 fields
->f_Rm
= value
;
1061 case XSTORMY16_OPERAND_RS
:
1062 fields
->f_Rs
= value
;
1064 case XSTORMY16_OPERAND_ABS24
:
1065 fields
->f_abs24
= value
;
1067 case XSTORMY16_OPERAND_BCOND2
:
1068 fields
->f_op2
= value
;
1070 case XSTORMY16_OPERAND_BCOND5
:
1071 fields
->f_op5
= value
;
1073 case XSTORMY16_OPERAND_HMEM8
:
1074 fields
->f_hmem8
= value
;
1076 case XSTORMY16_OPERAND_IMM12
:
1077 fields
->f_imm12
= value
;
1079 case XSTORMY16_OPERAND_IMM16
:
1080 fields
->f_imm16
= value
;
1082 case XSTORMY16_OPERAND_IMM2
:
1083 fields
->f_imm2
= value
;
1085 case XSTORMY16_OPERAND_IMM3
:
1086 fields
->f_imm3
= value
;
1088 case XSTORMY16_OPERAND_IMM3B
:
1089 fields
->f_imm3b
= value
;
1091 case XSTORMY16_OPERAND_IMM4
:
1092 fields
->f_imm4
= value
;
1094 case XSTORMY16_OPERAND_IMM8
:
1095 fields
->f_imm8
= value
;
1097 case XSTORMY16_OPERAND_IMM8SMALL
:
1098 fields
->f_imm8
= value
;
1100 case XSTORMY16_OPERAND_LMEM8
:
1101 fields
->f_lmem8
= value
;
1103 case XSTORMY16_OPERAND_REL12
:
1104 fields
->f_rel12
= value
;
1106 case XSTORMY16_OPERAND_REL12A
:
1107 fields
->f_rel12a
= value
;
1109 case XSTORMY16_OPERAND_REL8_2
:
1110 fields
->f_rel8_2
= value
;
1112 case XSTORMY16_OPERAND_REL8_4
:
1113 fields
->f_rel8_4
= value
;
1115 case XSTORMY16_OPERAND_WS2
:
1116 fields
->f_op2m
= value
;
1120 /* xgettext:c-format */
1121 fprintf (stderr
, _("Unrecognized field %d while setting int operand.\n"),
1128 xstormy16_cgen_set_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED
,
1130 CGEN_FIELDS
* fields
,
1135 case XSTORMY16_OPERAND_RB
:
1136 fields
->f_Rb
= value
;
1138 case XSTORMY16_OPERAND_RBJ
:
1139 fields
->f_Rbj
= value
;
1141 case XSTORMY16_OPERAND_RD
:
1142 fields
->f_Rd
= value
;
1144 case XSTORMY16_OPERAND_RDM
:
1145 fields
->f_Rdm
= value
;
1147 case XSTORMY16_OPERAND_RM
:
1148 fields
->f_Rm
= value
;
1150 case XSTORMY16_OPERAND_RS
:
1151 fields
->f_Rs
= value
;
1153 case XSTORMY16_OPERAND_ABS24
:
1154 fields
->f_abs24
= value
;
1156 case XSTORMY16_OPERAND_BCOND2
:
1157 fields
->f_op2
= value
;
1159 case XSTORMY16_OPERAND_BCOND5
:
1160 fields
->f_op5
= value
;
1162 case XSTORMY16_OPERAND_HMEM8
:
1163 fields
->f_hmem8
= value
;
1165 case XSTORMY16_OPERAND_IMM12
:
1166 fields
->f_imm12
= value
;
1168 case XSTORMY16_OPERAND_IMM16
:
1169 fields
->f_imm16
= value
;
1171 case XSTORMY16_OPERAND_IMM2
:
1172 fields
->f_imm2
= value
;
1174 case XSTORMY16_OPERAND_IMM3
:
1175 fields
->f_imm3
= value
;
1177 case XSTORMY16_OPERAND_IMM3B
:
1178 fields
->f_imm3b
= value
;
1180 case XSTORMY16_OPERAND_IMM4
:
1181 fields
->f_imm4
= value
;
1183 case XSTORMY16_OPERAND_IMM8
:
1184 fields
->f_imm8
= value
;
1186 case XSTORMY16_OPERAND_IMM8SMALL
:
1187 fields
->f_imm8
= value
;
1189 case XSTORMY16_OPERAND_LMEM8
:
1190 fields
->f_lmem8
= value
;
1192 case XSTORMY16_OPERAND_REL12
:
1193 fields
->f_rel12
= value
;
1195 case XSTORMY16_OPERAND_REL12A
:
1196 fields
->f_rel12a
= value
;
1198 case XSTORMY16_OPERAND_REL8_2
:
1199 fields
->f_rel8_2
= value
;
1201 case XSTORMY16_OPERAND_REL8_4
:
1202 fields
->f_rel8_4
= value
;
1204 case XSTORMY16_OPERAND_WS2
:
1205 fields
->f_op2m
= value
;
1209 /* xgettext:c-format */
1210 fprintf (stderr
, _("Unrecognized field %d while setting vma operand.\n"),
1216 /* Function to call before using the instruction builder tables. */
1219 xstormy16_cgen_init_ibld_table (CGEN_CPU_DESC cd
)
1221 cd
->insert_handlers
= & xstormy16_cgen_insert_handlers
[0];
1222 cd
->extract_handlers
= & xstormy16_cgen_extract_handlers
[0];
1224 cd
->insert_operand
= xstormy16_cgen_insert_operand
;
1225 cd
->extract_operand
= xstormy16_cgen_extract_operand
;
1227 cd
->get_int_operand
= xstormy16_cgen_get_int_operand
;
1228 cd
->set_int_operand
= xstormy16_cgen_set_int_operand
;
1229 cd
->get_vma_operand
= xstormy16_cgen_get_vma_operand
;
1230 cd
->set_vma_operand
= xstormy16_cgen_set_vma_operand
;