X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fconfig%2Fm68hc11%2Fm68hc11.md;h=4ef5cd7b5a14df4841cd362a2d657f86a8a89bbc;hb=a361b456a6601ea251d6fa2365ef359963fbf62e;hp=c87a2188d0e7ca83ce8fcb18d7946b379b78ceae;hpb=a233be5e6405e6b50786a499172ed27696a820bf;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/config/m68hc11/m68hc11.md b/gcc/config/m68hc11/m68hc11.md index c87a2188d0e..4ef5cd7b5a1 100644 --- a/gcc/config/m68hc11/m68hc11.md +++ b/gcc/config/m68hc11/m68hc11.md @@ -1,21 +1,22 @@ ;;- Machine description file for Motorola 68HC11 and 68HC12. -;;- Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. -;;- Contributed by Stephane Carrez (stcarrez@worldnet.fr) +;;- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 +;;- Free Software Foundation, Inc. +;;- Contributed by Stephane Carrez (stcarrez@nerim.fr) -;; This file is part of GNU CC. +;; This file is part of GCC. -;; GNU CC is free software; you can redistribute it and/or modify +;; GCC is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. -;; GNU CC is distributed in the hope that it will be useful, +;; GCC is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU CC; see the file COPYING. If not, write to +;; along with GCC; see the file COPYING. If not, write to ;; the Free Software Foundation, 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA. @@ -65,9 +66,20 @@ ;; ;; Other constraints: ;; -;; T an operand that can be accessed with 68HC1X direct addressing -;; mode. For 68HC11 this includes the pseudo soft registers and -;; any memory operand that is a direct addressing (.page0). +;; Q an operand which is in memory but whose address is constant +;; (i.e., a (MEM (SYMBOL_REF x))). This constraint is used by +;; bset/bclr instructions together with linker relaxation. The +;; operand can be translated to a page0 addressing mode if the +;; symbol address is in page0 (0..255). +;; +;; R an operand which is in memory and whose address is expressed +;; with 68HC11/68HC12 indexed addressing mode. In general this +;; is any valid (MEM) except a (MEM (SYMBOL_REF x)). +;; +;; U an operand which is in memory and if it uses the 68HC12 indexed +;; addressing mode, the offset is in the range -16..+15. This is +;; used by 68HC12 movb/movw instructions since they do not accept +;; the full 16-bit offset range (as other insn do). ;; ;; ;; Immediate integer operand constraints: @@ -82,7 +94,7 @@ ;; Operands modifiers: ;; ;; %b Get the low part of the operand (to obtain a QImode) -;; This modified must always be used for QImode operations +;; This modifier must always be used for QImode operations ;; because a correction must be applied when the operand ;; is a soft register (ex: *ZD1). Otherwise, we generate ;; *ZD1 and this is the high part of the register. For other @@ -94,9 +106,9 @@ ;; some values in bad registers. ;; ;; 32/64-bit Patterns: -;; The 68HC11 does not support 32/64-bit operations. Most of the +;; The 68HC11 does not support 32/64-bit operations. Most of the ;; 32/64-bit patterns are defined to split the instruction in -;; 16-bits patterns. Providing split patterns generates better code +;; 16-bits patterns. Providing split patterns generates better code ;; than letting GCC implement the 32/64-bit operation itself. ;; ;; @@ -111,7 +123,7 @@ ;; them correctly (it would treat the X, Y or D register as dead sometimes). ;; ;; o Some split pattern generate instructions that operate on 'a' or 'b' -;; register directory (high part and low part of D respectively). +;; register directly (high part and low part of D respectively). ;; Such split pattern must also be valid when z_replacement_completed == 2 ;; because flow/cse is not aware that D is composed of {a, b}. ;; @@ -132,6 +144,9 @@ (A_REGNUM 5) ; A (high part of D) (B_REGNUM 6) ; B (low part of D) (CC_REGNUM 7) ; Condition code register + (SOFT_TMP_REGNUM 10) ; TMP soft register + (SOFT_Z_REGNUM 11) ; Z soft register + (SOFT_XY_REGNUM 12) ; XY soft register ]) ;;-------------------------------------------------------------------- @@ -142,7 +157,7 @@ ;; an auto-inc mode. If we do this, the reload can emit move insns ;; after the test or compare. Such move will set the flags and therefore ;; break the comparison. This can happen if the auto-inc register -;; does not happen to be a hard register (ie, reloading occurs). +;; does not happen to be a hard register (i.e., reloading occurs). ;; An offsetable memory operand should be ok. The 'tst_operand' and ;; 'cmp_operand' predicates take care of this rule. ;; @@ -170,7 +185,7 @@ (define_insn "tsthi_1" [(set (cc0) - (match_operand:HI 0 "tst_operand" "dx,y"))] + (match_operand:HI 0 "tst_operand" "dx,*y"))] "" "* { @@ -193,32 +208,41 @@ ;; ;; Split pattern for (tst:QI) on an address register. -;; The value is saved in memory and we test the low part only. ;; (define_split [(set (cc0) - (match_operand:QI 0 "hard_addr_reg_operand" "xy"))] + (match_operand:QI 0 "hard_addr_reg_operand" ""))] "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode" - [(set (match_dup 3) (match_dup 2)) - (set (cc0) (match_dup 4))] - "operands[2] = gen_rtx (REG, HImode, REGNO (operands[0])); - operands[3] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); - operands[4] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);") + [(parallel [(set (reg:HI D_REGNUM) (match_dup 1)) + (set (match_dup 1) (reg:HI D_REGNUM))]) + (set (cc0) (reg:QI D_REGNUM)) + (parallel [(set (reg:HI D_REGNUM) (match_dup 1)) + (set (match_dup 1) (reg:HI D_REGNUM))])] + "operands[1] = gen_rtx_REG (HImode, REGNO (operands[0]));") (define_insn "tstqi_1" [(set (cc0) (match_operand:QI 0 "tst_operand" "m,d,*A,!u"))] "" - "@ - tst\\t%0 - tstb - # - tst\\t%b0") + "* +{ + if (A_REG_P (operands[0])) + return \"#\"; + + else if (D_REG_P (operands[0])) + return \"tstb\"; + + else if (dead_register_here (insn, d_reg)) + return \"ldab\\t%b0\"; + + else + return \"tst\\t%b0\"; +}") ;; ;; tstqi_z_used, cmpqi_z_used and cmphi_z_used are patterns generated ;; during the Z register replacement. They are used when an operand -;; uses the Z register as an index register (ie, (MEM:QI (REG:HI Z))). +;; uses the Z register as an index register (i.e., (MEM:QI (REG:HI Z))). ;; In that case, we have to preserve the values of the replacement ;; register (as well as the CC0 since the insns are compare insns). ;; To do this, the replacement register is pushed on the stack and @@ -226,25 +250,19 @@ ;; avoid problems with the flow+cse register pass which are made ;; after Z register replacement. ;; -(define_insn "tstqi_z_used" +(define_insn_and_split "tstqi_z_used" [(set (cc0) (match_operand:QI 0 "tst_operand" "m")) (use (match_operand:HI 1 "hard_reg_operand" "dxy")) - (use (reg:HI 11))] + (use (reg:HI SOFT_Z_REGNUM))] "" - "#") - -(define_split /* "tstqi_z_used" */ - [(set (cc0) - (match_operand:QI 0 "tst_operand" "m")) - (use (match_operand:HI 1 "hard_reg_operand" "dxy")) - (use (reg:HI 11))] + "#" "z_replacement_completed == 2" [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1)) (set (match_dup 1) (match_dup 2)) (set (cc0) (match_dup 0)) (set (match_dup 1) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))] - "operands[2] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);") + "operands[2] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);") ;;-------------------------------------------------------------------- @@ -277,13 +295,25 @@ ;; (define_split [(set (cc0) - (compare (match_operand:HI 0 "hard_reg_operand" "dxy") - (match_operand:HI 1 "hard_reg_operand" "Aw")))] - "reload_completed" + (compare (match_operand:HI 0 "hard_reg_operand" "") + (match_operand:HI 1 "hard_reg_operand" "")))] + "TARGET_M6811 + && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))" [(set (match_dup 2) (match_dup 1)) (set (cc0) (compare (match_dup 0) (match_dup 2)))] - "operands[2] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);") + "operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);") + +(define_split + [(set (cc0) + (compare (match_operand:HI 0 "hard_reg_operand" "") + (match_operand:HI 1 "hard_reg_operand" "")))] + "0 && TARGET_M6812 + && reload_completed && !(Z_REG_P (operands[0]) || Z_REG_P (operands[1]))" + [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 1)) + (set (cc0) + (compare (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM)))))] + "") (define_expand "cmphi" [(set (cc0) @@ -300,42 +330,62 @@ DONE; }") -(define_insn "cmphi_1" +(define_insn "cmphi_1_hc12" + [(set (cc0) + (compare (match_operand:HI 0 "tst_operand" + "d,?xy,xyd,?xy,d,m,!u,dxy,dxy") + (match_operand:HI 1 "general_operand" + "i,i,!u,m,m,dxy,dxy,?*d*A,!*w")))] + "TARGET_M6812" + "* +{ + if (H_REG_P (operands[1]) && !H_REG_P (operands[0])) + { + cc_status.flags |= CC_REVERSED; + return \"cp%1\\t%0\"; + } + else if (SP_REG_P (operands[1])) + return \"sts\\t2,-sp\n\\tcp%0\\t2,sp+\"; + else if (H_REG_P (operands[1])) + return \"psh%1\n\\tcp%0\\t2,sp+\"; + else + return \"cp%0\\t%1\"; +}") + +(define_insn "cmphi_1_hc11" [(set (cc0) (compare (match_operand:HI 0 "tst_operand" - "xy,d,?xy,d,dxy,dxy,dxy") + "dx,y,xyd,?xy,d,m,m,dxy,dxy,?u*z,dxy,*z") (match_operand:HI 1 "cmp_operand" - "i,i,m,m,?*d*A,?u,!*w")))] - "" + "i,i,!u,m,m,?xy,d,?*d*A,?u,dxy,!*w,i")))] + "TARGET_M6811" "* { - if (H_REG_P (operands[1])) + if (H_REG_P (operands[1]) && !H_REG_P (operands[0])) + { + cc_status.flags |= CC_REVERSED; + return \"cp%1\\t%0\"; + } + else if (H_REG_P (operands[1])) return \"#\"; else return \"cp%0\\t%1\"; }") -(define_insn "cmphi_z_used" +(define_insn_and_split "cmphi_z_used" [(set (cc0) - (compare (match_operand:HI 0 "hard_reg_operand" "dxy") - (match_operand:HI 1 "cmp_operand" "m"))) - (use (match_operand:HI 2 "hard_reg_operand" "dxy")) - (use (reg:HI 11))] + (compare (match_operand:HI 0 "tst_operand" "dxy,m") + (match_operand:HI 1 "cmp_operand" "mi,dxy"))) + (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy")) + (use (reg:HI SOFT_Z_REGNUM))] "" - "#") - -(define_split /* "cmphi_z_used" */ - [(set (cc0) - (compare (match_operand:HI 0 "hard_reg_operand" "dxy") - (match_operand:HI 1 "cmp_operand" "m"))) - (use (match_operand:HI 2 "hard_reg_operand" "dxy")) - (use (reg:HI 11))] + "#" "z_replacement_completed == 2" [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2)) (set (match_dup 2) (match_dup 3)) (set (cc0) (compare (match_dup 0) (match_dup 1))) (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))] - "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);") + "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);") ;; ;; 8-bit comparison with address register. @@ -345,8 +395,8 @@ ;; (define_split [(set (cc0) - (compare (match_operand:QI 0 "hard_addr_reg_operand" "xy") - (match_operand:QI 1 "cmp_operand" "uimA")))] + (compare (match_operand:QI 0 "hard_addr_reg_operand" "") + (match_operand:QI 1 "cmp_operand" "")))] "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode" [(parallel [(set (reg:HI D_REGNUM) (match_dup 3)) (set (match_dup 3) (reg:HI D_REGNUM))]) @@ -354,19 +404,19 @@ (compare (reg:QI D_REGNUM) (match_dup 1))) (parallel [(set (reg:HI D_REGNUM) (match_dup 3)) (set (match_dup 3) (reg:HI D_REGNUM))])] - "operands[3] = gen_rtx (REG, HImode, REGNO (operands[0]));") + "operands[3] = gen_rtx_REG (HImode, REGNO (operands[0]));") (define_split [(set (cc0) - (compare (match_operand:QI 0 "hard_reg_operand" "dxy") - (match_operand:QI 1 "hard_reg_operand" "dxy")))] + (compare (match_operand:QI 0 "hard_reg_operand" "") + (match_operand:QI 1 "hard_reg_operand" "")))] "reload_completed" [(set (match_dup 3) (match_dup 4)) (set (cc0) (compare (match_dup 0) (match_dup 2)))] - "operands[2] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM); - operands[3] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); - operands[4] = gen_rtx (REG, HImode, REGNO (operands[1]));") + "operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM); + operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM); + operands[4] = gen_rtx_REG (HImode, REGNO (operands[1]));") (define_expand "cmpqi" [(set (cc0) @@ -397,36 +447,29 @@ (define_split /* "bitcmpqi" */ [(set (cc0) - (and:QI (match_operand:QI 0 "tst_operand" "d") - (match_operand:QI 1 "hard_addr_reg_operand" "xy")))] - "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode" + (and:QI (match_operand:QI 0 "tst_operand" "") + (match_operand:QI 1 "hard_addr_reg_operand" "")))] + "z_replacement_completed == 2" [(set (match_dup 3) (match_dup 2)) (set (cc0) (and:QI (match_dup 0) (match_dup 4)))] - "operands[2] = gen_rtx (REG, HImode, REGNO (operands[1])); - operands[3] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); - operands[4] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM);") + "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1])); + operands[3] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM); + operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM);") -(define_insn "bitcmpqi_z_used" +(define_insn_and_split "bitcmpqi_z_used" [(set (cc0) (and:QI (match_operand:QI 0 "tst_operand" "d,m") (match_operand:QI 1 "cmp_operand" "m,d"))) (use (match_operand:HI 2 "hard_reg_operand" "xy,xy")) - (use (reg:HI 11))] + (use (reg:HI SOFT_Z_REGNUM))] "" - "#") - -(define_split /* "bitcmpqi_z_used" */ - [(set (cc0) - (and:QI (match_operand:QI 0 "tst_operand" "d,m") - (match_operand:QI 1 "cmp_operand" "m,d"))) - (use (match_operand:HI 2 "hard_reg_operand" "xy,xy")) - (use (reg:HI 11))] + "#" "z_replacement_completed == 2" - [(set (mem:HI (pre_dec:HI (reg:HI 3))) (match_dup 2)) + [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2)) (set (match_dup 2) (match_dup 3)) (set (cc0) (and:QI (match_dup 0) (match_dup 1))) - (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI 3))))] - "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);") + (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))] + "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);") (define_insn "bitcmphi" [(set (cc0) @@ -479,60 +522,37 @@ (define_insn "cmpqi_1" [(set (cc0) - (compare (match_operand:QI 0 "tst_operand" "d,d,*x*y,*x*y") - (match_operand:QI 1 "cmp_operand" "im,!u,!u,?dim*x*y")))] + (compare (match_operand:QI 0 "tst_operand" "d,m,d,!u,*B,d*B") + (match_operand:QI 1 "cmp_operand" "im,d,!u,d,dim*A,*u")))] "" - "@ - cmpb\\t%1 - cmpb\\t%b1 - # - #") + "* +{ + if (A_REG_P (operands[0]) || A_REG_P (operands[1])) + { + return \"#\"; + } + else if (D_REG_P (operands[0])) + { + return \"cmpb\\t%b1\"; + } + cc_status.flags |= CC_REVERSED; + return \"cmpb\\t%b0\"; +}") -(define_insn "cmpqi_z_used" +(define_insn_and_split "cmpqi_z_used" [(set (cc0) - (compare (match_operand:QI 0 "hard_reg_operand" "dxy") - (match_operand:QI 1 "cmp_operand" "m"))) - (use (match_operand:HI 2 "hard_reg_operand" "dxy")) - (use (reg:HI 11))] + (compare (match_operand:QI 0 "tst_operand" "dxy,m") + (match_operand:QI 1 "cmp_operand" "m,dxy"))) + (use (match_operand:HI 2 "hard_reg_operand" "dxy,dxy")) + (use (reg:HI SOFT_Z_REGNUM))] "" - "#") - -(define_split /* cmpqi_z_used */ - [(set (cc0) - (compare (match_operand:QI 0 "hard_reg_operand" "dxy") - (match_operand:QI 1 "cmp_operand" "m"))) - (use (match_operand:HI 2 "hard_reg_operand" "dxy")) - (use (reg:HI 11))] + "#" "z_replacement_completed == 2" [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2)) (set (match_dup 2) (match_dup 3)) (set (cc0) (compare (match_dup 0) (match_dup 1))) (set (match_dup 2) (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))] - "operands[3] = gen_rtx (REG, HImode, SOFT_Z_REGNUM);") - -(define_expand "cmpdf" - [(set (cc0) - (compare (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" "")))] - "0" - " -{ - m68hc11_compare_op0 = operands[0]; - m68hc11_compare_op1 = operands[1]; - DONE; -}") - -(define_expand "cmpsf" - [(set (cc0) - (compare (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" "")))] - "0" - " -{ - m68hc11_compare_op0 = operands[0]; - m68hc11_compare_op1 = operands[1]; - DONE; -}") + "operands[3] = gen_rtx_REG (HImode, SOFT_Z_REGNUM);") ;;-------------------------------------------------------------------- ;;- Move strict_low_part @@ -543,41 +563,29 @@ ;; (strict_low_part ...) information. This is correct for our machine ;; description but not for GCC optimization passes. ;; -(define_insn "movstrictsi" +(define_insn_and_split "movstrictsi" [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D")) (match_operand:SI 1 "general_operand" "D,Dim,uD"))] "" - "#") - -(define_split - [(set (strict_low_part (match_operand:SI 0 "non_push_operand" "+um,D,D")) - (match_operand:SI 1 "general_operand" "D,Dim,u"))] + "#" "z_replacement_completed == 2" [(set (match_dup 0) (match_dup 1))] "") -(define_insn "movstricthi" +(define_insn_and_split "movstricthi" [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA")) (match_operand:HI 1 "general_operand" "dA,dAim,u"))] "" - "#") - -(define_split - [(set (strict_low_part (match_operand:HI 0 "non_push_operand" "+um,dA,dA")) - (match_operand:HI 1 "general_operand" "dA,dAim,u"))] + "#" "z_replacement_completed == 2" [(set (match_dup 0) (match_dup 1))] "") -(define_insn "movstrictqi" +(define_insn_and_split "movstrictqi" [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,!dA")) (match_operand:QI 1 "general_operand" "d,imudA"))] "" - "#") - -(define_split - [(set (strict_low_part (match_operand:QI 0 "non_push_operand" "+mu,dA")) - (match_operand:QI 1 "general_operand" "d,imudA"))] + "#" "z_replacement_completed == 2" [(set (match_dup 0) (match_dup 1))] "") @@ -591,7 +599,7 @@ ;; because there is no memory->memory moves. It must be defined with ;; earlyclobber (&) so that it does not appear in the source or destination ;; address. Providing patterns for movdi/movdf allows GCC to generate -;; better code. [Until now, the scratch register is limited to D becuse +;; better code. [Until now, the scratch register is limited to D because ;; otherwise we can run out of registers in the A_REGS class for reload]. ;; ;; For 68HC12, the scratch register is not necessary. To use the same @@ -621,17 +629,26 @@ } ") -(define_insn "movdi_internal" - [(set (match_operand:DI 0 "nonimmediate_operand" "=U,!u,U,m,m,!u") - (match_operand:DI 1 "general_operand" "iU,iU,!u,mi,!u,!mu")) - (clobber (match_scratch:HI 2 "=&d,&d,&d,&d,&d,&d"))] +;; Separate push from normal moves to avoid reloading problems +;; The 'clr' is not able to push on 68HC11 so we really need a scratch. +;; We can also accept more scratch registers. +(define_insn_and_split "*pushdi_internal" + [(set (match_operand:DI 0 "push_operand" "=<,<,<,<") + (match_operand:DI 1 "general_operand" "i,U,m,!u")) + (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))] "" - "#") + "#" + "reload_completed" + [(const_int 0)] + "m68hc11_split_move (operands[0], operands[1], operands[2]); + DONE;") -(define_split - [(set (match_operand:DI 0 "nonimmediate_operand" "=uUm") - (match_operand:DI 1 "general_operand" "iuUm")) - (clobber (match_scratch:HI 2 "=&d"))] +(define_insn_and_split "movdi_internal" + [(set (match_operand:DI 0 "non_push_operand" "=m!u,U,!u,U,m,m,!u") + (match_operand:DI 1 "general_operand" "K,iU,iU,!u,mi,!u,!mu")) + (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))] + "" + "#" "reload_completed" [(const_int 0)] "m68hc11_split_move (operands[0], operands[1], operands[2]); @@ -657,17 +674,24 @@ } ") -(define_insn "movdf_internal" - [(set (match_operand:DF 0 "nonimmediate_operand" "=U,!u,U,m,m,!u") - (match_operand:DF 1 "general_operand" "iU,iU,!u,mi,!u,!mu")) - (clobber (match_scratch:HI 2 "=&d,&d,&d,&d,&d,&d"))] +;; See pushdi_internal +(define_insn_and_split "*pushdf_internal" + [(set (match_operand:DF 0 "push_operand" "=<,<,<,<") + (match_operand:DF 1 "general_operand" "i,U,m,!u")) + (clobber (match_scratch:HI 2 "=&dA,&d,&d,&dA"))] "" - "#") + "#" + "reload_completed" + [(const_int 0)] + "m68hc11_split_move (operands[0], operands[1], operands[2]); + DONE;") -(define_split - [(set (match_operand:DF 0 "nonimmediate_operand" "=uUm") - (match_operand:DF 1 "general_operand" "iuUm")) - (clobber (match_scratch:HI 2 "=&d"))] +(define_insn_and_split "movdf_internal" + [(set (match_operand:DF 0 "non_push_operand" "=mu,U,!u,U,m,m,!u") + (match_operand:DF 1 "general_operand" "G,iU,iU,!u,mi,!u,!mu")) + (clobber (match_scratch:HI 2 "=X,&d,&d,&d,&d,&d,&d"))] + "" + "#" "reload_completed" [(const_int 0)] "m68hc11_split_move (operands[0], operands[1], operands[2]); @@ -702,17 +726,23 @@ } ") -(define_insn "movsi_internal" - [(set (match_operand:SI 0 "nonimmediate_operand" "=mu,?D,m,?D,?u,?u,!u,D") - (match_operand:SI 1 "general_operand" "imu,im,?D,!u,?D,mi,!u,!D")) - (clobber (match_scratch:HI 2 "=&d,X,X,X,X,&d,&d,X"))] +(define_insn_and_split "*pushsi_internal" + [(set (match_operand:SI 0 "push_operand" "=<,<,<,<,<") + (match_operand:SI 1 "general_operand" "!D,i,U,m,!u")) + (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))] "" - "#") + "#" + "reload_completed" + [(const_int 0)] + "m68hc11_split_move (operands[0], operands[1], operands[2]); + DONE;") -(define_split - [(set (match_operand:SI 0 "nonimmediate_operand" "=m,D,m,D,!u,!u,!u,D") - (match_operand:SI 1 "general_operand" "im,im,D,!u,D,mi,!u,!D")) - (clobber (match_scratch:HI 2 "=&d,X,X,X,X,&d,&d,X"))] +(define_insn_and_split "movsi_internal" + [(set (match_operand:SI 0 "nonimmediate_operand" "=mu,mu,?D,m,?D,?u,?u,!u,D") + (match_operand:SI 1 "general_operand" "K,imu,im,?D,!u,?D,mi,!u,!D")) + (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))] + "" + "#" "reload_completed" [(const_int 0)] "m68hc11_split_move (operands[0], operands[1], operands[2]); @@ -738,17 +768,23 @@ } ") -(define_insn "movsf_internal" - [(set (match_operand:SF 0 "nonimmediate_operand" "=m,D,m,D,!u,!u,!u,D") - (match_operand:SF 1 "general_operand" "im,im,D,!u,D,mi,!u,!D")) - (clobber (match_scratch:HI 2 "=&d,X,X,X,X,&d,&d,X"))] +(define_insn_and_split "*pushsf_internal" + [(set (match_operand:SF 0 "push_operand" "=<,<,<,<,<") + (match_operand:SF 1 "general_operand" "!D,i,U,m,!u")) + (clobber (match_scratch:HI 2 "=X,&dA,&d,&d,&dA"))] "" - "#") + "#" + "reload_completed" + [(const_int 0)] + "m68hc11_split_move (operands[0], operands[1], operands[2]); + DONE;") -(define_split - [(set (match_operand:SF 0 "nonimmediate_operand" "=m,D,m,D,!u,!u,!u,D") - (match_operand:SF 1 "general_operand" "im,im,D,!u,D,mi,!u,!D")) - (clobber (match_scratch:HI 2 "=&d,X,X,X,X,&d,&d,X"))] +(define_insn_and_split "movsf_internal" + [(set (match_operand:SF 0 "nonimmediate_operand" "=m!u,m,D,m,D,!u,!u,!u,D") + (match_operand:SF 1 "general_operand" "G,im,im,D,!u,D,mi,!u,!D")) + (clobber (match_scratch:HI 2 "=X,&d,X,X,X,X,&d,&d,X"))] + "" + "#" "reload_completed" [(const_int 0)] "m68hc11_split_move (operands[0], operands[1], operands[2]); @@ -761,8 +797,8 @@ ;;-------------------------------------------------------------------- (define_insn "*movhi2_push" - [(set (match_operand:HI 0 "push_operand" "=<,<") - (match_operand:HI 1 "general_operand" "xy,?d"))] + [(set (match_operand:HI 0 "push_operand" "=<,<,<") + (match_operand:HI 1 "general_operand" "xy,?d,!z"))] "TARGET_M6811 && !TARGET_M6812" "* { @@ -840,7 +876,7 @@ { rtx insn; - insn = emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); + insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1])); REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, stack_pointer_rtx, REG_NOTES (insn)); @@ -849,7 +885,7 @@ }") (define_insn "movhi_const0" - [(set (match_operand:HI 0 "non_push_operand" "=d,A,um") + [(set (match_operand:HI 0 "splitable_operand" "=d,A,um") (const_int 0))] "" "@ @@ -858,8 +894,8 @@ clr\\t%b0\\n\\tclr\\t%h0") (define_insn "*movhi_68hc12" - [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,U,U,m,!u") - (match_operand:HI 1 "general_operand" "U,rim,dAwi,!u,dAw,riU"))] + [(set (match_operand:HI 0 "nonimmediate_operand" "=U,dAw,dAw,U,U,m,!u") + (match_operand:HI 1 "general_operand" "U,dAwim,!u,dAwi,!u,dAw,riU"))] "TARGET_M6812" "* { @@ -904,33 +940,33 @@ ;; appear in the source operand. ;; (define_split - [(set (match_operand:QI 0 "hard_addr_reg_operand" "=A") + [(set (match_operand:QI 0 "hard_addr_reg_operand" "") (match_operand:QI 1 "general_operand" ""))] - "z_replacement_completed == 2 && GET_MODE (operands[0]) == QImode + "z_replacement_completed == 2 && !reg_mentioned_p (operands[0], operands[1]) - && !D_REG_P (operands[1])" + && !(D_REG_P (operands[1]) || Q_REG_P (operands[1]))" [(parallel [(set (reg:HI D_REGNUM) (match_dup 2)) (set (match_dup 2) (reg:HI D_REGNUM))]) (set (reg:QI D_REGNUM) (match_dup 1)) (parallel [(set (reg:HI D_REGNUM) (match_dup 2)) (set (match_dup 2) (reg:HI D_REGNUM))])] - "operands[2] = gen_rtx (REG, HImode, REGNO (operands[0]));") + "operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));") ;; ;; 8-bit operations on address registers. ;; (define_split [(set (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand:QI 1 "hard_addr_reg_operand" "=A"))] - "z_replacement_completed == 2 && GET_MODE (operands[1]) == QImode + (match_operand:QI 1 "hard_addr_reg_operand" ""))] + "z_replacement_completed == 2 && !reg_mentioned_p (operands[1], operands[0]) - && !D_REG_P (operands[0])" + && !(D_REG_P (operands[0]) || Q_REG_P (operands[0]))" [(parallel [(set (reg:HI D_REGNUM) (match_dup 2)) (set (match_dup 2) (reg:HI D_REGNUM))]) (set (match_dup 0) (reg:QI D_REGNUM)) (parallel [(set (reg:HI D_REGNUM) (match_dup 2)) (set (match_dup 2) (reg:HI D_REGNUM))])] - "operands[2] = gen_rtx (REG, HImode, REGNO (operands[1]));") + "operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));") (define_insn "*movqi2_push" [(set (match_operand:QI 0 "push_operand" "=<,<") @@ -980,7 +1016,7 @@ { rtx insn; - insn = emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1])); + insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1])); REG_NOTES (insn) = alloc_EXPR_LIST (REG_INC, stack_pointer_rtx, REG_NOTES (insn)); @@ -989,8 +1025,10 @@ }") (define_insn "*movqi_68hc12" - [(set (match_operand:QI 0 "nonimmediate_operand" "=d*AuU*q,d*A*qu,d*A*q,m,m") - (match_operand:QI 1 "general_operand" "rui*q,U,m,d*q,!A"))] + [(set (match_operand:QI 0 "nonimmediate_operand" + "=U,d*AU*q,d*A*qU,d*A*q,m,?*u,m") + (match_operand:QI 1 "general_operand" + "U,*ri*q,U,m,d*q,*ri*qU,!*A"))] "TARGET_M6812" "* { @@ -999,8 +1037,8 @@ }") (define_insn "*movqi_m68hc11" - [(set (match_operand:QI 0 "nonimmediate_operand" "=dA*q,m,m,dA*q,*u") - (match_operand:QI 1 "general_operand" "dAim*q,d*q,!A,*u,dA*q"))] + [(set (match_operand:QI 0 "nonimmediate_operand" "=d*A*q,m,m,d*A*q,*u") + (match_operand:QI 1 "general_operand" "d*Aim*q,d*q,!*A,*u,d*A*q"))] "TARGET_M6811" "* { @@ -1066,8 +1104,8 @@ "#") (define_split - [(set (match_operand:DI 0 "push_operand" "=<") - (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "dmu*B"))) + [(set (match_operand:DI 0 "push_operand" "") + (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" ""))) (clobber (match_scratch:HI 2 "=&dB"))] "z_replacement_completed == 2" [(const_int 0)] @@ -1077,15 +1115,15 @@ rtx push = m68hc11_gen_lowpart (HImode, low); rtx src = operands[1]; - /* Source operand must be in a hard register. */ + /* Source operand must be in a hard register. */ if (!H_REG_P (src)) { - src = gen_rtx (REG, QImode, REGNO (operands[2])); + src = gen_rtx_REG (QImode, REGNO (operands[2])); emit_move_insn (src, operands[1]); } /* Source is in D, we can push B then one word of 0 and we do - a correction on the stack pointer. */ + a correction on the stack pointer. */ if (D_REG_P (src)) { emit_move_insn (m68hc11_gen_lowpart (QImode, push), src); @@ -1097,8 +1135,8 @@ else { emit_move_insn (push, operands[2]); - emit_insn (gen_addhi3 (gen_rtx (REG, HImode, HARD_SP_REGNUM), - gen_rtx (REG, HImode, HARD_SP_REGNUM), + emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM), + gen_rtx_REG (HImode, HARD_SP_REGNUM), const1_rtx)); } } @@ -1106,15 +1144,15 @@ { /* Source is in X or Y. It's better to push the 16-bit register and then to some stack adjustment. */ - src = gen_rtx (REG, HImode, REGNO (src)); + src = gen_rtx_REG (HImode, REGNO (src)); emit_move_insn (push, src); emit_move_insn (operands[2], const0_rtx); - emit_insn (gen_addhi3 (gen_rtx (REG, HImode, HARD_SP_REGNUM), - gen_rtx (REG, HImode, HARD_SP_REGNUM), + emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM), + gen_rtx_REG (HImode, HARD_SP_REGNUM), const1_rtx)); emit_move_insn (push, operands[2]); - emit_insn (gen_addhi3 (gen_rtx (REG, HImode, HARD_SP_REGNUM), - gen_rtx (REG, HImode, HARD_SP_REGNUM), + emit_insn (gen_addhi3 (gen_rtx_REG (HImode, HARD_SP_REGNUM), + gen_rtx_REG (HImode, HARD_SP_REGNUM), const1_rtx)); } emit_move_insn (push, operands[2]); @@ -1124,8 +1162,8 @@ }") (define_split - [(set (match_operand:DI 0 "nonimmediate_operand" "=mu") - (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "dmu*B"))) + [(set (match_operand:DI 0 "nonimmediate_operand" "") + (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" ""))) (clobber (match_scratch:HI 2 "=&dB"))] "z_replacement_completed == 2" [(const_int 0)] @@ -1135,16 +1173,16 @@ rtx low2 = m68hc11_gen_lowpart (HImode, low); rtx src = operands[1]; - /* Source operand must be in a hard register. */ + /* Source operand must be in a hard register. */ if (!H_REG_P (src)) { - src = gen_rtx (REG, QImode, REGNO (operands[2])); + src = gen_rtx_REG (QImode, REGNO (operands[2])); emit_move_insn (src, operands[1]); } emit_move_insn (m68hc11_gen_lowpart (QImode, low2), src); emit_move_insn (operands[2], const0_rtx); - src = gen_rtx (REG, QImode, REGNO (operands[2])); + src = gen_rtx_REG (QImode, REGNO (operands[2])); emit_move_insn (m68hc11_gen_highpart (QImode, low2), src); emit_move_insn (m68hc11_gen_highpart (HImode, low), operands[2]); @@ -1163,10 +1201,10 @@ "#") (define_split - [(set (match_operand:DI 0 "non_push_operand" "=m,m,m,!u,!u") + [(set (match_operand:DI 0 "non_push_operand" "") (zero_extend:DI - (match_operand:HI 1 "nonimmediate_operand" "m,dA,!u,dmA,!u"))) - (clobber (match_scratch:HI 2 "=&d,&dB,&dB,&dB,&dB"))] + (match_operand:HI 1 "nonimmediate_operand" ""))) + (clobber (match_scratch:HI 2 ""))] "z_replacement_completed == 2" [(const_int 0)] " @@ -1197,15 +1235,15 @@ [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u") (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du"))) - (clobber (match_scratch:HI 2 "=d,d,&dB,d"))] + (clobber (match_scratch:HI 2 "=d,d,&d,d"))] "" "#") (define_split - [(set (match_operand:DI 0 "nonimmediate_operand" "=m,m,!u,!u") + [(set (match_operand:DI 0 "nonimmediate_operand" "") (zero_extend:DI - (match_operand:SI 1 "nonimmediate_operand" "m,Du,m,Du"))) - (clobber (match_scratch:HI 2 "=d,d,&dB,d"))] + (match_operand:SI 1 "nonimmediate_operand" ""))) + (clobber (match_scratch:HI 2 ""))] "z_replacement_completed == 2" [(const_int 0)] " @@ -1236,10 +1274,10 @@ "#") (define_split - [(set (match_operand:SI 0 "non_push_operand" "=D,mu,m,m,!u,!u") + [(set (match_operand:SI 0 "non_push_operand" "") (zero_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "dAmu,dA,m,!u,m,!u"))) - (clobber (match_scratch:HI 2 "=X,X,&d,&dB,&dB,&dB"))] + (match_operand:HI 1 "nonimmediate_operand" ""))) + (clobber (match_scratch:HI 2 ""))] "reload_completed" [(const_int 0)] " @@ -1257,15 +1295,15 @@ }") (define_insn "zero_extendqisi2" - [(set (match_operand:SI 0 "non_push_operand" "=D,m,u") + [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,m,u") (zero_extend:SI - (match_operand:QI 1 "nonimmediate_operand" "dxymu,dxy,dxy")))] + (match_operand:QI 1 "nonimmediate_operand" "dmu,xy,d,xy,dxy")))] "" "#") (define_split - [(set (match_operand:SI 0 "non_push_operand" "=mu") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dxy")))] + [(set (match_operand:SI 0 "non_push_operand" "") + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] "reload_completed && !X_REG_P (operands[0])" [(set (match_dup 2) (zero_extend:HI (match_dup 1))) (set (match_dup 3) (const_int 0))] @@ -1274,8 +1312,8 @@ operands[3] = m68hc11_gen_highpart (HImode, operands[0]);") (define_split - [(set (match_operand:SI 0 "hard_reg_operand" "=D") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dxymu")))] + [(set (match_operand:SI 0 "hard_reg_operand" "") + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] "z_replacement_completed == 2 && X_REG_P (operands[0])" [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (const_int 0)) @@ -1283,48 +1321,46 @@ " if (X_REG_P (operands[1])) { - emit_insn (gen_swap_areg (gen_rtx (REG, HImode, HARD_D_REGNUM), - gen_rtx (REG, HImode, HARD_X_REGNUM))); - emit_insn (gen_zero_extendqihi2 (gen_rtx (REG, HImode, HARD_D_REGNUM), - gen_rtx (REG, QImode, HARD_D_REGNUM))); - emit_move_insn (gen_rtx (REG, HImode, HARD_X_REGNUM), + emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM), + gen_rtx_REG (HImode, HARD_X_REGNUM))); + emit_insn (gen_zero_extendqihi2 (gen_rtx_REG (HImode, HARD_D_REGNUM), + gen_rtx_REG (QImode, HARD_D_REGNUM))); + emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), const0_rtx); DONE; } - if (reg_mentioned_p (gen_rtx (REG, HImode, HARD_X_REGNUM), operands[1])) + if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[1])) { emit_insn (gen_zero_extendqihi2 (m68hc11_gen_lowpart (HImode, operands[0]), operands[1])); - emit_move_insn (gen_rtx (REG, HImode, HARD_X_REGNUM), const0_rtx); + emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), const0_rtx); DONE; } operands[4] = m68hc11_gen_highpart (HImode, operands[0]); operands[5] = m68hc11_gen_lowpart (HImode, operands[0]); if (A_REG_P (operands[1])) { - operands[2] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); - operands[3] = gen_rtx (REG, HImode, REGNO (operands[1])); - operands[6] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM); + operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM); + operands[3] = gen_rtx_REG (HImode, REGNO (operands[1])); + operands[6] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM); } else { operands[5] = operands[2] = - operands[3] = gen_rtx (REG, HImode, HARD_D_REGNUM); + operands[3] = gen_rtx_REG (HImode, HARD_D_REGNUM); operands[6] = operands[1]; } ") (define_insn "zero_extendqihi2" - [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!u,d,m,!u") + [(set (match_operand:HI 0 "non_push_operand" "=dm,d,*A,!*u,d,m,!*u") (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,*A,d*Am,d,!um,*A,*A")))] "" "* { - rtx ops[2]; - if (A_REG_P (operands[0])) return \"#\"; @@ -1389,7 +1425,6 @@ "" "* { - extern rtx ix_reg; rtx ops[3]; int need_tst = 0; @@ -1400,7 +1435,7 @@ { if (!D_REG_P (operands[1])) { - ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM); + ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM); ops[1] = operands[1]; m68hc11_gen_movqi (insn, ops); } @@ -1417,7 +1452,7 @@ else if (X_REG_P (operands[0])) { /* X can be used as an indexed addressing in the source. - Get the value before clearing it. */ + Get the value before clearing it. */ if (reg_mentioned_p (ix_reg, operands[1])) { output_asm_insn (\"ldab\\t%b1\", operands); @@ -1455,7 +1490,7 @@ if (X_REG_P (operands[0])) output_asm_insn (\"dex\", operands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2])); + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2])); if (!X_REG_P (operands[0])) { @@ -1506,7 +1541,7 @@ { if (!D_REG_P (operands[1])) { - ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM); + ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM); ops[1] = operands[1]; m68hc11_gen_movqi (insn, ops); } @@ -1524,7 +1559,7 @@ output_asm_insn (\"bpl\\t%l0\", ops); output_asm_insn (\"deca\", operands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); } else @@ -1542,7 +1577,7 @@ output_asm_insn (\"bpl\\t%l0\", ops); } output_asm_insn (\"dec\\t%h0\", operands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); } @@ -1556,8 +1591,8 @@ ;; a temporary scratch memory location. ;; (define_split - [(set (match_operand:SI 0 "register_operand" "=D") - (sign_extend:SI (match_operand:HI 1 "register_operand" "A")))] + [(set (match_operand:SI 0 "register_operand" "") + (sign_extend:SI (match_operand:HI 1 "register_operand" "")))] "reload_completed && (Y_REG_P (operands[1]) || Z_REG_P (operands[1]))" [(set (reg:HI D_REGNUM) (match_dup 1)) (set (match_dup 0) (sign_extend:SI (reg:HI D_REGNUM)))] @@ -1569,7 +1604,6 @@ "" "* { - extern rtx ix_reg; rtx ops[2]; int x_reg_used; @@ -1583,12 +1617,12 @@ } else { - /* X can be used as a indexed addressing in the source. - Get the value before clearing it. */ + /* X can be used as an indexed addressing in the source. + Get the value before clearing it. */ x_reg_used = reg_mentioned_p (ix_reg, operands[1]); if (x_reg_used) { - ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM); + ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM); ops[1] = operands[1]; m68hc11_gen_movhi (insn, ops); } @@ -1601,7 +1635,7 @@ Don't use it; keep it for documentation. */ if (!D_REG_P (operands[1]) && !x_reg_used) { - ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM); + ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM); ops[1] = operands[1]; m68hc11_gen_movhi (insn, ops); } @@ -1618,7 +1652,7 @@ } else { - ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM); + ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM); ops[1] = operands[1]; m68hc11_gen_movhi (insn, ops); } @@ -1626,7 +1660,7 @@ ops[0] = gen_label_rtx (); output_asm_insn (\"bpl\\t%l0\", ops); output_asm_insn (\"dex\", operands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); return \"\"; }") @@ -1639,7 +1673,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m") (umin:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") (match_operand:QI 2 "general_operand" "m,d")))] - "TARGET_M6812" + "TARGET_M6812 && TARGET_MIN_MAX" "* { /* Flags are set according to (sub:QI (operand 1) (operand2)). @@ -1661,7 +1695,7 @@ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m") (umax:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") (match_operand:QI 2 "general_operand" "m,d")))] - "TARGET_M6812" + "TARGET_M6812 && TARGET_MIN_MAX" "* { /* Flags are set according to (sub:QI (operand 1) (operand2)). @@ -1683,7 +1717,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m") (umin:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") (match_operand:HI 2 "general_operand" "m,d")))] - "TARGET_M6812" + "TARGET_M6812 && TARGET_MIN_MAX" "* { /* Flags are set according to (sub:HI (operand 1) (operand2)). */ @@ -1702,7 +1736,7 @@ [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m") (umax:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") (match_operand:HI 2 "general_operand" "m,d")))] - "TARGET_M6812" + "TARGET_M6812 && TARGET_MIN_MAX" "* { /* Flags are set according to (sub:HI (operand 1) (operand2)). */ @@ -1736,35 +1770,12 @@ ;; (define_expand "addsi3" [(parallel [(set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_operand:SI 1 "register_operand" "") + (plus:SI (match_operand:SI 1 "general_operand" "") (match_operand:SI 2 "general_operand" ""))) (clobber (match_scratch:HI 3 ""))])] "" "") -;; -;; Translate D = D + D into D = D << 1 -;; We have to do this because adding a register to itself is not possible. -;; -;; Manipulation of A and B registers directly confuses the cse-regs pass -;; so the split must be made after z-replacement register. -;; -(define_split - [(set (match_operand:SI 0 "register_operand" "=D") - (plus:SI (match_dup 0) - (match_dup 0))) - (clobber (match_scratch:HI 1 "=X"))] - "reload_completed && z_replacement_completed == 2" - [(set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1))) - (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM)) - (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))]) - (set (reg:QI B_REGNUM) (rotate:QI (reg:QI B_REGNUM) (reg:QI CC_REGNUM))) - (set (reg:QI A_REGNUM) (rotate:QI (reg:QI A_REGNUM) (reg:QI CC_REGNUM))) - (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM)) - (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])] - "") - - (define_insn "*addsi3_zero_extendhi" [(set (match_operand:SI 0 "register_operand" "=D,D,D,D") (plus:SI (zero_extend:SI @@ -1788,7 +1799,7 @@ } else if (!D_REG_P (operands[1])) { - ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM); + ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM); ops[1] = operands[1]; m68hc11_gen_movhi (insn, ops); } @@ -1797,7 +1808,7 @@ } ops[2] = gen_label_rtx (); - /* ldx preserves the carry, propagate it by incrementing X directly. */ + /* ldx preserves the carry, propagate it by incrementing X directly. */ output_asm_insn (\"addd\\t%0\", ops); if (!X_REG_P (operands[2])) output_asm_insn (\"ldx\\t%1\", ops); @@ -1806,16 +1817,16 @@ output_asm_insn (\"inx\", ops); CC_STATUS_INIT; - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2])); + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2])); return \"\"; }") (define_split /* "*addsi3_zero_extendqi" */ - [(set (match_operand:SI 0 "register_operand" "=D,D") + [(set (match_operand:SI 0 "register_operand" "") (plus:SI (zero_extend:SI - (match_operand:QI 1 "general_operand" "dAmi,!dAmiu")) - (match_operand:SI 2 "memory_operand" "m,m"))) + (match_operand:QI 1 "general_operand" "")) + (match_operand:SI 2 "memory_operand" ""))) (clobber (match_scratch:HI 3 "=X,X"))] "reload_completed" [(set (reg:HI D_REGNUM) (zero_extend:HI (match_dup 1))) @@ -1842,15 +1853,15 @@ { if (H_REG_P (operands[1])) { - ops[0] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); - ops[1] = gen_rtx (REG, HImode, REGNO (operands[1])); + ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM); + ops[1] = gen_rtx_REG (HImode, REGNO (operands[1])); m68hc11_gen_movhi (insn, ops); } else { ops[0] = operands[1]; } - ops[1] = gen_rtx (CONST_INT, VOIDmode, 0); + ops[1] = const0_rtx; } else { @@ -1860,7 +1871,7 @@ } else if (!D_REG_P (operands[1])) { - ops[0] = gen_rtx (REG, QImode, HARD_D_REGNUM); + ops[0] = gen_rtx_REG (QImode, HARD_D_REGNUM); ops[1] = operands[1]; m68hc11_gen_movqi (insn, ops); } @@ -1871,7 +1882,7 @@ output_asm_insn (\"clra\", ops); } - /* ldx preserves the carry, propagate it by incrementing X directly. */ + /* ldx preserves the carry, propagate it by incrementing X directly. */ output_asm_insn (\"addb\\t%b0\", ops); output_asm_insn (\"adca\\t%h1\", ops); if (!X_REG_P (operands[2])) @@ -1888,7 +1899,7 @@ output_asm_insn (\"bcc\\t%l3\", ops); output_asm_insn (\"inx\", ops); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[3])); } CC_STATUS_INIT; @@ -1896,18 +1907,18 @@ }") (define_insn "*addsi3" - [(set (match_operand:SI 0 "non_push_operand" "=m,D,!u,?D,D") + [(set (match_operand:SI 0 "non_push_operand" "=o,D,!u,?D,D") (plus:SI (match_operand:SI 1 "non_push_operand" "%0,0,0,0,0") - (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?miu"))) + (match_operand:SI 2 "general_operand" "ML,i,ML,?D,?oiu"))) (clobber (match_scratch:HI 3 "=d,X,d,X,X"))] "" "* { rtx ops[3]; - char* add_insn; - char* inc_insn; - char* incb_mem; - char* inch_mem; + const char* add_insn; + const char* inc_insn; + const char* incb_mem; + const char* inch_mem; HOST_WIDE_INT val; if (which_alternative > 2) @@ -1951,7 +1962,7 @@ } else { - ops[1] = gen_rtx (CONST_INT, VOIDmode, - val); + ops[1] = GEN_INT (- val); add_insn = \"subd\\t%1\"; inc_insn = \"dex\"; incb_mem = \"dec\\t%b1\"; @@ -1991,17 +2002,17 @@ output_asm_insn (inch_mem, ops); } } - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2])); + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[2])); CC_STATUS_INIT; return \"\"; }") (define_split - [(set (match_operand:SI 0 "register_operand" "=D,u") - (plus:SI (match_operand:SI 1 "register_operand" "%0,0") + [(set (match_operand:SI 0 "register_operand" "") + (plus:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "const_int_operand" ""))) - (clobber (match_scratch:HI 3 "=X,d"))] + (clobber (match_scratch:HI 3 ""))] "reload_completed && z_replacement_completed == 2 && ((INTVAL (operands[2]) & 0x0FFFF) == 0)" [(set (match_dup 5) (match_dup 6)) @@ -2010,7 +2021,7 @@ "operands[4] = m68hc11_gen_highpart (HImode, operands[2]); if (X_REG_P (operands[0])) { - operands[5] = operands[6] = gen_rtx (REG, HImode, HARD_D_REGNUM); + operands[5] = operands[6] = gen_rtx_REG (HImode, HARD_D_REGNUM); } else { @@ -2020,9 +2031,9 @@ ") (define_split - [(set (match_operand:SI 0 "register_operand" "=D") - (plus:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "general_operand" "mui"))) + [(set (match_operand:SI 0 "register_operand" "") + (plus:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "general_operand" ""))) (clobber (match_scratch:HI 3 "=X"))] "reload_completed && z_replacement_completed == 2 && (GET_CODE (operands[2]) != CONST_INT || @@ -2056,7 +2067,7 @@ ops[0] = gen_label_rtx (); output_asm_insn (\"bcc\\t%l0\", ops); output_asm_insn (\"in%0\", operands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); CC_STATUS_INIT; return \"\"; }") @@ -2073,47 +2084,28 @@ { if (TARGET_M6811 && SP_REG_P (operands[0])) { - emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, - gen_rtx (SET, VOIDmode, + emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, + gen_rtx_SET (VOIDmode, operand0, - gen_rtx (PLUS, HImode, + gen_rtx_PLUS (HImode, operand1, operand2)), - gen_rtx (CLOBBER, VOIDmode, - gen_rtx (SCRATCH, HImode))))); + gen_rtx_CLOBBER (VOIDmode, + gen_rtx_SCRATCH (HImode))))); DONE; } }") -(define_split /* "*addhi3_strict_low_part" */ - [(set (strict_low_part (match_operand:QI 0 "register_operand" "+dxy")) - (plus:QI (match_operand:QI 1 "register_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "0 && z_replacement_completed == 2" - [(set (match_dup 0) - (plus:QI (match_dup 1) (match_dup 2)))] - "") - -(define_split /* "*addhi3_strict_low_part" */ - [(set (match_operand:HI 0 "register_operand" "=dA") - (plus:HI (match_operand:HI 1 "register_operand" "%0") - (match_operand:HI 2 "general_operand" ""))) - (clobber (match_scratch:HI 3 ""))] - "0 && z_replacement_completed == 2 && !SP_REG_P (operands[0])" - [(set (match_dup 0) - (plus:HI (match_dup 1) (match_dup 2)))] - "") - (define_insn "*addhi3_68hc12" - [(set (match_operand:HI 0 "register_operand" "=*d,A*w,A*w,A") - (plus:HI (match_operand:HI 1 "register_operand" "%0,0,Aw,0") - (match_operand:HI 2 "general_operand" "imA*wu,id,id,!muA")))] + [(set (match_operand:HI 0 "register_operand" "=d*A,d,xy*A*w,xy*A*w,xy*A") + (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,xy*Aw,0") + (match_operand:HI 2 "general_operand" "i,m*A*wu,id,id,!mu*A")))] "TARGET_M6812" "* { int val; const char* insn_code; - if (which_alternative >= 3) + if (which_alternative >= 4) { if (A_REG_P (operands[2])) { @@ -2154,7 +2146,7 @@ else val = 1000; - if (val != -1 || val != 1 || !rtx_equal_p (operands[0], operands[1])) + if ((val != -1 && val != 1) || !rtx_equal_p (operands[0], operands[1])) { m68hc11_notice_keep_cc (operands[0]); switch (REGNO (operands[0])) @@ -2185,7 +2177,7 @@ } /* For X and Y increment, the flags are not complete. Only the Z flag - is updated. For SP increment, flags are not changed. */ + is updated. For SP increment, flags are not changed. */ if (SP_REG_P (operands[0])) { cc_status = cc_prev_status; @@ -2227,14 +2219,15 @@ { HOST_WIDE_INT val; + if (optimize && Y_REG_P (operands[3]) + && dead_register_here (insn, gen_rtx_REG (HImode, HARD_X_REGNUM))) + operands[3] = gen_rtx_REG (HImode, HARD_X_REGNUM); + if (GET_CODE (operands[2]) == CONST_INT && (val = INTVAL (operands[2])) != 0 && (CONST_OK_FOR_LETTER_P (val, 'P') || (val > 0 && val <= 8))) { - if (optimize && Y_REG_P (operands[3]) - && dead_register_here (insn, gen_rtx (REG, HImode, HARD_X_REGNUM))) - operands[3] = gen_rtx (REG, HImode, HARD_X_REGNUM); while (val > 1 || val < -1) { if (val > 0) @@ -2268,41 +2261,38 @@ return \"\"; } - /* Need to transfer to SP to IY and then to D register. - Register IY is lost, this is specified by the (clobber) statement. */ + /* Need to transfer to SP to X/Y and then to D register. + Register X/Y is lost, this is specified by the (clobber) statement. */ output_asm_insn (\"ts%3\", operands); - output_asm_insn (\"xgd%3\", operands); - output_asm_insn (\"addd\\t%2\", operands); - output_asm_insn (\"xgd%3\", operands); + if (GET_CODE (operands[2]) == CONST_INT + && ((val = INTVAL (operands[2])) >= 0 && val < 0x100) + && dead_register_here (insn, gen_rtx_REG (HImode, HARD_D_REGNUM))) + { + output_asm_insn (\"ldab\\t%2\", operands); + output_asm_insn (\"ab%3\", operands); + CC_STATUS_INIT; + } + else + { + output_asm_insn (\"xgd%3\", operands); + output_asm_insn (\"addd\\t%2\", operands); + output_asm_insn (\"xgd%3\", operands); + } /* The status flags correspond to the addd. xgdy and tys do not modify the flags. */ return \"t%3s\"; }") -;; -;; Translate d = d + d into d = d << 1 -;; We have to do this because adding a register to itself is not possible. -;; ??? It's not clear whether this is really necessary. -;; -(define_split - [(set (match_operand:HI 0 "hard_reg_operand" "=dA") - (plus:HI (match_dup 0) - (match_dup 0)))] - "reload_completed" - [(set (match_dup 0) (ashift:HI (match_dup 0) (const_int 1)))] - "") - (define_insn "*addhi3" - [(set (match_operand:HI 0 "hard_reg_operand" "=A,d,!A,d*A,!d") - (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0") - (match_operand:HI 2 "general_operand" "N,i,I,mi*A*d,!u*d*w")))] + [(set (match_operand:HI 0 "hard_reg_operand" "=A,dA,d,!A,d*A,d,!d*A") + (plus:HI (match_operand:HI 1 "general_operand" "%0,0,0,0,0,0,0") + (match_operand:HI 2 "general_operand" "N,I,i,I,mi*A*d,*u,!u*d*w")))] "TARGET_M6811" "* { const char* insn_code; int val; - extern rtx ix_reg; if (D_REG_P (operands[0]) && SP_REG_P (operands[2])) { @@ -2313,7 +2303,7 @@ if (GET_CODE (operands[2]) != CONST_INT) { /* Adding to an address register or with another/same register - is not possible. This must be replaced. */ + is not possible. This must be replaced. */ if (A_REG_P (operands[0]) || H_REG_P (operands[2])) return \"#\"; @@ -2409,7 +2399,7 @@ ;; ??? It's not clear whether this is really necessary. ;; (define_split - [(set (match_operand:QI 0 "hard_reg_operand" "=dA") + [(set (match_operand:QI 0 "hard_reg_operand" "") (plus:QI (match_dup 0) (match_dup 0)))] "0 && reload_completed" @@ -2417,9 +2407,9 @@ "") (define_insn "addqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=!*rm,dq*A") - (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") - (match_operand:QI 2 "general_operand" "N,ium*A*d")))] + [(set (match_operand:QI 0 "nonimmediate_operand" "=!d*rm,dq,!*A") + (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") + (match_operand:QI 2 "general_operand" "N,ium*A*d,ium*A*d")))] "" "* { @@ -2516,28 +2506,46 @@ "") (define_insn "*subsi3" - [(set (match_operand:SI 0 "register_operand" "=D,D") - (minus:SI (match_operand:SI 1 "general_operand" "0,!mui") - (match_operand:SI 2 "general_operand" "!mui,!D"))) - (clobber (match_scratch:HI 3 "=X,X"))] + [(set (match_operand:SI 0 "register_operand" "=D,D,D,D,!u") + (minus:SI (match_operand:SI 1 "general_operand" "0,oi,0,!u,0") + (match_operand:SI 2 "general_operand" "oi,D,!u,D,!oui"))) + (clobber (match_scratch:HI 3 "=X,X,X,X,d"))] "" "#") (define_insn "*subsi3_zero_extendhi" [(set (match_operand:SI 0 "register_operand" "=D") (minus:SI (match_operand:SI 1 "register_operand" "0") - (zero_extend:SI (match_operand:HI 2 "general_operand" "d!mui")))) + (zero_extend:SI (match_operand:HI 2 "general_operand" "dmui*A")))) (clobber (match_scratch:HI 3 "=X"))] "" "* { rtx ops[2]; + if (A_REG_P (operands[2])) + { + if (TARGET_M6812) + ops[0] = gen_rtx_MEM (HImode, + gen_rtx_PRE_DEC (HImode, + gen_rtx_REG (HImode, HARD_SP_REGNUM))); + else + ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM); + + ops[1] = operands[2]; + m68hc11_gen_movhi (insn, ops); + if (TARGET_M6812) + operands[2] = gen_rtx_MEM (HImode, + gen_rtx_POST_INC (HImode, + gen_rtx_REG (HImode, HARD_SP_REGNUM))); + else + operands[2] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM); + } ops[0] = gen_label_rtx (); output_asm_insn (\"subd\\t%2\", operands); output_asm_insn (\"bcc\\t%l0\", ops); output_asm_insn (\"dex\", ops); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); CC_STATUS_INIT; return \"\"; }") @@ -2545,19 +2553,26 @@ (define_insn "*subsi3_zero_extendqi" [(set (match_operand:SI 0 "register_operand" "=D") (minus:SI (match_operand:SI 1 "register_operand" "0") - (zero_extend:SI (match_operand:QI 2 "general_operand" "!dmui")))) + (zero_extend:SI (match_operand:QI 2 "general_operand" "dmui*A")))) (clobber (match_scratch:HI 3 "=X"))] "" "* { rtx ops[2]; + if (A_REG_P (operands[2])) + { + ops[0] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM); + ops[1] = operands[2]; + m68hc11_gen_movhi (insn, ops); + operands[2] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM); + } ops[0] = gen_label_rtx (); output_asm_insn (\"subb\\t%b2\", operands); output_asm_insn (\"sbca\\t#0\", operands); output_asm_insn (\"bcc\\t%l0\", ops); output_asm_insn (\"dex\", ops); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); CC_STATUS_INIT; return \"\"; }") @@ -2567,9 +2582,9 @@ ;; reg:QI 7 -> ccr reg:QI 5 -> A ;; (define_split /* "*subsi3" */ - [(set (match_operand:SI 0 "register_operand" "=D") - (minus:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "general_operand" "mui"))) + [(set (match_operand:SI 0 "register_operand" "") + (minus:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "general_operand" ""))) (clobber (match_scratch:HI 3 "=X"))] "reload_completed && z_replacement_completed == 2 && X_REG_P (operands[1])" @@ -2586,9 +2601,9 @@ operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);") (define_split /* "*subsi3" */ - [(set (match_operand:SI 0 "register_operand" "=D") - (minus:SI (match_operand:SI 1 "general_operand" "mui") - (match_operand:SI 2 "register_operand" "D"))) + [(set (match_operand:SI 0 "register_operand" "") + (minus:SI (match_operand:SI 1 "general_operand" "") + (match_operand:SI 2 "register_operand" ""))) (clobber (match_scratch:HI 3 "=X"))] "reload_completed && z_replacement_completed == 2 && X_REG_P (operands[2])" @@ -2605,6 +2620,27 @@ operands[5] = m68hc11_gen_highpart (QImode, operands[4]); operands[4] = m68hc11_gen_lowpart (QImode, operands[4]);") +(define_split /* "*subsi3" */ + [(set (match_operand:SI 0 "nonimmediate_operand" "") + (minus:SI (match_operand:SI 1 "general_operand" "") + (match_operand:SI 2 "general_operand" ""))) + (clobber (match_scratch:HI 3 "=d"))] + "reload_completed && z_replacement_completed == 2 + && !X_REG_P (operands[0])" + [(set (match_dup 3) (match_dup 4)) + (set (match_dup 3) (minus:HI (match_dup 3) (match_dup 5))) + (set (match_dup 4) (match_dup 3)) + (set (match_dup 3) (match_dup 6)) + (set (reg:QI 6) (minus:QI (minus:QI (reg:QI 7) (reg:QI 6)) (match_dup 7))) + (set (reg:QI 5) (minus:QI (minus:QI (reg:QI 7) (reg:QI 5)) (match_dup 8))) + (set (match_dup 6) (match_dup 3))] + "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]); + operands[5] = m68hc11_gen_lowpart (HImode, operands[2]); + operands[6] = m68hc11_gen_highpart (HImode, operands[1]); + operands[7] = m68hc11_gen_highpart (HImode, operands[2]); + operands[8] = m68hc11_gen_highpart (QImode, operands[7]); + operands[7] = m68hc11_gen_lowpart (QImode, operands[7]);") + ;; ;; - 16-bit Subtract. ;; @@ -2613,20 +2649,7 @@ (minus:HI (match_operand:HI 1 "register_operand" "0") (match_operand:HI 2 "general_operand" "g")))] "" - " -{ - if (TARGET_M6811 && SP_REG_P (operands[0])) - { - emit_insn (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2, - gen_rtx (SET, VOIDmode, - operand0, - gen_rtx (MINUS, HImode, - operand1, operand2)), - gen_rtx (CLOBBER, VOIDmode, - gen_rtx (SCRATCH, HImode, 0))))); - DONE; - } -}") + "") ;; ;; Subtract from stack. This is better if we provide a pattern. @@ -2657,40 +2680,47 @@ if (D_REG_P (operands[3])) { - output_asm_insn (\"xgdx\", operands); + int save_x; + + save_x = !dead_register_here (insn, ix_reg); + if (save_x) + output_asm_insn (\"xgdx\", operands); output_asm_insn (\"tsx\", operands); output_asm_insn (\"xgdx\", operands); output_asm_insn (\"subd\\t%2\", operands); output_asm_insn (\"xgdx\", operands); /* The status flags correspond to the addd. xgdx/y and tx/ys do not - modify the flags. */ + modify the flags. */ output_asm_insn (\"txs\", operands); - return \"xgdx\"; + if (save_x) + return \"xgdx\"; + else + return \"\"; } /* Need to transfer to SP to X,Y and then to D register. - Register X,Y is lost, this is specified by the (clobber) statement. */ + Register X,Y is lost, this is specified by the (clobber) statement. */ output_asm_insn (\"ts%3\", operands); output_asm_insn (\"xgd%3\", operands); output_asm_insn (\"subd\\t%2\", operands); output_asm_insn (\"xgd%3\", operands); /* The status flags correspond to the addd. xgdx/y and tx/ys do not - modify the flags. */ + modify the flags. */ return \"t%3s\"; }") (define_insn "*subhi3" - [(set (match_operand:HI 0 "register_operand" "=d,*A,d*A") - (minus:HI (match_operand:HI 1 "register_operand" "0,0,0") - (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,!u")))] + [(set (match_operand:HI 0 "register_operand" "=d,*A,d,*A") + (minus:HI (match_operand:HI 1 "register_operand" "0,0,0,0") + (match_operand:HI 2 "general_operand" "im*A*d,im*d*A,u,!u")))] "" "* { /* Adding to an address register or with another/same register - is not possible. This must be replaced. */ + is not possible. This must be replaced. */ if (A_REG_P (operands[0]) || H_REG_P (operands[2])) return \"#\"; @@ -2709,7 +2739,7 @@ { rtx ops[2]; - ops[0] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM); + ops[0] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM); ops[1] = operands[2]; m68hc11_gen_movqi (insn, ops); return \"subb\\t%T0\\n\\tsbca\\t#0\"; @@ -2856,7 +2886,7 @@ operands[1] = temp; } - ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM); + ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM); ops[1] = operands[2]; m68hc11_gen_movqi (insn, ops); @@ -2871,12 +2901,15 @@ }") (define_insn "mulqi3" - [(set (match_operand:QI 0 "register_operand" "=d") - (mult:QI (match_operand:QI 1 "nonimmediate_operand" "dum") - (match_operand:QI 2 "nonimmediate_operand" "dum")))] + [(set (match_operand:QI 0 "register_operand" "=d,*x,*y") + (mult:QI (match_operand:QI 1 "nonimmediate_operand" "%dum,0,0") + (match_operand:QI 2 "general_operand" "dium,*xium,*yium")))] "" "* { + if (A_REG_P (operands[0])) + return \"#\"; + if (D_REG_P (operands[1]) && D_REG_P (operands[2])) { output_asm_insn (\"tba\", operands); @@ -2902,6 +2935,28 @@ return \"mul\"; }") +(define_split + [(set (match_operand:QI 0 "hard_addr_reg_operand" "") + (mult:QI (match_operand:QI 1 "general_operand" "") + (match_operand:QI 2 "general_operand" "")))] + "z_replacement_completed == 2" + [(parallel [(set (reg:HI D_REGNUM) (match_dup 3)) + (set (match_dup 3) (reg:HI D_REGNUM))]) + (set (reg:QI D_REGNUM) (mult:QI (match_dup 5) (match_dup 6))) + (parallel [(set (reg:HI D_REGNUM) (match_dup 3)) + (set (match_dup 3) (reg:HI D_REGNUM))])] + " + operands[3] = gen_rtx_REG (HImode, REGNO (operands[0])); + if (A_REG_P (operands[1])) + operands[5] = gen_rtx_REG (QImode, HARD_D_REGNUM); + else + operands[5] = operands[1]; + if (A_REG_P (operands[2])) + operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM); + else + operands[6] = operands[2]; + ") + (define_insn "mulqihi3" [(set (match_operand:HI 0 "register_operand" "=d,d") (mult:HI (sign_extend:HI @@ -2928,7 +2983,7 @@ { rtx ops[2]; - ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM); + ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM); ops[1] = operands[2]; m68hc11_gen_movqi (insn, ops); } @@ -3005,147 +3060,259 @@ ;;- and instructions. ;;-------------------------------------------------------------------- -(define_insn "anddi3" +(define_insn_and_split "anddi3" [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u") (and:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu") (match_operand:DI 2 "general_operand" "imu,imu"))) (clobber (match_scratch:HI 3 "=d,d"))] "" - "#") + "#" + "reload_completed" + [(const_int 0)] + "m68hc11_split_logical (SImode, AND, operands); + DONE;") -(define_insn "andsi3" - [(set (match_operand:SI 0 "register_operand" "=D") - (and:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "general_operand" "Dimu")))] +(define_insn_and_split "andsi3" + [(set (match_operand:SI 0 "register_operand" "=D,!u") + (and:SI (match_operand:SI 1 "register_operand" "%0,0") + (match_operand:SI 2 "general_operand" "Dimu,imu"))) + (clobber (match_scratch:HI 3 "=X,d"))] "" - "#") + "#" + "reload_completed" + [(const_int 0)] + "m68hc11_split_logical (HImode, AND, operands); + DONE;") -(define_insn "andhi3" - [(set (match_operand:HI 0 "register_operand" "=d,!u,d,!*A") - (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0") - (match_operand:HI 2 "general_operand" "i,i,!um*A,!ium*A")))] +(define_expand "andhi3" + [(set (match_operand:HI 0 "register_operand" "") + (and:HI (match_operand:HI 1 "register_operand" "") + (match_operand:HI 2 "general_operand" "")))] "" + "") + +(define_insn "*andhi3_mem" + [(set (match_operand:HI 0 "memory_operand" "=R,Q") + (and:HI (match_dup 0) + (match_operand:HI 1 "immediate_operand" "i,i"))) + (clobber (match_scratch:HI 2 "=X,xy"))] + "TARGET_RELAX && !TARGET_M6812" "* { - if (A_REG_P (operands[0]) || H_REG_P (operands[2])) - return \"#\"; + int val = INTVAL (operands[1]) & 0x0FFFF; - if (GET_CODE (operands[2]) == CONST_INT) + if (val == 0x0ffff) { - int val = INTVAL (operands[2]) & 0x0FFFF; - char lowpart_zero = 0; - char lowpart_unknown = 0; - char highpart_zero = 0; - char highpart_unknown = 0; + cc_status = cc_prev_status; + return \"\"; + } - if (val == 0xFFFF) - { - cc_status = cc_prev_status; - return \"\"; - } + CC_STATUS_INIT; - /* First, try to clear the low and high part. - If that's possible, the second 'and' will give - the good status flags and we can avoid a tsthi. */ - if ((val & 0x0FF) == 0) - { - if (D_REG_P (operands[0])) - output_asm_insn (\"clrb\", operands); - else - output_asm_insn (\"clr\\t%b0\", operands); - lowpart_zero = 1; - } - if ((val & 0x0FF00) == 0) - { - if (D_REG_P (operands[0])) - output_asm_insn (\"clra\", operands); - else - output_asm_insn (\"clr\\t%h0\", operands); - highpart_zero = 1; - } + /* The bclr instruction uses an inverted mask. */ + operands[1] = GEN_INT ((~val) & 0x0FFFF); - if ((val & 0x0FF) == 0x0FF) - { - lowpart_unknown = 1; - } - else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0])) - { - rtx ops[2]; + /* When destination is a global variable, generate a .relax instruction + and load the address in the clobber register. That load can be + eliminated by the linker if the address is in page0. */ + if (which_alternative == 1) + { + rtx ops[3]; - ops[0] = operands[0]; - ops[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF); - output_asm_insn (\"bclr\\t%b0, %1\", ops); - } - else if ((val & 0x0FF) != 0) - { - output_asm_insn (\"andb\\t%b2\", operands); - } + ops[0] = operands[2]; + ops[1] = XEXP (operands[0], 0); + ops[2] = gen_label_rtx (); + output_asm_insn (\".relax\\t%l2\", ops); + m68hc11_gen_movhi (insn, ops); + if ((val & 0x0FF) != 0x0FF) + output_asm_insn (\"bclr\\t1,%2, %b1\", operands); - if ((val & 0x0FF00) == 0x0FF00) - { - highpart_unknown = 1; - } - else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0])) - { - rtx ops[2]; + if ((val & 0x0FF00) != 0x0FF00) + output_asm_insn (\"bclr\\t0,%2, %h1\", operands); - ops[0] = operands[0]; - ops[1] = gen_rtx (CONST_INT, VOIDmode, ((~val) & 0x0FF00) >> 8); - output_asm_insn (\"bclr\\t%h0, %1\", ops); - } - else if ((val & 0x0FF00) != 0) - { - output_asm_insn (\"anda\\t%h2\", operands); - } + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", + CODE_LABEL_NUMBER (ops[2])); + return \"\"; + } + + if ((val & 0x0FF) != 0x0FF) + output_asm_insn (\"bclr\\t%b0, %b1\", operands); + + if ((val & 0x0FF00) != 0x0FF00) + output_asm_insn (\"bclr\\t%h0, %h1\", operands); - if (highpart_unknown || lowpart_unknown) - CC_STATUS_INIT; - else if (highpart_zero == 0 && lowpart_zero == 0) - CC_STATUS_INIT; + return \"\"; +}") +(define_insn "*andhi3_const" + [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A") + (and:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0") + (match_operand:HI 2 "const_int_operand" "")))] + "" + "* +{ + int val = INTVAL (operands[2]) & 0x0FFFF; + int lowpart_zero = 0; + int highpart_zero = 0; + int lowpart_unknown = 0; + int highpart_unknown = 0; + + if (A_REG_P (operands[0]) || H_REG_P (operands[2])) + return \"#\"; + + if (val == 0x0ffff) + { + cc_status = cc_prev_status; return \"\"; } + /* First, try to clear the low and high part. + If that's possible, the second 'and' will give + the good status flags and we can avoid a tsthi. */ + if ((val & 0x0FF) == 0) + { + if (D_REG_P (operands[0])) + output_asm_insn (\"clrb\", operands); + else + output_asm_insn (\"clr\\t%b0\", operands); + lowpart_zero = 1; + } + if ((val & 0x0FF00) == 0) + { + if (D_REG_P (operands[0])) + output_asm_insn (\"clra\", operands); + else + output_asm_insn (\"clr\\t%h0\", operands); + highpart_zero = 1; + } + + if ((val & 0x0FF) == 0x0FF) + { + lowpart_unknown = 1; + } + else if ((val & 0x0FF) != 0 && !H_REG_P (operands[0])) + { + rtx ops[2]; + + ops[0] = operands[0]; + ops[1] = GEN_INT ((~val) & 0x0FF); + output_asm_insn (\"bclr\\t%b0, %1\", ops); + } + else if ((val & 0x0FF) != 0) + { + output_asm_insn (\"andb\\t%b2\", operands); + } + + if ((val & 0x0FF00) == 0x0FF00) + { + highpart_unknown = 1; + } + else if (((val & 0x0FF00) != 0) && !H_REG_P (operands[0])) + { + rtx ops[2]; + + ops[0] = operands[0]; + ops[1] = GEN_INT (((~val) & 0x0FF00) >> 8); + output_asm_insn (\"bclr\\t%h0, %1\", ops); + } + else if ((val & 0x0FF00) != 0) + { + output_asm_insn (\"anda\\t%h2\", operands); + } + + if (highpart_unknown || lowpart_unknown) + CC_STATUS_INIT; + else if (highpart_zero == 0 && lowpart_zero == 0) + CC_STATUS_INIT; + + return \"\"; +}") + +(define_insn "*andhi3_gen" + [(set (match_operand:HI 0 "register_operand" "=d,d,!*A") + (and:HI (match_operand:HI 1 "splitable_operand" "%0,0,0") + (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))] + "" + "* +{ + if (A_REG_P (operands[0]) || H_REG_P (operands[2])) + return \"#\"; + CC_STATUS_INIT; - return \"andb\\t%b2\\n\\tanda\\t%h2\"; + return \"anda\\t%h2\\n\\tandb\\t%b2\"; }") -(define_insn "andqi3" - [(set (match_operand:QI 0 "register_operand" "=d,!u,d,d,?*A,?*A,!*q") - (and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0,0") - (match_operand:QI 2 "general_operand" "i,i,!um,?*A,!ium,?*A*d,!ium*A")))] +(define_expand "andqi3" + [(set (match_operand:QI 0 "register_operand" "") + (and:QI (match_operand:QI 1 "register_operand" "") + (match_operand:QI 2 "general_operand" "")))] "" + "") + +(define_insn "*andqi3_mem" + [(set (match_operand:QI 0 "memory_operand" "=R,Q") + (and:QI (match_dup 0) + (match_operand:QI 1 "const_int_operand" "i,i"))) + (clobber (match_scratch:HI 2 "=X,xy"))] + "TARGET_RELAX && !TARGET_M6812" "* { + int val = INTVAL (operands[1]) & 0x0FF; + + if (val == 0x0ff) + { + cc_status = cc_prev_status; + return \"\"; + } + + /* The bclr instruction uses an inverted mask. */ + operands[1] = GEN_INT ((~val) & 0x0FF); + + /* When destination is a global variable, generate a .relax instruction + and load the address in the clobber register. That load can be + eliminated by the linker if the address is in page0. */ + if (which_alternative == 1) + { + rtx ops[3]; + + ops[0] = operands[2]; + ops[1] = XEXP (operands[0], 0); + ops[2] = gen_label_rtx (); + output_asm_insn (\".relax\\t%l2\", ops); + m68hc11_gen_movhi (insn, ops); + output_asm_insn (\"bclr\\t0,%2, %1\", operands); + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", + CODE_LABEL_NUMBER (ops[2])); + return \"\"; + } + return \"bclr\\t%b0, %1\"; +}") + +(define_insn "*andqi3_const" + [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q") + (and:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0") + (match_operand:QI 2 "const_int_operand" "")))] + "" + "* +{ + int val = INTVAL (operands[2]) & 0x0FF; + if (A_REG_P (operands[0]) || H_REG_P (operands[2])) return \"#\"; - if (GET_CODE (operands[2]) == CONST_INT) + if (val == 0x0ff) { - int val = INTVAL (operands[2]) & 0x0FF; + cc_status = cc_prev_status; + return \"\"; + } + if (!H_REG_P (operands[0])) + { + rtx ops[2]; - if (val == 0xFF) - { - cc_status = cc_prev_status; - return \"\"; - } - if (val == 0) - { - if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) - return \"clrb\"; - else if (DA_REG_P (operands[0])) - return \"clra\"; - else - return \"clr\\t%b0\"; - } - if (!H_REG_P (operands[0])) - { - rtx ops[2]; - ops[0] = operands[0]; - ops[1] = gen_rtx (CONST_INT, VOIDmode, (~val) & 0x0FF); - output_asm_insn (\"bclr\\t%b0, %b1\", ops); - return \"\"; - } + ops[0] = operands[0]; + ops[1] = GEN_INT ((~val) & 0x0FF); + output_asm_insn (\"bclr\\t%b0, %b1\", ops); + return \"\"; } if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) return \"andb\\t%b2\"; @@ -3155,92 +3322,216 @@ fatal_insn (\"Invalid operand in the instruction\", insn); }") +(define_insn "*andqi3_gen" + [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q") + (and:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0") + (match_operand:QI 2 "general_operand" "mi,!u,?*A,!um,?*A*d,!um*A")))] + "" + "* +{ + if (A_REG_P (operands[0]) || H_REG_P (operands[2])) + return \"#\"; + + if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) + return \"andb\\t%b2\"; + else if (DA_REG_P (operands[0])) + return \"anda\\t%b2\"; + else + fatal_insn (\"Invalid operand in the instruction\", insn); +}") + ;;-------------------------------------------------------------------- ;;- Bit set or instructions. ;;-------------------------------------------------------------------- -(define_insn "iordi3" +(define_insn_and_split "iordi3" [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u") (ior:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu") (match_operand:DI 2 "general_operand" "imu,imu"))) (clobber (match_scratch:HI 3 "=d,d"))] "" - "#") + "#" + "reload_completed" + [(const_int 0)] + "m68hc11_split_logical (SImode, IOR, operands); + DONE;") -(define_insn "iorsi3" - [(set (match_operand:SI 0 "register_operand" "=D") - (ior:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "general_operand" "Dimu")))] +(define_insn_and_split "iorsi3" + [(set (match_operand:SI 0 "register_operand" "=D,!u") + (ior:SI (match_operand:SI 1 "register_operand" "%0,0") + (match_operand:SI 2 "general_operand" "Dimu,imu"))) + (clobber (match_scratch:HI 3 "=X,d"))] "" - "#") + "#" + "reload_completed" + [(const_int 0)] + "m68hc11_split_logical (HImode, IOR, operands); + DONE;") -(define_insn "iorhi3" - [(set (match_operand:HI 0 "register_operand" "=d,!u,d,!*A") - (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0") - (match_operand:HI 2 "general_operand" "i,i,!um*A,!ium*A")))] +(define_expand "iorhi3" + [(set (match_operand:HI 0 "register_operand" "") + (ior:HI (match_operand:HI 1 "register_operand" "") + (match_operand:HI 2 "splitable_operand" "")))] "" + "") + +(define_insn "*iorhi3_mem" + [(set (match_operand:HI 0 "memory_operand" "=R,Q") + (ior:HI (match_dup 0) + (match_operand:HI 1 "const_int_operand" ""))) + (clobber (match_scratch:HI 2 "=X,xy"))] + "TARGET_RELAX && !TARGET_M6812" "* { - if (A_REG_P (operands[0]) || H_REG_P (operands[2])) - return \"#\"; + int val = INTVAL (operands[1]) & 0x0FFFF; - if (GET_CODE (operands[2]) == CONST_INT) + if (val == 0) { - int val = INTVAL (operands[2]) & 0x0FFFF; + cc_status = cc_prev_status; + return \"\"; + } + CC_STATUS_INIT; + if (which_alternative == 1) + { + rtx ops[3]; - if (val == 0) - { - cc_status = cc_prev_status; - return \"\"; - } + ops[0] = operands[2]; + ops[1] = XEXP (operands[0], 0); + ops[2] = gen_label_rtx (); + output_asm_insn (\".relax\\t%l2\", ops); + m68hc11_gen_movhi (insn, ops); if ((val & 0x0FF) != 0) - { - if (!H_REG_P (operands[0])) - output_asm_insn (\"bset\\t%b0, %b2\", operands); - else - output_asm_insn (\"orab\\t%b2\", operands); - } + output_asm_insn (\"bset\\t1,%2, %b1\", operands); if ((val & 0x0FF00) != 0) - { - if (!H_REG_P (operands[0])) - output_asm_insn (\"bset\\t%h0, %h2\", operands); - else - output_asm_insn (\"oraa\\t%h2\", operands); - } + output_asm_insn (\"bset\\t0,%2, %h1\", operands); + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", + CODE_LABEL_NUMBER (ops[2])); + return \"\"; + } - CC_STATUS_INIT; + if ((val & 0x0FF) != 0) + output_asm_insn (\"bset\\t%b0, %b1\", operands); + + if ((val & 0x0FF00) != 0) + output_asm_insn (\"bset\\t%h0, %h1\", operands); + + return \"\"; +}") + +(define_insn "*iorhi3_const" + [(set (match_operand:HI 0 "reg_or_some_mem_operand" "=R,d,?*A") + (ior:HI (match_operand:HI 1 "reg_or_some_mem_operand" "%0,0,0") + (match_operand:HI 2 "const_int_operand" "")))] + "" + "* +{ + int val = INTVAL (operands[2]) & 0x0FFFF; + + if (A_REG_P (operands[0]) || H_REG_P (operands[2])) + return \"#\"; + + if (val == 0) + { + cc_status = cc_prev_status; return \"\"; } + if ((val & 0x0FF) != 0) + { + if (!H_REG_P (operands[0])) + output_asm_insn (\"bset\\t%b0, %b2\", operands); + else + output_asm_insn (\"orab\\t%b2\", operands); + } + + if ((val & 0x0FF00) != 0) + { + if (!H_REG_P (operands[0])) + output_asm_insn (\"bset\\t%h0, %h2\", operands); + else + output_asm_insn (\"oraa\\t%h2\", operands); + } + CC_STATUS_INIT; - return \"orab\\t%b2\\n\\toraa\\t%h2\"; + return \"\"; }") -(define_insn "iorqi3" - [(set (match_operand:QI 0 "register_operand" "=d,!u,d,d,?*A,?*A,!*q") - (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0,0") - (match_operand:QI 2 "general_operand" "i,i,!um,!*A,!ium,?*A*d,!ium*A")))] +(define_insn "*iorhi3_gen" + [(set (match_operand:HI 0 "register_operand" "=d,d,!*A") + (ior:HI (match_operand:HI 1 "splitable_operand" "%0,0,0") + (match_operand:HI 2 "splitable_operand" "mi,!u*A,!um*Ai")))] "" "* { if (A_REG_P (operands[0]) || H_REG_P (operands[2])) return \"#\"; - if (GET_CODE (operands[2]) == CONST_INT) + CC_STATUS_INIT; + return \"oraa\\t%h2\\n\\torab\\t%b2\"; +}") + +(define_expand "iorqi3" + [(set (match_operand:QI 0 "register_operand" "") + (ior:QI (match_operand:QI 1 "register_operand" "") + (match_operand:QI 2 "general_operand" "")))] + "" + "") + +(define_insn "*iorqi3_mem" + [(set (match_operand:QI 0 "memory_operand" "=R,Q") + (ior:QI (match_dup 0) + (match_operand:QI 1 "const_int_operand" ""))) + (clobber (match_scratch:HI 2 "=X,xy"))] + "TARGET_RELAX && !TARGET_M6812" + "* +{ + int val = INTVAL (operands[1]) & 0x0FF; + + if (val == 0) { - int val = INTVAL (operands[2]) & 0x0FF; + cc_status = cc_prev_status; + return \"\"; + } + if (which_alternative == 1) + { + rtx ops[3]; - if (val == 0) - { - cc_status = cc_prev_status; - return \"\"; - } - if (!H_REG_P (operands[0])) - { - return \"bset\\t%b0, %2\"; - } + ops[0] = operands[2]; + ops[1] = XEXP (operands[0], 0); + ops[2] = gen_label_rtx (); + output_asm_insn (\".relax\\t%l2\", ops); + m68hc11_gen_movhi (insn, ops); + output_asm_insn (\"bset\\t0,%2, %1\", operands); + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", + CODE_LABEL_NUMBER (ops[2])); + return \"\"; + } + return \"bset\\t%b0, %1\"; +}") + +(define_insn "*iorqi3_const" + [(set (match_operand:QI 0 "reg_or_some_mem_operand" "=R,d,?*A*q") + (ior:QI (match_operand:QI 1 "reg_or_some_mem_operand" "%0,0,0") + (match_operand:QI 2 "const_int_operand" "")))] + "" + "* +{ + int val = INTVAL (operands[2]) & 0x0FF; + + if (A_REG_P (operands[0]) || H_REG_P (operands[2])) + return \"#\"; + + if (val == 0) + { + cc_status = cc_prev_status; + return \"\"; + } + if (!H_REG_P (operands[0])) + { + return \"bset\\t%b0, %2\"; } + if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) return \"orab\\t%b2\"; else if (DA_REG_P (operands[0])) @@ -3249,29 +3540,57 @@ fatal_insn (\"Invalid operand in the instruction\", insn); }") +(define_insn "*iorqi3_gen" + [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q") + (ior:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0") + (match_operand:QI 2 "general_operand" "mi,!u,!*A,!um,?*A*d,!um*A")))] + "" + "* +{ + if (A_REG_P (operands[0]) || H_REG_P (operands[2])) + return \"#\"; + + if (D_REG_P (operands[0]) || DB_REG_P (operands[0])) + return \"orab\\t%b2\"; + else if (DA_REG_P (operands[0])) + return \"oraa\\t%b2\"; + else + fatal_insn (\"Invalid operand in the instruction\", insn); +}") + + ;;-------------------------------------------------------------------- ;;- xor instructions. ;;-------------------------------------------------------------------- -(define_insn "xordi3" +(define_insn_and_split "xordi3" [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=m,u") (xor:DI (match_operand:DI 1 "reg_or_some_mem_operand" "%imu,imu") (match_operand:DI 2 "general_operand" "imu,imu"))) (clobber (match_scratch:HI 3 "=d,d"))] "" - "#") + "#" + "reload_completed" + [(const_int 0)] + "m68hc11_split_logical (SImode, XOR, operands); + DONE;") -(define_insn "xorsi3" - [(set (match_operand:SI 0 "register_operand" "=D") - (xor:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "general_operand" "Dimu")))] +(define_insn_and_split "xorsi3" + [(set (match_operand:SI 0 "register_operand" "=D,!u") + (xor:SI (match_operand:SI 1 "register_operand" "%0,0") + (match_operand:SI 2 "general_operand" "Dimu,imu"))) + (clobber (match_scratch:HI 3 "=X,d"))] "" - "#") + "#" + "reload_completed" + [(const_int 0)] + "m68hc11_split_logical (HImode, XOR, operands); + DONE;") (define_insn "xorhi3" [(set (match_operand:HI 0 "register_operand" "=d,d,!*A") - (xor:HI (match_operand:HI 1 "register_operand" "%0,0,0") - (match_operand:HI 2 "general_operand" "im,!u*A,!ium*A")))] + (xor:HI (match_operand:HI 1 "splitable_operand" "%0,0,0") + (match_operand:HI 2 "splitable_operand" "im,!u*A,!ium*A")))] "" "* { @@ -3310,13 +3629,13 @@ } CC_STATUS_INIT; - return \"eorb\\t%b2\\n\\teora\\t%h2\"; + return \"eora\\t%h2\\n\\teorb\\t%b2\"; }") (define_insn "xorqi3" [(set (match_operand:QI 0 "register_operand" "=d,d,d,?*A,?*A,!*q") (xor:QI (match_operand:QI 1 "register_operand" "%0,0,0,0,0,0") - (match_operand:QI 2 "general_operand" "i,!um,!*A,!ium,?*A*d,!ium*A")))] + (match_operand:QI 2 "general_operand" "im,!u,!*A,!ium,?*A*d,!ium*A")))] "" "* { @@ -3352,30 +3671,47 @@ ;;- Bit set or instructions. ;;-------------------------------------------------------------------- -(define_insn "*logicalsi3_zexthi" - [(set (match_operand:SI 0 "register_operand" "=D,D") +(define_insn_and_split "*logicalsi3_zexthi" + [(set (match_operand:SI 0 "register_operand" "=D") (match_operator:SI 3 "m68hc11_logical_operator" [(zero_extend:SI - (match_operand:HI 1 "general_operand" "imdA,!udimA")) - (match_operand:SI 2 "general_operand" "Dimu,!Dimu")]))] + (match_operand:HI 1 "general_operand" "imudA")) + (match_operand:SI 2 "general_operand" "Dimu")]))] "" - "#") + "#" + "reload_completed" + [(set (reg:HI D_REGNUM) (match_dup 4)) + (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)])) + (set (reg:HI X_REGNUM) (match_dup 6))] + "PUT_MODE (operands[3], HImode); + if (X_REG_P (operands[2])) + { + operands[5] = operands[1]; + /* Make all the (set (REG:x) (REG:y)) a nop set. */ + operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM); + operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM); + } + else + { + operands[4] = operands[1]; + operands[5] = m68hc11_gen_lowpart (HImode, operands[2]); + operands[6] = m68hc11_gen_highpart (HImode, operands[2]); + } + /* For an AND, make sure the high 16-bit part is cleared. */ + if (GET_CODE (operands[3]) == AND) + { + operands[6] = const0_rtx; + } + ") -(define_insn "*logicalsi3_zextqi" +(define_insn_and_split "*logicalsi3_zextqi" [(set (match_operand:SI 0 "register_operand" "=D,D,D") (match_operator:SI 3 "m68hc11_logical_operator" [(zero_extend:SI (match_operand:QI 1 "general_operand" "d,*A,imu")) (match_operand:SI 2 "general_operand" "imu,imu,0")]))] "" - "#") - -(define_split - [(set (match_operand:SI 0 "register_operand" "=D,D") - (match_operator:SI 3 "m68hc11_logical_operator" - [(zero_extend:SI - (match_operand:QI 1 "general_operand" "dxy,imu")) - (match_operand:SI 2 "general_operand" "imuD,imuD")]))] + "#" "z_replacement_completed == 2" [(set (reg:QI A_REGNUM) (match_dup 4)) (set (reg:QI D_REGNUM) (match_dup 7)) @@ -3386,9 +3722,9 @@ { operands[5] = operands[1]; /* Make all the (set (REG:x) (REG:y)) a nop set. */ - operands[4] = gen_rtx (REG, QImode, HARD_A_REGNUM); - operands[7] = gen_rtx (REG, QImode, HARD_D_REGNUM); - operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM); + operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM); + operands[7] = gen_rtx_REG (QImode, HARD_D_REGNUM); + operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM); } else { @@ -3397,61 +3733,56 @@ operands[5] = m68hc11_gen_lowpart (QImode, operands[4]); operands[4] = m68hc11_gen_highpart (QImode, operands[4]); operands[6] = m68hc11_gen_highpart (HImode, operands[2]); - } - ") - -(define_split - [(set (match_operand:SI 0 "register_operand" "=D,D") - (match_operator:SI 3 "m68hc11_logical_operator" - [(zero_extend:SI - (match_operand:HI 1 "general_operand" "dA,imu")) - (match_operand:SI 2 "general_operand" "imuD,imuD")]))] - "reload_completed" - [(set (reg:HI D_REGNUM) (match_dup 4)) - (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)])) - (set (reg:HI X_REGNUM) (match_dup 6))] - "PUT_MODE (operands[3], HImode); - if (X_REG_P (operands[2])) - { - operands[5] = operands[1]; - /* Make all the (set (REG:x) (REG:y)) a nop set. */ - operands[4] = gen_rtx (REG, HImode, HARD_D_REGNUM); - operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM); } - else + /* For an AND, make sure the high 24-bit part is cleared. */ + if (GET_CODE (operands[3]) == AND) { - operands[4] = operands[1]; - operands[5] = m68hc11_gen_lowpart (HImode, operands[2]); - operands[6] = m68hc11_gen_highpart (HImode, operands[2]); - } + operands[4] = const0_rtx; + operands[6] = const0_rtx; + } ") -(define_insn "*logicallhi3_zexthi_ashift8" +(define_insn_and_split "*logicalhi3_zexthi_ashift8" [(set (match_operand:HI 0 "register_operand" "=d") (match_operator:HI 3 "m68hc11_logical_operator" [(zero_extend:HI - (match_operand:QI 1 "general_operand" "imud")) + (match_operand:QI 1 "general_operand" "imud*A")) (ashift:HI - (match_operand:HI 2 "general_operand" "dimu") + (match_operand:HI 2 "general_operand" "imud*A") (const_int 8))]))] "" - "#") + "#" + "z_replacement_completed == 2" + [(set (reg:QI A_REGNUM) (match_dup 4)) + (set (reg:QI B_REGNUM) (match_dup 5))] + " + if (GET_CODE (operands[3]) == AND) + { + emit_insn (gen_movhi (operands[0], const0_rtx)); + DONE; + } + else + { + operands[5] = operands[1]; + if (D_REG_P (operands[2])) + { + operands[4] = gen_rtx_REG (QImode, HARD_B_REGNUM); + } + else + { + operands[4] = m68hc11_gen_lowpart (QImode, operands[2]); + } + } + ") -(define_insn "*logicalhi3_zexthi" - [(set (match_operand:HI 0 "register_operand" "=d") +(define_insn_and_split "*logicalhi3_zexthi" + [(set (match_operand:HI 0 "register_operand" "=d,d") (match_operator:HI 3 "m68hc11_logical_operator" [(zero_extend:HI - (match_operand:QI 1 "general_operand" "imud")) - (match_operand:HI 2 "general_operand" "dimu")]))] + (match_operand:QI 1 "general_operand" "imd*A,?u")) + (match_operand:HI 2 "general_operand" "dim,?dimu")]))] "" - "#") - -(define_split - [(set (match_operand:HI 0 "register_operand" "=d") - (match_operator:HI 3 "m68hc11_logical_operator" - [(zero_extend:HI - (match_operand:QI 1 "general_operand" "imud")) - (match_operand:HI 2 "general_operand" "dimu")]))] + "#" "z_replacement_completed == 2" [(set (reg:QI B_REGNUM) (match_dup 6)) (set (reg:QI A_REGNUM) (match_dup 4)) @@ -3460,69 +3791,36 @@ PUT_MODE (operands[3], QImode); if (D_REG_P (operands[2])) { - operands[4] = gen_rtx (REG, QImode, HARD_A_REGNUM); + operands[4] = gen_rtx_REG (QImode, HARD_A_REGNUM); operands[5] = operands[1]; - operands[6] = gen_rtx (REG, QImode, HARD_B_REGNUM); + operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM); } else { operands[4] = m68hc11_gen_highpart (QImode, operands[2]); operands[5] = m68hc11_gen_lowpart (QImode, operands[2]); if (D_REG_P (operands[1])) - operands[6] = gen_rtx (REG, QImode, HARD_B_REGNUM); + operands[6] = gen_rtx_REG (QImode, HARD_B_REGNUM); else operands[6] = operands[1]; } - ") - -(define_split - [(set (match_operand:HI 0 "register_operand" "=d") - (match_operator:HI 3 "m68hc11_logical_operator" - [(zero_extend:HI - (match_operand:QI 1 "general_operand" "imud")) - (ashift:HI - (match_operand:HI 2 "general_operand" "dimu") - (const_int 8))]))] - "z_replacement_completed == 2" - [(set (reg:QI A_REGNUM) (match_dup 4)) - (set (reg:QI B_REGNUM) (match_dup 5))] - " + /* For an AND, make sure the high 8-bit part is cleared. */ if (GET_CODE (operands[3]) == AND) { - emit_insn (gen_movhi (operands[0], const0_rtx)); - DONE; - } - else - { - operands[5] = operands[1]; - if (D_REG_P (operands[2])) - { - operands[4] = gen_rtx (REG, QImode, HARD_B_REGNUM); - } - else - { - operands[4] = m68hc11_gen_lowpart (QImode, operands[2]); - } + operands[4] = const0_rtx; } ") -(define_insn "*logicalsi3_silshr16" - [(set (match_operand:SI 0 "register_operand" "=D,D") + +(define_insn_and_split "*logicalsi3_silshr16" + [(set (match_operand:SI 0 "register_operand" "=D,D,D,?D") (match_operator:SI 3 "m68hc11_logical_operator" [(lshiftrt:SI - (match_operand:SI 1 "general_operand" "uim,?D") + (match_operand:SI 1 "general_operand" "uim,uim,0,0") (const_int 16)) - (match_operand:SI 2 "general_operand" "uim,0")]))] + (match_operand:SI 2 "general_operand" "uim,0,uim,0")]))] "" - "#") - -(define_split - [(set (match_operand:SI 0 "register_operand" "=D,D") - (match_operator:SI 3 "m68hc11_logical_operator" - [(lshiftrt:SI - (match_operand:SI 1 "general_operand" "uim,?D") - (const_int 16)) - (match_operand:SI 2 "general_operand" "uim,0")]))] + "#" "reload_completed" [(set (reg:HI D_REGNUM) (match_dup 4)) (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 5)])) @@ -3530,8 +3828,8 @@ "operands[5] = m68hc11_gen_highpart (HImode, operands[1]); if (X_REG_P (operands[2])) { - operands[4] = gen_rtx (REG, HImode, HARD_D_REGNUM); - operands[6] = gen_rtx (REG, HImode, HARD_X_REGNUM); + operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM); + operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM); } else { @@ -3540,9 +3838,14 @@ } PUT_MODE (operands[3], HImode); + /* For an AND, make sure the high 16-bit part is cleared. */ + if (GET_CODE (operands[3]) == AND) + { + operands[6] = const0_rtx; + } ") -(define_insn "*logicalsi3_silshl16" +(define_insn_and_split "*logicalsi3_silshl16" [(set (match_operand:SI 0 "register_operand" "=D,D") (match_operator:SI 3 "m68hc11_logical_operator" [(ashift:SI @@ -3550,54 +3853,58 @@ (const_int 16)) (match_operand:SI 2 "general_operand" "0,0")]))] "" - "#") - -(define_split - [(set (match_operand:SI 0 "register_operand" "=D,D") - (match_operator:SI 3 "m68hc11_logical_operator" - [(ashift:SI - (match_operand:SI 1 "general_operand" "uim,?D") - (const_int 16)) - (match_operand:SI 2 "general_operand" "0,0")]))] + "#" "z_replacement_completed == 2" - [(parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM)) - (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))]) - (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 4)])) - (parallel [(set (reg:HI D_REGNUM) (reg:HI X_REGNUM)) - (set (reg:HI X_REGNUM) (reg:HI D_REGNUM))])] + [(set (reg:HI X_REGNUM) (match_op_dup 3 [(reg:HI X_REGNUM) (match_dup 4)])) + (set (reg:HI D_REGNUM) (match_dup 5))] "operands[4] = m68hc11_gen_lowpart (HImode, operands[1]); - PUT_MODE (operands[3], HImode);") - + PUT_MODE (operands[3], HImode); -;;-------------------------------------------------------------------- -;;- 64/32-bit Logical Operations. Patterns are defined so that GCC -;; can optimize correctly. These insns are split by the `final' -;; pass (# pattern). They are split to fall in the corresponding -;; 16-bit logical patterns. -;;-------------------------------------------------------------------- + if (GET_CODE (operands[3]) == AND) + operands[5] = const0_rtx; + else + operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM); + ") -;; Split 64-bit logical operations (AND, OR, XOR). -(define_split - [(set (match_operand:DI 0 "reg_or_some_mem_operand" "=mu") - (match_operator:DI 4 "m68hc11_logical_operator" - [(match_operand:DI 1 "reg_or_some_mem_operand" "%imu") - (match_operand:DI 2 "general_operand" "imu")])) - (clobber (match_scratch:HI 3 "=d"))] +(define_insn_and_split "*logicalsi3_silshl16_zext" + [(set (match_operand:SI 0 "register_operand" "=D,D,D") + (match_operator:SI 3 "m68hc11_logical_operator" + [(ashift:SI + (zero_extend:SI + (match_operand:HI 1 "general_operand" "uim,udA,!dA")) + (const_int 16)) + (zero_extend:SI (match_operand:HI 2 "general_operand" "uidA,um,!dA"))]))] + "" + "#" + ;; Must split before z register replacement "reload_completed" - [(const_int 0)] - "m68hc11_split_logical (SImode, GET_CODE (operands[4]), operands); - DONE;") + [(set (match_dup 4) (match_dup 5)) + (set (match_dup 6) (match_dup 7))] + " + /* set (X_REGNUM) (d), set (D_REGNUM) (1) */ + if (GET_CODE (operands[1]) == HARD_D_REGNUM + && GET_CODE (operands[3]) != AND) + { + /* This particular case is too early to be split before + Z register replacement because the cse-reg pass we do + does not recognize the 'swap_areg'. It is ok to handle + this case after. */ + if (z_replacement_completed != 2) + { + FAIL; + } + emit_move_insn (gen_rtx_REG (HImode, HARD_X_REGNUM), operands[2]); + emit_insn (gen_swap_areg (gen_rtx_REG (HImode, HARD_D_REGNUM), + gen_rtx_REG (HImode, HARD_X_REGNUM))); + } + operands[4] = gen_rtx_REG (HImode, HARD_D_REGNUM); + operands[6] = gen_rtx_REG (HImode, HARD_X_REGNUM); + operands[5] = operands[2]; + operands[7] = operands[1]; -;; Split 32-bit logical operations (AND, OR, XOR). -(define_split - [(set (match_operand:SI 0 "register_operand" "=D") - (match_operator:SI 3 "m68hc11_logical_operator" - [(match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "general_operand" "Dimu")]))] - "reload_completed" - [(const_int 0)] - "m68hc11_split_logical (HImode, GET_CODE (operands[3]), operands); - DONE;") + if (GET_CODE (operands[3]) == AND) + operands[5] = operands[7] = const0_rtx; + ") ;;-------------------------------------------------------------------- ;; 16-bit Arithmetic and logical operations on X and Y: @@ -3619,13 +3926,13 @@ ;; ;; (define_split - [(set (match_operand:HI 0 "hard_addr_reg_operand" "=A") + [(set (match_operand:HI 0 "hard_addr_reg_operand" "") (match_operator:HI 3 "m68hc11_arith_operator" - [(match_operand:HI 1 "hard_addr_reg_operand" "0") - (match_operand:HI 2 "general_operand" "dAuim")]))] + [(match_operand:HI 1 "hard_addr_reg_operand" "") + (match_operand:HI 2 "general_operand" "")]))] "z_replacement_completed == 2 /* If we are adding a small constant to X or Y, it's - better to use one or several inx/iny instructions. */ + better to use one or several inx/iny instructions. */ && !(GET_CODE (operands[3]) == PLUS && ((TARGET_M6812 && (immediate_operand (operands[2], HImode) @@ -3633,19 +3940,56 @@ || (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= -4 && INTVAL (operands[2]) <= 4)))" - [(set (match_dup 4) (match_dup 5)) + [(set (match_dup 9) (match_dup 0)) + (set (match_dup 4) (match_dup 5)) (set (match_dup 8) (match_dup 7)) + (set (match_dup 0) (match_dup 1)) (parallel [(set (reg:HI D_REGNUM) (match_dup 0)) (set (match_dup 0) (reg:HI D_REGNUM))]) (set (reg:HI D_REGNUM) (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 6)])) (parallel [(set (reg:HI D_REGNUM) (match_dup 0)) (set (match_dup 0) (reg:HI D_REGNUM))])] " - /* Save the operand2 in a temporary location and use it. */ - if (H_REG_P (operands[2]) - || reg_mentioned_p (operands[0], operands[2])) + operands[9] = operands[0]; + /* For 68HC12, push the value on the stack and do the operation + with a pop. */ + if (TARGET_M6812 + && m68hc11_non_shift_operator (operands[3], HImode) + && (H_REG_P (operands[2]) + || (m68hc11_small_indexed_indirect_p (operands[2], HImode) + && reg_mentioned_p (operands[0], operands[2])))) + { + operands[4] = gen_rtx_MEM (HImode, + gen_rtx_PRE_DEC (HImode, + gen_rtx_REG (HImode, HARD_SP_REGNUM))); + operands[6] = gen_rtx_MEM (HImode, + gen_rtx_POST_INC (HImode, + gen_rtx_REG (HImode, HARD_SP_REGNUM))); + operands[5] = operands[2]; + operands[8] = operands[7] = operands[0]; + } + /* Save the operand2 in a temporary location and use it. */ + else if ((H_REG_P (operands[2]) + || reg_mentioned_p (operands[0], operands[2])) + && !(SP_REG_P (operands[2]) && GET_CODE (operands[3]) == PLUS)) { - operands[4] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); + if (GET_CODE (operands[3]) == MINUS + && reg_mentioned_p (operands[0], operands[2])) + { + operands[9] = gen_rtx_MEM (HImode, + gen_rtx_PRE_DEC (HImode, + gen_rtx_REG (HImode, HARD_SP_REGNUM))); + operands[1] = gen_rtx_MEM (HImode, + gen_rtx_POST_INC (HImode, + gen_rtx_REG (HImode, HARD_SP_REGNUM))); + operands[8] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM); + operands[4] = operands[7] = operands[0]; + operands[6] = operands[8]; + operands[5] = operands[2]; + } + else + { + operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM); operands[6] = operands[4]; if (!H_REG_P (operands[2])) { @@ -3658,6 +4002,7 @@ operands[5] = operands[2]; operands[8] = operands[7] = operands[0]; } + } } else { @@ -3668,13 +4013,13 @@ ") (define_split - [(set (match_operand:HI 0 "hard_addr_reg_operand" "=A") + [(set (match_operand:HI 0 "hard_addr_reg_operand" "") (match_operator:HI 3 "m68hc11_arith_operator" - [(match_operand:HI 1 "general_operand" "mu") - (match_operand:HI 2 "general_operand" "dAuim")]))] + [(match_operand:HI 1 "general_operand" "") + (match_operand:HI 2 "general_operand" "")]))] "z_replacement_completed == 2 /* If we are adding a small constant to X or Y, it's - better to use one or several inx/iny instructions. */ + better to use one or several inx/iny instructions. */ && !(GET_CODE (operands[3]) == PLUS && ((TARGET_M6812 && (immediate_operand (operands[2], HImode) @@ -3701,24 +4046,46 @@ ;; ;; PLUS MINUS AND IOR XOR ;; -;; The shift operators are special and must not appear here. +;; The shift operators are special and must not appear here. +;; +(define_split + [(set (match_operand:HI 0 "d_register_operand" "") + (match_operator:HI 3 "m68hc11_non_shift_operator" + [(match_operand:HI 1 "d_register_operand" "") + (match_operand:HI 2 "hard_reg_operand" "")]))] + "TARGET_M6811 + && z_replacement_completed == 2 && !SP_REG_P (operands[2])" + [(set (match_dup 4) (match_dup 2)) + (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))] + "operands[4] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM);") + +;; +;; For 68HC12, push the operand[2] value on the stack and do the +;; logical/arithmetic operation with a pop. ;; (define_split - [(set (match_operand:HI 0 "d_register_operand" "=d") + [(set (match_operand:HI 0 "d_register_operand" "") (match_operator:HI 3 "m68hc11_non_shift_operator" - [(match_operand:HI 1 "d_register_operand" "%0") - (match_operand:HI 2 "hard_reg_operand" "*d*A")]))] - "z_replacement_completed == 2 && !SP_REG_P (operands[2])" + [(match_operand:HI 1 "d_register_operand" "") + (match_operand:HI 2 "hard_reg_operand" "")]))] + "TARGET_M6812 + && z_replacement_completed == 2 && !SP_REG_P (operands[2])" [(set (match_dup 4) (match_dup 2)) - (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))] - "operands[4] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM);") + (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 5)]))] + "operands[4] = gen_rtx_MEM (HImode, + gen_rtx_PRE_DEC (HImode, + gen_rtx_REG (HImode, HARD_SP_REGNUM))); + operands[5] = gen_rtx_MEM (HImode, + gen_rtx_POST_INC (HImode, + gen_rtx_REG (HImode, HARD_SP_REGNUM))); + ") ;;-------------------------------------------------------------------- ;; 16-bit Unary operations on X and Y: ;; ;; NOT NEG ;; -;; Operations on X or Y registers are split here. Instructions are +;; Operations on X or Y registers are split here. Instructions are ;; changed into: ;; - xgdx/xgdy instruction pattern, ;; - The same operation on register D, @@ -3732,9 +4099,9 @@ ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X))) ;; (define_split - [(set (match_operand:HI 0 "hard_addr_reg_operand" "=A") + [(set (match_operand:HI 0 "hard_addr_reg_operand" "") (match_operator:HI 2 "m68hc11_unary_operator" - [(match_operand 1 "general_operand" "uim*d*A")]))] + [(match_operand 1 "general_operand" "")]))] "z_replacement_completed == 2" [(set (match_dup 4) (match_dup 5)) (parallel [(set (reg:HI D_REGNUM) (match_dup 0)) @@ -3748,17 +4115,17 @@ && !rtx_equal_p (operands[0], operands[1])) || reg_mentioned_p (operands[0], operands[1])) { - /* Move to the destination register, before the xgdx. */ - operands[4] = gen_rtx (REG, GET_MODE (operands[1]), + /* Move to the destination register, before the xgdx. */ + operands[4] = gen_rtx_REG (GET_MODE (operands[1]), REGNO (operands[0])); operands[5] = operands[1]; - /* Apply the operation on D. */ - operands[3] = gen_rtx (REG, GET_MODE (operands[1]), HARD_D_REGNUM); + /* Apply the operation on D. */ + operands[3] = gen_rtx_REG (GET_MODE (operands[1]), HARD_D_REGNUM); } else { - /* Generate a copy to same register (nop). */ + /* Generate a copy to same register (nop). */ operands[4] = operands[5] = operands[0]; operands[3] = operands[1]; } @@ -3774,13 +4141,13 @@ ;; AND OR XOR PLUS MINUS ASHIFT ASHIFTRT LSHIFTRT ROTATE ROTATERT ;; (define_split - [(set (match_operand:QI 0 "hard_addr_reg_operand" "=xy") + [(set (match_operand:QI 0 "hard_addr_reg_operand" "") (match_operator:QI 3 "m68hc11_arith_operator" - [(match_operand:QI 1 "hard_addr_reg_operand" "%0") - (match_operand:QI 2 "general_operand" "dxyuim")]))] + [(match_operand:QI 1 "hard_addr_reg_operand" "") + (match_operand:QI 2 "general_operand" "")]))] "z_replacement_completed == 2 /* Reject a (plus:QI (reg:QI X) (const_int 1|-1)) because the - incqi pattern generates a better code. */ + incqi pattern generates a better code. */ && !(GET_CODE (operands[3]) == PLUS && GET_CODE (operands[2]) == CONST_INT && (INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == -1))" @@ -3790,28 +4157,28 @@ (set (reg:QI D_REGNUM) (match_op_dup 3 [(reg:QI D_REGNUM) (match_dup 7)])) (parallel [(set (reg:HI D_REGNUM) (match_dup 4)) (set (match_dup 4) (reg:HI D_REGNUM))])] - "operands[4] = gen_rtx (REG, HImode, REGNO (operands[0])); + "operands[4] = gen_rtx_REG (HImode, REGNO (operands[0])); /* For the second operand is a hard register or if the address register appears in the source, we have to save the operand[2] value in a temporary location and then use that temp. Otherwise, it's ok and we generate a (set (D) (D)) that - will result in a nop. */ + will result in a nop. */ if (H_REG_P (operands[2])) { - operands[5] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); - operands[6] = gen_rtx (REG, HImode, REGNO (operands[2])); - operands[7] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM); + operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM); + operands[6] = gen_rtx_REG (HImode, REGNO (operands[2])); + operands[7] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM); } else if (reg_mentioned_p (operands[0], operands[2])) { - operands[5] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM); + operands[5] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM); operands[6] = operands[2]; operands[7] = operands[5]; } else { - operands[5] = operands[6] = gen_rtx (REG, QImode, HARD_D_REGNUM); + operands[5] = operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM); operands[7] = operands[2]; } ") @@ -3829,23 +4196,23 @@ ;; The shift operators are special and must not appear here. ;; (define_split - [(set (match_operand:QI 0 "d_register_operand" "=d") + [(set (match_operand:QI 0 "d_register_operand" "") (match_operator:QI 3 "m68hc11_non_shift_operator" - [(match_operand:QI 1 "d_register_operand" "%0") - (match_operand:QI 2 "hard_reg_operand" "*d*x*y")]))] + [(match_operand:QI 1 "d_register_operand" "") + (match_operand:QI 2 "hard_reg_operand" "")]))] "reload_completed" [(set (match_dup 5) (match_dup 6)) (set (match_dup 0) (match_op_dup 3 [(match_dup 0) (match_dup 4)]))] - "operands[4] = gen_rtx (REG, QImode, SOFT_TMP_REGNUM); - operands[5] = gen_rtx (REG, HImode, SOFT_TMP_REGNUM); - operands[6] = gen_rtx (REG, HImode, REGNO (operands[2]));") + "operands[4] = gen_rtx_REG (QImode, SOFT_TMP_REGNUM); + operands[5] = gen_rtx_REG (HImode, SOFT_TMP_REGNUM); + operands[6] = gen_rtx_REG (HImode, REGNO (operands[2]));") ;;-------------------------------------------------------------------- ;; 8-bit Unary operations on X and Y: ;; ;; NOT NEG ;; -;; Operations on X or Y registers are split here. Instructions are +;; Operations on X or Y registers are split here. Instructions are ;; changed into: ;; - xgdx/xgdy instruction pattern, ;; - The same operation on register D, @@ -3859,9 +4226,9 @@ ;; (set (REG:HI X) (PLUS:HI (REG:HI X) (REG:HI X))) ;; (define_split - [(set (match_operand:QI 0 "hard_addr_reg_operand" "=xy") + [(set (match_operand:QI 0 "hard_addr_reg_operand" "") (match_operator:QI 2 "m68hc11_unary_operator" - [(match_operand:QI 1 "general_operand" "uim*d*x*y")]))] + [(match_operand:QI 1 "general_operand" "")]))] "z_replacement_completed == 2" [(set (match_dup 4) (match_dup 5)) (parallel [(set (reg:HI D_REGNUM) (match_dup 3)) @@ -3871,17 +4238,17 @@ (set (match_dup 3) (reg:HI D_REGNUM))])] " { - operands[3] = gen_rtx (REG, HImode, REGNO (operands[0])); + operands[3] = gen_rtx_REG (HImode, REGNO (operands[0])); if ((H_REG_P (operands[1]) && !rtx_equal_p (operands[0], operands[1])) || reg_mentioned_p (operands[0], operands[1])) { - /* Move to the destination register, before the xgdx. */ + /* Move to the destination register, before the xgdx. */ operands[4] = operands[0]; operands[5] = operands[1]; - /* Apply the operation on D. */ - operands[6] = gen_rtx (REG, QImode, HARD_D_REGNUM); + /* Apply the operation on D. */ + operands[6] = gen_rtx_REG (QImode, HARD_D_REGNUM); } else { @@ -3905,26 +4272,31 @@ (define_insn "negsi2" [(set (match_operand:SI 0 "register_operand" "=D") - (neg:SI (match_operand:SI 1 "register_operand" "0")))] + (neg:SI (match_operand:SI 1 "general_operand" "0")))] "" "* { + rtx ops[1]; + CC_STATUS_INIT; /* With -Os or without -O, use a special library call. */ if (optimize_size || optimize == 0) return \"bsr\\t___negsi2\"; - /* 32-bit complement and add 1. The comb/coma set the carry and they - are smaller (use it for low-part). The eorb/eora leave the carry - unchanged but are bigger (use it for high-part). */ - output_asm_insn (\"comb\\n\\tcoma\\n\\taddd\\t#1\\n\\txgdx\", operands); - output_asm_insn (\"eorb\\t#0xFF\\n\\teora\\t#0xFF\", operands); - return \"adcb\\t#0\\n\\tadca\\t#0\\n\\txgdx\"; + ops[0] = gen_label_rtx (); + + /* 32-bit complement and add 1. */ + output_asm_insn (\"comb\\n\\tcoma\\n\\txgdx\", operands); + output_asm_insn (\"comb\\n\\tcoma\\n\\tinx\\n\\txgdx\", operands); + output_asm_insn (\"bne\\t%l0\", ops); + output_asm_insn (\"inx\", operands); + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); + return \"\"; }") (define_insn "neghi2" - [(set (match_operand:HI 0 "register_operand" "=d,d,*A") + [(set (match_operand:HI 0 "register_operand" "=d,d,x*y") (neg:HI (match_operand:HI 1 "general_operand" "0,!duim,0")))] "" "@ @@ -3954,57 +4326,62 @@ DONE;") (define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "non_push_operand" "=D") - (not:SI (match_operand:SI 1 "general_operand" "0")))] + [(set (match_operand:SI 0 "non_push_operand" "=D,m,!u") + (not:SI (match_operand:SI 1 "general_operand" "0,m,0"))) + (clobber (match_scratch:HI 2 "=X,d,X"))] "" - "bsr\\t___one_cmplsi2") + "@ + bsr\\t___one_cmplsi2 + # + #") (define_insn "one_cmplhi2" - [(set (match_operand:HI 0 "non_push_operand" "=d,m,!u,*A") + [(set (match_operand:HI 0 "non_push_operand" "=d,m,*A,u") (not:HI (match_operand:HI 1 "general_operand" "0,0,0,0")))] "" "@ comb\\n\\tcoma com\\t%b0\\n\\tcom\\t%h0 - com\\t%b0\\n\\tcom\\t%h0 - #") + # + com\\t%b0\\n\\tcom\\t%h0") (define_insn "one_cmplqi2" - [(set (match_operand:QI 0 "non_push_operand" "=d,m,!u,!*A") + [(set (match_operand:QI 0 "non_push_operand" "=d,m,*A,u") (not:QI (match_operand:QI 1 "general_operand" "0,0,0,0")))] "" "@ comb com\\t%b0 - com\\t%b0 - #") + # + com\\t%b0") (define_split /* "*one_cmplsi2" */ - [(set (match_operand:SI 0 "non_push_operand" "=Dum") - (not:SI (match_operand:SI 1 "non_push_operand" "0")))] + [(set (match_operand:SI 0 "non_push_operand" "") + (not:SI (match_dup 0))) + (clobber (match_scratch:HI 1 ""))] "z_replacement_completed == 2 - && (!D_REG_P (operands[0]) || (optimize && optimize_size == 0))" - [(set (reg:HI D_REGNUM) (not:HI (reg:HI D_REGNUM))) - (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM)) - (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))]) - (set (reg:HI D_REGNUM) (not:HI (reg:HI D_REGNUM))) - (parallel [(set (reg:HI X_REGNUM) (reg:HI D_REGNUM)) - (set (reg:HI D_REGNUM) (reg:HI X_REGNUM))])] - " -{ - /* The result pattern only works for D register. - Generate 2 one_cmplhi2 instructions. */ - if (!D_REG_P (operands[0])) - { - rtx ops[2]; + && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))" + [(set (match_dup 2) (not:HI (match_dup 2))) + (set (match_dup 3) (not:HI (match_dup 3)))] + "operands[2] = m68hc11_gen_lowpart (HImode, operands[0]); + operands[3] = m68hc11_gen_highpart (HImode, operands[0]);") - ops[0] = m68hc11_gen_lowpart (HImode, operands[0]); - ops[1] = m68hc11_gen_highpart (HImode, operands[0]); - emit_insn (gen_one_cmplhi2 (ops[0], ops[0])); - emit_insn (gen_one_cmplhi2 (ops[1], ops[1])); - DONE; - } -}") +(define_split /* "*one_cmplsi2" */ + [(set (match_operand:SI 0 "non_push_operand" "") + (not:SI (match_operand:SI 1 "non_push_operand" ""))) + (clobber (match_operand:HI 2 "d_register_operand" ""))] + "z_replacement_completed == 2 + && (!X_REG_P (operands[0]) || (optimize && optimize_size == 0))" + [(set (match_dup 2) (match_dup 3)) + (set (match_dup 2) (not:HI (match_dup 2))) + (set (match_dup 4) (match_dup 2)) + (set (match_dup 2) (match_dup 5)) + (set (match_dup 2) (not:HI (match_dup 2))) + (set (match_dup 6) (match_dup 2))] + "operands[3] = m68hc11_gen_lowpart (HImode, operands[1]); + operands[5] = m68hc11_gen_highpart (HImode, operands[1]); + operands[4] = m68hc11_gen_lowpart (HImode, operands[0]); + operands[6] = m68hc11_gen_highpart (HImode, operands[0]);") ;;-------------------------------------------------------------------- ;;- arithmetic shifts @@ -4026,19 +4403,13 @@ } }") -(define_insn "*ashldi3_const32" +(define_insn_and_split "*ashldi3_const32" [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u") (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi,umi") (const_int 32))) (clobber (match_scratch:HI 2 "=&A,d,d"))] "" - "#") - -(define_split - [(set (match_operand:DI 0 "nonimmediate_operand" "=<,um") - (ashift:DI (match_operand:DI 1 "general_operand" "umi,umi") - (const_int 32))) - (clobber (match_scratch:HI 2 "=&A,d"))] + "#" "reload_completed" [(const_int 0)] "/* Move the lowpart in the highpart first in case the shift @@ -4047,6 +4418,13 @@ { m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]), const0_rtx, operands[2]); + + /* Adjust first operand if it uses SP so that we take into + account the above push. Can occur only for 68HC12. */ + if (reg_mentioned_p (gen_rtx_REG (HImode, HARD_SP_REGNUM), + operands[1])) + operands[1] = adjust_address (operands[1], + GET_MODE (operands[0]), 4); } m68hc11_split_move (m68hc11_gen_highpart (SImode, operands[0]), m68hc11_gen_lowpart (SImode, operands[1]), @@ -4058,34 +4436,34 @@ } DONE;") -(define_insn "*ashldi3_const1" +(define_insn_and_split "*ashldi3_const1" [(set (match_operand:DI 0 "non_push_operand" "=m,m,u") (ashift:DI (match_operand:DI 1 "general_operand" "mi,u,umi") (const_int 1))) (clobber (match_scratch:HI 2 "=d,d,d"))] "" - "#") - -(define_split - [(set (match_operand:DI 0 "non_push_operand" "=um") - (ashift:DI (match_operand:DI 1 "general_operand" "umi") - (const_int 1))) - (clobber (match_scratch:HI 2 "=d"))] + "#" "z_replacement_completed == 2" [(set (match_dup 2) (match_dup 3)) (set (match_dup 2) (ashift:HI (match_dup 2) (const_int 1))) (set (match_dup 4) (match_dup 2)) (set (match_dup 2) (match_dup 5)) - (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI CC_REGNUM))) + (parallel [(set (match_dup 2) + (rotate:HI (match_dup 2) (const_int 1))) + (clobber (reg:HI CC_REGNUM))]) (set (match_dup 6) (match_dup 2)) (set (match_dup 2) (match_dup 7)) - (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI CC_REGNUM))) + (parallel [(set (match_dup 2) + (rotate:HI (match_dup 2) (const_int 1))) + (clobber (reg:HI CC_REGNUM))]) (set (match_dup 8) (match_dup 2)) (set (match_dup 2) (match_dup 9)) - (set (match_dup 2) (rotate:HI (match_dup 2) (reg:HI CC_REGNUM))) + (parallel [(set (match_dup 2) + (rotate:HI (match_dup 2) (const_int 1))) + (clobber (reg:HI CC_REGNUM))]) (set (match_dup 10) (match_dup 2))] "operands[3] = m68hc11_gen_lowpart (SImode, operands[1]); operands[5] = m68hc11_gen_highpart (HImode, operands[3]); @@ -4104,23 +4482,50 @@ operands[8] = m68hc11_gen_lowpart (HImode, operands[8]);") (define_insn "addsi_silshr16" - [(set (match_operand:SI 0 "register_operand" "=D") - (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim") + [(set (match_operand:SI 0 "register_operand" "=D,D,!D") + (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "!*uim,0,0") (const_int 16)) - (match_operand:SI 2 "general_operand" "0")))] + (match_operand:SI 2 "general_operand" "0,m!*u,0")))] "" "#") (define_split - [(set (match_operand:SI 0 "register_operand" "=D") - (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim") + [(set (match_operand:SI 0 "register_operand" "") + (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "") (const_int 16)) - (match_operand:SI 2 "general_operand" "0")))] - "z_replacement_completed == 2" + (match_operand:SI 2 "general_operand" "")))] + "z_replacement_completed == 2 && !X_REG_P (operands[1])" [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3))) - (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))] + (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) + (const_int 0)) + (reg:HI CC_REGNUM)))] "operands[3] = m68hc11_gen_highpart (HImode, operands[1]);") +(define_split + [(set (match_operand:SI 0 "register_operand" "") + (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "") + (const_int 16)) + (match_operand:SI 2 "general_operand" "")))] + "z_replacement_completed == 2 && X_REG_P (operands[1])" + [(set (reg:HI D_REGNUM) (match_dup 5)) + (set (reg:HI X_REGNUM) (match_dup 3)) + (set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 4))) + (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) + (const_int 0)) + (reg:HI CC_REGNUM)))] + "operands[3] = m68hc11_gen_highpart (HImode, operands[2]); + if (X_REG_P (operands[2])) + { + operands[4] = gen_rtx_REG (HImode, HARD_X_REGNUM); + operands[5] = gen_rtx_REG (HImode, HARD_D_REGNUM); + } + else + { + operands[4] = m68hc11_gen_lowpart (HImode, operands[2]); + operands[5] = gen_rtx_REG (HImode, HARD_X_REGNUM); + } +") + (define_insn "addsi_ashift16" [(set (match_operand:SI 0 "register_operand" "=D") (plus:SI @@ -4132,11 +4537,11 @@ "#") (define_split - [(set (match_operand:SI 0 "register_operand" "=D") + [(set (match_operand:SI 0 "register_operand" "") (plus:SI - (mult:SI (match_operand:SI 2 "general_operand" "uim") + (mult:SI (match_operand:SI 2 "general_operand" "") (const_int 65536)) - (match_operand:SI 1 "general_operand" "0"))) + (match_operand:SI 1 "general_operand" ""))) (clobber (match_scratch:HI 3 "=X"))] "0 && reload_completed && z_replacement_completed == 2" [(set (reg:HI X_REGNUM) (plus:HI (reg:HI X_REGNUM) (match_dup 4)))] @@ -4145,19 +4550,13 @@ operands[4] = m68hc11_gen_lowpart (HImode, operands[2]); }") -(define_insn "addsi_andshr16" +(define_insn_and_split "addsi_andshr16" [(set (match_operand:SI 0 "register_operand" "=D") (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim") (const_int 65535)) (match_operand:SI 2 "general_operand" "0")))] "" - "#") - -(define_split - [(set (match_operand:SI 0 "register_operand" "=D") - (plus:SI (and:SI (match_operand:SI 1 "general_operand" "%uim") - (const_int 65535)) - (match_operand:SI 2 "general_operand" "0")))] + "#" "z_replacement_completed == 2" [(set (reg:HI D_REGNUM) (plus:HI (reg:HI D_REGNUM) (match_dup 3))) (set (reg:HI X_REGNUM) (plus:HI (plus:HI (reg:HI X_REGNUM) (const_int 0)) (reg:HI CC_REGNUM)))] @@ -4185,10 +4584,10 @@ "") (define_split - [(set (match_operand:SI 0 "nonimmediate_operand" "=D,um") - (ashift:SI (match_operand:SI 1 "general_operand" "Duim,D") + [(set (match_operand:SI 0 "nonimmediate_operand" "") + (ashift:SI (match_operand:SI 1 "general_operand" "") (const_int 16))) - (clobber (match_scratch:HI 3 "=X,X"))] + (clobber (match_scratch:HI 3 ""))] "" [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (const_int 0))] @@ -4204,31 +4603,24 @@ "" "#") -(define_insn "*ashlsi3_const16_zexthi" +(define_insn_and_split "*ashlsi3_const16_zexthi" [(set (match_operand:SI 0 "nonimmediate_operand" "=D") (ashift:SI (zero_extend:HI (match_operand:HI 1 "general_operand" "duim*A")) (const_int 16))) (clobber (match_scratch:HI 2 "=X"))] "" - "#") - -(define_split /* "*ashlsi3_const16_zexthi"*/ - [(set (match_operand:SI 0 "nonimmediate_operand" "=D") - (ashift:SI (zero_extend:HI - (match_operand:HI 1 "general_operand" "duim*a")) - (const_int 16))) - (clobber (match_scratch:HI 2 "=X"))] + "#" "reload_completed" [(set (reg:HI X_REGNUM) (match_dup 1)) (set (reg:HI D_REGNUM) (const_int 0))] "") (define_insn "*ashlsi3_const1" - [(set (match_operand:SI 0 "non_push_operand" "=D,D,m,!*u,?*um") - (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,*um,0,0,*um") + [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u") + (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m") (const_int 1))) - (clobber (match_scratch:HI 2 "=X,X,&d,&d,&d"))] + (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))] "" "* { @@ -4242,7 +4634,7 @@ rtx ops[2]; ops[1] = m68hc11_gen_lowpart (HImode, operands[1]); - ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM); + ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM); m68hc11_gen_movhi (insn, ops); output_asm_insn (\"lsld\", ops); if (!X_REG_P (operands[0])) @@ -4258,7 +4650,7 @@ { /* Load the high part in X in case the source operand uses X as a memory pointer. */ - ops[0] = gen_rtx (REG, HImode, HARD_X_REGNUM); + ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM); ops[1] = m68hc11_gen_highpart (HImode, operands[1]); m68hc11_gen_movhi (insn, ops); output_asm_insn (\"xgdx\", ops); @@ -4284,7 +4676,7 @@ (ashift:SI (match_dup 0) (match_operand:HI 1 "const_int_operand" ""))) (clobber (match_scratch:HI 2 "=y"))] - "" + "TARGET_M6811 /* See *ashlsi3 note. */" "* { CC_STATUS_INIT; @@ -4294,7 +4686,7 @@ (define_insn "*ashlsi3" [(set (match_operand:SI 0 "register_operand" "+D,D") (ashift:SI (match_dup 0) - (match_operand:HI 1 "general_operand" "y,m"))) + (match_operand:HI 1 "general_operand" "y,mi"))) (clobber (match_scratch:HI 2 "=1,X"))] "" "* @@ -4307,20 +4699,27 @@ is not enough register in class A_REGS. Assuming that 'operands[1]' does not refer to the stack (which - is true for 68hc11 only, we save temporary the value of Y. */ + is true for 68hc11 only, we save temporary the value of Y. + + For 68HC12 we must also accept a constant because Z register is + disabled when compiling with -fomit-frame-pointer. We can come up + with a reload problem and the *lshrsi3_const pattern was disabled + for that reason. */ if (!Y_REG_P (operands[2])) { rtx ops[1]; + int y_dead = dead_register_here (insn, iy_reg); ops[0] = operands[1]; - output_asm_insn (\"pshy\", operands); - if (reg_mentioned_p (stack_pointer_rtx, operands[1])) + if (y_dead == 0) { - ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2); + output_asm_insn (\"pshy\", operands); + if (reg_mentioned_p (stack_pointer_rtx, operands[1])) + ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2); } output_asm_insn (\"ldy\\t%0\", ops); output_asm_insn (\"bsr\\t___ashlsi3\", operands); - return \"puly\"; + return y_dead == 0 ? \"puly\" : \"\"; } return \"bsr\\t___ashlsi3\"; }") @@ -4336,12 +4735,12 @@ { rtx scratch = gen_reg_rtx (HImode); emit_move_insn (scratch, operands[2]); - emit_insn (gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (2, gen_rtx (SET, VOIDmode, + emit_insn (gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (2, gen_rtx_SET (VOIDmode, operand0, gen_rtx_ASHIFT (HImode, operand1, scratch)), - gen_rtx (CLOBBER, VOIDmode, scratch)))); + gen_rtx_CLOBBER (VOIDmode, scratch)))); DONE; } }") @@ -4369,13 +4768,16 @@ (define_insn "*ashlhi3_2" - [(set (match_operand:HI 0 "register_operand" "=d") - (ashift:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:HI 2 "register_operand" "+x"))) + [(set (match_operand:HI 0 "register_operand" "=d,*x") + (ashift:HI (match_operand:HI 1 "register_operand" "0,0") + (match_operand:HI 2 "register_operand" "+x,+d"))) (clobber (match_dup 2))] "" "* { + if (A_REG_P (operands[0])) + return \"#\"; + CC_STATUS_INIT; return \"bsr\\t___lshlhi3\"; }") @@ -4526,7 +4928,7 @@ if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0])) return \"#\"; - ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM); + ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM); ops[1] = operands[2]; m68hc11_gen_movqi (insn, ops); @@ -4546,12 +4948,12 @@ rtx scratch = gen_reg_rtx (HImode); emit_move_insn (scratch, operands[2]); - emit_insn (gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (2, gen_rtx (SET, VOIDmode, + emit_insn (gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (2, gen_rtx_SET (VOIDmode, operand0, gen_rtx_ASHIFTRT (HImode, operand1, scratch)), - gen_rtx (CLOBBER, VOIDmode, scratch)))); + gen_rtx_CLOBBER (VOIDmode, scratch)))); DONE; } }") @@ -4598,14 +5000,14 @@ output_asm_insn (\"clrb\", operands); output_asm_insn (\"rola\", operands); - /* Clear A without clearing the carry flag. */ + /* Clear A without clearing the carry flag. */ output_asm_insn (\"tba\", operands); output_asm_insn (\"bcc\\t%l0\", ops); output_asm_insn (\"coma\", operands); output_asm_insn (\"comb\", operands); CC_STATUS_INIT; - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); return \"\"; } @@ -4619,7 +5021,7 @@ output_asm_insn (\"bge\\t%l0\", ops); output_asm_insn (\"deca\", operands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); val -= 8; @@ -4629,7 +5031,7 @@ output_asm_insn (\"asrb\", operands); val--; } - /* Status is ok. */ + /* Status is ok. */ return \"\"; } if (val == 7) @@ -4642,7 +5044,7 @@ output_asm_insn (\"bcc\\t%l0\", ops); output_asm_insn (\"coma\", ops); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); return \"\"; } @@ -4658,21 +5060,17 @@ }") (define_insn "*ashrhi3" - [(set (match_operand:HI 0 "register_operand" "=d,x") + [(set (match_operand:HI 0 "register_operand" "=d,*x") (ashiftrt:HI (match_operand:HI 1 "register_operand" "0,0") (match_operand:HI 2 "register_operand" "+x,+d"))) (clobber (match_dup 2))] "" "* { - CC_STATUS_INIT; - if (D_REG_P (operands[2])) - output_asm_insn (\"xgd%0\", operands); + if (A_REG_P (operands[0])) + return \"#\"; output_asm_insn (\"bsr\\t___ashrhi3\", operands); - if (D_REG_P (operands[2])) - output_asm_insn (\"xgd%0\", operands); - return \"\"; }") @@ -4693,7 +5091,7 @@ (ashiftrt:SI (match_dup 0) (match_operand:HI 1 "const_int_operand" ""))) (clobber (match_scratch:HI 2 "=y"))] - "" + "TARGET_M6811 /* See *ashrsi3 note. */" "* { CC_STATUS_INIT; @@ -4703,7 +5101,7 @@ (define_insn "*ashrsi3" [(set (match_operand:SI 0 "register_operand" "+D,D") (ashiftrt:SI (match_dup 0) - (match_operand:HI 1 "general_operand" "y,m"))) + (match_operand:HI 1 "general_operand" "y,mi"))) (clobber (match_scratch:HI 2 "=1,X"))] "" "* @@ -4715,20 +5113,27 @@ is not enough register in class A_REGS. Assuming that 'operands[1]' does not refer to the stack (which - is true for 68hc11 only, we save temporary the value of Y. */ + is true for 68hc11 only, we save temporary the value of Y. + + For 68HC12 we must also accept a constant because Z register is + disabled when compiling with -fomit-frame-pointer. We can come up + with a reload problem and the *lshrsi3_const pattern was disabled + for that reason. */ if (!Y_REG_P (operands[2])) { rtx ops[1]; + int y_dead = dead_register_here (insn, iy_reg); ops[0] = operands[1]; - output_asm_insn (\"pshy\", operands); - if (reg_mentioned_p (stack_pointer_rtx, operands[1])) + if (y_dead == 0) { - ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2); + output_asm_insn (\"pshy\", operands); + if (reg_mentioned_p (stack_pointer_rtx, operands[1])) + ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2); } output_asm_insn (\"ldy\\t%0\", ops); output_asm_insn (\"bsr\\t___ashrsi3\", operands); - return \"puly\"; + return y_dead == 0 ? \"puly\" : \"\"; } return \"bsr\\t___ashrsi3\"; }") @@ -4792,7 +5197,7 @@ if (!D_REG_P (operands[0]) && !Q_REG_P (operands[0])) return \"#\"; - ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM); + ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM); ops[1] = operands[2]; m68hc11_gen_movqi (insn, ops); @@ -4819,19 +5224,13 @@ } }") -(define_insn "*lshrdi3_const32" +(define_insn_and_split "*lshrdi3_const32" [(set (match_operand:DI 0 "nonimmediate_operand" "=<,m,u") (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi,umi") (const_int 32))) (clobber (match_scratch:HI 2 "=&A,d,d"))] "" - "#") - -(define_split - [(set (match_operand:DI 0 "nonimmediate_operand" "=<,um") - (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi") - (const_int 32))) - (clobber (match_scratch:HI 2 "=&A,d"))] + "#" "reload_completed" [(const_int 0)] "m68hc11_split_move (m68hc11_gen_lowpart (SImode, operands[0]), @@ -4850,8 +5249,8 @@ "#") (define_split - [(set (match_operand:DI 0 "nonimmediate_operand" "=um") - (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi") + [(set (match_operand:DI 0 "nonimmediate_operand" "") + (lshiftrt:DI (match_operand:DI 1 "general_operand" "") (match_operand:DI 2 "const_int_operand" ""))) (clobber (match_scratch:HI 3 "=d"))] "z_replacement_completed && INTVAL (operands[2]) >= 56" @@ -4863,7 +5262,7 @@ (set (match_dup 5) (reg:HI D_REGNUM)) (set (match_dup 6) (reg:HI D_REGNUM)) (set (match_dup 7) (reg:HI D_REGNUM))] - "operands[8] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 56); + "operands[8] = GEN_INT (INTVAL (operands[2]) - 56); operands[4] = m68hc11_gen_lowpart (SImode, operands[0]); operands[5] = m68hc11_gen_highpart (HImode, operands[4]); operands[4] = m68hc11_gen_lowpart (HImode, operands[4]); @@ -4877,8 +5276,8 @@ operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);") (define_split - [(set (match_operand:DI 0 "nonimmediate_operand" "=um") - (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi") + [(set (match_operand:DI 0 "nonimmediate_operand" "") + (lshiftrt:DI (match_operand:DI 1 "general_operand" "") (match_operand:DI 2 "const_int_operand" ""))) (clobber (match_scratch:HI 3 "=d"))] "z_replacement_completed && INTVAL (operands[2]) >= 48 @@ -4890,7 +5289,7 @@ (set (match_dup 5) (reg:HI D_REGNUM)) (set (match_dup 6) (reg:HI D_REGNUM)) (set (match_dup 7) (reg:HI D_REGNUM))] - "operands[8] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 48); + "operands[8] = GEN_INT (INTVAL (operands[2]) - 48); operands[4] = m68hc11_gen_lowpart (SImode, operands[0]); operands[5] = m68hc11_gen_highpart (HImode, operands[4]); operands[4] = m68hc11_gen_lowpart (HImode, operands[4]); @@ -4901,34 +5300,31 @@ operands[7] = m68hc11_gen_highpart (HImode, operands[6]); operands[6] = m68hc11_gen_lowpart (HImode, operands[6]);") -(define_insn "*lshrdi_const1" +(define_insn_and_split "*lshrdi_const1" [(set (match_operand:DI 0 "non_push_operand" "=m,u") (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi,umi") (const_int 1))) (clobber (match_scratch:HI 2 "=d,d"))] "" - "#") - -(define_split - [(set (match_operand:DI 0 "non_push_operand" "=um") - (lshiftrt:DI (match_operand:DI 1 "general_operand" "umi") - (const_int 1))) - (clobber (match_scratch:HI 2 "=d"))] + "#" "z_replacement_completed == 2" [(set (match_dup 2) (match_dup 3)) (set (match_dup 2) (lshiftrt:HI (match_dup 2) (const_int 1))) (set (match_dup 4) (match_dup 2)) (set (match_dup 2) (match_dup 5)) - (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI CC_REGNUM))) + (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1))) + (clobber (reg:HI CC_REGNUM))]) (set (match_dup 6) (match_dup 2)) (set (match_dup 2) (match_dup 7)) - (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI CC_REGNUM))) + (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1))) + (clobber (reg:HI CC_REGNUM))]) (set (match_dup 8) (match_dup 2)) (set (match_dup 2) (match_dup 9)) - (set (match_dup 2) (rotatert:HI (match_dup 2) (reg:HI CC_REGNUM))) + (parallel [(set (match_dup 2) (rotatert:HI (match_dup 2) (const_int 1))) + (clobber (reg:HI CC_REGNUM))]) (set (match_dup 10) (match_dup 2))] "operands[3] = m68hc11_gen_highpart (SImode, operands[1]); operands[5] = m68hc11_gen_lowpart (HImode, operands[3]); @@ -4959,10 +5355,10 @@ "") (define_split - [(set (match_operand:SI 0 "non_push_operand" "=D,um") - (lshiftrt:SI (match_operand:SI 1 "general_operand" "uim,D") + [(set (match_operand:SI 0 "non_push_operand" "") + (lshiftrt:SI (match_operand:SI 1 "general_operand" "") (const_int 16))) - (clobber (match_scratch:HI 3 "=X,X"))] + (clobber (match_scratch:HI 3 ""))] "reload_completed && !(X_REG_P (operands[0]) && X_REG_P (operands[1]))" [(set (match_dup 2) (match_dup 3)) (set (match_dup 4) (const_int 0))] @@ -4983,10 +5379,10 @@ #") (define_insn "*lshrsi3_const1" - [(set (match_operand:SI 0 "non_push_operand" "=D,m,*u") - (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "D*um,*um,*um") + [(set (match_operand:SI 0 "non_push_operand" "=D,D,D,m,*u,*u") + (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,*u,m,*u,m") (const_int 1))) - (clobber (match_scratch:HI 2 "=X,&d,&d"))] + (clobber (match_scratch:HI 2 "=X,X,X,&d,&d,&d"))] "" "* { @@ -5000,7 +5396,7 @@ rtx ops[2]; ops[1] = m68hc11_gen_highpart (HImode, operands[1]); - ops[0] = gen_rtx (REG, HImode, HARD_D_REGNUM); + ops[0] = gen_rtx_REG (HImode, HARD_D_REGNUM); m68hc11_gen_movhi (insn, ops); output_asm_insn (\"lsrd\", ops); if (!X_REG_P (operands[0])) @@ -5015,7 +5411,7 @@ else { /* Load the lowpart in X in case the operands is some N,x. */ - ops[0] = gen_rtx (REG, HImode, HARD_X_REGNUM); + ops[0] = gen_rtx_REG (HImode, HARD_X_REGNUM); ops[1] = m68hc11_gen_lowpart (HImode, operands[1]); m68hc11_gen_movhi (insn, ops); output_asm_insn (\"xgdx\", ops); @@ -5037,7 +5433,7 @@ (lshiftrt:SI (match_dup 0) (match_operand:HI 1 "const_int_operand" ""))) (clobber (match_scratch:HI 2 "=y"))] - "" + "TARGET_M6811 /* See *lshrsi3 note. */" "* { CC_STATUS_INIT; @@ -5047,7 +5443,7 @@ (define_insn "*lshrsi3" [(set (match_operand:SI 0 "register_operand" "+D,D") (lshiftrt:SI (match_dup 0) - (match_operand:HI 1 "general_operand" "y,m"))) + (match_operand:HI 1 "general_operand" "y,mi"))) (clobber (match_scratch:HI 2 "=1,X"))] "" "* @@ -5059,20 +5455,27 @@ is not enough register in class A_REGS. Assuming that 'operands[1]' does not refer to the stack (which - is true for 68hc11 only, we save temporary the value of Y. */ + is true for 68hc11 only, we save temporary the value of Y. + + For 68HC12 we must also accept a constant because Z register is + disabled when compiling with -fomit-frame-pointer. We can come up + with a reload problem and the *lshrsi3_const pattern was disabled + for that reason. */ if (!Y_REG_P (operands[2])) { rtx ops[1]; + int y_dead = dead_register_here (insn, iy_reg); ops[0] = operands[1]; - output_asm_insn (\"pshy\", operands); - if (reg_mentioned_p (stack_pointer_rtx, operands[1])) + if (y_dead == 0) { - ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2); + output_asm_insn (\"pshy\", operands); + if (reg_mentioned_p (stack_pointer_rtx, operands[1])) + ops[0] = adjust_address (operands[1], GET_MODE (operands[1]), 2); } output_asm_insn (\"ldy\\t%0\", ops); output_asm_insn (\"bsr\\t___lshrsi3\", operands); - return \"puly\"; + return y_dead == 0 ? \"puly\" : \"\"; } return \"bsr\\t___lshrsi3\"; }") @@ -5090,12 +5493,12 @@ operand1 = force_reg (HImode, operand1); emit_move_insn (scratch, operands[2]); - emit_insn (gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (2, gen_rtx (SET, VOIDmode, + emit_insn (gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (2, gen_rtx_SET (VOIDmode, operand0, gen_rtx_LSHIFTRT (HImode, operand1, scratch)), - gen_rtx (CLOBBER, VOIDmode, scratch)))); + gen_rtx_CLOBBER (VOIDmode, scratch)))); DONE; } }") @@ -5202,22 +5605,17 @@ }") (define_insn "*lshrhi3" - [(set (match_operand:HI 0 "register_operand" "=d,x") + [(set (match_operand:HI 0 "register_operand" "=d,*x") (lshiftrt:HI (match_operand:HI 1 "register_operand" "0,0") (match_operand:HI 2 "register_operand" "+x,+d"))) (clobber (match_dup 2))] "" "* { - CC_STATUS_INIT; - if (D_REG_P (operands[2])) - output_asm_insn (\"xgd%0\", operands); - - output_asm_insn (\"bsr\\t___lshrhi3\", operands); - if (D_REG_P (operands[2])) - output_asm_insn (\"xgd%0\", operands); + if (A_REG_P (operands[0])) + return \"#\"; - return \"\"; + return \"bsr\\t___lshrhi3\"; }") (define_expand "lshrqi3" @@ -5317,7 +5715,7 @@ return \"#\"; CC_STATUS_INIT; - ops[0] = gen_rtx (REG, QImode, HARD_A_REGNUM); + ops[0] = gen_rtx_REG (QImode, HARD_A_REGNUM); ops[1] = operands[2]; m68hc11_gen_movqi (insn, ops); @@ -5330,14 +5728,14 @@ ops[1] = gen_label_rtx (); output_asm_insn (\"ble\\t%l1\", ops); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[0])); output_asm_insn (\"lsrb\", operands); output_asm_insn (\"deca\", operands); output_asm_insn (\"bne\\t%l0\", ops); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + (*targetm.asm_out.internal_label) (asm_out_file, \"L\", CODE_LABEL_NUMBER (ops[1])); return \"\"; }") @@ -5358,7 +5756,8 @@ (define_insn "*rotlhi3_with_carry" [(set (match_operand:HI 0 "register_operand" "=d") (rotate:HI (match_operand:HI 1 "register_operand" "0") - (reg:HI CC_REGNUM)))] + (const_int 1))) + (clobber (reg:HI CC_REGNUM))] "" "* { @@ -5369,7 +5768,8 @@ (define_insn "*rotrhi3_with_carry" [(set (match_operand:HI 0 "register_operand" "=d") (rotatert:HI (match_operand:HI 1 "register_operand" "0") - (reg:HI CC_REGNUM)))] + (const_int 1))) + (clobber (reg:HI CC_REGNUM))] "" "* { @@ -5388,7 +5788,41 @@ return \"\"; }") -(define_insn "rotlhi3" +(define_insn "rotrqi3" + [(set (match_operand:QI 0 "register_operand" "=d,!q") + (rotatert:QI (match_operand:QI 1 "register_operand" "0,0") + (match_operand:QI 2 "const_int_operand" "i,i")))] + "" + "* +{ + m68hc11_gen_rotate (ROTATERT, insn, operands); + return \"\"; +}") + +(define_expand "rotlhi3" + [(set (match_operand:HI 0 "register_operand" "") + (rotate:HI (match_operand:HI 1 "register_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "" + " +{ + if (GET_CODE (operands[2]) != CONST_INT) + { + rtx scratch = gen_reg_rtx (HImode); + operand1 = force_reg (HImode, operand1); + + emit_move_insn (scratch, operands[2]); + emit_insn (gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (2, gen_rtx_SET (VOIDmode, + operand0, + gen_rtx_ROTATE (HImode, + operand1, scratch)), + gen_rtx_CLOBBER (VOIDmode, scratch)))); + DONE; + } +}") + +(define_insn "rotlhi3_const" [(set (match_operand:HI 0 "register_operand" "=d") (rotate:HI (match_operand:HI 1 "register_operand" "0") (match_operand:HI 2 "const_int_operand" "i")))] @@ -5399,10 +5833,47 @@ return \"\"; }") -(define_insn "rotrqi3" - [(set (match_operand:QI 0 "register_operand" "=d,!q") - (rotatert:QI (match_operand:QI 1 "register_operand" "0,0") - (match_operand:QI 2 "const_int_operand" "i,i")))] +(define_insn "*rotlhi3" + [(set (match_operand:HI 0 "register_operand" "=d,*x") + (rotate:HI (match_operand:HI 1 "register_operand" "0,0") + (match_operand:HI 2 "general_operand" "+x,+d"))) + (clobber (match_dup 2))] + "" + "* +{ + if (A_REG_P (operands[0])) + return \"#\"; + + return \"bsr\\t___rotlhi3\"; +}") + +(define_expand "rotrhi3" + [(set (match_operand:HI 0 "register_operand" "") + (rotatert:HI (match_operand:HI 1 "general_operand" "") + (match_operand:HI 2 "general_operand" "")))] + "" + " +{ + if (GET_CODE (operands[2]) != CONST_INT) + { + rtx scratch = gen_reg_rtx (HImode); + operand1 = force_reg (HImode, operand1); + + emit_move_insn (scratch, operands[2]); + emit_insn (gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (2, gen_rtx_SET (VOIDmode, + operand0, + gen_rtx_ROTATERT (HImode, + operand1, scratch)), + gen_rtx_CLOBBER (VOIDmode, scratch)))); + DONE; + } +}") + +(define_insn "rotrhi3_const" + [(set (match_operand:HI 0 "register_operand" "=d") + (rotatert:HI (match_operand:HI 1 "register_operand" "0") + (match_operand:HI 2 "const_int_operand" "i")))] "" "* { @@ -5410,17 +5881,249 @@ return \"\"; }") -(define_insn "rotrhi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (rotatert:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:HI 2 "const_int_operand" "i")))] - "" +(define_insn "*rotrhi3" + [(set (match_operand:HI 0 "register_operand" "=d,*x") + (rotatert:HI (match_operand:HI 1 "register_operand" "0,0") + (match_operand:HI 2 "general_operand" "+x,+d"))) + (clobber (match_dup 2))] + "" + "* +{ + if (A_REG_P (operands[0])) + return \"#\"; + + return \"bsr\\t___rotrhi3\"; +}") + +;; Split a shift operation on an address register in a shift +;; on D_REGNUM. +(define_split /* "*rotrhi3_addr" */ + [(set (match_operand:HI 0 "hard_addr_reg_operand" "") + (match_operator:HI 3 "m68hc11_shift_operator" + [(match_operand:HI 1 "register_operand" "") + (match_operand:HI 2 "register_operand" "")])) + (clobber (match_dup 2))] + "z_replacement_completed == 2" + [(parallel [(set (reg:HI D_REGNUM) (match_dup 0)) + (set (match_dup 0) (reg:HI D_REGNUM))]) + (parallel [(set (reg:HI D_REGNUM) + (match_op_dup 3 [(reg:HI D_REGNUM) (match_dup 0)])) + (clobber (match_dup 0))]) + (parallel [(set (reg:HI D_REGNUM) (match_dup 0)) + (set (match_dup 0) (reg:HI D_REGNUM))])] + "") + +;;-------------------------------------------------------------------- +;;- 68HC12 Decrement/Increment and branch +;;-------------------------------------------------------------------- +;; These patterns are used by loop optimization as well as peephole2 +;; They must handle reloading themselves and the scratch register +;; is used for that. Even if we accept memory operand, we must not +;; accept them on the predicate because it might create too many reloads. +;; (specially on HC12 due to its auto-incdec addressing modes). +;; +(define_expand "decrement_and_branch_until_zero" + [(parallel [(set (pc) + (if_then_else + (ne (plus:HI (match_operand:HI 0 "register_operand" "") + (const_int 0)) + (const_int 1)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:HI (match_dup 0) + (const_int -1))) + (clobber (match_scratch:HI 2 ""))])] + "TARGET_M6812" + "") + +(define_expand "doloop_end" + [(use (match_operand 0 "" "")) ; loop pseudo + (use (match_operand 1 "" "")) ; iterations; zero if unknown + (use (match_operand 2 "" "")) ; max iterations + (use (match_operand 3 "" "")) ; loop level + (use (match_operand 4 "" ""))] ; label + "TARGET_M6812" + " +{ + /* Reject non-constant loops as it generates bigger code due to + the handling of the loop register. We can do better by using + the peephole2 dbcc/ibcc patterns. */ + if (INTVAL (operands[1]) == 0) + { + FAIL; + } + + /* Note that for xxx_dbcc_dec_yy the gen_rtx_NE is only used to pass + the operator and its operands are not relevant. */ + if (GET_MODE (operands[0]) == HImode) + { + emit_jump_insn (gen_m68hc12_dbcc_dec_hi (operands[0], + gen_rtx_NE (HImode, + operands[0], + const1_rtx), + operands[4])); + DONE; + } + if (GET_MODE (operands[0]) == QImode) + { + emit_jump_insn (gen_m68hc12_dbcc_dec_qi (operands[0], + gen_rtx_NE (QImode, + operands[0], + const1_rtx), + operands[4])); + DONE; + } + + FAIL; +}") + +;; Decrement-and-branch insns. +(define_insn "m68hc12_dbcc_dec_hi" + [(set (pc) + (if_then_else + (match_operator 1 "m68hc11_eq_compare_operator" + [(match_operand:HI 0 "register_operand" "+dxy,m*u*z") + (const_int 1)]) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (match_dup 0) + (plus:HI (match_dup 0) (const_int -1))) + (clobber (match_scratch:HI 3 "=X,dxy"))] + "TARGET_M6812" + "* +{ + if (!H_REG_P (operands[0])) + return \"#\"; + + CC_STATUS_INIT; + if (GET_CODE (operands[1]) == EQ) + return \"dbeq\\t%0,%l2\"; + else + return \"dbne\\t%0,%l2\"; +}") + +;; Decrement-and-branch insns. +(define_insn "m68hc12_dbcc_inc_hi" + [(set (pc) + (if_then_else + (match_operator 1 "m68hc11_eq_compare_operator" + [(match_operand:HI 0 "register_operand" "+dxy,m*u*z") + (const_int -1)]) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (match_dup 0) + (plus:HI (match_dup 0) (const_int 1))) + (clobber (match_scratch:HI 3 "=X,dxy"))] + "TARGET_M6812" + "* +{ + if (!H_REG_P (operands[0])) + return \"#\"; + + CC_STATUS_INIT; + if (GET_CODE (operands[1]) == EQ) + return \"ibeq\\t%0,%l2\"; + else + return \"ibeq\\t%0,%l2\"; +}") + +;; Decrement-and-branch (QImode). +(define_insn "m68hc12_dbcc_dec_qi" + [(set (pc) + (if_then_else + (match_operator 1 "m68hc11_eq_compare_operator" + [(match_operand:QI 0 "register_operand" "+d,m*u*A") + (const_int 1)]) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (match_dup 0) + (plus:QI (match_dup 0) (const_int -1))) + (clobber (match_scratch:QI 3 "=X,d"))] + "TARGET_M6812" + "* +{ + if (!D_REG_P (operands[0])) + return \"#\"; + + CC_STATUS_INIT; + if (GET_CODE (operands[1]) == EQ) + return \"dbeq\\tb,%l2\"; + else + return \"dbne\\tb,%l2\"; +}") + +;; Increment-and-branch (QImode). +(define_insn "m68hc12_dbcc_inc_qi" + [(set (pc) + (if_then_else + (match_operator 1 "m68hc11_eq_compare_operator" + [(match_operand:QI 0 "register_operand" "+d,m*u*A") + (const_int -1)]) + (label_ref (match_operand 2 "" "")) + (pc))) + (set (match_dup 0) + (plus:QI (match_dup 0) (const_int 1))) + (clobber (match_scratch:QI 3 "=X,d"))] + "TARGET_M6812" "* { - m68hc11_gen_rotate (ROTATERT, insn, operands); - return \"\"; + if (!D_REG_P (operands[0])) + return \"#\"; + + CC_STATUS_INIT; + if (GET_CODE (operands[1]) == EQ) + return \"ibeq\\tb,%l2\"; + else + return \"ibeq\\tb,%l2\"; }") +;; Split the above to handle the case where operand 0 is in memory +;; (a register that couldn't get a hard register) +(define_split + [(set (pc) + (if_then_else + (match_operator 3 "m68hc11_eq_compare_operator" + [(match_operand:HI 0 "general_operand" "") + (match_operand:HI 1 "const_int_operand" "")]) + (label_ref (match_operand 4 "" "")) + (pc))) + (set (match_dup 0) + (plus:HI (match_dup 0) (match_operand 2 "const_int_operand" ""))) + (clobber (match_operand:HI 5 "hard_reg_operand" ""))] + "TARGET_M6812 && reload_completed" + [(set (match_dup 5) (match_dup 0)) + (set (match_dup 5) (plus:HI (match_dup 5) (match_dup 2))) + (set (match_dup 0) (match_dup 5)) + (set (pc) + (if_then_else (match_op_dup 3 + [(match_dup 5) (const_int 0)]) + (label_ref (match_dup 4)) (pc)))] + "") + +;; Split the above to handle the case where operand 0 is in memory +;; (a register that couldn't get a hard register) +(define_split + [(set (pc) + (if_then_else + (match_operator 3 "m68hc11_eq_compare_operator" + [(match_operand:QI 0 "general_operand" "") + (match_operand:QI 1 "const_int_operand" "")]) + (label_ref (match_operand 4 "" "")) + (pc))) + (set (match_dup 0) + (plus:QI (match_dup 0) (match_operand 2 "const_int_operand" ""))) + (clobber (match_operand:QI 5 "hard_reg_operand" ""))] + "TARGET_M6812 && reload_completed" + [(set (match_dup 5) (match_dup 0)) + (set (match_dup 5) (plus:QI (match_dup 5) (match_dup 2))) + (set (match_dup 0) (match_dup 5)) + (set (pc) + (if_then_else (match_op_dup 3 + [(match_dup 5) (const_int 0)]) + (label_ref (match_dup 4)) (pc)))] + "") + ;;-------------------------------------------------------------------- ;;- Jumps and transfers ;;-------------------------------------------------------------------- @@ -5598,7 +6301,8 @@ smaller and a little bit faster. This happens quite often due to reloading of operands[0]. In that case, flags are set correctly due to the load instruction. */ - if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0])) + if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0])) + || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0]))) return \"beq\\t%l1\"; else return \"tbeq\\t%0,%l1\"; @@ -5613,7 +6317,8 @@ "TARGET_M6812" "* { - if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0])) + if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0])) + || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0]))) return \"bne\\t%l1\"; else return \"tbne\\t%0,%l1\"; @@ -5631,7 +6336,8 @@ "TARGET_M6812" "* { - if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0])) + if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0])) + || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0]))) return \"beq\\t%l1\"; else return \"tbeq\\tb,%l1\"; @@ -5646,7 +6352,8 @@ "TARGET_M6812" "* { - if (cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0])) + if ((cc_status.value1 && rtx_equal_p (cc_status.value1, operands[0])) + || (cc_status.value2 && rtx_equal_p (cc_status.value2, operands[0]))) return \"bne\\t%l1\"; else return \"tbne\\tb,%l1\"; @@ -5885,7 +6592,22 @@ { if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) { - if (SYMBOL_REF_FLAG (XEXP (operands[0], 0)) == 1) + if (m68hc11_is_far_symbol (operands[0])) + { + if (TARGET_M6812) + { + output_asm_insn (\"call\\t%0\", operands); + return \"\"; + } + else + { + output_asm_insn (\"pshb\", operands); + output_asm_insn (\"ldab\\t#%%page(%0)\", operands); + output_asm_insn (\"ldy\\t#%%addr(%0)\", operands); + return \"jsr\\t__call_a32\"; + } + } + if (m68hc11_is_trap_symbol (operands[0])) return \"swi\"; else return \"bsr\\t%0\"; @@ -5905,7 +6627,22 @@ { if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) { - if (SYMBOL_REF_FLAG (XEXP (operands[1], 0)) == 1) + if (m68hc11_is_far_symbol (operands[1])) + { + if (TARGET_M6812) + { + output_asm_insn (\"call\\t%1\", operands); + return \"\"; + } + else + { + output_asm_insn (\"pshb\", operands); + output_asm_insn (\"ldab\\t#%%page(%1)\", operands); + output_asm_insn (\"ldy\\t#%%addr(%1)\", operands); + return \"jsr\\t__call_a32\"; + } + } + if (m68hc11_is_trap_symbol (operands[1])) return \"swi\"; else return \"bsr\\t%1\"; @@ -5993,18 +6730,18 @@ if (ret_size && ret_size <= 2) { - emit_insn (gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (2, gen_rtx_RETURN (VOIDmode), - gen_rtx_USE (VOIDmode, - gen_rtx_REG (HImode, 1))))); + emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (2, gen_rtx_RETURN (VOIDmode), + gen_rtx_USE (VOIDmode, + gen_rtx_REG (HImode, 1))))); DONE; } if (ret_size) { - emit_insn (gen_rtx (PARALLEL, VOIDmode, - gen_rtvec (2, gen_rtx_RETURN (VOIDmode), - gen_rtx_USE (VOIDmode, - gen_rtx_REG (SImode, 0))))); + emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, + gen_rtvec (2, gen_rtx_RETURN (VOIDmode), + gen_rtx_USE (VOIDmode, + gen_rtx_REG (SImode, 0))))); DONE; } }") @@ -6022,7 +6759,25 @@ return \"\"; if (current_function_interrupt || current_function_trap) return \"rti\"; - return \"rts\"; + else if (!current_function_far) + return \"rts\"; + else if (TARGET_M6812) + return \"rtc\"; + else + { + int ret_size = 0; + + if (current_function_return_rtx) + ret_size = GET_MODE_SIZE (GET_MODE (current_function_return_rtx)); + + if (ret_size == 0) + return \"jmp\\t__return_void\"; + if (ret_size <= 2) + return \"jmp\\t__return_16\"; + if (ret_size <= 4) + return \"jmp\\t__return_32\"; + return \"jmp\\t__return_16\"; + } }") (define_insn "*return_16bit" @@ -6039,7 +6794,12 @@ return \"\"; if (current_function_interrupt || current_function_trap) return \"rti\"; - return \"rts\"; + else if (!current_function_far) + return \"rts\"; + else if (TARGET_M6812) + return \"rtc\"; + else + return \"jmp\\t__return_16\"; }") (define_insn "*return_32bit" @@ -6056,7 +6816,12 @@ return \"\"; if (current_function_interrupt || current_function_trap) return \"rti\"; - return \"rts\"; + else if (!current_function_far) + return \"rts\"; + else if (TARGET_M6812) + return \"rtc\"; + else + return \"jmp\\t__return_32\"; }") (define_insn "indirect_jump" @@ -6088,6 +6853,571 @@ ;;- Peepholes ;;-------------------------------------------------------------------- +;;-------------------------------------------------------------------- +;;- 68HC12 dbcc/ibcc peepholes +;;-------------------------------------------------------------------- +;; +;; Replace: "addd #-1; bne L1" into "dbne d,L1" +;; "addd #-1; beq L1" into "dbeq d,L1" +;; "addd #1; bne L1" into "ibne d,L1" +;; "addd #1; beq L1" into "ibeq d,L1" +;; +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (plus:HI (match_dup 0) + (match_operand:HI 1 "const_int_operand" ""))) + (set (pc) + (if_then_else (match_operator 2 "m68hc11_eq_compare_operator" + [(match_dup 0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) (pc)))] + "TARGET_M6812 && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)" + [(parallel [ + (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)]) + (label_ref (match_dup 3)) (pc))) + (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1))) + (clobber (match_dup 4))])] + "operands[4] = gen_rtx_SCRATCH(HImode); + operands[5] = GEN_INT (-INTVAL (operands[1]));") + + +;; +;; Replace: "addb #-1; bne L1" into "dbne b,L1" +;; "addb #-1; beq L1" into "dbeq b,L1" +;; +(define_peephole2 + [(set (match_operand:QI 0 "hard_reg_operand" "") + (plus:QI (match_dup 0) + (match_operand:QI 1 "const_int_operand" ""))) + (set (pc) + (if_then_else (match_operator 2 "m68hc11_eq_compare_operator" + [(match_dup 0) + (const_int 0)]) + (label_ref (match_operand 3 "" "")) (pc)))] + "TARGET_M6812 && D_REG_P (operands[0]) + && (INTVAL (operands[1]) == 1 || INTVAL (operands[1]) == -1)" + [(parallel [ + (set (pc) (if_then_else (match_op_dup 2 [(match_dup 0) (match_dup 5)]) + (label_ref (match_dup 3)) (pc))) + (set (match_dup 0) (plus:QI (match_dup 0) (match_dup 1))) + (clobber (match_dup 4))])] + "operands[4] = gen_rtx_SCRATCH(QImode); + operands[5] = GEN_INT (-INTVAL (operands[1]));") + + +;;-------------------------------------------------------------------- +;;- Move peephole2 +;;-------------------------------------------------------------------- + +;; +;; Replace "leas 2,sp" with a "pulx" or a "puly". +;; On 68HC12, this is one cycle slower but one byte smaller. +;; pr target/6899: This peephole is not valid because a register CSE +;; pass removes the pulx/puly. +;; +(define_peephole2 + [(set (reg:HI SP_REGNUM) (plus:HI (reg:HI SP_REGNUM) (const_int 2))) + (match_scratch:HI 0 "xy")] + "0 && TARGET_M6812 && optimize_size" + [(set (match_dup 0) (match_dup 1))] + "operands[1] = gen_rtx_MEM (HImode, + gen_rtx_POST_INC (HImode, + gen_rtx_REG (HImode, HARD_SP_REGNUM)));") + +;; Replace: "pshx; tfr d,x; stx 0,sp" into "pshd; tfr d,x" +;; +;; PR 14542: emit a use to pretend we need the value of initial register. +;; Otherwise verify_local_live_at_start will abort due to a live change +;; of that register. +;; +(define_peephole2 + [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) + (match_operand:HI 0 "hard_reg_operand" "")) + (set (match_dup 0) + (match_operand:HI 1 "hard_reg_operand" "")) + (set (mem:HI (reg:HI SP_REGNUM)) + (match_dup 0))] + "TARGET_M6812" + [(use (match_dup 0)) + (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) + (match_dup 1)) + (set (match_dup 0) (match_dup 1))] + "") + +;; +;; Change: "ldd 0,sp; pulx" into "puld" +;; This sequence usually appears at end a functions. +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (mem:HI (reg:HI SP_REGNUM))) + (use (match_dup 0)) + (set (match_operand:HI 1 "hard_reg_operand" "") + (mem:HI (post_inc:HI (reg:HI SP_REGNUM))))] + "peep2_reg_dead_p (2, operands[1])" + [(set (match_dup 0) (mem:HI (post_inc:HI (reg:HI SP_REGNUM)))) + (use (match_dup 0))] + "") + +;; Replace: "pshx; clr 0,sp; clr 1,sp" by "clr 1,-sp; clr 1,-sp" +;; Appears to allocate local variables. +(define_peephole2 + [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) + (match_operand:HI 0 "hard_reg_operand" "")) + (set (mem:QI (plus:HI (reg:HI SP_REGNUM) (const_int 1))) + (const_int 0)) + (set (mem:QI (reg:HI SP_REGNUM)) + (const_int 0))] + "TARGET_M6812" + [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) + (const_int 0))] + "") + +;; Likewise for HI mode +(define_peephole2 + [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) + (match_operand:HI 0 "hard_reg_operand" "")) + (set (mem:HI (reg:HI SP_REGNUM)) + (const_int 0))] + "TARGET_M6812" + [(set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) + (const_int 0))] + "") +;;-------------------------------------------------------------------- +;;- +;;-------------------------------------------------------------------- +;; +;; Optimize memory<->memory moves when the value is also loaded in +;; a register. +;; +(define_peephole2 + [(set (match_operand:QI 0 "memory_operand" "") + (match_operand:QI 1 "memory_operand" "")) + (set (reg:QI D_REGNUM) + (match_operand:QI 2 "memory_operand" ""))] + "(rtx_equal_p (operands[0], operands[2]) && !side_effects_p (operands[0])) + || (GET_CODE (XEXP (operands[0], 0)) == REG + && GET_CODE (XEXP (operands[2], 0)) == POST_INC + && rtx_equal_p (XEXP (operands[0], 0), XEXP (XEXP (operands[2], 0), 0)))" + [(set (reg:QI D_REGNUM) (match_dup 1)) + (set (match_dup 2) (reg:QI D_REGNUM))] + "") + +;; +;; Remove a possible move before a compare instruction when that +;; move will go in a dead register. Compare with the source then. +;; +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (match_operand:HI 1 "hard_reg_operand" "")) + (set (cc0) + (compare (match_dup 0) + (match_operand:HI 2 "cmp_operand" "")))] + "(X_REG_P (operands[1]) || Y_REG_P (operands[1])) + && peep2_reg_dead_p (2, operands[0]) + && !reg_mentioned_p (operands[0], operands[2])" + [(set (cc0) (compare (match_dup 1) (match_dup 2)))] + "") + +;; +;; Optimize loading a constant to memory when that same constant +;; is loaded to a hard register. Switch the two to use the register +;; for memory initialization. In most cases, the constant is 0. +;; +(define_peephole2 + [(set (match_operand:HI 0 "memory_operand" "") + (match_operand:HI 1 "immediate_operand" "")) + (set (match_operand:HI 2 "hard_reg_operand" "") + (match_dup 1))] + "(D_REG_P (operands[2]) || X_REG_P (operands[2]) || Y_REG_P (operands[2])) + && !reg_mentioned_p (operands[2], operands[0])" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 0) (match_dup 2))] + "") + +;; +;; Reorganize to optimize address computations. +;; +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (match_operand:HI 1 "const_int_operand" "")) + (set (match_dup 0) + (plus:HI (match_dup 0) + (match_operand:HI 2 "general_operand" "")))] + "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)" + [(set (match_dup 0) (match_dup 2)) + (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))] + "") + +;; +;; Replace: "ldx #N; xgdx; addd ; xgdx" by "ldab #N; ldx ; abx" +;; +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (match_operand:HI 1 "const_int_operand" "")) + (set (match_dup 0) + (plus:HI (match_dup 0) + (match_operand:HI 2 "general_operand" ""))) + (match_scratch:QI 3 "d")] + "TARGET_M6811 && (INTVAL (operands[1]) >= 0 && INTVAL (operands[1]) <= 0x0ff)" + [(set (match_dup 3) (match_dup 4)) + (set (match_dup 0) (match_dup 2)) + (set (match_dup 0) (plus:HI (zero_extend:HI (match_dup 3)) (match_dup 0)))] + "operands[4] = m68hc11_gen_lowpart (QImode, operands[1]);") + +;; +;; Replace: "ldx #N; xgdx; addd ; xgdx" by "ldab #N; ldx ; abx" +;; +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (match_operand:HI 1 "const_int_operand" "")) + (set (match_dup 0) + (plus:HI (match_dup 0) + (match_operand:HI 2 "general_operand" "")))] + "TARGET_M6812" + [(set (match_dup 0) (match_dup 2)) + (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))] + "") + +;; +;; Optimize an address register increment and a compare to use +;; a PRE_INC or PRE_DEC addressing mode (disabled on the tst insn +;; before reload, but can be enabled after). +;; +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (plus:HI (match_dup 0) + (match_operand:HI 1 "const_int_operand" ""))) + (set (cc0) + (match_operand:QI 2 "memory_operand" ""))] + "TARGET_AUTO_INC_DEC + && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1) + && reg_mentioned_p (operands[0], operands[2])" + [(set (cc0) (match_dup 3))] + "if (INTVAL (operands[1]) == 1) + operands[3] = gen_rtx_MEM (QImode, + gen_rtx_PRE_INC (HImode, operands[0])); + else + operands[3] = gen_rtx_MEM (QImode, + gen_rtx_PRE_DEC (HImode, operands[0])); + ") + +;; +;; Likewise for compare. +;; +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (plus:HI (match_dup 0) + (match_operand:HI 1 "const_int_operand" ""))) + (set (cc0) + (compare (match_operand:QI 2 "hard_reg_operand" "") + (match_operand:QI 3 "memory_operand" "")))] + "TARGET_AUTO_INC_DEC + && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1) + && reg_mentioned_p (operands[0], operands[3])" + [(set (cc0) (compare (match_dup 2) (match_dup 4)))] + "if (INTVAL (operands[1]) == 1) + operands[4] = gen_rtx_MEM (QImode, + gen_rtx_PRE_INC (HImode, operands[0])); + else + operands[4] = gen_rtx_MEM (QImode, + gen_rtx_PRE_DEC (HImode, operands[0])); + ") + +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (plus:HI (match_dup 0) + (match_operand:HI 1 "const_int_operand" ""))) + (set (cc0) + (compare (match_operand:QI 2 "memory_operand" "") + (match_operand:QI 3 "hard_reg_operand" "")))] + "TARGET_AUTO_INC_DEC + && (INTVAL (operands[1]) == -1 || INTVAL (operands[1]) == 1) + && reg_mentioned_p (operands[0], operands[2])" + [(set (cc0) (compare (match_dup 4) (match_dup 3)))] + "if (INTVAL (operands[1]) == 1) + operands[4] = gen_rtx_MEM (QImode, + gen_rtx_PRE_INC (HImode, operands[0])); + else + operands[4] = gen_rtx_MEM (QImode, + gen_rtx_PRE_DEC (HImode, operands[0])); + ") + +;; +;; Replace a "ldx #N; addx " with a "ldx ; addx #n" +;; (avoids many temporary moves because we can't add sp to another reg easily) +;; +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (match_operand:HI 1 "const_int_operand" "")) + (set (match_dup 0) (plus:HI (match_dup 0) (reg:HI SP_REGNUM)))] + "" + [(set (match_dup 0) (reg:HI SP_REGNUM)) + (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))] + "") + +;; +;; Replace "ldd #N; addd " with "ldd ; addd #N". +;; +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (match_operand:HI 1 "const_int_operand" "")) + (set (match_dup 0) + (plus:HI (match_dup 0) + (match_operand:HI 2 "general_operand" "")))] + "(INTVAL (operands[1]) >= -2 && INTVAL (operands[1]) <= 2)" + [(set (match_dup 0) (match_dup 2)) + (set (match_dup 0) (plus:HI (match_dup 0) (match_dup 1)))] + "") + +;; +;; +;; +(define_peephole2 + [(parallel + [(set (match_operand:SI 0 "hard_reg_operand" "") + (ashift:SI (match_operand:SI 1 "general_operand" "") + (const_int 1))) + (clobber (match_scratch:HI 2 ""))]) + (set (match_operand:HI 3 "nonimmediate_operand" "") (reg:HI D_REGNUM)) + (set (match_operand:HI 4 "nonimmediate_operand" "") (reg:HI X_REGNUM))] + "!X_REG_P (operands[1]) + && peep2_reg_dead_p (2, gen_rtx_REG (HImode, D_REGNUM)) + && peep2_reg_dead_p (3, gen_rtx_REG (HImode, X_REGNUM))" + [(set (reg:HI D_REGNUM) (match_dup 5)) + (set (reg:HI D_REGNUM) (ashift:HI (reg:HI D_REGNUM) (const_int 1))) + (set (match_dup 3) (reg:HI D_REGNUM)) + (set (reg:HI D_REGNUM) (match_dup 6)) + (parallel [(set (reg:HI D_REGNUM) + (rotate:HI (reg:HI D_REGNUM) (const_int 1))) + (clobber (reg:HI CC_REGNUM))]) + (set (match_dup 4) (reg:HI D_REGNUM))] + "operands[5] = m68hc11_gen_lowpart (HImode, operands[1]); + operands[6] = m68hc11_gen_highpart (HImode, operands[1]);") + +;; +;; Replace a "ldd ; psha; pshb" with a "ldx ; pshx". +;; +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (match_operand:HI 1 "memory_operand" "")) + (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) + (match_dup 0)) + (match_scratch:HI 2 "x")] + "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (2, operands[0])" + [(set (match_dup 2) (match_dup 1)) + (set (mem:HI (pre_dec:HI (reg:HI SP_REGNUM))) (match_dup 2))] + "") + +;; +;; Remove one load when copying a value to/from memory and also +;; to a register. Take care not clobbering a possible register used +;; by operand 2. +;; Replace: "ldd 0,y; std 2,y; ldx 0,y" into "ldx 0,y; stx 2,y" +;; +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (match_operand:HI 1 "general_operand" "")) + (set (match_operand:HI 2 "nonimmediate_operand" "") (match_dup 0)) + (set (match_operand:HI 3 "hard_reg_operand" "") (match_dup 1))] + "peep2_reg_dead_p (2, operands[0]) + && !side_effects_p (operands[1]) + && !side_effects_p (operands[2]) + && !reg_mentioned_p (operands[3], operands[2])" + [(set (match_dup 3) (match_dup 1)) + (set (match_dup 2) (match_dup 3))] + "") + +;; +;; Replace a "ldd ; addd #N; std " into a +;; "ldx ; leax; stx " if we have a free X/Y register +;; and the constant is small. +;; +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (match_operand:HI 1 "general_operand" "")) + (set (match_dup 0) (plus:HI (match_dup 0) + (match_operand:HI 2 "const_int_operand" ""))) + (set (match_operand:HI 3 "nonimmediate_operand" "") + (match_dup 0)) + (match_scratch:HI 4 "xy")] + "D_REG_P (operands[0]) + && (TARGET_M6812 + || (INTVAL (operands[2]) >= -2 && INTVAL (operands[2]) <= 2)) + && peep2_reg_dead_p (3, operands[0])" + [(set (match_dup 4) (match_dup 1)) + (set (match_dup 4) (plus:HI (match_dup 4) (match_dup 2))) + (set (match_dup 3) (match_dup 4))] + "if (reg_mentioned_p (operands[4], operands[1])) FAIL; + if (reg_mentioned_p (operands[4], operands[3])) FAIL;") + +;;-------------------------------------------------------------------- +;;- Bset peephole2 +;;-------------------------------------------------------------------- +;; These peepholes try to replace some logical sequences by 'bset' and 'bclr'. +;; +;; Replace 'ldab ; orab #N; stab ' by 'bset #N'. +;; Register D must be dead and there must be no register side effects for mem. +;; The *can* be volatile this is why we must not use 'side_effects_p'. +;; The good side effect is that it makes the sequence atomic. +;; +(define_peephole2 + [(set (match_operand:QI 0 "hard_reg_operand" "") + (match_operand:QI 1 "nonimmediate_operand" "")) + (set (match_dup 0) (ior:QI (match_dup 0) + (match_operand:QI 2 "const_int_operand" ""))) + (set (match_dup 1) (match_dup 0))] + "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode)) + && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0))) + && peep2_reg_dead_p (3, operands[0])" + [(set (match_dup 1) (ior:QI (match_dup 1) (match_dup 2)))] + "") + +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (match_operand:HI 1 "nonimmediate_operand" "")) + (set (match_dup 0) (ior:HI (match_dup 0) + (match_operand:HI 2 "const_int_operand" ""))) + (set (match_dup 1) (match_dup 0))] + "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode)) + && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0))) + && peep2_reg_dead_p (3, operands[0])" + [(set (match_dup 1) (ior:HI (match_dup 1) (match_dup 2)))] + "") + +;;-------------------------------------------------------------------- +;;- Bclr peephole2 +;;-------------------------------------------------------------------- +;; Replace 'ldab ; andab #N; stab ' by 'bclr #N'. +;; See Bset peephole2. +;; +(define_peephole2 + [(set (match_operand:QI 0 "hard_reg_operand" "") + (match_operand:QI 1 "nonimmediate_operand" "")) + (set (match_dup 0) (and:QI (match_dup 0) + (match_operand:QI 2 "const_int_operand" ""))) + (set (match_dup 1) (match_dup 0))] + "(TARGET_M6812 || m68hc11_indirect_p (operands[1], QImode)) + && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0))) + && peep2_reg_dead_p (3, operands[0])" + [(set (match_dup 1) (and:QI (match_dup 1) (match_dup 2)))] + "") + +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (match_operand:HI 1 "nonimmediate_operand" "")) + (set (match_dup 0) (and:HI (match_dup 0) + (match_operand:HI 2 "const_int_operand" ""))) + (set (match_dup 1) (match_dup 0))] + "(TARGET_M6812 || m68hc11_indirect_p (operands[1], HImode)) + && (GET_CODE (operands[1]) != MEM || !auto_inc_p (XEXP (operands[1], 0))) + && peep2_reg_dead_p (3, operands[0])" + [(set (match_dup 1) (and:HI (match_dup 1) (match_dup 2)))] + "") + + +;;-------------------------------------------------------------------- +;;- Compare peephole2 +;;-------------------------------------------------------------------- +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (match_operand:HI 1 "hard_reg_operand" "")) + (set (match_dup 1) (plus:HI (match_dup 1) + (match_operand:HI 2 "const_int_operand" ""))) + (set (cc0) (match_dup 0))] + "peep2_reg_dead_p (3, operands[0]) && !Z_REG_P (operands[1])" + [(set (match_dup 1) (plus:HI (match_dup 1) (match_dup 2))) + (set (cc0) (compare (match_dup 1) (match_dup 2)))] + "") + +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (match_operand:HI 1 "hard_reg_operand" "")) + (set (match_operand:HI 2 "hard_reg_operand" "") + (plus:HI (match_dup 2) + (match_operand:HI 3 "const_int_operand" ""))) + (set (match_operand:HI 4 "memory_operand" "") (match_dup 2)) + (set (cc0) (match_operand:HI 5 "hard_reg_operand" ""))] + "peep2_reg_dead_p (4, operands[5]) && !Z_REG_P (operands[2]) + && !reg_mentioned_p (operands[2], operands[4]) + + && ((rtx_equal_p (operands[5], operands[0]) + && rtx_equal_p (operands[2], operands[1])) + + || (rtx_equal_p (operands[5], operands[1]) + && rtx_equal_p (operands[2], operands[0])))" + [(set (match_dup 2) (match_dup 1)) + (set (match_dup 2) (plus:HI (match_dup 2) (match_dup 3))) + (set (match_dup 4) (match_dup 2)) + (set (cc0) (compare (match_dup 2) (match_dup 3)))] + "") + + +;;-------------------------------------------------------------------- +;;- Load peephole2 +;;-------------------------------------------------------------------- +;; +;; Optimize initialization of 2 hard regs from the same memory location +;; Since we can't copy easily X, Y and D to each other, load the 2 registers +;; from the same memory location. +;; +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") + (match_operand:HI 1 "memory_operand" "")) + (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))] + "TARGET_M6811 + && !side_effects_p (operands[1]) + && !reg_mentioned_p (operands[0], operands[1])" + [(set (match_dup 0) (match_dup 1)) + (set (match_dup 2) (match_dup 1))] + "") + +;; Replace "ldd #N; addd " with "ldd ; addd #N". +;; +(define_peephole2 + [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0)) + (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0)) + (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0)) + (set (match_operand:HI 3 "nonimmediate_operand" "") (const_int 0)) + (match_scratch:HI 4 "d")] + "" + [(set (match_dup 4) (const_int 0)) + (set (match_dup 0) (match_dup 4)) + (set (match_dup 1) (match_dup 4)) + (set (match_dup 2) (match_dup 4)) + (set (match_dup 3) (match_dup 4))] + "") + +;; +;; Replace "ldd #N; addd " with "ldd ; addd #N". +;; +(define_peephole2 + [(set (match_operand:HI 0 "nonimmediate_operand" "") (const_int 0)) + (set (match_operand:HI 1 "nonimmediate_operand" "") (const_int 0)) + (set (match_operand:HI 2 "nonimmediate_operand" "") (const_int 0)) + (match_scratch:HI 3 "d")] + "" + [(set (match_dup 3) (const_int 0)) + (set (match_dup 0) (match_dup 3)) + (set (match_dup 1) (match_dup 3)) + (set (match_dup 2) (match_dup 3))] + "") + +;; +;; Replace "ldd #N; addd " with "ldd ; addd #N". +;; +(define_peephole2 + [(set (match_operand:HI 0 "hard_reg_operand" "") (const_int 0)) + (set (match_operand:HI 1 "push_operand" "") (match_dup 0)) + (set (match_operand:HI 2 "push_operand" "") (match_dup 0)) + (set (match_operand:HI 3 "push_operand" "") (match_dup 0)) + (match_scratch:HI 4 "x")] + "TARGET_M6811 && D_REG_P (operands[0]) && peep2_reg_dead_p (4, operands[0])" + [(set (match_dup 4) (const_int 0)) + (set (match_dup 1) (match_dup 4)) + (set (match_dup 2) (match_dup 4)) + (set (match_dup 3) (match_dup 4))] + "") + ;; ;; This peephole catches the address computations generated by the reload ;; pass. @@ -6106,9 +7436,14 @@ { int value_loaded = 1; - if (X_REG_P (operands[0])) + if (X_REG_P (operands[0]) || SP_REG_P (operands[2])) { - output_asm_insn (\"ldx\\t%2\\n\\txgdx\", operands); + rtx ops[2]; + + ops[0] = operands[0]; + ops[1] = operands[2]; + m68hc11_gen_movhi (insn, ops); + output_asm_insn (\"xgd%0\", operands); } else if (Y_REG_P (operands[0])) { @@ -6127,7 +7462,7 @@ output_asm_insn (\"ldd\\t%2\", operands); if ((INTVAL (operands[1]) & 0x0ff00) == 0x100) output_asm_insn (\"inca\", operands); - else if (INTVAL (operands[1]) & 0x0ff00 == 0xff00) + else if ((INTVAL (operands[1]) & 0x0ff00) == 0xff00) output_asm_insn (\"deca\", operands); else if (INTVAL (operands[1]) != 0) output_asm_insn (\"adda\\t%h1\", operands); @@ -6223,7 +7558,7 @@ rtx ops[2]; ops[0] = operands[0]; - ops[1] = gen_rtx (REG, HImode, HARD_D_REGNUM); + ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM); m68hc11_gen_movhi (insn, ops); return \"\"; } @@ -6231,7 +7566,7 @@ ;;; ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't -;;; need to emit anything. Otherwise, we just need an copy of D to X/Y. +;;; need to emit anything. Otherwise, we just need a copy of D to X/Y. ;;; (define_peephole [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A")) @@ -6247,7 +7582,7 @@ ;;; ;;; Catch an xgdx/xgdy followed by a (set D X/Y). If X/Y is dead, we don't -;;; need to emit anything. Otherwise, we just need an copy of D to X/Y. +;;; need to emit anything. Otherwise, we just need a copy of D to X/Y. ;;; (define_peephole [(parallel [(set (reg:HI D_REGNUM) (match_operand:HI 0 "hard_reg_operand" "A")) @@ -6276,7 +7611,7 @@ rtx ops[2]; ops[0] = operands[0]; - ops[1] = gen_rtx (REG, HImode, HARD_D_REGNUM); + ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM); m68hc11_gen_movhi (insn, ops); return \"\"; } @@ -6296,7 +7631,7 @@ rtx ops[2]; ops[0] = operands[0]; - ops[1] = gen_rtx (REG, HImode, HARD_D_REGNUM); + ops[1] = gen_rtx_REG (HImode, HARD_D_REGNUM); m68hc11_gen_movhi (insn, ops); return \"\"; } @@ -6333,8 +7668,8 @@ rtx ops[2]; ops[0] = operands[2]; - ops[1] = gen_rtx (MEM, HImode, - gen_rtx (POST_INC, HImode, stack_pointer_rtx)); + ops[1] = gen_rtx_MEM (HImode, + gen_rtx_POST_INC (HImode, stack_pointer_rtx)); m68hc11_gen_movhi (insn, ops); return \"\"; } @@ -6352,3 +7687,41 @@ return \"sts\\t%t0\\n\\tld%0\\t%t0\"; } ") + +(define_peephole + [(set (match_operand:HI 0 "hard_reg_operand" "") + (match_operand:HI 1 "memory_operand" "")) + (set (match_operand:HI 2 "hard_reg_operand" "") (match_dup 0))] + "TARGET_M6811 + && !side_effects_p (operands[1]) + && !reg_mentioned_p (operands[0], operands[1])" + "* +{ + rtx ops[2]; + + ops[0] = operands[0]; + ops[1] = operands[1]; + m68hc11_gen_movhi (insn, ops); + ops[0] = operands[2]; + m68hc11_gen_movhi (insn, ops); + return \"\"; +}") + +;; Peephole for Z register replacement. +;; Avoid to use _.tmp register when comparing D and X if we can compare +;; with soft register +(define_peephole + [(set (match_operand:HI 0 "hard_reg_operand" "") (reg:HI SOFT_XY_REGNUM)) + (set (reg:HI SOFT_TMP_REGNUM) (match_dup 0)) + (set (cc0) (compare (match_operand:HI 2 "hard_reg_operand" "") + (reg:HI SOFT_TMP_REGNUM)))] + "X_REG_P (operands[0]) || Y_REG_P (operands[0])" + "* +{ + rtx ops[2]; + + ops[0] = operands[0]; + ops[1] = operands[1]; + m68hc11_gen_movhi (insn, ops); + return \"cp%2\\t%1\"; +}")