This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] h8300-{hms,elf}-ld: Fix a bug in relaxation.


Hi,

Attached is a patch to fix a bug in the relaxation code.

_foo:
        mov.w   r0,r0
        beq     .L1
        jsr     @_bar
.L1:
        rts
_bar:
        rts

Without the patch, the above code gets relaxed to

00000100 <_start>:
 100:   0c ee             mov.b r6l,r6l
 102:   46 02             bne   .+2 (106)

00000104 <.L1>:
 104:   54 70             rts

00000106 <_bar>:
 106:   54 70             rts

We have to call _bar, not jump to _bar, so the relaxation went wrong.
With the patch, I get

00000100 <_start>:
 100:   0c ee             mov.b r6l,r6l
 102:   47 02             beq   .+2 (106)
 104:   55 02             bsr   .+2 (108)

00000106 <.L1>:
 106:   54 70             rts

00000108 <_bar>:
 108:   54 70             rts

This is OK because jsr (long call) simply became bsr (short call).

The patch fixes the problem by telling the relaxation code not to not
to optimize away jsr after a short jump.

Both h8300-hms-ld and h8300-elf-ld have the above problem.  OK to
apply?

Kazu Hirata

2002-11-11  Kazu Hirata  <kazu@cs.umass.edu>

	* coff-h8300.c (h8300_reloc16_estimate): Do not optimize away
	jsr after a short jump.
	* elf32-h8300.c (elf32_h8_relax_section): Likewise.

Index: coff-h8300.c
===================================================================
RCS file: /cvs/src/src/bfd/coff-h8300.c,v
retrieving revision 1.13
diff -c -r1.13 coff-h8300.c
*** coff-h8300.c	11 Nov 2002 05:05:22 -0000	1.13
--- coff-h8300.c	11 Nov 2002 05:44:19 -0000
***************
*** 483,488 ****
--- 483,496 ----
  	 closer if we do relax this branch.  */
        if ((int) gap >= -128 && (int) gap <= 128)
  	{
+ 	  bfd_byte code;
+ 
+ 	  if (!bfd_get_section_contents (abfd, input_section,
+ 					 &code, reloc->address,
+ 					 1))
+ 	    break;
+ 	  code = bfd_get_8 (code);
+ 
  	  /* It's possible we may be able to eliminate this branch entirely;
  	     if the previous instruction is a branch around this instruction,
  	     and there's no label at this instruction, then we can reverse
***************
*** 496,502 ****
  	     This saves 4 bytes instead of two, and should be relatively
  	     common.  */
  
! 	  if (gap <= 126
  	      && last_reloc
  	      && last_reloc->howto->type == R_PCRBYTE)
  	    {
--- 504,511 ----
  	     This saves 4 bytes instead of two, and should be relatively
  	     common.  */
  
! 	  if (code = 0x5a
! 	      && gap <= 126
  	      && last_reloc
  	      && last_reloc->howto->type == R_PCRBYTE)
  	    {
***************
*** 504,510 ****
  	      last_value = bfd_coff_reloc16_get_value (last_reloc, link_info,
  						       input_section) + 1;
  
! 	      if (last_value == dot + 2
  		  && last_reloc->address + 1 == reloc->address
  		  && !h8300_symbol_address_p (abfd, input_section, dot - 2))
  		{
--- 513,520 ----
  	      last_value = bfd_coff_reloc16_get_value (last_reloc, link_info,
  						       input_section) + 1;
  
! 	      if (code == 0x5a
! 		  && last_value == dot + 2
  		  && last_reloc->address + 1 == reloc->address
  		  && !h8300_symbol_address_p (abfd, input_section, dot - 2))
  		{
Index: elf32-h8300.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-h8300.c,v
retrieving revision 1.17
diff -c -r1.17 elf32-h8300.c
*** elf32-h8300.c	11 Nov 2002 05:05:22 -0000	1.17
--- elf32-h8300.c	11 Nov 2002 05:44:20 -0000
***************
*** 819,825 ****
  	       two bytes closer if we do relax this branch.  */
  	    if ((int) gap >= -126 && (int) gap <= 130)
  	      {
! 		unsigned char code;
  
  		/* Note that we've changed the relocs, section contents,
  		   etc.  */
--- 819,826 ----
  	       two bytes closer if we do relax this branch.  */
  	    if ((int) gap >= -126 && (int) gap <= 130)
  	      {
! 		unsigned char code =
! 		  bfd_get_8 (abfd, contents + irel->r_offset - 1);
  
  		/* Note that we've changed the relocs, section contents,
  		   etc.  */
***************
*** 834,840 ****
  
  		   Such sequences are used by the compiler to deal with
  		   long conditional branches.  */
! 		if ((int) gap <= 130
  		    && (int) gap >= -128
  		    && last_reloc
  		    && ELF32_R_TYPE (last_reloc->r_info) == R_H8_PCREL8
--- 835,842 ----
  
  		   Such sequences are used by the compiler to deal with
  		   long conditional branches.  */
! 		if (code == 0x5a
! 		    && (int) gap <= 130
  		    && (int) gap >= -128
  		    && last_reloc
  		    && ELF32_R_TYPE (last_reloc->r_info) == R_H8_PCREL8
***************
*** 891,898 ****
  		  }
  
  		/* We could not eliminate this jump, so just shorten it.  */
- 		code = bfd_get_8 (abfd, contents + irel->r_offset - 1);
- 
  		if (code == 0x5e)
  		  bfd_put_8 (abfd, 0x55, contents + irel->r_offset - 1);
  		else if (code == 0x5a)
--- 893,898 ----


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]