or1k-asm.c revision 1.1.1.4 1 /* DO NOT EDIT! -*- buffer-read-only: t -*- vi:set ro: */
2 /* Assembler interface for targets using CGEN. -*- C -*-
3 CGEN: Cpu tools GENerator
4
5 THIS FILE IS MACHINE GENERATED WITH CGEN.
6 - the resultant file is machine generated, cgen-asm.in isn't
7
8 Copyright (C) 1996-2018 Free Software Foundation, Inc.
9
10 This file is part of libopcodes.
11
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.
16
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.
21
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. */
25
26
27 /* ??? Eventually more and more of this stuff can go to cpu-independent files.
28 Keep that in mind. */
29
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"
41
42 #undef min
43 #define min(a,b) ((a) < (b) ? (a) : (b))
44 #undef max
45 #define max(a,b) ((a) > (b) ? (a) : (b))
46
47 static const char * parse_insn_normal
48 (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
49
50 /* -- assembler routines inserted here. */
52
53 /* -- asm.c */
54
55 static const char * MISSING_CLOSING_PARENTHESIS = N_("missing `)'");
56
57 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
58
59 static const char *
60 parse_disp26 (CGEN_CPU_DESC cd,
61 const char ** strp,
62 int opindex,
63 int opinfo,
64 enum cgen_parse_operand_result * resultp,
65 bfd_vma * valuep)
66 {
67 const char *errmsg = NULL;
68 enum cgen_parse_operand_result result_type;
69
70 if (strncasecmp (*strp, "plt(", 4) == 0)
71 {
72 bfd_vma value;
73
74 *strp += 4;
75 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_PLT26,
76 & result_type, & value);
77 if (**strp != ')')
78 return MISSING_CLOSING_PARENTHESIS;
79 ++*strp;
80 if (errmsg == NULL
81 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
82 value = (value >> 2) & 0xffff;
83 *valuep = value;
84 return errmsg;
85 }
86 return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
87 }
88
89 static const char *
90 parse_simm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, long * valuep)
91 {
92 const char *errmsg;
93 enum cgen_parse_operand_result result_type;
94 long ret;
95
96 if (**strp == '#')
97 ++*strp;
98
99 if (strncasecmp (*strp, "hi(", 3) == 0)
100 {
101 bfd_vma value;
102
103 *strp += 3;
104 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_HI16,
105 & result_type, & value);
106 if (**strp != ')')
107 errmsg = MISSING_CLOSING_PARENTHESIS;
108 ++*strp;
109
110 ret = value;
111
112 if (errmsg == NULL
113 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
114 {
115 ret >>= 16;
116 ret &= 0xffff;
117 ret = (ret ^ 0x8000) - 0x8000;
118 }
119 }
120 else if (strncasecmp (*strp, "lo(", 3) == 0)
121 {
122 bfd_vma value;
123
124 *strp += 3;
125 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_LO16,
126 & result_type, & value);
127 if (**strp != ')')
128 return MISSING_CLOSING_PARENTHESIS;
129 ++*strp;
130
131 ret = value;
132
133 if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
134 {
135 ret &= 0xffff;
136 ret = (ret ^ 0x8000) - 0x8000;
137 }
138 }
139 else if (strncasecmp (*strp, "got(", 4) == 0)
140 {
141 bfd_vma value;
142
143 *strp += 4;
144 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_OR1K_GOT16,
145 & result_type, & value);
146 if (**strp != ')')
147 return MISSING_CLOSING_PARENTHESIS;
148 ++*strp;
149 if (errmsg == NULL
150 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
151 value &= 0xffff;
152 *valuep = value;
153 return errmsg;
154 }
155 else if (strncasecmp (*strp, "gotpchi(", 8) == 0)
156 {
157 bfd_vma value;
158
159 *strp += 8;
160 errmsg = cgen_parse_address (cd, strp, opindex,
161 BFD_RELOC_OR1K_GOTPC_HI16,
162 & result_type, & value);
163 if (**strp != ')')
164 return MISSING_CLOSING_PARENTHESIS;
165 ++*strp;
166 if (errmsg == NULL
167 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
168 value = (value >> 16) & 0xffff;
169 *valuep = value;
170 return errmsg;
171 }
172 else if (strncasecmp (*strp, "gotpclo(", 8) == 0)
173 {
174 bfd_vma value;
175
176 *strp += 8;
177 errmsg = cgen_parse_address (cd, strp, opindex,
178 BFD_RELOC_OR1K_GOTPC_LO16,
179 &result_type, &value);
180 if (**strp != ')')
181 return MISSING_CLOSING_PARENTHESIS;
182 ++*strp;
183 if (errmsg == NULL
184 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
185 value &= 0xffff;
186 *valuep = value;
187 return errmsg;
188 }
189 else if (strncasecmp (*strp, "gotoffhi(", 9) == 0)
190 {
191 bfd_vma value;
192
193 *strp += 9;
194 errmsg = cgen_parse_address (cd, strp, opindex,
195 BFD_RELOC_OR1K_GOTOFF_HI16,
196 & result_type, & value);
197
198 if (**strp != ')')
199 return MISSING_CLOSING_PARENTHESIS;
200 ++*strp;
201 if (errmsg == NULL
202 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
203 value = (value >> 16) & 0xffff;
204 *valuep = value;
205 return errmsg;
206 }
207 else if (strncasecmp (*strp, "gotofflo(", 9) == 0)
208 {
209 bfd_vma value;
210
211 *strp += 9;
212 errmsg = cgen_parse_address (cd, strp, opindex,
213 BFD_RELOC_OR1K_GOTOFF_LO16,
214 &result_type, &value);
215 if (**strp != ')')
216 return MISSING_CLOSING_PARENTHESIS;
217 ++*strp;
218 if (errmsg == NULL
219 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
220 value &= 0xffff;
221 *valuep = value;
222 return errmsg;
223 }
224 else if (strncasecmp (*strp, "tlsgdhi(", 8) == 0)
225 {
226 bfd_vma value;
227
228 *strp += 8;
229 errmsg = cgen_parse_address (cd, strp, opindex,
230 BFD_RELOC_OR1K_TLS_GD_HI16,
231 & result_type, & value);
232
233 if (**strp != ')')
234 return MISSING_CLOSING_PARENTHESIS;
235 ++*strp;
236 if (errmsg == NULL
237 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
238 value = (value >> 16) & 0xffff;
239 *valuep = value;
240 return errmsg;
241 }
242 else if (strncasecmp (*strp, "tlsgdlo(", 8) == 0)
243 {
244 bfd_vma value;
245
246 *strp += 8;
247 errmsg = cgen_parse_address (cd, strp, opindex,
248 BFD_RELOC_OR1K_TLS_GD_LO16,
249 &result_type, &value);
250 if (**strp != ')')
251 return MISSING_CLOSING_PARENTHESIS;
252 ++*strp;
253 if (errmsg == NULL
254 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
255 value &= 0xffff;
256 *valuep = value;
257 return errmsg;
258 }
259 else if (strncasecmp (*strp, "tlsldmhi(", 9) == 0)
260 {
261 bfd_vma value;
262
263 *strp += 9;
264 errmsg = cgen_parse_address (cd, strp, opindex,
265 BFD_RELOC_OR1K_TLS_LDM_HI16,
266 & result_type, & value);
267
268 if (**strp != ')')
269 return MISSING_CLOSING_PARENTHESIS;
270 ++*strp;
271 if (errmsg == NULL
272 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
273 value = (value >> 16) & 0xffff;
274 *valuep = value;
275 return errmsg;
276 }
277 else if (strncasecmp (*strp, "tlsldmlo(", 9) == 0)
278 {
279 bfd_vma value;
280
281 *strp += 9;
282 errmsg = cgen_parse_address (cd, strp, opindex,
283 BFD_RELOC_OR1K_TLS_LDM_LO16,
284 &result_type, &value);
285 if (**strp != ')')
286 return MISSING_CLOSING_PARENTHESIS;
287 ++*strp;
288 if (errmsg == NULL
289 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
290 value &= 0xffff;
291 *valuep = value;
292 return errmsg;
293 }
294 else if (strncasecmp (*strp, "dtpoffhi(", 9) == 0)
295 {
296 bfd_vma value;
297
298 *strp += 9;
299 errmsg = cgen_parse_address (cd, strp, opindex,
300 BFD_RELOC_OR1K_TLS_LDO_HI16,
301 & result_type, & value);
302
303 if (**strp != ')')
304 return MISSING_CLOSING_PARENTHESIS;
305 ++*strp;
306 if (errmsg == NULL
307 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
308 value = (value >> 16) & 0xffff;
309 *valuep = value;
310 return errmsg;
311 }
312 else if (strncasecmp (*strp, "dtpofflo(", 9) == 0)
313 {
314 bfd_vma value;
315
316 *strp += 9;
317 errmsg = cgen_parse_address (cd, strp, opindex,
318 BFD_RELOC_OR1K_TLS_LDO_LO16,
319 &result_type, &value);
320 if (**strp != ')')
321 return MISSING_CLOSING_PARENTHESIS;
322 ++*strp;
323 if (errmsg == NULL
324 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
325 value &= 0xffff;
326 *valuep = value;
327 return errmsg;
328 }
329 else if (strncasecmp (*strp, "gottpoffhi(", 11) == 0)
330 {
331 bfd_vma value;
332
333 *strp += 11;
334 errmsg = cgen_parse_address (cd, strp, opindex,
335 BFD_RELOC_OR1K_TLS_IE_HI16,
336 & result_type, & value);
337
338 if (**strp != ')')
339 return MISSING_CLOSING_PARENTHESIS;
340 ++*strp;
341 if (errmsg == NULL
342 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
343 value = (value >> 16) & 0xffff;
344 *valuep = value;
345 return errmsg;
346 }
347 else if (strncasecmp (*strp, "gottpofflo(", 11) == 0)
348 {
349 bfd_vma value;
350
351 *strp += 11;
352 errmsg = cgen_parse_address (cd, strp, opindex,
353 BFD_RELOC_OR1K_TLS_IE_LO16,
354 &result_type, &value);
355 if (**strp != ')')
356 return MISSING_CLOSING_PARENTHESIS;
357 ++*strp;
358 if (errmsg == NULL
359 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
360 value &= 0xffff;
361 *valuep = value;
362 return errmsg;
363 }
364 else if (strncasecmp (*strp, "tpoffhi(", 8) == 0)
365 {
366 bfd_vma value;
367
368 *strp += 8;
369 errmsg = cgen_parse_address (cd, strp, opindex,
370 BFD_RELOC_OR1K_TLS_LE_HI16,
371 & result_type, & value);
372
373 if (**strp != ')')
374 return MISSING_CLOSING_PARENTHESIS;
375 ++*strp;
376 if (errmsg == NULL
377 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
378 value = (value >> 16) & 0xffff;
379 *valuep = value;
380 return errmsg;
381 }
382 else if (strncasecmp (*strp, "tpofflo(", 8) == 0)
383 {
384 bfd_vma value;
385
386 *strp += 8;
387 errmsg = cgen_parse_address (cd, strp, opindex,
388 BFD_RELOC_OR1K_TLS_LE_LO16,
389 &result_type, &value);
390 if (**strp != ')')
391 return MISSING_CLOSING_PARENTHESIS;
392 ++*strp;
393 if (errmsg == NULL
394 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
395 value &= 0xffff;
396 *valuep = value;
397 return errmsg;
398 }
399 else
400 {
401 long value;
402 errmsg = cgen_parse_signed_integer (cd, strp, opindex, &value);
403 ret = value;
404 }
405
406 if (errmsg == NULL)
407 *valuep = ret;
408
409 return errmsg;
410 }
411
412 static const char *
413 parse_uimm16 (CGEN_CPU_DESC cd, const char ** strp, int opindex, unsigned long * valuep)
414 {
415 const char *errmsg = parse_simm16(cd, strp, opindex, (long *) valuep);
416
417 if (errmsg == NULL)
418 *valuep &= 0xffff;
419 return errmsg;
420 }
421
422 /* -- */
423
424 const char * or1k_cgen_parse_operand
425 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
426
427 /* Main entry point for operand parsing.
428
429 This function is basically just a big switch statement. Earlier versions
430 used tables to look up the function to use, but
431 - if the table contains both assembler and disassembler functions then
432 the disassembler contains much of the assembler and vice-versa,
433 - there's a lot of inlining possibilities as things grow,
434 - using a switch statement avoids the function call overhead.
435
436 This function could be moved into `parse_insn_normal', but keeping it
437 separate makes clear the interface between `parse_insn_normal' and each of
438 the handlers. */
439
440 const char *
441 or1k_cgen_parse_operand (CGEN_CPU_DESC cd,
442 int opindex,
443 const char ** strp,
444 CGEN_FIELDS * fields)
445 {
446 const char * errmsg = NULL;
447 /* Used by scalar operands that still need to be parsed. */
448 long junk ATTRIBUTE_UNUSED;
449
450 switch (opindex)
451 {
452 case OR1K_OPERAND_DISP26 :
453 {
454 bfd_vma value = 0;
455 errmsg = parse_disp26 (cd, strp, OR1K_OPERAND_DISP26, 0, NULL, & value);
456 fields->f_disp26 = value;
457 }
458 break;
459 case OR1K_OPERAND_RA :
460 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r2);
461 break;
462 case OR1K_OPERAND_RADF :
463 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
464 break;
465 case OR1K_OPERAND_RASF :
466 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r2);
467 break;
468 case OR1K_OPERAND_RB :
469 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r3);
470 break;
471 case OR1K_OPERAND_RBDF :
472 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
473 break;
474 case OR1K_OPERAND_RBSF :
475 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r3);
476 break;
477 case OR1K_OPERAND_RD :
478 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r1);
479 break;
480 case OR1K_OPERAND_RDDF :
481 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
482 break;
483 case OR1K_OPERAND_RDSF :
484 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r1);
485 break;
486 case OR1K_OPERAND_SIMM16 :
487 errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16, (long *) (& fields->f_simm16));
488 break;
489 case OR1K_OPERAND_SIMM16_SPLIT :
490 errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16_SPLIT, (long *) (& fields->f_simm16_split));
491 break;
492 case OR1K_OPERAND_UIMM16 :
493 errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16));
494 break;
495 case OR1K_OPERAND_UIMM16_SPLIT :
496 errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16_SPLIT, (unsigned long *) (& fields->f_uimm16_split));
497 break;
498 case OR1K_OPERAND_UIMM6 :
499 errmsg = cgen_parse_unsigned_integer (cd, strp, OR1K_OPERAND_UIMM6, (unsigned long *) (& fields->f_uimm6));
500 break;
501
502 default :
503 /* xgettext:c-format */
504 opcodes_error_handler
505 (_("internal error: unrecognized field %d while parsing"),
506 opindex);
507 abort ();
508 }
509
510 return errmsg;
511 }
512
513 cgen_parse_fn * const or1k_cgen_parse_handlers[] =
514 {
515 parse_insn_normal,
516 };
517
518 void
519 or1k_cgen_init_asm (CGEN_CPU_DESC cd)
520 {
521 or1k_cgen_init_opcode_table (cd);
522 or1k_cgen_init_ibld_table (cd);
523 cd->parse_handlers = & or1k_cgen_parse_handlers[0];
524 cd->parse_operand = or1k_cgen_parse_operand;
525 #ifdef CGEN_ASM_INIT_HOOK
526 CGEN_ASM_INIT_HOOK
527 #endif
528 }
529
530
531
533 /* Regex construction routine.
534
535 This translates an opcode syntax string into a regex string,
536 by replacing any non-character syntax element (such as an
537 opcode) with the pattern '.*'
538
539 It then compiles the regex and stores it in the opcode, for
540 later use by or1k_cgen_assemble_insn
541
542 Returns NULL for success, an error message for failure. */
543
544 char *
545 or1k_cgen_build_insn_regex (CGEN_INSN *insn)
546 {
547 CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
548 const char *mnem = CGEN_INSN_MNEMONIC (insn);
549 char rxbuf[CGEN_MAX_RX_ELEMENTS];
550 char *rx = rxbuf;
551 const CGEN_SYNTAX_CHAR_TYPE *syn;
552 int reg_err;
553
554 syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
555
556 /* Mnemonics come first in the syntax string. */
557 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
558 return _("missing mnemonic in syntax string");
559 ++syn;
560
561 /* Generate a case sensitive regular expression that emulates case
562 insensitive matching in the "C" locale. We cannot generate a case
563 insensitive regular expression because in Turkish locales, 'i' and 'I'
564 are not equal modulo case conversion. */
565
566 /* Copy the literal mnemonic out of the insn. */
567 for (; *mnem; mnem++)
568 {
569 char c = *mnem;
570
571 if (ISALPHA (c))
572 {
573 *rx++ = '[';
574 *rx++ = TOLOWER (c);
575 *rx++ = TOUPPER (c);
576 *rx++ = ']';
577 }
578 else
579 *rx++ = c;
580 }
581
582 /* Copy any remaining literals from the syntax string into the rx. */
583 for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
584 {
585 if (CGEN_SYNTAX_CHAR_P (* syn))
586 {
587 char c = CGEN_SYNTAX_CHAR (* syn);
588
589 switch (c)
590 {
591 /* Escape any regex metacharacters in the syntax. */
592 case '.': case '[': case '\\':
593 case '*': case '^': case '$':
594
595 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
596 case '?': case '{': case '}':
597 case '(': case ')': case '*':
598 case '|': case '+': case ']':
599 #endif
600 *rx++ = '\\';
601 *rx++ = c;
602 break;
603
604 default:
605 if (ISALPHA (c))
606 {
607 *rx++ = '[';
608 *rx++ = TOLOWER (c);
609 *rx++ = TOUPPER (c);
610 *rx++ = ']';
611 }
612 else
613 *rx++ = c;
614 break;
615 }
616 }
617 else
618 {
619 /* Replace non-syntax fields with globs. */
620 *rx++ = '.';
621 *rx++ = '*';
622 }
623 }
624
625 /* Trailing whitespace ok. */
626 * rx++ = '[';
627 * rx++ = ' ';
628 * rx++ = '\t';
629 * rx++ = ']';
630 * rx++ = '*';
631
632 /* But anchor it after that. */
633 * rx++ = '$';
634 * rx = '\0';
635
636 CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
637 reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
638
639 if (reg_err == 0)
640 return NULL;
641 else
642 {
643 static char msg[80];
644
645 regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
646 regfree ((regex_t *) CGEN_INSN_RX (insn));
647 free (CGEN_INSN_RX (insn));
648 (CGEN_INSN_RX (insn)) = NULL;
649 return msg;
650 }
651 }
652
653
654 /* Default insn parser.
656
657 The syntax string is scanned and operands are parsed and stored in FIELDS.
658 Relocs are queued as we go via other callbacks.
659
660 ??? Note that this is currently an all-or-nothing parser. If we fail to
661 parse the instruction, we return 0 and the caller will start over from
662 the beginning. Backtracking will be necessary in parsing subexpressions,
663 but that can be handled there. Not handling backtracking here may get
664 expensive in the case of the m68k. Deal with later.
665
666 Returns NULL for success, an error message for failure. */
667
668 static const char *
669 parse_insn_normal (CGEN_CPU_DESC cd,
670 const CGEN_INSN *insn,
671 const char **strp,
672 CGEN_FIELDS *fields)
673 {
674 /* ??? Runtime added insns not handled yet. */
675 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
676 const char *str = *strp;
677 const char *errmsg;
678 const char *p;
679 const CGEN_SYNTAX_CHAR_TYPE * syn;
680 #ifdef CGEN_MNEMONIC_OPERANDS
681 /* FIXME: wip */
682 int past_opcode_p;
683 #endif
684
685 /* For now we assume the mnemonic is first (there are no leading operands).
686 We can parse it without needing to set up operand parsing.
687 GAS's input scrubber will ensure mnemonics are lowercase, but we may
688 not be called from GAS. */
689 p = CGEN_INSN_MNEMONIC (insn);
690 while (*p && TOLOWER (*p) == TOLOWER (*str))
691 ++p, ++str;
692
693 if (* p)
694 return _("unrecognized instruction");
695
696 #ifndef CGEN_MNEMONIC_OPERANDS
697 if (* str && ! ISSPACE (* str))
698 return _("unrecognized instruction");
699 #endif
700
701 CGEN_INIT_PARSE (cd);
702 cgen_init_parse_operand (cd);
703 #ifdef CGEN_MNEMONIC_OPERANDS
704 past_opcode_p = 0;
705 #endif
706
707 /* We don't check for (*str != '\0') here because we want to parse
708 any trailing fake arguments in the syntax string. */
709 syn = CGEN_SYNTAX_STRING (syntax);
710
711 /* Mnemonics come first for now, ensure valid string. */
712 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
713 abort ();
714
715 ++syn;
716
717 while (* syn != 0)
718 {
719 /* Non operand chars must match exactly. */
720 if (CGEN_SYNTAX_CHAR_P (* syn))
721 {
722 /* FIXME: While we allow for non-GAS callers above, we assume the
723 first char after the mnemonic part is a space. */
724 /* FIXME: We also take inappropriate advantage of the fact that
725 GAS's input scrubber will remove extraneous blanks. */
726 if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
727 {
728 #ifdef CGEN_MNEMONIC_OPERANDS
729 if (CGEN_SYNTAX_CHAR(* syn) == ' ')
730 past_opcode_p = 1;
731 #endif
732 ++ syn;
733 ++ str;
734 }
735 else if (*str)
736 {
737 /* Syntax char didn't match. Can't be this insn. */
738 static char msg [80];
739
740 /* xgettext:c-format */
741 sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
742 CGEN_SYNTAX_CHAR(*syn), *str);
743 return msg;
744 }
745 else
746 {
747 /* Ran out of input. */
748 static char msg [80];
749
750 /* xgettext:c-format */
751 sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
752 CGEN_SYNTAX_CHAR(*syn));
753 return msg;
754 }
755 continue;
756 }
757
758 #ifdef CGEN_MNEMONIC_OPERANDS
759 (void) past_opcode_p;
760 #endif
761 /* We have an operand of some sort. */
762 errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
763 if (errmsg)
764 return errmsg;
765
766 /* Done with this operand, continue with next one. */
767 ++ syn;
768 }
769
770 /* If we're at the end of the syntax string, we're done. */
771 if (* syn == 0)
772 {
773 /* FIXME: For the moment we assume a valid `str' can only contain
774 blanks now. IE: We needn't try again with a longer version of
775 the insn and it is assumed that longer versions of insns appear
776 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
777 while (ISSPACE (* str))
778 ++ str;
779
780 if (* str != '\0')
781 return _("junk at end of line"); /* FIXME: would like to include `str' */
782
783 return NULL;
784 }
785
786 /* We couldn't parse it. */
787 return _("unrecognized instruction");
788 }
789
790 /* Main entry point.
792 This routine is called for each instruction to be assembled.
793 STR points to the insn to be assembled.
794 We assume all necessary tables have been initialized.
795 The assembled instruction, less any fixups, is stored in BUF.
796 Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
797 still needs to be converted to target byte order, otherwise BUF is an array
798 of bytes in target byte order.
799 The result is a pointer to the insn's entry in the opcode table,
800 or NULL if an error occured (an error message will have already been
801 printed).
802
803 Note that when processing (non-alias) macro-insns,
804 this function recurses.
805
806 ??? It's possible to make this cpu-independent.
807 One would have to deal with a few minor things.
808 At this point in time doing so would be more of a curiosity than useful
809 [for example this file isn't _that_ big], but keeping the possibility in
810 mind helps keep the design clean. */
811
812 const CGEN_INSN *
813 or1k_cgen_assemble_insn (CGEN_CPU_DESC cd,
814 const char *str,
815 CGEN_FIELDS *fields,
816 CGEN_INSN_BYTES_PTR buf,
817 char **errmsg)
818 {
819 const char *start;
820 CGEN_INSN_LIST *ilist;
821 const char *parse_errmsg = NULL;
822 const char *insert_errmsg = NULL;
823 int recognized_mnemonic = 0;
824
825 /* Skip leading white space. */
826 while (ISSPACE (* str))
827 ++ str;
828
829 /* The instructions are stored in hashed lists.
830 Get the first in the list. */
831 ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
832
833 /* Keep looking until we find a match. */
834 start = str;
835 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
836 {
837 const CGEN_INSN *insn = ilist->insn;
838 recognized_mnemonic = 1;
839
840 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
841 /* Not usually needed as unsupported opcodes
842 shouldn't be in the hash lists. */
843 /* Is this insn supported by the selected cpu? */
844 if (! or1k_cgen_insn_supported (cd, insn))
845 continue;
846 #endif
847 /* If the RELAXED attribute is set, this is an insn that shouldn't be
848 chosen immediately. Instead, it is used during assembler/linker
849 relaxation if possible. */
850 if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
851 continue;
852
853 str = start;
854
855 /* Skip this insn if str doesn't look right lexically. */
856 if (CGEN_INSN_RX (insn) != NULL &&
857 regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
858 continue;
859
860 /* Allow parse/insert handlers to obtain length of insn. */
861 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
862
863 parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
864 if (parse_errmsg != NULL)
865 continue;
866
867 /* ??? 0 is passed for `pc'. */
868 insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
869 (bfd_vma) 0);
870 if (insert_errmsg != NULL)
871 continue;
872
873 /* It is up to the caller to actually output the insn and any
874 queued relocs. */
875 return insn;
876 }
877
878 {
879 static char errbuf[150];
880 const char *tmp_errmsg;
881 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
882 #define be_verbose 1
883 #else
884 #define be_verbose 0
885 #endif
886
887 if (be_verbose)
888 {
889 /* If requesting verbose error messages, use insert_errmsg.
890 Failing that, use parse_errmsg. */
891 tmp_errmsg = (insert_errmsg ? insert_errmsg :
892 parse_errmsg ? parse_errmsg :
893 recognized_mnemonic ?
894 _("unrecognized form of instruction") :
895 _("unrecognized instruction"));
896
897 if (strlen (start) > 50)
898 /* xgettext:c-format */
899 sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
900 else
901 /* xgettext:c-format */
902 sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
903 }
904 else
905 {
906 if (strlen (start) > 50)
907 /* xgettext:c-format */
908 sprintf (errbuf, _("bad instruction `%.50s...'"), start);
909 else
910 /* xgettext:c-format */
911 sprintf (errbuf, _("bad instruction `%.50s'"), start);
912 }
913
914 *errmsg = errbuf;
915 return NULL;
916 }
917 }
918