From patchwork Fri Feb 2 18:13:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John David Anglin X-Patchwork-Id: 195974 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:9bc1:b0:106:209c:c626 with SMTP id op1csp609924dyc; Fri, 2 Feb 2024 10:14:19 -0800 (PST) X-Google-Smtp-Source: AGHT+IHOpW9cu9T6/xi2iRn+FHr46Xo5lADebp/QnRjqsV6U/HuPcv69RjS01PbgxsD6lP+1YiFK X-Received: by 2002:ac8:7fd5:0:b0:42a:7e53:827 with SMTP id b21-20020ac87fd5000000b0042a7e530827mr9264010qtk.30.1706897659205; Fri, 02 Feb 2024 10:14:19 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706897659; cv=pass; d=google.com; s=arc-20160816; b=WkQxaHiaQIk9B5cjc8/3DD7Br0/tdCXaKphgCOsI94gnmo16eUWpIJVoUthSkxEAHd jhGYcKukeIEsJnLb6jWO35FOcdyB1vGwsnH6XssuJ/YtH13xpcBY2x7z0Vm6QXNJ9UTj CZHdkv+TrU2dEfc4hhjAUU1Gm/ALTIOi6UPKI65R0ioKLx8MKzf69V64mZB0NbsDpRnx 3pE0kspd79WtCp8elkueHkLt6e6l9+NKMfQv47MJGEQvJyCY8nqHq1FqVmU07Hu1KNdb jnsfk8mrzg5J3Wz54OzRXJHku8a2FtP5r0rkTeuxqePYYtRgGPUL4QEYNZ62E6HyCaKo kL9Q== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-disposition :mime-version:message-id:subject:to:from:date:arc-filter :dmarc-filter:delivered-to; bh=/1n/p6XMMKdNXekiTQY3DVzXl3VYmt7Yj2SAEFkrxe4=; fh=3Fw9sqvuLKFO+0urzVGqegUJFRHQ5aKuIhfw/9+zOcQ=; b=lYQ5ivxSj5RDj5DojCH+kOTZe0smq7BpR2ANySPgkfIEJYqPYiGbFRZ/JqzJOFPpXy 0NmpoFHpT2CBTZ/Utw3Cus94TX9f4rvoxR2t7MTfSddrKCEt7w2T/izGYm1N1J250+Pd IgqrPzy1UQjH/o7HREstOAv7Ufckq2fiOoUomT2CShLlpCKGv49DdlAK3FALCRkyguCP e/3n8seyOyL/MmmAuZovCn32bUsX0vEj31CGJ/5WEepl/iYWt9FHKDuDTt9Vs5LzRN/7 wYjOAlKZucSL7yQOXVqNRETpFbc/Dv6+3mMDVLuiiWzhYwP84PXXwCaYHj2XNK4IbvSA KIhg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org" X-Forwarded-Encrypted: i=1; AJvYcCUOnQspNzo5oLc1Rhur7wSTS9hq0XA93qw24TqlsrhENQe7IqnA3HgmqRUIUKqs63iGwVGM2Uc4SJArqiQ+qlgeu+Y23w== Received: from server2.sourceware.org (server2.sourceware.org. [2620:52:3:1:0:246e:9693:128c]) by mx.google.com with ESMTPS id o17-20020ac85a51000000b0042c078f0018si1189940qta.265.2024.02.02.10.14.19 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 02 Feb 2024 10:14:19 -0800 (PST) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) client-ip=2620:52:3:1:0:246e:9693:128c; Authentication-Results: mx.google.com; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 2620:52:3:1:0:246e:9693:128c as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org" Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E12413858403 for ; Fri, 2 Feb 2024 18:14:18 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from dellerweb.de (unknown [IPv6:2a02:c207:3003:236::1]) by sourceware.org (Postfix) with ESMTPS id 1DEB93858403 for ; Fri, 2 Feb 2024 18:13:22 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 1DEB93858403 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=parisc-linux.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=parisc-linux.org ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 1DEB93858403 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a02:c207:3003:236::1 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706897604; cv=none; b=IJSCaIlSGsR+EF8hRU5zmK4J19ASRQLP6Y7Z5wef2AAV5KBZpWSMT3yfrLMmfwVo4RLPIsoMcycuYhp4VP5/1aTx7cBB2fKrYBNdrP4YIQ2OhcOqkno3z05uz5/CQ8TUXPSKuLESGpv4HRcyNDTO1yxR/pv07WCL48FR0bpYIjE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706897604; c=relaxed/simple; bh=R6UnH51MXspGgN3Dv1eZB2zya1AYesQFTiSEuihm6ts=; h=Date:From:To:Subject:Message-ID:MIME-Version; b=kAabQOBwLukWuQ3BcKW/VhDRfYfdSKhqWE3uRX0BCzIjRMjKPWAKfwfLkzQ8iCbtsfJ9VaUFlSqnP+1gj01mGHev9At78nF/ZOBst+jGMVRWqfa2bJVBFS8T/s0HYXcXN0EOtDUatk7DDK28cV4vvtGaCM4Uzr78YD0Tpc2rTig= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from mx3210.localdomain (bras-base-otwaon0906w-grc-03-142-126-114-79.dsl.bell.ca [142.126.114.79]) by dellerweb.de (Postfix) with ESMTPSA id A537016001C0; Fri, 2 Feb 2024 19:13:20 +0100 (CET) Received: by mx3210.localdomain (Postfix, from userid 1000) id 297FF22012D; Fri, 2 Feb 2024 18:13:19 +0000 (UTC) Date: Fri, 2 Feb 2024 18:13:18 +0000 From: John David Anglin To: GCC Patches Subject: [committed] hppa: Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV Message-ID: MIME-Version: 1.0 Content-Disposition: inline X-Spam-Status: No, score=-9.6 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE 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.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1789811919926368128 X-GMAIL-MSGID: 1789811919926368128 Tested on hppa-unknown-linux-gnu and hppa64-hp-hpux11.11. This is the first step in fixing PR target/59778. libatomic/fenv.c needs fixing for hppa so exceptions are correctly raised. Committed to trunk. Dave --- hppa: Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV This change implements __builtin_get_fpsr() and __builtin_set_fpsr(x) to get and set the floating-point status register. They are used to implement pa_atomic_assign_expand_fenv(). 2024-02-02 John David Anglin gcc/ChangeLog: PR target/59778 * config/pa/pa.cc (enum pa_builtins): Add PA_BUILTIN_GET_FPSR and PA_BUILTIN_SET_FPSR builtins. * (pa_builtins_icode): Declare. * (def_builtin, pa_fpu_init_builtins): New. * (pa_init_builtins): Initialize FPU builtins. * (pa_builtin_decl, pa_expand_builtin_1): New. * (pa_expand_builtin): Handle PA_BUILTIN_GET_FPSR and PA_BUILTIN_SET_FPSR builtins. * (pa_atomic_assign_expand_fenv): New. * config/pa/pa.md (UNSPECV_GET_FPSR, UNSPECV_SET_FPSR): New UNSPECV constants. (get_fpsr, put_fpsr): New expanders. (get_fpsr_32, get_fpsr_64, set_fpsr_32, set_fpsr_64): New insn patterns. diff --git a/gcc/config/pa/pa.cc b/gcc/config/pa/pa.cc index c58b0a0d75e..694123e37c9 100644 --- a/gcc/config/pa/pa.cc +++ b/gcc/config/pa/pa.cc @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "rtl.h" #include "tree.h" +#include "gimple.h" #include "df.h" #include "tm_p.h" #include "stringpool.h" @@ -142,6 +143,7 @@ static void pa_asm_out_destructor (rtx, int); #endif static void pa_init_builtins (void); static rtx pa_expand_builtin (tree, rtx, rtx, machine_mode mode, int); +static tree pa_builtin_decl (unsigned, bool); static rtx hppa_builtin_saveregs (void); static void hppa_va_start (tree, rtx); static tree hppa_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *); @@ -205,6 +207,7 @@ static bool pa_modes_tieable_p (machine_mode, machine_mode); static bool pa_can_change_mode_class (machine_mode, machine_mode, reg_class_t); static HOST_WIDE_INT pa_starting_frame_offset (void); static section* pa_elf_select_rtx_section(machine_mode, rtx, unsigned HOST_WIDE_INT) ATTRIBUTE_UNUSED; +static void pa_atomic_assign_expand_fenv (tree *, tree *, tree *); /* The following extra sections are only used for SOM. */ static GTY(()) section *som_readonly_data_section; @@ -314,9 +317,10 @@ static size_t n_deferred_plabels = 0; #undef TARGET_INIT_BUILTINS #define TARGET_INIT_BUILTINS pa_init_builtins - #undef TARGET_EXPAND_BUILTIN #define TARGET_EXPAND_BUILTIN pa_expand_builtin +#undef TARGET_BUILTIN_DECL +#define TARGET_BUILTIN_DECL pa_builtin_decl #undef TARGET_REGISTER_MOVE_COST #define TARGET_REGISTER_MOVE_COST hppa_register_move_cost @@ -426,6 +430,9 @@ static size_t n_deferred_plabels = 0; #undef TARGET_HAVE_SPECULATION_SAFE_VALUE #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed +#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV +#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV pa_atomic_assign_expand_fenv + struct gcc_target targetm = TARGET_INITIALIZER; /* Parse the -mfixed-range= option string. */ @@ -592,6 +599,10 @@ pa_option_override (void) enum pa_builtins { + /* FPU builtins. */ + PA_BUILTIN_GET_FPSR, + PA_BUILTIN_SET_FPSR, + PA_BUILTIN_COPYSIGNQ, PA_BUILTIN_FABSQ, PA_BUILTIN_INFQ, @@ -600,10 +611,48 @@ enum pa_builtins }; static GTY(()) tree pa_builtins[(int) PA_BUILTIN_max]; +static GTY(()) enum insn_code pa_builtins_icode[(int) PA_BUILTIN_max]; + +/* Add a PA builtin function with NAME, ICODE, CODE and TYPE. Return the + function decl or NULL_TREE if the builtin was not added. */ + +static tree +def_builtin (const char *name, enum insn_code icode, enum pa_builtins code, + tree type) +{ + tree t + = add_builtin_function (name, type, code, BUILT_IN_MD, NULL, NULL_TREE); + + if (t) + { + pa_builtins[code] = t; + pa_builtins_icode[code] = icode; + } + + return t; +} + +/* Create builtin functions for FPU instructions. */ + +static void +pa_fpu_init_builtins (void) +{ + tree ftype; + + ftype = build_function_type_list (unsigned_type_node, 0); + def_builtin ("__builtin_get_fpsr", CODE_FOR_get_fpsr, + PA_BUILTIN_GET_FPSR, ftype); + ftype = build_function_type_list (void_type_node, unsigned_type_node, 0); + def_builtin ("__builtin_set_fpsr", CODE_FOR_set_fpsr, + PA_BUILTIN_SET_FPSR, ftype); +} static void pa_init_builtins (void) { + if (!TARGET_SOFT_FLOAT) + pa_fpu_init_builtins (); + #ifdef DONT_HAVE_FPUTC_UNLOCKED { tree decl = builtin_decl_explicit (BUILT_IN_PUTC_UNLOCKED); @@ -663,6 +712,92 @@ pa_init_builtins (void) } } +/* Implement TARGET_BUILTIN_DECL. */ + +static tree +pa_builtin_decl (unsigned int code, bool initialize_p ATTRIBUTE_UNUSED) +{ + if (code >= PA_BUILTIN_max) + return error_mark_node; + return pa_builtins[code]; +} + +static rtx +pa_expand_builtin_1 (tree exp, rtx target, + rtx subtarget ATTRIBUTE_UNUSED, + machine_mode tmode ATTRIBUTE_UNUSED, + int ignore ATTRIBUTE_UNUSED) +{ + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); + enum pa_builtins code + = (enum pa_builtins) DECL_MD_FUNCTION_CODE (fndecl); + enum insn_code icode = pa_builtins_icode[code]; + bool nonvoid = TREE_TYPE (TREE_TYPE (fndecl)) != void_type_node; + call_expr_arg_iterator iter; + int arg_count = 0; + rtx pat, op[4]; + tree arg; + + if (nonvoid) + { + machine_mode tmode = insn_data[icode].operand[0].mode; + if (!target + || GET_MODE (target) != tmode + || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) + op[0] = gen_reg_rtx (tmode); + else + op[0] = target; + } + else + op[0] = NULL_RTX; + + FOR_EACH_CALL_EXPR_ARG (arg, iter, exp) + { + const struct insn_operand_data *insn_op; + int idx; + + if (arg == error_mark_node) + return NULL_RTX; + + arg_count++; + idx = arg_count - !nonvoid; + insn_op = &insn_data[icode].operand[idx]; + op[arg_count] = expand_normal (arg); + + if (! (*insn_data[icode].operand[idx].predicate) (op[arg_count], + insn_op->mode)) + op[arg_count] = copy_to_mode_reg (insn_op->mode, op[arg_count]); + } + + switch (arg_count) + { + case 0: + pat = GEN_FCN (icode) (op[0]); + break; + case 1: + if (nonvoid) + pat = GEN_FCN (icode) (op[0], op[1]); + else + pat = GEN_FCN (icode) (op[1]); + break; + case 2: + pat = GEN_FCN (icode) (op[0], op[1], op[2]); + break; + case 3: + pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]); + break; + default: + gcc_unreachable (); + } + + if (!pat) + return NULL_RTX; + + emit_insn (pat); + + return (nonvoid ? op[0] : const0_rtx); +} + static rtx pa_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, machine_mode mode ATTRIBUTE_UNUSED, @@ -673,6 +808,10 @@ pa_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, switch (fcode) { + case PA_BUILTIN_GET_FPSR: + case PA_BUILTIN_SET_FPSR: + return pa_expand_builtin_1 (exp, target, subtarget, mode, ignore); + case PA_BUILTIN_FABSQ: case PA_BUILTIN_COPYSIGNQ: return expand_call (exp, target, ignore); @@ -11099,4 +11238,78 @@ pa_function_arg_size (machine_mode mode, const_tree type) return (int) CEIL (size, UNITS_PER_WORD); } +/* Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV. */ + +static void +pa_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update) +{ + const unsigned PA_FE_INEXACT = 1; + const unsigned PA_FE_UNDERFLOW = 2; + const unsigned PA_FE_OVERFLOW = 4; + const unsigned PA_FE_DIVBYZERO = 8; + const unsigned PA_FE_INVALID = 16; + const unsigned HOST_WIDE_INT PA_FE_ALL_EXCEPT = (PA_FE_INVALID + | PA_FE_DIVBYZERO + | PA_FE_OVERFLOW + | PA_FE_UNDERFLOW + | PA_FE_INEXACT); + const unsigned HOST_WIDE_INT PA_FE_EXCEPT_SHIFT = 27; + tree fenv_var, get_fpsr, set_fpsr, mask, ld_fenv, masked_fenv; + tree hold_all, new_fenv_var, reload_fenv, restore_fnenv; + tree get_fpsr_call, set_fpsr_call, update_call, atomic_feraiseexcept; + + if (TARGET_SOFT_FLOAT) + return; + + /* Generate the equivalent of : + unsigned int fenv_var; + fenv_var = __builtin_get_fpsr (); + + unsigned int masked_fenv; + masked_fenv = fenv_var & mask; + + __builtin_set_fpsr (masked_fenv); */ + + fenv_var = create_tmp_var_raw (unsigned_type_node); + get_fpsr = pa_builtins[PA_BUILTIN_GET_FPSR]; + set_fpsr = pa_builtins[PA_BUILTIN_SET_FPSR]; + mask = build_int_cst (unsigned_type_node, + ~((PA_FE_ALL_EXCEPT << PA_FE_EXCEPT_SHIFT) + | PA_FE_ALL_EXCEPT)); + + get_fpsr_call = build_call_expr (get_fpsr, 0); + ld_fenv = build4 (TARGET_EXPR, unsigned_type_node, + fenv_var, get_fpsr_call, + NULL_TREE, NULL_TREE); + masked_fenv = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_var, mask); + hold_all = build2 (COMPOUND_EXPR, void_type_node, masked_fenv, ld_fenv); + set_fpsr_call = build_call_expr (set_fpsr, 1, masked_fenv); + *hold = build2 (COMPOUND_EXPR, void_type_node, hold_all, set_fpsr_call); + + /* Store the value of masked_fenv to clear the exceptions: + __builtin_set_fpsr (masked_fenv); */ + + *clear = set_fpsr_call; + + /* Generate the equivalent of : + unsigned int new_fenv_var; + new_fenv_var = __builtin_get_fpsr (); + + __builtin_set_fpsr (fenv_var); + + __atomic_feraiseexcept (new_fenv_var); */ + + new_fenv_var = create_tmp_var_raw (unsigned_type_node); + reload_fenv = build4 (TARGET_EXPR, unsigned_type_node, new_fenv_var, + get_fpsr_call, NULL_TREE, NULL_TREE); + restore_fnenv = build_call_expr (set_fpsr, 1, fenv_var); + atomic_feraiseexcept = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT); + update_call = build_call_expr (atomic_feraiseexcept, 1, + fold_convert (integer_type_node, + new_fenv_var)); + *update = build2 (COMPOUND_EXPR, void_type_node, + build2 (COMPOUND_EXPR, void_type_node, + reload_fenv, restore_fnenv), update_call); +} + #include "gt-pa.h" diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index 52ad0c3776d..3bcb8473479 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -96,6 +96,8 @@ UNSPECV_OPC ; outline_prologue_call UNSPECV_OEC ; outline_epilogue_call UNSPECV_LONGJMP ; builtin_longjmp + UNSPECV_GET_FPSR ; get floating-point status register + UNSPECV_SET_FPSR ; set floating-point status register ]) ;; Maximum pc-relative branch offsets. @@ -10784,3 +10786,85 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" "ldo 15(%%sp),%1\n\t{dep|depw} %%r0,31,3,%1\n\t{ldcw|ldcw,co} 0(%1),%1" [(set_attr "type" "binary") (set_attr "length" "12")]) + +;; Get floating-point status register. + +(define_expand "get_fpsr" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))] + "" +{ + if (TARGET_SOFT_FLOAT) + FAIL; + + if (TARGET_64BIT) + emit_insn (gen_get_fpsr_64 (operands[0])); + else + emit_insn (gen_get_fpsr_32 (operands[0])); + DONE; +}) + +;; The floating-point status register is stored to an unused slot in +;; the frame marker and then loaded to register operand 0. The final +;; floating-point load restores the T bit in the status register. + +;; The final load might be avoided if a word mode store was used to +;; store the status register. It is unclear why we need a double-word +;; store. I suspect PA 1.0 didn't support single-word stores of the +;; status register. + +(define_insn "get_fpsr_32" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))] + "!TARGET_SOFT_FLOAT && !TARGET_64BIT" + "{fstds|fstd} %%fr0,-16(%%sp)\n\tldw -16(%%sp),%0\n\t{fldds|fldd} -16(%%sp),%%fr0" + [(set_attr "type" "fpstore_load") + (set_attr "length" "12")]) + +;; The 64-bit pattern is similar to the 32-bit pattern except we need +;; compute the address of the frame location as long displacements aren't +;; supported on Linux targets. + +(define_insn "get_fpsr_64" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR)) + (clobber (match_scratch:DI 1 "=&r"))] + "!TARGET_SOFT_FLOAT && TARGET_64BIT" + "ldo -40(%%sp),%1\n\tfstd %%fr0,0(%1)\n\tldw 0(%1),%0\n\tfldd 0(%1),%%fr0" + [(set_attr "type" "fpstore_load") + (set_attr "length" "16")]) + +;; Set floating-point status register. + +(define_expand "set_fpsr" + [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)] + "" +{ + if (TARGET_SOFT_FLOAT) + FAIL; + + if (TARGET_64BIT) + emit_insn (gen_set_fpsr_64 (operands[0])); + else + emit_insn (gen_set_fpsr_32 (operands[0])); + DONE; +}) + +;; The old T bit is extracted and stored in the new status register. + +(define_insn "set_fpsr_32" + [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR) + (clobber (match_scratch:SI 1 "=&r"))] + "!TARGET_SOFT_FLOAT && !TARGET_64BIT" + "{fstds|fstd} %%fr0,-16(%%sp)\n\tldw -16(%%sp),%1\n\t{extru|extrw,u} %1,25,1,%1\n\t{dep|depw} %1,25,1,%0\n\tstw %0,-16(%%sp)\n\t{fldds|fldd} -16(%%sp),%%fr0" + [(set_attr "type" "store_fpload") + (set_attr "length" "24")]) + +(define_insn "set_fpsr_64" + [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR) + (clobber (match_scratch:DI 1 "=&r")) + (clobber (match_scratch:SI 2 "=&r"))] + "!TARGET_SOFT_FLOAT && TARGET_64BIT" + "ldo -40(%%sp),%1\n\tfstd %%fr0,0(%1)\n\tldw 0(%1),%2\n\textrw,u %2,25,1,%2\n\tdepw %2,25,1,%0\n\tstw %0,0(%1)\n\tfldd 0(%1),%%fr0" + [(set_attr "type" "store_fpload") + (set_attr "length" "28")])