aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/avr/avr-fixed.md
diff options
context:
space:
mode:
authorGeorg-Johann Lay <avr@gjlay.de>2012-09-15 15:52:28 +0000
committerGeorg-Johann Lay <gjl@gcc.gnu.org>2012-09-15 15:52:28 +0000
commit51526856a1ca4a9434919d012a2bed07c8395ee0 (patch)
tree89382cc27ddcd6714736d847af8f8dc0b6289abc /gcc/config/avr/avr-fixed.md
parentfc2655fb3082182075b288b58c93ac563ef661a0 (diff)
downloadgcc-51526856a1ca4a9434919d012a2bed07c8395ee0.zip
gcc-51526856a1ca4a9434919d012a2bed07c8395ee0.tar.gz
gcc-51526856a1ca4a9434919d012a2bed07c8395ee0.tar.bz2
re PR target/54222 ([avr] Implement fixed-point support)
gcc/ PR target/54222 * config/avr/avr-fixed.md (ALL2S, ALL4S, ALL24S, ALL124S, ALL124U): New mode iterators. (<code_stdname><mode>3): New insns for SS_PLUS, SS_MINUS. (<code_stdname><mode>3): New insns for US_PLUS, US_MINUS. (usneg<mode>2): New insns. (<code_stdname><mode>2): New expanders for SS_NEG, SS_ABS. (*<code_stdname><mode>2): New insns for SS_NEG, SS_ABS. * config/avr/avr-dimode.md (ALL8U, ALL8S): New mode iterators. (avr_out_plus64, avr_out_minus64): Use avr_out_plus instead. (<code_stdname><mode>3): New expanders for SS_PLUS, SS_MINUS. (<code_stdname><mode>3): New expanders for US_PLUS, US_MINUS. (<code_stdname><mode>3_insn): New insns. (<code_stdname><mode>3_const_insn): New insns. * config/avr/avr.md (cc): Add: plus. Remove: out_plus, out_plus_noclobber, minus. (length): Add: plus. Remove: out_plus, out_plus_noclobber, plus64, minus, minus64. (abelian): New code_attr. (code_stdname): Handle: ss_plus, ss_minus, ss_neg, ss_abs, us_plus, us_minus, us_neg. (*add<mode>3, add<mode>3_clobber, add<mode>3, addpsi3, sub<mode>3): Use avr_out_plus to output. * config/avr/avr-protos.h (avr_out_plus): Change prototype. (avr_out_plus_noclobber, avr_out_minus): Remove. (avr_out_plus64, avr_out_minus64): Remove. * config/avr/avr.c (avr_out_plus_1): Add new default arguments code_sat, sign. Saturate after operation if code_sat != UNKNOWN. (avr_out_plus_symbol): New static function. (avr_out_plus): Rewrite. (adjust_insn_length): Handle: ADJUST_LEN_PLUS. Remove handling of: ADJUST_LEN_OUT_PLUS, ADJUST_LEN_PLUS64, ADJUST_LEN_MINUS, ADJUST_LEN_MINUS64, ADJUST_LEN_OUT_PLUS_NOCLOBBER. (notice_update_cc): Handle: CC_PLUS. Remove handling of: CC_MINUS, CC_OUT_PLUS, CC_OUT_PLUS_NOCLOBBER (avr_out_plus_noclobber, avr_out_minus): Remove. (avr_out_plus64, avr_out_minus64): Remove. (avr_print_operand): Print raw REGNO if 'r' is used with REG. libgcc/ PR target/54222 * config/avr/lib1funcs-fixed.S (__ssneg_2, __ssabs_2, __ssneg_4, __ssabs_4, __clr_8, __ssneg_8, __ssabs_8, __usadd_8, __ussub_8, __ssadd_8, __sssub_8): New functions. (__divsa3): Use __negsi2 to negate r_quoL. * config/avr/lib1funcs.S (FALIAS): New macro. (__divmodsi4): Break out and use __divmodsi4_neg1 as... (__negsi2): ...this new function. * config/avr/t-avr (LIB1ASMFUNCS): Add _negsi2, _clr_8, _ssneg_2, _ssneg_4, _ssneg_8, _ssabs_2, _ssabs_4, _ssabs_8, _ssadd_8, _sssub_8, _usadd_8, _ussub_8. (LIB2FUNCS_EXCLUDE): Fix typo for _add _sub. Add: _ssadd*, _sssub*, _ssneg*, _ssabs* for signed fixed modes. Add: _usadd*, _ussub*, _usneg* for unsigned fixed modes. gcc/testsuite/ PR target/54222 * gcc.target/avr/torture/fix-types.h: New. * gcc.target/avr/torture/vals-hr.def: New. * gcc.target/avr/torture/vals-r.def: New. * gcc.target/avr/torture/vals-k.def: New. * gcc.target/avr/torture/vals-ur.def: New. * gcc.target/avr/torture/vals-uk.def: New. * gcc.target/avr/torture/vals-uhr.def: New. * gcc.target/avr/torture/vals-llk.def: New. * gcc.target/avr/torture/vals-ullk.def: New. * gcc.target/avr/torture/sat-hr-plus-minus.c: New. * gcc.target/avr/torture/sat-r-plus-minus.c: New. * gcc.target/avr/torture/sat-k-plus-minus.c: New. * gcc.target/avr/torture/sat-ur-plus-minus.c: New. * gcc.target/avr/torture/sat-uk-plus-minus.c: New. * gcc.target/avr/torture/sat-uhr-plus-minus.c: New. * gcc.target/avr/torture/sat-llk-plus-minus.c: New. * gcc.target/avr/torture/sat-ullk-plus-minus.c: New. From-SVN: r191345
Diffstat (limited to 'gcc/config/avr/avr-fixed.md')
-rw-r--r--gcc/config/avr/avr-fixed.md112
1 files changed, 112 insertions, 0 deletions
diff --git a/gcc/config/avr/avr-fixed.md b/gcc/config/avr/avr-fixed.md
index bfbdaec..5a99499 100644
--- a/gcc/config/avr/avr-fixed.md
+++ b/gcc/config/avr/avr-fixed.md
@@ -29,6 +29,12 @@
(HA "") (UHA "")])
(define_mode_iterator ALL4A [(SA "") (USA "")])
+(define_mode_iterator ALL2S [HQ HA])
+(define_mode_iterator ALL4S [SA SQ])
+(define_mode_iterator ALL24S [ HQ HA SA SQ])
+(define_mode_iterator ALL124S [ QQ HQ HA SA SQ])
+(define_mode_iterator ALL124U [UQQ UHQ UHA USA USQ])
+
;;; Conversions
(define_mode_iterator FIXED_A
@@ -72,6 +78,112 @@
(set_attr "adjust_len" "ufract")])
;******************************************************************************
+;** Saturated Addition and Subtraction
+;******************************************************************************
+
+;; Fixme: It would be nice if we could expand the 32-bit versions to a
+;; transparent libgcc call if $2 is a REG. Problem is that it is
+;; not possible to describe that addition is commutative.
+;; And defining register classes/constraintrs for the involved hard
+;; registers and let IRA do the work, yields inacceptable bloated code.
+;; Thus, we have to live with the up to 11 instructions that are output
+;; for these 32-bit saturated operations.
+
+;; "ssaddqq3" "ssaddhq3" "ssaddha3" "ssaddsq3" "ssaddsa3"
+;; "sssubqq3" "sssubhq3" "sssubha3" "sssubsq3" "sssubsa3"
+(define_insn "<code_stdname><mode>3"
+ [(set (match_operand:ALL124S 0 "register_operand" "=??d,d")
+ (ss_addsub:ALL124S (match_operand:ALL124S 1 "register_operand" "<abelian>0,0")
+ (match_operand:ALL124S 2 "nonmemory_operand" "r,Ynn")))]
+ ""
+ {
+ return avr_out_plus (insn, operands);
+ }
+ [(set_attr "cc" "clobber")
+ (set_attr "adjust_len" "plus")])
+
+;; "usadduqq3" "usadduhq3" "usadduha3" "usaddusq3" "usaddusa3"
+;; "ussubuqq3" "ussubuhq3" "ussubuha3" "ussubusq3" "ussubusa3"
+(define_insn "<code_stdname><mode>3"
+ [(set (match_operand:ALL124U 0 "register_operand" "=??r,d")
+ (us_addsub:ALL124U (match_operand:ALL124U 1 "register_operand" "<abelian>0,0")
+ (match_operand:ALL124U 2 "nonmemory_operand" "r,Ynn")))]
+ ""
+ {
+ return avr_out_plus (insn, operands);
+ }
+ [(set_attr "cc" "clobber")
+ (set_attr "adjust_len" "plus")])
+
+;******************************************************************************
+;** Saturated Negation and Absolute Value
+;******************************************************************************
+
+;; Fixme: This will always result in 0. Dunno why simplify-rtx.c says
+;; "unknown" on how to optimize this. libgcc call would be in order,
+;; but the performance is *PLAIN* *HORROR* because the optimizers don't
+;; manage to optimize out MEMCPY that's sprincled all over fixed-bit.c */
+
+(define_expand "usneg<mode>2"
+ [(parallel [(match_operand:ALL124U 0 "register_operand" "")
+ (match_operand:ALL124U 1 "nonmemory_operand" "")])]
+ ""
+ {
+ emit_move_insn (operands[0], CONST0_RTX (<MODE>mode));
+ DONE;
+ })
+
+(define_insn "ssnegqq2"
+ [(set (match_operand:QQ 0 "register_operand" "=r")
+ (ss_neg:QQ (match_operand:QQ 1 "register_operand" "0")))]
+ ""
+ "neg %0\;brvc 0f\;dec %0\;0:"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "3")])
+
+(define_insn "ssabsqq2"
+ [(set (match_operand:QQ 0 "register_operand" "=r")
+ (ss_abs:QQ (match_operand:QQ 1 "register_operand" "0")))]
+ ""
+ "sbrc %0,7\;neg %0\;sbrc %0,7\;dec %0"
+ [(set_attr "cc" "clobber")
+ (set_attr "length" "4")])
+
+;; "ssneghq2" "ssnegha2" "ssnegsq2" "ssnegsa2"
+;; "ssabshq2" "ssabsha2" "ssabssq2" "ssabssa2"
+(define_expand "<code_stdname><mode>2"
+ [(set (match_dup 2)
+ (match_operand:ALL24S 1 "register_operand" ""))
+ (set (match_dup 2)
+ (ss_abs_neg:ALL24S (match_dup 2)))
+ (set (match_operand:ALL24S 0 "register_operand" "")
+ (match_dup 2))]
+ ""
+ {
+ operands[2] = gen_rtx_REG (<MODE>mode, 26 - GET_MODE_SIZE (<MODE>mode));
+ })
+
+;; "*ssneghq2" "*ssnegha2"
+;; "*ssabshq2" "*ssabsha2"
+(define_insn "*<code_stdname><mode>2"
+ [(set (reg:ALL2S 24)
+ (ss_abs_neg:ALL2S (reg:ALL2S 24)))]
+ ""
+ "%~call __<code_stdname>_2"
+ [(set_attr "type" "xcall")
+ (set_attr "cc" "clobber")])
+
+;; "*ssnegsq2" "*ssnegsa2"
+;; "*ssabssq2" "*ssabssa2"
+(define_insn "*<code_stdname><mode>2"
+ [(set (reg:ALL4S 22)
+ (ss_abs_neg:ALL4S (reg:ALL4S 22)))]
+ ""
+ "%~call __<code_stdname>_4"
+ [(set_attr "type" "xcall")
+ (set_attr "cc" "clobber")])
+
+;******************************************************************************
; mul
;; "mulqq3" "muluqq3"