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_RADF :
524 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r2);
525 break;
526 case OR1K_OPERAND_RADI :
527 errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RADI, (unsigned long *) (& fields->f_rad32));
528 break;
529 case OR1K_OPERAND_RASF :
530 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r2);
531 break;
532 case OR1K_OPERAND_RB :
533 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r3);
534 break;
535 case OR1K_OPERAND_RBD32F :
536 errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RBD32F, (unsigned long *) (& fields->f_rbd32));
537 break;
538 case OR1K_OPERAND_RBDF :
539 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r3);
540 break;
541 case OR1K_OPERAND_RBDI :
542 errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RBDI, (unsigned long *) (& fields->f_rbd32));
543 break;
544 case OR1K_OPERAND_RBSF :
545 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r3);
546 break;
547 case OR1K_OPERAND_RD :
548 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_gpr, & fields->f_r1);
549 break;
550 case OR1K_OPERAND_RDD32F :
551 errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RDD32F, (unsigned long *) (& fields->f_rdd32));
552 break;
553 case OR1K_OPERAND_RDDF :
554 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fdr, & fields->f_r1);
555 break;
556 case OR1K_OPERAND_RDDI :
557 errmsg = parse_regpair (cd, strp, OR1K_OPERAND_RDDI, (unsigned long *) (& fields->f_rdd32));
558 break;
559 case OR1K_OPERAND_RDSF :
560 errmsg = cgen_parse_keyword (cd, strp, & or1k_cgen_opval_h_fsr, & fields->f_r1);
561 break;
562 case OR1K_OPERAND_SIMM16 :
563 errmsg = parse_simm16 (cd, strp, OR1K_OPERAND_SIMM16, (long *) (& fields->f_simm16));
564 break;
565 case OR1K_OPERAND_SIMM16_SPLIT :
566 errmsg = parse_simm16_split (cd, strp, OR1K_OPERAND_SIMM16_SPLIT, (long *) (& fields->f_simm16_split));
567 break;
568 case OR1K_OPERAND_UIMM16 :
569 errmsg = parse_uimm16 (cd, strp, OR1K_OPERAND_UIMM16, (unsigned long *) (& fields->f_uimm16));
570 break;
571 case OR1K_OPERAND_UIMM16_SPLIT :
572 errmsg = parse_uimm16_split (cd, strp, OR1K_OPERAND_UIMM16_SPLIT, (unsigned long *) (& fields->f_uimm16_split));
573 break;
574 case OR1K_OPERAND_UIMM6 :
575 errmsg = cgen_parse_unsigned_integer (cd, strp, OR1K_OPERAND_UIMM6, (unsigned long *) (& fields->f_uimm6));
576 break;
577
578 default :
579 /* xgettext:c-format */
580 opcodes_error_handler
581 (_("internal error: unrecognized field %d while parsing"),
582 opindex);
583 abort ();
584 }
585
586 return errmsg;
587 }
588
589 cgen_parse_fn * const or1k_cgen_parse_handlers[] =
590 {
591 parse_insn_normal,
592 };
593
594 void
595 or1k_cgen_init_asm (CGEN_CPU_DESC cd)
596 {
597 or1k_cgen_init_opcode_table (cd);
598 or1k_cgen_init_ibld_table (cd);
599 cd->parse_handlers = & or1k_cgen_parse_handlers[0];
600 cd->parse_operand = or1k_cgen_parse_operand;
601 #ifdef CGEN_ASM_INIT_HOOK
602 CGEN_ASM_INIT_HOOK
603 #endif
604 }
605
606
607
609 /* Regex construction routine.
610
611 This translates an opcode syntax string into a regex string,
612 by replacing any non-character syntax element (such as an
613 opcode) with the pattern '.*'
614
615 It then compiles the regex and stores it in the opcode, for
616 later use by or1k_cgen_assemble_insn
617
618 Returns NULL for success, an error message for failure. */
619
620 char *
621 or1k_cgen_build_insn_regex (CGEN_INSN *insn)
622 {
623 CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
624 const char *mnem = CGEN_INSN_MNEMONIC (insn);
625 char rxbuf[CGEN_MAX_RX_ELEMENTS];
626 char *rx = rxbuf;
627 const CGEN_SYNTAX_CHAR_TYPE *syn;
628 int reg_err;
629
630 syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
631
632 /* Mnemonics come first in the syntax string. */
633 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
634 return _("missing mnemonic in syntax string");
635 ++syn;
636
637 /* Generate a case sensitive regular expression that emulates case
638 insensitive matching in the "C" locale. We cannot generate a case
639 insensitive regular expression because in Turkish locales, 'i' and 'I'
640 are not equal modulo case conversion. */
641
642 /* Copy the literal mnemonic out of the insn. */
643 for (; *mnem; mnem++)
644 {
645 char c = *mnem;
646
647 if (ISALPHA (c))
648 {
649 *rx++ = '[';
650 *rx++ = TOLOWER (c);
651 *rx++ = TOUPPER (c);
652 *rx++ = ']';
653 }
654 else
655 *rx++ = c;
656 }
657
658 /* Copy any remaining literals from the syntax string into the rx. */
659 for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
660 {
661 if (CGEN_SYNTAX_CHAR_P (* syn))
662 {
663 char c = CGEN_SYNTAX_CHAR (* syn);
664
665 switch (c)
666 {
667 /* Escape any regex metacharacters in the syntax. */
668 case '.': case '[': case '\\':
669 case '*': case '^': case '$':
670
671 #ifdef CGEN_ESCAPE_EXTENDED_REGEX
672 case '?': case '{': case '}':
673 case '(': case ')': case '*':
674 case '|': case '+': case ']':
675 #endif
676 *rx++ = '\\';
677 *rx++ = c;
678 break;
679
680 default:
681 if (ISALPHA (c))
682 {
683 *rx++ = '[';
684 *rx++ = TOLOWER (c);
685 *rx++ = TOUPPER (c);
686 *rx++ = ']';
687 }
688 else
689 *rx++ = c;
690 break;
691 }
692 }
693 else
694 {
695 /* Replace non-syntax fields with globs. */
696 *rx++ = '.';
697 *rx++ = '*';
698 }
699 }
700
701 /* Trailing whitespace ok. */
702 * rx++ = '[';
703 * rx++ = ' ';
704 * rx++ = '\t';
705 * rx++ = ']';
706 * rx++ = '*';
707
708 /* But anchor it after that. */
709 * rx++ = '$';
710 * rx = '\0';
711
712 CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
713 reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
714
715 if (reg_err == 0)
716 return NULL;
717 else
718 {
719 static char msg[80];
720
721 regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
722 regfree ((regex_t *) CGEN_INSN_RX (insn));
723 free (CGEN_INSN_RX (insn));
724 (CGEN_INSN_RX (insn)) = NULL;
725 return msg;
726 }
727 }
728
729
730 /* Default insn parser.
732
733 The syntax string is scanned and operands are parsed and stored in FIELDS.
734 Relocs are queued as we go via other callbacks.
735
736 ??? Note that this is currently an all-or-nothing parser. If we fail to
737 parse the instruction, we return 0 and the caller will start over from
738 the beginning. Backtracking will be necessary in parsing subexpressions,
739 but that can be handled there. Not handling backtracking here may get
740 expensive in the case of the m68k. Deal with later.
741
742 Returns NULL for success, an error message for failure. */
743
744 static const char *
745 parse_insn_normal (CGEN_CPU_DESC cd,
746 const CGEN_INSN *insn,
747 const char **strp,
748 CGEN_FIELDS *fields)
749 {
750 /* ??? Runtime added insns not handled yet. */
751 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
752 const char *str = *strp;
753 const char *errmsg;
754 const char *p;
755 const CGEN_SYNTAX_CHAR_TYPE * syn;
756 #ifdef CGEN_MNEMONIC_OPERANDS
757 /* FIXME: wip */
758 int past_opcode_p;
759 #endif
760
761 /* For now we assume the mnemonic is first (there are no leading operands).
762 We can parse it without needing to set up operand parsing.
763 GAS's input scrubber will ensure mnemonics are lowercase, but we may
764 not be called from GAS. */
765 p = CGEN_INSN_MNEMONIC (insn);
766 while (*p && TOLOWER (*p) == TOLOWER (*str))
767 ++p, ++str;
768
769 if (* p)
770 return _("unrecognized instruction");
771
772 #ifndef CGEN_MNEMONIC_OPERANDS
773 if (* str && ! ISSPACE (* str))
774 return _("unrecognized instruction");
775 #endif
776
777 CGEN_INIT_PARSE (cd);
778 cgen_init_parse_operand (cd);
779 #ifdef CGEN_MNEMONIC_OPERANDS
780 past_opcode_p = 0;
781 #endif
782
783 /* We don't check for (*str != '\0') here because we want to parse
784 any trailing fake arguments in the syntax string. */
785 syn = CGEN_SYNTAX_STRING (syntax);
786
787 /* Mnemonics come first for now, ensure valid string. */
788 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
789 abort ();
790
791 ++syn;
792
793 while (* syn != 0)
794 {
795 /* Non operand chars must match exactly. */
796 if (CGEN_SYNTAX_CHAR_P (* syn))
797 {
798 /* FIXME: While we allow for non-GAS callers above, we assume the
799 first char after the mnemonic part is a space. */
800 /* FIXME: We also take inappropriate advantage of the fact that
801 GAS's input scrubber will remove extraneous blanks. */
802 if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
803 {
804 #ifdef CGEN_MNEMONIC_OPERANDS
805 if (CGEN_SYNTAX_CHAR(* syn) == ' ')
806 past_opcode_p = 1;
807 #endif
808 ++ syn;
809 ++ str;
810 }
811 else if (*str)
812 {
813 /* Syntax char didn't match. Can't be this insn. */
814 static char msg [80];
815
816 /* xgettext:c-format */
817 sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
818 CGEN_SYNTAX_CHAR(*syn), *str);
819 return msg;
820 }
821 else
822 {
823 /* Ran out of input. */
824 static char msg [80];
825
826 /* xgettext:c-format */
827 sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
828 CGEN_SYNTAX_CHAR(*syn));
829 return msg;
830 }
831 continue;
832 }
833
834 #ifdef CGEN_MNEMONIC_OPERANDS
835 (void) past_opcode_p;
836 #endif
837 /* We have an operand of some sort. */
838 errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
839 if (errmsg)
840 return errmsg;
841
842 /* Done with this operand, continue with next one. */
843 ++ syn;
844 }
845
846 /* If we're at the end of the syntax string, we're done. */
847 if (* syn == 0)
848 {
849 /* FIXME: For the moment we assume a valid `str' can only contain
850 blanks now. IE: We needn't try again with a longer version of
851 the insn and it is assumed that longer versions of insns appear
852 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
853 while (ISSPACE (* str))
854 ++ str;
855
856 if (* str != '\0')
857 return _("junk at end of line"); /* FIXME: would like to include `str' */
858
859 return NULL;
860 }
861
862 /* We couldn't parse it. */
863 return _("unrecognized instruction");
864 }
865
866 /* Main entry point.
868 This routine is called for each instruction to be assembled.
869 STR points to the insn to be assembled.
870 We assume all necessary tables have been initialized.
871 The assembled instruction, less any fixups, is stored in BUF.
872 Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
873 still needs to be converted to target byte order, otherwise BUF is an array
874 of bytes in target byte order.
875 The result is a pointer to the insn's entry in the opcode table,
876 or NULL if an error occured (an error message will have already been
877 printed).
878
879 Note that when processing (non-alias) macro-insns,
880 this function recurses.
881
882 ??? It's possible to make this cpu-independent.
883 One would have to deal with a few minor things.
884 At this point in time doing so would be more of a curiosity than useful
885 [for example this file isn't _that_ big], but keeping the possibility in
886 mind helps keep the design clean. */
887
888 const CGEN_INSN *
889 or1k_cgen_assemble_insn (CGEN_CPU_DESC cd,
890 const char *str,
891 CGEN_FIELDS *fields,
892 CGEN_INSN_BYTES_PTR buf,
893 char **errmsg)
894 {
895 const char *start;
896 CGEN_INSN_LIST *ilist;
897 const char *parse_errmsg = NULL;
898 const char *insert_errmsg = NULL;
899 int recognized_mnemonic = 0;
900
901 /* Skip leading white space. */
902 while (ISSPACE (* str))
903 ++ str;
904
905 /* The instructions are stored in hashed lists.
906 Get the first in the list. */
907 ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
908
909 /* Keep looking until we find a match. */
910 start = str;
911 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
912 {
913 const CGEN_INSN *insn = ilist->insn;
914 recognized_mnemonic = 1;
915
916 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
917 /* Not usually needed as unsupported opcodes
918 shouldn't be in the hash lists. */
919 /* Is this insn supported by the selected cpu? */
920 if (! or1k_cgen_insn_supported (cd, insn))
921 continue;
922 #endif
923 /* If the RELAXED attribute is set, this is an insn that shouldn't be
924 chosen immediately. Instead, it is used during assembler/linker
925 relaxation if possible. */
926 if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
927 continue;
928
929 str = start;
930
931 /* Skip this insn if str doesn't look right lexically. */
932 if (CGEN_INSN_RX (insn) != NULL &&
933 regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
934 continue;
935
936 /* Allow parse/insert handlers to obtain length of insn. */
937 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
938
939 parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
940 if (parse_errmsg != NULL)
941 continue;
942
943 /* ??? 0 is passed for `pc'. */
944 insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
945 (bfd_vma) 0);
946 if (insert_errmsg != NULL)
947 continue;
948
949 /* It is up to the caller to actually output the insn and any
950 queued relocs. */
951 return insn;
952 }
953
954 {
955 static char errbuf[150];
956 const char *tmp_errmsg;
957 #ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
958 #define be_verbose 1
959 #else
960 #define be_verbose 0
961 #endif
962
963 if (be_verbose)
964 {
965 /* If requesting verbose error messages, use insert_errmsg.
966 Failing that, use parse_errmsg. */
967 tmp_errmsg = (insert_errmsg ? insert_errmsg :
968 parse_errmsg ? parse_errmsg :
969 recognized_mnemonic ?
970 _("unrecognized form of instruction") :
971 _("unrecognized instruction"));
972
973 if (strlen (start) > 50)
974 /* xgettext:c-format */
975 sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
976 else
977 /* xgettext:c-format */
978 sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
979 }
980 else
981 {
982 if (strlen (start) > 50)
983 /* xgettext:c-format */
984 sprintf (errbuf, _("bad instruction `%.50s...'"), start);
985 else
986 /* xgettext:c-format */
987 sprintf (errbuf, _("bad instruction `%.50s'"), start);
988 }
989
990 *errmsg = errbuf;
991 return NULL;
992 }
993 }
994