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