Annotation of src/external/gpl3/binutils/dist/opcodes/fr30-asm.c, Revision 1.1.1.5.2.2
1.1.1.5 christos 1: /* DO NOT EDIT! -*- buffer-read-only: t -*- vi:set ro: */
1.1 skrll 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:
1.1.1.5.2.2! martin 8: Copyright (C) 1996-2020 Free Software Foundation, Inc.
1.1 skrll 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 "fr30-desc.h"
36: #include "fr30-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. */
51:
52: /* -- asm.c */
53: /* Handle register lists for LDMx and STMx. */
54:
55: static int
56: parse_register_number (const char **strp)
57: {
58: int regno;
59:
60: if (**strp < '0' || **strp > '9')
61: return -1; /* Error. */
62: regno = **strp - '0';
63: ++*strp;
64:
65: if (**strp >= '0' && **strp <= '9')
66: {
67: regno = regno * 10 + (**strp - '0');
68: ++*strp;
69: }
70:
71: return regno;
72: }
73:
74: static const char *
75: parse_register_list (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
76: const char **strp,
77: int opindex ATTRIBUTE_UNUSED,
78: unsigned long *valuep,
79: int high_low, /* 0 == high, 1 == low. */
80: int load_store) /* 0 == load, 1 == store. */
81: {
82: *valuep = 0;
83: while (**strp && **strp != ')')
84: {
85: int regno;
86:
87: if (**strp != 'R' && **strp != 'r')
88: break;
89: ++*strp;
90:
91: regno = parse_register_number (strp);
92: if (regno == -1)
93: return _("Register number is not valid");
94: if (regno > 7 && !high_low)
95: return _("Register must be between r0 and r7");
96: if (regno < 8 && high_low)
97: return _("Register must be between r8 and r15");
98:
99: if (high_low)
100: regno -= 8;
101:
102: if (load_store) /* Mask is reversed for store. */
103: *valuep |= 0x80 >> regno;
104: else
105: *valuep |= 1 << regno;
106:
107: if (**strp == ',')
108: {
109: if (*(*strp + 1) == ')')
110: break;
111: ++*strp;
112: }
113: }
114:
115: if (!*strp || **strp != ')')
116: return _("Register list is not valid");
117:
118: return NULL;
119: }
120:
121: static const char *
122: parse_low_register_list_ld (CGEN_CPU_DESC cd,
123: const char **strp,
124: int opindex,
125: unsigned long *valuep)
126: {
127: return parse_register_list (cd, strp, opindex, valuep,
128: 0 /* Low. */, 0 /* Load. */);
129: }
130:
131: static const char *
132: parse_hi_register_list_ld (CGEN_CPU_DESC cd,
133: const char **strp,
134: int opindex,
135: unsigned long *valuep)
136: {
137: return parse_register_list (cd, strp, opindex, valuep,
138: 1 /* High. */, 0 /* Load. */);
139: }
140:
141: static const char *
142: parse_low_register_list_st (CGEN_CPU_DESC cd,
143: const char **strp,
144: int opindex,
145: unsigned long *valuep)
146: {
147: return parse_register_list (cd, strp, opindex, valuep,
148: 0 /* Low. */, 1 /* Store. */);
149: }
150:
151: static const char *
152: parse_hi_register_list_st (CGEN_CPU_DESC cd,
153: const char **strp,
154: int opindex,
155: unsigned long *valuep)
156: {
157: return parse_register_list (cd, strp, opindex, valuep,
158: 1 /* High. */, 1 /* Store. */);
159: }
160:
161: /* -- */
162:
163: const char * fr30_cgen_parse_operand
164: (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
165:
166: /* Main entry point for operand parsing.
167:
168: This function is basically just a big switch statement. Earlier versions
169: used tables to look up the function to use, but
170: - if the table contains both assembler and disassembler functions then
171: the disassembler contains much of the assembler and vice-versa,
172: - there's a lot of inlining possibilities as things grow,
173: - using a switch statement avoids the function call overhead.
174:
175: This function could be moved into `parse_insn_normal', but keeping it
176: separate makes clear the interface between `parse_insn_normal' and each of
177: the handlers. */
178:
179: const char *
180: fr30_cgen_parse_operand (CGEN_CPU_DESC cd,
181: int opindex,
182: const char ** strp,
183: CGEN_FIELDS * fields)
184: {
185: const char * errmsg = NULL;
186: /* Used by scalar operands that still need to be parsed. */
187: long junk ATTRIBUTE_UNUSED;
188:
189: switch (opindex)
190: {
191: case FR30_OPERAND_CRI :
192: errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_cr_names, & fields->f_CRi);
193: break;
194: case FR30_OPERAND_CRJ :
195: errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_cr_names, & fields->f_CRj);
196: break;
197: case FR30_OPERAND_R13 :
198: errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r13, & junk);
199: break;
200: case FR30_OPERAND_R14 :
201: errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r14, & junk);
202: break;
203: case FR30_OPERAND_R15 :
204: errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_r15, & junk);
205: break;
206: case FR30_OPERAND_RI :
207: errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Ri);
208: break;
209: case FR30_OPERAND_RIC :
210: errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Ric);
211: break;
212: case FR30_OPERAND_RJ :
213: errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Rj);
214: break;
215: case FR30_OPERAND_RJC :
216: errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_gr_names, & fields->f_Rjc);
217: break;
218: case FR30_OPERAND_RS1 :
219: errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_dr_names, & fields->f_Rs1);
220: break;
221: case FR30_OPERAND_RS2 :
222: errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_dr_names, & fields->f_Rs2);
223: break;
224: case FR30_OPERAND_CC :
225: errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_CC, (unsigned long *) (& fields->f_cc));
226: break;
227: case FR30_OPERAND_CCC :
228: errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_CCC, (unsigned long *) (& fields->f_ccc));
229: break;
230: case FR30_OPERAND_DIR10 :
231: errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR10, (unsigned long *) (& fields->f_dir10));
232: break;
233: case FR30_OPERAND_DIR8 :
234: errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR8, (unsigned long *) (& fields->f_dir8));
235: break;
236: case FR30_OPERAND_DIR9 :
237: errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_DIR9, (unsigned long *) (& fields->f_dir9));
238: break;
239: case FR30_OPERAND_DISP10 :
240: errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP10, (long *) (& fields->f_disp10));
241: break;
242: case FR30_OPERAND_DISP8 :
243: errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP8, (long *) (& fields->f_disp8));
244: break;
245: case FR30_OPERAND_DISP9 :
246: errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_DISP9, (long *) (& fields->f_disp9));
247: break;
248: case FR30_OPERAND_I20 :
249: errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I20, (unsigned long *) (& fields->f_i20));
250: break;
251: case FR30_OPERAND_I32 :
252: errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I32, (unsigned long *) (& fields->f_i32));
253: break;
254: case FR30_OPERAND_I8 :
255: errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_I8, (unsigned long *) (& fields->f_i8));
256: break;
257: case FR30_OPERAND_LABEL12 :
258: {
259: bfd_vma value = 0;
260: errmsg = cgen_parse_address (cd, strp, FR30_OPERAND_LABEL12, 0, NULL, & value);
261: fields->f_rel12 = value;
262: }
263: break;
264: case FR30_OPERAND_LABEL9 :
265: {
266: bfd_vma value = 0;
267: errmsg = cgen_parse_address (cd, strp, FR30_OPERAND_LABEL9, 0, NULL, & value);
268: fields->f_rel9 = value;
269: }
270: break;
271: case FR30_OPERAND_M4 :
272: errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_M4, (long *) (& fields->f_m4));
273: break;
274: case FR30_OPERAND_PS :
275: errmsg = cgen_parse_keyword (cd, strp, & fr30_cgen_opval_h_ps, & junk);
276: break;
277: case FR30_OPERAND_REGLIST_HI_LD :
278: errmsg = parse_hi_register_list_ld (cd, strp, FR30_OPERAND_REGLIST_HI_LD, (unsigned long *) (& fields->f_reglist_hi_ld));
279: break;
280: case FR30_OPERAND_REGLIST_HI_ST :
281: errmsg = parse_hi_register_list_st (cd, strp, FR30_OPERAND_REGLIST_HI_ST, (unsigned long *) (& fields->f_reglist_hi_st));
282: break;
283: case FR30_OPERAND_REGLIST_LOW_LD :
284: errmsg = parse_low_register_list_ld (cd, strp, FR30_OPERAND_REGLIST_LOW_LD, (unsigned long *) (& fields->f_reglist_low_ld));
285: break;
286: case FR30_OPERAND_REGLIST_LOW_ST :
287: errmsg = parse_low_register_list_st (cd, strp, FR30_OPERAND_REGLIST_LOW_ST, (unsigned long *) (& fields->f_reglist_low_st));
288: break;
289: case FR30_OPERAND_S10 :
290: errmsg = cgen_parse_signed_integer (cd, strp, FR30_OPERAND_S10, (long *) (& fields->f_s10));
291: break;
292: case FR30_OPERAND_U10 :
293: errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U10, (unsigned long *) (& fields->f_u10));
294: break;
295: case FR30_OPERAND_U4 :
296: errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U4, (unsigned long *) (& fields->f_u4));
297: break;
298: case FR30_OPERAND_U4C :
299: errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U4C, (unsigned long *) (& fields->f_u4c));
300: break;
301: case FR30_OPERAND_U8 :
302: errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_U8, (unsigned long *) (& fields->f_u8));
303: break;
304: case FR30_OPERAND_UDISP6 :
305: errmsg = cgen_parse_unsigned_integer (cd, strp, FR30_OPERAND_UDISP6, (unsigned long *) (& fields->f_udisp6));
306: break;
307:
308: default :
309: /* xgettext:c-format */
1.1.1.5.2.1 christos 310: opcodes_error_handler
311: (_("internal error: unrecognized field %d while parsing"),
312: opindex);
1.1 skrll 313: abort ();
314: }
315:
316: return errmsg;
317: }
318:
1.1.1.3 christos 319: cgen_parse_fn * const fr30_cgen_parse_handlers[] =
1.1 skrll 320: {
321: parse_insn_normal,
322: };
323:
324: void
325: fr30_cgen_init_asm (CGEN_CPU_DESC cd)
326: {
327: fr30_cgen_init_opcode_table (cd);
328: fr30_cgen_init_ibld_table (cd);
329: cd->parse_handlers = & fr30_cgen_parse_handlers[0];
330: cd->parse_operand = fr30_cgen_parse_operand;
331: #ifdef CGEN_ASM_INIT_HOOK
332: CGEN_ASM_INIT_HOOK
333: #endif
334: }
335:
336:
337:
338: /* Regex construction routine.
339:
340: This translates an opcode syntax string into a regex string,
341: by replacing any non-character syntax element (such as an
342: opcode) with the pattern '.*'
343:
344: It then compiles the regex and stores it in the opcode, for
345: later use by fr30_cgen_assemble_insn
346:
347: Returns NULL for success, an error message for failure. */
348:
1.1.1.3 christos 349: char *
1.1 skrll 350: fr30_cgen_build_insn_regex (CGEN_INSN *insn)
1.1.1.3 christos 351: {
1.1 skrll 352: CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
353: const char *mnem = CGEN_INSN_MNEMONIC (insn);
354: char rxbuf[CGEN_MAX_RX_ELEMENTS];
355: char *rx = rxbuf;
356: const CGEN_SYNTAX_CHAR_TYPE *syn;
357: int reg_err;
358:
359: syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
360:
361: /* Mnemonics come first in the syntax string. */
362: if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
363: return _("missing mnemonic in syntax string");
364: ++syn;
365:
366: /* Generate a case sensitive regular expression that emulates case
367: insensitive matching in the "C" locale. We cannot generate a case
368: insensitive regular expression because in Turkish locales, 'i' and 'I'
369: are not equal modulo case conversion. */
370:
371: /* Copy the literal mnemonic out of the insn. */
372: for (; *mnem; mnem++)
373: {
374: char c = *mnem;
375:
376: if (ISALPHA (c))
377: {
378: *rx++ = '[';
379: *rx++ = TOLOWER (c);
380: *rx++ = TOUPPER (c);
381: *rx++ = ']';
382: }
383: else
384: *rx++ = c;
385: }
386:
387: /* Copy any remaining literals from the syntax string into the rx. */
388: for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
389: {
1.1.1.3 christos 390: if (CGEN_SYNTAX_CHAR_P (* syn))
1.1 skrll 391: {
392: char c = CGEN_SYNTAX_CHAR (* syn);
393:
1.1.1.3 christos 394: switch (c)
1.1 skrll 395: {
396: /* Escape any regex metacharacters in the syntax. */
1.1.1.3 christos 397: case '.': case '[': case '\\':
398: case '*': case '^': case '$':
1.1 skrll 399:
400: #ifdef CGEN_ESCAPE_EXTENDED_REGEX
1.1.1.3 christos 401: case '?': case '{': case '}':
1.1 skrll 402: case '(': case ')': case '*':
403: case '|': case '+': case ']':
404: #endif
405: *rx++ = '\\';
406: *rx++ = c;
407: break;
408:
409: default:
410: if (ISALPHA (c))
411: {
412: *rx++ = '[';
413: *rx++ = TOLOWER (c);
414: *rx++ = TOUPPER (c);
415: *rx++ = ']';
416: }
417: else
418: *rx++ = c;
419: break;
420: }
421: }
422: else
423: {
424: /* Replace non-syntax fields with globs. */
425: *rx++ = '.';
426: *rx++ = '*';
427: }
428: }
429:
430: /* Trailing whitespace ok. */
1.1.1.3 christos 431: * rx++ = '[';
432: * rx++ = ' ';
433: * rx++ = '\t';
434: * rx++ = ']';
435: * rx++ = '*';
1.1 skrll 436:
437: /* But anchor it after that. */
1.1.1.3 christos 438: * rx++ = '$';
1.1 skrll 439: * rx = '\0';
440:
441: CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
442: reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
443:
1.1.1.3 christos 444: if (reg_err == 0)
1.1 skrll 445: return NULL;
446: else
447: {
448: static char msg[80];
449:
450: regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
451: regfree ((regex_t *) CGEN_INSN_RX (insn));
452: free (CGEN_INSN_RX (insn));
453: (CGEN_INSN_RX (insn)) = NULL;
454: return msg;
455: }
456: }
457:
458:
459: /* Default insn parser.
460:
461: The syntax string is scanned and operands are parsed and stored in FIELDS.
462: Relocs are queued as we go via other callbacks.
463:
464: ??? Note that this is currently an all-or-nothing parser. If we fail to
465: parse the instruction, we return 0 and the caller will start over from
466: the beginning. Backtracking will be necessary in parsing subexpressions,
467: but that can be handled there. Not handling backtracking here may get
468: expensive in the case of the m68k. Deal with later.
469:
470: Returns NULL for success, an error message for failure. */
471:
472: static const char *
473: parse_insn_normal (CGEN_CPU_DESC cd,
474: const CGEN_INSN *insn,
475: const char **strp,
476: CGEN_FIELDS *fields)
477: {
478: /* ??? Runtime added insns not handled yet. */
479: const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
480: const char *str = *strp;
481: const char *errmsg;
482: const char *p;
483: const CGEN_SYNTAX_CHAR_TYPE * syn;
484: #ifdef CGEN_MNEMONIC_OPERANDS
485: /* FIXME: wip */
486: int past_opcode_p;
487: #endif
488:
489: /* For now we assume the mnemonic is first (there are no leading operands).
490: We can parse it without needing to set up operand parsing.
491: GAS's input scrubber will ensure mnemonics are lowercase, but we may
492: not be called from GAS. */
493: p = CGEN_INSN_MNEMONIC (insn);
494: while (*p && TOLOWER (*p) == TOLOWER (*str))
495: ++p, ++str;
496:
497: if (* p)
498: return _("unrecognized instruction");
499:
500: #ifndef CGEN_MNEMONIC_OPERANDS
501: if (* str && ! ISSPACE (* str))
502: return _("unrecognized instruction");
503: #endif
504:
505: CGEN_INIT_PARSE (cd);
506: cgen_init_parse_operand (cd);
507: #ifdef CGEN_MNEMONIC_OPERANDS
508: past_opcode_p = 0;
509: #endif
510:
511: /* We don't check for (*str != '\0') here because we want to parse
512: any trailing fake arguments in the syntax string. */
513: syn = CGEN_SYNTAX_STRING (syntax);
514:
515: /* Mnemonics come first for now, ensure valid string. */
516: if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
517: abort ();
518:
519: ++syn;
520:
521: while (* syn != 0)
522: {
523: /* Non operand chars must match exactly. */
524: if (CGEN_SYNTAX_CHAR_P (* syn))
525: {
526: /* FIXME: While we allow for non-GAS callers above, we assume the
527: first char after the mnemonic part is a space. */
528: /* FIXME: We also take inappropriate advantage of the fact that
529: GAS's input scrubber will remove extraneous blanks. */
530: if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
531: {
532: #ifdef CGEN_MNEMONIC_OPERANDS
533: if (CGEN_SYNTAX_CHAR(* syn) == ' ')
534: past_opcode_p = 1;
535: #endif
536: ++ syn;
537: ++ str;
538: }
539: else if (*str)
540: {
541: /* Syntax char didn't match. Can't be this insn. */
542: static char msg [80];
543:
544: /* xgettext:c-format */
545: sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
546: CGEN_SYNTAX_CHAR(*syn), *str);
547: return msg;
548: }
549: else
550: {
551: /* Ran out of input. */
552: static char msg [80];
553:
554: /* xgettext:c-format */
555: sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
556: CGEN_SYNTAX_CHAR(*syn));
557: return msg;
558: }
559: continue;
560: }
561:
1.1.1.2 christos 562: #ifdef CGEN_MNEMONIC_OPERANDS
563: (void) past_opcode_p;
564: #endif
1.1 skrll 565: /* We have an operand of some sort. */
1.1.1.2 christos 566: errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
1.1 skrll 567: if (errmsg)
568: return errmsg;
569:
570: /* Done with this operand, continue with next one. */
571: ++ syn;
572: }
573:
574: /* If we're at the end of the syntax string, we're done. */
575: if (* syn == 0)
576: {
577: /* FIXME: For the moment we assume a valid `str' can only contain
578: blanks now. IE: We needn't try again with a longer version of
579: the insn and it is assumed that longer versions of insns appear
580: before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
581: while (ISSPACE (* str))
582: ++ str;
583:
584: if (* str != '\0')
585: return _("junk at end of line"); /* FIXME: would like to include `str' */
586:
587: return NULL;
588: }
589:
590: /* We couldn't parse it. */
591: return _("unrecognized instruction");
592: }
593:
594: /* Main entry point.
595: This routine is called for each instruction to be assembled.
596: STR points to the insn to be assembled.
597: We assume all necessary tables have been initialized.
598: The assembled instruction, less any fixups, is stored in BUF.
599: Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
600: still needs to be converted to target byte order, otherwise BUF is an array
601: of bytes in target byte order.
602: The result is a pointer to the insn's entry in the opcode table,
603: or NULL if an error occured (an error message will have already been
604: printed).
605:
606: Note that when processing (non-alias) macro-insns,
607: this function recurses.
608:
609: ??? It's possible to make this cpu-independent.
610: One would have to deal with a few minor things.
611: At this point in time doing so would be more of a curiosity than useful
612: [for example this file isn't _that_ big], but keeping the possibility in
613: mind helps keep the design clean. */
614:
615: const CGEN_INSN *
616: fr30_cgen_assemble_insn (CGEN_CPU_DESC cd,
617: const char *str,
618: CGEN_FIELDS *fields,
619: CGEN_INSN_BYTES_PTR buf,
620: char **errmsg)
621: {
622: const char *start;
623: CGEN_INSN_LIST *ilist;
624: const char *parse_errmsg = NULL;
625: const char *insert_errmsg = NULL;
626: int recognized_mnemonic = 0;
627:
628: /* Skip leading white space. */
629: while (ISSPACE (* str))
630: ++ str;
631:
632: /* The instructions are stored in hashed lists.
633: Get the first in the list. */
634: ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
635:
636: /* Keep looking until we find a match. */
637: start = str;
638: for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
639: {
640: const CGEN_INSN *insn = ilist->insn;
641: recognized_mnemonic = 1;
642:
1.1.1.3 christos 643: #ifdef CGEN_VALIDATE_INSN_SUPPORTED
1.1 skrll 644: /* Not usually needed as unsupported opcodes
645: shouldn't be in the hash lists. */
646: /* Is this insn supported by the selected cpu? */
647: if (! fr30_cgen_insn_supported (cd, insn))
648: continue;
649: #endif
650: /* If the RELAXED attribute is set, this is an insn that shouldn't be
651: chosen immediately. Instead, it is used during assembler/linker
652: relaxation if possible. */
653: if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
654: continue;
655:
656: str = start;
657:
658: /* Skip this insn if str doesn't look right lexically. */
659: if (CGEN_INSN_RX (insn) != NULL &&
660: regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
661: continue;
662:
663: /* Allow parse/insert handlers to obtain length of insn. */
664: CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
665:
666: parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
667: if (parse_errmsg != NULL)
668: continue;
669:
670: /* ??? 0 is passed for `pc'. */
671: insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
672: (bfd_vma) 0);
673: if (insert_errmsg != NULL)
674: continue;
675:
676: /* It is up to the caller to actually output the insn and any
677: queued relocs. */
678: return insn;
679: }
680:
681: {
682: static char errbuf[150];
683: const char *tmp_errmsg;
1.1.1.2 christos 684: #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
685: #define be_verbose 1
1.1 skrll 686: #else
1.1.1.2 christos 687: #define be_verbose 0
1.1 skrll 688: #endif
1.1.1.2 christos 689:
690: if (be_verbose)
691: {
692: /* If requesting verbose error messages, use insert_errmsg.
693: Failing that, use parse_errmsg. */
694: tmp_errmsg = (insert_errmsg ? insert_errmsg :
695: parse_errmsg ? parse_errmsg :
696: recognized_mnemonic ?
697: _("unrecognized form of instruction") :
698: _("unrecognized instruction"));
699:
700: if (strlen (start) > 50)
701: /* xgettext:c-format */
702: sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
1.1.1.3 christos 703: else
1.1.1.2 christos 704: /* xgettext:c-format */
705: sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
706: }
707: else
708: {
709: if (strlen (start) > 50)
710: /* xgettext:c-format */
711: sprintf (errbuf, _("bad instruction `%.50s...'"), start);
1.1.1.3 christos 712: else
1.1.1.2 christos 713: /* xgettext:c-format */
714: sprintf (errbuf, _("bad instruction `%.50s'"), start);
715: }
1.1.1.3 christos 716:
1.1 skrll 717: *errmsg = errbuf;
718: return NULL;
719: }
720: }
CVSweb <webmaster@jp.NetBSD.org>