diff options
-rw-r--r-- | bfd/ChangeLog | 6 | ||||
-rw-r--r-- | bfd/elf32-avr.c | 18 | ||||
-rw-r--r-- | ld/ChangeLog | 6 | ||||
-rw-r--r-- | ld/testsuite/ld-avr/relax-insn-at-range-boundary.d | 17 | ||||
-rw-r--r-- | ld/testsuite/ld-avr/relax-insn-at-range-boundary.s | 11 |
5 files changed, 55 insertions, 3 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 0d7eda4..7d22cc0 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,11 @@ 2019-05-21 Senthil Kumar Selvaraj <senthilkumar.selvaraj@microchip.com> + 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 <senthilkumar.selvaraj@microchip.com> + PR ld/24564 * bfd/elf32-avr.c (avr_relative_distance_considering_wrap_around): Wrap around even if distance equals avr_pc_wrap_around. diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c index f8a843e..34ad423 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 20be135..e038e40 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,5 +1,11 @@ 2019-05-21 Senthil Kumar Selvaraj <senthilkumar.selvaraj@microchip.com> + 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 <senthilkumar.selvaraj@microchip.com> + PR ld/24564 * testsuite/ld-avr/wraparound-range-boundary.d: New test. * testsuite/ld-avr/wraparound-range-boundary.s: New test. 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 0000000..6183896 --- /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 <forward_target> + ... + +00002000 <forward_target>: +#... 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 0000000..4d710df --- /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 + |