Add cutoff for changes in 2.16 release
[binutils.git] / opcodes / ip2k-asm.c
blobc5a318767f8c89c5151d294dd01f8a547d9469b4
1 /* Assembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
4 THIS FILE IS MACHINE GENERATED WITH CGEN.
5 - the resultant file is machine generated, cgen-asm.in isn't
7 Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
9 This file is part of the GNU Binutils and GDB, the GNU debugger.
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2, or (at your option)
14 any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software Foundation, Inc.,
23 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
25 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
26 Keep that in mind. */
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"
40 #undef min
41 #define min(a,b) ((a) < (b) ? (a) : (b))
42 #undef max
43 #define max(a,b) ((a) > (b) ? (a) : (b))
45 static const char * parse_insn_normal
46 (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
48 /* -- assembler routines inserted here. */
50 /* -- asm.c */
52 #define PARSE_FUNC_DECL(name) \
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 *)
57 PARSE_UFUNC_DECL (parse_fr);
58 PARSE_UFUNC_DECL (parse_addr16);
59 PARSE_UFUNC_DECL (parse_addr16_cjp);
60 PARSE_FUNC_DECL (parse_lit8);
61 PARSE_UFUNC_DECL (parse_bit3);
64 static const char *
65 parse_fr (cd, strp, opindex, valuep)
66 CGEN_CPU_DESC cd;
67 const char **strp;
68 int opindex;
69 unsigned long *valuep;
71 const char *errmsg;
72 const char *old_strp;
73 char *afteroffset;
74 enum cgen_parse_operand_result result_type;
75 bfd_vma value;
76 extern CGEN_KEYWORD ip2k_cgen_opval_register_names;
77 bfd_vma tempvalue;
79 old_strp = *strp;
80 afteroffset = NULL;
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))
86 (*strp)++;
88 if ((strncmp (*strp, ",", 1) == 0) || ISSPACE (**strp))
90 /* We've been passed a w. Return with an error message so that
91 cgen will try the next parsing option. */
92 errmsg = _("W keyword invalid in FR operand slot.");
93 return errmsg;
95 *strp = old_strp;
98 /* Attempt parse as register keyword. */
99 errmsg = cgen_parse_keyword (cd, strp, & ip2k_cgen_opval_register_names,
100 (long *) valuep);
101 if (*strp != NULL
102 && errmsg == NULL)
103 return errmsg;
105 /* Attempt to parse for "(IP)". */
106 afteroffset = strstr (*strp, "(IP)");
108 if (afteroffset == NULL)
109 /* Make sure it's not in lower case. */
110 afteroffset = strstr (*strp, "(ip)");
112 if (afteroffset != NULL)
114 if (afteroffset != *strp)
116 /* Invalid offset present. */
117 errmsg = _("offset(IP) is not a valid form");
118 return errmsg;
120 else
122 *strp += 4;
123 *valuep = 0;
124 errmsg = NULL;
125 return errmsg;
129 /* Attempt to parse for DP. ex: mov w, offset(DP)
130 mov offset(DP),w */
132 /* Try parsing it as an address and see what comes back. */
133 afteroffset = strstr (*strp, "(DP)");
135 if (afteroffset == NULL)
136 /* Maybe it's in lower case. */
137 afteroffset = strstr (*strp, "(dp)");
139 if (afteroffset != NULL)
141 if (afteroffset == *strp)
143 /* No offset present. Use 0 by default. */
144 tempvalue = 0;
145 errmsg = NULL;
147 else
148 errmsg = cgen_parse_address (cd, strp, opindex,
149 BFD_RELOC_IP2K_FR_OFFSET,
150 & result_type, & tempvalue);
152 if (errmsg == NULL)
154 if (tempvalue <= 127)
156 /* Value is ok. Fix up the first 2 bits and return. */
157 *valuep = 0x0100 | tempvalue;
158 *strp += 4; /* skip over the (DP) in *strp. */
159 return errmsg;
161 else
163 /* Found something there in front of (DP) but it's out
164 of range. */
165 errmsg = _("(DP) offset out of range.");
166 return errmsg;
172 /* Attempt to parse for SP. ex: mov w, offset(SP)
173 mov offset(SP), w. */
174 afteroffset = strstr (*strp, "(SP)");
176 if (afteroffset == NULL)
177 /* Maybe it's in lower case. */
178 afteroffset = strstr (*strp, "(sp)");
180 if (afteroffset != NULL)
182 if (afteroffset == *strp)
184 /* No offset present. Use 0 by default. */
185 tempvalue = 0;
186 errmsg = NULL;
188 else
189 errmsg = cgen_parse_address (cd, strp, opindex,
190 BFD_RELOC_IP2K_FR_OFFSET,
191 & result_type, & tempvalue);
193 if (errmsg == NULL)
195 if (tempvalue <= 127)
197 /* Value is ok. Fix up the first 2 bits and return. */
198 *valuep = 0x0180 | tempvalue;
199 *strp += 4; /* skip over the (SP) in *strp. */
200 return errmsg;
202 else
204 /* Found something there in front of (SP) but it's out
205 of range. */
206 errmsg = _("(SP) offset out of range.");
207 return errmsg;
212 /* Attempt to parse as an address. */
213 *strp = old_strp;
214 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_IP2K_FR9,
215 & result_type, & value);
216 if (errmsg == NULL)
218 *valuep = value;
220 /* if a parenthesis is found, warn about invalid form. */
221 if (**strp == '(')
222 errmsg = _("illegal use of parentheses");
224 /* if a numeric value is specified, ensure that it is between
225 1 and 255. */
226 else if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
228 if (value < 0x1 || value > 0xff)
229 errmsg = _("operand out of range (not between 1 and 255)");
232 return errmsg;
235 static const char *
236 parse_addr16 (cd, strp, opindex, valuep)
237 CGEN_CPU_DESC cd;
238 const char **strp;
239 int opindex;
240 unsigned long *valuep;
242 const char *errmsg;
243 enum cgen_parse_operand_result result_type;
244 bfd_reloc_code_real_type code = BFD_RELOC_NONE;
245 bfd_vma value;
247 if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16H)
248 code = BFD_RELOC_IP2K_HI8DATA;
249 else if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16L)
250 code = BFD_RELOC_IP2K_LO8DATA;
251 else
253 /* Something is very wrong. opindex has to be one of the above. */
254 errmsg = _("parse_addr16: invalid opindex.");
255 return errmsg;
258 errmsg = cgen_parse_address (cd, strp, opindex, code,
259 & result_type, & value);
260 if (errmsg == NULL)
262 /* We either have a relocation or a number now. */
263 if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
265 /* We got a number back. */
266 if (code == BFD_RELOC_IP2K_HI8DATA)
267 value >>= 8;
268 else /* code = BFD_RELOC_IP2K_LOW8DATA */
269 value &= 0x00FF;
271 *valuep = value;
274 return errmsg;
278 static const char *
279 parse_addr16_cjp (cd, strp, opindex, valuep)
280 CGEN_CPU_DESC cd;
281 const char **strp;
282 int opindex;
283 unsigned long *valuep;
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;
290 if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16CJP)
291 code = BFD_RELOC_IP2K_ADDR16CJP;
292 else if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16P)
293 code = BFD_RELOC_IP2K_PAGE3;
295 errmsg = cgen_parse_address (cd, strp, opindex, code,
296 & result_type, & value);
297 if (errmsg == NULL)
299 if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
301 if ((value & 0x1) == 0) /* If the address is even .... */
303 if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16CJP)
304 *valuep = (value >> 1) & 0x1FFF; /* Should mask be 1FFF? */
305 else if (opindex == (CGEN_OPERAND_TYPE) IP2K_OPERAND_ADDR16P)
306 *valuep = (value >> 14) & 0x7;
308 else
309 errmsg = _("Byte address required. - must be even.");
311 else if (result_type == CGEN_PARSE_OPERAND_RESULT_QUEUED)
313 /* This will happen for things like (s2-s1) where s2 and s1
314 are labels. */
315 *valuep = value;
317 else
318 errmsg = _("cgen_parse_address returned a symbol. Literal required.");
320 return errmsg;
324 static const char *
325 parse_lit8 (cd, strp, opindex, valuep)
326 CGEN_CPU_DESC cd;
327 const char **strp;
328 int opindex;
329 long *valuep;
331 const char *errmsg;
332 enum cgen_parse_operand_result result_type;
333 bfd_reloc_code_real_type code = BFD_RELOC_NONE;
334 bfd_vma value;
336 /* Parse %OP relocating operators. */
337 if (strncmp (*strp, "%bank", 5) == 0)
339 *strp += 5;
340 code = BFD_RELOC_IP2K_BANK;
342 else if (strncmp (*strp, "%lo8data", 8) == 0)
344 *strp += 8;
345 code = BFD_RELOC_IP2K_LO8DATA;
347 else if (strncmp (*strp, "%hi8data", 8) == 0)
349 *strp += 8;
350 code = BFD_RELOC_IP2K_HI8DATA;
352 else if (strncmp (*strp, "%ex8data", 8) == 0)
354 *strp += 8;
355 code = BFD_RELOC_IP2K_EX8DATA;
357 else if (strncmp (*strp, "%lo8insn", 8) == 0)
359 *strp += 8;
360 code = BFD_RELOC_IP2K_LO8INSN;
362 else if (strncmp (*strp, "%hi8insn", 8) == 0)
364 *strp += 8;
365 code = BFD_RELOC_IP2K_HI8INSN;
369 /* Parse %op operand. */
370 if (code != BFD_RELOC_NONE)
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");
378 *valuep = value;
380 /* Parse as a number. */
381 else
383 errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
385 /* Truncate to eight bits to accept both signed and unsigned input. */
386 if (errmsg == NULL)
387 *valuep &= 0xFF;
390 return errmsg;
393 static const char *
394 parse_bit3 (cd, strp, opindex, valuep)
395 CGEN_CPU_DESC cd;
396 const char **strp;
397 int opindex;
398 unsigned long *valuep;
400 const char *errmsg;
401 char mode = 0;
402 long count = 0;
403 unsigned long value;
405 if (strncmp (*strp, "%bit", 4) == 0)
407 *strp += 4;
408 mode = 1;
410 else if (strncmp (*strp, "%msbbit", 7) == 0)
412 *strp += 7;
413 mode = 1;
415 else if (strncmp (*strp, "%lsbbit", 7) == 0)
417 *strp += 7;
418 mode = 2;
421 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
422 if (errmsg)
423 return errmsg;
425 if (mode)
427 value = * valuep;
428 if (value == 0)
430 errmsg = _("Attempt to find bit index of 0");
431 return errmsg;
434 if (mode == 1)
436 count = 31;
437 while ((value & 0x80000000) == 0)
439 count--;
440 value <<= 1;
443 else if (mode == 2)
445 count = 0;
446 while ((value & 0x00000001) == 0)
448 count++;
449 value >>= 1;
453 *valuep = count;
456 return errmsg;
460 /* -- dis.c */
462 const char * ip2k_cgen_parse_operand
463 PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
465 /* Main entry point for operand parsing.
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.
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. */
478 const char *
479 ip2k_cgen_parse_operand (cd, opindex, strp, fields)
480 CGEN_CPU_DESC cd;
481 int opindex;
482 const char ** strp;
483 CGEN_FIELDS * fields;
485 const char * errmsg = NULL;
486 /* Used by scalar operands that still need to be parsed. */
487 long junk ATTRIBUTE_UNUSED;
489 switch (opindex)
491 case IP2K_OPERAND_ADDR16CJP :
492 errmsg = parse_addr16_cjp (cd, strp, IP2K_OPERAND_ADDR16CJP, (unsigned long *) (& fields->f_addr16cjp));
493 break;
494 case IP2K_OPERAND_ADDR16H :
495 errmsg = parse_addr16 (cd, strp, IP2K_OPERAND_ADDR16H, (unsigned long *) (& fields->f_imm8));
496 break;
497 case IP2K_OPERAND_ADDR16L :
498 errmsg = parse_addr16 (cd, strp, IP2K_OPERAND_ADDR16L, (unsigned long *) (& fields->f_imm8));
499 break;
500 case IP2K_OPERAND_ADDR16P :
501 errmsg = parse_addr16_cjp (cd, strp, IP2K_OPERAND_ADDR16P, (unsigned long *) (& fields->f_page3));
502 break;
503 case IP2K_OPERAND_BITNO :
504 errmsg = parse_bit3 (cd, strp, IP2K_OPERAND_BITNO, (unsigned long *) (& fields->f_bitno));
505 break;
506 case IP2K_OPERAND_CBIT :
507 errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_CBIT, (unsigned long *) (& junk));
508 break;
509 case IP2K_OPERAND_DCBIT :
510 errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_DCBIT, (unsigned long *) (& junk));
511 break;
512 case IP2K_OPERAND_FR :
513 errmsg = parse_fr (cd, strp, IP2K_OPERAND_FR, (unsigned long *) (& fields->f_reg));
514 break;
515 case IP2K_OPERAND_LIT8 :
516 errmsg = parse_lit8 (cd, strp, IP2K_OPERAND_LIT8, (long *) (& fields->f_imm8));
517 break;
518 case IP2K_OPERAND_PABITS :
519 errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_PABITS, (unsigned long *) (& junk));
520 break;
521 case IP2K_OPERAND_RETI3 :
522 errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_RETI3, (unsigned long *) (& fields->f_reti3));
523 break;
524 case IP2K_OPERAND_ZBIT :
525 errmsg = cgen_parse_unsigned_integer (cd, strp, IP2K_OPERAND_ZBIT, (unsigned long *) (& junk));
526 break;
528 default :
529 /* xgettext:c-format */
530 fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
531 abort ();
534 return errmsg;
537 cgen_parse_fn * const ip2k_cgen_parse_handlers[] =
539 parse_insn_normal,
542 void
543 ip2k_cgen_init_asm (cd)
544 CGEN_CPU_DESC cd;
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;
554 /* Regex construction routine.
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 '.*'
560 It then compiles the regex and stores it in the opcode, for
561 later use by ip2k_cgen_assemble_insn
563 Returns NULL for success, an error message for failure. */
565 char *
566 ip2k_cgen_build_insn_regex (CGEN_INSN *insn)
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;
575 syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
577 /* Mnemonics come first in the syntax string. */
578 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
579 return _("missing mnemonic in syntax string");
580 ++syn;
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. */
587 /* Copy the literal mnemonic out of the insn. */
588 for (; *mnem; mnem++)
590 char c = *mnem;
592 if (ISALPHA (c))
594 *rx++ = '[';
595 *rx++ = TOLOWER (c);
596 *rx++ = TOUPPER (c);
597 *rx++ = ']';
599 else
600 *rx++ = c;
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)
606 if (CGEN_SYNTAX_CHAR_P (* syn))
608 char c = CGEN_SYNTAX_CHAR (* syn);
610 switch (c)
612 /* Escape any regex metacharacters in the syntax. */
613 case '.': case '[': case '\\':
614 case '*': case '^': case '$':
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;
625 default:
626 if (ISALPHA (c))
628 *rx++ = '[';
629 *rx++ = TOLOWER (c);
630 *rx++ = TOUPPER (c);
631 *rx++ = ']';
633 else
634 *rx++ = c;
635 break;
638 else
640 /* Replace non-syntax fields with globs. */
641 *rx++ = '.';
642 *rx++ = '*';
646 /* Trailing whitespace ok. */
647 * rx++ = '[';
648 * rx++ = ' ';
649 * rx++ = '\t';
650 * rx++ = ']';
651 * rx++ = '*';
653 /* But anchor it after that. */
654 * rx++ = '$';
655 * rx = '\0';
657 CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
658 reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
660 if (reg_err == 0)
661 return NULL;
662 else
664 static char msg[80];
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;
675 /* Default insn parser.
677 The syntax string is scanned and operands are parsed and stored in FIELDS.
678 Relocs are queued as we go via other callbacks.
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.
686 Returns NULL for success, an error message for failure. */
688 static const char *
689 parse_insn_normal (CGEN_CPU_DESC cd,
690 const CGEN_INSN *insn,
691 const char **strp,
692 CGEN_FIELDS *fields)
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
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;
713 if (* p)
714 return _("unrecognized instruction");
716 #ifndef CGEN_MNEMONIC_OPERANDS
717 if (* str && ! ISSPACE (* str))
718 return _("unrecognized instruction");
719 #endif
721 CGEN_INIT_PARSE (cd);
722 cgen_init_parse_operand (cd);
723 #ifdef CGEN_MNEMONIC_OPERANDS
724 past_opcode_p = 0;
725 #endif
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);
731 /* Mnemonics come first for now, ensure valid string. */
732 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
733 abort ();
735 ++syn;
737 while (* syn != 0)
739 /* Non operand chars must match exactly. */
740 if (CGEN_SYNTAX_CHAR_P (* syn))
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)))
748 #ifdef CGEN_MNEMONIC_OPERANDS
749 if (CGEN_SYNTAX_CHAR(* syn) == ' ')
750 past_opcode_p = 1;
751 #endif
752 ++ syn;
753 ++ str;
755 else if (*str)
757 /* Syntax char didn't match. Can't be this insn. */
758 static char msg [80];
760 /* xgettext:c-format */
761 sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
762 CGEN_SYNTAX_CHAR(*syn), *str);
763 return msg;
765 else
767 /* Ran out of input. */
768 static char msg [80];
770 /* xgettext:c-format */
771 sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
772 CGEN_SYNTAX_CHAR(*syn));
773 return msg;
775 continue;
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;
784 /* Done with this operand, continue with next one. */
785 ++ syn;
788 /* If we're at the end of the syntax string, we're done. */
789 if (* syn == 0)
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;
798 if (* str != '\0')
799 return _("junk at end of line"); /* FIXME: would like to include `str' */
801 return NULL;
804 /* We couldn't parse it. */
805 return _("unrecognized instruction");
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).
820 Note that when processing (non-alias) macro-insns,
821 this function recurses.
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. */
829 const CGEN_INSN *
830 ip2k_cgen_assemble_insn (CGEN_CPU_DESC cd,
831 const char *str,
832 CGEN_FIELDS *fields,
833 CGEN_INSN_BYTES_PTR buf,
834 char **errmsg)
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;
842 /* Skip leading white space. */
843 while (ISSPACE (* str))
844 ++ str;
846 /* The instructions are stored in hashed lists.
847 Get the first in the list. */
848 ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
850 /* Keep looking until we find a match. */
851 start = str;
852 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
854 const CGEN_INSN *insn = ilist->insn;
855 recognized_mnemonic = 1;
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
864 /* If the RELAXED attribute is set, this is an insn that shouldn't be
865 chosen immediately. Instead, it is used during assembler/linker
866 relaxation if possible. */
867 if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
868 continue;
870 str = start;
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;
877 /* Allow parse/insert handlers to obtain length of insn. */
878 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
880 parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
881 if (parse_errmsg != NULL)
882 continue;
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;
890 /* It is up to the caller to actually output the insn and any
891 queued relocs. */
892 return insn;
896 static char errbuf[150];
897 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
898 const char *tmp_errmsg;
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"));
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
923 *errmsg = errbuf;
924 return NULL;
928 #if 0 /* This calls back to GAS which we can't do without care. */
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. */
934 /* Record each member of OPVALS in the assembler's symbol table.
935 FIXME: Not currently used. */
937 void
938 ip2k_cgen_asm_hash_keywords (CGEN_CPU_DESC cd, CGEN_KEYWORD *opvals)
940 CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
941 const CGEN_KEYWORD_ENTRY * ke;
943 while ((ke = cgen_keyword_search_next (& search)) != NULL)
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);
953 #endif /* 0 */