* cgen-asm.c (cgen_parse_operand_fn): New global.
[deliverable/binutils-gdb.git] / opcodes / cgen-asm.c
CommitLineData
9c03036a
DE
1/* CGEN generic assembler support code.
2
3Copyright (C) 1996, 1997 Free Software Foundation, Inc.
4
5This file is part of the GNU Binutils and GDB, the GNU debugger.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License along
18with this program; if not, write to the Free Software Foundation, Inc.,
1959 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21#include "config.h"
22#include <stdio.h>
23#ifdef HAVE_STRING_H
24#include <string.h>
25#endif
26#ifdef HAVE_STRINGS_H
27#include <strings.h>
28#endif
29#include "ansidecl.h"
30#include "libiberty.h"
31#include "bfd.h"
32#include "opcode/cgen.h"
33
5b3b8cb0 34/* Operand parsing callback. */
a394e326
DE
35const char * (*cgen_parse_operand_fn)
36 PARAMS ((enum cgen_parse_operand_type, const char **, int, int,
37 enum cgen_parse_operand_result *, bfd_vma *));
5b3b8cb0 38
9c03036a
DE
39/* This is not published as part of the public interface so we don't
40 declare this in cgen.h. */
41extern CGEN_OPCODE_DATA *cgen_current_opcode_data;
42
43/* Assembler instruction hash table. */
44static CGEN_INSN_LIST **asm_hash_table;
45
a394e326
DE
46/* Called once at startup and whenever machine/endian change. */
47
9c03036a
DE
48void
49cgen_asm_init ()
50{
51 if (asm_hash_table)
52 {
53 free (asm_hash_table);
54 asm_hash_table = NULL;
55 }
56}
57
a394e326
DE
58/* Called whenever starting to parse an insn. */
59
60void
61cgen_init_parse_operand ()
62{
63 /* This tells the callback to re-initialize. */
64 (void) (*cgen_parse_operand_fn) (CGEN_PARSE_OPERAND_INIT, NULL, 0, 0,
65 NULL, NULL);
66}
67
9c03036a
DE
68/* Build the assembler instruction hash table. */
69
70static void
71build_asm_hash_table ()
72{
73 int i;
74 unsigned int hash;
75 int count = cgen_insn_count ();
76 CGEN_OPCODE_DATA *data = cgen_current_opcode_data;
77 CGEN_INSN_TABLE *insn_table = data->insn_table;
78 unsigned int hash_size = insn_table->asm_hash_table_size;
79 const CGEN_INSN *insn;
80 CGEN_INSN_LIST *insn_lists,*new_insns;
81
82 /* The space allocated for the hash table consists of two parts:
83 the hash table and the hash lists. */
84
85 asm_hash_table = (CGEN_INSN_LIST **)
86 xmalloc (hash_size * sizeof (CGEN_INSN_LIST *)
87 + count * sizeof (CGEN_INSN_LIST));
88 memset (asm_hash_table, 0,
89 hash_size * sizeof (CGEN_INSN_LIST *)
90 + count * sizeof (CGEN_INSN_LIST));
91 insn_lists = (CGEN_INSN_LIST *) (asm_hash_table + hash_size);
92
93 /* Add compiled in insns.
94 The table is scanned backwards as later additions are inserted in
95 front of earlier ones and we want earlier ones to be prefered.
96 We stop at the first one as it is a reserved entry. */
97
98 for (insn = insn_table->init_entries + insn_table->num_init_entries - 1;
99 insn > insn_table->init_entries;
100 --insn, ++insn_lists)
101 {
102 hash = (*insn_table->asm_hash) (insn->syntax.mnemonic);
103 insn_lists->next = asm_hash_table[hash];
104 insn_lists->insn = insn;
105 asm_hash_table[hash] = insn_lists;
106 }
107
108 /* Add runtime added insns.
109 ??? Currently later added insns will be prefered over earlier ones.
110 Not sure this is a bug or not. */
111 for (new_insns = insn_table->new_entries;
112 new_insns != NULL;
113 new_insns = new_insns->next, ++insn_lists)
114 {
115 hash = (*insn_table->asm_hash) (new_insns->insn->syntax.mnemonic);
116 insn_lists->next = asm_hash_table[hash];
117 insn_lists->insn = new_insns->insn;
118 asm_hash_table[hash] = insn_lists;
119 }
120}
121
122/* Return the first entry in the hash list for INSN. */
123
124CGEN_INSN_LIST *
125cgen_asm_lookup_insn (insn)
126 const char *insn;
127{
128 unsigned int hash;
129
130 if (asm_hash_table == NULL)
131 build_asm_hash_table ();
132
133 hash = (*cgen_current_opcode_data->insn_table->asm_hash) (insn);
134 return asm_hash_table[hash];
135}
136\f
137/* Keyword parser.
138 The result is NULL upon success or an error message.
139 If successful, *STRP is updated to point passed the keyword.
140
141 ??? At present we have a static notion of how to pick out a keyword.
142 Later we can allow a target to customize this if necessary [say by
143 recording something in the keyword table]. */
144
145const char *
146cgen_parse_keyword (strp, keyword_table, valuep)
147 const char **strp;
148 struct cgen_keyword *keyword_table;
149 long *valuep;
150{
151 const struct cgen_keyword_entry *ke;
152 char buf[256];
153 const char *p;
154
155 p = *strp;
156
157 /* Allow any first character. */
158 if (*p)
159 ++p;
160
161 /* Now allow letters, digits, and _. */
162 while (isalnum (*p) || *p == '_')
163 ++p;
164
165 if (p - *strp > 255)
166 return "unrecognized keyword/register name";
167
168 memcpy (buf, *strp, p - *strp);
169 buf[p - *strp] = 0;
170
171 ke = cgen_keyword_lookup_name (keyword_table, buf);
172
173 if (ke != NULL)
174 {
175 *valuep = ke->value;
176 *strp = p;
177 return NULL;
178 }
179
180 return "unrecognized keyword/register name";
181}
182
183/* Signed integer parser. */
184
185const char *
186cgen_parse_signed_integer (strp, opindex, min, max, valuep)
187 const char **strp;
188 int opindex;
189 long min, max;
190 long *valuep;
191{
192 long value;
a394e326 193 enum cgen_parse_operand_result result;
9c03036a
DE
194 const char *errmsg;
195
a394e326
DE
196 errmsg = (*cgen_parse_operand_fn) (CGEN_PARSE_OPERAND_INTEGER, strp,
197 opindex, BFD_RELOC_NONE,
198 &result, &value);
9c03036a
DE
199 /* FIXME: Examine `result'. */
200 if (!errmsg)
201 {
202 if (value < min || value > max)
203 return "integer operand out of range";
204 *valuep = value;
205 }
206 return errmsg;
207}
208
209/* Unsigned integer parser. */
210
211const char *
212cgen_parse_unsigned_integer (strp, opindex, min, max, valuep)
213 const char **strp;
214 int opindex;
215 unsigned long min, max;
216 unsigned long *valuep;
217{
218 unsigned long value;
a394e326 219 enum cgen_parse_operand_result result;
9c03036a
DE
220 const char *errmsg;
221
a394e326
DE
222 errmsg = (*cgen_parse_operand_fn) (CGEN_PARSE_OPERAND_INTEGER, strp,
223 opindex, BFD_RELOC_NONE,
224 &result, &value);
9c03036a
DE
225 /* FIXME: Examine `result'. */
226 if (!errmsg)
227 {
228 if (value < min || value > max)
229 return "integer operand out of range";
230 *valuep = value;
231 }
232 return errmsg;
233}
234
235/* Address parser. */
236
237const char *
238cgen_parse_address (strp, opindex, opinfo, valuep)
239 const char **strp;
240 int opindex;
241 int opinfo;
242 long *valuep;
243{
244 long value;
a394e326 245 enum cgen_parse_operand_result result;
9c03036a
DE
246 const char *errmsg;
247
a394e326
DE
248 errmsg = (*cgen_parse_operand_fn) (CGEN_PARSE_OPERAND_ADDRESS, strp,
249 opindex, opinfo,
250 &result, &value);
9c03036a
DE
251 /* FIXME: Examine `result'. */
252 if (!errmsg)
253 {
254 *valuep = value;
255 }
256 return errmsg;
257}
258\f
259/* Signed integer validation routine. */
260
261const char *
262cgen_validate_signed_integer (value, min, max)
263 long value, min, max;
264{
265 if (value < min || value > max)
266 {
267 const char *err =
268 "operand out of range (%ld not between %ld and %ld)";
269 static char buf[100];
270
271 sprintf (buf, err, value, min, max);
272 return buf;
273 }
274
275 return NULL;
276}
277
278/* Unsigned integer validation routine.
279 Supplying `min' here may seem unnecessary, but we also want to handle
280 cases where min != 0 (and max > LONG_MAX). */
281
282const char *
283cgen_validate_unsigned_integer (value, min, max)
284 unsigned long value, min, max;
285{
286 if (value < min || value > max)
287 {
288 const char *err =
289 "operand out of range (%lu not between %lu and %lu)";
290 static char buf[100];
291
292 sprintf (buf, err, value, min, max);
293 return buf;
294 }
295
296 return NULL;
297}
This page took 0.034413 seconds and 4 git commands to generate.