[gcc r17-2987] AVR: Add [un]signed sat accum divisions.

Georg-Johann Lay via Gcc-cvs <[email protected]> Wed, 5 Aug 2026 15:31:01 +0000 (GMT)
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:898cd93819867f14fe26d708288434a0c033721a

commit r17-2987-g898cd93819867f14fe26d708288434a0c033721a
Author: Georg-Johann Lay <[email protected]>
Date:   Wed Aug 5 17:28:35 2026 +0200

    AVR: Add [un]signed sat accum divisions.
    
    This patch adds support for the signed and unsigned
    saturated accum [U]SAmode divisions.  The functions
    can be used without adjustment on the Reduced Core,
    so enable them there.
    
    The code for the vanilla divisions has been reworked, and
    the non-saturating functions are now just aliases of the
    saturating ones.  This entails the following size changes:
    __udivusa3: Becomes one instruction shorter.
    __divsa3: Grows by 7 instructions that handle saturation.
    
    gcc/
            * config/avr/avr.md (code_stdname): Add code attributes
            for: ss_div, us_div, div, udiv.
            * config/avr/avr-fixed.md (alldiv): New code iterator.
            Use it in all [U]SAmode division expanders and insns.
            Use <code_stdname> instead of <code> as needed.
    libgcc/
            * config/avr/t-avr (FUNCS_notiny) <_divsa3, _udivusa3>: Move
            to LIB1ASMFUNCS.
            * config/avr/lib1funcs-fixed.S (__divsa3, __udivusa3): Overhaul.
            Saturate result.
            (__ssdivsa3, __usdivusa3, __udivusa3.2): New ENTRYs.
    gcc/testsuite/
            * gcc.target/avr/fx32-div-1.c: New test.
            * gcc.target/avr/fx32-div-2.c: New test.
            * gcc.target/avr/fx32-div-3.c: New test.
            * gcc.target/avr/fx32.h: New file.

Diff:
---
 gcc/config/avr/avr-fixed.md               |  37 +++---
 gcc/config/avr/avr.md                     |   1 +
 gcc/testsuite/gcc.target/avr/fx32-div-1.c |  72 ++++++++++
 gcc/testsuite/gcc.target/avr/fx32-div-2.c |  72 ++++++++++
 gcc/testsuite/gcc.target/avr/fx32-div-3.c |  54 ++++++++
 gcc/testsuite/gcc.target/avr/fx32.h       |  36 +++++
 libgcc/config/avr/lib1funcs-fixed.S       | 210 +++++++++++++++++-------------
 libgcc/config/avr/t-avr                   |   2 +-
 8 files changed, 379 insertions(+), 105 deletions(-)

diff --git a/gcc/config/avr/avr-fixed.md b/gcc/config/avr/avr-fixed.md
index d638d0b68d7b..4d8c9b1af01b 100644
--- a/gcc/config/avr/avr-fixed.md
+++ b/gcc/config/avr/avr-fixed.md
@@ -460,7 +460,8 @@
 ; / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
 ; div
 
-(define_code_iterator usdiv [udiv div])
+(define_code_iterator usdiv  [udiv div])
+(define_code_iterator alldiv [udiv div us_div ss_div])
 
 ;; "divqq3" "udivuqq3"
 (define_expand "<code><mode>3"
@@ -549,45 +550,51 @@
 ;; Note the first parameter gets passed in already offset by 2 bytes
 
 ;; "divsa3" "udivusa3"
-(define_expand "<code><mode>3"
+;; "ssdivsa3" "usdivusa3"
+(define_expand "<code_stdname><mode>3"
   [(set (reg:ALL4A 24)
         (match_operand:ALL4A 1 "register_operand" ""))
    (set (reg:ALL4A 18)
         (match_operand:ALL4A 2 "register_operand" ""))
    (parallel [(set (reg:ALL4A 22)
-                   (usdiv:ALL4A (reg:ALL4A 24)
-                                (reg:ALL4A 18)))
+                   (alldiv:ALL4A (reg:ALL4A 24)
+                                 (reg:ALL4A 18)))
               (clobber (reg:HI 26))
               (clobber (reg:HI 30))])
    (set (match_operand:ALL4A 0 "register_operand" "")
         (reg:ALL4A 22))]
-  ""
+  "SIGNED_FIXED_POINT_MODE_P (<MODE>mode)
+   == (<CODE> == DIV || <CODE> == SS_DIV)"
   {
     avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 24));
   })
 
-;; "*divsa3.call" "*udivusa3.call"
-(define_insn_and_split "*<code><mode>3.call_split"
+;; "*divsa3.split" "*udivusa3.split" "*ssdivsa3.split" "*usdivusa3.split"
+(define_insn_and_split "*<code_stdname><mode>3.split"
   [(set (reg:ALL4A 22)
-        (usdiv:ALL4A (reg:ALL4A 24)
-                     (reg:ALL4A 18)))
+        (alldiv:ALL4A (reg:ALL4A 24)
+                      (reg:ALL4A 18)))
    (clobber (reg:HI 26))
    (clobber (reg:HI 30))]
-  ""
+  "SIGNED_FIXED_POINT_MODE_P (<MODE>mode)
+   == (<CODE> == DIV || <CODE> == SS_DIV)"
   "#"
   "&& reload_completed"
   [(scratch)]
   { DONE_ADD_CCC })
 
-(define_insn "*<code><mode>3.call"
+;; "*divsa3.call" "*udivusa3.call" "*ssdivsa3.call" "*usdivusa3.call"
+(define_insn "*<code_stdname><mode>3.call"
   [(set (reg:ALL4A 22)
-        (usdiv:ALL4A (reg:ALL4A 24)
-                     (reg:ALL4A 18)))
+        (alldiv:ALL4A (reg:ALL4A 24)
+                      (reg:ALL4A 18)))
    (clobber (reg:HI 26))
    (clobber (reg:HI 30))
    (clobber (reg:CC REG_CC))]
-  "reload_completed"
-  "%~call __<code><mode>3"
+  "reload_completed
+   && SIGNED_FIXED_POINT_MODE_P (<MODE>mode)
+      == (<CODE> == DIV || <CODE> == SS_DIV)"
+  "%~call __<code_stdname><mode>3"
   [(set_attr "type" "xcall")])
 
 
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index f57df70db930..f67278b87ad2 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -390,6 +390,7 @@
    (rotate   "rotl")
    (ss_plus  "ssadd")  (ss_minus "sssub")  (ss_neg "ssneg")  (ss_abs "ssabs")
    (us_plus  "usadd")  (us_minus "ussub")  (us_neg "usneg")
+   (ss_div   "ssdiv")  (us_div   "usdiv")  (div "div")  (udiv "udiv")
    ])
 
 ;;========================================================================
diff --git a/gcc/testsuite/gcc.target/avr/fx32-div-1.c b/gcc/testsuite/gcc.target/avr/fx32-div-1.c
new file mode 100644
index 000000000000..cdaebb644824
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/fx32-div-1.c
@@ -0,0 +1,72 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options { -std=gnu99 -Os -mcall-prologues } } */
+
+#include "fx32.h"
+
+#define MK_TEST(fx)				    \
+  NI bool in_range_##fx (float x)		    \
+  {						    \
+    return x < fmax_##fx && x >= fmin_##fx;	    \
+  }						    \
+						    \
+  NI void test_div_##fx (float a, float b)	    \
+  {						    \
+    if (!in_range_##fx (a))			    \
+      return;					    \
+    if (!in_range_##fx (b))			    \
+      return;					    \
+    float f = b ? a / b : 0.0f;			    \
+    __asm volatile ("" : "+r" (f));		    \
+    fx##_t ax = (fx##_t) a;			    \
+    fx##_t bx = (fx##_t) b;			    \
+    fx##_t ab = ax / bx;			    \
+    if ((b == 0 && a < 0) || (b && f < fmin_##fx))  \
+      {						    \
+	if (ab != min_##fx)			    \
+	  exit (id_##fx + 1);			    \
+	return;					    \
+      }						    \
+    if ((b == 0 && a >= 0) || (b && f > fmax_##fx)) \
+      {						    \
+	if (ab != max_##fx)			    \
+	  exit (id_##fx + 2);			    \
+	return;					    \
+      }						    \
+    if (f != (float) ab)			    \
+      exit (id_##fx + 3);			    \
+  }
+
+MK_TEST (k)
+MK_TEST (uk)
+
+NI void test_div (float a, float b)
+{
+  test_div_k (a, b);
+  test_div_uk (a, b);
+}
+
+// Results / args must be representable as float, so no rounding occurs.
+// Non-overflow results must be representable as fixed, so no rounding occurs.
+const PROGMEM float fvals[] =
+  {
+    0.0,
+    +1.0, +2.0, +0.5, +0x1p5, +0x1p6, +0x1p-7,
+    -1.0, -2.0, -0.5, -0x1p5, -0x1p6, -0x1p-7,
+  };
+
+NI void test1 (void)
+{
+  for (uint8_t a = 0; a < ARRAY_SIZE (fvals); ++a)
+    for (uint8_t b = 0; b < ARRAY_SIZE (fvals); ++b)
+      {
+	float fa = pgm_read_float (&fvals[a]);
+	float fb = pgm_read_float (&fvals[b]);
+	test_div (fa, fb);
+      }
+}
+
+int main (void)
+{
+  test1 ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/avr/fx32-div-2.c b/gcc/testsuite/gcc.target/avr/fx32-div-2.c
new file mode 100644
index 000000000000..41279424dbda
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/fx32-div-2.c
@@ -0,0 +1,72 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options { -std=gnu99 -Os -mcall-prologues } } */
+
+#include "fx32.h"
+
+NI void test_k (uint32_t a, float fb, uint32_t res)
+{
+  k_t b = (k_t) fb;
+  if (kbits (a) / b != kbits (res))
+    exit (id_k + 4);
+}
+
+NI void test_uk (uint32_t a, float fb, uint32_t res)
+{
+  uk_t b = (uk_t) fb;
+  if (ukbits (a) / b != ukbits (res))
+    exit (id_uk + 4);
+}
+
+NI void test2_k (uint32_t a, uint32_t b, uint32_t res)
+{
+  if (kbits (a) / kbits (b) != kbits (res))
+    exit (id_k + 5);
+}
+
+NI void test2_uk (uint32_t a, uint32_t b, uint32_t res)
+{
+  if (ukbits (a) / ukbits (b) != ukbits (res))
+    exit (id_uk + 5);
+}
+
+NI void test2 (void)
+{
+  test_uk (+0xaabbcc99, +0x11.0p0f, +0x0a0b0c09);
+  test_k  (-0x77bbcc99, +0x11.0p0f, -0x070b0c09);
+  test_k  (+0x77bbcc99, -0x11.0p0f, -0x070b0c09);
+  test_k  (-0x77bbcc99, -0x11.0p0f, +0x070b0c09);
+  test_k  (-0x7ffe0268, 2.0f, -0x3fff0134);
+  test_uk (+0x7ffe0268, 2.0f, +0x3fff0134);
+  test_uk (+0xc42ecb55, 2.0f, +0x621765aa);
+  test_k  (-0x642ecb55, 2.0f, -0x321765aa);
+  test_uk (+0xffffffff, 2.0f, +0x7fffffff);
+  test_k  (-0x7fffffff, 2.0f, -0x3fffffff);
+  test_k  (+0, 0.0f, SMAX);
+  test_k  (+1, 0.0f, SMAX);
+  test_k  (-1, 0.0f, SMIN);
+  test_uk (+0, 0.0f, UMAX);
+  test_uk (+1, 0.0f, UMAX);
+  test_k  (SMAX - 1000, +0x0.fffp0f, SMAX);
+  test_k  (SMIN + 1000, +0x0.fffp0f, SMIN);
+  test_k  (SMAX - 1000, -0x0.fffp0f, SMIN);
+  test_k  (SMIN + 1000, -0x0.fffp0f, SMAX);
+  test_uk (UMAX - 1000, +0x0.fffp0f, UMAX);
+  test_uk (UMAX - 1000, +0x0.fffp0f, UMAX);
+
+  test2_uk (X80 + 1, X80, uk_1);
+  test2_uk (X80, X80 + 1, uk_1 - 1);
+  test2_uk (UMAX - 1, UMAX, uk_1 - 1);
+  test2_k  (SMAX, SMIN, -(k_1 - 1));
+  test2_k  (SMIN, SMAX, -k_1);
+  test2_k  (SMAX, SMAX, k_1);
+  test2_k  (SMAX, SMAX, k_1);
+  test2_uk (SMIN, SMIN, uk_1);
+  test2_uk (1, 1, uk_1);
+  test2_k  (1, 1, k_1);
+}
+
+int main (void)
+{
+  test2 ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/avr/fx32-div-3.c b/gcc/testsuite/gcc.target/avr/fx32-div-3.c
new file mode 100644
index 000000000000..616f3ea8f0eb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/fx32-div-3.c
@@ -0,0 +1,54 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options { -std=gnu99 -Os -mcall-prologues } } */
+
+#include "fx32.h"
+
+#define MK_TEST(fx)						\
+  NI void test_div_##fx (uint32_t a, float fb, uint32_t r)	\
+  {								\
+    fx##_t ab = fx##bits (a) / (fx##_t) fb;			\
+    if (ab != fx##bits (r))					\
+      exit (id_##fx + 6);					\
+    return;							\
+  }
+
+MK_TEST (k)
+MK_TEST (uk)
+
+NI void test1_div (uint32_t a, float fb, uint32_t r)
+{
+  test_div_uk (a, fb, r);
+  if ((a & X80) == 0)
+    {
+      test_div_k (a, fb, r);
+    }
+}
+
+NI void test2_div (uint32_t a, float fb, uint32_t r)
+{
+  test_div_uk (a, fb, r);
+  if ((r & X80) == 0)
+    {
+      test_div_k (a, fb, r);
+    }
+  else
+    {
+      test_div_k (a, fb, SMAX);
+    }
+}
+
+NI void test3 (void)
+{
+  for (uint32_t a = (uint32_t) 0xff01 << (32 - 16); a; a >>= 1)
+    {
+      test1_div (a, 2.0f, a >> 1);
+      if ((a & X80) == 0)
+	test2_div (a, 0.5f, a << 1);
+    }
+}
+
+int main (void)
+{
+  test3 ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/avr/fx32.h b/gcc/testsuite/gcc.target/avr/fx32.h
new file mode 100644
index 000000000000..0fdc00128f31
--- /dev/null
+++ b/gcc/testsuite/gcc.target/avr/fx32.h
@@ -0,0 +1,36 @@
+#include <stdfix.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <avr/pgmspace.h>
+
+#define NI __attribute((noipa))
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x))
+
+typedef accum k_t;
+typedef unsigned accum uk_t;
+
+typedef sat accum sat_k_t;
+typedef sat unsigned accum sat_uk_t;
+
+// Values are in fmin <= x < fmax.
+#define fmax_k 0x1.0p16f
+#define fmin_k (-fmax_k)
+#define fmax_uk fmax_k
+#define fmin_uk 0.0f
+
+#define UMAX 0xffffffff
+#define SMAX 0x7fffffff
+#define SMIN 0x80000000
+#define X80  0x80000000
+
+// Values are in min <= x <= max.
+#define max_k kbits (SMAX)
+#define min_k kbits (SMIN)
+#define max_uk ukbits (UMAX)
+#define min_uk ukbits (0)
+
+#define k_1   (1ul << __SA_FBIT__)
+#define uk_1  (1ul << __USA_FBIT__)
+
+#define id_k   10
+#define id_uk  20
diff --git a/libgcc/config/avr/lib1funcs-fixed.S b/libgcc/config/avr/lib1funcs-fixed.S
index 2996a5960eb1..a380db1e708b 100644
--- a/libgcc/config/avr/lib1funcs-fixed.S
+++ b/libgcc/config/avr/lib1funcs-fixed.S
@@ -1681,112 +1681,144 @@ ENDF __udivuha3
 #undef  r_divH
 #undef  r_cnt
 
-/*******************************************************
-    Fixed Division 16.16 / 16.16
-*******************************************************/
+/*********************************************************
+    Fixed 16.16 and s16.15 saturated [U]SAmode Divisions
+*********************************************************/
 
-#ifndef __AVR_TINY__
+;;; Argument 1: Dividend gets passed already in place.
+#define A0 24
+#define A1 A0+1
+#define A2 26
+#define A3 A2+1
+
+;;; Argument 2: Divisor
+#define B0 18
+#define B1 B0+1
+#define B2 20
+#define B3 B2+1
 
-#define r_arg1L  24    /* arg1 gets passed already in place */
-#define r_arg1H  25
-#define r_arg1HL 26
-#define r_arg1HH 27
-#define r_divdL  26    /* dividend Low */
-#define r_divdH  27
-#define r_divdHL 30
-#define r_divdHH 31    /* dividend High */
-#define r_quoL   22    /* quotient Low */
-#define r_quoH   23
-#define r_quoHL  24
-#define r_quoHH  25    /* quotient High */
-#define r_divL   18    /* divisor Low */
-#define r_divH   19
-#define r_divHL  20
-#define r_divHH  21    /* divisor High */
-#define r_cnt  __zero_reg__  /* loop count (0 after the loop!) */
+;;; Return value: Quotient
+#define Q0 22
+#define Q1 Q0+1
+#define Q2 A0
+#define Q3 A0+1
+
+;;; Remainder
+#define M0 A2
+#define M1 A2+1
+#define M2 __tmp_reg__
+#define M3 __zero_reg__
+
+#define Cnt  r31
+#define Sign r30
 
 #if defined (L_divsa3)
+;;; (set (reg:SA 22)
+;;;      (ss_div:SA (reg:SA 24)
+;;;                 (reg:SA 18)))
 DEFUN   __divsa3
-    mov     r0, r_arg1HH
-    eor     r0, r_divHH
-    .call_if_neg r_divHH, __negsi2_r18
-    sbrs    r_arg1HH, 7
+ENTRY   __ssdivsa3
+    mov     Sign, B3
+    .call_if_neg B3, __negsi2_r18
+    sbrs    A3, 7
     rjmp    2f
-    NEG4    r_arg1L
-2:
-    XCALL   __udivusa3
-    lsr     r_quoHH ; adjust to 15 fractional bits
-    ror     r_quoHL
-    ror     r_quoH
-    ror     r_quoL
-    sbrs    r0, 7   ; negate result if needed
+    com     Sign
+    NEG4    A0
+2:  lsr     A3              ; Adjust to 15 fractional bits.
+    ror     A2
+    ror     A1
+    ror     A0              ; Pass LSB in C.
+    XCALL   __udivusa3.2    ; N = sign (Q)
+    ;; In the negative result case, Q = 0x80.. is no overflow,
+    ;; but treating it as such keeps the value unchanged.
+    brmi .Lsaturate          ; Overflow?
+    ;; Handle result sign.
+    sbrs    Sign, 7
     ret
-    ;; negate r_quoL
     XJMP    __negsi2
+.Lsaturate:
+    ;; Sign.7 = 0 -> C = 1 -> 0x7f..
+    ;; Sign.7 = 1 -> C = 0 -> 0x80..
+    cpi     Sign, 0x80
+    sbc     Q0, Q0
+    sbc     Q1, Q1
+    wmov    Q2, Q0
+    subi    Q3, 0x80
+    ret
 ENDF __divsa3
 #endif  /* defined (L_divsa3) */
 
 #if defined (L_udivusa3)
+;;; (set (reg:USA 22)
+;;;      (us_div:USA (reg:USA 24)
+;;;                  (reg:USA 18)))
+;;; Register layout:
+;;;         A3  A2  A1  A0          [---const----]
+;;; M3  M2  M1  M0  Q3  Q2  Q1  Q0  B3  B2  B1  B0
+;;; r1  r0  27  26  25  24  23  22  21  20  19  18
 DEFUN   __udivusa3
-    ldi     r_divdHL, 32    ; init loop counter
-    mov     r_cnt, r_divdHL
-    clr     r_divdHL
-    clr     r_divdHH
-    wmov    r_quoL, r_divdHL
-    lsl     r_quoHL         ; shift quotient into carry
-    rol     r_quoHH
-__udivusa3_loop:
-    rol     r_divdL         ; shift dividend (with CARRY)
-    rol     r_divdH
-    rol     r_divdHL
-    rol     r_divdHH
-    brcs    __udivusa3_ep   ; dividend overflow
-    cp      r_divdL,r_divL  ; compare dividend & divisor
-    cpc     r_divdH,r_divH
-    cpc     r_divdHL,r_divHL
-    cpc     r_divdHH,r_divHH
-    brcc    __udivusa3_ep   ; dividend >= divisor
-    rol     r_quoL          ; shift quotient (with CARRY)
-    rjmp    __udivusa3_cont
-__udivusa3_ep:
-    sub     r_divdL,r_divL  ; restore dividend
-    sbc     r_divdH,r_divH
-    sbc     r_divdHL,r_divHL
-    sbc     r_divdHH,r_divHH
-    lsl     r_quoL          ; shift quotient (without CARRY)
-__udivusa3_cont:
-    rol     r_quoH          ; shift quotient
-    rol     r_quoHL
-    rol     r_quoHH
-    dec     r_cnt           ; decrement loop counter
-    brne    __udivusa3_loop
-    com     r_quoL          ; complement result
-    com     r_quoH          ; because C flag was complemented in loop
-    com     r_quoHL
-    com     r_quoHH
+ENTRY   __usdivusa3
+    clc
+ENTRY   __udivusa3.2
+    ldi     Cnt, 33     ; Init loop counter.
+    clr     M2
+    wmov    Q0, M2      ; M3 === R1 = 0 already.
+    ;; C = 0 (unsigned).
+    ;; C = LSB (from signed caller).
+    rjmp    .Lstart
+.Loop:
+    rol     M0          ; Shift dividend with Carry from Q.
+    rol     M1
+    rol     M2
+    rol     M3
+    brcs .Lsub          ; Remainder overflow: B will always fit.
+    cp      M0, B0      ; Compare remainder and divisor.
+    cpc     M1, B1
+    cpc     M2, B2
+    cpc     M3, B3
+    brcc .Lsub          ; Remainder >= divisor?
+    rol     Q0          ; No: Shift quotient (C = 1, 0 in result)
+    rjmp .Lcont
+.Lsub:
+    sub     M0, B0      ; Yes: Restore remainder.
+    sbc     M1, B1
+    sbc     M2, B2
+    sbc     M3, B3
+    lsl     Q0          ; Shift quotient (C = 0, 1 in result).
+.Lcont:
+    rol     Q1          ; Shift quotient into C into M.
+.Lstart:
+    rol     Q2
+    rol     Q3
+    dec     Cnt         ; Decrement loop counter until 0.
+    brne .Loop
+    clr     __zero_reg__
+    com     Q0          ; Complement result because Carry
+    com     Q1          ; was complemented in the loop.
+    com     Q2
+    com     Q3          ; N is the sign of Q
     ret
 ENDF __udivusa3
 #endif  /* defined (L_udivusa3) */
 
-#undef  r_arg1L
-#undef  r_arg1H
-#undef  r_arg1HL
-#undef  r_arg1HH
-#undef  r_divdL
-#undef  r_divdH
-#undef  r_divdHL
-#undef  r_divdHH
-#undef  r_quoL
-#undef  r_quoH
-#undef  r_quoHL
-#undef  r_quoHH
-#undef  r_divL
-#undef  r_divH
-#undef  r_divHL
-#undef  r_divHH
-#undef  r_cnt
-
-#endif /* ! AVR_TINY */
+#undef A0
+#undef A1
+#undef A2
+#undef A3
+#undef M0
+#undef M1
+#undef M2
+#undef M3
+#undef Q0
+#undef Q1
+#undef Q2
+#undef Q3
+#undef B0
+#undef B1
+#undef B2
+#undef B3
+#undef Cnt
+#undef Sign
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/libgcc/config/avr/t-avr b/libgcc/config/avr/t-avr
index edd0e8f86983..da4be9fb55dc 100644
--- a/libgcc/config/avr/t-avr
+++ b/libgcc/config/avr/t-avr
@@ -44,6 +44,7 @@ LIB1ASMFUNCS = \
 	_divqq3 _udivuqq3 _divqq_helper \
 	_divhq3 _udivuhq3 \
 	_divha3 _udivuha3 \
+	_divsa3 _udivusa3 \
 	_ssneg_2 \
 	_ssabs_1 _ssabs_2 \
 	_mask1 _ret \
@@ -99,7 +100,6 @@ FUNCS_notiny += \
 	_muluda3 _muluta3 _muludq3 \
 	_mulda3 _multa3 _muldq3 \
 	_muluQ64_tail _mulQ64_work \
-	_divsa3 _udivusa3 \
 	_udivuda3 _udivuta3 _udivudq3 _udivuQ64_common \
 	_divda3 _divta3 _divdq3 _divQ64_tail \
 	_clr_8 \