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. */
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.
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
*));
42 /* Default insertion routine.
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.
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. */
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. */
56 static CGEN_INLINE
void
57 insert_normal (value
, attrs
, start
, length
, shift
, total_length
, buffer
)
60 int start
, length
, shift
, total_length
;
65 #if 0 /*def CGEN_INT_INSN*/
66 *buffer
|= ((value
& ((1 << length
) - 1))
67 << (total_length
- (start
+ length
)));
72 x
= *(unsigned char *) buffer
;
75 if (CGEN_CURRENT_ENDIAN
== CGEN_ENDIAN_BIG
)
76 x
= bfd_getb16 (buffer
);
78 x
= bfd_getl16 (buffer
);
81 if (CGEN_CURRENT_ENDIAN
== CGEN_ENDIAN_BIG
)
82 x
= bfd_getb32 (buffer
);
84 x
= bfd_getl32 (buffer
);
95 x
|= ((value
& ((1 << length
) - 1))
96 << (total_length
- (start
+ length
)));
104 if (CGEN_CURRENT_ENDIAN
== CGEN_ENDIAN_BIG
)
105 bfd_putb16 (x
, buffer
);
107 bfd_putl16 (x
, buffer
);
110 if (CGEN_CURRENT_ENDIAN
== CGEN_ENDIAN_BIG
)
111 bfd_putb32 (x
, buffer
);
113 bfd_putl32 (x
, buffer
);
121 /* -- assembler routines inserted here */
124 /* Handle shigh(), high(). */
127 parse_h_hi16 (strp
, opindex
, min
, max
, valuep
)
130 unsigned long min
, max
;
131 unsigned long *valuep
;
135 /* FIXME: Need # in assembler syntax (means '#' is optional). */
139 if (strncmp (*strp
, "high(", 5) == 0)
142 /* FIXME: If value was a number, right shift by 16. */
143 errmsg
= cgen_parse_address (strp
, opindex
, BFD_RELOC_M32R_HI16_ULO
, valuep
);
145 return "missing `)'";
149 else if (strncmp (*strp
, "shigh(", 6) == 0)
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
);
155 return "missing `)'";
160 return cgen_parse_unsigned_integer (strp
, opindex
, min
, max
, valuep
);
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. */
168 parse_h_slo16 (strp
, opindex
, min
, max
, valuep
)
176 /* FIXME: Need # in assembler syntax (means '#' is optional). */
180 if (strncmp (*strp
, "low(", 4) == 0)
183 errmsg
= cgen_parse_address (strp
, opindex
, BFD_RELOC_M32R_LO16
, valuep
);
185 return "missing `)'";
190 if (strncmp (*strp
, "sda(", 4) == 0)
193 errmsg
= cgen_parse_address (strp
, opindex
, BFD_RELOC_M32R_SDA16
, valuep
);
195 return "missing `)'";
200 return cgen_parse_signed_integer (strp
, opindex
, min
, max
, valuep
);
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. */
208 parse_h_ulo16 (strp
, opindex
, min
, max
, valuep
)
211 unsigned long min
, max
;
212 unsigned long *valuep
;
216 /* FIXME: Need # in assembler syntax (means '#' is optional). */
220 if (strncmp (*strp
, "low(", 4) == 0)
223 errmsg
= cgen_parse_address (strp
, opindex
, BFD_RELOC_M32R_LO16
, valuep
);
225 return "missing `)'";
230 return cgen_parse_unsigned_integer (strp
, opindex
, min
, max
, valuep
);
235 /* Main entry point for operand parsing.
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.
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
249 CGEN_INLINE
const char *
250 m32r_cgen_parse_operand (opindex
, strp
, fields
)
253 struct cgen_fields
*fields
;
260 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_gr
, &fields
->f_r2
);
263 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_gr
, &fields
->f_r1
);
266 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_gr
, &fields
->f_r1
);
269 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_gr
, &fields
->f_r2
);
272 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_cr
, &fields
->f_r2
);
275 errmsg
= cgen_parse_keyword (strp
, & m32r_cgen_opval_h_cr
, &fields
->f_r1
);
278 errmsg
= cgen_parse_signed_integer (strp
, 6, -128, 127, &fields
->f_simm8
);
281 errmsg
= cgen_parse_signed_integer (strp
, 7, -32768, 32767, &fields
->f_simm16
);
284 errmsg
= cgen_parse_unsigned_integer (strp
, 8, 0, 15, &fields
->f_uimm4
);
287 errmsg
= cgen_parse_unsigned_integer (strp
, 9, 0, 31, &fields
->f_uimm5
);
290 errmsg
= cgen_parse_unsigned_integer (strp
, 10, 0, 65535, &fields
->f_uimm16
);
293 errmsg
= parse_h_hi16 (strp
, 11, 0, 65535, &fields
->f_hi16
);
296 errmsg
= parse_h_slo16 (strp
, 12, -32768, 32767, &fields
->f_simm16
);
299 errmsg
= parse_h_ulo16 (strp
, 13, 0, 65535, &fields
->f_uimm16
);
302 errmsg
= cgen_parse_address (strp
, 14, 0, &fields
->f_uimm24
);
305 errmsg
= cgen_parse_address (strp
, 15, 0, &fields
->f_disp8
);
308 errmsg
= cgen_parse_address (strp
, 16, 0, &fields
->f_disp16
);
311 errmsg
= cgen_parse_address (strp
, 17, 0, &fields
->f_disp24
);
315 fprintf (stderr
, "Unrecognized field %d while parsing.\n", opindex
);
322 /* Main entry point for operand insertion.
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.
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.
338 m32r_cgen_insert_operand (opindex
, fields
, buffer
)
340 struct cgen_fields
*fields
;
346 insert_normal (fields
->f_r2
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
349 insert_normal (fields
->f_r1
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
352 insert_normal (fields
->f_r1
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
355 insert_normal (fields
->f_r2
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
358 insert_normal (fields
->f_r2
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
361 insert_normal (fields
->f_r1
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 4, 4, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
364 insert_normal (fields
->f_simm8
, 0, 8, 8, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
367 insert_normal (fields
->f_simm16
, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
370 insert_normal (fields
->f_uimm4
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 12, 4, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
373 insert_normal (fields
->f_uimm5
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 11, 5, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
376 insert_normal (fields
->f_uimm16
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
379 insert_normal (fields
->f_hi16
, 0|(1<<CGEN_OPERAND_SIGN_OPT
)|(1<<CGEN_OPERAND_UNSIGNED
), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
382 insert_normal (fields
->f_simm16
, 0, 16, 16, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
385 insert_normal (fields
->f_uimm16
, 0|(1<<CGEN_OPERAND_UNSIGNED
), 16, 16, 0, CGEN_FIELDS_BITSIZE (fields
), buffer
);
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
);
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
);
394 insert_normal (fields
->f_disp16
, 0|(1<<CGEN_OPERAND_RELOC
)|(1<<CGEN_OPERAND_PCREL_ADDR
), 16, 16, 2, CGEN_FIELDS_BITSIZE (fields
), buffer
);
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
);
401 fprintf (stderr
, "Unrecognized field %d while building insn.\n",
407 /* Main entry point for operand validation.
409 This function is called from GAS when it has fully resolved an operand
410 that couldn't be resolved during parsing.
412 The result is NULL for success or an error message (which may be
413 computed into a static buffer).
416 CGEN_INLINE
const char *
417 m32r_cgen_validate_operand (opindex
, fields
)
419 const struct cgen_fields
*fields
;
421 const char *errmsg
= NULL
;
444 errmsg
= cgen_validate_signed_integer (fields
->f_simm8
, -128, 127);
447 errmsg
= cgen_validate_signed_integer (fields
->f_simm16
, -32768, 32767);
450 errmsg
= cgen_validate_unsigned_integer (fields
->f_uimm4
, 0, 15);
453 errmsg
= cgen_validate_unsigned_integer (fields
->f_uimm5
, 0, 31);
456 errmsg
= cgen_validate_unsigned_integer (fields
->f_uimm16
, 0, 65535);
459 errmsg
= cgen_validate_unsigned_integer (fields
->f_hi16
, 0, 65535);
462 errmsg
= cgen_validate_signed_integer (fields
->f_simm16
, -32768, 32767);
465 errmsg
= cgen_validate_unsigned_integer (fields
->f_uimm16
, 0, 65535);
481 fprintf (stderr
, "Unrecognized field %d while validating operand.\n",
489 cgen_parse_fn
*m32r_cgen_parse_handlers
[] = {
494 cgen_insert_fn
*m32r_cgen_insert_handlers
[] = {
500 m32r_cgen_init_asm (mach
, endian
)
502 enum cgen_endian endian
;
504 m32r_cgen_init_tables (mach
);
505 cgen_set_cpu (& m32r_cgen_opcode_data
, mach
, endian
);
510 /* Default insn parser.
512 The syntax string is scanned and operands are parsed and stored in FIELDS.
513 Relocs are queued as we go via other callbacks.
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.
521 Returns NULL for success, an error message for failure.
525 parse_insn_normal (insn
, strp
, fields
)
526 const struct cgen_insn
*insn
;
528 struct cgen_fields
*fields
;
530 const struct cgen_syntax
*syntax
= CGEN_INSN_SYNTAX (insn
);
531 const char *str
= *strp
;
533 const unsigned char *syn
;
534 #ifdef CGEN_MNEMONIC_OPERANDS
538 /* If mnemonics are constant, they're not stored with the syntax string. */
539 #ifndef CGEN_MNEMONIC_OPERANDS
541 const char *p
= syntax
->mnemonic
;
543 while (*p
&& *p
== *str
)
545 if (*p
|| (*str
&& !isspace (*str
)))
546 return "unrecognized instruction";
548 while (isspace (*str
))
554 #ifdef CGEN_MNEMONIC_OPERANDS
558 /* We don't check for (*str != '\0') here because we want to parse
559 any trailing fake arguments in the syntax string. */
560 for (syn
= syntax
->syntax
; *syn
!= '\0'; )
562 /* Non operand chars must match exactly. */
563 /* FIXME: Need to better handle whitespace. */
564 if (CGEN_SYNTAX_CHAR_P (*syn
))
566 if (*str
== CGEN_SYNTAX_CHAR (*syn
))
568 #ifdef CGEN_MNEMONIC_OPERANDS
577 /* Syntax char didn't match. Can't be this insn. */
578 /* FIXME: would like to return "expected char `c'" */
579 return "syntax error";
584 /* We have an operand of some sort. */
585 errmsg
= m32r_cgen_parse_operand (CGEN_SYNTAX_FIELD (*syn
),
590 /* Done with this operand, continue with next one. */
594 /* If we're at the end of the syntax string, we're done. */
597 /* FIXME: For the moment we assume a valid `str' can only contain
598 blanks now. IE: We needn't try again with a longer version of
599 the insn and it is assumed that longer versions of insns appear
600 before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3). */
601 while (isspace (*str
))
605 return "junk at end of line"; /* FIXME: would like to include `str' */
610 /* We couldn't parse it. */
611 return "unrecognized instruction";
614 /* Default insn builder (insert handler).
615 The instruction is recorded in target byte order. */
618 insert_insn_normal (insn
, fields
, buffer
)
619 const struct cgen_insn
*insn
;
620 struct cgen_fields
*fields
;
623 const struct cgen_syntax
*syntax
= CGEN_INSN_SYNTAX (insn
);
625 const unsigned char *syn
;
628 value
= syntax
->value
;
630 /* If we're recording insns as numbers (rather than a string of bytes),
631 target byte order handling is deferred until later. */
633 #define min(a,b) ((a) < (b) ? (a) : (b))
634 #if 0 /*def CGEN_INT_INSN*/
637 switch (min (CGEN_BASE_INSN_BITSIZE
, CGEN_FIELDS_BITSIZE (fields
)))
643 if (CGEN_CURRENT_ENDIAN
== CGEN_ENDIAN_BIG
)
644 bfd_putb16 (value
, (char *) buffer
);
646 bfd_putl16 (value
, (char *) buffer
);
649 if (CGEN_CURRENT_ENDIAN
== CGEN_ENDIAN_BIG
)
650 bfd_putb32 (value
, (char *) buffer
);
652 bfd_putl32 (value
, (char *) buffer
);
659 /* ??? Rather than scanning the syntax string again, we could store
660 in `fields' a null terminated list of the fields that are present. */
662 for (syn
= syntax
->syntax
; *syn
!= '\0'; ++syn
)
664 if (CGEN_SYNTAX_CHAR_P (*syn
))
667 m32r_cgen_insert_operand (CGEN_SYNTAX_FIELD (*syn
), fields
, buffer
);
672 This routine is called for each instruction to be assembled.
673 STR points to the insn to be assembled.
674 We assume all necessary tables have been initialized.
675 The result is a pointer to the insn's entry in the opcode table,
676 or NULL if an error occured (an error message will have already been
679 const struct cgen_insn
*
680 m32r_cgen_assemble_insn (str
, fields
, buf
, errmsg
)
682 struct cgen_fields
*fields
;
687 CGEN_INSN_LIST
*ilist
;
689 /* Skip leading white space. */
690 while (isspace (*str
))
693 /* The instructions are stored in hashed lists.
694 Get the first in the list. */
695 ilist
= CGEN_ASM_LOOKUP_INSN (str
);
697 /* Keep looking until we find a match. */
700 for ( ; ilist
!= NULL
; ilist
= CGEN_ASM_NEXT_INSN (ilist
))
702 const struct cgen_insn
*insn
= ilist
->insn
;
704 #if 0 /* not needed as unsupported opcodes shouldn't be in the hash lists */
705 /* Is this insn supported by the selected cpu? */
706 if (! m32r_cgen_insn_supported (insn
))
710 #if 1 /* FIXME: wip */
711 /* If the RELAX attribute is set, this is an insn that shouldn't be
712 chosen immediately. Instead, it is used during assembler/linker
713 relaxation if possible. */
714 if (CGEN_INSN_ATTR (insn
, CGEN_INSN_RELAX
) != 0)
720 /* Record a default length for the insn. This will get set to the
721 correct value while parsing. */
723 CGEN_FIELDS_BITSIZE (fields
) = CGEN_INSN_BITSIZE (insn
);
725 /* ??? The extent to which moving the parse and insert handlers into
726 this function (thus removing the function call) will speed things up
727 is unclear. The simplicity and flexibility of the current scheme is
728 appropriate for now. One could have the best of both worlds with
729 inline functions but of course that would only work for gcc. Since
730 we're machine generating some code we could do that here too. Maybe
732 if (! (*CGEN_PARSE_FN (insn
)) (insn
, &str
, fields
))
734 (*CGEN_INSERT_FN (insn
)) (insn
, fields
, buf
);
735 /* It is up to the caller to actually output the insn and any
740 /* Try the next entry. */
743 /* FIXME: We can return a better error message than this.
744 Need to track why it failed and pick the right one. */
746 static char errbuf
[100];
747 sprintf (errbuf
, "bad instruction `%.50s%s'",
748 start
, strlen (start
) > 50 ? "..." : "");
754 #if 0 /* This calls back to GAS which we can't do without care. */
756 /* Record each member of OPVALS in the assembler's symbol table.
757 This lets GAS parse registers for us.
758 ??? Interesting idea but not currently used. */
761 m32r_cgen_asm_hash_keywords (opvals
)
762 struct cgen_keyword
*opvals
;
764 struct cgen_keyword_search search
= cgen_keyword_search_init (opvals
, NULL
);
765 const struct cgen_keyword_entry
*ke
;
767 while ((ke
= cgen_keyword_search_next (&search
)) != NULL
)
769 #if 0 /* Unnecessary, should be done in the search routine. */
770 if (! m32r_cgen_opval_supported (ke
))
773 cgen_asm_record_register (ke
->name
, ke
->value
);