OSDN Git Service

cb29a266068052222d2a5fca850df0efbf00b5f6
[pf3gnuchains/pf3gnuchains3x.git] / opcodes / openrisc-ibld.c
1 /* Instruction building/extraction support for openrisc. -*- 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 Free Software Foundation, Inc.
7
8 This file is part of the GNU Binutils and GDB, the GNU debugger.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software Foundation, Inc.,
22 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
23
24 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
25    Keep that in mind.  */
26
27 #include "sysdep.h"
28 #include <ctype.h>
29 #include <stdio.h>
30 #include "ansidecl.h"
31 #include "dis-asm.h"
32 #include "bfd.h"
33 #include "symcat.h"
34 #include "openrisc-desc.h"
35 #include "openrisc-opc.h"
36 #include "opintl.h"
37
38 #undef min
39 #define min(a,b) ((a) < (b) ? (a) : (b))
40 #undef max
41 #define max(a,b) ((a) > (b) ? (a) : (b))
42
43 /* Used by the ifield rtx function.  */
44 #define FLD(f) (fields->f)
45
46 static const char * insert_normal
47      PARAMS ((CGEN_CPU_DESC, long, unsigned int, unsigned int, unsigned int,
48               unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR));
49 static const char * insert_insn_normal
50      PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *,
51               CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma));
52 static int extract_normal
53      PARAMS ((CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
54               unsigned int, unsigned int, unsigned int, unsigned int,
55               unsigned int, unsigned int, bfd_vma, long *));
56 static int extract_insn_normal
57      PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
58               CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma));
59 #if CGEN_INT_INSN_P
60 static void put_insn_int_value
61      PARAMS ((CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT));
62 #endif
63 #if ! CGEN_INT_INSN_P
64 static CGEN_INLINE void insert_1
65      PARAMS ((CGEN_CPU_DESC, unsigned long, int, int, int, unsigned char *));
66 static CGEN_INLINE int fill_cache
67      PARAMS ((CGEN_CPU_DESC, CGEN_EXTRACT_INFO *,  int, int, bfd_vma));
68 static CGEN_INLINE long extract_1
69      PARAMS ((CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, int,
70               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 (cd, value, start, length, word_length, bufp)
81      CGEN_CPU_DESC cd;
82      unsigned long value;
83      int start,length,word_length;
84      unsigned char *bufp;
85 {
86   unsigned long x,mask;
87   int shift;
88
89   x = cgen_get_insn_value (cd, bufp, word_length);
90
91   /* Written this way to avoid undefined behaviour.  */
92   mask = (((1L << (length - 1)) - 1) << 1) | 1;
93   if (CGEN_INSN_LSB0_P)
94     shift = (start + 1) - length;
95   else
96     shift = (word_length - (start + length));
97   x = (x & ~(mask << shift)) | ((value & mask) << shift);
98
99   cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
100 }
101
102 #endif /* ! CGEN_INT_INSN_P */
103
104 /* Default insertion routine.
105
106    ATTRS is a mask of the boolean attributes.
107    WORD_OFFSET is the offset in bits from the start of the insn of the value.
108    WORD_LENGTH is the length of the word in bits in which the value resides.
109    START is the starting bit number in the word, architecture origin.
110    LENGTH is the length of VALUE in bits.
111    TOTAL_LENGTH is the total length of the insn in bits.
112
113    The result is an error message or NULL if success.  */
114
115 /* ??? This duplicates functionality with bfd's howto table and
116    bfd_install_relocation.  */
117 /* ??? This doesn't handle bfd_vma's.  Create another function when
118    necessary.  */
119
120 static const char *
121 insert_normal (cd, value, attrs, word_offset, start, length, word_length,
122                total_length, buffer)
123      CGEN_CPU_DESC cd;
124      long value;
125      unsigned int attrs;
126      unsigned int word_offset, start, length, word_length, total_length;
127      CGEN_INSN_BYTES_PTR buffer;
128 {
129   static char errbuf[100];
130   /* Written this way to avoid undefined behaviour.  */
131   unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
132
133   /* If LENGTH is zero, this operand doesn't contribute to the value.  */
134   if (length == 0)
135     return NULL;
136
137 #if 0
138   if (CGEN_INT_INSN_P
139       && word_offset != 0)
140     abort ();
141 #endif
142
143   if (word_length > 32)
144     abort ();
145
146   /* For architectures with insns smaller than the base-insn-bitsize,
147      word_length may be too big.  */
148   if (cd->min_insn_bitsize < cd->base_insn_bitsize)
149     {
150       if (word_offset == 0
151           && word_length > total_length)
152         word_length = total_length;
153     }
154
155   /* Ensure VALUE will fit.  */
156   if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
157     {
158       long minval = - (1L << (length - 1));
159       unsigned long maxval = mask;
160       
161       if ((value > 0 && (unsigned long) value > maxval)
162           || value < minval)
163         {
164           /* xgettext:c-format */
165           sprintf (errbuf,
166                    _("operand out of range (%ld not between %ld and %lu)"),
167                    value, minval, maxval);
168           return errbuf;
169         }
170     }
171   else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
172     {
173       unsigned long maxval = mask;
174       
175       if ((unsigned long) value > maxval)
176         {
177           /* xgettext:c-format */
178           sprintf (errbuf,
179                    _("operand out of range (%lu not between 0 and %lu)"),
180                    value, maxval);
181           return errbuf;
182         }
183     }
184   else
185     {
186       if (! cgen_signed_overflow_ok_p (cd))
187         {
188           long minval = - (1L << (length - 1));
189           long maxval =   (1L << (length - 1)) - 1;
190           
191           if (value < minval || value > maxval)
192             {
193               sprintf
194                 /* xgettext:c-format */
195                 (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
196                  value, minval, maxval);
197               return errbuf;
198             }
199         }
200     }
201
202 #if CGEN_INT_INSN_P
203
204   {
205     int shift;
206
207     if (CGEN_INSN_LSB0_P)
208       shift = (word_offset + start + 1) - length;
209     else
210       shift = total_length - (word_offset + start + length);
211     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
212   }
213
214 #else /* ! CGEN_INT_INSN_P */
215
216   {
217     unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
218
219     insert_1 (cd, value, start, length, word_length, bufp);
220   }
221
222 #endif /* ! CGEN_INT_INSN_P */
223
224   return NULL;
225 }
226
227 /* Default insn builder (insert handler).
228    The instruction is recorded in CGEN_INT_INSN_P byte order (meaning
229    that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is
230    recorded in host byte order, otherwise BUFFER is an array of bytes
231    and the value is recorded in target byte order).
232    The result is an error message or NULL if success.  */
233
234 static const char *
235 insert_insn_normal (cd, insn, fields, buffer, pc)
236      CGEN_CPU_DESC cd;
237      const CGEN_INSN * insn;
238      CGEN_FIELDS * fields;
239      CGEN_INSN_BYTES_PTR buffer;
240      bfd_vma pc;
241 {
242   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
243   unsigned long value;
244   const CGEN_SYNTAX_CHAR_TYPE * syn;
245
246   CGEN_INIT_INSERT (cd);
247   value = CGEN_INSN_BASE_VALUE (insn);
248
249   /* If we're recording insns as numbers (rather than a string of bytes),
250      target byte order handling is deferred until later.  */
251
252 #if CGEN_INT_INSN_P
253
254   put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
255                       CGEN_FIELDS_BITSIZE (fields), value);
256
257 #else
258
259   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
260                                         (unsigned) CGEN_FIELDS_BITSIZE (fields)),
261                        value);
262
263 #endif /* ! CGEN_INT_INSN_P */
264
265   /* ??? It would be better to scan the format's fields.
266      Still need to be able to insert a value based on the operand though;
267      e.g. storing a branch displacement that got resolved later.
268      Needs more thought first.  */
269
270   for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn)
271     {
272       const char *errmsg;
273
274       if (CGEN_SYNTAX_CHAR_P (* syn))
275         continue;
276
277       errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
278                                        fields, buffer, pc);
279       if (errmsg)
280         return errmsg;
281     }
282
283   return NULL;
284 }
285
286 #if CGEN_INT_INSN_P
287 /* Cover function to store an insn value into an integral insn.  Must go here
288  because it needs <prefix>-desc.h for CGEN_INT_INSN_P.  */
289
290 static void
291 put_insn_int_value (cd, buf, length, insn_length, value)
292      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
293      CGEN_INSN_BYTES_PTR buf;
294      int length;
295      int insn_length;
296      CGEN_INSN_INT value;
297 {
298   /* For architectures with insns smaller than the base-insn-bitsize,
299      length may be too big.  */
300   if (length > insn_length)
301     *buf = value;
302   else
303     {
304       int shift = insn_length - length;
305       /* Written this way to avoid undefined behaviour.  */
306       CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
307       *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
308     }
309 }
310 #endif
311 \f
312 /* Operand extraction.  */
313
314 #if ! CGEN_INT_INSN_P
315
316 /* Subroutine of extract_normal.
317    Ensure sufficient bytes are cached in EX_INFO.
318    OFFSET is the offset in bytes from the start of the insn of the value.
319    BYTES is the length of the needed value.
320    Returns 1 for success, 0 for failure.  */
321
322 static CGEN_INLINE int
323 fill_cache (cd, ex_info, offset, bytes, pc)
324      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
325      CGEN_EXTRACT_INFO *ex_info;
326      int offset, bytes;
327      bfd_vma pc;
328 {
329   /* It's doubtful that the middle part has already been fetched so
330      we don't optimize that case.  kiss.  */
331   unsigned int mask;
332   disassemble_info *info = (disassemble_info *) ex_info->dis_info;
333
334   /* First do a quick check.  */
335   mask = (1 << bytes) - 1;
336   if (((ex_info->valid >> offset) & mask) == mask)
337     return 1;
338
339   /* Search for the first byte we need to read.  */
340   for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
341     if (! (mask & ex_info->valid))
342       break;
343
344   if (bytes)
345     {
346       int status;
347
348       pc += offset;
349       status = (*info->read_memory_func)
350         (pc, ex_info->insn_bytes + offset, bytes, info);
351
352       if (status != 0)
353         {
354           (*info->memory_error_func) (status, pc, info);
355           return 0;
356         }
357
358       ex_info->valid |= ((1 << bytes) - 1) << offset;
359     }
360
361   return 1;
362 }
363
364 /* Subroutine of extract_normal.  */
365
366 static CGEN_INLINE long
367 extract_1 (cd, ex_info, start, length, word_length, bufp, pc)
368      CGEN_CPU_DESC cd;
369      CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED;
370      int start,length,word_length;
371      unsigned char *bufp;
372      bfd_vma pc ATTRIBUTE_UNUSED;
373 {
374   unsigned long x;
375   int shift;
376 #if 0
377   int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
378
379   x = cgen_get_insn_value (cd, bufp, word_length);
380 #endif
381   if (CGEN_INSN_LSB0_P)
382     shift = (start + 1) - length;
383   else
384     shift = (word_length - (start + length));
385   return x >> shift;
386 }
387
388 #endif /* ! CGEN_INT_INSN_P */
389
390 /* Default extraction routine.
391
392    INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
393    or sometimes less for cases like the m32r where the base insn size is 32
394    but some insns are 16 bits.
395    ATTRS is a mask of the boolean attributes.  We only need `SIGNED',
396    but for generality we take a bitmask of all of them.
397    WORD_OFFSET is the offset in bits from the start of the insn of the value.
398    WORD_LENGTH is the length of the word in bits in which the value resides.
399    START is the starting bit number in the word, architecture origin.
400    LENGTH is the length of VALUE in bits.
401    TOTAL_LENGTH is the total length of the insn in bits.
402
403    Returns 1 for success, 0 for failure.  */
404
405 /* ??? The return code isn't properly used.  wip.  */
406
407 /* ??? This doesn't handle bfd_vma's.  Create another function when
408    necessary.  */
409
410 static int
411 extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length,
412                 word_length, total_length, pc, valuep)
413      CGEN_CPU_DESC cd;
414 #if ! CGEN_INT_INSN_P
415      CGEN_EXTRACT_INFO *ex_info;
416 #else
417      CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED;
418 #endif
419      CGEN_INSN_INT insn_value;
420      unsigned int attrs;
421      unsigned int word_offset, start, length, word_length, total_length;
422 #if ! CGEN_INT_INSN_P
423      bfd_vma pc;
424 #else
425      bfd_vma pc ATTRIBUTE_UNUSED;
426 #endif
427      long *valuep;
428 {
429   long value, mask;
430
431   /* If LENGTH is zero, this operand doesn't contribute to the value
432      so give it a standard value of zero.  */
433   if (length == 0)
434     {
435       *valuep = 0;
436       return 1;
437     }
438
439 #if 0
440   if (CGEN_INT_INSN_P
441       && word_offset != 0)
442     abort ();
443 #endif
444
445   if (word_length > 32)
446     abort ();
447
448   /* For architectures with insns smaller than the insn-base-bitsize,
449      word_length may be too big.  */
450   if (cd->min_insn_bitsize < cd->base_insn_bitsize)
451     {
452       if (word_offset == 0
453           && word_length > total_length)
454         word_length = total_length;
455     }
456
457   /* Does the value reside in INSN_VALUE, and at the right alignment?  */
458
459   if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
460     {
461       if (CGEN_INSN_LSB0_P)
462         value = insn_value >> ((word_offset + start + 1) - length);
463       else
464         value = insn_value >> (total_length - ( word_offset + start + length));
465     }
466
467 #if ! CGEN_INT_INSN_P
468
469   else
470     {
471       unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
472
473       if (word_length > 32)
474         abort ();
475
476       if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
477         return 0;
478
479       value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
480     }
481
482 #endif /* ! CGEN_INT_INSN_P */
483
484   /* Written this way to avoid undefined behaviour.  */
485   mask = (((1L << (length - 1)) - 1) << 1) | 1;
486
487   value &= mask;
488   /* sign extend? */
489   if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
490       && (value & (1L << (length - 1))))
491     value |= ~mask;
492
493   *valuep = value;
494
495   return 1;
496 }
497
498 /* Default insn extractor.
499
500    INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
501    The extracted fields are stored in FIELDS.
502    EX_INFO is used to handle reading variable length insns.
503    Return the length of the insn in bits, or 0 if no match,
504    or -1 if an error occurs fetching data (memory_error_func will have
505    been called).  */
506
507 static int
508 extract_insn_normal (cd, insn, ex_info, insn_value, fields, pc)
509      CGEN_CPU_DESC cd;
510      const CGEN_INSN *insn;
511      CGEN_EXTRACT_INFO *ex_info;
512      CGEN_INSN_INT insn_value;
513      CGEN_FIELDS *fields;
514      bfd_vma pc;
515 {
516   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
517   const CGEN_SYNTAX_CHAR_TYPE *syn;
518
519   CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
520
521   CGEN_INIT_EXTRACT (cd);
522
523   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
524     {
525       int length;
526
527       if (CGEN_SYNTAX_CHAR_P (*syn))
528         continue;
529
530       length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
531                                         ex_info, insn_value, fields, pc);
532       if (length <= 0)
533         return length;
534     }
535
536   /* We recognized and successfully extracted this insn.  */
537   return CGEN_INSN_BITSIZE (insn);
538 }
539 \f
540 /* machine generated code added here */
541
542 const char * openrisc_cgen_insert_operand
543   PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma));
544
545 /* Main entry point for operand insertion.
546
547    This function is basically just a big switch statement.  Earlier versions
548    used tables to look up the function to use, but
549    - if the table contains both assembler and disassembler functions then
550      the disassembler contains much of the assembler and vice-versa,
551    - there's a lot of inlining possibilities as things grow,
552    - using a switch statement avoids the function call overhead.
553
554    This function could be moved into `parse_insn_normal', but keeping it
555    separate makes clear the interface between `parse_insn_normal' and each of
556    the handlers.  It's also needed by GAS to insert operands that couldn't be
557    resolved during parsing.
558 */
559
560 const char *
561 openrisc_cgen_insert_operand (cd, opindex, fields, buffer, pc)
562      CGEN_CPU_DESC cd;
563      int opindex;
564      CGEN_FIELDS * fields;
565      CGEN_INSN_BYTES_PTR buffer;
566      bfd_vma pc ATTRIBUTE_UNUSED;
567 {
568   const char * errmsg = NULL;
569   unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
570
571   switch (opindex)
572     {
573     case OPENRISC_OPERAND_ABS_26 :
574       {
575         long value = fields->f_abs26;
576         value = ((unsigned int) (pc) >> (2));
577         errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_ABS_ADDR), 0, 25, 26, 32, total_length, buffer);
578       }
579       break;
580     case OPENRISC_OPERAND_DISP_26 :
581       {
582         long value = fields->f_disp26;
583         value = ((int) (((value) - (pc))) >> (2));
584         errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 25, 26, 32, total_length, buffer);
585       }
586       break;
587     case OPENRISC_OPERAND_HI16 :
588       errmsg = insert_normal (cd, fields->f_simm16, 0|(1<<CGEN_IFLD_SIGNED), 0, 15, 16, 32, total_length, buffer);
589       break;
590     case OPENRISC_OPERAND_LO16 :
591       errmsg = insert_normal (cd, fields->f_lo16, 0|(1<<CGEN_IFLD_SIGNED), 0, 15, 16, 32, total_length, buffer);
592       break;
593     case OPENRISC_OPERAND_OP_F_23 :
594       errmsg = insert_normal (cd, fields->f_op4, 0, 0, 23, 3, 32, total_length, buffer);
595       break;
596     case OPENRISC_OPERAND_OP_F_3 :
597       errmsg = insert_normal (cd, fields->f_op5, 0, 0, 25, 5, 32, total_length, buffer);
598       break;
599     case OPENRISC_OPERAND_RA :
600       errmsg = insert_normal (cd, fields->f_r2, 0, 0, 20, 5, 32, total_length, buffer);
601       break;
602     case OPENRISC_OPERAND_RB :
603       errmsg = insert_normal (cd, fields->f_r3, 0, 0, 15, 5, 32, total_length, buffer);
604       break;
605     case OPENRISC_OPERAND_RD :
606       errmsg = insert_normal (cd, fields->f_r1, 0, 0, 25, 5, 32, total_length, buffer);
607       break;
608     case OPENRISC_OPERAND_SIMM_16 :
609       errmsg = insert_normal (cd, fields->f_simm16, 0|(1<<CGEN_IFLD_SIGNED), 0, 15, 16, 32, total_length, buffer);
610       break;
611     case OPENRISC_OPERAND_UI16NC :
612       {
613 {
614   FLD (f_i16_2) = ((((unsigned int) (FLD (f_i16nc)) >> (11))) & (31));
615   FLD (f_i16_1) = ((FLD (f_i16nc)) & (2047));
616 }
617         errmsg = insert_normal (cd, fields->f_i16_1, 0, 0, 10, 11, 32, total_length, buffer);
618         if (errmsg)
619           break;
620         errmsg = insert_normal (cd, fields->f_i16_2, 0, 0, 25, 5, 32, total_length, buffer);
621         if (errmsg)
622           break;
623       }
624       break;
625     case OPENRISC_OPERAND_UIMM_16 :
626       errmsg = insert_normal (cd, fields->f_uimm16, 0, 0, 15, 16, 32, total_length, buffer);
627       break;
628     case OPENRISC_OPERAND_UIMM_5 :
629       errmsg = insert_normal (cd, fields->f_uimm5, 0, 0, 4, 5, 32, total_length, buffer);
630       break;
631
632     default :
633       /* xgettext:c-format */
634       fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
635                opindex);
636       abort ();
637   }
638
639   return errmsg;
640 }
641
642 int openrisc_cgen_extract_operand
643   PARAMS ((CGEN_CPU_DESC, int, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
644            CGEN_FIELDS *, bfd_vma));
645
646 /* Main entry point for operand extraction.
647    The result is <= 0 for error, >0 for success.
648    ??? Actual values aren't well defined right now.
649
650    This function is basically just a big switch statement.  Earlier versions
651    used tables to look up the function to use, but
652    - if the table contains both assembler and disassembler functions then
653      the disassembler contains much of the assembler and vice-versa,
654    - there's a lot of inlining possibilities as things grow,
655    - using a switch statement avoids the function call overhead.
656
657    This function could be moved into `print_insn_normal', but keeping it
658    separate makes clear the interface between `print_insn_normal' and each of
659    the handlers.
660 */
661
662 int
663 openrisc_cgen_extract_operand (cd, opindex, ex_info, insn_value, fields, pc)
664      CGEN_CPU_DESC cd;
665      int opindex;
666      CGEN_EXTRACT_INFO *ex_info;
667      CGEN_INSN_INT insn_value;
668      CGEN_FIELDS * fields;
669      bfd_vma pc;
670 {
671   /* Assume success (for those operands that are nops).  */
672   int length = 1;
673   unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
674
675   switch (opindex)
676     {
677     case OPENRISC_OPERAND_ABS_26 :
678       {
679         long value;
680         length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_ABS_ADDR), 0, 25, 26, 32, total_length, pc, & value);
681         value = ((value) << (2));
682         fields->f_abs26 = value;
683       }
684       break;
685     case OPENRISC_OPERAND_DISP_26 :
686       {
687         long value;
688         length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 25, 26, 32, total_length, pc, & value);
689         value = ((((value) << (2))) + (pc));
690         fields->f_disp26 = value;
691       }
692       break;
693     case OPENRISC_OPERAND_HI16 :
694       length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 15, 16, 32, total_length, pc, & fields->f_simm16);
695       break;
696     case OPENRISC_OPERAND_LO16 :
697       length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 15, 16, 32, total_length, pc, & fields->f_lo16);
698       break;
699     case OPENRISC_OPERAND_OP_F_23 :
700       length = extract_normal (cd, ex_info, insn_value, 0, 0, 23, 3, 32, total_length, pc, & fields->f_op4);
701       break;
702     case OPENRISC_OPERAND_OP_F_3 :
703       length = extract_normal (cd, ex_info, insn_value, 0, 0, 25, 5, 32, total_length, pc, & fields->f_op5);
704       break;
705     case OPENRISC_OPERAND_RA :
706       length = extract_normal (cd, ex_info, insn_value, 0, 0, 20, 5, 32, total_length, pc, & fields->f_r2);
707       break;
708     case OPENRISC_OPERAND_RB :
709       length = extract_normal (cd, ex_info, insn_value, 0, 0, 15, 5, 32, total_length, pc, & fields->f_r3);
710       break;
711     case OPENRISC_OPERAND_RD :
712       length = extract_normal (cd, ex_info, insn_value, 0, 0, 25, 5, 32, total_length, pc, & fields->f_r1);
713       break;
714     case OPENRISC_OPERAND_SIMM_16 :
715       length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 15, 16, 32, total_length, pc, & fields->f_simm16);
716       break;
717     case OPENRISC_OPERAND_UI16NC :
718       {
719         length = extract_normal (cd, ex_info, insn_value, 0, 0, 10, 11, 32, total_length, pc, & fields->f_i16_1);
720         if (length <= 0) break;
721         length = extract_normal (cd, ex_info, insn_value, 0, 0, 25, 5, 32, total_length, pc, & fields->f_i16_2);
722         if (length <= 0) break;
723 {
724   FLD (f_i16nc) = openrisc_sign_extend_16bit (((((FLD (f_i16_2)) << (11))) | (FLD (f_i16_1))));
725 }
726       }
727       break;
728     case OPENRISC_OPERAND_UIMM_16 :
729       length = extract_normal (cd, ex_info, insn_value, 0, 0, 15, 16, 32, total_length, pc, & fields->f_uimm16);
730       break;
731     case OPENRISC_OPERAND_UIMM_5 :
732       length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 5, 32, total_length, pc, & fields->f_uimm5);
733       break;
734
735     default :
736       /* xgettext:c-format */
737       fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
738                opindex);
739       abort ();
740     }
741
742   return length;
743 }
744
745 cgen_insert_fn * const openrisc_cgen_insert_handlers[] = 
746 {
747   insert_insn_normal,
748 };
749
750 cgen_extract_fn * const openrisc_cgen_extract_handlers[] = 
751 {
752   extract_insn_normal,
753 };
754
755 int openrisc_cgen_get_int_operand
756   PARAMS ((CGEN_CPU_DESC, int, const CGEN_FIELDS *));
757 bfd_vma openrisc_cgen_get_vma_operand
758   PARAMS ((CGEN_CPU_DESC, int, const CGEN_FIELDS *));
759
760 /* Getting values from cgen_fields is handled by a collection of functions.
761    They are distinguished by the type of the VALUE argument they return.
762    TODO: floating point, inlining support, remove cases where result type
763    not appropriate.  */
764
765 int
766 openrisc_cgen_get_int_operand (cd, opindex, fields)
767      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
768      int opindex;
769      const CGEN_FIELDS * fields;
770 {
771   int value;
772
773   switch (opindex)
774     {
775     case OPENRISC_OPERAND_ABS_26 :
776       value = fields->f_abs26;
777       break;
778     case OPENRISC_OPERAND_DISP_26 :
779       value = fields->f_disp26;
780       break;
781     case OPENRISC_OPERAND_HI16 :
782       value = fields->f_simm16;
783       break;
784     case OPENRISC_OPERAND_LO16 :
785       value = fields->f_lo16;
786       break;
787     case OPENRISC_OPERAND_OP_F_23 :
788       value = fields->f_op4;
789       break;
790     case OPENRISC_OPERAND_OP_F_3 :
791       value = fields->f_op5;
792       break;
793     case OPENRISC_OPERAND_RA :
794       value = fields->f_r2;
795       break;
796     case OPENRISC_OPERAND_RB :
797       value = fields->f_r3;
798       break;
799     case OPENRISC_OPERAND_RD :
800       value = fields->f_r1;
801       break;
802     case OPENRISC_OPERAND_SIMM_16 :
803       value = fields->f_simm16;
804       break;
805     case OPENRISC_OPERAND_UI16NC :
806       value = fields->f_i16nc;
807       break;
808     case OPENRISC_OPERAND_UIMM_16 :
809       value = fields->f_uimm16;
810       break;
811     case OPENRISC_OPERAND_UIMM_5 :
812       value = fields->f_uimm5;
813       break;
814
815     default :
816       /* xgettext:c-format */
817       fprintf (stderr, _("Unrecognized field %d while getting int operand.\n"),
818                        opindex);
819       abort ();
820   }
821
822   return value;
823 }
824
825 bfd_vma
826 openrisc_cgen_get_vma_operand (cd, opindex, fields)
827      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
828      int opindex;
829      const CGEN_FIELDS * fields;
830 {
831   bfd_vma value;
832
833   switch (opindex)
834     {
835     case OPENRISC_OPERAND_ABS_26 :
836       value = fields->f_abs26;
837       break;
838     case OPENRISC_OPERAND_DISP_26 :
839       value = fields->f_disp26;
840       break;
841     case OPENRISC_OPERAND_HI16 :
842       value = fields->f_simm16;
843       break;
844     case OPENRISC_OPERAND_LO16 :
845       value = fields->f_lo16;
846       break;
847     case OPENRISC_OPERAND_OP_F_23 :
848       value = fields->f_op4;
849       break;
850     case OPENRISC_OPERAND_OP_F_3 :
851       value = fields->f_op5;
852       break;
853     case OPENRISC_OPERAND_RA :
854       value = fields->f_r2;
855       break;
856     case OPENRISC_OPERAND_RB :
857       value = fields->f_r3;
858       break;
859     case OPENRISC_OPERAND_RD :
860       value = fields->f_r1;
861       break;
862     case OPENRISC_OPERAND_SIMM_16 :
863       value = fields->f_simm16;
864       break;
865     case OPENRISC_OPERAND_UI16NC :
866       value = fields->f_i16nc;
867       break;
868     case OPENRISC_OPERAND_UIMM_16 :
869       value = fields->f_uimm16;
870       break;
871     case OPENRISC_OPERAND_UIMM_5 :
872       value = fields->f_uimm5;
873       break;
874
875     default :
876       /* xgettext:c-format */
877       fprintf (stderr, _("Unrecognized field %d while getting vma operand.\n"),
878                        opindex);
879       abort ();
880   }
881
882   return value;
883 }
884
885 void openrisc_cgen_set_int_operand
886   PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, int));
887 void openrisc_cgen_set_vma_operand
888   PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, bfd_vma));
889
890 /* Stuffing values in cgen_fields is handled by a collection of functions.
891    They are distinguished by the type of the VALUE argument they accept.
892    TODO: floating point, inlining support, remove cases where argument type
893    not appropriate.  */
894
895 void
896 openrisc_cgen_set_int_operand (cd, opindex, fields, value)
897      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
898      int opindex;
899      CGEN_FIELDS * fields;
900      int value;
901 {
902   switch (opindex)
903     {
904     case OPENRISC_OPERAND_ABS_26 :
905       fields->f_abs26 = value;
906       break;
907     case OPENRISC_OPERAND_DISP_26 :
908       fields->f_disp26 = value;
909       break;
910     case OPENRISC_OPERAND_HI16 :
911       fields->f_simm16 = value;
912       break;
913     case OPENRISC_OPERAND_LO16 :
914       fields->f_lo16 = value;
915       break;
916     case OPENRISC_OPERAND_OP_F_23 :
917       fields->f_op4 = value;
918       break;
919     case OPENRISC_OPERAND_OP_F_3 :
920       fields->f_op5 = value;
921       break;
922     case OPENRISC_OPERAND_RA :
923       fields->f_r2 = value;
924       break;
925     case OPENRISC_OPERAND_RB :
926       fields->f_r3 = value;
927       break;
928     case OPENRISC_OPERAND_RD :
929       fields->f_r1 = value;
930       break;
931     case OPENRISC_OPERAND_SIMM_16 :
932       fields->f_simm16 = value;
933       break;
934     case OPENRISC_OPERAND_UI16NC :
935       fields->f_i16nc = value;
936       break;
937     case OPENRISC_OPERAND_UIMM_16 :
938       fields->f_uimm16 = value;
939       break;
940     case OPENRISC_OPERAND_UIMM_5 :
941       fields->f_uimm5 = value;
942       break;
943
944     default :
945       /* xgettext:c-format */
946       fprintf (stderr, _("Unrecognized field %d while setting int operand.\n"),
947                        opindex);
948       abort ();
949   }
950 }
951
952 void
953 openrisc_cgen_set_vma_operand (cd, opindex, fields, value)
954      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
955      int opindex;
956      CGEN_FIELDS * fields;
957      bfd_vma value;
958 {
959   switch (opindex)
960     {
961     case OPENRISC_OPERAND_ABS_26 :
962       fields->f_abs26 = value;
963       break;
964     case OPENRISC_OPERAND_DISP_26 :
965       fields->f_disp26 = value;
966       break;
967     case OPENRISC_OPERAND_HI16 :
968       fields->f_simm16 = value;
969       break;
970     case OPENRISC_OPERAND_LO16 :
971       fields->f_lo16 = value;
972       break;
973     case OPENRISC_OPERAND_OP_F_23 :
974       fields->f_op4 = value;
975       break;
976     case OPENRISC_OPERAND_OP_F_3 :
977       fields->f_op5 = value;
978       break;
979     case OPENRISC_OPERAND_RA :
980       fields->f_r2 = value;
981       break;
982     case OPENRISC_OPERAND_RB :
983       fields->f_r3 = value;
984       break;
985     case OPENRISC_OPERAND_RD :
986       fields->f_r1 = value;
987       break;
988     case OPENRISC_OPERAND_SIMM_16 :
989       fields->f_simm16 = value;
990       break;
991     case OPENRISC_OPERAND_UI16NC :
992       fields->f_i16nc = value;
993       break;
994     case OPENRISC_OPERAND_UIMM_16 :
995       fields->f_uimm16 = value;
996       break;
997     case OPENRISC_OPERAND_UIMM_5 :
998       fields->f_uimm5 = value;
999       break;
1000
1001     default :
1002       /* xgettext:c-format */
1003       fprintf (stderr, _("Unrecognized field %d while setting vma operand.\n"),
1004                        opindex);
1005       abort ();
1006   }
1007 }
1008
1009 /* Function to call before using the instruction builder tables.  */
1010
1011 void
1012 openrisc_cgen_init_ibld_table (cd)
1013      CGEN_CPU_DESC cd;
1014 {
1015   cd->insert_handlers = & openrisc_cgen_insert_handlers[0];
1016   cd->extract_handlers = & openrisc_cgen_extract_handlers[0];
1017
1018   cd->insert_operand = openrisc_cgen_insert_operand;
1019   cd->extract_operand = openrisc_cgen_extract_operand;
1020
1021   cd->get_int_operand = openrisc_cgen_get_int_operand;
1022   cd->set_int_operand = openrisc_cgen_set_int_operand;
1023   cd->get_vma_operand = openrisc_cgen_get_vma_operand;
1024   cd->set_vma_operand = openrisc_cgen_set_vma_operand;
1025 }