1 /* Assembler interface for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
4 This file is used to generate m32r-asm.c.
6 Copyright (C) 1996, 1997 Free Software Foundation, Inc.
8 This file is part of the GNU Binutils and GDB, the GNU debugger.
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)
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.
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. */
31 /* ??? The layout of this stuff is still work in progress.
32 For speed in assembly/disassembly, we use inline functions. That of course
33 will only work for GCC. When this stuff is finished, we can decide whether
34 to keep the inline functions (and only get the performance increase when
35 compiled with GCC), or switch to macros, or use something else.
38 static const char * parse_insn_normal
39 PARAMS ((const CGEN_INSN
*, const char **, CGEN_FIELDS
*));
40 static void insert_insn_normal
41 PARAMS ((const CGEN_INSN
*, CGEN_FIELDS
*, cgen_insn_t
*));
43 /* Default insertion routine.
45 SHIFT is negative for left shifts, positive for right shifts.
46 All bits of VALUE to be inserted must be valid as we don't handle
47 signed vs unsigned shifts.
49 ATTRS is a mask of the boolean attributes. We don't need any at the
50 moment, but for consistency with extract_normal we have them. */
52 /* FIXME: This duplicates functionality with bfd's howto table and
53 bfd_install_relocation. */
54 /* FIXME: For architectures where insns can be representable as ints,
55 store insn in `field' struct and add registers, etc. while parsing. */
57 static CGEN_INLINE
void
58 insert_normal (value
, attrs
, start
, length
, shift
, total_length
, buffer
)
69 #if 0 /*def CGEN_INT_INSN*/
70 *buffer
|= ((value
& ((1 << length
) - 1))
71 << (total_length
- (start
+ length
)));
76 x
= * (unsigned char *) buffer
;
79 if (CGEN_CURRENT_ENDIAN
== CGEN_ENDIAN_BIG
)
80 x
= bfd_getb16 (buffer
);
82 x
= bfd_getl16 (buffer
);
85 if (CGEN_CURRENT_ENDIAN
== CGEN_ENDIAN_BIG
)
86 x
= bfd_getb32 (buffer
);
88 x
= bfd_getl32 (buffer
);
99 x
|= ((value
& ((1 << length
) - 1))
100 << (total_length
- (start
+ length
)));
102 switch (total_length
)
108 if (CGEN_CURRENT_ENDIAN
== CGEN_ENDIAN_BIG
)
109 bfd_putb16 (x
, buffer
);
111 bfd_putl16 (x
, buffer
);
114 if (CGEN_CURRENT_ENDIAN
== CGEN_ENDIAN_BIG
)
115 bfd_putb32 (x
, buffer
);
117 bfd_putl32 (x
, buffer
);
125 /* -- assembler routines inserted here */
128 /* Handle shigh(), high(). */
131 parse_h_hi16 (strp
, opindex
, min
, max
, valuep
)
134 unsigned long min
, max
;
135 unsigned long *valuep
;
138 enum cgen_parse_operand_result result_type
;
140 /* FIXME: Need # in assembler syntax (means '#' is optional). */
144 if (strncmp (*strp
, "high(", 5) == 0)
147 errmsg
= cgen_parse_address (strp
, opindex
, BFD_RELOC_M32R_HI16_ULO
,
148 &result_type
, valuep
);
150 return "missing `)'";
153 && result_type
== CGEN_PARSE_OPERAND_RESULT_NUMBER
)
157 else if (strncmp (*strp
, "shigh(", 6) == 0)
160 errmsg
= cgen_parse_address (strp
, opindex
, BFD_RELOC_M32R_HI16_SLO
,
161 &result_type
, valuep
);
163 return "missing `)'";
166 && result_type
== CGEN_PARSE_OPERAND_RESULT_NUMBER
)
167 *valuep
= (*valuep
>> 16) + ((*valuep
) & 0x8000 ? 1 : 0);
171 return cgen_parse_unsigned_integer (strp
, opindex
, min
, max
, valuep
);
174 /* Handle low() in a signed context. Also handle sda().
175 The signedness of the value doesn't matter to low(), but this also
176 handles the case where low() isn't present. */
179 parse_h_slo16 (strp
, opindex
, min
, max
, valuep
)
186 enum cgen_parse_operand_result result_type
;
188 /* FIXME: Need # in assembler syntax (means '#' is optional). */
192 if (strncmp (*strp
, "low(", 4) == 0)
195 errmsg
= cgen_parse_address (strp
, opindex
, BFD_RELOC_M32R_LO16
,
196 &result_type
, valuep
);
198 return "missing `)'";
203 if (strncmp (*strp
, "sda(", 4) == 0)
206 errmsg
= cgen_parse_address (strp
, opindex
, BFD_RELOC_M32R_SDA16
, NULL
, valuep
);
208 return "missing `)'";
213 return cgen_parse_signed_integer (strp
, opindex
, min
, max
, valuep
);
216 /* Handle low() in an unsigned context.
217 The signedness of the value doesn't matter to low(), but this also
218 handles the case where low() isn't present. */
221 parse_h_ulo16 (strp
, opindex
, min
, max
, valuep
)
224 unsigned long min
, max
;
225 unsigned long *valuep
;
228 enum cgen_parse_operand_result result_type
;
230 /* FIXME: Need # in assembler syntax (means '#' is optional). */
234 if (strncmp (*strp
, "low(", 4) == 0)
237 errmsg
= cgen_parse_address (strp
, opindex
, BFD_RELOC_M32R_LO16
,
238 &result_type
, valuep
);
240 return "missing `)'";
245 return cgen_parse_unsigned_integer (strp
, opindex
, min
, max
, valuep
);
250 /* Main entry point for operand parsing.
252 This function is basically just a big switch statement. Earlier versions
253 used tables to look up the function to use, but
254 - if the table contains both assembler and disassembler functions then
255 the disassembler contains much of the assembler and vice-versa,
256 - there's a lot of inlining possibilities as things grow,
257 - using a switch statement avoids the function call overhead.
259 This function could be moved into `parse_insn_normal', but keeping it
260 separate makes clear the interface between `parse_insn_normal' and each of
264 CGEN_INLINE
const char *
265 m32r_cgen_parse_operand (opindex
, strp
, fields
)
268 CGEN_FIELDS
* fields
;
274 case M32R_OPERAND_SR
:
275 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_gr
, & fields
->f_r2
);
277 case M32R_OPERAND_DR
:
278 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_gr
, & fields
->f_r1
);
280 case M32R_OPERAND_SRC1
:
281 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_gr
, & fields
->f_r1
);
283 case M32R_OPERAND_SRC2
:
284 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_gr
, & fields
->f_r2
);
286 case M32R_OPERAND_SCR
:
287 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_cr
, & fields
->f_r2
);
289 case M32R_OPERAND_DCR
:
290 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_cr
, & fields
->f_r1
);
292 case M32R_OPERAND_SIMM8
:
293 errmsg
= cgen_parse_signed_integer (strp
, 7, -128, 127, &fields
->f_simm8
);
295 case M32R_OPERAND_SIMM16
:
296 errmsg
= cgen_parse_signed_integer (strp
, 8, -32768, 32767, &fields
->f_simm16
);
298 case M32R_OPERAND_UIMM4
:
299 errmsg
= cgen_parse_unsigned_integer (strp
, 9, 0, 15, &fields
->f_uimm4
);
301 case M32R_OPERAND_UIMM5
:
302 errmsg
= cgen_parse_unsigned_integer (strp
, 10, 0, 31, &fields
->f_uimm5
);
304 case M32R_OPERAND_UIMM16
:
305 errmsg
= cgen_parse_unsigned_integer (strp
, 11, 0, 65535, &fields
->f_uimm16
);
307 case M32R_OPERAND_HI16
:
308 errmsg
= parse_h_hi16 (strp
, 12, 0, 65535, &fields
->f_hi16
);
310 case M32R_OPERAND_SLO16
:
311 errmsg
= parse_h_slo16 (strp
, 13, -32768, 32767, &fields
->f_simm16
);
313 case M32R_OPERAND_ULO16
:
314 errmsg
= parse_h_ulo16 (strp
, 14, 0, 65535, &fields
->f_uimm16
);
316 case M32R_OPERAND_UIMM24
:
317 errmsg
= cgen_parse_address (strp
, 15, 0, NULL
, & fields
->f_uimm24
);
319 case M32R_OPERAND_DISP8
:
320 errmsg
= cgen_parse_address (strp
, 16, 0, NULL
, & fields
->f_disp8
);
322 case M32R_OPERAND_DISP16
:
323 errmsg
= cgen_parse_address (strp
, 17, 0, NULL
, & fields
->f_disp16
);
325 case M32R_OPERAND_DISP24
:
326 errmsg
= cgen_parse_address (strp
, 18, 0, NULL
, & fields
->f_disp24
);
330 fprintf (stderr
, "Unrecognized field %d while parsing.\n", opindex
);
337 /* Main entry point for operand insertion.
339 This function is basically just a big switch statement. Earlier versions
340 used tables to look up the function to use, but
341 - if the table contains both assembler and disassembler functions then
342 the disassembler contains much of the assembler and vice-versa,
343 - there's a lot of inlining possibilities as things grow,
344 - using a switch statement avoids the function call overhead.
346 This function could be moved into `parse_insn_normal', but keeping it
347 separate makes clear the interface between `parse_insn_normal' and each of
348 the handlers. It's also needed by GAS to insert operands that couldn't be
349 resolved during parsing.
353 m32r_cgen_insert_operand (opindex
, fields
, buffer
)
355 CGEN_FIELDS
* fields
;
356 cgen_insn_t
* buffer
;
360 case M32R_OPERAND_SR
:
361 insert_normal (fields
->f_r2
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
363 case M32R_OPERAND_DR
:
364 insert_normal (fields
->f_r1
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
366 case M32R_OPERAND_SRC1
:
367 insert_normal (fields
->f_r1
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
369 case M32R_OPERAND_SRC2
:
370 insert_normal (fields
->f_r2
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
372 case M32R_OPERAND_SCR
:
373 insert_normal (fields
->f_r2
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
375 case M32R_OPERAND_DCR
:
376 insert_normal (fields
->f_r1
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
378 case M32R_OPERAND_SIMM8
:
379 insert_normal (fields
->f_simm8
, 0, 8, 8, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
381 case M32R_OPERAND_SIMM16
:
382 insert_normal (fields
->f_simm16
, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
384 case M32R_OPERAND_UIMM4
:
385 insert_normal (fields
->f_uimm4
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
387 case M32R_OPERAND_UIMM5
:
388 insert_normal (fields
->f_uimm5
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 11, 5, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
390 case M32R_OPERAND_UIMM16
:
391 insert_normal (fields
->f_uimm16
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
393 case M32R_OPERAND_HI16
:
394 insert_normal (fields
->f_hi16
, 0|(1<<CGEN_OPERAND_SIGN_OPT
)|(1<<CGEN_OPERAND_UNSIGNED
), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
396 case M32R_OPERAND_SLO16
:
397 insert_normal (fields
->f_simm16
, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
399 case M32R_OPERAND_ULO16
:
400 insert_normal (fields
->f_uimm16
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
402 case M32R_OPERAND_UIMM24
:
403 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
);
405 case M32R_OPERAND_DISP8
:
406 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
);
408 case M32R_OPERAND_DISP16
:
409 insert_normal (fields
->f_disp16
, 0|(1<<CGEN_OPERAND_RELOC
)|(1<<CGEN_OPERAND_PCREL_ADDR
), 16, 16, 2, CGEN_FIELDS_BITSIZE (fields
), buffer
);
411 case M32R_OPERAND_DISP24
:
412 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
);
416 fprintf (stderr
, "Unrecognized field %d while building insn.\n",
422 /* Main entry point for operand validation.
424 This function is called from GAS when it has fully resolved an operand
425 that couldn't be resolved during parsing.
427 The result is NULL for success or an error message (which may be
428 computed into a static buffer).
431 CGEN_INLINE
const char *
432 m32r_cgen_validate_operand (opindex
, fields
)
434 const CGEN_FIELDS
* fields
;
436 const char * errmsg
= NULL
;
440 case M32R_OPERAND_SR
:
443 case M32R_OPERAND_DR
:
446 case M32R_OPERAND_SRC1
:
449 case M32R_OPERAND_SRC2
:
452 case M32R_OPERAND_SCR
:
455 case M32R_OPERAND_DCR
:
458 case M32R_OPERAND_SIMM8
:
459 errmsg
= cgen_validate_signed_integer (fields
->f_simm8
, -128, 127);
461 case M32R_OPERAND_SIMM16
:
462 errmsg
= cgen_validate_signed_integer (fields
->f_simm16
, -32768, 32767);
464 case M32R_OPERAND_UIMM4
:
465 errmsg
= cgen_validate_unsigned_integer (fields
->f_uimm4
, 0, 15);
467 case M32R_OPERAND_UIMM5
:
468 errmsg
= cgen_validate_unsigned_integer (fields
->f_uimm5
, 0, 31);
470 case M32R_OPERAND_UIMM16
:
471 errmsg
= cgen_validate_unsigned_integer (fields
->f_uimm16
, 0, 65535);
473 case M32R_OPERAND_HI16
:
474 errmsg
= cgen_validate_unsigned_integer (fields
->f_hi16
, 0, 65535);
476 case M32R_OPERAND_SLO16
:
477 errmsg
= cgen_validate_signed_integer (fields
->f_simm16
, -32768, 32767);
479 case M32R_OPERAND_ULO16
:
480 errmsg
= cgen_validate_unsigned_integer (fields
->f_uimm16
, 0, 65535);
482 case M32R_OPERAND_UIMM24
:
485 case M32R_OPERAND_DISP8
:
488 case M32R_OPERAND_DISP16
:
491 case M32R_OPERAND_DISP24
:
496 fprintf (stderr
, "Unrecognized field %d while validating operand.\n",
504 cgen_parse_fn
* m32r_cgen_parse_handlers
[] =
510 cgen_insert_fn
* m32r_cgen_insert_handlers
[] =
517 m32r_cgen_init_asm (mach
, endian
)
519 enum cgen_endian endian
;
521 m32r_cgen_init_tables (mach
);
522 cgen_set_cpu (& m32r_cgen_opcode_data
, mach
, endian
);
527 /* Default insn parser.
529 The syntax string is scanned and operands are parsed and stored in FIELDS.
530 Relocs are queued as we go via other callbacks.
532 ??? Note that this is currently an all-or-nothing parser. If we fail to
533 parse the instruction, we return 0 and the caller will start over from
534 the beginning. Backtracking will be necessary in parsing subexpressions,
535 but that can be handled there. Not handling backtracking here may get
536 expensive in the case of the m68k. Deal with later.
538 Returns NULL for success, an error message for failure.
542 parse_insn_normal (insn
, strp
, fields
)
543 const CGEN_INSN
* insn
;
545 CGEN_FIELDS
* fields
;
547 const CGEN_SYNTAX
* syntax
= CGEN_INSN_SYNTAX (insn
);
548 const char * str
= *strp
;
551 const unsigned char * syn
;
552 #ifdef CGEN_MNEMONIC_OPERANDS
556 /* For now we assume the mnemonic is first (there are no leading operands).
557 We can parse it without needing to set up operand parsing. */
558 p
= CGEN_INSN_MNEMONIC (insn
);
559 while (* p
&& * p
== * str
)
561 if (* p
|| (* str
&& !isspace (* str
)))
562 return "unrecognized instruction";
565 cgen_init_parse_operand ();
566 #ifdef CGEN_MNEMONIC_OPERANDS
570 /* We don't check for (*str != '\0') here because we want to parse
571 any trailing fake arguments in the syntax string. */
572 syn
= CGEN_SYNTAX_STRING (CGEN_INSN_SYNTAX (insn
));
574 /* Mnemonics come first for now, ensure valid string. */
575 if (! CGEN_SYNTAX_MNEMONIC_P (* syn
))
582 /* Non operand chars must match exactly. */
583 /* FIXME: Need to better handle whitespace. */
584 if (CGEN_SYNTAX_CHAR_P (* syn
))
586 if (*str
== CGEN_SYNTAX_CHAR (* syn
))
588 #ifdef CGEN_MNEMONIC_OPERANDS
597 /* Syntax char didn't match. Can't be this insn. */
598 /* FIXME: would like to return "expected char `c'" */
599 return "syntax error";
604 /* We have an operand of some sort. */
605 errmsg
= m32r_cgen_parse_operand (CGEN_SYNTAX_FIELD (*syn
),
610 /* Done with this operand, continue with next one. */
614 /* If we're at the end of the syntax string, we're done. */
617 /* FIXME: For the moment we assume a valid `str' can only contain
618 blanks now. IE: We needn't try again with a longer version of
619 the insn and it is assumed that longer versions of insns appear
620 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
621 while (isspace (* str
))
625 return "junk at end of line"; /* FIXME: would like to include `str' */
630 /* We couldn't parse it. */
631 return "unrecognized instruction";
634 /* Default insn builder (insert handler).
635 The instruction is recorded in target byte order. */
638 insert_insn_normal (insn
, fields
, buffer
)
639 const CGEN_INSN
* insn
;
640 CGEN_FIELDS
* fields
;
641 cgen_insn_t
* buffer
;
643 const CGEN_SYNTAX
* syntax
= CGEN_INSN_SYNTAX (insn
);
645 const unsigned char * syn
;
648 value
= CGEN_INSN_VALUE (insn
);
650 /* If we're recording insns as numbers (rather than a string of bytes),
651 target byte order handling is deferred until later. */
653 #define min(a,b) ((a) < (b) ? (a) : (b))
654 #if 0 /*def CGEN_INT_INSN*/
657 switch (min (CGEN_BASE_INSN_BITSIZE
, CGEN_FIELDS_BITSIZE (fields
)))
663 if (CGEN_CURRENT_ENDIAN
== CGEN_ENDIAN_BIG
)
664 bfd_putb16 (value
, (char *) buffer
);
666 bfd_putl16 (value
, (char *) buffer
);
669 if (CGEN_CURRENT_ENDIAN
== CGEN_ENDIAN_BIG
)
670 bfd_putb32 (value
, (char *) buffer
);
672 bfd_putl32 (value
, (char *) buffer
);
679 /* ??? Rather than scanning the syntax string again, we could store
680 in `fields' a null terminated list of the fields that are present. */
682 for (syn
= CGEN_SYNTAX_STRING (syntax
); * syn
!= '\0'; ++ syn
)
684 if (CGEN_SYNTAX_CHAR_P (* syn
))
687 m32r_cgen_insert_operand (CGEN_SYNTAX_FIELD (*syn
), fields
, buffer
);
692 This routine is called for each instruction to be assembled.
693 STR points to the insn to be assembled.
694 We assume all necessary tables have been initialized.
695 The result is a pointer to the insn's entry in the opcode table,
696 or NULL if an error occured (an error message will have already been
700 m32r_cgen_assemble_insn (str
, fields
, buf
, errmsg
)
702 CGEN_FIELDS
* fields
;
707 CGEN_INSN_LIST
* ilist
;
709 /* Skip leading white space. */
710 while (isspace (* str
))
713 /* The instructions are stored in hashed lists.
714 Get the first in the list. */
715 ilist
= CGEN_ASM_LOOKUP_INSN (str
);
717 /* Keep looking until we find a match. */
720 for ( ; ilist
!= NULL
; ilist
= CGEN_ASM_NEXT_INSN (ilist
))
722 const CGEN_INSN
*insn
= ilist
->insn
;
724 #if 0 /* not needed as unsupported opcodes shouldn't be in the hash lists */
725 /* Is this insn supported by the selected cpu? */
726 if (! m32r_cgen_insn_supported (insn
))
730 #if 1 /* FIXME: wip */
731 /* If the RELAX attribute is set, this is an insn that shouldn't be
732 chosen immediately. Instead, it is used during assembler/linker
733 relaxation if possible. */
734 if (CGEN_INSN_ATTR (insn
, CGEN_INSN_RELAX
) != 0)
740 /* Record a default length for the insn. This will get set to the
741 correct value while parsing. */
743 CGEN_FIELDS_BITSIZE (fields
) = CGEN_INSN_BITSIZE (insn
);
745 /* ??? The extent to which moving the parse and insert handlers into
746 this function (thus removing the function call) will speed things up
747 is unclear. The simplicity and flexibility of the current scheme is
748 appropriate for now. One could have the best of both worlds with
749 inline functions but of course that would only work for gcc. Since
750 we're machine generating some code we could do that here too. Maybe
752 if (! CGEN_PARSE_FN (insn
) (insn
, & str
, fields
))
754 CGEN_INSERT_FN (insn
) (insn
, fields
, buf
);
755 /* It is up to the caller to actually output the insn and any
760 /* Try the next entry. */
763 /* FIXME: We can return a better error message than this.
764 Need to track why it failed and pick the right one. */
766 static char errbuf
[100];
767 sprintf (errbuf
, "bad instruction `%.50s%s'",
768 start
, strlen (start
) > 50 ? "..." : "");
774 #if 0 /* This calls back to GAS which we can't do without care. */
776 /* Record each member of OPVALS in the assembler's symbol table.
777 This lets GAS parse registers for us.
778 ??? Interesting idea but not currently used. */
780 /* Record each member of OPVALS in the assembler's symbol table.
781 FIXME: Not currently used. */
784 m32r_cgen_asm_hash_keywords (opvals
)
785 CGEN_KEYWORD
* opvals
;
787 CGEN_KEYWORD_SEARCH search
= cgen_keyword_search_init (opvals
, NULL
);
788 const CGEN_KEYWORD_ENTRY
* ke
;
790 while ((ke
= cgen_keyword_search_next (& search
)) != NULL
)
792 #if 0 /* Unnecessary, should be done in the search routine. */
793 if (! m32r_cgen_opval_supported (ke
))
796 cgen_asm_record_register (ke
->name
, ke
->value
);