aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--opcodes/ChangeLog5
-rw-r--r--opcodes/cgen-ibld.in2
-rw-r--r--opcodes/fr30-asm.c109
-rw-r--r--opcodes/fr30-desc.c38
-rw-r--r--opcodes/fr30-dis.c44
-rw-r--r--opcodes/fr30-ibld.c33
-rw-r--r--opcodes/fr30-opc.c6
-rw-r--r--opcodes/m32r-asm.c107
-rw-r--r--opcodes/m32r-desc.c32
-rw-r--r--opcodes/m32r-dis.c21
-rw-r--r--opcodes/m32r-ibld.c23
-rw-r--r--opcodes/m32r-opc.c6
-rw-r--r--opcodes/m32r-opinst.c128
-rw-r--r--opcodes/openrisc-asm.c107
-rw-r--r--opcodes/openrisc-desc.c28
-rw-r--r--opcodes/openrisc-dis.c44
-rw-r--r--opcodes/openrisc-ibld.c23
-rw-r--r--opcodes/openrisc-opc.c6
18 files changed, 624 insertions, 138 deletions
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index 2a12444..bd51464 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 0ca4200..213b888 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 b2a95e3..9ad3f2c 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 4223833..b2a205f 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 f389dcc..0e4aceb 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 6bfca21..90ad6ef 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 4d0ab6a..877f26b 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 4d18d64..0e69a80 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 8bcd790..d07c657 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 477a85b..687eb51 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 f999bcd..447f014 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 3c579a4..12491d7 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 55e7e4f..aaaa1c0 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 7f2e951..a8ed30b 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 ff6cba2..f9605e6 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 726b301..64cab8e 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 ea7535e..c828aba 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 86ee35b..c0b2869 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;