* cgen-asm.c (cgen_parse_operand_fn): New global.
[deliverable/binutils-gdb.git] / opcodes / m32r-asm.c
1 /* Assembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
4 This file is used to generate m32r-asm.c.
5
6 Copyright (C) 1996, 1997 Free Software Foundation, Inc.
7
8 This file is part of the GNU Binutils and GDB, the GNU debugger.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23
24 #include <ctype.h>
25 #include <stdio.h>
26 #include "ansidecl.h"
27 #include "bfd.h"
28 #include "m32r-opc.h"
29
30 /* ??? The layout of this stuff is still work in progress.
31 For speed in assembly/disassembly, we use inline functions. That of course
32 will only work for GCC. When this stuff is finished, we can decide whether
33 to keep the inline functions (and only get the performance increase when
34 compiled with GCC), or switch to macros, or use something else.
35 */
36
37 static const char *parse_insn_normal
38 PARAMS ((const struct cgen_insn *, const char **, struct cgen_fields *));
39 static void insert_insn_normal
40 PARAMS ((const struct cgen_insn *, struct cgen_fields *, cgen_insn_t *));
41 \f
42 /* Default insertion routine.
43
44 SHIFT is negative for left shifts, positive for right shifts.
45 All bits of VALUE to be inserted must be valid as we don't handle
46 signed vs unsigned shifts.
47
48 ATTRS is a mask of the boolean attributes. We don't need any at the
49 moment, but for consistency with extract_normal we have them. */
50
51 /* FIXME: This duplicates functionality with bfd's howto table and
52 bfd_install_relocation. */
53 /* FIXME: For architectures where insns can be representable as ints,
54 store insn in `field' struct and add registers, etc. while parsing. */
55
56 static CGEN_INLINE void
57 insert_normal (value, attrs, start, length, shift, total_length, buffer)
58 long value;
59 unsigned int attrs;
60 int start, length, shift, total_length;
61 char *buffer;
62 {
63 bfd_vma x;
64
65 #if 0 /*def CGEN_INT_INSN*/
66 *buffer |= ((value & ((1 << length) - 1))
67 << (total_length - (start + length)));
68 #else
69 switch (total_length)
70 {
71 case 8:
72 x = *(unsigned char *) buffer;
73 break;
74 case 16:
75 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
76 x = bfd_getb16 (buffer);
77 else
78 x = bfd_getl16 (buffer);
79 break;
80 case 32:
81 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
82 x = bfd_getb32 (buffer);
83 else
84 x = bfd_getl32 (buffer);
85 break;
86 default :
87 abort ();
88 }
89
90 if (shift < 0)
91 value <<= -shift;
92 else
93 value >>= shift;
94
95 x |= ((value & ((1 << length) - 1))
96 << (total_length - (start + length)));
97
98 switch (total_length)
99 {
100 case 8:
101 *buffer = value;
102 break;
103 case 16:
104 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
105 bfd_putb16 (x, buffer);
106 else
107 bfd_putl16 (x, buffer);
108 break;
109 case 32:
110 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
111 bfd_putb32 (x, buffer);
112 else
113 bfd_putl32 (x, buffer);
114 break;
115 default :
116 abort ();
117 }
118 #endif
119 }
120 \f
121 /* -- assembler routines inserted here */
122 /* -- asm.c */
123
124 /* Handle shigh(), high(). */
125
126 static const char *
127 parse_h_hi16 (strp, opindex, min, max, valuep)
128 const char **strp;
129 int opindex;
130 unsigned long min, max;
131 unsigned long *valuep;
132 {
133 const char *errmsg;
134
135 /* FIXME: Need # in assembler syntax (means '#' is optional). */
136 if (**strp == '#')
137 ++*strp;
138
139 if (strncmp (*strp, "high(", 5) == 0)
140 {
141 *strp += 5;
142 /* FIXME: If value was a number, right shift by 16. */
143 errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_HI16_ULO, valuep);
144 if (**strp != ')')
145 return "missing `)'";
146 ++*strp;
147 return errmsg;
148 }
149 else if (strncmp (*strp, "shigh(", 6) == 0)
150 {
151 *strp += 6;
152 /* FIXME: If value was a number, right shift by 16 (+ sign test). */
153 errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_HI16_SLO, valuep);
154 if (**strp != ')')
155 return "missing `)'";
156 ++*strp;
157 return errmsg;
158 }
159
160 return cgen_parse_unsigned_integer (strp, opindex, min, max, valuep);
161 }
162
163 /* Handle low() in a signed context. Also handle sda().
164 The signedness of the value doesn't matter to low(), but this also
165 handles the case where low() isn't present. */
166
167 static const char *
168 parse_h_slo16 (strp, opindex, min, max, valuep)
169 const char **strp;
170 int opindex;
171 long min, max;
172 long *valuep;
173 {
174 const char *errmsg;
175
176 /* FIXME: Need # in assembler syntax (means '#' is optional). */
177 if (**strp == '#')
178 ++*strp;
179
180 if (strncmp (*strp, "low(", 4) == 0)
181 {
182 *strp += 4;
183 errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_LO16, valuep);
184 if (**strp != ')')
185 return "missing `)'";
186 ++*strp;
187 return errmsg;
188 }
189
190 if (strncmp (*strp, "sda(", 4) == 0)
191 {
192 *strp += 4;
193 errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_SDA16, valuep);
194 if (**strp != ')')
195 return "missing `)'";
196 ++*strp;
197 return errmsg;
198 }
199
200 return cgen_parse_signed_integer (strp, opindex, min, max, valuep);
201 }
202
203 /* Handle low() in an unsigned context.
204 The signedness of the value doesn't matter to low(), but this also
205 handles the case where low() isn't present. */
206
207 static const char *
208 parse_h_ulo16 (strp, opindex, min, max, valuep)
209 const char **strp;
210 int opindex;
211 unsigned long min, max;
212 unsigned long *valuep;
213 {
214 const char *errmsg;
215
216 /* FIXME: Need # in assembler syntax (means '#' is optional). */
217 if (**strp == '#')
218 ++*strp;
219
220 if (strncmp (*strp, "low(", 4) == 0)
221 {
222 *strp += 4;
223 errmsg = cgen_parse_address (strp, opindex, BFD_RELOC_M32R_LO16, valuep);
224 if (**strp != ')')
225 return "missing `)'";
226 ++*strp;
227 return errmsg;
228 }
229
230 return cgen_parse_unsigned_integer (strp, opindex, min, max, valuep);
231 }
232
233 /* -- */
234
235 /* Main entry point for operand parsing.
236
237 This function is basically just a big switch statement. Earlier versions
238 used tables to look up the function to use, but
239 - if the table contains both assembler and disassembler functions then
240 the disassembler contains much of the assembler and vice-versa,
241 - there's a lot of inlining possibilities as things grow,
242 - using a switch statement avoids the function call overhead.
243
244 This function could be moved into `parse_insn_normal', but keeping it
245 separate makes clear the interface between `parse_insn_normal' and each of
246 the handlers.
247 */
248
249 CGEN_INLINE const char *
250 m32r_cgen_parse_operand (opindex, strp, fields)
251 int opindex;
252 const char **strp;
253 struct cgen_fields *fields;
254 {
255 const char *errmsg;
256
257 switch (opindex)
258 {
259 case 0 :
260 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, &fields->f_r2);
261 break;
262 case 1 :
263 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, &fields->f_r1);
264 break;
265 case 2 :
266 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, &fields->f_r1);
267 break;
268 case 3 :
269 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_gr, &fields->f_r2);
270 break;
271 case 4 :
272 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_cr, &fields->f_r2);
273 break;
274 case 5 :
275 errmsg = cgen_parse_keyword (strp, & m32r_cgen_opval_h_cr, &fields->f_r1);
276 break;
277 case 6 :
278 errmsg = cgen_parse_signed_integer (strp, 6, -128, 127, &fields->f_simm8);
279 break;
280 case 7 :
281 errmsg = cgen_parse_signed_integer (strp, 7, -32768, 32767, &fields->f_simm16);
282 break;
283 case 8 :
284 errmsg = cgen_parse_unsigned_integer (strp, 8, 0, 15, &fields->f_uimm4);
285 break;
286 case 9 :
287 errmsg = cgen_parse_unsigned_integer (strp, 9, 0, 31, &fields->f_uimm5);
288 break;
289 case 10 :
290 errmsg = cgen_parse_unsigned_integer (strp, 10, 0, 65535, &fields->f_uimm16);
291 break;
292 case 11 :
293 errmsg = parse_h_hi16 (strp, 11, 0, 65535, &fields->f_hi16);
294 break;
295 case 12 :
296 errmsg = parse_h_slo16 (strp, 12, -32768, 32767, &fields->f_simm16);
297 break;
298 case 13 :
299 errmsg = parse_h_ulo16 (strp, 13, 0, 65535, &fields->f_uimm16);
300 break;
301 case 14 :
302 errmsg = cgen_parse_address (strp, 14, 0, &fields->f_uimm24);
303 break;
304 case 15 :
305 errmsg = cgen_parse_address (strp, 15, 0, &fields->f_disp8);
306 break;
307 case 16 :
308 errmsg = cgen_parse_address (strp, 16, 0, &fields->f_disp16);
309 break;
310 case 17 :
311 errmsg = cgen_parse_address (strp, 17, 0, &fields->f_disp24);
312 break;
313
314 default :
315 fprintf (stderr, "Unrecognized field %d while parsing.\n", opindex);
316 abort ();
317 }
318
319 return errmsg;
320 }
321
322 /* Main entry point for operand insertion.
323
324 This function is basically just a big switch statement. Earlier versions
325 used tables to look up the function to use, but
326 - if the table contains both assembler and disassembler functions then
327 the disassembler contains much of the assembler and vice-versa,
328 - there's a lot of inlining possibilities as things grow,
329 - using a switch statement avoids the function call overhead.
330
331 This function could be moved into `parse_insn_normal', but keeping it
332 separate makes clear the interface between `parse_insn_normal' and each of
333 the handlers. It's also needed by GAS to insert operands that couldn't be
334 resolved during parsing.
335 */
336
337 CGEN_INLINE void
338 m32r_cgen_insert_operand (opindex, fields, buffer)
339 int opindex;
340 struct cgen_fields *fields;
341 cgen_insn_t *buffer;
342 {
343 switch (opindex)
344 {
345 case 0 :
346 insert_normal (fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
347 break;
348 case 1 :
349 insert_normal (fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
350 break;
351 case 2 :
352 insert_normal (fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
353 break;
354 case 3 :
355 insert_normal (fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
356 break;
357 case 4 :
358 insert_normal (fields->f_r2, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
359 break;
360 case 5 :
361 insert_normal (fields->f_r1, 0|(1<<CGEN_OPERAND_UNSIGNED), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
362 break;
363 case 6 :
364 insert_normal (fields->f_simm8, 0, 8, 8, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
365 break;
366 case 7 :
367 insert_normal (fields->f_simm16, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
368 break;
369 case 8 :
370 insert_normal (fields->f_uimm4, 0|(1<<CGEN_OPERAND_UNSIGNED), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
371 break;
372 case 9 :
373 insert_normal (fields->f_uimm5, 0|(1<<CGEN_OPERAND_UNSIGNED), 11, 5, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
374 break;
375 case 10 :
376 insert_normal (fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
377 break;
378 case 11 :
379 insert_normal (fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT)|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
380 break;
381 case 12 :
382 insert_normal (fields->f_simm16, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
383 break;
384 case 13 :
385 insert_normal (fields->f_uimm16, 0|(1<<CGEN_OPERAND_UNSIGNED), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
386 break;
387 case 14 :
388 insert_normal (fields->f_uimm24, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR)|(1<<CGEN_OPERAND_UNSIGNED), 8, 24, 0, CGEN_FIELDS_BITSIZE (fields), buffer);
389 break;
390 case 15 :
391 insert_normal (fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 8, 2, CGEN_FIELDS_BITSIZE (fields), buffer);
392 break;
393 case 16 :
394 insert_normal (fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 16, 16, 2, CGEN_FIELDS_BITSIZE (fields), buffer);
395 break;
396 case 17 :
397 insert_normal (fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), 8, 24, 2, CGEN_FIELDS_BITSIZE (fields), buffer);
398 break;
399
400 default :
401 fprintf (stderr, "Unrecognized field %d while building insn.\n",
402 opindex);
403 abort ();
404 }
405 }
406
407 /* Main entry point for operand validation.
408
409 This function is called from GAS when it has fully resolved an operand
410 that couldn't be resolved during parsing.
411
412 The result is NULL for success or an error message (which may be
413 computed into a static buffer).
414 */
415
416 CGEN_INLINE const char *
417 m32r_cgen_validate_operand (opindex, fields)
418 int opindex;
419 const struct cgen_fields *fields;
420 {
421 const char *errmsg = NULL;
422
423 switch (opindex)
424 {
425 case 0 :
426 /* nothing to do */
427 break;
428 case 1 :
429 /* nothing to do */
430 break;
431 case 2 :
432 /* nothing to do */
433 break;
434 case 3 :
435 /* nothing to do */
436 break;
437 case 4 :
438 /* nothing to do */
439 break;
440 case 5 :
441 /* nothing to do */
442 break;
443 case 6 :
444 errmsg = cgen_validate_signed_integer (fields->f_simm8, -128, 127);
445 break;
446 case 7 :
447 errmsg = cgen_validate_signed_integer (fields->f_simm16, -32768, 32767);
448 break;
449 case 8 :
450 errmsg = cgen_validate_unsigned_integer (fields->f_uimm4, 0, 15);
451 break;
452 case 9 :
453 errmsg = cgen_validate_unsigned_integer (fields->f_uimm5, 0, 31);
454 break;
455 case 10 :
456 errmsg = cgen_validate_unsigned_integer (fields->f_uimm16, 0, 65535);
457 break;
458 case 11 :
459 errmsg = cgen_validate_unsigned_integer (fields->f_hi16, 0, 65535);
460 break;
461 case 12 :
462 errmsg = cgen_validate_signed_integer (fields->f_simm16, -32768, 32767);
463 break;
464 case 13 :
465 errmsg = cgen_validate_unsigned_integer (fields->f_uimm16, 0, 65535);
466 break;
467 case 14 :
468 /* nothing to do */
469 break;
470 case 15 :
471 /* nothing to do */
472 break;
473 case 16 :
474 /* nothing to do */
475 break;
476 case 17 :
477 /* nothing to do */
478 break;
479
480 default :
481 fprintf (stderr, "Unrecognized field %d while validating operand.\n",
482 opindex);
483 abort ();
484 }
485
486 return errmsg;
487 }
488
489 cgen_parse_fn *m32r_cgen_parse_handlers[] = {
490 0, /* default */
491 parse_insn_normal,
492 };
493
494 cgen_insert_fn *m32r_cgen_insert_handlers[] = {
495 0, /* default */
496 insert_insn_normal,
497 };
498
499 void
500 m32r_cgen_init_asm (mach, endian)
501 int mach;
502 enum cgen_endian endian;
503 {
504 m32r_cgen_init_tables (mach);
505 cgen_set_cpu (& m32r_cgen_opcode_data, mach, endian);
506 cgen_asm_init ();
507 }
508
509 \f
510 /* Default insn parser.
511
512 The syntax string is scanned and operands are parsed and stored in FIELDS.
513 Relocs are queued as we go via other callbacks.
514
515 ??? Note that this is currently an all-or-nothing parser. If we fail to
516 parse the instruction, we return 0 and the caller will start over from
517 the beginning. Backtracking will be necessary in parsing subexpressions,
518 but that can be handled there. Not handling backtracking here may get
519 expensive in the case of the m68k. Deal with later.
520
521 Returns NULL for success, an error message for failure.
522 */
523
524 static const char *
525 parse_insn_normal (insn, strp, fields)
526 const struct cgen_insn *insn;
527 const char **strp;
528 struct cgen_fields *fields;
529 {
530 const struct cgen_syntax *syntax = CGEN_INSN_SYNTAX (insn);
531 const char *str = *strp;
532 const char *errmsg;
533 const unsigned char *syn;
534 #ifdef CGEN_MNEMONIC_OPERANDS
535 int past_opcode_p;
536 #endif
537
538 /* If mnemonics are constant, they're not stored with the syntax string. */
539 #ifndef CGEN_MNEMONIC_OPERANDS
540 {
541 const char *p = syntax->mnemonic;
542
543 while (*p && *p == *str)
544 ++p, ++str;
545 if (*p || (*str && !isspace (*str)))
546 return "unrecognized instruction";
547
548 while (isspace (*str))
549 ++str;
550 }
551 #endif
552
553 CGEN_INIT_PARSE ();
554 cgen_init_parse_operand ();
555 #ifdef CGEN_MNEMONIC_OPERANDS
556 past_opcode_p = 0;
557 #endif
558
559 /* We don't check for (*str != '\0') here because we want to parse
560 any trailing fake arguments in the syntax string. */
561 for (syn = syntax->syntax; *syn != '\0'; )
562 {
563 /* Non operand chars must match exactly. */
564 /* FIXME: Need to better handle whitespace. */
565 if (CGEN_SYNTAX_CHAR_P (*syn))
566 {
567 if (*str == CGEN_SYNTAX_CHAR (*syn))
568 {
569 #ifdef CGEN_MNEMONIC_OPERANDS
570 if (*syn == ' ')
571 past_opcode_p = 1;
572 #endif
573 ++syn;
574 ++str;
575 }
576 else
577 {
578 /* Syntax char didn't match. Can't be this insn. */
579 /* FIXME: would like to return "expected char `c'" */
580 return "syntax error";
581 }
582 continue;
583 }
584
585 /* We have an operand of some sort. */
586 errmsg = m32r_cgen_parse_operand (CGEN_SYNTAX_FIELD (*syn),
587 &str, fields);
588 if (errmsg)
589 return errmsg;
590
591 /* Done with this operand, continue with next one. */
592 ++syn;
593 }
594
595 /* If we're at the end of the syntax string, we're done. */
596 if (*syn == '\0')
597 {
598 /* FIXME: For the moment we assume a valid `str' can only contain
599 blanks now. IE: We needn't try again with a longer version of
600 the insn and it is assumed that longer versions of insns appear
601 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
602 while (isspace (*str))
603 ++str;
604
605 if (*str != '\0')
606 return "junk at end of line"; /* FIXME: would like to include `str' */
607
608 return NULL;
609 }
610
611 /* We couldn't parse it. */
612 return "unrecognized instruction";
613 }
614
615 /* Default insn builder (insert handler).
616 The instruction is recorded in target byte order. */
617
618 static void
619 insert_insn_normal (insn, fields, buffer)
620 const struct cgen_insn *insn;
621 struct cgen_fields *fields;
622 cgen_insn_t *buffer;
623 {
624 const struct cgen_syntax *syntax = CGEN_INSN_SYNTAX (insn);
625 bfd_vma value;
626 const unsigned char *syn;
627
628 CGEN_INIT_INSERT ();
629 value = syntax->value;
630
631 /* If we're recording insns as numbers (rather than a string of bytes),
632 target byte order handling is deferred until later. */
633 #undef min
634 #define min(a,b) ((a) < (b) ? (a) : (b))
635 #if 0 /*def CGEN_INT_INSN*/
636 *buffer = value;
637 #else
638 switch (min (CGEN_BASE_INSN_BITSIZE, CGEN_FIELDS_BITSIZE (fields)))
639 {
640 case 8:
641 *buffer = value;
642 break;
643 case 16:
644 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
645 bfd_putb16 (value, (char *) buffer);
646 else
647 bfd_putl16 (value, (char *) buffer);
648 break;
649 case 32:
650 if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG)
651 bfd_putb32 (value, (char *) buffer);
652 else
653 bfd_putl32 (value, (char *) buffer);
654 break;
655 default:
656 abort ();
657 }
658 #endif
659
660 /* ??? Rather than scanning the syntax string again, we could store
661 in `fields' a null terminated list of the fields that are present. */
662
663 for (syn = syntax->syntax; *syn != '\0'; ++syn)
664 {
665 if (CGEN_SYNTAX_CHAR_P (*syn))
666 continue;
667
668 m32r_cgen_insert_operand (CGEN_SYNTAX_FIELD (*syn), fields, buffer);
669 }
670 }
671 \f
672 /* Main entry point.
673 This routine is called for each instruction to be assembled.
674 STR points to the insn to be assembled.
675 We assume all necessary tables have been initialized.
676 The result is a pointer to the insn's entry in the opcode table,
677 or NULL if an error occured (an error message will have already been
678 printed). */
679
680 const struct cgen_insn *
681 m32r_cgen_assemble_insn (str, fields, buf, errmsg)
682 const char *str;
683 struct cgen_fields *fields;
684 cgen_insn_t *buf;
685 char **errmsg;
686 {
687 const char *start;
688 CGEN_INSN_LIST *ilist;
689
690 /* Skip leading white space. */
691 while (isspace (*str))
692 ++str;
693
694 /* The instructions are stored in hashed lists.
695 Get the first in the list. */
696 ilist = CGEN_ASM_LOOKUP_INSN (str);
697
698 /* Keep looking until we find a match. */
699
700 start = str;
701 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
702 {
703 const struct cgen_insn *insn = ilist->insn;
704
705 #if 0 /* not needed as unsupported opcodes shouldn't be in the hash lists */
706 /* Is this insn supported by the selected cpu? */
707 if (! m32r_cgen_insn_supported (insn))
708 continue;
709 #endif
710
711 #if 1 /* FIXME: wip */
712 /* If the RELAX attribute is set, this is an insn that shouldn't be
713 chosen immediately. Instead, it is used during assembler/linker
714 relaxation if possible. */
715 if (CGEN_INSN_ATTR (insn, CGEN_INSN_RELAX) != 0)
716 continue;
717 #endif
718
719 str = start;
720
721 /* Record a default length for the insn. This will get set to the
722 correct value while parsing. */
723 /* FIXME: wip */
724 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
725
726 /* ??? The extent to which moving the parse and insert handlers into
727 this function (thus removing the function call) will speed things up
728 is unclear. The simplicity and flexibility of the current scheme is
729 appropriate for now. One could have the best of both worlds with
730 inline functions but of course that would only work for gcc. Since
731 we're machine generating some code we could do that here too. Maybe
732 later. */
733 if (! (*CGEN_PARSE_FN (insn)) (insn, &str, fields))
734 {
735 (*CGEN_INSERT_FN (insn)) (insn, fields, buf);
736 /* It is up to the caller to actually output the insn and any
737 queued relocs. */
738 return insn;
739 }
740
741 /* Try the next entry. */
742 }
743
744 /* FIXME: We can return a better error message than this.
745 Need to track why it failed and pick the right one. */
746 {
747 static char errbuf[100];
748 sprintf (errbuf, "bad instruction `%.50s%s'",
749 start, strlen (start) > 50 ? "..." : "");
750 *errmsg = errbuf;
751 return NULL;
752 }
753 }
754 \f
755 #if 0 /* This calls back to GAS which we can't do without care. */
756
757 /* Record each member of OPVALS in the assembler's symbol table.
758 This lets GAS parse registers for us.
759 ??? Interesting idea but not currently used. */
760
761 void
762 m32r_cgen_asm_hash_keywords (opvals)
763 struct cgen_keyword *opvals;
764 {
765 struct cgen_keyword_search search = cgen_keyword_search_init (opvals, NULL);
766 const struct cgen_keyword_entry *ke;
767
768 while ((ke = cgen_keyword_search_next (&search)) != NULL)
769 {
770 #if 0 /* Unnecessary, should be done in the search routine. */
771 if (! m32r_cgen_opval_supported (ke))
772 continue;
773 #endif
774 cgen_asm_record_register (ke->name, ke->value);
775 }
776 }
777
778 #endif /* 0 */
This page took 0.046725 seconds and 5 git commands to generate.