Commit 51526856 by Georg-Johann Lay Committed by Georg-Johann Lay

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
parent fc2655fb
2012-09-15 Georg-Johann Lay <avr@gjlay.de>
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.
2012-09-15 Oleg Endo <olegendo@gcc.gnu.org> 2012-09-15 Oleg Endo <olegendo@gcc.gnu.org>
* config/sh/sh.c (sh_rtx_costs): Add handling of MEM, SIGN_EXTEND, * config/sh/sh.c (sh_rtx_costs): Add handling of MEM, SIGN_EXTEND,
......
...@@ -48,10 +48,10 @@ ...@@ -48,10 +48,10 @@
(ACC_B 10)]) (ACC_B 10)])
;; Supported modes that are 8 bytes wide ;; Supported modes that are 8 bytes wide
(define_mode_iterator ALL8 [(DI "") (define_mode_iterator ALL8 [DI DQ UDQ DA UDA TA UTA])
(DQ "") (UDQ "")
(DA "") (UDA "") (define_mode_iterator ALL8U [UDQ UDA UTA])
(TA "") (UTA "")]) (define_mode_iterator ALL8S [ DQ DA TA])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Addition ;; Addition
...@@ -124,9 +124,9 @@ ...@@ -124,9 +124,9 @@
"avr_have_dimode "avr_have_dimode
&& !s8_operand (operands[0], VOIDmode)" && !s8_operand (operands[0], VOIDmode)"
{ {
return avr_out_plus64 (operands[0], NULL); return avr_out_plus (insn, operands);
} }
[(set_attr "adjust_len" "plus64") [(set_attr "adjust_len" "plus")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
...@@ -185,11 +185,106 @@ ...@@ -185,11 +185,106 @@
(match_operand:ALL8 0 "const_operand" "n Ynn")))] (match_operand:ALL8 0 "const_operand" "n Ynn")))]
"avr_have_dimode" "avr_have_dimode"
{ {
return avr_out_minus64 (operands[0], NULL); return avr_out_plus (insn, operands);
}
[(set_attr "adjust_len" "plus")
(set_attr "cc" "clobber")])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Signed Saturating Addition and Subtraction
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define_expand "<code_stdname><mode>3"
[(set (match_operand:ALL8S 0 "general_operand" "")
(ss_addsub:ALL8S (match_operand:ALL8S 1 "general_operand" "")
(match_operand:ALL8S 2 "general_operand" "")))]
"avr_have_dimode"
{
rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A);
emit_move_insn (acc_a, operands[1]);
if (const_operand (operands[2], GET_MODE (operands[2])))
{
emit_insn (gen_<code_stdname><mode>3_const_insn (operands[2]));
}
else
{
emit_move_insn (gen_rtx_REG (<MODE>mode, ACC_B), operands[2]);
emit_insn (gen_<code_stdname><mode>3_insn ());
}
emit_move_insn (operands[0], acc_a);
DONE;
})
(define_insn "<code_stdname><mode>3_insn"
[(set (reg:ALL8S ACC_A)
(ss_addsub:ALL8S (reg:ALL8S ACC_A)
(reg:ALL8S ACC_B)))]
"avr_have_dimode"
"%~call __<code_stdname><mode>3"
[(set_attr "adjust_len" "call")
(set_attr "cc" "clobber")])
(define_insn "<code_stdname><mode>3_const_insn"
[(set (reg:ALL8S ACC_A)
(ss_addsub:ALL8S (reg:ALL8S ACC_A)
(match_operand:ALL8S 0 "const_operand" "n Ynn")))]
"avr_have_dimode"
{
return avr_out_plus (insn, operands);
} }
[(set_attr "adjust_len" "minus64") [(set_attr "adjust_len" "plus")
(set_attr "cc" "clobber")])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Unsigned Saturating Addition and Subtraction
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define_expand "<code_stdname><mode>3"
[(set (match_operand:ALL8U 0 "general_operand" "")
(us_addsub:ALL8U (match_operand:ALL8U 1 "general_operand" "")
(match_operand:ALL8U 2 "general_operand" "")))]
"avr_have_dimode"
{
rtx acc_a = gen_rtx_REG (<MODE>mode, ACC_A);
emit_move_insn (acc_a, operands[1]);
if (const_operand (operands[2], GET_MODE (operands[2])))
{
emit_insn (gen_<code_stdname><mode>3_const_insn (operands[2]));
}
else
{
emit_move_insn (gen_rtx_REG (<MODE>mode, ACC_B), operands[2]);
emit_insn (gen_<code_stdname><mode>3_insn ());
}
emit_move_insn (operands[0], acc_a);
DONE;
})
(define_insn "<code_stdname><mode>3_insn"
[(set (reg:ALL8U ACC_A)
(us_addsub:ALL8U (reg:ALL8U ACC_A)
(reg:ALL8U ACC_B)))]
"avr_have_dimode"
"%~call __<code_stdname><mode>3"
[(set_attr "adjust_len" "call")
(set_attr "cc" "clobber")]) (set_attr "cc" "clobber")])
(define_insn "<code_stdname><mode>3_const_insn"
[(set (reg:ALL8U ACC_A)
(us_addsub:ALL8U (reg:ALL8U ACC_A)
(match_operand:ALL8U 0 "const_operand" "n Ynn")))]
"avr_have_dimode"
{
return avr_out_plus (insn, operands);
}
[(set_attr "adjust_len" "plus")
(set_attr "cc" "clobber")])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Negation ;; Negation
......
...@@ -29,6 +29,12 @@ ...@@ -29,6 +29,12 @@
(HA "") (UHA "")]) (HA "") (UHA "")])
(define_mode_iterator ALL4A [(SA "") (USA "")]) (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 ;;; Conversions
(define_mode_iterator FIXED_A (define_mode_iterator FIXED_A
...@@ -72,6 +78,112 @@ ...@@ -72,6 +78,112 @@
(set_attr "adjust_len" "ufract")]) (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 ; mul
;; "mulqq3" "muluqq3" ;; "mulqq3" "muluqq3"
......
...@@ -91,12 +91,8 @@ extern int avr_starting_frame_offset (void); ...@@ -91,12 +91,8 @@ extern int avr_starting_frame_offset (void);
extern void avr_output_addr_vec_elt (FILE *stream, int value); extern void avr_output_addr_vec_elt (FILE *stream, int value);
extern const char *avr_out_sbxx_branch (rtx insn, rtx operands[]); extern const char *avr_out_sbxx_branch (rtx insn, rtx operands[]);
extern const char* avr_out_bitop (rtx, rtx*, int*); extern const char* avr_out_bitop (rtx, rtx*, int*);
extern const char* avr_out_plus (rtx*, int*, int*); extern const char* avr_out_plus (rtx, rtx*, int* =NULL, int* =NULL);
extern const char* avr_out_plus_noclobber (rtx*, int*, int*);
extern const char* avr_out_plus64 (rtx, int*);
extern const char* avr_out_addto_sp (rtx*, int*); extern const char* avr_out_addto_sp (rtx*, int*);
extern const char* avr_out_minus (rtx*, int*, int*);
extern const char* avr_out_minus64 (rtx, int*);
extern const char* avr_out_xload (rtx, rtx*, int*); extern const char* avr_out_xload (rtx, rtx*, int*);
extern const char* avr_out_movmem (rtx, rtx*, int*); extern const char* avr_out_movmem (rtx, rtx*, int*);
extern const char* avr_out_insert_bits (rtx*, int*); extern const char* avr_out_insert_bits (rtx*, int*);
......
...@@ -91,7 +91,7 @@ ...@@ -91,7 +91,7 @@
;; Condition code settings. ;; Condition code settings.
(define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber, (define_attr "cc" "none,set_czn,set_zn,set_n,compare,clobber,
out_plus, out_plus_noclobber,ldi,minus" plus,ldi"
(const_string "none")) (const_string "none"))
(define_attr "type" "branch,branch1,arith,xcall" (define_attr "type" "branch,branch1,arith,xcall"
...@@ -138,8 +138,7 @@ ...@@ -138,8 +138,7 @@
;; Otherwise do special processing depending on the attribute. ;; Otherwise do special processing depending on the attribute.
(define_attr "adjust_len" (define_attr "adjust_len"
"out_bitop, out_plus, out_plus_noclobber, plus64, addto_sp, "out_bitop, plus, addto_sp,
minus, minus64,
tsthi, tstpsi, tstsi, compare, compare64, call, tsthi, tstpsi, tstsi, compare, compare64, call,
mov8, mov16, mov24, mov32, reload_in16, reload_in24, reload_in32, mov8, mov16, mov24, mov32, reload_in16, reload_in24, reload_in32,
ufract, sfract, ufract, sfract,
...@@ -250,6 +249,10 @@ ...@@ -250,6 +249,10 @@
(define_code_iterator xior [xor ior]) (define_code_iterator xior [xor ior])
(define_code_iterator eqne [eq ne]) (define_code_iterator eqne [eq ne])
(define_code_iterator ss_addsub [ss_plus ss_minus])
(define_code_iterator us_addsub [us_plus us_minus])
(define_code_iterator ss_abs_neg [ss_abs ss_neg])
;; Define code attributes ;; Define code attributes
(define_code_attr extend_su (define_code_attr extend_su
[(sign_extend "s") [(sign_extend "s")
...@@ -268,6 +271,10 @@ ...@@ -268,6 +271,10 @@
[(zero_extend "r") [(zero_extend "r")
(sign_extend "d")]) (sign_extend "d")])
(define_code_attr abelian
[(ss_minus "") (us_minus "")
(ss_plus "%") (us_plus "%")])
;; Map RTX code to its standard insn name ;; Map RTX code to its standard insn name
(define_code_attr code_stdname (define_code_attr code_stdname
[(ashift "ashl") [(ashift "ashl")
...@@ -275,7 +282,10 @@ ...@@ -275,7 +282,10 @@
(lshiftrt "lshr") (lshiftrt "lshr")
(ior "ior") (ior "ior")
(xor "xor") (xor "xor")
(rotate "rotl")]) (rotate "rotl")
(ss_plus "ssadd") (ss_minus "sssub") (ss_neg "ssneg") (ss_abs "ssabs")
(us_plus "usadd") (us_minus "ussub") (us_neg "usneg")
])
;;======================================================================== ;;========================================================================
;; The following is used by nonlocal_goto and setjmp. ;; The following is used by nonlocal_goto and setjmp.
...@@ -1181,17 +1191,11 @@ ...@@ -1181,17 +1191,11 @@
(match_operand:ALL2 2 "nonmemory_or_const_operand" "r,s,IJ YIJ,n Ynn")))] (match_operand:ALL2 2 "nonmemory_or_const_operand" "r,s,IJ YIJ,n Ynn")))]
"" ""
{ {
if (REG_P (operands[2])) return avr_out_plus (insn, operands);
return "add %A0,%A2\;adc %B0,%B2";
else if (CONST_INT_P (operands[2])
|| CONST_FIXED == GET_CODE (operands[2]))
return avr_out_plus_noclobber (operands, NULL, NULL);
else
return "subi %A0,lo8(-(%2))\;sbci %B0,hi8(-(%2))";
} }
[(set_attr "length" "2,2,2,2") [(set_attr "length" "2")
(set_attr "adjust_len" "*,*,out_plus_noclobber,out_plus_noclobber") (set_attr "adjust_len" "plus")
(set_attr "cc" "set_n,set_czn,out_plus_noclobber,out_plus_noclobber")]) (set_attr "cc" "plus")])
;; Adding a constant to NO_LD_REGS might have lead to a reload of ;; Adding a constant to NO_LD_REGS might have lead to a reload of
;; that constant to LD_REGS. We don't add a scratch to *addhi3 ;; that constant to LD_REGS. We don't add a scratch to *addhi3
...@@ -1238,13 +1242,11 @@ ...@@ -1238,13 +1242,11 @@
(clobber (match_scratch:QI 3 "=X ,X ,&d"))] (clobber (match_scratch:QI 3 "=X ,X ,&d"))]
"" ""
{ {
gcc_assert (REGNO (operands[0]) == REGNO (operands[1])); return avr_out_plus (insn, operands);
return avr_out_plus (operands, NULL, NULL);
} }
[(set_attr "length" "4") [(set_attr "length" "4")
(set_attr "adjust_len" "out_plus") (set_attr "adjust_len" "plus")
(set_attr "cc" "out_plus")]) (set_attr "cc" "plus")])
;; "addsi3" ;; "addsi3"
...@@ -1257,14 +1259,11 @@ ...@@ -1257,14 +1259,11 @@
(clobber (match_scratch:QI 3 "=X,X ,&d"))] (clobber (match_scratch:QI 3 "=X,X ,&d"))]
"" ""
{ {
if (REG_P (operands[2])) return avr_out_plus (insn, operands);
return "add %A0,%A2\;adc %B0,%B2\;adc %C0,%C2\;adc %D0,%D2";
return avr_out_plus (operands, NULL, NULL);
} }
[(set_attr "length" "4,4,8") [(set_attr "length" "4")
(set_attr "adjust_len" "*,out_plus,out_plus") (set_attr "adjust_len" "plus")
(set_attr "cc" "set_n,out_plus,out_plus")]) (set_attr "cc" "plus")])
(define_insn "*addpsi3_zero_extend.qi" (define_insn "*addpsi3_zero_extend.qi"
[(set (match_operand:PSI 0 "register_operand" "=r") [(set (match_operand:PSI 0 "register_operand" "=r")
...@@ -1318,22 +1317,11 @@ ...@@ -1318,22 +1317,11 @@
(clobber (match_scratch:QI 3 "=X,X ,X,&d"))] (clobber (match_scratch:QI 3 "=X,X ,X,&d"))]
"" ""
{ {
static const char * const asm_code[] = return avr_out_plus (insn, operands);
{
"add %A0,%A2\;adc %B0,%B2\;adc %C0,%C2",
"subi %0,lo8(-(%2))\;sbci %B0,hi8(-(%2))\;sbci %C0,hlo8(-(%2))",
"",
""
};
if (*asm_code[which_alternative])
return asm_code[which_alternative];
return avr_out_plus (operands, NULL, NULL);
} }
[(set_attr "length" "3,3,3,6") [(set_attr "length" "3")
(set_attr "adjust_len" "*,*,out_plus,out_plus") (set_attr "adjust_len" "plus")
(set_attr "cc" "set_n,set_czn,out_plus,out_plus")]) (set_attr "cc" "plus")])
(define_insn "subpsi3" (define_insn "subpsi3"
[(set (match_operand:PSI 0 "register_operand" "=r") [(set (match_operand:PSI 0 "register_operand" "=r")
...@@ -1401,10 +1389,10 @@ ...@@ -1401,10 +1389,10 @@
(clobber (match_scratch:QI 3 "=X,X ,&d"))] (clobber (match_scratch:QI 3 "=X,X ,&d"))]
"" ""
{ {
return avr_out_minus (operands, NULL, NULL); return avr_out_plus (insn, operands);
} }
[(set_attr "adjust_len" "minus") [(set_attr "adjust_len" "plus")
(set_attr "cc" "minus")]) (set_attr "cc" "plus")])
(define_insn "*subhi3_zero_extend1" (define_insn "*subhi3_zero_extend1"
[(set (match_operand:HI 0 "register_operand" "=r") [(set (match_operand:HI 0 "register_operand" "=r")
...@@ -1438,14 +1426,10 @@ ...@@ -1438,14 +1426,10 @@
(clobber (match_scratch:QI 3 "=X,X ,&d"))] (clobber (match_scratch:QI 3 "=X,X ,&d"))]
"" ""
{ {
if (REG_P (operands[2])) return avr_out_plus (insn, operands);
return "sub %0,%2\;sbc %B0,%B2\;sbc %C0,%C2\;sbc %D0,%D2";
return avr_out_minus (operands, NULL, NULL);
} }
[(set_attr "length" "4") [(set_attr "adjust_len" "plus")
(set_attr "adjust_len" "*,minus,minus") (set_attr "cc" "plus")])
(set_attr "cc" "set_czn")])
(define_insn "*subsi3_zero_extend" (define_insn "*subsi3_zero_extend"
[(set (match_operand:SI 0 "register_operand" "=r") [(set (match_operand:SI 0 "register_operand" "=r")
......
2012-09-15 Georg-Johann Lay <avr@gjlay.de>
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.
2012-09-14 Dehao Chen <dehao@google.com> 2012-09-14 Dehao Chen <dehao@google.com>
* g++.dg/debug/dwarf2/deallocator.C: New test. * g++.dg/debug/dwarf2/deallocator.C: New test.
......
typedef __INT8_TYPE__ int_hr_t;
typedef __UINT8_TYPE__ int_uhr_t;
typedef __INT16_TYPE__ int_hk_t;
typedef __UINT16_TYPE__ int_uhk_t;
typedef __INT16_TYPE__ int_r_t;
typedef __UINT16_TYPE__ int_ur_t;
typedef __INT32_TYPE__ int_k_t;
typedef __UINT32_TYPE__ int_uk_t;
typedef __INT32_TYPE__ int_lr_t;
typedef __UINT32_TYPE__ int_ulr_t;
typedef __INT64_TYPE__ int_lk_t;
typedef __UINT64_TYPE__ int_ulk_t;
typedef __INT64_TYPE__ int_llr_t;
typedef __UINT64_TYPE__ int_ullr_t;
typedef __INT64_TYPE__ int_llk_t;
typedef __UINT64_TYPE__ int_ullk_t;
typedef __INT16_TYPE__ xint_hr_t;
typedef __UINT16_TYPE__ xint_uhr_t;
typedef __INT32_TYPE__ xint_hk_t;
typedef __UINT32_TYPE__ xint_uhk_t;
typedef __INT32_TYPE__ xint_r_t;
typedef __UINT32_TYPE__ xint_ur_t;
typedef __INT64_TYPE__ xint_k_t;
typedef __UINT64_TYPE__ xint_uk_t;
typedef __INT64_TYPE__ xint_lr_t;
typedef __UINT64_TYPE__ xint_ulr_t;
#define INThr_MAX __INT8_MAX__
#define INThr_MIN (-__INT8_MAX__-1)
#define INTuhr_MAX __UINT8_MAX__
#define INTr_MAX __INT16_MAX__
#define INTr_MIN (-__INT16_MAX__-1)
#define INTur_MAX __UINT16_MAX__
#define INThk_MAX __INT16_MAX__
#define INThk_MIN (-__INT16_MAX__-1)
#define INTuhk_MAX __UINT16_MAX__
#define INTlr_MAX __INT32_MAX__
#define INTlr_MIN (-__INT32_MAX__-1)
#define INTulr_MAX __UINT32_MAX__
#define INTk_MAX __INT32_MAX__
#define INTk_MIN (-__INT32_MAX__-1)
#define INTuk_MAX __UINT32_MAX__
#define INTlk_MAX __INT64_MAX__
#define INTlk_MIN (-__INT64_MAX__-1)
#define INTulk_MAX __UINT64_MAX__
#define INTllk_MAX __INT64_MAX__
#define INTllk_MIN (-__INT64_MAX__-1)
#define INTullk_MAX __UINT64_MAX__
#define SS_FUN(NAME, OP, T, FX) \
T __attribute__((noinline,noclone)) \
NAME##_##FX (T fa, T fb) \
{ \
int_##FX##_t ia; \
int_##FX##_t ib; \
xint_##FX##_t ic; \
__builtin_memcpy (&ia, &fa, sizeof (ia)); \
__builtin_memcpy (&ib, &fb, sizeof (ib)); \
ic = (xint_##FX##_t) ia OP ib; \
if (ic > INT##FX##_MAX) \
ic = INT##FX##_MAX; \
else if (ic < INT##FX##_MIN) \
ic = INT##FX##_MIN; \
ia = (int_##FX##_t) ic; \
__builtin_memcpy (&fa, &ia, sizeof (ia)); \
return fa; \
}
#define US_FUN(NAME, OP, T, FX) \
T __attribute__((noinline,noclone)) \
NAME##_##FX (T fa, T fb) \
{ \
int_##FX##_t ia; \
int_##FX##_t ib; \
xint_##FX##_t ic; \
__builtin_memcpy (&ia, &fa, sizeof (ia)); \
__builtin_memcpy (&ib, &fb, sizeof (ib)); \
ic = (xint_##FX##_t) ia OP ib; \
if (ic > INT##FX##_MAX) \
ic = INT##FX##_MAX; \
else if (ic < 0) \
ic = 0; \
ia = (int_##FX##_t) ic; \
__builtin_memcpy (&fa, &ia, sizeof (ia)); \
return fa; \
}
#define SS_LFUN(NAME, OP, T, FX, CMP) \
T __attribute__((noinline,noclone)) \
NAME##_##FX (T fa, T fb) \
{ \
int_##FX##_t ia; \
int_##FX##_t ib; \
int_##FX##_t ic; \
__builtin_memcpy (&ia, &fa, sizeof (ia)); \
__builtin_memcpy (&ib, &fb, sizeof (ib)); \
ic = (int_##FX##_t) ia OP ib; \
if (ic < ia && ib CMP 0) \
ic = INT##FX##_MAX; \
else if (ic > ia && 0 CMP ib) \
ic = INT##FX##_MIN; \
__builtin_memcpy (&fa, &ic, sizeof (ic)); \
return fa; \
}
#define US_LFUN(NAME, OP, T, FX, CMP) \
T __attribute__((noinline,noclone)) \
NAME##_##FX (T fa, T fb) \
{ \
int_##FX##_t ia; \
int_##FX##_t ib; \
int_##FX##_t ic; \
__builtin_memcpy (&ia, &fa, sizeof (ia)); \
__builtin_memcpy (&ib, &fb, sizeof (ib)); \
ic = (int_##FX##_t) ia OP ib; \
if (ia CMP ic && 1 CMP 0) \
ic = INT##FX##_MAX; \
if (ia CMP ic && 0 CMP 1) \
ic = 0; \
__builtin_memcpy (&fa, &ic, sizeof (ic)); \
return fa; \
}
/* { dg-do run } */
/* { dg-options "-std=gnu99 -fwrapv" } */
#include "fix-types.h"
extern void abort (void);
extern void exit (int);
typedef short _Fract fx_t;
typedef short _Sat _Fract satfx_t;
typedef char intfx_t;
SS_FUN (ss_add, +, fx_t, hr)
SS_FUN (ss_sub, -, fx_t, hr)
#define VAL(N, X) \
__attribute__((noinline,noclone)) \
satfx_t ss_add2_##N (satfx_t a) \
{ \
return ss_add_hr (a, X##P##-##7hr); \
} \
__attribute__((noinline,noclone)) \
satfx_t ss_add_##N (satfx_t a) \
{ \
return a + X##P##-##7hr; \
} \
__attribute__((noinline,noclone)) \
satfx_t ss_sub2_##N (satfx_t a) \
{ \
return ss_sub_hr (a, X##P##-##7hr); \
} \
__attribute__((noinline,noclone)) \
satfx_t ss_sub_##N (satfx_t a) \
{ \
return a - X##P##-##7hr; \
}
#include "vals-hr.def"
#undef VAL
__attribute__((noinline,noclone))
satfx_t ss_add2_99 (satfx_t a)
{
return ss_add_hr (a, __FRACT_MIN__);
}
__attribute__((noinline,noclone))
satfx_t ss_add_99 (satfx_t a)
{
return a + __FRACT_MIN__;
}
__attribute__((noinline,noclone))
satfx_t ss_sub2_99 (satfx_t a)
{
return ss_sub_hr (a, __FRACT_MIN__);
}
__attribute__((noinline,noclone))
satfx_t ss_sub_99 (satfx_t a)
{
return a - __FRACT_MIN__;
}
satfx_t (* __flash const fun[])(satfx_t) =
{
#define VAL(N, X) \
ss_add_##N, ss_add2_##N, \
ss_sub_##N, ss_sub2_##N,
#include "vals-hr.def"
VAL (99,)
#undef VAL
};
const volatile __flash intfx_t vals[] =
{
0, 1, 2, 0x7f, 0x80, 0x81, 0xff,
0x40, 0x3e, 0x3f, 0xbf, 0xc0, 0xc1
};
int main (void)
{
for (unsigned int i = 0; i < sizeof (vals) / sizeof (*vals); i++)
{
satfx_t a, f1, f2;
intfx_t val = vals[i];
__builtin_memcpy (&a, &val, sizeof (satfx_t));
for (unsigned int f = 0; f < sizeof (fun) / sizeof (*fun); f += 2)
{
if (fun[f](a) != fun[f+1](a))
abort();
}
}
exit (0);
return 0;
}
/* { dg-do run } */
/* { dg-options "-std=gnu99 -fwrapv" } */
#include "fix-types.h"
extern void abort (void);
extern void exit (int);
typedef _Accum fx_t;
typedef _Sat _Accum satfx_t;
typedef long intfx_t;
SS_FUN (ss_add, +, fx_t, k)
SS_FUN (ss_sub, -, fx_t, k)
#define VAL(N, X) \
__attribute__((noinline,noclone)) \
satfx_t ss_add2_##N (satfx_t a) \
{ \
return ss_add_k (a, X##P##-##16k); \
} \
__attribute__((noinline,noclone)) \
satfx_t ss_add_##N (satfx_t a) \
{ \
return a + X##P##-##16k; \
} \
__attribute__((noinline,noclone)) \
satfx_t ss_sub2_##N (satfx_t a) \
{ \
return ss_sub_k (a, X##P##-##16k); \
} \
__attribute__((noinline,noclone)) \
satfx_t ss_sub_##N (satfx_t a) \
{ \
return a - X##P##-##16k; \
}
#include "vals-k.def"
#undef VAL
__attribute__((noinline,noclone))
satfx_t ss_add2_99 (satfx_t a)
{
return ss_add_k (a, __ACCUM_MIN__);
}
__attribute__((noinline,noclone))
satfx_t ss_add_99 (satfx_t a)
{
return a + __ACCUM_MIN__;
}
__attribute__((noinline,noclone))
satfx_t ss_sub2_99 (satfx_t a)
{
return ss_sub_k (a, __ACCUM_MIN__);
}
__attribute__((noinline,noclone))
satfx_t ss_sub_99 (satfx_t a)
{
return a - __ACCUM_MIN__;
}
satfx_t (* __flash const fun[])(satfx_t) =
{
#define VAL(N, X) \
ss_add_##N, ss_add2_##N, \
ss_sub_##N, ss_sub2_##N,
#include "vals-k.def"
VAL (99,)
#undef VAL
};
const volatile __flash intfx_t vals[] =
{
0, -1, 1, -2, 2, -127, -128, -129,
0x7f, 0x80, 0x81, 0x100,
0x40000000, 0x3e800000, 0x3f800000,
0x7ffffffe, 0x7fffffff, 0x7f800000,
0x7f7f7f7f, 0x7f810080, 0x7f008000,
0x7f000001,
0x80000000, 0x80000001, 0x80808080,
0x80810000, 0x80ffffff, 0x80fffffe,
0x81000000, 0x81800000, 0x81800000,
0xff000000, 0xffffff01, 0xffffff80,
0xffffff7f, 0xff80ff80
};
int main (void)
{
for (unsigned int i = 0; i < sizeof (vals) / sizeof (*vals); i++)
{
satfx_t a, f1, f2;
intfx_t val = vals[i];
__builtin_memcpy (&a, &val, sizeof (satfx_t));
for (unsigned int f = 0; f < sizeof (fun) / sizeof (*fun); f += 2)
{
if (fun[f](a) != fun[f+1](a))
abort();
}
}
exit (0);
return 0;
}
/* { dg-do run } */
/* { dg-options "-std=gnu99 -fwrapv" } */
#include "fix-types.h"
extern void abort (void);
extern void exit (int);
typedef long long _Accum fx_t;
typedef long long _Sat _Accum satfx_t;
typedef long long intfx_t;
SS_LFUN (ss_add, +, fx_t, llk, >)
SS_LFUN (ss_sub, -, fx_t, llk, <)
#define VAL(N, X) \
__attribute__((noinline,noclone)) \
satfx_t ss_add2_##N (satfx_t a) \
{ \
return ss_add_llk (a, X##P##-##48llk); \
} \
__attribute__((noinline,noclone)) \
satfx_t ss_add_##N (satfx_t a) \
{ \
return a + X##P##-##48llk; \
} \
__attribute__((noinline,noclone)) \
satfx_t ss_sub2_##N (satfx_t a) \
{ \
return ss_sub_llk (a, X##P##-##48llk); \
} \
__attribute__((noinline,noclone)) \
satfx_t ss_sub_##N (satfx_t a) \
{ \
return a - X##P##-##48llk; \
}
#include "vals-llk.def"
#undef VAL
__attribute__((noinline,noclone))
satfx_t ss_add2_99 (satfx_t a)
{
return ss_add_llk (a, __LLACCUM_MIN__);
}
__attribute__((noinline,noclone))
satfx_t ss_add_99 (satfx_t a)
{
return a + __LLACCUM_MIN__;
}
__attribute__((noinline,noclone))
satfx_t ss_sub2_99 (satfx_t a)
{
return ss_sub_llk (a, __LLACCUM_MIN__);
}
__attribute__((noinline,noclone))
satfx_t ss_sub_99 (satfx_t a)
{
return a - __LLACCUM_MIN__;
}
satfx_t (* __flash const fun[])(satfx_t) =
{
#define VAL(N, X) \
ss_add_##N, ss_add2_##N, \
ss_sub_##N, ss_sub2_##N,
#include "vals-llk.def"
VAL (99,)
#undef VAL
};
const volatile __flash intfx_t vals[] =
{
0, -1, 1, -2, 2, -127, -128, -129,
0x7f, 0x80, 0x81, 0x100,
0x4000000000000000, 0x3e80000000000000, 0x3f80000000000000,
0x7ffffffffffffffe, 0x7fffffffffffffff, 0x7f80000000000000,
0x7f7f7f7f7f7f7f7f, 0x7f81000000000080, 0x7f00000080000000,
0x7f00000000000001,
0x8000000000000000, 0x8000000000000001, 0x8080808080808080,
0x8081000000000000, 0x80ffffffffffffff, 0x80fffffffffffffe,
0x8100000000000000, 0x8180000000000000, 0x818000000000000,
0xff00000000000000, 0xffffffffffffff01, 0xffffffffffffff80,
0xffffffffffffff7f, 0xff80ff80ff80ff80
};
int main (void)
{
for (unsigned int i = 0; i < sizeof (vals) / sizeof (*vals); i++)
{
satfx_t a, f1, f2;
intfx_t val = vals[i];
__builtin_memcpy (&a, &val, sizeof (satfx_t));
for (unsigned int f = 0; f < sizeof (fun) / sizeof (*fun); f += 2)
{
if (fun[f](a) != fun[f+1](a))
abort();
}
}
exit (0);
return 0;
}
/* { dg-do run } */
/* { dg-options "-std=gnu99 -fwrapv" } */
#include "fix-types.h"
extern void abort (void);
extern void exit (int);
typedef _Fract fx_t;
typedef _Sat _Fract satfx_t;
typedef int intfx_t;
SS_FUN (ss_add, +, fx_t, r)
SS_FUN (ss_sub, -, fx_t, r)
#define VAL(N, X) \
__attribute__((noinline,noclone)) \
satfx_t ss_add2_##N (satfx_t a) \
{ \
return ss_add_r (a, X##P##-##15r); \
} \
__attribute__((noinline,noclone)) \
satfx_t ss_add_##N (satfx_t a) \
{ \
return a + X##P##-##15r; \
} \
__attribute__((noinline,noclone)) \
satfx_t ss_sub2_##N (satfx_t a) \
{ \
return ss_sub_r (a, X##P##-##15r); \
} \
__attribute__((noinline,noclone)) \
satfx_t ss_sub_##N (satfx_t a) \
{ \
return a - X##P##-##15r; \
}
#include "vals-r.def"
#undef VAL
__attribute__((noinline,noclone))
satfx_t ss_add2_99 (satfx_t a)
{
return ss_add_r (a, __FRACT_MIN__);
}
__attribute__((noinline,noclone))
satfx_t ss_add_99 (satfx_t a)
{
return a + __FRACT_MIN__;
}
__attribute__((noinline,noclone))
satfx_t ss_sub2_99 (satfx_t a)
{
return ss_sub_r (a, __FRACT_MIN__);
}
__attribute__((noinline,noclone))
satfx_t ss_sub_99 (satfx_t a)
{
return a - __FRACT_MIN__;
}
satfx_t (* __flash const fun[])(satfx_t) =
{
#define VAL(N, X) \
ss_add_##N, ss_add2_##N, \
ss_sub_##N, ss_sub2_##N,
#include "vals-r.def"
VAL (99,)
#undef VAL
};
const volatile __flash intfx_t vals[] =
{
0, -1, 1, -2, 2, -127, -128, -129,
0x7f, 0x80, 0x81, 0x100,
0x4000, 0x3e80, 0x3f80,
0x7ffe, 0x7fff,
0x7f7f, 0x7f81, 0x7f80,
0x7f01,
0x8000, 0x8001, 0x8080,
0x8081, 0x80ff, 0x80fe,
0x8100, 0x8180, 0x817f,
0xff00, 0xff01, 0xff01,
0xff7f, 0xff80
};
int main (void)
{
for (unsigned int i = 0; i < sizeof (vals) / sizeof (*vals); i++)
{
satfx_t a, f1, f2;
intfx_t val = vals[i];
__builtin_memcpy (&a, &val, sizeof (satfx_t));
for (unsigned int f = 0; f < sizeof (fun) / sizeof (*fun); f += 2)
{
if (fun[f](a) != fun[f+1](a))
abort();
}
}
exit (0);
return 0;
}
/* { dg-do run } */
/* { dg-options "-std=gnu99 -fwrapv" } */
#include "fix-types.h"
extern void abort (void);
extern void exit (int);
typedef unsigned short _Fract fx_t;
typedef unsigned short _Sat _Fract satfx_t;
typedef unsigned char intfx_t;
US_LFUN (us_add, +, fx_t, uhr, >)
US_LFUN (us_sub, -, fx_t, uhr, <)
#define VAL(N, X) \
__attribute__((noinline,noclone)) \
satfx_t us_add2_##N (satfx_t a) \
{ \
return us_add_uhr (a, X##P##-##8uhr); \
} \
__attribute__((noinline,noclone)) \
satfx_t us_add_##N (satfx_t a) \
{ \
return a + X##P##-##8uhr; \
} \
__attribute__((noinline,noclone)) \
satfx_t us_sub2_##N (satfx_t a) \
{ \
return us_sub_uhr (a, X##P##-##8uhr); \
} \
__attribute__((noinline,noclone)) \
satfx_t us_sub_##N (satfx_t a) \
{ \
return a - X##P##-##8uhr; \
}
#include "vals-uhr.def"
#undef VAL
satfx_t (* __flash const fun[])(satfx_t) =
{
#define VAL(N, X) \
us_add_##N, us_add2_##N, \
us_sub_##N, us_sub2_##N,
#include "vals-uhr.def"
#undef VAL
};
const volatile __flash intfx_t vals[] =
{
0, 1, 2, 0x7f, 0x80, 0x81, 0xff,
0x40, 0x3e, 0x3f, 0xbf, 0xc0, 0xc1
};
int main (void)
{
for (unsigned int i = 0; i < sizeof (vals) / sizeof (*vals); i++)
{
satfx_t a, f1, f2;
intfx_t val = vals[i];
__builtin_memcpy (&a, &val, sizeof (satfx_t));
for (unsigned int f = 0; f < sizeof (fun) / sizeof (*fun); f += 2)
{
if (fun[f](a) != fun[f+1](a))
abort();
}
}
exit (0);
return 0;
}
/* { dg-do run } */
/* { dg-options "-std=gnu99 -fwrapv" } */
#include "fix-types.h"
extern void abort (void);
extern void exit (int);
typedef unsigned _Accum fx_t;
typedef unsigned _Sat _Accum satfx_t;
typedef unsigned long intfx_t;
US_LFUN (us_add, +, fx_t, uk, >)
US_LFUN (us_sub, -, fx_t, uk, <)
#define VAL(N, X) \
__attribute__((noinline,noclone)) \
satfx_t us_add2_##N (satfx_t a) \
{ \
return us_add_uk (a, X##P##-##16uk); \
} \
__attribute__((noinline,noclone)) \
satfx_t us_add_##N (satfx_t a) \
{ \
return a + X##P##-##16uk; \
} \
__attribute__((noinline,noclone)) \
satfx_t us_sub2_##N (satfx_t a) \
{ \
return us_sub_uk (a, X##P##-##16uk); \
} \
__attribute__((noinline,noclone)) \
satfx_t us_sub_##N (satfx_t a) \
{ \
return a - X##P##-##16uk; \
}
#include "vals-uk.def"
#undef VAL
satfx_t (* __flash const fun[])(satfx_t) =
{
#define VAL(N, X) \
us_add_##N, us_add2_##N, \
us_sub_##N, us_sub2_##N,
#include "vals-uk.def"
#undef VAL
};
const volatile __flash intfx_t vals[] =
{
0, -1, 1, -2, 2, -127, -128, -129,
0x7f, 0x80, 0x81, 0x100,
0x40000000, 0x3e800000, 0x3f800000,
0x7ffffffe, 0x7fffffff, 0x7f800000,
0x7f7f7f7f, 0x7f810080, 0x7f008000,
0x7f000001,
0x80000000, 0x80000001, 0x80808080,
0x80810000, 0x80ffffff, 0x80fffffe,
0x81000000, 0x81800000, 0x81800000,
0xff000000, 0xffffff01, 0xffffff80,
0xffffff7f, 0xff80ff80
};
int main (void)
{
for (unsigned int i = 0; i < sizeof (vals) / sizeof (*vals); i++)
{
satfx_t a, f1, f2;
intfx_t val = vals[i];
__builtin_memcpy (&a, &val, sizeof (satfx_t));
for (unsigned int f = 0; f < sizeof (fun) / sizeof (*fun); f += 2)
{
if (fun[f](a) != fun[f+1](a))
abort();
}
}
exit (0);
return 0;
}
/* { dg-do run } */
/* { dg-options "-std=gnu99 -fwrapv" } */
#include "fix-types.h"
extern void abort (void);
extern void exit (int);
typedef unsigned long long _Accum fx_t;
typedef unsigned long long _Sat _Accum satfx_t;
typedef unsigned long long intfx_t;
US_LFUN (us_add, +, fx_t, ullk, >)
US_LFUN (us_sub, -, fx_t, ullk, <)
#define VAL(N, X) \
__attribute__((noinline,noclone)) \
satfx_t us_add2_##N (satfx_t a) \
{ \
return us_add_ullk (a, X##P##-##48ullk); \
} \
__attribute__((noinline,noclone)) \
satfx_t us_add_##N (satfx_t a) \
{ \
return a + X##P##-##48ullk; \
} \
__attribute__((noinline,noclone)) \
satfx_t us_sub2_##N (satfx_t a) \
{ \
return us_sub_ullk (a, X##P##-##48ullk); \
} \
__attribute__((noinline,noclone)) \
satfx_t us_sub_##N (satfx_t a) \
{ \
return a - X##P##-##48ullk; \
}
#include "vals-ullk.def"
#undef VAL
satfx_t (* __flash const fun[])(satfx_t) =
{
#define VAL(N, X) \
us_add_##N, us_add2_##N, \
us_sub_##N, us_sub2_##N,
#include "vals-ullk.def"
#undef VAL
};
const volatile __flash intfx_t vals[] =
{
0, -1, 1, -2, 2, -127, -128, -129,
0x7f, 0x80, 0x81, 0x100,
0x4000000000000000, 0x3e80000000000000, 0x3f80000000000000,
0x7ffffffffffffffe, 0x7fffffffffffffff, 0x7f80000000000000,
0x7f7f7f7f7f7f7f7f, 0x7f81000000000080, 0x7f00000080000000,
0x7f00000000000001,
0x8000000000000000, 0x8000000000000001, 0x8080808080808080,
0x8081000000000000, 0x80ffffffffffffff, 0x80fffffffffffffe,
0x8100000000000000, 0x8180000000000000, 0x818000000000000,
0xff00000000000000, 0xffffffffffffff01, 0xffffffffffffff80,
0xffffffffffffff7f, 0xff80ff80ff80ff80
};
int main (void)
{
for (unsigned int i = 0; i < sizeof (vals) / sizeof (*vals); i++)
{
satfx_t a, f1, f2;
intfx_t val = vals[i];
__builtin_memcpy (&a, &val, sizeof (satfx_t));
for (unsigned int f = 0; f < sizeof (fun) / sizeof (*fun); f += 2)
{
if (fun[f](a) != fun[f+1](a))
abort();
}
}
exit (0);
return 0;
}
/* { dg-do run } */
/* { dg-options "-std=gnu99 -fwrapv" } */
#include "fix-types.h"
extern void abort (void);
extern void exit (int);
typedef unsigned _Fract fx_t;
typedef unsigned _Sat _Fract satfx_t;
typedef unsigned int intfx_t;
US_LFUN (us_add, +, fx_t, ur, >)
US_LFUN (us_sub, -, fx_t, ur, <)
#define VAL(N, X) \
__attribute__((noinline,noclone)) \
satfx_t us_add2_##N (satfx_t a) \
{ \
return us_add_ur (a, X##P##-##16ur); \
} \
__attribute__((noinline,noclone)) \
satfx_t us_add_##N (satfx_t a) \
{ \
return a + X##P##-##16ur; \
} \
__attribute__((noinline,noclone)) \
satfx_t us_sub2_##N (satfx_t a) \
{ \
return us_sub_ur (a, X##P##-##16ur); \
} \
__attribute__((noinline,noclone)) \
satfx_t us_sub_##N (satfx_t a) \
{ \
return a - X##P##-##16ur; \
}
#include "vals-ur.def"
#undef VAL
satfx_t (* __flash const fun[])(satfx_t) =
{
#define VAL(N, X) \
us_add_##N, us_add2_##N, \
us_sub_##N, us_sub2_##N,
#include "vals-ur.def"
#undef VAL
};
const volatile __flash intfx_t vals[] =
{
0, -1, 1, -2, 2, -127, -128, -129,
0x7f, 0x80, 0x81, 0x100,
0x4000, 0x3e80, 0x3f80,
0x7ffe, 0x7fff,
0x7f7f, 0x7f81, 0x7f80,
0x7f01,
0x8000, 0x8001, 0x8080,
0x8081, 0x80ff, 0x80fe,
0x8100, 0x8180, 0x817f,
0xff00, 0xff01, 0xff01,
0xff7f, 0xff80
};
int main (void)
{
for (unsigned int i = 0; i < sizeof (vals) / sizeof (*vals); i++)
{
satfx_t a, f1, f2;
intfx_t val = vals[i];
__builtin_memcpy (&a, &val, sizeof (satfx_t));
for (unsigned int f = 0; f < sizeof (fun) / sizeof (*fun); f += 2)
{
if (fun[f](a) != fun[f+1](a))
abort();
}
}
exit (0);
return 0;
}
VAL (01, 0x0)
VAL (02, 0x1)
VAL (03, 0x3f)
VAL (04,-0x3f)
VAL (07, 0x40)
VAL (08,-0x40)
VAL (10,-0x1)
VAL (12, 0x3f)
VAL (13,-0x3f)
VAL (14, 0x7f)
VAL (15,-0x7f)
VAL (01, 0x0)
VAL (02, 0x1)
VAL (03, 0x3f)
VAL (04, 0x80)
VAL (05, -0x1)
VAL (06, -0x3f)
VAL (07, 0x40000000)
VAL (08,-0x40000000)
VAL (10,-0x7fffffff)
VAL (11, 0x7fffffff)
VAL (12, 0x7f800000)
VAL (13,-0x7f800000)
VAL (14, 0x7f800001)
VAL (15,-0x7f800001)
VAL (16, 0x7f7f7f7f)
VAL (17,-0x7f7f7f7f)
VAL (18, 0x7f808080)
VAL (19,-0x7f808080)
VAL (20, 0x3e800000)
VAL (21,-0x3e800000)
VAL (22, 0x3f800000)
VAL (23,-0x3f800000)
VAL (24, 0x400000)
VAL (25,-0x400000)
VAL (26, 0x3f000000)
VAL (27,-0x3f000000)
VAL (28, 0xffff00)
VAL (29,-0xffff00)
VAL (30, 0x00ff00ff)
VAL (31,-0x00ff00ff)
VAL (01, 0x0)
VAL (02, 0x1)
VAL (03, 0x3f)
VAL (04, 0x80)
VAL (05, -0x1)
VAL (06, -0x3f)
VAL (07, 0x4000000000000000)
VAL (08,-0x4000000000000000)
VAL (10,-0x7fffffffffffffff)
VAL (11, 0x7fffffffffffffff)
VAL (12, 0x7f80000000000000)
VAL (13,-0x7f80000000000000)
VAL (14, 0x7f80000000000001)
VAL (15,-0x7f80000000000001)
VAL (16, 0x7f7f7f7f7f7f7f7f)
VAL (17,-0x7f7f7f7f7f7f7f7f)
VAL (18, 0x7f80808080808000)
VAL (19,-0x7f80808080808000)
VAL (20, 0x3e80000000000000)
VAL (21,-0x3e80000000000000)
VAL (22, 0x3f80000000000000)
VAL (23,-0x3f80000000000000)
VAL (24, 0x40000000000000)
VAL (25,-0x40000000000000)
VAL (26, 0x3f000000000000)
VAL (27,-0x3f000000000000)
VAL (28, 0xffffff00)
VAL (29,-0xffffff00)
VAL (30, 0x00ff00ff00ff00ff)
VAL (31,-0x00ff00ff00ff00ff)
VAL (01, 0x0)
VAL (02, 0x1)
VAL (03, 0x3f)
VAL (04, 0x80)
VAL (05, -0x1)
VAL (06, -0x3f)
VAL (07, 0x4000)
VAL (08,-0x4000)
VAL (10,-0x7fff)
VAL (11, 0x7fff)
VAL (12, 0x7f80)
VAL (13,-0x7f80)
VAL (14, 0x7f81)
VAL (15,-0x7f81)
VAL (16, 0x7f7f)
VAL (17,-0x7f7f)
VAL (18, 0x7f80)
VAL (19,-0x7f80)
VAL (20, 0x3e80)
VAL (21,-0x3e80)
VAL (22, 0x3f80)
VAL (23,-0x3f80)
VAL (24, 0x40)
VAL (25,-0x40)
VAL (26, 0x3f00)
VAL (27,-0x3f00)
VAL (30, 0x00ff)
VAL (31,-0x00ff)
VAL (01, 0x0)
VAL (02, 0x1)
VAL (03, 0x3f)
VAL (07, 0x40)
VAL (08, 0xc0)
VAL (10, 0xc1)
VAL (12, 0xff)
VAL (14, 0x7f)
VAL (16, 0x81)
VAL (20, 0xbf)
VAL (99, 0x80)
VAL (01, 0x0)
VAL (02, 0x1)
VAL (03, 0x3f)
VAL (04, 0x80)
VAL (07, 0x40000000)
VAL (08, 0xc0000000)
VAL (10, 0x7fffffff)
VAL (12, 0x7f800000)
VAL (14, 0x7f800001)
VAL (16, 0x7f7f7f7f)
VAL (18, 0x7f808000)
VAL (20, 0x3e800000)
VAL (22, 0x3f800000)
VAL (24, 0x40000000)
VAL (26, 0x3f000000)
VAL (28, 0xffff00)
VAL (30, 0x00ff00ff)
VAL (31, 0xff00ff00)
VAL (32, 0x10000000)
VAL (33, 0xff000000)
VAL (99, 0x80000000)
VAL (01, 0x0)
VAL (02, 0x1)
VAL (03, 0x3f)
VAL (04, 0x80)
VAL (07, 0x4000000000000000)
VAL (08, 0x4000000000000000)
VAL (10, 0x7fffffffffffffff)
VAL (12, 0x7f80000000000000)
VAL (14, 0x7f80000000000001)
VAL (16, 0x7f7f7f7f7f7f7f7f)
VAL (18, 0x7f80808080808000)
VAL (20, 0x3e80000000000000)
VAL (22, 0x3f80000000000000)
VAL (24, 0x40000000000000)
VAL (26, 0x3f000000000000)
VAL (28, 0xffffff00)
VAL (30, 0x00ff00ff00ff00ff)
VAL (99, 0x8000000000000000)
VAL (01, 0x0)
VAL (02, 0x1)
VAL (03, 0x3f)
VAL (04, 0x80)
VAL (07, 0x4000)
VAL (08, 0xc000)
VAL (10, 0x7fff)
VAL (12, 0x7f80)
VAL (14, 0x7f81)
VAL (16, 0x7f7f)
VAL (20, 0x3e80)
VAL (22, 0x3f80)
VAL (26, 0x3f00)
VAL (32, 0x100)
VAL (99, 0x8000)
2012-09-15 Georg-Johann Lay <avr@gjlay.de>
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.
2012-09-10 Oleg Endo <olegendo@gcc.gnu.org> 2012-09-10 Oleg Endo <olegendo@gcc.gnu.org>
PR target/54089 PR target/54089
......
...@@ -808,8 +808,8 @@ DEFUN __divsa3 ...@@ -808,8 +808,8 @@ DEFUN __divsa3
XCALL __udivusa3 XCALL __udivusa3
sbrs r0, 7 ; negate result if needed sbrs r0, 7 ; negate result if needed
ret ret
NEG4 r_quoL ;; negate r_quoL
ret XJMP __negsi2
ENDF __divsa3 ENDF __divsa3
#endif /* defined (L_divsa3) */ #endif /* defined (L_divsa3) */
...@@ -872,3 +872,223 @@ ENDF __udivusa3 ...@@ -872,3 +872,223 @@ ENDF __udivusa3
#undef r_divHL #undef r_divHL
#undef r_divHH #undef r_divHH
#undef r_cnt #undef r_cnt
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Saturation, 2 Bytes
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; First Argument and Return Register
#define A0 24
#define A1 A0+1
#if defined (L_ssneg_2)
DEFUN __ssneg_2
NEG2 A0
brvc 0f
sbiw A0, 1
0: ret
ENDF __ssneg_2
#endif /* L_ssneg_2 */
#if defined (L_ssabs_2)
DEFUN __ssabs_2
sbrs A1, 7
ret
XJMP __ssneg_2
ENDF __ssabs_2
#endif /* L_ssabs_2 */
#undef A0
#undef A1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Saturation, 4 Bytes
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; First Argument and Return Register
#define A0 22
#define A1 A0+1
#define A2 A0+2
#define A3 A0+3
#if defined (L_ssneg_4)
DEFUN __ssneg_4
XCALL __negsi2
brvc 0f
ldi A3, 0x7f
ldi A2, 0xff
ldi A1, 0xff
ldi A0, 0xff
0: ret
ENDF __ssneg_4
#endif /* L_ssneg_4 */
#if defined (L_ssabs_4)
DEFUN __ssabs_4
sbrs A3, 7
ret
XJMP __ssneg_4
ENDF __ssabs_4
#endif /* L_ssabs_4 */
#undef A0
#undef A1
#undef A2
#undef A3
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Saturation, 8 Bytes
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; First Argument and Return Register
#define A0 18
#define A1 A0+1
#define A2 A0+2
#define A3 A0+3
#define A4 A0+4
#define A5 A0+5
#define A6 A0+6
#define A7 A0+7
#if defined (L_clr_8)
FALIAS __usneguta2
FALIAS __usneguda2
FALIAS __usnegudq2
;; Clear Carry and all Bytes
DEFUN __clr_8
;; Clear Carry and set Z
sub A7, A7
;; FALLTHRU
ENDF __clr_8
;; Propagate Carry to all Bytes, Carry unaltered
DEFUN __sbc_8
sbc A7, A7
sbc A6, A6
wmov A4, A6
wmov A2, A6
wmov A0, A6
ret
ENDF __sbc_8
#endif /* L_clr_8 */
#if defined (L_ssneg_8)
FALIAS __ssnegta2
FALIAS __ssnegda2
FALIAS __ssnegdq2
DEFUN __ssneg_8
XCALL __negdi2
brvc 0f
;; A[] = 0x7fffffff
sec
XCALL __sbc_8
ldi A7, 0x7f
0: ret
ENDF __ssneg_8
#endif /* L_ssneg_8 */
#if defined (L_ssabs_8)
FALIAS __ssabsta2
FALIAS __ssabsda2
FALIAS __ssabsdq2
DEFUN __ssabs_8
sbrs A7, 7
ret
XJMP __ssneg_8
ENDF __ssabs_8
#endif /* L_ssabs_8 */
;; Second Argument
#define B0 10
#define B1 B0+1
#define B2 B0+2
#define B3 B0+3
#define B4 B0+4
#define B5 B0+5
#define B6 B0+6
#define B7 B0+7
#if defined (L_usadd_8)
FALIAS __usadduta3
FALIAS __usadduda3
FALIAS __usaddudq3
DEFUN __usadd_8
XCALL __adddi3
brcs 0f
ret
;; A[] = 0xffffffff
0: XJMP __sbc_8
ENDF __usadd_8
#endif /* L_usadd_8 */
#if defined (L_ussub_8)
FALIAS __ussubuta3
FALIAS __ussubuda3
FALIAS __ussubudq3
DEFUN __ussub_8
XCALL __subdi3
brcs 0f
ret
;; A[] = 0
0: XJMP __clr_8
ENDF __ussub_8
#endif /* L_ussub_8 */
#if defined (L_ssadd_8)
FALIAS __ssaddta3
FALIAS __ssaddda3
FALIAS __ssadddq3
DEFUN __ssadd_8
;; A = (B >= 0) ? INT64_MAX : INT64_MIN
XCALL __adddi3
brvc 0f
cpi B7, 0x80
XCALL __sbc_8
subi A7, 0x80
0: ret
ENDF __ssadd_8
#endif /* L_ssadd_8 */
#if defined (L_sssub_8)
FALIAS __sssubta3
FALIAS __sssubda3
FALIAS __sssubdq3
DEFUN __sssub_8
XCALL __subdi3
brvc 0f
;; A = (B < 0) ? INT64_MAX : INT64_MIN
ldi A7, 0x7f
cp A7, B7
XCALL __sbc_8
subi A7, 0x80
0: ret
ENDF __sssub_8
#endif /* L_sssub_8 */
#undef A0
#undef A1
#undef A2
#undef A3
#undef A4
#undef A5
#undef A6
#undef A7
#undef B0
#undef B1
#undef B2
#undef B3
#undef B4
#undef B5
#undef B6
#undef B7
...@@ -91,6 +91,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ...@@ -91,6 +91,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
.endfunc .endfunc
.endm .endm
.macro FALIAS name
.global \name
.func \name
\name:
.size \name, .-\name
.endfunc
.endm
;; Negate a 2-byte value held in consecutive registers ;; Negate a 2-byte value held in consecutive registers
.macro NEG2 reg .macro NEG2 reg
com \reg+1 com \reg+1
...@@ -99,6 +107,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ...@@ -99,6 +107,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
.endm .endm
;; Negate a 4-byte value held in consecutive registers ;; Negate a 4-byte value held in consecutive registers
;; Sets the V flag for signed overflow tests if REG >= 16
.macro NEG4 reg .macro NEG4 reg
com \reg+3 com \reg+3
com \reg+2 com \reg+2
...@@ -1325,7 +1334,7 @@ DEFUN __divmodsi4 ...@@ -1325,7 +1334,7 @@ DEFUN __divmodsi4
bst r_arg1HH,7 ; store sign of dividend bst r_arg1HH,7 ; store sign of dividend
brtc 0f brtc 0f
com __tmp_reg__ ; r0.7 is sign of result com __tmp_reg__ ; r0.7 is sign of result
rcall __divmodsi4_neg1 ; dividend negative: negate XCALL __negsi2 ; dividend negative: negate
0: 0:
sbrc r_arg2HH,7 sbrc r_arg2HH,7
rcall __divmodsi4_neg2 ; divisor negative: negate rcall __divmodsi4_neg2 ; divisor negative: negate
...@@ -1333,16 +1342,7 @@ DEFUN __divmodsi4 ...@@ -1333,16 +1342,7 @@ DEFUN __divmodsi4
sbrc __tmp_reg__, 7 ; correct quotient sign sbrc __tmp_reg__, 7 ; correct quotient sign
rcall __divmodsi4_neg2 rcall __divmodsi4_neg2
brtc __divmodsi4_exit ; correct remainder sign brtc __divmodsi4_exit ; correct remainder sign
__divmodsi4_neg1: XJMP __negsi2
;; correct dividend/remainder sign
com r_arg1HH
com r_arg1HL
com r_arg1H
neg r_arg1L
sbci r_arg1H, 0xff
sbci r_arg1HL,0xff
sbci r_arg1HH,0xff
ret
__divmodsi4_neg2: __divmodsi4_neg2:
;; correct divisor/quotient sign ;; correct divisor/quotient sign
com r_arg2HH com r_arg2HH
...@@ -1357,6 +1357,16 @@ __divmodsi4_exit: ...@@ -1357,6 +1357,16 @@ __divmodsi4_exit:
ENDF __divmodsi4 ENDF __divmodsi4
#endif /* defined (L_divmodsi4) */ #endif /* defined (L_divmodsi4) */
#if defined (L_negsi2)
;; (set (reg:SI 22)
;; (neg:SI (reg:SI 22)))
;; Sets the V flag for signed overflow tests
DEFUN __negsi2
NEG4 22
ret
ENDF __negsi2
#endif /* L_negsi2 */
#undef r_remHH #undef r_remHH
#undef r_remHL #undef r_remHL
#undef r_remH #undef r_remH
...@@ -1689,6 +1699,8 @@ ENDF __divdi3_moddi3 ...@@ -1689,6 +1699,8 @@ ENDF __divdi3_moddi3
;; (set (reg:DI 18) ;; (set (reg:DI 18)
;; (plus:DI (reg:DI 18) ;; (plus:DI (reg:DI 18)
;; (reg:DI 10))) ;; (reg:DI 10)))
;; Sets the V flag for signed overflow tests
;; Sets the C flag for unsigned overflow tests
DEFUN __adddi3 DEFUN __adddi3
ADD A0,B0 $ adc A1,B1 $ adc A2,B2 $ adc A3,B3 ADD A0,B0 $ adc A1,B1 $ adc A2,B2 $ adc A3,B3
adc A4,B4 $ adc A5,B5 $ adc A6,B6 $ adc A7,B7 adc A4,B4 $ adc A5,B5 $ adc A6,B6 $ adc A7,B7
...@@ -1700,6 +1712,8 @@ ENDF __adddi3 ...@@ -1700,6 +1712,8 @@ ENDF __adddi3
;; (set (reg:DI 18) ;; (set (reg:DI 18)
;; (plus:DI (reg:DI 18) ;; (plus:DI (reg:DI 18)
;; (sign_extend:SI (reg:QI 26)))) ;; (sign_extend:SI (reg:QI 26))))
;; Sets the V flag for signed overflow tests
;; Sets the C flag for unsigned overflow tests provided 0 <= R26 < 128
DEFUN __adddi3_s8 DEFUN __adddi3_s8
clr TT clr TT
sbrc r26, 7 sbrc r26, 7
...@@ -1714,6 +1728,8 @@ ENDF __adddi3_s8 ...@@ -1714,6 +1728,8 @@ ENDF __adddi3_s8
;; (set (reg:DI 18) ;; (set (reg:DI 18)
;; (minus:DI (reg:DI 18) ;; (minus:DI (reg:DI 18)
;; (reg:DI 10))) ;; (reg:DI 10)))
;; Sets the V flag for signed overflow tests
;; Sets the C flag for unsigned overflow tests
DEFUN __subdi3 DEFUN __subdi3
SUB A0,B0 $ sbc A1,B1 $ sbc A2,B2 $ sbc A3,B3 SUB A0,B0 $ sbc A1,B1 $ sbc A2,B2 $ sbc A3,B3
sbc A4,B4 $ sbc A5,B5 $ sbc A6,B6 $ sbc A7,B7 sbc A4,B4 $ sbc A5,B5 $ sbc A6,B6 $ sbc A7,B7
...@@ -1747,6 +1763,9 @@ ENDF __cmpdi2_s8 ...@@ -1747,6 +1763,9 @@ ENDF __cmpdi2_s8
#endif /* L_cmpdi2_s8 */ #endif /* L_cmpdi2_s8 */
#if defined (L_negdi2) #if defined (L_negdi2)
;; (set (reg:DI 18)
;; (neg:DI (reg:DI 18)))
;; Sets the V flag for signed overflow tests
DEFUN __negdi2 DEFUN __negdi2
com A4 $ com A5 $ com A6 $ com A7 com A4 $ com A5 $ com A6 $ com A7
......
...@@ -20,7 +20,7 @@ LIB1ASMFUNCS = \ ...@@ -20,7 +20,7 @@ LIB1ASMFUNCS = \
_divdi3 _udivdi3 \ _divdi3 _udivdi3 \
_muldi3 \ _muldi3 \
_udivmod64 \ _udivmod64 \
_negdi2 \ _negsi2 _negdi2 \
_prologue \ _prologue \
_epilogue \ _epilogue \
_exit \ _exit \
...@@ -72,7 +72,12 @@ LIB1ASMFUNCS += \ ...@@ -72,7 +72,12 @@ LIB1ASMFUNCS += \
_divqq3 _udivuqq3 \ _divqq3 _udivuqq3 \
_divhq3 _udivuhq3 \ _divhq3 _udivuhq3 \
_divha3 _udivuha3 \ _divha3 _udivuha3 \
_divsa3 _udivusa3 _divsa3 _udivusa3 \
_clr_8 \
_ssneg_2 _ssneg_4 _ssneg_8 \
_ssabs_2 _ssabs_4 _ssabs_8 \
_ssadd_8 _sssub_8 \
_usadd_8 _ussub_8
LIB2FUNCS_EXCLUDE = \ LIB2FUNCS_EXCLUDE = \
_moddi3 _umoddi3 \ _moddi3 _umoddi3 \
...@@ -103,6 +108,7 @@ endif ...@@ -103,6 +108,7 @@ endif
# Filter out supported conversions from fixed-bit.c # Filter out supported conversions from fixed-bit.c
# Also filter out TQ and UTQ.
conv_XY=$(conv)$(mode1)$(mode2) conv_XY=$(conv)$(mode1)$(mode2)
func_X=$(func)$(mode) func_X=$(func)$(mode)
...@@ -141,8 +147,20 @@ allfix_modes = QQ UQQ HQ UHQ HA UHA SQ USQ SA USA DA UDA DQ UDQ TQ UTQ TA UTA ...@@ -141,8 +147,20 @@ allfix_modes = QQ UQQ HQ UHQ HA UHA SQ USQ SA USA DA UDA DQ UDQ TQ UTQ TA UTA
LIB2FUNCS_EXCLUDE += \ LIB2FUNCS_EXCLUDE += \
$(foreach func,_add _sub,\ $(foreach func,_add _sub,\
$(foreach mode,$(allfix_modes),$(func_X)3)) $(foreach mode,$(allfix_modes),$(func_X)))
LIB2FUNCS_EXCLUDE += \ LIB2FUNCS_EXCLUDE += \
$(foreach func,_lshr _ashl _ashr _cmp,\ $(foreach func,_lshr _ashl _ashr _cmp,\
$(foreach mode,$(allfix_modes),$(func_X))) $(foreach mode,$(allfix_modes),$(func_X)))
usat_modes = UQQ UHQ UHA USQ USA UDQ UDA UTQ UTA
ssat_modes = QQ HQ HA SQ SA DQ DA TQ TA
LIB2FUNCS_EXCLUDE += \
$(foreach func,_ssadd _sssub _ssneg _ssabs,\
$(foreach mode,$(ssat_modes),$(func_X)))
LIB2FUNCS_EXCLUDE += \
$(foreach func,_usadd _ussub _usneg,\
$(foreach mode,$(usat_modes),$(func_X)))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment