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