From patchwork Tue Apr 10 00:31:15 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oleg Endo X-Patchwork-Id: 151502 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 1562CB6FFF for ; Tue, 10 Apr 2012 10:32:02 +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=1334622723; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Subject:From:To:Content-Type:Date:Message-ID:Mime-Version: Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:Sender:Delivered-To; bh=jbEPpKxud4P6e0cvekO8 +v1gGE4=; b=gCcxQz13NcSPnVFMRRp6imzGYdsCtl/+eDlAaEmZCh7ZMJmsk0Gc MWA8vI2nqLeViiSaBKPW0W/YsMxz9lX19dSmkUsNNRSPwCljp9f0sxWedYlH7Gb2 ale3lc6I0YltvyKBeSGfSEjx88AsRWuYQmQnXNUxa0DO+8ITRv0l3/4= 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:Received:Received:Subject:From:To:Content-Type:Date:Message-ID:Mime-Version:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=w3aQU27gdlclTrTXKLD0Uh+8XD3vki7+ji3CwJ6O55VWGApKT8DphWN1EoZWpo RJZwR2lPId6X753pdCRRdwKMPb74MW/b4DdS9qCAXAYBJVdaNP3OnBR6t8JEtgJ+ 03Q/xtehTpx//kTihi3/kjsIWYCkyXW/a/QkzN0aETUCk=; Received: (qmail 23561 invoked by alias); 10 Apr 2012 00:31:59 -0000 Received: (qmail 23535 invoked by uid 22791); 10 Apr 2012 00:31:55 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_NONE, RCVD_IN_HOSTKARMA_NO, TW_OV, TW_VH, TW_VQ, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY X-Spam-Check-By: sourceware.org Received: from mailout01.t-online.de (HELO mailout01.t-online.de) (194.25.134.80) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 10 Apr 2012 00:31:39 +0000 Received: from fwd09.aul.t-online.de (fwd09.aul.t-online.de ) by mailout01.t-online.de with smtp id 1SHOzg-0000jB-5h; Tue, 10 Apr 2012 02:31:36 +0200 Received: from [192.168.0.104] (rxEr9GZvYhEst7MQo6NyLiJJM6+ked26v6EcAFxV9TLr+xpiTXsLTHjXQ0sPv8twf4@[87.157.48.8]) by fwd09.t-online.de with esmtp id 1SHOzf-1APdVg0; Tue, 10 Apr 2012 02:31:35 +0200 Subject: [SH] PR 50751 - add HImode displacement addressing support From: Oleg Endo To: gcc-patches Date: Tue, 10 Apr 2012 02:31:15 +0200 Message-ID: <1334017875.19154.144.camel@yam-132-YW-E178-FTW> Mime-Version: 1.0 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 Hello, The attached patch adds HImode addressing support. Tested against rev. 186243 with sudo make -k check RUNTESTFLAGS="--target_board=sh-sim \{-m2/-ml,-m2/-mb,-m2a/-mb,-m2a-single/-mb,-m4/-ml,-m4/-mb, -m4-single/-ml,-m4-single/-mb,-m4a-single/-ml,-m4a-single/-mb}" and no new failures. Test cases will follow soon. Cheers, Oleg ChangeLog: PR target/50751 * config/sh/sh-protos.h (sh_legitimate_index_p): Add new arguments consider_sh2a and allow_zero. * config/sh/sh.c (sh_legitimate_index_p): Likewise. (disp_addr_displacement): New function. (sh_address_cost): Use disp_addr_displacement function instead of DISP_ADDR_OFFSET. (sh_legitimate_address_p): Adapt to changed sh_legitimate_index_p declaration. (sh_find_mov_disp_adjust): Remove HImode check. (sh_secondary_reload): Add HImode case. Use satisfies_constraint_Sdd, disp_addr_displacement and max_mov_insn_displacement. (max_mov_insn_displacement): Remove HImode check. * config/sh/sh.h (CONST_OK_FOR_K04, CONST_OK_FOR_K12, DISP_ADDR_P, DISP_ADDR_OFFSET): Remove. * config/sh/constraints.md (K05, K13): New constraints. (K12): Correct comment. (Sdd): Do not use DISP_ADDR_P macro. (Snd): Use satisfies_constraint_Sdd. (Sbw): Likewise. * config/sh/sh.md (extendhisi2): Remove constraints from expander. (*extendhisi2_compact, movhi_i): Remove. (*extendhisi2_compact_reg, *extendhisi2_compact_mem_disp, *extendhisi2_compact_mem_disp, *extendhisi2_compact_snd, *movhi_reg_reg, *movhi_store_mem_disp05, *movhi_store_mem_disp13, *movhi_load_mem_disp, *movhi_load_mem_disp, *movhi): New insns. (*extendqisi2_compact_mem_disp, *extendqisi2_compact_mem_disp, *movqi_store_mem_disp04, *movqi_store_mem_disp12, *movqi_load_mem_disp, *movqi_load_mem_disp): Use sh_legitimate_index_p instead of CONST_OK_FOR_Kxx. Add new peepholes for HImode displacement addressing. Index: gcc/config/sh/predicates.md =================================================================== --- gcc/config/sh/predicates.md (revision 186233) +++ gcc/config/sh/predicates.md (working copy) @@ -404,7 +404,7 @@ if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))) - return sh_legitimate_index_p (mode, XEXP (x, 1)); + return sh_legitimate_index_p (mode, XEXP (x, 1), TARGET_SH2A, false); } if (TARGET_SHMEDIA @@ -466,7 +466,7 @@ if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))) - return sh_legitimate_index_p (mode, XEXP (x, 1)); + return sh_legitimate_index_p (mode, XEXP (x, 1), TARGET_SH2A, false); } return general_operand (op, mode); Index: gcc/config/sh/sh-protos.h =================================================================== --- gcc/config/sh/sh-protos.h (revision 186233) +++ gcc/config/sh/sh-protos.h (working copy) @@ -56,7 +56,7 @@ extern bool fp_zero_operand (rtx); extern bool fp_one_operand (rtx); extern rtx get_fpscr_rtx (void); -extern bool sh_legitimate_index_p (enum machine_mode, rtx); +extern bool sh_legitimate_index_p (enum machine_mode, rtx, bool, bool); extern bool sh_legitimize_reload_address (rtx *, enum machine_mode, int, int); extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx); extern bool nonpic_symbol_mentioned_p (rtx); Index: gcc/config/sh/sh.c =================================================================== --- gcc/config/sh/sh.c (revision 186233) +++ gcc/config/sh/sh.c (working copy) @@ -304,6 +304,7 @@ static int mov_insn_size (enum machine_mode, bool); static int max_mov_insn_displacement (enum machine_mode, bool); static int mov_insn_alignment_mask (enum machine_mode, bool); +static HOST_WIDE_INT disp_addr_displacement (rtx); static void sh_init_sync_libfuncs (void) ATTRIBUTE_UNUSED; @@ -3160,11 +3161,6 @@ scale the max. displacement value accordingly. */ const int disp_scale = consider_sh2a ? (4095 / 15) : 1; - /* FIXME: HImode with displacement addressing is not supported yet. - Make it purposefully fail for now. */ - if (mode == HImode) - return 0; - /* SH2A supports FPU move insns with 12 bit displacements. Other variants to do not support any kind of displacements for FPU move insns. */ @@ -3194,15 +3190,24 @@ return mov_insn_sz > 0 ? (mov_insn_sz - 1) : 0; } +/* Return the displacement value of a displacement address. */ + +static inline HOST_WIDE_INT +disp_addr_displacement (rtx x) +{ + gcc_assert (satisfies_constraint_Sdd (x)); + return INTVAL (XEXP (XEXP (x, 0), 1)); +} + /* Compute the cost of an address. */ static int sh_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED) { /* 'reg + disp' addressing. */ - if (DISP_ADDR_P (x)) + if (satisfies_constraint_Sdd (x)) { - const HOST_WIDE_INT offset = DISP_ADDR_OFFSET (x); + const HOST_WIDE_INT offset = disp_addr_displacement (x); const enum machine_mode mode = GET_MODE (x); /* The displacement would fit into a 2 byte move insn. */ @@ -9665,7 +9670,8 @@ with MODE. */ bool -sh_legitimate_index_p (enum machine_mode mode, rtx op) +sh_legitimate_index_p (enum machine_mode mode, rtx op, bool consider_sh2a, + bool allow_zero) { if (! CONST_INT_P (op)) return false; @@ -9686,15 +9692,15 @@ else { const HOST_WIDE_INT offset = INTVAL (op); - const int max_disp = max_mov_insn_displacement (mode, TARGET_SH2A); - const int align_mask = mov_insn_alignment_mask (mode, TARGET_SH2A); + const int max_disp = max_mov_insn_displacement (mode, consider_sh2a); + const int align_mask = mov_insn_alignment_mask (mode, consider_sh2a); /* If the mode does not support any displacement always return false. Even though an index of '0' is actually always valid, it will cause troubles when e.g. a DFmode move is split into two SFmode moves, where one SFmode move will have index '0' and the other move will have index '4'. */ - if (max_disp < 1) + if (!allow_zero && max_disp < 1) return false; return offset >= 0 && offset <= max_disp && (offset & align_mask) == 0; @@ -9728,7 +9734,7 @@ if (GET_MODE_SIZE (mode) <= 8 && MAYBE_BASE_REGISTER_RTX_P (xop0, strict) - && sh_legitimate_index_p (mode, xop1)) + && sh_legitimate_index_p (mode, xop1, TARGET_SH2A, false)) return true; if ((ALLOW_INDEXED_ADDRESS || GET_MODE (x) == DImode @@ -9875,11 +9881,6 @@ if (mode_sz < 1 || mode_sz > 8 || max_disp < 1) return res; - /* FIXME: HImode with displacement addressing is not supported yet. - Make it purposefully fail for now. */ - if (mov_insn_sz == 2) - return res; - /* Keeps the previous behavior for QImode displacement addressing. This just decides how the offset is re-based. Removing this special case will result in slightly bigger code on average, but it's not that @@ -12566,12 +12567,14 @@ if (rclass == FPUL_REGS && true_regnum (x) == -1) return GENERAL_REGS; - /* Force mov.b displacement addressing insn to use R0 as the other operand. + /* Force mov.b / mov.w displacement addressing insn to use R0 as + the other operand. On SH2A could also just leave it alone here, which would result in a 4 byte move insn being generated instead. However, for this to work the insns must have the appropriate alternatives. */ - if (mode == QImode && rclass != R0_REGS - && DISP_ADDR_P (x) && DISP_ADDR_OFFSET (x) < 16) + if ((mode == QImode || mode == HImode) && rclass != R0_REGS + && satisfies_constraint_Sdd (x) + && disp_addr_displacement (x) <= max_mov_insn_displacement (mode, false)) return R0_REGS; /* When reload is trying to address a QImode or HImode subreg on the stack, Index: gcc/config/sh/sh.h =================================================================== --- gcc/config/sh/sh.h (revision 186233) +++ gcc/config/sh/sh.h (working copy) @@ -1210,24 +1210,12 @@ ((HOST_BITS_PER_WIDE_INT >= 64 && (VALUE) == (HOST_WIDE_INT) 0xffffffff) \ || (HOST_BITS_PER_WIDE_INT >= 64 && (VALUE) == (HOST_WIDE_INT) -1 << 32)) -#define CONST_OK_FOR_K04(VALUE) (((HOST_WIDE_INT)(VALUE))>= 0 \ - && ((HOST_WIDE_INT)(VALUE)) <= 15) - #define CONST_OK_FOR_K08(VALUE) (((HOST_WIDE_INT)(VALUE))>= 0 \ && ((HOST_WIDE_INT)(VALUE)) <= 255) -#define CONST_OK_FOR_K12(VALUE) (((HOST_WIDE_INT)(VALUE))>= 0 \ - && ((HOST_WIDE_INT)(VALUE)) <= 4095) - #define ZERO_EXTRACT_ANDMASK(EXTRACT_SZ_RTX, EXTRACT_POS_RTX)\ (((1 << INTVAL (EXTRACT_SZ_RTX)) - 1) << INTVAL (EXTRACT_POS_RTX)) -#define DISP_ADDR_P(X) (MEM_P (X) && GET_CODE (XEXP (X, 0)) == PLUS \ - && REG_P (XEXP (XEXP (X, 0), 0)) \ - && CONST_INT_P (XEXP (XEXP (X, 0), 1))) - -#define DISP_ADDR_OFFSET(X) (INTVAL (XEXP (XEXP (X, 0), 1))) - #if 0 #define SECONDARY_INOUT_RELOAD_CLASS(CLASS,MODE,X,ELSE) \ ((((REGCLASS_HAS_FP_REG (CLASS) \ Index: gcc/config/sh/constraints.md =================================================================== --- gcc/config/sh/constraints.md (revision 186234) +++ gcc/config/sh/constraints.md (working copy) @@ -145,16 +145,28 @@ (and (match_code "const_int") (match_test "ival >= 0 && ival <= 15"))) +(define_constraint "K05" + "An unsigned 5-bit constant, as used in mov.w displacement addressing." + (and (match_code "const_int") + (match_test "ival >= 0 && ival <= 31"))) + (define_constraint "K08" "An unsigned 8-bit constant, as used in and, or, etc." (and (match_code "const_int") (match_test "ival >= 0 && ival <= 255"))) (define_constraint "K12" - "An unsigned 12-bit constant, as used in SH2A 12-bit displacement addressing." + "An unsigned 12-bit constant, as used in SH2A 12-bit mov.b displacement + addressing." (and (match_code "const_int") (match_test "ival >= 0 && ival <= 4095"))) +(define_constraint "K13" + "An unsigned 13-bit constant, as used in SH2A 12-bit mov.w displacement + addressing." + (and (match_code "const_int") + (match_test "ival >= 0 && ival <= 8191"))) + (define_constraint "K16" "An unsigned 16-bit constant, as used in SHmedia shori." (and (match_code "const_int") @@ -262,6 +274,16 @@ (and (match_test "memory_operand (op, GET_MODE (op))") (match_test "GET_CODE (XEXP (op, 0)) != PLUS"))) +(define_memory_constraint "Sdd" + "A memory reference that uses displacement addressing." + (and (match_test "MEM_P (op) && GET_CODE (XEXP (op, 0)) == PLUS") + (match_test "REG_P (XEXP (XEXP (op, 0), 0))") + (match_test "CONST_INT_P (XEXP (XEXP (op, 0), 1))"))) + +(define_memory_constraint "Snd" + "A memory reference that excludes displacement addressing." + (match_test "! satisfies_constraint_Sdd (op)")) + (define_memory_constraint "Sbv" "A memory reference, as used in SH2A bclr.b, bset.b, etc." (and (match_test "MEM_P (op) && GET_MODE (op) == QImode") @@ -269,15 +291,7 @@ (define_memory_constraint "Sbw" "A memory reference, as used in SH2A bclr.b, bset.b, etc." - (and (match_test "MEM_P (op) && GET_MODE (op) == QImode") - (match_test "GET_CODE (XEXP (op, 0)) == PLUS") - (match_test "REG_P (XEXP (XEXP (op, 0), 0))") + (and (match_test "satisfies_constraint_Sdd (op)") + (match_test "GET_MODE (op) == QImode") (match_test "satisfies_constraint_K12 (XEXP (XEXP (op, 0), 1))"))) -(define_memory_constraint "Snd" - "A memory reference that excludes displacement addressing." - (match_test "! DISP_ADDR_P (op)")) - -(define_memory_constraint "Sdd" - "A memory reference that uses displacement addressing." - (match_test "DISP_ADDR_P (op)")) Index: gcc/config/sh/sh.md =================================================================== --- gcc/config/sh/sh.md (revision 186233) +++ gcc/config/sh/sh.md (working copy) @@ -4768,20 +4768,18 @@ operands[1] = XEXP (operands[1], 0); }) +;; FIXME: Maybe fold HImode and QImode stuff with mode iterator? (define_expand "extendhisi2" - [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") - (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "r,m")))] + [(set (match_operand:SI 0 "arith_reg_dest" "") + (sign_extend:SI (match_operand:HI 1 "general_extend_operand" "")))] "" "") -(define_insn "*extendhisi2_compact" - [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") - (sign_extend:SI (match_operand:HI 1 "general_movsrc_operand" "r,m")))] - "TARGET_SH1" - "@ - exts.w %1,%0 - mov.w %1,%0" - [(set_attr "type" "arith,load")]) +(define_expand "extendqisi2" + [(set (match_operand:SI 0 "arith_reg_dest" "") + (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "")))] + "" + "") (define_insn "*extendhisi2_media" [(set (match_operand:SI 0 "register_operand" "=r,r") @@ -4811,12 +4809,6 @@ subreg_lowpart_offset (SImode, GET_MODE (op1))); }) -(define_expand "extendqisi2" - [(set (match_operand:SI 0 "arith_reg_dest" "") - (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "")))] - "" - "") - (define_insn "*extendqisi2_compact_reg" [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") (sign_extend:SI (match_operand:QI 1 "register_operand" "r,t")))] @@ -4826,6 +4818,15 @@ movt %0" [(set_attr "type" "arith,arith")]) +(define_insn "*extendhisi2_compact_reg" + [(set (match_operand:SI 0 "arith_reg_dest" "=r,r") + (sign_extend:SI (match_operand:HI 1 "register_operand" "r,t")))] + "TARGET_SH1" + "@ + exts.w %1,%0 + movt %0" + [(set_attr "type" "arith,arith")]) + ;; FIXME: Fold non-SH2A and SH2A alternatives with "enabled" attribute. ;; See movqi insns. (define_insn "*extendqisi2_compact_mem_disp" @@ -4833,20 +4834,31 @@ (sign_extend:SI (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r") (match_operand:SI 2 "const_int_operand" "K04,N")))))] - "TARGET_SH1 && ! TARGET_SH2A && CONST_OK_FOR_K04 (INTVAL (operands[2]))" + "TARGET_SH1 && ! TARGET_SH2A + && sh_legitimate_index_p (QImode, operands[2], false, true)" "@ mov.b @(%O2,%1),%0 mov.b @%1,%0" [(set_attr "type" "load")]) +(define_insn "*extendhisi2_compact_mem_disp" + [(set (match_operand:SI 0 "arith_reg_dest" "=z,r") + (sign_extend:SI + (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r") + (match_operand:SI 2 "const_int_operand" "K05,N")))))] + "TARGET_SH1 && ! TARGET_SH2A + && sh_legitimate_index_p (HImode, operands[2], false, true)" + "@ + mov.w @(%O2,%1),%0 + mov.w @%1,%0" + [(set_attr "type" "load")]) + (define_insn "*extendqisi2_compact_mem_disp" [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r") (sign_extend:SI (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,r") (match_operand:SI 2 "const_int_operand" "K04,N,K12")))))] - "TARGET_SH2A - && (CONST_OK_FOR_K04 (INTVAL (operands[2])) - || (CONST_OK_FOR_K12 (INTVAL (operands[2]))))" + "TARGET_SH2A && sh_legitimate_index_p (QImode, operands[2], true, true)" "@ mov.b @(%O2,%1),%0 mov.b @%1,%0 @@ -4854,8 +4866,23 @@ [(set_attr "type" "load") (set_attr "length" "2,2,4")]) -;; This will take care of other QImode addressing modes than displacement -;; addressing. +(define_insn "*extendhisi2_compact_mem_disp" + [(set (match_operand:SI 0 "arith_reg_dest" "=z,r,r") + (sign_extend:SI + (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,r") + (match_operand:SI 2 "const_int_operand" "K05,N,K13")))))] + "TARGET_SH2A && sh_legitimate_index_p (HImode, operands[2], true, true)" + "@ + mov.w @(%O2,%1),%0 + mov.w @%1,%0 + mov.w @(%O2,%1),%0" + [(set_attr "type" "load") + (set_attr "length" "2,2,4")]) + +;; The *_snd patterns will take care of other QImode/HImode addressing +;; modes than displacement addressing. They must be defined _after_ the +;; displacement addressing patterns. Otherwise the displacement addressing +;; patterns will not be picked. (define_insn "*extendqisi2_compact_snd" [(set (match_operand:SI 0 "arith_reg_dest" "=r") (sign_extend:SI (match_operand:QI 1 "movsrc_no_disp_mem_operand" "Snd")))] @@ -4863,6 +4890,13 @@ "mov.b %1,%0" [(set_attr "type" "load")]) +(define_insn "*extendhisi2_compact_snd" + [(set (match_operand:SI 0 "arith_reg_dest" "=r") + (sign_extend:SI (match_operand:HI 1 "movsrc_no_disp_mem_operand" "Snd")))] + "TARGET_SH1" + "mov.w %1,%0" + [(set_attr "type" "load")]) + (define_insn "*extendqisi2_media" [(set (match_operand:SI 0 "register_operand" "=r,r") (sign_extend:SI (match_operand:QI 1 "general_extend_operand" "r,m")))] @@ -5441,6 +5475,14 @@ [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")]) +(define_expand "movhi" + [(set (match_operand:HI 0 "general_movdst_operand" "") + (match_operand:HI 1 "general_movsrc_operand" ""))] + "" +{ + prepare_move_operands (operands, HImode); +}) + (define_expand "movqi" [(set (match_operand:QI 0 "general_operand" "") (match_operand:QI 1 "general_operand" ""))] @@ -5456,6 +5498,7 @@ ;; With the movqi_reg_reg being specified before movqi it will be intially ;; picked to load/store regs. If the regs regs are on the stack reload will ;; try other insns and not stick to movqi_reg_reg. +;; The same applies to the movhi variants. (define_insn "*movqi_reg_reg" [(set (match_operand:QI 0 "arith_reg_dest" "=r,r") (match_operand:QI 1 "register_operand" "r,t"))] @@ -5465,44 +5508,82 @@ movt %0" [(set_attr "type" "move,arith")]) +(define_insn "*movhi_reg_reg" + [(set (match_operand:HI 0 "arith_reg_dest" "=r,r") + (match_operand:HI 1 "register_operand" "r,t"))] + "TARGET_SH1" + "@ + mov %1,%0 + movt %0" + [(set_attr "type" "move,arith")]) + ;; FIXME: The non-SH2A and SH2A variants should be combined by adding ;; "enabled" attribute as it is done in other targets. (define_insn "*movqi_store_mem_disp04" [(set (mem:QI (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r") (match_operand:SI 1 "const_int_operand" "K04,N"))) (match_operand:QI 2 "arith_reg_operand" "z,r"))] - "TARGET_SH1 && CONST_OK_FOR_K04 (INTVAL (operands[1]))" + "TARGET_SH1 && sh_legitimate_index_p (QImode, operands[1], false, true)" "@ mov.b %2,@(%O1,%0) mov.b %2,@%0" [(set_attr "type" "store")]) +(define_insn "*movhi_store_mem_disp05" + [(set (mem:HI (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r,r") + (match_operand:SI 1 "const_int_operand" "K05,N"))) + (match_operand:HI 2 "arith_reg_operand" "z,r"))] + "TARGET_SH1 && sh_legitimate_index_p (HImode, operands[1], false, true)" + "@ + mov.w %2,@(%O1,%0) + mov.w %2,@%0" + [(set_attr "type" "store")]) + (define_insn "*movqi_store_mem_disp12" [(set (mem:QI (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r") (match_operand:SI 1 "const_int_operand" "K12"))) (match_operand:QI 2 "arith_reg_operand" "r"))] - "TARGET_SH2A && CONST_OK_FOR_K12 (INTVAL (operands[1]))" + "TARGET_SH2A && sh_legitimate_index_p (QImode, operands[1], true, true)" "mov.b %2,@(%O1,%0)" [(set_attr "type" "store") (set_attr "length" "4")]) +(define_insn "*movhi_store_mem_disp13" + [(set (mem:HI (plus:SI (match_operand:SI 0 "arith_reg_operand" "%r") + (match_operand:SI 1 "const_int_operand" "K13"))) + (match_operand:HI 2 "arith_reg_operand" "r"))] + "TARGET_SH2A && sh_legitimate_index_p (HImode, operands[1], true, true)" + "mov.w %2,@(%O1,%0)" + [(set_attr "type" "store") + (set_attr "length" "4")]) + (define_insn "*movqi_load_mem_disp" [(set (match_operand:QI 0 "arith_reg_dest" "=z,r") (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r") (match_operand:SI 2 "const_int_operand" "K04,N"))))] - "TARGET_SH1 && ! TARGET_SH2A && CONST_OK_FOR_K04 (INTVAL (operands[2]))" + "TARGET_SH1 && ! TARGET_SH2A + && sh_legitimate_index_p (QImode, operands[2], false, true)" "@ mov.b @(%O2,%1),%0 mov.b @%1,%0" [(set_attr "type" "load")]) +(define_insn "*movhi_load_mem_disp" + [(set (match_operand:HI 0 "arith_reg_dest" "=z,r") + (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r") + (match_operand:SI 2 "const_int_operand" "K05,N"))))] + "TARGET_SH1 && ! TARGET_SH2A + && sh_legitimate_index_p (HImode, operands[2], false, true)" + "@ + mov.w @(%O2,%1),%0 + mov.w @%1,%0" + [(set_attr "type" "load")]) + (define_insn "*movqi_load_mem_disp" [(set (match_operand:QI 0 "arith_reg_dest" "=z,r,r") (mem:QI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,r") (match_operand:SI 2 "const_int_operand" "K04,N,K12"))))] - "TARGET_SH2A - && (CONST_OK_FOR_K04 (INTVAL (operands[2])) - || CONST_OK_FOR_K12 (INTVAL (operands[2])))" + "TARGET_SH2A && sh_legitimate_index_p (QImode, operands[2], true, true)" "@ mov.b @(%O2,%1),%0 mov.b @%1,%0 @@ -5510,6 +5591,18 @@ [(set_attr "type" "load") (set_attr "length" "2,2,4")]) +(define_insn "*movhi_load_mem_disp" + [(set (match_operand:HI 0 "arith_reg_dest" "=z,r,r") + (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "%r,r,r") + (match_operand:SI 2 "const_int_operand" "K05,N,K13"))))] + "TARGET_SH2A && sh_legitimate_index_p (HImode, operands[2], true, true)" + "@ + mov.w @(%O2,%1),%0 + mov.w @%1,%0 + mov.w @(%O2,%1),%0" + [(set_attr "type" "load") + (set_attr "length" "2,2,4")]) + ;; The m constraints basically allow any kind of addresses to be used with any ;; source/target register as the other operand. This is not true for ;; displacement addressing modes on anything but SH2A. That's why the @@ -5528,6 +5621,21 @@ lds %1,%0" [(set_attr "type" "movi8,load,store,prget,prset")]) +(define_insn "*movhi" + [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,m,r,l") + (match_operand:HI 1 "general_movsrc_operand" "Q,i,m,r,l,r"))] + "TARGET_SH1 + && (arith_reg_operand (operands[0], HImode) + || arith_reg_operand (operands[1], HImode))" + "@ + mov.w %1,%0 + mov %1,%0 + mov.w %1,%0 + mov.w %1,%0 + sts %1,%0 + lds %1,%0" + [(set_attr "type" "pcload,movi8,load,store,prget,prset")]) + (define_insn "*movqi_media" [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m") (match_operand:QI 1 "general_movsrc_operand" "r,I16Css,m,rZ"))] @@ -5560,28 +5668,6 @@ operands[3] = gen_rtx_REG (DImode, REGNO (operands[2])); }) -;; When storing r0, we have to avoid reg+reg addressing. -(define_insn "movhi_i" - [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m,r,l,r") - (match_operand:HI 1 "general_movsrc_operand" "Q,rI08,m,t,r,l,r,i"))] - "TARGET_SH1 - && (arith_reg_operand (operands[0], HImode) - || arith_reg_operand (operands[1], HImode)) - && (!MEM_P (operands[0]) - || GET_CODE (XEXP (operands[0], 0)) != PLUS - || !REG_P (XEXP (XEXP (operands[0], 0), 1)) - || ! refers_to_regno_p (R0_REG, R0_REG + 1, operands[1], (rtx *)0))" - "@ - mov.w %1,%0 - mov %1,%0 - mov.w %1,%0 - movt %0 - mov.w %1,%0 - sts %1,%0 - lds %1,%0 - fake %1,%0" - [(set_attr "type" "pcload,move,load,move,store,move,move,pcload")]) - (define_insn "*movhi_media" [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,r,m") (match_operand:HI 1 "general_movsrc_operand" "r,I16Css,n,m,rZ"))] @@ -5607,14 +5693,6 @@ && ! satisfies_constraint_I16 (operands[1])" [(set (subreg:DI (match_dup 0) 0) (match_dup 1))]) -(define_expand "movhi" - [(set (match_operand:HI 0 "general_movdst_operand" "") - (match_operand:HI 1 "general_movsrc_operand" ""))] - "" -{ - prepare_move_operands (operands, HImode); -}) - (define_expand "reload_inhi" [(set (match_operand:SI 2 "" "=&r") (match_operand:HI 1 "inqhi_operand" "")) @@ -11563,10 +11641,10 @@ ;; Fold sequence: ;; mov #54,r0 -;; mov.b @(r0,r15),r0 +;; mov.{b,w} @(r0,r15),r0 ;; mov r0,r3 ;; into: -;; mov.b @(54,r15),r3 +;; mov.{b,w} @(54,r15),r3 ;; (define_peephole2 [(set (match_operand:SI 0 "arith_reg_dest" "") @@ -11578,17 +11656,33 @@ (set (match_operand:QI 4 "arith_reg_dest" "") (match_operand:QI 5 "arith_reg_operand" ""))] "TARGET_SH2A - && CONST_OK_FOR_K12 (INTVAL (operands[1])) + && sh_legitimate_index_p (QImode, operands[1], true, true) && REGNO (operands[2]) == REGNO (operands[5]) && peep2_reg_dead_p (3, operands[5])" [(set (match_dup 4) (mem:QI (plus:SI (match_dup 3) (match_dup 1))))] "") +(define_peephole2 + [(set (match_operand:SI 0 "arith_reg_dest" "") + (match_operand:SI 1 "const_int_operand" "")) + (set (match_operand:SI 2 "arith_reg_dest" "") + (sign_extend:SI + (mem:HI (plus:SI (match_dup 0) + (match_operand:SI 3 "arith_reg_operand" ""))))) + (set (match_operand:HI 4 "arith_reg_dest" "") + (match_operand:HI 5 "arith_reg_operand" ""))] + "TARGET_SH2A + && sh_legitimate_index_p (HImode, operands[1], true, true) + && REGNO (operands[2]) == REGNO (operands[5]) + && peep2_reg_dead_p (3, operands[5])" + [(set (match_dup 4) (mem:HI (plus:SI (match_dup 3) (match_dup 1))))] + "") + ;; Fold sequence: ;; mov #54,r0 -;; mov.b @(r0,r15),r1 +;; mov.{b,w} @(r0,r15),r1 ;; into: -;; mov.b @(54,r15),r1 +;; mov.{b,w} @(54,r15),r1 ;; (define_peephole2 [(set (match_operand:SI 0 "arith_reg_dest" "") @@ -11598,19 +11692,37 @@ (mem:QI (plus:SI (match_dup 0) (match_operand:SI 3 "arith_reg_operand" "")))))] "TARGET_SH2A - && CONST_OK_FOR_K12 (INTVAL (operands[1])) + && sh_legitimate_index_p (QImode, operands[1], true, true) && (peep2_reg_dead_p (2, operands[0]) || REGNO (operands[0]) == REGNO (operands[2]))" [(set (match_dup 2) (sign_extend:SI (mem:QI (plus:SI (match_dup 3) (match_dup 1)))))] "") +(define_peephole2 + [(set (match_operand:SI 0 "arith_reg_dest" "") + (match_operand:SI 1 "const_int_operand" "")) + (set (match_operand:SI 2 "arith_reg_dest" "") + (sign_extend:SI + (mem:HI (plus:SI (match_dup 0) + (match_operand:SI 3 "arith_reg_operand" "")))))] + "TARGET_SH2A + && sh_legitimate_index_p (HImode, operands[1], true, true) + && (peep2_reg_dead_p (2, operands[0]) + || REGNO (operands[0]) == REGNO (operands[2]))" + [(set (match_dup 2) + (sign_extend:SI (mem:HI (plus:SI (match_dup 3) (match_dup 1)))))] + "") + ;; Fold sequence: -;; mov.b @(r0,r15),r0 +;; mov.{b,w} @(r0,r15),r0 ;; mov r0,r3 ;; into: -;; mov.b @(r0,r15),r3 +;; mov.{b,w} @(r0,r15),r3 ;; +;; This can happen when initially a displacement address is picked, where +;; the destination reg is fixed to r0, and then the address is transformed +;; into 'r0 + reg'. (define_peephole2 [(set (match_operand:SI 0 "arith_reg_dest" "") (sign_extend:SI @@ -11625,6 +11737,20 @@ (mem:QI (plus:SI (match_dup 1) (match_dup 2))))] "") +(define_peephole2 + [(set (match_operand:SI 0 "arith_reg_dest" "") + (sign_extend:SI + (mem:HI (plus:SI (match_operand:SI 1 "arith_reg_operand" "") + (match_operand:SI 2 "arith_reg_operand" ""))))) + (set (match_operand:HI 3 "arith_reg_dest" "") + (match_operand:HI 4 "arith_reg_operand" ""))] + "TARGET_SH1 + && REGNO (operands[0]) == REGNO (operands[4]) + && peep2_reg_dead_p (2, operands[0])" + [(set (match_dup 3) + (mem:HI (plus:SI (match_dup 1) (match_dup 2))))] + "") + ;; These convert sequences such as `mov #k,r0; add r15,r0; mov.l @r0,rn' ;; to `mov #k,r0; mov.l @(r0,r15),rn'. These sequences are generated by ;; reload when the constant is too large for a reg+offset address.