Commit e55e4056 by Georg-Johann Lay Committed by Georg-Johann Lay

re PR target/54222 ([avr] Implement fixed-point support)

libgcc/
	PR target/54222
	* config/avr/lib1funcs-fixed.S: New file.
	* config/avr/lib1funcs.S: Include it.  Undefine some divmodsi
	after they are used.
	(neg2, neg4): New macros.
	(__mulqihi3,__umulqihi3,__mulhi3): Rewrite non-MUL variants.
	(__mulhisi3,__umulhisi3,__mulsi3): Rewrite non-MUL variants.
	(__umulhisi3): Speed up MUL variant if there is enough flash.
	* config/avr/avr-lib.h (TA, UTA): Adjust according to gcc's
	avr-modes.def.
	* config/avr/t-avr (LIB1ASMFUNCS): Add: _fractqqsf, _fractuqqsf,
	_fracthqsf, _fractuhqsf, _fracthasf, _fractuhasf, _fractsasf,
	_fractusasf, _fractsfqq, _fractsfuqq, _fractsfhq, _fractsfuhq,
	_fractsfha, _fractsfsa, _mulqq3, _muluqq3, _mulhq3, _muluhq3,
	_mulha3, _muluha3, _mulsa3, _mulusa3, _divqq3, _udivuqq3, _divhq3,
	_udivuhq3, _divha3, _udivuha3, _divsa3, _udivusa3.
	(LIB2FUNCS_EXCLUDE): Add supported functions.

gcc/
	PR target/54222
	* avr-modes.def (HA, SA, DA, TA, UTA): Adjust modes.
	* avr/avr-fixed.md: New file.
	* avr/avr.md: Include it.
	(cc): Add: minus.
	(adjust_len): Add: minus, minus64, ufract, sfract.
	(ALL1, ALL2, ALL4, ORDERED234): New mode iterators.
	(MOVMODE): Add: QQ, UQQ, HQ, UHQ, HA, UHA, SQ, USQ, SA, USA.
	(MPUSH): Add: HQ, UHQ, HA, UHA, SQ, USQ, SA, USA.
	(pushqi1, xload8_A, xload_8, movqi_insn, *reload_inqi, addqi3,
	subqi3, ashlqi3, *ashlqi3, ashrqi3, lshrqi3, *lshrqi3, *cmpqi, 
	cbranchqi4, *cpse.eq): Generalize to handle all 8-bit modes in ALL1.
	(*movhi, reload_inhi, addhi3, *addhi3, addhi3_clobber, subhi3,
	ashlhi3, *ashlhi3_const, ashrhi3, *ashirhi3_const, lshrhi3,
	*lshrhi3_const, *cmphi, cbranchhi4): Generalize to handle all
	16-bit modes in ALL2.
	(subhi3, casesi, strlenhi): Add clobber when expanding minus:HI.
	(*movsi, *reload_insi, addsi3, subsi3, ashlsi3, *ashlsi3_const,
	ashrsi3, *ashrhi3_const, *ashrsi3_const, lshrsi3, *lshrsi3_const,
	*reversed_tstsi, *cmpsi, cbranchsi4): Generalize to handle all
	32-bit modes in ALL4.
	* avr-dimode.md (ALL8): New mode iterator.
	(adddi3, adddi3_insn, adddi3_const_insn, subdi3, subdi3_insn,
	subdi3_const_insn, cbranchdi4, compare_di2,
	compare_const_di2, ashrdi3, lshrdi3, rotldi3, ashldi3_insn,
	ashrdi3_insn, lshrdi3_insn, rotldi3_insn): Generalize to handle
	all 64-bit modes in ALL8.
	* config/avr/avr-protos.h (avr_to_int_mode): New prototype.
	(avr_out_fract, avr_out_minus, avr_out_minus64): New prototypes.
	* config/avr/avr.c (TARGET_FIXED_POINT_SUPPORTED_P): Define to...
	(avr_fixed_point_supported_p): ...this new static function.
	(TARGET_BUILD_BUILTIN_VA_LIST): Define to...
	(avr_build_builtin_va_list): ...this new static function.
	(avr_adjust_type_node): New static function.
	(avr_scalar_mode_supported_p): Allow if ALL_FIXED_POINT_MODE_P.
	(avr_builtin_setjmp_frame_value): Use gen_subhi3 and return new
	pseudo instead of gen_rtx_MINUS.
	(avr_print_operand, avr_operand_rtx_cost): Handle: CONST_FIXED.
	(notice_update_cc): Handle: CC_MINUS.
	(output_movqi): Generalize to handle respective fixed-point modes.
	(output_movhi, output_movsisf, avr_2word_insn_p): Ditto.
	(avr_out_compare, avr_out_plus_1): Also handle fixed-point modes.
	(avr_assemble_integer): Ditto.
	(output_reload_in_const, output_reload_insisf): Ditto.
	(avr_compare_pattern): Skip all modes > 4 bytes.
	(avr_2word_insn_p): Skip movuqq_insn, movqq_insn.
	(avr_out_fract, avr_out_minus, avr_out_minus64): New functions.
	(avr_to_int_mode): New function.
	(adjust_insn_length): Handle: ADJUST_LEN_SFRACT,
	ADJUST_LEN_UFRACT, ADJUST_LEN_MINUS, ADJUST_LEN_MINUS64.
	* config/avr/predicates.md (const0_operand): Allow const_fixed.
	(const_operand, const_or_immediate_operand): New.
	(nonmemory_or_const_operand): New.
	* config/avr/constraints.md (Ynn, Y00, Y01, Y02, Ym1, Ym2, YIJ):
	New constraints.
	* config/avr/avr.h (LONG_LONG_ACCUM_TYPE_SIZE): Define.

From-SVN: r190644
parent 2960a368
2012-08-24 Georg-Johann Lay <avr@gjlay.de>
PR target/54222
* avr-modes.def (HA, SA, DA, TA, UTA): Adjust modes.
* avr/avr-fixed.md: New file.
* avr/avr.md: Include it.
(cc): Add: minus.
(adjust_len): Add: minus, minus64, ufract, sfract.
(ALL1, ALL2, ALL4, ORDERED234): New mode iterators.
(MOVMODE): Add: QQ, UQQ, HQ, UHQ, HA, UHA, SQ, USQ, SA, USA.
(MPUSH): Add: HQ, UHQ, HA, UHA, SQ, USQ, SA, USA.
(pushqi1, xload8_A, xload_8, movqi_insn, *reload_inqi, addqi3,
subqi3, ashlqi3, *ashlqi3, ashrqi3, lshrqi3, *lshrqi3, *cmpqi,
cbranchqi4, *cpse.eq): Generalize to handle all 8-bit modes in ALL1.
(*movhi, reload_inhi, addhi3, *addhi3, addhi3_clobber, subhi3,
ashlhi3, *ashlhi3_const, ashrhi3, *ashirhi3_const, lshrhi3,
*lshrhi3_const, *cmphi, cbranchhi4): Generalize to handle all
16-bit modes in ALL2.
(subhi3, casesi, strlenhi): Add clobber when expanding minus:HI.
(*movsi, *reload_insi, addsi3, subsi3, ashlsi3, *ashlsi3_const,
ashrsi3, *ashrhi3_const, *ashrsi3_const, lshrsi3, *lshrsi3_const,
*reversed_tstsi, *cmpsi, cbranchsi4): Generalize to handle all
32-bit modes in ALL4.
* avr-dimode.md (ALL8): New mode iterator.
(adddi3, adddi3_insn, adddi3_const_insn, subdi3, subdi3_insn,
subdi3_const_insn, cbranchdi4, compare_di2,
compare_const_di2, ashrdi3, lshrdi3, rotldi3, ashldi3_insn,
ashrdi3_insn, lshrdi3_insn, rotldi3_insn): Generalize to handle
all 64-bit modes in ALL8.
* config/avr/avr-protos.h (avr_to_int_mode): New prototype.
(avr_out_fract, avr_out_minus, avr_out_minus64): New prototypes.
* config/avr/avr.c (TARGET_FIXED_POINT_SUPPORTED_P): Define to...
(avr_fixed_point_supported_p): ...this new static function.
(TARGET_BUILD_BUILTIN_VA_LIST): Define to...
(avr_build_builtin_va_list): ...this new static function.
(avr_adjust_type_node): New static function.
(avr_scalar_mode_supported_p): Allow if ALL_FIXED_POINT_MODE_P.
(avr_builtin_setjmp_frame_value): Use gen_subhi3 and return new
pseudo instead of gen_rtx_MINUS.
(avr_print_operand, avr_operand_rtx_cost): Handle: CONST_FIXED.
(notice_update_cc): Handle: CC_MINUS.
(output_movqi): Generalize to handle respective fixed-point modes.
(output_movhi, output_movsisf, avr_2word_insn_p): Ditto.
(avr_out_compare, avr_out_plus_1): Also handle fixed-point modes.
(avr_assemble_integer): Ditto.
(output_reload_in_const, output_reload_insisf): Ditto.
(avr_compare_pattern): Skip all modes > 4 bytes.
(avr_2word_insn_p): Skip movuqq_insn, movqq_insn.
(avr_out_fract, avr_out_minus, avr_out_minus64): New functions.
(avr_to_int_mode): New function.
(adjust_insn_length): Handle: ADJUST_LEN_SFRACT,
ADJUST_LEN_UFRACT, ADJUST_LEN_MINUS, ADJUST_LEN_MINUS64.
* config/avr/predicates.md (const0_operand): Allow const_fixed.
(const_operand, const_or_immediate_operand): New.
(nonmemory_or_const_operand): New.
* config/avr/constraints.md (Ynn, Y00, Y01, Y02, Ym1, Ym2, YIJ):
New constraints.
* config/avr/avr.h (LONG_LONG_ACCUM_TYPE_SIZE): Define.
2012-08-23 Kenneth Zadeck <zadeck@naturalbridge.com> 2012-08-23 Kenneth Zadeck <zadeck@naturalbridge.com>
* alias.c (rtx_equal_for_memref_p): Convert constant cases. * alias.c (rtx_equal_for_memref_p): Convert constant cases.
......
;; This file contains instructions that support fixed-point operations
;; for Atmel AVR micro controllers.
;; Copyright (C) 2012
;; Free Software Foundation, Inc.
;;
;; Contributed by Sean D'Epagnier (sean@depagnier.com)
;; Georg-Johann Lay (avr@gjlay.de)
;; This file is part of GCC.
;;
;; GCC is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;;
;; GCC is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING3. If not see
;; <http://www.gnu.org/licenses/>.
(define_mode_iterator ALL1Q [(QQ "") (UQQ "")])
(define_mode_iterator ALL2Q [(HQ "") (UHQ "")])
(define_mode_iterator ALL2A [(HA "") (UHA "")])
(define_mode_iterator ALL2QA [(HQ "") (UHQ "")
(HA "") (UHA "")])
(define_mode_iterator ALL4A [(SA "") (USA "")])
;;; Conversions
(define_mode_iterator FIXED_A
[(QQ "") (UQQ "")
(HQ "") (UHQ "") (HA "") (UHA "")
(SQ "") (USQ "") (SA "") (USA "")
(DQ "") (UDQ "") (DA "") (UDA "")
(TA "") (UTA "")
(QI "") (HI "") (SI "") (DI "")])
;; Same so that be can build cross products
(define_mode_iterator FIXED_B
[(QQ "") (UQQ "")
(HQ "") (UHQ "") (HA "") (UHA "")
(SQ "") (USQ "") (SA "") (USA "")
(DQ "") (UDQ "") (DA "") (UDA "")
(TA "") (UTA "")
(QI "") (HI "") (SI "") (DI "")])
(define_insn "fract<FIXED_B:mode><FIXED_A:mode>2"
[(set (match_operand:FIXED_A 0 "register_operand" "=r")
(fract_convert:FIXED_A
(match_operand:FIXED_B 1 "register_operand" "r")))]
"<FIXED_B:MODE>mode != <FIXED_A:MODE>mode"
{
return avr_out_fract (insn, operands, true, NULL);
}
[(set_attr "cc" "clobber")
(set_attr "adjust_len" "sfract")])
(define_insn "fractuns<FIXED_B:mode><FIXED_A:mode>2"
[(set (match_operand:FIXED_A 0 "register_operand" "=r")
(unsigned_fract_convert:FIXED_A
(match_operand:FIXED_B 1 "register_operand" "r")))]
"<FIXED_B:MODE>mode != <FIXED_A:MODE>mode"
{
return avr_out_fract (insn, operands, false, NULL);
}
[(set_attr "cc" "clobber")
(set_attr "adjust_len" "ufract")])
;******************************************************************************
; mul
;; "mulqq3" "muluqq3"
(define_expand "mul<mode>3"
[(parallel [(match_operand:ALL1Q 0 "register_operand" "")
(match_operand:ALL1Q 1 "register_operand" "")
(match_operand:ALL1Q 2 "register_operand" "")])]
""
{
emit_insn (AVR_HAVE_MUL
? gen_mul<mode>3_enh (operands[0], operands[1], operands[2])
: gen_mul<mode>3_nomul (operands[0], operands[1], operands[2]));
DONE;
})
(define_insn "mulqq3_enh"
[(set (match_operand:QQ 0 "register_operand" "=r")
(mult:QQ (match_operand:QQ 1 "register_operand" "a")
(match_operand:QQ 2 "register_operand" "a")))]
"AVR_HAVE_MUL"
"fmuls %1,%2\;dec r1\;brvs 0f\;inc r1\;0:\;mov %0,r1\;clr __zero_reg__"
[(set_attr "length" "6")
(set_attr "cc" "clobber")])
(define_insn "muluqq3_enh"
[(set (match_operand:UQQ 0 "register_operand" "=r")
(mult:UQQ (match_operand:UQQ 1 "register_operand" "r")
(match_operand:UQQ 2 "register_operand" "r")))]
"AVR_HAVE_MUL"
"mul %1,%2\;mov %0,r1\;clr __zero_reg__"
[(set_attr "length" "3")
(set_attr "cc" "clobber")])
(define_expand "mulqq3_nomul"
[(set (reg:QQ 24)
(match_operand:QQ 1 "register_operand" ""))
(set (reg:QQ 25)
(match_operand:QQ 2 "register_operand" ""))
;; "*mulqq3.call"
(parallel [(set (reg:QQ 23)
(mult:QQ (reg:QQ 24)
(reg:QQ 25)))
(clobber (reg:QI 22))
(clobber (reg:HI 24))])
(set (match_operand:QQ 0 "register_operand" "")
(reg:QQ 23))]
"!AVR_HAVE_MUL")
(define_expand "muluqq3_nomul"
[(set (reg:UQQ 22)
(match_operand:UQQ 1 "register_operand" ""))
(set (reg:UQQ 24)
(match_operand:UQQ 2 "register_operand" ""))
;; "*umulqihi3.call"
(parallel [(set (reg:HI 24)
(mult:HI (zero_extend:HI (reg:QI 22))
(zero_extend:HI (reg:QI 24))))
(clobber (reg:QI 21))
(clobber (reg:HI 22))])
(set (match_operand:UQQ 0 "register_operand" "")
(reg:UQQ 25))]
"!AVR_HAVE_MUL")
(define_insn "*mulqq3.call"
[(set (reg:QQ 23)
(mult:QQ (reg:QQ 24)
(reg:QQ 25)))
(clobber (reg:QI 22))
(clobber (reg:HI 24))]
"!AVR_HAVE_MUL"
"%~call __mulqq3"
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
;; "mulhq3" "muluhq3"
;; "mulha3" "muluha3"
(define_expand "mul<mode>3"
[(set (reg:ALL2QA 18)
(match_operand:ALL2QA 1 "register_operand" ""))
(set (reg:ALL2QA 26)
(match_operand:ALL2QA 2 "register_operand" ""))
;; "*mulhq3.call.enh"
(parallel [(set (reg:ALL2QA 24)
(mult:ALL2QA (reg:ALL2QA 18)
(reg:ALL2QA 26)))
(clobber (reg:HI 22))])
(set (match_operand:ALL2QA 0 "register_operand" "")
(reg:ALL2QA 24))]
"AVR_HAVE_MUL")
;; "*mulhq3.call" "*muluhq3.call"
;; "*mulha3.call" "*muluha3.call"
(define_insn "*mul<mode>3.call"
[(set (reg:ALL2QA 24)
(mult:ALL2QA (reg:ALL2QA 18)
(reg:ALL2QA 26)))
(clobber (reg:HI 22))]
"AVR_HAVE_MUL"
"%~call __mul<mode>3"
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
;; On the enhanced core, don't clobber either input and use a separate output
;; "mulsa3" "mulusa3"
(define_expand "mul<mode>3"
[(set (reg:ALL4A 16)
(match_operand:ALL4A 1 "register_operand" ""))
(set (reg:ALL4A 20)
(match_operand:ALL4A 2 "register_operand" ""))
(set (reg:ALL4A 24)
(mult:ALL4A (reg:ALL4A 16)
(reg:ALL4A 20)))
(set (match_operand:ALL4A 0 "register_operand" "")
(reg:ALL4A 24))]
"AVR_HAVE_MUL")
;; "*mulsa3.call" "*mulusa3.call"
(define_insn "*mul<mode>3.call"
[(set (reg:ALL4A 24)
(mult:ALL4A (reg:ALL4A 16)
(reg:ALL4A 20)))]
"AVR_HAVE_MUL"
"%~call __mul<mode>3"
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
; / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
; div
(define_code_iterator usdiv [udiv div])
;; "divqq3" "udivuqq3"
(define_expand "<code><mode>3"
[(set (reg:ALL1Q 25)
(match_operand:ALL1Q 1 "register_operand" ""))
(set (reg:ALL1Q 22)
(match_operand:ALL1Q 2 "register_operand" ""))
(parallel [(set (reg:ALL1Q 24)
(usdiv:ALL1Q (reg:ALL1Q 25)
(reg:ALL1Q 22)))
(clobber (reg:QI 25))])
(set (match_operand:ALL1Q 0 "register_operand" "")
(reg:ALL1Q 24))])
;; "*divqq3.call" "*udivuqq3.call"
(define_insn "*<code><mode>3.call"
[(set (reg:ALL1Q 24)
(usdiv:ALL1Q (reg:ALL1Q 25)
(reg:ALL1Q 22)))
(clobber (reg:QI 25))]
""
"%~call __<code><mode>3"
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
;; "divhq3" "udivuhq3"
;; "divha3" "udivuha3"
(define_expand "<code><mode>3"
[(set (reg:ALL2QA 26)
(match_operand:ALL2QA 1 "register_operand" ""))
(set (reg:ALL2QA 22)
(match_operand:ALL2QA 2 "register_operand" ""))
(parallel [(set (reg:ALL2QA 24)
(usdiv:ALL2QA (reg:ALL2QA 26)
(reg:ALL2QA 22)))
(clobber (reg:HI 26))
(clobber (reg:QI 21))])
(set (match_operand:ALL2QA 0 "register_operand" "")
(reg:ALL2QA 24))])
;; "*divhq3.call" "*udivuhq3.call"
;; "*divha3.call" "*udivuha3.call"
(define_insn "*<code><mode>3.call"
[(set (reg:ALL2QA 24)
(usdiv:ALL2QA (reg:ALL2QA 26)
(reg:ALL2QA 22)))
(clobber (reg:HI 26))
(clobber (reg:QI 21))]
""
"%~call __<code><mode>3"
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
;; Note the first parameter gets passed in already offset by 2 bytes
;; "divsa3" "udivusa3"
(define_expand "<code><mode>3"
[(set (reg:ALL4A 24)
(match_operand:ALL4A 1 "register_operand" ""))
(set (reg:ALL4A 18)
(match_operand:ALL4A 2 "register_operand" ""))
(parallel [(set (reg:ALL4A 22)
(usdiv:ALL4A (reg:ALL4A 24)
(reg:ALL4A 18)))
(clobber (reg:HI 26))
(clobber (reg:HI 30))])
(set (match_operand:ALL4A 0 "register_operand" "")
(reg:ALL4A 22))])
;; "*divsa3.call" "*udivusa3.call"
(define_insn "*<code><mode>3.call"
[(set (reg:ALL4A 22)
(usdiv:ALL4A (reg:ALL4A 24)
(reg:ALL4A 18)))
(clobber (reg:HI 26))
(clobber (reg:HI 30))]
""
"%~call __<code><mode>3"
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
FRACTIONAL_INT_MODE (PSI, 24, 3); FRACTIONAL_INT_MODE (PSI, 24, 3);
/* On 8 bit machines it requires fewer instructions for fixed point
routines if the decimal place is on a byte boundary which is not
the default for signed accum types. */
ADJUST_IBIT (HA, 7);
ADJUST_FBIT (HA, 8);
ADJUST_IBIT (SA, 15);
ADJUST_FBIT (SA, 16);
ADJUST_IBIT (DA, 31);
ADJUST_FBIT (DA, 32);
/* Make TA and UTA 64 bits wide.
128 bit wide modes would be insane on a 8-bit machine.
This needs special treatment in avr.c and avr-lib.h. */
ADJUST_BYTESIZE (TA, 8);
ADJUST_ALIGNMENT (TA, 1);
ADJUST_IBIT (TA, 15);
ADJUST_FBIT (TA, 48);
ADJUST_BYTESIZE (UTA, 8);
ADJUST_ALIGNMENT (UTA, 1);
ADJUST_IBIT (UTA, 16);
ADJUST_FBIT (UTA, 48);
...@@ -79,6 +79,9 @@ extern const char* avr_load_lpm (rtx, rtx*, int*); ...@@ -79,6 +79,9 @@ extern const char* avr_load_lpm (rtx, rtx*, int*);
extern bool avr_rotate_bytes (rtx operands[]); extern bool avr_rotate_bytes (rtx operands[]);
extern const char* avr_out_fract (rtx, rtx[], bool, int*);
extern rtx avr_to_int_mode (rtx);
extern void expand_prologue (void); extern void expand_prologue (void);
extern void expand_epilogue (bool); extern void expand_epilogue (bool);
extern bool avr_emit_movmemhi (rtx*); extern bool avr_emit_movmemhi (rtx*);
...@@ -92,6 +95,8 @@ extern const char* avr_out_plus (rtx*, int*, int*); ...@@ -92,6 +95,8 @@ extern const char* avr_out_plus (rtx*, int*, int*);
extern const char* avr_out_plus_noclobber (rtx*, int*, int*); extern const char* avr_out_plus_noclobber (rtx*, int*, int*);
extern const char* avr_out_plus64 (rtx, 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*);
......
...@@ -261,6 +261,7 @@ enum ...@@ -261,6 +261,7 @@ enum
#define FLOAT_TYPE_SIZE 32 #define FLOAT_TYPE_SIZE 32
#define DOUBLE_TYPE_SIZE 32 #define DOUBLE_TYPE_SIZE 32
#define LONG_DOUBLE_TYPE_SIZE 32 #define LONG_DOUBLE_TYPE_SIZE 32
#define LONG_LONG_ACCUM_TYPE_SIZE 64
#define DEFAULT_SIGNED_CHAR 1 #define DEFAULT_SIGNED_CHAR 1
......
...@@ -192,3 +192,47 @@ ...@@ -192,3 +192,47 @@
"32-bit integer constant where no nibble equals 0xf." "32-bit integer constant where no nibble equals 0xf."
(and (match_code "const_int") (and (match_code "const_int")
(match_test "!avr_has_nibble_0xf (op)"))) (match_test "!avr_has_nibble_0xf (op)")))
;; CONST_FIXED is no element of 'n' so cook our own.
;; "i" or "s" would match but because the insn uses iterators that cover
;; INT_MODE, "i" or "s" is not always possible.
(define_constraint "Ynn"
"Fixed-point constant known at compile time."
(match_code "const_fixed"))
(define_constraint "Y00"
"Fixed-point or integer constant with bit representation 0x0"
(and (match_code "const_fixed,const_int")
(match_test "op == CONST0_RTX (GET_MODE (op))")))
(define_constraint "Y01"
"Fixed-point or integer constant with bit representation 0x1"
(ior (and (match_code "const_fixed")
(match_test "1 == INTVAL (avr_to_int_mode (op))"))
(match_test "satisfies_constraint_P (op)")))
(define_constraint "Ym1"
"Fixed-point or integer constant with bit representation -0x1"
(ior (and (match_code "const_fixed")
(match_test "-1 == INTVAL (avr_to_int_mode (op))"))
(match_test "satisfies_constraint_N (op)")))
(define_constraint "Y02"
"Fixed-point or integer constant with bit representation 0x2"
(ior (and (match_code "const_fixed")
(match_test "2 == INTVAL (avr_to_int_mode (op))"))
(match_test "satisfies_constraint_K (op)")))
(define_constraint "Ym2"
"Fixed-point or integer constant with bit representation -0x2"
(ior (and (match_code "const_fixed")
(match_test "-2 == INTVAL (avr_to_int_mode (op))"))
(match_test "satisfies_constraint_Cm2 (op)")))
;; Similar to "IJ" used with ADIW/SBIW, but for CONST_FIXED.
(define_constraint "YIJ"
"Fixed-point constant from @minus{}0x003f to 0x003f."
(and (match_code "const_fixed")
(match_test "IN_RANGE (INTVAL (avr_to_int_mode (op)), -63, 63)")))
...@@ -74,7 +74,7 @@ ...@@ -74,7 +74,7 @@
;; Return 1 if OP is the zero constant for MODE. ;; Return 1 if OP is the zero constant for MODE.
(define_predicate "const0_operand" (define_predicate "const0_operand"
(and (match_code "const_int,const_double") (and (match_code "const_int,const_fixed,const_double")
(match_test "op == CONST0_RTX (mode)"))) (match_test "op == CONST0_RTX (mode)")))
;; Return 1 if OP is the one constant integer for MODE. ;; Return 1 if OP is the one constant integer for MODE.
...@@ -248,3 +248,21 @@ ...@@ -248,3 +248,21 @@
(define_predicate "o16_operand" (define_predicate "o16_operand"
(and (match_code "const_int") (and (match_code "const_int")
(match_test "IN_RANGE (INTVAL (op), -(1<<16), -1)"))) (match_test "IN_RANGE (INTVAL (op), -(1<<16), -1)")))
;; Const int, fixed, or double operand
(define_predicate "const_operand"
(ior (match_code "const_fixed")
(match_code "const_double")
(match_operand 0 "const_int_operand")))
;; Const int, const fixed, or const double operand
(define_predicate "nonmemory_or_const_operand"
(ior (match_code "const_fixed")
(match_code "const_double")
(match_operand 0 "nonmemory_operand")))
;; Immediate, const fixed, or const double operand
(define_predicate "const_or_immediate_operand"
(ior (match_code "const_fixed")
(match_code "const_double")
(match_operand 0 "immediate_operand")))
2012-08-24 Georg-Johann Lay <avr@gjlay.de>
PR target/54222
* config/avr/lib1funcs-fixed.S: New file.
* config/avr/lib1funcs.S: Include it. Undefine some divmodsi
after they are used.
(neg2, neg4): New macros.
(__mulqihi3,__umulqihi3,__mulhi3): Rewrite non-MUL variants.
(__mulhisi3,__umulhisi3,__mulsi3): Rewrite non-MUL variants.
(__umulhisi3): Speed up MUL variant if there is enough flash.
* config/avr/avr-lib.h (TA, UTA): Adjust according to gcc's
avr-modes.def.
* config/avr/t-avr (LIB1ASMFUNCS): Add: _fractqqsf, _fractuqqsf,
_fracthqsf, _fractuhqsf, _fracthasf, _fractuhasf, _fractsasf,
_fractusasf, _fractsfqq, _fractsfuqq, _fractsfhq, _fractsfuhq,
_fractsfha, _fractsfsa, _mulqq3, _muluqq3, _mulhq3, _muluhq3,
_mulha3, _muluha3, _mulsa3, _mulusa3, _divqq3, _udivuqq3, _divhq3,
_udivuhq3, _divha3, _udivuha3, _divsa3, _udivusa3.
(LIB2FUNCS_EXCLUDE): Add supported functions.
2012-08-22 Georg-Johann Lay <avr@gjlay.de> 2012-08-22 Georg-Johann Lay <avr@gjlay.de>
* Makefile.in (fixed-funcs,fixed-conv-funcs): filter-out * Makefile.in (fixed-funcs,fixed-conv-funcs): filter-out
......
...@@ -4,3 +4,79 @@ ...@@ -4,3 +4,79 @@
#define DI SI #define DI SI
typedef int QItype __attribute__ ((mode (QI))); typedef int QItype __attribute__ ((mode (QI)));
#endif #endif
/* fixed-bit.h does not define functions for TA and UTA because
that part is wrapped in #if MIN_UNITS_PER_WORD > 4.
This would lead to empty functions for TA and UTA.
Thus, supply appropriate defines as if HAVE_[U]TA == 1.
#define HAVE_[U]TA 1 won't work because avr-modes.def
uses ADJUST_BYTESIZE(TA,8) and fixed-bit.h is not generic enough
to arrange for such changes of the mode size. */
typedef unsigned _Fract UTAtype __attribute__ ((mode (UTA)));
#if defined (UTA_MODE)
#define FIXED_SIZE 8 /* in bytes */
#define INT_C_TYPE UDItype
#define UINT_C_TYPE UDItype
#define HINT_C_TYPE USItype
#define HUINT_C_TYPE USItype
#define MODE_NAME UTA
#define MODE_NAME_S uta
#define MODE_UNSIGNED 1
#endif
#if defined (FROM_UTA)
#define FROM_TYPE 4 /* ID for fixed-point */
#define FROM_MODE_NAME UTA
#define FROM_MODE_NAME_S uta
#define FROM_INT_C_TYPE UDItype
#define FROM_SINT_C_TYPE DItype
#define FROM_UINT_C_TYPE UDItype
#define FROM_MODE_UNSIGNED 1
#define FROM_FIXED_SIZE 8 /* in bytes */
#elif defined (TO_UTA)
#define TO_TYPE 4 /* ID for fixed-point */
#define TO_MODE_NAME UTA
#define TO_MODE_NAME_S uta
#define TO_INT_C_TYPE UDItype
#define TO_SINT_C_TYPE DItype
#define TO_UINT_C_TYPE UDItype
#define TO_MODE_UNSIGNED 1
#define TO_FIXED_SIZE 8 /* in bytes */
#endif
/* Same for TAmode */
typedef _Fract TAtype __attribute__ ((mode (TA)));
#if defined (TA_MODE)
#define FIXED_SIZE 8 /* in bytes */
#define INT_C_TYPE DItype
#define UINT_C_TYPE UDItype
#define HINT_C_TYPE SItype
#define HUINT_C_TYPE USItype
#define MODE_NAME TA
#define MODE_NAME_S ta
#define MODE_UNSIGNED 0
#endif
#if defined (FROM_TA)
#define FROM_TYPE 4 /* ID for fixed-point */
#define FROM_MODE_NAME TA
#define FROM_MODE_NAME_S ta
#define FROM_INT_C_TYPE DItype
#define FROM_SINT_C_TYPE DItype
#define FROM_UINT_C_TYPE UDItype
#define FROM_MODE_UNSIGNED 0
#define FROM_FIXED_SIZE 8 /* in bytes */
#elif defined (TO_TA)
#define TO_TYPE 4 /* ID for fixed-point */
#define TO_MODE_NAME TA
#define TO_MODE_NAME_S ta
#define TO_INT_C_TYPE DItype
#define TO_SINT_C_TYPE DItype
#define TO_UINT_C_TYPE UDItype
#define TO_MODE_UNSIGNED 0
#define TO_FIXED_SIZE 8 /* in bytes */
#endif
...@@ -2,6 +2,7 @@ LIB1ASMSRC = avr/lib1funcs.S ...@@ -2,6 +2,7 @@ LIB1ASMSRC = avr/lib1funcs.S
LIB1ASMFUNCS = \ LIB1ASMFUNCS = \
_mulqi3 \ _mulqi3 \
_mulhi3 \ _mulhi3 \
_mulqihi3 _umulqihi3 \
_mulpsi3 _mulsqipsi3 \ _mulpsi3 _mulsqipsi3 \
_mulhisi3 \ _mulhisi3 \
_umulhisi3 \ _umulhisi3 \
...@@ -55,6 +56,24 @@ LIB1ASMFUNCS = \ ...@@ -55,6 +56,24 @@ LIB1ASMFUNCS = \
_cmpdi2 _cmpdi2_s8 \ _cmpdi2 _cmpdi2_s8 \
_fmul _fmuls _fmulsu _fmul _fmuls _fmulsu
# Fixed point routines in avr/lib1funcs-fixed.S
LIB1ASMFUNCS += \
_fractqqsf _fractuqqsf \
_fracthqsf _fractuhqsf _fracthasf _fractuhasf \
_fractsasf _fractusasf _fractsqsf _fractusqsf \
\
_fractsfqq _fractsfuqq \
_fractsfhq _fractsfuhq _fractsfha _fractsfuha \
_fractsfsa _fractsfusa \
_mulqq3 \
_mulhq3 _muluhq3 \
_mulha3 _muluha3 _muluha3_round \
_mulsa3 _mulusa3 \
_divqq3 _udivuqq3 \
_divhq3 _udivuhq3 \
_divha3 _udivuha3 \
_divsa3 _udivusa3
LIB2FUNCS_EXCLUDE = \ LIB2FUNCS_EXCLUDE = \
_moddi3 _umoddi3 \ _moddi3 _umoddi3 \
_clz _clz
...@@ -81,3 +100,49 @@ libgcc-objects += $(patsubst %,%$(objext),$(hiintfuncs16)) ...@@ -81,3 +100,49 @@ libgcc-objects += $(patsubst %,%$(objext),$(hiintfuncs16))
ifeq ($(enable_shared),yes) ifeq ($(enable_shared),yes)
libgcc-s-objects += $(patsubst %,%_s$(objext),$(hiintfuncs16)) libgcc-s-objects += $(patsubst %,%_s$(objext),$(hiintfuncs16))
endif endif
# Filter out supported conversions from fixed-bit.c
conv_XY=$(conv)$(mode1)$(mode2)
conv_X=$(conv)$(mode)
# Conversions supported by the compiler
convf_modes = QI UQI QQ UQQ \
HI UHI HQ UHQ HA UHA \
SI USI SQ USQ SA USA \
DI UDI DQ UDQ DA UDA \
TI UTI TQ UTQ TA UTA
LIB2FUNCS_EXCLUDE += \
$(foreach conv,_fract _fractuns,\
$(foreach mode1,$(convf_modes),\
$(foreach mode2,$(convf_modes),$(conv_XY))))
# Conversions supported by lib1funcs-fixed.S
conv_to_sf_modes = QQ UQQ HQ UHQ HA UHA SQ USQ SA USA
conv_from_sf_modes = QQ UQQ HQ UHQ HA UHA SA USA
LIB2FUNCS_EXCLUDE += \
$(foreach conv,_fract, \
$(foreach mode1,$(conv_to_sf_modes), \
$(foreach mode2,SF,$(conv_XY))))
LIB2FUNCS_EXCLUDE += \
$(foreach conv,_fract,\
$(foreach mode1,SF,\
$(foreach mode2,$(conv_from_sf_modes),$(conv_XY))))
# Arithmetik supported by the compiler
allfix_modes = QQ UQQ HQ UHQ HA UHA SQ USQ SA USA DA UDA DQ UDQ TQ UTQ TA UTA
LIB2FUNCS_EXCLUDE += \
$(foreach conv,_add _sub,\
$(foreach mode,$(allfix_modes),$(conv_X)3))
LIB2FUNCS_EXCLUDE += \
$(foreach conv,_lshr _ashl _ashr _cmp,\
$(foreach mode,$(allfix_modes),$(conv_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