]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - opcodes/frv-asm.c
ChangeLog rotatation and copyright year update
[thirdparty/binutils-gdb.git] / opcodes / frv-asm.c
CommitLineData
fd3c93d5
DB
1/* Assembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
47b0e7ad
NC
4 THIS FILE IS MACHINE GENERATED WITH CGEN.
5 - the resultant file is machine generated, cgen-asm.in isn't
fd3c93d5 6
b90efa5b 7 Copyright (C) 1996-2015 Free Software Foundation, Inc.
fd3c93d5 8
9b201bb5 9 This file is part of libopcodes.
fd3c93d5 10
9b201bb5 11 This library is free software; you can redistribute it and/or modify
47b0e7ad 12 it under the terms of the GNU General Public License as published by
9b201bb5 13 the Free Software Foundation; either version 3, or (at your option)
47b0e7ad 14 any later version.
fd3c93d5 15
9b201bb5
NC
16 It is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
19 License for more details.
fd3c93d5 20
47b0e7ad
NC
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
fd3c93d5 24
9b201bb5 25
fd3c93d5
DB
26/* ??? Eventually more and more of this stuff can go to cpu-independent files.
27 Keep that in mind. */
28
29#include "sysdep.h"
30#include <stdio.h>
31#include "ansidecl.h"
32#include "bfd.h"
33#include "symcat.h"
34#include "frv-desc.h"
35#include "frv-opc.h"
36#include "opintl.h"
37#include "xregex.h"
38#include "libiberty.h"
39#include "safe-ctype.h"
40
41#undef min
42#define min(a,b) ((a) < (b) ? (a) : (b))
43#undef max
44#define max(a,b) ((a) > (b) ? (a) : (b))
45
46static const char * parse_insn_normal
ffead7ae 47 (CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *);
fd3c93d5
DB
48\f
49/* -- assembler routines inserted here. */
50
51/* -- asm.c */
90219bd0
AO
52inline static const char *
53parse_symbolic_address (CGEN_CPU_DESC cd,
54 const char **strp,
55 int opindex,
56 int opinfo,
57 enum cgen_parse_operand_result *resultp,
58 bfd_vma *valuep)
59{
60 enum cgen_parse_operand_result result_type;
61 const char *errmsg = (* cd->parse_operand_fn)
62 (cd, CGEN_PARSE_OPERAND_SYMBOLIC, strp, opindex, opinfo,
63 &result_type, valuep);
64
65 if (errmsg == NULL
66 && result_type != CGEN_PARSE_OPERAND_RESULT_QUEUED)
67 return "symbolic expression required";
68
69 if (resultp)
70 *resultp = result_type;
71
72 return errmsg;
73}
74
75static const char *
76parse_ldd_annotation (CGEN_CPU_DESC cd,
77 const char **strp,
78 int opindex,
33b71eeb 79 unsigned long *valuep)
90219bd0
AO
80{
81 const char *errmsg;
82 enum cgen_parse_operand_result result_type;
83 bfd_vma value;
84
85 if (**strp == '#' || **strp == '%')
86 {
87 if (strncasecmp (*strp + 1, "tlsdesc(", 8) == 0)
88 {
89 *strp += 9;
90 errmsg = parse_symbolic_address (cd, strp, opindex,
91 BFD_RELOC_FRV_TLSDESC_RELAX,
92 &result_type, &value);
93 if (**strp != ')')
94 return "missing ')'";
95 if (valuep)
96 *valuep = value;
97 ++*strp;
98 if (errmsg)
99 return errmsg;
100 }
101 }
102
103 while (**strp == ' ' || **strp == '\t')
104 ++*strp;
105
106 if (**strp != '@')
107 return "missing `@'";
108
109 ++*strp;
110
111 return NULL;
112}
113
114static const char *
115parse_call_annotation (CGEN_CPU_DESC cd,
116 const char **strp,
117 int opindex,
33b71eeb 118 unsigned long *valuep)
90219bd0
AO
119{
120 const char *errmsg;
121 enum cgen_parse_operand_result result_type;
122 bfd_vma value;
123
124 if (**strp == '#' || **strp == '%')
125 {
126 if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
127 {
128 *strp += 11;
129 errmsg = parse_symbolic_address (cd, strp, opindex,
130 BFD_RELOC_FRV_GETTLSOFF_RELAX,
131 &result_type, &value);
132 if (**strp != ')')
133 return "missing ')'";
134 if (valuep)
135 *valuep = value;
136 ++*strp;
137 if (errmsg)
138 return errmsg;
139 }
140 }
141
142 while (**strp == ' ' || **strp == '\t')
143 ++*strp;
144
145 if (**strp != '@')
146 return "missing `@'";
147
148 ++*strp;
149
150 return NULL;
151}
152
153static const char *
154parse_ld_annotation (CGEN_CPU_DESC cd,
155 const char **strp,
156 int opindex,
33b71eeb 157 unsigned long *valuep)
90219bd0
AO
158{
159 const char *errmsg;
160 enum cgen_parse_operand_result result_type;
161 bfd_vma value;
162
163 if (**strp == '#' || **strp == '%')
164 {
165 if (strncasecmp (*strp + 1, "tlsoff(", 7) == 0)
166 {
167 *strp += 8;
168 errmsg = parse_symbolic_address (cd, strp, opindex,
169 BFD_RELOC_FRV_TLSOFF_RELAX,
170 &result_type, &value);
171 if (**strp != ')')
172 return "missing ')'";
173 if (valuep)
174 *valuep = value;
175 ++*strp;
176 if (errmsg)
177 return errmsg;
178 }
179 }
180
181 while (**strp == ' ' || **strp == '\t')
182 ++*strp;
183
184 if (**strp != '@')
185 return "missing `@'";
186
187 ++*strp;
188
189 return NULL;
190}
191
fd3c93d5 192static const char *
47b0e7ad
NC
193parse_ulo16 (CGEN_CPU_DESC cd,
194 const char **strp,
195 int opindex,
196 unsigned long *valuep)
fd3c93d5
DB
197{
198 const char *errmsg;
199 enum cgen_parse_operand_result result_type;
200 bfd_vma value;
201
202 if (**strp == '#' || **strp == '%')
203 {
204 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
205 {
206 *strp += 4;
207 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
47b0e7ad 208 & result_type, & value);
fd3c93d5
DB
209 if (**strp != ')')
210 return "missing `)'";
211 ++*strp;
212 if (errmsg == NULL
213 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
214 value &= 0xffff;
215 *valuep = value;
216 return errmsg;
217 }
218 if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
219 {
220 *strp += 9;
90219bd0
AO
221 errmsg = parse_symbolic_address (cd, strp, opindex,
222 BFD_RELOC_FRV_GPRELLO,
47b0e7ad 223 & result_type, & value);
fd3c93d5
DB
224 if (**strp != ')')
225 return "missing ')'";
226 ++*strp;
ba2d3f07
AO
227 *valuep = value;
228 return errmsg;
229 }
230 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
231 {
232 *strp += 7;
90219bd0
AO
233 errmsg = parse_symbolic_address (cd, strp, opindex,
234 BFD_RELOC_FRV_GOTLO,
47b0e7ad 235 & result_type, & value);
ba2d3f07
AO
236 if (**strp != ')')
237 return "missing ')'";
238 ++*strp;
ba2d3f07
AO
239 *valuep = value;
240 return errmsg;
241 }
242 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
243 {
244 *strp += 15;
90219bd0
AO
245 errmsg = parse_symbolic_address (cd, strp, opindex,
246 BFD_RELOC_FRV_FUNCDESC_GOTLO,
47b0e7ad 247 & result_type, & value);
ba2d3f07
AO
248 if (**strp != ')')
249 return "missing ')'";
250 ++*strp;
ba2d3f07
AO
251 *valuep = value;
252 return errmsg;
253 }
254 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
255 {
256 *strp += 10;
90219bd0
AO
257 errmsg = parse_symbolic_address (cd, strp, opindex,
258 BFD_RELOC_FRV_GOTOFFLO,
47b0e7ad 259 & result_type, & value);
ba2d3f07
AO
260 if (**strp != ')')
261 return "missing ')'";
262 ++*strp;
ba2d3f07
AO
263 *valuep = value;
264 return errmsg;
265 }
266 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
267 {
268 *strp += 18;
90219bd0
AO
269 errmsg = parse_symbolic_address (cd, strp, opindex,
270 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
47b0e7ad 271 & result_type, & value);
90219bd0
AO
272 if (**strp != ')')
273 return "missing ')'";
274 ++*strp;
275 *valuep = value;
276 return errmsg;
277 }
278 else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
279 {
280 *strp += 14;
281 errmsg = parse_symbolic_address (cd, strp, opindex,
282 BFD_RELOC_FRV_GOTTLSDESCLO,
47b0e7ad 283 & result_type, & value);
90219bd0
AO
284 if (**strp != ')')
285 return "missing ')'";
286 ++*strp;
287 *valuep = value;
288 return errmsg;
289 }
290 else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
291 {
292 *strp += 11;
293 errmsg = parse_symbolic_address (cd, strp, opindex,
294 BFD_RELOC_FRV_TLSMOFFLO,
47b0e7ad 295 & result_type, & value);
90219bd0
AO
296 if (**strp != ')')
297 return "missing ')'";
298 ++*strp;
299 *valuep = value;
300 return errmsg;
301 }
302 else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
303 {
304 *strp += 13;
305 errmsg = parse_symbolic_address (cd, strp, opindex,
306 BFD_RELOC_FRV_GOTTLSOFFLO,
47b0e7ad 307 & result_type, & value);
ba2d3f07
AO
308 if (**strp != ')')
309 return "missing ')'";
310 ++*strp;
fd3c93d5
DB
311 *valuep = value;
312 return errmsg;
313 }
314 }
33b71eeb 315 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
fd3c93d5
DB
316}
317
318static const char *
47b0e7ad
NC
319parse_uslo16 (CGEN_CPU_DESC cd,
320 const char **strp,
321 int opindex,
322 signed long *valuep)
fd3c93d5
DB
323{
324 const char *errmsg;
325 enum cgen_parse_operand_result result_type;
326 bfd_vma value;
327
328 if (**strp == '#' || **strp == '%')
329 {
330 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
331 {
332 *strp += 4;
333 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
47b0e7ad 334 & result_type, & value);
fd3c93d5
DB
335 if (**strp != ')')
336 return "missing `)'";
337 ++*strp;
338 if (errmsg == NULL
339 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
340 value &= 0xffff;
341 *valuep = value;
342 return errmsg;
343 }
344 else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
345 {
346 *strp += 9;
90219bd0
AO
347 errmsg = parse_symbolic_address (cd, strp, opindex,
348 BFD_RELOC_FRV_GPRELLO,
47b0e7ad 349 & result_type, & value);
fd3c93d5
DB
350 if (**strp != ')')
351 return "missing ')'";
352 ++*strp;
fd3c93d5
DB
353 *valuep = value;
354 return errmsg;
355 }
ba2d3f07
AO
356 else if (strncasecmp (*strp + 1, "gotlo(", 6) == 0)
357 {
358 *strp += 7;
90219bd0
AO
359 errmsg = parse_symbolic_address (cd, strp, opindex,
360 BFD_RELOC_FRV_GOTLO,
47b0e7ad 361 & result_type, & value);
ba2d3f07
AO
362 if (**strp != ')')
363 return "missing ')'";
364 ++*strp;
ba2d3f07
AO
365 *valuep = value;
366 return errmsg;
367 }
368 else if (strncasecmp (*strp + 1, "gotfuncdesclo(", 14) == 0)
369 {
370 *strp += 15;
90219bd0
AO
371 errmsg = parse_symbolic_address (cd, strp, opindex,
372 BFD_RELOC_FRV_FUNCDESC_GOTLO,
47b0e7ad 373 & result_type, & value);
ba2d3f07
AO
374 if (**strp != ')')
375 return "missing ')'";
376 ++*strp;
ba2d3f07
AO
377 *valuep = value;
378 return errmsg;
379 }
380 else if (strncasecmp (*strp + 1, "gotofflo(", 9) == 0)
381 {
382 *strp += 10;
90219bd0
AO
383 errmsg = parse_symbolic_address (cd, strp, opindex,
384 BFD_RELOC_FRV_GOTOFFLO,
47b0e7ad 385 & result_type, & value);
ba2d3f07
AO
386 if (**strp != ')')
387 return "missing ')'";
388 ++*strp;
ba2d3f07
AO
389 *valuep = value;
390 return errmsg;
391 }
392 else if (strncasecmp (*strp + 1, "gotofffuncdesclo(", 17) == 0)
393 {
394 *strp += 18;
90219bd0
AO
395 errmsg = parse_symbolic_address (cd, strp, opindex,
396 BFD_RELOC_FRV_FUNCDESC_GOTOFFLO,
47b0e7ad 397 & result_type, & value);
90219bd0
AO
398 if (**strp != ')')
399 return "missing ')'";
400 ++*strp;
401 *valuep = value;
402 return errmsg;
403 }
404 else if (strncasecmp (*strp + 1, "gottlsdesclo(", 13) == 0)
405 {
406 *strp += 14;
407 errmsg = parse_symbolic_address (cd, strp, opindex,
408 BFD_RELOC_FRV_GOTTLSDESCLO,
47b0e7ad 409 & result_type, & value);
90219bd0
AO
410 if (**strp != ')')
411 return "missing ')'";
412 ++*strp;
413 *valuep = value;
414 return errmsg;
415 }
416 else if (strncasecmp (*strp + 1, "tlsmofflo(", 10) == 0)
417 {
418 *strp += 11;
419 errmsg = parse_symbolic_address (cd, strp, opindex,
420 BFD_RELOC_FRV_TLSMOFFLO,
47b0e7ad 421 & result_type, & value);
90219bd0
AO
422 if (**strp != ')')
423 return "missing ')'";
424 ++*strp;
425 *valuep = value;
426 return errmsg;
427 }
428 else if (strncasecmp (*strp + 1, "gottlsofflo(", 12) == 0)
429 {
430 *strp += 13;
431 errmsg = parse_symbolic_address (cd, strp, opindex,
432 BFD_RELOC_FRV_GOTTLSOFFLO,
47b0e7ad 433 & result_type, & value);
ba2d3f07
AO
434 if (**strp != ')')
435 return "missing ')'";
436 ++*strp;
ba2d3f07
AO
437 *valuep = value;
438 return errmsg;
439 }
fd3c93d5 440 }
33b71eeb 441 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
fd3c93d5
DB
442}
443
444static const char *
47b0e7ad
NC
445parse_uhi16 (CGEN_CPU_DESC cd,
446 const char **strp,
447 int opindex,
448 unsigned long *valuep)
fd3c93d5
DB
449{
450 const char *errmsg;
451 enum cgen_parse_operand_result result_type;
452 bfd_vma value;
453
454 if (**strp == '#' || **strp == '%')
455 {
456 if (strncasecmp (*strp + 1, "hi(", 3) == 0)
457 {
458 *strp += 4;
459 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
47b0e7ad 460 & result_type, & value);
fd3c93d5
DB
461 if (**strp != ')')
462 return "missing `)'";
463 ++*strp;
464 if (errmsg == NULL
465 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
90219bd0 466 {
5011093d
NC
467 /* If value is wider than 32 bits then be
468 careful about how we extract bits 16-31. */
469 if (sizeof (value) > 4)
470 value &= (((bfd_vma)1 << 16) << 16) - 1;
471
90219bd0
AO
472 value >>= 16;
473 }
fd3c93d5
DB
474 *valuep = value;
475 return errmsg;
476 }
477 else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
478 {
479 *strp += 9;
90219bd0
AO
480 errmsg = parse_symbolic_address (cd, strp, opindex,
481 BFD_RELOC_FRV_GPRELHI,
47b0e7ad 482 & result_type, & value);
fd3c93d5
DB
483 if (**strp != ')')
484 return "missing ')'";
485 ++*strp;
fd3c93d5
DB
486 *valuep = value;
487 return errmsg;
488 }
ba2d3f07
AO
489 else if (strncasecmp (*strp + 1, "gothi(", 6) == 0)
490 {
491 *strp += 7;
90219bd0
AO
492 errmsg = parse_symbolic_address (cd, strp, opindex,
493 BFD_RELOC_FRV_GOTHI,
47b0e7ad 494 & result_type, & value);
ba2d3f07
AO
495 if (**strp != ')')
496 return "missing ')'";
497 ++*strp;
ba2d3f07
AO
498 *valuep = value;
499 return errmsg;
500 }
501 else if (strncasecmp (*strp + 1, "gotfuncdeschi(", 14) == 0)
502 {
503 *strp += 15;
90219bd0
AO
504 errmsg = parse_symbolic_address (cd, strp, opindex,
505 BFD_RELOC_FRV_FUNCDESC_GOTHI,
47b0e7ad 506 & result_type, & value);
ba2d3f07
AO
507 if (**strp != ')')
508 return "missing ')'";
509 ++*strp;
ba2d3f07
AO
510 *valuep = value;
511 return errmsg;
512 }
513 else if (strncasecmp (*strp + 1, "gotoffhi(", 9) == 0)
514 {
515 *strp += 10;
90219bd0
AO
516 errmsg = parse_symbolic_address (cd, strp, opindex,
517 BFD_RELOC_FRV_GOTOFFHI,
47b0e7ad 518 & result_type, & value);
ba2d3f07
AO
519 if (**strp != ')')
520 return "missing ')'";
521 ++*strp;
ba2d3f07
AO
522 *valuep = value;
523 return errmsg;
524 }
525 else if (strncasecmp (*strp + 1, "gotofffuncdeschi(", 17) == 0)
526 {
527 *strp += 18;
90219bd0
AO
528 errmsg = parse_symbolic_address (cd, strp, opindex,
529 BFD_RELOC_FRV_FUNCDESC_GOTOFFHI,
47b0e7ad 530 & result_type, & value);
90219bd0
AO
531 if (**strp != ')')
532 return "missing ')'";
533 ++*strp;
534 *valuep = value;
535 return errmsg;
536 }
537 else if (strncasecmp (*strp + 1, "gottlsdeschi(", 13) == 0)
538 {
539 *strp += 14;
540 errmsg = parse_symbolic_address (cd, strp, opindex,
541 BFD_RELOC_FRV_GOTTLSDESCHI,
542 &result_type, &value);
543 if (**strp != ')')
544 return "missing ')'";
545 ++*strp;
546 *valuep = value;
547 return errmsg;
548 }
549 else if (strncasecmp (*strp + 1, "tlsmoffhi(", 10) == 0)
550 {
551 *strp += 11;
552 errmsg = parse_symbolic_address (cd, strp, opindex,
553 BFD_RELOC_FRV_TLSMOFFHI,
47b0e7ad 554 & result_type, & value);
90219bd0
AO
555 if (**strp != ')')
556 return "missing ')'";
557 ++*strp;
558 *valuep = value;
559 return errmsg;
560 }
561 else if (strncasecmp (*strp + 1, "gottlsoffhi(", 12) == 0)
562 {
563 *strp += 13;
564 errmsg = parse_symbolic_address (cd, strp, opindex,
565 BFD_RELOC_FRV_GOTTLSOFFHI,
47b0e7ad 566 & result_type, & value);
ba2d3f07
AO
567 if (**strp != ')')
568 return "missing ')'";
569 ++*strp;
ba2d3f07
AO
570 *valuep = value;
571 return errmsg;
572 }
fd3c93d5
DB
573 }
574 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
575}
576
577static long
47b0e7ad 578parse_register_number (const char **strp)
fd3c93d5
DB
579{
580 int regno;
47b0e7ad 581
fd3c93d5
DB
582 if (**strp < '0' || **strp > '9')
583 return -1; /* error */
584
585 regno = **strp - '0';
586 for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
587 regno = regno * 10 + (**strp - '0');
588
589 return regno;
590}
591
592static const char *
47b0e7ad
NC
593parse_spr (CGEN_CPU_DESC cd,
594 const char **strp,
595 CGEN_KEYWORD * table,
596 long *valuep)
fd3c93d5
DB
597{
598 const char *save_strp;
599 long regno;
600
601 /* Check for spr index notation. */
602 if (strncasecmp (*strp, "spr[", 4) == 0)
603 {
604 *strp += 4;
605 regno = parse_register_number (strp);
606 if (**strp != ']')
47b0e7ad 607 return _("missing `]'");
fd3c93d5
DB
608 ++*strp;
609 if (! spr_valid (regno))
47b0e7ad 610 return _("Special purpose register number is out of range");
fd3c93d5
DB
611 *valuep = regno;
612 return NULL;
613 }
614
615 save_strp = *strp;
616 regno = parse_register_number (strp);
617 if (regno != -1)
618 {
619 if (! spr_valid (regno))
47b0e7ad 620 return _("Special purpose register number is out of range");
fd3c93d5
DB
621 *valuep = regno;
622 return NULL;
623 }
624
625 *strp = save_strp;
626 return cgen_parse_keyword (cd, strp, table, valuep);
627}
628
629static const char *
47b0e7ad
NC
630parse_d12 (CGEN_CPU_DESC cd,
631 const char **strp,
632 int opindex,
633 long *valuep)
fd3c93d5
DB
634{
635 const char *errmsg;
636 enum cgen_parse_operand_result result_type;
637 bfd_vma value;
638
639 /* Check for small data reference. */
640 if (**strp == '#' || **strp == '%')
641 {
642 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
643 {
644 *strp += 9;
90219bd0
AO
645 errmsg = parse_symbolic_address (cd, strp, opindex,
646 BFD_RELOC_FRV_GPREL12,
47b0e7ad 647 & result_type, & value);
fd3c93d5
DB
648 if (**strp != ')')
649 return "missing `)'";
650 ++*strp;
651 *valuep = value;
652 return errmsg;
653 }
ba2d3f07
AO
654 else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
655 {
656 *strp += 7;
90219bd0
AO
657 errmsg = parse_symbolic_address (cd, strp, opindex,
658 BFD_RELOC_FRV_GOT12,
47b0e7ad 659 & result_type, & value);
ba2d3f07
AO
660 if (**strp != ')')
661 return "missing ')'";
662 ++*strp;
663 *valuep = value;
664 return errmsg;
665 }
666 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
667 {
668 *strp += 15;
90219bd0
AO
669 errmsg = parse_symbolic_address (cd, strp, opindex,
670 BFD_RELOC_FRV_FUNCDESC_GOT12,
47b0e7ad 671 & result_type, & value);
ba2d3f07
AO
672 if (**strp != ')')
673 return "missing ')'";
674 ++*strp;
675 *valuep = value;
676 return errmsg;
677 }
678 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
679 {
680 *strp += 10;
90219bd0
AO
681 errmsg = parse_symbolic_address (cd, strp, opindex,
682 BFD_RELOC_FRV_GOTOFF12,
47b0e7ad 683 & result_type, & value);
ba2d3f07
AO
684 if (**strp != ')')
685 return "missing ')'";
686 ++*strp;
687 *valuep = value;
688 return errmsg;
689 }
690 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
691 {
692 *strp += 18;
90219bd0
AO
693 errmsg = parse_symbolic_address (cd, strp, opindex,
694 BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
47b0e7ad 695 & result_type, & value);
90219bd0
AO
696 if (**strp != ')')
697 return "missing ')'";
698 ++*strp;
699 *valuep = value;
700 return errmsg;
701 }
702 else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
703 {
704 *strp += 14;
705 errmsg = parse_symbolic_address (cd, strp, opindex,
706 BFD_RELOC_FRV_GOTTLSDESC12,
47b0e7ad 707 & result_type, & value);
90219bd0
AO
708 if (**strp != ')')
709 return "missing ')'";
710 ++*strp;
711 *valuep = value;
712 return errmsg;
713 }
714 else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
715 {
716 *strp += 11;
717 errmsg = parse_symbolic_address (cd, strp, opindex,
718 BFD_RELOC_FRV_TLSMOFF12,
47b0e7ad 719 & result_type, & value);
90219bd0
AO
720 if (**strp != ')')
721 return "missing ')'";
722 ++*strp;
723 *valuep = value;
724 return errmsg;
725 }
726 else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
727 {
728 *strp += 13;
729 errmsg = parse_symbolic_address (cd, strp, opindex,
730 BFD_RELOC_FRV_GOTTLSOFF12,
47b0e7ad 731 & result_type, & value);
ba2d3f07
AO
732 if (**strp != ')')
733 return "missing ')'";
734 ++*strp;
735 *valuep = value;
736 return errmsg;
737 }
fd3c93d5
DB
738 }
739 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
740}
741
742static const char *
47b0e7ad
NC
743parse_s12 (CGEN_CPU_DESC cd,
744 const char **strp,
745 int opindex,
746 long *valuep)
fd3c93d5
DB
747{
748 const char *errmsg;
749 enum cgen_parse_operand_result result_type;
750 bfd_vma value;
751
752 /* Check for small data reference. */
90219bd0 753 if (**strp == '#' || **strp == '%')
fd3c93d5 754 {
90219bd0
AO
755 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
756 {
757 *strp += 9;
758 errmsg = parse_symbolic_address (cd, strp, opindex,
759 BFD_RELOC_FRV_GPREL12,
47b0e7ad 760 & result_type, & value);
90219bd0
AO
761 if (**strp != ')')
762 return "missing `)'";
763 ++*strp;
764 *valuep = value;
765 return errmsg;
766 }
767 else if (strncasecmp (*strp + 1, "got12(", 6) == 0)
768 {
769 *strp += 7;
770 errmsg = parse_symbolic_address (cd, strp, opindex,
771 BFD_RELOC_FRV_GOT12,
47b0e7ad 772 & result_type, & value);
90219bd0
AO
773 if (**strp != ')')
774 return "missing ')'";
775 ++*strp;
776 *valuep = value;
777 return errmsg;
778 }
779 else if (strncasecmp (*strp + 1, "gotfuncdesc12(", 14) == 0)
780 {
781 *strp += 15;
782 errmsg = parse_symbolic_address (cd, strp, opindex,
783 BFD_RELOC_FRV_FUNCDESC_GOT12,
47b0e7ad 784 & result_type, & value);
90219bd0
AO
785 if (**strp != ')')
786 return "missing ')'";
787 ++*strp;
788 *valuep = value;
789 return errmsg;
790 }
791 else if (strncasecmp (*strp + 1, "gotoff12(", 9) == 0)
792 {
793 *strp += 10;
794 errmsg = parse_symbolic_address (cd, strp, opindex,
795 BFD_RELOC_FRV_GOTOFF12,
47b0e7ad 796 & result_type, & value);
90219bd0
AO
797 if (**strp != ')')
798 return "missing ')'";
799 ++*strp;
800 *valuep = value;
801 return errmsg;
802 }
803 else if (strncasecmp (*strp + 1, "gotofffuncdesc12(", 17) == 0)
804 {
805 *strp += 18;
806 errmsg = parse_symbolic_address (cd, strp, opindex,
807 BFD_RELOC_FRV_FUNCDESC_GOTOFF12,
47b0e7ad 808 & result_type, & value);
90219bd0
AO
809 if (**strp != ')')
810 return "missing ')'";
811 ++*strp;
812 *valuep = value;
813 return errmsg;
814 }
815 else if (strncasecmp (*strp + 1, "gottlsdesc12(", 13) == 0)
816 {
817 *strp += 14;
818 errmsg = parse_symbolic_address (cd, strp, opindex,
819 BFD_RELOC_FRV_GOTTLSDESC12,
47b0e7ad 820 & result_type, & value);
90219bd0
AO
821 if (**strp != ')')
822 return "missing ')'";
823 ++*strp;
824 *valuep = value;
825 return errmsg;
826 }
827 else if (strncasecmp (*strp + 1, "tlsmoff12(", 10) == 0)
828 {
829 *strp += 11;
830 errmsg = parse_symbolic_address (cd, strp, opindex,
831 BFD_RELOC_FRV_TLSMOFF12,
47b0e7ad 832 & result_type, & value);
90219bd0
AO
833 if (**strp != ')')
834 return "missing ')'";
835 ++*strp;
836 *valuep = value;
837 return errmsg;
838 }
839 else if (strncasecmp (*strp + 1, "gottlsoff12(", 12) == 0)
840 {
841 *strp += 13;
842 errmsg = parse_symbolic_address (cd, strp, opindex,
843 BFD_RELOC_FRV_GOTTLSOFF12,
47b0e7ad 844 & result_type, & value);
90219bd0
AO
845 if (**strp != ')')
846 return "missing ')'";
847 ++*strp;
848 *valuep = value;
849 return errmsg;
850 }
fd3c93d5 851 }
90219bd0
AO
852
853 if (**strp == '#')
854 ++*strp;
855 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
fd3c93d5
DB
856}
857
858static const char *
47b0e7ad
NC
859parse_u12 (CGEN_CPU_DESC cd,
860 const char **strp,
861 int opindex,
862 long *valuep)
fd3c93d5
DB
863{
864 const char *errmsg;
865 enum cgen_parse_operand_result result_type;
866 bfd_vma value;
867
868 /* Check for small data reference. */
869 if ((**strp == '#' || **strp == '%')
870 && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
871 {
872 *strp += 9;
90219bd0
AO
873 errmsg = parse_symbolic_address (cd, strp, opindex,
874 BFD_RELOC_FRV_GPRELU12,
47b0e7ad 875 & result_type, & value);
fd3c93d5
DB
876 if (**strp != ')')
877 return "missing `)'";
878 ++*strp;
879 *valuep = value;
880 return errmsg;
881 }
882 else
883 {
884 if (**strp == '#')
885 ++*strp;
886 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
887 }
888}
889
ecd51ad3 890static const char *
47b0e7ad
NC
891parse_A (CGEN_CPU_DESC cd,
892 const char **strp,
893 int opindex,
894 unsigned long *valuep,
895 unsigned long A)
ecd51ad3
DB
896{
897 const char *errmsg;
898
899 if (**strp == '#')
900 ++*strp;
901
902 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
903 if (errmsg)
904 return errmsg;
905
906 if (*valuep != A)
47b0e7ad 907 return _("Value of A operand must be 0 or 1");
ecd51ad3
DB
908
909 return NULL;
910}
911
912static const char *
47b0e7ad
NC
913parse_A0 (CGEN_CPU_DESC cd,
914 const char **strp,
915 int opindex,
916 unsigned long *valuep)
ecd51ad3
DB
917{
918 return parse_A (cd, strp, opindex, valuep, 0);
919}
920
921static const char *
47b0e7ad
NC
922parse_A1 (CGEN_CPU_DESC cd,
923 const char **strp,
924 int opindex,
925 unsigned long *valuep)
ecd51ad3
DB
926{
927 return parse_A (cd, strp, opindex, valuep, 1);
928}
929
36c3ae24 930static const char *
47b0e7ad
NC
931parse_even_register (CGEN_CPU_DESC cd,
932 const char ** strP,
933 CGEN_KEYWORD * tableP,
934 long * valueP)
36c3ae24
NC
935{
936 const char * errmsg;
937 const char * saved_star_strP = * strP;
938
939 errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
940
941 if (errmsg == NULL && ((* valueP) & 1))
942 {
943 errmsg = _("register number must be even");
944 * strP = saved_star_strP;
945 }
946
947 return errmsg;
948}
90219bd0
AO
949
950static const char *
951parse_call_label (CGEN_CPU_DESC cd,
952 const char **strp,
953 int opindex,
954 int opinfo,
955 enum cgen_parse_operand_result *resultp,
956 bfd_vma *valuep)
957{
958 const char *errmsg;
959 bfd_vma value;
960
961 /* Check for small data reference. */
962 if (opinfo == 0 && (**strp == '#' || **strp == '%'))
963 {
964 if (strncasecmp (*strp + 1, "gettlsoff(", 10) == 0)
965 {
966 *strp += 11;
967 errmsg = parse_symbolic_address (cd, strp, opindex,
968 BFD_RELOC_FRV_GETTLSOFF,
969 resultp, &value);
970 if (**strp != ')')
47b0e7ad 971 return _("missing `)'");
90219bd0
AO
972 ++*strp;
973 *valuep = value;
974 return errmsg;
975 }
976 }
977
978 return cgen_parse_address (cd, strp, opindex, opinfo, resultp, valuep);
979}
980
fd3c93d5
DB
981/* -- */
982
983const char * frv_cgen_parse_operand
47b0e7ad 984 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
fd3c93d5
DB
985
986/* Main entry point for operand parsing.
987
988 This function is basically just a big switch statement. Earlier versions
989 used tables to look up the function to use, but
990 - if the table contains both assembler and disassembler functions then
991 the disassembler contains much of the assembler and vice-versa,
992 - there's a lot of inlining possibilities as things grow,
993 - using a switch statement avoids the function call overhead.
994
995 This function could be moved into `parse_insn_normal', but keeping it
996 separate makes clear the interface between `parse_insn_normal' and each of
997 the handlers. */
998
999const char *
47b0e7ad
NC
1000frv_cgen_parse_operand (CGEN_CPU_DESC cd,
1001 int opindex,
1002 const char ** strp,
1003 CGEN_FIELDS * fields)
fd3c93d5
DB
1004{
1005 const char * errmsg = NULL;
1006 /* Used by scalar operands that still need to be parsed. */
1007 long junk ATTRIBUTE_UNUSED;
1008
1009 switch (opindex)
1010 {
ecd51ad3 1011 case FRV_OPERAND_A0 :
33b71eeb 1012 errmsg = parse_A0 (cd, strp, FRV_OPERAND_A0, (unsigned long *) (& fields->f_A));
ecd51ad3
DB
1013 break;
1014 case FRV_OPERAND_A1 :
33b71eeb 1015 errmsg = parse_A1 (cd, strp, FRV_OPERAND_A1, (unsigned long *) (& fields->f_A));
fd3c93d5
DB
1016 break;
1017 case FRV_OPERAND_ACC40SI :
1018 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Si);
1019 break;
1020 case FRV_OPERAND_ACC40SK :
1021 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Sk);
1022 break;
1023 case FRV_OPERAND_ACC40UI :
1024 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Ui);
1025 break;
1026 case FRV_OPERAND_ACC40UK :
1027 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Uk);
1028 break;
1029 case FRV_OPERAND_ACCGI :
1030 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_accg_names, & fields->f_ACCGi);
1031 break;
1032 case FRV_OPERAND_ACCGK :
1033 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_accg_names, & fields->f_ACCGk);
1034 break;
1035 case FRV_OPERAND_CCI :
1036 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CCi);
1037 break;
1038 case FRV_OPERAND_CPRDOUBLEK :
f7c541f6 1039 errmsg = parse_even_register (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRk);
fd3c93d5
DB
1040 break;
1041 case FRV_OPERAND_CPRI :
1042 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRi);
1043 break;
1044 case FRV_OPERAND_CPRJ :
1045 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRj);
1046 break;
1047 case FRV_OPERAND_CPRK :
1048 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRk);
1049 break;
1050 case FRV_OPERAND_CRI :
1051 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRi);
1052 break;
1053 case FRV_OPERAND_CRJ :
1054 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRj);
1055 break;
1056 case FRV_OPERAND_CRJ_FLOAT :
1057 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRj_float);
1058 break;
1059 case FRV_OPERAND_CRJ_INT :
1060 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRj_int);
1061 break;
1062 case FRV_OPERAND_CRK :
1063 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRk);
1064 break;
1065 case FRV_OPERAND_FCCI_1 :
1066 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCi_1);
1067 break;
1068 case FRV_OPERAND_FCCI_2 :
1069 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCi_2);
1070 break;
1071 case FRV_OPERAND_FCCI_3 :
1072 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCi_3);
1073 break;
1074 case FRV_OPERAND_FCCK :
1075 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCk);
1076 break;
1077 case FRV_OPERAND_FRDOUBLEI :
f7c541f6 1078 errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
fd3c93d5
DB
1079 break;
1080 case FRV_OPERAND_FRDOUBLEJ :
f7c541f6 1081 errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
fd3c93d5
DB
1082 break;
1083 case FRV_OPERAND_FRDOUBLEK :
f7c541f6 1084 errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
fd3c93d5
DB
1085 break;
1086 case FRV_OPERAND_FRI :
1087 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
1088 break;
1089 case FRV_OPERAND_FRINTI :
1090 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
1091 break;
36c3ae24
NC
1092 case FRV_OPERAND_FRINTIEVEN :
1093 errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
1094 break;
fd3c93d5
DB
1095 case FRV_OPERAND_FRINTJ :
1096 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
1097 break;
36c3ae24
NC
1098 case FRV_OPERAND_FRINTJEVEN :
1099 errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
1100 break;
fd3c93d5
DB
1101 case FRV_OPERAND_FRINTK :
1102 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
1103 break;
36c3ae24
NC
1104 case FRV_OPERAND_FRINTKEVEN :
1105 errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
1106 break;
fd3c93d5
DB
1107 case FRV_OPERAND_FRJ :
1108 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
1109 break;
1110 case FRV_OPERAND_FRK :
1111 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
1112 break;
1113 case FRV_OPERAND_FRKHI :
1114 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
1115 break;
1116 case FRV_OPERAND_FRKLO :
1117 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
1118 break;
1119 case FRV_OPERAND_GRDOUBLEK :
f7c541f6 1120 errmsg = parse_even_register (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
fd3c93d5
DB
1121 break;
1122 case FRV_OPERAND_GRI :
1123 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRi);
1124 break;
1125 case FRV_OPERAND_GRJ :
1126 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRj);
1127 break;
1128 case FRV_OPERAND_GRK :
1129 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
1130 break;
1131 case FRV_OPERAND_GRKHI :
1132 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
1133 break;
1134 case FRV_OPERAND_GRKLO :
1135 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
1136 break;
1137 case FRV_OPERAND_ICCI_1 :
1138 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_iccr_names, & fields->f_ICCi_1);
1139 break;
1140 case FRV_OPERAND_ICCI_2 :
1141 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_iccr_names, & fields->f_ICCi_2);
1142 break;
1143 case FRV_OPERAND_ICCI_3 :
1144 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_iccr_names, & fields->f_ICCi_3);
1145 break;
1146 case FRV_OPERAND_LI :
33b71eeb 1147 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LI, (unsigned long *) (& fields->f_LI));
fd3c93d5 1148 break;
676a64f4 1149 case FRV_OPERAND_LRAD :
33b71eeb 1150 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LRAD, (unsigned long *) (& fields->f_LRAD));
676a64f4
RS
1151 break;
1152 case FRV_OPERAND_LRAE :
33b71eeb 1153 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LRAE, (unsigned long *) (& fields->f_LRAE));
676a64f4
RS
1154 break;
1155 case FRV_OPERAND_LRAS :
33b71eeb 1156 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LRAS, (unsigned long *) (& fields->f_LRAS));
676a64f4
RS
1157 break;
1158 case FRV_OPERAND_TLBPRL :
33b71eeb 1159 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_TLBPRL, (unsigned long *) (& fields->f_TLBPRL));
676a64f4
RS
1160 break;
1161 case FRV_OPERAND_TLBPROPX :
33b71eeb 1162 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_TLBPROPX, (unsigned long *) (& fields->f_TLBPRopx));
676a64f4 1163 break;
fd3c93d5 1164 case FRV_OPERAND_AE :
33b71eeb 1165 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_AE, (unsigned long *) (& fields->f_ae));
fd3c93d5 1166 break;
90219bd0 1167 case FRV_OPERAND_CALLANN :
33b71eeb 1168 errmsg = parse_call_annotation (cd, strp, FRV_OPERAND_CALLANN, (unsigned long *) (& fields->f_reloc_ann));
90219bd0 1169 break;
fd3c93d5 1170 case FRV_OPERAND_CCOND :
33b71eeb 1171 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_CCOND, (unsigned long *) (& fields->f_ccond));
fd3c93d5
DB
1172 break;
1173 case FRV_OPERAND_COND :
33b71eeb 1174 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_COND, (unsigned long *) (& fields->f_cond));
fd3c93d5
DB
1175 break;
1176 case FRV_OPERAND_D12 :
33b71eeb 1177 errmsg = parse_d12 (cd, strp, FRV_OPERAND_D12, (long *) (& fields->f_d12));
fd3c93d5
DB
1178 break;
1179 case FRV_OPERAND_DEBUG :
33b71eeb 1180 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_DEBUG, (unsigned long *) (& fields->f_debug));
fd3c93d5
DB
1181 break;
1182 case FRV_OPERAND_EIR :
33b71eeb 1183 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_EIR, (unsigned long *) (& fields->f_eir));
fd3c93d5
DB
1184 break;
1185 case FRV_OPERAND_HINT :
33b71eeb 1186 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_HINT, (unsigned long *) (& fields->f_hint));
fd3c93d5
DB
1187 break;
1188 case FRV_OPERAND_HINT_NOT_TAKEN :
1189 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_hint_not_taken, & fields->f_hint);
1190 break;
1191 case FRV_OPERAND_HINT_TAKEN :
1192 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_hint_taken, & fields->f_hint);
1193 break;
1194 case FRV_OPERAND_LABEL16 :
1195 {
9494d739 1196 bfd_vma value = 0;
fd3c93d5
DB
1197 errmsg = cgen_parse_address (cd, strp, FRV_OPERAND_LABEL16, 0, NULL, & value);
1198 fields->f_label16 = value;
1199 }
1200 break;
1201 case FRV_OPERAND_LABEL24 :
1202 {
9494d739 1203 bfd_vma value = 0;
90219bd0 1204 errmsg = parse_call_label (cd, strp, FRV_OPERAND_LABEL24, 0, NULL, & value);
fd3c93d5
DB
1205 fields->f_label24 = value;
1206 }
1207 break;
90219bd0 1208 case FRV_OPERAND_LDANN :
33b71eeb 1209 errmsg = parse_ld_annotation (cd, strp, FRV_OPERAND_LDANN, (unsigned long *) (& fields->f_reloc_ann));
90219bd0
AO
1210 break;
1211 case FRV_OPERAND_LDDANN :
33b71eeb 1212 errmsg = parse_ldd_annotation (cd, strp, FRV_OPERAND_LDDANN, (unsigned long *) (& fields->f_reloc_ann));
90219bd0 1213 break;
fd3c93d5 1214 case FRV_OPERAND_LOCK :
33b71eeb 1215 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LOCK, (unsigned long *) (& fields->f_lock));
fd3c93d5
DB
1216 break;
1217 case FRV_OPERAND_PACK :
1218 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_pack, & fields->f_pack);
1219 break;
1220 case FRV_OPERAND_S10 :
33b71eeb 1221 errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S10, (long *) (& fields->f_s10));
fd3c93d5
DB
1222 break;
1223 case FRV_OPERAND_S12 :
33b71eeb 1224 errmsg = parse_s12 (cd, strp, FRV_OPERAND_S12, (long *) (& fields->f_d12));
fd3c93d5
DB
1225 break;
1226 case FRV_OPERAND_S16 :
33b71eeb 1227 errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S16, (long *) (& fields->f_s16));
fd3c93d5
DB
1228 break;
1229 case FRV_OPERAND_S5 :
33b71eeb 1230 errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S5, (long *) (& fields->f_s5));
fd3c93d5
DB
1231 break;
1232 case FRV_OPERAND_S6 :
33b71eeb 1233 errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S6, (long *) (& fields->f_s6));
fd3c93d5
DB
1234 break;
1235 case FRV_OPERAND_S6_1 :
33b71eeb 1236 errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S6_1, (long *) (& fields->f_s6_1));
fd3c93d5
DB
1237 break;
1238 case FRV_OPERAND_SLO16 :
33b71eeb 1239 errmsg = parse_uslo16 (cd, strp, FRV_OPERAND_SLO16, (long *) (& fields->f_s16));
fd3c93d5
DB
1240 break;
1241 case FRV_OPERAND_SPR :
1242 errmsg = parse_spr (cd, strp, & frv_cgen_opval_spr_names, & fields->f_spr);
1243 break;
1244 case FRV_OPERAND_U12 :
33b71eeb 1245 errmsg = parse_u12 (cd, strp, FRV_OPERAND_U12, (long *) (& fields->f_u12));
fd3c93d5
DB
1246 break;
1247 case FRV_OPERAND_U16 :
33b71eeb 1248 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_U16, (unsigned long *) (& fields->f_u16));
fd3c93d5
DB
1249 break;
1250 case FRV_OPERAND_U6 :
33b71eeb 1251 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_U6, (unsigned long *) (& fields->f_u6));
fd3c93d5
DB
1252 break;
1253 case FRV_OPERAND_UHI16 :
33b71eeb 1254 errmsg = parse_uhi16 (cd, strp, FRV_OPERAND_UHI16, (unsigned long *) (& fields->f_u16));
fd3c93d5
DB
1255 break;
1256 case FRV_OPERAND_ULO16 :
33b71eeb 1257 errmsg = parse_ulo16 (cd, strp, FRV_OPERAND_ULO16, (unsigned long *) (& fields->f_u16));
fd3c93d5
DB
1258 break;
1259
1260 default :
1261 /* xgettext:c-format */
1262 fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
1263 abort ();
1264 }
1265
1266 return errmsg;
1267}
1268
1269cgen_parse_fn * const frv_cgen_parse_handlers[] =
1270{
1271 parse_insn_normal,
1272};
1273
1274void
47b0e7ad 1275frv_cgen_init_asm (CGEN_CPU_DESC cd)
fd3c93d5
DB
1276{
1277 frv_cgen_init_opcode_table (cd);
1278 frv_cgen_init_ibld_table (cd);
1279 cd->parse_handlers = & frv_cgen_parse_handlers[0];
1280 cd->parse_operand = frv_cgen_parse_operand;
1620f33d
AM
1281#ifdef CGEN_ASM_INIT_HOOK
1282CGEN_ASM_INIT_HOOK
1283#endif
fd3c93d5
DB
1284}
1285
1286\f
1287
1288/* Regex construction routine.
1289
1290 This translates an opcode syntax string into a regex string,
1291 by replacing any non-character syntax element (such as an
1292 opcode) with the pattern '.*'
1293
1294 It then compiles the regex and stores it in the opcode, for
1295 later use by frv_cgen_assemble_insn
1296
1297 Returns NULL for success, an error message for failure. */
1298
1299char *
ffead7ae 1300frv_cgen_build_insn_regex (CGEN_INSN *insn)
fd3c93d5
DB
1301{
1302 CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
1303 const char *mnem = CGEN_INSN_MNEMONIC (insn);
1304 char rxbuf[CGEN_MAX_RX_ELEMENTS];
1305 char *rx = rxbuf;
1306 const CGEN_SYNTAX_CHAR_TYPE *syn;
1307 int reg_err;
1308
1309 syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
1310
1311 /* Mnemonics come first in the syntax string. */
1312 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
1313 return _("missing mnemonic in syntax string");
1314 ++syn;
1315
1316 /* Generate a case sensitive regular expression that emulates case
1317 insensitive matching in the "C" locale. We cannot generate a case
1318 insensitive regular expression because in Turkish locales, 'i' and 'I'
1319 are not equal modulo case conversion. */
1320
1321 /* Copy the literal mnemonic out of the insn. */
1322 for (; *mnem; mnem++)
1323 {
1324 char c = *mnem;
1325
1326 if (ISALPHA (c))
1327 {
1328 *rx++ = '[';
1329 *rx++ = TOLOWER (c);
1330 *rx++ = TOUPPER (c);
1331 *rx++ = ']';
1332 }
1333 else
1334 *rx++ = c;
1335 }
1336
1337 /* Copy any remaining literals from the syntax string into the rx. */
1338 for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
1339 {
1340 if (CGEN_SYNTAX_CHAR_P (* syn))
1341 {
1342 char c = CGEN_SYNTAX_CHAR (* syn);
1343
1344 switch (c)
1345 {
1346 /* Escape any regex metacharacters in the syntax. */
1347 case '.': case '[': case '\\':
1348 case '*': case '^': case '$':
1349
1350#ifdef CGEN_ESCAPE_EXTENDED_REGEX
1351 case '?': case '{': case '}':
1352 case '(': case ')': case '*':
1353 case '|': case '+': case ']':
1354#endif
1355 *rx++ = '\\';
1356 *rx++ = c;
1357 break;
1358
1359 default:
1360 if (ISALPHA (c))
1361 {
1362 *rx++ = '[';
1363 *rx++ = TOLOWER (c);
1364 *rx++ = TOUPPER (c);
1365 *rx++ = ']';
1366 }
1367 else
1368 *rx++ = c;
1369 break;
1370 }
1371 }
1372 else
1373 {
1374 /* Replace non-syntax fields with globs. */
1375 *rx++ = '.';
1376 *rx++ = '*';
1377 }
1378 }
1379
1380 /* Trailing whitespace ok. */
1381 * rx++ = '[';
1382 * rx++ = ' ';
1383 * rx++ = '\t';
1384 * rx++ = ']';
1385 * rx++ = '*';
1386
1387 /* But anchor it after that. */
1388 * rx++ = '$';
1389 * rx = '\0';
1390
1391 CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
1392 reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
1393
1394 if (reg_err == 0)
1395 return NULL;
1396 else
1397 {
1398 static char msg[80];
1399
1400 regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
1401 regfree ((regex_t *) CGEN_INSN_RX (insn));
1402 free (CGEN_INSN_RX (insn));
1403 (CGEN_INSN_RX (insn)) = NULL;
1404 return msg;
1405 }
1406}
1407
1408\f
1409/* Default insn parser.
1410
1411 The syntax string is scanned and operands are parsed and stored in FIELDS.
1412 Relocs are queued as we go via other callbacks.
1413
1414 ??? Note that this is currently an all-or-nothing parser. If we fail to
1415 parse the instruction, we return 0 and the caller will start over from
1416 the beginning. Backtracking will be necessary in parsing subexpressions,
1417 but that can be handled there. Not handling backtracking here may get
1418 expensive in the case of the m68k. Deal with later.
1419
1420 Returns NULL for success, an error message for failure. */
1421
1422static const char *
ffead7ae
MM
1423parse_insn_normal (CGEN_CPU_DESC cd,
1424 const CGEN_INSN *insn,
1425 const char **strp,
1426 CGEN_FIELDS *fields)
fd3c93d5
DB
1427{
1428 /* ??? Runtime added insns not handled yet. */
1429 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
1430 const char *str = *strp;
1431 const char *errmsg;
1432 const char *p;
1433 const CGEN_SYNTAX_CHAR_TYPE * syn;
1434#ifdef CGEN_MNEMONIC_OPERANDS
1435 /* FIXME: wip */
1436 int past_opcode_p;
1437#endif
1438
1439 /* For now we assume the mnemonic is first (there are no leading operands).
1440 We can parse it without needing to set up operand parsing.
1441 GAS's input scrubber will ensure mnemonics are lowercase, but we may
1442 not be called from GAS. */
1443 p = CGEN_INSN_MNEMONIC (insn);
1444 while (*p && TOLOWER (*p) == TOLOWER (*str))
1445 ++p, ++str;
1446
1447 if (* p)
1448 return _("unrecognized instruction");
1449
1450#ifndef CGEN_MNEMONIC_OPERANDS
1451 if (* str && ! ISSPACE (* str))
1452 return _("unrecognized instruction");
1453#endif
1454
1455 CGEN_INIT_PARSE (cd);
1456 cgen_init_parse_operand (cd);
1457#ifdef CGEN_MNEMONIC_OPERANDS
1458 past_opcode_p = 0;
1459#endif
1460
1461 /* We don't check for (*str != '\0') here because we want to parse
1462 any trailing fake arguments in the syntax string. */
1463 syn = CGEN_SYNTAX_STRING (syntax);
1464
1465 /* Mnemonics come first for now, ensure valid string. */
1466 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
1467 abort ();
1468
1469 ++syn;
1470
1471 while (* syn != 0)
1472 {
1473 /* Non operand chars must match exactly. */
1474 if (CGEN_SYNTAX_CHAR_P (* syn))
1475 {
1476 /* FIXME: While we allow for non-GAS callers above, we assume the
1477 first char after the mnemonic part is a space. */
1478 /* FIXME: We also take inappropriate advantage of the fact that
1479 GAS's input scrubber will remove extraneous blanks. */
1480 if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
1481 {
1482#ifdef CGEN_MNEMONIC_OPERANDS
1483 if (CGEN_SYNTAX_CHAR(* syn) == ' ')
1484 past_opcode_p = 1;
1485#endif
1486 ++ syn;
1487 ++ str;
1488 }
1489 else if (*str)
1490 {
1491 /* Syntax char didn't match. Can't be this insn. */
1492 static char msg [80];
1493
1494 /* xgettext:c-format */
1495 sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
1496 CGEN_SYNTAX_CHAR(*syn), *str);
1497 return msg;
1498 }
1499 else
1500 {
1501 /* Ran out of input. */
1502 static char msg [80];
1503
1504 /* xgettext:c-format */
1505 sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
1506 CGEN_SYNTAX_CHAR(*syn));
1507 return msg;
1508 }
1509 continue;
1510 }
1511
c7e2358a
AM
1512#ifdef CGEN_MNEMONIC_OPERANDS
1513 (void) past_opcode_p;
1514#endif
fd3c93d5 1515 /* We have an operand of some sort. */
c7e2358a 1516 errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn), &str, fields);
fd3c93d5
DB
1517 if (errmsg)
1518 return errmsg;
1519
1520 /* Done with this operand, continue with next one. */
1521 ++ syn;
1522 }
1523
1524 /* If we're at the end of the syntax string, we're done. */
1525 if (* syn == 0)
1526 {
1527 /* FIXME: For the moment we assume a valid `str' can only contain
1528 blanks now. IE: We needn't try again with a longer version of
1529 the insn and it is assumed that longer versions of insns appear
1530 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
1531 while (ISSPACE (* str))
1532 ++ str;
1533
1534 if (* str != '\0')
1535 return _("junk at end of line"); /* FIXME: would like to include `str' */
1536
1537 return NULL;
1538 }
1539
1540 /* We couldn't parse it. */
1541 return _("unrecognized instruction");
1542}
1543\f
1544/* Main entry point.
1545 This routine is called for each instruction to be assembled.
1546 STR points to the insn to be assembled.
1547 We assume all necessary tables have been initialized.
1548 The assembled instruction, less any fixups, is stored in BUF.
1549 Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
1550 still needs to be converted to target byte order, otherwise BUF is an array
1551 of bytes in target byte order.
1552 The result is a pointer to the insn's entry in the opcode table,
1553 or NULL if an error occured (an error message will have already been
1554 printed).
1555
1556 Note that when processing (non-alias) macro-insns,
1557 this function recurses.
1558
1559 ??? It's possible to make this cpu-independent.
1560 One would have to deal with a few minor things.
1561 At this point in time doing so would be more of a curiosity than useful
1562 [for example this file isn't _that_ big], but keeping the possibility in
1563 mind helps keep the design clean. */
1564
1565const CGEN_INSN *
ffead7ae
MM
1566frv_cgen_assemble_insn (CGEN_CPU_DESC cd,
1567 const char *str,
1568 CGEN_FIELDS *fields,
1569 CGEN_INSN_BYTES_PTR buf,
1570 char **errmsg)
fd3c93d5
DB
1571{
1572 const char *start;
1573 CGEN_INSN_LIST *ilist;
1574 const char *parse_errmsg = NULL;
1575 const char *insert_errmsg = NULL;
1576 int recognized_mnemonic = 0;
1577
1578 /* Skip leading white space. */
1579 while (ISSPACE (* str))
1580 ++ str;
1581
1582 /* The instructions are stored in hashed lists.
1583 Get the first in the list. */
1584 ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
1585
1586 /* Keep looking until we find a match. */
1587 start = str;
1588 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
1589 {
1590 const CGEN_INSN *insn = ilist->insn;
1591 recognized_mnemonic = 1;
1592
1593#ifdef CGEN_VALIDATE_INSN_SUPPORTED
1594 /* Not usually needed as unsupported opcodes
1595 shouldn't be in the hash lists. */
1596 /* Is this insn supported by the selected cpu? */
1597 if (! frv_cgen_insn_supported (cd, insn))
1598 continue;
1599#endif
b11dcf4e 1600 /* If the RELAXED attribute is set, this is an insn that shouldn't be
fd3c93d5
DB
1601 chosen immediately. Instead, it is used during assembler/linker
1602 relaxation if possible. */
b11dcf4e 1603 if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAXED) != 0)
fd3c93d5
DB
1604 continue;
1605
1606 str = start;
1607
1608 /* Skip this insn if str doesn't look right lexically. */
1609 if (CGEN_INSN_RX (insn) != NULL &&
1610 regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
1611 continue;
1612
1613 /* Allow parse/insert handlers to obtain length of insn. */
1614 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
1615
1616 parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
1617 if (parse_errmsg != NULL)
1618 continue;
1619
1620 /* ??? 0 is passed for `pc'. */
1621 insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
1622 (bfd_vma) 0);
1623 if (insert_errmsg != NULL)
1624 continue;
1625
1626 /* It is up to the caller to actually output the insn and any
1627 queued relocs. */
1628 return insn;
1629 }
1630
1631 {
1632 static char errbuf[150];
fd3c93d5 1633 const char *tmp_errmsg;
c7e2358a
AM
1634#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
1635#define be_verbose 1
fd3c93d5 1636#else
c7e2358a 1637#define be_verbose 0
fd3c93d5 1638#endif
c7e2358a
AM
1639
1640 if (be_verbose)
1641 {
1642 /* If requesting verbose error messages, use insert_errmsg.
1643 Failing that, use parse_errmsg. */
1644 tmp_errmsg = (insert_errmsg ? insert_errmsg :
1645 parse_errmsg ? parse_errmsg :
1646 recognized_mnemonic ?
1647 _("unrecognized form of instruction") :
1648 _("unrecognized instruction"));
1649
1650 if (strlen (start) > 50)
1651 /* xgettext:c-format */
1652 sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
1653 else
1654 /* xgettext:c-format */
1655 sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
1656 }
1657 else
1658 {
1659 if (strlen (start) > 50)
1660 /* xgettext:c-format */
1661 sprintf (errbuf, _("bad instruction `%.50s...'"), start);
1662 else
1663 /* xgettext:c-format */
1664 sprintf (errbuf, _("bad instruction `%.50s'"), start);
1665 }
fd3c93d5
DB
1666
1667 *errmsg = errbuf;
1668 return NULL;
1669 }
1670}