Thu Nov 12 19:21:57 1998 Dave Brolley <brolley@cygnus.com>
[deliverable/binutils-gdb.git] / opcodes / cgen-opc.in
CommitLineData
ab0bd049
DE
1/* Generic opcode table support for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
0499462e 4THIS FILE IS USED TO GENERATE @prefix@-opc.c.
ab0bd049
DE
5
6Copyright (C) 1998 Free Software Foundation, Inc.
7
8This file is part of the GNU Binutils and GDB, the GNU debugger.
9
10This program is free software; you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation; either version 2, or (at your option)
13any later version.
14
15This program is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
0499462e
DE
21along with this program; if not, write to the Free Software Foundation, Inc.,
2259 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
ab0bd049
DE
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"
0499462e 30#include "@prefix@-opc.h"
1e74d15c 31#include "opintl.h"
ab0bd049 32
c2009f4a
DE
33/* The hash functions are recorded here to help keep assembler code out of
34 the disassembler and vice versa. */
35
36static int asm_hash_insn_p PARAMS ((const CGEN_INSN *));
37static unsigned int asm_hash_insn PARAMS ((const char *));
38static int dis_hash_insn_p PARAMS ((const CGEN_INSN *));
39static unsigned int dis_hash_insn PARAMS ((const char *, unsigned long));
40
fcea6f20
DE
41/* Cover function to read and properly byteswap an insn value. */
42
43CGEN_INSN_INT
44cgen_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
77void
78cgen_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
ab0bd049 106/* Look up instruction INSN_VALUE and extract its fields.
2613b5e6 107 INSN, if non-null, is the insn table entry.
ab0bd049
DE
108 Otherwise INSN_VALUE is examined to compute it.
109 LENGTH is the bit length of INSN_VALUE if known, otherwise 0.
fcea6f20 110 0 is only valid if `insn == NULL && ! CGEN_INT_INSN_P'.
2613b5e6 111 If INSN != NULL, LENGTH must be valid.
390bd87d 112 ALIAS_P is non-zero if alias insns are to be included in the search.
2613b5e6 113
ab0bd049
DE
114 The result a pointer to the insn table entry, or NULL if the instruction
115 wasn't recognized. */
116
117const CGEN_INSN *
c2009f4a
DE
118@arch@_cgen_lookup_insn (od, insn, insn_value, length, fields, alias_p)
119 CGEN_OPCODE_DESC od;
ab0bd049 120 const CGEN_INSN *insn;
fcea6f20 121 CGEN_INSN_BYTES insn_value;
ab0bd049
DE
122 int length;
123 CGEN_FIELDS *fields;
2613b5e6 124 int alias_p;
ab0bd049 125{
fcea6f20
DE
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
ab0bd049
DE
141
142 if (!insn)
143 {
144 const CGEN_INSN_LIST *insn_list;
145
fcea6f20
DE
146#if CGEN_INT_INSN_P
147 cgen_put_insn_value (od, buf, length, insn_value);
148 bufp = buf;
149 base_insn = insn_value; /*???*/
ab0bd049 150#else
fcea6f20
DE
151 base_insn = cgen_get_insn_value (od, buf, length);
152 bufp = insn_value;
ab0bd049
DE
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
fcea6f20 158 insn_list = CGEN_DIS_LOOKUP_INSN (od, bufp, base_insn);
ab0bd049
DE
159 while (insn_list != NULL)
160 {
161 insn = insn_list->insn;
162
390bd87d
DE
163 if (alias_p
164 || ! CGEN_INSN_ATTR (insn, CGEN_INSN_ALIAS))
ab0bd049 165 {
390bd87d
DE
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 {
fbc8134d 171 /* ??? 0 is passed for `pc' */
fcea6f20 172 int elength = (*CGEN_EXTRACT_FN (insn)) (od, insn, info,
fbc8134d
DE
173 insn_value, fields,
174 (bfd_vma) 0);
2613b5e6
DE
175 if (elength > 0)
176 {
177 /* sanity check */
178 if (length != 0 && length != elength)
179 abort ();
180 return insn;
181 }
390bd87d 182 }
ab0bd049
DE
183 }
184
185 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
186 }
187 }
188 else
189 {
390bd87d
DE
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 ();
2613b5e6
DE
194 /* Sanity check: length must be correct. */
195 if (length != CGEN_INSN_BITSIZE (insn))
196 abort ();
390bd87d 197
fbc8134d 198 /* ??? 0 is passed for `pc' */
fcea6f20 199 length = (*CGEN_EXTRACT_FN (insn)) (od, insn, info, insn_value, fields,
fbc8134d 200 (bfd_vma) 0);
2613b5e6
DE
201 /* Sanity check: must succeed.
202 Could relax this later if it ever proves useful. */
203 if (length == 0)
204 abort ();
205 return insn;
ab0bd049
DE
206 }
207
208 return NULL;
209}
210
2613b5e6 211/* Fill in the operand instances used by INSN whose operands are FIELDS.
bed9a23c 212 INDICES is a pointer to a buffer of MAX_OPERAND_INSTANCES ints to be filled
2613b5e6 213 in. */
ab0bd049 214
2613b5e6 215void
c2009f4a
DE
216@arch@_cgen_get_insn_operands (od, insn, fields, indices)
217 CGEN_OPCODE_DESC od;
2613b5e6
DE
218 const CGEN_INSN * insn;
219 const CGEN_FIELDS * fields;
ab0bd049
DE
220 int *indices;
221{
ab0bd049
DE
222 const CGEN_OPERAND_INSTANCE *opinst;
223 int i;
224
ab0bd049 225 for (i = 0, opinst = CGEN_INSN_OPERANDS (insn);
b2f18612
DE
226 opinst != NULL
227 && CGEN_OPERAND_INSTANCE_TYPE (opinst) != CGEN_OPERAND_INSTANCE_END;
ab0bd049
DE
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
fbc8134d
DE
234 indices[i] = @arch@_cgen_get_int_operand (CGEN_OPERAND_INDEX (op),
235 fields);
ab0bd049 236 }
2613b5e6
DE
237}
238
239/* Cover function to @arch@_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 @arch@_cgen_lookup_insn unchanged.
243
244 The result is the insn table entry or NULL if the instruction wasn't
245 recognized. */
246
247const CGEN_INSN *
c2009f4a
DE
248@arch@_cgen_lookup_get_insn_operands (od, insn, insn_value, length, indices)
249 CGEN_OPCODE_DESC od;
2613b5e6 250 const CGEN_INSN *insn;
fcea6f20 251 CGEN_INSN_BYTES insn_value;
2613b5e6
DE
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. */
c2009f4a 259 insn = @arch@_cgen_lookup_insn (od, insn, insn_value, length, &fields,
2613b5e6
DE
260 insn != NULL);
261 if (! insn)
262 return NULL;
ab0bd049 263
c2009f4a 264 @arch@_cgen_get_insn_operands (od, insn, &fields, indices);
ab0bd049
DE
265 return insn;
266}
This page took 0.135944 seconds and 4 git commands to generate.