This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

AVR mul/divmod optimizations


I have finally applied this, hope that's OK.  Too late before the branch,
I know - but I have tested it for some time now.  (And, on weekends I have
"only" 20% packet loss to gcc.gnu.org - normally it's about 50%...)

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.

Index: config/avr/avr.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/avr/avr.h,v
retrieving revision 1.17
diff -c -3 -p -r1.17 avr.h
*** avr.h	2001/01/01 20:35:27	1.17
--- avr.h	2001/01/20 16:42:55
*************** valid_machine_decl_attribute (DECL, ATTR
*** 3228,3277 ****
  
  #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 ();					\
  }
  
--- 3228,3233 ----
Index: config/avr/avr.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/avr/avr.md,v
retrieving revision 1.24
diff -c -3 -p -r1.24 avr.md
*** avr.md	2001/01/13 21:42:07	1.24
--- avr.md	2001/01/20 16:43:10
***************
*** 21,26 ****
--- 21,36 ----
  ;; 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".
***************
*** 633,640 ****
  
  ;******************************************************************************
  ; mul
  
! (define_insn "mulqi3"
    [(set (match_operand:QI 0 "register_operand" "=r")
  	(mult:QI (match_operand:QI 1 "register_operand" "r")
  		 (match_operand:QI 2 "register_operand" "r")))]
--- 643,663 ----
  
  ;******************************************************************************
  ; mul
+ 
+ (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")))]
***************
*** 645,650 ****
--- 668,692 ----
    [(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"))
***************
*** 667,673 ****
    [(set_attr "length" "3")
     (set_attr "cc" "clobber")])
  
! (define_insn "mulhi3"
    [(set (match_operand:HI 0 "register_operand" "=&r")
  	(mult:HI (match_operand:HI 1 "register_operand" "r")
  		 (match_operand:HI 2 "register_operand" "r")))]
--- 709,729 ----
    [(set_attr "length" "3")
     (set_attr "cc" "clobber")])
  
! (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")))]
***************
*** 682,687 ****
--- 738,937 ----
    [(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
  
***************
*** 1794,1802 ****
  		AS2 (mov, r31, %B0) CR_TAB
  		\"icall\");
      }
!   else if (!AVR_MEGA)
!      return AS1(rcall,%c0);   
!   return AS1(call,%c0);
  }"
    [(set_attr "cc" "clobber,clobber,clobber")
     (set_attr_alternative "length"
--- 2044,2050 ----
  		AS2 (mov, r31, %B0) CR_TAB
  		\"icall\");
      }
!   return AS1(%~call,%c0);
  }"
    [(set_attr "cc" "clobber,clobber,clobber")
     (set_attr_alternative "length"
***************
*** 1829,1837 ****
  		AS2 (mov, r31, %B1) CR_TAB
  		\"icall\");
      }
!   else if (!AVR_MEGA)
!      return AS1(rcall,%c1);   
!   return AS1(call,%c1);
  }"
    [(set_attr "cc" "clobber,clobber,clobber")
     (set_attr_alternative "length"
--- 2077,2083 ----
  		AS2 (mov, r31, %B1) CR_TAB
  		\"icall\");
      }
!   return AS1(%~call,%c1);
  }"
    [(set_attr "cc" "clobber,clobber,clobber")
     (set_attr_alternative "length"
Index: config/avr/libgcc.S
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/avr/libgcc.S,v
retrieving revision 1.9
diff -c -3 -p -r1.9 libgcc.S
*** libgcc.S	2000/11/14 19:05:41	1.9
--- libgcc.S	2001/01/20 16:43:11
*************** Boston, MA 02111-1307, USA.  */
*** 32,39 ****
--- 32,60 ----
  #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__)
  /*******************************************************
*************** __mulqi3_exit:	
*** 67,72 ****
--- 88,116 ----
  .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
*************** __mulqi3_exit:	
*** 76,82 ****
  #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_resH  r21		/* result High */
  
  	.global	__mulhi3
--- 120,126 ----
  #define	r_arg1H	r25		/* multiplier High */
  #define	r_arg2L	r22		/* multiplicand Low */
  #define	r_arg2H	r23		/* multiplicand High */
! #define r_resL	__tmp_reg__	/* result Low */
  #define r_resH  r21		/* result High */
  
  	.global	__mulhi3
*************** __mulhi3_exit:
*** 116,121 ****
--- 160,197 ----
  #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
*************** __mulsi3_exit:
*** 227,307 ****
  /*******************************************************
         Division 8 / 8 => (result + remainder)
  *******************************************************/
! #define	r_rem	r26	/* remainder */
! #define	r_arg1	r24	/* dividend */
  #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) */
  
! #if defined (L_modqi3)
! 	
! 	.global	__modqi3
! 	.func	__modqi3
! __modqi3:
! 	rcall	__divqi3
! 	mov	r24,r_rem
  	ret
! .endfunc
! #endif /* defined (L_modqi3) */
  
! #if defined (L_divqi3)
! 
! 	.global	__divqi3
! 	.func	__divqi3
! __divqi3:
!         bst     r_arg1,7	; store sign of divident
          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
          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_rem		; correct remainder sign
! __divqi3_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) */
  
  #undef r_rem
  #undef r_arg1
--- 303,356 ----
  /*******************************************************
         Division 8 / 8 => (result + remainder)
  *******************************************************/
! #define	r_rem	r25	/* remainder */
! #define	r_arg1	r24	/* dividend, quotient */
  #define	r_arg2	r22	/* divisor */
! #define	r_cnt	r23	/* loop count */
  
! #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_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		; dividend negative : negate
          sbrc	r_arg2,7
! 	neg     r_arg2		; divisor negative : negate
! 	rcall	__udivmodqi4	; do the unsigned div/mod
! 	brtc	__divmodqi4_1
  	neg	r_rem		; correct remainder sign
! __divmodqi4_1:
  	sbrc	__tmp_reg__,7
  	neg	r_arg1		; correct result sign
! __divmodqi4_exit:
! 	ret
! 	.endfunc
! #endif /* defined (L_divmodqi4) */
  
  #undef r_rem
  #undef r_arg1
*************** __divqi3_exit:
*** 314,426 ****
  *******************************************************/
  #define	r_remL	r26	/* remainder Low */
  #define	r_remH	r27	/* remainder High */
! 	
  #define	r_arg1L	r24	/* dividend Low */
  #define	r_arg1H	r25	/* dividend High */
! 	
  #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:
  	sub	r_remL,r_remL
! 	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:
          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
          sub	r_remL,r_arg2L	; restore remainder
          sbc	r_remH,r_arg2H
! __divhi3_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:
  	tst	__tmp_reg__
! 	brpl	__divhi3_exit
! 	adiw	r_arg1L,1	; correct result sign
  	ret
! __divhi3_exit:
! 	com	r_arg1L
  	com	r_arg1H
  	ret
! .endfunc
! #endif /* defined (L_divhi3) */
! 	
  #undef r_remH  
  #undef r_remL  
               
--- 363,442 ----
  *******************************************************/
  #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_udivmodhi4)
! 	.global	__udivmodhi4
! 	.func	__udivmodhi4
! __udivmodhi4:
  	sub	r_remL,r_remL
! 	sub	r_remH,r_remH	; clear remainder and carry
  	ldi	r_cnt,17	; init loop counter
! 	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	__udivmodhi4_ep	; remainder < divisor
          sub	r_remL,r_arg2L	; restore remainder
          sbc	r_remH,r_arg2H
! __udivmodhi4_ep:
          rol	r_arg1L		; shift dividend (with CARRY)
          rol	r_arg1H
          dec	r_cnt		; decrement loop counter
!         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	__divmodhi4_exit
! __divmodhi4_neg2:
! 	com	r_arg2H
! 	neg	r_arg2L		; correct divisor/result sign
! 	sbci	r_arg2H,0xff
! __divmodhi4_exit:
  	ret
! __divmodhi4_neg1:
! 	brtc	__divmodhi4_exit
  	com	r_arg1H
+ 	neg	r_arg1L		; correct dividend/remainder sign
+ 	sbci	r_arg1H,0xff
  	ret
! 	.endfunc
! #endif /* defined (L_divmodhi4) */
! 
  #undef r_remH  
  #undef r_remL  
               
*************** __divhi3_exit:
*** 439,551 ****
  #define	r_remHL	r30
  #define	r_remH	r27
  #define	r_remL	r26	/* remainder Low */
! 	
  #define	r_arg1HH r25	/* dividend High */
  #define	r_arg1HL r24
  #define	r_arg1H  r23
  #define	r_arg1L  r22	/* dividend Low */
! 	
  #define	r_arg2HH r21	/* divisor High */
  #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_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:
  	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:
          rol	r_remL		; shift dividend into remainder
  	rol	r_remH
  	rol	r_remHL
--- 455,487 ----
  #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
  #define	r_arg2L  r18	/* divisor Low */
  	
  #define	r_cnt __zero_reg__  /* loop count (0 after the loop!) */
  
! #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	; 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
*************** __divsi3_loop:
*** 554,596 ****
  	cpc	r_remH,r_arg2H
  	cpc	r_remHL,r_arg2HL
  	cpc	r_remHH,r_arg2HH
!         brcs	__divsi3_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:
          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
  				; __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
  	ret
! .endfunc
! #endif /* defined (L_divsi3) */
  
  /**********************************
   * This is a prologue subroutine
--- 490,561 ----
  	cpc	r_remH,r_arg2H
  	cpc	r_remHL,r_arg2HL
  	cpc	r_remHH,r_arg2HH
! 	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
! __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	__udivmodsi4_loop
  				; __zero_reg__ now restored (r_cnt == 0)
  	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_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
*************** __epilogue_restores__:
*** 664,675 ****
  	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
  	ret
  .endfunc
  #endif /* defined (L_epilogue) */
--- 629,636 ----
  	out	__SP_H__,r29
  	out	__SREG__,__tmp_reg__
  	out	__SP_L__,r28
! 	mov_l	r28, r26
! 	mov_h	r29, r27
  	ret
  .endfunc
  #endif /* defined (L_epilogue) */
*************** __tablejump2__:
*** 708,714 ****
  	lpm
  	push	r0
  	ret
- .endfunc
  #endif
  #endif /* defined (L_tablejump) */
  
--- 669,675 ----
  	lpm
  	push	r0
  	ret
  #endif
+ .endfunc
  #endif /* defined (L_tablejump) */
  
Index: config/avr/t-avr
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/avr/t-avr,v
retrieving revision 1.4
diff -c -3 -p -r1.4 t-avr
*** t-avr	2000/08/29 19:37:45	1.4
--- t-avr	2001/01/20 16:43:12
*************** LIB1ASMFUNCS = \
*** 8,25 ****
  	_mulqi3 \
  	_mulhi3 \
  	_mulsi3 \
! 	_umodqi3 \
! 	_udivqi3 \
! 	_modqi3 \
! 	_divqi3 \
! 	_umodhi3 \
! 	_udivhi3 \
! 	_modhi3 \
! 	_divhi3 \
! 	_umodsi3 \
! 	_udivsi3 \
! 	_modsi3 \
! 	_divsi3 \
  	_prologue \
  	_epilogue \
  	_exit \
--- 8,19 ----
  	_mulqi3 \
  	_mulhi3 \
  	_mulsi3 \
! 	_udivmodqi4 \
! 	_divmodqi4 \
! 	_udivmodhi4 \
! 	_divmodhi4 \
! 	_udivmodsi4 \
! 	_divmodsi4 \
  	_prologue \
  	_epilogue \
  	_exit \


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]