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