From patchwork Fri Sep 14 15:43:36 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Georg-Johann Lay X-Patchwork-Id: 183962 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 803612C009C for ; Sat, 15 Sep 2012 01:44:30 +1000 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1348242271; h=Comment: DomainKey-Signature:Received:Received:Received:Received: Message-ID:Date:From:User-Agent:MIME-Version:To:CC:Subject: Content-Type:Mailing-List:Precedence:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=U3kvD0P yu2YeWxinmzRlM6aXffU=; b=T2GcyXtVNRDx73hVRmxOg5hxCyKDFxOktMmDLRo OUgoO1/7gmhxIGFLvEXWkdG3j9RvV+bqqU6mBg97FGwqJKbiJ/zzX8cFoZu8jmhN 43Xf/ACGxMno596+/k3s5kM+t0IK043bnhIkYE7HLvb4DbflqLX93CwCU/O5I5I0 Jjeg= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:X-RZG-AUTH:X-RZG-CLASS-ID:Received:Message-ID:Date:From:User-Agent:MIME-Version:To:CC:Subject:Content-Type:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=GWov93Ne1cMarPcWtui4rjJJoa6jc4RptZRXhba6uMVxBzOo8mD1nohKPdveoZ c5f41IVLafomFZexRrys9l7tm+7Td8JE9g1Ab5FgSOraTC/7ro6ofCq+TS7uaP0A Q87vdIl7eBqS+zifOLRnWaJ/unxYkgibRPCieZjqlx93k=; Received: (qmail 9309 invoked by alias); 14 Sep 2012 15:44:21 -0000 Received: (qmail 9282 invoked by uid 22791); 14 Sep 2012 15:44:11 -0000 X-SWARE-Spam-Status: No, hits=1.6 required=5.0 tests=AWL, BAYES_50, RCVD_IN_DNSWL_NONE, SARE_HTML_INV_TAG, TW_BD, TW_BT, TW_DD, TW_DT, TW_GD, TW_GT, TW_IV, TW_OV, TW_QN, TW_RV, TW_SD, TW_UH, TW_UQ, TW_VH, TW_VQ, TW_VU, TW_XF X-Spam-Check-By: sourceware.org Received: from mo-p00-ob.rzone.de (HELO mo-p00-ob.rzone.de) (81.169.146.162) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 14 Sep 2012 15:43:48 +0000 X-RZG-AUTH: :LXoWVUeid/7A29J/hMvvT2k715jHQaJercGObUOFkj18odoYNahU4Q== X-RZG-CLASS-ID: mo00 Received: from [192.168.0.22] (business-188-111-022-002.static.arcor-ip.net [188.111.22.2]) by smtp.strato.de (jored mo14) (RZmta 30.14 AUTH) with ESMTPA id d07eb8o8EEkut7 ; Fri, 14 Sep 2012 17:43:36 +0200 (CEST) Message-ID: <505350A8.3000003@gjlay.de> Date: Fri, 14 Sep 2012 17:43:36 +0200 From: Georg-Johann Lay User-Agent: Thunderbird 2.0.0.24 (X11/20100302) MIME-Version: 1.0 To: gcc-patches@gcc.gnu.org CC: Sean D'Epagnier , Denis Chertykov , Eric Weddington Subject: [Patch,avr] ad PR54222: Support saturated +, -, ABS X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This patch adds more fixed-point support, namely saturated operations: SS_PLUS, SS_MINUS, SS_NEG, SS_ABS, US_PLUS, US_MINUS, US_NEG for all supported fixed-point modes: [U]QQ, [U]HQ, [U]HA, [U]SQ, [U]SA, [U]DQ, [U]DA, [U]TA. Depending on their complexity, the functions are implemented in libgcc or are natively supported by avr-gcc. The bulk of code is in the avr_out_plus_1 routine which has been generalized to perform saturation. avr_out_plus has been rewritten and is now generic enough to handle all the cases that were formerly treated by: avr_out_plus avr_out_plus_noclobber avr_out_minus avr_out_plus64 avr_out_minus64 The latter 4 functions are removed and the md files are cleaned up to use avr_out_plus. There are no new regressions. However, all new tests with "-Os -flto" fail because they trigger a segmentation fault in lto1 at gcc/tree-streamer-in.c:unpack_ts_fixed_cst_value_fields() while that function tries to deserialize TREE_FIXED_CST. Thus, these FAILs are because of an LTO issue. Except the "-Os -flto" cases, all other new tests PASS. Ok for trunk? Johann gcc/ PR target/54222 * config/avr/avr-fixed.md (ALL2S, ALL4S, ALL24S, ALL124S, ALL124U): New mode iterators. (3): New insns for SS_PLUS, SS_MINUS. (3): New insns for US_PLUS, US_MINUS. (usneg2): New insns. (2): New expanders for SS_NEG, SS_ABS. (*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. (3): New expanders for SS_PLUS, SS_MINUS. (3): New expanders for US_PLUS, US_MINUS. (3_insn): New insns. (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. (*add3, add3_clobber, add3, addpsi3, sub3): 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. 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. Index: gcc/testsuite/gcc.target/avr/torture/vals-llk.def =================================================================== --- gcc/testsuite/gcc.target/avr/torture/vals-llk.def (revision 0) +++ gcc/testsuite/gcc.target/avr/torture/vals-llk.def (revision 0) @@ -0,0 +1,32 @@ +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) + Index: gcc/testsuite/gcc.target/avr/torture/vals-uhr.def =================================================================== --- gcc/testsuite/gcc.target/avr/torture/vals-uhr.def (revision 0) +++ gcc/testsuite/gcc.target/avr/torture/vals-uhr.def (revision 0) @@ -0,0 +1,13 @@ +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) + Index: gcc/testsuite/gcc.target/avr/torture/sat-uk-plus-minus.c =================================================================== --- gcc/testsuite/gcc.target/avr/torture/sat-uk-plus-minus.c (revision 0) +++ gcc/testsuite/gcc.target/avr/torture/sat-uk-plus-minus.c (revision 0) @@ -0,0 +1,82 @@ +/* { dg-do run } */ +/* { dg-options "-std=gnu99 -fno-strict-overflow" } */ + +#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; +} Index: gcc/testsuite/gcc.target/avr/torture/sat-llk-plus-minus.c =================================================================== --- gcc/testsuite/gcc.target/avr/torture/sat-llk-plus-minus.c (revision 0) +++ gcc/testsuite/gcc.target/avr/torture/sat-llk-plus-minus.c (revision 0) @@ -0,0 +1,108 @@ +/* { dg-do run } */ +/* { dg-options "-std=gnu99 -fno-strict-overflow" } */ + +#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; +} Index: gcc/testsuite/gcc.target/avr/torture/sat-uhr-plus-minus.c =================================================================== --- gcc/testsuite/gcc.target/avr/torture/sat-uhr-plus-minus.c (revision 0) +++ gcc/testsuite/gcc.target/avr/torture/sat-uhr-plus-minus.c (revision 0) @@ -0,0 +1,73 @@ +/* { dg-do run } */ +/* { dg-options "-std=gnu99 -fno-strict-overflow" } */ + +#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; +} Index: gcc/testsuite/gcc.target/avr/torture/vals-uk.def =================================================================== --- gcc/testsuite/gcc.target/avr/torture/vals-uk.def (revision 0) +++ gcc/testsuite/gcc.target/avr/torture/vals-uk.def (revision 0) @@ -0,0 +1,23 @@ +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) + Index: gcc/testsuite/gcc.target/avr/torture/sat-r-plus-minus.c =================================================================== --- gcc/testsuite/gcc.target/avr/torture/sat-r-plus-minus.c (revision 0) +++ gcc/testsuite/gcc.target/avr/torture/sat-r-plus-minus.c (revision 0) @@ -0,0 +1,107 @@ +/* { dg-do run } */ +/* { dg-options "-std=gnu99 -fno-strict-overflow" } */ + +#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; +} Index: gcc/testsuite/gcc.target/avr/torture/vals-ur.def =================================================================== --- gcc/testsuite/gcc.target/avr/torture/vals-ur.def (revision 0) +++ gcc/testsuite/gcc.target/avr/torture/vals-ur.def (revision 0) @@ -0,0 +1,17 @@ +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) + Index: gcc/testsuite/gcc.target/avr/torture/sat-ullk-plus-minus.c =================================================================== --- gcc/testsuite/gcc.target/avr/torture/sat-ullk-plus-minus.c (revision 0) +++ gcc/testsuite/gcc.target/avr/torture/sat-ullk-plus-minus.c (revision 0) @@ -0,0 +1,82 @@ +/* { dg-do run } */ +/* { dg-options "-std=gnu99 -fno-strict-overflow" } */ + +#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; +} Index: gcc/testsuite/gcc.target/avr/torture/sat-hr-plus-minus.c =================================================================== --- gcc/testsuite/gcc.target/avr/torture/sat-hr-plus-minus.c (revision 0) +++ gcc/testsuite/gcc.target/avr/torture/sat-hr-plus-minus.c (revision 0) @@ -0,0 +1,98 @@ +/* { dg-do run } */ +/* { dg-options "-std=gnu99 -fno-strict-overflow" } */ + +#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; +} Index: gcc/testsuite/gcc.target/avr/torture/vals-k.def =================================================================== --- gcc/testsuite/gcc.target/avr/torture/vals-k.def (revision 0) +++ gcc/testsuite/gcc.target/avr/torture/vals-k.def (revision 0) @@ -0,0 +1,32 @@ +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) + Index: gcc/testsuite/gcc.target/avr/torture/vals-r.def =================================================================== --- gcc/testsuite/gcc.target/avr/torture/vals-r.def (revision 0) +++ gcc/testsuite/gcc.target/avr/torture/vals-r.def (revision 0) @@ -0,0 +1,30 @@ +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) + Index: gcc/testsuite/gcc.target/avr/torture/sat-ur-plus-minus.c =================================================================== --- gcc/testsuite/gcc.target/avr/torture/sat-ur-plus-minus.c (revision 0) +++ gcc/testsuite/gcc.target/avr/torture/sat-ur-plus-minus.c (revision 0) @@ -0,0 +1,82 @@ +/* { dg-do run } */ +/* { dg-options "-std=gnu99 -fno-strict-overflow" } */ + +#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; +} Index: gcc/testsuite/gcc.target/avr/torture/vals-ullk.def =================================================================== --- gcc/testsuite/gcc.target/avr/torture/vals-ullk.def (revision 0) +++ gcc/testsuite/gcc.target/avr/torture/vals-ullk.def (revision 0) @@ -0,0 +1,20 @@ +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) + Index: gcc/testsuite/gcc.target/avr/torture/vals-hr.def =================================================================== --- gcc/testsuite/gcc.target/avr/torture/vals-hr.def (revision 0) +++ gcc/testsuite/gcc.target/avr/torture/vals-hr.def (revision 0) @@ -0,0 +1,12 @@ +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) + Index: gcc/testsuite/gcc.target/avr/torture/sat-k-plus-minus.c =================================================================== --- gcc/testsuite/gcc.target/avr/torture/sat-k-plus-minus.c (revision 0) +++ gcc/testsuite/gcc.target/avr/torture/sat-k-plus-minus.c (revision 0) @@ -0,0 +1,108 @@ +/* { dg-do run } */ +/* { dg-options "-std=gnu99 -fno-strict-overflow" } */ + +#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; +} Index: gcc/testsuite/gcc.target/avr/torture/fix-types.h =================================================================== --- gcc/testsuite/gcc.target/avr/torture/fix-types.h (revision 0) +++ gcc/testsuite/gcc.target/avr/torture/fix-types.h (revision 0) @@ -0,0 +1,134 @@ +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; \ + }