binutils/Remove-more-shifts-for-sign-zero-extension.patch
2019-12-25 15:42:36 +08:00

308 lines
11 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 1d61b032265e69317f42e8019e072506f11890c5 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Wed, 11 Dec 2019 16:45:14 +1030
Subject: [PATCH 026/109] Remove more shifts for sign/zero extension
cpu/
* epiphany.cpu (f-sdisp11): Don't sign extend with shifts.
* lm32.cpu (f-branch, f-vall): Likewise.
* m32.cpu (f-lab-8-16): Likewise.
opcodes/
* arc-dis.c (BITS): Don't truncate high bits with shifts.
* nios2-dis.c (nios2_print_insn_arg): Don't sign extend with shifts.
* tic54x-dis.c (print_instruction): Likewise.
* tilegx-opc.c (parse_insn_tilegx): Likewise.
* tilepro-opc.c (parse_insn_tilepro): Likewise.
* visium-dis.c (disassem_class0): Likewise.
* pdp11-dis.c (sign_extend): Likewise.
(SIGN_BITS): Delete.
* epiphany-ibld.c: Regenerate.
* lm32-ibld.c: Regenerate.
* m32c-ibld.c: Regenerate.
---
cpu/ChangeLog | 6 ++++++
cpu/epiphany.cpu | 9 +++++----
cpu/lm32.cpu | 8 ++++++--
cpu/m32c.cpu | 9 ++++++---
opcodes/ChangeLog | 14 ++++++++++++++
opcodes/arc-dis.c | 3 +--
opcodes/epiphany-ibld.c | 2 +-
opcodes/lm32-ibld.c | 4 ++--
opcodes/m32c-ibld.c | 4 ++--
opcodes/nios2-dis.c | 16 ++++++++--------
opcodes/pdp11-dis.c | 3 +--
opcodes/tic54x-dis.c | 3 +--
opcodes/tilegx-opc.c | 4 ++--
opcodes/tilepro-opc.c | 4 ++--
opcodes/visium-dis.c | 2 +-
15 files changed, 58 insertions(+), 33 deletions(-)
diff --git a/cpu/epiphany.cpu b/cpu/epiphany.cpu
index 9f873b3..02bce07 100644
--- a/cpu/epiphany.cpu
+++ b/cpu/epiphany.cpu
@@ -228,10 +228,11 @@
(set (ifield f-disp3) (and SI (ifield f-sdisp11) 7)))
(sequence () ;decode
(set (ifield f-sdisp11)
- (sra SI (sll SI (or SI (sll (ifield f-disp8) 3)
- (ifield f-disp3))
- 21)
- 21)))
+ (sub SI (xor (and (or (sll (ifield f-disp8) 3)
+ (ifield f-disp3))
+ #x7ff)
+ #x400)
+ #x400)))
)
(dnmf f-imm16 "Short immediate for move/add/sub" () UINT (f-imm8 f-imm-27-8)
diff --git a/cpu/lm32.cpu b/cpu/lm32.cpu
index 83c839f..ecd8160 100644
--- a/cpu/lm32.cpu
+++ b/cpu/lm32.cpu
@@ -128,11 +128,15 @@
(df f-branch "branch offset field" (PCREL-ADDR) 15 16 INT
((value pc) (sra SI (sub SI value pc) 2))
- ((value pc) (add SI pc (sra SI (sll SI value 16) 14)))
+ ((value pc) (add SI pc (sub (xor (sll (and value #xffff) 2)
+ #x20000)
+ #x20000)))
)
(df f-call "call offset field" (PCREL-ADDR) 25 26 INT
((value pc) (sra SI (sub SI value pc) 2))
- ((value pc) (add SI pc (sra SI (sll SI value 6) 4)))
+ ((value pc) (add SI pc (sub (xor (sll (and value #x3ffffff) 2)
+ #x8000000)
+ #x8000000)))
)
diff --git a/cpu/m32c.cpu b/cpu/m32c.cpu
index bcc3616..5a38f1b 100644
--- a/cpu/m32c.cpu
+++ b/cpu/m32c.cpu
@@ -956,9 +956,12 @@
)
(df f-lab-8-16 "16 bit pc relative signed offset" (PCREL-ADDR SIGN-OPT all-isas) 8 16 UINT
((value pc) (or SI (sll (and (sub value (add pc 1)) #xff) 8)
- (srl (and (sub value (add pc 1)) #xffff) 8)))
- ((value pc) (add SI (or (srl (and value #xffff) 8)
- (sra (sll (and value #xff) 24) 16)) (add pc 1)))
+ (srl (and (sub value (add pc 1)) #xff00) 8)))
+ ((value pc) (add SI (sub (xor (or (srl (and value #xff00) 8)
+ (sll (and value #xff) 8))
+ #x8000)
+ #x8000)
+ (add pc 1)))
)
(df f-lab-8-24 "24 bit absolute" (all-isas ABS-ADDR) 8 24 UINT
((value pc) (or SI
diff --git a/opcodes/arc-dis.c b/opcodes/arc-dis.c
index a038fa0..a47e81f 100644
--- a/opcodes/arc-dis.c
+++ b/opcodes/arc-dis.c
@@ -137,8 +137,7 @@ static bfd_boolean print_hex = FALSE;
(info->endian == BFD_ENDIAN_LITTLE ? bfd_getm32 (bfd_getl32 (buf)) \
: bfd_getb32 (buf))
-#define BITS(word,s,e) (((word) << (sizeof (word) * 8 - 1 - e)) >> \
- (s + (sizeof (word) * 8 - 1 - e)))
+#define BITS(word,s,e) (((word) >> (s)) & ((1ull << ((e) - (s)) << 1) - 1))
#define OPCODE_32BIT_INSN(word) (BITS ((word), 27, 31))
/* Functions implementation. */
diff --git a/opcodes/epiphany-ibld.c b/opcodes/epiphany-ibld.c
index 6e6fd7b..aa567d8 100644
--- a/opcodes/epiphany-ibld.c
+++ b/opcodes/epiphany-ibld.c
@@ -1092,7 +1092,7 @@ epiphany_cgen_extract_operand (CGEN_CPU_DESC cd,
length = extract_normal (cd, ex_info, insn_value, 0, 0, 23, 8, 32, total_length, pc, & fields->f_disp8);
if (length <= 0) break;
{
- FLD (f_sdisp11) = ((SI) (((((((FLD (f_disp8)) << (3))) | (FLD (f_disp3)))) << (21))) >> (21));
+ FLD (f_sdisp11) = ((((((((((FLD (f_disp8)) << (3))) | (FLD (f_disp3)))) & (2047))) ^ (1024))) - (1024));
}
}
break;
diff --git a/opcodes/lm32-ibld.c b/opcodes/lm32-ibld.c
index 4bc63fb..a79398d 100644
--- a/opcodes/lm32-ibld.c
+++ b/opcodes/lm32-ibld.c
@@ -680,7 +680,7 @@ lm32_cgen_extract_operand (CGEN_CPU_DESC cd,
{
long value;
length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 15, 16, 32, total_length, pc, & value);
- value = ((pc) + (((SI) (((value) << (16))) >> (14))));
+ value = ((pc) + (((((((((value) & (65535))) << (2))) ^ (131072))) - (131072))));
fields->f_branch = value;
}
break;
@@ -688,7 +688,7 @@ lm32_cgen_extract_operand (CGEN_CPU_DESC cd,
{
long value;
length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 25, 26, 32, total_length, pc, & value);
- value = ((pc) + (((SI) (((value) << (6))) >> (4))));
+ value = ((pc) + (((((((((value) & (67108863))) << (2))) ^ (134217728))) - (134217728))));
fields->f_call = value;
}
break;
diff --git a/opcodes/m32c-ibld.c b/opcodes/m32c-ibld.c
index 29c9411..8473e17 100644
--- a/opcodes/m32c-ibld.c
+++ b/opcodes/m32c-ibld.c
@@ -1489,7 +1489,7 @@ m32c_cgen_insert_operand (CGEN_CPU_DESC cd,
case M32C_OPERAND_LAB_8_16 :
{
long value = fields->f_lab_8_16;
- value = ((((((((value) - (((pc) + (1))))) & (255))) << (8))) | (((USI) (((((value) - (((pc) + (1))))) & (65535))) >> (8))));
+ value = ((((((((value) - (((pc) + (1))))) & (255))) << (8))) | (((USI) (((((value) - (((pc) + (1))))) & (65280))) >> (8))));
errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGN_OPT)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 16, 32, total_length, buffer);
}
break;
@@ -2654,7 +2654,7 @@ m32c_cgen_extract_operand (CGEN_CPU_DESC cd,
{
long value;
length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGN_OPT)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 8, 16, 32, total_length, pc, & value);
- value = ((((((USI) (((value) & (65535))) >> (8))) | (((SI) (((((value) & (255))) << (24))) >> (16))))) + (((pc) + (1))));
+ value = ((((((((((USI) (((value) & (65280))) >> (8))) | (((((value) & (255))) << (8))))) ^ (32768))) - (32768))) + (((pc) + (1))));
fields->f_lab_8_16 = value;
}
break;
diff --git a/opcodes/nios2-dis.c b/opcodes/nios2-dis.c
index adf0091..731860c 100644
--- a/opcodes/nios2-dis.c
+++ b/opcodes/nios2-dis.c
@@ -554,10 +554,10 @@ nios2_print_insn_arg (const char *argptr,
switch (op->format)
{
case iw_i_type:
- s = (int32_t) (GET_IW_I_IMM16 (opcode) << 16) >> 16;
+ s = ((GET_IW_I_IMM16 (opcode) & 0xffff) ^ 0x8000) - 0x8000;
break;
case iw_F2I16_type:
- s = (int32_t) (GET_IW_F2I16_IMM16 (opcode) << 16) >> 16;
+ s = ((GET_IW_F2I16_IMM16 (opcode) & 0xffff) ^ 0x8000) - 0x8000;
break;
default:
bad_opcode (op);
@@ -570,10 +570,10 @@ nios2_print_insn_arg (const char *argptr,
switch (op->format)
{
case iw_F2X4I12_type:
- s = (int32_t) (GET_IW_F2X4I12_IMM12 (opcode) << 20) >> 20;
+ s = ((GET_IW_F2X4I12_IMM12 (opcode) & 0xfff) ^ 0x800) - 0x800;
break;
case iw_F1X4I12_type:
- s = (int32_t) (GET_IW_F1X4I12_IMM12 (opcode) << 20) >> 20;
+ s = ((GET_IW_F1X4I12_IMM12 (opcode) & 0xfff) ^ 0x800) - 0x800;
break;
default:
bad_opcode (op);
@@ -673,10 +673,10 @@ nios2_print_insn_arg (const char *argptr,
switch (op->format)
{
case iw_i_type:
- o = (int32_t) (GET_IW_I_IMM16 (opcode) << 16) >> 16;
+ o = ((GET_IW_I_IMM16 (opcode) & 0xffff) ^ 0x8000) - 0x8000;
break;
case iw_F2I16_type:
- o = (int32_t) (GET_IW_F2I16_IMM16 (opcode) << 16) >> 16;
+ o = ((GET_IW_F2I16_IMM16 (opcode) & 0xffff) ^ 0x8000) - 0x8000;
break;
default:
bad_opcode (op);
@@ -690,7 +690,7 @@ nios2_print_insn_arg (const char *argptr,
switch (op->format)
{
case iw_I10_type:
- o = (int32_t) (GET_IW_I10_IMM10 (opcode) << 22) >> 21;
+ o = (((GET_IW_I10_IMM10 (opcode) & 0x3ff) ^ 0x400) - 0x400) << 1;
break;
default:
bad_opcode (op);
@@ -704,7 +704,7 @@ nios2_print_insn_arg (const char *argptr,
switch (op->format)
{
case iw_T1I7_type:
- o = (int32_t) (GET_IW_T1I7_IMM7 (opcode) << 25) >> 24;
+ o = (((GET_IW_T1I7_IMM7 (opcode) & 0x7f) ^ 0x40) - 0x40) << 1;
break;
default:
bad_opcode (op);
diff --git a/opcodes/pdp11-dis.c b/opcodes/pdp11-dis.c
index e9708e6..a19fbc0 100644
--- a/opcodes/pdp11-dis.c
+++ b/opcodes/pdp11-dis.c
@@ -31,8 +31,7 @@
#define F info->stream
/* Sign-extend a 16-bit number in an int. */
-#define SIGN_BITS (8 * sizeof (int) - 16)
-#define sign_extend(x) (((x) << SIGN_BITS) >> SIGN_BITS)
+#define sign_extend(x) ((((x) & 0xffff) ^ 0x8000) - 0x8000)
static int
read_word (bfd_vma memaddr, int *word, disassemble_info *info)
diff --git a/opcodes/tic54x-dis.c b/opcodes/tic54x-dis.c
index c4ecdda..d8b80a3 100644
--- a/opcodes/tic54x-dis.c
+++ b/opcodes/tic54x-dis.c
@@ -394,8 +394,7 @@ print_instruction (disassemble_info *info,
break;
}
case OP_k5:
- sprintf (operand[i], "#%d",
- (int) (((signed char) opcode & 0x1F) << 3) >> 3);
+ sprintf (operand[i], "#%d", ((opcode & 0x1F) ^ 0x10) - 0x10);
info->fprintf_func (info->stream, "%s%s", comma, operand[i]);
break;
case OP_k8u:
diff --git a/opcodes/tilegx-opc.c b/opcodes/tilegx-opc.c
index 49819e8..cc9ce86 100644
--- a/opcodes/tilegx-opc.c
+++ b/opcodes/tilegx-opc.c
@@ -8102,8 +8102,8 @@ parse_insn_tilegx (tilegx_bundle_bits bits,
if (op->is_signed)
{
/* Sign-extend the operand. */
- int shift = (int)((sizeof(int) * 8) - op->num_bits);
- raw_opval = (raw_opval << shift) >> shift;
+ unsigned int sign = 1u << (op->num_bits - 1);
+ raw_opval = ((raw_opval & (sign + sign - 1)) ^ sign) - sign;
}
/* Adjust PC-relative scaled branch offsets. */
diff --git a/opcodes/tilepro-opc.c b/opcodes/tilepro-opc.c
index ea15822..c71da3d 100644
--- a/opcodes/tilepro-opc.c
+++ b/opcodes/tilepro-opc.c
@@ -10220,8 +10220,8 @@ parse_insn_tilepro (tilepro_bundle_bits bits,
if (op->is_signed)
{
/* Sign-extend the operand. */
- int shift = (int)((sizeof(int) * 8) - op->num_bits);
- opval = (opval << shift) >> shift;
+ unsigned int sign = 1u << (op->num_bits - 1);
+ opval = ((opval & (sign + sign - 1)) ^ sign) - sign;
}
/* Adjust PC-relative scaled branch offsets. */
diff --git a/opcodes/visium-dis.c b/opcodes/visium-dis.c
index c71f8cf..41943ad 100644
--- a/opcodes/visium-dis.c
+++ b/opcodes/visium-dis.c
@@ -94,7 +94,7 @@ disassem_class0 (disassemble_info *info, unsigned int ins)
/* BRR instruction. */
{
unsigned cbf = (ins >> 27) & 0x000f;
- int displacement = ((int) (ins << 16)) >> 16;
+ int displacement = ((ins & 0xffff) ^ 0x8000) - 0x8000;
if (ins == 0)
(*info->fprintf_func) (info->stream, "nop");
--
1.8.3.1