This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
2.10.91: The target of MIPS jump instructions is handled wrong
- To: binutils at sourceware dot cygnus dot com
- Subject: 2.10.91: The target of MIPS jump instructions is handled wrong
- From: "Maciej W. Rozycki" <macro at ds2 dot pg dot gda dot pl>
- Date: Fri, 19 Jan 2001 22:06:19 +0100 (MET)
- cc: Ralf Baechle <ralf at uni-koblenz dot de>, Ulf Carlsson <ulfc at engr dot sgi dot com>
- Organization: Technical University of Gdansk
Hi,
Another patch that did not went in... From the original mail:
I've noticed we handle MIPS jump instructions wrong. These instructions
make 28 least significant bits of the PC change while 4 most significant
bits remain intact. But we incorrectly assume these four bits are those
of the jump instruction, while they are really the ones of the instruction
in the delay slot, i.e. the following one.
Here is a patch that fixes all places I could find including comments.
bfd/ChangeLog:
2001-01-18 Maciej W. Rozycki <macro@ds2.pg.gda.pl>
* elf32-mips.c (elf_mips_howto_table): Fix the comment on
the R_MIPS_26 relocation.
(mips_elf_calculate_relocation): Use (p + 4) instead of p for
the R_MIPS_26 relocation.
(mips_elf_perform_relocation): Fix the comment on the R_MIPS16_26
relocation.
* elf64-mips.c (mips_elf64_howto_table_rel): Fix the comment on
the R_MIPS_26 relocation.
(mips_elf64_howto_table_rela): Likewise.
opcodes/ChangeLog:
2001-01-18 Maciej W. Rozycki <macro@ds2.pg.gda.pl>
* mips-dis.c (print_insn_arg): Use top four bits of the address of
the following instruction not of the jump itself for the jump
target.
(print_mips16_insn_arg): Likewise.
Maciej
--
+ Maciej W. Rozycki, Technical University of Gdansk, Poland +
+--------------------------------------------------------------+
+ e-mail: macro@ds2.pg.gda.pl, PGP key available +
binutils-2.10.91-20010116-mips-j.patch
diff -up --recursive --new-file binutils.macro/bfd/elf32-mips.c binutils/bfd/elf32-mips.c
--- binutils.macro/bfd/elf32-mips.c Wed Dec 13 04:26:02 2000
+++ binutils/bfd/elf32-mips.c Thu Jan 18 22:33:35 2001
@@ -531,7 +531,7 @@ static reloc_howto_type elf_mips_howto_t
complain_overflow_dont, /* complain_on_overflow */
/* This needs complex overflow
detection, because the upper four
- bits must match the PC. */
+ bits must match the PC + 4. */
bfd_elf_generic_reloc, /* special_function */
"R_MIPS_26", /* name */
true, /* partial_inplace */
@@ -6320,14 +6320,14 @@ mips_elf_calculate_relocation (abfd,
break;
case R_MIPS16_26:
- /* The calculation for R_MIPS_26 is just the same as for an
+ /* The calculation for R_MIPS16_26 is just the same as for an
R_MIPS_26. It's only the storage of the relocated field into
the output file that's different. That's handled in
mips_elf_perform_relocation. So, we just fall through to the
R_MIPS_26 case here. */
case R_MIPS_26:
if (local_p)
- value = (((addend << 2) | (p & 0xf0000000)) + symbol) >> 2;
+ value = (((addend << 2) | ((p + 4) & 0xf0000000)) + symbol) >> 2;
else
value = (mips_elf_sign_extend (addend << 2, 28) + symbol) >> 2;
value &= howto->dst_mask;
@@ -6620,9 +6620,9 @@ mips_elf_perform_relocation (info, howto
((sub1 << 16) | sub2)).
When producing a relocateable object file, the calculation is
- (((A < 2) | (P & 0xf0000000) + S) >> 2)
+ (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
When producing a fully linked file, the calculation is
- let R = (((A < 2) | (P & 0xf0000000) + S) >> 2)
+ let R = (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2)
((R & 0x1f0000) << 5) | ((R & 0x3e00000) >> 5) | (R & 0xffff) */
if (!info->relocateable)
diff -up --recursive --new-file binutils.macro/bfd/elf64-mips.c binutils/bfd/elf64-mips.c
--- binutils.macro/bfd/elf64-mips.c Sat Dec 9 04:26:17 2000
+++ binutils/bfd/elf64-mips.c Thu Jan 18 22:33:35 2001
@@ -161,7 +161,7 @@ static reloc_howto_type mips_elf64_howto
complain_overflow_dont, /* complain_on_overflow */
/* This needs complex overflow
detection, because the upper four
- bits must match the PC. */
+ bits must match the PC + 4. */
bfd_elf_generic_reloc, /* special_function */
"R_MIPS_26", /* name */
true, /* partial_inplace */
@@ -714,7 +714,7 @@ static reloc_howto_type mips_elf64_howto
complain_overflow_dont, /* complain_on_overflow */
/* This needs complex overflow
detection, because the upper four
- bits must match the PC. */
+ bits must match the PC + 4. */
bfd_elf_generic_reloc, /* special_function */
"R_MIPS_26", /* name */
true, /* partial_inplace */
diff -up --recursive --new-file binutils.macro/opcodes/mips-dis.c binutils/opcodes/mips-dis.c
--- binutils.macro/opcodes/mips-dis.c Sat Dec 2 04:25:52 2000
+++ binutils/opcodes/mips-dis.c Thu Jan 18 22:34:34 2001
@@ -137,7 +137,7 @@ print_insn_arg (d, l, pc, info)
case 'a':
(*info->print_address_func)
- (((pc & ~ (bfd_vma) 0x0fffffff)
+ ((((pc + 4) & ~ (bfd_vma) 0x0fffffff)
| (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)),
info);
break;
@@ -1038,9 +1038,9 @@ print_mips16_insn_arg (type, op, l, use_
if (! use_extend)
extend = 0;
l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
- (*info->print_address_func) ((memaddr & 0xf0000000) | l, info);
+ (*info->print_address_func) (((memaddr + 4) & 0xf0000000) | l, info);
info->insn_type = dis_jsr;
- info->target = (memaddr & 0xf0000000) | l;
+ info->target = ((memaddr + 4) & 0xf0000000) | l;
info->branch_delay_insns = 1;
break;