aboutsummaryrefslogtreecommitdiff
path: root/libgcc
diff options
context:
space:
mode:
authorGeorg-Johann Lay <gjl@gcc.gnu.org>2011-11-04 16:20:18 +0000
committerGeorg-Johann Lay <gjl@gcc.gnu.org>2011-11-04 16:20:18 +0000
commite4fe948a6e9049df934677fc95d78b11c5cff4bd (patch)
tree8a4a616f637a4b3c284af95ea6b72a33644a4462 /libgcc
parent2fcc5e64740e48417e93d986bd58595296bec0c5 (diff)
downloadgcc-e4fe948a6e9049df934677fc95d78b11c5cff4bd.zip
gcc-e4fe948a6e9049df934677fc95d78b11c5cff4bd.tar.gz
gcc-e4fe948a6e9049df934677fc95d78b11c5cff4bd.tar.bz2
re PR target/50931 ([avr] Support a 24-bit scalar integer mode)
gcc/ PR target/50931 * config/avr/avr-modes.def: New file defining PSImode. * config/avr/avr-c.c (__INT24_MAX__, __INT24_MIN__, __UINT24_MAX__): New built-in defines. * config/avr/avr.md (adjust_len): Add tstpsi, mov24, reload_in24, ashlpsi, ashrpsi, lshrpsi. (QISO, QIDI, HISI, HIDI, MPUSH, rotx, rotsmode): Add PSI. (MOVMODE): New mode iterator. (movpsi): New expander. (movqi, movhi, movsi, movsf, movpsi): Write as one using MOVMODE. (*reload_inpsi, *movpsi): New insns. (*reload_inpsi): New RTL peephole. (addpsi3, *addpsi3_zero_extend.qi, *addpsi3_zero_extend.hi, *addpsi3_sign_extend.hi): New insns. (subpsi3, *subpsi3_zero_extend.qi, *subpsi3_zero_extend.hi, *subpsi3_sign_extend.hi): New insns. (divmodpsi4, udivmodpsi4): New define insn-and-split. (*divmodpsi4_call, *udivmodpsi4_call): New insns. (andpsi3, iorpsi3, xorpsi3): New insns. (*rotlpsi2.1, *rotlpsi2.23): New insns. (*rotw<mode>): Insn condition only allow even-sized modes. (*rotb<mode>): Insn condition allows odd-sized modes. (ashlpsi3, ashrpsi3, lshrpsi3, *addpsi3.lt0): New insns. (negpsi2, one_cmplpsi2): New insns. (extendqipsi2, extendhipsi2, extendpsisi2): New insns. (zero_extendqipsi2, zero_extendhipsi2, zero_extendpsisi2): New insn-and-splits. (*cmppsi, *negated_tstpsi, *reversed_tstpsi): New insns. (cbranchpsi4): New expander. * config/avr/constraints.md (Ca3, Co3, Cx3): New constraints. * config/avr/avr-protos.h (avr_out_tstpsi, avr_out_movpsi, avr_out_ashlpsi3, avr_out_ashrpsi3, avr_out_lshrpsi3, avr_out_reload_inpsi): New prototypes. * config/avr/avr.c (TARGET_SCALAR_MODE_SUPPORTED_P): Define to... (avr_scalar_mode_supported_p): ...this new static function. (avr_asm_len): Always return "". (avr_out_load_psi, avr_out_store_psi): New static functions. (avr_out_movpsi, avr_out_reload_inpsi): New functions. (avr_out_tstpsi): New function. (avr_out_ashlpsi3, avr_out_ashrpsi3, avr_out_lshrpsi3): New functions. (avr_out_plus_1, output_reload_in_const): Handle 3-byte types. (avr_simplify_comparison_p): Ditto. (adjust_insn_length): Handle ADJUST_LEN_RELOAD_IN24, ADJUST_LEN_MOV24, ADJUST_LEN_TSTPSI, ADJUST_LEN_ASHLPSI, ADJUST_LEN_ASHRPSI, ADJUST_LEN_LSHRPSI. (avr_rtx_costs_1): Report PSI costs. (avr_libcall_value): Handle odd-sized parameters. (avr_init_builtin_int24): New static function to define built-in 24-bit types __int24 and __uint24. (avr_init_builtins): Use it. libgcc/ PR target/50931 * config/t-avr (LIB1ASMFUNCS): Add _divmodpsi4, _udivmodpsi4. * config/lib1funcs.S (__udivmodpsi4, __divmodpsi4): New functions. From-SVN: r180962
Diffstat (limited to 'libgcc')
-rw-r--r--libgcc/ChangeLog6
-rw-r--r--libgcc/config/avr/lib1funcs.S137
-rw-r--r--libgcc/config/avr/t-avr1
3 files changed, 143 insertions, 1 deletions
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index f629ac0d..df6ad30 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,9 @@
+2011-11-04 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/50931
+ * config/t-avr (LIB1ASMFUNCS): Add _divmodpsi4, _udivmodpsi4.
+ * config/lib1funcs.S (__udivmodpsi4, __divmodpsi4): New functions.
+
2011-11-04 Joel Sherrill <joel.sherrill@oarcorp.com>
PR target/50989
diff --git a/libgcc/config/avr/lib1funcs.S b/libgcc/config/avr/lib1funcs.S
index 8c369c9..cd88a57 100644
--- a/libgcc/config/avr/lib1funcs.S
+++ b/libgcc/config/avr/lib1funcs.S
@@ -599,7 +599,142 @@ ENDF __divmodhi4
#undef r_arg2L
#undef r_cnt
-
+
+/*******************************************************
+ Division 24 / 24 => (result + remainder)
+*******************************************************/
+
+;; A[0..2]: In: Dividend; Out: Quotient
+#define A0 22
+#define A1 A0+1
+#define A2 A0+2
+
+;; B[0..2]: In: Divisor; Out: Remainder
+#define B0 18
+#define B1 B0+1
+#define B2 B0+2
+
+;; C[0..2]: Expand remainder
+#define C0 __zero_reg__
+#define C1 26
+#define C2 25
+
+;; Loop counter
+#define r_cnt 21
+
+#if defined (L_udivmodpsi4)
+;; R24:R22 = R24:R22 udiv R20:R18
+;; R20:R18 = R24:R22 umod R20:R18
+;; Clobbers: R21, R25, R26
+
+DEFUN __udivmodpsi4
+ ; init loop counter
+ ldi r_cnt, 24+1
+ ; Clear remainder and carry. C0 is already 0
+ clr C1
+ sub C2, C2
+ ; jump to entry point
+ rjmp __udivmodpsi4_start
+__udivmodpsi4_loop:
+ ; shift dividend into remainder
+ rol C0
+ rol C1
+ rol C2
+ ; compare remainder & divisor
+ cp C0, B0
+ cpc C1, B1
+ cpc C2, B2
+ brcs __udivmodpsi4_start ; remainder <= divisor
+ sub C0, B0 ; restore remainder
+ sbc C1, B1
+ sbc C2, B2
+__udivmodpsi4_start:
+ ; shift dividend (with CARRY)
+ rol A0
+ rol A1
+ rol A2
+ ; decrement loop counter
+ dec r_cnt
+ brne __udivmodpsi4_loop
+ com A0
+ com A1
+ com A2
+ ; div/mod results to return registers
+ ; remainder
+ mov B0, C0
+ mov B1, C1
+ mov B2, C2
+ clr __zero_reg__ ; C0
+ ret
+ENDF __udivmodpsi4
+#endif /* defined (L_udivmodpsi4) */
+
+#if defined (L_divmodpsi4)
+;; R24:R22 = R24:R22 div R20:R18
+;; R20:R18 = R24:R22 mod R20:R18
+;; Clobbers: T, __tmp_reg__, R21, R25, R26
+
+DEFUN __divmodpsi4
+ ; R0.7 will contain the sign of the result:
+ ; R0.7 = A.sign ^ B.sign
+ mov __tmp_reg__, B2
+ ; T-flag = sign of dividend
+ bst A2, 7
+ brtc 0f
+ com __tmp_reg__
+ ; Adjust dividend's sign
+ rcall __divmodpsi4_negA
+0:
+ ; Adjust divisor's sign
+ sbrc B2, 7
+ rcall __divmodpsi4_negB
+
+ ; Do the unsigned div/mod
+ XCALL __udivmodpsi4
+
+ ; Adjust quotient's sign
+ sbrc __tmp_reg__, 7
+ rcall __divmodpsi4_negA
+
+ ; Adjust remainder's sign
+ brtc __divmodpsi4_end
+
+__divmodpsi4_negB:
+ ; Correct divisor/remainder sign
+ com B2
+ com B1
+ neg B0
+ sbci B1, -1
+ sbci B2, -1
+ ret
+
+ ; Correct dividend/quotient sign
+__divmodpsi4_negA:
+ com A2
+ com A1
+ neg A0
+ sbci A1, -1
+ sbci A2, -1
+__divmodpsi4_end:
+ ret
+
+ENDF __divmodpsi4
+#endif /* defined (L_divmodpsi4) */
+
+#undef A0
+#undef A1
+#undef A2
+
+#undef B0
+#undef B1
+#undef B2
+
+#undef C0
+#undef C1
+#undef C2
+
+#undef r_cnt
+
/*******************************************************
Division 32 / 32 => (result + remainder)
*******************************************************/
diff --git a/libgcc/config/avr/t-avr b/libgcc/config/avr/t-avr
index a669f61..63f7460 100644
--- a/libgcc/config/avr/t-avr
+++ b/libgcc/config/avr/t-avr
@@ -12,6 +12,7 @@ LIB1ASMFUNCS = \
_divmodqi4 \
_udivmodhi4 \
_divmodhi4 \
+ _divmodpsi4 _udivmodpsi4 \
_udivmodsi4 \
_divmodsi4 \
_prologue \