From mboxrd@z Thu Jan 1 00:00:00 1970 From: Richard Sandiford To: Doug Evans Cc: binutils@sources.redhat.com, cgen@sources.redhat.com Subject: Re: CGEN patch Date: Tue, 02 Jan 2001 06:51:00 -0000 Message-id: References: <14914.32352.563095.486108@casey.transmeta.com> X-SW-Source: 2001-q1/msg00001.html On Thu, 21 Dec 2000, Doug Evans wrote: > fwiw, I'd prefer to keep cgen_get/put_insn_value kept as functions. > They can still call the bfd routines, but I'd rather not > have them as functions. > OK, revised patch below. 2001-01-02 Richard Sandiford * cgen-dis.c (hash_insn_array): Use bfd_put_bits(). (hash_insn_list): Likewise * cgen-ibld.in (insert_1): Use bfd_put_bits() and bfd_get_bits(). (extract_1): Use bfd_get_bits(). (extract_normal): Apply sign extension to both extraction methods. * cgen-op.c (cgen_get_insn_value): Use bfd_get_bits() (cgen_put_insn_value): Use bfd_put_bits() Index: opcodes/cgen-dis.c =================================================================== RCS file: /cvs/src/src/opcodes/cgen-dis.c,v retrieving revision 1.2 diff -c -r1.2 cgen-dis.c *** cgen-dis.c 2000/07/26 22:45:49 1.2 --- opcodes/cgen-dis.c 2001/01/02 14:36:44 *************** *** 64,90 **** to hash on, so set both up. */ value = CGEN_INSN_BASE_VALUE (insn); ! switch (CGEN_INSN_MASK_BITSIZE (insn)) ! { ! case 8: ! buf[0] = value; ! break; ! case 16: ! if (big_p) ! bfd_putb16 ((bfd_vma) value, buf); ! else ! bfd_putl16 ((bfd_vma) value, buf); ! break; ! case 32: ! if (big_p) ! bfd_putb32 ((bfd_vma) value, buf); ! else ! bfd_putl32 ((bfd_vma) value, buf); ! break; ! default: ! abort (); ! } ! hash = (* cd->dis_hash) (buf, value); hentbuf->next = htable[hash]; hentbuf->insn = insn; --- 64,73 ---- to hash on, so set both up. */ value = CGEN_INSN_BASE_VALUE (insn); ! bfd_put_bits ((bfd_vma) value, ! buf, ! CGEN_INSN_MASK_BITSIZE (insn), ! big_p); hash = (* cd->dis_hash) (buf, value); hentbuf->next = htable[hash]; hentbuf->insn = insn; *************** *** 121,147 **** to hash on, so set both up. */ value = CGEN_INSN_BASE_VALUE (ilist->insn); ! switch (CGEN_INSN_MASK_BITSIZE (ilist->insn)) ! { ! case 8: ! buf[0] = value; ! break; ! case 16: ! if (big_p) ! bfd_putb16 ((bfd_vma) value, buf); ! else ! bfd_putl16 ((bfd_vma) value, buf); ! break; ! case 32: ! if (big_p) ! bfd_putb32 ((bfd_vma) value, buf); ! else ! bfd_putl32 ((bfd_vma) value, buf); ! break; ! default: ! abort (); ! } ! hash = (* cd->dis_hash) (buf, value); hentbuf->next = htable [hash]; hentbuf->insn = ilist->insn; --- 104,113 ---- to hash on, so set both up. */ value = CGEN_INSN_BASE_VALUE (ilist->insn); ! bfd_put_bits((bfd_vma) value, ! buf, ! CGEN_INSN_MASK_BITSIZE (ilist->insn), ! big_p); hash = (* cd->dis_hash) (buf, value); hentbuf->next = htable [hash]; hentbuf->insn = ilist->insn; Index: opcodes/cgen-opc.c =================================================================== RCS file: /cvs/src/src/opcodes/cgen-opc.c,v retrieving revision 1.4 diff -c -r1.4 cgen-opc.c *** cgen-opc.c 2000/12/21 18:43:33 1.4 --- opcodes/cgen-opc.c 2001/01/02 14:36:46 *************** *** 374,403 **** unsigned char *buf; int length; { ! CGEN_INSN_INT value; ! ! switch (length) ! { ! case 8: ! value = *buf; ! break; ! case 16: ! if (cd->insn_endian == CGEN_ENDIAN_BIG) ! value = bfd_getb16 (buf); ! else ! value = bfd_getl16 (buf); ! break; ! case 32: ! if (cd->insn_endian == 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. */ --- 374,380 ---- unsigned char *buf; int length; { ! bfd_get_bits (buf, length, cd->insn_endian == CGEN_ENDIAN_BIG); } /* Cover function to store an insn value properly byteswapped. */ *************** *** 409,434 **** int length; CGEN_INSN_INT value; { ! switch (length) ! { ! case 8: ! buf[0] = value; ! break; ! case 16: ! if (cd->insn_endian == CGEN_ENDIAN_BIG) ! bfd_putb16 (value, buf); ! else ! bfd_putl16 (value, buf); ! break; ! case 32: ! if (cd->insn_endian == CGEN_ENDIAN_BIG) ! bfd_putb32 (value, buf); ! else ! bfd_putl32 (value, buf); ! break; ! default: ! abort (); ! } } /* Look up instruction INSN_*_VALUE and extract its fields. --- 386,393 ---- int length; CGEN_INSN_INT value; { ! bfd_put_bits ((bfd_vma) value, buf, length, ! cd->insn_endian == CGEN_ENDIAN_BIG); } /* Look up instruction INSN_*_VALUE and extract its fields. Index: opcodes/cgen-ibld.in =================================================================== RCS file: /cvs/src/src/opcodes/cgen-ibld.in,v retrieving revision 1.2 diff -c -r1.2 cgen-ibld.in *** cgen-ibld.in 2000/08/28 18:17:54 1.2 --- opcodes/cgen-ibld.in 2001/01/02 14:36:47 *************** *** 78,111 **** int shift; int big_p = CGEN_CPU_INSN_ENDIAN (cd) == 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; --- 78,84 ---- int shift; int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG; ! x = bfd_get_bits (bufp, word_length, big_p); /* Written this way to avoid undefined behaviour. */ mask = (((1L << (length - 1)) - 1) << 1) | 1; *************** *** 115,154 **** 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 */ --- 88,94 ---- shift = (word_length - (start + length)); x = (x & ~(mask << shift)) | ((value & mask) << shift); ! bfd_put_bits ((bfd_vma) x, bufp, word_length, big_p); } #endif /* ! CGEN_INT_INSN_P */ *************** *** 406,451 **** unsigned char *bufp; bfd_vma pc; { ! unsigned long x,mask; int shift; int big_p = CGEN_CPU_INSN_ENDIAN (cd) == 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)); ! return (x >> shift) & mask; } #endif /* ! CGEN_INT_INSN_P */ --- 346,362 ---- unsigned char *bufp; bfd_vma pc; { ! unsigned long x; int shift; int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG; ! x = bfd_get_bits (bufp, word_length, big_p); if (CGEN_INSN_LSB0_P) shift = (start + 1) - length; else shift = (word_length - (start + length)); ! return x >> shift; } #endif /* ! CGEN_INT_INSN_P */ *************** *** 489,495 **** #endif long *valuep; { ! CGEN_INSN_INT value; /* If LENGTH is zero, this operand doesn't contribute to the value so give it a standard value of zero. */ --- 400,406 ---- #endif long *valuep; { ! CGEN_INSN_INT value, mask; /* If LENGTH is zero, this operand doesn't contribute to the value so give it a standard value of zero. */ *************** *** 521,538 **** if (CGEN_INT_INSN_P || 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 >> ((word_offset + start + 1) - length); else value = insn_value >> (total_length - ( word_offset + start + length)); - value &= mask; - /* sign extend? */ - if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED) - && (value & (1L << (length - 1)))) - value |= ~mask; } #if ! CGEN_INT_INSN_P --- 432,441 ---- *************** *** 551,556 **** --- 454,468 ---- } #endif /* ! CGEN_INT_INSN_P */ + + /* Written this way to avoid undefined behaviour. */ + mask = (((1L << (length - 1)) - 1) << 1) | 1; + + value &= mask; + /* sign extend? */ + if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED) + && (value & (1L << (length - 1)))) + value |= ~mask; *valuep = value;