From 9a63dee43dc3415c872f8087c9ef4ea7cb68208b Mon Sep 17 00:00:00 2001 From: Georg-Johann Lay Date: Wed, 29 Jun 2011 07:52:56 +0000 Subject: [PATCH] t-avr (LIB1ASMFUNCS): Add _mulhisi3, _umulhisi3, _xmulhisi3_exit. * config/avr/t-avr (LIB1ASMFUNCS): Add _mulhisi3, _umulhisi3, _xmulhisi3_exit. * config/avr/libgcc.S (_xmulhisi3_exit): New Function. (__mulhisi3): Optimize if have MUL*. Use XJMP instead of rjmp. (__umulhisi3): Ditto. * config/avr/avr.md (mulhisi3): New insn expender. (umulhisi3): New insn expender. (*mulhisi3_call): New insn. (*umulhisi3_call): New insn. From-SVN: r175620 --- gcc/ChangeLog | 12 ++++ gcc/config/avr/avr.md | 44 +++++++++++++ gcc/config/avr/libgcc.S | 136 +++++++++++++++++++++++++++++++++++++--- gcc/config/avr/t-avr | 3 + 4 files changed, 185 insertions(+), 10 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 19a381b1a9d..2b40b2c1046 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2011-06-29 Georg-Johann Lay + + * config/avr/t-avr (LIB1ASMFUNCS): Add _mulhisi3, _umulhisi3, + _xmulhisi3_exit. + * config/avr/libgcc.S (_xmulhisi3_exit): New Function. + (__mulhisi3): Optimize if have MUL*. Use XJMP instead of rjmp. + (__umulhisi3): Ditto. + * config/avr/avr.md (mulhisi3): New insn expender. + (umulhisi3): New insn expender. + (*mulhisi3_call): New insn. + (*umulhisi3_call): New insn. + 2011-06-28 Joseph Myers * Makefile.in (LIBGCC2_CFLAGS): Remove -D__GCC_FLOAT_NOT_NEEDED. diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index b7799bed49e..a07992389cb 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -1056,6 +1056,50 @@ [(set_attr "type" "xcall") (set_attr "cc" "clobber")]) +(define_expand "mulhisi3" + [(set (reg:HI 18) + (match_operand:HI 1 "register_operand" "")) + (set (reg:HI 20) + (match_operand:HI 2 "register_operand" "")) + (set (reg:SI 22) + (mult:SI (sign_extend:SI (reg:HI 18)) + (sign_extend:SI (reg:HI 20)))) + (set (match_operand:SI 0 "register_operand" "") + (reg:SI 22))] + "AVR_HAVE_MUL" + "") + +(define_expand "umulhisi3" + [(set (reg:HI 18) + (match_operand:HI 1 "register_operand" "")) + (set (reg:HI 20) + (match_operand:HI 2 "register_operand" "")) + (set (reg:SI 22) + (mult:SI (zero_extend:SI (reg:HI 18)) + (zero_extend:SI (reg:HI 20)))) + (set (match_operand:SI 0 "register_operand" "") + (reg:SI 22))] + "AVR_HAVE_MUL" + "") + +(define_insn "*mulhisi3_call" + [(set (reg:SI 22) + (mult:SI (sign_extend:SI (reg:HI 18)) + (sign_extend:SI (reg:HI 20))))] + "AVR_HAVE_MUL" + "%~call __mulhisi3" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + +(define_insn "*umulhisi3_call" + [(set (reg:SI 22) + (mult:SI (zero_extend:SI (reg:HI 18)) + (zero_extend:SI (reg:HI 20))))] + "AVR_HAVE_MUL" + "%~call __umulhisi3" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + ; / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % / % ; divmod diff --git a/gcc/config/avr/libgcc.S b/gcc/config/avr/libgcc.S index 1988de91d1c..9d13d9611b4 100644 --- a/gcc/config/avr/libgcc.S +++ b/gcc/config/avr/libgcc.S @@ -178,10 +178,58 @@ __mulhi3_exit: #endif /* defined (L_mulhi3) */ #endif /* !defined (__AVR_HAVE_MUL__) */ +/******************************************************* + Widening Multiplication 32 = 16 x 16 +*******************************************************/ + #if defined (L_mulhisi3) - .global __mulhisi3 - .func __mulhisi3 -__mulhisi3: +DEFUN __mulhisi3 +#if defined (__AVR_HAVE_MUL__) + +;; r25:r22 = r19:r18 * r21:r20 + +#define A0 18 +#define B0 20 +#define C0 22 + +#define A1 A0+1 +#define B1 B0+1 +#define C1 C0+1 +#define C2 C0+2 +#define C3 C0+3 + + ; C = (signed)A1 * (signed)B1 + muls A1, B1 + movw C2, R0 + + ; C += A0 * B0 + mul A0, B0 + movw C0, R0 + + ; C += (signed)A1 * B0 + mulsu A1, B0 + sbci C3, 0 + add C1, R0 + adc C2, R1 + clr __zero_reg__ + adc C3, __zero_reg__ + + ; C += (signed)B1 * A0 + mulsu B1, A0 + sbci C3, 0 + XJMP __xmulhisi3_exit + +#undef A0 +#undef A1 +#undef B0 +#undef B1 +#undef C0 +#undef C1 +#undef C2 +#undef C3 + +#else /* !__AVR_HAVE_MUL__ */ +;;; FIXME: This is dead code (noone calls it) mov_l r18, r24 mov_h r19, r25 clr r24 @@ -192,24 +240,92 @@ __mulhisi3: sbrc r19, 7 dec r20 mov r21, r20 - rjmp __mulsi3 - .endfunc + XJMP __mulsi3 +#endif /* __AVR_HAVE_MUL__ */ +ENDF __mulhisi3 #endif /* defined (L_mulhisi3) */ #if defined (L_umulhisi3) - .global __umulhisi3 - .func __umulhisi3 -__umulhisi3: +DEFUN __umulhisi3 +#if defined (__AVR_HAVE_MUL__) + +;; r25:r22 = r19:r18 * r21:r20 + +#define A0 18 +#define B0 20 +#define C0 22 + +#define A1 A0+1 +#define B1 B0+1 +#define C1 C0+1 +#define C2 C0+2 +#define C3 C0+3 + + ; C = A1 * B1 + mul A1, B1 + movw C2, R0 + + ; C += A0 * B0 + mul A0, B0 + movw C0, R0 + + ; C += A1 * B0 + mul A1, B0 + add C1, R0 + adc C2, R1 + clr __zero_reg__ + adc C3, __zero_reg__ + + ; C += B1 * A0 + mul B1, A0 + XJMP __xmulhisi3_exit + +#undef A0 +#undef A1 +#undef B0 +#undef B1 +#undef C0 +#undef C1 +#undef C2 +#undef C3 + +#else /* !__AVR_HAVE_MUL__ */ +;;; FIXME: This is dead code (noone calls it) mov_l r18, r24 mov_h r19, r25 clr r24 clr r25 clr r20 clr r21 - rjmp __mulsi3 - .endfunc + XJMP __mulsi3 +#endif /* __AVR_HAVE_MUL__ */ +ENDF __umulhisi3 #endif /* defined (L_umulhisi3) */ +#if defined (L_xmulhisi3_exit) + +;;; Helper for __mulhisi3 resp. __umulhisi3. + +#define C0 22 +#define C1 C0+1 +#define C2 C0+2 +#define C3 C0+3 + +DEFUN __xmulhisi3_exit + add C1, R0 + adc C2, R1 + clr __zero_reg__ + adc C3, __zero_reg__ + ret +ENDF __xmulhisi3_exit + +#undef C0 +#undef C1 +#undef C2 +#undef C3 + +#endif /* defined (L_xmulhisi3_exit) */ + #if defined (L_mulsi3) /******************************************************* Multiplication 32 x 32 diff --git a/gcc/config/avr/t-avr b/gcc/config/avr/t-avr index f941962f5b9..026ee10b10e 100644 --- a/gcc/config/avr/t-avr +++ b/gcc/config/avr/t-avr @@ -39,6 +39,9 @@ LIB1ASMSRC = avr/libgcc.S LIB1ASMFUNCS = \ _mulqi3 \ _mulhi3 \ + _mulhisi3 \ + _umulhisi3 \ + _xmulhisi3_exit \ _mulsi3 \ _udivmodqi4 \ _divmodqi4 \ -- 2.30.2