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)
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 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
25 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
33 #include "ip2k-desc.h"
37 #include "libiberty.h"
38 #include "safe-ctype.h"
41 #define min(a,b) ((a) < (b) ? (a) : (b))
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. */
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
);
65 parse_fr (cd
, strp
, opindex
, valuep
)
69 unsigned long *valuep
;
74 enum cgen_parse_operand_result result_type
;
76 extern CGEN_KEYWORD ip2k_cgen_opval_register_names
;
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))
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.");
98 /* Attempt parse as register keyword. */
99 errmsg
= cgen_parse_keyword (cd
, strp
, & ip2k_cgen_opval_register_names
,
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");
129 /* Attempt to parse for DP. ex: mov w, offset(DP)
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. */
148 errmsg
= cgen_parse_address (cd
, strp
, opindex
,
149 BFD_RELOC_IP2K_FR_OFFSET
,
150 & result_type
, & tempvalue
);
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. */
163 /* Found something there in front of (DP) but it's out
165 errmsg
= _("(DP) offset out of range.");
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. */
189 errmsg
= cgen_parse_address (cd
, strp
, opindex
,
190 BFD_RELOC_IP2K_FR_OFFSET
,
191 & result_type
, & tempvalue
);
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. */
204 /* Found something there in front of (SP) but it's out
206 errmsg
= _("(SP) offset out of range.");
212 /* Attempt to parse as an address. */
214 errmsg
= cgen_parse_address (cd
, strp
, opindex
, BFD_RELOC_IP2K_FR9
,
215 & result_type
, & value
);
220 /* if a parenthesis is found, warn about invalid form. */
222 errmsg
= _("illegal use of parentheses");
224 /* if a numeric value is specified, ensure that it is between
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)");
236 parse_addr16 (cd
, strp
, opindex
, valuep
)
240 unsigned long *valuep
;
243 enum cgen_parse_operand_result result_type
;
244 bfd_reloc_code_real_type code
= BFD_RELOC_NONE
;
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
;
253 /* Something is very wrong. opindex has to be one of the above. */
254 errmsg
= _("parse_addr16: invalid opindex.");
258 errmsg
= cgen_parse_address (cd
, strp
, opindex
, code
,
259 & result_type
, & value
);
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
)
268 else /* code = BFD_RELOC_IP2K_LOW8DATA */
279 parse_addr16_cjp (cd
, strp
, opindex
, valuep
)
283 unsigned long *valuep
;
286 enum cgen_parse_operand_result result_type
;
287 bfd_reloc_code_real_type code
= BFD_RELOC_NONE
;
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
);
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;
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
318 errmsg
= _("cgen_parse_address returned a symbol. Literal required.");
325 parse_lit8 (cd
, strp
, opindex
, valuep
)
332 enum cgen_parse_operand_result result_type
;
333 bfd_reloc_code_real_type code
= BFD_RELOC_NONE
;
336 /* Parse %OP relocating operators. */
337 if (strncmp (*strp
, "%bank", 5) == 0)
340 code
= BFD_RELOC_IP2K_BANK
;
342 else if (strncmp (*strp
, "%lo8data", 8) == 0)
345 code
= BFD_RELOC_IP2K_LO8DATA
;
347 else if (strncmp (*strp
, "%hi8data", 8) == 0)
350 code
= BFD_RELOC_IP2K_HI8DATA
;
352 else if (strncmp (*strp
, "%ex8data", 8) == 0)
355 code
= BFD_RELOC_IP2K_EX8DATA
;
357 else if (strncmp (*strp
, "%lo8insn", 8) == 0)
360 code
= BFD_RELOC_IP2K_LO8INSN
;
362 else if (strncmp (*strp
, "%hi8insn", 8) == 0)
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
= _("percent-operator operand is not a symbol");
380 /* Parse as a number. */
383 errmsg
= cgen_parse_signed_integer (cd
, strp
, opindex
, valuep
);
385 /* Truncate to eight bits to accept both signed and unsigned input. */
394 parse_bit3 (cd
, strp
, opindex
, valuep
)
398 unsigned long *valuep
;
405 if (strncmp (*strp
, "%bit", 4) == 0)
410 else if (strncmp (*strp
, "%msbbit", 7) == 0)
415 else if (strncmp (*strp
, "%lsbbit", 7) == 0)
421 errmsg
= cgen_parse_unsigned_integer (cd
, strp
, opindex
, valuep
);
430 errmsg
= _("Attempt to find bit index of 0");
437 while ((value
& 0x80000000) == 0)
446 while ((value
& 0x00000001) == 0)
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
479 ip2k_cgen_parse_operand (cd
, opindex
, strp
, fields
)
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
;
491 case IP2K_OPERAND_ADDR16CJP
:
492 errmsg
= parse_addr16_cjp (cd
, strp
, IP2K_OPERAND_ADDR16CJP
, (unsigned long *) (& fields
->f_addr16cjp
));
494 case IP2K_OPERAND_ADDR16H
:
495 errmsg
= parse_addr16 (cd
, strp
, IP2K_OPERAND_ADDR16H
, (unsigned long *) (& fields
->f_imm8
));
497 case IP2K_OPERAND_ADDR16L
:
498 errmsg
= parse_addr16 (cd
, strp
, IP2K_OPERAND_ADDR16L
, (unsigned long *) (& fields
->f_imm8
));
500 case IP2K_OPERAND_ADDR16P
:
501 errmsg
= parse_addr16_cjp (cd
, strp
, IP2K_OPERAND_ADDR16P
, (unsigned long *) (& fields
->f_page3
));
503 case IP2K_OPERAND_BITNO
:
504 errmsg
= parse_bit3 (cd
, strp
, IP2K_OPERAND_BITNO
, (unsigned long *) (& fields
->f_bitno
));
506 case IP2K_OPERAND_CBIT
:
507 errmsg
= cgen_parse_unsigned_integer (cd
, strp
, IP2K_OPERAND_CBIT
, (unsigned long *) (& junk
));
509 case IP2K_OPERAND_DCBIT
:
510 errmsg
= cgen_parse_unsigned_integer (cd
, strp
, IP2K_OPERAND_DCBIT
, (unsigned long *) (& junk
));
512 case IP2K_OPERAND_FR
:
513 errmsg
= parse_fr (cd
, strp
, IP2K_OPERAND_FR
, (unsigned long *) (& fields
->f_reg
));
515 case IP2K_OPERAND_LIT8
:
516 errmsg
= parse_lit8 (cd
, strp
, IP2K_OPERAND_LIT8
, (long *) (& fields
->f_imm8
));
518 case IP2K_OPERAND_PABITS
:
519 errmsg
= cgen_parse_unsigned_integer (cd
, strp
, IP2K_OPERAND_PABITS
, (unsigned long *) (& junk
));
521 case IP2K_OPERAND_RETI3
:
522 errmsg
= cgen_parse_unsigned_integer (cd
, strp
, IP2K_OPERAND_RETI3
, (unsigned long *) (& fields
->f_reti3
));
524 case IP2K_OPERAND_ZBIT
:
525 errmsg
= cgen_parse_unsigned_integer (cd
, strp
, IP2K_OPERAND_ZBIT
, (unsigned long *) (& junk
));
529 /* xgettext:c-format */
530 fprintf (stderr
, _("Unrecognized field %d while parsing.\n"), opindex
);
537 cgen_parse_fn
* const ip2k_cgen_parse_handlers
[] =
543 ip2k_cgen_init_asm (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. */
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
];
572 const CGEN_SYNTAX_CHAR_TYPE
*syn
;
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");
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
++)
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
);
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 ']':
640 /* Replace non-syntax fields with globs. */
646 /* Trailing whitespace ok. */
653 /* But anchor it after that. */
657 CGEN_INSN_RX (insn
) = xmalloc (sizeof (regex_t
));
658 reg_err
= regcomp ((regex_t
*) CGEN_INSN_RX (insn
), rxbuf
, REG_NOSUB
);
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
;
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. */
689 parse_insn_normal (CGEN_CPU_DESC cd
,
690 const CGEN_INSN
*insn
,
694 /* ??? Runtime added insns not handled yet. */
695 const CGEN_SYNTAX
*syntax
= CGEN_INSN_SYNTAX (insn
);
696 const char *str
= *strp
;
699 const CGEN_SYNTAX_CHAR_TYPE
* syn
;
700 #ifdef CGEN_MNEMONIC_OPERANDS
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
))
714 return _("unrecognized instruction");
716 #ifndef CGEN_MNEMONIC_OPERANDS
717 if (* str
&& ! ISSPACE (* str
))
718 return _("unrecognized instruction");
721 CGEN_INIT_PARSE (cd
);
722 cgen_init_parse_operand (cd
);
723 #ifdef CGEN_MNEMONIC_OPERANDS
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
))
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
) == ' ')
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
);
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
));
778 /* We have an operand of some sort. */
779 errmsg
= cd
->parse_operand (cd
, CGEN_SYNTAX_FIELD (*syn
),
784 /* Done with this operand, continue with next one. */
788 /* If we're at the end of the syntax string, we're done. */
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
))
799 return _("junk at end of line"); /* FIXME: would like to include `str' */
804 /* We couldn't parse it. */
805 return _("unrecognized instruction");
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
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. */
830 ip2k_cgen_assemble_insn (CGEN_CPU_DESC cd
,
833 CGEN_INSN_BYTES_PTR buf
,
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
))
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. */
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
))
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)
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
)
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
)
884 /* ??? 0 is passed for `pc'. */
885 insert_errmsg
= CGEN_INSERT_FN (cd
, insn
) (cd
, insn
, fields
, buf
,
887 if (insert_errmsg
!= NULL
)
890 /* It is up to the caller to actually output the insn and any
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
);
912 /* xgettext:c-format */
913 sprintf (errbuf
, "%s `%.50s'", tmp_errmsg
, start
);
915 if (strlen (start
) > 50)
916 /* xgettext:c-format */
917 sprintf (errbuf
, _("bad instruction `%.50s...'"), start
);
919 /* xgettext:c-format */
920 sprintf (errbuf
, _("bad instruction `%.50s'"), start
);
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. */
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
))
949 cgen_asm_record_register (cd
, ke
->name
, ke
->value
);