bug and patch for bfd (v850 version) MOVHI/MOVLO management
Gianluca Moro
glctr@abc.it
Thu Nov 19 09:56:00 GMT 1998
BUG REPORT:
binutils-2.9.1
cross compiled on Linux for NEC-V850
Management of addressing mode R_V850_HI16_S/R_V850_LO16
FOR "egcs-bugs@cygnus.com": I'm sending a patch to the bug report
included at the end of the mail: I sent it to you the
original bug report, thinking it was a gcc bug,
but it appears to be a binutils bug.
This Report is cc "bug-gnu-utils@gnu.org" and "egcs-bugs@cygnus.com"
Regards
Caterina Masiero
Gianluca Moro
SHORT BUG DESCRIPTION:
The bug occurs with the following instruction sequence:
a couple of instruction using address mode
R_V850_HI16_S
R_V850_LO16
with no overflow in bit 15 of lower 16 bit address
3 instruction using address mode
R_V850_HI16_S
R_V850_LO16
R_V850_LO16
with overflow in bit 15 of lower 16 bit address
VERBOSE BUG DESCRIPTION:
We have the following output code:
...
105350: 40 56 13 00 movhi 19, r0, r10
105354: 2a e6 48 7f movea 32584, r10, r28
...
1053da: 40 56 13 00 movhi 19, r0, r10
1053de: 6a 07 28 81 st.h r0, -32472[r10]
1053e2: 2a 5e 28 81 movea -32472, r10, r11
...
where the correct line 105350 should be:
105350: 40 56 12 00 movhi 18, r0, r10
as the correct value to store in r28 is 0x127f48.
The sequence of the operations which generate the wrong code is:
1 - the address in instructions 105350-105354 is correctly computed.
in the table in file binutils-2.9.1/bfd/elf32-v850.c
static hi16s_location previous_hi16s[ 10 ]; /* XXX is this enough ? */
there's an entry corresponding to that address.
2 - the instruction 1053da generates another entry corresponding to
its own address.
3 - the instruction 1053de, having bit 15 setted, finds and deletes
this entry
4 - the instruction 1053e2, having bit 15 setted, looks for the entry
in the table, but it finds the entry relating to address of
instruction 105350.
As it has bit 15 setted, it increments the high part of
the address from 0x12 to the resulting 0x13.
APPLIED PATCHES:
*** binutils-2.9.1/bfd/elf32-v850.c.ori Thu Nov 19 12:29:39 1998
--- binutils-2.9.1/bfd/elf32-v850.c Thu Nov 19 14:30:19 1998
*************** v850_elf_check_relocs (abfd, info, sec,
*** 527,537 ****
--- 527,556 ----
return ret;
}
+ /*
+ * In the old version, when an entry was checked out from the table,
+ * it was deleted.
+ * This produced an error if the entry was needed more than once,
+ * as the second attempted retry failed.
+ *
+ * In the current version, the entry is not deleted, but we register
+ * in the flag "found" if the entry has already been looked up.
+ * This is needed if we have to look up more than once an address
+ * that generate an overflow in bit 15 of lower address: we
+ * must update the higher 16 bit of the address just the first time.
+ *
+ * TODO - TOFIX: is it possible that we need to restore 2 different
+ * addresses from the same table entry, whose the first
+ * generate an overflow, while the second do not?
+ * (If so, this code fails!)
+ */
+
typedef struct
{
long addend;
bfd_byte * address;
unsigned long counter;
+ boolean found;
}
hi16s_location;
*************** remember_hi16s_reloc (addend, address)
*** 566,571 ****
--- 585,591 ----
oldest->addend = addend;
oldest->address = address;
oldest->counter = hi16s_counter ++;
+ oldest->found = false;
/* Cope with wrap around of our counter. */
if (hi16s_counter == 0)
*************** remember_hi16s_reloc (addend, address)
*** 585,592 ****
}
static bfd_byte *
! find_remembered_hi16s_reloc (addend)
long addend;
{
hi16s_location * match = NULL;
int i;
--- 605,613 ----
}
static bfd_byte *
! find_remembered_hi16s_reloc (addend, already_found)
long addend;
+ boolean * already_found;
{
hi16s_location * match = NULL;
int i;
*************** find_remembered_hi16s_reloc (addend)
*** 607,618 ****
{
bfd_byte * addr;
/* Empty the table entry. */
match->addend = 0;
-
- addr = match->address;
match->address = NULL;
!
return addr;
}
--- 628,642 ----
{
bfd_byte * addr;
+ addr = match->address;
+ #if 0
/* Empty the table entry. */
match->addend = 0;
match->address = NULL;
! #else
! *already_found = match->found;
! match->found = true;
! #endif
return addr;
}
*************** v850_elf_store_addend_in_insn (abfd, r_t
*** 843,856 ****
|| (OVERFLOWS (addend, insn)
&& ((! BIT15_SET (insn)) || (BIT15_SET (addend)))))
{
! bfd_byte * hi16s_address = find_remembered_hi16s_reloc (addend);
/* Amend the matching HI16_S relocation. */
if (hi16s_address != NULL)
{
! insn = bfd_get_16 (abfd, hi16s_address);
! insn += 1;
! bfd_put_16 (abfd, insn, hi16s_address);
}
else
{
--- 867,884 ----
|| (OVERFLOWS (addend, insn)
&& ((! BIT15_SET (insn)) || (BIT15_SET (addend)))))
{
! boolean already_updated;
! bfd_byte * hi16s_address = find_remembered_hi16s_reloc (addend,
&already_updated);
/* Amend the matching HI16_S relocation. */
if (hi16s_address != NULL)
{
! if (!already_updated)
! {
! insn = bfd_get_16 (abfd, hi16s_address);
! insn += 1;
! bfd_put_16 (abfd, insn, hi16s_address);
! }
}
else
{
FOR "egcs-bugs@cygnus.com":
>
>
> BUG REPORT:
> egcs-1.0
> output by v850-gcc --version: egcs-2.90.21 971202 (egcs-1.00 release)
> cross compiler for NEC-V850
> Management of address by MOVHI-MOVEA
>
>
> I have the following situation, generated by a C code "aus = &acq_info[0]",
> where aus is a pointer to s atructure, and acq_info is a vector of structures:
>
> ...
> (gdb) disass my_function
> Dump of assembler code for function my_function:
> ...
> 0x105350 <my_function+20>: movhi 19, r0, r10
> 0x105354 <my_function+24>: movea 32584, r10, r28
> ...
> (gdb) p aus ;; here the code has just been executed
> $25 = (ACQ_INFO *) 0x137f48
> (gdb) p &acq_info
> $26 = (ACQ_INFO (*)[20]) 0x127f48
> ...
>
> The high part of the address is incremented by 1
> with respect of its true value.
> It seems to me that it's a problem related to the
> MOVEA sign-extension management.
> probably it's an error in the carry management while
> separating the 32 bit address in low and high part.
>
> The compilation command line is
>
> v850-gcc -O2 -Wall -pipe -msda=16 -g -mnested-interrupts
> -mcheck-stack -I. -I/home/giammy/biomedin/include
> -I/home/giammy/biomedin/include/v850 -c
> -o admanage-lib.o admanage-lib.c
>
> I have the same error if I do not use the option -O2
>
> Regards
> Gianluca Moro
>
>
--
+-----------------------------------------------------+
| Biomedin s.r.l Phone +39-049-8751644 |
| P.za Insurrezione, 1 Fax +39-049-8754240 |
| I-35137 Padova, ITALY e-mail glctr@abc.it |
+-----------------------------------------------------+
More information about the Gcc-bugs
mailing list