From 8948cc6971fb82feffc49e2d21747111466ad642 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 9 Jan 2020 06:44:16 +1030 Subject: [PATCH] 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. --- include/ChangeLog | 9 +++++++++ include/opcode/spu.h | 37 ++++++++++++++++++++----------------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/include/ChangeLog b/include/ChangeLog index cd0410494d..91765c5be6 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,12 @@ +2020-01-10 Alan Modra + + * 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 * opcode/arc.h (insn_class_t): Add 'LLOCK' and 'SCOND'. diff --git a/include/opcode/spu.h b/include/opcode/spu.h index 50dce8a900..d8505ef6da 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)) -- 2.34.1