* scripttempl/mmo.sc: For relocateable links, set $OUTPUT_FORMAT to
[binutils.git] / opcodes / xstormy16-ibld.c
blob7609fb0461a11442346461a41f6d5592dcf8627e
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 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 "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;
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))
178 val &= 0xFFFFFFFF;
180 if (val > maxval)
182 /* xgettext:c-format */
183 sprintf (errbuf,
184 _("operand out of range (0x%lx not between 0 and 0x%lx)"),
185 val, maxval);
186 return errbuf;
189 else
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)
198 sprintf
199 /* xgettext:c-format */
200 (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
201 value, minval, maxval);
202 return errbuf;
207 #if CGEN_INT_INSN_P
210 int shift;
212 if (CGEN_INSN_LSB0_P)
213 shift = (word_offset + start + 1) - length;
214 else
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 */
229 return NULL;
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. */
239 static const char *
240 insert_insn_normal (CGEN_CPU_DESC cd,
241 const CGEN_INSN * insn,
242 CGEN_FIELDS * fields,
243 CGEN_INSN_BYTES_PTR buffer,
244 bfd_vma pc)
246 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
247 unsigned long value;
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. */
256 #if CGEN_INT_INSN_P
258 put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
259 CGEN_FIELDS_BITSIZE (fields), value);
261 #else
263 cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
264 (unsigned) CGEN_FIELDS_BITSIZE (fields)),
265 value);
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)
276 const char *errmsg;
278 if (CGEN_SYNTAX_CHAR_P (* syn))
279 continue;
281 errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
282 fields, buffer, pc);
283 if (errmsg)
284 return errmsg;
287 return NULL;
290 #if CGEN_INT_INSN_P
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. */
294 static void
295 put_insn_int_value (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
296 CGEN_INSN_BYTES_PTR buf,
297 int length,
298 int insn_length,
299 CGEN_INSN_INT value)
301 /* For architectures with insns smaller than the base-insn-bitsize,
302 length may be too big. */
303 if (length > insn_length)
304 *buf = value;
305 else
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);
314 #endif
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,
329 int offset,
330 int bytes,
331 bfd_vma pc)
333 /* It's doubtful that the middle part has already been fetched so
334 we don't optimize that case. kiss. */
335 unsigned int mask;
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)
341 return 1;
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))
346 break;
348 if (bytes)
350 int status;
352 pc += offset;
353 status = (*info->read_memory_func)
354 (pc, ex_info->insn_bytes + offset, bytes, info);
356 if (status != 0)
358 (*info->memory_error_func) (status, pc, info);
359 return 0;
362 ex_info->valid |= ((1 << bytes) - 1) << offset;
365 return 1;
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,
373 int start,
374 int length,
375 int word_length,
376 unsigned char *bufp,
377 bfd_vma pc ATTRIBUTE_UNUSED)
379 unsigned long x;
380 int shift;
382 x = cgen_get_insn_value (cd, bufp, word_length);
384 if (CGEN_INSN_LSB0_P)
385 shift = (start + 1) - length;
386 else
387 shift = (word_length - (start + length));
388 return x >> shift;
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
411 necessary. */
413 static int
414 extract_normal (CGEN_CPU_DESC cd,
415 #if ! CGEN_INT_INSN_P
416 CGEN_EXTRACT_INFO *ex_info,
417 #else
418 CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
419 #endif
420 CGEN_INSN_INT insn_value,
421 unsigned int attrs,
422 unsigned int word_offset,
423 unsigned int start,
424 unsigned int length,
425 unsigned int word_length,
426 unsigned int total_length,
427 #if ! CGEN_INT_INSN_P
428 bfd_vma pc,
429 #else
430 bfd_vma pc ATTRIBUTE_UNUSED,
431 #endif
432 long *valuep)
434 long value, mask;
436 /* If LENGTH is zero, this operand doesn't contribute to the value
437 so give it a standard value of zero. */
438 if (length == 0)
440 *valuep = 0;
441 return 1;
444 if (word_length > 32)
445 abort ();
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);
461 else
462 value = insn_value >> (total_length - ( word_offset + start + length));
465 #if ! CGEN_INT_INSN_P
467 else
469 unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
471 if (word_length > 32)
472 abort ();
474 if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
475 return 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;
485 value &= mask;
486 /* sign extend? */
487 if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
488 && (value & (1L << (length - 1))))
489 value |= ~mask;
491 *valuep = value;
493 return 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
503 been called). */
505 static int
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,
510 CGEN_FIELDS *fields,
511 bfd_vma pc)
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)
522 int length;
524 if (CGEN_SYNTAX_CHAR_P (*syn))
525 continue;
527 length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
528 ex_info, insn_value, fields, pc);
529 if (length <= 0)
530 return length;
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. */
556 const char *
557 xstormy16_cgen_insert_operand (CGEN_CPU_DESC cd,
558 int opindex,
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);
566 switch (opindex)
568 case XSTORMY16_OPERAND_RB :
569 errmsg = insert_normal (cd, fields->f_Rb, 0, 0, 17, 3, 32, total_length, buffer);
570 break;
571 case XSTORMY16_OPERAND_RBJ :
572 errmsg = insert_normal (cd, fields->f_Rbj, 0, 0, 11, 1, 32, total_length, buffer);
573 break;
574 case XSTORMY16_OPERAND_RD :
575 errmsg = insert_normal (cd, fields->f_Rd, 0, 0, 12, 4, 32, total_length, buffer);
576 break;
577 case XSTORMY16_OPERAND_RDM :
578 errmsg = insert_normal (cd, fields->f_Rdm, 0, 0, 13, 3, 32, total_length, buffer);
579 break;
580 case XSTORMY16_OPERAND_RM :
581 errmsg = insert_normal (cd, fields->f_Rm, 0, 0, 4, 3, 32, total_length, buffer);
582 break;
583 case XSTORMY16_OPERAND_RS :
584 errmsg = insert_normal (cd, fields->f_Rs, 0, 0, 8, 4, 32, total_length, buffer);
585 break;
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);
593 if (errmsg)
594 break;
595 errmsg = insert_normal (cd, fields->f_abs24_2, 0, 0, 16, 16, 32, total_length, buffer);
596 if (errmsg)
597 break;
599 break;
600 case XSTORMY16_OPERAND_BCOND2 :
601 errmsg = insert_normal (cd, fields->f_op2, 0, 0, 4, 4, 32, total_length, buffer);
602 break;
603 case XSTORMY16_OPERAND_BCOND5 :
604 errmsg = insert_normal (cd, fields->f_op5, 0, 0, 16, 4, 32, total_length, buffer);
605 break;
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);
612 break;
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);
615 break;
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);
618 break;
619 case XSTORMY16_OPERAND_IMM2 :
620 errmsg = insert_normal (cd, fields->f_imm2, 0, 0, 10, 2, 32, total_length, buffer);
621 break;
622 case XSTORMY16_OPERAND_IMM3 :
623 errmsg = insert_normal (cd, fields->f_imm3, 0, 0, 4, 3, 32, total_length, buffer);
624 break;
625 case XSTORMY16_OPERAND_IMM3B :
626 errmsg = insert_normal (cd, fields->f_imm3b, 0, 0, 17, 3, 32, total_length, buffer);
627 break;
628 case XSTORMY16_OPERAND_IMM4 :
629 errmsg = insert_normal (cd, fields->f_imm4, 0, 0, 8, 4, 32, total_length, buffer);
630 break;
631 case XSTORMY16_OPERAND_IMM8 :
632 errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 8, 8, 32, total_length, buffer);
633 break;
634 case XSTORMY16_OPERAND_IMM8SMALL :
635 errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 8, 8, 32, total_length, buffer);
636 break;
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);
639 break;
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);
646 break;
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);
653 break;
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);
660 break;
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);
667 break;
668 case XSTORMY16_OPERAND_WS2 :
669 errmsg = insert_normal (cd, fields->f_op2m, 0, 0, 7, 1, 32, total_length, buffer);
670 break;
672 default :
673 /* xgettext:c-format */
674 fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
675 opindex);
676 abort ();
679 return errmsg;
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
698 the handlers. */
701 xstormy16_cgen_extract_operand (CGEN_CPU_DESC cd,
702 int opindex,
703 CGEN_EXTRACT_INFO *ex_info,
704 CGEN_INSN_INT insn_value,
705 CGEN_FIELDS * fields,
706 bfd_vma pc)
708 /* Assume success (for those operands that are nops). */
709 int length = 1;
710 unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
712 switch (opindex)
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);
716 break;
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);
719 break;
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);
722 break;
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);
725 break;
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);
728 break;
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);
731 break;
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)));
740 break;
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);
743 break;
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);
746 break;
747 case XSTORMY16_OPERAND_HMEM8 :
749 long value;
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;
754 break;
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);
757 break;
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);
760 break;
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);
763 break;
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);
766 break;
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);
769 break;
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);
772 break;
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);
775 break;
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);
778 break;
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);
781 break;
782 case XSTORMY16_OPERAND_REL12 :
784 long value;
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;
789 break;
790 case XSTORMY16_OPERAND_REL12A :
792 long value;
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;
797 break;
798 case XSTORMY16_OPERAND_REL8_2 :
800 long value;
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;
805 break;
806 case XSTORMY16_OPERAND_REL8_4 :
808 long value;
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;
813 break;
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);
816 break;
818 default :
819 /* xgettext:c-format */
820 fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
821 opindex);
822 abort ();
825 return length;
828 cgen_insert_fn * const xstormy16_cgen_insert_handlers[] =
830 insert_insn_normal,
833 cgen_extract_fn * const xstormy16_cgen_extract_handlers[] =
835 extract_insn_normal,
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
844 not appropriate. */
847 xstormy16_cgen_get_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
848 int opindex,
849 const CGEN_FIELDS * fields)
851 int value;
853 switch (opindex)
855 case XSTORMY16_OPERAND_RB :
856 value = fields->f_Rb;
857 break;
858 case XSTORMY16_OPERAND_RBJ :
859 value = fields->f_Rbj;
860 break;
861 case XSTORMY16_OPERAND_RD :
862 value = fields->f_Rd;
863 break;
864 case XSTORMY16_OPERAND_RDM :
865 value = fields->f_Rdm;
866 break;
867 case XSTORMY16_OPERAND_RM :
868 value = fields->f_Rm;
869 break;
870 case XSTORMY16_OPERAND_RS :
871 value = fields->f_Rs;
872 break;
873 case XSTORMY16_OPERAND_ABS24 :
874 value = fields->f_abs24;
875 break;
876 case XSTORMY16_OPERAND_BCOND2 :
877 value = fields->f_op2;
878 break;
879 case XSTORMY16_OPERAND_BCOND5 :
880 value = fields->f_op5;
881 break;
882 case XSTORMY16_OPERAND_HMEM8 :
883 value = fields->f_hmem8;
884 break;
885 case XSTORMY16_OPERAND_IMM12 :
886 value = fields->f_imm12;
887 break;
888 case XSTORMY16_OPERAND_IMM16 :
889 value = fields->f_imm16;
890 break;
891 case XSTORMY16_OPERAND_IMM2 :
892 value = fields->f_imm2;
893 break;
894 case XSTORMY16_OPERAND_IMM3 :
895 value = fields->f_imm3;
896 break;
897 case XSTORMY16_OPERAND_IMM3B :
898 value = fields->f_imm3b;
899 break;
900 case XSTORMY16_OPERAND_IMM4 :
901 value = fields->f_imm4;
902 break;
903 case XSTORMY16_OPERAND_IMM8 :
904 value = fields->f_imm8;
905 break;
906 case XSTORMY16_OPERAND_IMM8SMALL :
907 value = fields->f_imm8;
908 break;
909 case XSTORMY16_OPERAND_LMEM8 :
910 value = fields->f_lmem8;
911 break;
912 case XSTORMY16_OPERAND_REL12 :
913 value = fields->f_rel12;
914 break;
915 case XSTORMY16_OPERAND_REL12A :
916 value = fields->f_rel12a;
917 break;
918 case XSTORMY16_OPERAND_REL8_2 :
919 value = fields->f_rel8_2;
920 break;
921 case XSTORMY16_OPERAND_REL8_4 :
922 value = fields->f_rel8_4;
923 break;
924 case XSTORMY16_OPERAND_WS2 :
925 value = fields->f_op2m;
926 break;
928 default :
929 /* xgettext:c-format */
930 fprintf (stderr, _("Unrecognized field %d while getting int operand.\n"),
931 opindex);
932 abort ();
935 return value;
938 bfd_vma
939 xstormy16_cgen_get_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
940 int opindex,
941 const CGEN_FIELDS * fields)
943 bfd_vma value;
945 switch (opindex)
947 case XSTORMY16_OPERAND_RB :
948 value = fields->f_Rb;
949 break;
950 case XSTORMY16_OPERAND_RBJ :
951 value = fields->f_Rbj;
952 break;
953 case XSTORMY16_OPERAND_RD :
954 value = fields->f_Rd;
955 break;
956 case XSTORMY16_OPERAND_RDM :
957 value = fields->f_Rdm;
958 break;
959 case XSTORMY16_OPERAND_RM :
960 value = fields->f_Rm;
961 break;
962 case XSTORMY16_OPERAND_RS :
963 value = fields->f_Rs;
964 break;
965 case XSTORMY16_OPERAND_ABS24 :
966 value = fields->f_abs24;
967 break;
968 case XSTORMY16_OPERAND_BCOND2 :
969 value = fields->f_op2;
970 break;
971 case XSTORMY16_OPERAND_BCOND5 :
972 value = fields->f_op5;
973 break;
974 case XSTORMY16_OPERAND_HMEM8 :
975 value = fields->f_hmem8;
976 break;
977 case XSTORMY16_OPERAND_IMM12 :
978 value = fields->f_imm12;
979 break;
980 case XSTORMY16_OPERAND_IMM16 :
981 value = fields->f_imm16;
982 break;
983 case XSTORMY16_OPERAND_IMM2 :
984 value = fields->f_imm2;
985 break;
986 case XSTORMY16_OPERAND_IMM3 :
987 value = fields->f_imm3;
988 break;
989 case XSTORMY16_OPERAND_IMM3B :
990 value = fields->f_imm3b;
991 break;
992 case XSTORMY16_OPERAND_IMM4 :
993 value = fields->f_imm4;
994 break;
995 case XSTORMY16_OPERAND_IMM8 :
996 value = fields->f_imm8;
997 break;
998 case XSTORMY16_OPERAND_IMM8SMALL :
999 value = fields->f_imm8;
1000 break;
1001 case XSTORMY16_OPERAND_LMEM8 :
1002 value = fields->f_lmem8;
1003 break;
1004 case XSTORMY16_OPERAND_REL12 :
1005 value = fields->f_rel12;
1006 break;
1007 case XSTORMY16_OPERAND_REL12A :
1008 value = fields->f_rel12a;
1009 break;
1010 case XSTORMY16_OPERAND_REL8_2 :
1011 value = fields->f_rel8_2;
1012 break;
1013 case XSTORMY16_OPERAND_REL8_4 :
1014 value = fields->f_rel8_4;
1015 break;
1016 case XSTORMY16_OPERAND_WS2 :
1017 value = fields->f_op2m;
1018 break;
1020 default :
1021 /* xgettext:c-format */
1022 fprintf (stderr, _("Unrecognized field %d while getting vma operand.\n"),
1023 opindex);
1024 abort ();
1027 return value;
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
1036 not appropriate. */
1038 void
1039 xstormy16_cgen_set_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1040 int opindex,
1041 CGEN_FIELDS * fields,
1042 int value)
1044 switch (opindex)
1046 case XSTORMY16_OPERAND_RB :
1047 fields->f_Rb = value;
1048 break;
1049 case XSTORMY16_OPERAND_RBJ :
1050 fields->f_Rbj = value;
1051 break;
1052 case XSTORMY16_OPERAND_RD :
1053 fields->f_Rd = value;
1054 break;
1055 case XSTORMY16_OPERAND_RDM :
1056 fields->f_Rdm = value;
1057 break;
1058 case XSTORMY16_OPERAND_RM :
1059 fields->f_Rm = value;
1060 break;
1061 case XSTORMY16_OPERAND_RS :
1062 fields->f_Rs = value;
1063 break;
1064 case XSTORMY16_OPERAND_ABS24 :
1065 fields->f_abs24 = value;
1066 break;
1067 case XSTORMY16_OPERAND_BCOND2 :
1068 fields->f_op2 = value;
1069 break;
1070 case XSTORMY16_OPERAND_BCOND5 :
1071 fields->f_op5 = value;
1072 break;
1073 case XSTORMY16_OPERAND_HMEM8 :
1074 fields->f_hmem8 = value;
1075 break;
1076 case XSTORMY16_OPERAND_IMM12 :
1077 fields->f_imm12 = value;
1078 break;
1079 case XSTORMY16_OPERAND_IMM16 :
1080 fields->f_imm16 = value;
1081 break;
1082 case XSTORMY16_OPERAND_IMM2 :
1083 fields->f_imm2 = value;
1084 break;
1085 case XSTORMY16_OPERAND_IMM3 :
1086 fields->f_imm3 = value;
1087 break;
1088 case XSTORMY16_OPERAND_IMM3B :
1089 fields->f_imm3b = value;
1090 break;
1091 case XSTORMY16_OPERAND_IMM4 :
1092 fields->f_imm4 = value;
1093 break;
1094 case XSTORMY16_OPERAND_IMM8 :
1095 fields->f_imm8 = value;
1096 break;
1097 case XSTORMY16_OPERAND_IMM8SMALL :
1098 fields->f_imm8 = value;
1099 break;
1100 case XSTORMY16_OPERAND_LMEM8 :
1101 fields->f_lmem8 = value;
1102 break;
1103 case XSTORMY16_OPERAND_REL12 :
1104 fields->f_rel12 = value;
1105 break;
1106 case XSTORMY16_OPERAND_REL12A :
1107 fields->f_rel12a = value;
1108 break;
1109 case XSTORMY16_OPERAND_REL8_2 :
1110 fields->f_rel8_2 = value;
1111 break;
1112 case XSTORMY16_OPERAND_REL8_4 :
1113 fields->f_rel8_4 = value;
1114 break;
1115 case XSTORMY16_OPERAND_WS2 :
1116 fields->f_op2m = value;
1117 break;
1119 default :
1120 /* xgettext:c-format */
1121 fprintf (stderr, _("Unrecognized field %d while setting int operand.\n"),
1122 opindex);
1123 abort ();
1127 void
1128 xstormy16_cgen_set_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1129 int opindex,
1130 CGEN_FIELDS * fields,
1131 bfd_vma value)
1133 switch (opindex)
1135 case XSTORMY16_OPERAND_RB :
1136 fields->f_Rb = value;
1137 break;
1138 case XSTORMY16_OPERAND_RBJ :
1139 fields->f_Rbj = value;
1140 break;
1141 case XSTORMY16_OPERAND_RD :
1142 fields->f_Rd = value;
1143 break;
1144 case XSTORMY16_OPERAND_RDM :
1145 fields->f_Rdm = value;
1146 break;
1147 case XSTORMY16_OPERAND_RM :
1148 fields->f_Rm = value;
1149 break;
1150 case XSTORMY16_OPERAND_RS :
1151 fields->f_Rs = value;
1152 break;
1153 case XSTORMY16_OPERAND_ABS24 :
1154 fields->f_abs24 = value;
1155 break;
1156 case XSTORMY16_OPERAND_BCOND2 :
1157 fields->f_op2 = value;
1158 break;
1159 case XSTORMY16_OPERAND_BCOND5 :
1160 fields->f_op5 = value;
1161 break;
1162 case XSTORMY16_OPERAND_HMEM8 :
1163 fields->f_hmem8 = value;
1164 break;
1165 case XSTORMY16_OPERAND_IMM12 :
1166 fields->f_imm12 = value;
1167 break;
1168 case XSTORMY16_OPERAND_IMM16 :
1169 fields->f_imm16 = value;
1170 break;
1171 case XSTORMY16_OPERAND_IMM2 :
1172 fields->f_imm2 = value;
1173 break;
1174 case XSTORMY16_OPERAND_IMM3 :
1175 fields->f_imm3 = value;
1176 break;
1177 case XSTORMY16_OPERAND_IMM3B :
1178 fields->f_imm3b = value;
1179 break;
1180 case XSTORMY16_OPERAND_IMM4 :
1181 fields->f_imm4 = value;
1182 break;
1183 case XSTORMY16_OPERAND_IMM8 :
1184 fields->f_imm8 = value;
1185 break;
1186 case XSTORMY16_OPERAND_IMM8SMALL :
1187 fields->f_imm8 = value;
1188 break;
1189 case XSTORMY16_OPERAND_LMEM8 :
1190 fields->f_lmem8 = value;
1191 break;
1192 case XSTORMY16_OPERAND_REL12 :
1193 fields->f_rel12 = value;
1194 break;
1195 case XSTORMY16_OPERAND_REL12A :
1196 fields->f_rel12a = value;
1197 break;
1198 case XSTORMY16_OPERAND_REL8_2 :
1199 fields->f_rel8_2 = value;
1200 break;
1201 case XSTORMY16_OPERAND_REL8_4 :
1202 fields->f_rel8_4 = value;
1203 break;
1204 case XSTORMY16_OPERAND_WS2 :
1205 fields->f_op2m = value;
1206 break;
1208 default :
1209 /* xgettext:c-format */
1210 fprintf (stderr, _("Unrecognized field %d while setting vma operand.\n"),
1211 opindex);
1212 abort ();
1216 /* Function to call before using the instruction builder tables. */
1218 void
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;