X-Git-Url: https://oss.titaniummirror.com/gitweb?a=blobdiff_plain;f=gcc%2Fconfig%2Fmn10300%2Fmn10300.md;fp=gcc%2Fconfig%2Fmn10300%2Fmn10300.md;h=35b0e589cb55c69e48d236290482f75404b10e01;hb=6fed43773c9b0ce596dca5686f37ac3fc0fa11c0;hp=31239559192bf5dda05012faa4740b12affd0ef4;hpb=27b11d56b743098deb193d510b337ba22dc52e5c;p=msp430-gcc.git diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md index 31239559..35b0e589 100644 --- a/gcc/config/mn10300/mn10300.md +++ b/gcc/config/mn10300/mn10300.md @@ -1,24 +1,23 @@ ;; GCC machine description for Matsushita MN10300 -;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 -;; Free Software Foundation, Inc. +;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, +;; 2007, 2008 Free Software Foundation, Inc. ;; Contributed by Jeff Law (law@cygnus.com). -;; 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) +;; the Free Software Foundation; either version 3, 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 -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. +;; along with GCC; see the file COPYING3. If not see +;; . ;; The original PO technology requires these to be ordered by speed, ;; so that assigner will pick the fastest. @@ -33,10 +32,24 @@ ;; set_znv - insn sets z,n,v to usable values; c is unusable. ;; set_zn - insn sets z,n to usable values; v,c are unusable. ;; compare - compare instruction -;; invert -- like compare, but flags are inverted. ;; clobber - value of cc is unknown -(define_attr "cc" "none,none_0hit,set_znv,set_zn,compare,clobber,invert" +(define_attr "cc" "none,none_0hit,set_znv,set_zn,compare,clobber" (const_string "clobber")) + +(define_constants [ + (PIC_REG 6) + (SP_REG 9) + + (UNSPEC_INT_LABEL 0) + (UNSPEC_PIC 1) + (UNSPEC_GOT 2) + (UNSPEC_GOTOFF 3) + (UNSPEC_PLT 4) + (UNSPEC_GOTSYM_OFF 5) +]) + +(include "predicates.md") +(include "constraints.md") ;; ---------------------------------------------------------------------- ;; MOVE INSTRUCTIONS @@ -57,8 +70,8 @@ }") (define_insn "" - [(set (match_operand:QI 0 "nonimmediate_operand" "=d*x*a,d*x,d*x*a,d*x*a,m") - (match_operand:QI 1 "general_operand" "0,I,d*xai,m,d*xa"))] + [(set (match_operand:QI 0 "nonimmediate_operand" "=d*x*a*f,d*x,d*x*a,d*x*a,m,*f,d*x*a") + (match_operand:QI 1 "general_operand" "0,I,d*xai,m,d*xa,d*xa*f,*f"))] "TARGET_AM33 && (register_operand (operands[0], QImode) || register_operand (operands[1], QImode))" @@ -93,15 +106,18 @@ case 3: case 4: return \"movbu %1,%0\"; + case 5: + case 6: + return \"fmov %1,%0\"; default: - abort (); + gcc_unreachable (); } }" - [(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit")]) + [(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) (define_insn "" - [(set (match_operand:QI 0 "nonimmediate_operand" "=d*a,d,d*a,d,m") - (match_operand:QI 1 "general_operand" "0,I,dai,m,d"))] + [(set (match_operand:QI 0 "nonimmediate_operand" "=d*a,d,d,!*a,d*a,d,m") + (match_operand:QI 1 "general_operand" "0,I,i,i,da,m,d"))] "register_operand (operands[0], QImode) || register_operand (operands[1], QImode)" "* @@ -113,6 +129,8 @@ case 1: return \"clr %0\"; case 2: + case 3: + case 4: if (GET_CODE (operands[1]) == CONST_DOUBLE) { rtx xoperands[2]; @@ -123,14 +141,14 @@ } return \"mov %1,%0\"; - case 3: - case 4: + case 5: + case 6: return \"movbu %1,%0\"; default: - abort (); + gcc_unreachable (); } }" - [(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit")]) + [(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) ;; movhi @@ -147,8 +165,8 @@ }") (define_insn "" - [(set (match_operand:HI 0 "nonimmediate_operand" "=d*x*a,d*x,d*x*a,d*x*a,m") - (match_operand:HI 1 "general_operand" "0,I,d*x*ai,m,d*x*a"))] + [(set (match_operand:HI 0 "nonimmediate_operand" "=d*x*a*f,d*x,d*x*a,d*x*a,m,*f,d*x*a") + (match_operand:HI 1 "general_operand" "0,I,d*x*ai,m,d*x*a,d*x*a*f,*f"))] "TARGET_AM33 && (register_operand (operands[0], HImode) || register_operand (operands[1], HImode))" @@ -183,15 +201,18 @@ case 3: case 4: return \"movhu %1,%0\"; + case 5: + case 6: + return \"fmov %1,%0\"; default: - abort (); + gcc_unreachable (); } }" - [(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit")]) + [(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) (define_insn "" - [(set (match_operand:HI 0 "nonimmediate_operand" "=d*a,d,d*a,d,m") - (match_operand:HI 1 "general_operand" "0,I,dai,m,d"))] + [(set (match_operand:HI 0 "nonimmediate_operand" "=d*a,d,d,!*a,d*a,d,m") + (match_operand:HI 1 "general_operand" "0,I,i,i,da,m,d"))] "register_operand (operands[0], HImode) || register_operand (operands[1], HImode)" "* @@ -203,6 +224,8 @@ case 1: return \"clr %0\"; case 2: + case 3: + case 4: if (GET_CODE (operands[1]) == CONST_DOUBLE) { rtx xoperands[2]; @@ -212,14 +235,14 @@ return \"\"; } return \"mov %1,%0\"; - case 3: - case 4: + case 5: + case 6: return \"movhu %1,%0\"; default: - abort (); + gcc_unreachable (); } }" - [(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit")]) + [(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) ;; movsi and helpers @@ -263,6 +286,12 @@ DONE; }") +(define_insn "pop_pic_reg" + [(set (reg:SI PIC_REG) + (mem:SI (post_inc:SI (reg:SI SP_REG))))] + "reload_completed" + "movm (sp),[a2]") + (define_expand "movsi" [(set (match_operand:SI 0 "general_operand" "") (match_operand:SI 1 "general_operand" ""))] @@ -273,13 +302,43 @@ if (!register_operand (operand1, SImode) && !register_operand (operand0, SImode)) operands[1] = copy_to_mode_reg (SImode, operand1); + if (flag_pic) + { + rtx temp; + if (SYMBOLIC_CONST_P (operands[1])) + { + if (GET_CODE (operands[0]) == MEM) + operands[1] = force_reg (Pmode, operands[1]); + else + { + temp = (!can_create_pseudo_p () + ? operands[0] + : gen_reg_rtx (Pmode)); + operands[1] = legitimize_pic_address (operands[1], temp); + } + } + else if (GET_CODE (operands[1]) == CONST + && GET_CODE (XEXP (operands[1], 0)) == PLUS + && SYMBOLIC_CONST_P (XEXP (XEXP (operands[1], 0), 0))) + { + temp = !can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode); + temp = legitimize_pic_address (XEXP (XEXP (operands[1], 0), 0), + temp); + operands[1] = expand_binop (SImode, add_optab, temp, + XEXP (XEXP (operands[1], 0), 1), + (!can_create_pseudo_p () + ? temp + : gen_reg_rtx (Pmode)), + 0, OPTAB_LIB_WIDEN); + } + } }") (define_insn "" [(set (match_operand:SI 0 "nonimmediate_operand" - "=dx,ax,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax,axR,!*y") + "=dx,ax,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax,axR,!*y,*f,*f,dxaQ") (match_operand:SI 1 "general_operand" - "0,0,I,I,dx,ax,dx,ax,dixm,aixm,dixm,aixm,!*y,axR"))] + "0,0,I,I,dx,ax,dx,ax,dixm,aixm,dixm,aixm,!*y,axR,0,dxaQi*f,*f"))] "register_operand (operands[0], SImode) || register_operand (operands[1], SImode)" "* @@ -321,11 +380,16 @@ return \"movu %1,%0\"; } return \"mov %1,%0\"; + case 14: + return \"nop\"; + case 15: + case 16: + return \"fmov %1,%0\"; default: - abort (); + gcc_unreachable (); } }" - [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) + [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none,none_0hit,none_0hit")]) (define_expand "movsf" [(set (match_operand:SF 0 "general_operand" "") @@ -340,8 +404,8 @@ }") (define_insn "" - [(set (match_operand:SF 0 "nonimmediate_operand" "=dx,ax,dx,a,daxm,dax") - (match_operand:SF 1 "general_operand" "0,0,G,G,dax,daxFm"))] + [(set (match_operand:SF 0 "nonimmediate_operand" "=f,dx,ax,dx,a,f,dxaQ,daxm,dax") + (match_operand:SF 1 "general_operand" "0,0,0,G,G,fdxaQF,f,dax,daxFm"))] "register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode)" "* @@ -350,12 +414,17 @@ { case 0: case 1: - return \"nop\"; case 2: - return \"clr %0\"; + return \"nop\"; case 3: - case 4: + return \"clr %0\"; + /* case 4: below */ case 5: + case 6: + return \"fmov %1, %0\"; + case 4: + case 7: + case 8: if (REGNO_REG_CLASS (true_regnum (operands[0])) == EXTENDED_REGS && GET_CODE (operands[1]) == CONST_INT) { @@ -367,10 +436,10 @@ } return \"mov %1,%0\"; default: - abort (); + gcc_unreachable (); } }" - [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit")]) + [(set_attr "cc" "none,none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) (define_expand "movdi" [(set (match_operand:DI 0 "general_operand" "") @@ -386,9 +455,9 @@ (define_insn "" [(set (match_operand:DI 0 "nonimmediate_operand" - "=dx,ax,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax") + "=dx,ax,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax,*f,*f,*f,dxa,*f,Q") (match_operand:DI 1 "general_operand" - "0,0,I,I,dx,ax,dx,ax,dxim,axim,dxim,axim"))] + "0,0,I,I,dx,ax,dx,ax,dxim,axim,dxim,axim,0,*f,dxai,*f,Q,*f"))] "register_operand (operands[0], DImode) || register_operand (operands[1], DImode)" "* @@ -448,15 +517,14 @@ while (GET_CODE (temp) == SUBREG) temp = SUBREG_REG (temp); - if (GET_CODE (temp) != REG) - abort (); + gcc_assert (GET_CODE (temp) == REG); if (reg_overlap_mentioned_p (gen_rtx_REG (SImode, REGNO (temp)), XEXP (operands[1], 0))) return \"mov %H1,%H0\;mov %L1,%L0\"; else return \"mov %L1,%L0\;mov %H1,%H0\"; - + } else if (GET_CODE (operands[1]) == MEM && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)) @@ -488,7 +556,7 @@ == EXTENDED_REGS) && (((val[0] & 0x80) && ! (val[0] & 0xffffff00)) || ((val[0] & 0x800000) && ! (val[0] & 0xff000000)))) - output_asm_insn (\"movu %1,%0\", operands); + output_asm_insn (\"movu %L1,%L0\", operands); else output_asm_insn (\"mov %L1,%L0\", operands); @@ -511,16 +579,56 @@ == EXTENDED_REGS) && (((val[1] & 0x80) && ! (val[1] & 0xffffff00)) || ((val[1] & 0x800000) && ! (val[1] & 0xff000000)))) - output_asm_insn (\"movu %1,%0\", operands); + output_asm_insn (\"movu %H1,%H0\", operands); else output_asm_insn (\"mov %H1,%H0\", operands); return \"\"; } + case 12: + return \"nop\"; + case 13: + case 14: + case 15: + return \"fmov %L1, %L0\;fmov %H1, %H0\"; + case 16: + if (GET_CODE (operands[1]) == MEM + && GET_CODE (XEXP (operands[1], 0)) == CONST_INT + && (INTVAL (XEXP (operands[1], 0)) & 7) == 0) + return \"fmov %D1, %D0\"; + else + return \"fmov %L1, %L0\;fmov %H1, %H0\"; + case 17: + if (GET_CODE (operands[0]) == MEM + && GET_CODE (XEXP (operands[0], 0)) == CONST_INT + && (INTVAL (XEXP (operands[0], 0)) & 7) == 0) + return \"fmov %D1, %D0\"; + else + return \"fmov %L1, %L0\;fmov %H1, %H0\"; default: - abort (); + gcc_unreachable (); } }" - [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) + [(set (attr "cc") + (cond + [ + (ior (lt (symbol_ref "which_alternative") (const_int 2)) + (eq (symbol_ref "which_alternative") (const_int 12)) + ) (const_string "none") + (eq (symbol_ref "which_alternative") (const_int 2) + ) (const_string "clobber") + (eq (symbol_ref "which_alternative") (const_int 3) + ) (if_then_else + (ne (symbol_ref "rtx_equal_p (operands[0], operands[1])") + (const_int 0)) (const_string "clobber") + (const_string "none_0hit")) + (ior (eq (symbol_ref "which_alternative") (const_int 8)) + (eq (symbol_ref "which_alternative") (const_int 9)) + ) (if_then_else + (ne (symbol_ref "mn10300_wide_const_load_uses_clr + (operands)") + (const_int 0)) (const_string "clobber") + (const_string "none_0hit")) + ] (const_string "none_0hit")))]) (define_expand "movdf" [(set (match_operand:DF 0 "general_operand" "") @@ -536,9 +644,9 @@ (define_insn "" [(set (match_operand:DF 0 "nonimmediate_operand" - "=dx,ax,dx,a,dxm,dxm,axm,axm,dx,dx,ax,ax") + "=f,dx,ax,dx,f,f,dxa,f,Q,a,dxm,dxm,axm,axm,dx,dx,ax,ax") (match_operand:DF 1 "general_operand" - "0,0,G,G,dx,ax,dx,ax,dxFm,axFm,dxFm,axFm"))] + "0,0,0,G,f,dxaF,f,Q,f,G,dx,ax,dx,ax,dxFm,axFm,dxFm,axFm"))] "register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode)" "* @@ -550,24 +658,46 @@ { case 0: case 1: + case 2: return \"nop\"; - case 2: + case 3: return \"clr %L0\;clr %H0\"; - case 3: - if (rtx_equal_p (operands[0], operands[1])) - return \"sub %L1,%L0\;mov %L0,%H0\"; - else - return \"mov %1,%L0\;mov %L0,%H0\"; case 4: case 5: case 6: + return \"fmov %L1, %L0\;fmov %H1, %H0\"; + case 7: + if (GET_CODE (operands[1]) == MEM + && GET_CODE (XEXP (operands[1], 0)) == CONST_INT + && (INTVAL (XEXP (operands[1], 0)) & 7) == 0) + return \"fmov %D1, %D0\"; + else + return \"fmov %L1, %L0\;fmov %H1, %H0\"; + case 8: + if (GET_CODE (operands[0]) == MEM + && GET_CODE (XEXP (operands[0], 0)) == CONST_INT + && (INTVAL (XEXP (operands[0], 0)) & 7) == 0) + return \"fmov %D1, %D0\"; + else + return \"fmov %L1, %L0\;fmov %H1, %H0\"; + case 9: + if (rtx_equal_p (operands[0], operands[1])) + return \"sub %L1,%L0\;mov %L0,%H0\"; + else + return \"mov %1,%L0\;mov %L0,%H0\"; case 10: case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: if (GET_CODE (operands[1]) == CONST_INT) { rtx low, high; @@ -598,15 +728,14 @@ while (GET_CODE (temp) == SUBREG) temp = SUBREG_REG (temp); - if (GET_CODE (temp) != REG) - abort (); + gcc_assert (GET_CODE (temp) == REG); if (reg_overlap_mentioned_p (gen_rtx_REG (SImode, REGNO (temp)), XEXP (operands[1], 0))) return \"mov %H1,%H0\;mov %L1,%L0\"; else return \"mov %L1,%L0\;mov %H1,%H0\"; - + } else if (GET_CODE (operands[1]) == MEM && CONSTANT_ADDRESS_P (XEXP (operands[1], 0)) @@ -638,7 +767,7 @@ == EXTENDED_REGS) && (((val[0] & 0x80) && ! (val[0] & 0xffffff00)) || ((val[0] & 0x800000) && ! (val[0] & 0xff000000)))) - output_asm_insn (\"movu %1,%0\", operands); + output_asm_insn (\"movu %L1,%L0\", operands); else output_asm_insn (\"mov %L1,%L0\", operands); @@ -661,16 +790,35 @@ == EXTENDED_REGS) && (((val[1] & 0x80) && ! (val[1] & 0xffffff00)) || ((val[1] & 0x800000) && ! (val[1] & 0xff000000)))) - output_asm_insn (\"movu %1,%0\", operands); + output_asm_insn (\"movu %H1,%H0\", operands); else output_asm_insn (\"mov %H1,%H0\", operands); return \"\"; } default: - abort (); + gcc_unreachable (); } }" - [(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")]) + [(set (attr "cc") + (cond + [ + (lt (symbol_ref "which_alternative") (const_int 3) + ) (const_string "none") + (eq (symbol_ref "which_alternative") (const_int 3) + ) (const_string "clobber") + (eq (symbol_ref "which_alternative") (const_int 9) + ) (if_then_else + (ne (symbol_ref "rtx_equal_p (operands[0], operands[1])") + (const_int 0)) (const_string "clobber") + (const_string "none_0hit")) + (ior (eq (symbol_ref "which_alternative") (const_int 14)) + (eq (symbol_ref "which_alternative") (const_int 15)) + ) (if_then_else + (ne (symbol_ref "mn10300_wide_const_load_uses_clr + (operands)") + (const_int 0)) (const_string "clobber") + (const_string "none_0hit")) + ] (const_string "none_0hit")))]) @@ -718,7 +866,7 @@ ;; but will have the proper effect on cc0. Using d0 is arbitrary; any ;; data register would work.) -;; Even though the first alternative would be preferrable if it can +;; Even though the first alternative would be preferable if it can ;; possibly match, reload must not be given the opportunity to attempt ;; to use it. It assumes that such matches can only occur when one of ;; the operands is used for input and the other for output. Since @@ -735,6 +883,14 @@ btst 0,d0 cmp %1,%0" [(set_attr "cc" "compare,compare")]) + +(define_insn "cmpsf" + [(set (cc0) + (compare (match_operand:SF 0 "register_operand" "f,f") + (match_operand:SF 1 "nonmemory_operand" "f,F")))] + "TARGET_AM33_2" + "fcmp %1,%0" + [(set_attr "cc" "compare,compare")]) ;; ---------------------------------------------------------------------- ;; ADD INSTRUCTIONS @@ -772,7 +928,7 @@ src1_class = REGNO_REG_CLASS (true_regnum (operands[1])); src2_class = REGNO_REG_CLASS (true_regnum (operands[2])); dst_class = REGNO_REG_CLASS (true_regnum (operands[0])); - + /* I'm not sure if this can happen or not. Might as well be prepared and generate the best possible code if it does happen. */ if (true_regnum (operands[0]) == true_regnum (operands[1])) @@ -790,7 +946,7 @@ add the other source to the destination. Carefully select which source to copy to the destination; a naive - implementation will waste a byte when the source classes are + implementation will waste a byte when the source classes are different and the destination is an address register. Selecting the lowest cost register copy will optimize this sequence. */ if (REGNO_REG_CLASS (true_regnum (operands[1])) @@ -821,7 +977,7 @@ return \"mov %2,%0\;add %1,%0\"; } default: - abort (); + gcc_unreachable (); } }" [(set_attr "cc" "set_zn,none_0hit,set_zn,none_0hit,set_zn,none_0hit,set_zn")]) @@ -863,7 +1019,7 @@ return \"mov %1,%0\;add %2,%0\"; return \"mov %2,%0\;add %1,%0\"; default: - abort (); + gcc_unreachable (); } }" [(set_attr "cc" "set_zn,none_0hit,none_0hit,set_zn,none_0hit,set_zn")]) @@ -925,7 +1081,7 @@ { rtx target = gen_reg_rtx (SImode); - emit_move_insn (target, GEN_INT (0)); + emit_move_insn (target, const0_rtx); emit_insn (gen_subsi3 (target, target, operands[1])); emit_move_insn (operands[0], target); DONE; @@ -971,7 +1127,7 @@ return \"mul %2,%0\"; }" [(set_attr "cc" "set_zn")]) - + (define_insn "" [(set (match_operand:SI 0 "register_operand" "=dx") (mult:SI (match_operand:SI 1 "register_operand" "%0") @@ -1075,7 +1231,22 @@ return \"and %1,%0\"; return \"and %2,%0\"; }" - [(set_attr "cc" "none_0hit,set_znv,set_znv")]) + [(set (attr "cc") + (cond + [ + (eq (symbol_ref "which_alternative") (const_int 0) + ) (const_string "none_0hit") + (ne (symbol_ref "GET_CODE (operands[2]) == CONST_INT + && (INTVAL (operands[2]) == 0x7fffffff + || INTVAL (operands[2]) == 0x3fffffff + || INTVAL (operands[2]) == 0x1fffffff + || INTVAL (operands[2]) == 0x0fffffff + || INTVAL (operands[2]) == 0xfffffffe + || INTVAL (operands[2]) == 0xfffffffc + || INTVAL (operands[2]) == 0xfffffff8 + || INTVAL (operands[2]) == 0xfffffff0)") + (const_int 0)) (const_string "set_zn") + ] (const_string "set_znv")))]) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=dx,dx") @@ -1106,7 +1277,27 @@ return \"lsr 4,%0\;asl2 %0\;asl2 %0\"; return \"and %2,%0\"; }" - [(set_attr "cc" "none_0hit,set_znv")]) + [(set (attr "cc") + (cond + [ + (eq (symbol_ref "which_alternative") (const_int 0) + ) (const_string "none_0hit") + ;; Shifts don't set the V flag, but bitwise operations clear + ;; it (which correctly reflects the absence of overflow in a + ;; compare-with-zero that might follow). As for the + ;; 0xfffffffe case, the add may overflow, so we can't use the + ;; V flag. + (ne (symbol_ref "GET_CODE (operands[2]) == CONST_INT + && (INTVAL (operands[2]) == 0x7fffffff + || INTVAL (operands[2]) == 0x3fffffff + || INTVAL (operands[2]) == 0x1fffffff + || INTVAL (operands[2]) == 0x0fffffff + || INTVAL (operands[2]) == 0xfffffffe + || INTVAL (operands[2]) == 0xfffffffc + || INTVAL (operands[2]) == 0xfffffff8 + || INTVAL (operands[2]) == 0xfffffff0)") + (const_int 0)) (const_string "set_zn") + ] (const_string "set_znv")))]) ;; ---------------------------------------------------------------------- ;; OR INSTRUCTIONS @@ -1257,6 +1448,17 @@ and %1,%0" [(set_attr "cc" "clobber,set_znv")]) +(define_insn "" + [(set (match_operand:QI 0 "memory_operand" "=R,T") + (and:QI + (match_dup 0) + (not:QI (match_operand:QI 1 "nonmemory_operand" "i,d"))))] + "" + "@ + bclr %U1,%A0 + bclr %1,%0" + [(set_attr "cc" "clobber,clobber")]) + (define_insn "" [(set (match_operand:QI 0 "nonimmediate_operand" "+R,d") (subreg:QI @@ -1264,10 +1466,48 @@ (match_operand:SI 1 "const_int_operand" "i,i")) 0))] "" "@ - bset %1,%A0 + bset %U1,%A0 or %1,%0" [(set_attr "cc" "clobber,set_znv")]) +(define_expand "iorqi3" + [(set (match_operand:QI 0 "nonimmediate_operand" "") + (ior:QI (match_operand:QI 1 "nonimmediate_operand" "") + (match_operand:QI 2 "nonmemory_operand" "")))] + "" + "") + +(define_insn "" + [(set (match_operand:QI 0 "nonimmediate_operand" "=R,T,r") + (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") + ;; This constraint should really be nonmemory_operand, + ;; but making it general_operand, along with the + ;; condition that not both input operands are MEMs, it + ;; here helps combine do a better job. + (match_operand:QI 2 "general_operand" "i,d,ir")))] + "TARGET_AM33 && + (GET_CODE (operands[2]) != MEM || GET_CODE (operands[1]) != MEM)" + "@ + bset %U2,%A0 + bset %2,%0 + or %2,%0" + [(set_attr "cc" "clobber,clobber,set_znv")]) + +(define_insn "" + [(set (match_operand:QI 0 "nonimmediate_operand" "=R,T,d") + (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0") + ;; This constraint should really be nonmemory_operand, + ;; but making it general_operand, along with the + ;; condition that not both input operands are MEMs, it + ;; here helps combine do a better job. + (match_operand:QI 2 "general_operand" "i,d,id")))] + "GET_CODE (operands[2]) != MEM || GET_CODE (operands[1]) != MEM" + "@ + bset %U2,%A0 + bset %2,%0 + or %2,%0" + [(set_attr "cc" "clobber,clobber,set_znv")]) + (define_insn "" [(set (cc0) (zero_extract:SI (match_operand:SI 0 "register_operand" "dx") @@ -1315,7 +1555,7 @@ len--; } - /* If the source operand is not a reg (ie it is memory), then extract the + /* If the source operand is not a reg (i.e. it is memory), then extract the bits from mask that we actually want to test. Note that the mask will never cross a byte boundary. */ if (!REG_P (operands[0])) @@ -1329,13 +1569,13 @@ else if (mask & 0xff000000) mask = (mask >> 24) & 0xff; } - + xoperands[0] = operands[0]; xoperands[1] = GEN_INT (trunc_int_for_mode (mask, SImode)); if (GET_CODE (operands[0]) == REG) output_asm_insn (\"btst %1,%0\", xoperands); else - output_asm_insn (\"btst %1,%A0\", xoperands); + output_asm_insn (\"btst %U1,%A0\", xoperands); return \"\"; }" [(set_attr "cc" "clobber")]) @@ -1354,7 +1594,7 @@ (match_operand:SI 1 "const_8bit_operand" "")))] "" "@ - btst %1,%A0 + btst %U1,%A0 btst %1,%0" [(set_attr "cc" "clobber")]) @@ -1464,6 +1704,8 @@ "" "* { + if (cc_status.mdep.fpCC) + return \"fb%b1 %0\"; if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 && (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE @@ -1483,6 +1725,8 @@ "" "* { + if (cc_status.mdep.fpCC) + return \"fb%B1 %0\"; if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0 && (GET_CODE (operands[1]) == GT || GET_CODE (operands[1]) == GE @@ -1508,6 +1752,43 @@ "jmp (%0)" [(set_attr "cc" "none")]) +(define_expand "builtin_setjmp_receiver" + [(match_operand 0 "" "")] + "flag_pic" + " +{ + if (flag_pic) + emit_insn (gen_GOTaddr2picreg ()); + + DONE; +}") + +(define_expand "casesi" + [(match_operand:SI 0 "register_operand" "") + (match_operand:SI 1 "immediate_operand" "") + (match_operand:SI 2 "immediate_operand" "") + (match_operand 3 "" "") (match_operand 4 "" "")] + "" + " +{ + rtx table = gen_reg_rtx (SImode); + rtx index = gen_reg_rtx (SImode); + rtx addr = gen_reg_rtx (Pmode); + + emit_move_insn (table, gen_rtx_LABEL_REF (VOIDmode, operands[3])); + emit_move_insn (index, plus_constant (operands[0], - INTVAL (operands[1]))); + emit_insn (gen_cmpsi (index, operands[2])); + emit_jump_insn (gen_bgtu (operands[4])); + emit_move_insn (index, gen_rtx_ASHIFT (SImode, index, const2_rtx)); + emit_move_insn (addr, gen_rtx_MEM (SImode, + gen_rtx_PLUS (SImode, table, index))); + if (flag_pic) + emit_move_insn (addr, gen_rtx_PLUS (SImode, addr, table)); + + emit_jump_insn (gen_tablejump (addr, operands[3])); + DONE; +}") + (define_insn "tablejump" [(set (pc) (match_operand:SI 0 "register_operand" "a")) (use (label_ref (match_operand 1 "" "")))] @@ -1523,14 +1804,30 @@ "" " { + if (flag_pic && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) + { + if (MN10300_GLOBAL_P (XEXP (operands[0], 0))) + { + /* The PLT code won't run on AM30, but then, there's no + shared library support for AM30 either, so we just assume + the linker is going to adjust all @PLT relocs to the + actual symbols. */ + emit_use (pic_offset_table_rtx); + XEXP (operands[0], 0) = gen_sym2PLT (XEXP (operands[0], 0)); + } + else + XEXP (operands[0], 0) = gen_sym2PIC (XEXP (operands[0], 0)); + } if (! call_address_operand (XEXP (operands[0], 0), VOIDmode)) XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0)); emit_call_insn (gen_call_internal (XEXP (operands[0], 0), operands[1])); DONE; }") +;; NB: Mode on match_operand 0 deliberately omitted in +;; order to be able to match UNSPECs in PIC mode. (define_insn "call_internal" - [(call (mem:QI (match_operand:SI 0 "call_address_operand" "aS")) + [(call (mem:QI (match_operand 0 "call_address_operand" "aS")) (match_operand:SI 1 "general_operand" "g"))] "" "* @@ -1552,6 +1849,20 @@ "" " { + if (flag_pic && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) + { + if (MN10300_GLOBAL_P (XEXP (operands[1], 0))) + { + /* The PLT code won't run on AM30, but then, there's no + shared library support for AM30 either, so we just assume + the linker is going to adjust all @PLT relocs to the + actual symbols. */ + emit_use (pic_offset_table_rtx); + XEXP (operands[1], 0) = gen_sym2PLT (XEXP (operands[1], 0)); + } + else + XEXP (operands[1], 0) = gen_sym2PIC (XEXP (operands[1], 0)); + } if (! call_address_operand (XEXP (operands[1], 0), VOIDmode)) XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0)); emit_call_insn (gen_call_value_internal (operands[0], @@ -1560,10 +1871,12 @@ DONE; }") +;; NB: Mode on match_operands 0 and 1 deliberately omitted +;; in order to be able to match UNSPECs in PIC mode. (define_insn "call_value_internal" - [(set (match_operand 0 "" "=dax") - (call (mem:QI (match_operand:SI 1 "call_address_operand" "aS")) - (match_operand:SI 2 "general_operand" "g")))] + [(set (match_operand 0 "register_operand" "=dax") + (call (mem:QI (match_operand 1 "call_address_operand" "aS")) + (match_operand:SI 2 "general_operand" "g")))] "" "* { @@ -1884,8 +2197,7 @@ operand_subword_force (operands[1], 1, DFmode), GEN_INT (0x7fffffff), target, 0, OPTAB_WIDEN); - if (result == 0) - abort (); + gcc_assert (result); if (result != target) emit_move_insn (result, target); @@ -1896,7 +2208,7 @@ insns = get_insns (); end_sequence (); - emit_no_conflict_block (insns, operands[0], operands[1], 0, 0); + emit_insn (insns); DONE; }") @@ -1909,12 +2221,17 @@ rtx result; rtx target; + if (TARGET_AM33_2) + { + emit_insn (gen_abssf2_am33_2 (operands[0], operands[1])); + DONE; + } + target = operand_subword_force (operands[0], 0, SFmode); result = expand_binop (SImode, and_optab, operand_subword_force (operands[1], 0, SFmode), GEN_INT (0x7fffffff), target, 0, OPTAB_WIDEN); - if (result == 0) - abort (); + gcc_assert (result); if (result != target) emit_move_insn (result, target); @@ -1925,6 +2242,15 @@ }") +(define_insn "abssf2_am33_2" + [(set (match_operand:SF 0 "register_operand" "=f,f") + (abs:SF (match_operand:SF 1 "register_operand" "0,?f")))] + "TARGET_AM33_2" + "@ + fabs %0 + fabs %1, %0" + [(set_attr "cc" "none_0hit")]) + (define_expand "negdf2" [(set (match_operand:DF 0 "register_operand" "") (neg:DF (match_operand:DF 1 "register_operand" "")))] @@ -1940,8 +2266,7 @@ GEN_INT (trunc_int_for_mode (0x80000000, SImode)), target, 0, OPTAB_WIDEN); - if (result == 0) - abort (); + gcc_assert (result); if (result != target) emit_move_insn (result, target); @@ -1952,7 +2277,7 @@ insns = get_insns (); end_sequence (); - emit_no_conflict_block (insns, operands[0], operands[1], 0, 0); + emit_insn (insns); DONE; }") @@ -1965,13 +2290,18 @@ rtx result; rtx target; + if (TARGET_AM33_2) + { + emit_insn (gen_negsf2_am33_2 (operands[0], operands[1])); + DONE; + } + target = operand_subword_force (operands[0], 0, SFmode); result = expand_binop (SImode, xor_optab, operand_subword_force (operands[1], 0, SFmode), GEN_INT (trunc_int_for_mode (0x80000000, SImode)), target, 0, OPTAB_WIDEN); - if (result == 0) - abort (); + gcc_assert (result); if (result != target) emit_move_insn (result, target); @@ -1981,6 +2311,114 @@ DONE; }") +(define_insn "negsf2_am33_2" + [(set (match_operand:SF 0 "register_operand" "=f,f") + (neg:SF (match_operand:SF 1 "register_operand" "0,?f")))] + "TARGET_AM33_2" + "@ + fneg %0 + fneg %1, %0" + [(set_attr "cc" "none_0hit")]) + +(define_expand "sqrtsf2" + [(set (match_operand:SF 0 "register_operand" "") + (sqrt:SF (match_operand:SF 1 "register_operand" "")))] + "TARGET_AM33_2 && flag_unsafe_math_optimizations" + " +{ + rtx scratch = gen_reg_rtx (SFmode); + emit_insn (gen_rsqrtsf2 (scratch, operands[1], CONST1_RTX (SFmode))); + emit_insn (gen_divsf3 (operands[0], force_reg (SFmode, CONST1_RTX (SFmode)), + scratch)); + DONE; +}") + +(define_insn "rsqrtsf2" + [(set (match_operand:SF 0 "register_operand" "=f,f") + (div:SF (match_operand:SF 2 "const_1f_operand" "F,F") + (sqrt:SF (match_operand:SF 1 "register_operand" "0,?f"))))] + "TARGET_AM33_2" + "@ + frsqrt %0 + frsqrt %1, %0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "addsf3" + [(set (match_operand:SF 0 "register_operand" "=f,f") + (plus:SF (match_operand:SF 1 "register_operand" "%0,f") + (match_operand:SF 2 "general_operand" "f,?fF")))] + "TARGET_AM33_2" + "@ + fadd %2, %0 + fadd %2, %1, %0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "subsf3" + [(set (match_operand:SF 0 "register_operand" "=f,f") + (minus:SF (match_operand:SF 1 "register_operand" "0,f") + (match_operand:SF 2 "general_operand" "f,?fF")))] + "TARGET_AM33_2" + "@ + fsub %2, %0 + fsub %2, %1, %0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "mulsf3" + [(set (match_operand:SF 0 "register_operand" "=f,f") + (mult:SF (match_operand:SF 1 "register_operand" "%0,f") + (match_operand:SF 2 "general_operand" "f,?fF")))] + "TARGET_AM33_2" + "@ + fmul %2, %0 + fmul %2, %1, %0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "divsf3" + [(set (match_operand:SF 0 "register_operand" "=f,f") + (div:SF (match_operand:SF 1 "register_operand" "0,f") + (match_operand:SF 2 "general_operand" "f,?fF")))] + "TARGET_AM33_2" + "@ + fdiv %2, %0 + fdiv %2, %1, %0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "fmaddsf4" + [(set (match_operand:SF 0 "register_operand" "=A") + (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "%f") + (match_operand:SF 2 "register_operand" "f")) + (match_operand:SF 3 "register_operand" "f")))] + "TARGET_AM33_2" + "fmadd %1, %2, %3, %0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "fmsubsf4" + [(set (match_operand:SF 0 "register_operand" "=A") + (minus:SF (mult:SF (match_operand:SF 1 "register_operand" "%f") + (match_operand:SF 2 "register_operand" "f")) + (match_operand:SF 3 "register_operand" "f")))] + "TARGET_AM33_2" + "fmsub %1, %2, %3, %0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "fnmaddsf4" + [(set (match_operand:SF 0 "register_operand" "=A") + (minus:SF (match_operand:SF 3 "register_operand" "f") + (mult:SF (match_operand:SF 1 "register_operand" "%f") + (match_operand:SF 2 "register_operand" "f"))))] + "TARGET_AM33_2" + "fnmadd %1, %2, %3, %0" + [(set_attr "cc" "none_0hit")]) + +(define_insn "fnmsubsf4" + [(set (match_operand:SF 0 "register_operand" "=A") + (minus:SF (neg:SF (mult:SF (match_operand:SF 1 "register_operand" "%f") + (match_operand:SF 2 "register_operand" "f"))) + (match_operand:SF 3 "register_operand" "f")))] + "TARGET_AM33_2" + "fnmsub %1, %2, %3, %0" + [(set_attr "cc" "none_0hit")]) + ;; ---------------------------------------------------------------------- ;; PROLOGUE/EPILOGUE @@ -2036,7 +2474,7 @@ return \"\"; }" [(set_attr "cc" "clobber")]) - + (define_insn "return" [(return)] "can_use_return_insn ()" @@ -2115,3 +2553,123 @@ "add %0,%0\;bcc %1" [(set_attr "cc" "clobber")]) +(define_expand "int_label" + [(unspec [(match_operand:SI 0 "" "")] UNSPEC_INT_LABEL)] + "" "") + +(define_expand "GOTaddr2picreg" + [(match_dup 0)] + "" " +{ + /* It would be nice to be able to have int_label keep track of the + counter and all, but if we add C code to it, we'll get an insn + back, and we just want the pattern. */ + operands[0] = gen_int_label (GEN_INT (mn10300_unspec_int_label_counter++)); + if (TARGET_AM33) + emit_insn (gen_am33_loadPC (operands[0])); + else + emit_insn (gen_mn10300_loadPC (operands[0])); + emit_insn (gen_add_GOT_to_pic_reg (copy_rtx (operands[0]))); + DONE; +} +") + +(define_insn "am33_loadPC" + [(parallel + [(set (reg:SI PIC_REG) (pc)) + (use (match_operand 0 "" ""))])] + "TARGET_AM33" + "%0:\;mov pc,a2") + + +(define_insn_and_split "mn10300_loadPC" + [(parallel + [(set (reg:SI PIC_REG) (pc)) + (use (match_operand 0 "" ""))])] + "" + "#" + "reload_completed" + [(match_operand 0 "" "")] + " +{ + rtx sp_reg = gen_rtx_REG (SImode, SP_REG); + int need_stack_space = (get_frame_size () == 0 + && crtl->outgoing_args_size == 0); + + if (need_stack_space) + emit_move_insn (sp_reg, plus_constant (sp_reg, -4)); + + emit_insn (gen_call_next_insn (operands[0])); + + if (need_stack_space) + emit_insn (gen_pop_pic_reg ()); + else + emit_move_insn (pic_offset_table_rtx, gen_rtx_MEM (SImode, sp_reg)); + + DONE; +}") + +(define_insn "call_next_insn" + [(parallel + [(set (mem:SI (reg:SI SP_REG)) (pc)) + (use (match_operand 0 "" ""))])] + "reload_completed" + "calls %0\;%0:") + +(define_expand "add_GOT_to_pic_reg" + [(set (reg:SI PIC_REG) + (plus:SI + (reg:SI PIC_REG) + (const:SI + (unspec:SI [(match_operand:SI 0 "" "")] UNSPEC_GOTSYM_OFF))))] + "") + +(define_expand "symGOT2reg" + [(match_operand:SI 0 "" "") + (match_operand:SI 1 "" "")] + "" + " +{ + rtx insn = emit_insn (gen_symGOT2reg_i (operands[0], operands[1])); + + MEM_READONLY_P (SET_SRC (PATTERN (insn))) = 1; + + set_unique_reg_note (insn, REG_EQUAL, operands[1]); + + DONE; +}") + +(define_expand "symGOT2reg_i" + [(set (match_operand:SI 0 "" "") + (mem:SI (plus:SI (reg:SI PIC_REG) + (const (unspec [(match_operand:SI 1 "" "")] + UNSPEC_GOT)))))] + "" + "") + +(define_expand "symGOTOFF2reg" + [(match_operand:SI 0 "" "") (match_operand:SI 1 "" "")] + "" + " +{ + rtx insn = emit_insn (gen_symGOTOFF2reg_i (operands[0], operands[1])); + + set_unique_reg_note (insn, REG_EQUAL, operands[1]); + + DONE; +}") + +(define_expand "symGOTOFF2reg_i" + [(set (match_operand:SI 0 "" "") + (const (unspec [(match_operand:SI 1 "" "")] UNSPEC_GOTOFF))) + (set (match_dup 0) (plus:SI (match_dup 0) (reg:SI PIC_REG)))] + "" + "") + +(define_expand "sym2PIC" + [(unspec [(match_operand:SI 0 "" "")] UNSPEC_PIC)] + "" "") + +(define_expand "sym2PLT" + [(unspec [(match_operand:SI 0 "" "")] UNSPEC_PLT)] + "" "")