AVR: target/116407 - Fix linker error "relocation truncated to fit".
Some text peepholes output extra instructions prior to a branch instruction and that increase the jump offset of backward branches. PR target/116407 gcc/ * config/avr/avr-protos.h (avr_jump_mode): Add an int argument. * config/avr/avr.cc (avr_jump_mode): Add an int argument to increase the computed jump offset of backwards branches. * config/avr/avr.md (*dec-and-branchhi!=-1, *dec-and-branchsi!=-1): Increase the jump offset used by avr_jump_mode() as needed. gcc/testsuite/ * gcc.target/avr/torture/pr116407-2.c: New test. * gcc.target/avr/torture/pr116407-4.c: New test.
This commit is contained in:
parent
3ae8794665
commit
dfb2e8caa8
5 changed files with 80 additions and 9 deletions
|
@ -115,7 +115,7 @@ extern const char* avr_out_reload_inpsi (rtx*, rtx, int*);
|
|||
extern const char* avr_out_lpm (rtx_insn *, rtx*, int*);
|
||||
extern void avr_notice_update_cc (rtx body, rtx_insn *insn);
|
||||
extern int reg_unused_after (rtx_insn *insn, rtx reg);
|
||||
extern int avr_jump_mode (rtx x, rtx_insn *insn);
|
||||
extern int avr_jump_mode (rtx x, rtx_insn *insn, int = 0);
|
||||
extern int test_hard_reg_class (enum reg_class rclass, rtx x);
|
||||
extern int jump_over_one_insn_p (rtx_insn *insn, rtx dest);
|
||||
|
||||
|
|
|
@ -4133,19 +4133,22 @@ avr_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size,
|
|||
/* Choose mode for jump insn:
|
||||
1 - relative jump in range -63 <= x <= 62 ;
|
||||
2 - relative jump in range -2046 <= x <= 2045 ;
|
||||
3 - absolute jump (only for ATmega[16]03). */
|
||||
3 - absolute jump (only when we have JMP / CALL).
|
||||
|
||||
When jumping backwards, assume the jump offset is EXTRA words
|
||||
bigger than inferred from insn addresses. */
|
||||
|
||||
int
|
||||
avr_jump_mode (rtx x, rtx_insn *insn)
|
||||
avr_jump_mode (rtx x, rtx_insn *insn, int extra)
|
||||
{
|
||||
int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
|
||||
? XEXP (x, 0) : x));
|
||||
int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
|
||||
int jump_distance = cur_addr - dest_addr;
|
||||
|
||||
if (IN_RANGE (jump_distance, -63, 62))
|
||||
if (IN_RANGE (jump_distance, -63, 62 - extra))
|
||||
return 1;
|
||||
else if (IN_RANGE (jump_distance, -2046, 2045))
|
||||
else if (IN_RANGE (jump_distance, -2046, 2045 - extra))
|
||||
return 2;
|
||||
else if (AVR_HAVE_JMP_CALL)
|
||||
return 3;
|
||||
|
|
|
@ -7605,7 +7605,7 @@
|
|||
"sbc %C0,__zero_reg__" CR_TAB
|
||||
"sbc %D0,__zero_reg__", operands);
|
||||
|
||||
int jump_mode = avr_jump_mode (operands[2], insn);
|
||||
int jump_mode = avr_jump_mode (operands[2], insn, 3 - avr_adiw_reg_p (operands[0]));
|
||||
const char *op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs";
|
||||
operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
|
||||
|
||||
|
@ -7642,7 +7642,7 @@
|
|||
output_asm_insn ("subi %A0,1" CR_TAB
|
||||
"sbc %B0,__zero_reg__", operands);
|
||||
|
||||
int jump_mode = avr_jump_mode (operands[2], insn);
|
||||
int jump_mode = avr_jump_mode (operands[2], insn, 1 - avr_adiw_reg_p (operands[0]));
|
||||
const char *op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs";
|
||||
operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
|
||||
|
||||
|
@ -7681,7 +7681,7 @@
|
|||
output_asm_insn ("subi %A0,1" CR_TAB
|
||||
"sbc %B0,__zero_reg__", operands);
|
||||
|
||||
int jump_mode = avr_jump_mode (operands[2], insn);
|
||||
int jump_mode = avr_jump_mode (operands[2], insn, 1 - avr_adiw_reg_p (operands[0]));
|
||||
const char *op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs";
|
||||
operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
|
||||
|
||||
|
@ -7718,7 +7718,7 @@
|
|||
"sub %A0,%3" CR_TAB
|
||||
"sbc %B0,__zero_reg__", operands);
|
||||
|
||||
int jump_mode = avr_jump_mode (operands[2], insn);
|
||||
int jump_mode = avr_jump_mode (operands[2], insn, 1 - avr_adiw_reg_p (operands[0]));
|
||||
const char *op = ((EQ == <CODE>) ^ (jump_mode == 1)) ? "brcc" : "brcs";
|
||||
operands[1] = gen_rtx_CONST_STRING (VOIDmode, op);
|
||||
|
||||
|
|
34
gcc/testsuite/gcc.target/avr/torture/pr116407-2.c
Normal file
34
gcc/testsuite/gcc.target/avr/torture/pr116407-2.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* { dg-do link } */
|
||||
|
||||
typedef __UINT16_TYPE__ u16;
|
||||
typedef __INT16_TYPE__ T;
|
||||
|
||||
#ifdef __OPTIMIZE__
|
||||
|
||||
static __inline__ __attribute__((always_inline))
|
||||
void delay (T x, u16 nops)
|
||||
{
|
||||
do
|
||||
__builtin_avr_nops (nops);
|
||||
while (--x != -1);
|
||||
}
|
||||
|
||||
#ifdef __AVR_HAVE_JMP_CALL__
|
||||
|
||||
void delay_2043 (T x) { delay (x, 2043); }
|
||||
void delay_2044 (T x) { delay (x, 2044); }
|
||||
void delay_2045 (T x) { delay (x, 2045); }
|
||||
void delay_2046 (T x) { delay (x, 2046); }
|
||||
|
||||
#endif /* have JUMP, CALL */
|
||||
|
||||
void delay_61 (T x) { delay (x, 61); }
|
||||
void delay_62 (T x) { delay (x, 62); }
|
||||
void delay_63 (T x) { delay (x, 63); }
|
||||
|
||||
#endif /* optimize */
|
||||
|
||||
int main (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
34
gcc/testsuite/gcc.target/avr/torture/pr116407-4.c
Normal file
34
gcc/testsuite/gcc.target/avr/torture/pr116407-4.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/* { dg-do link } */
|
||||
|
||||
typedef __UINT16_TYPE__ u16;
|
||||
typedef __INT32_TYPE__ T;
|
||||
|
||||
#ifdef __OPTIMIZE__
|
||||
|
||||
static __inline__ __attribute__((always_inline))
|
||||
void delay (T x, u16 nops)
|
||||
{
|
||||
do
|
||||
__builtin_avr_nops (nops);
|
||||
while (--x != -1);
|
||||
}
|
||||
|
||||
#ifdef __AVR_HAVE_JMP_CALL__
|
||||
|
||||
void delay_2043 (T x) { delay (x, 2043); }
|
||||
void delay_2044 (T x) { delay (x, 2044); }
|
||||
void delay_2045 (T x) { delay (x, 2045); }
|
||||
void delay_2046 (T x) { delay (x, 2046); }
|
||||
|
||||
#endif /* have JUMP, CALL */
|
||||
|
||||
void delay_61 (T x) { delay (x, 61); }
|
||||
void delay_62 (T x) { delay (x, 62); }
|
||||
void delay_63 (T x) { delay (x, 63); }
|
||||
|
||||
#endif /* optimize */
|
||||
|
||||
int main (void)
|
||||
{
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue