OSDN Git Service

Update function declarations to ISO C90 formatting
[pf3gnuchains/pf3gnuchains4x.git] / opcodes / xstormy16-ibld.c
1 /* Instruction building/extraction support for xstormy16. -*- C -*-
2
3    THIS FILE IS MACHINE GENERATED WITH CGEN: Cpu tools GENerator.
4    - the resultant file is machine generated, cgen-ibld.in isn't
5
6    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2005
7    Free Software Foundation, Inc.
8
9    This file is part of the GNU Binutils and GDB, the GNU debugger.
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 2, or (at your option)
14    any later version.
15
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.
20
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.  */
24
25 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
26    Keep that in mind.  */
27
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"
38
39 #undef  min
40 #define min(a,b) ((a) < (b) ? (a) : (b))
41 #undef  max
42 #define max(a,b) ((a) > (b) ? (a) : (b))
43
44 /* Used by the ifield rtx function.  */
45 #define FLD(f) (fields->f)
46
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
72 \f
73 /* Operand insertion.  */
74
75 #if ! CGEN_INT_INSN_P
76
77 /* Subroutine of insert_normal.  */
78
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)
86 {
87   unsigned long x,mask;
88   int shift;
89
90   x = cgen_get_insn_value (cd, bufp, word_length);
91
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);
99
100   cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
101 }
102
103 #endif /* ! CGEN_INT_INSN_P */
104
105 /* Default insertion routine.
106
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.
113
114    The result is an error message or NULL if success.  */
115
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.  */
120
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)
131 {
132   static char errbuf[100];
133   /* Written this way to avoid undefined behaviour.  */
134   unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
135
136   /* If LENGTH is zero, this operand doesn't contribute to the value.  */
137   if (length == 0)
138     return NULL;
139
140   if (word_length > 32)
141     abort ();
142
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)
146     {
147       if (word_offset == 0
148           && word_length > total_length)
149         word_length = total_length;
150     }
151
152   /* Ensure VALUE will fit.  */
153   if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
154     {
155       long minval = - (1L << (length - 1));
156       unsigned long maxval = mask;
157       
158       if ((value > 0 && (unsigned long) value > maxval)
159           || value < minval)
160         {
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;
166         }
167     }
168   else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
169     {
170       unsigned long maxval = mask;
171       
172       if ((unsigned long) value > maxval)
173         {
174           /* xgettext:c-format */
175           sprintf (errbuf,
176                    _("operand out of range (%lu not between 0 and %lu)"),
177                    value, maxval);
178           return errbuf;
179         }
180     }
181   else
182     {
183       if (! cgen_signed_overflow_ok_p (cd))
184         {
185           long minval = - (1L << (length - 1));
186           long maxval =   (1L << (length - 1)) - 1;
187           
188           if (value < minval || value > maxval)
189             {
190               sprintf
191                 /* xgettext:c-format */
192                 (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
193                  value, minval, maxval);
194               return errbuf;
195             }
196         }
197     }
198
199 #if CGEN_INT_INSN_P
200
201   {
202     int shift;
203
204     if (CGEN_INSN_LSB0_P)
205       shift = (word_offset + start + 1) - length;
206     else
207       shift = total_length - (word_offset + start + length);
208     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
209   }
210
211 #else /* ! CGEN_INT_INSN_P */
212
213   {
214     unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
215
216     insert_1 (cd, value, start, length, word_length, bufp);
217   }
218
219 #endif /* ! CGEN_INT_INSN_P */
220
221   return NULL;
222 }
223
224 /* Default insn builder (insert handler).
225    The instruction is recorded in CGEN_INT_INSN_P byte order (meaning
226    that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is
227    recorded in host byte order, otherwise BUFFER is an array of bytes
228    and the value is recorded in target byte order).
229    The result is an error message or NULL if success.  */
230
231 static const char *
232 insert_insn_normal (CGEN_CPU_DESC cd,
233                     const CGEN_INSN * insn,
234                     CGEN_FIELDS * fields,
235                     CGEN_INSN_BYTES_PTR buffer,
236                     bfd_vma pc)
237 {
238   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
239   unsigned long value;
240   const CGEN_SYNTAX_CHAR_TYPE * syn;
241
242   CGEN_INIT_INSERT (cd);
243   value = CGEN_INSN_BASE_VALUE (insn);
244
245   /* If we're recording insns as numbers (rather than a string of bytes),
246      target byte order handling is deferred until later.  */
247
248 #if CGEN_INT_INSN_P
249
250   put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
251                       CGEN_FIELDS_BITSIZE (fields), value);
252
253 #else
254
255   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
256                                         (unsigned) CGEN_FIELDS_BITSIZE (fields)),
257                        value);
258
259 #endif /* ! CGEN_INT_INSN_P */
260
261   /* ??? It would be better to scan the format's fields.
262      Still need to be able to insert a value based on the operand though;
263      e.g. storing a branch displacement that got resolved later.
264      Needs more thought first.  */
265
266   for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn)
267     {
268       const char *errmsg;
269
270       if (CGEN_SYNTAX_CHAR_P (* syn))
271         continue;
272
273       errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
274                                        fields, buffer, pc);
275       if (errmsg)
276         return errmsg;
277     }
278
279   return NULL;
280 }
281
282 #if CGEN_INT_INSN_P
283 /* Cover function to store an insn value into an integral insn.  Must go here
284    because it needs <prefix>-desc.h for CGEN_INT_INSN_P.  */
285
286 static void
287 put_insn_int_value (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
288                     CGEN_INSN_BYTES_PTR buf,
289                     int length,
290                     int insn_length,
291                     CGEN_INSN_INT value)
292 {
293   /* For architectures with insns smaller than the base-insn-bitsize,
294      length may be too big.  */
295   if (length > insn_length)
296     *buf = value;
297   else
298     {
299       int shift = insn_length - length;
300       /* Written this way to avoid undefined behaviour.  */
301       CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
302
303       *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
304     }
305 }
306 #endif
307 \f
308 /* Operand extraction.  */
309
310 #if ! CGEN_INT_INSN_P
311
312 /* Subroutine of extract_normal.
313    Ensure sufficient bytes are cached in EX_INFO.
314    OFFSET is the offset in bytes from the start of the insn of the value.
315    BYTES is the length of the needed value.
316    Returns 1 for success, 0 for failure.  */
317
318 static CGEN_INLINE int
319 fill_cache (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
320             CGEN_EXTRACT_INFO *ex_info,
321             int offset,
322             int bytes,
323             bfd_vma pc)
324 {
325   /* It's doubtful that the middle part has already been fetched so
326      we don't optimize that case.  kiss.  */
327   unsigned int mask;
328   disassemble_info *info = (disassemble_info *) ex_info->dis_info;
329
330   /* First do a quick check.  */
331   mask = (1 << bytes) - 1;
332   if (((ex_info->valid >> offset) & mask) == mask)
333     return 1;
334
335   /* Search for the first byte we need to read.  */
336   for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
337     if (! (mask & ex_info->valid))
338       break;
339
340   if (bytes)
341     {
342       int status;
343
344       pc += offset;
345       status = (*info->read_memory_func)
346         (pc, ex_info->insn_bytes + offset, bytes, info);
347
348       if (status != 0)
349         {
350           (*info->memory_error_func) (status, pc, info);
351           return 0;
352         }
353
354       ex_info->valid |= ((1 << bytes) - 1) << offset;
355     }
356
357   return 1;
358 }
359
360 /* Subroutine of extract_normal.  */
361
362 static CGEN_INLINE long
363 extract_1 (CGEN_CPU_DESC cd,
364            CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
365            int start,
366            int length,
367            int word_length,
368            unsigned char *bufp,
369            bfd_vma pc ATTRIBUTE_UNUSED)
370 {
371   unsigned long x;
372   int shift;
373
374   x = cgen_get_insn_value (cd, bufp, word_length);
375
376   if (CGEN_INSN_LSB0_P)
377     shift = (start + 1) - length;
378   else
379     shift = (word_length - (start + length));
380   return x >> shift;
381 }
382
383 #endif /* ! CGEN_INT_INSN_P */
384
385 /* Default extraction routine.
386
387    INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
388    or sometimes less for cases like the m32r where the base insn size is 32
389    but some insns are 16 bits.
390    ATTRS is a mask of the boolean attributes.  We only need `SIGNED',
391    but for generality we take a bitmask of all of them.
392    WORD_OFFSET is the offset in bits from the start of the insn of the value.
393    WORD_LENGTH is the length of the word in bits in which the value resides.
394    START is the starting bit number in the word, architecture origin.
395    LENGTH is the length of VALUE in bits.
396    TOTAL_LENGTH is the total length of the insn in bits.
397
398    Returns 1 for success, 0 for failure.  */
399
400 /* ??? The return code isn't properly used.  wip.  */
401
402 /* ??? This doesn't handle bfd_vma's.  Create another function when
403    necessary.  */
404
405 static int
406 extract_normal (CGEN_CPU_DESC cd,
407 #if ! CGEN_INT_INSN_P
408                 CGEN_EXTRACT_INFO *ex_info,
409 #else
410                 CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
411 #endif
412                 CGEN_INSN_INT insn_value,
413                 unsigned int attrs,
414                 unsigned int word_offset,
415                 unsigned int start,
416                 unsigned int length,
417                 unsigned int word_length,
418                 unsigned int total_length,
419 #if ! CGEN_INT_INSN_P
420                 bfd_vma pc,
421 #else
422                 bfd_vma pc ATTRIBUTE_UNUSED,
423 #endif
424                 long *valuep)
425 {
426   long value, mask;
427
428   /* If LENGTH is zero, this operand doesn't contribute to the value
429      so give it a standard value of zero.  */
430   if (length == 0)
431     {
432       *valuep = 0;
433       return 1;
434     }
435
436   if (word_length > 32)
437     abort ();
438
439   /* For architectures with insns smaller than the insn-base-bitsize,
440      word_length may be too big.  */
441   if (cd->min_insn_bitsize < cd->base_insn_bitsize)
442     {
443       if (word_offset == 0
444           && word_length > total_length)
445         word_length = total_length;
446     }
447
448   /* Does the value reside in INSN_VALUE, and at the right alignment?  */
449
450   if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
451     {
452       if (CGEN_INSN_LSB0_P)
453         value = insn_value >> ((word_offset + start + 1) - length);
454       else
455         value = insn_value >> (total_length - ( word_offset + start + length));
456     }
457
458 #if ! CGEN_INT_INSN_P
459
460   else
461     {
462       unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
463
464       if (word_length > 32)
465         abort ();
466
467       if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
468         return 0;
469
470       value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
471     }
472
473 #endif /* ! CGEN_INT_INSN_P */
474
475   /* Written this way to avoid undefined behaviour.  */
476   mask = (((1L << (length - 1)) - 1) << 1) | 1;
477
478   value &= mask;
479   /* sign extend? */
480   if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
481       && (value & (1L << (length - 1))))
482     value |= ~mask;
483
484   *valuep = value;
485
486   return 1;
487 }
488
489 /* Default insn extractor.
490
491    INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
492    The extracted fields are stored in FIELDS.
493    EX_INFO is used to handle reading variable length insns.
494    Return the length of the insn in bits, or 0 if no match,
495    or -1 if an error occurs fetching data (memory_error_func will have
496    been called).  */
497
498 static int
499 extract_insn_normal (CGEN_CPU_DESC cd,
500                      const CGEN_INSN *insn,
501                      CGEN_EXTRACT_INFO *ex_info,
502                      CGEN_INSN_INT insn_value,
503                      CGEN_FIELDS *fields,
504                      bfd_vma pc)
505 {
506   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
507   const CGEN_SYNTAX_CHAR_TYPE *syn;
508
509   CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
510
511   CGEN_INIT_EXTRACT (cd);
512
513   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
514     {
515       int length;
516
517       if (CGEN_SYNTAX_CHAR_P (*syn))
518         continue;
519
520       length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
521                                         ex_info, insn_value, fields, pc);
522       if (length <= 0)
523         return length;
524     }
525
526   /* We recognized and successfully extracted this insn.  */
527   return CGEN_INSN_BITSIZE (insn);
528 }
529 \f
530 /* Machine generated code added here.  */
531
532 const char * xstormy16_cgen_insert_operand
533   (CGEN_CPU_DESC, int, CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
534
535 /* Main entry point for operand insertion.
536
537    This function is basically just a big switch statement.  Earlier versions
538    used tables to look up the function to use, but
539    - if the table contains both assembler and disassembler functions then
540      the disassembler contains much of the assembler and vice-versa,
541    - there's a lot of inlining possibilities as things grow,
542    - using a switch statement avoids the function call overhead.
543
544    This function could be moved into `parse_insn_normal', but keeping it
545    separate makes clear the interface between `parse_insn_normal' and each of
546    the handlers.  It's also needed by GAS to insert operands that couldn't be
547    resolved during parsing.  */
548
549 const char *
550 xstormy16_cgen_insert_operand (CGEN_CPU_DESC cd,
551                              int opindex,
552                              CGEN_FIELDS * fields,
553                              CGEN_INSN_BYTES_PTR buffer,
554                              bfd_vma pc ATTRIBUTE_UNUSED)
555 {
556   const char * errmsg = NULL;
557   unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
558
559   switch (opindex)
560     {
561     case XSTORMY16_OPERAND_RB :
562       errmsg = insert_normal (cd, fields->f_Rb, 0, 0, 17, 3, 32, total_length, buffer);
563       break;
564     case XSTORMY16_OPERAND_RBJ :
565       errmsg = insert_normal (cd, fields->f_Rbj, 0, 0, 11, 1, 32, total_length, buffer);
566       break;
567     case XSTORMY16_OPERAND_RD :
568       errmsg = insert_normal (cd, fields->f_Rd, 0, 0, 12, 4, 32, total_length, buffer);
569       break;
570     case XSTORMY16_OPERAND_RDM :
571       errmsg = insert_normal (cd, fields->f_Rdm, 0, 0, 13, 3, 32, total_length, buffer);
572       break;
573     case XSTORMY16_OPERAND_RM :
574       errmsg = insert_normal (cd, fields->f_Rm, 0, 0, 4, 3, 32, total_length, buffer);
575       break;
576     case XSTORMY16_OPERAND_RS :
577       errmsg = insert_normal (cd, fields->f_Rs, 0, 0, 8, 4, 32, total_length, buffer);
578       break;
579     case XSTORMY16_OPERAND_ABS24 :
580       {
581 {
582   FLD (f_abs24_1) = ((FLD (f_abs24)) & (255));
583   FLD (f_abs24_2) = ((unsigned int) (FLD (f_abs24)) >> (8));
584 }
585         errmsg = insert_normal (cd, fields->f_abs24_1, 0, 0, 8, 8, 32, total_length, buffer);
586         if (errmsg)
587           break;
588         errmsg = insert_normal (cd, fields->f_abs24_2, 0, 0, 16, 16, 32, total_length, buffer);
589         if (errmsg)
590           break;
591       }
592       break;
593     case XSTORMY16_OPERAND_BCOND2 :
594       errmsg = insert_normal (cd, fields->f_op2, 0, 0, 4, 4, 32, total_length, buffer);
595       break;
596     case XSTORMY16_OPERAND_BCOND5 :
597       errmsg = insert_normal (cd, fields->f_op5, 0, 0, 16, 4, 32, total_length, buffer);
598       break;
599     case XSTORMY16_OPERAND_HMEM8 :
600       {
601         long value = fields->f_hmem8;
602         value = ((value) - (32512));
603         errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, buffer);
604       }
605       break;
606     case XSTORMY16_OPERAND_IMM12 :
607       errmsg = insert_normal (cd, fields->f_imm12, 0|(1<<CGEN_IFLD_SIGNED), 0, 20, 12, 32, total_length, buffer);
608       break;
609     case XSTORMY16_OPERAND_IMM16 :
610       errmsg = insert_normal (cd, fields->f_imm16, 0|(1<<CGEN_IFLD_SIGN_OPT), 0, 16, 16, 32, total_length, buffer);
611       break;
612     case XSTORMY16_OPERAND_IMM2 :
613       errmsg = insert_normal (cd, fields->f_imm2, 0, 0, 10, 2, 32, total_length, buffer);
614       break;
615     case XSTORMY16_OPERAND_IMM3 :
616       errmsg = insert_normal (cd, fields->f_imm3, 0, 0, 4, 3, 32, total_length, buffer);
617       break;
618     case XSTORMY16_OPERAND_IMM3B :
619       errmsg = insert_normal (cd, fields->f_imm3b, 0, 0, 17, 3, 32, total_length, buffer);
620       break;
621     case XSTORMY16_OPERAND_IMM4 :
622       errmsg = insert_normal (cd, fields->f_imm4, 0, 0, 8, 4, 32, total_length, buffer);
623       break;
624     case XSTORMY16_OPERAND_IMM8 :
625       errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 8, 8, 32, total_length, buffer);
626       break;
627     case XSTORMY16_OPERAND_IMM8SMALL :
628       errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 8, 8, 32, total_length, buffer);
629       break;
630     case XSTORMY16_OPERAND_LMEM8 :
631       errmsg = insert_normal (cd, fields->f_lmem8, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, buffer);
632       break;
633     case XSTORMY16_OPERAND_REL12 :
634       {
635         long value = fields->f_rel12;
636         value = ((value) - (((pc) + (4))));
637         errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 20, 12, 32, total_length, buffer);
638       }
639       break;
640     case XSTORMY16_OPERAND_REL12A :
641       {
642         long value = fields->f_rel12a;
643         value = ((int) (((value) - (((pc) + (2))))) >> (1));
644         errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 4, 11, 32, total_length, buffer);
645       }
646       break;
647     case XSTORMY16_OPERAND_REL8_2 :
648       {
649         long value = fields->f_rel8_2;
650         value = ((value) - (((pc) + (2))));
651         errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, buffer);
652       }
653       break;
654     case XSTORMY16_OPERAND_REL8_4 :
655       {
656         long value = fields->f_rel8_4;
657         value = ((value) - (((pc) + (4))));
658         errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, buffer);
659       }
660       break;
661     case XSTORMY16_OPERAND_WS2 :
662       errmsg = insert_normal (cd, fields->f_op2m, 0, 0, 7, 1, 32, total_length, buffer);
663       break;
664
665     default :
666       /* xgettext:c-format */
667       fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
668                opindex);
669       abort ();
670   }
671
672   return errmsg;
673 }
674
675 int xstormy16_cgen_extract_operand
676   (CGEN_CPU_DESC, int, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
677
678 /* Main entry point for operand extraction.
679    The result is <= 0 for error, >0 for success.
680    ??? Actual values aren't well defined right now.
681
682    This function is basically just a big switch statement.  Earlier versions
683    used tables to look up the function to use, but
684    - if the table contains both assembler and disassembler functions then
685      the disassembler contains much of the assembler and vice-versa,
686    - there's a lot of inlining possibilities as things grow,
687    - using a switch statement avoids the function call overhead.
688
689    This function could be moved into `print_insn_normal', but keeping it
690    separate makes clear the interface between `print_insn_normal' and each of
691    the handlers.  */
692
693 int
694 xstormy16_cgen_extract_operand (CGEN_CPU_DESC cd,
695                              int opindex,
696                              CGEN_EXTRACT_INFO *ex_info,
697                              CGEN_INSN_INT insn_value,
698                              CGEN_FIELDS * fields,
699                              bfd_vma pc)
700 {
701   /* Assume success (for those operands that are nops).  */
702   int length = 1;
703   unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
704
705   switch (opindex)
706     {
707     case XSTORMY16_OPERAND_RB :
708       length = extract_normal (cd, ex_info, insn_value, 0, 0, 17, 3, 32, total_length, pc, & fields->f_Rb);
709       break;
710     case XSTORMY16_OPERAND_RBJ :
711       length = extract_normal (cd, ex_info, insn_value, 0, 0, 11, 1, 32, total_length, pc, & fields->f_Rbj);
712       break;
713     case XSTORMY16_OPERAND_RD :
714       length = extract_normal (cd, ex_info, insn_value, 0, 0, 12, 4, 32, total_length, pc, & fields->f_Rd);
715       break;
716     case XSTORMY16_OPERAND_RDM :
717       length = extract_normal (cd, ex_info, insn_value, 0, 0, 13, 3, 32, total_length, pc, & fields->f_Rdm);
718       break;
719     case XSTORMY16_OPERAND_RM :
720       length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 3, 32, total_length, pc, & fields->f_Rm);
721       break;
722     case XSTORMY16_OPERAND_RS :
723       length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 32, total_length, pc, & fields->f_Rs);
724       break;
725     case XSTORMY16_OPERAND_ABS24 :
726       {
727         length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 32, total_length, pc, & fields->f_abs24_1);
728         if (length <= 0) break;
729         length = extract_normal (cd, ex_info, insn_value, 0, 0, 16, 16, 32, total_length, pc, & fields->f_abs24_2);
730         if (length <= 0) break;
731   FLD (f_abs24) = ((((FLD (f_abs24_2)) << (8))) | (FLD (f_abs24_1)));
732       }
733       break;
734     case XSTORMY16_OPERAND_BCOND2 :
735       length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 4, 32, total_length, pc, & fields->f_op2);
736       break;
737     case XSTORMY16_OPERAND_BCOND5 :
738       length = extract_normal (cd, ex_info, insn_value, 0, 0, 16, 4, 32, total_length, pc, & fields->f_op5);
739       break;
740     case XSTORMY16_OPERAND_HMEM8 :
741       {
742         long value;
743         length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, pc, & value);
744         value = ((value) + (32512));
745         fields->f_hmem8 = value;
746       }
747       break;
748     case XSTORMY16_OPERAND_IMM12 :
749       length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 20, 12, 32, total_length, pc, & fields->f_imm12);
750       break;
751     case XSTORMY16_OPERAND_IMM16 :
752       length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGN_OPT), 0, 16, 16, 32, total_length, pc, & fields->f_imm16);
753       break;
754     case XSTORMY16_OPERAND_IMM2 :
755       length = extract_normal (cd, ex_info, insn_value, 0, 0, 10, 2, 32, total_length, pc, & fields->f_imm2);
756       break;
757     case XSTORMY16_OPERAND_IMM3 :
758       length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 3, 32, total_length, pc, & fields->f_imm3);
759       break;
760     case XSTORMY16_OPERAND_IMM3B :
761       length = extract_normal (cd, ex_info, insn_value, 0, 0, 17, 3, 32, total_length, pc, & fields->f_imm3b);
762       break;
763     case XSTORMY16_OPERAND_IMM4 :
764       length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 4, 32, total_length, pc, & fields->f_imm4);
765       break;
766     case XSTORMY16_OPERAND_IMM8 :
767       length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 32, total_length, pc, & fields->f_imm8);
768       break;
769     case XSTORMY16_OPERAND_IMM8SMALL :
770       length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 8, 32, total_length, pc, & fields->f_imm8);
771       break;
772     case XSTORMY16_OPERAND_LMEM8 :
773       length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 8, 32, total_length, pc, & fields->f_lmem8);
774       break;
775     case XSTORMY16_OPERAND_REL12 :
776       {
777         long value;
778         length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 20, 12, 32, total_length, pc, & value);
779         value = ((value) + (((pc) + (4))));
780         fields->f_rel12 = value;
781       }
782       break;
783     case XSTORMY16_OPERAND_REL12A :
784       {
785         long value;
786         length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 4, 11, 32, total_length, pc, & value);
787         value = ((((value) << (1))) + (((pc) + (2))));
788         fields->f_rel12a = value;
789       }
790       break;
791     case XSTORMY16_OPERAND_REL8_2 :
792       {
793         long value;
794         length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, pc, & value);
795         value = ((value) + (((pc) + (2))));
796         fields->f_rel8_2 = value;
797       }
798       break;
799     case XSTORMY16_OPERAND_REL8_4 :
800       {
801         long value;
802         length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 8, 32, total_length, pc, & value);
803         value = ((value) + (((pc) + (4))));
804         fields->f_rel8_4 = value;
805       }
806       break;
807     case XSTORMY16_OPERAND_WS2 :
808       length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 1, 32, total_length, pc, & fields->f_op2m);
809       break;
810
811     default :
812       /* xgettext:c-format */
813       fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
814                opindex);
815       abort ();
816     }
817
818   return length;
819 }
820
821 cgen_insert_fn * const xstormy16_cgen_insert_handlers[] = 
822 {
823   insert_insn_normal,
824 };
825
826 cgen_extract_fn * const xstormy16_cgen_extract_handlers[] = 
827 {
828   extract_insn_normal,
829 };
830
831 int xstormy16_cgen_get_int_operand     (CGEN_CPU_DESC, int, const CGEN_FIELDS *);
832 bfd_vma xstormy16_cgen_get_vma_operand (CGEN_CPU_DESC, int, const CGEN_FIELDS *);
833
834 /* Getting values from cgen_fields is handled by a collection of functions.
835    They are distinguished by the type of the VALUE argument they return.
836    TODO: floating point, inlining support, remove cases where result type
837    not appropriate.  */
838
839 int
840 xstormy16_cgen_get_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
841                              int opindex,
842                              const CGEN_FIELDS * fields)
843 {
844   int value;
845
846   switch (opindex)
847     {
848     case XSTORMY16_OPERAND_RB :
849       value = fields->f_Rb;
850       break;
851     case XSTORMY16_OPERAND_RBJ :
852       value = fields->f_Rbj;
853       break;
854     case XSTORMY16_OPERAND_RD :
855       value = fields->f_Rd;
856       break;
857     case XSTORMY16_OPERAND_RDM :
858       value = fields->f_Rdm;
859       break;
860     case XSTORMY16_OPERAND_RM :
861       value = fields->f_Rm;
862       break;
863     case XSTORMY16_OPERAND_RS :
864       value = fields->f_Rs;
865       break;
866     case XSTORMY16_OPERAND_ABS24 :
867       value = fields->f_abs24;
868       break;
869     case XSTORMY16_OPERAND_BCOND2 :
870       value = fields->f_op2;
871       break;
872     case XSTORMY16_OPERAND_BCOND5 :
873       value = fields->f_op5;
874       break;
875     case XSTORMY16_OPERAND_HMEM8 :
876       value = fields->f_hmem8;
877       break;
878     case XSTORMY16_OPERAND_IMM12 :
879       value = fields->f_imm12;
880       break;
881     case XSTORMY16_OPERAND_IMM16 :
882       value = fields->f_imm16;
883       break;
884     case XSTORMY16_OPERAND_IMM2 :
885       value = fields->f_imm2;
886       break;
887     case XSTORMY16_OPERAND_IMM3 :
888       value = fields->f_imm3;
889       break;
890     case XSTORMY16_OPERAND_IMM3B :
891       value = fields->f_imm3b;
892       break;
893     case XSTORMY16_OPERAND_IMM4 :
894       value = fields->f_imm4;
895       break;
896     case XSTORMY16_OPERAND_IMM8 :
897       value = fields->f_imm8;
898       break;
899     case XSTORMY16_OPERAND_IMM8SMALL :
900       value = fields->f_imm8;
901       break;
902     case XSTORMY16_OPERAND_LMEM8 :
903       value = fields->f_lmem8;
904       break;
905     case XSTORMY16_OPERAND_REL12 :
906       value = fields->f_rel12;
907       break;
908     case XSTORMY16_OPERAND_REL12A :
909       value = fields->f_rel12a;
910       break;
911     case XSTORMY16_OPERAND_REL8_2 :
912       value = fields->f_rel8_2;
913       break;
914     case XSTORMY16_OPERAND_REL8_4 :
915       value = fields->f_rel8_4;
916       break;
917     case XSTORMY16_OPERAND_WS2 :
918       value = fields->f_op2m;
919       break;
920
921     default :
922       /* xgettext:c-format */
923       fprintf (stderr, _("Unrecognized field %d while getting int operand.\n"),
924                        opindex);
925       abort ();
926   }
927
928   return value;
929 }
930
931 bfd_vma
932 xstormy16_cgen_get_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
933                              int opindex,
934                              const CGEN_FIELDS * fields)
935 {
936   bfd_vma value;
937
938   switch (opindex)
939     {
940     case XSTORMY16_OPERAND_RB :
941       value = fields->f_Rb;
942       break;
943     case XSTORMY16_OPERAND_RBJ :
944       value = fields->f_Rbj;
945       break;
946     case XSTORMY16_OPERAND_RD :
947       value = fields->f_Rd;
948       break;
949     case XSTORMY16_OPERAND_RDM :
950       value = fields->f_Rdm;
951       break;
952     case XSTORMY16_OPERAND_RM :
953       value = fields->f_Rm;
954       break;
955     case XSTORMY16_OPERAND_RS :
956       value = fields->f_Rs;
957       break;
958     case XSTORMY16_OPERAND_ABS24 :
959       value = fields->f_abs24;
960       break;
961     case XSTORMY16_OPERAND_BCOND2 :
962       value = fields->f_op2;
963       break;
964     case XSTORMY16_OPERAND_BCOND5 :
965       value = fields->f_op5;
966       break;
967     case XSTORMY16_OPERAND_HMEM8 :
968       value = fields->f_hmem8;
969       break;
970     case XSTORMY16_OPERAND_IMM12 :
971       value = fields->f_imm12;
972       break;
973     case XSTORMY16_OPERAND_IMM16 :
974       value = fields->f_imm16;
975       break;
976     case XSTORMY16_OPERAND_IMM2 :
977       value = fields->f_imm2;
978       break;
979     case XSTORMY16_OPERAND_IMM3 :
980       value = fields->f_imm3;
981       break;
982     case XSTORMY16_OPERAND_IMM3B :
983       value = fields->f_imm3b;
984       break;
985     case XSTORMY16_OPERAND_IMM4 :
986       value = fields->f_imm4;
987       break;
988     case XSTORMY16_OPERAND_IMM8 :
989       value = fields->f_imm8;
990       break;
991     case XSTORMY16_OPERAND_IMM8SMALL :
992       value = fields->f_imm8;
993       break;
994     case XSTORMY16_OPERAND_LMEM8 :
995       value = fields->f_lmem8;
996       break;
997     case XSTORMY16_OPERAND_REL12 :
998       value = fields->f_rel12;
999       break;
1000     case XSTORMY16_OPERAND_REL12A :
1001       value = fields->f_rel12a;
1002       break;
1003     case XSTORMY16_OPERAND_REL8_2 :
1004       value = fields->f_rel8_2;
1005       break;
1006     case XSTORMY16_OPERAND_REL8_4 :
1007       value = fields->f_rel8_4;
1008       break;
1009     case XSTORMY16_OPERAND_WS2 :
1010       value = fields->f_op2m;
1011       break;
1012
1013     default :
1014       /* xgettext:c-format */
1015       fprintf (stderr, _("Unrecognized field %d while getting vma operand.\n"),
1016                        opindex);
1017       abort ();
1018   }
1019
1020   return value;
1021 }
1022
1023 void xstormy16_cgen_set_int_operand  (CGEN_CPU_DESC, int, CGEN_FIELDS *, int);
1024 void xstormy16_cgen_set_vma_operand  (CGEN_CPU_DESC, int, CGEN_FIELDS *, bfd_vma);
1025
1026 /* Stuffing values in cgen_fields is handled by a collection of functions.
1027    They are distinguished by the type of the VALUE argument they accept.
1028    TODO: floating point, inlining support, remove cases where argument type
1029    not appropriate.  */
1030
1031 void
1032 xstormy16_cgen_set_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1033                              int opindex,
1034                              CGEN_FIELDS * fields,
1035                              int value)
1036 {
1037   switch (opindex)
1038     {
1039     case XSTORMY16_OPERAND_RB :
1040       fields->f_Rb = value;
1041       break;
1042     case XSTORMY16_OPERAND_RBJ :
1043       fields->f_Rbj = value;
1044       break;
1045     case XSTORMY16_OPERAND_RD :
1046       fields->f_Rd = value;
1047       break;
1048     case XSTORMY16_OPERAND_RDM :
1049       fields->f_Rdm = value;
1050       break;
1051     case XSTORMY16_OPERAND_RM :
1052       fields->f_Rm = value;
1053       break;
1054     case XSTORMY16_OPERAND_RS :
1055       fields->f_Rs = value;
1056       break;
1057     case XSTORMY16_OPERAND_ABS24 :
1058       fields->f_abs24 = value;
1059       break;
1060     case XSTORMY16_OPERAND_BCOND2 :
1061       fields->f_op2 = value;
1062       break;
1063     case XSTORMY16_OPERAND_BCOND5 :
1064       fields->f_op5 = value;
1065       break;
1066     case XSTORMY16_OPERAND_HMEM8 :
1067       fields->f_hmem8 = value;
1068       break;
1069     case XSTORMY16_OPERAND_IMM12 :
1070       fields->f_imm12 = value;
1071       break;
1072     case XSTORMY16_OPERAND_IMM16 :
1073       fields->f_imm16 = value;
1074       break;
1075     case XSTORMY16_OPERAND_IMM2 :
1076       fields->f_imm2 = value;
1077       break;
1078     case XSTORMY16_OPERAND_IMM3 :
1079       fields->f_imm3 = value;
1080       break;
1081     case XSTORMY16_OPERAND_IMM3B :
1082       fields->f_imm3b = value;
1083       break;
1084     case XSTORMY16_OPERAND_IMM4 :
1085       fields->f_imm4 = value;
1086       break;
1087     case XSTORMY16_OPERAND_IMM8 :
1088       fields->f_imm8 = value;
1089       break;
1090     case XSTORMY16_OPERAND_IMM8SMALL :
1091       fields->f_imm8 = value;
1092       break;
1093     case XSTORMY16_OPERAND_LMEM8 :
1094       fields->f_lmem8 = value;
1095       break;
1096     case XSTORMY16_OPERAND_REL12 :
1097       fields->f_rel12 = value;
1098       break;
1099     case XSTORMY16_OPERAND_REL12A :
1100       fields->f_rel12a = value;
1101       break;
1102     case XSTORMY16_OPERAND_REL8_2 :
1103       fields->f_rel8_2 = value;
1104       break;
1105     case XSTORMY16_OPERAND_REL8_4 :
1106       fields->f_rel8_4 = value;
1107       break;
1108     case XSTORMY16_OPERAND_WS2 :
1109       fields->f_op2m = value;
1110       break;
1111
1112     default :
1113       /* xgettext:c-format */
1114       fprintf (stderr, _("Unrecognized field %d while setting int operand.\n"),
1115                        opindex);
1116       abort ();
1117   }
1118 }
1119
1120 void
1121 xstormy16_cgen_set_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
1122                              int opindex,
1123                              CGEN_FIELDS * fields,
1124                              bfd_vma value)
1125 {
1126   switch (opindex)
1127     {
1128     case XSTORMY16_OPERAND_RB :
1129       fields->f_Rb = value;
1130       break;
1131     case XSTORMY16_OPERAND_RBJ :
1132       fields->f_Rbj = value;
1133       break;
1134     case XSTORMY16_OPERAND_RD :
1135       fields->f_Rd = value;
1136       break;
1137     case XSTORMY16_OPERAND_RDM :
1138       fields->f_Rdm = value;
1139       break;
1140     case XSTORMY16_OPERAND_RM :
1141       fields->f_Rm = value;
1142       break;
1143     case XSTORMY16_OPERAND_RS :
1144       fields->f_Rs = value;
1145       break;
1146     case XSTORMY16_OPERAND_ABS24 :
1147       fields->f_abs24 = value;
1148       break;
1149     case XSTORMY16_OPERAND_BCOND2 :
1150       fields->f_op2 = value;
1151       break;
1152     case XSTORMY16_OPERAND_BCOND5 :
1153       fields->f_op5 = value;
1154       break;
1155     case XSTORMY16_OPERAND_HMEM8 :
1156       fields->f_hmem8 = value;
1157       break;
1158     case XSTORMY16_OPERAND_IMM12 :
1159       fields->f_imm12 = value;
1160       break;
1161     case XSTORMY16_OPERAND_IMM16 :
1162       fields->f_imm16 = value;
1163       break;
1164     case XSTORMY16_OPERAND_IMM2 :
1165       fields->f_imm2 = value;
1166       break;
1167     case XSTORMY16_OPERAND_IMM3 :
1168       fields->f_imm3 = value;
1169       break;
1170     case XSTORMY16_OPERAND_IMM3B :
1171       fields->f_imm3b = value;
1172       break;
1173     case XSTORMY16_OPERAND_IMM4 :
1174       fields->f_imm4 = value;
1175       break;
1176     case XSTORMY16_OPERAND_IMM8 :
1177       fields->f_imm8 = value;
1178       break;
1179     case XSTORMY16_OPERAND_IMM8SMALL :
1180       fields->f_imm8 = value;
1181       break;
1182     case XSTORMY16_OPERAND_LMEM8 :
1183       fields->f_lmem8 = value;
1184       break;
1185     case XSTORMY16_OPERAND_REL12 :
1186       fields->f_rel12 = value;
1187       break;
1188     case XSTORMY16_OPERAND_REL12A :
1189       fields->f_rel12a = value;
1190       break;
1191     case XSTORMY16_OPERAND_REL8_2 :
1192       fields->f_rel8_2 = value;
1193       break;
1194     case XSTORMY16_OPERAND_REL8_4 :
1195       fields->f_rel8_4 = value;
1196       break;
1197     case XSTORMY16_OPERAND_WS2 :
1198       fields->f_op2m = value;
1199       break;
1200
1201     default :
1202       /* xgettext:c-format */
1203       fprintf (stderr, _("Unrecognized field %d while setting vma operand.\n"),
1204                        opindex);
1205       abort ();
1206   }
1207 }
1208
1209 /* Function to call before using the instruction builder tables.  */
1210
1211 void
1212 xstormy16_cgen_init_ibld_table (CGEN_CPU_DESC cd)
1213 {
1214   cd->insert_handlers = & xstormy16_cgen_insert_handlers[0];
1215   cd->extract_handlers = & xstormy16_cgen_extract_handlers[0];
1216
1217   cd->insert_operand = xstormy16_cgen_insert_operand;
1218   cd->extract_operand = xstormy16_cgen_extract_operand;
1219
1220   cd->get_int_operand = xstormy16_cgen_get_int_operand;
1221   cd->set_int_operand = xstormy16_cgen_set_int_operand;
1222   cd->get_vma_operand = xstormy16_cgen_get_vma_operand;
1223   cd->set_vma_operand = xstormy16_cgen_set_vma_operand;
1224 }