From: Doug Evans Date: Wed, 6 Jan 1999 00:21:27 +0000 (+0000) Subject: * cgen-asm.in (insert_normal): Use CGEN_BOOL_ATTR. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5730d39d2cd1974c77899555dac466babc316589;p=binutils-gdb.git * cgen-asm.in (insert_normal): Use CGEN_BOOL_ATTR. * cgen-asm.in (extract_normal): Ditto. * fr30-asm.c,fr30-dis.c,fr30-opc.h,fr30-opc.c: Regenerate. * i960c-asm.c,i960c-dis.c,i960c-opc.h,i960c-opc.c: Regenerate. * m32r-asm.c,m32r-dis.c,m32r-opc.h,m32r-opc.c: Regenerate. --- diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index a6c46de07c0..c44ed052fac 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,15 @@ +1999-01-05 Doug Evans + +start-sanitize-cygnus + * cgen-asm.in (insert_normal): Use CGEN_BOOL_ATTR. + * cgen-asm.in (extract_normal): Ditto. +end-sanitize-cygnus +start-sanitize-fr30 + * fr30-asm.c,fr30-dis.c,fr30-opc.h,fr30-opc.c: Regenerate. +end-sanitize-fr30 + * i960c-asm.c,i960c-dis.c,i960c-opc.h,i960c-opc.c: Regenerate. + * m32r-asm.c,m32r-dis.c,m32r-opc.h,m32r-opc.c: Regenerate. + 1999-01-04 Jason Molenda (jsm@bugshack.cygnus.com) * configure.in: Require autoconf 2.12.1 or higher. diff --git a/opcodes/cgen-asm.in b/opcodes/cgen-asm.in index 681262d651d..27d6bb64022 100644 --- a/opcodes/cgen-asm.in +++ b/opcodes/cgen-asm.in @@ -30,127 +30,219 @@ along with this program; if not, write to the Free Software Foundation, Inc., #include "@prefix@-opc.h" #include "opintl.h" -/* ??? The layout of this stuff is still work in progress. - For speed in assembly/disassembly, we use inline functions. That of course - will only work for GCC. When this stuff is finished, we can decide whether - to keep the inline functions (and only get the performance increase when - compiled with GCC), or switch to macros, or use something else. -*/ +#undef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#undef max +#define max(a,b) ((a) > (b) ? (a) : (b)) + +#undef INLINE +#ifdef __GNUC__ +#define INLINE __inline__ +#else +#define INLINE +#endif + +/* Used by the ifield rtx function. */ +#define FLD(f) (fields->f) static const char * insert_normal - PARAMS ((long, unsigned int, int, int, int, char *)); + PARAMS ((CGEN_OPCODE_DESC, long, unsigned int, unsigned int, unsigned int, + unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR)); static const char * parse_insn_normal - PARAMS ((const CGEN_INSN *, const char **, CGEN_FIELDS *)); + PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *, + const char **, CGEN_FIELDS *)); static const char * insert_insn_normal - PARAMS ((const CGEN_INSN *, CGEN_FIELDS *, cgen_insn_t *, bfd_vma)); + PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *, + CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma)); /* -- assembler routines inserted here */ +#if ! CGEN_INT_INSN_P + +/* Subroutine of insert_normal. */ + +static INLINE void +insert_1 (od, value, start, length, word_length, bufp) + CGEN_OPCODE_DESC od; + unsigned long value; + int start,length,word_length; + unsigned char *bufp; +{ + unsigned long x,mask; + int shift; + int big_p = CGEN_OPCODE_INSN_ENDIAN (od) == CGEN_ENDIAN_BIG; + + switch (word_length) + { + case 8: + x = *bufp; + break; + case 16: + if (big_p) + x = bfd_getb16 (bufp); + else + x = bfd_getl16 (bufp); + break; + case 24: + /* ??? 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 = (bufp[0] << 16) | bfd_getb16 (bufp + 1); + else + x = bfd_getl16 (bufp) | (bufp[2] << 16); + break; + case 32: + if (big_p) + x = bfd_getb32 (bufp); + else + x = bfd_getl32 (bufp); + break; + default : + abort (); + } + + /* Written this way to avoid undefined behaviour. */ + mask = (((1L << (length - 1)) - 1) << 1) | 1; + if (CGEN_INSN_LSB0_P) + shift = (start + 1) - length; + else + shift = (word_length - (start + length)); + x = (x & ~(mask << shift)) | ((value & mask) << shift); + + switch (word_length) + { + case 8: + *bufp = x; + break; + case 16: + if (big_p) + bfd_putb16 (x, bufp); + else + bfd_putl16 (x, bufp); + break; + case 24: + /* ??? 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) + { + bufp[0] = x >> 16; + bfd_putb16 (x, bufp + 1); + } + else + { + bfd_putl16 (x, bufp); + bufp[2] = x >> 16; + } + break; + case 32: + if (big_p) + bfd_putb32 (x, bufp); + else + bfd_putl32 (x, bufp); + break; + default : + abort (); + } +} + +#endif /* ! CGEN_INT_INSN_P */ + /* Default insertion routine. ATTRS is a mask of the boolean attributes. + WORD_OFFSET is the offset in bits from the start of the insn of the value. + WORD_LENGTH is the length of the word in bits in which the value resides. + START is the starting bit number in the word, architecture origin. LENGTH is the length of VALUE in bits. - TOTAL_LENGTH is the total length of the insn (currently 8,16,32). + TOTAL_LENGTH is the total length of the insn in bits. The result is an error message or NULL if success. */ /* ??? This duplicates functionality with bfd's howto table and bfd_install_relocation. */ -/* ??? For architectures where insns can be representable as ints, - store insn in `field' struct and add registers, etc. while parsing? */ +/* ??? This doesn't handle bfd_vma's. Create another function when + necessary. */ static const char * -insert_normal (value, attrs, start, length, total_length, buffer) +insert_normal (od, value, attrs, word_offset, start, length, word_length, + total_length, buffer) + CGEN_OPCODE_DESC od; long value; unsigned int attrs; - int start; - int length; - int total_length; - char * buffer; + unsigned int word_offset, start, length, word_length, total_length; + CGEN_INSN_BYTES_PTR buffer; { - bfd_vma x; - static char buf[100]; - /* Written this way to avoid undefined behaviour. - Yes, `long' will be bfd_vma but not yet. */ - long mask = (((1L << (length - 1)) - 1) << 1) | 1; + static char errbuf[100]; + /* Written this way to avoid undefined behaviour. */ + unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1; /* If LENGTH is zero, this operand doesn't contribute to the value. */ if (length == 0) return NULL; + if (CGEN_INT_INSN_P + && word_offset != 0) + abort (); + + if (word_length > 32) + abort (); + + /* For architectures with insns smaller than the insn-base-bitsize, + word_length may be too big. */ +#if CGEN_MIN_INSN_BITSIZE < CGEN_BASE_INSN_BITSIZE + if (word_offset == 0 + && word_length > total_length) + word_length = total_length; +#endif + /* Ensure VALUE will fit. */ - if ((attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED)) != 0) + if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED)) { - unsigned long max = mask; - if ((unsigned long) value > max) + unsigned long maxval = mask; + if ((unsigned long) value > maxval) { /* xgettext:c-format */ - sprintf (buf, _("operand out of range (%lu not between 0 and %lu)"), - value, max); - return buf; + sprintf (errbuf, + _("operand out of range (%lu not between 0 and %lu)"), + value, maxval); + return errbuf; } } else { - long min = - (1L << (length - 1)); - long max = (1L << (length - 1)) - 1; - if (value < min || value > max) + long minval = - (1L << (length - 1)); + long maxval = (1L << (length - 1)) - 1; + if (value < minval || value > maxval) { sprintf /* xgettext:c-format */ - (buf, _("operand out of range (%ld not between %ld and %ld)"), - value, min, max); - return buf; + (errbuf, _("operand out of range (%ld not between %ld and %ld)"), + value, minval, maxval); + return errbuf; } } -#if 0 /*def CGEN_INT_INSN*/ - *buffer |= (value & mask) << (total_length - (start + length)); -#else - switch (total_length) - { - case 8: - x = * (unsigned char *) buffer; - break; - case 16: - if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) - x = bfd_getb16 (buffer); - else - x = bfd_getl16 (buffer); - break; - case 32: - if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) - x = bfd_getb32 (buffer); - else - x = bfd_getl32 (buffer); - break; - default : - abort (); - } +#if CGEN_INT_INSN_P - x |= (value & mask) << (total_length - (start + length)); + { + int shift; - switch (total_length) - { - case 8: - * buffer = value; - break; - case 16: - if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) - bfd_putb16 (x, buffer); - else - bfd_putl16 (x, buffer); - break; - case 32: - if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) - bfd_putb32 (x, buffer); - else - bfd_putl32 (x, buffer); - break; - default : - abort (); - } -#endif + if (CGEN_INSN_LSB0_P) + shift = (start + 1) - length; + else + shift = word_length - (start + length); + *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift); + } + +#else /* ! CGEN_INT_INSN_P */ + + { + unsigned char *bufp = (unsigned char *) buffer + word_offset / 8; + + insert_1 (od, value, start, length, word_length, bufp); + } + +#endif /* ! CGEN_INT_INSN_P */ return NULL; } @@ -170,7 +262,8 @@ insert_normal (value, attrs, start, length, total_length, buffer) */ static const char * -parse_insn_normal (insn, strp, fields) +parse_insn_normal (od, insn, strp, fields) + CGEN_OPCODE_DESC od; const CGEN_INSN * insn; const char ** strp; CGEN_FIELDS * fields; @@ -186,23 +279,25 @@ parse_insn_normal (insn, strp, fields) #endif /* For now we assume the mnemonic is first (there are no leading operands). - We can parse it without needing to set up operand parsing. */ + We can parse it without needing to set up operand parsing. + GAS's input scrubber will ensure mnemonics are lowercase, but we may + not be called from GAS. */ p = CGEN_INSN_MNEMONIC (insn); - while (* p && * p == * str) - ++ p, ++ str; + while (*p && tolower (*p) == tolower (*str)) + ++p, ++str; if (* p || (* str && !isspace (* str))) return _("unrecognized instruction"); - CGEN_INIT_PARSE (); - cgen_init_parse_operand (); + CGEN_INIT_PARSE (od); + cgen_init_parse_operand (od); #ifdef CGEN_MNEMONIC_OPERANDS past_opcode_p = 0; #endif /* We don't check for (*str != '\0') here because we want to parse any trailing fake arguments in the syntax string. */ - syn = CGEN_SYNTAX_STRING (CGEN_INSN_SYNTAX (insn)); + syn = CGEN_SYNTAX_STRING (syntax); /* Mnemonics come first for now, ensure valid string. */ if (! CGEN_SYNTAX_MNEMONIC_P (* syn)) @@ -235,8 +330,8 @@ parse_insn_normal (insn, strp, fields) } /* We have an operand of some sort. */ - errmsg = @arch@_cgen_parse_operand (CGEN_SYNTAX_FIELD (*syn), - &str, fields); + errmsg = @arch@_cgen_parse_operand (od, CGEN_SYNTAX_FIELD (*syn), + &str, fields); if (errmsg) return errmsg; @@ -261,59 +356,50 @@ parse_insn_normal (insn, strp, fields) } /* We couldn't parse it. */ - return "unrecognized instruction"; + return _("unrecognized instruction"); } /* Default insn builder (insert handler). - The instruction is recorded in target byte order. + 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 result is an error message or NULL if success. */ -/* FIXME: change buffer to char *? */ static const char * -insert_insn_normal (insn, fields, buffer, pc) +insert_insn_normal (od, insn, fields, buffer, pc) + CGEN_OPCODE_DESC od; const CGEN_INSN * insn; CGEN_FIELDS * fields; - cgen_insn_t * buffer; + CGEN_INSN_BYTES_PTR buffer; bfd_vma pc; { const CGEN_SYNTAX * syntax = CGEN_INSN_SYNTAX (insn); - bfd_vma value; + unsigned long value; const unsigned char * syn; - CGEN_INIT_INSERT (); - value = CGEN_INSN_VALUE (insn); + CGEN_INIT_INSERT (od); + value = CGEN_INSN_BASE_VALUE (insn); /* If we're recording insns as numbers (rather than a string of bytes), target byte order handling is deferred until later. */ -#undef min -#define min(a,b) ((a) < (b) ? (a) : (b)) -#if 0 /*def CGEN_INT_INSN*/ + +#if CGEN_INT_INSN_P + *buffer = value; + #else - switch (min (CGEN_BASE_INSN_BITSIZE, CGEN_FIELDS_BITSIZE (fields))) - { - case 8: - * buffer = value; - break; - case 16: - if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) - bfd_putb16 (value, (char *) buffer); - else - bfd_putl16 (value, (char *) buffer); - break; - case 32: - if (CGEN_CURRENT_ENDIAN == CGEN_ENDIAN_BIG) - bfd_putb32 (value, (char *) buffer); - else - bfd_putl32 (value, (char *) buffer); - break; - default: - abort (); - } -#endif - /* ??? Rather than scanning the syntax string again, we could store - in `fields' a null terminated list of the fields that are present. */ + cgen_put_insn_value (od, buffer, min (CGEN_BASE_INSN_BITSIZE, + CGEN_FIELDS_BITSIZE (fields)), + value); + +#endif /* ! CGEN_INT_INSN_P */ + + /* ??? It would be better to scan the format's fields. + Still need to be able to insert a value based on the operand though; + e.g. storing a branch displacement that got resolved later. + Needs more thought first. */ for (syn = CGEN_SYNTAX_STRING (syntax); * syn != '\0'; ++ syn) { @@ -322,8 +408,8 @@ insert_insn_normal (insn, fields, buffer, pc) if (CGEN_SYNTAX_CHAR_P (* syn)) continue; - errmsg = @arch@_cgen_insert_operand (CGEN_SYNTAX_FIELD (*syn), fields, - (char *) buffer, pc); + errmsg = @arch@_cgen_insert_operand (od, CGEN_SYNTAX_FIELD (*syn), + fields, buffer, pc); if (errmsg) return errmsg; } @@ -335,8 +421,10 @@ insert_insn_normal (insn, fields, buffer, pc) This routine is called for each instruction to be assembled. STR points to the insn to be assembled. We assume all necessary tables have been initialized. - The assembled instruction, less any fixups, is stored in buf. - [??? What byte order?] + The assembled instruction, less any fixups, is stored in BUF. + Remember that if CGEN_INT_INSN_P then BUF is an int and thus the value + still needs to be converted to target byte order, otherwise BUF is an array + of bytes in target byte order. The result is a pointer to the insn's entry in the opcode table, or NULL if an error occured (an error message will have already been printed). @@ -345,10 +433,11 @@ insert_insn_normal (insn, fields, buffer, pc) this function recurses. */ const CGEN_INSN * -@arch@_cgen_assemble_insn (str, fields, buf, errmsg) +@arch@_cgen_assemble_insn (od, str, fields, buf, errmsg) + CGEN_OPCODE_DESC od; const char * str; CGEN_FIELDS * fields; - cgen_insn_t * buf; + CGEN_INSN_BYTES_PTR buf; char ** errmsg; { const char * start; @@ -360,7 +449,7 @@ const CGEN_INSN * /* The instructions are stored in hashed lists. Get the first in the list. */ - ilist = CGEN_ASM_LOOKUP_INSN (str); + ilist = CGEN_ASM_LOOKUP_INSN (od, str); /* Keep looking until we find a match. */ @@ -371,7 +460,7 @@ const CGEN_INSN * #if 0 /* not needed as unsupported opcodes shouldn't be in the hash lists */ /* Is this insn supported by the selected cpu? */ - if (! @arch@_cgen_insn_supported (insn)) + if (! @arch@_cgen_insn_supported (od, insn)) continue; #endif @@ -383,15 +472,13 @@ const CGEN_INSN * str = start; - /* Record a default length for the insn. This will get set to the - correct value while parsing. */ - /* FIXME: wip */ + /* Allow parse/insert handlers to obtain length of insn. */ CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); - if (! CGEN_PARSE_FN (insn) (insn, & str, fields)) + if (! CGEN_PARSE_FN (insn) (od, insn, & str, fields)) { /* ??? 0 is passed for `pc' */ - if (CGEN_INSERT_FN (insn) (insn, fields, buf, (bfd_vma) 0) != NULL) + if (CGEN_INSERT_FN (insn) (od, insn, fields, buf, (bfd_vma) 0) != NULL) continue; /* It is up to the caller to actually output the insn and any queued relocs. */ @@ -427,7 +514,8 @@ const CGEN_INSN * FIXME: Not currently used. */ void -@arch@_cgen_asm_hash_keywords (opvals) +@arch@_cgen_asm_hash_keywords (od, opvals) + CGEN_OPCODE_DESC od; CGEN_KEYWORD * opvals; { CGEN_KEYWORD_SEARCH search = cgen_keyword_search_init (opvals, NULL); @@ -439,7 +527,7 @@ void if (! @arch@_cgen_opval_supported (ke)) continue; #endif - cgen_asm_record_register (ke->name, ke->value); + cgen_asm_record_register (od, ke->name, ke->value); } } diff --git a/opcodes/cgen-dis.in b/opcodes/cgen-dis.in index 77edb9a210f..31a6afd9954 100644 --- a/opcodes/cgen-dis.in +++ b/opcodes/cgen-dis.in @@ -40,9 +40,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., /* Default text to print if an instruction isn't recognized. */ #define UNKNOWN_INSN_MSG _("*unknown*") +/* Used by the ifield rtx function. */ +#define FLD(f) (fields->f) + 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, unsigned int, unsigned int, unsigned int, + unsigned int, unsigned 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 +55,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)); @@ -64,21 +68,68 @@ static int default_print_insn #if ! CGEN_INT_INSN_P +/* Subroutine of extract_normal. + Ensure sufficient bytes are cached in EX_INFO. + OFFSET is the offset in bytes from the start of the insn of the value. + BYTES is the length of the needed value. + Returns 1 for success, 0 for failure. */ + +static INLINE int +fill_cache (od, ex_info, offset, bytes, pc) + CGEN_OPCODE_DESC od; + CGEN_EXTRACT_INFO *ex_info; + int offset, bytes; + bfd_vma pc; +{ + /* It's doubtful that the middle part has already been fetched so + we don't optimize that case. kiss. */ + int mask; + disassemble_info *info = (disassemble_info *) ex_info->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: @@ -94,9 +145,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) @@ -111,7 +162,7 @@ extract_1 (od, ex_info, start, length, word_length, bufp) /* Written this way to avoid undefined behaviour. */ mask = (((1L << (length - 1)) - 1) << 1) | 1; if (CGEN_INSN_LSB0_P) - shift = start; + shift = (start + 1) - length; else shift = (word_length - (start + length)); return (x >> shift) & mask; @@ -121,22 +172,36 @@ extract_1 (od, ex_info, start, length, word_length, bufp) /* Default extraction routine. - ATTRS is a mask of the boolean attributes. We only need `unsigned', - but for generality we take a bitmask of all of them. */ + 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. + WORD_OFFSET is the offset in bits from the start of the insn of the value. + WORD_LENGTH is the length of the word in bits in which the value resides. + START is the starting bit number in the word, architecture origin. + LENGTH is the length of VALUE in bits. + TOTAL_LENGTH is the total length of the insn in bits. + + Returns 1 for success, 0 for failure. */ + +/* ??? The return code isn't properly used. wip. */ /* ??? 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, word_offset, start, length, + word_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; + unsigned int word_offset, start, length, word_length, total_length; + bfd_vma pc; long *valuep; { - unsigned long value; + CGEN_INSN_INT value; /* If LENGTH is zero, this operand doesn't contribute to the value so give it a standard value of zero. */ @@ -146,100 +211,58 @@ extract_normal (od, ex_info, insn_value, attrs, start, length, total_length, val return 1; } -#if CGEN_INT_INSN_P + if (CGEN_INT_INSN_P + && word_offset != 0) + abort (); - { - /* Written this way to avoid undefined behaviour. */ - unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1; + if (word_length > 32) + abort (); - 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; - } + /* For architectures with insns smaller than the insn-base-bitsize, + word_length may be too big. */ +#if CGEN_MIN_INSN_BITSIZE < CGEN_BASE_INSN_BITSIZE + if (word_offset == 0 + && word_length > total_length) + word_length = total_length; +#endif -#else + /* Does the value reside in INSN_VALUE? */ - /* 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 - to be when a field straddles a (loosely defined) word boundary - (??? which may require target specific help to determine). */ + if (word_offset == 0) + { + /* Written this way to avoid undefined behaviour. */ + CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1; -#if 0 /*wip*/ + if (CGEN_INSN_LSB0_P) + value = insn_value >> ((start + 1) - length); + else + value = insn_value >> (word_length - (start + length)); + value &= mask; + /* sign extend? */ + if (! CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED) + && (value & (1L << (length - 1)))) + value |= ~mask; + } -#define HARD_CASE_P 0 /* FIXME:wip */ +#if ! CGEN_INT_INSN_P - if (HARD_CASE_P) - { - } -#endif else { - unsigned char *bufp = (unsigned char *) insn_value; + unsigned char *bufp = ex_info->insn_bytes + word_offset / 8; - if (length > 32) + if (word_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 - 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). */ - - if (total_length > 32) - { - int needed_width = start % 8 + length; - int fetch_length = (needed_width <= 8 ? 8 - : needed_width <= 16 ? 16 - : 32); - - if (CGEN_INSN_LSB0_P) - { - if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG) - { - abort (); /* wip */ - } - else - { - int offset = start & ~7; - - bufp += offset / 8; - start -= offset; - total_length -= offset; - } - } - else - { - if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG) - { - int offset = start & ~7; - - bufp += offset / 8; - start -= offset; - total_length -= offset; - } - else - { - abort (); /* wip */ - } - } - } + if (fill_cache (od, ex_info, word_offset / 8, word_length / 8, pc) == 0) + return 0; - /* FIXME: which bytes are being extracted have been lost. */ - value = extract_1 (od, ex_info, start, length, total_length, bufp); + value = extract_1 (od, ex_info, start, length, word_length, bufp, pc); } #endif /* ! CGEN_INT_INSN_P */ *valuep = value; - /* FIXME: for now */ return 1; } @@ -333,7 +356,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; { @@ -420,7 +443,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) { @@ -456,7 +479,8 @@ print_insn (od, 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_MASK (insn)) == CGEN_INSN_VALUE (insn)) + if ((insn_value & CGEN_INSN_BASE_MASK (insn)) + == CGEN_INSN_BASE_VALUE (insn)) { /* Printing is handled in two passes. The first pass parses the machine insn and extracts the fields. The second pass prints diff --git a/opcodes/fr30-asm.c b/opcodes/fr30-asm.c index 05f9e71c1e7..8094201310a 100644 --- a/opcodes/fr30-asm.c +++ b/opcodes/fr30-asm.c @@ -79,12 +79,13 @@ parse_register_number (strp) } static const char * -parse_register_list (od, strp, opindex, valuep, high_low) +parse_register_list (od, strp, opindex, valuep, high_low, load_store) CGEN_OPCODE_DESC od; const char **strp; int opindex; unsigned long *valuep; - int high_low; + int high_low; /* 0 == high, 1 == low */ + int load_store; /* 0 == load, 1 == store */ { int regno; *valuep = 0; @@ -105,7 +106,10 @@ parse_register_list (od, strp, opindex, valuep, high_low) if (high_low) regno -= 8; - *valuep |= 1 << regno; + if (load_store) /* mask is reversed for store */ + *valuep |= 0x80 >> regno; + else + *valuep |= 1 << regno; if (**strp == ',') { @@ -122,23 +126,43 @@ parse_register_list (od, strp, opindex, valuep, high_low) } static const char * -parse_low_register_list (od, strp, opindex, valuep) +parse_low_register_list_ld (od, strp, opindex, valuep) CGEN_OPCODE_DESC od; const char **strp; int opindex; unsigned long *valuep; { - return parse_register_list (od, strp, opindex, valuep, 0/*low*/); + return parse_register_list (od, strp, opindex, valuep, 0/*low*/, 0/*load*/); } static const char * -parse_hi_register_list (od, strp, opindex, valuep) +parse_hi_register_list_ld (od, strp, opindex, valuep) CGEN_OPCODE_DESC od; const char **strp; int opindex; unsigned long *valuep; { - return parse_register_list (od, strp, opindex, valuep, 1/*high*/); + return parse_register_list (od, strp, opindex, valuep, 1/*high*/, 0/*load*/); +} + +static const char * +parse_low_register_list_st (od, strp, opindex, valuep) + CGEN_OPCODE_DESC od; + const char **strp; + int opindex; + unsigned long *valuep; +{ + return parse_register_list (od, strp, opindex, valuep, 0/*low*/, 1/*store*/); +} + +static const char * +parse_hi_register_list_st (od, strp, opindex, valuep) + CGEN_OPCODE_DESC od; + const char **strp; + int opindex; + unsigned long *valuep; +{ + return parse_register_list (od, strp, opindex, valuep, 1/*high*/, 1/*store*/); } /* -- */ @@ -266,11 +290,17 @@ fr30_cgen_parse_operand (od, opindex, strp, fields) fields->f_rel12 = value; } break; - case FR30_OPERAND_REGLIST_LOW : - errmsg = parse_low_register_list (od, strp, FR30_OPERAND_REGLIST_LOW, &fields->f_reglist_low); + case FR30_OPERAND_REGLIST_LOW_LD : + errmsg = parse_low_register_list_ld (od, strp, FR30_OPERAND_REGLIST_LOW_LD, &fields->f_reglist_low_ld); + break; + case FR30_OPERAND_REGLIST_HI_LD : + errmsg = parse_hi_register_list_ld (od, strp, FR30_OPERAND_REGLIST_HI_LD, &fields->f_reglist_hi_ld); + break; + case FR30_OPERAND_REGLIST_LOW_ST : + errmsg = parse_low_register_list_st (od, strp, FR30_OPERAND_REGLIST_LOW_ST, &fields->f_reglist_low_st); break; - case FR30_OPERAND_REGLIST_HI : - errmsg = parse_hi_register_list (od, strp, FR30_OPERAND_REGLIST_HI, &fields->f_reglist_hi); + case FR30_OPERAND_REGLIST_HI_ST : + errmsg = parse_hi_register_list_st (od, strp, FR30_OPERAND_REGLIST_HI_ST, &fields->f_reglist_hi_st); break; case FR30_OPERAND_CC : errmsg = cgen_parse_unsigned_integer (od, strp, FR30_OPERAND_CC, &fields->f_cc); @@ -372,27 +402,27 @@ fr30_cgen_insert_operand (od, opindex, fields, buffer, pc) } break; case FR30_OPERAND_DISP8 : - errmsg = insert_normal (od, fields->f_disp8, 0|(1<f_disp8, 0|(1<f_disp9; value = ((int) (value) >> (1)); - errmsg = insert_normal (od, value, 0|(1<f_disp10; value = ((int) (value) >> (2)); - errmsg = insert_normal (od, value, 0|(1<f_s10; value = ((int) (value) >> (2)); - errmsg = insert_normal (od, value, 0|(1<f_rel9; value = ((int) (((value) - (((pc) + (2))))) >> (1)); - errmsg = insert_normal (od, value, 0|(1<f_rel12; value = ((int) (((value) - (((pc) + (2))))) >> (1)); - errmsg = insert_normal (od, value, 0|(1<f_reglist_low, 0|(1<f_reglist_low_ld, 0|(1<f_reglist_hi_ld, 0|(1<f_reglist_low_st, 0|(1<f_reglist_hi, 0|(1<f_reglist_hi_st, 0|(1<f_cc, 0|(1< maxval) diff --git a/opcodes/fr30-dis.c b/opcodes/fr30-dis.c index 0f62aae40b2..f171395cbea 100644 --- a/opcodes/fr30-dis.c +++ b/opcodes/fr30-dis.c @@ -68,28 +68,57 @@ static int default_print_insn /* -- dis.c */ static void -print_register_list (dis_info, value, offset) +print_register_list (dis_info, value, offset, load_store) PTR dis_info; long value; long offset; + int load_store; /* 0 == load, 1 == store */ { disassemble_info *info = dis_info; - int mask = 1; + int mask; int index = 0; + char* comma = ""; - if (value & mask) - (*info->fprintf_func) (info->stream, "r%i", index + offset); + if (load_store) + mask = 0x80; + else + mask = 1; + if (value & mask) + { + (*info->fprintf_func) (info->stream, "r%i", index + offset); + comma = ","; + } + for (index = 1; index <= 7; ++index) { - mask <<= 1; + if (load_store) + mask >>= 1; + else + mask <<= 1; + if (value & mask) - (*info->fprintf_func) (info->stream, ",r%i", index + offset); + { + (*info->fprintf_func) (info->stream, "%sr%i", comma, index + offset); + comma = ","; + } } } static void -print_hi_register_list (od, dis_info, value, attrs, pc, length) +print_hi_register_list_ld (od, dis_info, value, attrs, pc, length) + CGEN_OPCODE_DESC od; + PTR dis_info; + long value; + unsigned int attrs; + bfd_vma pc; + int length; +{ + print_register_list (dis_info, value, 8, 0/*load*/); +} + +static void +print_low_register_list_ld (od, dis_info, value, attrs, pc, length) CGEN_OPCODE_DESC od; PTR dis_info; long value; @@ -97,11 +126,11 @@ print_hi_register_list (od, dis_info, value, attrs, pc, length) bfd_vma pc; int length; { - print_register_list (dis_info, value, 8); + print_register_list (dis_info, value, 0, 0/*load*/); } static void -print_low_register_list (od, dis_info, value, attrs, pc, length) +print_hi_register_list_st (od, dis_info, value, attrs, pc, length) CGEN_OPCODE_DESC od; PTR dis_info; long value; @@ -109,7 +138,19 @@ print_low_register_list (od, dis_info, value, attrs, pc, length) bfd_vma pc; int length; { - print_register_list (dis_info, value, 0); + print_register_list (dis_info, value, 8, 1/*store*/); +} + +static void +print_low_register_list_st (od, dis_info, value, attrs, pc, length) + CGEN_OPCODE_DESC od; + PTR dis_info; + long value; + unsigned int attrs; + bfd_vma pc; + int length; +{ + print_register_list (dis_info, value, 0, 1/*store*/); } static void @@ -211,12 +252,12 @@ fr30_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc) } 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; } @@ -224,7 +265,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; } @@ -232,7 +273,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; } @@ -287,7 +328,7 @@ do { case FR30_OPERAND_LABEL9 : { long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_rel9 = value; } @@ -295,16 +336,22 @@ do { case FR30_OPERAND_LABEL12 : { long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_rel12 = value; } break; - case FR30_OPERAND_REGLIST_LOW : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_reglist_low); + case FR30_OPERAND_REGLIST_LOW_LD : + length = extract_normal (od, ex_info, insn_value, 0|(1<f_reglist_low_ld); break; - case FR30_OPERAND_REGLIST_HI : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_reglist_hi); + case FR30_OPERAND_REGLIST_HI_LD : + length = extract_normal (od, ex_info, insn_value, 0|(1<f_reglist_hi_ld); + break; + case FR30_OPERAND_REGLIST_LOW_ST : + length = extract_normal (od, ex_info, insn_value, 0|(1<f_reglist_low_st); + break; + case FR30_OPERAND_REGLIST_HI_ST : + length = extract_normal (od, ex_info, insn_value, 0|(1<f_reglist_hi_st); break; case FR30_OPERAND_CC : length = extract_normal (od, ex_info, insn_value, 0|(1<f_cc); @@ -401,16 +448,16 @@ fr30_cgen_print_operand (od, opindex, info, fields, attrs, pc, length) print_normal (od, info, fields->f_udisp6, 0|(1<f_disp8, 0|(1<f_disp8, 0|(1<f_disp9, 0|(1<f_disp9, 0|(1<f_disp10, 0|(1<f_disp10, 0|(1<f_s10, 0|(1<f_s10, 0|(1<f_u10, 0|(1<f_dir10, 0|(1<f_rel9, 0|(1<f_rel9, 0|(1<f_rel12, 0|(1<f_rel12, 0|(1<f_reglist_low_ld, 0|(1<f_reglist_hi_ld, 0|(1<f_reglist_low, 0|(1<f_reglist_low_st, 0|(1<f_reglist_hi, 0|(1<f_reglist_hi_st, 0|(1<f_cc, 0|(1<> (word_length - (start + length)); value &= mask; /* sign extend? */ - if (! (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED)) + if (! CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED) && (value & (1L << (length - 1)))) value |= ~mask; } diff --git a/opcodes/fr30-opc.c b/opcodes/fr30-opc.c index fce7b483c41..2c78e4aeaac 100644 --- a/opcodes/fr30-opc.c +++ b/opcodes/fr30-opc.c @@ -202,6 +202,13 @@ fr30_cgen_lookup_get_insn_operands (od, insn, insn_value, length, indices) } /* Attributes. */ +static const CGEN_ATTR_ENTRY bool_attr[] = +{ + { "#f", 0 }, + { "#t", 1 }, + { 0, 0 } +}; + static const CGEN_ATTR_ENTRY MACH_attr[] = { { "base", MACH_BASE }, @@ -210,43 +217,61 @@ static const CGEN_ATTR_ENTRY MACH_attr[] = { 0, 0 } }; +const CGEN_ATTR_TABLE fr30_cgen_ifield_attr_table[] = +{ + { "MACH", & MACH_attr[0] }, + { "VIRTUAL", &bool_attr[0], &bool_attr[0] }, + { "UNSIGNED", &bool_attr[0], &bool_attr[0] }, + { "PCREL-ADDR", &bool_attr[0], &bool_attr[0] }, + { "ABS-ADDR", &bool_attr[0], &bool_attr[0] }, + { "RESERVED", &bool_attr[0], &bool_attr[0] }, + { "SIGN-OPT", &bool_attr[0], &bool_attr[0] }, + { 0, 0, 0 } +}; + const CGEN_ATTR_TABLE fr30_cgen_hardware_attr_table[] = { - { "CACHE-ADDR", NULL }, - { "FUN-ACCESS", NULL }, - { "PC", NULL }, - { "PROFILE", NULL }, - { 0, 0 } + { "MACH", & MACH_attr[0] }, + { "VIRTUAL", &bool_attr[0], &bool_attr[0] }, + { "UNSIGNED", &bool_attr[0], &bool_attr[0] }, + { "SIGNED", &bool_attr[0], &bool_attr[0] }, + { "CACHE-ADDR", &bool_attr[0], &bool_attr[0] }, + { "FUN-ACCESS", &bool_attr[0], &bool_attr[0] }, + { "PC", &bool_attr[0], &bool_attr[0] }, + { "PROFILE", &bool_attr[0], &bool_attr[0] }, + { 0, 0, 0 } }; const CGEN_ATTR_TABLE fr30_cgen_operand_attr_table[] = { - { "ABS-ADDR", NULL }, - { "HASH-PREFIX", NULL }, - { "NEGATIVE", NULL }, - { "PCREL-ADDR", NULL }, - { "RELAX", NULL }, - { "SEM-ONLY", NULL }, - { "SIGN-OPT", NULL }, - { "SIGNED", NULL }, - { "UNSIGNED", NULL }, - { "VIRTUAL", NULL }, - { 0, 0 } + { "MACH", & MACH_attr[0] }, + { "VIRTUAL", &bool_attr[0], &bool_attr[0] }, + { "UNSIGNED", &bool_attr[0], &bool_attr[0] }, + { "PCREL-ADDR", &bool_attr[0], &bool_attr[0] }, + { "ABS-ADDR", &bool_attr[0], &bool_attr[0] }, + { "SIGN-OPT", &bool_attr[0], &bool_attr[0] }, + { "NEGATIVE", &bool_attr[0], &bool_attr[0] }, + { "RELAX", &bool_attr[0], &bool_attr[0] }, + { "SEM-ONLY", &bool_attr[0], &bool_attr[0] }, + { "HASH-PREFIX", &bool_attr[0], &bool_attr[0] }, + { 0, 0, 0 } }; const CGEN_ATTR_TABLE fr30_cgen_insn_attr_table[] = { - { "ALIAS", NULL }, - { "COND-CTI", NULL }, - { "DELAY-SLOT", NULL }, - { "NO-DIS", NULL }, - { "NOT-IN-DELAY-SLOT", NULL }, - { "RELAX", NULL }, - { "RELAXABLE", NULL }, - { "SKIP-CTI", NULL }, - { "UNCOND-CTI", NULL }, - { "VIRTUAL", NULL }, - { 0, 0 } + { "MACH", & MACH_attr[0] }, + { "VIRTUAL", &bool_attr[0], &bool_attr[0] }, + { "UNCOND-CTI", &bool_attr[0], &bool_attr[0] }, + { "COND-CTI", &bool_attr[0], &bool_attr[0] }, + { "SKIP-CTI", &bool_attr[0], &bool_attr[0] }, + { "DELAY-SLOT", &bool_attr[0], &bool_attr[0] }, + { "RELAXABLE", &bool_attr[0], &bool_attr[0] }, + { "RELAX", &bool_attr[0], &bool_attr[0] }, + { "ALIAS", &bool_attr[0], &bool_attr[0] }, + { "NO-DIS", &bool_attr[0], &bool_attr[0] }, + { "PBB", &bool_attr[0], &bool_attr[0] }, + { "NOT-IN-DELAY-SLOT", &bool_attr[0], &bool_attr[0] }, + { 0, 0, 0 } }; CGEN_KEYWORD_ENTRY fr30_cgen_opval_h_gr_entries[] = @@ -370,31 +395,31 @@ CGEN_KEYWORD fr30_cgen_opval_h_r15 = #define HW_ENT(n) fr30_cgen_hw_entries[n] static const CGEN_HW_ENTRY fr30_cgen_hw_entries[] = { - { HW_H_PC, & HW_ENT (HW_H_PC + 1), "h-pc", CGEN_ASM_KEYWORD, (PTR) 0, { 0, 0|(1<f_br_disp; value = ((int) (((value) - (pc))) >> (2)); - errmsg = insert_normal (od, value, 0|(1<f_ctrl_disp; value = ((int) (((value) - (pc))) >> (2)); - errmsg = insert_normal (od, value, 0|(1< maxval) diff --git a/opcodes/i960c-dis.c b/opcodes/i960c-dis.c index 4985fec0b6f..9d6d9e0a75b 100644 --- a/opcodes/i960c-dis.c +++ b/opcodes/i960c-dis.c @@ -136,7 +136,7 @@ i960_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc) case I960_OPERAND_BR_DISP : { long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_br_disp = value; } @@ -147,7 +147,7 @@ i960_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc) case I960_OPERAND_CTRL_DISP : { long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_ctrl_disp = value; } @@ -229,13 +229,13 @@ i960_cgen_print_operand (od, opindex, info, fields, attrs, pc, length) print_keyword (od, info, & i960_cgen_opval_h_gr, fields->f_br_src2, 0|(1<f_br_disp, 0|(1<f_br_disp, 0|(1<f_br_src1, 0|(1<f_ctrl_disp, 0|(1<f_ctrl_disp, 0|(1<> (word_length - (start + length)); value &= mask; /* sign extend? */ - if (! (attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED)) + if (! CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED) && (value & (1L << (length - 1)))) value |= ~mask; } diff --git a/opcodes/i960c-opc.c b/opcodes/i960c-opc.c index e8b4c01fb22..581c7ad2799 100644 --- a/opcodes/i960c-opc.c +++ b/opcodes/i960c-opc.c @@ -202,6 +202,13 @@ i960_cgen_lookup_get_insn_operands (od, insn, insn_value, length, indices) } /* Attributes. */ +static const CGEN_ATTR_ENTRY bool_attr[] = +{ + { "#f", 0 }, + { "#t", 1 }, + { 0, 0 } +}; + static const CGEN_ATTR_ENTRY MACH_attr[] = { { "base", MACH_BASE }, @@ -211,39 +218,59 @@ static const CGEN_ATTR_ENTRY MACH_attr[] = { 0, 0 } }; +const CGEN_ATTR_TABLE i960_cgen_ifield_attr_table[] = +{ + { "MACH", & MACH_attr[0] }, + { "VIRTUAL", &bool_attr[0], &bool_attr[0] }, + { "UNSIGNED", &bool_attr[0], &bool_attr[0] }, + { "PCREL-ADDR", &bool_attr[0], &bool_attr[0] }, + { "ABS-ADDR", &bool_attr[0], &bool_attr[0] }, + { "RESERVED", &bool_attr[0], &bool_attr[0] }, + { "SIGN-OPT", &bool_attr[0], &bool_attr[0] }, + { 0, 0, 0 } +}; + const CGEN_ATTR_TABLE i960_cgen_hardware_attr_table[] = { - { "CACHE-ADDR", NULL }, - { "PC", NULL }, - { "PROFILE", NULL }, - { 0, 0 } + { "MACH", & MACH_attr[0] }, + { "VIRTUAL", &bool_attr[0], &bool_attr[0] }, + { "UNSIGNED", &bool_attr[0], &bool_attr[0] }, + { "SIGNED", &bool_attr[0], &bool_attr[0] }, + { "CACHE-ADDR", &bool_attr[0], &bool_attr[0] }, + { "FUN-ACCESS", &bool_attr[0], &bool_attr[0] }, + { "PC", &bool_attr[0], &bool_attr[0] }, + { "PROFILE", &bool_attr[0], &bool_attr[0] }, + { 0, 0, 0 } }; const CGEN_ATTR_TABLE i960_cgen_operand_attr_table[] = { - { "ABS-ADDR", NULL }, - { "NEGATIVE", NULL }, - { "PCREL-ADDR", NULL }, - { "RELAX", NULL }, - { "RELOC", NULL }, - { "SEM-ONLY", NULL }, - { "SIGN-OPT", NULL }, - { "UNSIGNED", NULL }, - { 0, 0 } + { "MACH", & MACH_attr[0] }, + { "VIRTUAL", &bool_attr[0], &bool_attr[0] }, + { "UNSIGNED", &bool_attr[0], &bool_attr[0] }, + { "PCREL-ADDR", &bool_attr[0], &bool_attr[0] }, + { "ABS-ADDR", &bool_attr[0], &bool_attr[0] }, + { "SIGN-OPT", &bool_attr[0], &bool_attr[0] }, + { "NEGATIVE", &bool_attr[0], &bool_attr[0] }, + { "RELAX", &bool_attr[0], &bool_attr[0] }, + { "SEM-ONLY", &bool_attr[0], &bool_attr[0] }, + { 0, 0, 0 } }; const CGEN_ATTR_TABLE i960_cgen_insn_attr_table[] = { - { "ALIAS", NULL }, - { "COND-CTI", NULL }, - { "DELAY-SLOT", NULL }, - { "NO-DIS", NULL }, - { "RELAX", NULL }, - { "RELAXABLE", NULL }, - { "SKIP-CTI", NULL }, - { "UNCOND-CTI", NULL }, - { "VIRTUAL", NULL }, - { 0, 0 } + { "MACH", & MACH_attr[0] }, + { "VIRTUAL", &bool_attr[0], &bool_attr[0] }, + { "UNCOND-CTI", &bool_attr[0], &bool_attr[0] }, + { "COND-CTI", &bool_attr[0], &bool_attr[0] }, + { "SKIP-CTI", &bool_attr[0], &bool_attr[0] }, + { "DELAY-SLOT", &bool_attr[0], &bool_attr[0] }, + { "RELAXABLE", &bool_attr[0], &bool_attr[0] }, + { "RELAX", &bool_attr[0], &bool_attr[0] }, + { "ALIAS", &bool_attr[0], &bool_attr[0] }, + { "NO-DIS", &bool_attr[0], &bool_attr[0] }, + { "PBB", &bool_attr[0], &bool_attr[0] }, + { 0, 0, 0 } }; CGEN_KEYWORD_ENTRY i960_cgen_opval_h_gr_entries[] = @@ -307,14 +334,14 @@ CGEN_KEYWORD i960_cgen_opval_h_cc = #define HW_ENT(n) i960_cgen_hw_entries[n] static const CGEN_HW_ENTRY i960_cgen_hw_entries[] = { - { HW_H_PC, & HW_ENT (HW_H_PC + 1), "h-pc", CGEN_ASM_KEYWORD, (PTR) 0, { 0, 0|(1<f) + static const char * insert_normal - PARAMS ((CGEN_OPCODE_DESC, long, unsigned int, int, int, int, - CGEN_INSN_BYTES_PTR)); + PARAMS ((CGEN_OPCODE_DESC, long, unsigned int, unsigned int, unsigned int, + unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR)); static const char * parse_insn_normal PARAMS ((CGEN_OPCODE_DESC, const CGEN_INSN *, const char **, CGEN_FIELDS *)); @@ -355,100 +358,101 @@ m32r_cgen_insert_operand (od, opindex, fields, buffer, pc) bfd_vma pc; { const char * errmsg; + unsigned int total_length = CGEN_FIELDS_BITSIZE (fields); switch (opindex) { case M32R_OPERAND_SR : - errmsg = insert_normal (od, fields->f_r2, 0|(1<f_r2, 0|(1<f_r1, 0|(1<f_r1, 0|(1<f_r1, 0|(1<f_r1, 0|(1<f_r2, 0|(1<f_r2, 0|(1<f_r2, 0|(1<f_r2, 0|(1<f_r1, 0|(1<f_r1, 0|(1<f_simm8, 0|(1<f_simm8, 0|(1<f_simm16, 0|(1<f_simm16, 0|(1<f_uimm4, 0|(1<f_uimm4, 0|(1<f_uimm5, 0|(1<f_uimm5, 0|(1<f_uimm16, 0|(1<f_uimm16, 0|(1<f_imm1; value = ((value) - (1)); - errmsg = insert_normal (od, value, 0|(1<f_accd, 0|(1<f_accd, 0|(1<f_accs, 0|(1<f_accs, 0|(1<f_acc, 0|(1<f_acc, 0|(1<f_nil, 0, 0, 0, CGEN_FIELDS_BITSIZE (fields), buffer); + errmsg = insert_normal (od, fields->f_nil, 0, 0, 0, 0, 0, total_length, buffer); break; case M32R_OPERAND_HI16 : - errmsg = insert_normal (od, fields->f_hi16, 0|(1<f_hi16, 0|(1<f_simm16, 0, 16, 16, CGEN_FIELDS_BITSIZE (fields), buffer); + errmsg = insert_normal (od, fields->f_simm16, 0, 0, 16, 16, 32, total_length, buffer); break; case M32R_OPERAND_ULO16 : - errmsg = insert_normal (od, fields->f_uimm16, 0|(1<f_uimm16, 0|(1<f_uimm24, 0|(1<f_uimm24, 0|(1<f_disp8; value = ((int) (((value) - (((pc) & (-4))))) >> (2)); - errmsg = insert_normal (od, value, 0|(1<f_disp16; value = ((int) (((value) - (pc))) >> (2)); - errmsg = insert_normal (od, value, 0|(1<f_disp24; value = ((int) (((value) - (pc))) >> (2)); - errmsg = insert_normal (od, value, 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: @@ -574,33 +578,26 @@ insert_1 (od, value, start, length, word_length, bufp) /* Default insertion routine. ATTRS is a mask of the boolean attributes. - START is the starting bit number, architecture origin. + WORD_OFFSET is the offset in bits from the start of the insn of the value. + WORD_LENGTH is the length of the word in bits in which the value resides. + START is the starting bit number in the word, architecture origin. LENGTH is the length of VALUE in bits. - TOTAL_LENGTH is the total length of the insn. + TOTAL_LENGTH is the total length of the insn in bits. 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, - store insn in `field' struct and add registers, etc. while parsing? */ /* ??? This doesn't handle bfd_vma's. Create another function when necessary. */ static const char * -insert_normal (od, value, attrs, start, length, total_length, buffer) +insert_normal (od, value, attrs, word_offset, start, length, word_length, + total_length, buffer) CGEN_OPCODE_DESC od; long value; unsigned int attrs; - int start; - int length; - int total_length; + unsigned int word_offset, start, length, word_length, total_length; CGEN_INSN_BYTES_PTR buffer; { static char errbuf[100]; @@ -611,8 +608,23 @@ insert_normal (od, value, attrs, start, length, total_length, buffer) if (length == 0) return NULL; + if (CGEN_INT_INSN_P + && word_offset != 0) + abort (); + + if (word_length > 32) + abort (); + + /* For architectures with insns smaller than the insn-base-bitsize, + word_length may be too big. */ +#if CGEN_MIN_INSN_BITSIZE < CGEN_BASE_INSN_BITSIZE + if (word_offset == 0 + && word_length > total_length) + word_length = total_length; +#endif + /* Ensure VALUE will fit. */ - if ((attrs & CGEN_ATTR_MASK (CGEN_OPERAND_UNSIGNED)) != 0) + if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED)) { unsigned long maxval = mask; if ((unsigned long) value > maxval) @@ -640,152 +652,23 @@ insert_normal (od, value, attrs, start, length, total_length, buffer) #if CGEN_INT_INSN_P - if (total_length > 32) - abort (); { int shift; if (CGEN_INSN_LSB0_P) - shift = start; + shift = (start + 1) - length; else - shift = total_length - (start + length); + shift = word_length - (start + length); *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift); } -#else - - /* 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 - 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) - { - unsigned char *bufp = (unsigned char *) buffer; - int insn_length_left = total_length; - - if (CGEN_INSN_LSB0_P) - { - int word_offset = (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG - ? ... - : start / CGEN_BASE_INSN_BITSIZE); - bufp += word_offset * (CGEN_BASE_INSN_BITSIZE / 8); - if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG) - else - start -= word_offset * CGEN_BASE_INSN_BITSIZE; - } - else - { - int word_offset = (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG - ? start / CGEN_BASE_INSN_BITSIZE - : ...); - bufp += word_offset * (CGEN_BASE_INSN_BITSIZE / 8); - if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG) - start -= word_offset * CGEN_BASE_INSN_BITSIZE; - else - } - - /* Loop so we handle a field straddling an insn word boundary - (remember, "insn word boundary" is loosely defined here). */ - - while (length > 0) - { - int this_pass_length = length; - int this_pass_start = start; - int this_pass_word_length = min (insn_length_left, - (CGEN_BASE_INSN_BITSIZE == 8 - ? 32 - : CGEN_BASE_INSN_BITSIZE)); - - insert_1 (od, value, attrs, - this_pass_start, this_pass_length, this_pass_word_length, - bufp); - - length -= this_pass_length; - insn_length_left -= this_pass_word_length; - if (???) - { - value >>= ???; - start += ???; - } - else - { - value >>= ???; - start += ???; - } - bufp += this_pass_word_length / 8; - } - } - else -#endif /* 0 */ - { - unsigned char *bufp = (unsigned char *) buffer; - - 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 - 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). */ - - if (total_length > 32) - { - int needed_width = start % 8 + length; - int fetch_length = (needed_width <= 8 ? 8 - : needed_width <= 16 ? 16 - : 32); +#else /* ! CGEN_INT_INSN_P */ - if (CGEN_INSN_LSB0_P) - { - if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG) - { - abort (); /* wip */ - } - else - { - int offset = start & ~7; - - bufp += offset / 8; - start -= offset; - total_length -= offset; - } - } - else - { - if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG) - { - int offset = start & ~7; - - bufp += offset / 8; - start -= offset; - total_length -= offset; - } - else - { - abort (); /* wip */ - } - } - } + { + unsigned char *bufp = (unsigned char *) buffer + word_offset / 8; - insert_1 (od, value, start, length, total_length, bufp); - } + insert_1 (od, value, start, length, word_length, bufp); + } #endif /* ! CGEN_INT_INSN_P */ @@ -924,7 +807,7 @@ insert_insn_normal (od, insn, fields, buffer, pc) const unsigned char * syn; CGEN_INIT_INSERT (od); - value = CGEN_INSN_VALUE (insn); + value = CGEN_INSN_BASE_VALUE (insn); /* If we're recording insns as numbers (rather than a string of bytes), target byte order handling is deferred until later. */ @@ -935,14 +818,16 @@ 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); #endif /* ! CGEN_INT_INSN_P */ - /* ??? Rather than scanning the syntax string again, we could store - in `fields' a null terminated list of the fields that are present. */ + /* ??? It would be better to scan the format's fields. + Still need to be able to insert a value based on the operand though; + e.g. storing a branch displacement that got resolved later. + Needs more thought first. */ for (syn = CGEN_SYNTAX_STRING (syntax); * syn != '\0'; ++ syn) { @@ -1015,9 +900,7 @@ m32r_cgen_assemble_insn (od, str, fields, buf, errmsg) str = start; - /* Record a default length for the insn. This will get set to the - correct value while parsing. */ - /* FIXME: wip */ + /* Allow parse/insert handlers to obtain length of insn. */ CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn); if (! CGEN_PARSE_FN (insn) (od, insn, & str, fields)) diff --git a/opcodes/m32r-dis.c b/opcodes/m32r-dis.c index 5c3b10f8ea3..0037746177a 100644 --- a/opcodes/m32r-dis.c +++ b/opcodes/m32r-dis.c @@ -40,9 +40,13 @@ along with this program; if not, write to the Free Software Foundation, Inc., /* Default text to print if an instruction isn't recognized. */ #define UNKNOWN_INSN_MSG _("*unknown*") +/* Used by the ifield rtx function. */ +#define FLD(f) (fields->f) + 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, unsigned int, unsigned int, unsigned int, + unsigned int, unsigned 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 +55,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)); @@ -160,52 +164,53 @@ m32r_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; { int length; + unsigned int total_length = CGEN_FIELDS_BITSIZE (fields); switch (opindex) { case M32R_OPERAND_SR : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_r2); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_r2); break; case M32R_OPERAND_DR : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_r1); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_r1); break; case M32R_OPERAND_SRC1 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_r1); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_r1); break; case M32R_OPERAND_SRC2 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_r2); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_r2); break; case M32R_OPERAND_SCR : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_r2); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_r2); break; case M32R_OPERAND_DCR : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_r1); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_r1); break; case M32R_OPERAND_SIMM8 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_simm8); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_simm8); break; case M32R_OPERAND_SIMM16 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_simm16); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_simm16); break; case M32R_OPERAND_UIMM4 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_uimm4); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_uimm4); break; case M32R_OPERAND_UIMM5 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_uimm5); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_uimm5); break; case M32R_OPERAND_UIMM16 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_uimm16); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_uimm16); break; /* start-sanitize-m32rx */ case M32R_OPERAND_IMM1 : { long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_imm1 = value; } @@ -213,38 +218,38 @@ m32r_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc) /* end-sanitize-m32rx */ /* start-sanitize-m32rx */ case M32R_OPERAND_ACCD : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_accd); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_accd); break; /* end-sanitize-m32rx */ /* start-sanitize-m32rx */ case M32R_OPERAND_ACCS : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_accs); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_accs); break; /* end-sanitize-m32rx */ /* start-sanitize-m32rx */ case M32R_OPERAND_ACC : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_acc); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_acc); break; /* end-sanitize-m32rx */ case M32R_OPERAND_HASH : - 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, 0, 0, total_length, pc, & fields->f_nil); break; case M32R_OPERAND_HI16 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_hi16); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_hi16); break; case M32R_OPERAND_SLO16 : - length = extract_normal (od, ex_info, insn_value, 0, 16, 16, CGEN_FIELDS_BITSIZE (fields), & fields->f_simm16); + length = extract_normal (od, ex_info, insn_value, 0, 0, 16, 16, 32, total_length, pc, & fields->f_simm16); break; case M32R_OPERAND_ULO16 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_uimm16); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_uimm16); break; case M32R_OPERAND_UIMM24 : - length = extract_normal (od, ex_info, insn_value, 0|(1<f_uimm24); + length = extract_normal (od, ex_info, insn_value, 0|(1<f_uimm24); break; case M32R_OPERAND_DISP8 : { long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_disp8 = value; } @@ -252,7 +257,7 @@ m32r_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc) case M32R_OPERAND_DISP16 : { long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_disp16 = value; } @@ -260,7 +265,7 @@ m32r_cgen_extract_operand (od, opindex, ex_info, insn_value, fields, pc) case M32R_OPERAND_DISP24 : { long value; - length = extract_normal (od, ex_info, insn_value, 0|(1<f_disp24 = value; } @@ -410,21 +415,68 @@ m32r_cgen_init_dis (od) #if ! CGEN_INT_INSN_P +/* Subroutine of extract_normal. + Ensure sufficient bytes are cached in EX_INFO. + OFFSET is the offset in bytes from the start of the insn of the value. + BYTES is the length of the needed value. + Returns 1 for success, 0 for failure. */ + +static INLINE int +fill_cache (od, ex_info, offset, bytes, pc) + CGEN_OPCODE_DESC od; + CGEN_EXTRACT_INFO *ex_info; + int offset, bytes; + bfd_vma pc; +{ + /* It's doubtful that the middle part has already been fetched so + we don't optimize that case. kiss. */ + int mask; + disassemble_info *info = (disassemble_info *) ex_info->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: @@ -440,9 +492,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) @@ -457,7 +509,7 @@ extract_1 (od, ex_info, start, length, word_length, bufp) /* Written this way to avoid undefined behaviour. */ mask = (((1L << (length - 1)) - 1) << 1) | 1; if (CGEN_INSN_LSB0_P) - shift = start; + shift = (start + 1) - length; else shift = (word_length - (start + length)); return (x >> shift) & mask; @@ -467,22 +519,36 @@ extract_1 (od, ex_info, start, length, word_length, bufp) /* Default extraction routine. - ATTRS is a mask of the boolean attributes. We only need `unsigned', - but for generality we take a bitmask of all of them. */ + 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. + WORD_OFFSET is the offset in bits from the start of the insn of the value. + WORD_LENGTH is the length of the word in bits in which the value resides. + START is the starting bit number in the word, architecture origin. + LENGTH is the length of VALUE in bits. + TOTAL_LENGTH is the total length of the insn in bits. + + Returns 1 for success, 0 for failure. */ + +/* ??? The return code isn't properly used. wip. */ /* ??? 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, word_offset, start, length, + word_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; + unsigned int word_offset, start, length, word_length, total_length; + bfd_vma pc; long *valuep; { - unsigned long value; + CGEN_INSN_INT value; /* If LENGTH is zero, this operand doesn't contribute to the value so give it a standard value of zero. */ @@ -492,100 +558,58 @@ 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; - } - -#else + if (CGEN_INT_INSN_P + && word_offset != 0) + abort (); - /* 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 - to be when a field straddles a (loosely defined) word boundary - (??? which may require target specific help to determine). */ + if (word_length > 32) + abort (); -#if 0 /*wip*/ + /* For architectures with insns smaller than the insn-base-bitsize, + word_length may be too big. */ +#if CGEN_MIN_INSN_BITSIZE < CGEN_BASE_INSN_BITSIZE + if (word_offset == 0 + && word_length > total_length) + word_length = total_length; +#endif -#define HARD_CASE_P 0 /* FIXME:wip */ + /* Does the value reside in INSN_VALUE? */ - if (HARD_CASE_P) + if (word_offset == 0) { + /* Written this way to avoid undefined behaviour. */ + CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1; + + if (CGEN_INSN_LSB0_P) + value = insn_value >> ((start + 1) - length); + else + value = insn_value >> (word_length - (start + length)); + value &= mask; + /* sign extend? */ + if (! CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_UNSIGNED) + && (value & (1L << (length - 1)))) + value |= ~mask; } -#endif + +#if ! CGEN_INT_INSN_P + else { - unsigned char *bufp = (unsigned char *) insn_value; + unsigned char *bufp = ex_info->insn_bytes + word_offset / 8; - if (length > 32) + if (word_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 - 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). */ - - if (total_length > 32) - { - int needed_width = start % 8 + length; - int fetch_length = (needed_width <= 8 ? 8 - : needed_width <= 16 ? 16 - : 32); - - if (CGEN_INSN_LSB0_P) - { - if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG) - { - abort (); /* wip */ - } - else - { - int offset = start & ~7; - - bufp += offset / 8; - start -= offset; - total_length -= offset; - } - } - else - { - if (CGEN_INSN_WORD_ENDIAN (od) == CGEN_ENDIAN_BIG) - { - int offset = start & ~7; - - bufp += offset / 8; - start -= offset; - total_length -= offset; - } - else - { - abort (); /* wip */ - } - } - } + if (fill_cache (od, ex_info, word_offset / 8, word_length / 8, pc) == 0) + return 0; - /* FIXME: which bytes are being extracted have been lost. */ - value = extract_1 (od, ex_info, start, length, total_length, bufp); + value = extract_1 (od, ex_info, start, length, word_length, bufp, pc); } #endif /* ! CGEN_INT_INSN_P */ *valuep = value; - /* FIXME: for now */ return 1; } @@ -679,7 +703,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; { @@ -766,7 +790,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) { @@ -802,7 +826,8 @@ print_insn (od, 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_MASK (insn)) == CGEN_INSN_VALUE (insn)) + if ((insn_value & CGEN_INSN_BASE_MASK (insn)) + == CGEN_INSN_BASE_VALUE (insn)) { /* Printing is handled in two passes. The first pass parses the machine insn and extracts the fields. The second pass prints diff --git a/opcodes/m32r-opc.c b/opcodes/m32r-opc.c index 67ff11e7bcb..394d68345ac 100644 --- a/opcodes/m32r-opc.c +++ b/opcodes/m32r-opc.c @@ -30,78 +30,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., #include "m32r-opc.h" #include "opintl.h" +/* Used by the ifield rtx function. */ +#define FLD(f) (fields->f) + /* The hash functions are recorded here to help keep assembler code out of the disassembler and vice versa. */ 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 +49,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 +61,9 @@ m32r_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 +71,22 @@ m32r_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 +101,12 @@ m32r_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_BASE_MASK (insn)) + == CGEN_INSN_BASE_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 +132,7 @@ m32r_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. */ @@ -266,6 +202,13 @@ m32r_cgen_lookup_get_insn_operands (od, insn, insn_value, length, indices) } /* Attributes. */ +static const CGEN_ATTR_ENTRY bool_attr[] = +{ + { "#f", 0 }, + { "#t", 1 }, + { 0, 0 } +}; + static const CGEN_ATTR_ENTRY MACH_attr[] = { { "base", MACH_BASE }, @@ -288,30 +231,46 @@ static const CGEN_ATTR_ENTRY PIPE_attr[] = }; /* end-sanitize-m32rx */ +const CGEN_ATTR_TABLE m32r_cgen_ifield_attr_table[] = +{ + { "MACH", & MACH_attr[0] }, + { "VIRTUAL", &bool_attr[0], &bool_attr[0] }, + { "UNSIGNED", &bool_attr[0], &bool_attr[0] }, + { "PCREL-ADDR", &bool_attr[0], &bool_attr[0] }, + { "ABS-ADDR", &bool_attr[0], &bool_attr[0] }, + { "RESERVED", &bool_attr[0], &bool_attr[0] }, + { "SIGN-OPT", &bool_attr[0], &bool_attr[0] }, + { "RELOC", &bool_attr[0], &bool_attr[0] }, + { 0, 0, 0 } +}; + const CGEN_ATTR_TABLE m32r_cgen_hardware_attr_table[] = { { "MACH", & MACH_attr[0] }, - { "CACHE-ADDR", NULL }, - { "FUN-ACCESS", NULL }, - { "PC", NULL }, - { "PROFILE", NULL }, - { "SIGN-OPT", NULL }, - { "UNSIGNED", NULL }, - { 0, 0 } + { "VIRTUAL", &bool_attr[0], &bool_attr[0] }, + { "UNSIGNED", &bool_attr[0], &bool_attr[0] }, + { "SIGNED", &bool_attr[0], &bool_attr[0] }, + { "CACHE-ADDR", &bool_attr[0], &bool_attr[0] }, + { "FUN-ACCESS", &bool_attr[0], &bool_attr[0] }, + { "PC", &bool_attr[0], &bool_attr[0] }, + { "PROFILE", &bool_attr[0], &bool_attr[0] }, + { 0, 0, 0 } }; const CGEN_ATTR_TABLE m32r_cgen_operand_attr_table[] = { - { "ABS-ADDR", NULL }, - { "HASH-PREFIX", NULL }, - { "NEGATIVE", NULL }, - { "PCREL-ADDR", NULL }, - { "RELAX", NULL }, - { "RELOC", NULL }, - { "SEM-ONLY", NULL }, - { "SIGN-OPT", NULL }, - { "UNSIGNED", NULL }, - { 0, 0 } + { "MACH", & MACH_attr[0] }, + { "VIRTUAL", &bool_attr[0], &bool_attr[0] }, + { "UNSIGNED", &bool_attr[0], &bool_attr[0] }, + { "PCREL-ADDR", &bool_attr[0], &bool_attr[0] }, + { "ABS-ADDR", &bool_attr[0], &bool_attr[0] }, + { "SIGN-OPT", &bool_attr[0], &bool_attr[0] }, + { "NEGATIVE", &bool_attr[0], &bool_attr[0] }, + { "RELAX", &bool_attr[0], &bool_attr[0] }, + { "SEM-ONLY", &bool_attr[0], &bool_attr[0] }, + { "RELOC", &bool_attr[0], &bool_attr[0] }, + { "HASH-PREFIX", &bool_attr[0], &bool_attr[0] }, + { 0, 0, 0 } }; const CGEN_ATTR_TABLE m32r_cgen_insn_attr_table[] = @@ -320,17 +279,21 @@ const CGEN_ATTR_TABLE m32r_cgen_insn_attr_table[] = /* start-sanitize-m32rx */ { "PIPE", & PIPE_attr[0] }, /* end-sanitize-m32rx */ - { "ALIAS", NULL }, - { "COND-CTI", NULL }, - { "FILL-SLOT", NULL }, - { "NO-DIS", NULL }, - { "RELAX", NULL }, - { "RELAXABLE", NULL }, - { "SKIP-CTI", NULL }, - { "SPECIAL", NULL }, - { "UNCOND-CTI", NULL }, - { "VIRTUAL", NULL }, - { 0, 0 } + { "VIRTUAL", &bool_attr[0], &bool_attr[0] }, + { "UNCOND-CTI", &bool_attr[0], &bool_attr[0] }, + { "COND-CTI", &bool_attr[0], &bool_attr[0] }, + { "SKIP-CTI", &bool_attr[0], &bool_attr[0] }, + { "DELAY-SLOT", &bool_attr[0], &bool_attr[0] }, + { "RELAXABLE", &bool_attr[0], &bool_attr[0] }, + { "RELAX", &bool_attr[0], &bool_attr[0] }, + { "ALIAS", &bool_attr[0], &bool_attr[0] }, + { "NO-DIS", &bool_attr[0], &bool_attr[0] }, + { "PBB", &bool_attr[0], &bool_attr[0] }, + { "FILL-SLOT", &bool_attr[0], &bool_attr[0] }, +/* start-sanitize-m32rx */ + { "SPECIAL", &bool_attr[0], &bool_attr[0] }, +/* end-sanitize-m32rx */ + { 0, 0, 0 } }; CGEN_KEYWORD_ENTRY m32r_cgen_opval_h_gr_entries[] = @@ -421,7 +384,7 @@ static const CGEN_HW_ENTRY m32r_cgen_hw_entries[] = { HW_H_UINT, & HW_ENT (HW_H_UINT + 1), "h-uint", CGEN_ASM_KEYWORD, (PTR) 0, { CGEN_HW_NBOOL_ATTRS, 0, { (1<. */ +/* Given symbol S, return m32r_cgen_. */ #define CGEN_SYM(s) CONCAT3 (m32r,_cgen_,s) /* Selected cpu families. */ -#define HAVE_CPU_M32R +#define HAVE_CPU_M32RBF /* start-sanitize-m32rx */ -#define HAVE_CPU_M32RX +#define HAVE_CPU_M32RXF /* end-sanitize-m32rx */ +#define CGEN_INSN_LSB0_P 0 #define CGEN_WORD_BITSIZE 32 #define CGEN_DEFAULT_INSN_BITSIZE 32 #define CGEN_BASE_INSN_BITSIZE 32 @@ -45,7 +46,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #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 +#define CGEN_INT_INSN_P 1 /* FIXME: Need to compute CGEN_MAX_SYNTAX_BYTES. */ @@ -56,6 +57,9 @@ with this program; if not, write to the Free Software Foundation, Inc., /* Maximum number of operands any insn or macro-insn has. */ #define CGEN_MAX_INSN_OPERANDS 16 +/* Maximum number of fields in an instruction. */ +#define CGEN_MAX_IFMT_OPERANDS 7 + /* Enums. */ /* Enum declaration for insn format enums. */ @@ -86,11 +90,11 @@ typedef enum h_gr { /* Enum declaration for control registers. */ typedef enum h_cr { H_CR_PSW = 0, H_CR_CBR = 1, H_CR_SPI = 2, H_CR_SPU = 3 - , H_CR_BPC = 6, H_CR_CR0 = 0, H_CR_CR1 = 1, H_CR_CR2 = 2 - , H_CR_CR3 = 3, H_CR_CR4 = 4, H_CR_CR5 = 5, H_CR_CR6 = 6 - , H_CR_CR7 = 7, H_CR_CR8 = 8, H_CR_CR9 = 9, H_CR_CR10 = 10 - , H_CR_CR11 = 11, H_CR_CR12 = 12, H_CR_CR13 = 13, H_CR_CR14 = 14 - , H_CR_CR15 = 15 + , H_CR_BPC = 6, H_CR_BBPSW = 8, H_CR_BBPC = 14, H_CR_CR0 = 0 + , H_CR_CR1 = 1, H_CR_CR2 = 2, H_CR_CR3 = 3, H_CR_CR4 = 4 + , H_CR_CR5 = 5, H_CR_CR6 = 6, H_CR_CR7 = 7, H_CR_CR8 = 8 + , H_CR_CR9 = 9, H_CR_CR10 = 10, H_CR_CR11 = 11, H_CR_CR12 = 12 + , H_CR_CR13 = 13, H_CR_CR14 = 14, H_CR_CR15 = 15 } H_CR; /* start-sanitize-m32rx */ @@ -100,33 +104,11 @@ typedef enum h_accums { } H_ACCUMS; /* end-sanitize-m32rx */ -/* Enum declaration for m32r operand types. */ -typedef enum cgen_operand_type { - M32R_OPERAND_PC, M32R_OPERAND_SR, M32R_OPERAND_DR, M32R_OPERAND_SRC1 - , M32R_OPERAND_SRC2, M32R_OPERAND_SCR, M32R_OPERAND_DCR, M32R_OPERAND_SIMM8 - , M32R_OPERAND_SIMM16, M32R_OPERAND_UIMM4, M32R_OPERAND_UIMM5, M32R_OPERAND_UIMM16 -/* start-sanitize-m32rx */ - , M32R_OPERAND_IMM1 -/* end-sanitize-m32rx */ -/* start-sanitize-m32rx */ - , M32R_OPERAND_ACCD -/* end-sanitize-m32rx */ -/* start-sanitize-m32rx */ - , M32R_OPERAND_ACCS -/* end-sanitize-m32rx */ -/* start-sanitize-m32rx */ - , M32R_OPERAND_ACC -/* end-sanitize-m32rx */ - , M32R_OPERAND_HASH, M32R_OPERAND_HI16, M32R_OPERAND_SLO16, M32R_OPERAND_ULO16 - , M32R_OPERAND_UIMM24, M32R_OPERAND_DISP8, M32R_OPERAND_DISP16, M32R_OPERAND_DISP24 - , M32R_OPERAND_CONDBIT, M32R_OPERAND_ACCUM, M32R_OPERAND_MAX -} CGEN_OPERAND_TYPE; - -/* Non-boolean attributes. */ +/* Attributes. */ /* Enum declaration for machine type selection. */ typedef enum mach_attr { - MACH_M32R + MACH_BASE, MACH_M32R /* start-sanitize-m32rx */ , MACH_M32RX /* end-sanitize-m32rx */ @@ -143,23 +125,119 @@ typedef enum pipe_attr { /* Number of architecture variants. */ #define MAX_MACHS ((int) MACH_MAX) -/* Number of operands types. */ -#define MAX_OPERANDS ((int) M32R_OPERAND_MAX) +/* Ifield attribute indices. */ -/* Maximum number of operands referenced by any insn. */ -#define MAX_OPERAND_INSTANCES 8 +/* Enum declaration for cgen_ifld attrs. */ +typedef enum cgen_ifld_attr { + CGEN_IFLD_MACH, CGEN_IFLD_VIRTUAL, CGEN_IFLD_UNSIGNED, CGEN_IFLD_PCREL_ADDR + , CGEN_IFLD_ABS_ADDR, CGEN_IFLD_RESERVED, CGEN_IFLD_SIGN_OPT, CGEN_IFLD_RELOC +} CGEN_IFLD_ATTR; + +/* Number of non-boolean elements in cgen_ifld. */ +#define CGEN_IFLD_NBOOL_ATTRS ((int) CGEN_IFLD_VIRTUAL) + +/* Enum declaration for m32r ifield types. */ +typedef enum ifield_type { + M32R_F_NIL, M32R_F_OP1, M32R_F_OP2, M32R_F_COND + , M32R_F_R1, M32R_F_R2, M32R_F_SIMM8, M32R_F_SIMM16 + , M32R_F_SHIFT_OP2, M32R_F_UIMM4, M32R_F_UIMM5, M32R_F_UIMM16 + , M32R_F_UIMM24, M32R_F_HI16, M32R_F_DISP8, M32R_F_DISP16 + , M32R_F_DISP24 +/* start-sanitize-m32rx */ + , M32R_F_OP23 +/* end-sanitize-m32rx */ +/* start-sanitize-m32rx */ + , M32R_F_OP3 +/* end-sanitize-m32rx */ +/* start-sanitize-m32rx */ + , M32R_F_ACC +/* end-sanitize-m32rx */ +/* start-sanitize-m32rx */ + , M32R_F_ACCS +/* end-sanitize-m32rx */ +/* start-sanitize-m32rx */ + , M32R_F_ACCD +/* end-sanitize-m32rx */ +/* start-sanitize-m32rx */ + , M32R_F_BITS67 +/* end-sanitize-m32rx */ +/* start-sanitize-m32rx */ + , M32R_F_BIT14 +/* end-sanitize-m32rx */ +/* start-sanitize-m32rx */ + , M32R_F_IMM1 +/* end-sanitize-m32rx */ + , M32R_F_MAX +} IFIELD_TYPE; + +#define MAX_IFLD ((int) M32R_F_MAX) -/* Operand and instruction attribute indices. */ +/* Hardware attribute indices. */ + +/* Enum declaration for cgen_hw attrs. */ +typedef enum cgen_hw_attr { + CGEN_HW_MACH, CGEN_HW_VIRTUAL, CGEN_HW_UNSIGNED, CGEN_HW_SIGNED + , CGEN_HW_CACHE_ADDR, CGEN_HW_FUN_ACCESS, CGEN_HW_PC, CGEN_HW_PROFILE +} CGEN_HW_ATTR; + +/* Number of non-boolean elements in cgen_hw. */ +#define CGEN_HW_NBOOL_ATTRS ((int) CGEN_HW_VIRTUAL) + +/* Enum declaration for m32r hardware types. */ +typedef enum hw_type { + HW_H_PC, HW_H_MEMORY, HW_H_SINT, HW_H_UINT + , HW_H_ADDR, HW_H_IADDR, HW_H_HI16, HW_H_SLO16 + , HW_H_ULO16, HW_H_GR, HW_H_CR, HW_H_ACCUM +/* start-sanitize-m32rx */ + , HW_H_ACCUMS +/* end-sanitize-m32rx */ + , HW_H_COND, HW_H_PSW, HW_H_BPSW, HW_H_BBPSW + , HW_H_LOCK, HW_MAX +} HW_TYPE; + +#define MAX_HW ((int) HW_MAX) + +/* Operand attribute indices. */ /* Enum declaration for cgen_operand attrs. */ typedef enum cgen_operand_attr { - CGEN_OPERAND_ABS_ADDR, CGEN_OPERAND_FAKE, CGEN_OPERAND_HASH_PREFIX, CGEN_OPERAND_NEGATIVE - , CGEN_OPERAND_PCREL_ADDR, CGEN_OPERAND_RELAX, CGEN_OPERAND_RELOC, CGEN_OPERAND_SIGN_OPT - , CGEN_OPERAND_UNSIGNED + CGEN_OPERAND_MACH, CGEN_OPERAND_VIRTUAL, CGEN_OPERAND_UNSIGNED, CGEN_OPERAND_PCREL_ADDR + , CGEN_OPERAND_ABS_ADDR, CGEN_OPERAND_SIGN_OPT, CGEN_OPERAND_NEGATIVE, CGEN_OPERAND_RELAX + , CGEN_OPERAND_SEM_ONLY, CGEN_OPERAND_RELOC, CGEN_OPERAND_HASH_PREFIX } CGEN_OPERAND_ATTR; /* Number of non-boolean elements in cgen_operand. */ -#define CGEN_OPERAND_NBOOL_ATTRS ((int) CGEN_OPERAND_ABS_ADDR) +#define CGEN_OPERAND_NBOOL_ATTRS ((int) CGEN_OPERAND_VIRTUAL) + +/* Enum declaration for m32r operand types. */ +typedef enum cgen_operand_type { + M32R_OPERAND_PC, M32R_OPERAND_SR, M32R_OPERAND_DR, M32R_OPERAND_SRC1 + , M32R_OPERAND_SRC2, M32R_OPERAND_SCR, M32R_OPERAND_DCR, M32R_OPERAND_SIMM8 + , M32R_OPERAND_SIMM16, M32R_OPERAND_UIMM4, M32R_OPERAND_UIMM5, M32R_OPERAND_UIMM16 +/* start-sanitize-m32rx */ + , M32R_OPERAND_IMM1 +/* end-sanitize-m32rx */ +/* start-sanitize-m32rx */ + , M32R_OPERAND_ACCD +/* end-sanitize-m32rx */ +/* start-sanitize-m32rx */ + , M32R_OPERAND_ACCS +/* end-sanitize-m32rx */ +/* start-sanitize-m32rx */ + , M32R_OPERAND_ACC +/* end-sanitize-m32rx */ + , M32R_OPERAND_HASH, M32R_OPERAND_HI16, M32R_OPERAND_SLO16, M32R_OPERAND_ULO16 + , M32R_OPERAND_UIMM24, M32R_OPERAND_DISP8, M32R_OPERAND_DISP16, M32R_OPERAND_DISP24 + , M32R_OPERAND_CONDBIT, M32R_OPERAND_ACCUM, M32R_OPERAND_MAX +} CGEN_OPERAND_TYPE; + +/* Number of operands types. */ +#define MAX_OPERANDS ((int) M32R_OPERAND_MAX) + +/* Maximum number of operands referenced by any insn. */ +#define MAX_OPERAND_INSTANCES 11 + +/* Insn attribute indices. */ /* Enum declaration for cgen_insn attrs. */ typedef enum cgen_insn_attr { @@ -167,17 +245,20 @@ typedef enum cgen_insn_attr { /* start-sanitize-m32rx */ , CGEN_INSN_PIPE /* end-sanitize-m32rx */ - , CGEN_INSN_ALIAS, CGEN_INSN_COND_CTI, CGEN_INSN_FILL_SLOT, CGEN_INSN_NO_DIS - , CGEN_INSN_PARALLEL, CGEN_INSN_RELAX, CGEN_INSN_RELAXABLE, CGEN_INSN_SPECIAL - , CGEN_INSN_UNCOND_CTI + , CGEN_INSN_VIRTUAL, CGEN_INSN_UNCOND_CTI, CGEN_INSN_COND_CTI, CGEN_INSN_SKIP_CTI + , CGEN_INSN_DELAY_SLOT, CGEN_INSN_RELAXABLE, CGEN_INSN_RELAX, CGEN_INSN_ALIAS + , CGEN_INSN_NO_DIS, CGEN_INSN_PBB, CGEN_INSN_FILL_SLOT +/* start-sanitize-m32rx */ + , CGEN_INSN_SPECIAL +/* end-sanitize-m32rx */ } CGEN_INSN_ATTR; /* Number of non-boolean elements in cgen_insn. */ -#define CGEN_INSN_NBOOL_ATTRS ((int) CGEN_INSN_ALIAS) +#define CGEN_INSN_NBOOL_ATTRS ((int) CGEN_INSN_VIRTUAL) /* Enum declaration for m32r instruction types. */ typedef enum cgen_insn_type { - M32R_INSN_ILLEGAL, M32R_INSN_ADD, M32R_INSN_ADD3, M32R_INSN_AND + M32R_INSN_INVALID, M32R_INSN_ADD, M32R_INSN_ADD3, M32R_INSN_AND , M32R_INSN_AND3, M32R_INSN_OR, M32R_INSN_OR3, M32R_INSN_XOR , M32R_INSN_XOR3, M32R_INSN_ADDI, M32R_INSN_ADDV, M32R_INSN_ADDV3 , M32R_INSN_ADDX, M32R_INSN_BC8, M32R_INSN_BC24, M32R_INSN_BEQ @@ -321,8 +402,8 @@ typedef enum cgen_insn_type { , M32R_INSN_MAX } CGEN_INSN_TYPE; -/* Index of `illegal' insn place holder. */ -#define CGEN_INSN_ILLEGAL M32R_INSN_ILLEGAL +/* Index of `invalid' insn place holder. */ +#define CGEN_INSN_INVALID M32R_INSN_INVALID /* Total number of insns in table. */ #define MAX_INSNS ((int) M32R_INSN_MAX) @@ -377,24 +458,10 @@ struct cgen_fields }; /* Attributes. */ +extern const CGEN_ATTR_TABLE m32r_cgen_hw_attr_table[]; extern const CGEN_ATTR_TABLE m32r_cgen_operand_attr_table[]; extern const CGEN_ATTR_TABLE m32r_cgen_insn_attr_table[]; -/* Enum declaration for m32r hardware types. */ -typedef enum hw_type { - HW_H_PC, HW_H_MEMORY, HW_H_SINT, HW_H_UINT - , HW_H_ADDR, HW_H_IADDR, HW_H_HI16, HW_H_SLO16 - , HW_H_ULO16, HW_H_GR, HW_H_CR, HW_H_ACCUM -/* start-sanitize-m32rx */ - , HW_H_ACCUMS -/* end-sanitize-m32rx */ - , HW_H_COND, HW_H_SM, HW_H_BSM, HW_H_IE - , HW_H_BIE, HW_H_BCOND, HW_H_BPC, HW_H_LOCK - , HW_MAX -} HW_TYPE; - -#define MAX_HW ((int) HW_MAX) - /* Hardware decls. */ extern CGEN_KEYWORD m32r_cgen_opval_h_gr;