* cgen-dis.in (print_normal): CGEN_OPERAND_FAKE renamed to
[external/binutils.git] / opcodes / fr30-opc.c
1 /* Generic opcode table support for targets using CGEN. -*- C -*-
2    CGEN: Cpu tools GENerator
3
4 THIS FILE IS USED TO GENERATE fr30-opc.c.
5
6 Copyright (C) 1998 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 #include "sysdep.h"
25 #include <stdio.h>
26 #include "ansidecl.h"
27 #include "libiberty.h"
28 #include "bfd.h"
29 #include "symcat.h"
30 #include "fr30-opc.h"
31 #include "opintl.h"
32
33 /* The hash functions are recorded here to help keep assembler code out of
34    the disassembler and vice versa.  */
35
36 static int asm_hash_insn_p PARAMS ((const CGEN_INSN *));
37 static unsigned int asm_hash_insn PARAMS ((const char *));
38 static int dis_hash_insn_p PARAMS ((const CGEN_INSN *));
39 static unsigned int dis_hash_insn PARAMS ((const char *, unsigned long));
40
41 /* Cover function to read and properly byteswap an insn value.  */
42
43 CGEN_INSN_INT
44 cgen_get_insn_value (od, buf, length)
45      CGEN_OPCODE_DESC od;
46      unsigned char *buf;
47      int length;
48 {
49   CGEN_INSN_INT value;
50
51   switch (length)
52     {
53     case 8:
54       value = *buf;
55       break;
56     case 16:
57       if (CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG)
58         value = bfd_getb16 (buf);
59       else
60         value = bfd_getl16 (buf);
61       break;
62     case 32:
63       if (CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG)
64         value = bfd_getb32 (buf);
65       else
66         value = bfd_getl32 (buf);
67       break;
68     default:
69       abort ();
70     }
71
72   return value;
73 }
74
75 /* Cover function to store an insn value properly byteswapped.  */
76
77 void
78 cgen_put_insn_value (od, buf, length, value)
79      CGEN_OPCODE_DESC od;
80      unsigned char *buf;
81      int length;
82      CGEN_INSN_INT value;
83 {
84   switch (length)
85     {
86     case 8:
87       buf[0] = value;
88       break;
89     case 16:
90       if (CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG)
91         bfd_putb16 (value, buf);
92       else
93         bfd_putl16 (value, buf);
94       break;
95     case 32:
96       if (CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG)
97         bfd_putb32 (value, buf);
98       else
99         bfd_putl32 (value, buf);
100       break;
101     default:
102       abort ();
103     }
104 }
105
106 /* Look up instruction INSN_VALUE and extract its fields.
107    INSN, if non-null, is the insn table entry.
108    Otherwise INSN_VALUE is examined to compute it.
109    LENGTH is the bit length of INSN_VALUE if known, otherwise 0.
110    0 is only valid if `insn == NULL && ! CGEN_INT_INSN_P'.
111    If INSN != NULL, LENGTH must be valid.
112    ALIAS_P is non-zero if alias insns are to be included in the search.
113
114    The result a pointer to the insn table entry, or NULL if the instruction
115    wasn't recognized.  */
116
117 const CGEN_INSN *
118 fr30_cgen_lookup_insn (od, insn, insn_value, length, fields, alias_p)
119      CGEN_OPCODE_DESC od;
120      const CGEN_INSN *insn;
121      CGEN_INSN_BYTES insn_value;
122      int length;
123      CGEN_FIELDS *fields;
124      int alias_p;
125 {
126   unsigned char buf[16];
127   unsigned char *bufp;
128   unsigned int base_insn;
129 #if CGEN_INT_INSN_P
130   CGEN_EXTRACT_INFO *info = NULL;
131 #else
132   CGEN_EXTRACT_INFO ex_info;
133   CGEN_EXTRACT_INFO *info = &ex_info;
134 #endif
135
136 #if ! CGEN_INT_INSN_P
137   ex_info.dis_info = NULL;
138   ex_info.bytes = insn_value;
139   ex_info.valid = -1;
140 #endif
141
142   if (!insn)
143     {
144       const CGEN_INSN_LIST *insn_list;
145
146 #if CGEN_INT_INSN_P
147       cgen_put_insn_value (od, buf, length, insn_value);
148       bufp = buf;
149       base_insn = insn_value; /*???*/
150 #else
151       base_insn = cgen_get_insn_value (od, buf, length);
152       bufp = insn_value;
153 #endif
154
155       /* The instructions are stored in hash lists.
156          Pick the first one and keep trying until we find the right one.  */
157
158       insn_list = CGEN_DIS_LOOKUP_INSN (od, bufp, base_insn);
159       while (insn_list != NULL)
160         {
161           insn = insn_list->insn;
162
163           if (alias_p
164               || ! CGEN_INSN_ATTR (insn, CGEN_INSN_ALIAS))
165             {
166               /* Basic bit mask must be correct.  */
167               /* ??? May wish to allow target to defer this check until the
168                  extract handler.  */
169               if ((insn_value & CGEN_INSN_MASK (insn)) == CGEN_INSN_VALUE (insn))
170                 {
171                   /* ??? 0 is passed for `pc' */
172                   int elength = (*CGEN_EXTRACT_FN (insn)) (od, insn, info,
173                                                            insn_value, fields,
174                                                            (bfd_vma) 0);
175                   if (elength > 0)
176                     {
177                       /* sanity check */
178                       if (length != 0 && length != elength)
179                         abort ();
180                       return insn;
181                     }
182                 }
183             }
184
185           insn_list = CGEN_DIS_NEXT_INSN (insn_list);
186         }
187     }
188   else
189     {
190       /* Sanity check: can't pass an alias insn if ! alias_p.  */
191       if (! alias_p
192           && CGEN_INSN_ATTR (insn, CGEN_INSN_ALIAS))
193         abort ();
194       /* Sanity check: length must be correct.  */
195       if (length != CGEN_INSN_BITSIZE (insn))
196         abort ();
197
198       /* ??? 0 is passed for `pc' */
199       length = (*CGEN_EXTRACT_FN (insn)) (od, insn, info, insn_value, fields,
200                                           (bfd_vma) 0);
201       /* Sanity check: must succeed.
202          Could relax this later if it ever proves useful.  */
203       if (length == 0)
204         abort ();
205       return insn;
206     }
207
208   return NULL;
209 }
210
211 /* Fill in the operand instances used by INSN whose operands are FIELDS.
212    INDICES is a pointer to a buffer of MAX_OPERAND_INSTANCES ints to be filled
213    in.  */
214
215 void
216 fr30_cgen_get_insn_operands (od, insn, fields, indices)
217      CGEN_OPCODE_DESC od;
218      const CGEN_INSN * insn;
219      const CGEN_FIELDS * fields;
220      int *indices;
221 {
222   const CGEN_OPERAND_INSTANCE *opinst;
223   int i;
224
225   for (i = 0, opinst = CGEN_INSN_OPERANDS (insn);
226        opinst != NULL
227          && CGEN_OPERAND_INSTANCE_TYPE (opinst) != CGEN_OPERAND_INSTANCE_END;
228        ++i, ++opinst)
229     {
230       const CGEN_OPERAND *op = CGEN_OPERAND_INSTANCE_OPERAND (opinst);
231       if (op == NULL)
232         indices[i] = CGEN_OPERAND_INSTANCE_INDEX (opinst);
233       else
234         indices[i] = fr30_cgen_get_int_operand (CGEN_OPERAND_INDEX (op),
235                                                   fields);
236     }
237 }
238
239 /* Cover function to fr30_cgen_get_insn_operands when either INSN or FIELDS
240    isn't known.
241    The INSN, INSN_VALUE, and LENGTH arguments are passed to
242    fr30_cgen_lookup_insn unchanged.
243
244    The result is the insn table entry or NULL if the instruction wasn't
245    recognized.  */
246
247 const CGEN_INSN *
248 fr30_cgen_lookup_get_insn_operands (od, insn, insn_value, length, indices)
249      CGEN_OPCODE_DESC od;
250      const CGEN_INSN *insn;
251      CGEN_INSN_BYTES insn_value;
252      int length;
253      int *indices;
254 {
255   CGEN_FIELDS fields;
256
257   /* Pass non-zero for ALIAS_P only if INSN != NULL.
258      If INSN == NULL, we want a real insn.  */
259   insn = fr30_cgen_lookup_insn (od, insn, insn_value, length, &fields,
260                                   insn != NULL);
261   if (! insn)
262     return NULL;
263
264   fr30_cgen_get_insn_operands (od, insn, &fields, indices);
265   return insn;
266 }
267 /* Attributes.  */
268
269 static const CGEN_ATTR_ENTRY MACH_attr[] =
270 {
271   { "base", MACH_BASE },
272   { "fr30", MACH_FR30 },
273   { "max", MACH_MAX },
274   { 0, 0 }
275 };
276
277 const CGEN_ATTR_TABLE fr30_cgen_hardware_attr_table[] =
278 {
279   { "CACHE-ADDR", NULL },
280   { "FUN-ACCESS", NULL },
281   { "PC", NULL },
282   { "PROFILE", NULL },
283   { 0, 0 }
284 };
285
286 const CGEN_ATTR_TABLE fr30_cgen_operand_attr_table[] =
287 {
288   { "ABS-ADDR", NULL },
289   { "NEGATIVE", NULL },
290   { "PCREL-ADDR", NULL },
291   { "RELAX", NULL },
292   { "SEM-ONLY", NULL },
293   { "SIGN-OPT", NULL },
294   { "UNSIGNED", NULL },
295   { 0, 0 }
296 };
297
298 const CGEN_ATTR_TABLE fr30_cgen_insn_attr_table[] =
299 {
300   { "ALIAS", NULL },
301   { "COND-CTI", NULL },
302   { "NO-DIS", NULL },
303   { "RELAX", NULL },
304   { "RELAXABLE", NULL },
305   { "SKIP-CTI", NULL },
306   { "UNCOND-CTI", NULL },
307   { "VIRTUAL", NULL },
308   { 0, 0 }
309 };
310
311 CGEN_KEYWORD_ENTRY fr30_cgen_opval_h_gr_entries[] = 
312 {
313   { "ac", 13 },
314   { "fp", 14 },
315   { "sp", 15 },
316   { "r0", 0 },
317   { "r1", 1 },
318   { "r2", 2 },
319   { "r3", 3 },
320   { "r4", 4 },
321   { "r5", 5 },
322   { "r6", 6 },
323   { "r7", 7 },
324   { "r8", 8 },
325   { "r9", 9 },
326   { "r10", 10 },
327   { "r11", 11 },
328   { "r12", 12 },
329   { "r13", 13 },
330   { "r14", 14 },
331   { "r15", 15 }
332 };
333
334 CGEN_KEYWORD fr30_cgen_opval_h_gr = 
335 {
336   & fr30_cgen_opval_h_gr_entries[0],
337   19
338 };
339
340 CGEN_KEYWORD_ENTRY fr30_cgen_opval_h_dr_entries[] = 
341 {
342   { "tbr", 0 },
343   { "rp", 1 },
344   { "ssp", 2 },
345   { "usp", 3 }
346 };
347
348 CGEN_KEYWORD fr30_cgen_opval_h_dr = 
349 {
350   & fr30_cgen_opval_h_dr_entries[0],
351   4
352 };
353
354 CGEN_KEYWORD_ENTRY fr30_cgen_opval_h_mdr_entries[] = 
355 {
356   { "mdh", 4 },
357   { "mdl", 5 }
358 };
359
360 CGEN_KEYWORD fr30_cgen_opval_h_mdr = 
361 {
362   & fr30_cgen_opval_h_mdr_entries[0],
363   2
364 };
365
366 CGEN_KEYWORD_ENTRY fr30_cgen_opval_h_cr_entries[] = 
367 {
368   { "pc", 0 },
369   { "ps", 1 }
370 };
371
372 CGEN_KEYWORD fr30_cgen_opval_h_cr = 
373 {
374   & fr30_cgen_opval_h_cr_entries[0],
375   2
376 };
377
378
379 /* The hardware table.  */
380
381 #define HW_ENT(n) fr30_cgen_hw_entries[n]
382 static const CGEN_HW_ENTRY fr30_cgen_hw_entries[] =
383 {
384   { HW_H_PC, & HW_ENT (HW_H_PC + 1), "h-pc", CGEN_ASM_KEYWORD, (PTR) 0, { 0, 0|(1<<CGEN_HW_PROFILE)|(1<<CGEN_HW_PC), { 0 } } },
385   { HW_H_MEMORY, & HW_ENT (HW_H_MEMORY + 1), "h-memory", CGEN_ASM_KEYWORD, (PTR) 0, { 0, 0, { 0 } } },
386   { HW_H_SINT, & HW_ENT (HW_H_SINT + 1), "h-sint", CGEN_ASM_KEYWORD, (PTR) 0, { 0, 0, { 0 } } },
387   { HW_H_UINT, & HW_ENT (HW_H_UINT + 1), "h-uint", CGEN_ASM_KEYWORD, (PTR) 0, { 0, 0, { 0 } } },
388   { HW_H_ADDR, & HW_ENT (HW_H_ADDR + 1), "h-addr", CGEN_ASM_KEYWORD, (PTR) 0, { 0, 0, { 0 } } },
389   { HW_H_IADDR, & HW_ENT (HW_H_IADDR + 1), "h-iaddr", CGEN_ASM_KEYWORD, (PTR) 0, { 0, 0, { 0 } } },
390   { HW_H_GR, & HW_ENT (HW_H_GR + 1), "h-gr", CGEN_ASM_KEYWORD, (PTR) & fr30_cgen_opval_h_gr, { 0, 0|(1<<CGEN_HW_CACHE_ADDR)|(1<<CGEN_HW_PROFILE), { 0 } } },
391   { HW_H_DR, & HW_ENT (HW_H_DR + 1), "h-dr", CGEN_ASM_KEYWORD, (PTR) & fr30_cgen_opval_h_dr, { 0, 0, { 0 } } },
392   { HW_H_MDR, & HW_ENT (HW_H_MDR + 1), "h-mdr", CGEN_ASM_KEYWORD, (PTR) & fr30_cgen_opval_h_mdr, { 0, 0, { 0 } } },
393   { HW_H_CR, & HW_ENT (HW_H_CR + 1), "h-cr", CGEN_ASM_KEYWORD, (PTR) & fr30_cgen_opval_h_cr, { 0, 0, { 0 } } },
394   { HW_H_NBIT, & HW_ENT (HW_H_NBIT + 1), "h-nbit", CGEN_ASM_KEYWORD, (PTR) 0, { 0, 0|(1<<CGEN_HW_FUN_ACCESS), { 0 } } },
395   { HW_H_ZBIT, & HW_ENT (HW_H_ZBIT + 1), "h-zbit", CGEN_ASM_KEYWORD, (PTR) 0, { 0, 0|(1<<CGEN_HW_FUN_ACCESS), { 0 } } },
396   { HW_H_VBIT, & HW_ENT (HW_H_VBIT + 1), "h-vbit", CGEN_ASM_KEYWORD, (PTR) 0, { 0, 0|(1<<CGEN_HW_FUN_ACCESS), { 0 } } },
397   { HW_H_CBIT, & HW_ENT (HW_H_CBIT + 1), "h-cbit", CGEN_ASM_KEYWORD, (PTR) 0, { 0, 0|(1<<CGEN_HW_FUN_ACCESS), { 0 } } },
398   { 0 }
399 };
400
401 /* The operand table.  */
402
403 #define OPERAND(op) CONCAT2 (FR30_OPERAND_,op)
404 #define OP_ENT(op) fr30_cgen_operand_table[OPERAND (op)]
405
406 const CGEN_OPERAND fr30_cgen_operand_table[MAX_OPERANDS] =
407 {
408 /* pc: program counter */
409   { "pc", & HW_ENT (HW_H_PC), 0, 0,
410     { 0, 0|(1<<CGEN_OPERAND_SEM_ONLY), { 0 } }  },
411 /* Ri: destination register */
412   { "Ri", & HW_ENT (HW_H_GR), 12, 4,
413     { 0, 0|(1<<CGEN_OPERAND_UNSIGNED), { 0 } }  },
414 /* Rj: source register */
415   { "Rj", & HW_ENT (HW_H_GR), 8, 4,
416     { 0, 0|(1<<CGEN_OPERAND_UNSIGNED), { 0 } }  },
417 /* nbit: negative bit */
418   { "nbit", & HW_ENT (HW_H_NBIT), 0, 0,
419     { 0, 0|(1<<CGEN_OPERAND_SEM_ONLY), { 0 } }  },
420 /* vbit: overflow bit */
421   { "vbit", & HW_ENT (HW_H_VBIT), 0, 0,
422     { 0, 0|(1<<CGEN_OPERAND_SEM_ONLY), { 0 } }  },
423 /* zbit: zero     bit */
424   { "zbit", & HW_ENT (HW_H_ZBIT), 0, 0,
425     { 0, 0|(1<<CGEN_OPERAND_SEM_ONLY), { 0 } }  },
426 /* cbit: carry    bit */
427   { "cbit", & HW_ENT (HW_H_CBIT), 0, 0,
428     { 0, 0|(1<<CGEN_OPERAND_SEM_ONLY), { 0 } }  },
429 };
430
431 /* Operand references.  */
432
433 #define INPUT CGEN_OPERAND_INSTANCE_INPUT
434 #define OUTPUT CGEN_OPERAND_INSTANCE_OUTPUT
435
436 static const CGEN_OPERAND_INSTANCE fmt_add_ops[] = {
437   { INPUT, "Rj", & HW_ENT (HW_H_GR), CGEN_MODE_SI, & OP_ENT (RJ), 0 },
438   { INPUT, "Ri", & HW_ENT (HW_H_GR), CGEN_MODE_SI, & OP_ENT (RI), 0 },
439   { OUTPUT, "Ri", & HW_ENT (HW_H_GR), CGEN_MODE_SI, & OP_ENT (RI), 0 },
440   { OUTPUT, "vbit", & HW_ENT (HW_H_VBIT), CGEN_MODE_BI, 0, 0 },
441   { OUTPUT, "cbit", & HW_ENT (HW_H_CBIT), CGEN_MODE_BI, 0, 0 },
442   { OUTPUT, "zbit", & HW_ENT (HW_H_ZBIT), CGEN_MODE_BI, 0, 0 },
443   { OUTPUT, "nbit", & HW_ENT (HW_H_NBIT), CGEN_MODE_BI, 0, 0 },
444   { 0 }
445 };
446
447 #undef INPUT
448 #undef OUTPUT
449
450 #define A(a) (1 << CONCAT2 (CGEN_INSN_,a))
451 #define MNEM CGEN_SYNTAX_MNEMONIC /* syntax value for mnemonic */
452 #define OP(field) CGEN_SYNTAX_MAKE_FIELD (OPERAND (field))
453
454 /* The instruction table.
455    This is currently non-static because the simulator accesses it
456    directly.  */
457
458 const CGEN_INSN fr30_cgen_insn_table_entries[MAX_INSNS] =
459 {
460   /* Special null first entry.
461      A `num' value of zero is thus invalid.
462      Also, the special `invalid' insn resides here.  */
463   { { 0 }, 0 },
464 /* add $Rj,$Ri */
465   {
466     { 1, 1, 1, 1 },
467     FR30_INSN_ADD, "add", "add",
468     { { MNEM, ' ', OP (RJ), ',', OP (RI), 0 } },
469     { 16, 16, 0xff00 }, 0xa600,
470     (PTR) & fmt_add_ops[0],
471     { 0, 0, { 0 } }
472   },
473 };
474
475 #undef A
476 #undef MNEM
477 #undef OP
478
479 static const CGEN_INSN_TABLE insn_table =
480 {
481   & fr30_cgen_insn_table_entries[0],
482   sizeof (CGEN_INSN),
483   MAX_INSNS,
484   NULL
485 };
486
487 /* Each non-simple macro entry points to an array of expansion possibilities.  */
488
489 #define A(a) (1 << CONCAT2 (CGEN_INSN_,a))
490 #define MNEM CGEN_SYNTAX_MNEMONIC /* syntax value for mnemonic */
491 #define OP(field) CGEN_SYNTAX_MAKE_FIELD (OPERAND (field))
492
493 /* The macro instruction table.  */
494
495 static const CGEN_INSN macro_insn_table_entries[] =
496 {
497 };
498
499 #undef A
500 #undef MNEM
501 #undef OP
502
503 static const CGEN_INSN_TABLE macro_insn_table =
504 {
505   & macro_insn_table_entries[0],
506   sizeof (CGEN_INSN),
507   (sizeof (macro_insn_table_entries) /
508    sizeof (macro_insn_table_entries[0])),
509   NULL
510 };
511
512 static void
513 init_tables ()
514 {
515 }
516
517 /* Return non-zero if INSN is to be added to the hash table.
518    Targets are free to override CGEN_{ASM,DIS}_HASH_P in the .opc file.  */
519
520 static int
521 asm_hash_insn_p (insn)
522      const CGEN_INSN * insn;
523 {
524   return CGEN_ASM_HASH_P (insn);
525 }
526
527 static int
528 dis_hash_insn_p (insn)
529      const CGEN_INSN * insn;
530 {
531   /* If building the hash table and the NO-DIS attribute is present,
532      ignore.  */
533   if (CGEN_INSN_ATTR (insn, CGEN_INSN_NO_DIS))
534     return 0;
535   return CGEN_DIS_HASH_P (insn);
536 }
537
538 /* The result is the hash value of the insn.
539    Targets are free to override CGEN_{ASM,DIS}_HASH in the .opc file.  */
540
541 static unsigned int
542 asm_hash_insn (mnem)
543      const char * mnem;
544 {
545   return CGEN_ASM_HASH (mnem);
546 }
547
548 /* BUF is a pointer to the insn's bytes in target order.
549    VALUE is an integer of the first CGEN_BASE_INSN_BITSIZE bits,
550    host order.  */
551
552 static unsigned int
553 dis_hash_insn (buf, value)
554      const char * buf;
555      unsigned long value;
556 {
557   return CGEN_DIS_HASH (buf, value);
558 }
559
560 /* Initialize an opcode table and return a descriptor.
561    It's much like opening a file, and must be the first function called.  */
562
563 CGEN_OPCODE_DESC
564 fr30_cgen_opcode_open (mach, endian)
565      int mach;
566      enum cgen_endian endian;
567 {
568   CGEN_OPCODE_TABLE * table = (CGEN_OPCODE_TABLE *) xmalloc (sizeof (CGEN_OPCODE_TABLE));
569   static int init_p;
570
571   if (! init_p)
572     {
573       init_tables ();
574       init_p = 1;
575     }
576
577   memset (table, 0, sizeof (*table));
578
579   CGEN_OPCODE_MACH (table) = mach;
580   CGEN_OPCODE_ENDIAN (table) = endian;
581   /* FIXME: for the sparc case we can determine insn-endianness statically.
582      The worry here is where both data and insn endian can be independently
583      chosen, in which case this function will need another argument.
584      Actually, will want to allow for more arguments in the future anyway.  */
585   CGEN_OPCODE_INSN_ENDIAN (table) = endian;
586
587   CGEN_OPCODE_HW_LIST (table) = & fr30_cgen_hw_entries[0];
588
589   CGEN_OPCODE_OPERAND_TABLE (table) = & fr30_cgen_operand_table[0];
590
591   * CGEN_OPCODE_INSN_TABLE (table) = insn_table;
592
593   * CGEN_OPCODE_MACRO_INSN_TABLE (table) = macro_insn_table;
594
595   CGEN_OPCODE_ASM_HASH_P (table) = asm_hash_insn_p;
596   CGEN_OPCODE_ASM_HASH (table) = asm_hash_insn;
597   CGEN_OPCODE_ASM_HASH_SIZE (table) = CGEN_ASM_HASH_SIZE;
598
599   CGEN_OPCODE_DIS_HASH_P (table) = dis_hash_insn_p;
600   CGEN_OPCODE_DIS_HASH (table) = dis_hash_insn;
601   CGEN_OPCODE_DIS_HASH_SIZE (table) = CGEN_DIS_HASH_SIZE;
602
603   return (CGEN_OPCODE_DESC) table;
604 }
605
606 /* Close an opcode table.  */
607
608 void
609 fr30_cgen_opcode_close (desc)
610      CGEN_OPCODE_DESC desc;
611 {
612   free (desc);
613 }
614
615 /* Getting values from cgen_fields is handled by a collection of functions.
616    They are distinguished by the type of the VALUE argument they return.
617    TODO: floating point, inlining support, remove cases where result type
618    not appropriate.  */
619
620 int
621 fr30_cgen_get_int_operand (opindex, fields)
622      int opindex;
623      const CGEN_FIELDS * fields;
624 {
625   int value;
626
627   switch (opindex)
628     {
629     case FR30_OPERAND_RI :
630       value = fields->f_Ri;
631       break;
632     case FR30_OPERAND_RJ :
633       value = fields->f_Rj;
634       break;
635
636     default :
637       /* xgettext:c-format */
638       fprintf (stderr, _("Unrecognized field %d while getting int operand.\n"),
639                        opindex);
640       abort ();
641   }
642
643   return value;
644 }
645
646 bfd_vma
647 fr30_cgen_get_vma_operand (opindex, fields)
648      int opindex;
649      const CGEN_FIELDS * fields;
650 {
651   bfd_vma value;
652
653   switch (opindex)
654     {
655     case FR30_OPERAND_RI :
656       value = fields->f_Ri;
657       break;
658     case FR30_OPERAND_RJ :
659       value = fields->f_Rj;
660       break;
661
662     default :
663       /* xgettext:c-format */
664       fprintf (stderr, _("Unrecognized field %d while getting vma operand.\n"),
665                        opindex);
666       abort ();
667   }
668
669   return value;
670 }
671
672 /* Stuffing values in cgen_fields is handled by a collection of functions.
673    They are distinguished by the type of the VALUE argument they accept.
674    TODO: floating point, inlining support, remove cases where argument type
675    not appropriate.  */
676
677 void
678 fr30_cgen_set_int_operand (opindex, fields, value)
679      int opindex;
680      CGEN_FIELDS * fields;
681      int value;
682 {
683   switch (opindex)
684     {
685     case FR30_OPERAND_RI :
686       fields->f_Ri = value;
687       break;
688     case FR30_OPERAND_RJ :
689       fields->f_Rj = value;
690       break;
691
692     default :
693       /* xgettext:c-format */
694       fprintf (stderr, _("Unrecognized field %d while setting int operand.\n"),
695                        opindex);
696       abort ();
697   }
698 }
699
700 void
701 fr30_cgen_set_vma_operand (opindex, fields, value)
702      int opindex;
703      CGEN_FIELDS * fields;
704      bfd_vma value;
705 {
706   switch (opindex)
707     {
708     case FR30_OPERAND_RI :
709       fields->f_Ri = value;
710       break;
711     case FR30_OPERAND_RJ :
712       fields->f_Rj = value;
713       break;
714
715     default :
716       /* xgettext:c-format */
717       fprintf (stderr, _("Unrecognized field %d while setting vma operand.\n"),
718                        opindex);
719       abort ();
720   }
721 }
722