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, 1998 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. */
32 /* ??? The layout of this stuff is still work in progress.
33 For speed in assembly/disassembly, we use inline functions. That of course
34 will only work for GCC. When this stuff is finished, we can decide whether
35 to keep the inline functions (and only get the performance increase when
36 compiled with GCC), or switch to macros, or use something else.
39 static const char * insert_normal
40 PARAMS ((long, unsigned int, int, int, int, char *));
41 static const char * parse_insn_normal
42 PARAMS ((const CGEN_INSN
*, const char **, CGEN_FIELDS
*));
43 static const char * insert_insn_normal
44 PARAMS ((const CGEN_INSN
*, CGEN_FIELDS
*, cgen_insn_t
*));
46 /* -- assembler routines inserted here */
49 /* Handle '#' prefixes (i.e. skip over them). */
52 parse_hash (strp
, opindex
, valuep
)
55 unsigned long *valuep
;
62 /* Handle shigh(), high(). */
65 parse_hi16 (strp
, opindex
, valuep
)
68 unsigned long *valuep
;
71 enum cgen_parse_operand_result result_type
;
76 if (strncmp (*strp
, "high(", 5) == 0)
79 errmsg
= cgen_parse_address (strp
, opindex
, BFD_RELOC_M32R_HI16_ULO
,
80 &result_type
, valuep
);
85 && result_type
== CGEN_PARSE_OPERAND_RESULT_NUMBER
)
89 else if (strncmp (*strp
, "shigh(", 6) == 0)
92 errmsg
= cgen_parse_address (strp
, opindex
, BFD_RELOC_M32R_HI16_SLO
,
93 &result_type
, valuep
);
98 && result_type
== CGEN_PARSE_OPERAND_RESULT_NUMBER
)
99 *valuep
= (*valuep
>> 16) + ((*valuep
) & 0x8000 ? 1 : 0);
103 return cgen_parse_unsigned_integer (strp
, opindex
, valuep
);
106 /* Handle low() in a signed context. Also handle sda().
107 The signedness of the value doesn't matter to low(), but this also
108 handles the case where low() isn't present. */
111 parse_slo16 (strp
, opindex
, valuep
)
117 enum cgen_parse_operand_result result_type
;
122 if (strncmp (*strp
, "low(", 4) == 0)
125 errmsg
= cgen_parse_address (strp
, opindex
, BFD_RELOC_M32R_LO16
,
126 &result_type
, valuep
);
128 return "missing `)'";
131 && result_type
== CGEN_PARSE_OPERAND_RESULT_NUMBER
)
136 if (strncmp (*strp
, "sda(", 4) == 0)
139 errmsg
= cgen_parse_address (strp
, opindex
, BFD_RELOC_M32R_SDA16
, NULL
, valuep
);
141 return "missing `)'";
146 return cgen_parse_signed_integer (strp
, opindex
, valuep
);
149 /* Handle low() in an unsigned context.
150 The signedness of the value doesn't matter to low(), but this also
151 handles the case where low() isn't present. */
154 parse_ulo16 (strp
, opindex
, valuep
)
157 unsigned long *valuep
;
160 enum cgen_parse_operand_result result_type
;
165 if (strncmp (*strp
, "low(", 4) == 0)
168 errmsg
= cgen_parse_address (strp
, opindex
, BFD_RELOC_M32R_LO16
,
169 &result_type
, valuep
);
171 return "missing `)'";
174 && result_type
== CGEN_PARSE_OPERAND_RESULT_NUMBER
)
179 return cgen_parse_unsigned_integer (strp
, opindex
, valuep
);
184 /* Main entry point for operand parsing.
186 This function is basically just a big switch statement. Earlier versions
187 used tables to look up the function to use, but
188 - if the table contains both assembler and disassembler functions then
189 the disassembler contains much of the assembler and vice-versa,
190 - there's a lot of inlining possibilities as things grow,
191 - using a switch statement avoids the function call overhead.
193 This function could be moved into `parse_insn_normal', but keeping it
194 separate makes clear the interface between `parse_insn_normal' and each of
199 m32r_cgen_parse_operand (opindex
, strp
, fields
)
202 CGEN_FIELDS
* fields
;
208 case M32R_OPERAND_SR
:
209 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_gr
, & fields
->f_r2
);
211 case M32R_OPERAND_DR
:
212 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_gr
, & fields
->f_r1
);
214 case M32R_OPERAND_SRC1
:
215 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_gr
, & fields
->f_r1
);
217 case M32R_OPERAND_SRC2
:
218 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_gr
, & fields
->f_r2
);
220 case M32R_OPERAND_SCR
:
221 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_cr
, & fields
->f_r2
);
223 case M32R_OPERAND_DCR
:
224 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_cr
, & fields
->f_r1
);
226 case M32R_OPERAND_SIMM8
:
227 errmsg
= cgen_parse_signed_integer (strp
, M32R_OPERAND_SIMM8
, &fields
->f_simm8
);
229 case M32R_OPERAND_SIMM16
:
230 errmsg
= cgen_parse_signed_integer (strp
, M32R_OPERAND_SIMM16
, &fields
->f_simm16
);
232 case M32R_OPERAND_UIMM4
:
233 errmsg
= cgen_parse_unsigned_integer (strp
, M32R_OPERAND_UIMM4
, &fields
->f_uimm4
);
235 case M32R_OPERAND_UIMM5
:
236 errmsg
= cgen_parse_unsigned_integer (strp
, M32R_OPERAND_UIMM5
, &fields
->f_uimm5
);
238 case M32R_OPERAND_UIMM16
:
239 errmsg
= cgen_parse_unsigned_integer (strp
, M32R_OPERAND_UIMM16
, &fields
->f_uimm16
);
241 /* start-sanitize-m32rx */
242 case M32R_OPERAND_IMM1
:
243 errmsg
= cgen_parse_unsigned_integer (strp
, M32R_OPERAND_IMM1
, &fields
->f_imm1
);
245 /* end-sanitize-m32rx */
246 /* start-sanitize-m32rx */
247 case M32R_OPERAND_ACCD
:
248 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_accums
, & fields
->f_accd
);
250 /* end-sanitize-m32rx */
251 /* start-sanitize-m32rx */
252 case M32R_OPERAND_ACCS
:
253 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_accums
, & fields
->f_accs
);
255 /* end-sanitize-m32rx */
256 /* start-sanitize-m32rx */
257 case M32R_OPERAND_ACC
:
258 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_accums
, & fields
->f_acc
);
260 /* end-sanitize-m32rx */
261 case M32R_OPERAND_HASH
:
262 errmsg
= parse_hash (strp
, M32R_OPERAND_HASH
, &fields
->f_nil
);
264 case M32R_OPERAND_HI16
:
265 errmsg
= parse_hi16 (strp
, M32R_OPERAND_HI16
, &fields
->f_hi16
);
267 case M32R_OPERAND_SLO16
:
268 errmsg
= parse_slo16 (strp
, M32R_OPERAND_SLO16
, &fields
->f_simm16
);
270 case M32R_OPERAND_ULO16
:
271 errmsg
= parse_ulo16 (strp
, M32R_OPERAND_ULO16
, &fields
->f_uimm16
);
273 case M32R_OPERAND_UIMM24
:
274 errmsg
= cgen_parse_address (strp
, M32R_OPERAND_UIMM24
, 0, NULL
, & fields
->f_uimm24
);
276 case M32R_OPERAND_DISP8
:
277 errmsg
= cgen_parse_address (strp
, M32R_OPERAND_DISP8
, 0, NULL
, & fields
->f_disp8
);
279 case M32R_OPERAND_DISP16
:
280 errmsg
= cgen_parse_address (strp
, M32R_OPERAND_DISP16
, 0, NULL
, & fields
->f_disp16
);
282 case M32R_OPERAND_DISP24
:
283 errmsg
= cgen_parse_address (strp
, M32R_OPERAND_DISP24
, 0, NULL
, & fields
->f_disp24
);
287 fprintf (stderr
, "Unrecognized field %d while parsing.\n", opindex
);
294 /* Main entry point for operand insertion.
296 This function is basically just a big switch statement. Earlier versions
297 used tables to look up the function to use, but
298 - if the table contains both assembler and disassembler functions then
299 the disassembler contains much of the assembler and vice-versa,
300 - there's a lot of inlining possibilities as things grow,
301 - using a switch statement avoids the function call overhead.
303 This function could be moved into `parse_insn_normal', but keeping it
304 separate makes clear the interface between `parse_insn_normal' and each of
305 the handlers. It's also needed by GAS to insert operands that couldn't be
306 resolved during parsing.
310 m32r_cgen_insert_operand (opindex
, fields
, buffer
)
312 CGEN_FIELDS
* fields
;
319 case M32R_OPERAND_SR
:
320 errmsg
= insert_normal (fields
->f_r2
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 12, 4, CGEN_FIELDS_BITSIZE (fields
), buffer
);
322 case M32R_OPERAND_DR
:
323 errmsg
= insert_normal (fields
->f_r1
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 4, 4, CGEN_FIELDS_BITSIZE (fields
), buffer
);
325 case M32R_OPERAND_SRC1
:
326 errmsg
= insert_normal (fields
->f_r1
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 4, 4, CGEN_FIELDS_BITSIZE (fields
), buffer
);
328 case M32R_OPERAND_SRC2
:
329 errmsg
= insert_normal (fields
->f_r2
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 12, 4, CGEN_FIELDS_BITSIZE (fields
), buffer
);
331 case M32R_OPERAND_SCR
:
332 errmsg
= insert_normal (fields
->f_r2
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 12, 4, CGEN_FIELDS_BITSIZE (fields
), buffer
);
334 case M32R_OPERAND_DCR
:
335 errmsg
= insert_normal (fields
->f_r1
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 4, 4, CGEN_FIELDS_BITSIZE (fields
), buffer
);
337 case M32R_OPERAND_SIMM8
:
338 errmsg
= insert_normal (fields
->f_simm8
, 0|(1<<CGEN_OPERAND_HASH_PREFIX
), 8, 8, CGEN_FIELDS_BITSIZE (fields
), buffer
);
340 case M32R_OPERAND_SIMM16
:
341 errmsg
= insert_normal (fields
->f_simm16
, 0|(1<<CGEN_OPERAND_HASH_PREFIX
), 16, 16, CGEN_FIELDS_BITSIZE (fields
), buffer
);
343 case M32R_OPERAND_UIMM4
:
344 errmsg
= insert_normal (fields
->f_uimm4
, 0|(1<<CGEN_OPERAND_HASH_PREFIX
)|(1<<CGEN_OPERAND_UNSIGNED
), 12, 4, CGEN_FIELDS_BITSIZE (fields
), buffer
);
346 case M32R_OPERAND_UIMM5
:
347 errmsg
= insert_normal (fields
->f_uimm5
, 0|(1<<CGEN_OPERAND_HASH_PREFIX
)|(1<<CGEN_OPERAND_UNSIGNED
), 11, 5, CGEN_FIELDS_BITSIZE (fields
), buffer
);
349 case M32R_OPERAND_UIMM16
:
350 errmsg
= insert_normal (fields
->f_uimm16
, 0|(1<<CGEN_OPERAND_HASH_PREFIX
)|(1<<CGEN_OPERAND_UNSIGNED
), 16, 16, CGEN_FIELDS_BITSIZE (fields
), buffer
);
352 /* start-sanitize-m32rx */
353 case M32R_OPERAND_IMM1
:
355 long value
= ((fields
->f_imm1
) - (1));
356 errmsg
= insert_normal (value
, 0|(1<<CGEN_OPERAND_HASH_PREFIX
)|(1<<CGEN_OPERAND_UNSIGNED
), 15, 1, CGEN_FIELDS_BITSIZE (fields
), buffer
);
359 /* end-sanitize-m32rx */
360 /* start-sanitize-m32rx */
361 case M32R_OPERAND_ACCD
:
362 errmsg
= insert_normal (fields
->f_accd
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 4, 2, CGEN_FIELDS_BITSIZE (fields
), buffer
);
364 /* end-sanitize-m32rx */
365 /* start-sanitize-m32rx */
366 case M32R_OPERAND_ACCS
:
367 errmsg
= insert_normal (fields
->f_accs
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 12, 2, CGEN_FIELDS_BITSIZE (fields
), buffer
);
369 /* end-sanitize-m32rx */
370 /* start-sanitize-m32rx */
371 case M32R_OPERAND_ACC
:
372 errmsg
= insert_normal (fields
->f_acc
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 8, 1, CGEN_FIELDS_BITSIZE (fields
), buffer
);
374 /* end-sanitize-m32rx */
375 case M32R_OPERAND_HASH
:
376 errmsg
= insert_normal (fields
->f_nil
, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
378 case M32R_OPERAND_HI16
:
379 errmsg
= insert_normal (fields
->f_hi16
, 0|(1<<CGEN_OPERAND_SIGN_OPT
)|(1<<CGEN_OPERAND_UNSIGNED
), 16, 16, CGEN_FIELDS_BITSIZE (fields
), buffer
);
381 case M32R_OPERAND_SLO16
:
382 errmsg
= insert_normal (fields
->f_simm16
, 0, 16, 16, CGEN_FIELDS_BITSIZE (fields
), buffer
);
384 case M32R_OPERAND_ULO16
:
385 errmsg
= insert_normal (fields
->f_uimm16
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 16, 16, CGEN_FIELDS_BITSIZE (fields
), buffer
);
387 case M32R_OPERAND_UIMM24
:
388 errmsg
= insert_normal (fields
->f_uimm24
, 0|(1<<CGEN_OPERAND_HASH_PREFIX
)|(1<<CGEN_OPERAND_RELOC
)|(1<<CGEN_OPERAND_ABS_ADDR
)|(1<<CGEN_OPERAND_UNSIGNED
), 8, 24, CGEN_FIELDS_BITSIZE (fields
), buffer
);
390 case M32R_OPERAND_DISP8
:
392 long value
= ((fields
->f_disp8
) >> (2));
393 errmsg
= insert_normal (value
, 0|(1<<CGEN_OPERAND_RELAX
)|(1<<CGEN_OPERAND_RELOC
)|(1<<CGEN_OPERAND_PCREL_ADDR
), 8, 8, CGEN_FIELDS_BITSIZE (fields
), buffer
);
396 case M32R_OPERAND_DISP16
:
398 long value
= ((fields
->f_disp16
) >> (2));
399 errmsg
= insert_normal (value
, 0|(1<<CGEN_OPERAND_RELOC
)|(1<<CGEN_OPERAND_PCREL_ADDR
), 16, 16, CGEN_FIELDS_BITSIZE (fields
), buffer
);
402 case M32R_OPERAND_DISP24
:
404 long value
= ((fields
->f_disp24
) >> (2));
405 errmsg
= insert_normal (value
, 0|(1<<CGEN_OPERAND_RELAX
)|(1<<CGEN_OPERAND_RELOC
)|(1<<CGEN_OPERAND_PCREL_ADDR
), 8, 24, CGEN_FIELDS_BITSIZE (fields
), buffer
);
410 fprintf (stderr
, "Unrecognized field %d while building insn.\n",
418 cgen_parse_fn
* m32r_cgen_parse_handlers
[] =
424 cgen_insert_fn
* m32r_cgen_insert_handlers
[] =
431 m32r_cgen_init_asm (mach
, endian
)
433 enum cgen_endian endian
;
435 m32r_cgen_init_tables (mach
);
436 cgen_set_cpu (& m32r_cgen_opcode_table
, mach
, endian
);
441 /* Default insertion routine.
443 ATTRS is a mask of the boolean attributes.
444 LENGTH is the length of VALUE in bits.
445 TOTAL_LENGTH is the total length of the insn (currently 8,16,32).
447 The result is an error message or NULL if success. */
449 /* ??? This duplicates functionality with bfd's howto table and
450 bfd_install_relocation. */
451 /* ??? For architectures where insns can be representable as ints,
452 store insn in `field' struct and add registers, etc. while parsing? */
455 insert_normal (value
, attrs
, start
, length
, total_length
, buffer
)
464 static char buf
[100];
466 /* Ensure VALUE will fit. */
467 if ((attrs
& (1 << CGEN_OPERAND_UNSIGNED
)) != 0)
469 unsigned long max
= (1 << length
) - 1;
470 if ((unsigned long) value
> max
)
472 const char *err
= "operand out of range (%lu not between 0 and %lu)";
474 sprintf (buf
, err
, value
, max
);
480 long min
= - (1 << (length
- 1));
481 long max
= (1 << (length
- 1)) - 1;
482 if (value
< min
|| value
> max
)
484 const char *err
= "operand out of range (%ld not between %ld and %ld)";
486 sprintf (buf
, err
, value
, min
, max
);
491 #if 0 /*def CGEN_INT_INSN*/
492 *buffer
|= ((value
& ((1 << length
) - 1))
493 << (total_length
- (start
+ length
)));
495 switch (total_length
)
498 x
= * (unsigned char *) buffer
;
501 if (CGEN_CURRENT_ENDIAN
== CGEN_ENDIAN_BIG
)
502 x
= bfd_getb16 (buffer
);
504 x
= bfd_getl16 (buffer
);
507 if (CGEN_CURRENT_ENDIAN
== CGEN_ENDIAN_BIG
)
508 x
= bfd_getb32 (buffer
);
510 x
= bfd_getl32 (buffer
);
516 x
|= ((value
& ((1 << length
) - 1))
517 << (total_length
- (start
+ length
)));
519 switch (total_length
)
525 if (CGEN_CURRENT_ENDIAN
== CGEN_ENDIAN_BIG
)
526 bfd_putb16 (x
, buffer
);
528 bfd_putl16 (x
, buffer
);
531 if (CGEN_CURRENT_ENDIAN
== CGEN_ENDIAN_BIG
)
532 bfd_putb32 (x
, buffer
);
534 bfd_putl32 (x
, buffer
);
544 /* Default insn parser.
546 The syntax string is scanned and operands are parsed and stored in FIELDS.
547 Relocs are queued as we go via other callbacks.
549 ??? Note that this is currently an all-or-nothing parser. If we fail to
550 parse the instruction, we return 0 and the caller will start over from
551 the beginning. Backtracking will be necessary in parsing subexpressions,
552 but that can be handled there. Not handling backtracking here may get
553 expensive in the case of the m68k. Deal with later.
555 Returns NULL for success, an error message for failure.
559 parse_insn_normal (insn
, strp
, fields
)
560 const CGEN_INSN
* insn
;
562 CGEN_FIELDS
* fields
;
564 const CGEN_SYNTAX
* syntax
= CGEN_INSN_SYNTAX (insn
);
565 const char * str
= *strp
;
568 const unsigned char * syn
;
569 #ifdef CGEN_MNEMONIC_OPERANDS
573 /* For now we assume the mnemonic is first (there are no leading operands).
574 We can parse it without needing to set up operand parsing. */
575 p
= CGEN_INSN_MNEMONIC (insn
);
576 while (* p
&& * p
== * str
)
578 if (* p
|| (* str
&& !isspace (* str
)))
579 return "unrecognized instruction";
582 cgen_init_parse_operand ();
583 #ifdef CGEN_MNEMONIC_OPERANDS
587 /* We don't check for (*str != '\0') here because we want to parse
588 any trailing fake arguments in the syntax string. */
589 syn
= CGEN_SYNTAX_STRING (CGEN_INSN_SYNTAX (insn
));
591 /* Mnemonics come first for now, ensure valid string. */
592 if (! CGEN_SYNTAX_MNEMONIC_P (* syn
))
599 /* Non operand chars must match exactly. */
600 /* FIXME: Need to better handle whitespace. */
601 if (CGEN_SYNTAX_CHAR_P (* syn
))
603 if (*str
== CGEN_SYNTAX_CHAR (* syn
))
605 #ifdef CGEN_MNEMONIC_OPERANDS
614 /* Syntax char didn't match. Can't be this insn. */
615 /* FIXME: would like to return something like
616 "expected char `c'" */
617 return "syntax error";
622 /* We have an operand of some sort. */
623 errmsg
= m32r_cgen_parse_operand (CGEN_SYNTAX_FIELD (*syn
),
628 /* Done with this operand, continue with next one. */
632 /* If we're at the end of the syntax string, we're done. */
635 /* FIXME: For the moment we assume a valid `str' can only contain
636 blanks now. IE: We needn't try again with a longer version of
637 the insn and it is assumed that longer versions of insns appear
638 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
639 while (isspace (* str
))
643 return "junk at end of line"; /* FIXME: would like to include `str' */
648 /* We couldn't parse it. */
649 return "unrecognized instruction";
652 /* Default insn builder (insert handler).
653 The instruction is recorded in target byte order.
654 The result is an error message or NULL if success. */
655 /* FIXME: change buffer to char *? */
658 insert_insn_normal (insn
, fields
, buffer
)
659 const CGEN_INSN
* insn
;
660 CGEN_FIELDS
* fields
;
661 cgen_insn_t
* buffer
;
663 const CGEN_SYNTAX
* syntax
= CGEN_INSN_SYNTAX (insn
);
665 const unsigned char * syn
;
668 value
= CGEN_INSN_VALUE (insn
);
670 /* If we're recording insns as numbers (rather than a string of bytes),
671 target byte order handling is deferred until later. */
673 #define min(a,b) ((a) < (b) ? (a) : (b))
674 #if 0 /*def CGEN_INT_INSN*/
677 switch (min (CGEN_BASE_INSN_BITSIZE
, CGEN_FIELDS_BITSIZE (fields
)))
683 if (CGEN_CURRENT_ENDIAN
== CGEN_ENDIAN_BIG
)
684 bfd_putb16 (value
, (char *) buffer
);
686 bfd_putl16 (value
, (char *) buffer
);
689 if (CGEN_CURRENT_ENDIAN
== CGEN_ENDIAN_BIG
)
690 bfd_putb32 (value
, (char *) buffer
);
692 bfd_putl32 (value
, (char *) buffer
);
699 /* ??? Rather than scanning the syntax string again, we could store
700 in `fields' a null terminated list of the fields that are present. */
702 for (syn
= CGEN_SYNTAX_STRING (syntax
); * syn
!= '\0'; ++ syn
)
706 if (CGEN_SYNTAX_CHAR_P (* syn
))
709 errmsg
= m32r_cgen_insert_operand (CGEN_SYNTAX_FIELD (*syn
), fields
,
719 This routine is called for each instruction to be assembled.
720 STR points to the insn to be assembled.
721 We assume all necessary tables have been initialized.
722 The assembled instruction, less any fixups, is stored in buf.
723 [??? What byte order?]
724 The result is a pointer to the insn's entry in the opcode table,
725 or NULL if an error occured (an error message will have already been
728 Note that when processing (non-alias) macro-insns,
729 this function recurses. */
732 m32r_cgen_assemble_insn (str
, fields
, buf
, errmsg
)
734 CGEN_FIELDS
* fields
;
739 CGEN_INSN_LIST
* ilist
;
741 /* Skip leading white space. */
742 while (isspace (* str
))
745 /* The instructions are stored in hashed lists.
746 Get the first in the list. */
747 ilist
= CGEN_ASM_LOOKUP_INSN (str
);
749 /* Keep looking until we find a match. */
752 for ( ; ilist
!= NULL
; ilist
= CGEN_ASM_NEXT_INSN (ilist
))
754 const CGEN_INSN
*insn
= ilist
->insn
;
756 #if 0 /* not needed as unsupported opcodes shouldn't be in the hash lists */
757 /* Is this insn supported by the selected cpu? */
758 if (! m32r_cgen_insn_supported (insn
))
762 #if 1 /* FIXME: wip */
763 /* If the RELAX attribute is set, this is an insn that shouldn't be
764 chosen immediately. Instead, it is used during assembler/linker
765 relaxation if possible. */
766 if (CGEN_INSN_ATTR (insn
, CGEN_INSN_RELAX
) != 0)
772 /* Record a default length for the insn. This will get set to the
773 correct value while parsing. */
775 CGEN_FIELDS_BITSIZE (fields
) = CGEN_INSN_BITSIZE (insn
);
777 if (! CGEN_PARSE_FN (insn
) (insn
, & str
, fields
))
779 if (CGEN_INSERT_FN (insn
) (insn
, fields
, buf
) != NULL
)
781 /* It is up to the caller to actually output the insn and any
786 /* Try the next entry. */
789 /* FIXME: We can return a better error message than this.
790 Need to track why it failed and pick the right one. */
792 static char errbuf
[100];
793 sprintf (errbuf
, "bad instruction `%.50s%s'",
794 start
, strlen (start
) > 50 ? "..." : "");
800 #if 0 /* This calls back to GAS which we can't do without care. */
802 /* Record each member of OPVALS in the assembler's symbol table.
803 This lets GAS parse registers for us.
804 ??? Interesting idea but not currently used. */
806 /* Record each member of OPVALS in the assembler's symbol table.
807 FIXME: Not currently used. */
810 m32r_cgen_asm_hash_keywords (opvals
)
811 CGEN_KEYWORD
* opvals
;
813 CGEN_KEYWORD_SEARCH search
= cgen_keyword_search_init (opvals
, NULL
);
814 const CGEN_KEYWORD_ENTRY
* ke
;
816 while ((ke
= cgen_keyword_search_next (& search
)) != NULL
)
818 #if 0 /* Unnecessary, should be done in the search routine. */
819 if (! m32r_cgen_opval_supported (ke
))
822 cgen_asm_record_register (ke
->name
, ke
->value
);