[binutils-gdb] ubsan: spu: left shift of negative value

Alan Modra amodra@sourceware.org
Fri Jan 10 11:11:00 GMT 2020


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=8948cc6971fb82feffc49e2d21747111466ad642

commit 8948cc6971fb82feffc49e2d21747111466ad642
Author: Alan Modra <amodra@gmail.com>
Date:   Thu Jan 9 06:44:16 2020 +1030

    ubsan: spu: left shift of negative value
    
    Also fixes a real bug.  The DECODE_INSN_I9a and DECODE_INSN_I9b both
    use UNSIGNED_EXTRACT for 7 low bits of the result, but this was an
    unsigned value due to "insn" being unsigned.  DECODE_INSN_I9* is
    therefore unsigned too, leading to a zero extension in an expression
    using a bfd_vma if bfd_vma is 64 bits.
    
    	* opcode/spu.h: Formatting.
    	(UNSIGNED_EXTRACT): Use 1u.
    	(SIGNED_EXTRACT): Don't sign extend with shifts.
    	(DECODE_INSN_I9a, DECODE_INSN_I9b): Avoid left shift of signed value.
    	Keep result signed.
    	(DECODE_INSN_U9a, DECODE_INSN_U9b): Delete.

Diff:
---
 include/ChangeLog    |  9 +++++++++
 include/opcode/spu.h | 37 ++++++++++++++++++++-----------------
 2 files changed, 29 insertions(+), 17 deletions(-)

diff --git a/include/ChangeLog b/include/ChangeLog
index cd04104..91765c5 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,12 @@
+2020-01-10  Alan Modra  <amodra@gmail.com>
+
+	* opcode/spu.h: Formatting.
+	(UNSIGNED_EXTRACT): Use 1u.
+	(SIGNED_EXTRACT): Don't sign extend with shifts.
+	(DECODE_INSN_I9a, DECODE_INSN_I9b): Avoid left shift of signed value.
+	Keep result signed.
+	(DECODE_INSN_U9a, DECODE_INSN_U9b): Delete.
+
 2020-01-07  Shahab Vahedi  <shahab@synopsys.com>
 
 	* opcode/arc.h (insn_class_t): Add 'LLOCK' and 'SCOND'.
diff --git a/include/opcode/spu.h b/include/opcode/spu.h
index 50dce8a..d8505ef 100644
--- a/include/opcode/spu.h
+++ b/include/opcode/spu.h
@@ -87,39 +87,42 @@ struct spu_opcode
    int arg[5];
 };
 
-#define SIGNED_EXTRACT(insn,size,pos) (((int)((insn) << (32-size-pos))) >> (32-size))
-#define UNSIGNED_EXTRACT(insn,size,pos) (((insn) >> pos) & ((1 << size)-1))
+#define UNSIGNED_EXTRACT(insn, size, pos)	\
+  (((insn) >> (pos)) & ((1u << (size)) - 1))
+#define SIGNED_EXTRACT(insn, size, pos)			\
+  (((int) UNSIGNED_EXTRACT(insn, size, pos)		\
+    ^ (1 << ((size) - 1))) - (1 << ((size) - 1)))
 
 #define DECODE_INSN_RT(insn) (insn & 0x7f)
 #define DECODE_INSN_RA(insn) ((insn >> 7) & 0x7f)
 #define DECODE_INSN_RB(insn) ((insn >> 14) & 0x7f)
 #define DECODE_INSN_RC(insn) ((insn >> 21) & 0x7f)
 
-#define DECODE_INSN_I10(insn) SIGNED_EXTRACT(insn,10,14)
-#define DECODE_INSN_U10(insn) UNSIGNED_EXTRACT(insn,10,14)
+#define DECODE_INSN_I10(insn) SIGNED_EXTRACT (insn, 10, 14)
+#define DECODE_INSN_U10(insn) UNSIGNED_EXTRACT (insn, 10, 14)
 
 /* For branching, immediate loads, hbr and  lqa/stqa. */
-#define DECODE_INSN_I16(insn) SIGNED_EXTRACT(insn,16,7)
-#define DECODE_INSN_U16(insn) UNSIGNED_EXTRACT(insn,16,7)
+#define DECODE_INSN_I16(insn) SIGNED_EXTRACT (insn, 16, 7)
+#define DECODE_INSN_U16(insn) UNSIGNED_EXTRACT (insn, 16, 7)
 
 /* for stop */
-#define DECODE_INSN_U14(insn) UNSIGNED_EXTRACT(insn,14,0)
+#define DECODE_INSN_U14(insn) UNSIGNED_EXTRACT (insn, 14, 0)
 
 /* For ila */
-#define DECODE_INSN_I18(insn) SIGNED_EXTRACT(insn,18,7)
-#define DECODE_INSN_U18(insn) UNSIGNED_EXTRACT(insn,18,7)
+#define DECODE_INSN_I18(insn) SIGNED_EXTRACT (insn, 18, 7)
+#define DECODE_INSN_U18(insn) UNSIGNED_EXTRACT (insn, 18, 7)
 
 /* For rotate and shift and generate control mask */
-#define DECODE_INSN_I7(insn) SIGNED_EXTRACT(insn,7,14)
-#define DECODE_INSN_U7(insn) UNSIGNED_EXTRACT(insn,7,14)
+#define DECODE_INSN_I7(insn) SIGNED_EXTRACT (insn, 7, 14)
+#define DECODE_INSN_U7(insn) UNSIGNED_EXTRACT (insn, 7, 14)
 
 /* For float <-> int conversion */
-#define DECODE_INSN_I8(insn)  SIGNED_EXTRACT(insn,8,14)
-#define DECODE_INSN_U8(insn) UNSIGNED_EXTRACT(insn,8,14)
+#define DECODE_INSN_I8(insn) SIGNED_EXTRACT (insn, 8, 14)
+#define DECODE_INSN_U8(insn) UNSIGNED_EXTRACT (insn, 8, 14)
 
 /* For hbr  */
-#define DECODE_INSN_I9a(insn) ((SIGNED_EXTRACT(insn,2,23) << 7) | UNSIGNED_EXTRACT(insn,7,0))
-#define DECODE_INSN_I9b(insn) ((SIGNED_EXTRACT(insn,2,14) << 7) | UNSIGNED_EXTRACT(insn,7,0))
-#define DECODE_INSN_U9a(insn) ((UNSIGNED_EXTRACT(insn,2,23) << 7) | UNSIGNED_EXTRACT(insn,7,0))
-#define DECODE_INSN_U9b(insn) ((UNSIGNED_EXTRACT(insn,2,14) << 7) | UNSIGNED_EXTRACT(insn,7,0))
+#define DECODE_INSN_I9a(insn) \
+  ((SIGNED_EXTRACT (insn, 2, 23) * 128) | (int) UNSIGNED_EXTRACT (insn, 7, 0))
+#define DECODE_INSN_I9b(insn) \
+  ((SIGNED_EXTRACT (insn, 2, 14) * 128) | (int) UNSIGNED_EXTRACT (insn, 7, 0))



More information about the Binutils-cvs mailing list