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);
/* 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;
"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);
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);
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);
"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);
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+}