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