]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas: also maintain signed-ness for O_big expressions
authorJan Beulich <jbeulich@suse.com>
Fri, 13 Jun 2025 06:39:44 +0000 (08:39 +0200)
committerJan Beulich <jbeulich@suse.com>
Fri, 13 Jun 2025 06:39:44 +0000 (08:39 +0200)
Interestingly emit_leb128_expr() already assumes X_unsigned is properly
set for O_big. Adjust its conversion-to-bignum to respect the incoming
flag, and have convert_to_bignum() correctly set it on output.

It further can't be quite right that convert_to_bignum() depends on
anything other than the incoming expression. Therefore adjust
emit_expr_with_reloc() to be in line with the other invocation.

This also requires an adjustment for SH, which really should have been
part of 762acf217c40 ("gas: maintain O_constant signedness in more
cases").

gas/config/tc-sh.c
gas/expr.c
gas/expr.h
gas/read.c
gas/testsuite/gas/all/octa.d
gas/testsuite/gas/all/octa.s

index 9620eef9e936a2b4441ee266844130cb40f372e8..c37306f2f58f2b4a8e159626f365a502154b5850 100644 (file)
@@ -544,6 +544,7 @@ sh_optimize_expr (expressionS *l, operatorT op, expressionS *r)
       add_to_result (l, symval_diff, symval_diff < 0);
       l->X_op = O_constant;
       l->X_add_symbol = 0;
+      l->X_unsigned = 0;
       return 1;
     }
   return 0;
index bf58fc3a768e13efca7816ac31d3adc0c754cd93..78a247cde097d78579236e9495d540fb6758876b 100644 (file)
@@ -632,6 +632,7 @@ integer_constant (int radix, expressionS *expressionP)
       /* Not a small number.  */
       expressionP->X_op = O_big;
       expressionP->X_add_number = number;      /* Number of littlenums.  */
+      expressionP->X_unsigned = 1;
       input_line_pointer--;    /* -> char following number.  */
     }
 }
@@ -707,6 +708,7 @@ mri_char_constant (expressionS *expressionP)
     {
       expressionP->X_op = O_big;
       expressionP->X_add_number = i;
+      expressionP->X_unsigned = 1;
     }
   else
     {
@@ -1164,6 +1166,8 @@ operand (expressionS *expressionP, enum expr_mode mode)
                      if (generic_bignum[i])
                        break;
                    }
+
+               expressionP->X_unsigned = 0;
              }
            else if (op == O_logical_not)
              {
index 14787c413430fa03f71b6580fdfe0067c61de20f..2be3d69683c0d3921dc9ba9ea3a9df5ebb47f2fe 100644 (file)
@@ -131,10 +131,12 @@ typedef struct expressionS
   unsigned char X_op;
 #endif
 
-  /* Non-zero if X_add_number should be regarded as unsigned.  This is
-     only valid for O_constant expressions.  It is only used when an
-     O_constant must be extended into a bignum (i.e., it is not used
-     when performing arithmetic on these values).
+  /* Non-zero if the expression value should be regarded as unsigned.  This is
+     only valid for
+     - O_constant expressions, where it is only used when an O_constant must be
+       extended into a bignum (i.e., it is not used when performing arithmetic
+       on these values),
+     - O_big integer expressions, i.e. when X_add_number is positive.
      FIXME: This field is not set very reliably.  */
   unsigned int X_unsigned : 1;
   /* This is used to implement "word size + 1 bit" arithmetic, so that e.g.
index c9cbd224a7d50c5d6e2e18b4f60b9001c5744448..1b483d683d5d36ba8cbc267f557dd1c6426f05c8 100644 (file)
@@ -1458,6 +1458,7 @@ convert_to_bignum (expressionS *exp, int sign)
     generic_bignum[i++] = sign ? LITTLENUM_MASK : 0;
   exp->X_op = O_big;
   exp->X_add_number = i;
+  exp->X_unsigned = !sign;
 }
 
 /* For most MRI pseudo-ops, the line actually ends at the first
@@ -4651,8 +4652,8 @@ emit_expr_with_reloc (expressionS *exp,
      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, !exp->X_unsigned);
+      extra_digit = exp->X_unsigned ? 0 : -exp->X_extrabit;
+      convert_to_bignum (exp, -extra_digit);
       op = O_big;
     }
 
@@ -5371,12 +5372,14 @@ emit_leb128_expr (expressionS *exp, int sign)
     }
   else if (op == O_constant
           && sign
-          && (exp->X_add_number < 0) == !exp->X_extrabit)
+          && (exp->X_unsigned
+              ? exp->X_add_number < 0
+              : (exp->X_add_number < 0) != exp->X_extrabit))
     {
       /* 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, exp->X_extrabit);
+      convert_to_bignum (exp, !exp->X_unsigned && exp->X_extrabit);
       op = O_big;
     }
 
index e8eff2ce82849faba1df748710fb059f57c5a402..9c9120605d78eeaaa8a2d7e25422d7b8fcd77769 100644 (file)
@@ -14,3 +14,11 @@ Contents of section .data:
  [^ ]* (00000000 ffffffff ffffffff ffffffff|ffffffff ffffffff ffffffff 00000000) .*
  [^ ]* (00000080 ffffffff ffffffff ffffffff|ffffffff ffffffff ffffffff 80000000) .*
  [^ ]* (01000000 ffffffff ffffffff ffffffff|ffffffff ffffffff ffffffff 00000001) .*
+ [^ ]* (00000000 000000f0 ffffffff ffffffff|ffffffff ffffffff f0000000 00000000) .*
+ [^ ]* (00000000 00000010 00000000 00000000|00000000 00000000 10000000 00000000) .*
+ [^ ]* (ffffffff ffffffef ffffffff ffffffff|ffffffff ffffffff efffffff ffffffff) .*
+ [^ ]* (01000000 00000010 00000000 00000000|00000000 00000000 10000000 00000001) .*
+ [^ ]* (01000000 000000f0 ffffffff ffffffff|ffffffff ffffffff f0000000 00000001) .*
+ [^ ]* (feffffff ffffff0f 00000000 00000000|00000000 00000000 0fffffff fffffffe) .*
+ [^ ]* (02000000 000000f0 ffffffff ffffffff|ffffffff ffffffff f0000000 00000002) .*
+ [^ ]* (fdffffff ffffff0f 00000000 00000000|00000000 00000000 0fffffff fffffffd) .*
index faa21fa7ba04fac8f8a8a4e017f75e5523eb1e69..037941f2e6d0d04aa5f17b7e88a4f56625a8f8b2 100644 (file)
@@ -9,3 +9,13 @@
  .octa ~0xffffffff
  .octa 0 - 0x80000000
  .octa 0 - 0xffffffff
+
+ .octa ~0xfffffffffffffff
+ .octa -~0xfffffffffffffff
+ .octa ~-~0xfffffffffffffff
+ .octa -~-~0xfffffffffffffff
+
+ .octa -0xfffffffffffffff
+ .octa ~-0xfffffffffffffff
+ .octa -~-0xfffffffffffffff
+ .octa ~-~-0xfffffffffffffff