summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgjl <gjl@138bc75d-0d04-0410-961f-82ee72b054a4>2011-06-29 07:52:56 +0000
committergjl <gjl@138bc75d-0d04-0410-961f-82ee72b054a4>2011-06-29 07:52:56 +0000
commit8e8584fdb03d7d1e9e35a07da2fe3ec20fff3138 (patch)
treebc2060ac8eb6c415f5985e6e51b7e04a1b03d11c
parent442e9f34c2ba6d374252fda246316a8c566ce3bb (diff)
downloadgcc-8e8584fdb03d7d1e9e35a07da2fe3ec20fff3138.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@175620 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/config/avr/avr.md44
-rw-r--r--gcc/config/avr/libgcc.S136
-rw-r--r--gcc/config/avr/t-avr3
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 <avr@gjlay.de>
+
+ * 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 <joseph@codesourcery.com>
* 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 \