Automatic date update in version.in
[binutils-gdb.git] / opcodes / or1k-asm.c
blob9351c1b407b1beae802bc8255552fdd4734adf69
1 /* DO NOT EDIT! -*- buffer-read-only: t -*- vi:set ro: */
2 /* Assembler interface for targets using CGEN. -*- C -*-
3 CGEN: Cpu tools GENerator
5 THIS FILE IS MACHINE GENERATED WITH CGEN.
6 - the resultant file is machine generated, cgen-asm.in isn't
8 Copyright (C) 1996-2024 Free Software Foundation, Inc.
10 This file is part of libopcodes.
12 This library is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3, or (at your option)
15 any later version.
17 It is distributed in the hope that it will be useful, but WITHOUT
18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
20 License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software Foundation, Inc.,
24 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
27 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
28 Keep that in mind. */
30 #include "sysdep.h"
31 #include <stdio.h>
32 #include "ansidecl.h"
33 #include "bfd.h"
34 #include "symcat.h"
35 #include "or1k-desc.h"
36 #include "or1k-opc.h"
37 #include "opintl.h"
38 #include "xregex.h"
39 #include "libiberty.h"
40 #include "safe-ctype.h"
42 #undef min
43 #define min(a,b) ((a) < (b) ? (a) : (b))
44 #undef max
45 #define max(a,b) ((a) > (b) ? (a) : (b))
47 static const char * parse_insn_normal
48 (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
50 /* -- assembler routines inserted here. */
52 /* -- asm.c */
54 static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
55 static const char * INVALID_STORE_RELOC = N_("relocation invalid for store");
56 static const char * INVALID_RELOC_TYPE = N_("internal relocation type invalid");
58 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
60 static const char *
61 parse_disp26 (CGEN_CPU_DESC cd,
62 const char ** strp,
63 int opindex,
64 int opinfo ATTRIBUTE_UNUSED,
65 enum cgen_parse_operand_result * resultp,
66 bfd_vma * valuep)
68 const char *str = *strp;
69 const char *errmsg = NULL;
70 bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_REL_26;
72 if (strncasecmp (str, "plta(", 5) == 0)
74 *strp = str + 5;
75 reloc = BFD_RELOC_OR1K_PLTA26;
77 else if (strncasecmp (str, "plt(", 4) == 0)
79 *strp = str + 4;
80 reloc = BFD_RELOC_OR1K_PLT26;
83 errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
85 if (reloc != BFD_RELOC_OR1K_REL_26)
87 if (**strp != ')')
88 errmsg = MISSING_CLOSING_PARENTHESIS;
89 else
90 ++*strp;
93 return errmsg;
96 static const char *
97 parse_disp21 (CGEN_CPU_DESC cd,
98 const char ** strp,
99 int opindex,
100 int opinfo ATTRIBUTE_UNUSED,
101 enum cgen_parse_operand_result * resultp,
102 bfd_vma * valuep)
104 const char *str = *strp;
105 const char *errmsg = NULL;
106 bfd_reloc_code_real_type reloc = BFD_RELOC_OR1K_PCREL_PG21;
108 if (strncasecmp (str, "got(", 4) == 0)
110 *strp = str + 4;
111 reloc = BFD_RELOC_OR1K_GOT_PG21;
113 else if (strncasecmp (str, "tlsgd(", 6) == 0)
115 *strp = str + 6;
116 reloc = BFD_RELOC_OR1K_TLS_GD_PG21;
118 else if (strncasecmp (str, "tlsldm(", 7) == 0)
120 *strp = str + 7;
121 reloc = BFD_RELOC_OR1K_TLS_LDM_PG21;
123 else if (strncasecmp (str, "gottp(", 6) == 0)
125 *strp = str + 6;
126 reloc = BFD_RELOC_OR1K_TLS_IE_PG21;
129 errmsg = cgen_parse_address (cd, strp, opindex, reloc, resultp, valuep);
131 if (reloc != BFD_RELOC_OR1K_PCREL_PG21)
133 if (**strp != ')')
134 errmsg = MISSING_CLOSING_PARENTHESIS;
135 else
136 ++*strp;
139 return errmsg;
142 enum or1k_rclass
144 RCLASS_DIRECT = 0,
145 RCLASS_GOT = 1,
146 RCLASS_GOTPC = 2,
147 RCLASS_GOTOFF = 3,
148 RCLASS_TLSGD = 4,
149 RCLASS_TLSLDM = 5,
150 RCLASS_DTPOFF = 6,
151 RCLASS_GOTTPOFF = 7,
152 RCLASS_TPOFF = 8,
155 enum or1k_rtype
157 RTYPE_LO = 0,
158 RTYPE_SLO = 1,
159 RTYPE_PO = 2,
160 RTYPE_SPO = 3,
161 RTYPE_HI = 4,
162 RTYPE_AHI = 5,
165 #define RCLASS_SHIFT 3
166 #define RTYPE_MASK 7
168 static const bfd_reloc_code_real_type or1k_imm16_relocs[][6] = {
169 { BFD_RELOC_LO16,
170 BFD_RELOC_OR1K_SLO16,
171 BFD_RELOC_OR1K_LO13,
172 BFD_RELOC_OR1K_SLO13,
173 BFD_RELOC_HI16,
174 BFD_RELOC_HI16_S, },
175 { BFD_RELOC_OR1K_GOT16,
176 BFD_RELOC_UNUSED,
177 BFD_RELOC_OR1K_GOT_LO13,
178 BFD_RELOC_UNUSED,
179 BFD_RELOC_UNUSED,
180 BFD_RELOC_OR1K_GOT_AHI16 },
181 { BFD_RELOC_OR1K_GOTPC_LO16,
182 BFD_RELOC_UNUSED,
183 BFD_RELOC_UNUSED,
184 BFD_RELOC_UNUSED,
185 BFD_RELOC_OR1K_GOTPC_HI16,
186 BFD_RELOC_UNUSED },
187 { BFD_RELOC_LO16_GOTOFF,
188 BFD_RELOC_OR1K_GOTOFF_SLO16,
189 BFD_RELOC_UNUSED,
190 BFD_RELOC_UNUSED,
191 BFD_RELOC_HI16_GOTOFF,
192 BFD_RELOC_HI16_S_GOTOFF },
193 { BFD_RELOC_OR1K_TLS_GD_LO16,
194 BFD_RELOC_UNUSED,
195 BFD_RELOC_OR1K_TLS_GD_LO13,
196 BFD_RELOC_UNUSED,
197 BFD_RELOC_OR1K_TLS_GD_HI16,
198 BFD_RELOC_UNUSED },
199 { BFD_RELOC_OR1K_TLS_LDM_LO16,
200 BFD_RELOC_UNUSED,
201 BFD_RELOC_OR1K_TLS_LDM_LO13,
202 BFD_RELOC_UNUSED,
203 BFD_RELOC_OR1K_TLS_LDM_HI16,
204 BFD_RELOC_UNUSED },
205 { BFD_RELOC_OR1K_TLS_LDO_LO16,
206 BFD_RELOC_UNUSED,
207 BFD_RELOC_UNUSED,
208 BFD_RELOC_UNUSED,
209 BFD_RELOC_OR1K_TLS_LDO_HI16,
210 BFD_RELOC_UNUSED },
211 { BFD_RELOC_OR1K_TLS_IE_LO16,
212 BFD_RELOC_UNUSED,
213 BFD_RELOC_OR1K_TLS_IE_LO13,
214 BFD_RELOC_UNUSED,
215 BFD_RELOC_OR1K_TLS_IE_HI16,
216 BFD_RELOC_OR1K_TLS_IE_AHI16 },
217 { BFD_RELOC_OR1K_TLS_LE_LO16,
218 BFD_RELOC_OR1K_TLS_LE_SLO16,
219 BFD_RELOC_UNUSED,
220 BFD_RELOC_UNUSED,
221 BFD_RELOC_OR1K_TLS_LE_HI16,
222 BFD_RELOC_OR1K_TLS_LE_AHI16 },
225 static int
226 parse_reloc (const char **strp)
228 const char *str = *strp;
229 enum or1k_rclass cls = RCLASS_DIRECT;
230 enum or1k_rtype typ;
232 if (strncasecmp (str, "got(", 4) == 0)
234 *strp = str + 4;
235 return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_LO;
237 if (strncasecmp (str, "gotpo(", 6) == 0)
239 *strp = str + 6;
240 return (RCLASS_GOT << RCLASS_SHIFT) | RTYPE_PO;
242 if (strncasecmp (str, "gottppo(", 8) == 0)
244 *strp = str + 8;
245 return (RCLASS_GOTTPOFF << RCLASS_SHIFT) | RTYPE_PO;
248 if (strncasecmp (str, "gotpc", 5) == 0)
250 str += 5;
251 cls = RCLASS_GOTPC;
253 else if (strncasecmp (str, "gotoff", 6) == 0)
255 str += 6;
256 cls = RCLASS_GOTOFF;
258 else if (strncasecmp (str, "tlsgd", 5) == 0)
260 str += 5;
261 cls = RCLASS_TLSGD;
263 else if (strncasecmp (str, "tlsldm", 6) == 0)
265 str += 6;
266 cls = RCLASS_TLSLDM;
268 else if (strncasecmp (str, "dtpoff", 6) == 0)
270 str += 6;
271 cls = RCLASS_DTPOFF;
273 else if (strncasecmp (str, "gottpoff", 8) == 0)
275 str += 8;
276 cls = RCLASS_GOTTPOFF;
278 else if (strncasecmp (str, "tpoff", 5) == 0)
280 str += 5;
281 cls = RCLASS_TPOFF;
283 else if (strncasecmp (str, "got", 3) == 0)
285 str += 3;
286 cls = RCLASS_GOT;
289 if (strncasecmp (str, "hi(", 3) == 0)
291 str += 3;
292 typ = RTYPE_HI;
294 else if (strncasecmp (str, "lo(", 3) == 0)
296 str += 3;
297 typ = RTYPE_LO;
299 else if (strncasecmp (str, "ha(", 3) == 0)
301 str += 3;
302 typ = RTYPE_AHI;
304 else if (strncasecmp (str, "po(", 3) == 0 && cls != RCLASS_GOTTPOFF)
306 str += 3;
307 typ = RTYPE_PO;
309 else
310 return -1;
312 *strp = str;
313 return (cls << RCLASS_SHIFT) | typ;
316 static const char *
317 parse_imm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
318 long *valuep, int splitp)
320 const char *errmsg;
321 enum cgen_parse_operand_result result_type;
322 bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
323 enum or1k_rtype reloc_type;
324 int reloc_code;
325 bfd_vma ret;
327 if (**strp == '#')
328 ++*strp;
330 reloc_code = parse_reloc (strp);
331 reloc_type = reloc_code & RTYPE_MASK;
332 if (reloc_code >= 0)
334 enum or1k_rclass reloc_class = reloc_code >> RCLASS_SHIFT;
335 if (splitp)
337 if ((reloc_type == RTYPE_LO || reloc_type == RTYPE_PO)
338 && reloc_class != RCLASS_GOT)
339 /* If split we or up the type to RTYPE_SLO or RTYPE_SPO. */
340 reloc_type |= 1;
341 else
342 return INVALID_STORE_RELOC;
344 reloc = or1k_imm16_relocs[reloc_class][reloc_type];
347 if (reloc != BFD_RELOC_UNUSED)
349 bfd_vma value;
351 errmsg = cgen_parse_address (cd, strp, opindex, reloc,
352 &result_type, &value);
353 if (**strp != ')')
354 errmsg = MISSING_CLOSING_PARENTHESIS;
355 ++*strp;
357 ret = value;
359 if (errmsg == NULL && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
360 switch (reloc_type)
362 case RTYPE_AHI:
363 ret += 0x8000;
364 /* FALLTHRU */
365 case RTYPE_HI:
366 ret >>= 16;
367 /* FALLTHRU */
368 case RTYPE_LO:
369 case RTYPE_SLO:
370 ret &= 0xffff;
371 ret = (ret ^ 0x8000) - 0x8000;
372 break;
373 case RTYPE_PO:
374 case RTYPE_SPO:
375 ret &= 0x1fff;
376 break;
377 default:
378 errmsg = INVALID_RELOC_TYPE;
381 else
383 long value;
384 errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
385 ret = value;
388 if (errmsg == NULL)
389 *valuep = ret;
391 return errmsg;
394 static const char *
395 parse_simm16 (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
397 return parse_imm16(cd, strp, opindex, (long *) valuep, 0);
400 static const char *
401 parse_simm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
402 long *valuep)
404 return parse_imm16(cd, strp, opindex, (long *) valuep, 1);
407 static const char *
408 parse_uimm16 (CGEN_CPU_DESC cd, const char **strp, int opindex,
409 unsigned long *valuep)
411 const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 0);
412 if (errmsg == NULL)
413 *valuep &= 0xffff;
414 return errmsg;
417 static const char *
418 parse_uimm16_split (CGEN_CPU_DESC cd, const char **strp, int opindex,
419 unsigned long *valuep)
421 const char *errmsg = parse_imm16(cd, strp, opindex, (long *) valuep, 1);
422 if (errmsg == NULL)
423 *valuep &= 0xffff;
424 return errmsg;
427 /* Parse register pairs with syntax rA,rB to a flag + rA value. */
429 static const char *
430 parse_regpair (CGEN_CPU_DESC cd, const char **strp,
431 int opindex ATTRIBUTE_UNUSED, unsigned long *valuep)
433 long reg1_index;
434 long reg2_index;
435 const char *errmsg;
437 /* The first part should just be a register. */
438 errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
439 &reg1_index);
441 /* If that worked skip the comma separator. */
442 if (errmsg == NULL)
444 if (**strp == ',')
445 ++*strp;
446 else
447 errmsg = "Unexpected character, expected ','";
450 /* If that worked the next part is just another register. */
451 if (errmsg == NULL)
452 errmsg = cgen_parse_keyword (cd, strp, &or1k_cgen_opval_h_gpr,
453 &reg2_index);
455 /* Validate the register pair is valid and create the output value. */
456 if (errmsg == NULL)
458 int regoffset = reg2_index - reg1_index;
460 if (regoffset == 1 || regoffset == 2)
462 unsigned short offsetmask;
463 unsigned short value;
465 offsetmask = ((regoffset == 2 ? 1 : 0) << 5);
466 value = offsetmask | reg1_index;
468 *valuep = value;
470 else
471 errmsg = "Invalid register pair, offset not 1 or 2.";
474 return errmsg;
477 /* -- */
479 const char * or1k_cgen_parse_operand
480 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
482 /* Main entry point for operand parsing.
484 This function is basically just a big switch statement. Earlier versions
485 used tables to look up the function to use, but
486 - if the table contains both assembler and disassembler functions then
487 the disassembler contains much of the assembler and vice-versa,
488 - there's a lot of inlining possibilities as things grow,
489 - using a switch statement avoids the function call overhead.
491 This function could be moved into `parse_insn_normal', but keeping it
492 separate makes clear the interface between `parse_insn_normal' and each of
493 the handlers. */
495 const char *
496 or1k_cgen_parse_operand (CGEN_CPU_DESC cd,
497 int opindex,
498 const char ** strp,
499 CGEN_FIELDS * fields)
501 const char * errmsg = NULL;
502 /* Used by scalar operands that still need to be parsed. */
503 long junk ATTRIBUTE_UNUSED;
505 switch (opindex)
507 case OR1K_OPERAND_DISP21 :
509 bfd_vma value = 0;
510 errmsg = parse_disp21 (cd, strp, OR1K_OPERAND_DISP21, 0, NULL, & value);
511 fields->f_disp21 = value;
513 break;
514 case OR1K_OPERAND_DISP26 :
516 bfd_vma value = 0;
517 errmsg = parse_disp26 (cd, strp, OR1K_OPERAND_DISP26, 0, NULL, & value);
518 fields->f_disp26 = value;
520 break;
521 case OR1K_OPERAND_RA :
522 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r2);
523 break;
524 case OR1K_OPERAND_RAD32F :
525 errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RAD32F, (unsigned long *) (& fields->f_rad32));
526 break;
527 case OR1K_OPERAND_RADI :
528 errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RADI, (unsigned long *) (& fields->f_rad32));
529 break;
530 case OR1K_OPERAND_RASF :
531 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r2);
532 break;
533 case OR1K_OPERAND_RB :
534 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r3);
535 break;
536 case OR1K_OPERAND_RBD32F :
537 errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RBD32F, (unsigned long *) (& fields->f_rbd32));
538 break;
539 case OR1K_OPERAND_RBDI :
540 errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RBDI, (unsigned long *) (& fields->f_rbd32));
541 break;
542 case OR1K_OPERAND_RBSF :
543 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r3);
544 break;
545 case OR1K_OPERAND_RD :
546 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r1);
547 break;
548 case OR1K_OPERAND_RDD32F :
549 errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RDD32F, (unsigned long *) (& fields->f_rdd32));
550 break;
551 case OR1K_OPERAND_RDDI :
552 errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RDDI, (unsigned long *) (& fields->f_rdd32));
553 break;
554 case OR1K_OPERAND_RDSF :
555 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r1);
556 break;
557 case OR1K_OPERAND_SIMM16 :
558 errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16, (long *) (& fields->f_simm16));
559 break;
560 case OR1K_OPERAND_SIMM16_SPLIT :
561 errmsg = parse_simm16_split (cd, strp, OR1K_OPERAND_SIMM16_SPLIT, (long *) (& fields->f_simm16_split));
562 break;
563 case OR1K_OPERAND_UIMM16 :
564 errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16));
565 break;
566 case OR1K_OPERAND_UIMM16_SPLIT :
567 errmsg = parse_uimm16_split (cd, strp, OR1K_OPERAND_UIMM16_SPLIT, (unsigned long *) (& fields->f_uimm16_split));
568 break;
569 case OR1K_OPERAND_UIMM6 :
570 errmsg = cgen_parse_unsigned_integer (cd, strp, OR1K_OPERAND_UIMM6, (unsigned long *) (& fields->f_uimm6));
571 break;
573 default :
574 /* xgettext:c-format */
575 opcodes_error_handler
576 (_("internal error: unrecognized field %d while parsing"),
577 opindex);
578 abort ();
581 return errmsg;
584 cgen_parse_fn * const or1k_cgen_parse_handlers[] =
586 parse_insn_normal,
589 void
590 or1k_cgen_init_asm (CGEN_CPU_DESC cd)
592 or1k_cgen_init_opcode_table (cd);
593 or1k_cgen_init_ibld_table (cd);
594 cd->parse_handlers = & or1k_cgen_parse_handlers[0];
595 cd->parse_operand = or1k_cgen_parse_operand;
596 #ifdef CGEN_ASM_INIT_HOOK
597 CGEN_ASM_INIT_HOOK
598 #endif
603 /* Regex construction routine.
605 This translates an opcode syntax string into a regex string,
606 by replacing any non-character syntax element (such as an
607 opcode) with the pattern '.*'
609 It then compiles the regex and stores it in the opcode, for
610 later use by or1k_cgen_assemble_insn
612 Returns NULL for success, an error message for failure. */
614 char *
615 or1k_cgen_build_insn_regex (CGEN_INSN *insn)
617 CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
618 const char *mnem = CGEN_INSN_MNEMONIC (insn);
619 char rxbuf[CGEN_MAX_RX_ELEMENTS];
620 char *rx = rxbuf;
621 const CGEN_SYNTAX_CHAR_TYPE *syn;
622 char prev_syntax_char = 0;
623 int reg_err;
625 syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
627 /* Mnemonics come first in the syntax string. */
628 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
629 return _("missing mnemonic in syntax string");
630 ++syn;
632 /* Generate a case sensitive regular expression that emulates case
633 insensitive matching in the "C" locale. We cannot generate a case
634 insensitive regular expression because in Turkish locales, 'i' and 'I'
635 are not equal modulo case conversion. */
637 /* Copy the literal mnemonic out of the insn. */
638 for (; *mnem; mnem++)
640 char c = *mnem;
642 if (ISALPHA (c))
644 *rx++ = '[';
645 *rx++ = TOLOWER (c);
646 *rx++ = TOUPPER (c);
647 *rx++ = ']';
649 else
650 *rx++ = c;
653 /* Copy any remaining literals from the syntax string into the rx. */
654 for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
656 if (CGEN_SYNTAX_CHAR_P (* syn))
658 char c = CGEN_SYNTAX_CHAR (* syn);
660 /* See whitespace related comments in parse_insn_normal(). */
661 if (c != ' ' && prev_syntax_char != ' '
662 && (!ISALNUM (c) || !ISALNUM (prev_syntax_char)))
664 *rx++ = ' ';
665 *rx++ = '*';
667 prev_syntax_char = c;
669 switch (c)
671 /* Escape any regex metacharacters in the syntax. */
672 case '.': case '[': case '\\':
673 case '*': case '^': case '$':
675 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
676 case '?': case '{': case '}':
677 case '(': case ')': case '*':
678 case '|': case '+': case ']':
679 #endif
680 *rx++ = '\\';
681 *rx++ = c;
682 break;
684 default:
685 if (ISALPHA (c))
687 *rx++ = '[';
688 *rx++ = TOLOWER (c);
689 *rx++ = TOUPPER (c);
690 *rx++ = ']';
692 else
693 *rx++ = c;
694 break;
697 else
699 /* Replace non-syntax fields with globs. */
700 *rx++ = '.';
701 *rx++ = '*';
702 prev_syntax_char = 0;
706 /* Trailing whitespace ok. */
707 * rx++ = '[';
708 * rx++ = ' ';
709 * rx++ = '\t';
710 * rx++ = ']';
711 * rx++ = '*';
713 /* But anchor it after that. */
714 * rx++ = '$';
715 * rx = '\0';
717 CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
718 reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
720 if (reg_err == 0)
721 return NULL;
722 else
724 static char msg[80];
726 regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
727 regfree ((regex_t *) CGEN_INSN_RX (insn));
728 free (CGEN_INSN_RX (insn));
729 (CGEN_INSN_RX (insn)) = NULL;
730 return msg;
735 /* Default insn parser.
737 The syntax string is scanned and operands are parsed and stored in FIELDS.
738 Relocs are queued as we go via other callbacks.
740 ??? Note that this is currently an all-or-nothing parser. If we fail to
741 parse the instruction, we return 0 and the caller will start over from
742 the beginning. Backtracking will be necessary in parsing subexpressions,
743 but that can be handled there. Not handling backtracking here may get
744 expensive in the case of the m68k. Deal with later.
746 Returns NULL for success, an error message for failure. */
748 static const char *
749 parse_insn_normal (CGEN_CPU_DESC cd,
750 const CGEN_INSN *insn,
751 const char **strp,
752 CGEN_FIELDS *fields)
754 /* ??? Runtime added insns not handled yet. */
755 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
756 const char *str = *strp;
757 const char *errmsg;
758 const char *p;
759 const CGEN_SYNTAX_CHAR_TYPE * syn;
760 char prev_syntax_char = 0;
761 bool past_opcode_p;
763 /* For now we assume the mnemonic is first (there are no leading operands).
764 We can parse it without needing to set up operand parsing.
765 GAS's input scrubber will ensure mnemonics are lowercase, but we may
766 not be called from GAS. */
767 p = CGEN_INSN_MNEMONIC (insn);
768 while (*p && TOLOWER (*p) == TOLOWER (*str))
769 ++p, ++str;
771 if (* p)
772 return _("unrecognized instruction");
774 #ifndef CGEN_MNEMONIC_OPERANDS
775 if (* str && ! ISSPACE (* str))
776 return _("unrecognized instruction");
777 past_opcode_p = true;
778 #else
779 past_opcode_p = false;
780 #endif
782 CGEN_INIT_PARSE (cd);
783 cgen_init_parse_operand (cd);
785 /* We don't check for (*str != '\0') here because we want to parse
786 any trailing fake arguments in the syntax string. */
787 syn = CGEN_SYNTAX_STRING (syntax);
789 /* Mnemonics come first for now, ensure valid string. */
790 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
791 abort ();
793 ++syn;
795 while (* syn != 0)
797 char c = CGEN_SYNTAX_CHAR_P (*syn) ? CGEN_SYNTAX_CHAR (*syn) : 0;
799 /* FIXME: Despite this check we may still take inappropriate advantage of
800 the fact that GAS's input scrubber will remove extraneous whitespace.
801 We may also be a little too lax with this now, yet being more strict
802 would require targets to indicate where whitespace is permissible. */
803 if (past_opcode_p && c != ' ' && ISSPACE (*str)
804 /* No whitespace between consecutive alphanumeric syntax elements. */
805 && (!ISALNUM (c) || !ISALNUM (prev_syntax_char)))
806 ++str;
807 prev_syntax_char = c;
809 /* Non operand chars must match exactly. */
810 if (c != 0)
812 /* FIXME: While we allow for non-GAS callers above, we assume the
813 first char after the mnemonic part is a space. */
814 if (TOLOWER (*str) == TOLOWER (c))
816 #ifdef CGEN_MNEMONIC_OPERANDS
817 if (c == ' ')
818 past_opcode_p = true;
819 #endif
820 ++ syn;
821 ++ str;
823 else if (*str)
825 /* Syntax char didn't match. Can't be this insn. */
826 static char msg [80];
828 /* xgettext:c-format */
829 sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
830 c, *str);
831 return msg;
833 else
835 /* Ran out of input. */
836 static char msg [80];
838 /* xgettext:c-format */
839 sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
841 return msg;
843 continue;
846 /* We have an operand of some sort. */
847 errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
848 if (errmsg)
849 return errmsg;
851 /* Done with this operand, continue with next one. */
852 ++ syn;
855 /* If we're at the end of the syntax string, we're done. */
856 if (* syn == 0)
858 /* FIXME: For the moment we assume a valid `str' can only contain
859 blanks now. IE: We needn't try again with a longer version of
860 the insn and it is assumed that longer versions of insns appear
861 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
862 while (ISSPACE (* str))
863 ++ str;
865 if (* str != '\0')
866 return _("junk at end of line"); /* FIXME: would like to include `str' */
868 return NULL;
871 /* We couldn't parse it. */
872 return _("unrecognized instruction");
875 /* Main entry point.
876 This routine is called for each instruction to be assembled.
877 STR points to the insn to be assembled.
878 We assume all necessary tables have been initialized.
879 The assembled instruction, less any fixups, is stored in BUF.
880 Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
881 still needs to be converted to target byte order, otherwise BUF is an array
882 of bytes in target byte order.
883 The result is a pointer to the insn's entry in the opcode table,
884 or NULL if an error occured (an error message will have already been
885 printed).
887 Note that when processing (non-alias) macro-insns,
888 this function recurses.
890 ??? It's possible to make this cpu-independent.
891 One would have to deal with a few minor things.
892 At this point in time doing so would be more of a curiosity than useful
893 [for example this file isn't _that_ big], but keeping the possibility in
894 mind helps keep the design clean. */
896 const CGEN_INSN *
897 or1k_cgen_assemble_insn (CGEN_CPU_DESC cd,
898 const char *str,
899 CGEN_FIELDS *fields,
900 CGEN_INSN_BYTES_PTR buf,
901 char **errmsg)
903 const char *start;
904 CGEN_INSN_LIST *ilist;
905 const char *parse_errmsg = NULL;
906 const char *insert_errmsg = NULL;
907 int recognized_mnemonic = 0;
909 /* Skip leading white space. */
910 while (ISSPACE (* str))
911 ++ str;
913 /* The instructions are stored in hashed lists.
914 Get the first in the list. */
915 ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
917 /* Keep looking until we find a match. */
918 start = str;
919 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
921 const CGEN_INSN *insn = ilist->insn;
922 recognized_mnemonic = 1;
924 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
925 /* Not usually needed as unsupported opcodes
926 shouldn't be in the hash lists. */
927 /* Is this insn supported by the selected cpu? */
928 if (! or1k_cgen_insn_supported (cd, insn))
929 continue;
930 #endif
931 /* If the RELAXED attribute is set, this is an insn that shouldn't be
932 chosen immediately. Instead, it is used during assembler/linker
933 relaxation if possible. */
934 if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
935 continue;
937 str = start;
939 /* Skip this insn if str doesn't look right lexically. */
940 if (CGEN_INSN_RX (insn) != NULL &&
941 regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
942 continue;
944 /* Allow parse/insert handlers to obtain length of insn. */
945 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
947 parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
948 if (parse_errmsg != NULL)
949 continue;
951 /* ??? 0 is passed for `pc'. */
952 insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
953 (bfd_vma) 0);
954 if (insert_errmsg != NULL)
955 continue;
957 /* It is up to the caller to actually output the insn and any
958 queued relocs. */
959 return insn;
963 static char errbuf[150];
964 const char *tmp_errmsg;
965 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
966 #define be_verbose 1
967 #else
968 #define be_verbose 0
969 #endif
971 if (be_verbose)
973 /* If requesting verbose error messages, use insert_errmsg.
974 Failing that, use parse_errmsg. */
975 tmp_errmsg = (insert_errmsg ? insert_errmsg :
976 parse_errmsg ? parse_errmsg :
977 recognized_mnemonic ?
978 _("unrecognized form of instruction") :
979 _("unrecognized instruction"));
981 if (strlen (start) > 50)
982 /* xgettext:c-format */
983 sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
984 else
985 /* xgettext:c-format */
986 sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
988 else
990 if (strlen (start) > 50)
991 /* xgettext:c-format */
992 sprintf (errbuf, _("bad instruction `%.50s...'"), start);
993 else
994 /* xgettext:c-format */
995 sprintf (errbuf, _("bad instruction `%.50s'"), start);
998 *errmsg = errbuf;
999 return NULL;