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