* po/Make-in (install-info): New target.
[deliverable/binutils-gdb.git] / opcodes / cgen-asm.c
CommitLineData
9c03036a
DE
1/* CGEN generic assembler support code.
2
2613b5e6 3 Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
9c03036a 4
2613b5e6 5 This file is part of the GNU Binutils and GDB, the GNU debugger.
9c03036a 6
2613b5e6
DE
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
9c03036a 11
2613b5e6
DE
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
9c03036a 16
2613b5e6
DE
17 You should have received a copy of the GNU General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
9c03036a 20
2613b5e6 21#include "sysdep.h"
9c03036a 22#include <stdio.h>
2613b5e6 23#include <ctype.h>
9c03036a
DE
24#include "ansidecl.h"
25#include "libiberty.h"
26#include "bfd.h"
2613b5e6 27#include "symcat.h"
9c03036a 28#include "opcode/cgen.h"
240f5c9f 29#include "opintl.h"
9c03036a 30
5b3b8cb0 31/* Operand parsing callback. */
a394e326
DE
32const char * (*cgen_parse_operand_fn)
33 PARAMS ((enum cgen_parse_operand_type, const char **, int, int,
34 enum cgen_parse_operand_result *, bfd_vma *));
5b3b8cb0 35
9c03036a
DE
36/* This is not published as part of the public interface so we don't
37 declare this in cgen.h. */
2613b5e6 38extern CGEN_OPCODE_TABLE *cgen_current_opcode_table;
9c03036a
DE
39
40/* Assembler instruction hash table. */
41static CGEN_INSN_LIST **asm_hash_table;
2613b5e6 42static CGEN_INSN_LIST *asm_hash_table_entries;
9c03036a 43
a394e326
DE
44/* Called once at startup and whenever machine/endian change. */
45
9c03036a
DE
46void
47cgen_asm_init ()
48{
49 if (asm_hash_table)
50 {
51 free (asm_hash_table);
2613b5e6 52 free (asm_hash_table_entries);
9c03036a 53 asm_hash_table = NULL;
2613b5e6 54 asm_hash_table_entries = NULL;
9c03036a
DE
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
2613b5e6
DE
68/* Subroutine of build_asm_hash_table to add INSNS to the hash table.
69
70 COUNT is the number of elements in INSNS.
71 ENTSIZE is sizeof (CGEN_INSN) for the target.
72 This is a bit tricky as the size of the attribute member of CGEN_INSN
73 is variable among architectures. This code could be moved to
74 cgen-asm.in, but I prefer to keep it here for now.
75 OTABLE is the opcode table.
76 HTABLE points to the hash table.
77 HENTBUF is a pointer to sufficiently large buffer of hash entries.
78 The result is a pointer to the next entry to use.
79
80 The table is scanned backwards as additions are made to the front of the
81 list and we want earlier ones to be prefered. */
82
83static CGEN_INSN_LIST *
84hash_insn_array (insns, count, entsize, otable, htable, hentbuf)
85 const CGEN_INSN * insns;
86 int count;
87 int entsize;
88 const CGEN_OPCODE_TABLE * otable;
89 CGEN_INSN_LIST ** htable;
90 CGEN_INSN_LIST * hentbuf;
91{
92 const CGEN_INSN * insn;
93
94 for (insn = (CGEN_INSN *) ((char *) insns + entsize * (count - 1));
95 insn >= insns;
96 insn = (CGEN_INSN *) ((char *) insn - entsize), ++ hentbuf)
97 {
98 unsigned int hash;
99
100 if (! (*otable->asm_hash_p) (insn))
101 continue;
102 hash = (*otable->asm_hash) (CGEN_INSN_MNEMONIC (insn));
103 hentbuf->next = htable[hash];
104 hentbuf->insn = insn;
105 htable[hash] = hentbuf;
106 }
107
108 return hentbuf;
109}
110
111/* Subroutine of build_asm_hash_table to add INSNS to the hash table.
112 This function is identical to hash_insn_array except the insns are
113 in a list. */
114
115static CGEN_INSN_LIST *
116hash_insn_list (insns, otable, htable, hentbuf)
117 const CGEN_INSN_LIST * insns;
118 const CGEN_OPCODE_TABLE * otable;
119 CGEN_INSN_LIST ** htable;
120 CGEN_INSN_LIST * hentbuf;
121{
122 const CGEN_INSN_LIST * ilist;
123
124 for (ilist = insns; ilist != NULL; ilist = ilist->next, ++ hentbuf)
125 {
126 unsigned int hash;
127
128 if (! (*otable->asm_hash_p) (ilist->insn))
129 continue;
130 hash = (*otable->asm_hash) (CGEN_INSN_MNEMONIC (ilist->insn));
131 hentbuf->next = htable[hash];
132 hentbuf->insn = ilist->insn;
133 asm_hash_table[hash] = hentbuf;
134 }
135
136 return hentbuf;
137}
138
9c03036a
DE
139/* Build the assembler instruction hash table. */
140
141static void
142build_asm_hash_table ()
143{
2613b5e6
DE
144 int count = cgen_insn_count () + cgen_macro_insn_count ();
145 CGEN_OPCODE_TABLE *opcode_table = cgen_current_opcode_table;
146 CGEN_INSN_TABLE *insn_table = opcode_table->insn_table;
147 CGEN_INSN_TABLE *macro_insn_table = opcode_table->macro_insn_table;
148 unsigned int hash_size = opcode_table->asm_hash_table_size;
149 CGEN_INSN_LIST *hash_entry_buf;
9c03036a
DE
150
151 /* The space allocated for the hash table consists of two parts:
152 the hash table and the hash lists. */
153
154 asm_hash_table = (CGEN_INSN_LIST **)
2613b5e6
DE
155 xmalloc (hash_size * sizeof (CGEN_INSN_LIST *));
156 memset (asm_hash_table, 0, hash_size * sizeof (CGEN_INSN_LIST *));
157 asm_hash_table_entries = hash_entry_buf = (CGEN_INSN_LIST *)
158 xmalloc (count * sizeof (CGEN_INSN_LIST));
9c03036a
DE
159
160 /* Add compiled in insns.
2613b5e6
DE
161 Don't include the first one as it is a reserved entry. */
162 /* ??? It was the end of all hash chains, and also the special
163 "illegal insn" marker. May be able to do it differently now. */
9c03036a 164
2613b5e6
DE
165 hash_entry_buf = hash_insn_array ((CGEN_INSN *) ((char *) insn_table->init_entries
166 + insn_table->entry_size),
167 insn_table->num_init_entries - 1,
168 insn_table->entry_size,
169 opcode_table, asm_hash_table, hash_entry_buf);
170
171 /* Add compiled in macro-insns. */
172
173 hash_entry_buf = hash_insn_array (macro_insn_table->init_entries,
174 macro_insn_table->num_init_entries,
175 macro_insn_table->entry_size,
176 opcode_table, asm_hash_table, hash_entry_buf);
9c03036a
DE
177
178 /* Add runtime added insns.
2613b5e6
DE
179 Later added insns will be prefered over earlier ones. */
180
181 hash_entry_buf = hash_insn_list (insn_table->new_entries, opcode_table,
182 asm_hash_table, hash_entry_buf);
183
184 /* Add runtime added macro-insns. */
185
186 hash_insn_list (macro_insn_table->new_entries,
187 opcode_table, asm_hash_table, hash_entry_buf);
9c03036a
DE
188}
189
2613b5e6
DE
190/* Return the first entry in the hash list for INSN.
191 ??? Of course it would be better to pass in a pointer to the
192 opcode data structure, rather than reference a global. Later. */
9c03036a
DE
193
194CGEN_INSN_LIST *
195cgen_asm_lookup_insn (insn)
196 const char *insn;
197{
198 unsigned int hash;
199
200 if (asm_hash_table == NULL)
201 build_asm_hash_table ();
202
2613b5e6 203 hash = (*cgen_current_opcode_table->asm_hash) (insn);
9c03036a
DE
204 return asm_hash_table[hash];
205}
206\f
207/* Keyword parser.
208 The result is NULL upon success or an error message.
209 If successful, *STRP is updated to point passed the keyword.
210
211 ??? At present we have a static notion of how to pick out a keyword.
212 Later we can allow a target to customize this if necessary [say by
213 recording something in the keyword table]. */
214
215const char *
216cgen_parse_keyword (strp, keyword_table, valuep)
217 const char **strp;
2613b5e6 218 CGEN_KEYWORD *keyword_table;
9c03036a
DE
219 long *valuep;
220{
2613b5e6 221 const CGEN_KEYWORD_ENTRY *ke;
9c03036a 222 char buf[256];
2613b5e6 223 const char *p,*start;
9c03036a 224
2613b5e6 225 p = start = *strp;
9c03036a 226
2613b5e6
DE
227 /* Allow any first character.
228 Note that this allows recognizing ",a" for the annul flag in sparc
229 even though "," is subsequently not a valid keyword char. */
9c03036a
DE
230 if (*p)
231 ++p;
232
233 /* Now allow letters, digits, and _. */
2613b5e6
DE
234 while (((p - start) < (int) sizeof (buf))
235 && (isalnum ((unsigned char) *p) || *p == '_'))
9c03036a
DE
236 ++p;
237
2613b5e6 238 if (p - start >= (int) sizeof (buf))
240f5c9f 239 return _("unrecognized keyword/register name");
9c03036a 240
2613b5e6
DE
241 memcpy (buf, start, p - start);
242 buf[p - start] = 0;
9c03036a
DE
243
244 ke = cgen_keyword_lookup_name (keyword_table, buf);
245
246 if (ke != NULL)
247 {
248 *valuep = ke->value;
2613b5e6
DE
249 /* Don't advance pointer if we recognized the null keyword. */
250 if (ke->name[0] != 0)
251 *strp = p;
9c03036a
DE
252 return NULL;
253 }
254
255 return "unrecognized keyword/register name";
256}
257
258/* Signed integer parser. */
259
260const char *
2613b5e6 261cgen_parse_signed_integer (strp, opindex, valuep)
9c03036a
DE
262 const char **strp;
263 int opindex;
9c03036a
DE
264 long *valuep;
265{
2613b5e6 266 bfd_vma value;
a394e326 267 enum cgen_parse_operand_result result;
9c03036a
DE
268 const char *errmsg;
269
a394e326
DE
270 errmsg = (*cgen_parse_operand_fn) (CGEN_PARSE_OPERAND_INTEGER, strp,
271 opindex, BFD_RELOC_NONE,
272 &result, &value);
9c03036a
DE
273 /* FIXME: Examine `result'. */
274 if (!errmsg)
2613b5e6 275 *valuep = value;
9c03036a
DE
276 return errmsg;
277}
278
279/* Unsigned integer parser. */
280
281const char *
2613b5e6 282cgen_parse_unsigned_integer (strp, opindex, valuep)
9c03036a
DE
283 const char **strp;
284 int opindex;
9c03036a
DE
285 unsigned long *valuep;
286{
2613b5e6 287 bfd_vma value;
a394e326 288 enum cgen_parse_operand_result result;
9c03036a
DE
289 const char *errmsg;
290
a394e326
DE
291 errmsg = (*cgen_parse_operand_fn) (CGEN_PARSE_OPERAND_INTEGER, strp,
292 opindex, BFD_RELOC_NONE,
293 &result, &value);
9c03036a
DE
294 /* FIXME: Examine `result'. */
295 if (!errmsg)
2613b5e6 296 *valuep = value;
9c03036a
DE
297 return errmsg;
298}
299
300/* Address parser. */
301
302const char *
2613b5e6 303cgen_parse_address (strp, opindex, opinfo, resultp, valuep)
9c03036a
DE
304 const char **strp;
305 int opindex;
306 int opinfo;
2613b5e6 307 enum cgen_parse_operand_result *resultp;
9c03036a
DE
308 long *valuep;
309{
2613b5e6
DE
310 bfd_vma value;
311 enum cgen_parse_operand_result result_type;
9c03036a
DE
312 const char *errmsg;
313
a394e326
DE
314 errmsg = (*cgen_parse_operand_fn) (CGEN_PARSE_OPERAND_ADDRESS, strp,
315 opindex, opinfo,
2613b5e6 316 &result_type, &value);
9c03036a
DE
317 /* FIXME: Examine `result'. */
318 if (!errmsg)
319 {
2613b5e6
DE
320 if (resultp != NULL)
321 *resultp = result_type;
9c03036a
DE
322 *valuep = value;
323 }
324 return errmsg;
325}
326\f
327/* Signed integer validation routine. */
328
329const char *
330cgen_validate_signed_integer (value, min, max)
331 long value, min, max;
332{
333 if (value < min || value > max)
334 {
9c03036a
DE
335 static char buf[100];
336
240f5c9f
NC
337 /* xgettext:c-format */
338 sprintf (buf, _("operand out of range (%ld not between %ld and %ld)"),
339 value, min, max);
9c03036a
DE
340 return buf;
341 }
342
343 return NULL;
344}
345
346/* Unsigned integer validation routine.
347 Supplying `min' here may seem unnecessary, but we also want to handle
348 cases where min != 0 (and max > LONG_MAX). */
349
350const char *
351cgen_validate_unsigned_integer (value, min, max)
352 unsigned long value, min, max;
353{
354 if (value < min || value > max)
355 {
9c03036a
DE
356 static char buf[100];
357
240f5c9f
NC
358 sprintf (buf, _("operand out of range (%lu not between %lu and %lu)"),
359 value, min, max);
9c03036a
DE
360 return buf;
361 }
362
363 return NULL;
364}
This page took 0.112929 seconds and 4 git commands to generate.