This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: CGEN patch
- To: Doug Evans <dje at transmeta dot com>
- Subject: Re: CGEN patch
- From: Richard Sandiford <rsandifo at cambridge dot redhat dot com>
- Date: Tue, 2 Jan 2001 14:50:59 +0000 (GMT)
- Cc: binutils at sources dot redhat dot com, cgen at sources dot redhat dot com
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 <rsandifo@redhat.com>
* 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;