]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
AVR: Add 16-bit saturated fixed-point divisions. master trunk
authorGeorg-Johann Lay <avr@gjlay.de>
Wed, 5 Aug 2026 15:34:19 +0000 (17:34 +0200)
committerGeorg-Johann Lay <avr@gjlay.de>
Wed, 5 Aug 2026 15:34:24 +0000 (17:34 +0200)
Overhaul the 16-bit fixed-point divisions:  Add support for
saturating divisions of [U]HAmode and [U]HQmode to libgcc.
The non-saturating functions are just aliases of the saturating
ones.  Add test cases.

gcc/
* config/avr/avr-fixed.md: Use alldiv as code iterator for the
16-bit fixed-point insns and expanders of [U]HAmode, [U]HQmode.
Support saturated divisions in [U]HAmode, [U]HQmode.
libgcc/
* config/avr/t-avr (LIB1ASMFUNCS): Add _divQ16_tail.
* config/avr/lib1funcs-fixed.S (__divQ16_tail): New DEFUN.
(__divhq3, __udivuhq3, __divha3, __udivuha3): Overhaul.
(__ssdivhq3, __usdivuhq3, __ssdivha3, __usdivuha3): New ENTRYs.
gcc/testsuite/
* gcc.target/avr/fx16.h: New file.
* gcc.target/avr/fx16-div-1.c: New test.
* gcc.target/avr/fx16-div-2.c: New test.
* gcc.target/avr/fx16-div-3.c: New test.

gcc/config/avr/avr-fixed.md
gcc/testsuite/gcc.target/avr/fx16-div-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/avr/fx16-div-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/avr/fx16-div-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/avr/fx16.h [new file with mode: 0644]
libgcc/config/avr/lib1funcs-fixed.S
libgcc/config/avr/t-avr

index 4d8c9b1af01bfa05e9f30a38df11757b942508fc..e4c08cbd84fc03c5ba88f48a6d648dff0712ca11 100644 (file)
   "%~call __<code><mode>3"
   [(set_attr "type" "xcall")])
 
-;; "divhq3" "udivuhq3"
-;; "divha3" "udivuha3"
-(define_expand "<code><mode>3"
+;; "divhq3" "udivuhq3" "ssdivhq3" "usdivuhq3"
+;; "divha3" "udivuha3" "ssdivha3" "usdivuha3"
+(define_expand "<code_stdname><mode>3"
   [(set (reg:ALL2QA 26)
         (match_operand:ALL2QA 1 "register_operand" ""))
    (set (reg:ALL2QA 22)
         (match_operand:ALL2QA 2 "register_operand" ""))
    (parallel [(set (reg:ALL2QA 24)
-                   (usdiv:ALL2QA (reg:ALL2QA 26)
-                                 (reg:ALL2QA 22)))
+                   (alldiv:ALL2QA (reg:ALL2QA 26)
+                                  (reg:ALL2QA 22)))
               (clobber (reg:HI 26))
               (clobber (reg:QI 21))])
    (set (match_operand:ALL2QA 0 "register_operand" "")
         (reg:ALL2QA 24))]
-  ""
+  "SIGNED_FIXED_POINT_MODE_P (<MODE>mode)
+   == (<CODE> == DIV || <CODE> == SS_DIV)"
   {
     avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 26));
   })
 
-;; "*divhq3.call" "*udivuhq3.call"
-;; "*divha3.call" "*udivuha3.call"
-(define_insn_and_split "*<code><mode>3.call_split"
+;; "*divhq3.split" "*udivuhq3.split" "*ssdivhq3.split" "*usdivuhq3.split"
+;; "*divha3.split" "*udivuha3.split" "*ssdivha3.split" "*usdivuha3.split"
+(define_insn_and_split "*<code_stdname><mode>3.split"
   [(set (reg:ALL2QA 24)
-        (usdiv:ALL2QA (reg:ALL2QA 26)
-                      (reg:ALL2QA 22)))
+        (alldiv:ALL2QA (reg:ALL2QA 26)
+                       (reg:ALL2QA 22)))
    (clobber (reg:HI 26))
    (clobber (reg:QI 21))]
-  ""
+  "SIGNED_FIXED_POINT_MODE_P (<MODE>mode)
+   == (<CODE> == DIV || <CODE> == SS_DIV)"
   "#"
   "&& reload_completed"
   [(scratch)]
   { DONE_ADD_CCC })
 
-(define_insn "*<code><mode>3.call"
+;; "*divhq3.call" "*udivuhq3.call" "*ssdivhq3.call" "*usdivuhq3.call"
+;; "*divha3.call" "*udivuha3.call" "*ssdivha3.call" "*usdivuha3.call"
+(define_insn "*<code_stdname><mode>3.call"
   [(set (reg:ALL2QA 24)
-        (usdiv:ALL2QA (reg:ALL2QA 26)
-                      (reg:ALL2QA 22)))
+        (alldiv:ALL2QA (reg:ALL2QA 26)
+                       (reg:ALL2QA 22)))
    (clobber (reg:HI 26))
    (clobber (reg:QI 21))
    (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")])
 
 ;; Note the first parameter gets passed in already offset by 2 bytes
diff --git a/gcc/testsuite/gcc.target/avr/fx16-div-1.c b/gcc/testsuite/gcc.target/avr/fx16-div-1.c
new file mode 100644 (file)
index 0000000..e51b84e
--- /dev/null
@@ -0,0 +1,74 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options { -std=gnu99 -Os -mcall-prologues } } */
+
+#include "fx16.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 (hk)
+MK_TEST (uhk)
+MK_TEST (r)
+MK_TEST (ur)
+
+NI void test_div (float a, float b)
+{
+  test_div_hk (a, b);
+  test_div_uhk (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, +0x1p2, +0x1p3, +0x1p-3,
+    -1.0, -2.0, -0.5, -0x1p2, -0x1p3, -0x1p-3,
+  };
+
+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/fx16-div-2.c b/gcc/testsuite/gcc.target/avr/fx16-div-2.c
new file mode 100644 (file)
index 0000000..fadc7ea
--- /dev/null
@@ -0,0 +1,66 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options { -std=gnu99 -Os -mcall-prologues } } */
+
+#include "fx16.h"
+
+NI void test_hk (uint16_t a, float fb, uint16_t res)
+{
+  hk_t b = (hk_t) fb;
+  if (hkbits (a) / b != hkbits (res))
+    exit (id_hk + 4);
+}
+
+NI void test_uhk (uint16_t a, float fb, uint16_t res)
+{
+  uhk_t b = (hk_t) fb;
+  if (uhkbits (a) / b != uhkbits (res))
+    exit (id_uhk + 4);
+}
+
+NI void test2_uhk (uint16_t a, uint16_t b, uint16_t res)
+{
+  if (uhkbits (a) / uhkbits (b) != uhkbits (res))
+    exit (id_uhk + 5);
+}
+
+NI void test2_hk (uint16_t a, uint16_t b, uint16_t res)
+{
+  if (hkbits (a) / hkbits (b) != hkbits (res))
+    exit (id_hk + 5);
+}
+
+void test2 (void)
+{
+  test_uhk (+0xaabb, +0x11.0p0f, +0x0a0b);
+  test_hk  (-0x77bb, +0x11.0p0f, -0x070b);
+  test_hk  (+0x77bb, -0x11.0p0f, -0x070b);
+  test_hk  (-0x77bb, -0x11.0p0f, +0x070b);
+  test_hk  (-0x7ffe, 2.0f, -0x3fff);
+  test_uhk (+0x7ffe, 2.0f, +0x3fff);
+  test_uhk (+0xa955, 2.0f, +0x54aa);
+  test_hk  (+0x5955, 2.0f, +0x2caa);
+  test_hk  (-0x5955, 2.0f, -0x2caa);
+  test_uhk (+0xffff, 2.0f, +0x7fff);
+  test_hk  (-0x7fff, 2.0f, -0x3fff);
+  test_hk  (+0, 0.0f, SMAX);
+  test_hk  (+1, 0.0f, SMAX);
+  test_hk  (-1, 0.0f, SMIN);
+  test_uhk (+0, 0.0f, UMAX);
+  test_uhk (+1, 0.0f, UMAX);
+  test_hk  (SMAX - 100, +0x0.f8p0f, SMAX);
+  test_hk  (SMIN + 100, +0x0.f8p0f, SMIN);
+  test_hk  (SMAX - 100, -0x0.f8p0f, SMIN);
+  test_hk  (SMIN + 100, -0x0.f8p0f, SMAX);
+  test_uhk (UMAX - 100, +0x0.f8p0f, UMAX);
+  test_uhk (UMAX - 100, +0x0.f8p0f, UMAX);
+
+  test2_uhk (X80 + 1, X80,  uhk_1);
+  test2_uhk (X80, X80 + 1,  uhk_1 - 1);
+  test2_uhk (UMAX - 1, UMAX, uhk_1 - 1);
+}
+
+int main (void)
+{
+  test2 ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/avr/fx16-div-3.c b/gcc/testsuite/gcc.target/avr/fx16-div-3.c
new file mode 100644 (file)
index 0000000..9c9ffc9
--- /dev/null
@@ -0,0 +1,64 @@
+/* { dg-do run { target { ! avr_tiny } } } */
+/* { dg-additional-options { -std=gnu99 -Os -mcall-prologues } } */
+
+#include "fx16.h"
+
+#define MK_TEST(fx)                                            \
+  NI void test_div_##fx (uint16_t a, float fb, uint16_t r)     \
+  {                                                            \
+    if (fb < fmax_##fx)                                                \
+      {                                                                \
+       fx##_t b = (fx##_t) fb;                                 \
+       fx##_t ab = fx##bits (a) / b;                           \
+       if (ab != fx##bits (r))                                 \
+         exit (id_##fx + 6);                                   \
+      }                                                                \
+  }
+
+MK_TEST (hk)
+MK_TEST (uhk)
+MK_TEST (r)
+MK_TEST (ur)
+
+NI void test1_div (uint16_t a, float fb, uint16_t r)
+{
+  test_div_uhk (a, fb, r);
+  test_div_ur (a, fb, r);
+  if ((a & X80) == 0)
+    {
+      test_div_hk (a, fb, r);
+      test_div_r (a, fb, r);
+    }
+}
+
+NI void test2_div (uint16_t a, float fb, uint16_t r)
+{
+  test_div_uhk (a, fb, r);
+  test_div_ur (a, fb, r);
+  if ((r & X80) == 0)
+    {
+      test_div_hk (a, fb, r);
+      test_div_r (a, fb, r);
+    }
+  else
+    {
+      test_div_hk (a, fb, SMAX);
+      test_div_r (a, fb, SMAX);
+    }
+}
+
+NI void test3 (void)
+{
+  for (uint16_t a = (uint16_t) 0xff01; 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/fx16.h b/gcc/testsuite/gcc.target/avr/fx16.h
new file mode 100644 (file)
index 0000000..a0c1a24
--- /dev/null
@@ -0,0 +1,50 @@
+#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 short accum hk_t;
+typedef unsigned short accum uhk_t;
+typedef fract r_t;
+typedef unsigned fract ur_t;
+
+typedef short sat accum sat_hk_t;
+typedef short sat unsigned accum sat_uhk_t;
+typedef sat fract sat_r_t;
+typedef sat unsigned fract sat_ur_t;
+
+// Values are in fmin <= x < fmax.
+#define fmax_hk 0x1.0p8f
+#define fmin_hk (-fmax_hk)
+#define fmax_uhk fmax_hk
+#define fmin_uhk 0.0f
+#define fmax_r  0x1.0p0f
+#define fmin_r  (-fmax_r)
+#define fmax_ur fmax_r
+#define fmin_ur 0.0f
+
+#define UMAX 0xffff
+#define SMAX 0x7fff
+#define SMIN 0x8000
+#define X80  0x8000
+
+// Values are in min <= x <= max.
+#define max_hk hkbits (SMAX)
+#define min_hk hkbits (SMIN)
+#define max_uhk uhkbits (UMAX)
+#define min_uhk uhkbits (0)
+#define max_r   rbits (SMAX)
+#define min_r   rbits (SMIN)
+#define max_ur  urbits (UMAX)
+#define min_ur  urbits (0)
+
+#define hk_1   (1u << __HA_FBIT__)
+#define uhk_1  (1u << __UHA_FBIT__)
+
+#define id_hk   10
+#define id_uhk  20
+#define id_r    30
+#define id_ur   40
index a380db1e708b5a20904e733ec6001fa9774d67f2..d7a297064b4a097a2d1babd306c375809fa84f31 100644 (file)
@@ -1568,118 +1568,171 @@ ENDF __divqq_helper
 /*******************************************************
     Fractional Division 16 / 16
 *******************************************************/
-#define r_divdL 26     /* dividend Low */
-#define r_divdH 27     /* dividend Hig */
-#define r_quoL  24     /* quotient Low */
-#define r_quoH  25     /* quotient High */
-#define r_divL  22     /* divisor */
-#define r_divH  23     /* divisor */
-#define r_cnt   21
+;;; Argument 1: Dividend and remainder
+#define A0 26
+#define A1 A0+1
+
+;;; Argument 2: Divisor
+#define B0 22
+#define B1 B0+1
+
+;;; Return value: Quotient
+#define Q0 24
+#define Q1 Q0+1
+
+#define Cnt 21
+#define Sign __tmp_reg__
 
 #if defined (L_divhq3)
-DEFUN   __divhq3
-    mov     __tmp_reg__, r_divdH
-    eor     __tmp_reg__, r_divH
-    sbrs    r_divH, 7
-    rjmp    1f
-    NEG2    r_divL
+;;;  (set (reg:HQ 24)
+;;;       (ss_div:HQ (reg:HQ 26)
+;;;                  (reg:HQ 22)))
+;;;  (clobber (reg:HI 26))
+;;;  (clobber (reg:QI 21))
+;;; Rounds towards zero.  Overflow saturates.
+DEFUN __divhq3
+ENTRY __ssdivhq3
+    mov     Sign, A1
+    tst     B1
+    brpl 1f
+    com     Sign
+    NEG2    B0
 1:
-    sbrs    r_divdH, 7
-    rjmp    2f
-    NEG2    r_divdL
+    tst     A1
+    brpl 2f
+    NEG2    A0
 2:
-    cp      r_divdL, r_divL
-    cpc     r_divdH, r_divH
-    breq    __divhq3_minus1  ; if equal return -1
-    XCALL   __udivuhq3
-    lsr     r_quoH
-    ror     r_quoL
-    brpl    9f
-    ;; negate result if needed
-    NEG2    r_quoL
-9:
-    ret
-__divhq3_minus1:
-    ldi     r_quoH, 0x80
-    clr     r_quoL
-    ret
+    lsr     A1                  ; Adjust for FBIT = 15.
+    ror     A0                  ; Pass LSB in C.
+    clr     Q1
+    XCALL   __udivuhq3.2
+    XJMP    __divQ16_tail
 ENDF __divhq3
 #endif  /* defined (L_divhq3) */
 
+#if defined (L_divQ16_tail)
+DEFUN __divQ16_tail
+    ;; In the negative result case, Q = 0x80.. is no overflow,
+    ;; but treating it as such keeps the value unchanged.
+    brmi    .Lsaturate          ; N = sign (Q)
+    ;; Negate result as needed.
+    sbrs    Sign, 7
+    ret
+    NEG2    Q0
+    ret
+.Lsaturate:
+    ;; Sign.7 = 0 -> 0x7f..
+    ;; Sign.7 = 1 -> 0x80..
+#ifndef __AVR_TINY__
+    ldi     Q0, lo8(0x7fff)
+    ldi     Q1, hi8(0x7fff)
+    sbrc    Sign, 7
+    adiw    Q0, 1
+#else
+    cpi     Sign, 0x80
+    sbc     Q0, Q0
+    sbc     Q1, Q1
+    subi    Q1, 0x80
+#endif
+    ret
+ENDF __divQ16_tail
+#endif /* L_divQ16_tail */
+
 #if defined (L_udivuhq3)
-DEFUN   __udivuhq3
-    sub     r_quoH,r_quoH   ; clear quotient and carry
-    ;; FALLTHRU
+;;;  (set (reg:UHQ 24)
+;;;       (us_div:UHQ (reg:UHQ 26)
+;;;                   (reg:UHQ 22)))
+;;;  (clobber (reg:HI 26))
+;;;  (clobber (reg:QI 21))
+;;; Rounds towards zero.  Overflow saturates.
+DEFUN __udivuhq3
+ENTRY __usdivuhq3
+    sub     Q1, Q1      ; CLC
+ENTRY __udivuhq3.2
+    clr     Q0          ; Clear quotient
+    ldi     Cnt, 16     ; Init loop counter.
+    ;; C = 0 (unsigned).
+    ;; C = LSB from the caller (signed).
+.Loop:
+    rol     A0          ; Shift one more dividend bit into the remainder.
+    rol     A1
+    brcs .Lsub          ; Divisor always fits in remainder?
+    cp      A0, B0      ; Remainder >= B?
+    cpc     A1, B1
+    brcc .Lsub
+    rol     Q0          ; No: Shift quotient with C = 1 (0 in result).
+    rjmp .Lcont
+.Lsub:
+    sub     A0, B0      ; Yes: Restore remainder by subtracting B...
+    sbc     A1, B1
+    lsl     Q0          ; ...and shift quotient with C = 0 (1 in result).
+.Lcont:
+    rol     Q1          ; Shift quotient.
+    dec     Cnt         ; Decrement loop counter.
+    brne .Loop
+    com     Q0          ; Complement result because C was
+    com     Q1          ; complemented in the loop.
+    ret                 ; N = sign (Q).
 ENDF __udivuhq3
-
-DEFUN   __udivuha3_common
-    clr     r_quoL          ; clear quotient
-    ldi     r_cnt,16        ; init loop counter
-__udivuhq3_loop:
-    rol     r_divdL         ; shift dividend (with CARRY)
-    rol     r_divdH
-    brcs    __udivuhq3_ep   ; dividend overflow
-    cp      r_divdL,r_divL  ; compare dividend & divisor
-    cpc     r_divdH,r_divH
-    brcc    __udivuhq3_ep   ; dividend >= divisor
-    rol     r_quoL          ; shift quotient (with CARRY)
-    rjmp    __udivuhq3_cont
-__udivuhq3_ep:
-    sub     r_divdL,r_divL  ; restore dividend
-    sbc     r_divdH,r_divH
-    lsl     r_quoL          ; shift quotient (without CARRY)
-__udivuhq3_cont:
-    rol     r_quoH          ; shift quotient
-    dec     r_cnt           ; decrement loop counter
-    brne    __udivuhq3_loop
-    com     r_quoL          ; complement result
-    com     r_quoH          ; because C flag was complemented in loop
-    ret
-ENDF __udivuha3_common
 #endif  /* defined (L_udivuhq3) */
 
 /*******************************************************
     Fixed Division 8.8 / 8.8
 *******************************************************/
 #if defined (L_divha3)
-DEFUN   __divha3
-    mov     __tmp_reg__, r_divdH
-    eor     __tmp_reg__, r_divH
-    sbrs    r_divH, 7
-    rjmp    1f
-    NEG2    r_divL
+;;;  (set (reg:HA 24)
+;;;       (ss_div:HA (reg:HA 26)
+;;;                  (reg:HA 22)))
+;;;  (clobber (reg:HI 26))
+;;;  (clobber (reg:QI 21))
+;;; Rounds towards zero.  Overflow saturates.
+DEFUN __divha3
+ENTRY __ssdivha3
+    mov     Sign, A1
+    tst     B1
+    brpl 1f
+    com     Sign
+    NEG2    B0
 1:
-    sbrs    r_divdH, 7
-    rjmp    2f
-    NEG2    r_divdL
+    tst     A1
+    brpl 2f
+    NEG2    A0
 2:
-    XCALL   __udivuha3
-    lsr     r_quoH  ; adjust to 7 fractional bits
-    ror     r_quoL
-    sbrs    __tmp_reg__, 7  ; negate result if needed
-    ret
-    NEG2    r_quoL
-    ret
+    lsr     A1              ; Adjust to FBIT = 7.
+    ror     A0              ; Pass LSB in C.
+    XCALL   __udivuha3.2    ; N = sign (Q)
+    XJMP    __divQ16_tail
 ENDF __divha3
 #endif  /* defined (L_divha3) */
 
 #if defined (L_udivuha3)
-DEFUN   __udivuha3
-    mov     r_quoH, r_divdL
-    mov     r_divdL, r_divdH
-    clr     r_divdH
-    lsl     r_quoH     ; shift quotient into carry
-    XJMP    __udivuha3_common ; same as fractional after rearrange
+;;;  (set (reg:UHA 24)
+;;;       (us_div:UHA (reg:UHA 26)
+;;;                   (reg:UHA 22)))
+;;;  (clobber (reg:HI 26))
+;;;  (clobber (reg:QI 21))
+;;; Rounds towards zero.  Overflow saturates.
+DEFUN __udivuha3
+ENTRY __usdivuha3
+    clc
+ENTRY __udivuha3.2
+    mov     Q1, A0          ; Put dividend in A0:Q1.
+    mov     A0, A1
+    clr     A1
+    rol     Q1              ; Shift quotient into carry.
+    XJMP    __udivuhq3.2    ; Same as fractional after rearrange.
 ENDF __udivuha3
 #endif  /* defined (L_udivuha3) */
 
-#undef  r_divdL
-#undef  r_divdH
-#undef  r_quoL
-#undef  r_quoH
-#undef  r_divL
-#undef  r_divH
-#undef  r_cnt
+#undef A0
+#undef A1
+#undef Q0
+#undef Q1
+#undef B0
+#undef B1
+#undef Cnt
+#undef Sign
+
 
 /*********************************************************
     Fixed 16.16 and s16.15 saturated [U]SAmode Divisions
index da4be9fb55dc64f06f12bcc2e9c09c2ef082168a..56e26870c0df2c30652cb9bf4680f5b12f2a3228 100644 (file)
@@ -42,7 +42,7 @@ LIB1ASMFUNCS = \
        _mulha3 _muluha3 _muluha3_round \
        _usmuluha3 _ssmulha3 \
        _divqq3 _udivuqq3 _divqq_helper \
-       _divhq3 _udivuhq3 \
+       _divhq3 _udivuhq3 _divQ16_tail \
        _divha3 _udivuha3 \
        _divsa3 _udivusa3 \
        _ssneg_2 \