source: branches/GNU/src/binutils/opcodes/openrisc-asm.c@ 608

Last change on this file since 608 was 608, checked in by (none), 22 years ago

This commit was manufactured by cvs2svn to create branch 'GNU'.

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 18.9 KB
Line 
1/* Assembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
4THIS FILE IS MACHINE GENERATED WITH CGEN.
5- the resultant file is machine generated, cgen-asm.in isn't
6
7Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
8
9This file is part of the GNU Binutils and GDB, the GNU debugger.
10
11This program is free software; you can redistribute it and/or modify
12it under the terms of the GNU General Public License as published by
13the Free Software Foundation; either version 2, or (at your option)
14any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License
22along with this program; if not, write to the Free Software Foundation, Inc.,
2359 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24
25/* ??? Eventually more and more of this stuff can go to cpu-independent files.
26 Keep that in mind. */
27
28#include "sysdep.h"
29#include <stdio.h>
30#include "ansidecl.h"
31#include "bfd.h"
32#include "symcat.h"
33#include "openrisc-desc.h"
34#include "openrisc-opc.h"
35#include "opintl.h"
36#include "xregex.h"
37#include "libiberty.h"
38#include "safe-ctype.h"
39
40#undef min
41#define min(a,b) ((a) < (b) ? (a) : (b))
42#undef max
43#define max(a,b) ((a) > (b) ? (a) : (b))
44
45static const char * parse_insn_normal
46 PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *));
47
48
49/* -- assembler routines inserted here. */
50
51/* -- asm.c */
52
53#define CGEN_VERBOSE_ASSEMBLER_ERRORS
54
55static const char * parse_hi16
56 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
57static const char * parse_lo16
58 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
59
60long
61openrisc_sign_extend_16bit (value)
62 long value;
63{
64 return (long) (short) value;
65}
66
67/* Handle hi(). */
68
69static const char *
70parse_hi16 (cd, strp, opindex, valuep)
71 CGEN_CPU_DESC cd;
72 const char **strp;
73 int opindex;
74 unsigned long *valuep;
75{
76 const char *errmsg;
77 enum cgen_parse_operand_result result_type;
78 bfd_vma value;
79
80 if (**strp == '#')
81 ++*strp;
82
83 if (strncasecmp (*strp, "hi(", 3) == 0)
84 {
85 *strp += 3;
86
87#if 0
88 errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
89 if (errmsg != NULL)
90 fprintf (stderr, "parse_hi: %s\n", errmsg);
91 if (errmsg != NULL)
92#endif
93 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
94 &result_type, &value);
95 if (**strp != ')')
96 return "missing `)'";
97 ++*strp;
98 if (errmsg == NULL
99 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
100 value >>= 16;
101 *valuep = (long) (short) value;
102
103 return errmsg;
104 }
105 else
106 {
107 if (**strp == '-')
108 errmsg = cgen_parse_signed_integer (cd, strp, opindex, (long *) &value);
109 else
110 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) &value);
111 }
112 *valuep = (long) (short) (value & 0xffff);
113 return errmsg;
114}
115
116/* Handle lo(). */
117
118static const char *
119parse_lo16 (cd, strp, opindex, valuep)
120 CGEN_CPU_DESC cd;
121 const char **strp;
122 int opindex;
123 unsigned long *valuep;
124{
125 const char *errmsg;
126 enum cgen_parse_operand_result result_type;
127 bfd_vma value;
128
129 if (**strp == '#')
130 ++*strp;
131
132 if (strncasecmp (*strp, "lo(", 3) == 0)
133 {
134 *strp += 3;
135
136#if 0
137 errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
138 if (errmsg != NULL)
139 fprintf (stderr, "parse_lo: %s\n", errmsg);
140
141 if (errmsg != NULL)
142#endif
143 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
144 &result_type, &value);
145 if (**strp != ')')
146 return "missing `)'";
147 ++*strp;
148 if (errmsg == NULL
149 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
150 value &= 0xffff;
151 *valuep = (long) (short) value;
152
153 return errmsg;
154 }
155
156 if (**strp == '-')
157 errmsg = cgen_parse_signed_integer (cd, strp, opindex, (long *) &value);
158 else
159 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) &value);
160 *valuep = (long) (short) (value & 0xffff);
161 return errmsg;
162}
163
164/* -- */
165
166const char * openrisc_cgen_parse_operand
167 PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
168
169/* Main entry point for operand parsing.
170
171 This function is basically just a big switch statement. Earlier versions
172 used tables to look up the function to use, but
173 - if the table contains both assembler and disassembler functions then
174 the disassembler contains much of the assembler and vice-versa,
175 - there's a lot of inlining possibilities as things grow,
176 - using a switch statement avoids the function call overhead.
177
178 This function could be moved into `parse_insn_normal', but keeping it
179 separate makes clear the interface between `parse_insn_normal' and each of
180 the handlers. */
181
182const char *
183openrisc_cgen_parse_operand (cd, opindex, strp, fields)
184 CGEN_CPU_DESC cd;
185 int opindex;
186 const char ** strp;
187 CGEN_FIELDS * fields;
188{
189 const char * errmsg = NULL;
190 /* Used by scalar operands that still need to be parsed. */
191 long junk ATTRIBUTE_UNUSED;
192
193 switch (opindex)
194 {
195 case OPENRISC_OPERAND_ABS_26 :
196 {
197 bfd_vma value;
198 errmsg = cgen_parse_address (cd, strp, OPENRISC_OPERAND_ABS_26, 0, NULL, & value);
199 fields->f_abs26 = value;
200 }
201 break;
202 case OPENRISC_OPERAND_DISP_26 :
203 {
204 bfd_vma value;
205 errmsg = cgen_parse_address (cd, strp, OPENRISC_OPERAND_DISP_26, 0, NULL, & value);
206 fields->f_disp26 = value;
207 }
208 break;
209 case OPENRISC_OPERAND_HI16 :
210 errmsg = parse_hi16 (cd, strp, OPENRISC_OPERAND_HI16, &fields->f_simm16);
211 break;
212 case OPENRISC_OPERAND_LO16 :
213 errmsg = parse_lo16 (cd, strp, OPENRISC_OPERAND_LO16, &fields->f_lo16);
214 break;
215 case OPENRISC_OPERAND_OP_F_23 :
216 errmsg = cgen_parse_unsigned_integer (cd, strp, OPENRISC_OPERAND_OP_F_23, &fields->f_op4);
217 break;
218 case OPENRISC_OPERAND_OP_F_3 :
219 errmsg = cgen_parse_unsigned_integer (cd, strp, OPENRISC_OPERAND_OP_F_3, &fields->f_op5);
220 break;
221 case OPENRISC_OPERAND_RA :
222 errmsg = cgen_parse_keyword (cd, strp, & openrisc_cgen_opval_h_gr, & fields->f_r2);
223 break;
224 case OPENRISC_OPERAND_RB :
225 errmsg = cgen_parse_keyword (cd, strp, & openrisc_cgen_opval_h_gr, & fields->f_r3);
226 break;
227 case OPENRISC_OPERAND_RD :
228 errmsg = cgen_parse_keyword (cd, strp, & openrisc_cgen_opval_h_gr, & fields->f_r1);
229 break;
230 case OPENRISC_OPERAND_SIMM_16 :
231 errmsg = cgen_parse_signed_integer (cd, strp, OPENRISC_OPERAND_SIMM_16, &fields->f_simm16);
232 break;
233 case OPENRISC_OPERAND_UI16NC :
234 errmsg = parse_lo16 (cd, strp, OPENRISC_OPERAND_UI16NC, &fields->f_i16nc);
235 break;
236 case OPENRISC_OPERAND_UIMM_16 :
237 errmsg = cgen_parse_unsigned_integer (cd, strp, OPENRISC_OPERAND_UIMM_16, &fields->f_uimm16);
238 break;
239 case OPENRISC_OPERAND_UIMM_5 :
240 errmsg = cgen_parse_unsigned_integer (cd, strp, OPENRISC_OPERAND_UIMM_5, &fields->f_uimm5);
241 break;
242
243 default :
244 /* xgettext:c-format */
245 fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
246 abort ();
247 }
248
249 return errmsg;
250}
251
252cgen_parse_fn * const openrisc_cgen_parse_handlers[] =
253{
254 parse_insn_normal,
255};
256
257void
258openrisc_cgen_init_asm (cd)
259 CGEN_CPU_DESC cd;
260{
261 openrisc_cgen_init_opcode_table (cd);
262 openrisc_cgen_init_ibld_table (cd);
263 cd->parse_handlers = & openrisc_cgen_parse_handlers[0];
264 cd->parse_operand = openrisc_cgen_parse_operand;
265}
266
267
268
269
270/* Regex construction routine.
271
272 This translates an opcode syntax string into a regex string,
273 by replacing any non-character syntax element (such as an
274 opcode) with the pattern '.*'
275
276 It then compiles the regex and stores it in the opcode, for
277 later use by openrisc_cgen_assemble_insn
278
279 Returns NULL for success, an error message for failure. */
280
281char *
282openrisc_cgen_build_insn_regex (insn)
283 CGEN_INSN *insn;
284{
285 CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
286 const char *mnem = CGEN_INSN_MNEMONIC (insn);
287 char rxbuf[CGEN_MAX_RX_ELEMENTS];
288 char *rx = rxbuf;
289 const CGEN_SYNTAX_CHAR_TYPE *syn;
290 int reg_err;
291
292 syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
293
294 /* Mnemonics come first in the syntax string. */
295 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
296 return _("missing mnemonic in syntax string");
297 ++syn;
298
299 /* Generate a case sensitive regular expression that emulates case
300 insensitive matching in the "C" locale. We cannot generate a case
301 insensitive regular expression because in Turkish locales, 'i' and 'I'
302 are not equal modulo case conversion. */
303
304 /* Copy the literal mnemonic out of the insn. */
305 for (; *mnem; mnem++)
306 {
307 char c = *mnem;
308
309 if (ISALPHA (c))
310 {
311 *rx++ = '[';
312 *rx++ = TOLOWER (c);
313 *rx++ = TOUPPER (c);
314 *rx++ = ']';
315 }
316 else
317 *rx++ = c;
318 }
319
320 /* Copy any remaining literals from the syntax string into the rx. */
321 for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
322 {
323 if (CGEN_SYNTAX_CHAR_P (* syn))
324 {
325 char c = CGEN_SYNTAX_CHAR (* syn);
326
327 switch (c)
328 {
329 /* Escape any regex metacharacters in the syntax. */
330 case '.': case '[': case '\\':
331 case '*': case '^': case '$':
332
333#ifdef CGEN_ESCAPE_EXTENDED_REGEX
334 case '?': case '{': case '}':
335 case '(': case ')': case '*':
336 case '|': case '+': case ']':
337#endif
338 *rx++ = '\\';
339 *rx++ = c;
340 break;
341
342 default:
343 if (ISALPHA (c))
344 {
345 *rx++ = '[';
346 *rx++ = TOLOWER (c);
347 *rx++ = TOUPPER (c);
348 *rx++ = ']';
349 }
350 else
351 *rx++ = c;
352 break;
353 }
354 }
355 else
356 {
357 /* Replace non-syntax fields with globs. */
358 *rx++ = '.';
359 *rx++ = '*';
360 }
361 }
362
363 /* Trailing whitespace ok. */
364 * rx++ = '[';
365 * rx++ = ' ';
366 * rx++ = '\t';
367 * rx++ = ']';
368 * rx++ = '*';
369
370 /* But anchor it after that. */
371 * rx++ = '$';
372 * rx = '\0';
373
374 CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
375 reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
376
377 if (reg_err == 0)
378 return NULL;
379 else
380 {
381 static char msg[80];
382
383 regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
384 regfree ((regex_t *) CGEN_INSN_RX (insn));
385 free (CGEN_INSN_RX (insn));
386 (CGEN_INSN_RX (insn)) = NULL;
387 return msg;
388 }
389}
390
391
392
393/* Default insn parser.
394