* frv.cpu: Add IDOC attribute.
[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
46 PARAMS ((CGEN_CPU_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *));
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
54 PARAMS ((CGEN_CPU_DESC, const char **, int, unsigned long *));
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 *));
fd3c93d5
DB
69
70static const char *
71parse_ulo16 (cd, strp, opindex, valuep)
72 CGEN_CPU_DESC cd;
73 const char **strp;
74 int opindex;
75 unsigned long *valuep;
76{
77 const char *errmsg;
78 enum cgen_parse_operand_result result_type;
79 bfd_vma value;
80
81 if (**strp == '#' || **strp == '%')
82 {
83 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
84 {
85 *strp += 4;
86 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
87 &result_type, &value);
88 if (**strp != ')')
89 return "missing `)'";
90 ++*strp;
91 if (errmsg == NULL
92 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
93 value &= 0xffff;
94 *valuep = value;
95 return errmsg;
96 }
97 if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
98 {
99 *strp += 9;
100 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
101 &result_type, &value);
102 if (**strp != ')')
103 return "missing ')'";
104 ++*strp;
105 if (errmsg == NULL
106 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
107 value >>= 16;
108 *valuep = value;
109 return errmsg;
110 }
111 }
112 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
113}
114
115static const char *
116parse_uslo16 (cd, strp, opindex, valuep)
117 CGEN_CPU_DESC cd;
118 const char **strp;
119 int opindex;
120 unsigned long *valuep;
121{
122 const char *errmsg;
123 enum cgen_parse_operand_result result_type;
124 bfd_vma value;
125
126 if (**strp == '#' || **strp == '%')
127 {
128 if (strncasecmp (*strp + 1, "lo(", 3) == 0)
129 {
130 *strp += 4;
131 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_LO16,
132 &result_type, &value);
133 if (**strp != ')')
134 return "missing `)'";
135 ++*strp;
136 if (errmsg == NULL
137 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
138 value &= 0xffff;
139 *valuep = value;
140 return errmsg;
141 }
142 else if (strncasecmp (*strp + 1, "gprello(", 8) == 0)
143 {
144 *strp += 9;
145 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELLO,
146 &result_type, &value);
147 if (**strp != ')')
148 return "missing ')'";
149 ++*strp;
150 if (errmsg == NULL
151 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
152 value &= 0xffff;
153 *valuep = value;
154 return errmsg;
155 }
156 }
157 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
158}
159
160static const char *
161parse_uhi16 (cd, strp, opindex, valuep)
162 CGEN_CPU_DESC cd;
163 const char **strp;
164 int opindex;
165 unsigned long *valuep;
166{
167 const char *errmsg;
168 enum cgen_parse_operand_result result_type;
169 bfd_vma value;
170
171 if (**strp == '#' || **strp == '%')
172 {
173 if (strncasecmp (*strp + 1, "hi(", 3) == 0)
174 {
175 *strp += 4;
176 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_HI16,
177 &result_type, &value);
178 if (**strp != ')')
179 return "missing `)'";
180 ++*strp;
181 if (errmsg == NULL
182 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
183 value >>= 16;
184 *valuep = value;
185 return errmsg;
186 }
187 else if (strncasecmp (*strp + 1, "gprelhi(", 8) == 0)
188 {
189 *strp += 9;
190 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELHI,
191 &result_type, &value);
192 if (**strp != ')')
193 return "missing ')'";
194 ++*strp;
195 if (errmsg == NULL
196 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
197 value >>= 16;
198 *valuep = value;
199 return errmsg;
200 }
201 }
202 return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
203}
204
205static long
206parse_register_number (strp)
207 const char **strp;
208{
209 int regno;
210 if (**strp < '0' || **strp > '9')
211 return -1; /* error */
212
213 regno = **strp - '0';
214 for (++*strp; **strp >= '0' && **strp <= '9'; ++*strp)
215 regno = regno * 10 + (**strp - '0');
216
217 return regno;
218}
219
220static const char *
221parse_spr (cd, strp, table, valuep)
222 CGEN_CPU_DESC cd;
223 const char **strp;
224 CGEN_KEYWORD * table;
225 long *valuep;
226{
227 const char *save_strp;
228 long regno;
229
230 /* Check for spr index notation. */
231 if (strncasecmp (*strp, "spr[", 4) == 0)
232 {
233 *strp += 4;
234 regno = parse_register_number (strp);
235 if (**strp != ']')
236 return "missing `]'";
237 ++*strp;
238 if (! spr_valid (regno))
239 return "Special purpose register number is out of range";
240 *valuep = regno;
241 return NULL;
242 }
243
244 save_strp = *strp;
245 regno = parse_register_number (strp);
246 if (regno != -1)
247 {
248 if (! spr_valid (regno))
249 return "Special purpose register number is out of range";
250 *valuep = regno;
251 return NULL;
252 }
253
254 *strp = save_strp;
255 return cgen_parse_keyword (cd, strp, table, valuep);
256}
257
258static const char *
259parse_d12 (cd, strp, opindex, valuep)
260 CGEN_CPU_DESC cd;
261 const char **strp;
262 int opindex;
263 long *valuep;
264{
265 const char *errmsg;
266 enum cgen_parse_operand_result result_type;
267 bfd_vma value;
268
269 /* Check for small data reference. */
270 if (**strp == '#' || **strp == '%')
271 {
272 if (strncasecmp (*strp + 1, "gprel12(", 8) == 0)
273 {
274 *strp += 9;
275 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
276 &result_type, &value);
277 if (**strp != ')')
278 return "missing `)'";
279 ++*strp;
280 *valuep = value;
281 return errmsg;
282 }
283 }
284 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
285}
286
287static const char *
288parse_s12 (cd, strp, opindex, valuep)
289 CGEN_CPU_DESC cd;
290 const char **strp;
291 int opindex;
292 long *valuep;
293{
294 const char *errmsg;
295 enum cgen_parse_operand_result result_type;
296 bfd_vma value;
297
298 /* Check for small data reference. */
299 if ((**strp == '#' || **strp == '%')
300 && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
301 {
302 *strp += 9;
303 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPREL12,
304 &result_type, &value);
305 if (**strp != ')')
306 return "missing `)'";
307 ++*strp;
308 *valuep = value;
309 return errmsg;
310 }
311 else
312 {
313 if (**strp == '#')
314 ++*strp;
315 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
316 }
317}
318
319static const char *
320parse_u12 (cd, strp, opindex, valuep)
321 CGEN_CPU_DESC cd;
322 const char **strp;
323 int opindex;
324 long *valuep;
325{
326 const char *errmsg;
327 enum cgen_parse_operand_result result_type;
328 bfd_vma value;
329
330 /* Check for small data reference. */
331 if ((**strp == '#' || **strp == '%')
332 && strncasecmp (*strp + 1, "gprel12(", 8) == 0)
333 {
334 *strp += 9;
335 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_FRV_GPRELU12,
336 &result_type, &value);
337 if (**strp != ')')
338 return "missing `)'";
339 ++*strp;
340 *valuep = value;
341 return errmsg;
342 }
343 else
344 {
345 if (**strp == '#')
346 ++*strp;
347 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
348 }
349}
350
36c3ae24
NC
351static const char *
352parse_even_register (cd, strP, tableP, valueP)
353 CGEN_CPU_DESC cd;
354 const char ** strP;
355 CGEN_KEYWORD * tableP;
356 long * valueP;
357{
358 const char * errmsg;
359 const char * saved_star_strP = * strP;
360
361 errmsg = cgen_parse_keyword (cd, strP, tableP, valueP);
362
363 if (errmsg == NULL && ((* valueP) & 1))
364 {
365 errmsg = _("register number must be even");
366 * strP = saved_star_strP;
367 }
368
369 return errmsg;
370}
fd3c93d5
DB
371/* -- */
372
373const char * frv_cgen_parse_operand
374 PARAMS ((CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *));
375
376/* Main entry point for operand parsing.
377
378 This function is basically just a big switch statement. Earlier versions
379 used tables to look up the function to use, but
380 - if the table contains both assembler and disassembler functions then
381 the disassembler contains much of the assembler and vice-versa,
382 - there's a lot of inlining possibilities as things grow,
383 - using a switch statement avoids the function call overhead.
384
385 This function could be moved into `parse_insn_normal', but keeping it
386 separate makes clear the interface between `parse_insn_normal' and each of
387 the handlers. */
388
389const char *
390frv_cgen_parse_operand (cd, opindex, strp, fields)
391 CGEN_CPU_DESC cd;
392 int opindex;
393 const char ** strp;
394 CGEN_FIELDS * fields;
395{
396 const char * errmsg = NULL;
397 /* Used by scalar operands that still need to be parsed. */
398 long junk ATTRIBUTE_UNUSED;
399
400 switch (opindex)
401 {
402 case FRV_OPERAND_A :
403 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_A, &fields->f_A);
404 break;
405 case FRV_OPERAND_ACC40SI :
406 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Si);
407 break;
408 case FRV_OPERAND_ACC40SK :
409 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Sk);
410 break;
411 case FRV_OPERAND_ACC40UI :
412 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Ui);
413 break;
414 case FRV_OPERAND_ACC40UK :
415 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_acc_names, & fields->f_ACC40Uk);
416 break;
417 case FRV_OPERAND_ACCGI :
418 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_accg_names, & fields->f_ACCGi);
419 break;
420 case FRV_OPERAND_ACCGK :
421 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_accg_names, & fields->f_ACCGk);
422 break;
423 case FRV_OPERAND_CCI :
424 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CCi);
425 break;
426 case FRV_OPERAND_CPRDOUBLEK :
427 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRk);
428 break;
429 case FRV_OPERAND_CPRI :
430 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRi);
431 break;
432 case FRV_OPERAND_CPRJ :
433 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRj);
434 break;
435 case FRV_OPERAND_CPRK :
436 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cpr_names, & fields->f_CPRk);
437 break;
438 case FRV_OPERAND_CRI :
439 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRi);
440 break;
441 case FRV_OPERAND_CRJ :
442 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRj);
443 break;
444 case FRV_OPERAND_CRJ_FLOAT :
445 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRj_float);
446 break;
447 case FRV_OPERAND_CRJ_INT :
448 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRj_int);
449 break;
450 case FRV_OPERAND_CRK :
451 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_cccr_names, & fields->f_CRk);
452 break;
453 case FRV_OPERAND_FCCI_1 :
454 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCi_1);
455 break;
456 case FRV_OPERAND_FCCI_2 :
457 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCi_2);
458 break;
459 case FRV_OPERAND_FCCI_3 :
460 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCi_3);
461 break;
462 case FRV_OPERAND_FCCK :
463 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fccr_names, & fields->f_FCCk);
464 break;
465 case FRV_OPERAND_FRDOUBLEI :
466 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
467 break;
468 case FRV_OPERAND_FRDOUBLEJ :
469 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
470 break;
471 case FRV_OPERAND_FRDOUBLEK :
472 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
473 break;
474 case FRV_OPERAND_FRI :
475 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
476 break;
477 case FRV_OPERAND_FRINTI :
478 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
479 break;
36c3ae24
NC
480 case FRV_OPERAND_FRINTIEVEN :
481 errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRi);
482 break;
fd3c93d5
DB
483 case FRV_OPERAND_FRINTJ :
484 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
485 break;
36c3ae24
NC
486 case FRV_OPERAND_FRINTJEVEN :
487 errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
488 break;
fd3c93d5
DB
489 case FRV_OPERAND_FRINTK :
490 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
491 break;
36c3ae24
NC
492 case FRV_OPERAND_FRINTKEVEN :
493 errmsg = parse_even_register (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
494 break;
fd3c93d5
DB
495 case FRV_OPERAND_FRJ :
496 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRj);
497 break;
498 case FRV_OPERAND_FRK :
499 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
500 break;
501 case FRV_OPERAND_FRKHI :
502 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
503 break;
504 case FRV_OPERAND_FRKLO :
505 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_fr_names, & fields->f_FRk);
506 break;
507 case FRV_OPERAND_GRDOUBLEK :
508 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
509 break;
510 case FRV_OPERAND_GRI :
511 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRi);
512 break;
513 case FRV_OPERAND_GRJ :
514 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRj);
515 break;
516 case FRV_OPERAND_GRK :
517 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
518 break;
519 case FRV_OPERAND_GRKHI :
520 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
521 break;
522 case FRV_OPERAND_GRKLO :
523 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_gr_names, & fields->f_GRk);
524 break;
525 case FRV_OPERAND_ICCI_1 :
526 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_iccr_names, & fields->f_ICCi_1);
527 break;
528 case FRV_OPERAND_ICCI_2 :
529 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_iccr_names, & fields->f_ICCi_2);
530 break;
531 case FRV_OPERAND_ICCI_3 :
532 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_iccr_names, & fields->f_ICCi_3);
533 break;
534 case FRV_OPERAND_LI :
535 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LI, &fields->f_LI);
536 break;
537 case FRV_OPERAND_AE :
538 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_AE, &fields->f_ae);
539 break;
540 case FRV_OPERAND_CCOND :
541 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_CCOND, &fields->f_ccond);
542 break;
543 case FRV_OPERAND_COND :
544 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_COND, &fields->f_cond);
545 break;
546 case FRV_OPERAND_D12 :
547 errmsg = parse_d12 (cd, strp, FRV_OPERAND_D12, &fields->f_d12);
548 break;
549 case FRV_OPERAND_DEBUG :
550 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_DEBUG, &fields->f_debug);
551 break;
552 case FRV_OPERAND_EIR :
553 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_EIR, &fields->f_eir);
554 break;
555 case FRV_OPERAND_HINT :
556 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_HINT, &fields->f_hint);
557 break;
558 case FRV_OPERAND_HINT_NOT_TAKEN :
559 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_hint_not_taken, & fields->f_hint);
560 break;
561 case FRV_OPERAND_HINT_TAKEN :
562 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_hint_taken, & fields->f_hint);
563 break;
564 case FRV_OPERAND_LABEL16 :
565 {
566 bfd_vma value;
567 errmsg = cgen_parse_address (cd, strp, FRV_OPERAND_LABEL16, 0, NULL, & value);
568 fields->f_label16 = value;
569 }
570 break;
571 case FRV_OPERAND_LABEL24 :
572 {
573 bfd_vma value;
574 errmsg = cgen_parse_address (cd, strp, FRV_OPERAND_LABEL24, 0, NULL, & value);
575 fields->f_label24 = value;
576 }
577 break;
578 case FRV_OPERAND_LOCK :
579 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_LOCK, &fields->f_lock);
580 break;
581 case FRV_OPERAND_PACK :
582 errmsg = cgen_parse_keyword (cd, strp, & frv_cgen_opval_h_pack, & fields->f_pack);
583 break;
584 case FRV_OPERAND_S10 :
585 errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S10, &fields->f_s10);
586 break;
587 case FRV_OPERAND_S12 :
588 errmsg = parse_s12 (cd, strp, FRV_OPERAND_S12, &fields->f_d12);
589 break;
590 case FRV_OPERAND_S16 :
591 errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S16, &fields->f_s16);
592 break;
593 case FRV_OPERAND_S5 :
594 errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S5, &fields->f_s5);
595 break;
596 case FRV_OPERAND_S6 :
597 errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S6, &fields->f_s6);
598 break;
599 case FRV_OPERAND_S6_1 :
600 errmsg = cgen_parse_signed_integer (cd, strp, FRV_OPERAND_S6_1, &fields->f_s6_1);
601 break;
602 case FRV_OPERAND_SLO16 :
603 errmsg = parse_uslo16 (cd, strp, FRV_OPERAND_SLO16, &fields->f_s16);
604 break;
605 case FRV_OPERAND_SPR :
606 errmsg = parse_spr (cd, strp, & frv_cgen_opval_spr_names, & fields->f_spr);
607 break;
608 case FRV_OPERAND_U12 :
609 errmsg = parse_u12 (cd, strp, FRV_OPERAND_U12, &fields->f_u12);
610 break;
611 case FRV_OPERAND_U16 :
612 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_U16, &fields->f_u16);
613 break;
614 case FRV_OPERAND_U6 :
615 errmsg = cgen_parse_unsigned_integer (cd, strp, FRV_OPERAND_U6, &fields->f_u6);
616 break;
617 case FRV_OPERAND_UHI16 :
618 errmsg = parse_uhi16 (cd, strp, FRV_OPERAND_UHI16, &fields->f_u16);
619 break;
620 case FRV_OPERAND_ULO16 :
621 errmsg = parse_ulo16 (cd, strp, FRV_OPERAND_ULO16, &fields->f_u16);
622 break;
623
624 default :
625 /* xgettext:c-format */
626 fprintf (stderr, _("Unrecognized field %d while parsing.\n"), opindex);
627 abort ();
628 }
629
630 return errmsg;
631}
632
633cgen_parse_fn * const frv_cgen_parse_handlers[] =
634{
635 parse_insn_normal,
636};
637
638void
639frv_cgen_init_asm (cd)
640 CGEN_CPU_DESC cd;
641{
642 frv_cgen_init_opcode_table (cd);
643 frv_cgen_init_ibld_table (cd);
644 cd->parse_handlers = & frv_cgen_parse_handlers[0];
645 cd->parse_operand = frv_cgen_parse_operand;
646}
647
648\f
649
650/* Regex construction routine.
651
652 This translates an opcode syntax string into a regex string,
653 by replacing any non-character syntax element (such as an
654 opcode) with the pattern '.*'
655
656 It then compiles the regex and stores it in the opcode, for
657 later use by frv_cgen_assemble_insn
658
659 Returns NULL for success, an error message for failure. */
660
661char *
662frv_cgen_build_insn_regex (insn)
663 CGEN_INSN *insn;
664{
665 CGEN_OPCODE *opc = (CGEN_OPCODE *) CGEN_INSN_OPCODE (insn);
666 const char *mnem = CGEN_INSN_MNEMONIC (insn);
667 char rxbuf[CGEN_MAX_RX_ELEMENTS];
668 char *rx = rxbuf;
669 const CGEN_SYNTAX_CHAR_TYPE *syn;
670 int reg_err;
671
672 syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc));
673
674 /* Mnemonics come first in the syntax string. */
675 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
676 return _("missing mnemonic in syntax string");
677 ++syn;
678
679 /* Generate a case sensitive regular expression that emulates case
680 insensitive matching in the "C" locale. We cannot generate a case
681 insensitive regular expression because in Turkish locales, 'i' and 'I'
682 are not equal modulo case conversion. */
683
684 /* Copy the literal mnemonic out of the insn. */
685 for (; *mnem; mnem++)
686 {
687 char c = *mnem;
688
689 if (ISALPHA (c))
690 {
691 *rx++ = '[';
692 *rx++ = TOLOWER (c);
693 *rx++ = TOUPPER (c);
694 *rx++ = ']';
695 }
696 else
697 *rx++ = c;
698 }
699
700 /* Copy any remaining literals from the syntax string into the rx. */
701 for(; * syn != 0 && rx <= rxbuf + (CGEN_MAX_RX_ELEMENTS - 7 - 4); ++syn)
702 {
703 if (CGEN_SYNTAX_CHAR_P (* syn))
704 {
705 char c = CGEN_SYNTAX_CHAR (* syn);
706
707 switch (c)
708 {
709 /* Escape any regex metacharacters in the syntax. */
710 case '.': case '[': case '\\':
711 case '*': case '^': case '$':
712
713#ifdef CGEN_ESCAPE_EXTENDED_REGEX
714 case '?': case '{': case '}':
715 case '(': case ')': case '*':
716 case '|': case '+': case ']':
717#endif
718 *rx++ = '\\';
719 *rx++ = c;
720 break;
721
722 default:
723 if (ISALPHA (c))
724 {
725 *rx++ = '[';
726 *rx++ = TOLOWER (c);
727 *rx++ = TOUPPER (c);
728 *rx++ = ']';
729 }
730 else
731 *rx++ = c;
732 break;
733 }
734 }
735 else
736 {
737 /* Replace non-syntax fields with globs. */
738 *rx++ = '.';
739 *rx++ = '*';
740 }
741 }
742
743 /* Trailing whitespace ok. */
744 * rx++ = '[';
745 * rx++ = ' ';
746 * rx++ = '\t';
747 * rx++ = ']';
748 * rx++ = '*';
749
750 /* But anchor it after that. */
751 * rx++ = '$';
752 * rx = '\0';
753
754 CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t));
755 reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB);
756
757 if (reg_err == 0)
758 return NULL;
759 else
760 {
761 static char msg[80];
762
763 regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80);
764 regfree ((regex_t *) CGEN_INSN_RX (insn));
765 free (CGEN_INSN_RX (insn));
766 (CGEN_INSN_RX (insn)) = NULL;
767 return msg;
768 }
769}
770
771\f
772/* Default insn parser.
773
774 The syntax string is scanned and operands are parsed and stored in FIELDS.
775 Relocs are queued as we go via other callbacks.
776
777 ??? Note that this is currently an all-or-nothing parser. If we fail to
778 parse the instruction, we return 0 and the caller will start over from
779 the beginning. Backtracking will be necessary in parsing subexpressions,
780 but that can be handled there. Not handling backtracking here may get
781 expensive in the case of the m68k. Deal with later.
782
783 Returns NULL for success, an error message for failure. */
784
785static const char *
786parse_insn_normal (cd, insn, strp, fields)
787 CGEN_CPU_DESC cd;
788 const CGEN_INSN *insn;
789 const char **strp;
790 CGEN_FIELDS *fields;
791{
792 /* ??? Runtime added insns not handled yet. */
793 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
794 const char *str = *strp;
795 const char *errmsg;
796 const char *p;
797 const CGEN_SYNTAX_CHAR_TYPE * syn;
798#ifdef CGEN_MNEMONIC_OPERANDS
799 /* FIXME: wip */
800 int past_opcode_p;
801#endif
802
803 /* For now we assume the mnemonic is first (there are no leading operands).
804 We can parse it without needing to set up operand parsing.
805 GAS's input scrubber will ensure mnemonics are lowercase, but we may
806 not be called from GAS. */
807 p = CGEN_INSN_MNEMONIC (insn);
808 while (*p && TOLOWER (*p) == TOLOWER (*str))
809 ++p, ++str;
810
811 if (* p)
812 return _("unrecognized instruction");
813
814#ifndef CGEN_MNEMONIC_OPERANDS
815 if (* str && ! ISSPACE (* str))
816 return _("unrecognized instruction");
817#endif
818
819 CGEN_INIT_PARSE (cd);
820 cgen_init_parse_operand (cd);
821#ifdef CGEN_MNEMONIC_OPERANDS
822 past_opcode_p = 0;
823#endif
824
825 /* We don't check for (*str != '\0') here because we want to parse
826 any trailing fake arguments in the syntax string. */
827 syn = CGEN_SYNTAX_STRING (syntax);
828
829 /* Mnemonics come first for now, ensure valid string. */
830 if (! CGEN_SYNTAX_MNEMONIC_P (* syn))
831 abort ();
832
833 ++syn;
834
835 while (* syn != 0)
836 {
837 /* Non operand chars must match exactly. */
838 if (CGEN_SYNTAX_CHAR_P (* syn))
839 {
840 /* FIXME: While we allow for non-GAS callers above, we assume the
841 first char after the mnemonic part is a space. */
842 /* FIXME: We also take inappropriate advantage of the fact that
843 GAS's input scrubber will remove extraneous blanks. */
844 if (TOLOWER (*str) == TOLOWER (CGEN_SYNTAX_CHAR (* syn)))
845 {
846#ifdef CGEN_MNEMONIC_OPERANDS
847 if (CGEN_SYNTAX_CHAR(* syn) == ' ')
848 past_opcode_p = 1;
849#endif
850 ++ syn;
851 ++ str;
852 }
853 else if (*str)
854 {
855 /* Syntax char didn't match. Can't be this insn. */
856 static char msg [80];
857
858 /* xgettext:c-format */
859 sprintf (msg, _("syntax error (expected char `%c', found `%c')"),
860 CGEN_SYNTAX_CHAR(*syn), *str);
861 return msg;
862 }
863 else
864 {
865 /* Ran out of input. */
866 static char msg [80];
867
868 /* xgettext:c-format */
869 sprintf (msg, _("syntax error (expected char `%c', found end of instruction)"),
870 CGEN_SYNTAX_CHAR(*syn));
871 return msg;
872 }
873 continue;
874 }
875
876 /* We have an operand of some sort. */
877 errmsg = cd->parse_operand (cd, CGEN_SYNTAX_FIELD (*syn),
878 &str, fields);
879 if (errmsg)
880 return errmsg;
881
882 /* Done with this operand, continue with next one. */
883 ++ syn;
884 }
885
886 /* If we're at the end of the syntax string, we're done. */
887 if (* syn == 0)
888 {
889 /* FIXME: For the moment we assume a valid `str' can only contain
890 blanks now. IE: We needn't try again with a longer version of
891 the insn and it is assumed that longer versions of insns appear
892 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
893 while (ISSPACE (* str))
894 ++ str;
895
896 if (* str != '\0')
897 return _("junk at end of line"); /* FIXME: would like to include `str' */
898
899 return NULL;
900 }
901
902 /* We couldn't parse it. */
903 return _("unrecognized instruction");
904}
905\f
906/* Main entry point.
907 This routine is called for each instruction to be assembled.
908 STR points to the insn to be assembled.
909 We assume all necessary tables have been initialized.
910 The assembled instruction, less any fixups, is stored in BUF.
911 Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value
912 still needs to be converted to target byte order, otherwise BUF is an array
913 of bytes in target byte order.
914 The result is a pointer to the insn's entry in the opcode table,
915 or NULL if an error occured (an error message will have already been
916 printed).
917
918 Note that when processing (non-alias) macro-insns,
919 this function recurses.
920
921 ??? It's possible to make this cpu-independent.
922 One would have to deal with a few minor things.
923 At this point in time doing so would be more of a curiosity than useful
924 [for example this file isn't _that_ big], but keeping the possibility in
925 mind helps keep the design clean. */
926
927const CGEN_INSN *
928frv_cgen_assemble_insn (cd, str, fields, buf, errmsg)
929 CGEN_CPU_DESC cd;
930 const char *str;
931 CGEN_FIELDS *fields;
932 CGEN_INSN_BYTES_PTR buf;
933 char **errmsg;
934{
935 const char *start;
936 CGEN_INSN_LIST *ilist;
937 const char *parse_errmsg = NULL;
938 const char *insert_errmsg = NULL;
939 int recognized_mnemonic = 0;
940
941 /* Skip leading white space. */
942 while (ISSPACE (* str))
943 ++ str;
944
945 /* The instructions are stored in hashed lists.
946 Get the first in the list. */
947 ilist = CGEN_ASM_LOOKUP_INSN (cd, str);
948
949 /* Keep looking until we find a match. */
950 start = str;
951 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
952 {
953 const CGEN_INSN *insn = ilist->insn;
954 recognized_mnemonic = 1;
955
956#ifdef CGEN_VALIDATE_INSN_SUPPORTED
957 /* Not usually needed as unsupported opcodes
958 shouldn't be in the hash lists. */
959 /* Is this insn supported by the selected cpu? */
960 if (! frv_cgen_insn_supported (cd, insn))
961 continue;
962#endif
963 /* If the RELAX attribute is set, this is an insn that shouldn't be
964 chosen immediately. Instead, it is used during assembler/linker
965 relaxation if possible. */
966 if (CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_RELAX) != 0)
967 continue;
968
969 str = start;
970
971 /* Skip this insn if str doesn't look right lexically. */
972 if (CGEN_INSN_RX (insn) != NULL &&
973 regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
974 continue;
975
976 /* Allow parse/insert handlers to obtain length of insn. */
977 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
978
979 parse_errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
980 if (parse_errmsg != NULL)
981 continue;
982
983 /* ??? 0 is passed for `pc'. */
984 insert_errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
985 (bfd_vma) 0);
986 if (insert_errmsg != NULL)
987 continue;
988
989 /* It is up to the caller to actually output the insn and any
990 queued relocs. */
991 return insn;
992 }
993
994 {
995 static char errbuf[150];
996#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS
997 const char *tmp_errmsg;
998
999 /* If requesting verbose error messages, use insert_errmsg.
1000 Failing that, use parse_errmsg. */
1001 tmp_errmsg = (insert_errmsg ? insert_errmsg :
1002 parse_errmsg ? parse_errmsg :
1003 recognized_mnemonic ?
1004 _("unrecognized form of instruction") :
1005 _("unrecognized instruction"));
1006
1007 if (strlen (start) > 50)
1008 /* xgettext:c-format */
1009 sprintf (errbuf, "%s `%.50s...'", tmp_errmsg, start);
1010 else
1011 /* xgettext:c-format */
1012 sprintf (errbuf, "%s `%.50s'", tmp_errmsg, start);
1013#else
1014 if (strlen (start) > 50)
1015 /* xgettext:c-format */
1016 sprintf (errbuf, _("bad instruction `%.50s...'"), start);
1017 else
1018 /* xgettext:c-format */
1019 sprintf (errbuf, _("bad instruction `%.50s'"), start);
1020#endif
1021
1022 *errmsg = errbuf;
1023 return NULL;
1024 }
1025}
1026\f
1027#if 0 /* This calls back to GAS which we can't do without care. */
1028
1029/* Record each member of OPVALS in the assembler's symbol table.
1030 This lets GAS parse registers for us.
1031 ??? Interesting idea but not currently used. */
1032
1033/* Record each member of OPVALS in the assembler's symbol table.
1034 FIXME: Not currently used. */
1035
1036void
1037frv_cgen_asm_hash_keywords (cd, opvals)
1038 CGEN_CPU_DESC cd;
1039 CGEN_KEYWORD *opvals;
1040{
1041 CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL);
1042 const CGEN_KEYWORD_ENTRY * ke;
1043
1044 while ((ke = cgen_keyword_search_next (& search)) != NULL)
1045 {
1046#if 0 /* Unnecessary, should be done in the search routine. */
1047 if (! frv_cgen_opval_supported (ke))
1048 continue;
1049#endif
1050 cgen_asm_record_register (cd, ke->name, ke->value);
1051 }
1052}
1053
1054#endif /* 0 */
This page took 0.128681 seconds and 4 git commands to generate.