Fix compile time warnings generated by gcc 4.0
[deliverable/binutils-gdb.git] / opcodes / ip2k-asm.c
CommitLineData
a40cbfa3
NC
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 "ip2k-desc.h"
34#include "ip2k-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
ffead7ae 46 (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
a40cbfa3
NC
47\f
48/* -- assembler routines inserted here. */
49
50/* -- asm.c */
51
98f70fc4 52#define PARSE_FUNC_DECL(name) \
33b71eeb
NC
53 static const char *name (CGEN_CPU_DESC, const char **, int, long *)
54#define PARSE_UFUNC_DECL(name) \
55 static const char *name (CGEN_CPU_DESC, const char **, int, unsigned long *)
98f70fc4 56
33b71eeb
NC
57PARSE_UFUNC_DECL (parse_fr);
58PARSE_UFUNC_DECL (parse_addr16);
59PARSE_UFUNC_DECL (parse_addr16_cjp);
98f70fc4 60PARSE_FUNC_DECL (parse_lit8);
33b71eeb 61PARSE_UFUNC_DECL (parse_bit3);
98f70fc4
AM
62
63
a40cbfa3
NC
64static const char *
65parse_fr (cd, strp, opindex, valuep)
66 CGEN_CPU_DESC cd;
67 const char **strp;
68 int opindex;
33b71eeb 69 unsigned long *valuep;
a40cbfa3
NC
70{
71 const char *errmsg;
98f70fc4 72 const char *old_strp;
a40cbfa3
NC
73 char *afteroffset;
74 enum cgen_parse_operand_result result_type;
75 bfd_vma value;
76 extern CGEN_KEYWORD ip2k_cgen_opval_register_names;
98f70fc4 77 bfd_vma tempvalue;
a40cbfa3
NC
78
79 old_strp = *strp;
80 afteroffset = NULL;
81
33b71eeb
NC
82 /* Check here to see if you're about to try parsing a w as the first arg
83 and return an error if you are. */
84 if ((strncmp (*strp, "w", 1) == 0) || (strncmp (*strp, "W", 1) == 0))
98f70fc4
AM
85 {
86 (*strp)++;
a40cbfa3 87
33b71eeb 88 if ((strncmp (*strp, ",", 1) == 0) || ISSPACE (**strp))
98f70fc4 89 {
33b71eeb
NC
90 /* We've been passed a w. Return with an error message so that
91 cgen will try the next parsing option. */
98f70fc4
AM
92 errmsg = _("W keyword invalid in FR operand slot.");
93 return errmsg;
94 }
95 *strp = old_strp;
96 }
a40cbfa3 97
a40cbfa3 98 /* Attempt parse as register keyword. */
98f70fc4 99 errmsg = cgen_parse_keyword (cd, strp, & ip2k_cgen_opval_register_names,
33b71eeb
NC
100 (long *) valuep);
101 if (*strp != NULL
102 && errmsg == NULL)
103 return errmsg;
a40cbfa3 104
33b71eeb
NC
105 /* Attempt to parse for "(IP)". */
106 afteroffset = strstr (*strp, "(IP)");
a40cbfa3 107
33b71eeb
NC
108 if (afteroffset == NULL)
109 /* Make sure it's not in lower case. */
110 afteroffset = strstr (*strp, "(ip)");
a40cbfa3 111
33b71eeb 112 if (afteroffset != NULL)
a40cbfa3 113 {
33b71eeb 114 if (afteroffset != *strp)
a40cbfa3 115 {
33b71eeb 116 /* Invalid offset present. */
a40cbfa3
NC
117 errmsg = _("offset(IP) is not a valid form");
118 return errmsg;
119 }
120 else
121 {
122 *strp += 4;
123 *valuep = 0;
124 errmsg = NULL;
125 return errmsg;
126 }
127 }
128
33b71eeb
NC
129 /* Attempt to parse for DP. ex: mov w, offset(DP)
130 mov offset(DP),w */
a40cbfa3 131
33b71eeb
NC
132 /* Try parsing it as an address and see what comes back. */
133 afteroffset = strstr (*strp, "(DP)");
a40cbfa3 134
33b71eeb
NC
135 if (afteroffset == NULL)
136 /* Maybe it's in lower case. */
137 afteroffset = strstr (*strp, "(dp)");
a40cbfa3 138
33b71eeb 139 if (afteroffset != NULL)
98f70fc4 140 {
33b71eeb 141 if (afteroffset == *strp)
98f70fc4 142 {
33b71eeb 143 /* No offset present. Use 0 by default. */
98f70fc4
AM
144 tempvalue = 0;
145 errmsg = NULL;
146 }
147 else
33b71eeb
NC
148 errmsg = cgen_parse_address (cd, strp, opindex,
149 BFD_RELOC_IP2K_FR_OFFSET,
150 & result_type, & tempvalue);
98f70fc4
AM
151
152 if (errmsg == NULL)
153 {
154 if (tempvalue <= 127)
155 {
33b71eeb 156 /* Value is ok. Fix up the first 2 bits and return. */
98f70fc4 157 *valuep = 0x0100 | tempvalue;
33b71eeb 158 *strp += 4; /* skip over the (DP) in *strp. */
98f70fc4
AM
159 return errmsg;
160 }
161 else
162 {
163 /* Found something there in front of (DP) but it's out
33b71eeb 164 of range. */
98f70fc4
AM
165 errmsg = _("(DP) offset out of range.");
166 return errmsg;
167 }
168 }
169 }
a40cbfa3
NC
170
171
33b71eeb
NC
172 /* Attempt to parse for SP. ex: mov w, offset(SP)
173 mov offset(SP), w. */
174 afteroffset = strstr (*strp, "(SP)");
a40cbfa3
NC
175
176 if (afteroffset == NULL)
33b71eeb
NC
177 /* Maybe it's in lower case. */
178 afteroffset = strstr (*strp, "(sp)");
a40cbfa3 179
33b71eeb 180 if (afteroffset != NULL)
98f70fc4 181 {
33b71eeb 182 if (afteroffset == *strp)
98f70fc4 183 {
33b71eeb 184 /* No offset present. Use 0 by default. */
98f70fc4
AM
185 tempvalue = 0;
186 errmsg = NULL;
187 }
188 else
33b71eeb
NC
189 errmsg = cgen_parse_address (cd, strp, opindex,
190 BFD_RELOC_IP2K_FR_OFFSET,
191 & result_type, & tempvalue);
192
98f70fc4
AM
193 if (errmsg == NULL)
194 {
195 if (tempvalue <= 127)
196 {
33b71eeb 197 /* Value is ok. Fix up the first 2 bits and return. */
98f70fc4 198 *valuep = 0x0180 | tempvalue;
33b71eeb 199 *strp += 4; /* skip over the (SP) in *strp. */
98f70fc4
AM
200 return errmsg;
201 }
202 else
203 {
204 /* Found something there in front of (SP) but it's out
33b71eeb 205 of range. */
98f70fc4
AM
206 errmsg = _("(SP) offset out of range.");
207 return errmsg;
208 }
98f70fc4
AM
209 }
210 }
a40cbfa3 211
33b71eeb 212 /* Attempt to parse as an address. */
a40cbfa3
NC
213 *strp = old_strp;
214 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IP2K_FR9,
215 & result_type, & value);
216 if (errmsg == NULL)
217 {
218 *valuep = value;
219
33b71eeb 220 /* if a parenthesis is found, warn about invalid form. */
a40cbfa3 221 if (**strp == '(')
33b71eeb
NC
222 errmsg = _("illegal use of parentheses");
223
98f70fc4 224 /* if a numeric value is specified, ensure that it is between
33b71eeb 225 1 and 255. */
a40cbfa3
NC
226 else if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
227 {
228 if (value < 0x1 || value > 0xff)
229 errmsg = _("operand out of range (not between 1 and 255)");
230 }
231 }
232 return errmsg;
233}
234
235static const char *
236parse_addr16 (cd, strp, opindex, valuep)
237 CGEN_CPU_DESC cd;
238 const char **strp;
239 int opindex;
33b71eeb 240 unsigned long *valuep;
a40cbfa3
NC
241{
242 const char *errmsg;
243 enum cgen_parse_operand_result result_type;
244 bfd_reloc_code_real_type code = BFD_RELOC_NONE;
98f70fc4 245 bfd_vma value;
a40cbfa3 246
33b71eeb 247 if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16H)
98f70fc4 248 code = BFD_RELOC_IP2K_HI8DATA;
33b71eeb 249 else if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16L)
98f70fc4 250 code = BFD_RELOC_IP2K_LO8DATA;
a40cbfa3
NC
251 else
252 {
253 /* Something is very wrong. opindex has to be one of the above. */
254 errmsg = _("parse_addr16: invalid opindex.");
255 return errmsg;
256 }
257
258 errmsg = cgen_parse_address (cd, strp, opindex, code,
98f70fc4 259 & result_type, & value);
a40cbfa3
NC
260 if (errmsg == NULL)
261 {
98f70fc4 262 /* We either have a relocation or a number now. */
33b71eeb 263 if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
98f70fc4
AM
264 {
265 /* We got a number back. */
33b71eeb 266 if (code == BFD_RELOC_IP2K_HI8DATA)
a40cbfa3 267 value >>= 8;
98f70fc4 268 else /* code = BFD_RELOC_IP2K_LOW8DATA */
a40cbfa3 269 value &= 0x00FF;
98f70fc4
AM
270 }
271 *valuep = value;
272 }
a40cbfa3
NC
273
274 return errmsg;
275}
276
277
98f70fc4
AM
278static const char *
279parse_addr16_cjp (cd, strp, opindex, valuep)
280 CGEN_CPU_DESC cd;
281 const char **strp;
282 int opindex;
33b71eeb 283 unsigned long *valuep;
98f70fc4
AM
284{
285 const char *errmsg;
286 enum cgen_parse_operand_result result_type;
287 bfd_reloc_code_real_type code = BFD_RELOC_NONE;
288 bfd_vma value;
a40cbfa3 289
33b71eeb 290 if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16CJP)
98f70fc4 291 code = BFD_RELOC_IP2K_ADDR16CJP;
33b71eeb 292 else if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16P)
98f70fc4
AM
293 code = BFD_RELOC_IP2K_PAGE3;
294
295 errmsg = cgen_parse_address (cd, strp, opindex, code,
296 & result_type, & value);
297 if (errmsg == NULL)
298 {
33b71eeb 299 if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
98f70fc4 300 {
33b71eeb 301 if ((value & 0x1) == 0) /* If the address is even .... */
98f70fc4 302 {
33b71eeb 303 if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16CJP)
a40cbfa3 304 *valuep = (value >> 1) & 0x1FFF; /* Should mask be 1FFF? */
33b71eeb 305 else if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16P)
a40cbfa3 306 *valuep = (value >> 14) & 0x7;
98f70fc4 307 }
a40cbfa3
NC
308 else
309 errmsg = _("Byte address required. - must be even.");
98f70fc4 310 }
33b71eeb 311 else if (result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED)
98f70fc4
AM
312 {
313 /* This will happen for things like (s2-s1) where s2 and s1
314 are labels. */
315 *valuep = value;
316 }
a40cbfa3
NC
317 else
318 errmsg = _("cgen_parse_address returned a symbol. Literal required.");
98f70fc4
AM
319 }
320 return errmsg;
321}
a40cbfa3
NC
322
323
324static const char *
325parse_lit8 (cd, strp, opindex, valuep)
326 CGEN_CPU_DESC cd;
327 const char **strp;
328 int opindex;
329 long *valuep;
330{
331 const char *errmsg;
332 enum cgen_parse_operand_result result_type;
333 bfd_reloc_code_real_type code = BFD_RELOC_NONE;
98f70fc4 334 bfd_vma value;
a40cbfa3
NC
335
336 /* Parse %OP relocating operators. */
337 if (strncmp (*strp, "%bank", 5) == 0)
338 {
339 *strp += 5;
340 code = BFD_RELOC_IP2K_BANK;
341 }
342 else if (strncmp (*strp, "%lo8data", 8) == 0)
343 {
344 *strp += 8;
345 code = BFD_RELOC_IP2K_LO8DATA;
346 }
347 else if (strncmp (*strp, "%hi8data", 8) == 0)
348 {
349 *strp += 8;
350 code = BFD_RELOC_IP2K_HI8DATA;
351 }
352 else if (strncmp (*strp, "%ex8data", 8) == 0)
353 {
354 *strp += 8;
355 code = BFD_RELOC_IP2K_EX8DATA;
356 }
357 else if (strncmp (*strp, "%lo8insn", 8) == 0)
358 {
359 *strp += 8;
360 code = BFD_RELOC_IP2K_LO8INSN;
361 }
362 else if (strncmp (*strp, "%hi8insn", 8) == 0)
363 {
364 *strp += 8;
365 code = BFD_RELOC_IP2K_HI8INSN;
366 }
367
368
369 /* Parse %op operand. */
370 if (code != BFD_RELOC_NONE)
371 {
372 errmsg = cgen_parse_address (cd, strp, opindex, code,
373 & result_type, & value);
374 if ((errmsg == NULL) &&
375 (result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED))
376 errmsg = _("%operator operand is not a symbol");
377
378 *valuep = value;
379 }
380 /* Parse as a number. */
381 else
382 {
383 errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
384
385 /* Truncate to eight bits to accept both signed and unsigned input. */
386 if (errmsg == NULL)
387 *valuep &= 0xFF;
388 }
389
390 return errmsg;
391}
392
393static const char *
394parse_bit3 (cd, strp, opindex, valuep)
395 CGEN_CPU_DESC cd;
396 const char **strp;
397 int opindex;
33b71eeb 398 unsigned long *valuep;
a40cbfa3
NC
399{
400 const char *errmsg;
401 char mode = 0;
402 long count = 0;
403 unsigned long value;
404
405 if (strncmp (*strp, "%bit", 4) == 0)
406 {
407 *strp += 4;
408 mode = 1;
409 }
410 else if (strncmp (*strp, "%msbbit", 7) == 0)
411 {
412 *strp += 7;
413 mode = 1;
414 }
415 else if (strncmp (*strp, "%lsbbit", 7) == 0)
416 {
417 *strp += 7;
418 mode = 2;
419 }
420
33b71eeb 421 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
98f70fc4 422 if (errmsg)
a40cbfa3 423 return errmsg;
a40cbfa3 424
98f70fc4
AM
425 if (mode)
426 {
33b71eeb 427 value = * valuep;
98f70fc4
AM
428 if (value == 0)
429 {
430 errmsg = _("Attempt to find bit index of 0");
431 return errmsg;
432 }
a40cbfa3 433
98f70fc4
AM
434 if (mode == 1)
435 {
436 count = 31;
437 while ((value & 0x80000000) == 0)
438 {
439 count--;
440 value <<= 1;
441 }
442 }
443 else if (mode == 2)
444 {
445 count = 0;
446 while ((value & 0x00000001) == 0)
447 {
448 count++;
449 value >>= 1;
450 }
451 }
a40cbfa3 452
98f70fc4
AM
453 *valuep = count;
454 }
a40cbfa3
NC
455
456 return errmsg;
457}
458
459
460/* -- dis.c */
461
462const char * ip2k_cgen_parse_operand
463 PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
464
465/* Main entry point for operand parsing.
466
467 This function is basically just a big switch statement. Earlier versions
468 used tables to look up the function to use, but
469 - if the table contains both assembler and disassembler functions then
470 the disassembler contains much of the assembler and vice-versa,
471 - there's a lot of inlining possibilities as things grow,
472 - using a switch statement avoids the function call overhead.
473
474 This function could be moved into `parse_insn_normal', but keeping it
475 separate makes clear the interface between `parse_insn_normal' and each of
476 the handlers. */
477
478const char *
479ip2k_cgen_parse_operand (cd, opindex, strp, fields)
480 CGEN_CPU_DESC cd;
481 int opindex;
482 const char ** strp;
483 CGEN_FIELDS * fields;
484{
485 const char * errmsg = NULL;
486 /* Used by scalar operands that still need to be parsed. */
487 long junk ATTRIBUTE_UNUSED;
488
489 switch (opindex)
490 {
491 case IP2K_OPERAND_ADDR16CJP :
33b71eeb 492 errmsg = parse_addr16_cjp (cd, strp, IP2K_OPERAND_ADDR16CJP, (unsigned long *) (& fields->f_addr16cjp));
a40cbfa3
NC
493 break;
494 case IP2K_OPERAND_ADDR16H :
33b71eeb 495 errmsg = parse_addr16 (cd, strp, IP2K_OPERAND_ADDR16H, (unsigned long *) (& fields->f_imm8));
a40cbfa3
NC
496 break;
497 case IP2K_OPERAND_ADDR16L :
33b71eeb 498 errmsg = parse_addr16 (cd, strp, IP2K_OPERAND_ADDR16L, (unsigned long *) (& fields->f_imm8));
a40cbfa3
NC
499 break;
500 case IP2K_OPERAND_ADDR16P :
33b71eeb 501 errmsg = parse_addr16_cjp (cd, strp, IP2K_OPERAND_ADDR16P, (unsigned long *) (& fields->f_page3));
a40cbfa3
NC
502 break;
503 case IP2K_OPERAND_BITNO :
33b71eeb 504 errmsg = parse_bit3 (cd, strp, IP2K_OPERAND_BITNO, (unsigned long *) (& fields->f_bitno));
a40cbfa3
NC
505 break;
506 case IP2K_OPERAND_CBIT :
33b71eeb 507 errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_CBIT, (unsigned long *) (& junk));
a40cbfa3
NC
508 break;
509 case IP2K_OPERAND_DCBIT :
33b71eeb 510 errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_DCBIT, (unsigned long *) (& junk));
a40cbfa3
NC
511 break;
512 case IP2K_OPERAND_FR :
33b71eeb 513 errmsg = parse_fr (cd, strp, IP2K_OPERAND_FR, (unsigned long *) (& fields->f_reg));
a40cbfa3
NC
514 break;
515 case IP2K_OPERAND_LIT8 :
33b71eeb 516 errmsg = parse_lit8 (cd, strp, IP2K_OPERAND_LIT8, (long *) (& fields->f_imm8));
a40cbfa3
NC
517 break;
518 case IP2K_OPERAND_PABITS :
33b71eeb 519 errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_PABITS, (unsigned long *) (& junk));
a40cbfa3
NC
520 break;
521 case IP2K_OPERAND_RETI3 :
33b71eeb 522 errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_RETI3, (unsigned long *) (& fields->f_reti3));
a40cbfa3
NC
523 break;
524 case IP2K_OPERAND_ZBIT :
33b71eeb 525 errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_ZBIT, (unsigned long *) (& junk));
a40cbfa3
NC
526 break;
527
528 default :
529 /* xgettext:c-format */
530 fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
531 abort ();
532 }
533
534 return errmsg;
535}
536
537cgen_parse_fn * const ip2k_cgen_parse_handlers[] =
538{
539 parse_insn_normal,
540};
541
542void
543ip2k_cgen_init_asm (cd)
544 CGEN_CPU_DESC cd;
545{
546 ip2k_cgen_init_opcode_table (cd);
547 ip2k_cgen_init_ibld_table (cd);
548 cd->parse_handlers = & ip2k_cgen_parse_handlers[0];
549 cd->parse_operand = ip2k_cgen_parse_operand;
550}
551
552\f
553
554/* Regex construction routine.
555
556 This translates an opcode syntax string into a regex string,
557 by replacing any non-character syntax element (such as an
558 opcode) with the pattern '.*'
559
560 It then compiles the regex and stores it in the opcode, for
561 later use by ip2k_cgen_assemble_insn
562
563 Returns NULL for success, an error message for failure. */
564
565char *
ffead7ae 566ip2k_cgen_build_insn_regex (CGEN_INSN *insn)
a40cbfa3
NC
567{
568 CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
569 const char *mnem = CGEN_INSN_MNEMONIC (insn);
570 char rxbuf[CGEN_MAX_RX_ELEMENTS];
571 char *rx = rxbuf;
572 const CGEN_SYNTAX_CHAR_TYPE *syn;
573 int reg_err;
574
575 syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
576
577 /* Mnemonics come first in the syntax string. */
578 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
579 return _("missing mnemonic in syntax string");
580 ++syn;
581
582 /* Generate a case sensitive regular expression that emulates case
583 insensitive matching in the "C" locale. We cannot generate a case
584 insensitive regular expression because in Turkish locales, 'i' and 'I'
585 are not equal modulo case conversion. */
586
587 /* Copy the literal mnemonic out of the insn. */
588 for (; *mnem; mnem++)
589 {
590 char c = *mnem;
591
592 if (ISALPHA (c))
593 {
594 *rx++ = '[';
595 *rx++ = TOLOWER (c);
596 *rx++ = TOUPPER (c);
597 *rx++ = ']';
598 }
599 else
600 *rx++ = c;
601 }
602
603 /* Copy any remaining literals from the syntax string into the rx. */
604 for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
605 {
606 if (CGEN_SYNTAX_CHAR_P (* syn))
607 {
608 char c = CGEN_SYNTAX_CHAR (* syn);
609
610 switch (c)
611 {
612 /* Escape any regex metacharacters in the syntax. */
613 case '.': case '[': case '\\':
614 case '*': case '^': case '$':
615
616#ifdef CGEN_ESCAPE_EXTENDED_REGEX
617 case '?': case '{': case '}':
618 case '(': case ')': case '*':
619 case '|': case '+': case ']':
620#endif
621 *rx++ = '\\';
622 *rx++ = c;
623 break;
624
625 default:
626 if (ISALPHA (c))
627 {
628 *rx++ = '[';
629 *rx++ = TOLOWER (c);
630 *rx++ = TOUPPER (c);
631 *rx++ = ']';
632 }
633 else
634 *rx++ = c;
635 break;
636 }
637 }
638 else
639 {
640 /* Replace non-syntax fields with globs. */
641 *rx++ = '.';
642 *rx++ = '*';
643 }
644 }
645
646 /* Trailing whitespace ok. */
647 * rx++ = '[';
648 * rx++ = ' ';
649 * rx++ = '\t';
650 * rx++ = ']';
651 * rx++ = '*';
652
653 /* But anchor it after that. */
654 * rx++ = '$';
655 * rx = '\0';
656
657 CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
658 reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
659
660 if (reg_err == 0)
661 return NULL;
662 else
663 {
664 static char msg[80];
665
666 regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
667 regfree ((regex_t *) CGEN_INSN_RX (insn));
668 free (CGEN_INSN_RX (insn));
669 (CGEN_INSN_RX (insn)) = NULL;
670 return msg;
671 }
672}
673
674\f
675/* Default insn parser.
676
677 The syntax string is scanned and operands are parsed and stored in FIELDS.
678 Relocs are queued as we go via other callbacks.
679
680 ??? Note that this is currently an all-or-nothing parser. If we fail to
681 parse the instruction, we return 0 and the caller will start over from
682 the beginning. Backtracking will be necessary in parsing subexpressions,
683 but that can be handled there. Not handling backtracking here may get
684 expensive in the case of the m68k. Deal with later.
685
686 Returns NULL for success, an error message for failure. */
687
688static const char *
ffead7ae
MM
689parse_insn_normal (CGEN_CPU_DESC cd,
690 const CGEN_INSN *insn,
691 const char **strp,
692 CGEN_FIELDS *fields)
a40cbfa3
NC
693{
694 /* ??? Runtime added insns not handled yet. */
695 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
696 const char *str = *strp;
697 const char *errmsg;
698 const char *p;
699 const CGEN_SYNTAX_CHAR_TYPE * syn;
700#ifdef CGEN_MNEMONIC_OPERANDS
701 /* FIXME: wip */
702 int past_opcode_p;
703#endif
704
705 /* For now we assume the mnemonic is first (there are no leading operands).
706 We can parse it without needing to set up operand parsing.
707 GAS's input scrubber will ensure mnemonics are lowercase, but we may
708 not be called from GAS. */
709 p = CGEN_INSN_MNEMONIC (insn);
710 while (*p && TOLOWER (*p) == TOLOWER (*str))
711 ++p, ++str;
712
713 if (* p)
714 return _("unrecognized instruction");
715
716#ifndef CGEN_MNEMONIC_OPERANDS
717 if (* str && ! ISSPACE (* str))
718 return _("unrecognized instruction");
719#endif
720
721 CGEN_INIT_PARSE (cd);
722 cgen_init_parse_operand (cd);
723#ifdef CGEN_MNEMONIC_OPERANDS
724 past_opcode_p = 0;
725#endif
726
727 /* We don't check for (*str != '\0') here because we want to parse
728 any trailing fake arguments in the syntax string. */
729 syn = CGEN_SYNTAX_STRING (syntax);
730
731 /* Mnemonics come first for now, ensure valid string. */
732 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
733 abort ();
734
735 ++syn;
736
737 while (* syn != 0)
738 {
739 /* Non operand chars must match exactly. */
740 if (CGEN_SYNTAX_CHAR_P (* syn))
741 {
742 /* FIXME: While we allow for non-GAS callers above, we assume the
743 first char after the mnemonic part is a space. */
744 /* FIXME: We also take inappropriate advantage of the fact that
745 GAS's input scrubber will remove extraneous blanks. */
746 if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
747 {
748#ifdef CGEN_MNEMONIC_OPERANDS
749 if (CGEN_SYNTAX_CHAR(* syn) == ' ')
750 past_opcode_p = 1;
751#endif
752 ++ syn;
753 ++ str;
754 }
755 else if (*str)
756 {
757 /* Syntax char didn't match. Can't be this insn. */
758 static char msg [80];
759
760 /* xgettext:c-format */
761 sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
762 CGEN_SYNTAX_CHAR(*syn), *str);
763 return msg;
764 }
765 else
766 {
767 /* Ran out of input. */
768 static char msg [80];
769
770 /* xgettext:c-format */
771 sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
772 CGEN_SYNTAX_CHAR(*syn));
773 return msg;
774 }
775 continue;
776 }
777
778 /* We have an operand of some sort. */
779 errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
780 &str, fields);
781 if (errmsg)
782 return errmsg;
783
784 /* Done with this operand, continue with next one. */
785 ++ syn;
786 }
787
788 /* If we're at the end of the syntax string, we're done. */
789 if (* syn == 0)
790 {
791 /* FIXME: For the moment we assume a valid `str' can only contain
792 blanks now. IE: We needn't try again with a longer version of
793 the insn and it is assumed that longer versions of insns appear
794 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
795 while (ISSPACE (* str))
796 ++ str;
797
798 if (* str != '\0')
799 return _("junk at end of line"); /* FIXME: would like to include `str' */
800
801 return NULL;
802 }
803
804 /* We couldn't parse it. */
805 return _("unrecognized instruction");
806}
807\f
808/* Main entry point.
809 This routine is called for each instruction to be assembled.
810 STR points to the insn to be assembled.
811 We assume all necessary tables have been initialized.
812 The assembled instruction, less any fixups, is stored in BUF.
813 Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
814 still needs to be converted to target byte order, otherwise BUF is an array
815 of bytes in target byte order.
816 The result is a pointer to the insn's entry in the opcode table,
817 or NULL if an error occured (an error message will have already been
818 printed).
819
820 Note that when processing (non-alias) macro-insns,
821 this function recurses.
822
823 ??? It's possible to make this cpu-independent.
824 One would have to deal with a few minor things.
825 At this point in time doing so would be more of a curiosity than useful
826 [for example this file isn't _that_ big], but keeping the possibility in
827 mind helps keep the design clean. */
828
829const CGEN_INSN *
ffead7ae
MM
830ip2k_cgen_assemble_insn (CGEN_CPU_DESC cd,
831 const char *str,
832 CGEN_FIELDS *fields,
833 CGEN_INSN_BYTES_PTR buf,
834 char **errmsg)
a40cbfa3
NC
835{
836 const char *start;
837 CGEN_INSN_LIST *ilist;
838 const char *parse_errmsg = NULL;
839 const char *insert_errmsg = NULL;
840 int recognized_mnemonic = 0;
841
842 /* Skip leading white space. */
843 while (ISSPACE (* str))
844 ++ str;
845
846 /* The instructions are stored in hashed lists.
847 Get the first in the list. */
848 ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
849
850 /* Keep looking until we find a match. */
851 start = str;
852 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
853 {
854 const CGEN_INSN *insn = ilist->insn;
855 recognized_mnemonic = 1;
856
857#ifdef CGEN_VALIDATE_INSN_SUPPORTED
858 /* Not usually needed as unsupported opcodes
859 shouldn't be in the hash lists. */
860 /* Is this insn supported by the selected cpu? */
861 if (! ip2k_cgen_insn_supported (cd, insn))
862 continue;
863#endif
b11dcf4e 864 /* If the RELAXED attribute is set, this is an insn that shouldn't be
a40cbfa3
NC
865 chosen immediately. Instead, it is used during assembler/linker
866 relaxation if possible. */
b11dcf4e 867 if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
a40cbfa3
NC
868 continue;
869
870 str = start;
871
872 /* Skip this insn if str doesn't look right lexically. */
873 if (CGEN_INSN_RX (insn) != NULL &&
874 regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
875 continue;
876
877 /* Allow parse/insert handlers to obtain length of insn. */
878 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
879
880 parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
881 if (parse_errmsg != NULL)
882 continue;
883
884 /* ??? 0 is passed for `pc'. */
885 insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
886 (bfd_vma) 0);
887 if (insert_errmsg != NULL)
888 continue;
889
890 /* It is up to the caller to actually output the insn and any
891 queued relocs. */
892 return insn;
893 }
894
895 {
896 static char errbuf[150];
897#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
898 const char *tmp_errmsg;
899
900 /* If requesting verbose error messages, use insert_errmsg.
901 Failing that, use parse_errmsg. */
902 tmp_errmsg = (insert_errmsg ? insert_errmsg :
903 parse_errmsg ? parse_errmsg :
904 recognized_mnemonic ?
905 _("unrecognized form of instruction") :
906 _("unrecognized instruction"));
907
908 if (strlen (start) > 50)
909 /* xgettext:c-format */
910 sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
911 else
912 /* xgettext:c-format */
913 sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
914#else
915 if (strlen (start) > 50)
916 /* xgettext:c-format */
917 sprintf (errbuf, _("bad instruction `%.50s...'"), start);
918 else
919 /* xgettext:c-format */
920 sprintf (errbuf, _("bad instruction `%.50s'"), start);
921#endif
922
923 *errmsg = errbuf;
924 return NULL;
925 }
926}
927\f
928#if 0 /* This calls back to GAS which we can't do without care. */
929
930/* Record each member of OPVALS in the assembler's symbol table.
931 This lets GAS parse registers for us.
932 ??? Interesting idea but not currently used. */
933
934/* Record each member of OPVALS in the assembler's symbol table.
935 FIXME: Not currently used. */
936
937void
ffead7ae 938ip2k_cgen_asm_hash_keywords (CGEN_CPU_DESC cd, CGEN_KEYWORD *opvals)
a40cbfa3
NC
939{
940 CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
941 const CGEN_KEYWORD_ENTRY * ke;
942
943 while ((ke = cgen_keyword_search_next (& search)) != NULL)
944 {
945#if 0 /* Unnecessary, should be done in the search routine. */
946 if (! ip2k_cgen_opval_supported (ke))
947 continue;
948#endif
949 cgen_asm_record_register (cd, ke->name, ke->value);
950 }
951}
952
953#endif /* 0 */
This page took 0.190176 seconds and 4 git commands to generate.