This patch outsources macros from lib1funcs.S to
a new header file asm-defs.h.
It adds a new macro REGNO that maps register names to
the respective register number, so that we can do
arithmetic with them. This is needed to replace
code like
mov_l r28, r26
mov_h r29, r27
with
wmov r28, r26
i.e. it is no more required to use plain register numbers
in wmov and similar macros.
The generated code is almost the same. It differs in
no-op changes, for example when
mov_h r29, r27
mov_l r28, r26
is replaced by
wmov r28, r26
in the case without MOVW, the generated code is now
mov r28, r26
mov r29, r27
i.e. MOVs are swapped.
Ok for trunk?
Johann
--
AVR: Outsource lib1func.S's macros to asm-defs.h.
libgcc/
* config/avr/lib1funcs.S: Fix trailing blanks.
(mov_h): Remove macro and invocations.
(mov_l): Remove macro. Replace invocations with wmov.
(__zero_reg__, __tmp_reg__, __SREG__, __SP_H__)
(__SP_L__, __RAMPZ__, __EIND__, skip, NEG2, NEG4)
(wmov, wsubi, waddi, mov4, XCALL, XJMP, XICALL, XIJMP)
(do_prologue_saves, do_epilogue_restores, .branch_plus)
(DEFUN, ENDF, FALIAS): Move macros to...
* config/avr/asm-defs.h: ...this new file.
* config/avr/lib1funcs-fixed.S: Fix trailing blanks.
diff --git a/libgcc/config/avr/asm-defs.h b/libgcc/config/avr/asm-defs.h
new file mode 100644
index 00000000000..1e0add53021
--- /dev/null
+++ b/libgcc/config/avr/asm-defs.h
@@ -0,0 +1,264 @@
+/* -*- Mode: Asm -*- */
+/* Copyright (C) 1998-2026 Free Software Foundation, Inc.
+ Contributed by Denis Chertykov <[email protected]>
+
+ This file is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 3, or (at your option) any
+ later version.
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Definitions for common SFRs and fixed registers.
+
+#if defined (__AVR_TINY__)
+#define __zero_reg__ r17
+#define __tmp_reg__ r16
+#else
+#define __zero_reg__ r1
+#define __tmp_reg__ r0
+#endif
+
+#if defined (__AVR_HAVE_SPH__)
+#define __SP_H__ 0x3e
+#endif
+
+#define __SP_L__ 0x3d
+#define __RAMPZ__ 0x3B
+#define __EIND__ 0x3C
+#define __SREG__ 0x3f
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Helper macros.
+
+;;; REGNO sets symbol SYM to the register number of REG.
+;;; Valid REGs are: r0..r31, R0..R31 and XL, yh, ZH etc.
+;;; Expressions that evaluate to a number can also be used.
+.macro REGNO sym, reg
+ ..regno.done = 0
+ ..regno = 0
+ .irp name, \
+ r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, \
+ r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
+ r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, \
+ r30, r31, \
+ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, \
+ R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, \
+ R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, \
+ R30, R31
+ .ifc \name,\reg
+ \sym = ..regno % 32
+ ..regno.done = 1
+ .endif
+ ..regno = ..regno + 1
+ .endr
+
+ ..regno = 0
+ .irp name, \
+ xl, xh, yl, yh, zl, zh, \
+ Xl, Xh, Yl, Yh, Zl, Zh, \
+ xL, xH, yL, yH, zL, zH, \
+ XL, XH, YL, YH, ZL, ZH
+ .ifc \name,\reg
+ \sym = 26 + ..regno % 6
+ ..regno.done = 1
+ .endif
+ ..regno = ..regno + 1
+ .endr
+
+ .if ! ..regno.done
+ ;; Assume that \reg is some valid numeric expression.
+ \sym = \reg
+ .endif
+.endm
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Definitions to factor out different ISAs.
+
+#if defined (__AVR_HAVE_JMP_CALL__)
+#define XCALL call
+#define XJMP jmp
+#else
+#define XCALL rcall
+#define XJMP rjmp
+#endif
+
+#if defined (__AVR_HAVE_EIJMP_EICALL__)
+#define XICALL eicall
+#define XIJMP eijmp
+#else
+#define XICALL icall
+#define XIJMP ijmp
+#endif
+
+
+;;; Like MOVW
+#ifdef __AVR_HAVE_MOVW__
+#define wmov movw
+#else
+.macro wmov dst, src
+ REGNO ..wmov.dst, \dst
+ REGNO ..wmov.src, \src
+ mov ..wmov.dst+0, ..wmov.src+0
+ mov ..wmov.dst+1, ..wmov.src+1
+.endm
+#endif /* __AVR_HAVE_MOVW__ */
+
+
+;;; Like SBIW, ADIW
+#ifdef __AVR_HAVE_ADIW__
+#define waddi adiw
+#define wsubi sbiw
+#else
+.macro wsubi reg, arg
+ REGNO ..wsubi.reg, \reg
+ subi ..wsubi.reg+0, lo8 (\arg)
+ sbci ..wsubi.reg+1, hi8 (\arg)
+.endm
+
+.macro waddi reg, arg
+ REGNO ..waddi.reg, \reg
+ subi ..waddi.reg+0, lo8 (-(\arg))
+ sbci ..waddi.reg+1, hi8 (-(\arg))
+.endm
+#endif /* __AVR_HAVE_ADIW__ */
+
+
+;;; [R]JMP to label LABL when REG is positive (REG.7 = 0).
+;;; Otherwise, fallthrough.
+.macro .branch_plus reg, labl
+#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
+ ;; Some cores have a problem skipping 2-word instructions.
+ tst \reg
+ brmi .L.branch_plus.\@
+#else
+ sbrs \reg, 7
+#endif /* skip erratum */
+ XJMP \labl
+.L.branch_plus.\@:
+.endm ; .branch_plus
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Macros for convenience.
+
+;; Skip the next instruction, typically a jump target.
+#define skip cpse 16,16
+
+
+.macro mov4 dst, src
+ REGNO ..mov4.dst, \dst
+ REGNO ..mov4.src, \src
+ .if ..mov4.dst < ..mov4.src
+ wmov ..mov4.dst+0, ..mov4.src+0
+ wmov ..mov4.dst+2, ..mov4.src+2
+ .else
+ wmov ..mov4.dst+2, ..mov4.src+2
+ wmov ..mov4.dst+0, ..mov4.src+0
+ .endif
+.endm
+
+
+;; Negate a 2-byte value held in consecutive registers.
+.macro NEG2 reg
+ com \reg+1
+ neg \reg
+ sbci \reg+1, -1
+.endm
+
+
+;; Negate a 4-byte value held in consecutive registers.
+;; Sets the V flag for signed overflow tests if REG >= 16.
+.macro NEG4 reg
+ com \reg+3
+ com \reg+2
+ com \reg+1
+.if \reg >= 16
+ neg \reg
+ sbci \reg+1, -1
+ sbci \reg+2, -1
+ sbci \reg+3, -1
+.else
+ com \reg
+ adc \reg, __zero_reg__
+ adc \reg+1, __zero_reg__
+ adc \reg+2, __zero_reg__
+ adc \reg+3, __zero_reg__
+.endif
+.endm
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Function entry and exit.
+
+.macro DEFUN name
+ .global \name
+ .func \name
+ \name:
+.endm
+
+.macro ENDF name
+ .size \name, .-\name
+ .endfunc
+.endm
+
+.macro FALIAS name
+ .global \name
+ .func \name
+ \name:
+ .size \name, .-\name
+ .endfunc
+.endm
+
+
+#ifndef __AVR_TINY__
+
+;;; Prologue stuff
+.macro do_prologue_saves n_pushed n_frame=0
+ ldi r26, lo8 (\n_frame)
+ ldi r27, hi8 (\n_frame)
+ ldi r30, lo8 (gs(.L_prologue_saves.\@))
+ ldi r31, hi8 (gs(.L_prologue_saves.\@))
+ XJMP __prologue_saves__ + ((18 - (\n_pushed)) * 2)
+.L_prologue_saves.\@:
+.endm
+
+
+;; Epilogue stuff
+.macro do_epilogue_restores n_pushed n_frame=0
+ in r28, __SP_L__
+#ifdef __AVR_HAVE_SPH__
+ in r29, __SP_H__
+.if \n_frame > 63
+ subi r28, lo8 (-(\n_frame))
+ sbci r29, hi8 (-(\n_frame))
+.elseif \n_frame > 0
+ adiw r28, \n_frame
+.endif
+#else
+ clr r29
+.if \n_frame > 0
+ subi r28, lo8 (-(\n_frame))
+.endif
+#endif /* HAVE SPH */
+ ldi r30, \n_pushed
+ XJMP __epilogue_restores__ + ((18 - (\n_pushed)) * 2)
+.endm
+
+#endif /* AVR_TINY */
diff --git a/libgcc/config/avr/lib1funcs-fixed.S b/libgcc/config/avr/lib1funcs-fixed.S
index 577129503cf..4b77ee2dd56 100644
--- a/libgcc/config/avr/lib1funcs-fixed.S
+++ b/libgcc/config/avr/lib1funcs-fixed.S
@@ -1598,7 +1598,7 @@ DEFUN __rounduha3
;; [ R25:R24 = 1 << (FBIT-1 - RP)
;; R23:R22 += 1 << (FBIT-1 - RP) ]
XCALL __addmask_2
- XJMP __round_u2_const
+ XJMP __round_u2_const
ENDF __rounduha3
#endif /* L_round_u2 */
@@ -1627,7 +1627,7 @@ DEFUN __round_u2_const
;; C[] = 2^{-RP}
lsl C0
rol C1
- ;;
+ ;;
NEG2 C0
;; Clear the bits beyond the rounding point.
and C0, A0
@@ -1717,7 +1717,7 @@ DEFUN __roundusa3
;; [ R25:R22 = 1 << (FBIT-1 - RP)
;; R21:R18 += 1 << (FBIT-1 - RP) ]
XCALL __addmask_4
- XJMP __round_u4_const
+ XJMP __round_u4_const
ENDF __roundusa3
#endif /* L_round_u4 */
diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
index f0f06e478e1..4978a2e969c 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -21,202 +21,18 @@
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
-#if defined (__AVR_TINY__)
-#define __zero_reg__ r17
-#define __tmp_reg__ r16
-#else
-#define __zero_reg__ r1
-#define __tmp_reg__ r0
-#endif
-#define __SREG__ 0x3f
-#if defined (__AVR_HAVE_SPH__)
-#define __SP_H__ 0x3e
-#endif
-#define __SP_L__ 0x3d
-#define __RAMPZ__ 0x3B
-#define __EIND__ 0x3C
+#include "asm-defs.h"
/* Most of the functions here are called directly from avr.md
patterns, instead of using the standard libcall mechanisms.
This can make better code because GCC knows exactly which
- of the call-used registers (not all of them) are clobbered. */
-
-/* FIXME: At present, there is no SORT directive in the linker
- script so that we must not assume that different modules
- in the same input section like .libgcc.text.mul will be
- located close together. Therefore, we cannot use
- RCALL/RJMP to call a function like __udivmodhi4 from
- __divmodhi4 and have to use lengthy XCALL/XJMP even
- though they are in the same input section and all same
- input sections together are small enough to reach every
- location with a RCALL/RJMP instruction. */
+ of the call-used registers (not all of them) are clobbered.
+ Some functions are using a non-ABI interface. */
#if defined (__AVR_HAVE_EIJMP_EICALL__) && !defined (__AVR_HAVE_ELPMX__)
#error device not supported
#endif
- .macro mov_l r_dest, r_src
-#if defined (__AVR_HAVE_MOVW__)
- movw \r_dest, \r_src
-#else
- mov \r_dest, \r_src
-#endif
- .endm
-
- .macro mov_h r_dest, r_src
-#if defined (__AVR_HAVE_MOVW__)
- ; empty
-#else
- mov \r_dest, \r_src
-#endif
- .endm
-
-.macro wmov r_dest, r_src
-#if defined (__AVR_HAVE_MOVW__)
- movw \r_dest, \r_src
-#else
- mov \r_dest, \r_src
- mov \r_dest+1, \r_src+1
-#endif
-.endm
-
-.macro mov4 r_dest, r_src
- wmov \r_dest, \r_src
- wmov \r_dest+2, \r_src+2
-.endm
-
-#if defined (__AVR_HAVE_JMP_CALL__)
-#define XCALL call
-#define XJMP jmp
-#else
-#define XCALL rcall
-#define XJMP rjmp
-#endif
-
-#if defined (__AVR_HAVE_EIJMP_EICALL__)
-#define XICALL eicall
-#define XIJMP eijmp
-#else
-#define XICALL icall
-#define XIJMP ijmp
-#endif
-
-;;; [R]JMP to label \labl when \reg is positive (\reg.7 = 0).
-;;; Otherwise, fallthrough.
-.macro .branch_plus reg, labl
-#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
- ;; Some cores have a problem skipping 2-word instructions
- tst \reg
- brmi .L..\@
-#else
- sbrs \reg, 7
-#endif /* skip erratum */
- XJMP \labl
-.L..\@:
-.endm ; .branch_plus
-
-;; Prologue stuff
-
-.macro do_prologue_saves n_pushed n_frame=0
- ldi r26, lo8(\n_frame)
- ldi r27, hi8(\n_frame)
- ldi r30, lo8(gs(.L_prologue_saves.\@))
- ldi r31, hi8(gs(.L_prologue_saves.\@))
- XJMP __prologue_saves__ + ((18 - (\n_pushed)) * 2)
-.L_prologue_saves.\@:
-.endm
-
-;; Epilogue stuff
-
-.macro do_epilogue_restores n_pushed n_frame=0
- in r28, __SP_L__
-#ifdef __AVR_HAVE_SPH__
- in r29, __SP_H__
-.if \n_frame > 63
- subi r28, lo8(-\n_frame)
- sbci r29, hi8(-\n_frame)
-.elseif \n_frame > 0
- adiw r28, \n_frame
-.endif
-#else
- clr r29
-.if \n_frame > 0
- subi r28, lo8(-\n_frame)
-.endif
-#endif /* HAVE SPH */
- ldi r30, \n_pushed
- XJMP __epilogue_restores__ + ((18 - (\n_pushed)) * 2)
-.endm
-
-;; Support function entry and exit for convenience
-
-.macro wsubi r_arg1, i_arg2
-#if defined (__AVR_TINY__)
- subi \r_arg1, lo8(\i_arg2)
- sbci \r_arg1+1, hi8(\i_arg2)
-#else
- sbiw \r_arg1, \i_arg2
-#endif
-.endm
-
-.macro waddi r_arg1, i_arg2
-#if defined (__AVR_TINY__)
- subi \r_arg1, lo8(-\i_arg2)
- sbci \r_arg1+1, hi8(-\i_arg2)
-#else
- adiw \r_arg1, \i_arg2
-#endif
-.endm
-
-.macro DEFUN name
-.global \name
-.func \name
-\name:
-.endm
-
-.macro ENDF name
-.size \name, .-\name
-.endfunc
-.endm
-
-.macro FALIAS name
-.global \name
-.func \name
-\name:
-.size \name, .-\name
-.endfunc
-.endm
-
-;; Skip next instruction, typically a jump target
-#define skip cpse 16,16
-
-;; Negate a 2-byte value held in consecutive registers
-.macro NEG2 reg
- com \reg+1
- neg \reg
- sbci \reg+1, -1
-.endm
-
-;; Negate a 4-byte value held in consecutive registers
-;; Sets the V flag for signed overflow tests if REG >= 16
-.macro NEG4 reg
- com \reg+3
- com \reg+2
- com \reg+1
-.if \reg >= 16
- neg \reg
- sbci \reg+1, -1
- sbci \reg+2, -1
- sbci \reg+3, -1
-.else
- com \reg
- adc \reg, __zero_reg__
- adc \reg+1, __zero_reg__
- adc \reg+2, __zero_reg__
- adc \reg+3, __zero_reg__
-.endif
-.endm
-
#define exp_lo(N) hlo8 ((N) << 23)
#define exp_hi(N) hhi8 ((N) << 23)
@@ -244,7 +60,7 @@ DEFUN __mulqi3
breq __mulqi3_exit ; while multiplicand != 0
lsr r_arg1 ;
brne __mulqi3_loop ; exit if multiplier = 0
-__mulqi3_exit:
+__mulqi3_exit:
mov r_arg1,r_res ; result to return register
ret
ENDF __mulqi3
@@ -252,7 +68,7 @@ DEFUN __mulqi3
#undef r_arg2
#undef r_arg1
#undef r_res
-
+
#endif /* defined (L_mulqi3) */
@@ -501,7 +317,7 @@ DEFUN __mulsi3_helper
wmov C2, CC2
#if defined (__AVR_TINY__)
pop B1 ; restore callee saved regs
- pop B0
+ pop B0
#endif /* defined (__AVR_TINY__) */
ret
@@ -615,14 +431,7 @@ DEFUN __umulhisi3
;;; (C3:C0) = (signed long) A1:A0 * B3:B0
;;; Clobbers: __tmp_reg__
DEFUN __mulshisi3
-#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
- ;; Some cores have problem skipping 2-word instruction
- tst A1
- brmi __mulohisi3
-#else
- sbrs A1, 7
-#endif /* __AVR_HAVE_JMP_CALL__ */
- XJMP __muluhisi3
+ .branch_plus A1, __muluhisi3
;; FALLTHRU
ENDF __mulshisi3
@@ -760,13 +569,13 @@ DEFUN __mulpsi3
DEFUN __mulpsi3
#if defined (__AVR_TINY__)
- in r26,__SP_L__
+ in r26,__SP_L__
in r27,__SP_H__
subi r26, lo8(-3) ; Add 3 to point past return address
sbci r27, hi8(-3)
push B0 ; save callee saved regs
push B1
- ld B0,X+ ; load from caller stack
+ ld B0,X+ ; load from caller stack
ld B1,X+
ld B2,X+
#endif /* defined (__AVR_TINY__) */
@@ -1119,15 +928,15 @@ DEFUN __muldi3
#if defined (__AVR_HAVE_MUL__)
#define A0 r22
-#define A1 r23
+#define A1 r23
#define A2 r24
#define A3 r25
-
+
#define B0 r18
#define B1 r19
#define B2 r20
#define B3 r21
-
+
#define C0 18
#define C1 C0+1
#define C2 20
@@ -1349,7 +1158,7 @@ DEFUN __umulsidi3
#endif /* L_mulsidi3 && !HAVE_MUL */
#endif /* if not __AVR_TINY__ */
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
+
.section .text.libgcc.div, "ax", @progbits
@@ -1405,8 +1214,8 @@ DEFUN __divmodqi4
#undef r_arg1
#undef r_arg2
#undef r_cnt
-
-
+
+
/*******************************************************
Division 16 / 16 => (result + remainder)
*******************************************************/
@@ -1420,7 +1229,7 @@ DEFUN __divmodqi4
/* return: quotient */
#define r_arg2L r22 /* divisor Low */
#define r_arg2H r23 /* divisor High */
-
+
#define r_cnt r21 /* loop count */
#if defined (L_udivmodhi4)
@@ -1445,10 +1254,8 @@ DEFUN __udivmodhi4
com r_arg1L
com r_arg1H
; div/mod results to return registers, as for the div() function
- mov_l r_arg2L, r_arg1L ; quotient
- mov_h r_arg2H, r_arg1H
- mov_l r_arg1L, r_remL ; remainder
- mov_h r_arg1H, r_remH
+ wmov r_arg2L, r_arg1L ; quotient
+ wmov r_arg1L, r_remL ; remainder
ret
ENDF __udivmodhi4
#endif /* defined (L_udivmodhi4) */
@@ -1493,8 +1300,8 @@ DEFUN __divmodhi4
#undef r_arg2H
#undef r_arg2L
-
-#undef r_cnt
+
+#undef r_cnt
/*******************************************************
Division 24 / 24 => (result + remainder)
@@ -1650,7 +1457,7 @@ DEFUN __divmodpsi4
#define r_arg2HL r20
#define r_arg2H r19
#define r_arg2L r18 /* divisor Low */
-
+
#define r_cnt __zero_reg__ /* loop count (0 after the loop!) */
#if defined (L_udivmodsi4)
@@ -1659,8 +1466,7 @@ DEFUN __udivmodsi4
mov r_cnt, r_remL
sub r_remL,r_remL
sub r_remH,r_remH ; clear remainder and carry
- mov_l r_remHL, r_remL
- mov_h r_remHH, r_remH
+ wmov r_remHL, r_remL
rjmp __udivmodsi4_ep ; jump to entry point
__udivmodsi4_loop:
rol r_remL ; shift dividend into remainder
@@ -1689,14 +1495,10 @@ DEFUN __udivmodsi4
com r_arg1HL
com r_arg1HH
; div/mod results to return registers, as for the ldiv() function
- mov_l r_arg2L, r_arg1L ; quotient
- mov_h r_arg2H, r_arg1H
- mov_l r_arg2HL, r_arg1HL
- mov_h r_arg2HH, r_arg1HH
- mov_l r_arg1L, r_remL ; remainder
- mov_h r_arg1H, r_remH
- mov_l r_arg1HL, r_remHL
- mov_h r_arg1HH, r_remHH
+ wmov r_arg2L, r_arg1L ; quotient
+ wmov r_arg2HL, r_arg1HL
+ wmov r_arg1L, r_remL ; remainder
+ wmov r_arg1HL, r_remHL
ret
ENDF __udivmodsi4
#endif /* defined (L_udivmodsi4) */
@@ -2277,8 +2079,7 @@ DEFUN __epilogue_restores__
out __SP_H__,r29
out __SREG__,__tmp_reg__
out __SP_L__,r28
- mov_l r28, r26
- mov_h r29, r27
+ wmov r28, r26
#endif /* #SP = 8/16 */
ret
ENDF __epilogue_restores__
@@ -2353,7 +2154,7 @@ DEFUN __tablejump2__
wsubi 30, -(__AVR_TINY_PM_BASE_ADDRESS__) ; Add PM offset to Z
ld __tmp_reg__, Z+
ld r31, Z ; Use ld instead of lpm to load Z
- mov r30, __tmp_reg__
+ mov r30, __tmp_reg__
ijmp
#else
lpm
@@ -2496,8 +2297,7 @@ DEFUN __do_global_ctors
sbc r16, __zero_reg__
mov r24, r16
#endif /* HAVE_EIJMP */
- mov_h r31, r29
- mov_l r30, r28
+ wmov r30, r28
XCALL __tablejump2__
.L__do_global_ctors_start:
cpi r28, pm_lo8(__ctors_start)
@@ -2524,8 +2324,7 @@ DEFUN __do_global_dtors
#ifdef __AVR_HAVE_EIJMP_EICALL__
mov r24, r16
#endif /* HAVE_EIJMP */
- mov_h r31, r29
- mov_l r30, r28
+ wmov r30, r28
XCALL __tablejump2__
waddi 28, 1
#ifdef __AVR_HAVE_EIJMP_EICALL__
@@ -2764,14 +2563,8 @@ DEFUN __fload_4
#if !defined (__AVR_TINY__)
#if defined (L_strlen_memx)
DEFUN __strlen_memx
-#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
- tst r24
- brmi 1f
-#else
- sbrs r24, 7
-#endif
- XJMP strlen_PF ; AVR-LibC
-1: wmov 24, 22
+ .branch_plus r24, strlen_PF ; AVR-LibC
+ wmov 24, 22
XJMP strlen ; AVR-LibC
ENDF __strlen_memx
#endif /* L_strlen_memx */
@@ -2872,7 +2665,7 @@ DEFUN __movmemf_hi
#undef LOOP
#endif /* L_movmemf */
-#endif /* !defined (__AVR_TINY__) */
+#endif /* !defined (__AVR_TINY__) */
.section .text.libgcc.builtins, "ax", @progbits
@@ -2984,10 +2777,8 @@ DEFUN __clzdi2
XCALL __clzsi2
sbrs r24, 5
ret
- mov_l r22, r18
- mov_h r23, r19
- mov_l r24, r20
- mov_h r25, r21
+ wmov r22, r18
+ wmov r24, r20
XCALL __clzsi2
subi r24, -32
ret
@@ -3002,8 +2793,7 @@ DEFUN __clzsi2
XCALL __clzhi2
sbrs r24, 4
ret
- mov_l r24, r22
- mov_h r25, r23
+ wmov r24, r22
XCALL __clzhi2
subi r24, -16
ret
@@ -3124,8 +2914,7 @@ DEFUN __popcounthi2_tail
DEFUN __popcountsi2
XCALL __popcounthi2
push r24
- mov_l r24, r22
- mov_h r25, r23
+ wmov r24, r22
XCALL __popcounthi2
XJMP __popcounthi2_tail
ENDF __popcountsi2
@@ -3138,10 +2927,8 @@ DEFUN __popcountsi2
DEFUN __popcountdi2
XCALL __popcountsi2
push r24
- mov_l r22, r18
- mov_h r23, r19
- mov_l r24, r20
- mov_h r25, r21
+ wmov r22, r18
+ wmov r24, r20
XCALL __popcountsi2
XJMP __popcounthi2_tail
ENDF __popcountdi2
@@ -3433,15 +3220,8 @@ DEFUN __fmulsu_exit
;; A1 = |A1|
sbrc A1, 7
neg A1
-#ifdef __AVR_ERRATA_SKIP_JMP_CALL__
- ;; Some cores have problem skipping 2-word instruction
- tst A0
- brmi 1f
-#else
- sbrs A0, 7
-#endif /* __AVR_HAVE_JMP_CALL__ */
- XJMP __fmul
-1: XCALL __fmul
+ .branch_plus A0, __fmul
+ XCALL __fmul
;; C = -C iff A0.7 = 1
NEG2 C0
ret