avr.h (INIT_TARGET_OPTABS): Remove most of it, was the same as the default library...
authorMarek Michalkiewicz <marekm@linux.org.pl>
Sat, 20 Jan 2001 16:49:01 +0000 (17:49 +0100)
committerMarek Michalkiewicz <marekm@gcc.gnu.org>
Sat, 20 Jan 2001 16:49:01 +0000 (16:49 +0000)
* config/avr/avr.h (INIT_TARGET_OPTABS): Remove most of it, was
the same as the default library function names.
* config/avr/avr.md: Document special characters after '%'.
(mulqi3, mulhi3, mulsi3): Call libgcc.S functions ourselves,
knowing which of the call-used registers are really clobbered.
(divmodqi4, udivmodqi4, divmodhi4, udivmodhi4, divmodsi4, udivmodsi4):
New.  Both quotient and remainder from one libgcc.S call.
* config/avr/libgcc.S: Optimize mul/divmod for the new insns above,
clobber as few registers as possible.
* config/avr/t-avr (LIB1ASMFUNCS): Adjust for the above changes.

From-SVN: r39155

gcc/ChangeLog
gcc/config/avr/avr.h
gcc/config/avr/avr.md
gcc/config/avr/libgcc.S
gcc/config/avr/t-avr

index 918c56295bbfaeab91894dddf61b601ecea7fff5..cded5b23d6aec8e41746c20ab1236dc0846977a7 100644 (file)
@@ -1,3 +1,16 @@
+2001-01-20  Marek Michalkiewicz  <marekm@linux.org.pl>
+
+       * config/avr/avr.h (INIT_TARGET_OPTABS): Remove most of it, was
+       the same as the default library function names.
+       * config/avr/avr.md: Document special characters after '%'.
+       (mulqi3, mulhi3, mulsi3): Call libgcc.S functions ourselves,
+       knowing which of the call-used registers are really clobbered.
+       (divmodqi4, udivmodqi4, divmodhi4, udivmodhi4, divmodsi4, udivmodsi4):
+       New.  Both quotient and remainder from one libgcc.S call.
+       * config/avr/libgcc.S: Optimize mul/divmod for the new insns above,
+       clobber as few registers as possible.
+       * config/avr/t-avr (LIB1ASMFUNCS): Adjust for the above changes.
+
 2001-01-20  Neil Booth  <neil@daikokuya.demon.co.uk>
 
         * cppmacro.c (funlike_invocation_p): Don't move back up to the
index 468860427c5f21f9c3917e2c11737f3ecf6de863..773f8b3071f20d932588c9399125ed0277b24308 100644 (file)
@@ -3228,50 +3228,6 @@ valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
 
 #define INIT_TARGET_OPTABS                             \
 {                                                      \
-  smul_optab->handlers[(int) QImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "__mulqi3");         \
-                                                       \
-  sdiv_optab->handlers[(int) QImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "__divqi3");         \
-                                                       \
-  smod_optab->handlers[(int) QImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "__modqi3");         \
-                                                       \
-  udiv_optab->handlers[(int) QImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "__udivqi3");                \
-                                                       \
-  umod_optab->handlers[(int) QImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "__umodqi3");                \
-                                                       \
-  smul_optab->handlers[(int) HImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "__mulhi3");         \
-                                                       \
-  sdiv_optab->handlers[(int) HImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "__divhi3");         \
-                                                       \
-  smod_optab->handlers[(int) HImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "__modhi3");         \
-                                                       \
-  udiv_optab->handlers[(int) HImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "__udivhi3");                \
-                                                       \
-  umod_optab->handlers[(int) HImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "__umodhi3");                \
-                                                       \
-  smul_optab->handlers[(int) SImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "__mulsi3");         \
-                                                       \
-  sdiv_optab->handlers[(int) SImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "__divsi3");         \
-                                                       \
-  smod_optab->handlers[(int) SImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "__modsi3");         \
-                                                       \
-  udiv_optab->handlers[(int) SImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "__udivsi3");                \
-                                                       \
-  umod_optab->handlers[(int) SImode].libfunc           \
-    = gen_rtx (SYMBOL_REF, Pmode, "__umodsi3");                \
   avr_init_once ();                                    \
 }
 
index 858b39f4ce63f720edcf12978a085ae8648e52fa..663585669cfadae22bc46ccdf13c0eca8989683b 100644 (file)
 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
 ;; Boston, MA 02111-1307, USA.
 
+;; Special characters after '%':
+;;  A  No effect (add 0).
+;;  B  Add 1 to REG number, MEM address or CONST_INT.
+;;  C  Add 2.
+;;  D  Add 3.
+;;  j  Branch condition.
+;;  k  Reverse branch condition.
+;;  o  Displacement for (mem (plus (reg) (const_int))) operands.
+;;  ~  Output 'r' if not AVR_MEGA.
+
 ;; UNSPEC usage:
 ;;  0  Length of a string, see "strlenhi".
 ;;  1  Read from a word address in program memory, see "casesi".
 ;******************************************************************************
 ; mul
 
-(define_insn "mulqi3"
+(define_expand "mulqi3"
+  [(set (match_operand:QI 0 "register_operand" "")
+       (mult:QI (match_operand:QI 1 "register_operand" "")
+                (match_operand:QI 2 "register_operand" "")))]
+  ""
+  "{
+  if (!AVR_ENHANCED)
+    {
+      emit_insn (gen_mulqi3_call (operands[0], operands[1], operands[2]));
+      DONE;
+    }
+}")
+
+(define_insn "*mulqi3_enh"
   [(set (match_operand:QI 0 "register_operand" "=r")
        (mult:QI (match_operand:QI 1 "register_operand" "r")
                 (match_operand:QI 2 "register_operand" "r")))]
   [(set_attr "length" "3")
    (set_attr "cc" "clobber")])
 
+(define_expand "mulqi3_call"
+  [(set (reg:QI 24) (match_operand:QI 1 "register_operand" ""))
+   (set (reg:QI 22) (match_operand:QI 2 "register_operand" ""))
+   (parallel [(set (reg:QI 24) (mult:QI (reg:QI 24) (reg:QI 22)))
+             (clobber (reg:QI 22))])
+   (set (match_operand:QI 0 "register_operand" "") (reg:QI 24))]
+  ""
+  "")
+
+(define_insn "*mulqi3_call"
+  [(set (reg:QI 24) (mult:QI (reg:QI 24) (reg:QI 22)))
+   (clobber (reg:QI 22))]
+  "!AVR_ENHANCED"
+  "%~call __mulqi3"
+  [(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no")
+                                     (const_int 1)
+                                     (const_int 2)))
+   (set_attr "cc" "clobber")])
+
 (define_insn "mulqihi3"
   [(set (match_operand:HI 0 "register_operand" "=r")
        (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "d"))
   [(set_attr "length" "3")
    (set_attr "cc" "clobber")])
 
-(define_insn "mulhi3"
+(define_expand "mulhi3"
+  [(set (match_operand:HI 0 "register_operand" "")
+       (mult:HI (match_operand:HI 1 "register_operand" "")
+                (match_operand:HI 2 "register_operand" "")))]
+  ""
+  "
+{
+  if (!AVR_ENHANCED)
+    {
+      emit_insn (gen_mulhi3_call (operands[0], operands[1], operands[2]));
+      DONE;
+    }
+}")
+
+(define_insn "*mulhi3_enh"
   [(set (match_operand:HI 0 "register_operand" "=&r")
        (mult:HI (match_operand:HI 1 "register_operand" "r")
                 (match_operand:HI 2 "register_operand" "r")))]
   [(set_attr "length" "7")
    (set_attr "cc" "clobber")])
 
+(define_expand "mulhi3_call"
+  [(set (reg:HI 24) (match_operand:HI 1 "register_operand" ""))
+   (set (reg:HI 22) (match_operand:HI 2 "register_operand" ""))
+   (parallel [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22)))
+             (clobber (reg:HI 22))
+             (clobber (reg:QI 21))])
+   (set (match_operand:HI 0 "register_operand" "") (reg:HI 24))]
+  ""
+  "")
+
+(define_insn "*mulhi3_call"
+  [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22)))
+   (clobber (reg:HI 22))
+   (clobber (reg:QI 21))]
+  "!AVR_ENHANCED"
+  "%~call __mulhi3"
+  [(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no")
+                                     (const_int 1)
+                                     (const_int 2)))
+   (set_attr "cc" "clobber")])
+
+;; Operand 2 (reg:SI 18) not clobbered on the enhanced core.
+;; All call-used registers clobbered otherwise - normal library call.
+(define_expand "mulsi3"
+  [(set (reg:SI 22) (match_operand:SI 1 "register_operand" ""))
+   (set (reg:SI 18) (match_operand:SI 2 "register_operand" ""))
+   (parallel [(set (reg:SI 22) (mult:SI (reg:SI 22) (reg:SI 18)))
+             (clobber (reg:HI 26))
+             (clobber (reg:HI 30))])
+   (set (match_operand:SI 0 "register_operand" "") (reg:SI 22))]
+  "AVR_ENHANCED"
+  "")
+
+(define_insn "*mulsi3_call"
+  [(set (reg:SI 22) (mult:SI (reg:SI 22) (reg:SI 18)))
+   (clobber (reg:HI 26))
+   (clobber (reg:HI 30))]
+  "AVR_ENHANCED"
+  "%~call __mulsi3"
+  [(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no")
+                                     (const_int 1)
+                                     (const_int 2)))
+   (set_attr "cc" "clobber")])
+
+; / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / %
+; divmod
+
+;; Generate libgcc.S calls ourselves, because:
+;;  - we know exactly which registers are clobbered (for QI and HI
+;;    modes, some of the call-used registers are preserved)
+;;  - we get both the quotient and the remainder at no extra cost
+
+(define_expand "divmodqi4"
+  [(set (reg:QI 24) (match_operand:QI 1 "register_operand" ""))
+   (set (reg:QI 22) (match_operand:QI 2 "register_operand" ""))
+   (parallel [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
+             (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
+             (clobber (reg:QI 22))
+             (clobber (reg:QI 23))])
+   (set (match_operand:QI 0 "register_operand" "") (reg:QI 24))
+   (set (match_operand:QI 3 "register_operand" "") (reg:QI 25))]
+  ""
+  "")
+
+(define_insn "*divmodqi4_call"
+  [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
+   (set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
+   (clobber (reg:QI 22))
+   (clobber (reg:QI 23))]
+  ""
+  "%~call __divmodqi4"
+  [(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no")
+                                     (const_int 1)
+                                     (const_int 2)))
+   (set_attr "cc" "clobber")])
+
+(define_expand "udivmodqi4"
+  [(set (reg:QI 24) (match_operand:QI 1 "register_operand" ""))
+   (set (reg:QI 22) (match_operand:QI 2 "register_operand" ""))
+   (parallel [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22)))
+             (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22)))
+             (clobber (reg:QI 23))])
+   (set (match_operand:QI 0 "register_operand" "") (reg:QI 24))
+   (set (match_operand:QI 3 "register_operand" "") (reg:QI 25))]
+  ""
+  "")
+
+(define_insn "*udivmodqi4_call"
+  [(set (reg:QI 24) (udiv:QI (reg:QI 24) (reg:QI 22)))
+   (set (reg:QI 25) (umod:QI (reg:QI 24) (reg:QI 22)))
+   (clobber (reg:QI 23))]
+  ""
+  "%~call __udivmodqi4"
+  [(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no")
+                                     (const_int 1)
+                                     (const_int 2)))
+   (set_attr "cc" "clobber")])
+
+(define_expand "divmodhi4"
+  [(set (reg:HI 24) (match_operand:HI 1 "register_operand" ""))
+   (set (reg:HI 22) (match_operand:HI 2 "register_operand" ""))
+   (parallel [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
+             (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22)))
+             (clobber (reg:HI 26))
+             (clobber (reg:QI 21))])
+   (set (match_operand:HI 0 "register_operand" "") (reg:HI 22))
+   (set (match_operand:HI 3 "register_operand" "") (reg:HI 24))]
+  ""
+  "")
+
+(define_insn "*divmodhi4_call"
+  [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
+   (set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22)))
+   (clobber (reg:HI 26))
+   (clobber (reg:QI 21))]
+  ""
+  "%~call __divmodhi4"
+  [(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no")
+                                     (const_int 1)
+                                     (const_int 2)))
+   (set_attr "cc" "clobber")])
+
+(define_expand "udivmodhi4"
+  [(set (reg:HI 24) (match_operand:HI 1 "register_operand" ""))
+   (set (reg:HI 22) (match_operand:HI 2 "register_operand" ""))
+   (parallel [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22)))
+             (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22)))
+             (clobber (reg:HI 26))
+             (clobber (reg:QI 21))])
+   (set (match_operand:HI 0 "register_operand" "") (reg:HI 22))
+   (set (match_operand:HI 3 "register_operand" "") (reg:HI 24))]
+  ""
+  "")
+
+(define_insn "*udivmodhi4_call"
+  [(set (reg:HI 22) (udiv:HI (reg:HI 24) (reg:HI 22)))
+   (set (reg:HI 24) (umod:HI (reg:HI 24) (reg:HI 22)))
+   (clobber (reg:HI 26))
+   (clobber (reg:QI 21))]
+  ""
+  "%~call __udivmodhi4"
+  [(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no")
+                                     (const_int 1)
+                                     (const_int 2)))
+   (set_attr "cc" "clobber")])
+
+(define_expand "divmodsi4"
+  [(set (reg:SI 22) (match_operand:SI 1 "register_operand" ""))
+   (set (reg:SI 18) (match_operand:SI 2 "register_operand" ""))
+   (parallel [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18)))
+             (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18)))
+             (clobber (reg:HI 26))
+             (clobber (reg:HI 30))])
+   (set (match_operand:SI 0 "register_operand" "") (reg:SI 18))
+   (set (match_operand:SI 3 "register_operand" "") (reg:SI 22))]
+  ""
+  "")
+
+(define_insn "*divmodsi4_call"
+  [(set (reg:SI 18) (div:SI (reg:SI 22) (reg:SI 18)))
+   (set (reg:SI 22) (mod:SI (reg:SI 22) (reg:SI 18)))
+   (clobber (reg:HI 26))
+   (clobber (reg:HI 30))]
+  ""
+  "%~call __divmodsi4"
+  [(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no")
+                                     (const_int 1)
+                                     (const_int 2)))
+   (set_attr "cc" "clobber")])
+
+(define_expand "udivmodsi4"
+  [(set (reg:SI 22) (match_operand:SI 1 "register_operand" ""))
+   (set (reg:SI 18) (match_operand:SI 2 "register_operand" ""))
+   (parallel [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18)))
+             (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18)))
+             (clobber (reg:HI 26))
+             (clobber (reg:HI 30))])
+   (set (match_operand:SI 0 "register_operand" "") (reg:SI 18))
+   (set (match_operand:SI 3 "register_operand" "") (reg:SI 22))]
+  ""
+  "")
+
+(define_insn "*udivmodsi4_call"
+  [(set (reg:SI 18) (udiv:SI (reg:SI 22) (reg:SI 18)))
+   (set (reg:SI 22) (umod:SI (reg:SI 22) (reg:SI 18)))
+   (clobber (reg:HI 26))
+   (clobber (reg:HI 30))]
+  ""
+  "%~call __udivmodsi4"
+  [(set (attr "length") (if_then_else (eq_attr "mcu_mega" "no")
+                                     (const_int 1)
+                                     (const_int 2)))
+   (set_attr "cc" "clobber")])
+
 ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
 ; and
 
                AS2 (mov, r31, %B0) CR_TAB
                \"icall\");
     }
-  else if (!AVR_MEGA)
-     return AS1(rcall,%c0);   
-  return AS1(call,%c0);
+  return AS1(%~call,%c0);
 }"
   [(set_attr "cc" "clobber,clobber,clobber")
    (set_attr_alternative "length"
                AS2 (mov, r31, %B1) CR_TAB
                \"icall\");
     }
-  else if (!AVR_MEGA)
-     return AS1(rcall,%c1);   
-  return AS1(call,%c1);
+  return AS1(%~call,%c1);
 }"
   [(set_attr "cc" "clobber,clobber,clobber")
    (set_attr_alternative "length"
index cd2ab78ca98a50336f573b346b77b44a1d73d73d..aa96a520239618564aad612a1b188264fd384667 100644 (file)
@@ -32,8 +32,29 @@ Boston, MA 02111-1307, USA.  */
 #define __SP_H__ 0x3e
 #define __SP_L__ 0x3d
 
+/* 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.  */
+
        .section .text.libgcc, "ax", @progbits
 
+       .macro  mov_l  r_dest, r_src
+#if defined (__AVR_ENHANCED__)
+       movw    \r_dest, \r_src
+#else
+       mov     \r_dest, \r_src
+#endif
+       .endm
+
+       .macro  mov_h  r_dest, r_src
+#if defined (__AVR_ENHANCED__)
+       ; empty
+#else
+       mov     \r_dest, \r_src
+#endif
+       .endm
+
 /* Note: mulqi3, mulhi3 are open-coded on the enhanced core.  */
 #if !defined (__AVR_ENHANCED__)
 /*******************************************************
@@ -67,6 +88,29 @@ __mulqi3_exit:
 .endfunc
 #endif         /* defined (L_mulqi3) */
 
+#if defined (L_mulqihi3)
+       .global __mulqihi3
+       .func   __mulqihi3
+__mulqihi3:
+       clr     r25
+       sbrc    r24, 7
+       dec     r25
+       clr     r23
+       sbrc    r22, 7
+       dec     r22
+       rjmp    __mulhi3
+       .endfunc
+#endif /* defined (L_mulqihi3) */
+
+#if defined (L_umulqihi3)
+       .global __umulqihi3
+       .func   __umulqihi3
+__umulqihi3:
+       clr     r25
+       clr     r23
+       rjmp    __mulhi3
+       .endfunc
+#endif /* defined (L_umulqihi3) */
 
 /*******************************************************
                Multiplication  16 x 16
@@ -76,7 +120,7 @@ __mulqi3_exit:
 #define        r_arg1H r25             /* multiplier High */
 #define        r_arg2L r22             /* multiplicand Low */
 #define        r_arg2H r23             /* multiplicand High */
-#define r_resL r20             /* result Low */
+#define r_resL __tmp_reg__     /* result Low */
 #define r_resH  r21            /* result High */
 
        .global __mulhi3
@@ -116,6 +160,38 @@ __mulhi3_exit:
 #endif /* defined (L_mulhi3) */
 #endif /* !defined (__AVR_ENHANCED__) */
 
+#if defined (L_mulhisi3)
+       .global __mulhisi3
+       .func   __mulhisi3
+__mulhisi3:
+       mov_l   r18, r24
+       mov_h   r19, r25
+       clr     r24
+       sbrc    r23, 7
+       dec     r24
+       mov     r25, r24
+       clr     r20
+       sbrc    r19, 7
+       dec     r20
+       mov     r21, r20
+       rjmp    __mulsi3
+       .endfunc
+#endif /* defined (L_mulhisi3) */
+
+#if defined (L_umulhisi3)
+       .global __umulhisi3
+       .func   __umulhisi3
+__umulhisi3:
+       mov_l   r18, r24
+       mov_h   r19, r25
+       clr     r24
+       clr     r25
+       clr     r20
+       clr     r21
+       rjmp    __mulsi3
+       .endfunc
+#endif /* defined (L_umulhisi3) */
+
 #if defined (L_mulsi3)
 /*******************************************************
                Multiplication  32 x 32
@@ -227,81 +303,54 @@ __mulsi3_exit:
 /*******************************************************
        Division 8 / 8 => (result + remainder)
 *******************************************************/
-#define        r_rem   r26     /* remainder */
-#define        r_arg1  r24     /* dividend */
+#define        r_rem   r25     /* remainder */
+#define        r_arg1  r24     /* dividend, quotient */
 #define        r_arg2  r22     /* divisor */
-#define        r_cnt   r27     /* loop count */
-
-#if defined (L_umodqi3)
-
-       .global __umodqi3
-       .func   __umodqi3
-__umodqi3:
-       clt
-       rcall   __udivqi3
-       mov     r24,r_rem
-       ret
-.endfunc
-#endif /* defined (L_umodqi3) */
-       
-#if defined (L_udivqi3)
-
-       .global __udivqi3
-       .func   __udivqi3
-__udivqi3:
-       clr     __tmp_reg__
-       rjmp    __divqi_raw
-.endfunc
-#endif /* defined (L_udivqi3) */
+#define        r_cnt   r23     /* loop count */
 
-#if defined (L_modqi3)
-       
-       .global __modqi3
-       .func   __modqi3
-__modqi3:
-       rcall   __divqi3
-       mov     r24,r_rem
+#if defined (L_udivmodqi4)
+       .global __udivmodqi4
+       .func   __udivmodqi4
+__udivmodqi4:
+       sub     r_rem,r_rem     ; clear remainder and carry
+       ldi     r_cnt,9         ; init loop counter
+       rjmp    __udivmodqi4_ep ; jump to entry point
+__udivmodqi4_loop:
+       rol     r_rem           ; shift dividend into remainder
+       cp      r_rem,r_arg2    ; compare remainder & divisor
+       brcs    __udivmodqi4_ep ; remainder <= divisor
+       sub     r_rem,r_arg2    ; restore remainder
+__udivmodqi4_ep:
+       rol     r_arg1          ; shift dividend (with CARRY)
+       dec     r_cnt           ; decrement loop counter
+       brne    __udivmodqi4_loop
+       com     r_arg1          ; complement result 
+                               ; because C flag was complemented in loop
        ret
-.endfunc
-#endif /* defined (L_modqi3) */
-
-#if defined (L_divqi3)
-
-       .global __divqi3
-       .func   __divqi3
-__divqi3:
-        bst     r_arg1,7       ; store sign of divident
+       .endfunc
+#endif /* defined (L_udivmodqi4) */
+
+#if defined (L_divmodqi4)
+       .global __divmodqi4
+       .func   __divmodqi4
+__divmodqi4:
+        bst     r_arg1,7       ; store sign of dividend
         mov     __tmp_reg__,r_arg1
         eor     __tmp_reg__,r_arg2; r0.7 is sign of result
         sbrc   r_arg1,7
-        neg     r_arg1         ; divident negative : negate
+       neg     r_arg1          ; dividend negative : negate
         sbrc   r_arg2,7
-        neg     r_arg2         ; divisor negative : negate
-       .global __divqi_raw
-__divqi_raw:   
-       sub     r_rem,r_rem     ; clear remainder and carry
-       ldi     r_cnt,9         ; init loop counter
-       rjmp    __divqi3_ep     ; jump to entry point
-__divqi3_loop:
-        rol    r_rem           ; shift dividend into remainder
-        cp     r_rem,r_arg2    ; compare remainder & divisor
-        brcs   __divqi3_ep     ; remainder <= divisor
-        sub    r_rem,r_arg2    ; restore remainder
-__divqi3_ep:
-        rol    r_arg1          ; shift dividend (with CARRY)
-        dec    r_cnt           ; decrement loop counter
-        brne   __divqi3_loop   ; loop
-       com     r_arg1          ; complement result 
-                               ; because C flag was complemented in loop
-       brtc    __divqi3_1
+       neg     r_arg2          ; divisor negative : negate
+       rcall   __udivmodqi4    ; do the unsigned div/mod
+       brtc    __divmodqi4_1
        neg     r_rem           ; correct remainder sign
-__divqi3_1:
+__divmodqi4_1:
        sbrc    __tmp_reg__,7
        neg     r_arg1          ; correct result sign
-__divqi3_exit:
-       ret                     ; result already in r24 (r_arg1)
-.endfunc
-#endif /* defined (L_divqi3) */
+__divmodqi4_exit:
+       ret
+       .endfunc
+#endif /* defined (L_divmodqi4) */
 
 #undef r_rem
 #undef r_arg1
@@ -314,113 +363,80 @@ __divqi3_exit:
 *******************************************************/
 #define        r_remL  r26     /* remainder Low */
 #define        r_remH  r27     /* remainder High */
-       
+
+/* return: remainder */
 #define        r_arg1L r24     /* dividend Low */
 #define        r_arg1H r25     /* dividend High */
-       
+
+/* return: quotient */
 #define        r_arg2L r22     /* divisor Low */
 #define        r_arg2H r23     /* divisor High */
        
 #define        r_cnt   r21     /* loop count */
-#if defined (L_umodhi3)
-       .global __umodhi3
-       .func   __umodhi3
-__umodhi3:
-       clt
-       rcall   __udivhi3
-       .global __umodhi3_ret
-__umodhi3_ret:
-#if defined (__AVR_ENHANCED__)
-       movw    r24, r_remL
-#else
-       mov     r24,r_remL
-       mov     r25,r_remH
-#endif
-       ret
-.endfunc
-#endif /* defined (L_umodhi3) */
-       
-#if defined (L_udivhi3)
-       
-       .global __udivhi3
-       .func   __udivhi3
-__udivhi3:
-       clr     __tmp_reg__
-       rjmp    __divhi_raw
-.endfunc
-#endif /* defined (L_udivhi3) */
 
-#if defined (L_modhi3)
-       .global __modhi3
-       .func   __modhi3
-__modhi3:
-       .global _div
-_div:
-       rcall   __divhi3
-#if defined (__AVR_ENHANCED__)
-       movw    r22, r24
-#else
-       mov     r22,r24         ; needed for div () function
-       mov     r23,r25
-#endif
-       rjmp    __umodhi3_ret
-.endfunc
-#endif /* defined (L_modhi3) */
-       
-       
-#if defined (L_divhi3)
-       .global __divhi3
-       .func   __divhi3
-__divhi3:
-        bst     r_arg1H,7      ; store sign of divident
-        mov     __tmp_reg__,r_arg1H
-        eor     __tmp_reg__,r_arg2H   ; r0.7 is sign of result
-       brtc    __divhi3_skip1
-       com     r_arg1H
-        neg     r_arg1L                ; divident negative : negate
-       sbci    r_arg1H,0xff
-__divhi3_skip1:
-        tst    r_arg2H
-       brpl    __divhi3_skip2
-       com     r_arg2H
-        neg     r_arg2L                ; divisor negative : negate
-       sbci    r_arg2H,0xff
-__divhi3_skip2:
-       .global __divhi_raw
-__divhi_raw:
+#if defined (L_udivmodhi4)
+       .global __udivmodhi4
+       .func   __udivmodhi4
+__udivmodhi4:
        sub     r_remL,r_remL
-       sub     r_remH,r_remH           ; clear remainder and carry
+       sub     r_remH,r_remH   ; clear remainder and carry
        ldi     r_cnt,17        ; init loop counter
-       rjmp    __divhi3_ep     ; jump to entry point
-__divhi3_loop:
+       rjmp    __udivmodhi4_ep ; jump to entry point
+__udivmodhi4_loop:
         rol    r_remL          ; shift dividend into remainder
        rol     r_remH
         cp     r_remL,r_arg2L  ; compare remainder & divisor
        cpc     r_remH,r_arg2H
-        brcs   __divhi3_ep     ; remainder < divisor
+        brcs   __udivmodhi4_ep ; remainder < divisor
         sub    r_remL,r_arg2L  ; restore remainder
         sbc    r_remH,r_arg2H
-__divhi3_ep:
+__udivmodhi4_ep:
         rol    r_arg1L         ; shift dividend (with CARRY)
         rol    r_arg1H
         dec    r_cnt           ; decrement loop counter
-        brne   __divhi3_loop   ; loop
-       brtc    __divhi3_1
-       com     r_remH
-       neg     r_remL          ; correct remainder sign
-       sbci    r_remH,0xff
-__divhi3_1:
+        brne   __udivmodhi4_loop
+       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
+       ret
+       .endfunc
+#endif /* defined (L_udivmodhi4) */
+
+#if defined (L_divmodhi4)
+       .global __divmodhi4
+       .func   __divmodhi4
+__divmodhi4:
+       .global _div
+_div:
+        bst     r_arg1H,7      ; store sign of dividend
+        mov     __tmp_reg__,r_arg1H
+        eor     __tmp_reg__,r_arg2H   ; r0.7 is sign of result
+       rcall   __divmodhi4_neg1 ; dividend negative : negate
+       sbrc    r_arg2H,7
+       rcall   __divmodhi4_neg2 ; divisor negative : negate
+       rcall   __udivmodhi4    ; do the unsigned div/mod
+       rcall   __divmodhi4_neg1 ; correct remainder sign
        tst     __tmp_reg__
-       brpl    __divhi3_exit
-       adiw    r_arg1L,1       ; correct result sign
+       brpl    __divmodhi4_exit
+__divmodhi4_neg2:
+       com     r_arg2H
+       neg     r_arg2L         ; correct divisor/result sign
+       sbci    r_arg2H,0xff
+__divmodhi4_exit:
        ret
-__divhi3_exit:
-       com     r_arg1L
+__divmodhi4_neg1:
+       brtc    __divmodhi4_exit
        com     r_arg1H
+       neg     r_arg1L         ; correct dividend/remainder sign
+       sbci    r_arg1H,0xff
        ret
-.endfunc
-#endif /* defined (L_divhi3) */
-       
+       .endfunc
+#endif /* defined (L_divmodhi4) */
+
 #undef r_remH  
 #undef r_remL  
              
@@ -439,12 +455,14 @@ __divhi3_exit:
 #define        r_remHL r30
 #define        r_remH  r27
 #define        r_remL  r26     /* remainder Low */
-       
+
+/* return: remainder */
 #define        r_arg1HH r25    /* dividend High */
 #define        r_arg1HL r24
 #define        r_arg1H  r23
 #define        r_arg1L  r22    /* dividend Low */
-       
+
+/* return: quotient */
 #define        r_arg2HH r21    /* divisor High */
 #define        r_arg2HL r20
 #define        r_arg2H  r19
@@ -452,100 +470,18 @@ __divhi3_exit:
        
 #define        r_cnt __zero_reg__  /* loop count (0 after the loop!) */
 
-#if defined (L_umodsi3)
-
-       .global __umodsi3
-       .func   __umodsi3
-__umodsi3:
-       clt
-       rcall   __udivsi3
-       .global __umodsi3_ret
-__umodsi3_ret:
-#if defined (__AVR_ENHANCED__)
-       movw    r24, r_remHL
-       movw    r22, r_remL
-#else
-       mov     r25,r_remHH
-       mov     r24,r_remHL
-       mov     r23,r_remH
-       mov     r22,r_remL
-#endif
-       ret
-.endfunc
-#endif /* defined (L_umodsi3) */
-       
-#if defined (L_udivsi3)
-
-       .global __udivsi3
-       .func   __udivsi3
-__udivsi3:
-       clr     __tmp_reg__
-       rjmp    __divsi_raw
-.endfunc
-#endif /* defined (L_udivsi3) */
-
-#if defined (L_modsi3)
-       
-       .global __modsi3
-       .func   __modsi3
-__modsi3:
-       .global _ldiv
-_ldiv:
-       rcall   __divsi3
-#if defined (__AVR_ENHANCED__)
-       movw    r18, r22
-       movw    r20, r24
-#else
-       mov     r18,r22         /* Needed for ldiv */
-       mov     r19,r23
-       mov     r20,r24
-       mov     r21,r25
-#endif
-       rjmp    __umodsi3_ret
-.endfunc
-#endif /* defined (L_modsi3) */
-
-#if defined (L_divsi3)
-
-       .global __divsi3
-       .func   __divsi3
-__divsi3:
-        bst     r_arg1HH,7     ; store sign of divident
-        mov     __tmp_reg__,r_arg1HH
-        eor     __tmp_reg__,r_arg2HH   ; r0.7 is sign of result
-       brtc    __divsi3_skip1
-       com     r_arg1HH
-       com     r_arg1HL
-       com     r_arg1H
-        neg     r_arg1L                ; divident negative : negate
-       sbci    r_arg1H, 0xff
-       sbci    r_arg1HL,0xff
-       sbci    r_arg1HH,0xff
-__divsi3_skip1:
-        tst    r_arg2HH
-       brpl    __divsi3_skip2
-       com     r_arg2HH
-       com     r_arg2HL
-       com     r_arg2H
-        neg     r_arg2L                ; divisor negative : negate
-       sbci    r_arg2H, 0xff
-       sbci    r_arg2HL,0xff
-       sbci    r_arg2HH,0xff
-__divsi3_skip2:
-       .global __divsi_raw
-__divsi_raw:
+#if defined (L_udivmodsi4)
+       .global __udivmodsi4
+       .func   __udivmodsi4
+__udivmodsi4:
        ldi     r_remL, 33      ; init loop counter
        mov     r_cnt, r_remL
        sub     r_remL,r_remL
-       sub     r_remH,r_remH
-#if defined (__AVR_ENHANCED__)
-       movw    r_remHL, r_remL
-#else
-       sub     r_remHL,r_remHL
-       sub     r_remHH,r_remHH ; clear remainder and carry
-#endif
-       rjmp    __divsi3_ep     ; jump to entry point
-__divsi3_loop:
+       sub     r_remH,r_remH   ; clear remainder and carry
+       mov_l   r_remHL, r_remL
+       mov_h   r_remHH, r_remH
+       rjmp    __udivmodsi4_ep ; jump to entry point
+__udivmodsi4_loop:
         rol    r_remL          ; shift dividend into remainder
        rol     r_remH
        rol     r_remHL
@@ -554,43 +490,72 @@ __divsi3_loop:
        cpc     r_remH,r_arg2H
        cpc     r_remHL,r_arg2HL
        cpc     r_remHH,r_arg2HH
-        brcs   __divsi3_ep     ; remainder <= divisor
+       brcs    __udivmodsi4_ep ; remainder <= divisor
         sub    r_remL,r_arg2L  ; restore remainder
         sbc    r_remH,r_arg2H
         sbc    r_remHL,r_arg2HL
         sbc    r_remHH,r_arg2HH
-__divsi3_ep:
+__udivmodsi4_ep:
         rol    r_arg1L         ; shift dividend (with CARRY)
         rol    r_arg1H
         rol    r_arg1HL
         rol    r_arg1HH
         dec    r_cnt           ; decrement loop counter
-        brne   __divsi3_loop   ; loop
+        brne   __udivmodsi4_loop
                                ; __zero_reg__ now restored (r_cnt == 0)
-       brtc    __divsi3_1
-       com     r_remHH
-       com     r_remHL
-       com     r_remH
-       neg     r_remL          ; correct remainder sign
-       sbci    r_remH, 0xff
-       sbci    r_remHL,0xff
-       sbci    r_remHH,0xff
-__divsi3_1:
-       rol     __tmp_reg__
-       brcc    __divsi3_exit
-       adc     r_arg1L,__zero_reg__; correct result sign
-       adc     r_arg1H,__zero_reg__
-       adc     r_arg1HL,__zero_reg__
-       adc     r_arg1HH,__zero_reg__
-       ret
-__divsi3_exit:
        com     r_arg1L
        com     r_arg1H
        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
        ret
-.endfunc
-#endif /* defined (L_divsi3) */
+       .endfunc
+#endif /* defined (L_udivmodsi4) */
+
+#if defined (L_divmodsi4)
+       .global __divmodsi4
+       .func   __divmodsi4
+__divmodsi4:
+        bst     r_arg1HH,7     ; store sign of dividend
+        mov     __tmp_reg__,r_arg1HH
+        eor     __tmp_reg__,r_arg2HH   ; r0.7 is sign of result
+       rcall   __divmodsi4_neg1 ; dividend negative : negate
+       sbrc    r_arg2HH,7
+       rcall   __divmodsi4_neg2 ; divisor negative : negate
+       rcall   __udivmodsi4    ; do the unsigned div/mod
+       rcall   __divmodsi4_neg1 ; correct remainder sign
+       rol     __tmp_reg__
+       brcc    __divmodsi4_exit
+__divmodsi4_neg2:
+       com     r_arg2HH
+       com     r_arg2HL
+       com     r_arg2H
+       neg     r_arg2L         ; correct divisor/quotient sign
+       sbci    r_arg2H,0xff
+       sbci    r_arg2HL,0xff
+       sbci    r_arg2HH,0xff
+__divmodsi4_exit:
+       ret
+__divmodsi4_neg1:
+       brtc    __divmodsi4_exit
+       com     r_arg1HH
+       com     r_arg1HL
+       com     r_arg1H
+       neg     r_arg1L         ; correct dividend/remainder sign
+       sbci    r_arg1H, 0xff
+       sbci    r_arg1HL,0xff
+       sbci    r_arg1HH,0xff
+       ret
+       .endfunc
+#endif /* defined (L_divmodsi4) */
 
 /**********************************
  * This is a prologue subroutine
@@ -664,12 +629,8 @@ __epilogue_restores__:
        out     __SP_H__,r29
        out     __SREG__,__tmp_reg__
        out     __SP_L__,r28
-#if defined (__AVR_ENHANCED__)
-       movw    r28, r26
-#else
-       mov     r28,r26
-       mov     r29,r27
-#endif
+       mov_l   r28, r26
+       mov_h   r29, r27
        ret
 .endfunc
 #endif /* defined (L_epilogue) */
@@ -708,7 +669,7 @@ __tablejump2__:
        lpm
        push    r0
        ret
-.endfunc
 #endif
+.endfunc
 #endif /* defined (L_tablejump) */
 
index 7e4d0335170ebc06d19b157d079482d6fdfc4ddf..bc6aeeb5ffd163d529c920934d112e8e6fd4f0a5 100644 (file)
@@ -8,18 +8,12 @@ LIB1ASMFUNCS = \
        _mulqi3 \
        _mulhi3 \
        _mulsi3 \
-       _umodqi3 \
-       _udivqi3 \
-       _modqi3 \
-       _divqi3 \
-       _umodhi3 \
-       _udivhi3 \
-       _modhi3 \
-       _divhi3 \
-       _umodsi3 \
-       _udivsi3 \
-       _modsi3 \
-       _divsi3 \
+       _udivmodqi4 \
+       _divmodqi4 \
+       _udivmodhi4 \
+       _divmodhi4 \
+       _udivmodsi4 \
+       _divmodsi4 \
        _prologue \
        _epilogue \
        _exit \