OSDN Git Service

Fix compile time warnings
[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
53 static int extract_normal
54      PARAMS ((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      PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
59               CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma));
60 static void put_insn_int_value
61      PARAMS ((CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT));
62 const char * openrisc_cgen_insert_operand
63      PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma));
64 int openrisc_cgen_extract_operand
65      PARAMS ((CGEN_CPU_DESC, int, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma));
66 int openrisc_cgen_get_int_operand
67      PARAMS ((CGEN_CPU_DESC, int, const CGEN_FIELDS *));
68 bfd_vma openrisc_cgen_get_vma_operand
69      PARAMS ((CGEN_CPU_DESC, int, const CGEN_FIELDS *));
70 void openrisc_cgen_set_int_operand
71      PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, int));
72 void openrisc_cgen_set_vma_operand
73      PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, bfd_vma));
74 \f
75 /* Operand insertion.  */
76
77 #if ! CGEN_INT_INSN_P
78
79 /* Subroutine of insert_normal.  */
80
81 static CGEN_INLINE void
82 insert_1 (cd, value, start, length, word_length, bufp)
83      CGEN_CPU_DESC cd;
84      unsigned long value;
85      int start,length,word_length;
86      unsigned char *bufp;
87 {
88   unsigned long x,mask;
89   int shift;
90   int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
91
92   x = bfd_get_bits (bufp, word_length, big_p);
93
94   /* Written this way to avoid undefined behaviour.  */
95   mask = (((1L << (length - 1)) - 1) << 1) | 1;
96   if (CGEN_INSN_LSB0_P)
97     shift = (start + 1) - length;
98   else
99     shift = (word_length - (start + length));
100   x = (x & ~(mask << shift)) | ((value & mask) << shift);
101
102   bfd_put_bits ((bfd_vma) x, bufp, word_length, big_p);
103 }
104
105 #endif /* ! CGEN_INT_INSN_P */
106
107 /* Default insertion routine.
108
109    ATTRS is a mask of the boolean attributes.
110    WORD_OFFSET is the offset in bits from the start of the insn of the value.
111    WORD_LENGTH is the length of the word in bits in which the value resides.
112    START is the starting bit number in the word, architecture origin.
113    LENGTH is the length of VALUE in bits.
114    TOTAL_LENGTH is the total length of the insn in bits.
115
116    The result is an error message or NULL if success.  */
117
118 /* ??? This duplicates functionality with bfd's howto table and
119    bfd_install_relocation.  */
120 /* ??? This doesn't handle bfd_vma's.  Create another function when
121    necessary.  */
122
123 static const char *
124 insert_normal (cd, value, attrs, word_offset, start, length, word_length,
125                total_length, buffer)
126      CGEN_CPU_DESC cd;
127      long value;
128      unsigned int attrs;
129      unsigned int word_offset, start, length, word_length, 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 0
141   if (CGEN_INT_INSN_P
142       && word_offset != 0)
143     abort ();
144 #endif
145
146   if (word_length > 32)
147     abort ();
148
149   /* For architectures with insns smaller than the base-insn-bitsize,
150      word_length may be too big.  */
151   if (cd->min_insn_bitsize < cd->base_insn_bitsize)
152     {
153       if (word_offset == 0
154           && word_length > total_length)
155         word_length = total_length;
156     }
157
158   /* Ensure VALUE will fit.  */
159   if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
160     {
161       long minval = - (1L << (length - 1));
162       unsigned long maxval = mask;
163       
164       if ((value > 0 && (unsigned long) value > maxval)
165           || value < minval)
166         {
167           /* xgettext:c-format */
168           sprintf (errbuf,
169                    _("operand out of range (%ld not between %ld and %lu)"),
170                    value, minval, maxval);
171           return errbuf;
172         }
173     }
174   else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
175     {
176       unsigned long maxval = mask;
177       
178       if ((unsigned long) value > maxval)
179         {
180           /* xgettext:c-format */
181           sprintf (errbuf,
182                    _("operand out of range (%lu not between 0 and %lu)"),
183                    value, maxval);
184           return errbuf;
185         }
186     }
187   else
188     {
189       if (! cgen_signed_overflow_ok_p (cd))
190         {
191           long minval = - (1L << (length - 1));
192           long maxval =   (1L << (length - 1)) - 1;
193           
194           if (value < minval || value > maxval)
195             {
196               sprintf
197                 /* xgettext:c-format */
198                 (errbuf, _("operand out of range (%ld not between %ld and %ld)"),
199                  value, minval, maxval);
200               return errbuf;
201             }
202         }
203     }
204
205 #if CGEN_INT_INSN_P
206
207   {
208     int shift;
209
210     if (CGEN_INSN_LSB0_P)
211       shift = (word_offset + start + 1) - length;
212     else
213       shift = total_length - (word_offset + start + length);
214     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
215   }
216
217 #else /* ! CGEN_INT_INSN_P */
218
219   {
220     unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
221
222     insert_1 (cd, value, start, length, word_length, bufp);
223   }
224
225 #endif /* ! CGEN_INT_INSN_P */
226
227   return NULL;
228 }
229
230 /* Default insn builder (insert handler).
231    The instruction is recorded in CGEN_INT_INSN_P byte order (meaning
232    that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is
233    recorded in host byte order, otherwise BUFFER is an array of bytes
234    and the value is recorded in target byte order).
235    The result is an error message or NULL if success.  */
236
237 static const char *
238 insert_insn_normal (cd, insn, fields, buffer, pc)
239      CGEN_CPU_DESC cd;
240      const CGEN_INSN * insn;
241      CGEN_FIELDS * fields;
242      CGEN_INSN_BYTES_PTR buffer;
243      bfd_vma pc;
244 {
245   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
246   unsigned long value;
247   const CGEN_SYNTAX_CHAR_TYPE * syn;
248
249   CGEN_INIT_INSERT (cd);
250   value = CGEN_INSN_BASE_VALUE (insn);
251
252   /* If we're recording insns as numbers (rather than a string of bytes),
253      target byte order handling is deferred until later.  */
254
255 #if CGEN_INT_INSN_P
256
257   put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
258                       CGEN_FIELDS_BITSIZE (fields), value);
259
260 #else
261
262   cgen_put_insn_value (cd, buffer, min (cd->base_insn_bitsize,
263                                         CGEN_FIELDS_BITSIZE (fields)),
264                        value);
265
266 #endif /* ! CGEN_INT_INSN_P */
267
268   /* ??? It would be better to scan the format's fields.
269      Still need to be able to insert a value based on the operand though;
270      e.g. storing a branch displacement that got resolved later.
271      Needs more thought first.  */
272
273   for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn)
274     {
275       const char *errmsg;
276
277       if (CGEN_SYNTAX_CHAR_P (* syn))
278         continue;
279
280       errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
281                                        fields, buffer, pc);
282       if (errmsg)
283         return errmsg;
284     }
285
286   return NULL;
287 }
288
289 /* Cover function to store an insn value into an integral insn.  Must go here
290  because it needs <prefix>-desc.h for CGEN_INT_INSN_P.  */
291
292 static void
293 put_insn_int_value (cd, buf, length, insn_length, value)
294      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
295      CGEN_INSN_BYTES_PTR buf;
296      int length;
297      int insn_length;
298      CGEN_INSN_INT value;
299 {
300   /* For architectures with insns smaller than the base-insn-bitsize,
301      length may be too big.  */
302   if (length > insn_length)
303     *buf = value;
304   else
305     {
306       int shift = insn_length - length;
307       /* Written this way to avoid undefined behaviour.  */
308       CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
309       *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
310     }
311 }
312 \f
313 /* Operand extraction.  */
314
315 #if ! CGEN_INT_INSN_P
316
317 /* Subroutine of extract_normal.
318    Ensure sufficient bytes are cached in EX_INFO.
319    OFFSET is the offset in bytes from the start of the insn of the value.
320    BYTES is the length of the needed value.
321    Returns 1 for success, 0 for failure.  */
322
323 static CGEN_INLINE int
324 fill_cache (cd, ex_info, offset, bytes, pc)
325      CGEN_CPU_DESC cd;
326      CGEN_EXTRACT_INFO *ex_info;
327      int offset, bytes;
328      bfd_vma pc;
329 {
330   /* It's doubtful that the middle part has already been fetched so
331      we don't optimize that case.  kiss.  */
332   int mask;
333   disassemble_info *info = (disassemble_info *) ex_info->dis_info;
334
335   /* First do a quick check.  */
336   mask = (1 << bytes) - 1;
337   if (((ex_info->valid >> offset) & mask) == mask)
338     return 1;
339
340   /* Search for the first byte we need to read.  */
341   for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
342     if (! (mask & ex_info->valid))
343       break;
344
345   if (bytes)
346     {
347       int status;
348
349       pc += offset;
350       status = (*info->read_memory_func)
351         (pc, ex_info->insn_bytes + offset, bytes, info);
352
353       if (status != 0)
354         {
355           (*info->memory_error_func) (status, pc, info);
356           return 0;
357         }
358
359       ex_info->valid |= ((1 << bytes) - 1) << offset;
360     }
361
362   return 1;
363 }
364
365 /* Subroutine of extract_normal.  */
366
367 static CGEN_INLINE long
368 extract_1 (cd, ex_info, start, length, word_length, bufp, pc)
369      CGEN_CPU_DESC cd;
370      CGEN_EXTRACT_INFO *ex_info;
371      int start,length,word_length;
372      unsigned char *bufp;
373      bfd_vma pc;
374 {
375   unsigned long x;
376   int shift;
377   int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
378
379   x = bfd_get_bits (bufp, word_length, big_p);
380
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 /* Main entry point for operand insertion.
543
544    This function is basically just a big switch statement.  Earlier versions
545    used tables to look up the function to use, but
546    - if the table contains both assembler and disassembler functions then
547      the disassembler contains much of the assembler and vice-versa,
548    - there's a lot of inlining possibilities as things grow,
549    - using a switch statement avoids the function call overhead.
550
551    This function could be moved into `parse_insn_normal', but keeping it
552    separate makes clear the interface between `parse_insn_normal' and each of
553    the handlers.  It's also needed by GAS to insert operands that couldn't be
554    resolved during parsing.
555 */
556
557 const char *
558 openrisc_cgen_insert_operand (cd, opindex, fields, buffer, pc)
559      CGEN_CPU_DESC cd;
560      int opindex;
561      CGEN_FIELDS * fields;
562      CGEN_INSN_BYTES_PTR buffer;
563      bfd_vma pc;
564 {
565   const char * errmsg = NULL;
566   unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
567
568   switch (opindex)
569     {
570     case OPENRISC_OPERAND_ABS_26 :
571       {
572         long value = fields->f_abs26;
573         value = ((unsigned int) (pc) >> (2));
574         errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_ABS_ADDR), 0, 25, 26, 32, total_length, buffer);
575       }
576       break;
577     case OPENRISC_OPERAND_DISP_26 :
578       {
579         long value = fields->f_disp26;
580         value = ((int) (((value) - (pc))) >> (2));
581         errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 25, 26, 32, total_length, buffer);
582       }
583       break;
584     case OPENRISC_OPERAND_HI16 :
585       errmsg = insert_normal (cd, fields->f_simm16, 0|(1<<CGEN_IFLD_SIGNED), 0, 15, 16, 32, total_length, buffer);
586       break;
587     case OPENRISC_OPERAND_LO16 :
588       errmsg = insert_normal (cd, fields->f_lo16, 0|(1<<CGEN_IFLD_SIGNED), 0, 15, 16, 32, total_length, buffer);
589       break;
590     case OPENRISC_OPERAND_OP_F_23 :
591       errmsg = insert_normal (cd, fields->f_op4, 0, 0, 23, 3, 32, total_length, buffer);
592       break;
593     case OPENRISC_OPERAND_OP_F_3 :
594       errmsg = insert_normal (cd, fields->f_op5, 0, 0, 25, 5, 32, total_length, buffer);
595       break;
596     case OPENRISC_OPERAND_RA :
597       errmsg = insert_normal (cd, fields->f_r2, 0, 0, 20, 5, 32, total_length, buffer);
598       break;
599     case OPENRISC_OPERAND_RB :
600       errmsg = insert_normal (cd, fields->f_r3, 0, 0, 15, 5, 32, total_length, buffer);
601       break;
602     case OPENRISC_OPERAND_RD :
603       errmsg = insert_normal (cd, fields->f_r1, 0, 0, 25, 5, 32, total_length, buffer);
604       break;
605     case OPENRISC_OPERAND_SIMM_16 :
606       errmsg = insert_normal (cd, fields->f_simm16, 0|(1<<CGEN_IFLD_SIGNED), 0, 15, 16, 32, total_length, buffer);
607       break;
608     case OPENRISC_OPERAND_UI16NC :
609       {
610 {
611   FLD (f_i16_2) = ((((unsigned int) (FLD (f_i16nc)) >> (11))) & (31));
612   FLD (f_i16_1) = ((FLD (f_i16nc)) & (2047));
613 }
614         errmsg = insert_normal (cd, fields->f_i16_1, 0, 0, 10, 11, 32, total_length, buffer);
615         if (errmsg)
616           break;
617         errmsg = insert_normal (cd, fields->f_i16_2, 0, 0, 25, 5, 32, total_length, buffer);
618         if (errmsg)
619           break;
620       }
621       break;
622     case OPENRISC_OPERAND_UIMM_16 :
623       errmsg = insert_normal (cd, fields->f_uimm16, 0, 0, 15, 16, 32, total_length, buffer);
624       break;
625     case OPENRISC_OPERAND_UIMM_5 :
626       errmsg = insert_normal (cd, fields->f_uimm5, 0, 0, 4, 5, 32, total_length, buffer);
627       break;
628
629     default :
630       /* xgettext:c-format */
631       fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
632                opindex);
633       abort ();
634   }
635
636   return errmsg;
637 }
638
639 /* Main entry point for operand extraction.
640    The result is <= 0 for error, >0 for success.
641    ??? Actual values aren't well defined right now.
642
643    This function is basically just a big switch statement.  Earlier versions
644    used tables to look up the function to use, but
645    - if the table contains both assembler and disassembler functions then
646      the disassembler contains much of the assembler and vice-versa,
647    - there's a lot of inlining possibilities as things grow,
648    - using a switch statement avoids the function call overhead.
649
650    This function could be moved into `print_insn_normal', but keeping it
651    separate makes clear the interface between `print_insn_normal' and each of
652    the handlers.
653 */
654
655 int
656 openrisc_cgen_extract_operand (cd, opindex, ex_info, insn_value, fields, pc)
657      CGEN_CPU_DESC cd;
658      int opindex;
659      CGEN_EXTRACT_INFO *ex_info;
660      CGEN_INSN_INT insn_value;
661      CGEN_FIELDS * fields;
662      bfd_vma pc;
663 {
664   /* Assume success (for those operands that are nops).  */
665   int length = 1;
666   unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
667
668   switch (opindex)
669     {
670     case OPENRISC_OPERAND_ABS_26 :
671       {
672         long value;
673         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);
674         value = ((value) << (2));
675         fields->f_abs26 = value;
676       }
677       break;
678     case OPENRISC_OPERAND_DISP_26 :
679       {
680         long value;
681         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);
682         value = ((((value) << (2))) + (pc));
683         fields->f_disp26 = value;
684       }
685       break;
686     case OPENRISC_OPERAND_HI16 :
687       length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 15, 16, 32, total_length, pc, & fields->f_simm16);
688       break;
689     case OPENRISC_OPERAND_LO16 :
690       length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 15, 16, 32, total_length, pc, & fields->f_lo16);
691       break;
692     case OPENRISC_OPERAND_OP_F_23 :
693       length = extract_normal (cd, ex_info, insn_value, 0, 0, 23, 3, 32, total_length, pc, & fields->f_op4);
694       break;
695     case OPENRISC_OPERAND_OP_F_3 :
696       length = extract_normal (cd, ex_info, insn_value, 0, 0, 25, 5, 32, total_length, pc, & fields->f_op5);
697       break;
698     case OPENRISC_OPERAND_RA :
699       length = extract_normal (cd, ex_info, insn_value, 0, 0, 20, 5, 32, total_length, pc, & fields->f_r2);
700       break;
701     case OPENRISC_OPERAND_RB :
702       length = extract_normal (cd, ex_info, insn_value, 0, 0, 15, 5, 32, total_length, pc, & fields->f_r3);
703       break;
704     case OPENRISC_OPERAND_RD :
705       length = extract_normal (cd, ex_info, insn_value, 0, 0, 25, 5, 32, total_length, pc, & fields->f_r1);
706       break;
707     case OPENRISC_OPERAND_SIMM_16 :
708       length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED), 0, 15, 16, 32, total_length, pc, & fields->f_simm16);
709       break;
710     case OPENRISC_OPERAND_UI16NC :
711       {
712         length = extract_normal (cd, ex_info, insn_value, 0, 0, 10, 11, 32, total_length, pc, & fields->f_i16_1);
713         if (length <= 0) break;
714         length = extract_normal (cd, ex_info, insn_value, 0, 0, 25, 5, 32, total_length, pc, & fields->f_i16_2);
715         if (length <= 0) break;
716 {
717   extern long openrisc_sign_extend_16bit PARAMS ((long));
718   
719   FLD (f_i16nc) = openrisc_sign_extend_16bit (((((FLD (f_i16_2)) << (11))) | (FLD (f_i16_1))));
720 }
721       }
722       break;
723     case OPENRISC_OPERAND_UIMM_16 :
724       length = extract_normal (cd, ex_info, insn_value, 0, 0, 15, 16, 32, total_length, pc, & fields->f_uimm16);
725       break;
726     case OPENRISC_OPERAND_UIMM_5 :
727       length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 5, 32, total_length, pc, & fields->f_uimm5);
728       break;
729
730     default :
731       /* xgettext:c-format */
732       fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
733                opindex);
734       abort ();
735     }
736
737   return length;
738 }
739
740 cgen_insert_fn * const openrisc_cgen_insert_handlers[] = 
741 {
742   insert_insn_normal,
743 };
744
745 cgen_extract_fn * const openrisc_cgen_extract_handlers[] = 
746 {
747   extract_insn_normal,
748 };
749
750 /* Getting values from cgen_fields is handled by a collection of functions.
751    They are distinguished by the type of the VALUE argument they return.
752    TODO: floating point, inlining support, remove cases where result type
753    not appropriate.  */
754
755 int
756 openrisc_cgen_get_int_operand (cd, opindex, fields)
757      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
758      int opindex;
759      const CGEN_FIELDS * fields;
760 {
761   int value;
762
763   switch (opindex)
764     {
765     case OPENRISC_OPERAND_ABS_26 :
766       value = fields->f_abs26;
767       break;
768     case OPENRISC_OPERAND_DISP_26 :
769       value = fields->f_disp26;
770       break;
771     case OPENRISC_OPERAND_HI16 :
772       value = fields->f_simm16;
773       break;
774     case OPENRISC_OPERAND_LO16 :
775       value = fields->f_lo16;
776       break;
777     case OPENRISC_OPERAND_OP_F_23 :
778       value = fields->f_op4;
779       break;
780     case OPENRISC_OPERAND_OP_F_3 :
781       value = fields->f_op5;
782       break;
783     case OPENRISC_OPERAND_RA :
784       value = fields->f_r2;
785       break;
786     case OPENRISC_OPERAND_RB :
787       value = fields->f_r3;
788       break;
789     case OPENRISC_OPERAND_RD :
790       value = fields->f_r1;
791       break;
792     case OPENRISC_OPERAND_SIMM_16 :
793       value = fields->f_simm16;
794       break;
795     case OPENRISC_OPERAND_UI16NC :
796       value = fields->f_i16nc;
797       break;
798     case OPENRISC_OPERAND_UIMM_16 :
799       value = fields->f_uimm16;
800       break;
801     case OPENRISC_OPERAND_UIMM_5 :
802       value = fields->f_uimm5;
803       break;
804
805     default :
806       /* xgettext:c-format */
807       fprintf (stderr, _("Unrecognized field %d while getting int operand.\n"),
808                        opindex);
809       abort ();
810   }
811
812   return value;
813 }
814
815 bfd_vma
816 openrisc_cgen_get_vma_operand (cd, opindex, fields)
817      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
818      int opindex;
819      const CGEN_FIELDS * fields;
820 {
821   bfd_vma value;
822
823   switch (opindex)
824     {
825     case OPENRISC_OPERAND_ABS_26 :
826       value = fields->f_abs26;
827       break;
828     case OPENRISC_OPERAND_DISP_26 :
829       value = fields->f_disp26;
830       break;
831     case OPENRISC_OPERAND_HI16 :
832       value = fields->f_simm16;
833       break;
834     case OPENRISC_OPERAND_LO16 :
835       value = fields->f_lo16;
836       break;
837     case OPENRISC_OPERAND_OP_F_23 :
838       value = fields->f_op4;
839       break;
840     case OPENRISC_OPERAND_OP_F_3 :
841       value = fields->f_op5;
842       break;
843     case OPENRISC_OPERAND_RA :
844       value = fields->f_r2;
845       break;
846     case OPENRISC_OPERAND_RB :
847       value = fields->f_r3;
848       break;
849     case OPENRISC_OPERAND_RD :
850       value = fields->f_r1;
851       break;
852     case OPENRISC_OPERAND_SIMM_16 :
853       value = fields->f_simm16;
854       break;
855     case OPENRISC_OPERAND_UI16NC :
856       value = fields->f_i16nc;
857       break;
858     case OPENRISC_OPERAND_UIMM_16 :
859       value = fields->f_uimm16;
860       break;
861     case OPENRISC_OPERAND_UIMM_5 :
862       value = fields->f_uimm5;
863       break;
864
865     default :
866       /* xgettext:c-format */
867       fprintf (stderr, _("Unrecognized field %d while getting vma operand.\n"),
868                        opindex);
869       abort ();
870   }
871
872   return value;
873 }
874
875 /* Stuffing values in cgen_fields is handled by a collection of functions.
876    They are distinguished by the type of the VALUE argument they accept.
877    TODO: floating point, inlining support, remove cases where argument type
878    not appropriate.  */
879
880 void
881 openrisc_cgen_set_int_operand (cd, opindex, fields, value)
882      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
883      int opindex;
884      CGEN_FIELDS * fields;
885      int value;
886 {
887   switch (opindex)
888     {
889     case OPENRISC_OPERAND_ABS_26 :
890       fields->f_abs26 = value;
891       break;
892     case OPENRISC_OPERAND_DISP_26 :
893       fields->f_disp26 = value;
894       break;
895     case OPENRISC_OPERAND_HI16 :
896       fields->f_simm16 = value;
897       break;
898     case OPENRISC_OPERAND_LO16 :
899       fields->f_lo16 = value;
900       break;
901     case OPENRISC_OPERAND_OP_F_23 :
902       fields->f_op4 = value;
903       break;
904     case OPENRISC_OPERAND_OP_F_3 :
905       fields->f_op5 = value;
906       break;
907     case OPENRISC_OPERAND_RA :
908       fields->f_r2 = value;
909       break;
910     case OPENRISC_OPERAND_RB :
911       fields->f_r3 = value;
912       break;
913     case OPENRISC_OPERAND_RD :
914       fields->f_r1 = value;
915       break;
916     case OPENRISC_OPERAND_SIMM_16 :
917       fields->f_simm16 = value;
918       break;
919     case OPENRISC_OPERAND_UI16NC :
920       fields->f_i16nc = value;
921       break;
922     case OPENRISC_OPERAND_UIMM_16 :
923       fields->f_uimm16 = value;
924       break;
925     case OPENRISC_OPERAND_UIMM_5 :
926       fields->f_uimm5 = value;
927       break;
928
929     default :
930       /* xgettext:c-format */
931       fprintf (stderr, _("Unrecognized field %d while setting int operand.\n"),
932                        opindex);
933       abort ();
934   }
935 }
936
937 void
938 openrisc_cgen_set_vma_operand (cd, opindex, fields, value)
939      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
940      int opindex;
941      CGEN_FIELDS * fields;
942      bfd_vma value;
943 {
944   switch (opindex)
945     {
946     case OPENRISC_OPERAND_ABS_26 :
947       fields->f_abs26 = value;
948       break;
949     case OPENRISC_OPERAND_DISP_26 :
950       fields->f_disp26 = value;
951       break;
952     case OPENRISC_OPERAND_HI16 :
953       fields->f_simm16 = value;
954       break;
955     case OPENRISC_OPERAND_LO16 :
956       fields->f_lo16 = value;
957       break;
958     case OPENRISC_OPERAND_OP_F_23 :
959       fields->f_op4 = value;
960       break;
961     case OPENRISC_OPERAND_OP_F_3 :
962       fields->f_op5 = value;
963       break;
964     case OPENRISC_OPERAND_RA :
965       fields->f_r2 = value;
966       break;
967     case OPENRISC_OPERAND_RB :
968       fields->f_r3 = value;
969       break;
970     case OPENRISC_OPERAND_RD :
971       fields->f_r1 = value;
972       break;
973     case OPENRISC_OPERAND_SIMM_16 :
974       fields->f_simm16 = value;
975       break;
976     case OPENRISC_OPERAND_UI16NC :
977       fields->f_i16nc = value;
978       break;
979     case OPENRISC_OPERAND_UIMM_16 :
980       fields->f_uimm16 = value;
981       break;
982     case OPENRISC_OPERAND_UIMM_5 :
983       fields->f_uimm5 = value;
984       break;
985
986     default :
987       /* xgettext:c-format */
988       fprintf (stderr, _("Unrecognized field %d while setting vma operand.\n"),
989                        opindex);
990       abort ();
991   }
992 }
993
994 /* Function to call before using the instruction builder tables.  */
995
996 void
997 openrisc_cgen_init_ibld_table (cd)
998      CGEN_CPU_DESC cd;
999 {
1000   cd->insert_handlers = & openrisc_cgen_insert_handlers[0];
1001   cd->extract_handlers = & openrisc_cgen_extract_handlers[0];
1002
1003   cd->insert_operand = openrisc_cgen_insert_operand;
1004   cd->extract_operand = openrisc_cgen_extract_operand;
1005
1006   cd->get_int_operand = openrisc_cgen_get_int_operand;
1007   cd->set_int_operand = openrisc_cgen_set_int_operand;
1008   cd->get_vma_operand = openrisc_cgen_get_vma_operand;
1009   cd->set_vma_operand = openrisc_cgen_set_vma_operand;
1010 }