ubsan: v850: left shift cannot be represented in type 'long'
authorAlan Modra <amodra@gmail.com>
Tue, 10 Dec 2019 22:23:50 +0000 (08:53 +1030)
committerAlan Modra <amodra@gmail.com>
Wed, 11 Dec 2019 01:11:52 +0000 (11:41 +1030)
* v850-dis.c (get_operand_value): Use unsigned arithmetic.  Don't
sign extend using shifts.

opcodes/ChangeLog
opcodes/v850-dis.c

index 3ba885c48b9b5d077fefaf1aab52d89be1ff54a3..2ad26cb5d6f05a28f9027677b887299aa8337973 100644 (file)
@@ -1,3 +1,8 @@
+2019-12-11  Alan Modra  <amodra@gmail.com>
+
+       * v850-dis.c (get_operand_value): Use unsigned arithmetic.  Don't
+       sign extend using shifts.
+
 2019-12-11  Alan Modra  <amodra@gmail.com>
 
        * tic6x-dis.c (tic6x_extract_32): Avoid signed overflow.
index f8b5d1c93f29b8e41ad46688e155476e1bddd6a7..45e6c65d83a19c25ee866b4d6e4334bcf03e95f2 100644 (file)
@@ -88,7 +88,7 @@ get_operand_value (const struct v850_operand *operand,
                   bfd_boolean noerror,
                   int *invalid)
 {
-  long value;
+  unsigned long value;
   bfd_byte buffer[4];
 
   if ((operand->flags & V850E_IMMEDIATE16)
@@ -158,11 +158,13 @@ get_operand_value (const struct v850_operand *operand,
       if (operand->bits == -1)
        value = (insn & operand->shift);
       else
-       value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
+       value = (insn >> operand->shift) & ((1ul << operand->bits) - 1);
 
       if (operand->flags & V850_OPERAND_SIGNED)
-       value = ((long)(value << (sizeof (long)*8 - operand->bits))
-                >> (sizeof (long)*8 - operand->bits));
+       {
+         unsigned long sign = 1ul << (operand->bits - 1);
+         value = (value ^ sign) - sign;
+       }
     }
 
   return value;