From 95b03313e0e5e27d4260f26cf17292fc1830eb5e Mon Sep 17 00:00:00 2001 From: Doug Evans Date: Wed, 18 Nov 1998 23:25:45 +0000 Subject: [PATCH] * cgen-asm.in (insert_1): Replace calls to bfd_getb8/putb8. (insert_normal, !CGEN_INT_INSN_P case): Only fetch enough bytes to hold value. (insert_insn_normal): Fix typo. * cgen-dis.c (cgen_dis_lookup_insn): Update type of `value' arg. * cgen-dis.in (extract_normal): Ditto. New arg `pc'. Rewrite ! CGEN_INT_INSN_P case. (extract_insn_normal): Ditto. (extract_1): New arg `pc'. All callers updated. Replace calls to bfd_getb8. (fill_cache): New fn. * cgen-opc.c (cgen_{get,put}_insn_value): Move here ... * cgen-opc.in: ... from here. (@arch@_cgen_lookup_insn): Rewrite ! CGEN_INT_INSN_P case. * m32r-asm.c,m32r-dis.c,m32r-opc.c: Rebuild. * fr30-asm.c,fr30-dis.c,fr30-opc.c: Rebuild. --- opcodes/ChangeLog | 21 ++++ opcodes/cgen-opc.in | 98 +++------------ opcodes/fr30-asm.c | 42 +++---- opcodes/fr30-dis.c | 202 +++++++++++++++++++----------- opcodes/fr30-opc.c | 290 +++++++++++++++++++------------------------- opcodes/fr30-opc.h | 67 +++++----- 6 files changed, 345 insertions(+), 375 deletions(-) diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 0804ab4198..9b160ce20d 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,24 @@ +1998-11-18 Doug Evans + + * cgen-asm.in (insert_1): Replace calls to bfd_getb8/putb8. + (insert_normal, !CGEN_INT_INSN_P case): Only fetch enough bytes + to hold value. + (insert_insn_normal): Fix typo. + * cgen-dis.c (cgen_dis_lookup_insn): Update type of `value' arg. + * cgen-dis.in (extract_normal): Ditto. New arg `pc'. + Rewrite ! CGEN_INT_INSN_P case. + (extract_insn_normal): Ditto. + (extract_1): New arg `pc'. All callers updated. + Replace calls to bfd_getb8. + (fill_cache): New fn. + * cgen-opc.c (cgen_{get,put}_insn_value): Move here ... + * cgen-opc.in: ... from here. + (@arch@_cgen_lookup_insn): Rewrite ! CGEN_INT_INSN_P case. + * m32r-asm.c,m32r-dis.c,m32r-opc.c: Rebuild. +start-sanitize-fr30 + * fr30-asm.c,fr30-dis.c,fr30-opc.c: Rebuild. +end-sanitize-fr30 + start-sanitize-fr30 Wed Nov 18 11:30:04 1998 Dave Brolley diff --git a/opcodes/cgen-opc.in b/opcodes/cgen-opc.in index 014d9a3522..2bb47a1d50 100644 --- a/opcodes/cgen-opc.in +++ b/opcodes/cgen-opc.in @@ -36,72 +36,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., static int asm_hash_insn_p PARAMS ((const CGEN_INSN *)); static unsigned int asm_hash_insn PARAMS ((const char *)); static int dis_hash_insn_p PARAMS ((const CGEN_INSN *)); -static unsigned int dis_hash_insn PARAMS ((const char *, unsigned long)); - -/* Cover function to read and properly byteswap an insn value. */ - -CGEN_INSN_INT -cgen_get_insn_value (od, buf, length) - CGEN_OPCODE_DESC od; - unsigned char *buf; - int length; -{ - CGEN_INSN_INT value; - - switch (length) - { - case 8: - value = *buf; - break; - case 16: - if (CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG) - value = bfd_getb16 (buf); - else - value = bfd_getl16 (buf); - break; - case 32: - if (CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG) - value = bfd_getb32 (buf); - else - value = bfd_getl32 (buf); - break; - default: - abort (); - } - - return value; -} - -/* Cover function to store an insn value properly byteswapped. */ - -void -cgen_put_insn_value (od, buf, length, value) - CGEN_OPCODE_DESC od; - unsigned char *buf; - int length; - CGEN_INSN_INT value; -{ - switch (length) - { - case 8: - buf[0] = value; - break; - case 16: - if (CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG) - bfd_putb16 (value, buf); - else - bfd_putl16 (value, buf); - break; - case 32: - if (CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG) - bfd_putb32 (value, buf); - else - bfd_putl32 (value, buf); - break; - default: - abort (); - } -} +static unsigned int dis_hash_insn PARAMS ((const char *, CGEN_INSN_INT)); /* Look up instruction INSN_VALUE and extract its fields. INSN, if non-null, is the insn table entry. @@ -111,7 +46,7 @@ cgen_put_insn_value (od, buf, length, value) If INSN != NULL, LENGTH must be valid. ALIAS_P is non-zero if alias insns are to be included in the search. - The result a pointer to the insn table entry, or NULL if the instruction + The result is a pointer to the insn table entry, or NULL if the instruction wasn't recognized. */ const CGEN_INSN * @@ -123,9 +58,9 @@ const CGEN_INSN * CGEN_FIELDS *fields; int alias_p; { - unsigned char buf[16]; + unsigned char buf[CGEN_MAX_INSN_SIZE]; unsigned char *bufp; - unsigned int base_insn; + CGEN_INSN_INT base_insn; #if CGEN_INT_INSN_P CGEN_EXTRACT_INFO *info = NULL; #else @@ -133,25 +68,22 @@ const CGEN_INSN * CGEN_EXTRACT_INFO *info = &ex_info; #endif -#if ! CGEN_INT_INSN_P +#if CGEN_INT_INSN_P + cgen_put_insn_value (od, buf, length, insn_value); + bufp = buf; + base_insn = insn_value; /*???*/ +#else ex_info.dis_info = NULL; - ex_info.bytes = insn_value; + ex_info.insn_bytes = insn_value; ex_info.valid = -1; + base_insn = cgen_get_insn_value (od, buf, length); + bufp = insn_value; #endif if (!insn) { const CGEN_INSN_LIST *insn_list; -#if CGEN_INT_INSN_P - cgen_put_insn_value (od, buf, length, insn_value); - bufp = buf; - base_insn = insn_value; /*???*/ -#else - base_insn = cgen_get_insn_value (od, buf, length); - bufp = insn_value; -#endif - /* The instructions are stored in hash lists. Pick the first one and keep trying until we find the right one. */ @@ -166,11 +98,11 @@ const CGEN_INSN * /* Basic bit mask must be correct. */ /* ??? May wish to allow target to defer this check until the extract handler. */ - if ((insn_value & CGEN_INSN_MASK (insn)) == CGEN_INSN_VALUE (insn)) + if ((base_insn & CGEN_INSN_MASK (insn)) == CGEN_INSN_VALUE (insn)) { /* ??? 0 is passed for `pc' */ int elength = (*CGEN_EXTRACT_FN (insn)) (od, insn, info, - insn_value, fields, + base_insn, fields, (bfd_vma) 0); if (elength > 0) { @@ -196,7 +128,7 @@ const CGEN_INSN * abort (); /* ??? 0 is passed for `pc' */ - length = (*CGEN_EXTRACT_FN (insn)) (od, insn, info, insn_value, fields, + length = (*CGEN_EXTRACT_FN (insn)) (od, insn, info, base_insn, fields, (bfd_vma) 0); /* Sanity check: must succeed. Could relax this later if it ever proves useful. */ diff --git a/opcodes/fr30-asm.c b/opcodes/fr30-asm.c index 75e20fb0d6..0a57766a1c 100644 --- a/opcodes/fr30-asm.c +++ b/opcodes/fr30-asm.c @@ -133,6 +133,9 @@ fr30_cgen_parse_operand (od, opindex, strp, fields) case FR30_OPERAND_U10 : errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_U10, &fields->f_u10); break; + case FR30_OPERAND_I32 : + errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_I32, &fields->f_i32); + break; case FR30_OPERAND_DIR8 : errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_DIR8, &fields->f_dir8); break; @@ -266,6 +269,9 @@ fr30_cgen_insert_operand (od, opindex, fields, buffer, pc) errmsg = insert_normal (od, value, 0|(1<f_i32, 0|(1<f_dir8, 0|(1<> 16, bufp); + bufp[0] = x >> 16; bfd_putb16 (x, bufp + 1); } else { bfd_putl16 (x, bufp); - bfd_putb8 (x >> 16, bufp + 2); + bufp[2] = x >> 16; } break; case 32: @@ -429,12 +435,6 @@ insert_1 (od, value, start, length, word_length, bufp) The result is an error message or NULL if success. */ -/* ??? May need to know word length in order to properly place values as - an insn may be made of multiple words and the current bit number handling - may be insufficient. Word length is an architectural attribute and thus - methinks the way to go [if needed] is to fetch this value from OD or - define a macro in -opc.h rather than adding an extra argument - - after all that's how endianness is handled. */ /* ??? This duplicates functionality with bfd's howto table and bfd_install_relocation. */ /* ??? For architectures where insns can be representable as ints, @@ -489,7 +489,7 @@ insert_normal (od, value, attrs, start, length, total_length, buffer) #if CGEN_INT_INSN_P - if (total_length > 32) + if (total_length > 32) /* 32 bits in a portable host int */ abort (); { int shift; @@ -505,17 +505,9 @@ insert_normal (od, value, attrs, start, length, total_length, buffer) /* FIXME: unfinished and untested */ -/* ??? To be defined in -opc.h as necessary. */ -#ifndef CGEN_WORD_ENDIAN -#define CGEN_WORD_ENDIAN(od) CGEN_OPCODE_ENDIAN (od) -#endif -#ifndef CGEN_INSN_WORD_ENDIAN -#define CGEN_INSN_WORD_ENDIAN(od) CGEN_WORD_ENDIAN (od) -#endif - /* The hard case is probably too slow for the normal cases. It's certainly more difficult to understand than the normal case. - Thus this is split into two. Keep it that way. The hard case is defined + Thus this is split into two. The hard case is defined to be when a field straddles a (loosely defined) word boundary (??? which may require target specific help to determine). */ @@ -590,9 +582,9 @@ insert_normal (od, value, attrs, start, length, total_length, buffer) /* Adjust start,total_length,bufp to point to the pseudo-word that holds the value. For example in a 48 bit insn where the value to insert - (say an immediate value) is the last 16 bits then word_length here + (say an immediate value) is the last 16 bits then fetch_length here would be 16. To handle a 24 bit insn with an 18 bit immediate, - insert_1 handles 24 bits (using a combination of bfd_get8,16). */ + insert_1 handles 24 bits. */ if (total_length > 32) { @@ -613,7 +605,7 @@ insert_normal (od, value, attrs, start, length, total_length, buffer) bufp += offset / 8; start -= offset; - total_length -= offset; + total_length = fetch_length; } } else @@ -624,7 +616,7 @@ insert_normal (od, value, attrs, start, length, total_length, buffer) bufp += offset / 8; start -= offset; - total_length -= offset; + total_length = fetch_length; } else { @@ -784,7 +776,7 @@ insert_insn_normal (od, insn, fields, buffer, pc) #else - cgen_insn_put_value (od, buffer, min (CGEN_BASE_INSN_BITSIZE, + cgen_put_insn_value (od, buffer, min (CGEN_BASE_INSN_BITSIZE, CGEN_FIELDS_BITSIZE (fields)), value); diff --git a/opcodes/fr30-dis.c b/opcodes/fr30-dis.c index 9aeb13a921..f9d1679061 100644 --- a/opcodes/fr30-dis.c +++ b/opcodes/fr30-dis.c @@ -41,8 +41,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., #define UNKNOWN_INSN_MSG _("*unknown*") static int extract_normal - PARAMS ((CGEN_OPCODE_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_BYTES, - unsigned int, int, int, int, long *)); + PARAMS ((CGEN_OPCODE_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, + unsigned int, int, int, int, bfd_vma, long *)); static void print_normal PARAMS ((CGEN_OPCODE_DESC, PTR, long, unsigned int, bfd_vma, int)); static void print_address @@ -51,7 +51,7 @@ static void print_keyword PARAMS ((CGEN_OPCODE_DESC, PTR, CGEN_KEYWORD *, long, unsigned int)); static int extract_insn_normal PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *, - unsigned long, CGEN_FIELDS *, bfd_vma)); + CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma)); static void print_insn_normal PARAMS ((CGEN_OPCODE_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int)); @@ -81,7 +81,7 @@ fr30_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc) CGEN_OPCODE_DESC od; int opindex; CGEN_EXTRACT_INFO *ex_info; - CGEN_INSN_BYTES insn_value; + CGEN_INSN_INT insn_value; CGEN_FIELDS * fields; bfd_vma pc; { @@ -90,61 +90,61 @@ fr30_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc) switch (opindex) { case FR30_OPERAND_RI : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_Ri); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_Ri); break; case FR30_OPERAND_RJ : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_Rj); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_Rj); break; case FR30_OPERAND_RS1 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_Rs1); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_Rs1); break; case FR30_OPERAND_RS2 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_Rs2); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_Rs2); break; case FR30_OPERAND_R13 : - length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_nil); + length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_nil); break; case FR30_OPERAND_R14 : - length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_nil); + length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_nil); break; case FR30_OPERAND_R15 : - length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_nil); + length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_nil); break; case FR30_OPERAND_PS : - length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), & fields->f_nil); + length = extract_normal (od, ex_info, insn_value, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), pc, & fields->f_nil); break; case FR30_OPERAND_U4 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_u4); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_u4); break; case FR30_OPERAND_M4 : { long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_m4 = value; } break; case FR30_OPERAND_U8 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_u8); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_u8); break; case FR30_OPERAND_I8 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_i8); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_i8); break; case FR30_OPERAND_UDISP6 : { long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_udisp6 = value; } break; case FR30_OPERAND_DISP8 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_disp8); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_disp8); break; case FR30_OPERAND_DISP9 : { long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_disp9 = value; } @@ -152,7 +152,7 @@ fr30_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc) case FR30_OPERAND_DISP10 : { long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_disp10 = value; } @@ -160,7 +160,7 @@ fr30_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc) case FR30_OPERAND_S10 : { long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_s10 = value; } @@ -168,18 +168,21 @@ fr30_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc) case FR30_OPERAND_U10 : { long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_u10 = value; } break; + case FR30_OPERAND_I32 : + length = extract_normal (od, ex_info, insn_value, 0|(1<f_i32); + break; case FR30_OPERAND_DIR8 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_dir8); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_dir8); break; case FR30_OPERAND_DIR9 : { long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_dir9 = value; } @@ -187,7 +190,7 @@ fr30_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc) case FR30_OPERAND_DIR10 : { long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_dir10 = value; } @@ -195,7 +198,7 @@ fr30_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc) case FR30_OPERAND_LABEL9 : { long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_rel9 = value; } @@ -203,13 +206,13 @@ fr30_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc) case FR30_OPERAND_LABEL12 : { long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_rel12 = value; } break; case FR30_OPERAND_CC : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_cc); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_cc); break; default : @@ -302,6 +305,9 @@ fr30_cgen_print_operand (od, opindex, info, fields, attrs, pc, length) case FR30_OPERAND_U10 : print_normal (od, info, fields->f_u10, 0|(1<f_i32, 0|(1<f_dir8, 0|(1<dis_info; + + /* First do a quick check. */ + mask = (1 << bytes) - 1; + if (((ex_info->valid >> offset) & mask) == mask) + return 1; + + /* Search for the first byte we need to read. */ + for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1) + if (! (mask & ex_info->valid)) + break; + + if (bytes) + { + int status; + + pc += offset; + status = (*info->read_memory_func) + (pc, ex_info->insn_bytes + offset, bytes, info); + + if (status != 0) + { + (*info->memory_error_func) (status, pc, info); + return 0; + } + + ex_info->valid |= ((1 << bytes) - 1) << offset; + } + + return 1; +} + /* Subroutine of extract_normal. */ static INLINE long -extract_1 (od, ex_info, start, length, word_length, bufp) +extract_1 (od, ex_info, start, length, word_length, bufp, pc) CGEN_OPCODE_DESC od; - CGEN_EXTRACT_INFO *info; + CGEN_EXTRACT_INFO *ex_info; int start,length,word_length; unsigned char *bufp; + bfd_vma pc; { unsigned long x,mask; int shift; int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG; - /* FIXME: Need to use ex_info to ensure bytes have been fetched. */ - switch (word_length) { case 8: @@ -381,9 +432,9 @@ extract_1 (od, ex_info, start, length, word_length, bufp) /* ??? This may need reworking as these cases don't necessarily want the first byte and the last two bytes handled like this. */ if (big_p) - x = (bfd_getb8 (bufp) << 16) | bfd_getb16 (bufp + 1); + x = (bufp[0] << 16) | bfd_getb16 (bufp + 1); else - x = bfd_getl16 (bufp) | (bfd_getb8 (bufp + 2) << 16); + x = bfd_getl16 (bufp) | (bufp[2] << 16); break; case 32: if (big_p) @@ -408,19 +459,26 @@ extract_1 (od, ex_info, start, length, word_length, bufp) /* Default extraction routine. + INSN_VALUE is the first CGEN_BASE_INSN_SIZE bits of the insn in host order, + or sometimes less for cases like the m32r where the base insn size is 32 + but some insns are 16 bits. ATTRS is a mask of the boolean attributes. We only need `unsigned', - but for generality we take a bitmask of all of them. */ + but for generality we take a bitmask of all of them. + TOTAL_LENGTH is the length of the insn in bits. + + Returns 1 for success, 0 for failure. */ /* ??? This doesn't handle bfd_vma's. Create another function when necessary. */ static int -extract_normal (od, ex_info, insn_value, attrs, start, length, total_length, valuep) +extract_normal (od, ex_info, insn_value, attrs, start, length, total_length, pc, valuep) CGEN_OPCODE_DESC od; CGEN_EXTRACT_INFO *ex_info; - CGEN_INSN_BYTES insn_value; + CGEN_INSN_INT insn_value; unsigned int attrs; int start, length, total_length; + bfd_vma pc; long *valuep; { unsigned long value; @@ -433,51 +491,52 @@ extract_normal (od, ex_info, insn_value, attrs, start, length, total_length, val return 1; } -#if CGEN_INT_INSN_P - - { - /* Written this way to avoid undefined behaviour. */ - unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1; - - if (CGEN_INSN_LSB0_P) - value = insn_value >> start; - else - value = insn_value >> (total_length - (start + length)); - value &= mask; - /* sign extend? */ - if (! (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED)) - && (value & (1L << (length - 1)))) - value |= ~mask; - } + if (CGEN_INT_INSN_P + || (CGEN_INSN_LSB0_P + ? ((total_length - start) <= CGEN_BASE_INSN_BITSIZE) + : ((start + length) <= CGEN_BASE_INSN_BITSIZE))) + { + /* Written this way to avoid undefined behaviour. */ + unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1; -#else + if (CGEN_INSN_LSB0_P) + value = insn_value >> start; + else + value = insn_value >> (total_length - (start + length)); + value &= mask; + /* sign extend? */ + if (! (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED)) + && (value & (1L << (length - 1)))) + value |= ~mask; + } + +#if ! CGEN_INT_INSN_P /* The hard case is probably too slow for the normal cases. It's certainly more difficult to understand than the normal case. - Thus this is split into two. Keep it that way. The hard case is defined + Thus this is split into two. The hard case is defined to be when a field straddles a (loosely defined) word boundary (??? which may require target specific help to determine). */ -#if 0 /*wip*/ - #define HARD_CASE_P 0 /* FIXME:wip */ - if (HARD_CASE_P) + else if (HARD_CASE_P) { } -#endif + else { - unsigned char *bufp = (unsigned char *) insn_value; + unsigned char *bufp = ex_info->insn_bytes; + int offset = 0; if (length > 32) abort (); /* Adjust start,total_length,bufp to point to the pseudo-word that holds the value. For example in a 48 bit insn where the value to insert - (say an immediate value) is the last 16 bits then word_length here + (say an immediate value) is the last 16 bits then fetch_length here would be 16. To handle a 24 bit insn with an 18 bit immediate, - extract_1 handles 24 bits (using a combination of bfd_get8,16). */ + extract_1 handles 24 bits. */ if (total_length > 32) { @@ -494,22 +553,22 @@ extract_normal (od, ex_info, insn_value, attrs, start, length, total_length, val } else { - int offset = start & ~7; + offset = start & ~7; bufp += offset / 8; start -= offset; - total_length -= offset; + total_length = fetch_length; } } else { if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG) { - int offset = start & ~7; + offset = start & ~7; bufp += offset / 8; start -= offset; - total_length -= offset; + total_length = fetch_length; } else { @@ -518,15 +577,16 @@ extract_normal (od, ex_info, insn_value, attrs, start, length, total_length, val } } - /* FIXME: which bytes are being extracted have been lost. */ - value = extract_1 (od, ex_info, start, length, total_length, bufp); + if (fill_cache (od, ex_info, offset / 8, total_length / 8, pc) == 0) + return 0; + + value = extract_1 (od, ex_info, start, length, total_length, bufp, pc); } #endif /* ! CGEN_INT_INSN_P */ *valuep = value; - /* FIXME: for now */ return 1; } @@ -620,7 +680,7 @@ extract_insn_normal (od, insn, ex_info, insn_value, fields, pc) CGEN_OPCODE_DESC od; const CGEN_INSN *insn; CGEN_EXTRACT_INFO *ex_info; - unsigned long insn_value; + CGEN_INSN_INT insn_value; CGEN_FIELDS *fields; bfd_vma pc; { @@ -707,7 +767,7 @@ print_insn (od, pc, info, buf, buflen) ex_info.dis_info = info; ex_info.valid = (1 << CGEN_BASE_INSN_SIZE) - 1; - ex_info.bytes = buf; + ex_info.insn_bytes = buf; switch (buflen) { diff --git a/opcodes/fr30-opc.c b/opcodes/fr30-opc.c index a218eb19d8..c5b7ca57ec 100644 --- a/opcodes/fr30-opc.c +++ b/opcodes/fr30-opc.c @@ -36,72 +36,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., static int asm_hash_insn_p PARAMS ((const CGEN_INSN *)); static unsigned int asm_hash_insn PARAMS ((const char *)); static int dis_hash_insn_p PARAMS ((const CGEN_INSN *)); -static unsigned int dis_hash_insn PARAMS ((const char *, unsigned long)); - -/* Cover function to read and properly byteswap an insn value. */ - -CGEN_INSN_INT -cgen_get_insn_value (od, buf, length) - CGEN_OPCODE_DESC od; - unsigned char *buf; - int length; -{ - CGEN_INSN_INT value; - - switch (length) - { - case 8: - value = *buf; - break; - case 16: - if (CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG) - value = bfd_getb16 (buf); - else - value = bfd_getl16 (buf); - break; - case 32: - if (CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG) - value = bfd_getb32 (buf); - else - value = bfd_getl32 (buf); - break; - default: - abort (); - } - - return value; -} - -/* Cover function to store an insn value properly byteswapped. */ - -void -cgen_put_insn_value (od, buf, length, value) - CGEN_OPCODE_DESC od; - unsigned char *buf; - int length; - CGEN_INSN_INT value; -{ - switch (length) - { - case 8: - buf[0] = value; - break; - case 16: - if (CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG) - bfd_putb16 (value, buf); - else - bfd_putl16 (value, buf); - break; - case 32: - if (CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG) - bfd_putb32 (value, buf); - else - bfd_putl32 (value, buf); - break; - default: - abort (); - } -} +static unsigned int dis_hash_insn PARAMS ((const char *, CGEN_INSN_INT)); /* Look up instruction INSN_VALUE and extract its fields. INSN, if non-null, is the insn table entry. @@ -111,7 +46,7 @@ cgen_put_insn_value (od, buf, length, value) If INSN != NULL, LENGTH must be valid. ALIAS_P is non-zero if alias insns are to be included in the search. - The result a pointer to the insn table entry, or NULL if the instruction + The result is a pointer to the insn table entry, or NULL if the instruction wasn't recognized. */ const CGEN_INSN * @@ -123,9 +58,9 @@ fr30_cgen_lookup_insn (od, insn, insn_value, length, fields, alias_p) CGEN_FIELDS *fields; int alias_p; { - unsigned char buf[16]; + unsigned char buf[CGEN_MAX_INSN_SIZE]; unsigned char *bufp; - unsigned int base_insn; + CGEN_INSN_INT base_insn; #if CGEN_INT_INSN_P CGEN_EXTRACT_INFO *info = NULL; #else @@ -133,25 +68,22 @@ fr30_cgen_lookup_insn (od, insn, insn_value, length, fields, alias_p) CGEN_EXTRACT_INFO *info = &ex_info; #endif -#if ! CGEN_INT_INSN_P +#if CGEN_INT_INSN_P + cgen_put_insn_value (od, buf, length, insn_value); + bufp = buf; + base_insn = insn_value; /*???*/ +#else ex_info.dis_info = NULL; - ex_info.bytes = insn_value; + ex_info.insn_bytes = insn_value; ex_info.valid = -1; + base_insn = cgen_get_insn_value (od, buf, length); + bufp = insn_value; #endif if (!insn) { const CGEN_INSN_LIST *insn_list; -#if CGEN_INT_INSN_P - cgen_put_insn_value (od, buf, length, insn_value); - bufp = buf; - base_insn = insn_value; /*???*/ -#else - base_insn = cgen_get_insn_value (od, buf, length); - bufp = insn_value; -#endif - /* The instructions are stored in hash lists. Pick the first one and keep trying until we find the right one. */ @@ -166,11 +98,11 @@ fr30_cgen_lookup_insn (od, insn, insn_value, length, fields, alias_p) /* Basic bit mask must be correct. */ /* ??? May wish to allow target to defer this check until the extract handler. */ - if ((insn_value & CGEN_INSN_MASK (insn)) == CGEN_INSN_VALUE (insn)) + if ((base_insn & CGEN_INSN_MASK (insn)) == CGEN_INSN_VALUE (insn)) { /* ??? 0 is passed for `pc' */ int elength = (*CGEN_EXTRACT_FN (insn)) (od, insn, info, - insn_value, fields, + base_insn, fields, (bfd_vma) 0); if (elength > 0) { @@ -196,7 +128,7 @@ fr30_cgen_lookup_insn (od, insn, insn_value, length, fields, alias_p) abort (); /* ??? 0 is passed for `pc' */ - length = (*CGEN_EXTRACT_FN (insn)) (od, insn, info, insn_value, fields, + length = (*CGEN_EXTRACT_FN (insn)) (od, insn, info, base_insn, fields, (bfd_vma) 0); /* Sanity check: must succeed. Could relax this later if it ever proves useful. */ @@ -487,6 +419,9 @@ const CGEN_OPERAND fr30_cgen_operand_table[MAX_OPERANDS] = /* u10: 10 bit unsigned immediate */ { "u10", & HW_ENT (HW_H_UINT), 8, 8, { 0, 0|(1<f_u10; break; + case FR30_OPERAND_I32 : + value = fields->f_i32; + break; case FR30_OPERAND_DIR8 : value = fields->f_dir8; break; @@ -2373,6 +2328,9 @@ fr30_cgen_get_vma_operand (opindex, fields) case FR30_OPERAND_U10 : value = fields->f_u10; break; + case FR30_OPERAND_I32 : + value = fields->f_i32; + break; case FR30_OPERAND_DIR8 : value = fields->f_dir8; break; @@ -2469,6 +2427,9 @@ fr30_cgen_set_int_operand (opindex, fields, value) case FR30_OPERAND_U10 : fields->f_u10 = value; break; + case FR30_OPERAND_I32 : + fields->f_i32 = value; + break; case FR30_OPERAND_DIR8 : fields->f_dir8 = value; break; @@ -2558,6 +2519,9 @@ fr30_cgen_set_vma_operand (opindex, fields, value) case FR30_OPERAND_U10 : fields->f_u10 = value; break; + case FR30_OPERAND_I32 : + fields->f_i32 = value; + break; case FR30_OPERAND_DIR8 : fields->f_dir8 = value; break; diff --git a/opcodes/fr30-opc.h b/opcodes/fr30-opc.h index d272b2cba1..3754ae0800 100644 --- a/opcodes/fr30-opc.h +++ b/opcodes/fr30-opc.h @@ -38,12 +38,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #define CGEN_DEFAULT_INSN_BITSIZE 16 #define CGEN_BASE_INSN_BITSIZE 16 #define CGEN_MIN_INSN_BITSIZE 16 -#define CGEN_MAX_INSN_BITSIZE 16 +#define CGEN_MAX_INSN_BITSIZE 48 #define CGEN_DEFAULT_INSN_SIZE (CGEN_DEFAULT_INSN_BITSIZE / 8) #define CGEN_BASE_INSN_SIZE (CGEN_BASE_INSN_BITSIZE / 8) #define CGEN_MIN_INSN_SIZE (CGEN_MIN_INSN_BITSIZE / 8) #define CGEN_MAX_INSN_SIZE (CGEN_MAX_INSN_BITSIZE / 8) -#define CGEN_INT_INSN_P 1 +#define CGEN_INT_INSN_P 0 /* FIXME: Need to compute CGEN_MAX_SYNTAX_BYTES. */ @@ -139,10 +139,10 @@ typedef enum cgen_operand_type { , FR30_OPERAND_RS2, FR30_OPERAND_R13, FR30_OPERAND_R14, FR30_OPERAND_R15 , FR30_OPERAND_PS, FR30_OPERAND_U4, FR30_OPERAND_M4, FR30_OPERAND_U8 , FR30_OPERAND_I8, FR30_OPERAND_UDISP6, FR30_OPERAND_DISP8, FR30_OPERAND_DISP9 - , FR30_OPERAND_DISP10, FR30_OPERAND_S10, FR30_OPERAND_U10, FR30_OPERAND_DIR8 - , FR30_OPERAND_DIR9, FR30_OPERAND_DIR10, FR30_OPERAND_LABEL9, FR30_OPERAND_LABEL12 - , FR30_OPERAND_CC, FR30_OPERAND_NBIT, FR30_OPERAND_VBIT, FR30_OPERAND_ZBIT - , FR30_OPERAND_CBIT, FR30_OPERAND_MAX + , FR30_OPERAND_DISP10, FR30_OPERAND_S10, FR30_OPERAND_U10, FR30_OPERAND_I32 + , FR30_OPERAND_DIR8, FR30_OPERAND_DIR9, FR30_OPERAND_DIR10, FR30_OPERAND_LABEL9 + , FR30_OPERAND_LABEL12, FR30_OPERAND_CC, FR30_OPERAND_NBIT, FR30_OPERAND_VBIT + , FR30_OPERAND_ZBIT, FR30_OPERAND_CBIT, FR30_OPERAND_MAX } CGEN_OPERAND_TYPE; /* Non-boolean attributes. */ @@ -205,33 +205,33 @@ typedef enum cgen_insn_type { , FR30_INSN_DIV1, FR30_INSN_DIV2, FR30_INSN_DIV3, FR30_INSN_DIV4S , FR30_INSN_LSL, FR30_INSN_LSLI, FR30_INSN_LSL2, FR30_INSN_LSR , FR30_INSN_LSRI, FR30_INSN_LSR2, FR30_INSN_ASR, FR30_INSN_ASRI - , FR30_INSN_ASR2, FR30_INSN_LDI_8, FR30_INSN_LD, FR30_INSN_LDUH - , FR30_INSN_LDUB, FR30_INSN_LDR13, FR30_INSN_LDR13UH, FR30_INSN_LDR13UB - , FR30_INSN_LDR14, FR30_INSN_LDR14UH, FR30_INSN_LDR14UB, FR30_INSN_LDR15 - , FR30_INSN_LDR15GR, FR30_INSN_LDR15DR, FR30_INSN_LDR15PS, FR30_INSN_ST - , FR30_INSN_STH, FR30_INSN_STB, FR30_INSN_STR13, FR30_INSN_STR13H - , FR30_INSN_STR13B, FR30_INSN_STR14, FR30_INSN_STR14H, FR30_INSN_STR14B - , FR30_INSN_STR15, FR30_INSN_STR15GR, FR30_INSN_STR15DR, FR30_INSN_STR15PS - , FR30_INSN_MOV, FR30_INSN_MOVDR, FR30_INSN_MOVPS, FR30_INSN_MOV2DR - , FR30_INSN_MOV2PS, FR30_INSN_JMP, FR30_INSN_JMPD, FR30_INSN_CALL - , FR30_INSN_CALLD, FR30_INSN_CALLR, FR30_INSN_CALLRD, FR30_INSN_RET - , FR30_INSN_RETD, FR30_INSN_INT, FR30_INSN_INTE, FR30_INSN_RETI - , FR30_INSN_BRA, FR30_INSN_BNO, FR30_INSN_BEQ, FR30_INSN_BNE - , FR30_INSN_BC, FR30_INSN_BNC, FR30_INSN_BN, FR30_INSN_BP - , FR30_INSN_BV, FR30_INSN_BNV, FR30_INSN_BLT, FR30_INSN_BGE - , FR30_INSN_BLE, FR30_INSN_BGT, FR30_INSN_BLS, FR30_INSN_BHI - , FR30_INSN_BRAD, FR30_INSN_BNOD, FR30_INSN_BEQD, FR30_INSN_BNED - , FR30_INSN_BCD, FR30_INSN_BNCD, FR30_INSN_BND, FR30_INSN_BPD - , FR30_INSN_BVD, FR30_INSN_BNVD, FR30_INSN_BLTD, FR30_INSN_BGED - , FR30_INSN_BLED, FR30_INSN_BGTD, FR30_INSN_BLSD, FR30_INSN_BHID - , FR30_INSN_DMOV2R13, FR30_INSN_DMOV2R13H, FR30_INSN_DMOV2R13B, FR30_INSN_DMOVR13 - , FR30_INSN_DMOVR13H, FR30_INSN_DMOVR13B, FR30_INSN_DMOV2R13PI, FR30_INSN_DMOV2R13PIH - , FR30_INSN_DMOV2R13PIB, FR30_INSN_DMOVR13PI, FR30_INSN_DMOVR13PIH, FR30_INSN_DMOVR13PIB - , FR30_INSN_DMOV2R15PD, FR30_INSN_DMOVR15PI, FR30_INSN_LDRES, FR30_INSN_STRES - , FR30_INSN_NOP, FR30_INSN_ANDCCR, FR30_INSN_ORCCR, FR30_INSN_STILM - , FR30_INSN_ADDSP, FR30_INSN_EXTSB, FR30_INSN_EXTUB, FR30_INSN_EXTSH - , FR30_INSN_EXTUH, FR30_INSN_ENTER, FR30_INSN_LEAVE, FR30_INSN_XCHB - , FR30_INSN_MAX + , FR30_INSN_ASR2, FR30_INSN_LDI_8, FR30_INSN_LDI32, FR30_INSN_LD + , FR30_INSN_LDUH, FR30_INSN_LDUB, FR30_INSN_LDR13, FR30_INSN_LDR13UH + , FR30_INSN_LDR13UB, FR30_INSN_LDR14, FR30_INSN_LDR14UH, FR30_INSN_LDR14UB + , FR30_INSN_LDR15, FR30_INSN_LDR15GR, FR30_INSN_LDR15DR, FR30_INSN_LDR15PS + , FR30_INSN_ST, FR30_INSN_STH, FR30_INSN_STB, FR30_INSN_STR13 + , FR30_INSN_STR13H, FR30_INSN_STR13B, FR30_INSN_STR14, FR30_INSN_STR14H + , FR30_INSN_STR14B, FR30_INSN_STR15, FR30_INSN_STR15GR, FR30_INSN_STR15DR + , FR30_INSN_STR15PS, FR30_INSN_MOV, FR30_INSN_MOVDR, FR30_INSN_MOVPS + , FR30_INSN_MOV2DR, FR30_INSN_MOV2PS, FR30_INSN_JMP, FR30_INSN_JMPD + , FR30_INSN_CALL, FR30_INSN_CALLD, FR30_INSN_CALLR, FR30_INSN_CALLRD + , FR30_INSN_RET, FR30_INSN_RETD, FR30_INSN_INT, FR30_INSN_INTE + , FR30_INSN_RETI, FR30_INSN_BRA, FR30_INSN_BNO, FR30_INSN_BEQ + , FR30_INSN_BNE, FR30_INSN_BC, FR30_INSN_BNC, FR30_INSN_BN + , FR30_INSN_BP, FR30_INSN_BV, FR30_INSN_BNV, FR30_INSN_BLT + , FR30_INSN_BGE, FR30_INSN_BLE, FR30_INSN_BGT, FR30_INSN_BLS + , FR30_INSN_BHI, FR30_INSN_BRAD, FR30_INSN_BNOD, FR30_INSN_BEQD + , FR30_INSN_BNED, FR30_INSN_BCD, FR30_INSN_BNCD, FR30_INSN_BND + , FR30_INSN_BPD, FR30_INSN_BVD, FR30_INSN_BNVD, FR30_INSN_BLTD + , FR30_INSN_BGED, FR30_INSN_BLED, FR30_INSN_BGTD, FR30_INSN_BLSD + , FR30_INSN_BHID, FR30_INSN_DMOV2R13, FR30_INSN_DMOV2R13H, FR30_INSN_DMOV2R13B + , FR30_INSN_DMOVR13, FR30_INSN_DMOVR13H, FR30_INSN_DMOVR13B, FR30_INSN_DMOV2R13PI + , FR30_INSN_DMOV2R13PIH, FR30_INSN_DMOV2R13PIB, FR30_INSN_DMOVR13PI, FR30_INSN_DMOVR13PIH + , FR30_INSN_DMOVR13PIB, FR30_INSN_DMOV2R15PD, FR30_INSN_DMOVR15PI, FR30_INSN_LDRES + , FR30_INSN_STRES, FR30_INSN_NOP, FR30_INSN_ANDCCR, FR30_INSN_ORCCR + , FR30_INSN_STILM, FR30_INSN_ADDSP, FR30_INSN_EXTSB, FR30_INSN_EXTUB + , FR30_INSN_EXTSH, FR30_INSN_EXTUH, FR30_INSN_ENTER, FR30_INSN_LEAVE + , FR30_INSN_XCHB, FR30_INSN_MAX } CGEN_INSN_TYPE; /* Index of `invalid' insn place holder. */ @@ -261,6 +261,7 @@ struct cgen_fields long f_m4; long f_u8; long f_i8; + long f_i32; long f_udisp6; long f_disp8; long f_disp9; -- 2.34.1