diff options
author | Richard Henderson <rth@redhat.com> | 2001-08-12 20:16:29 +0000 |
---|---|---|
committer | Richard Henderson <rth@redhat.com> | 2001-08-12 20:16:29 +0000 |
commit | fc7bc88384beca1d62919c19120cc0e70c0d1e4e (patch) | |
tree | 2b4a692ea199f3df001384947d93ed529700d5c7 | |
parent | d8b6305a45989e1260db502c8fd13fba53d44c45 (diff) | |
download | binutils-fc7bc88384beca1d62919c19120cc0e70c0d1e4e.tar.gz binutils-fc7bc88384beca1d62919c19120cc0e70c0d1e4e.tar.bz2 binutils-fc7bc88384beca1d62919c19120cc0e70c0d1e4e.zip |
* cgen-ibld.in (extract_normal): Match type of VALUE and MASK
to *VALUEP. Regenerate all cgen files.
-rw-r--r-- | opcodes/ChangeLog | 5 | ||||
-rw-r--r-- | opcodes/cgen-ibld.in | 2 | ||||
-rw-r--r-- | opcodes/fr30-asm.c | 109 | ||||
-rw-r--r-- | opcodes/fr30-desc.c | 38 | ||||
-rw-r--r-- | opcodes/fr30-dis.c | 44 | ||||
-rw-r--r-- | opcodes/fr30-ibld.c | 33 | ||||
-rw-r--r-- | opcodes/fr30-opc.c | 6 | ||||
-rw-r--r-- | opcodes/m32r-asm.c | 107 | ||||
-rw-r--r-- | opcodes/m32r-desc.c | 32 | ||||
-rw-r--r-- | opcodes/m32r-dis.c | 21 | ||||
-rw-r--r-- | opcodes/m32r-ibld.c | 23 | ||||
-rw-r--r-- | opcodes/m32r-opc.c | 6 | ||||
-rw-r--r-- | opcodes/m32r-opinst.c | 128 | ||||
-rw-r--r-- | opcodes/openrisc-asm.c | 107 | ||||
-rw-r--r-- | opcodes/openrisc-desc.c | 28 | ||||
-rw-r--r-- | opcodes/openrisc-dis.c | 44 | ||||
-rw-r--r-- | opcodes/openrisc-ibld.c | 23 | ||||
-rw-r--r-- | opcodes/openrisc-opc.c | 6 |
18 files changed, 624 insertions, 138 deletions
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 2a12444fa6b..bd514648502 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,8 @@ +2001-08-12 Richard Henderson <rth@redhat.com> + + * cgen-ibld.in (extract_normal): Match type of VALUE and MASK + to *VALUEP. Regenerate all cgen files. + 2001-08-10 Richard Sandiford <rsandifo@redhat.com> * mips-dis.c (print_insn_mips): Remove OPCODE_IS_MEMBER's gp32 diff --git a/opcodes/cgen-ibld.in b/opcodes/cgen-ibld.in index 0ca4200aa2a..213b8882d95 100644 --- a/opcodes/cgen-ibld.in +++ b/opcodes/cgen-ibld.in @@ -415,7 +415,7 @@ extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length, #endif long *valuep; { - CGEN_INSN_INT value, mask; + long value, mask; /* If LENGTH is zero, this operand doesn't contribute to the value so give it a standard value of zero. */ diff --git a/opcodes/fr30-asm.c b/opcodes/fr30-asm.c index b2a95e3c5f3..9ad3f2c5be3 100644 --- a/opcodes/fr30-asm.c +++ b/opcodes/fr30-asm.c @@ -34,6 +34,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., #include "fr30-desc.h" #include "fr30-opc.h" #include "opintl.h" +#include "xregex.h" #undef min #define min(a,b) ((a) < (b) ? (a) : (b)) @@ -325,6 +326,104 @@ fr30_cgen_init_asm (cd) } + +/* + Regex construction routine. + + This translates an opcode syntax string into a regex string, + by replacing any non-character syntax element (such as an + opcode) with the pattern '.*' + + It then compiles the regex and stores it in the opcode, for + later use by fr30_cgen_assemble_insn + + returns NULL for success, an error message for failure +*/ + +char * +fr30_cgen_build_insn_regex (insn) + CGEN_INSN *insn; +{ + CGEN_OPCODE *opc = CGEN_INSN_OPCODE (insn); + const char *mnem = CGEN_INSN_MNEMONIC (insn); + int mnem_len; + char rxbuf[CGEN_MAX_RX_ELEMENTS]; + char *rx = rxbuf; + const CGEN_SYNTAX_CHAR_TYPE *syn; + int reg_err; + + syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc)); + + /* Mnemonics come first in the syntax string */ + if (! CGEN_SYNTAX_MNEMONIC_P (* syn)) return "missing mnemonic in syntax string"; + ++syn; + + /* copy the literal mnemonic out of the insn */ + memset (rx, 0, CGEN_MAX_RX_ELEMENTS); + mnem_len = strlen(mnem); + memcpy (rx, mnem, mnem_len); + rx += mnem_len; + + /* copy any remaining literals from the syntax string into the rx */ + for(; * syn != 0 && rx < rxbuf + (CGEN_MAX_RX_ELEMENTS - 9); ++syn, ++rx) + { + if (CGEN_SYNTAX_CHAR_P (* syn)) + { + char tmp = CGEN_SYNTAX_CHAR (* syn); + switch (tmp) + { + /* escape any regex metacharacters in the syntax */ + case '.': case '[': case '\\': + case '*': case '^': case '$': + +#ifdef CGEN_ESCAPE_EXTENDED_REGEX + case '?': case '{': case '}': + case '(': case ')': case '*': + case '|': case '+': case ']': +#endif + + * rx++ = '\\'; + break; + } + /* insert syntax char into rx */ + * rx = tmp; + } + else + { + /* replace non-syntax fields with globs */ + * rx = '.'; + * ++rx = '*'; + } + } + + /* trailing whitespace ok */ + * rx++ = '['; + * rx++ = ' '; + * rx++ = '\t'; + * rx++ = ']'; + * rx++ = '*'; + + /* but anchor it after that */ + * rx++ = '$'; + * rx = '\0'; + + CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t)); + reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB|REG_ICASE); + + if (reg_err == 0) + return NULL; + else + { + static char msg[80]; + regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80); + regfree ((regex_t *) CGEN_INSN_RX (insn)); + free (CGEN_INSN_RX (insn)); + (CGEN_INSN_RX (insn)) = NULL; + return msg; + } +} + + /* Default insn parser. The syntax string is scanned and operands are parsed and stored in FIELDS. @@ -491,6 +590,7 @@ fr30_cgen_assemble_insn (cd, str, fields, buf, errmsg) CGEN_INSN_LIST *ilist; const char *parse_errmsg = NULL; const char *insert_errmsg = NULL; + int recognized_mnemonic = 0; /* Skip leading white space. */ while (isspace (* str)) @@ -506,6 +606,7 @@ fr30_cgen_assemble_insn (cd, str, fields, buf, errmsg) for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist)) { const CGEN_INSN *insn = ilist->insn; + recognized_mnemonic = 1; #ifdef CGEN_VALIDATE_INSN_SUPPORTED /* not usually needed as unsupported opcodes shouldn't be in the hash lists */ @@ -522,6 +623,11 @@ fr30_cgen_assemble_insn (cd, str, fields, buf, errmsg) str = start; + /* skip this insn if str doesn't look right lexically */ + if (CGEN_INSN_RX (insn) != NULL && + regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH) + continue; + /* Allow parse/insert handlers to obtain length of insn. */ CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); @@ -542,13 +648,14 @@ fr30_cgen_assemble_insn (cd, str, fields, buf, errmsg) { static char errbuf[150]; +#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS const char *tmp_errmsg; -#ifdef CGEN_VERBOSE_ASSEMBLER_ERRORS /* If requesting verbose error messages, use insert_errmsg. Failing that, use parse_errmsg */ tmp_errmsg = (insert_errmsg ? insert_errmsg : parse_errmsg ? parse_errmsg : + recognized_mnemonic ? _("unrecognized form of instruction") : _("unrecognized instruction")); if (strlen (start) > 50) diff --git a/opcodes/fr30-desc.c b/opcodes/fr30-desc.c index 4223833f622..b2a205fae58 100644 --- a/opcodes/fr30-desc.c +++ b/opcodes/fr30-desc.c @@ -122,8 +122,8 @@ static const CGEN_ISA fr30_cgen_isa_table[] = { /* Machine variants. */ static const CGEN_MACH fr30_cgen_mach_table[] = { - { "fr30", "fr30", MACH_FR30 }, - { 0, 0, 0 } + { "fr30", "fr30", MACH_FR30, 0 }, + { 0, 0, 0, 0 } }; static CGEN_KEYWORD_ENTRY fr30_cgen_opval_gr_names_entries[] = @@ -153,7 +153,7 @@ CGEN_KEYWORD fr30_cgen_opval_gr_names = { & fr30_cgen_opval_gr_names_entries[0], 19, - 0, 0, 0, 0 + 0, 0, 0, 0, "" }; static CGEN_KEYWORD_ENTRY fr30_cgen_opval_cr_names_entries[] = @@ -180,7 +180,7 @@ CGEN_KEYWORD fr30_cgen_opval_cr_names = { & fr30_cgen_opval_cr_names_entries[0], 16, - 0, 0, 0, 0 + 0, 0, 0, 0, "" }; static CGEN_KEYWORD_ENTRY fr30_cgen_opval_dr_names_entries[] = @@ -197,7 +197,7 @@ CGEN_KEYWORD fr30_cgen_opval_dr_names = { & fr30_cgen_opval_dr_names_entries[0], 6, - 0, 0, 0, 0 + 0, 0, 0, 0, "" }; static CGEN_KEYWORD_ENTRY fr30_cgen_opval_h_ps_entries[] = @@ -209,7 +209,7 @@ CGEN_KEYWORD fr30_cgen_opval_h_ps = { & fr30_cgen_opval_h_ps_entries[0], 1, - 0, 0, 0, 0 + 0, 0, 0, 0, "" }; static CGEN_KEYWORD_ENTRY fr30_cgen_opval_h_r13_entries[] = @@ -221,7 +221,7 @@ CGEN_KEYWORD fr30_cgen_opval_h_r13 = { & fr30_cgen_opval_h_r13_entries[0], 1, - 0, 0, 0, 0 + 0, 0, 0, 0, "" }; static CGEN_KEYWORD_ENTRY fr30_cgen_opval_h_r14_entries[] = @@ -233,7 +233,7 @@ CGEN_KEYWORD fr30_cgen_opval_h_r14 = { & fr30_cgen_opval_h_r14_entries[0], 1, - 0, 0, 0, 0 + 0, 0, 0, 0, "" }; static CGEN_KEYWORD_ENTRY fr30_cgen_opval_h_r15_entries[] = @@ -245,7 +245,7 @@ CGEN_KEYWORD fr30_cgen_opval_h_r15 = { & fr30_cgen_opval_h_r15_entries[0], 1, - 0, 0, 0, 0 + 0, 0, 0, 0, "" }; @@ -1476,11 +1476,9 @@ static void fr30_cgen_rebuild_tables (cd) CGEN_CPU_TABLE *cd; { - int i,n_isas; + int i; unsigned int isas = cd->isas; -#if 0 unsigned int machs = cd->machs; -#endif cd->int_insn_p = CGEN_INT_INSN_P; @@ -1518,20 +1516,26 @@ fr30_cgen_rebuild_tables (cd) cd->min_insn_bitsize = isa->min_insn_bitsize; if (isa->max_insn_bitsize > cd->max_insn_bitsize) cd->max_insn_bitsize = isa->max_insn_bitsize; - - ++n_isas; } -#if 0 /* Does nothing?? */ /* Data derived from the mach spec. */ for (i = 0; i < MAX_MACHS; ++i) if (((1 << i) & machs) != 0) { const CGEN_MACH *mach = & fr30_cgen_mach_table[i]; - ++n_machs; + if (mach->insn_chunk_bitsize != 0) + { + if (cd->insn_chunk_bitsize != 0 && cd->insn_chunk_bitsize != mach->insn_chunk_bitsize) + { + fprintf (stderr, "fr30_cgen_rebuild_tables: conflicting insn-chunk-bitsize values: `%d' vs. `%d'\n", + cd->insn_chunk_bitsize, mach->insn_chunk_bitsize); + abort (); + } + + cd->insn_chunk_bitsize = mach->insn_chunk_bitsize; + } } -#endif /* Determine which hw elements are used by MACH. */ build_hw_table (cd); diff --git a/opcodes/fr30-dis.c b/opcodes/fr30-dis.c index f389dcc1edb..0e4aceb1888 100644 --- a/opcodes/fr30-dis.c +++ b/opcodes/fr30-dis.c @@ -495,13 +495,19 @@ print_insn (cd, pc, info, buf, buflen) char *buf; int buflen; { - unsigned long insn_value; + CGEN_INSN_INT insn_value; const CGEN_INSN_LIST *insn_list; CGEN_EXTRACT_INFO ex_info; - int rc = read_insn (cd, pc, info, buf, buflen, & ex_info, & insn_value); - if (rc != 0) - return rc; + /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */ + insn_value = cgen_get_insn_value (cd, buf, buflen * 8); + + /* Fill in ex_info fields like read_insn would. Don't actually call + read_insn, since the incoming buffer is already read (and possibly + modified a la m32r). */ + ex_info.valid = (1 << buflen) - 1; + ex_info.dis_info = info; + ex_info.insn_bytes = buf; /* The instructions are stored in hash lists. Pick the first one and keep trying until we find the right one. */ @@ -512,6 +518,7 @@ print_insn (cd, pc, info, buf, buflen) const CGEN_INSN *insn = insn_list->insn; CGEN_FIELDS fields; int length; + unsigned long insn_value_cropped; #ifdef CGEN_VALIDATE_INSN_SUPPORTED /* not needed as insn shouldn't be in hash lists if not supported */ @@ -526,7 +533,17 @@ print_insn (cd, pc, info, buf, buflen) /* Basic bit mask must be correct. */ /* ??? May wish to allow target to defer this check until the extract handler. */ - if ((insn_value & CGEN_INSN_BASE_MASK (insn)) + + /* Base size may exceed this instruction's size. Extract the + relevant part from the buffer. */ + if ((CGEN_INSN_BITSIZE (insn) / 8) < buflen && + (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long)) + insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn), + info->endian == BFD_ENDIAN_BIG); + else + insn_value_cropped = insn_value; + + if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn)) == CGEN_INSN_BASE_VALUE (insn)) { /* Printing is handled in two passes. The first pass parses the @@ -549,7 +566,7 @@ print_insn (cd, pc, info, buf, buflen) } else length = CGEN_EXTRACT_FN (cd, insn) - (cd, insn, &ex_info, insn_value, &fields, pc); + (cd, insn, &ex_info, insn_value_cropped, &fields, pc); /* length < 0 -> error */ if (length < 0) @@ -583,18 +600,27 @@ default_print_insn (cd, pc, info) disassemble_info *info; { char buf[CGEN_MAX_INSN_SIZE]; + int buflen; int status; - /* Read the base part of the insn. */ + /* Attempt to read the base part of the insn. */ + buflen = cd->base_insn_bitsize / 8; + status = (*info->read_memory_func) (pc, buf, buflen, info); + + /* Try again with the minimum part, if min < base. */ + if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize)) + { + buflen = cd->min_insn_bitsize / 8; + status = (*info->read_memory_func) (pc, buf, buflen, info); + } - status = (*info->read_memory_func) (pc, buf, cd->base_insn_bitsize / 8, info); if (status != 0) { (*info->memory_error_func) (status, pc, info); return -1; } - return print_insn (cd, pc, info, buf, cd->base_insn_bitsize / 8); + return print_insn (cd, pc, info, buf, buflen); } /* Main entry point. diff --git a/opcodes/fr30-ibld.c b/opcodes/fr30-ibld.c index 6bfca21ecd1..90ad6ef7882 100644 --- a/opcodes/fr30-ibld.c +++ b/opcodes/fr30-ibld.c @@ -145,7 +145,22 @@ insert_normal (cd, value, attrs, word_offset, start, length, word_length, } /* Ensure VALUE will fit. */ - if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)) + if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT)) + { + long minval = - (1L << (length - 1)); + unsigned long maxval = mask; + + if ((value > 0 && (unsigned long) value > maxval) + || value < minval) + { + /* xgettext:c-format */ + sprintf (errbuf, + _("operand out of range (%ld not between %ld and %lu)"), + value, minval, maxval); + return errbuf; + } + } + else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)) { unsigned long maxval = mask; @@ -202,10 +217,10 @@ insert_normal (cd, value, attrs, word_offset, start, length, word_length, } /* Default insn builder (insert handler). - The instruction is recorded in CGEN_INT_INSN_P byte order - (meaning that if CGEN_INT_INSN_P BUFFER is an int * and thus the value is - recorded in host byte order, otherwise BUFFER is an array of bytes and the - value is recorded in target byte order). + The instruction is recorded in CGEN_INT_INSN_P byte order (meaning + that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is + recorded in host byte order, otherwise BUFFER is an array of bytes + and the value is recorded in target byte order). The result is an error message or NULL if success. */ static const char * @@ -265,7 +280,7 @@ insert_insn_normal (cd, insn, fields, buffer, pc) static void put_insn_int_value (cd, buf, length, insn_length, value) - CGEN_CPU_DESC cd; + CGEN_CPU_DESC cd ATTRIBUTE_UNUSED; CGEN_INSN_BYTES_PTR buf; int length; int insn_length; @@ -400,7 +415,7 @@ extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length, #endif long *valuep; { - CGEN_INSN_INT value, mask; + long value, mask; /* If LENGTH is zero, this operand doesn't contribute to the value so give it a standard value of zero. */ @@ -428,9 +443,9 @@ extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length, word_length = total_length; } - /* Does the value reside in INSN_VALUE? */ + /* Does the value reside in INSN_VALUE, and at the right alignment? */ - if (CGEN_INT_INSN_P || word_offset == 0) + if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length)) { if (CGEN_INSN_LSB0_P) value = insn_value >> ((word_offset + start + 1) - length); diff --git a/opcodes/fr30-opc.c b/opcodes/fr30-opc.c index 4d0ab6a767c..877f26b9067 100644 --- a/opcodes/fr30-opc.c +++ b/opcodes/fr30-opc.c @@ -1368,6 +1368,7 @@ fr30_cgen_init_opcode_table (cd) { insns[i].base = &ib[i]; insns[i].opcode = &oc[i]; + fr30_cgen_build_insn_regex (& insns[i]); } cd->macro_insn_table.init_entries = insns; cd->macro_insn_table.entry_size = sizeof (CGEN_IBASE); @@ -1376,7 +1377,10 @@ fr30_cgen_init_opcode_table (cd) oc = & fr30_cgen_insn_opcode_table[0]; insns = (CGEN_INSN *) cd->insn_table.init_entries; for (i = 0; i < MAX_INSNS; ++i) - insns[i].opcode = &oc[i]; + { + insns[i].opcode = &oc[i]; + fr30_cgen_build_insn_regex (& insns[i]); + } cd->sizeof_fields = sizeof (CGEN_FIELDS); cd->set_fields_bitsize = set_fields_bitsize; diff --git a/opcodes/m32r-asm.c b/opcodes/m32r-asm.c index 4d18d6451ef..0e69a80c5e9 100644 --- a/opcodes/m32r-asm.c +++ b/opcodes/m32r-asm.c @@ -34,6 +34,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., #include "m32r-desc.h" #include "m32r-opc.h" #include "opintl.h" +#include "xregex.h" #undef min #define min(a,b) ((a) < (b) ? (a) : (b)) @@ -333,6 +334,104 @@ m32r_cgen_init_asm (cd) } + +/* + Regex construction routine. + + This translates an opcode syntax string into a regex string, + by replacing any non-character syntax element (such as an + opcode) with the pattern '.*' + + It then compiles the regex and stores it in the opcode, for + later use by m32r_cgen_assemble_insn + + returns NULL for success, an error message for failure +*/ + +char * +m32r_cgen_build_insn_regex (insn) + CGEN_INSN *insn; +{ + CGEN_OPCODE *opc = CGEN_INSN_OPCODE (insn); + const char *mnem = CGEN_INSN_MNEMONIC (insn); + int mnem_len; + char rxbuf[CGEN_MAX_RX_ELEMENTS]; + char *rx = rxbuf; + const CGEN_SYNTAX_CHAR_TYPE *syn; + int reg_err; + + syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc)); + + /* Mnemonics come first in the syntax string */ + if (! CGEN_SYNTAX_MNEMONIC_P (* syn)) return "missing mnemonic in syntax string"; + ++syn; + + /* copy the literal mnemonic out of the insn */ + memset (rx, 0, CGEN_MAX_RX_ELEMENTS); + mnem_len = strlen(mnem); + memcpy (rx, mnem, mnem_len); + rx += mnem_len; + + /* copy any remaining literals from the syntax string into the rx */ + for(; * syn != 0 && rx < rxbuf + (CGEN_MAX_RX_ELEMENTS - 9); ++syn, ++rx) + { + if (CGEN_SYNTAX_CHAR_P (* syn)) + { + char tmp = CGEN_SYNTAX_CHAR (* syn); + switch (tmp) + { + /* escape any regex metacharacters in the syntax */ + case '.': case '[': case '\\': + case '*': case '^': case '$': + +#ifdef CGEN_ESCAPE_EXTENDED_REGEX + case '?': case '{': case '}': + case '(': case ')': case '*': + case '|': case '+': case ']': +#endif + + * rx++ = '\\'; + break; + } + /* insert syntax char into rx */ + * rx = tmp; + } + else + { + /* replace non-syntax fields with globs */ + * rx = '.'; + * ++rx = '*'; + } + } + + /* trailing whitespace ok */ + * rx++ = '['; + * rx++ = ' '; + * rx++ = '\t'; + * rx++ = ']'; + * rx++ = '*'; + + /* but anchor it after that */ + * rx++ = '$'; + * rx = '\0'; + + CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t)); + reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB|REG_ICASE); + + if (reg_err == 0) + return NULL; + else + { + static char msg[80]; + regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80); + regfree ((regex_t *) CGEN_INSN_RX (insn)); + free (CGEN_INSN_RX (insn)); + (CGEN_INSN_RX (insn)) = NULL; + return msg; + } +} + + /* Default insn parser. The syntax string is scanned and operands are parsed and stored in FIELDS. @@ -499,6 +598,7 @@ m32r_cgen_assemble_insn (cd, str, fields, buf, errmsg) CGEN_INSN_LIST *ilist; const char *parse_errmsg = NULL; const char *insert_errmsg = NULL; + int recognized_mnemonic = 0; /* Skip leading white space. */ while (isspace (* str)) @@ -514,6 +614,7 @@ m32r_cgen_assemble_insn (cd, str, fields, buf, errmsg) for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist)) { const CGEN_INSN *insn = ilist->insn; + recognized_mnemonic = 1; #ifdef CGEN_VALIDATE_INSN_SUPPORTED /* not usually needed as unsupported opcodes shouldn't be in the hash lists */ @@ -530,6 +631,11 @@ m32r_cgen_assemble_insn (cd, str, fields, buf, errmsg) str = start; + /* skip this insn if str doesn't look right lexically */ + if (CGEN_INSN_RX (insn) != NULL && + regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH) + continue; + /* Allow parse/insert handlers to obtain length of insn. */ CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); @@ -557,6 +663,7 @@ m32r_cgen_assemble_insn (cd, str, fields, buf, errmsg) Failing that, use parse_errmsg */ tmp_errmsg = (insert_errmsg ? insert_errmsg : parse_errmsg ? parse_errmsg : + recognized_mnemonic ? _("unrecognized form of instruction") : _("unrecognized instruction")); if (strlen (start) > 50) diff --git a/opcodes/m32r-desc.c b/opcodes/m32r-desc.c index 8bcd7904798..d07c6574717 100644 --- a/opcodes/m32r-desc.c +++ b/opcodes/m32r-desc.c @@ -136,9 +136,9 @@ static const CGEN_ISA m32r_cgen_isa_table[] = { /* Machine variants. */ static const CGEN_MACH m32r_cgen_mach_table[] = { - { "m32r", "m32r", MACH_M32R }, - { "m32rx", "m32rx", MACH_M32RX }, - { 0, 0, 0 } + { "m32r", "m32r", MACH_M32R, 0 }, + { "m32rx", "m32rx", MACH_M32RX, 0 }, + { 0, 0, 0, 0 } }; static CGEN_KEYWORD_ENTRY m32r_cgen_opval_gr_names_entries[] = @@ -168,7 +168,7 @@ CGEN_KEYWORD m32r_cgen_opval_gr_names = { & m32r_cgen_opval_gr_names_entries[0], 19, - 0, 0, 0, 0 + 0, 0, 0, 0, "" }; static CGEN_KEYWORD_ENTRY m32r_cgen_opval_cr_names_entries[] = @@ -202,7 +202,7 @@ CGEN_KEYWORD m32r_cgen_opval_cr_names = { & m32r_cgen_opval_cr_names_entries[0], 23, - 0, 0, 0, 0 + 0, 0, 0, 0, "" }; static CGEN_KEYWORD_ENTRY m32r_cgen_opval_h_accums_entries[] = @@ -215,7 +215,7 @@ CGEN_KEYWORD m32r_cgen_opval_h_accums = { & m32r_cgen_opval_h_accums_entries[0], 2, - 0, 0, 0, 0 + 0, 0, 0, 0, "" }; @@ -1200,11 +1200,9 @@ static void m32r_cgen_rebuild_tables (cd) CGEN_CPU_TABLE *cd; { - int i,n_isas; + int i; unsigned int isas = cd->isas; -#if 0 unsigned int machs = cd->machs; -#endif cd->int_insn_p = CGEN_INT_INSN_P; @@ -1242,20 +1240,26 @@ m32r_cgen_rebuild_tables (cd) cd->min_insn_bitsize = isa->min_insn_bitsize; if (isa->max_insn_bitsize > cd->max_insn_bitsize) cd->max_insn_bitsize = isa->max_insn_bitsize; - - ++n_isas; } -#if 0 /* Does nothing?? */ /* Data derived from the mach spec. */ for (i = 0; i < MAX_MACHS; ++i) if (((1 << i) & machs) != 0) { const CGEN_MACH *mach = & m32r_cgen_mach_table[i]; - ++n_machs; + if (mach->insn_chunk_bitsize != 0) + { + if (cd->insn_chunk_bitsize != 0 && cd->insn_chunk_bitsize != mach->insn_chunk_bitsize) + { + fprintf (stderr, "m32r_cgen_rebuild_tables: conflicting insn-chunk-bitsize values: `%d' vs. `%d'\n", + cd->insn_chunk_bitsize, mach->insn_chunk_bitsize); + abort (); + } + + cd->insn_chunk_bitsize = mach->insn_chunk_bitsize; + } } -#endif /* Determine which hw elements are used by MACH. */ build_hw_table (cd); diff --git a/opcodes/m32r-dis.c b/opcodes/m32r-dis.c index 477a85b9dae..687eb51c4cd 100644 --- a/opcodes/m32r-dis.c +++ b/opcodes/m32r-dis.c @@ -434,12 +434,12 @@ print_insn (cd, pc, info, buf, buflen) char *buf; int buflen; { - unsigned long insn_value; + CGEN_INSN_INT insn_value; const CGEN_INSN_LIST *insn_list; CGEN_EXTRACT_INFO ex_info; /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */ - insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG); + insn_value = cgen_get_insn_value (cd, buf, buflen * 8); /* Fill in ex_info fields like read_insn would. Don't actually call read_insn, since the incoming buffer is already read (and possibly @@ -505,7 +505,7 @@ print_insn (cd, pc, info, buf, buflen) } else length = CGEN_EXTRACT_FN (cd, insn) - (cd, insn, &ex_info, insn_value, &fields, pc); + (cd, insn, &ex_info, insn_value_cropped, &fields, pc); /* length < 0 -> error */ if (length < 0) @@ -539,18 +539,27 @@ default_print_insn (cd, pc, info) disassemble_info *info; { char buf[CGEN_MAX_INSN_SIZE]; + int buflen; int status; - /* Read the base part of the insn. */ + /* Attempt to read the base part of the insn. */ + buflen = cd->base_insn_bitsize / 8; + status = (*info->read_memory_func) (pc, buf, buflen, info); + + /* Try again with the minimum part, if min < base. */ + if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize)) + { + buflen = cd->min_insn_bitsize / 8; + status = (*info->read_memory_func) (pc, buf, buflen, info); + } - status = (*info->read_memory_func) (pc, buf, cd->base_insn_bitsize / 8, info); if (status != 0) { (*info->memory_error_func) (status, pc, info); return -1; } - return print_insn (cd, pc, info, buf, cd->base_insn_bitsize / 8); + return print_insn (cd, pc, info, buf, buflen); } /* Main entry point. diff --git a/opcodes/m32r-ibld.c b/opcodes/m32r-ibld.c index f999bcd8d7d..447f0140c3a 100644 --- a/opcodes/m32r-ibld.c +++ b/opcodes/m32r-ibld.c @@ -145,7 +145,22 @@ insert_normal (cd, value, attrs, word_offset, start, length, word_length, } /* Ensure VALUE will fit. */ - if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)) + if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT)) + { + long minval = - (1L << (length - 1)); + unsigned long maxval = mask; + + if ((value > 0 && (unsigned long) value > maxval) + || value < minval) + { + /* xgettext:c-format */ + sprintf (errbuf, + _("operand out of range (%ld not between %ld and %lu)"), + value, minval, maxval); + return errbuf; + } + } + else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)) { unsigned long maxval = mask; @@ -400,7 +415,7 @@ extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length, #endif long *valuep; { - CGEN_INSN_INT value, mask; + long value, mask; /* If LENGTH is zero, this operand doesn't contribute to the value so give it a standard value of zero. */ @@ -428,9 +443,9 @@ extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length, word_length = total_length; } - /* Does the value reside in INSN_VALUE? */ + /* Does the value reside in INSN_VALUE, and at the right alignment? */ - if (CGEN_INT_INSN_P || word_offset == 0) + if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length)) { if (CGEN_INSN_LSB0_P) value = insn_value >> ((word_offset + start + 1) - length); diff --git a/opcodes/m32r-opc.c b/opcodes/m32r-opc.c index 3c579a471e0..12491d78201 100644 --- a/opcodes/m32r-opc.c +++ b/opcodes/m32r-opc.c @@ -1685,6 +1685,7 @@ m32r_cgen_init_opcode_table (cd) { insns[i].base = &ib[i]; insns[i].opcode = &oc[i]; + m32r_cgen_build_insn_regex (& insns[i]); } cd->macro_insn_table.init_entries = insns; cd->macro_insn_table.entry_size = sizeof (CGEN_IBASE); @@ -1693,7 +1694,10 @@ m32r_cgen_init_opcode_table (cd) oc = & m32r_cgen_insn_opcode_table[0]; insns = (CGEN_INSN *) cd->insn_table.init_entries; for (i = 0; i < MAX_INSNS; ++i) - insns[i].opcode = &oc[i]; + { + insns[i].opcode = &oc[i]; + m32r_cgen_build_insn_regex (& insns[i]); + } cd->sizeof_fields = sizeof (CGEN_FIELDS); cd->set_fields_bitsize = set_fields_bitsize; diff --git a/opcodes/m32r-opinst.c b/opcodes/m32r-opinst.c index 55e7e4fed44..aaaa1c0749a 100644 --- a/opcodes/m32r-opinst.c +++ b/opcodes/m32r-opinst.c @@ -137,7 +137,7 @@ static const CGEN_OPINST sfmt_beqz_ops[] = { static const CGEN_OPINST sfmt_bl8_ops[] = { { INPUT, "disp8", HW_H_IADDR, CGEN_MODE_USI, OP_ENT (DISP8), 0, 0 }, { INPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, 0 }, - { OUTPUT, "h_gr_14", HW_H_GR, CGEN_MODE_SI, 0, 14, 0 }, + { OUTPUT, "h_gr_SI_14", HW_H_GR, CGEN_MODE_SI, 0, 14, 0 }, { OUTPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, 0 }, { END } }; @@ -145,7 +145,7 @@ static const CGEN_OPINST sfmt_bl8_ops[] = { static const CGEN_OPINST sfmt_bl24_ops[] = { { INPUT, "disp24", HW_H_IADDR, CGEN_MODE_USI, OP_ENT (DISP24), 0, 0 }, { INPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, 0 }, - { OUTPUT, "h_gr_14", HW_H_GR, CGEN_MODE_SI, 0, 14, 0 }, + { OUTPUT, "h_gr_SI_14", HW_H_GR, CGEN_MODE_SI, 0, 14, 0 }, { OUTPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, 0 }, { END } }; @@ -154,7 +154,7 @@ static const CGEN_OPINST sfmt_bcl8_ops[] = { { INPUT, "condbit", HW_H_COND, CGEN_MODE_BI, 0, 0, 0 }, { INPUT, "disp8", HW_H_IADDR, CGEN_MODE_USI, OP_ENT (DISP8), 0, COND_REF }, { INPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, COND_REF }, - { OUTPUT, "h_gr_14", HW_H_GR, CGEN_MODE_SI, 0, 14, COND_REF }, + { OUTPUT, "h_gr_SI_14", HW_H_GR, CGEN_MODE_SI, 0, 14, COND_REF }, { OUTPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, COND_REF }, { END } }; @@ -163,7 +163,7 @@ static const CGEN_OPINST sfmt_bcl24_ops[] = { { INPUT, "condbit", HW_H_COND, CGEN_MODE_BI, 0, 0, 0 }, { INPUT, "disp24", HW_H_IADDR, CGEN_MODE_USI, OP_ENT (DISP24), 0, COND_REF }, { INPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, COND_REF }, - { OUTPUT, "h_gr_14", HW_H_GR, CGEN_MODE_SI, 0, 14, COND_REF }, + { OUTPUT, "h_gr_SI_14", HW_H_GR, CGEN_MODE_SI, 0, 14, COND_REF }, { OUTPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, COND_REF }, { END } }; @@ -217,7 +217,7 @@ static const CGEN_OPINST sfmt_jc_ops[] = { static const CGEN_OPINST sfmt_jl_ops[] = { { INPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, 0 }, { INPUT, "sr", HW_H_GR, CGEN_MODE_SI, OP_ENT (SR), 0, 0 }, - { OUTPUT, "h_gr_14", HW_H_GR, CGEN_MODE_SI, 0, 14, 0 }, + { OUTPUT, "h_gr_SI_14", HW_H_GR, CGEN_MODE_SI, 0, 14, 0 }, { OUTPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, 0 }, { END } }; @@ -229,14 +229,44 @@ static const CGEN_OPINST sfmt_jmp_ops[] = { }; static const CGEN_OPINST sfmt_ld_ops[] = { - { INPUT, "h_memory_sr", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 }, + { INPUT, "h_memory_SI_sr", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 }, { INPUT, "sr", HW_H_GR, CGEN_MODE_USI, OP_ENT (SR), 0, 0 }, { OUTPUT, "dr", HW_H_GR, CGEN_MODE_SI, OP_ENT (DR), 0, 0 }, { END } }; static const CGEN_OPINST sfmt_ld_d_ops[] = { - { INPUT, "h_memory_add__DFLT_sr_slo16", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 }, + { INPUT, "h_memory_SI_add__DFLT_sr_slo16", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 }, + { INPUT, "slo16", HW_H_SLO16, CGEN_MODE_INT, OP_ENT (SLO16), 0, 0 }, + { INPUT, "sr", HW_H_GR, CGEN_MODE_SI, OP_ENT (SR), 0, 0 }, + { OUTPUT, "dr", HW_H_GR, CGEN_MODE_SI, OP_ENT (DR), 0, 0 }, + { END } +}; + +static const CGEN_OPINST sfmt_ldb_ops[] = { + { INPUT, "h_memory_QI_sr", HW_H_MEMORY, CGEN_MODE_QI, 0, 0, 0 }, + { INPUT, "sr", HW_H_GR, CGEN_MODE_USI, OP_ENT (SR), 0, 0 }, + { OUTPUT, "dr", HW_H_GR, CGEN_MODE_SI, OP_ENT (DR), 0, 0 }, + { END } +}; + +static const CGEN_OPINST sfmt_ldb_d_ops[] = { + { INPUT, "h_memory_QI_add__DFLT_sr_slo16", HW_H_MEMORY, CGEN_MODE_QI, 0, 0, 0 }, + { INPUT, "slo16", HW_H_SLO16, CGEN_MODE_INT, OP_ENT (SLO16), 0, 0 }, + { INPUT, "sr", HW_H_GR, CGEN_MODE_SI, OP_ENT (SR), 0, 0 }, + { OUTPUT, "dr", HW_H_GR, CGEN_MODE_SI, OP_ENT (DR), 0, 0 }, + { END } +}; + +static const CGEN_OPINST sfmt_ldh_ops[] = { + { INPUT, "h_memory_HI_sr", HW_H_MEMORY, CGEN_MODE_HI, 0, 0, 0 }, + { INPUT, "sr", HW_H_GR, CGEN_MODE_USI, OP_ENT (SR), 0, 0 }, + { OUTPUT, "dr", HW_H_GR, CGEN_MODE_SI, OP_ENT (DR), 0, 0 }, + { END } +}; + +static const CGEN_OPINST sfmt_ldh_d_ops[] = { + { INPUT, "h_memory_HI_add__DFLT_sr_slo16", HW_H_MEMORY, CGEN_MODE_HI, 0, 0, 0 }, { INPUT, "slo16", HW_H_SLO16, CGEN_MODE_INT, OP_ENT (SLO16), 0, 0 }, { INPUT, "sr", HW_H_GR, CGEN_MODE_SI, OP_ENT (SR), 0, 0 }, { OUTPUT, "dr", HW_H_GR, CGEN_MODE_SI, OP_ENT (DR), 0, 0 }, @@ -244,7 +274,7 @@ static const CGEN_OPINST sfmt_ld_d_ops[] = { }; static const CGEN_OPINST sfmt_ld_plus_ops[] = { - { INPUT, "h_memory_sr", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 }, + { INPUT, "h_memory_SI_sr", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 }, { INPUT, "sr", HW_H_GR, CGEN_MODE_USI, OP_ENT (SR), 0, 0 }, { OUTPUT, "dr", HW_H_GR, CGEN_MODE_SI, OP_ENT (DR), 0, 0 }, { OUTPUT, "sr", HW_H_GR, CGEN_MODE_SI, OP_ENT (SR), 0, 0 }, @@ -270,10 +300,10 @@ static const CGEN_OPINST sfmt_ldi16_ops[] = { }; static const CGEN_OPINST sfmt_lock_ops[] = { - { INPUT, "h_memory_sr", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 }, + { INPUT, "h_memory_SI_sr", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 }, { INPUT, "sr", HW_H_GR, CGEN_MODE_USI, OP_ENT (SR), 0, 0 }, { OUTPUT, "dr", HW_H_GR, CGEN_MODE_SI, OP_ENT (DR), 0, 0 }, - { OUTPUT, "h_lock", HW_H_LOCK, CGEN_MODE_BI, 0, 0, 0 }, + { OUTPUT, "h_lock_BI", HW_H_LOCK, CGEN_MODE_BI, 0, 0, 0 }, { END } }; @@ -369,13 +399,13 @@ static const CGEN_OPINST sfmt_rac_dsi_ops[] = { }; static const CGEN_OPINST sfmt_rte_ops[] = { - { INPUT, "h_bbpsw", HW_H_BBPSW, CGEN_MODE_UQI, 0, 0, 0 }, - { INPUT, "h_bpsw", HW_H_BPSW, CGEN_MODE_UQI, 0, 0, 0 }, - { INPUT, "h_cr_14", HW_H_CR, CGEN_MODE_USI, 0, 14, 0 }, - { INPUT, "h_cr_6", HW_H_CR, CGEN_MODE_USI, 0, 6, 0 }, - { OUTPUT, "h_bpsw", HW_H_BPSW, CGEN_MODE_UQI, 0, 0, 0 }, - { OUTPUT, "h_cr_6", HW_H_CR, CGEN_MODE_USI, 0, 6, 0 }, - { OUTPUT, "h_psw", HW_H_PSW, CGEN_MODE_UQI, 0, 0, 0 }, + { INPUT, "h_bbpsw_UQI", HW_H_BBPSW, CGEN_MODE_UQI, 0, 0, 0 }, + { INPUT, "h_bpsw_UQI", HW_H_BPSW, CGEN_MODE_UQI, 0, 0, 0 }, + { INPUT, "h_cr_USI_14", HW_H_CR, CGEN_MODE_USI, 0, 14, 0 }, + { INPUT, "h_cr_USI_6", HW_H_CR, CGEN_MODE_USI, 0, 6, 0 }, + { OUTPUT, "h_bpsw_UQI", HW_H_BPSW, CGEN_MODE_UQI, 0, 0, 0 }, + { OUTPUT, "h_cr_USI_6", HW_H_CR, CGEN_MODE_USI, 0, 6, 0 }, + { OUTPUT, "h_psw_UQI", HW_H_PSW, CGEN_MODE_UQI, 0, 0, 0 }, { OUTPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, 0 }, { END } }; @@ -403,7 +433,7 @@ static const CGEN_OPINST sfmt_slli_ops[] = { static const CGEN_OPINST sfmt_st_ops[] = { { INPUT, "src1", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC1), 0, 0 }, { INPUT, "src2", HW_H_GR, CGEN_MODE_USI, OP_ENT (SRC2), 0, 0 }, - { OUTPUT, "h_memory_src2", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 }, + { OUTPUT, "h_memory_SI_src2", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 }, { END } }; @@ -411,14 +441,14 @@ static const CGEN_OPINST sfmt_st_d_ops[] = { { INPUT, "slo16", HW_H_SLO16, CGEN_MODE_INT, OP_ENT (SLO16), 0, 0 }, { INPUT, "src1", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC1), 0, 0 }, { INPUT, "src2", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC2), 0, 0 }, - { OUTPUT, "h_memory_add__DFLT_src2_slo16", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 }, + { OUTPUT, "h_memory_SI_add__DFLT_src2_slo16", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 }, { END } }; static const CGEN_OPINST sfmt_stb_ops[] = { { INPUT, "src1", HW_H_GR, CGEN_MODE_QI, OP_ENT (SRC1), 0, 0 }, { INPUT, "src2", HW_H_GR, CGEN_MODE_USI, OP_ENT (SRC2), 0, 0 }, - { OUTPUT, "h_memory_src2", HW_H_MEMORY, CGEN_MODE_QI, 0, 0, 0 }, + { OUTPUT, "h_memory_QI_src2", HW_H_MEMORY, CGEN_MODE_QI, 0, 0, 0 }, { END } }; @@ -426,14 +456,14 @@ static const CGEN_OPINST sfmt_stb_d_ops[] = { { INPUT, "slo16", HW_H_SLO16, CGEN_MODE_INT, OP_ENT (SLO16), 0, 0 }, { INPUT, "src1", HW_H_GR, CGEN_MODE_QI, OP_ENT (SRC1), 0, 0 }, { INPUT, "src2", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC2), 0, 0 }, - { OUTPUT, "h_memory_add__DFLT_src2_slo16", HW_H_MEMORY, CGEN_MODE_QI, 0, 0, 0 }, + { OUTPUT, "h_memory_QI_add__DFLT_src2_slo16", HW_H_MEMORY, CGEN_MODE_QI, 0, 0, 0 }, { END } }; static const CGEN_OPINST sfmt_sth_ops[] = { { INPUT, "src1", HW_H_GR, CGEN_MODE_HI, OP_ENT (SRC1), 0, 0 }, { INPUT, "src2", HW_H_GR, CGEN_MODE_USI, OP_ENT (SRC2), 0, 0 }, - { OUTPUT, "h_memory_src2", HW_H_MEMORY, CGEN_MODE_HI, 0, 0, 0 }, + { OUTPUT, "h_memory_HI_src2", HW_H_MEMORY, CGEN_MODE_HI, 0, 0, 0 }, { END } }; @@ -441,39 +471,39 @@ static const CGEN_OPINST sfmt_sth_d_ops[] = { { INPUT, "slo16", HW_H_SLO16, CGEN_MODE_INT, OP_ENT (SLO16), 0, 0 }, { INPUT, "src1", HW_H_GR, CGEN_MODE_HI, OP_ENT (SRC1), 0, 0 }, { INPUT, "src2", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC2), 0, 0 }, - { OUTPUT, "h_memory_add__DFLT_src2_slo16", HW_H_MEMORY, CGEN_MODE_HI, 0, 0, 0 }, + { OUTPUT, "h_memory_HI_add__DFLT_src2_slo16", HW_H_MEMORY, CGEN_MODE_HI, 0, 0, 0 }, { END } }; static const CGEN_OPINST sfmt_st_plus_ops[] = { { INPUT, "src1", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC1), 0, 0 }, { INPUT, "src2", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC2), 0, 0 }, - { OUTPUT, "h_memory_new_src2", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 }, + { OUTPUT, "h_memory_SI_new_src2", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, 0 }, { OUTPUT, "src2", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC2), 0, 0 }, { END } }; static const CGEN_OPINST sfmt_trap_ops[] = { - { INPUT, "h_bpsw", HW_H_BPSW, CGEN_MODE_UQI, 0, 0, 0 }, - { INPUT, "h_cr_6", HW_H_CR, CGEN_MODE_USI, 0, 6, 0 }, - { INPUT, "h_psw", HW_H_PSW, CGEN_MODE_UQI, 0, 0, 0 }, + { INPUT, "h_bpsw_UQI", HW_H_BPSW, CGEN_MODE_UQI, 0, 0, 0 }, + { INPUT, "h_cr_USI_6", HW_H_CR, CGEN_MODE_USI, 0, 6, 0 }, + { INPUT, "h_psw_UQI", HW_H_PSW, CGEN_MODE_UQI, 0, 0, 0 }, { INPUT, "pc", HW_H_PC, CGEN_MODE_USI, 0, 0, 0 }, { INPUT, "uimm4", HW_H_UINT, CGEN_MODE_UINT, OP_ENT (UIMM4), 0, 0 }, - { OUTPUT, "h_bbpsw", HW_H_BBPSW, CGEN_MODE_UQI, 0, 0, 0 }, - { OUTPUT, "h_bpsw", HW_H_BPSW, CGEN_MODE_UQI, 0, 0, 0 }, - { OUTPUT, "h_cr_14", HW_H_CR, CGEN_MODE_USI, 0, 14, 0 }, - { OUTPUT, "h_cr_6", HW_H_CR, CGEN_MODE_USI, 0, 6, 0 }, - { OUTPUT, "h_psw", HW_H_PSW, CGEN_MODE_UQI, 0, 0, 0 }, + { OUTPUT, "h_bbpsw_UQI", HW_H_BBPSW, CGEN_MODE_UQI, 0, 0, 0 }, + { OUTPUT, "h_bpsw_UQI", HW_H_BPSW, CGEN_MODE_UQI, 0, 0, 0 }, + { OUTPUT, "h_cr_USI_14", HW_H_CR, CGEN_MODE_USI, 0, 14, 0 }, + { OUTPUT, "h_cr_USI_6", HW_H_CR, CGEN_MODE_USI, 0, 6, 0 }, + { OUTPUT, "h_psw_UQI", HW_H_PSW, CGEN_MODE_UQI, 0, 0, 0 }, { OUTPUT, "pc", HW_H_PC, CGEN_MODE_SI, 0, 0, 0 }, { END } }; static const CGEN_OPINST sfmt_unlock_ops[] = { - { INPUT, "h_lock", HW_H_LOCK, CGEN_MODE_BI, 0, 0, 0 }, + { INPUT, "h_lock_BI", HW_H_LOCK, CGEN_MODE_BI, 0, 0, 0 }, { INPUT, "src1", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC1), 0, COND_REF }, { INPUT, "src2", HW_H_GR, CGEN_MODE_USI, OP_ENT (SRC2), 0, COND_REF }, - { OUTPUT, "h_lock", HW_H_LOCK, CGEN_MODE_BI, 0, 0, 0 }, - { OUTPUT, "h_memory_src2", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, COND_REF }, + { OUTPUT, "h_lock_BI", HW_H_LOCK, CGEN_MODE_BI, 0, 0, 0 }, + { OUTPUT, "h_memory_SI_src2", HW_H_MEMORY, CGEN_MODE_SI, 0, 0, COND_REF }, { END } }; @@ -491,24 +521,24 @@ static const CGEN_OPINST sfmt_sat_ops[] = { }; static const CGEN_OPINST sfmt_sadd_ops[] = { - { INPUT, "h_accums_0", HW_H_ACCUMS, CGEN_MODE_DI, 0, 0, 0 }, - { INPUT, "h_accums_1", HW_H_ACCUMS, CGEN_MODE_DI, 0, 1, 0 }, - { OUTPUT, "h_accums_0", HW_H_ACCUMS, CGEN_MODE_DI, 0, 0, 0 }, + { INPUT, "h_accums_DI_0", HW_H_ACCUMS, CGEN_MODE_DI, 0, 0, 0 }, + { INPUT, "h_accums_DI_1", HW_H_ACCUMS, CGEN_MODE_DI, 0, 1, 0 }, + { OUTPUT, "h_accums_DI_0", HW_H_ACCUMS, CGEN_MODE_DI, 0, 0, 0 }, { END } }; static const CGEN_OPINST sfmt_macwu1_ops[] = { - { INPUT, "h_accums_1", HW_H_ACCUMS, CGEN_MODE_DI, 0, 1, 0 }, + { INPUT, "h_accums_DI_1", HW_H_ACCUMS, CGEN_MODE_DI, 0, 1, 0 }, { INPUT, "src1", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC1), 0, 0 }, { INPUT, "src2", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC2), 0, 0 }, - { OUTPUT, "h_accums_1", HW_H_ACCUMS, CGEN_MODE_DI, 0, 1, 0 }, + { OUTPUT, "h_accums_DI_1", HW_H_ACCUMS, CGEN_MODE_DI, 0, 1, 0 }, { END } }; static const CGEN_OPINST sfmt_mulwu1_ops[] = { { INPUT, "src1", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC1), 0, 0 }, { INPUT, "src2", HW_H_GR, CGEN_MODE_SI, OP_ENT (SRC2), 0, 0 }, - { OUTPUT, "h_accums_1", HW_H_ACCUMS, CGEN_MODE_DI, 0, 1, 0 }, + { OUTPUT, "h_accums_DI_1", HW_H_ACCUMS, CGEN_MODE_DI, 0, 1, 0 }, { END } }; @@ -576,14 +606,14 @@ static const CGEN_OPINST *m32r_cgen_opinst_table[MAX_INSNS] = { & sfmt_jmp_ops[0], & sfmt_ld_ops[0], & sfmt_ld_d_ops[0], - & sfmt_ld_ops[0], - & sfmt_ld_d_ops[0], - & sfmt_ld_ops[0], - & sfmt_ld_d_ops[0], - & sfmt_ld_ops[0], - & sfmt_ld_d_ops[0], - & sfmt_ld_ops[0], - & sfmt_ld_d_ops[0], + & sfmt_ldb_ops[0], + & sfmt_ldb_d_ops[0], + & sfmt_ldh_ops[0], + & sfmt_ldh_d_ops[0], + & sfmt_ldb_ops[0], + & sfmt_ldb_d_ops[0], + & sfmt_ldh_ops[0], + & sfmt_ldh_d_ops[0], & sfmt_ld_plus_ops[0], & sfmt_ld24_ops[0], & sfmt_ldi8_ops[0], diff --git a/opcodes/openrisc-asm.c b/opcodes/openrisc-asm.c index 7f2e9518966..a8ed30b91f6 100644 --- a/opcodes/openrisc-asm.c +++ b/opcodes/openrisc-asm.c @@ -34,6 +34,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., #include "openrisc-desc.h" #include "openrisc-opc.h" #include "opintl.h" +#include "xregex.h" #undef min #define min(a,b) ((a) < (b) ? (a) : (b)) @@ -257,6 +258,104 @@ openrisc_cgen_init_asm (cd) } + +/* + Regex construction routine. + + This translates an opcode syntax string into a regex string, + by replacing any non-character syntax element (such as an + opcode) with the pattern '.*' + + It then compiles the regex and stores it in the opcode, for + later use by openrisc_cgen_assemble_insn + + returns NULL for success, an error message for failure +*/ + +char * +openrisc_cgen_build_insn_regex (insn) + CGEN_INSN *insn; +{ + CGEN_OPCODE *opc = CGEN_INSN_OPCODE (insn); + const char *mnem = CGEN_INSN_MNEMONIC (insn); + int mnem_len; + char rxbuf[CGEN_MAX_RX_ELEMENTS]; + char *rx = rxbuf; + const CGEN_SYNTAX_CHAR_TYPE *syn; + int reg_err; + + syn = CGEN_SYNTAX_STRING (CGEN_OPCODE_SYNTAX (opc)); + + /* Mnemonics come first in the syntax string */ + if (! CGEN_SYNTAX_MNEMONIC_P (* syn)) return "missing mnemonic in syntax string"; + ++syn; + + /* copy the literal mnemonic out of the insn */ + memset (rx, 0, CGEN_MAX_RX_ELEMENTS); + mnem_len = strlen(mnem); + memcpy (rx, mnem, mnem_len); + rx += mnem_len; + + /* copy any remaining literals from the syntax string into the rx */ + for(; * syn != 0 && rx < rxbuf + (CGEN_MAX_RX_ELEMENTS - 9); ++syn, ++rx) + { + if (CGEN_SYNTAX_CHAR_P (* syn)) + { + char tmp = CGEN_SYNTAX_CHAR (* syn); + switch (tmp) + { + /* escape any regex metacharacters in the syntax */ + case '.': case '[': case '\\': + case '*': case '^': case '$': + +#ifdef CGEN_ESCAPE_EXTENDED_REGEX + case '?': case '{': case '}': + case '(': case ')': case '*': + case '|': case '+': case ']': +#endif + + * rx++ = '\\'; + break; + } + /* insert syntax char into rx */ + * rx = tmp; + } + else + { + /* replace non-syntax fields with globs */ + * rx = '.'; + * ++rx = '*'; + } + } + + /* trailing whitespace ok */ + * rx++ = '['; + * rx++ = ' '; + * rx++ = '\t'; + * rx++ = ']'; + * rx++ = '*'; + + /* but anchor it after that */ + * rx++ = '$'; + * rx = '\0'; + + CGEN_INSN_RX (insn) = xmalloc (sizeof (regex_t)); + reg_err = regcomp ((regex_t *) CGEN_INSN_RX (insn), rxbuf, REG_NOSUB|REG_ICASE); + + if (reg_err == 0) + return NULL; + else + { + static char msg[80]; + regerror (reg_err, (regex_t *) CGEN_INSN_RX (insn), msg, 80); + regfree ((regex_t *) CGEN_INSN_RX (insn)); + free (CGEN_INSN_RX (insn)); + (CGEN_INSN_RX (insn)) = NULL; + return msg; + } +} + + /* Default insn parser. The syntax string is scanned and operands are parsed and stored in FIELDS. @@ -423,6 +522,7 @@ openrisc_cgen_assemble_insn (cd, str, fields, buf, errmsg) CGEN_INSN_LIST *ilist; const char *parse_errmsg = NULL; const char *insert_errmsg = NULL; + int recognized_mnemonic = 0; /* Skip leading white space. */ while (isspace (* str)) @@ -438,6 +538,7 @@ openrisc_cgen_assemble_insn (cd, str, fields, buf, errmsg) for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist)) { const CGEN_INSN *insn = ilist->insn; + recognized_mnemonic = 1; #ifdef CGEN_VALIDATE_INSN_SUPPORTED /* not usually needed as unsupported opcodes shouldn't be in the hash lists */ @@ -454,6 +555,11 @@ openrisc_cgen_assemble_insn (cd, str, fields, buf, errmsg) str = start; + /* skip this insn if str doesn't look right lexically */ + if (CGEN_INSN_RX (insn) != NULL && + regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH) + continue; + /* Allow parse/insert handlers to obtain length of insn. */ CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); @@ -481,6 +587,7 @@ openrisc_cgen_assemble_insn (cd, str, fields, buf, errmsg) Failing that, use parse_errmsg */ tmp_errmsg = (insert_errmsg ? insert_errmsg : parse_errmsg ? parse_errmsg : + recognized_mnemonic ? _("unrecognized form of instruction") : _("unrecognized instruction")); if (strlen (start) > 50) diff --git a/opcodes/openrisc-desc.c b/opcodes/openrisc-desc.c index ff6cba251ca..f9605e69095 100644 --- a/opcodes/openrisc-desc.c +++ b/opcodes/openrisc-desc.c @@ -129,9 +129,9 @@ static const CGEN_ISA openrisc_cgen_isa_table[] = { /* Machine variants. */ static const CGEN_MACH openrisc_cgen_mach_table[] = { - { "openrisc", "openrisc", MACH_OPENRISC }, - { "or1300", "openrisc:1300", MACH_OR1300 }, - { 0, 0, 0 } + { "openrisc", "openrisc", MACH_OPENRISC, 0 }, + { "or1300", "openrisc:1300", MACH_OR1300, 0 }, + { 0, 0, 0, 0 } }; static CGEN_KEYWORD_ENTRY openrisc_cgen_opval_h_gr_entries[] = @@ -177,7 +177,7 @@ CGEN_KEYWORD openrisc_cgen_opval_h_gr = { & openrisc_cgen_opval_h_gr_entries[0], 35, - 0, 0, 0, 0 + 0, 0, 0, 0, "" }; @@ -779,11 +779,9 @@ static void openrisc_cgen_rebuild_tables (cd) CGEN_CPU_TABLE *cd; { - int i,n_isas; + int i; unsigned int isas = cd->isas; -#if 0 unsigned int machs = cd->machs; -#endif cd->int_insn_p = CGEN_INT_INSN_P; @@ -821,20 +819,26 @@ openrisc_cgen_rebuild_tables (cd) cd->min_insn_bitsize = isa->min_insn_bitsize; if (isa->max_insn_bitsize > cd->max_insn_bitsize) cd->max_insn_bitsize = isa->max_insn_bitsize; - - ++n_isas; } -#if 0 /* Does nothing?? */ /* Data derived from the mach spec. */ for (i = 0; i < MAX_MACHS; ++i) if (((1 << i) & machs) != 0) { const CGEN_MACH *mach = & openrisc_cgen_mach_table[i]; - ++n_machs; + if (mach->insn_chunk_bitsize != 0) + { + if (cd->insn_chunk_bitsize != 0 && cd->insn_chunk_bitsize != mach->insn_chunk_bitsize) + { + fprintf (stderr, "openrisc_cgen_rebuild_tables: conflicting insn-chunk-bitsize values: `%d' vs. `%d'\n", + cd->insn_chunk_bitsize, mach->insn_chunk_bitsize); + abort (); + } + + cd->insn_chunk_bitsize = mach->insn_chunk_bitsize; + } } -#endif /* Determine which hw elements are used by MACH. */ build_hw_table (cd); diff --git a/opcodes/openrisc-dis.c b/opcodes/openrisc-dis.c index 726b301d1da..64cab8e2dfa 100644 --- a/opcodes/openrisc-dis.c +++ b/opcodes/openrisc-dis.c @@ -325,13 +325,19 @@ print_insn (cd, pc, info, buf, buflen) char *buf; int buflen; { - unsigned long insn_value; + CGEN_INSN_INT insn_value; const CGEN_INSN_LIST *insn_list; CGEN_EXTRACT_INFO ex_info; - int rc = read_insn (cd, pc, info, buf, buflen, & ex_info, & insn_value); - if (rc != 0) - return rc; + /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */ + insn_value = cgen_get_insn_value (cd, buf, buflen * 8); + + /* Fill in ex_info fields like read_insn would. Don't actually call + read_insn, since the incoming buffer is already read (and possibly + modified a la m32r). */ + ex_info.valid = (1 << buflen) - 1; + ex_info.dis_info = info; + ex_info.insn_bytes = buf; /* The instructions are stored in hash lists. Pick the first one and keep trying until we find the right one. */ @@ -342,6 +348,7 @@ print_insn (cd, pc, info, buf, buflen) const CGEN_INSN *insn = insn_list->insn; CGEN_FIELDS fields; int length; + unsigned long insn_value_cropped; #ifdef CGEN_VALIDATE_INSN_SUPPORTED /* not needed as insn shouldn't be in hash lists if not supported */ @@ -356,7 +363,17 @@ print_insn (cd, pc, info, buf, buflen) /* Basic bit mask must be correct. */ /* ??? May wish to allow target to defer this check until the extract handler. */ - if ((insn_value & CGEN_INSN_BASE_MASK (insn)) + + /* Base size may exceed this instruction's size. Extract the + relevant part from the buffer. */ + if ((CGEN_INSN_BITSIZE (insn) / 8) < buflen && + (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long)) + insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn), + info->endian == BFD_ENDIAN_BIG); + else + insn_value_cropped = insn_value; + + if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn)) == CGEN_INSN_BASE_VALUE (insn)) { /* Printing is handled in two passes. The first pass parses the @@ -379,7 +396,7 @@ print_insn (cd, pc, info, buf, buflen) } else length = CGEN_EXTRACT_FN (cd, insn) - (cd, insn, &ex_info, insn_value, &fields, pc); + (cd, insn, &ex_info, insn_value_cropped, &fields, pc); /* length < 0 -> error */ if (length < 0) @@ -413,18 +430,27 @@ default_print_insn (cd, pc, info) disassemble_info *info; { char buf[CGEN_MAX_INSN_SIZE]; + int buflen; int status; - /* Read the base part of the insn. */ + /* Attempt to read the base part of the insn. */ + buflen = cd->base_insn_bitsize / 8; + status = (*info->read_memory_func) (pc, buf, buflen, info); + + /* Try again with the minimum part, if min < base. */ + if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize)) + { + buflen = cd->min_insn_bitsize / 8; + status = (*info->read_memory_func) (pc, buf, buflen, info); + } - status = (*info->read_memory_func) (pc, buf, cd->base_insn_bitsize / 8, info); if (status != 0) { (*info->memory_error_func) (status, pc, info); return -1; } - return print_insn (cd, pc, info, buf, cd->base_insn_bitsize / 8); + return print_insn (cd, pc, info, buf, buflen); } /* Main entry point. diff --git a/opcodes/openrisc-ibld.c b/opcodes/openrisc-ibld.c index ea7535ef4be..c828aba3b69 100644 --- a/opcodes/openrisc-ibld.c +++ b/opcodes/openrisc-ibld.c @@ -145,7 +145,22 @@ insert_normal (cd, value, attrs, word_offset, start, length, word_length, } /* Ensure VALUE will fit. */ - if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)) + if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT)) + { + long minval = - (1L << (length - 1)); + unsigned long maxval = mask; + + if ((value > 0 && (unsigned long) value > maxval) + || value < minval) + { + /* xgettext:c-format */ + sprintf (errbuf, + _("operand out of range (%ld not between %ld and %lu)"), + value, minval, maxval); + return errbuf; + } + } + else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)) { unsigned long maxval = mask; @@ -400,7 +415,7 @@ extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length, #endif long *valuep; { - CGEN_INSN_INT value, mask; + long value, mask; /* If LENGTH is zero, this operand doesn't contribute to the value so give it a standard value of zero. */ @@ -428,9 +443,9 @@ extract_normal (cd, ex_info, insn_value, attrs, word_offset, start, length, word_length = total_length; } - /* Does the value reside in INSN_VALUE? */ + /* Does the value reside in INSN_VALUE, and at the right alignment? */ - if (CGEN_INT_INSN_P || word_offset == 0) + if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length)) { if (CGEN_INSN_LSB0_P) value = insn_value >> ((word_offset + start + 1) - length); diff --git a/opcodes/openrisc-opc.c b/opcodes/openrisc-opc.c index 86ee35b7bf3..c0b28692a97 100644 --- a/opcodes/openrisc-opc.c +++ b/opcodes/openrisc-opc.c @@ -678,6 +678,7 @@ openrisc_cgen_init_opcode_table (cd) { insns[i].base = &ib[i]; insns[i].opcode = &oc[i]; + openrisc_cgen_build_insn_regex (& insns[i]); } cd->macro_insn_table.init_entries = insns; cd->macro_insn_table.entry_size = sizeof (CGEN_IBASE); @@ -686,7 +687,10 @@ openrisc_cgen_init_opcode_table (cd) oc = & openrisc_cgen_insn_opcode_table[0]; insns = (CGEN_INSN *) cd->insn_table.init_entries; for (i = 0; i < MAX_INSNS; ++i) - insns[i].opcode = &oc[i]; + { + insns[i].opcode = &oc[i]; + openrisc_cgen_build_insn_regex (& insns[i]); + } cd->sizeof_fields = sizeof (CGEN_FIELDS); cd->set_fields_bitsize = set_fields_bitsize; |