]> Git Repo - binutils.git/blob - opcodes/cgen-opc.in
Thu Nov 26 11:26:32 1998 Dave Brolley <[email protected]>
[binutils.git] / opcodes / cgen-opc.in
1 /* Generic opcode table support for targets using CGEN. -*- C -*-
2    CGEN: Cpu tools GENerator
3
4 THIS FILE IS USED TO GENERATE @[email protected].
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 "@[email protected]"
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 *, CGEN_INSN_INT));
40
41 /* Look up instruction INSN_VALUE and extract its fields.
42    INSN, if non-null, is the insn table entry.
43    Otherwise INSN_VALUE is examined to compute it.
44    LENGTH is the bit length of INSN_VALUE if known, otherwise 0.
45    0 is only valid if `insn == NULL && ! CGEN_INT_INSN_P'.
46    If INSN != NULL, LENGTH must be valid.
47    ALIAS_P is non-zero if alias insns are to be included in the search.
48
49    The result is a pointer to the insn table entry, or NULL if the instruction
50    wasn't recognized.  */
51
52 const CGEN_INSN *
53 @arch@_cgen_lookup_insn (od, insn, insn_value, length, fields, alias_p)
54      CGEN_OPCODE_DESC od;
55      const CGEN_INSN *insn;
56      CGEN_INSN_BYTES insn_value;
57      int length;
58      CGEN_FIELDS *fields;
59      int alias_p;
60 {
61   unsigned char buf[CGEN_MAX_INSN_SIZE];
62   unsigned char *bufp;
63   CGEN_INSN_INT base_insn;
64 #if CGEN_INT_INSN_P
65   CGEN_EXTRACT_INFO *info = NULL;
66 #else
67   CGEN_EXTRACT_INFO ex_info;
68   CGEN_EXTRACT_INFO *info = &ex_info;
69 #endif
70
71 #if CGEN_INT_INSN_P
72   cgen_put_insn_value (od, buf, length, insn_value);
73   bufp = buf;
74   base_insn = insn_value; /*???*/
75 #else
76   ex_info.dis_info = NULL;
77   ex_info.insn_bytes = insn_value;
78   ex_info.valid = -1;
79   base_insn = cgen_get_insn_value (od, buf, length);
80   bufp = insn_value;
81 #endif
82
83   if (!insn)
84     {
85       const CGEN_INSN_LIST *insn_list;
86
87       /* The instructions are stored in hash lists.
88          Pick the first one and keep trying until we find the right one.  */
89
90       insn_list = CGEN_DIS_LOOKUP_INSN (od, bufp, base_insn);
91       while (insn_list != NULL)
92         {
93           insn = insn_list->insn;
94
95           if (alias_p
96               || ! CGEN_INSN_ATTR (insn, CGEN_INSN_ALIAS))
97             {
98               /* Basic bit mask must be correct.  */
99               /* ??? May wish to allow target to defer this check until the
100                  extract handler.  */
101               if ((base_insn & CGEN_INSN_MASK (insn)) == CGEN_INSN_VALUE (insn))
102                 {
103                   /* ??? 0 is passed for `pc' */
104                   int elength = (*CGEN_EXTRACT_FN (insn)) (od, insn, info,
105                                                            base_insn, fields,
106                                                            (bfd_vma) 0);
107                   if (elength > 0)
108                     {
109                       /* sanity check */
110                       if (length != 0 && length != elength)
111                         abort ();
112                       return insn;
113                     }
114                 }
115             }
116
117           insn_list = CGEN_DIS_NEXT_INSN (insn_list);
118         }
119     }
120   else
121     {
122       /* Sanity check: can't pass an alias insn if ! alias_p.  */
123       if (! alias_p
124           && CGEN_INSN_ATTR (insn, CGEN_INSN_ALIAS))
125         abort ();
126       /* Sanity check: length must be correct.  */
127       if (length != CGEN_INSN_BITSIZE (insn))
128         abort ();
129
130       /* ??? 0 is passed for `pc' */
131       length = (*CGEN_EXTRACT_FN (insn)) (od, insn, info, base_insn, fields,
132                                           (bfd_vma) 0);
133       /* Sanity check: must succeed.
134          Could relax this later if it ever proves useful.  */
135       if (length == 0)
136         abort ();
137       return insn;
138     }
139
140   return NULL;
141 }
142
143 /* Fill in the operand instances used by INSN whose operands are FIELDS.
144    INDICES is a pointer to a buffer of MAX_OPERAND_INSTANCES ints to be filled
145    in.  */
146
147 void
148 @arch@_cgen_get_insn_operands (od, insn, fields, indices)
149      CGEN_OPCODE_DESC od;
150      const CGEN_INSN * insn;
151      const CGEN_FIELDS * fields;
152      int *indices;
153 {
154   const CGEN_OPERAND_INSTANCE *opinst;
155   int i;
156
157   for (i = 0, opinst = CGEN_INSN_OPERANDS (insn);
158        opinst != NULL
159          && CGEN_OPERAND_INSTANCE_TYPE (opinst) != CGEN_OPERAND_INSTANCE_END;
160        ++i, ++opinst)
161     {
162       const CGEN_OPERAND *op = CGEN_OPERAND_INSTANCE_OPERAND (opinst);
163       if (op == NULL)
164         indices[i] = CGEN_OPERAND_INSTANCE_INDEX (opinst);
165       else
166         indices[i] = @arch@_cgen_get_int_operand (CGEN_OPERAND_INDEX (op),
167                                                   fields);
168     }
169 }
170
171 /* Cover function to @arch@_cgen_get_insn_operands when either INSN or FIELDS
172    isn't known.
173    The INSN, INSN_VALUE, and LENGTH arguments are passed to
174    @arch@_cgen_lookup_insn unchanged.
175
176    The result is the insn table entry or NULL if the instruction wasn't
177    recognized.  */
178
179 const CGEN_INSN *
180 @arch@_cgen_lookup_get_insn_operands (od, insn, insn_value, length, indices)
181      CGEN_OPCODE_DESC od;
182      const CGEN_INSN *insn;
183      CGEN_INSN_BYTES insn_value;
184      int length;
185      int *indices;
186 {
187   CGEN_FIELDS fields;
188
189   /* Pass non-zero for ALIAS_P only if INSN != NULL.
190      If INSN == NULL, we want a real insn.  */
191   insn = @arch@_cgen_lookup_insn (od, insn, insn_value, length, &fields,
192                                   insn != NULL);
193   if (! insn)
194     return NULL;
195
196   @arch@_cgen_get_insn_operands (od, insn, &fields, indices);
197   return insn;
198 }
This page took 0.033706 seconds and 4 git commands to generate.