From patchwork Tue Aug 8 02:09:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: chenxiaolong X-Patchwork-Id: 1818366 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Received: from server2.sourceware.org (ip-8-43-85-97.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4RKc8749zFz1yYl for ; Tue, 8 Aug 2023 12:09:40 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id C3E1C3858017 for ; Tue, 8 Aug 2023 02:09:37 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from eggs.gnu.org (eggs.gnu.org [IPv6:2001:470:142:3::10]) by sourceware.org (Postfix) with ESMTPS id 3A3D63858C41 for ; Tue, 8 Aug 2023 02:09:23 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 3A3D63858C41 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=loongson.cn Received: from mail.loongson.cn ([114.242.206.163]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qTC9u-0007AC-6E for gcc-patches@gcc.gnu.org; Mon, 07 Aug 2023 22:09:22 -0400 Received: from loongson.cn (unknown [10.10.130.252]) by gateway (Coremail) with SMTP id _____8DxxPDCo9Fks3kSAA--.41858S3; Tue, 08 Aug 2023 10:09:07 +0800 (CST) Received: from slurm-master.loongson.cn (unknown [10.10.130.252]) by localhost.localdomain (Coremail) with SMTP id AQAAf8AxTSPAo9FkNC9OAA--.48401S4; Tue, 08 Aug 2023 10:09:04 +0800 (CST) From: chenxiaolong To: gcc-patches@gcc.gnu.org Cc: xry111@xry111.site, i@xen0n.name, xuchenghua@loongson.cn, chenglulu@loongson.cn, chenxiaolong Subject: [PATCH v2] LoongArch:Implement 128-bit floating point functions in gcc. Date: Tue, 8 Aug 2023 10:09:02 +0800 Message-Id: <20230808020902.11626-1-chenxiaolong@loongson.cn> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 X-CM-TRANSID: AQAAf8AxTSPAo9FkNC9OAA--.48401S4 X-CM-SenderInfo: hfkh05xldrz0tqj6z05rqj20fqof0/1tbiAQARBWTQbzEJQwAAs1 X-Coremail-Antispam: 1Uk129KBj9fXoW3Zw4UtF4DAr1DtFW3Zr13Awc_yoW8WF1rCo W5AF1qq3Z5Wr1Iva4YgwnIgryYvF18ArWkCry3Zw1fCa1kJr15Ca4qgw4rJ347KrZ3WF4U Ca43GrZxJFWxJFn5l-sFpf9Il3svdjkaLaAFLSUrUUUUbb8apTn2vfkv8UJUUUU8wcxFpf 9Il3svdxBIdaVrn0xqx4xG64xvF2IEw4CE5I8CrVC2j2Jv73VFW2AGmfu7bjvjm3AaLaJ3 UjIYCTnIWjp_UUUYU7kC6x804xWl14x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI 8IcIk0rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xG Y2AK021l84ACjcxK6xIIjxv20xvE14v26r1j6r1xM28EF7xvwVC0I7IYx2IY6xkF7I0E14 v26r1j6r4UM28EF7xvwVC2z280aVAFwI0_Gr0_Cr1l84ACjcxK6I8E87Iv6xkF7I0E14v2 6r4j6r4UJwAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07AIYIkI8VC2zVCFFI0UMc 02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWUXVWUAwAv7VC2z280aVAF wI0_Jr0_Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JMxAIw28IcxkI7V AKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCj r7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUAVWUtwCIc40Y0x0EwIxGrwCI42IY6x IIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVWUJVW8JwCI42IY6xAI w20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Jr0_Gr1lIxAIcVC2z280aVCY1x 0267AKxVWUJVW8JbIYCTnIWIevJa73UjIFyTuYvjxUwmhFDUUUU Received-SPF: pass client-ip=114.242.206.163; envelope-from=chenxiaolong@loongson.cn; helo=mail.loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Spam-Status: No, score=-15.2 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_SHORT, SPF_FAIL, SPF_HELO_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" In the implementation process, the "q" suffix function is Re-register and associate the "__float128" type with the "long double" type so that the compiler can handle the corresponding function correctly. The functions implemented include __builtin_{huge_valq infq, fabsq, copysignq, nanq, nansq}. gcc/ChangeLog: * config/loongarch/loongarch-builtins.cc (DEF_LARCH_FTYPE): (MATHQ_NUMS=):Counts the number of builtin functions with the suffix "q". (enum loongarch_builtin_type):Add the type of the function. (FLOAT_BUILTIN_HIQ): (FLOAT_BUILTIN_NNFCQ): (loongarch_init_builtins): (loongarch_fold_builtin): (loongarch_expand_builtin): * config/loongarch/loongarch-protos.h (loongarch_fold_builtin): (loongarch_c_mode_for_suffix):Add the declaration of the function. * config/loongarch/loongarch.cc (loongarch_c_mode_for_suffix):Add the definition of the function. (TARGET_FOLD_BUILTIN): (TARGET_C_MODE_FOR_SUFFIX): * config/loongarch/loongarch.md (infq): ():Add an instruction template to the machine description file to generate information such as the icode used by the function and the constructor. libgcc/ChangeLog: * config/loongarch/t-softfp-tf: * config/loongarch/tf-signs.c: New file. --- gcc/config/loongarch/loongarch-builtins.cc | 158 ++++++++++++++++++++- gcc/config/loongarch/loongarch-protos.h | 2 + gcc/config/loongarch/loongarch.cc | 14 ++ gcc/config/loongarch/loongarch.md | 25 ++++ libgcc/config/loongarch/t-softfp-tf | 3 + libgcc/config/loongarch/tf-signs.c | 99 +++++++++++++ 6 files changed, 299 insertions(+), 2 deletions(-) create mode 100644 libgcc/config/loongarch/tf-signs.c diff --git a/gcc/config/loongarch/loongarch-builtins.cc b/gcc/config/loongarch/loongarch-builtins.cc index b929f224dfa..6e32f86fc52 100644 --- a/gcc/config/loongarch/loongarch-builtins.cc +++ b/gcc/config/loongarch/loongarch-builtins.cc @@ -36,6 +36,8 @@ along with GCC; see the file COPYING3. If not see #include "fold-const.h" #include "expr.h" #include "langhooks.h" +#include "calls.h" +#include "explow.h" /* Macros to create an enumeration identifier for a function prototype. */ #define LARCH_FTYPE_NAME1(A, B) LARCH_##A##_FTYPE_##B @@ -48,9 +50,18 @@ enum loongarch_function_type #define DEF_LARCH_FTYPE(NARGS, LIST) LARCH_FTYPE_NAME##NARGS LIST, #include "config/loongarch/loongarch-ftypes.def" #undef DEF_LARCH_FTYPE + LARCH_BUILTIN_HUGE_VALQ, + LARCH_BUILTIN_INFQ, + LARCH_BUILTIN_FABSQ, + LARCH_BUILTIN_COPYSIGNQ, + LARCH_BUILTIN_NANQ, + LARCH_BUILTIN_NANSQ, LARCH_MAX_FTYPE_MAX }; +/* Count the number of functions with "q" as the suffix. */ +const int MATHQ_NUMS=(int)LARCH_MAX_FTYPE_MAX-(int)LARCH_BUILTIN_HUGE_VALQ; + /* Specifies how a built-in function should be converted into rtl. */ enum loongarch_builtin_type { @@ -63,6 +74,12 @@ enum loongarch_builtin_type value and the arguments are mapped to operands 0 and above. */ LARCH_BUILTIN_DIRECT_NO_TARGET, + /* The function corresponds to __builtin_{huge_valq,infq}. */ + LARCH_BUILTIN_HIQ_DIRECT, + + /* Define the type of the __builtin_{nanq,nansq,fabsq,copysignq} function. */ + LARCH_BUILTIN_NNFCQ_DIRECT + }; /* Declare an availability predicate for built-in functions that require @@ -136,6 +153,18 @@ AVAIL_ALL (hard_float, TARGET_HARD_FLOAT_ABI) LARCH_BUILTIN (INSN, #INSN, LARCH_BUILTIN_DIRECT_NO_TARGET, \ FUNCTION_TYPE, AVAIL) +/* Define an float to do funciton {huge_valq,infq}.*/ +#define FLOAT_BUILTIN_HIQ(INSN, FUNCTION_TYPE) \ + { CODE_FOR_ ## INSN, \ + "__builtin_" #INSN, LARCH_BUILTIN_HIQ_DIRECT, \ + FUNCTION_TYPE, loongarch_builtin_avail_default } + +/* Define an float to do funciton {nanq,nansq,fabsq,copysignq}.*/ +#define FLOAT_BUILTIN_NNFCQ(INSN, FUNCTION_TYPE) \ + { CODE_FOR_ ## INSN, \ + "__builtin_" #INSN, LARCH_BUILTIN_NNFCQ_DIRECT, \ + FUNCTION_TYPE, loongarch_builtin_avail_default } + static const struct loongarch_builtin_description loongarch_builtins[] = { #define LARCH_MOVFCSR2GR 0 DIRECT_BUILTIN (movfcsr2gr, LARCH_USI_FTYPE_UQI, hard_float), @@ -183,6 +212,14 @@ static const struct loongarch_builtin_description loongarch_builtins[] = { DIRECT_NO_TARGET_BUILTIN (asrtgt_d, LARCH_VOID_FTYPE_DI_DI, default), DIRECT_NO_TARGET_BUILTIN (syscall, LARCH_VOID_FTYPE_USI, default), DIRECT_NO_TARGET_BUILTIN (break, LARCH_VOID_FTYPE_USI, default), + + FLOAT_BUILTIN_HIQ (huge_valq, LARCH_BUILTIN_HUGE_VALQ), + FLOAT_BUILTIN_HIQ (infq, LARCH_BUILTIN_INFQ), + FLOAT_BUILTIN_NNFCQ (fabsq, LARCH_BUILTIN_FABSQ), + FLOAT_BUILTIN_NNFCQ (nanq, LARCH_BUILTIN_NANQ), + FLOAT_BUILTIN_NNFCQ (nansq, LARCH_BUILTIN_NANSQ), + FLOAT_BUILTIN_NNFCQ (copysignq, LARCH_BUILTIN_COPYSIGNQ), + }; /* Index I is the function declaration for loongarch_builtins[I], or null if @@ -255,10 +292,13 @@ loongarch_init_builtins (void) const struct loongarch_builtin_description *d; unsigned int i; tree type; + tree const_string_type + =build_pointer_type (build_qualified_type (char_type_node, + TYPE_QUAL_CONST)); /* Iterate through all of the bdesc arrays, initializing all of the builtin functions. */ - for (i = 0; i < ARRAY_SIZE (loongarch_builtins); i++) + for (i = 0; i < ARRAY_SIZE (loongarch_builtins)-MATHQ_NUMS; i++) { d = &loongarch_builtins[i]; if (d->avail ()) @@ -270,6 +310,63 @@ loongarch_init_builtins (void) loongarch_get_builtin_decl_index[d->icode] = i; } } + /* Register the type long_double_type_node as a built-in type and + give it an alias "__float128". */ + (*lang_hooks.types.register_builtin_type) (long_double_type_node, + "__float128"); + + type = build_function_type_list (long_double_type_node, NULL_TREE); + d = &loongarch_builtins[i]; + loongarch_builtin_decls[i] + =add_builtin_function ("__builtin_huge_valq", type, + i, BUILT_IN_MD, NULL, NULL_TREE); + loongarch_get_builtin_decl_index[d->icode]=i++; + + type = build_function_type_list (long_double_type_node, NULL_TREE); + d = &loongarch_builtins[i]; + loongarch_builtin_decls[i] + =add_builtin_function ("__builtin_infq", type, + i, BUILT_IN_MD, NULL, NULL_TREE); + loongarch_get_builtin_decl_index[d->icode]=i++; + + type = build_function_type_list (long_double_type_node, + long_double_type_node, + NULL_TREE); + d = &loongarch_builtins[i]; + loongarch_builtin_decls[i] + =add_builtin_function ("__builtin_fabsq", type, + i, BUILT_IN_MD, "__fabstf2", NULL_TREE); + TREE_READONLY (loongarch_builtin_decls[i]) =1; + loongarch_get_builtin_decl_index[d->icode]=i++; + + type = build_function_type_list (long_double_type_node, + long_double_type_node, + long_double_type_node, + NULL_TREE); + d = &loongarch_builtins[i]; + loongarch_builtin_decls[i] + =add_builtin_function ("__builtin_copysignq", type, + i, BUILT_IN_MD, "__copysigntf3", NULL_TREE); + TREE_READONLY (loongarch_builtin_decls[i]) =1; + loongarch_get_builtin_decl_index[d->icode]=i++; + + type=build_function_type_list (long_double_type_node, + const_string_type, + NULL_TREE); + d = &loongarch_builtins[i]; + loongarch_builtin_decls[i] + =add_builtin_function ("__builtin_nanq", type, + i, BUILT_IN_MD, "nanq", NULL_TREE); + TREE_READONLY (loongarch_builtin_decls[i]) =1; + loongarch_get_builtin_decl_index[d->icode]=i++; + + d = &loongarch_builtins[i]; + loongarch_builtin_decls[i] + =add_builtin_function ("__builtin_nansq", type, + i, BUILT_IN_MD, "nansq", NULL_TREE); + TREE_READONLY (loongarch_builtin_decls[i]) =1; + loongarch_get_builtin_decl_index[d->icode]=i; + } /* Implement TARGET_BUILTIN_DECL. */ @@ -282,6 +379,42 @@ loongarch_builtin_decl (unsigned int code, bool initialize_p ATTRIBUTE_UNUSED) return loongarch_builtin_decls[code]; } +tree +loongarch_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, + tree *args, bool ignore ATTRIBUTE_UNUSED) +{ + if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) + { + enum loongarch_function_type fn_code + = (enum loongarch_function_type) DECL_MD_FUNCTION_CODE (fndecl); + switch (fn_code) + { + case LARCH_BUILTIN_NANQ: + case LARCH_BUILTIN_NANSQ: + { + tree type = TREE_TYPE (TREE_TYPE (fndecl)); + const char *str = c_getstr (*args); + int quiet = fn_code == LARCH_BUILTIN_NANQ; + REAL_VALUE_TYPE real; + + if (str && real_nan (&real, str, quiet, TYPE_MODE (type))) + return build_real (type, real); + return NULL_TREE; + } + + default: + break; + } + } + +#ifdef SUBTARGET_FOLD_BUILTIN + return SUBTARGET_FOLD_BUILTIN (fndecl, n_args, args, ignore); +#endif + + return NULL_TREE; +} + + /* Take argument ARGNO from EXP's argument list and convert it into an expand operand. Store the operand in *OP. */ @@ -366,7 +499,28 @@ loongarch_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, case LARCH_BUILTIN_DIRECT_NO_TARGET: return loongarch_expand_builtin_direct (d->icode, target, exp, false); - } + + case LARCH_BUILTIN_NNFCQ_DIRECT: + return expand_call ( exp ,target , ignore); + + case LARCH_BUILTIN_HIQ_DIRECT: + { + machine_mode target_mode = TYPE_MODE (TREE_TYPE (exp)); + REAL_VALUE_TYPE inf; + rtx tmp; + + real_inf (&inf); + tmp = const_double_from_real_value (inf, target_mode); + + tmp=validize_mem (force_const_mem (target_mode,tmp)); + + if (target ==0) + target =gen_reg_rtx (target_mode); + emit_move_insn (target,tmp); + + return target; + } + } gcc_unreachable (); } diff --git a/gcc/config/loongarch/loongarch-protos.h b/gcc/config/loongarch/loongarch-protos.h index b71b188507a..35fc2ad7def 100644 --- a/gcc/config/loongarch/loongarch-protos.h +++ b/gcc/config/loongarch/loongarch-protos.h @@ -175,11 +175,13 @@ extern void loongarch_register_frame_header_opt (void); /* Routines implemented in loongarch-c.c. */ void loongarch_cpu_cpp_builtins (cpp_reader *); +extern tree loongarch_fold_builtin (tree, int, tree*, bool); extern void loongarch_init_builtins (void); extern void loongarch_atomic_assign_expand_fenv (tree *, tree *, tree *); extern tree loongarch_builtin_decl (unsigned int, bool); extern rtx loongarch_expand_builtin (tree, rtx, rtx subtarget ATTRIBUTE_UNUSED, machine_mode, int); extern tree loongarch_build_builtin_va_list (void); +extern machine_mode loongarch_c_mode_for_suffix (char suffix); #endif /* ! GCC_LOONGARCH_PROTOS_H */ diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index 5b8b93eb24b..0da147358b1 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -6789,6 +6789,16 @@ loongarch_set_handled_components (sbitmap components) cfun->machine->reg_is_wrapped_separately[regno] = true; } +/* Target hook for c_mode_for_suffix. */ +machine_mode +loongarch_c_mode_for_suffix (char suffix) +{ + if (suffix == 'q') + return TFmode; + + return VOIDmode; +} + /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" @@ -6900,6 +6910,10 @@ loongarch_set_handled_components (sbitmap components) #define TARGET_BUILTIN_DECL loongarch_builtin_decl #undef TARGET_EXPAND_BUILTIN #define TARGET_EXPAND_BUILTIN loongarch_expand_builtin +#undef TARGET_FOLD_BUILTIN +#define TARGET_FOLD_BUILTIN loongarch_fold_builtin +#undef TARGET_C_MODE_FOR_SUFFIX +#define TARGET_C_MODE_FOR_SUFFIX loongarch_c_mode_for_suffix /* The generic ELF target does not always have TLS support. */ #ifdef HAVE_AS_TLS diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md index b37e070660f..c545386aa7b 100644 --- a/gcc/config/loongarch/loongarch.md +++ b/gcc/config/loongarch/loongarch.md @@ -44,6 +44,13 @@ (define_c_enum "unspec" [ UNSPEC_FSCALEB UNSPEC_FLOGB + UNSPEC_INFQ + UNSPEC_HUGE_VALQ + UNSPEC_FABSQ + UNSPEC_COPYSIGNQ + UNSPEC_NANQ + UNSPEC_NANSQ + ;; Override return address for exception handling. UNSPEC_EH_RETURN @@ -563,6 +570,17 @@ (define_int_attr bytepick_imm [(8 "1") (48 "6") (56 "7")]) +;; mathq function +(define_int_iterator MATHQ[UNSPEC_INFQ UNSPEC_HUGE_VALQ UNSPEC_FABSQ + UNSPEC_COPYSIGNQ UNSPEC_NANQ UNSPEC_NANSQ]) +(define_int_attr mathq_pattern[(UNSPEC_INFQ "infq") + (UNSPEC_HUGE_VALQ "huge_valq") + (UNSPEC_FABSQ "fabsq") + (UNSPEC_COPYSIGNQ "copysignq") + (UNSPEC_NANQ "nanq") + (UNSPEC_NANSQ "nansq")] +) + ;; ;; .................... ;; @@ -2008,6 +2026,13 @@ (define_insn "movfcc" "" "movgr2cf\t%0,$r0") +;; Implements functions with a "q" suffix + +(define_insn "" + [(unspec:SI[(const_int 0)] MATHQ)] + "" + "") + ;; Conditional move instructions. (define_insn "*sel_using_" diff --git a/libgcc/config/loongarch/t-softfp-tf b/libgcc/config/loongarch/t-softfp-tf index 306677b1255..0e7c2b4cabe 100644 --- a/libgcc/config/loongarch/t-softfp-tf +++ b/libgcc/config/loongarch/t-softfp-tf @@ -1,3 +1,6 @@ softfp_float_modes += tf softfp_extensions += sftf dftf softfp_truncations += tfsf tfdf +#Used to implement a special 128-bit function with a q suffix +LIB2ADD += $(srcdir)/config/loongarch/tf-signs.c + diff --git a/libgcc/config/loongarch/tf-signs.c b/libgcc/config/loongarch/tf-signs.c new file mode 100644 index 00000000000..395d6a18623 --- /dev/null +++ b/libgcc/config/loongarch/tf-signs.c @@ -0,0 +1,99 @@ +/* Copyright (C) 2008-2023 Free Software Foundation, Inc. + +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. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ +#include +#include + +union _FP_UNION_Q +{ + __float128 flt; + struct + { + unsigned long frac0 : 64; + unsigned long frac1 : 48; + unsigned exp : 15; + unsigned sign : 1; + } bits __attribute__((packed)); +}; + +__float128 __copysigntf3 (__float128, __float128); +__float128 __fabstf2 (__float128); +int __signbittf2 (__float128); +__float128 nanq (const char *str); +__float128 nansq (const char *str); + +__float128 +__copysigntf3 (__float128 a, __float128 b) +{ + union _FP_UNION_Q A, B; + + A.flt = a; + B.flt = b; + A.bits.sign = B.bits.sign; + + return A.flt; +} + +__float128 +__fabstf2 (__float128 a) +{ + union _FP_UNION_Q A; + + A.flt = a; + A.bits.sign = 0; + + return A.flt; +} + +int +__signbittf2 (__float128 a) +{ + union _FP_UNION_Q A; + + A.flt = a; + + return A.bits.sign; +} + +__float128 nanq (const char * str) +{ + union _FP_UNION_Q nan; + nan.bits.frac0 = 0; + nan.bits.frac1 = 0; + nan.bits.exp = 0x7FFF; + nan.bits.sign = 1; + if (str != NULL && strlen (str) > 0) + return nan.flt; + return 0; +} +__float128 nansq (const char *str) +{ + union _FP_UNION_Q nan; + nan.bits.frac0 = 0; + nan.bits.frac1 = 0; + nan.bits.exp = 0x7FFF; + nan.bits.sign = 1; + if (str != NULL && strlen (str) > 0) + return nan.flt; + return 0; +} +