source: vendor/binutils/current/opcodes/frv-asm.c

Last change on this file was 608, checked in by (none), 22 years ago

This commit was manufactured by cvs2svn to create branch 'GNU'.

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