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