From patchwork Wed Jun 27 18:32:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Law X-Patchwork-Id: 935665 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-480573-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="xYOGW56U"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 41GBNN0GNvz9s2g for ; Thu, 28 Jun 2018 04:32:35 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:message-id:date:mime-version:content-type; q=dns; s= default; b=UivNq0cfvhfsuRSm/LuhmSi93NXJKjX0KCXTMffX6hEX6TVIzQemN CtWfyAhGQf2QTXxZLnL+wUXA+uRaNBMp4GJPh77W9mcuf0jZRul0pXpX0u6VPP7p YFjeudO3fti+LWBNiNlAwr9OlJ5Gc0e4dsncnf2p9qrqcQKGT0VtKA= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :subject:to:message-id:date:mime-version:content-type; s= default; bh=/ApqXs9vplfLZVBKlCLZxZg7GMo=; b=xYOGW56UPxEEFAEPkksd 0t+PZEJStHbUdA9drXpuMb5ItwfXLIqLlFd4cuFA1oqYVv0A+KHvpSGwumzmKzD8 tl3cwNweTEPxVOnzzJVUSJoT82L4rVIe2wcYIphGYNfJ8N9uplUQEu6f4UmJtURp WXzSoFrfkIq2kbO1gNK1l3s= Received: (qmail 70629 invoked by alias); 27 Jun 2018 18:32:27 -0000 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 Received: (qmail 70553 invoked by uid 89); 27 Jun 2018 18:32:22 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.1 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, KAM_LAZY_DOMAIN_SECURITY, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=FCC, fcc, movement, 0r X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 27 Jun 2018 18:32:16 +0000 Received: from smtp.corp.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1A5BD308A968 for ; Wed, 27 Jun 2018 18:32:15 +0000 (UTC) Received: from localhost.localdomain (ovpn-112-5.rdu2.redhat.com [10.10.112.5]) by smtp.corp.redhat.com (Postfix) with ESMTP id 17AAB903D1 for ; Wed, 27 Jun 2018 18:32:13 +0000 (UTC) From: Jeff Law Subject: [committed] [2/3] Converting the v850 port away from cc0 -- basic support for new scheme Openpgp: preference=signencrypt To: gcc-patches Message-ID: <90e9cdf4-9ddd-a3fd-6d5d-75bec16b9ab5@redhat.com> Date: Wed, 27 Jun 2018 12:32:13 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.8.0 MIME-Version: 1.0 X-IsSubscribed: yes This is the bulk of the changes. With this change in installed the v850 port should be using the new mechanism for condition code handling consistently, though without optimizing well. This is a fairly large change which hits a great many patterns. It's largely what one would expect. THe comparison/branch are kept together as a unit prior to reload, but split post-reload. Similarly for things like conditional moves and tst insns. Clobbers get added to several patterns that were missing them. One of the interesting v8 tidbits is that it was already using the new style for its floating point comparisons & branches. We actually get to simplify that a bit because we no longer need special branching patterns (FP comparison initially are stored in FCC, then get copied into the Z bit of CC_REG, then we use standard bz/bnz insns). This commit should work independently of #3 as #3 strictly adds flags setting variants of arithmetic, logicals and other patterns. But I haven't tested that extensively. Jeff * config/v850/v850-protos.h (notice_update_cc): Remove. * config/v850/v850.c (v850_compare_op0, v850_compare_op1): Remove. (v850_print_operand): Handle 'D' and "d". (v850_select_cc_mode): Remove ATTRIBUTE_UNUSED for last argument. Add handling of arithmetic/logical operations compared against zero. (v850_gen_float_compare): Remove ATTRIBUTE_UNUSED for last argument. Do not look at v850_compare_op, instead get mode from last argument. (v850_gen_compare): Remove (increment_stack): Use addsi3_clobber_flags to avoid splitting failure after reload for prologue insns. (expand_prologue): Account for CLOBBER of CC_REGNUM in various patterns. (construct_save_jarl): Likewise. (TARGET_FLAGS_REGNUM): Define. * config/v850/v850.h (v850_compare_op0, v850_compare_op1): Remove. (NOTICE_UPDATE_CC): Remove. * config/v850/v850.md (v850_tst1): Use (reg:CCZ CC_REGNUM) rather than cc0. Conditionalize on reload_completed. (cmpsi_insn, setfcc_insn): Likewise. (tst1 splitter): Turn into define_and_split which sets the flags after reload. (cstoresi4, cbranchsf4, cbranchdf4, cbranchsi4_insn): Likewise. (cbranchsi4, branch_normal, branch_invert): Do not expose cc0 here. (cstoresf4, cstoredf4): Clobber the flags. (cmpsi, cmpsf, cmpdf): Remove expanders. (setf_insn): Remove pattern. (addsi3): Turn into define_and_split which clobbers the flags after reload and a suitable pattern (addsi3_clobber_flags) for use after reload. (subsi3, negsi2, andsi3, iorsi3, xorsi3, one_cmplsi2) Likewise. (ashlsi3, ashlsi3_v850e2, lshrsi3, lsh4si3_v850e2): Likewise. (ashrsi3, ashrsi3_v850e2): Likewise. (bins): Clobber the flags. (movsicc_normal_cc, movsicc_normal, movsicc_tst1): Likewise. (movsicc_tst1_revesed, sasf, swap and rotate patterns): Likewise. (fix_loop_counter, call_internal_short, call_internal_long): Likewise. (call_value_internal_short, call_value_internal_long): Likewise. (callt_save_interrupt, callt_return_interrupt): Likewise. (save_interrupt, return_interrupt): Likewise. (callt_save_all_interrupt, save_all_interrupt): Likewise. (_save_all_interrupt, callt_restore_all_interrupt): Likewise. (restore_all_interrupt, _restore_all_interrupt): Likewise. (All FP comparisons): Only allow after reload has completed. (trfsr): Likewise. (divh, divhu): Tweak output template. (branch_z_normal, branch_z_invert): Remove (branch_nz_normal, branch_nz_invert): Likewise. (extendhisi_insn, extendqisi_insn): Do not clobber flags. diff --git a/gcc/config/v850/v850-protos.h b/gcc/config/v850/v850-protos.h index e8ff280..ca99703 100644 --- a/gcc/config/v850/v850-protos.h +++ b/gcc/config/v850/v850-protos.h @@ -32,7 +32,6 @@ extern void v850_init_expanders (void); #ifdef RTX_CODE extern rtx v850_return_addr (int); extern const char *output_move_single (rtx *); -extern void notice_update_cc (rtx, rtx_insn *); extern char * construct_save_jarl (rtx); extern char * construct_restore_jr (rtx); #ifdef HAVE_MACHINE_MODES diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c index e184718..cb2debf 100644 --- a/gcc/config/v850/v850.c +++ b/gcc/config/v850/v850.c @@ -68,8 +68,6 @@ data_area_stack_element * data_area_stack = NULL; function is an interrupt handler. */ static int v850_interrupt_cache_p = FALSE; -rtx v850_compare_op0, v850_compare_op1; - /* Whether current function is an interrupt handler. */ static int v850_interrupt_p = FALSE; @@ -418,7 +416,9 @@ v850_print_operand (FILE * file, rtx x, int code) case 'b': case 'B': case 'C': - switch ((code == 'B' || code == 'C') + case 'd': + case 'D': + switch ((code == 'B' || code == 'C' || code == 'D') ? reverse_condition (GET_CODE (x)) : GET_CODE (x)) { case NE: @@ -434,7 +434,10 @@ v850_print_operand (FILE * file, rtx x, int code) fprintf (file, "e"); break; case GE: - fprintf (file, "ge"); + if (code == 'D' || code == 'd') + fprintf (file, "p"); + else + fprintf (file, "ge"); break; case GT: fprintf (file, "gt"); @@ -443,7 +446,10 @@ v850_print_operand (FILE * file, rtx x, int code) fprintf (file, "le"); break; case LT: - fprintf (file, "lt"); + if (code == 'D' || code == 'd') + fprintf (file, "n"); + else + fprintf (file, "lt"); break; case GEU: fprintf (file, "nl"); @@ -905,7 +911,7 @@ output_move_single (rtx * operands) } machine_mode -v850_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1 ATTRIBUTE_UNUSED) +v850_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1) { if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT) { @@ -927,11 +933,20 @@ v850_select_cc_mode (enum rtx_code cond, rtx op0, rtx op1 ATTRIBUTE_UNUSED) gcc_unreachable (); } } + + if (op1 == const0_rtx + && (cond == EQ || cond == NE || cond == LT || cond == GE) + && (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS + || GET_CODE (op0) == NEG || GET_CODE (op0) == AND + || GET_CODE (op0) == IOR || GET_CODE (op0) == XOR + || GET_CODE (op0) == NOT || GET_CODE (op0) == ASHIFT)) + return CCNZmode; + return CCmode; } machine_mode -v850_gen_float_compare (enum rtx_code cond, machine_mode mode ATTRIBUTE_UNUSED, rtx op0, rtx op1) +v850_gen_float_compare (enum rtx_code cond, machine_mode mode, rtx op0, rtx op1) { if (GET_MODE (op0) == DFmode) { @@ -960,7 +975,7 @@ v850_gen_float_compare (enum rtx_code cond, machine_mode mode ATTRIBUTE_UNUSED, gcc_unreachable (); } } - else if (GET_MODE (v850_compare_op0) == SFmode) + else if (mode == SFmode) { switch (cond) { @@ -993,25 +1008,6 @@ v850_gen_float_compare (enum rtx_code cond, machine_mode mode ATTRIBUTE_UNUSED, return v850_select_cc_mode (cond, op0, op1); } -rtx -v850_gen_compare (enum rtx_code cond, machine_mode mode, rtx op0, rtx op1) -{ - if (GET_MODE_CLASS(GET_MODE (op0)) != MODE_FLOAT) - { - emit_insn (gen_cmpsi_insn (op0, op1)); - return gen_rtx_fmt_ee (cond, mode, gen_rtx_REG(CCmode, CC_REGNUM), const0_rtx); - } - else - { - rtx cc_reg; - mode = v850_gen_float_compare (cond, mode, op0, op1); - cc_reg = gen_rtx_REG (mode, CC_REGNUM); - emit_insn (gen_rtx_SET (cc_reg, gen_rtx_REG (mode, FCC_REGNUM))); - - return gen_rtx_fmt_ee (cond, mode, cc_reg, const0_rtx); - } -} - /* Return maximum offset supported for a short EP memory reference of mode MODE and signedness UNSIGNEDP. */ @@ -1635,7 +1631,7 @@ increment_stack (signed int amount, bool in_prologue) inc = reg; } - inc = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, inc)); + inc = emit_insn (gen_addsi3_clobber_flags (stack_pointer_rtx, stack_pointer_rtx, inc)); if (in_prologue) F (inc); } @@ -1712,7 +1708,7 @@ expand_prologue (void) save_all = gen_rtx_PARALLEL (VOIDmode, - rtvec_alloc (num_save + 1 + rtvec_alloc (num_save + 2 + (TARGET_DISABLE_CALLT ? (TARGET_LONG_CALLS ? 2 : 1) : 0))); XVECEXP (save_all, 0, 0) @@ -1731,13 +1727,16 @@ expand_prologue (void) save_regs[i]); } + XVECEXP (save_all, 0, num_save + 1) + = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, CC_REGNUM)); + if (TARGET_DISABLE_CALLT) { - XVECEXP (save_all, 0, num_save + 1) + XVECEXP (save_all, 0, num_save + 2) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 10)); if (TARGET_LONG_CALLS) - XVECEXP (save_all, 0, num_save + 2) + XVECEXP (save_all, 0, num_save + 3) = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 11)); } @@ -2330,7 +2329,7 @@ construct_save_jarl (rtx op) stack_bytes = INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)); /* Each push will put 4 bytes from the stack.... */ - stack_bytes += (count - (TARGET_LONG_CALLS ? 3 : 2)) * 4; + stack_bytes += (count - (TARGET_LONG_CALLS ? 4 : 3)) * 4; /* Make sure that the amount we are popping either 0 or 16 bytes. */ if (stack_bytes != 0) @@ -2341,7 +2340,7 @@ construct_save_jarl (rtx op) /* Now compute the bit mask of registers to push. */ mask = 0; - for (i = 1; i < count - (TARGET_LONG_CALLS ? 2 : 1); i++) + for (i = 1; i < count - (TARGET_LONG_CALLS ? 3 : 2); i++) { rtx vector_element = XVECEXP (op, 0, i); @@ -3325,6 +3324,9 @@ v850_modes_tieable_p (machine_mode mode1, machine_mode mode2) #undef TARGET_MODES_TIEABLE_P #define TARGET_MODES_TIEABLE_P v850_modes_tieable_p +#undef TARGET_FLAGS_REGNUM +#define TARGET_FLAGS_REGNUM 32 + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-v850.h" diff --git a/gcc/config/v850/v850.h b/gcc/config/v850/v850.h index 96bddc2..04d226a 100644 --- a/gcc/config/v850/v850.h +++ b/gcc/config/v850/v850.h @@ -26,9 +26,6 @@ #ifndef GCC_V850_H #define GCC_V850_H -extern GTY(()) rtx v850_compare_op0; -extern GTY(()) rtx v850_compare_op1; - #undef LIB_SPEC #define LIB_SPEC "%{!shared:%{!symbolic:--start-group -lc -lgcc --end-group}}" @@ -567,8 +564,6 @@ struct cum_arg { int nbytes; }; #define SELECT_CC_MODE(OP, X, Y) v850_select_cc_mode (OP, X, Y) -#define NOTICE_UPDATE_CC(EXP, INSN) - /* Nonzero if access to memory by bytes or half words is no faster than accessing full words. */ #define SLOW_BYTE_ACCESS 1 diff --git a/gcc/config/v850/v850.md b/gcc/config/v850/v850.md index 0fad9ea..3cfec74 100644 --- a/gcc/config/v850/v850.md +++ b/gcc/config/v850/v850.md @@ -28,6 +28,42 @@ ;; ;; One day we'll probably need to handle calls to targets more than 4M ;; away. +;; + +;; Condition codes +;; +;; Data movement (load, store, register copy) does not modify condition +;; codes. But there is no way to add two registers together without +;; modifying the condition codes. +;; +;; So we do not expose the condition codes until after reload. The +;; general approach is to have a define_insn_and_split for the basic +;; operation with no condition codes in the pattern (to give the +;; optimizers maximal freedom). The splitter adds a clobber of the +;; condition codes after reload. There is a distinct pattern which +;; sets the condition codes. +;; +;; As noted, data movement does not affect condition codes. +;; +;; Arithmetic generally set the codes in the expected ways, with mul +;; instructions being a notable outlier. div instructions generally +;; do the right thing, except when the output registers are the same +;; when the flags do not get set. We just assume they're clobbered +;; for div instructions to avoid MD bloat with marginal benefit +;; +;; The bit manipulation instructions (clr1, not1, set1) set condition +;; codes, but not in a useful way (they're set to the prior status of +;; the bit). So we just model those as clobbers. tst1 does set the +;; condition codes in a useful way. We could perhaps do better with +;; these by noting they only modify the Z flag, it doesn't seem worth +;; the effort. +;; +;; Byte swaps seem to change the condition codes, but I haven't tried +;; to describe how. +;; +;; I have no documentation on the rotate instructions. They likely +;; set the condition codes, but I've left them as clobbers for now. + ;; The size of instructions in bytes. @@ -352,110 +388,90 @@ ;; ---------------------------------------------------------------------- (define_insn "*v850_tst1" - [(set (cc0) + [(set (reg:CCZ CC_REGNUM) (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "m") (const_int 1) (match_operand:QI 1 "const_int_operand" "n")) (const_int 0)))] - "" + "reload_completed" "tst1 %1,%0" [(set_attr "length" "4")]) ;; This replaces ld.b;sar;andi with tst1;setf nz. +;; Should there be variants for HI or SI modes? -(define_split +(define_insn_and_split "" [(set (match_operand:SI 0 "register_operand" "") (compare (zero_extract:SI (match_operand:QI 1 "memory_operand" "") (const_int 1) (match_operand 2 "const_int_operand" "")) (const_int 0)))] "" - [(set (cc0) (compare (zero_extract:SI (match_dup 1) - (const_int 1) - (match_dup 2)) - (const_int 0))) - (set (match_dup 0) (ne:SI (cc0) (const_int 0)))]) + "#" + "reload_completed" + [(set (reg:CCZ CC_REGNUM) (compare (zero_extract:SI (match_dup 1) + (const_int 1) + (match_dup 2)) + (const_int 0))) + (set (match_dup 0) (ne:SI (reg:CCZ CC_REGNUM) (const_int 0)))]) (define_expand "cbranchsi4" - [(set (cc0) - (compare (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "reg_or_int5_operand" ""))) - (set (pc) + [(set (pc) (if_then_else - (match_operator 0 "ordered_comparison_operator" [(cc0) - (const_int 0)]) + (match_operator 0 "comparison_operator" + [(match_operand:SI 1 "register_operand") + (match_operand:SI 2 "reg_or_int5_operand")]) (label_ref (match_operand 3 "" "")) (pc)))] "") -(define_expand "cstoresi4" - [(set (cc0) - (compare (match_operand:SI 2 "register_operand" "") - (match_operand:SI 3 "reg_or_int5_operand" ""))) - (set (match_operand:SI 0 "register_operand") - (match_operator:SI 1 "ordered_comparison_operator" [(cc0) - (const_int 0)]))] - "") - -(define_expand "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "register_operand" "r,r") - (match_operand:SI 1 "reg_or_int5_operand" "r,J")))] - "" - { - v850_compare_op0 = operands[0]; - v850_compare_op1 = operands[1]; - DONE; - }) - (define_insn "cmpsi_insn" - [(set (cc0) + [(set (reg:CC CC_REGNUM) (compare (match_operand:SI 0 "register_operand" "r,r") (match_operand:SI 1 "reg_or_int5_operand" "r,J")))] - "" - "@ - cmp %1,%0 - cmp %1,%0" + "reload_completed" + "cmp %1,%0" [(set_attr "length" "2,2")]) -(define_expand "cbranchsf4" +(define_insn_and_split "cbranchsf4" [(set (pc) (if_then_else (match_operator 0 "ordered_comparison_operator" - [(match_operand:SF 1 "register_operand") - (match_operand:SF 2 "register_operand")]) + [(match_operand:SF 1 "register_operand" "r") + (match_operand:SF 2 "register_operand" "r")]) (label_ref (match_operand 3 "")) - (pc))) - (clobber (cc0))] + (pc)))] "TARGET_USE_FPU" -{ - enum rtx_code cond = GET_CODE (operands[0]); - machine_mode mode; - rtx fcc_reg; - rtx cc_reg; - rtx tmp; - - v850_compare_op0 = operands[1]; - v850_compare_op1 = operands[2]; - - if (GET_MODE_CLASS (GET_MODE (v850_compare_op0)) != MODE_FLOAT) - FAIL; - - mode = v850_gen_float_compare (cond, VOIDmode, v850_compare_op0, v850_compare_op1); - fcc_reg = gen_rtx_REG (mode, FCC_REGNUM); - cc_reg = gen_rtx_REG (mode, CC_REGNUM); - emit_insn (gen_rtx_SET (cc_reg, fcc_reg)); - tmp = gen_rtx_fmt_ee (cond, mode, cc_reg, const0_rtx); - tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, - gen_rtx_LABEL_REF (VOIDmode, operands[3]), pc_rtx); - emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)); - DONE; -}) + "#" + "reload_completed" + [(set (match_dup 4) (match_dup 5)) + (set (pc) + (if_then_else (match_dup 6) + (label_ref (match_dup 3)) + (pc)))] + "{ + /* This will generate the comparison insn at the start of + the sequence and get us the right mode to use for our + condition code registers. */ + enum machine_mode mode + = v850_gen_float_compare (GET_CODE (operands[0]), + GET_MODE (operands[1]), + operands[1], operands[2]); + /* We want operands referring to CC_REGNUM and FCC_REGNUM + in mode MODE. */ + operands[4] = gen_rtx_REG (mode, CC_REGNUM); + operands[5] = gen_rtx_REG (mode, FCC_REGNUM); + if (mode == CC_FPU_NEmode) + operands[6] = gen_rtx_NE (mode, operands[4], const0_rtx); + else + operands[6] = gen_rtx_EQ (mode, operands[4], const0_rtx); +}") (define_insn "cstoresf4" [(set (match_operand:SI 0 "register_operand" "=r") (match_operator:SI 1 "ordered_comparison_operator" [(match_operand:SF 2 "register_operand" "r") - (match_operand:SF 3 "register_operand" "r")]))] + (match_operand:SF 3 "register_operand" "r")])) + (clobber (reg:CC CC_REGNUM))] "TARGET_USE_FPU" { if (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE) @@ -471,44 +487,47 @@ [(set_attr "length" "12") (set_attr "type" "fpu")]) -(define_expand "cbranchdf4" +(define_insn_and_split "cbranchdf4" [(set (pc) (if_then_else (match_operator 0 "ordered_comparison_operator" - [(match_operand:DF 1 "even_reg_operand") - (match_operand:DF 2 "even_reg_operand")]) + [(match_operand:DF 1 "even_reg_operand" "r") + (match_operand:DF 2 "even_reg_operand" "r")]) (label_ref (match_operand 3 "")) - (pc))) - (clobber (cc0))] + (pc)))] "TARGET_USE_FPU" -{ - enum rtx_code cond = GET_CODE (operands[0]); - machine_mode mode; - rtx fcc_reg; - rtx cc_reg; - rtx tmp; - - v850_compare_op0 = operands[1]; - v850_compare_op1 = operands[2]; - - if (GET_MODE_CLASS (GET_MODE (v850_compare_op0)) != MODE_FLOAT) - FAIL; - - mode = v850_gen_float_compare (cond, VOIDmode, v850_compare_op0, v850_compare_op1); - fcc_reg = gen_rtx_REG (mode, FCC_REGNUM); - cc_reg = gen_rtx_REG (mode, CC_REGNUM); - emit_insn (gen_rtx_SET (cc_reg, fcc_reg)); - tmp = gen_rtx_fmt_ee (cond, mode, cc_reg, const0_rtx); - tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp, - gen_rtx_LABEL_REF (VOIDmode, operands[3]), pc_rtx); - emit_jump_insn (gen_rtx_SET (pc_rtx, tmp)); - DONE; -}) + "#" + "reload_completed" +;; How to get the mode here? + [(set (match_dup 4) (match_dup 5)) + (set (pc) + (if_then_else (match_dup 6) + (label_ref (match_dup 3)) + (pc)))] + "{ + /* This will generate the comparison insn at the start of + the sequence and get us the right mode to use for our + condition code registers. */ + enum machine_mode mode + = v850_gen_float_compare (GET_CODE (operands[0]), + GET_MODE (operands[1]), + operands[1], operands[2]); + PUT_MODE (operands[0], mode); + /* We want operands referring to CC_REGNUM and FCC_REGNUM + in mode MODE. */ + operands[4] = gen_rtx_REG (mode, CC_REGNUM); + operands[5] = gen_rtx_REG (mode, FCC_REGNUM); + if (mode == CC_FPU_NEmode) + operands[6] = gen_rtx_NE (mode, operands[4], const0_rtx); + else + operands[6] = gen_rtx_EQ (mode, operands[4], const0_rtx); +}") (define_insn "cstoredf4" [(set (match_operand:SI 0 "register_operand" "=r") (match_operator:SI 1 "ordered_comparison_operator" [(match_operand:DF 2 "even_reg_operand" "r") - (match_operand:DF 3 "even_reg_operand" "r")]))] + (match_operand:DF 3 "even_reg_operand" "r")])) + (clobber (reg:CC CC_REGNUM))] "TARGET_USE_FPU" { if (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE) @@ -524,38 +543,25 @@ [(set_attr "length" "12") (set_attr "type" "fpu")]) -(define_expand "cmpsf" - [(set (reg:CC CC_REGNUM) - (compare (match_operand:SF 0 "register_operand" "r") - (match_operand:SF 1 "register_operand" "r")))] - "TARGET_USE_FPU" - { - v850_compare_op0 = operands[0]; - v850_compare_op1 = operands[1]; - DONE; - }) - -(define_expand "cmpdf" - [(set (reg:CC CC_REGNUM) - (compare (match_operand:DF 0 "even_reg_operand" "r") - (match_operand:DF 1 "even_reg_operand" "r")))] - "TARGET_USE_FPU" - { - v850_compare_op0 = operands[0]; - v850_compare_op1 = operands[1]; - DONE; - }) - ;; ---------------------------------------------------------------------- ;; ADD INSTRUCTIONS ;; ---------------------------------------------------------------------- -(define_insn "addsi3" +(define_insn_and_split "addsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (plus:SI (match_operand:SI 1 "register_operand" "%0,r,r") + (match_operand:SI 2 "nonmemory_operand" "rJ,K,U")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])]) + +(define_insn "addsi3_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (plus:SI (match_operand:SI 1 "register_operand" "%0,r,r") (match_operand:SI 2 "nonmemory_operand" "rJ,K,U"))) (clobber (reg:CC CC_REGNUM))] - "" "@ add %2,%0 @@ -566,8 +572,17 @@ ;; ---------------------------------------------------------------------- ;; SUBTRACT INSTRUCTIONS ;; ---------------------------------------------------------------------- +(define_insn_and_split "subsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (minus:SI (match_operand:SI 1 "register_operand" "0,r") + (match_operand:SI 2 "register_operand" "r,0")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])]) -(define_insn "subsi3" +(define_insn "subsi3_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r,r") (minus:SI (match_operand:SI 1 "register_operand" "0,r") (match_operand:SI 2 "register_operand" "r,0"))) @@ -578,7 +593,16 @@ subr %1,%0" [(set_attr "length" "2,2")]) -(define_insn "negsi2" +(define_insn_and_split "negsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (neg:SI (match_operand:SI 1 "register_operand" "0")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (neg:SI (match_dup 1))) + (clobber (reg:CC CC_REGNUM))])]) + +(define_insn "negsi2_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r") (neg:SI (match_operand:SI 1 "register_operand" "0"))) (clobber (reg:CC CC_REGNUM))] @@ -703,7 +727,7 @@ (match_dup 2))) (clobber (reg:CC CC_REGNUM))] "TARGET_V850E_UP" - "sxh %0\n\tdivh %2,%0,%3" + "sxh %0\\n\\tdivh %2,%0,%3" [(set_attr "length" "6") (set_attr "type" "div")]) @@ -719,7 +743,7 @@ (match_dup 2))) (clobber (reg:CC CC_REGNUM))] "TARGET_V850E_UP" - "zxh %0\n\tdivhu %2,%0,%3" + "zxh %0\\n\\ndivhu %2,%0,%3" [(set_attr "length" "6") (set_attr "type" "div")]) @@ -785,12 +809,22 @@ [(set_attr "length" "4") (set_attr "type" "bit1")]) -(define_insn "andsi3" +(define_insn_and_split "andsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (and:SI (match_operand:SI 1 "register_operand" "%0,0,r") + (match_operand:SI 2 "nonmemory_operand" "r,I,M")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])]) + +(define_insn "andsi3_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (and:SI (match_operand:SI 1 "register_operand" "%0,0,r") (match_operand:SI 2 "nonmemory_operand" "r,I,M"))) (clobber (reg:CC CC_REGNUM))] - "" + "reload_completed" "@ and %2,%0 and %.,%0 @@ -860,7 +894,17 @@ [(set_attr "length" "4") (set_attr "type" "bit1")]) -(define_insn "iorsi3" +(define_insn_and_split "iorsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (ior:SI (match_operand:SI 1 "register_operand" "%0,0,r") + (match_operand:SI 2 "nonmemory_operand" "r,I,M")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])]) + +(define_insn "iorsi3_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (ior:SI (match_operand:SI 1 "register_operand" "%0,0,r") (match_operand:SI 2 "nonmemory_operand" "r,I,M"))) @@ -935,7 +979,17 @@ [(set_attr "length" "4") (set_attr "type" "bit1")]) -(define_insn "xorsi3" +(define_insn_and_split "xorsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r,r") + (xor:SI (match_operand:SI 1 "register_operand" "%0,0,r") + (match_operand:SI 2 "nonmemory_operand" "r,I,M")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])]) + +(define_insn "xorsi3_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r,r,r") (xor:SI (match_operand:SI 1 "register_operand" "%0,0,r") (match_operand:SI 2 "nonmemory_operand" "r,I,M"))) @@ -946,12 +1000,23 @@ xor %.,%0 xori %2,%1,%0" [(set_attr "length" "2,2,4")]) + ;; ---------------------------------------------------------------------- ;; NOT INSTRUCTIONS ;; ---------------------------------------------------------------------- -(define_insn "one_cmplsi2" +(define_insn_and_split "one_cmplsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (not:SI (match_operand:SI 1 "register_operand" "r")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (not:SI (match_dup 1))) + (clobber (reg:CC CC_REGNUM))])]) + + +(define_insn "one_cmplsi2_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r") (not:SI (match_operand:SI 1 "register_operand" "r"))) (clobber (reg:CC CC_REGNUM))] @@ -977,7 +1042,8 @@ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r") (match_operand:SI 1 "immediate_operand" "n") (match_operand:SI 2 "immediate_operand" "n")) - (match_operand:SI 3 "register_operand" "r"))] + (match_operand:SI 3 "register_operand" "r")) + (clobber (reg:CC CC_REGNUM))] "TARGET_V850E3V5_UP" "bins %3, %2, %1, %0" [(set_attr "length" "4")]) @@ -986,20 +1052,46 @@ ;; Scc INSTRUCTIONS ;; ----------------------------------------------------------------- -(define_insn "*setcc" +(define_insn_and_split "*cbranchsi4_insn" + [(set (pc) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "reg_or_int5_operand" "rJ")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" + "#" + "reload_completed" + [(set (reg:CC CC_REGNUM) + (compare:CC (match_dup 1) (match_dup 2))) + (set (pc) + (if_then_else (match_op_dup 0 + [(reg:CC CC_REGNUM) (const_int 0)]) + (label_ref (match_dup 3)) + (pc)))] + "") + + +(define_insn_and_split "cstoresi4" [(set (match_operand:SI 0 "register_operand" "=r") (match_operator:SI 1 "comparison_operator" - [(cc0) (const_int 0)]))] + [(match_operand:SI 2 "register_operand" "r") + (match_operand:SI 3 "reg_or_int5_operand" "rJ")]))] "" - "setf %c1,%0" - [(set_attr "length" "4")]) + "#" + "reload_completed" + [(set (reg:CC CC_REGNUM) + (compare:CC (match_dup 2) (match_dup 3))) + (set (match_dup 0) (match_op_dup 1 + [(reg:CC CC_REGNUM) (const_int 0)]))] + "") -(define_insn "setf_insn" +(define_insn "*setcc_insn" [(set (match_operand:SI 0 "register_operand" "=r") - (match_operator:SI 1 "comparison_operator" - [(reg:CC CC_REGNUM) (const_int 0)]))] - "" - "setf %b1,%0" + (match_operator:SI 1 "comparison_operator" + [(reg:CC CC_REGNUM) (const_int 0)]))] + "reload_completed" + "setf %c1,%0" [(set_attr "length" "4")]) (define_insn "set_z_insn" @@ -1065,12 +1157,6 @@ } }) -;; ??? Clobbering the condition codes is overkill. - -;; ??? We sometimes emit an unnecessary compare instruction because the -;; condition codes may have already been set by an earlier instruction, -;; but we have no code here to avoid the compare if it is unnecessary. - (define_insn "movsicc_normal_cc" [(set (match_operand:SI 0 "register_operand" "=r") (if_then_else:SI @@ -1078,7 +1164,7 @@ [(reg:CC CC_REGNUM) (const_int 0)]) (match_operand:SI 2 "reg_or_int5_operand" "rJ") (match_operand:SI 3 "reg_or_0_operand" "rI")))] - "(TARGET_V850E_UP)" + "reload_completed && (TARGET_V850E_UP)" "cmov %c1,%2,%z3,%0"; [(set_attr "length" "6")]) @@ -1089,11 +1175,11 @@ [(reg:CC CC_REGNUM) (const_int 0)]) (match_operand:SI 2 "reg_or_0_operand" "rI") (match_operand:SI 3 "reg_or_int5_operand" "rJ")))] - "(TARGET_V850E_UP)" + "reload_completed && (TARGET_V850E_UP)" "cmov %C1,%3,%z2,%0" [(set_attr "length" "6")]) -(define_insn "*movsicc_normal" +(define_insn_and_split "*movsicc_normal" [(set (match_operand:SI 0 "register_operand" "=r") (if_then_else:SI (match_operator 1 "comparison_operator" @@ -1102,21 +1188,35 @@ (match_operand:SI 2 "reg_or_int5_operand" "rJ") (match_operand:SI 3 "reg_or_0_operand" "rI")))] "(TARGET_V850E_UP)" - "cmp %5,%4 ; cmov %c1,%2,%z3,%0" - [(set_attr "length" "6")]) + "#" + "reload_completed" + [(set (reg:CC CC_REGNUM) + (compare:CC (match_dup 4) (match_dup 5))) + (set (match_dup 0) + (if_then_else:SI (match_op_dup 1 + [(reg:CC CC_REGNUM) (const_int 0)]) + (match_dup 2) (match_dup 3)))]) -(define_insn "*movsicc_reversed" + +(define_insn_and_split "*movsicc_reversed" [(set (match_operand:SI 0 "register_operand" "=r") (if_then_else:SI (match_operator 1 "comparison_operator" [(match_operand:SI 4 "register_operand" "r") (match_operand:SI 5 "reg_or_int5_operand" "rJ")]) - (match_operand:SI 2 "reg_or_0_operand" "rI") - (match_operand:SI 3 "reg_or_int5_operand" "rJ")))] + (match_operand:SI 2 "reg_or_int5_operand" "rI") + (match_operand:SI 3 "reg_or_0_operand" "rJ")))] "(TARGET_V850E_UP)" - "cmp %5,%4 ; cmov %C1,%3,%z2,%0" - [(set_attr "length" "6")]) + "#" + "reload_completed" + [(set (reg:CC CC_REGNUM) + (compare:CC (match_dup 4) (match_dup 5))) + (set (match_dup 0) + (if_then_else:SI (match_op_dup 1 + [(reg:CC CC_REGNUM) (const_int 0)]) + (match_dup 2) (match_dup 3)))]) +;; We could expose the setting of the condition codes here. (define_insn "*movsicc_tst1" [(set (match_operand:SI 0 "register_operand" "=r") (if_then_else:SI @@ -1127,11 +1227,13 @@ (match_operand 3 "const_int_operand" "n")) (const_int 0)]) (match_operand:SI 4 "reg_or_int5_operand" "rJ") - (match_operand:SI 5 "reg_or_0_operand" "rI")))] + (match_operand:SI 5 "reg_or_0_operand" "rI"))) + (clobber (reg:CC CC_REGNUM))] "(TARGET_V850E_UP)" "tst1 %3,%2 ; cmov %c1,%4,%z5,%0" [(set_attr "length" "8")]) +;; We could expose the setting of the condition codes here. (define_insn "*movsicc_tst1_reversed" [(set (match_operand:SI 0 "register_operand" "=r") (if_then_else:SI @@ -1142,7 +1244,8 @@ (match_operand 3 "const_int_operand" "n")) (const_int 0)]) (match_operand:SI 4 "reg_or_0_operand" "rI") - (match_operand:SI 5 "reg_or_int5_operand" "rJ")))] + (match_operand:SI 5 "reg_or_int5_operand" "rJ"))) + (clobber (reg:CC CC_REGNUM))] "(TARGET_V850E_UP)" "tst1 %3,%2 ; cmov %C1,%5,%z4,%0" [(set_attr "length" "8")]) @@ -1152,6 +1255,9 @@ ;; second pattern by subsequent combining. As above, we must include the ;; comparison to avoid input reloads in an insn using cc0. +;; We could expose the setting of the condition codes here. +;; However, I haven't seen this pattern used, so I'm not going +;; to bother. (define_insn "*sasf" [(set (match_operand:SI 0 "register_operand" "=r") (ior:SI @@ -1235,7 +1341,8 @@ [(ashift:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "const_int_operand" "n")) (lshiftrt:SI (match_dup 1) - (match_operand:SI 3 "const_int_operand" "n"))]))] + (match_operand:SI 3 "const_int_operand" "n"))])) + (clobber (reg:CC CC_REGNUM))] "TARGET_V850E3V5_UP && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32)" "rotl %2, %1, %0" [(set_attr "length" "4")]) @@ -1246,7 +1353,8 @@ [(lshiftrt:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 3 "const_int_operand" "n")) (ashift:SI (match_dup 1) - (match_operand:SI 2 "const_int_operand" "n"))]))] + (match_operand:SI 2 "const_int_operand" "n"))])) + (clobber (reg:CC CC_REGNUM))] "TARGET_V850E3V5_UP && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32)" "rotl %2, %1, %0" [(set_attr "length" "4")]) @@ -1287,9 +1395,11 @@ } ) +;; Note the embedded arithmetic. That affects the condition codes! (define_insn "fix_loop_counter" [(unspec:SI [(match_operand:SI 0 "register_operand" "+r,!m") - (clobber (match_scratch:SI 1 "=X,r"))] UNSPEC_LOOP)] + (clobber (match_scratch:SI 1 "=X,r"))] UNSPEC_LOOP) + (clobber (reg:CC CC_REGNUM))] "TARGET_V850E3V5_UP && TARGET_LOOP" { switch (which_alternative) @@ -1349,68 +1459,52 @@ ;; Conditional jump instructions -(define_insn "*branch_normal" +(define_insn_and_split "*cbranchsi4_insn" [(set (pc) - (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 0 "" "")) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "reg_or_int5_operand" "rJ")]) + (label_ref (match_operand 3 "" "")) (pc)))] "" -{ - if (get_attr_length (insn) == 2) - return "b%b1 %l0"; - if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4) - return "b%b1 %l0"; - return "b%B1 .+6 ; jr %l0"; -} - [(set (attr "length") - (if_then_else (lt (abs (minus (match_dup 0) (pc))) - (const_int 256)) - (const_int 2) - (if_then_else (lt (abs (minus (match_dup 0) (pc))) - (const_int 65536)) - (const_int 4) - (const_int 6))))]) + "#" + "reload_completed" + [(set (reg:CC CC_REGNUM) + (compare:CC (match_dup 1) (match_dup 2))) + (set (pc) + (if_then_else (match_op_dup 0 + [(reg:CC CC_REGNUM) (const_int 0)]) + (label_ref (match_dup 3)) + (pc)))] + "") -(define_insn "*branch_invert" +(define_insn "*branch_normal" [(set (pc) (if_then_else (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" -{ - if (get_attr_length (insn) == 2) - return "b%B1 %l0"; - - if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4) - return "b%B1 %l0"; - - return "b%b1 .+6 ; jr %l0"; -} - [(set (attr "length") - (if_then_else (lt (abs (minus (match_dup 0) (pc))) - (const_int 256)) - (const_int 2) - (if_then_else (lt (abs (minus (match_dup 0) (pc))) - (const_int 65536)) - (const_int 4) - (const_int 6))))]) - -(define_insn "branch_z_normal" - [(set (pc) - (if_then_else (match_operand 1 "v850_float_z_comparison_operator" "") + [(reg CC_REGNUM) (const_int 0)]) (label_ref (match_operand 0 "" "")) (pc)))] - "TARGET_V850E2V3_UP" + "reload_completed" { + bool nzmode = GET_MODE (XEXP (operands[1], 0)) == CCNZmode; if (get_attr_length (insn) == 2) - return "bz %l0"; - + { + if (nzmode) + return "b%d1 %l0"; + else + return "b%b1 %l0"; + } if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4) - return "bz %l0"; - - return "bnz 1f ; jr %l0 ; 1:"; + { + if (nzmode) + return "b%d1 %l0"; + else + return "b%b1 %l0"; + } + if (nzmode) + return "b%D1 .+6 ; jr %l0"; + else + return "b%B1 .+6 ; jr %l0"; } [(set (attr "length") (if_then_else (lt (abs (minus (match_dup 0) (pc))) @@ -1421,68 +1515,36 @@ (const_int 4) (const_int 6))))]) -(define_insn "*branch_z_invert" +(define_insn "*branch_invert" [(set (pc) - (if_then_else (match_operand 1 "v850_float_z_comparison_operator" "") + (if_then_else (match_operator 1 "comparison_operator" + [(reg CC_REGNUM) (const_int 0)]) (pc) (label_ref (match_operand 0 "" ""))))] - "TARGET_V850E2V3_UP" + "reload_completed" { - if (get_attr_length (insn) == 2) - return "bnz %l0"; - - if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4) - return "bnz %l0"; - - return "bz 1f ; jr %l0 ; 1:"; -} - [(set (attr "length") - (if_then_else (lt (abs (minus (match_dup 0) (pc))) - (const_int 256)) - (const_int 2) - (if_then_else (lt (abs (minus (match_dup 0) (pc))) - (const_int 65536)) - (const_int 4) - (const_int 6))))]) + bool nzmode = GET_MODE (XEXP (operands[1], 0)) == CCNZmode; -(define_insn "branch_nz_normal" - [(set (pc) - (if_then_else (match_operand 1 "v850_float_nz_comparison_operator" "") - (label_ref (match_operand 0 "" "")) - (pc)))] - "TARGET_V850E2V3_UP" -{ if (get_attr_length (insn) == 2) - return "bnz %l0"; - - if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4) - return "bnz %l0"; - - return "bz 1f ; jr %l0 ; 1:"; -} -[(set (attr "length") - (if_then_else (lt (abs (minus (match_dup 0) (pc))) - (const_int 256)) - (const_int 2) - (if_then_else (lt (abs (minus (match_dup 0) (pc))) - (const_int 65536)) - (const_int 4) - (const_int 6))))]) - -(define_insn "*branch_nz_invert" - [(set (pc) - (if_then_else (match_operand 1 "v850_float_nz_comparison_operator" "") - (pc) - (label_ref (match_operand 0 "" ""))))] - "TARGET_V850E2V3_UP" -{ - if (get_attr_length (insn) == 2) - return "bz %l0"; + { + if (nzmode) + return "b%D1 %l0"; + else + return "b%B1 %l0"; + } if (TARGET_V850E3V5_UP && get_attr_length (insn) == 4) - return "bz %l0"; + { + if (nzmode) + return "b%D1 %l0"; + else + return "b%B1 %l0"; + } - return "bnz 1f ; jr %l0 ; 1:"; + if (nzmode) + return "b%d1 .+6 ; jr %l0"; + else + return "b%b1 .+6 ; jr %l0"; } [(set (attr "length") (if_then_else (lt (abs (minus (match_dup 0) (pc))) @@ -1602,6 +1664,7 @@ (define_insn "call_internal_short" [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r")) (match_operand:SI 1 "general_operand" "g,g")) + (clobber (reg:CC CC_REGNUM)) (clobber (reg:SI 31))] "! TARGET_LONG_CALLS" { @@ -1620,6 +1683,7 @@ (define_insn "call_internal_long" [(call (mem:QI (match_operand:SI 0 "call_address_operand" "S,r")) (match_operand:SI 1 "general_operand" "g,g")) + (clobber (reg:CC CC_REGNUM)) (clobber (reg:SI 31))] "TARGET_LONG_CALLS" { @@ -1668,6 +1732,7 @@ [(set (match_operand 0 "" "=r,r") (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r")) (match_operand:SI 2 "general_operand" "g,g"))) + (clobber (reg:CC CC_REGNUM)) (clobber (reg:SI 31))] "! TARGET_LONG_CALLS" { @@ -1687,6 +1752,7 @@ [(set (match_operand 0 "" "=r,r") (call (mem:QI (match_operand:SI 1 "call_address_operand" "S,r")) (match_operand:SI 2 "general_operand" "g,g"))) + (clobber (reg:CC CC_REGNUM)) (clobber (reg:SI 31))] "TARGET_LONG_CALLS" { @@ -1719,6 +1785,7 @@ ;; EXTEND INSTRUCTIONS ;; ---------------------------------------------------------------------- +;; We only need the CC clobber because of the andi alternative (define_insn "*zero_extendhisi2_v850e" [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") (zero_extend:SI @@ -1791,8 +1858,7 @@ (define_insn "*extendhisi_insn" [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,Q,m"))) - (clobber (reg:CC CC_REGNUM))] + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,Q,m")))] "(TARGET_V850E_UP)" "@ sxh %0 @@ -1822,8 +1888,7 @@ (define_insn "*extendqisi_insn" [(set (match_operand:SI 0 "register_operand" "=r,r,r") - (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,Q,m"))) - (clobber (reg:CC CC_REGNUM))] + (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,Q,m")))] "(TARGET_V850E_UP)" "@ sxb %0 @@ -1853,7 +1918,18 @@ ;; SHIFTS ;; ---------------------------------------------------------------------- -(define_insn "ashlsi3" +(define_insn_and_split "ashlsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (ashift:SI + (match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "r,N")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])]) + +(define_insn "ashlsi3_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r,r") (ashift:SI (match_operand:SI 1 "register_operand" "0,0") @@ -1865,7 +1941,7 @@ shl %2,%0" [(set_attr "length" "4,2")]) -(define_insn "ashlsi3_v850e2" +(define_insn "ashlsi3_v850e2_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r") (ashift:SI (match_operand:SI 1 "register_operand" "r") @@ -1875,7 +1951,18 @@ "shl %2,%1,%0" [(set_attr "length" "4")]) -(define_insn "lshrsi3" +(define_insn_and_split "lshrsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (lshiftrt:SI + (match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "r,N")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (lshiftrt:SI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])]) + +(define_insn "lshrsi3_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r,r") (lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0") @@ -1887,7 +1974,7 @@ shr %2,%0" [(set_attr "length" "4,2")]) -(define_insn "lshrsi3_v850e2" +(define_insn "lshrsi3_v850e2_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r") (lshiftrt:SI (match_operand:SI 1 "register_operand" "r") @@ -1897,7 +1984,18 @@ "shr %2,%1,%0" [(set_attr "length" "4")]) -(define_insn "ashrsi3" +(define_insn_and_split "ashrsi3" + [(set (match_operand:SI 0 "register_operand" "=r,r") + (ashiftrt:SI + (match_operand:SI 1 "register_operand" "0,0") + (match_operand:SI 2 "nonmemory_operand" "r,N")))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (match_dup 2))) + (clobber (reg:CC CC_REGNUM))])]) + +(define_insn "ashrsi3_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r,r") (ashiftrt:SI (match_operand:SI 1 "register_operand" "0,0") @@ -1909,7 +2007,7 @@ sar %2,%0" [(set_attr "length" "4,2")]) -(define_insn "ashrsi3_v850e2" +(define_insn "ashrsi3_v850e2_clobber_flags" [(set (match_operand:SI 0 "register_operand" "=r") (ashiftrt:SI (match_operand:SI 1 "register_operand" "r") @@ -2279,6 +2377,8 @@ ;; ---------------- special insns ;; +;; reciprocal + ;; Generic code demands that the recip and rsqrt named patterns ;; have precisely one operand. So that's what we expose in the ;; expander via the strange UNSPEC. However, those expanders @@ -2417,7 +2517,7 @@ [(set (reg:CC_FPU_LE FCC_REGNUM) (compare:CC_FPU_LE (match_operand:SF 0 "register_operand" "r") (match_operand:SF 1 "register_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.s le, %z0, %z1" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2426,7 +2526,7 @@ [(set (reg:CC_FPU_LT FCC_REGNUM) (compare:CC_FPU_LT (match_operand:SF 0 "register_operand" "r") (match_operand:SF 1 "register_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.s lt, %z0, %z1" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2435,7 +2535,7 @@ [(set (reg:CC_FPU_GE FCC_REGNUM) (compare:CC_FPU_GE (match_operand:SF 0 "register_operand" "r") (match_operand:SF 1 "register_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.s le, %z1, %z0" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2444,7 +2544,7 @@ [(set (reg:CC_FPU_GT FCC_REGNUM) (compare:CC_FPU_GT (match_operand:SF 0 "register_operand" "r") (match_operand:SF 1 "register_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.s lt, %z1, %z0" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2453,7 +2553,7 @@ [(set (reg:CC_FPU_EQ FCC_REGNUM) (compare:CC_FPU_EQ (match_operand:SF 0 "register_operand" "r") (match_operand:SF 1 "register_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.s eq, %z0, %z1" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2464,7 +2564,7 @@ [(set (reg:CC_FPU_LE FCC_REGNUM) (compare:CC_FPU_LE (match_operand:DF 0 "even_reg_operand" "r") (match_operand:DF 1 "even_reg_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.d le, %z0, %z1" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2473,7 +2573,7 @@ [(set (reg:CC_FPU_LT FCC_REGNUM) (compare:CC_FPU_LT (match_operand:DF 0 "even_reg_operand" "r") (match_operand:DF 1 "even_reg_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.d lt, %z0, %z1" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2482,7 +2582,7 @@ [(set (reg:CC_FPU_GE FCC_REGNUM) (compare:CC_FPU_GE (match_operand:DF 0 "even_reg_operand" "r") (match_operand:DF 1 "even_reg_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.d le, %z1, %z0" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2491,7 +2591,7 @@ [(set (reg:CC_FPU_GT FCC_REGNUM) (compare:CC_FPU_GT (match_operand:DF 0 "even_reg_operand" "r") (match_operand:DF 1 "even_reg_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.d lt, %z1, %z0" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2500,7 +2600,7 @@ [(set (reg:CC_FPU_EQ FCC_REGNUM) (compare:CC_FPU_EQ (match_operand:DF 0 "even_reg_operand" "r") (match_operand:DF 1 "even_reg_operand" "r")))] - "TARGET_USE_FPU" + "reload_completed && TARGET_USE_FPU" "cmpf.d eq, %z0, %z1" [(set_attr "length" "4") (set_attr "type" "fpu")]) @@ -2512,7 +2612,8 @@ (define_insn "trfsr" [(set (match_operand 0 "" "") (match_operand 1 "" ""))] - "TARGET_USE_FPU + "reload_completed + && TARGET_USE_FPU && GET_MODE(operands[0]) == GET_MODE(operands[1]) && GET_CODE(operands[0]) == REG && REGNO (operands[0]) == CC_REGNUM && GET_CODE(operands[1]) == REG && REGNO (operands[1]) == FCC_REGNUM @@ -2668,7 +2769,8 @@ ;; Initialize an interrupt function. Do not depend on TARGET_PROLOG_FUNCTION. (define_insn "callt_save_interrupt" - [(unspec_volatile [(const_int 0)] 2)] + [(unspec_volatile [(const_int 0)] 2) + (clobber (reg:CC CC_REGNUM))] "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT" ;; The CALLT instruction stores the next address of CALLT to CTPC register ;; without saving its previous value. So if the interrupt handler @@ -2689,7 +2791,8 @@ [(set_attr "length" "26")]) (define_insn "callt_return_interrupt" - [(unspec_volatile [(const_int 0)] 3)] + [(unspec_volatile [(const_int 0)] 3) + (clobber (reg:CC CC_REGNUM))] "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT" "callt ctoff(__callt_return_interrupt)" [(set_attr "length" "2")]) @@ -2700,7 +2803,8 @@ (set (mem:SI (plus:SI (reg:SI 3) (const_int -16))) (reg:SI 4)) (set (mem:SI (plus:SI (reg:SI 3) (const_int -12))) (reg:SI 1)) (set (mem:SI (plus:SI (reg:SI 3) (const_int -8))) (reg:SI 10)) - (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 11))] + (set (mem:SI (plus:SI (reg:SI 3) (const_int -4))) (reg:SI 11)) + (clobber (reg:CC CC_REGNUM))] "" { if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) @@ -2733,7 +2837,8 @@ (set (reg:SI 10) (mem:SI (plus:SI (reg:SI 3) (const_int 12)))) (set (reg:SI 1) (mem:SI (plus:SI (reg:SI 3) (const_int 8)))) (set (reg:SI 4) (mem:SI (plus:SI (reg:SI 3) (const_int 4)))) - (set (reg:SI 30) (mem:SI (reg:SI 3)))] + (set (reg:SI 30) (mem:SI (reg:SI 3))) + (clobber (reg:CC CC_REGNUM))] "" { if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) @@ -2763,13 +2868,15 @@ ;; insns this complicated. (define_insn "callt_save_all_interrupt" - [(unspec_volatile [(const_int 0)] 0)] + [(unspec_volatile [(const_int 0)] 0) + (clobber (reg:CC CC_REGNUM))] "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT" "callt ctoff(__callt_save_all_interrupt)" [(set_attr "length" "2")]) (define_insn "save_all_interrupt" - [(unspec_volatile [(const_int 0)] 0)] + [(unspec_volatile [(const_int 0)] 0) + (clobber (reg:CC CC_REGNUM))] "" { if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) @@ -2844,10 +2951,12 @@ [(set (attr "length") (if_then_else (match_test "TARGET_LONG_CALLS") (const_int 4) - (const_int 62)))]) + (const_int 62) + ))]) (define_insn "_save_all_interrupt" - [(unspec_volatile [(const_int 0)] 0)] + [(unspec_volatile [(const_int 0)] 0) + (clobber (reg:CC CC_REGNUM))] "TARGET_V850 && ! TARGET_LONG_CALLS" "jarl __save_all_interrupt,r10" [(set_attr "length" "4")]) @@ -2859,13 +2968,15 @@ ;; insns this complicated. (define_insn "callt_restore_all_interrupt" - [(unspec_volatile [(const_int 0)] 1)] + [(unspec_volatile [(const_int 0)] 1) + (clobber (reg:CC CC_REGNUM))] "(TARGET_V850E_UP) && !TARGET_DISABLE_CALLT" "callt ctoff(__callt_restore_all_interrupt)" [(set_attr "length" "2")]) (define_insn "restore_all_interrupt" - [(unspec_volatile [(const_int 0)] 1)] + [(unspec_volatile [(const_int 0)] 1) + (clobber (reg:CC CC_REGNUM))] "" { if (TARGET_PROLOG_FUNCTION && !TARGET_LONG_CALLS) @@ -2942,7 +3053,8 @@ ))]) (define_insn "_restore_all_interrupt" - [(unspec_volatile [(const_int 0)] 1)] + [(unspec_volatile [(const_int 0)] 1) + (clobber (reg:CC CC_REGNUM))] "TARGET_V850 && ! TARGET_LONG_CALLS" "jarl __restore_all_interrupt,r10" [(set_attr "length" "4")])