diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 0d7eda4f70..7d22cc03d3 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2019-05-21 Senthil Kumar Selvaraj + + PR ld/24571 + * bfd/elf32-avr.c (elf32_avr_relax_section): Adjust range check + when computing distance_short_enough. + 2019-05-21 Senthil Kumar Selvaraj PR ld/24564 diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c index f8a843e16c..34ad42300d 100644 --- a/bfd/elf32-avr.c +++ b/bfd/elf32-avr.c @@ -2643,16 +2643,28 @@ elf32_avr_relax_section (bfd *abfd, /* Compute the distance from this insn to the branch target. */ gap = value - dot; + /* The ISA manual states that addressable range is PC - 2k + 1 to + PC + 2k. In bytes, that would be -4094 <= PC <= 4096. The range + is shifted one word to the right, because pc-relative instructions + implicitly add one word i.e. rjmp 0 jumps to next insn, not the + current one. + Therefore, for the !shrinkable case, the range is as above. + If shrinkable, then the current code only deletes bytes 3 and + 4 of the absolute call/jmp, so the forward jump range increases + by 2 bytes, but the backward (negative) jump range remains + the same. */ + + /* Check if the gap falls in the range that can be accommodated in 13bits signed (It is 12bits when encoded, as we deal with word addressing). */ - if (!shrinkable && ((int) gap >= -4096 && (int) gap <= 4095)) + if (!shrinkable && ((int) gap >= -4094 && (int) gap <= 4096)) distance_short_enough = 1; /* If shrinkable, then we can check for a range of distance which - is two bytes farther on both the directions because the call + is two bytes farther on the positive direction because the call or jump target will be closer by two bytes after the relaxation. */ - else if (shrinkable && ((int) gap >= -4094 && (int) gap <= 4097)) + else if (shrinkable && ((int) gap >= -4094 && (int) gap <= 4098)) distance_short_enough = 1; /* Here we handle the wrap-around case. E.g. for a 16k device diff --git a/ld/ChangeLog b/ld/ChangeLog index 20be135c6e..e038e40033 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,9 @@ +2019-05-21 Senthil Kumar Selvaraj + + PR ld/24571 + * ld/testsuite/ld-avr/relax-insn-at-range-boundary.d: New test. + * ld/testsuite/ld-avr/relax-insn-at-range-boundary.s: New test. + 2019-05-21 Senthil Kumar Selvaraj PR ld/24564 diff --git a/ld/testsuite/ld-avr/relax-insn-at-range-boundary.d b/ld/testsuite/ld-avr/relax-insn-at-range-boundary.d new file mode 100644 index 0000000000..6183896f7c --- /dev/null +++ b/ld/testsuite/ld-avr/relax-insn-at-range-boundary.d @@ -0,0 +1,17 @@ +#name: AVR relaxation, jump to symbol at ends of pc-relative range boundary +#as: -mlink-relax -mavr51 +#ld: --relax -mavr51 +#source: relax-insn-at-range-boundary.s +#objdump: -d +#target: avr-*-* + +#... +00000000.* + ... + ffc: 00 00 nop + ffe: 00 c8 rjmp .-4096 ; 0x0 .* + 1000: ff c7 rjmp .+4094 ; 0x2000 + ... + +00002000 : +#... diff --git a/ld/testsuite/ld-avr/relax-insn-at-range-boundary.s b/ld/testsuite/ld-avr/relax-insn-at-range-boundary.s new file mode 100644 index 0000000000..4d710df36d --- /dev/null +++ b/ld/testsuite/ld-avr/relax-insn-at-range-boundary.s @@ -0,0 +1,11 @@ +.section ".text", "ax",@progbits +.global main +main: +backward_target: ; Exactly -4094 bytes from jmp + .ds.b 4094, 0 + jmp backward_target + jmp forward_target + .ds.b 4094, 0 +forward_target: ; Exactly 4098 bytes before relax, 4096 bytes after relax + nop +