* cgen.h (<cpu>_cgen_assemble_insn): New arg for errmsg.
[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
DE
34/* Operand parsing callback. */
35const char * (*cgen_asm_parse_operand_fn)
36 PARAMS ((const char **, int, int, enum cgen_asm_result *, bfd_vma *));
37
9c03036a
DE
38/* This is not published as part of the public interface so we don't
39 declare this in cgen.h. */
40extern CGEN_OPCODE_DATA *cgen_current_opcode_data;
41
42/* Assembler instruction hash table. */
43static CGEN_INSN_LIST **asm_hash_table;
44
45void
46cgen_asm_init ()
47{
48 if (asm_hash_table)
49 {
50 free (asm_hash_table);
51 asm_hash_table = NULL;
52 }
53}
54
55/* Build the assembler instruction hash table. */
56
57static void
58build_asm_hash_table ()
59{
60 int i;
61 unsigned int hash;
62 int count = cgen_insn_count ();
63 CGEN_OPCODE_DATA *data = cgen_current_opcode_data;
64 CGEN_INSN_TABLE *insn_table = data->insn_table;
65 unsigned int hash_size = insn_table->asm_hash_table_size;
66 const CGEN_INSN *insn;
67 CGEN_INSN_LIST *insn_lists,*new_insns;
68
69 /* The space allocated for the hash table consists of two parts:
70 the hash table and the hash lists. */
71
72 asm_hash_table = (CGEN_INSN_LIST **)
73 xmalloc (hash_size * sizeof (CGEN_INSN_LIST *)
74 + count * sizeof (CGEN_INSN_LIST));
75 memset (asm_hash_table, 0,
76 hash_size * sizeof (CGEN_INSN_LIST *)
77 + count * sizeof (CGEN_INSN_LIST));
78 insn_lists = (CGEN_INSN_LIST *) (asm_hash_table + hash_size);
79
80 /* Add compiled in insns.
81 The table is scanned backwards as later additions are inserted in
82 front of earlier ones and we want earlier ones to be prefered.
83 We stop at the first one as it is a reserved entry. */
84
85 for (insn = insn_table->init_entries + insn_table->num_init_entries - 1;
86 insn > insn_table->init_entries;
87 --insn, ++insn_lists)
88 {
89 hash = (*insn_table->asm_hash) (insn->syntax.mnemonic);
90 insn_lists->next = asm_hash_table[hash];
91 insn_lists->insn = insn;
92 asm_hash_table[hash] = insn_lists;
93 }
94
95 /* Add runtime added insns.
96 ??? Currently later added insns will be prefered over earlier ones.
97 Not sure this is a bug or not. */
98 for (new_insns = insn_table->new_entries;
99 new_insns != NULL;
100 new_insns = new_insns->next, ++insn_lists)
101 {
102 hash = (*insn_table->asm_hash) (new_insns->insn->syntax.mnemonic);
103 insn_lists->next = asm_hash_table[hash];
104 insn_lists->insn = new_insns->insn;
105 asm_hash_table[hash] = insn_lists;
106 }
107}
108
109/* Return the first entry in the hash list for INSN. */
110
111CGEN_INSN_LIST *
112cgen_asm_lookup_insn (insn)
113 const char *insn;
114{
115 unsigned int hash;
116
117 if (asm_hash_table == NULL)
118 build_asm_hash_table ();
119
120 hash = (*cgen_current_opcode_data->insn_table->asm_hash) (insn);
121 return asm_hash_table[hash];
122}
123\f
124/* Keyword parser.
125 The result is NULL upon success or an error message.
126 If successful, *STRP is updated to point passed the keyword.
127
128 ??? At present we have a static notion of how to pick out a keyword.
129 Later we can allow a target to customize this if necessary [say by
130 recording something in the keyword table]. */
131
132const char *
133cgen_parse_keyword (strp, keyword_table, valuep)
134 const char **strp;
135 struct cgen_keyword *keyword_table;
136 long *valuep;
137{
138 const struct cgen_keyword_entry *ke;
139 char buf[256];
140 const char *p;
141
142 p = *strp;
143
144 /* Allow any first character. */
145 if (*p)
146 ++p;
147
148 /* Now allow letters, digits, and _. */
149 while (isalnum (*p) || *p == '_')
150 ++p;
151
152 if (p - *strp > 255)
153 return "unrecognized keyword/register name";
154
155 memcpy (buf, *strp, p - *strp);
156 buf[p - *strp] = 0;
157
158 ke = cgen_keyword_lookup_name (keyword_table, buf);
159
160 if (ke != NULL)
161 {
162 *valuep = ke->value;
163 *strp = p;
164 return NULL;
165 }
166
167 return "unrecognized keyword/register name";
168}
169
170/* Signed integer parser. */
171
172const char *
173cgen_parse_signed_integer (strp, opindex, min, max, valuep)
174 const char **strp;
175 int opindex;
176 long min, max;
177 long *valuep;
178{
179 long value;
180 enum cgen_asm_result result;
181 const char *errmsg;
182
5b3b8cb0
DE
183 errmsg = (*cgen_asm_parse_operand_fn) (strp, opindex, BFD_RELOC_NONE,
184 &result, &value);
9c03036a
DE
185 /* FIXME: Examine `result'. */
186 if (!errmsg)
187 {
188 if (value < min || value > max)
189 return "integer operand out of range";
190 *valuep = value;
191 }
192 return errmsg;
193}
194
195/* Unsigned integer parser. */
196
197const char *
198cgen_parse_unsigned_integer (strp, opindex, min, max, valuep)
199 const char **strp;
200 int opindex;
201 unsigned long min, max;
202 unsigned long *valuep;
203{
204 unsigned long value;
205 enum cgen_asm_result result;
206 const char *errmsg;
207
5b3b8cb0
DE
208 errmsg = (*cgen_asm_parse_operand_fn) (strp, opindex, BFD_RELOC_NONE,
209 &result, &value);
9c03036a
DE
210 /* FIXME: Examine `result'. */
211 if (!errmsg)
212 {
213 if (value < min || value > max)
214 return "integer operand out of range";
215 *valuep = value;
216 }
217 return errmsg;
218}
219
220/* Address parser. */
221
222const char *
223cgen_parse_address (strp, opindex, opinfo, valuep)
224 const char **strp;
225 int opindex;
226 int opinfo;
227 long *valuep;
228{
229 long value;
230 enum cgen_asm_result result;
231 const char *errmsg;
232
5b3b8cb0
DE
233 errmsg = (*cgen_asm_parse_operand_fn) (strp, opindex, opinfo,
234 &result, &value);
9c03036a
DE
235 /* FIXME: Examine `result'. */
236 if (!errmsg)
237 {
238 *valuep = value;
239 }
240 return errmsg;
241}
242\f
243/* Signed integer validation routine. */
244
245const char *
246cgen_validate_signed_integer (value, min, max)
247 long value, min, max;
248{
249 if (value < min || value > max)
250 {
251 const char *err =
252 "operand out of range (%ld not between %ld and %ld)";
253 static char buf[100];
254
255 sprintf (buf, err, value, min, max);
256 return buf;
257 }
258
259 return NULL;
260}
261
262/* Unsigned integer validation routine.
263 Supplying `min' here may seem unnecessary, but we also want to handle
264 cases where min != 0 (and max > LONG_MAX). */
265
266const char *
267cgen_validate_unsigned_integer (value, min, max)
268 unsigned long value, min, max;
269{
270 if (value < min || value > max)
271 {
272 const char *err =
273 "operand out of range (%lu not between %lu and %lu)";
274 static char buf[100];
275
276 sprintf (buf, err, value, min, max);
277 return buf;
278 }
279
280 return NULL;
281}
This page took 0.035541 seconds and 4 git commands to generate.