;; 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
+;; <http://www.gnu.org/licenses/>.
;; The original PO technology requires these to be ordered by speed,
;; so that assigner will pick the fastest.
;; 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")
\f
;; ----------------------------------------------------------------------
;; MOVE INSTRUCTIONS
}")
(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))"
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)"
"*
case 1:
return \"clr %0\";
case 2:
+ case 3:
+ case 4:
if (GET_CODE (operands[1]) == CONST_DOUBLE)
{
rtx xoperands[2];
}
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
}")
(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))"
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)"
"*
case 1:
return \"clr %0\";
case 2:
+ case 3:
+ case 4:
if (GET_CODE (operands[1]) == CONST_DOUBLE)
{
rtx xoperands[2];
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
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" ""))]
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)"
"*
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" "")
}")
(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)"
"*
{
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)
{
}
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" "")
(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)"
"*
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))
== 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);
== 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" "")
(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)"
"*
{
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;
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))
== 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);
== 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")))])
\f
;; 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
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")])
\f
;; ----------------------------------------------------------------------
;; ADD INSTRUCTIONS
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]))
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]))
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")])
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")])
{
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;
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")
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")
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
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
(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")
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]))
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")])
(match_operand:SI 1 "const_8bit_operand" "")))]
""
"@
- btst %1,%A0
+ btst %U1,%A0
btst %1,%0"
[(set_attr "cc" "clobber")])
""
"*
{
+ 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
""
"*
{
+ 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
"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 "" "")))]
""
"
{
+ 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"))]
""
"*
""
"
{
+ 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],
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")))]
""
"*
{
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);
insns = get_insns ();
end_sequence ();
- emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
+ emit_insn (insns);
DONE;
}")
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);
}")
+(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" "")))]
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);
insns = get_insns ();
end_sequence ();
- emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
+ emit_insn (insns);
DONE;
}")
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);
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
return \"\";
}"
[(set_attr "cc" "clobber")])
-
+
(define_insn "return"
[(return)]
"can_use_return_insn ()"
"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)]
+ "" "")