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