public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* RFC: .sleb128 and bignums
@ 2005-01-11 14:41 Richard Sandiford
  2005-01-11 16:37 ` Hans-Peter Nilsson
  2005-01-17 16:08 ` Nick Clifton
  0 siblings, 2 replies; 7+ messages in thread
From: Richard Sandiford @ 2005-01-11 14:41 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 4961 bytes --]

gas/read.c has two sets of functions for handling .sleb128, one for
O_constants and one for O_bigs.  The O_big version seems to be
horribly broken.  For example, a i686-linux-gnu configuration will
assemble:

        .data
        .sleb128        0x123456789a

as:

---------------------------------------------------------------------
Contents of section .data:
 0000 1a                                   .               
---------------------------------------------------------------------

This is because the continuation bit is only set by:

      if (size == 0)
        {
          if ((val == 0 && (byte & 0x40) == 0)
              || (~(val | ~(((valueT) 1 << loaded) - 1)) == 0
                  && (byte & 0x40) != 0))
            byte |= 0x80;
        }

where "size" is the number of littlenums left to read.  This whole
condition is inverted: it's setting the continuation bit in exactly
the situations where it _shouldn't_ be set!  The net effect is that
every bignum .sleb128 is one byte long.

Even with that fixed, there are a couple of problems.  First, the
routine uses unsigned values and arithmetic shifts and never does
any form of sign-extension.  Thus if (a) the number is negative and
(b) every bit of the final littlenum is added to the to the leb128,
the result won't necessarily be negative.  Example:

	.data
	.sleb128	-0x7000000000000000

gives:

---------------------------------------------------------------------
Contents of section .data:
 0000 80808080 80808080 9001               ..........      
---------------------------------------------------------------------

...where the final byte should be 0x7f instead.

Second, the routine strips off sign-filled littlenums using:

  /* Strip leading sign extensions off the bignum.  */
  while (size > 0 && bignum[size - 1] == (LITTLENUM_TYPE) -1)
    size--;

This fails to check the sign of bignum[size - 2] and can therefore
convert a negative number into a positive one.  Example:

	.data
	.sleb128	-0x100000000

gives:

---------------------------------------------------------------------
Contents of section .data:
 0000 808000                               ...             
---------------------------------------------------------------------

The first patch below should fix these cases.  That's only part of the
story though.  I was originally looking at this because the meaning of:

        .sleb128 0xffffffff

depends on whether you have a BFD64 toolchain or not.  If you don't
(as with powerpc-eabisim, for example) the constant is treated as -1.
If you do (as with mips-elf, which is still a 32-bit toolchain)
the constant is treated as an unsigned 33-bit value.

After the fix for gcc PR debug/14238, gcc will use the sleb128 above
for enumeration value FOO in:

        enum x { FOO = 0xffffffff } x;

gcc's HOST_WIDE_INT is 64 bits wide for powerpc-eabisim and so it can
store 0xffffffff as an unsigned value.  dwarf2asm.c:size_of_sleb128()
will therefore expect the sleb128 to be 5 bytes long, but gas produces
-1 instead, which throws off the offset calculations for the rest of
the .debug_info section.

I suppose this is really a gcc bug (it should probably be sign-extending
the constant) but I was curious to know whether the gas behaviour was
expected or not.  It seems odd for:

        .sleb128 0xffffffff

to be truncated but for a bigger number like:

        .sleb128 0x100000000

to be kept as-is.  The second patch below gets gas to treat the constant
as unsigned instead, but I'm not sure whether that's desirable.  It's also
something of a half-measure since any arithmetic involving 0xffffffff will
be done on O_constants, and thus:

        .sleb128 -0xffffffff

will still be treated as ".sleb128 1" by !BFD64 assemblers.

SO... to finally get to the point ;)  I guess there are three options:

  (1) Declare the treatment of 0xffffffff to be correct but fix the
      bignum problems (i.e. apply something like the first patch but
      not the second).

  (2) Treat values as unsigned if they were written that way (i.e. apply
      both patches, or variations of them).

  (3) Get rid of sleb128 bignum support altogether.  Treat everything
      as 32-bit if !BFD64.

(1) seems better than the status quo but the signed/unsigned thing is a
little odd.  I'm uneasy about (2) because of the arithmetic problem
described above.

According to the Cygnus repository, the bugs fixed by the first patch
have been around since the code was first added in Aug 1997.  That suggests
that bignum .sleb128s have never worked, yet as far as I know, no-one has
ever complained before.  Perhaps (3) really is a viable option?

At the moment, I'm really just posting these patches for comments.
I'll do proper testing, add testcases, etc., once I know what the
desired behaviour is.

Richard


gas/
	* read.c (output_big_sleb128): Fix setting of continuation bit.
	Check whether the final byte needs to be sign-extended.
	Fix size-shrinking loop.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: p1.diff --]
[-- Type: text/x-patch, Size: 2090 bytes --]

Index: gas/read.c
===================================================================
RCS file: /cvs/src/src/gas/read.c,v
retrieving revision 1.84
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.84 read.c
*** gas/read.c	29 Dec 2004 10:21:58 -0000	1.84
--- gas/read.c	11 Jan 2005 13:25:52 -0000
*************** output_big_sleb128 (char *p, LITTLENUM_T
*** 4276,4311 ****
    unsigned byte;
  
    /* Strip leading sign extensions off the bignum.  */
!   while (size > 0 && bignum[size - 1] == (LITTLENUM_TYPE) -1)
      size--;
  
    do
      {
!       if (loaded < 7 && size > 0)
! 	{
! 	  val |= (*bignum << loaded);
! 	  loaded += 8 * CHARS_PER_LITTLENUM;
! 	  size--;
! 	  bignum++;
! 	}
  
!       byte = val & 0x7f;
!       loaded -= 7;
!       val >>= 7;
! 
!       if (size == 0)
  	{
! 	  if ((val == 0 && (byte & 0x40) == 0)
! 	      || (~(val | ~(((valueT) 1 << loaded) - 1)) == 0
! 		  && (byte & 0x40) != 0))
  	    byte |= 0x80;
  	}
  
        if (orig)
! 	*p = byte;
        p++;
      }
-   while (byte & 0x80);
  
    return p - orig;
  }
--- 4285,4330 ----
    unsigned byte;
  
    /* Strip leading sign extensions off the bignum.  */
!   while (size > 1
! 	 && bignum[size - 1] == LITTLENUM_MASK
! 	 && bignum[size - 2] * 2 > LITTLENUM_MASK)
      size--;
  
    do
      {
!       /* OR in the next part of the littlenum.  */
!       val |= (*bignum << loaded);
!       loaded += LITTLENUM_NUMBER_OF_BITS;
!       size--;
!       bignum++;
  
!       /* Add bytes until there are less than 7 bits left in VAL
! 	 or until every non-sign bit has been written.  */
!       do
  	{
! 	  byte = val & 0x7f;
! 	  loaded -= 7;
! 	  val >>= 7;
! 	  if (size > 0
! 	      || val != ((byte & 0x40) == 0 ? 0 : ((valueT) 1 << loaded) - 1))
  	    byte |= 0x80;
+ 
+ 	  if (orig)
+ 	    *p = byte;
+ 	  p++;
  	}
+       while ((byte & 0x80) != 0 && loaded >= 7);
+     }
+   while (size > 0);
  
+   if ((byte & 0x80) != 0)
+     {
+       if (val & (1 << (loaded - 1)))
+ 	val |= ~0 << loaded;
        if (orig)
! 	*p = val & 0x7f;
        p++;
      }
  
    return p - orig;
  }

[-- Attachment #3: Type: text/plain, Size: 263 bytes --]


	* read.c (convert_to_bignum): New function, split out from...
	(emit_expr): ...here.
	(emit_leb128_expr): When generating a signed value, see whether an
	unsigned constant has been represented as a negative O_constant.
	Convert it to an unsigned bignum if so.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #4: p2.diff --]
[-- Type: text/x-patch, Size: 2572 bytes --]

Index: gas/read.c
===================================================================
RCS file: /cvs/src/src/gas/read.c,v
retrieving revision 1.84
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.84 read.c
*** gas/read.c	29 Dec 2004 10:21:58 -0000	1.84
--- gas/read.c	11 Jan 2005 13:25:52 -0000
*************** read_a_source_file (char *name)
*** 1082,1087 ****
--- 1082,1108 ----
  #endif
  }
  
+ /* Convert O_constant expression EXP to an equivalent O_big value.  */
+ 
+ static void
+ convert_to_bignum (expressionS *exp)
+ {
+   valueT value;
+   int index;
+ 
+   value = exp->X_add_number;
+   index = 0;
+   do
+     {
+       generic_bignum[index] = value & LITTLENUM_MASK;
+       value >>= LITTLENUM_NUMBER_OF_BITS;
+       index++;
+     }
+   while (value != 0);
+   exp->X_op = O_big;
+   exp->X_add_number = index;
+ }
+ 
  /* For most MRI pseudo-ops, the line actually ends at the first
     nonquoted space.  This function looks for that point, stuffs a null
     in, and sets *STOPCP to the character that used to be there, and
*************** emit_expr (expressionS *exp, unsigned in
*** 3541,3562 ****
       pass to md_number_to_chars, handle it as a bignum.  */
    if (op == O_constant && nbytes > sizeof (valueT))
      {
-       valueT val;
-       int gencnt;
- 
        if (!exp->X_unsigned && exp->X_add_number < 0)
  	extra_digit = (valueT) -1;
!       val = (valueT) exp->X_add_number;
!       gencnt = 0;
!       do
! 	{
! 	  generic_bignum[gencnt] = val & LITTLENUM_MASK;
! 	  val >>= LITTLENUM_NUMBER_OF_BITS;
! 	  ++gencnt;
! 	}
!       while (val != 0);
!       op = exp->X_op = O_big;
!       exp->X_add_number = gencnt;
      }
  
    if (op == O_constant)
--- 3562,3571 ----
       pass to md_number_to_chars, handle it as a bignum.  */
    if (op == O_constant && nbytes > sizeof (valueT))
      {
        if (!exp->X_unsigned && exp->X_add_number < 0)
  	extra_digit = (valueT) -1;
!       convert_to_bignum (exp);
!       op = O_big;
      }
  
    if (op == O_constant)
*************** emit_leb128_expr (expressionS *exp, int 
*** 4384,4389 ****
--- 4403,4417 ----
        as_warn (_("register value used as expression"));
        op = O_constant;
      }
+   else if (op == O_constant
+ 	   && sign
+ 	   && exp->X_unsigned
+ 	   && exp->X_add_number < 0)
+     {
+       convert_to_bignum (exp);
+       generic_bignum[exp->X_add_number++] = 0;
+       op = O_big;
+     }
  
    /* Let check_eh_frame know that data is being emitted.  nbytes == -1 is
       a signal that this is leb128 data.  It shouldn't optimize this away.  */

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFC: .sleb128 and bignums
  2005-01-11 14:41 RFC: .sleb128 and bignums Richard Sandiford
@ 2005-01-11 16:37 ` Hans-Peter Nilsson
  2005-01-11 19:47   ` Richard Sandiford
  2005-01-17 16:08 ` Nick Clifton
  1 sibling, 1 reply; 7+ messages in thread
From: Hans-Peter Nilsson @ 2005-01-11 16:37 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: binutils

On Tue, 11 Jan 2005, Richard Sandiford wrote:

> gas/read.c has two sets of functions for handling .sleb128, one for
> O_constants and one for O_bigs.  The O_big version seems to be
> horribly broken.  For example, a i686-linux-gnu configuration will
> assemble:
>
>         .data
>         .sleb128        0x123456789a
...

Pretty pretty please add one or more test-cases to gas.

brgds, H-P

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFC: .sleb128 and bignums
  2005-01-11 16:37 ` Hans-Peter Nilsson
@ 2005-01-11 19:47   ` Richard Sandiford
  0 siblings, 0 replies; 7+ messages in thread
From: Richard Sandiford @ 2005-01-11 19:47 UTC (permalink / raw)
  To: Hans-Peter Nilsson; +Cc: binutils

Hans-Peter Nilsson <hp@bitrange.com> writes:
> On Tue, 11 Jan 2005, Richard Sandiford wrote:
>
>> gas/read.c has two sets of functions for handling .sleb128, one for
>> O_constants and one for O_bigs.  The O_big version seems to be
>> horribly broken.  For example, a i686-linux-gnu configuration will
>> assemble:
>>
>>         .data
>>         .sleb128        0x123456789a
> ...
>
> Pretty pretty please add one or more test-cases to gas.

Well, like I said, I fully intend to once I know what the
intended behaviour is. ;)

Richard

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFC: .sleb128 and bignums
  2005-01-11 14:41 RFC: .sleb128 and bignums Richard Sandiford
  2005-01-11 16:37 ` Hans-Peter Nilsson
@ 2005-01-17 16:08 ` Nick Clifton
  2005-01-18  2:30   ` Alan Modra
  2005-01-18 13:27   ` Richard Sandiford
  1 sibling, 2 replies; 7+ messages in thread
From: Nick Clifton @ 2005-01-17 16:08 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: binutils

Hi Richard,

> SO... to finally get to the point ;)  I guess there are three options:
> 
>   (1) Declare the treatment of 0xffffffff to be correct but fix the
>       bignum problems (i.e. apply something like the first patch but
>       not the second).
> 
>   (2) Treat values as unsigned if they were written that way (i.e. apply
>       both patches, or variations of them).
> 
>   (3) Get rid of sleb128 bignum support altogether.  Treat everything
>       as 32-bit if !BFD64.
> 
> (1) seems better than the status quo but the signed/unsigned thing is a
> little odd.  I'm uneasy about (2) because of the arithmetic problem
> described above.
> 
> According to the Cygnus repository, the bugs fixed by the first patch
> have been around since the code was first added in Aug 1997.  That suggests
> that bignum .sleb128s have never worked, yet as far as I know, no-one has
> ever complained before.  Perhaps (3) really is a viable option?

Well we definitely ought to do (1).  Just because a problem has not been 
reported before there is no reason not to fix it now.

Personally I think that we ought to go with (2), but possibly arrange 
for a warning message to be generated and/or allow a command line switch 
or pseudo op to alter the new behaviour of GAS.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFC: .sleb128 and bignums
  2005-01-17 16:08 ` Nick Clifton
@ 2005-01-18  2:30   ` Alan Modra
  2005-01-18 13:27   ` Richard Sandiford
  1 sibling, 0 replies; 7+ messages in thread
From: Alan Modra @ 2005-01-18  2:30 UTC (permalink / raw)
  To: Nick Clifton; +Cc: Richard Sandiford, binutils

Note that there are other inconsistencies with gas expression
evaluation.  For instance

	    case O_right_shift:
	      /* We always use unsigned shifts, to avoid relying on
		 characteristics of the compiler used to compile gas.  */

while other operators use signed evaluation.  This is without even
considering what happens with bignums.

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFC: .sleb128 and bignums
  2005-01-17 16:08 ` Nick Clifton
  2005-01-18  2:30   ` Alan Modra
@ 2005-01-18 13:27   ` Richard Sandiford
  2005-01-19 11:27     ` Nick Clifton
  1 sibling, 1 reply; 7+ messages in thread
From: Richard Sandiford @ 2005-01-18 13:27 UTC (permalink / raw)
  To: Nick Clifton; +Cc: binutils

Nick Clifton <nickc@redhat.com> writes:
> Hi Richard,
>> SO... to finally get to the point ;)  I guess there are three options:
>>   (1) Declare the treatment of 0xffffffff to be correct but fix the
>>       bignum problems (i.e. apply something like the first patch but
>>       not the second).
>>   (2) Treat values as unsigned if they were written that way
>> (i.e. apply
>>       both patches, or variations of them).
>>   (3) Get rid of sleb128 bignum support altogether.  Treat everything
>>       as 32-bit if !BFD64.
>> (1) seems better than the status quo but the signed/unsigned thing is a
>> little odd.  I'm uneasy about (2) because of the arithmetic problem
>> described above.
>> According to the Cygnus repository, the bugs fixed by the first patch
>> have been around since the code was first added in Aug 1997.  That suggests
>> that bignum .sleb128s have never worked, yet as far as I know, no-one has
>> ever complained before.  Perhaps (3) really is a viable option?
>
> Well we definitely ought to do (1).  Just because a problem has not been
> reported before there is no reason not to fix it now.
>
> Personally I think that we ought to go with (2), but possibly arrange
> for a warning message to be generated and/or allow a command line switch
> or pseudo op to alter the new behaviour of GAS.

Thanks for the feedback.  Since posting the message, I've been coming
around to the idea that (2) is best as well.  Not sure about the warning
or command-line flag though.  Would it be OK to leave that for now, and
maybe add it later if anyone feels the need?

Alan's reply allays some of my concerns about the inconsistent treatment
of 32-bit vs. 64-bit numbers in general arithmetic, but I think we do
need to treat positive and negative constants consistently.  For example,
if we treat:

        .sleb128        0xffffffff

as a >32-bit number, then I think we need to do the same for:

        .sleb128        -0xffffffff

Handling both <literal> and -<literal> should be enough to keep gcc happy.

If we take that approach for .sleb128, I think we should be consistent
with other directives too.  At the moment:

        .quad           0x89abcdef

produces "efcdab89 00000000" on x86 (as expected), but:

        .quad           -0x89abcdef

produces "11325476 00000000", i.e. a positive 32-bit number.

The patch below implements (b) with the changes described above.
Tested on i686-pc-linux-gnu and mips64-linux-gnu (to check the two
endiannesses in the new .quad test).  OK to install?

Richard


gas/
	* read.c (convert_to_bignum): New function, split out from...
	(emit_expr): ...here.  Handle the case where X_add_number is
	positive and the input value is negative.
	(output_big_sleb128): Fix setting of continuation bit.  Check whether
	the final byte needs to be sign-extended.  Fix size-shrinking loop.
	(emit_leb128_expr): When generating a signed leb128, see whether the
	sign of an O_constant's X_add_number matches the sign of the input
	value.  Use a bignum if not.

gas/testsuite/
	* gas/all/sleb128.[sd]: New test.
	* gas/all/quad.[sd]: New test.
	* gas/all/gas.exp: Run them.

Index: gas/read.c
===================================================================
RCS file: /cvs/src/src/gas/read.c,v
retrieving revision 1.84
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.84 read.c
*** gas/read.c	29 Dec 2004 10:21:58 -0000	1.84
--- gas/read.c	18 Jan 2005 13:22:12 -0000
*************** read_a_source_file (char *name)
*** 1082,1087 ****
--- 1082,1110 ----
  #endif
  }
  
+ /* Convert O_constant expression EXP into the equivalent O_big representation.
+    Take the sign of the number from X_unsigned rather than X_add_number.  */
+ 
+ static void
+ convert_to_bignum (expressionS *exp)
+ {
+   valueT value;
+   unsigned int i;
+ 
+   value = exp->X_add_number;
+   for (i = 0; i < sizeof (exp->X_add_number) / CHARS_PER_LITTLENUM; i++)
+     {
+       generic_bignum[i] = value & LITTLENUM_MASK;
+       value >>= LITTLENUM_NUMBER_OF_BITS;
+     }
+   /* Add a sequence of sign bits if the top bit of X_add_number is not
+      the sign of the original value.  */
+   if ((exp->X_add_number < 0) != !exp->X_unsigned)
+     generic_bignum[i++] = exp->X_unsigned ? 0 : LITTLENUM_MASK;
+   exp->X_op = O_big;
+   exp->X_add_number = i;
+ }
+ 
  /* For most MRI pseudo-ops, the line actually ends at the first
     nonquoted space.  This function looks for that point, stuffs a null
     in, and sets *STOPCP to the character that used to be there, and
*************** emit_expr (expressionS *exp, unsigned in
*** 3541,3562 ****
       pass to md_number_to_chars, handle it as a bignum.  */
    if (op == O_constant && nbytes > sizeof (valueT))
      {
!       valueT val;
!       int gencnt;
! 
!       if (!exp->X_unsigned && exp->X_add_number < 0)
! 	extra_digit = (valueT) -1;
!       val = (valueT) exp->X_add_number;
!       gencnt = 0;
!       do
! 	{
! 	  generic_bignum[gencnt] = val & LITTLENUM_MASK;
! 	  val >>= LITTLENUM_NUMBER_OF_BITS;
! 	  ++gencnt;
! 	}
!       while (val != 0);
!       op = exp->X_op = O_big;
!       exp->X_add_number = gencnt;
      }
  
    if (op == O_constant)
--- 3564,3572 ----
       pass to md_number_to_chars, handle it as a bignum.  */
    if (op == O_constant && nbytes > sizeof (valueT))
      {
!       extra_digit = exp->X_unsigned ? 0 : -1;
!       convert_to_bignum (exp);
!       op = O_big;
      }
  
    if (op == O_constant)
*************** output_big_sleb128 (char *p, LITTLENUM_T
*** 4276,4311 ****
    unsigned byte;
  
    /* Strip leading sign extensions off the bignum.  */
!   while (size > 0 && bignum[size - 1] == (LITTLENUM_TYPE) -1)
      size--;
  
    do
      {
!       if (loaded < 7 && size > 0)
! 	{
! 	  val |= (*bignum << loaded);
! 	  loaded += 8 * CHARS_PER_LITTLENUM;
! 	  size--;
! 	  bignum++;
! 	}
! 
!       byte = val & 0x7f;
!       loaded -= 7;
!       val >>= 7;
  
!       if (size == 0)
  	{
! 	  if ((val == 0 && (byte & 0x40) == 0)
! 	      || (~(val | ~(((valueT) 1 << loaded) - 1)) == 0
! 		  && (byte & 0x40) != 0))
  	    byte |= 0x80;
  	}
  
        if (orig)
! 	*p = byte;
        p++;
      }
-   while (byte & 0x80);
  
    return p - orig;
  }
--- 4286,4333 ----
    unsigned byte;
  
    /* Strip leading sign extensions off the bignum.  */
!   while (size > 1
! 	 && bignum[size - 1] == LITTLENUM_MASK
! 	 && bignum[size - 2] > LITTLENUM_MASK / 2)
      size--;
  
    do
      {
!       /* OR in the next part of the littlenum.  */
!       val |= (*bignum << loaded);
!       loaded += LITTLENUM_NUMBER_OF_BITS;
!       size--;
!       bignum++;
  
!       /* Add bytes until there are less than 7 bits left in VAL
! 	 or until every non-sign bit has been written.  */
!       do
  	{
! 	  byte = val & 0x7f;
! 	  loaded -= 7;
! 	  val >>= 7;
! 	  if (size > 0
! 	      || val != ((byte & 0x40) == 0 ? 0 : ((valueT) 1 << loaded) - 1))
  	    byte |= 0x80;
+ 
+ 	  if (orig)
+ 	    *p = byte;
+ 	  p++;
  	}
+       while ((byte & 0x80) != 0 && loaded >= 7);
+     }
+   while (size > 0);
  
+   /* Mop up any left-over bits (of which there will be less than 7).  */
+   if ((byte & 0x80) != 0)
+     {
+       /* Sign-extend VAL.  */
+       if (val & (1 << (loaded - 1)))
+ 	val |= ~0 << loaded;
        if (orig)
! 	*p = val & 0x7f;
        p++;
      }
  
    return p - orig;
  }
*************** emit_leb128_expr (expressionS *exp, int 
*** 4384,4389 ****
--- 4406,4421 ----
        as_warn (_("register value used as expression"));
        op = O_constant;
      }
+   else if (op == O_constant
+ 	   && sign
+ 	   && (exp->X_add_number < 0) != !exp->X_unsigned)
+     {
+       /* We're outputting a signed leb128 and the sign of X_add_number
+ 	 doesn't reflect the sign of the original value.  Convert EXP
+ 	 to a correctly-extended bignum instead.  */
+       convert_to_bignum (exp);
+       op = O_big;
+     }
  
    /* Let check_eh_frame know that data is being emitted.  nbytes == -1 is
       a signal that this is leb128 data.  It shouldn't optimize this away.  */
Index: gas/testsuite/gas/all/gas.exp
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/all/gas.exp,v
retrieving revision 1.23
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.23 gas.exp
*** gas/testsuite/gas/all/gas.exp	22 Nov 2004 13:00:23 -0000	1.23
--- gas/testsuite/gas/all/gas.exp	18 Jan 2005 13:22:12 -0000
*************** if {   [istarget "i*86-*-*pe*"] \
*** 195,200 ****
--- 195,203 ----
    gas_test "fastcall.s" ""   "" "fastcall labels"
  }
  
+ run_dump_test sleb128
+ run_dump_test quad
+ 
  load_lib gas-dg.exp
  dg-init
  dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/err-*.s $srcdir/$subdir/warn-*.s]] "" ""
diff -c /dev/null gas/testsuite/gas/all/quad.d
*** /dev/null	2004-12-03 11:50:38.225654048 +0000
--- gas/testsuite/gas/all/quad.d	2005-01-18 13:21:29.561772137 +0000
***************
*** 0 ****
--- 1,12 ----
+ #objdump : -s -j .data
+ #name : .quad tests
+ 
+ .*: .*
+ 
+ Contents of section .data:
+  0000 (00000000 76543210 00000000 80000000|10325476 00000000 00000080 00000000) .*
+  0010 (00000000 87654321 00000000 ffffffff|21436587 00000000 ffffffff 00000000) .*
+  0020 (ffffffff 89abcdf0 ffffffff 80000000|f0cdab89 ffffffff 00000080 ffffffff) .*
+  0030 (ffffffff 789abcdf ffffffff 00000001|dfbc9a78 ffffffff 01000000 ffffffff) .*
+  0040 (01234567 89abcdef fedcba98 76543211|efcdab89 67452301 11325476 98badcfe) .*
+ #pass
diff -c /dev/null gas/testsuite/gas/all/quad.s
*** /dev/null	2004-12-03 11:50:38.225654048 +0000
--- gas/testsuite/gas/all/quad.s	2005-01-18 12:45:03.210086611 +0000
***************
*** 0 ****
--- 1,12 ----
+ 	.data
+ 	.quad	0x76543210
+ 	.quad	0x80000000
+ 	.quad	0x87654321
+ 	.quad	0xffffffff
+ 	.quad	-0x76543210
+ 	.quad	-0x80000000
+ 	.quad	-0x87654321
+ 	.quad	-0xffffffff
+ 
+ 	.quad	0x123456789abcdef
+ 	.quad	-0x123456789abcdef
diff -c /dev/null gas/testsuite/gas/all/sleb128.d
*** /dev/null	2004-12-03 11:50:38.225654048 +0000
--- gas/testsuite/gas/all/sleb128.d	2005-01-18 12:45:30.506962483 +0000
***************
*** 0 ****
--- 1,57 ----
+ #objdump : -s -j .data
+ #name : .sleb128 tests
+ 
+ .*: .*
+ 
+ Contents of section .data:
+ #
+ # 0x76543210   :           000_0111 0110_010 1_0100_00 11_0010_0 001_0000
+ # 0x80000000   :           000_1000 0000_000 0_0000_00 00_0000_0 000_0000
+ # 0x87654321   :           000_1000 0111_011 0_0101_01 00_0011_0 010_0001
+ # 0xffffffff   :           ..................................... 111_1111
+ #
+  0000 90e4d0b2 07808080 8008a186 95bb08ff .*
+ #
+ # 0xffffffff   :           000_1111 1111_111 1_1111_11 11_1111_1 ........
+ # -0x76543210  :           111_1000 1001_101 0_1011_11 00_1101_1 111_0000
+ # -0x80000000  :           111_1000 0000_000 0_0000_00 00_0000_0 000_0000
+ # -0x87654321  :           ........................... 11_1100_1 101_1111
+ #
+  0010 ffffff0f f09bafcd 78808080 8078dff9 .*
+ #
+ # -0x87654321  :           111_0111 1000_100 1_1010_10 ..................
+ # -0xffffffff  :           111_0000 0000_000 0_0000_00 00_0000_0 000_0001
+ #    789abcdef :           111_1000 1001_101 0_1011_11 00_1101_1 110_1111
+ # 0x123456     :           ........ 0010_001 1_0100_01 01_0110_0
+ #
+  0020 eac47781 80808070 ef9bafcd f8acd191 .*
+ #
+ # 0x123456     :           000_0001 ............................
+ #    789abcdef :           000_0111 0110_010 1_0100_00 11_0010_0 001_0001
+ # -0x123456    :           111_1110 1101_110 0_1011_10 01_1001_1
+ #    fffffffff :           000_0000 0000_000 0_0000_00 00_0000_0 000_0001
+ # -0x7ff       :                             ......... 00_0000_0
+ #
+  0030 0191e4d0 b287d3ae ee7e8180 80808080 .*
+ #
+ # -0x7ff       :                             1_1000_00 .........
+ #    000000000 :           000_0000 0000_000 0_0000_00 00_0000_0 000_0000
+ # -0x800       :                             1_1000_00 00_0000_0
+ #    fffffffff :           000_0000 0000_000 0_0000_00 00_0000_0 000_0001
+ # -0x7ffffff   : .................. 0000_000 0_0000_00 00_0000_0
+ #
+  0040 60808080 80808060 81808080 80808080 .*
+ #
+ # -0x7ffffff   : 11_1111_1 000_0000 ............................
+ #    000000000 :           000_0000 0000_000 0_0000_00 00_0000_0 000_0000
+ # -0x8000000   : 11_1111_1 000_0000 0000_000 0_0000_00 00_0000_0
+ # -0x100000000 :           ........ 0000_000 0_0000_00 00_0000_0 000_0000
+ #
+  0050 807f8080 80808080 8080807f 80808080 .*
+ #
+ # -0x100000000 :           111_0000 .....................................
+ #    000000000 :           000_0000 0000_000 0_0000_00 00_0000_0 000_0000
+ # -0x1000      :                             1_0000_00 00_0000_0
+ #
+  0060 70808080 80808040 00000000 00000000 .*
+ #pass
diff -c /dev/null gas/testsuite/gas/all/sleb128.s
*** /dev/null	2004-12-03 11:50:38.225654048 +0000
--- gas/testsuite/gas/all/sleb128.s	2005-01-18 10:50:21.000000000 +0000
***************
*** 0 ****
--- 1,22 ----
+ 	.data
+ 	.sleb128	0x76543210
+ 	.sleb128	0x80000000
+ 	.sleb128	0x87654321
+ 	.sleb128	0xffffffff
+ 	.sleb128	-0x76543210
+ 	.sleb128	-0x80000000
+ 	.sleb128	-0x87654321
+ 	.sleb128	-0xffffffff
+ 
+ 	.sleb128	0x123456789abcdef
+ 	.sleb128	-0x123456789abcdef
+ 
+ 	.sleb128	-0x7fffffffffff
+ 	.sleb128	-0x800000000000
+ 	.sleb128	-0x7fffffffffffffff
+ 	.sleb128	-0x8000000000000000
+ 
+ 	.sleb128	-0x100000000
+ 	.sleb128	-0x1000000000000
+ 
+ 	.fill		32

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFC: .sleb128 and bignums
  2005-01-18 13:27   ` Richard Sandiford
@ 2005-01-19 11:27     ` Nick Clifton
  0 siblings, 0 replies; 7+ messages in thread
From: Nick Clifton @ 2005-01-19 11:27 UTC (permalink / raw)
  To: Richard Sandiford; +Cc: binutils

Hi Richard,

> gas/
> 	* read.c (convert_to_bignum): New function, split out from...
> 	(emit_expr): ...here.  Handle the case where X_add_number is
> 	positive and the input value is negative.
> 	(output_big_sleb128): Fix setting of continuation bit.  Check whether
> 	the final byte needs to be sign-extended.  Fix size-shrinking loop.
> 	(emit_leb128_expr): When generating a signed leb128, see whether the
> 	sign of an O_constant's X_add_number matches the sign of the input
> 	value.  Use a bignum if not.
> 
> gas/testsuite/
> 	* gas/all/sleb128.[sd]: New test.
> 	* gas/all/quad.[sd]: New test.
> 	* gas/all/gas.exp: Run them.

Approved - please apply.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2005-01-19 11:27 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-01-11 14:41 RFC: .sleb128 and bignums Richard Sandiford
2005-01-11 16:37 ` Hans-Peter Nilsson
2005-01-11 19:47   ` Richard Sandiford
2005-01-17 16:08 ` Nick Clifton
2005-01-18  2:30   ` Alan Modra
2005-01-18 13:27   ` Richard Sandiford
2005-01-19 11:27     ` Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).