+++ /dev/null
-;; GCC machine description for Matsushita MN10200
-;; Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
-;; Contributed by Jeff Law (law@cygnus.com).
-
-;; This file is part of GNU CC.
-
-;; GNU CC 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,
-;; 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.
-
-;; The original PO technology requires these to be ordered by speed,
-;; so that assigner will pick the fastest.
-
-;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
-
-;; Condition code settings.
-;; none - insn does not affect cc
-;; none_0hit - insn does not affect cc but it does modify operand 0
-;; This attribute is used to keep track of when operand 0 changes.
-;; See the description of NOTICE_UPDATE_CC for more info.
-;; set_znv - sets z,n,v to usable values; c is unknown.
-;; set_zn - sets z,n to usable values; v,c is unknown.
-;; compare - compare instruction
-;; clobber - value of cc is unknown
-(define_attr "cc" "none,none_0hit,set_znv,set_zn,compare,clobber"
- (const_string "clobber"))
-\f
-;; ----------------------------------------------------------------------
-;; MOVE INSTRUCTIONS
-;; ----------------------------------------------------------------------
-;;
-;; Some general notes on move instructions.
-;;
-;; The hardware can't encode nop moves involving data registers, so
-;; we catch them and emit a nop instead.
-;;
-;; Loads/stores to/from address registers must be 16bit aligned,
-;; thus we avoid them for QImode.
-;;
-;; Stores from address registers always store 24bits, so avoid
-;; stores from address registers in HImode, SImode, and SFmode.
-;;
-;; As a result of the various problems using address registers in
-;; QImode, HImode, SImode, and SFmode, we discourage their use via
-;; '*' in their constraints. They're still allowed, but they're never
-;; the preferred class for insns with those modes.
-
-;; movqi
-
-(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- ""
- "
-{
- /* One of the ops has to be in a register */
- if (!register_operand (operand0, QImode)
- && !register_operand (operand1, QImode))
- operands[1] = copy_to_mode_reg (QImode, operand1);
-}")
-
-;; We avoid memory operations involving address registers because we
-;; can't be sure they'll be suitably aligned.
-;;
-;; We also discourage holding QImode values in address registers.
-(define_insn ""
- [(set (match_operand:QI 0 "general_operand" "=d,d,*a,d,d,m,d,*a,*a")
- (match_operand:QI 1 "general_operand" "0,I,I,di,m,d,*a,d,i*a"))]
- "register_operand (operands[0], QImode)
- || register_operand (operands[1], QImode)"
- "@
- nop
- sub %0,%0
- sub %0,%0
- mov %S1,%0
- movbu %1,%0
- movb %1,%0
- mov %1,%0
- mov %1,%0
- mov %1,%0"
- [(set_attr "cc" "none,clobber,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
-
-;; movhi
-
-(define_expand "movhi"
- [(set (match_operand:HI 0 "general_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
- ""
- "
-{
- /* One of the ops has to be in a register */
- if (!register_operand (operand1, HImode)
- && !register_operand (operand0, HImode))
- operands[1] = copy_to_mode_reg (HImode, operand1);
-}")
-
-(define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=d,d,*a,d,d,m,d,*a,*a,*a")
- (match_operand:HI 1 "general_operand" "0,I,I,di,m,d,*a,d,i*a,m"))]
- "register_operand (operands[0], HImode)
- || register_operand (operands[1], HImode)"
- "@
- nop
- sub %0,%0
- sub %0,%0
- mov %s1,%0
- mov %1,%0
- mov %1,%0
- mov %1,%0
- mov %1,%0
- mov %1,%0
- mov %A1,%0"
- [(set_attr "cc" "none,clobber,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
-
-;; movpsi and helpers
-
-(define_expand "movpsi"
- [(set (match_operand:PSI 0 "general_operand" "")
- (match_operand:PSI 1 "general_operand" ""))]
- ""
- "
-{
- /* One of the ops has to be in a register */
- if (!register_operand (operand1, PSImode)
- && !register_operand (operand0, PSImode))
- operands[1] = copy_to_mode_reg (PSImode, operand1);
-}")
-
-
-;; Constant and indexed addresses are not valid addresses for PSImode,
-;; therefore they won't be matched by the general movpsi pattern below.
-;; ??? We had patterns to handle indexed addresses, but they kept making
-;; us run out of regs, so they were eliminated.
-
-(define_insn ""
- [(set (match_operand:PSI 0 "register_operand" "=a")
- (match_operand:PSI 1 "constant_memory_operand" ""))]
- ""
- "mov %A1,%0"
- [(set_attr "cc" "none_0hit")])
-
-(define_insn ""
- [(set (match_operand:PSI 0 "constant_memory_operand" "=X")
- (match_operand:PSI 1 "register_operand" "a"))]
- ""
- "mov %1,%A0"
- [(set_attr "cc" "none_0hit")])
-
-;; We want to prefer address registers here because 24bit moves to/from
-;; memory are shorter and faster when done via address registers.
-(define_insn ""
- [(set (match_operand:PSI 0 "general_operand" "=d,a?d,?da,a,m,?d,m")
- (match_operand:PSI 1 "general_operand" "0,I,?dai,m,a,m,?d"))]
- "register_operand (operands[0], PSImode)
- || register_operand (operands[1], PSImode)"
- "@
- nop
- sub %0,%0
- mov %1,%0
- mov %A1,%0
- mov %1,%A0
- movx %A1,%0
- movx %1,%A0"
- [(set_attr "cc" "none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
-
-(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand" "")
- (match_operand:SI 1 "general_operand" ""))]
- ""
- "
-{
- /* One of the ops has to be in a register */
- if (!register_operand (operand1, SImode)
- && !register_operand (operand0, SImode))
- operands[1] = copy_to_mode_reg (SImode, operand1);
-}")
-
-(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=d,d,*a,dm,d,d,*a,*a,*a")
- (match_operand:SI 1 "general_operand" "0,I,I,d,dim,*a,d,*a,i"))]
- "register_operand (operands[0], SImode)
- || register_operand (operands[1], SImode)"
- "*
-{
- switch (which_alternative)
- {
- case 0:
- return \"nop\";
- case 1:
- case 2:
- return \"sub %H0,%H0\;sub %L0,%L0\";
- case 3:
- case 5:
- case 6:
- case 7:
- return \"mov %H1,%H0\;mov %L1,%L0\";
-
- /* The next two cases try to optimize cases where one half
- of the constant is all zeros, or when the two halves are
- the same. */
- case 4:
- case 8:
- if (REG_P (operands[0])
- && GET_CODE (operands[1]) == CONST_INT
- && (INTVAL (operands[1]) & 0xffff0000) == 0)
- output_asm_insn (\"sub %H0,%H0\", operands);
- else
- output_asm_insn (\"mov %h1,%H0\", operands);
-
- if (GET_CODE (operands[1]) == CONST_INT
- && ((INTVAL (operands[1]) & 0xffff)
- == ((INTVAL (operands[1]) >> 16) & 0xffff)))
- output_asm_insn (\"mov %H0,%L0\", operands);
- else if (GET_CODE (operands[1]) == CONST_INT
- && (INTVAL (operands[1]) & 0xffff) == 0)
- output_asm_insn (\"sub %L0,%L0\", operands);
- else
- output_asm_insn (\"mov %o1,%L0\", operands);
- return \"\";
- default:
- abort();
- }
-}"
- [(set_attr "cc" "none,clobber,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
-
-(define_expand "movsf"
- [(set (match_operand:SF 0 "general_operand" "")
- (match_operand:SF 1 "general_operand" ""))]
- ""
- "
-{
- /* One of the ops has to be in a register */
- if (!register_operand (operand1, SFmode)
- && !register_operand (operand0, SFmode))
- operands[1] = copy_to_mode_reg (SFmode, operand1);
-}")
-
-(define_insn ""
- [(set (match_operand:SF 0 "general_operand" "=d,d,*a,dm,d,d,*a,*a,*a")
- (match_operand:SF 1 "general_operand" "0,G,G,d,dim,*a,d,*a,i"))]
- "register_operand (operands[0], SFmode)
- || register_operand (operands[1], SFmode)"
- "*
-{
- switch (which_alternative)
- {
- case 0:
- return \"nop\";
-
- case 1:
- case 2:
- return \"sub %H0,%H0\;sub %L0,%L0\";
-
- default:
- {
- long val = 0;
- REAL_VALUE_TYPE rv;
-
- if (GET_CODE (operands[1]) == CONST_DOUBLE)
- {
- REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
- REAL_VALUE_TO_TARGET_SINGLE (rv, val);
- }
-
- if (GET_CODE (operands[1]) == CONST_INT)
- val = INTVAL (operands[1]);
-
- if ((GET_CODE (operands[1]) == CONST_INT
- || GET_CODE (operands[1]) == CONST_DOUBLE)
- && (val & 0xffff0000) == 0)
- output_asm_insn (\"sub %H0,%H0\", operands);
- else
- output_asm_insn (\"mov %h1,%H0\", operands);
-
- if (GET_CODE (operands[1]) == CONST_INT
- && ((INTVAL (operands[1]) & 0xffff)
- == ((INTVAL (operands[1]) >> 16) & 0xffff)))
- output_asm_insn (\"mov %H0,%L0\", operands);
- else if ((GET_CODE (operands[1]) == CONST_INT
- || GET_CODE (operands[1]) == CONST_DOUBLE)
- && (val & 0x0000ffff) == 0)
- output_asm_insn (\"sub %L0,%L0\", operands);
- else
- output_asm_insn (\"mov %o1,%L0\", operands);
- return \"\";
- }
- }
-}"
- [(set_attr "cc" "none,clobber,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
-
-\f
-;; ----------------------------------------------------------------------
-;; TEST INSTRUCTIONS
-;; ----------------------------------------------------------------------
-
-;; Go ahead and define tsthi and tstpsi so we can eliminate redundant tst insns
-;; when we start trying to optimize this port.
-(define_insn "tsthi"
- [(set (cc0) (match_operand:HI 0 "nonimmediate_operand" "da"))]
- ""
- "* return output_tst (operands[0], insn);"
- [(set_attr "cc" "set_znv")])
-
-(define_insn "tstpsi"
- [(set (cc0) (match_operand:PSI 0 "nonimmediate_operand" "da"))]
- ""
- "* return output_tst (operands[0], insn);"
- [(set_attr "cc" "set_znv")])
-
-(define_insn ""
- [(set (cc0) (zero_extend:HI (match_operand:QI 0 "memory_operand" "d")))]
- ""
- "* return output_tst (operands[0], insn);"
- [(set_attr "cc" "set_znv")])
-
-(define_insn ""
- [(set (cc0) (zero_extend:PSI (match_operand:QI 0 "memory_operand" "d")))]
- ""
- "* return output_tst (operands[0], insn);"
- [(set_attr "cc" "set_znv")])
-
-(define_insn "cmphi"
- [(set (cc0)
- (compare:HI (match_operand:HI 0 "nonimmediate_operand" "da")
- (match_operand:HI 1 "general_operand" "dai")))]
- ""
- "cmp %1,%0"
- [(set_attr "cc" "compare")])
-
-(define_insn "cmppsi"
- [(set (cc0)
- (compare:PSI (match_operand:PSI 0 "nonimmediate_operand" "da")
- (match_operand:PSI 1 "general_operand" "dai")))]
- ""
- "cmp %1,%0"
- [(set_attr "cc" "compare")])
-\f
-;; ----------------------------------------------------------------------
-;; ADD INSTRUCTIONS
-;; ----------------------------------------------------------------------
-
-(define_insn "addhi3"
- [(set (match_operand:HI 0 "general_operand" "=d")
- (plus:HI (match_operand:HI 1 "general_operand" "%0")
- (match_operand:HI 2 "general_operand" "dai")))]
- ""
- "add %2,%0"
- [(set_attr "cc" "set_zn")])
-
-(define_insn "addpsi3"
- [(set (match_operand:PSI 0 "general_operand" "=da")
- (plus:PSI (match_operand:PSI 1 "general_operand" "%0")
- (match_operand:PSI 2 "general_operand" "dai")))]
- ""
- "add %2,%0"
- [(set_attr "cc" "set_zn")])
-
-;; We want to avoid using explicit registers; reload won't tell us
-;; if it has to spill them and may generate incorrect code in such
-;; cases.
-;;
-;; So we call out to a library routine to perform 32bit add or
-;; subtract operations.
-;;
-;; operand2 must be nonmemory_operand so that we will accept CONST_INTs
-;; during initial code generation.
-(define_expand "addsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (plus:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "nonmemory_operand" "")))]
- ""
- "
-{
- /* If adding a CONST_INT, we are better off generating code ourselves.
-
- During RTL generation we call out to library routines.
-
- After RTL generation we can not call the library routines as
- they need to push arguments via virtual_outgoing_args_rtx which
- has already been instantiated. So, after RTL generation we just
- FAIL and open code the operation. */
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- if (!rtx_equal_p (operands[0], operands[1]))
- emit_move_insn (operands[0], operands[1]);
- emit_insn (gen_addsi3_const (operands[0], operands[0], operands[2]));
- DONE;
- }
- else if (rtx_equal_function_value_matters)
- {
- rtx ret, insns;
-
- start_sequence ();
- ret = emit_library_call_value (gen_rtx_SYMBOL_REF (Pmode, \"__addsi3\"),
- NULL_RTX, 1, SImode, 2, operands[1],
- SImode, operands[2], SImode);
- insns = get_insns ();
- end_sequence ();
- emit_libcall_block (insns, operands[0], ret,
- gen_rtx_PLUS (SImode, operands[1], operands[2]));
- DONE;
- }
- else
- FAIL;
-}")
-
-(define_insn "addsi3_const"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (plus:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "const_int_operand" "i")))
- (clobber (match_scratch:SI 3 "=&d"))]
- ""
- "*
-{
- unsigned long value = INTVAL (operands[2]);
-
- /* If only the high bits are set in the constant, then we only
- need a single add operation. It might be better to catch this
- at RTL expansion time. */
- if ((value & 0xffff) == 0)
- return \"add %h2,%H0\";
-
- value >>= 16;
- value &= 0xffff;
-
- if (value == 0)
- return \"sub %3,%3\;add %o2,%L0\;addc %3,%H0\";
- else
- return \"mov %h2,%3\;add %o2,%L0\;addc %3,%H0\";
-}"
- [(set_attr "cc" "clobber")])
-
-;; ----------------------------------------------------------------------
-;; SUBTRACT INSTRUCTIONS
-;; ----------------------------------------------------------------------
-
-(define_insn "subhi3"
- [(set (match_operand:HI 0 "general_operand" "=d")
- (minus:HI (match_operand:HI 1 "general_operand" "0")
- (match_operand:HI 2 "general_operand" "dai")))]
- ""
- "sub %2,%0"
- [(set_attr "cc" "set_zn")])
-
-(define_insn "subpsi3"
- [(set (match_operand:PSI 0 "general_operand" "=da")
- (minus:PSI (match_operand:PSI 1 "general_operand" "0")
- (match_operand:PSI 2 "general_operand" "dai")))]
- ""
- "sub %2,%0"
- [(set_attr "cc" "set_zn")])
-
-(define_expand "subsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (minus:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "register_operand" "")))]
- ""
- "
-{
- /* During RTL generation we call out to library routines.
-
- After RTL generation we can not call the library routines as
- they need to push arguments via virtual_outgoing_args_rtx which
- has already been instantiated. So, after RTL generation we just
- FAIL and open code the operation. */
- if (rtx_equal_function_value_matters)
- {
- rtx ret, insns;
-
- start_sequence ();
- ret = emit_library_call_value (gen_rtx_SYMBOL_REF (Pmode, \"__subsi3\"),
- NULL_RTX, 1, SImode, 2, operands[1],
- SImode, operands[2], SImode);
- insns = get_insns ();
- end_sequence ();
- emit_libcall_block (insns, operands[0], ret,
- gen_rtx_MINUS (SImode, operands[1], operands[2]));
- DONE;
- }
- else
- FAIL;
-}")
-
-;; There isn't a negate instruction, so we fake it.
-;;
-;; We used to expand this into patterns, but a single pattern
-;; actually generates better overall code.
-;;
-;; We could do HImode negations with a "not;add" sequence, but
-;; generally it's generated slightly worse code.
-;;
-;; The second alternative is not strictly necesasry, but helps
-;; when the register allocators start running short of registers.
-(define_insn "neghi2"
- [(set (match_operand:HI 0 "general_operand" "=&d,d")
- (neg:HI (match_operand:HI 1 "general_operand" "d,0")))]
- ""
- "@
- sub %0,%0\;sub %1,%0
- not %0\;add 1,%0"
- [(set_attr "cc" "set_zn")])
-
-;; The not/and sequence won't work here. It's not clear if we'll
-;; ever need to provide an alternate sequence since this should
-;; be used much less frequently than neghi2.
-(define_insn "negpsi2"
- [(set (match_operand:PSI 0 "general_operand" "=&d")
- (neg:PSI (match_operand:PSI 1 "general_operand" "d")))]
- ""
- "sub %0,%0\;sub %1,%0"
- [(set_attr "cc" "set_zn")])
-
-;; Using a magic libcall that accepts its arguments in any
-;; data register pair has proven to be the most efficient
-;; and most compact way to represent negsi2.
-(define_insn "negsi2"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (neg:SI (match_operand:SI 1 "register_operand" "0")))]
- ""
- "jsr ___negsi2_%0"
- [(set_attr "cc" "clobber")])
-
-;; ----------------------------------------------------------------------
-;; MULTIPLY INSTRUCTIONS
-;; ----------------------------------------------------------------------
-;;
-;; The mn10200 has HIxHI->SI widening multiply, but we get _severe_
-;; code density regressions if we enable such a pattern.
-
-(define_insn "mulhi3"
- [(set (match_operand:HI 0 "general_operand" "=d")
- (mult:HI (match_operand:HI 1 "general_operand" "%0")
- (match_operand:HI 2 "general_operand" "d")))]
- ""
- "mul %2,%0"
- [(set_attr "cc" "set_zn")])
-
-(define_insn "udivmodhi4"
- [(set (match_operand:HI 0 "general_operand" "=d")
- (udiv:HI (match_operand:HI 1 "general_operand" "0")
- (match_operand:HI 2 "general_operand" "d")))
- (set (match_operand:HI 3 "general_operand" "=&d")
- (umod:HI (match_dup 1) (match_dup 2)))]
- ""
- "*
-{
- if (zero_dreg)
- output_asm_insn (\"mov %0,mdr\", &zero_dreg);
- else
- output_asm_insn (\"sub %3,%3\;mov %3,mdr\", operands);
-
- if (find_reg_note (insn, REG_UNUSED, operands[3]))
- return \"divu %2,%0\";
- else
- return \"divu %2,%0\;mov mdr,%3\";
-}"
- [(set_attr "cc" "set_zn")])
-
-\f
-;; ----------------------------------------------------------------------
-;; AND INSTRUCTIONS
-;; ----------------------------------------------------------------------
-
-(define_insn "andhi3"
- [(set (match_operand:HI 0 "general_operand" "=d,d")
- (and:HI (match_operand:HI 1 "general_operand" "%0,0")
- (match_operand:HI 2 "general_operand" "M,di")))]
- ""
- "*
-{
- if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xff)
- return \"extxbu %0\";
- if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x7fff)
- return \"add %0,%0\;lsr %0\";
- if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0xfffe)
- return \"lsr %0\;add %0,%0\";
- return \"and %2,%0\";
-}"
- [(set_attr "cc" "none_0hit,set_znv")])
-
-;; This expander + pattern exist only to allow trampolines to be aligned
-;; in the stack.
-(define_expand "andpsi3"
- [(set (match_operand:PSI 0 "general_operand" "")
- (and:PSI (match_operand:PSI 1 "general_operand" "")
- (match_operand:PSI 2 "const_int_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[2]) != CONST_INT
- || (INTVAL (operands[2]) & 0xff0000) != 0xff0000)
- FAIL;
-}")
-
-(define_insn ""
- [(set (match_operand:PSI 0 "general_operand" "=d")
- (and:PSI (match_operand:PSI 1 "general_operand" "%0")
- (match_operand:PSI 2 "const_int_operand" "i")))]
- "GET_CODE (operands[2]) == CONST_INT
- && (INTVAL (operands[2]) & 0xff0000) == 0xff0000"
- "and %2,%0"
- [(set_attr "cc" "clobber")])
-
-;; ----------------------------------------------------------------------
-;; OR INSTRUCTIONS
-;; ----------------------------------------------------------------------
-
-(define_insn "iorhi3"
- [(set (match_operand:HI 0 "general_operand" "=d")
- (ior:HI (match_operand:HI 1 "general_operand" "%0")
- (match_operand:HI 2 "general_operand" "di")))]
- ""
- "or %2,%0"
- [(set_attr "cc" "set_znv")])
-
-;; ----------------------------------------------------------------------
-;; XOR INSTRUCTIONS
-;; ----------------------------------------------------------------------
-
-(define_insn "xorhi3"
- [(set (match_operand:HI 0 "general_operand" "=d")
- (xor:HI (match_operand:HI 1 "general_operand" "%0")
- (match_operand:HI 2 "general_operand" "di")))]
- ""
- "xor %2,%0"
- [(set_attr "cc" "set_znv")])
-
-;; ----------------------------------------------------------------------
-;; NOT INSTRUCTIONS
-;; ----------------------------------------------------------------------
-
-(define_insn "one_cmplhi2"
- [(set (match_operand:HI 0 "general_operand" "=d")
- (not:HI (match_operand:HI 1 "general_operand" "0")))]
- ""
- "not %0"
- [(set_attr "cc" "set_znv")])
-
-\f
-;; -----------------------------------------------------------------
-;; BIT INSTRUCTIONS
-;; -----------------------------------------------------------------
-
-;; These clears a constant set of bits in memory or in a register.
-;; We must support register destinations to make reload happy.
-(define_insn ""
- [(set (match_operand:QI 0 "general_operand" "+R,d")
- (subreg:QI
- (and:HI (subreg:HI (match_dup 0) 0)
- (match_operand 1 "const_int_operand" "")) 0))
- (clobber (match_scratch:HI 2 "=&d,X"))]
- ""
- "@
- mov %N1,%2\;bclr %2,%0
- and %1,%0"
- [(set_attr "cc" "clobber")])
-
-;; This clears a variable set of bits in memory or in a register.
-(define_insn ""
- [(set (match_operand:QI 0 "general_operand" "+R,d")
- (subreg:QI
- (and:HI (subreg:HI (match_dup 0) 0)
- (not:HI (match_operand:HI 1 "general_operand" "d,d"))) 0))
- (clobber (match_scratch:HI 2 "=X,&d"))]
- ""
- "@
- bclr %1,%0
- mov %1,%2\;not %2\;and %2,%0"
- [(set_attr "cc" "clobber")])
-
-(define_insn ""
- [(set (match_operand:QI 0 "general_operand" "+R,d")
- (subreg:QI
- (and:HI (not:HI (match_operand:HI 1 "general_operand" "d,d"))
- (subreg:HI (match_dup 0) 0)) 0))
- (clobber (match_scratch:HI 2 "=X,&d"))]
- ""
- "@
- bclr %1,%0
- mov %1,%2\;not %2\;and %2,%0"
- [(set_attr "cc" "clobber")])
-
-;; These set bits in memory.
-(define_insn ""
- [(set (match_operand:QI 0 "general_operand" "+R,d")
- (subreg:QI
- (ior:HI (subreg:HI (match_dup 0) 0)
- (match_operand:HI 1 "general_operand" "d,d")) 0))]
- ""
- "@
- bset %1,%0
- or %1,%0"
- [(set_attr "cc" "clobber")])
-
-(define_insn ""
- [(set (match_operand:QI 0 "general_operand" "+R,d")
- (subreg:QI
- (ior:HI (match_operand:HI 1 "general_operand" "d,d")
- (subreg:HI (match_dup 0) 0)) 0))]
- ""
- "@
- bset %1,%0
- or %1,%0"
- [(set_attr "cc" "clobber")])
-
-;; Not any shorter/faster than using cmp, but it might save a
-;; register if the result of the AND isn't ever used.
-
-(define_insn ""
- [(set (cc0)
- (zero_extract:HI (match_operand:HI 0 "general_operand" "d")
- (match_operand 1 "const_int_operand" "")
- (match_operand 2 "const_int_operand" "")))]
- ""
- "*
-{
- int len = INTVAL (operands[1]);
- int bit = INTVAL (operands[2]);
- int mask = 0;
- rtx xoperands[2];
-
- while (len > 0)
- {
- mask |= (1 << bit);
- bit++;
- len--;
- }
-
- xoperands[0] = operands[0];
- xoperands[1] = GEN_INT (mask);
- output_asm_insn (\"btst %1,%0\", xoperands);
- return \"\";
-}"
- [(set_attr "cc" "clobber")])
-
-(define_insn ""
- [(set (cc0) (and:HI (match_operand:HI 0 "general_operand" "d")
- (match_operand:HI 1 "const_int_operand" "i")))]
- ""
- "btst %1,%0"
- [(set_attr "cc" "clobber")])
-
-\f
-;; ----------------------------------------------------------------------
-;; JUMP INSTRUCTIONS
-;; ----------------------------------------------------------------------
-
-;; Conditional jump instructions
-
-(define_expand "ble"
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bleu"
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bge"
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgeu"
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "blt"
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bltu"
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgt"
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bgtu"
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "beq"
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_expand "bne"
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "")
-
-(define_insn ""
- [(set (pc)
- (if_then_else (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "*
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0
- && (GET_CODE (operands[1]) == GT
- || GET_CODE (operands[1]) == GE
- || GET_CODE (operands[1]) == LE
- || GET_CODE (operands[1]) == LT))
- return 0;
-
- if (GET_MODE (SET_SRC (PATTERN (PREV_INSN (insn)))) == PSImode)
- return \"b%b1x %0\";
- else
- return \"b%b1 %0\";
-}"
- [(set_attr "cc" "none")])
-
-(define_insn ""
- [(set (pc)
- (if_then_else (match_operator 1 "comparison_operator"
- [(cc0) (const_int 0)])
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
- "*
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0
- && (GET_CODE (operands[1]) == GT
- || GET_CODE (operands[1]) == GE
- || GET_CODE (operands[1]) == LE
- || GET_CODE (operands[1]) == LT))
- return 0;
-
- if (GET_MODE (SET_SRC (PATTERN (PREV_INSN (insn)))) == PSImode)
- return \"b%B1x %0\";
- else
- return \"b%B1 %0\";
-}"
- [(set_attr "cc" "none")])
-
-(define_insn "jump"
- [(set (pc)
- (label_ref (match_operand 0 "" "")))]
- ""
- "jmp %l0"
- [(set_attr "cc" "none")])
-
-(define_insn "indirect_jump"
- [(set (pc) (match_operand:PSI 0 "register_operand" "a"))]
- ""
- "jmp (%0)"
- [(set_attr "cc" "none")])
-
-(define_insn "tablejump"
- [(set (pc) (match_operand:PSI 0 "register_operand" "a"))
- (use (label_ref (match_operand 1 "" "")))]
- ""
- "jmp (%0)"
- [(set_attr "cc" "none")])
-
-;; Call subroutine with no return value.
-
-(define_expand "call"
- [(call (match_operand:QI 0 "general_operand" "")
- (match_operand:HI 1 "general_operand" ""))]
- ""
- "
-{
- if (! call_address_operand (XEXP (operands[0], 0), VOIDmode))
- XEXP (operands[0], 0) = force_reg (PSImode, XEXP (operands[0], 0));
- emit_call_insn (gen_call_internal (XEXP (operands[0], 0), operands[1]));
- DONE;
-}")
-
-(define_insn "call_internal"
- [(call (mem:QI (match_operand:PSI 0 "call_address_operand" "aS"))
- (match_operand:HI 1 "general_operand" "g"))]
- ""
- "jsr %C0"
- [(set_attr "cc" "clobber")])
-
-;; Call subroutine, returning value in operand 0
-;; (which must be a hard register).
-
-(define_expand "call_value"
- [(set (match_operand 0 "" "")
- (call (match_operand:QI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- if (! call_address_operand (XEXP (operands[1], 0), VOIDmode))
- XEXP (operands[1], 0) = force_reg (PSImode, XEXP (operands[1], 0));
- emit_call_insn (gen_call_value_internal (operands[0],
- XEXP (operands[1], 0),
- operands[2]));
- DONE;
-}")
-
-(define_insn "call_value_internal"
- [(set (match_operand 0 "" "=da")
- (call (mem:QI (match_operand:PSI 1 "call_address_operand" "aS"))
- (match_operand:HI 2 "general_operand" "g")))]
- ""
- "jsr %C1"
- [(set_attr "cc" "clobber")])
-
-(define_expand "untyped_call"
- [(parallel [(call (match_operand 0 "" "")
- (const_int 0))
- (match_operand 1 "" "")
- (match_operand 2 "" "")])]
- ""
- "
-{
- int i;
-
- emit_call_insn (gen_call (operands[0], const0_rtx));
-
- for (i = 0; i < XVECLEN (operands[2], 0); i++)
- {
- rtx set = XVECEXP (operands[2], 0, i);
- emit_move_insn (SET_DEST (set), SET_SRC (set));
- }
- DONE;
-}")
-
-(define_insn "nop"
- [(const_int 0)]
- ""
- "nop"
- [(set_attr "cc" "none")])
-\f
-;; ----------------------------------------------------------------------
-;; EXTEND INSTRUCTIONS
-;; ----------------------------------------------------------------------
-
-(define_insn "zero_extendqihi2"
- [(set (match_operand:HI 0 "general_operand" "=d,d,d")
- (zero_extend:HI
- (match_operand:QI 1 "general_operand" "0,di,m")))]
- ""
- "@
- extxbu %0
- mov %1,%0\;extxbu %0
- movbu %1,%0"
- [(set_attr "cc" "none_0hit")])
-
-(define_insn "zero_extendqipsi2"
- [(set (match_operand:PSI 0 "general_operand" "=d,d,d")
- (zero_extend:PSI
- (match_operand:QI 1 "general_operand" "0,di,m")))]
- ""
- "@
- extxbu %0
- mov %1,%0\;extxbu %0
- movbu %1,%0"
- [(set_attr "cc" "none_0hit")])
-
-(define_insn "zero_extendqisi2"
- [(set (match_operand:SI 0 "general_operand" "=d,d,d")
- (zero_extend:SI
- (match_operand:QI 1 "general_operand" "0,di,m")))]
- ""
- "@
- extxbu %L0\;sub %H0,%H0
- mov %1,%L0\;extxbu %L0\;sub %H0,%H0
- movbu %1,%L0\;sub %H0,%H0"
- [(set_attr "cc" "clobber")])
-
-(define_insn "zero_extendhipsi2"
- [(set (match_operand:PSI 0 "general_operand" "=d,d,d")
- (zero_extend:PSI
- (match_operand:HI 1 "general_operand" "0,di,m")))]
- ""
- "@
- extxu %0
- mov %1,%0\;extxu %0
- mov %1,%0\;extxu %0"
- [(set_attr "cc" "none_0hit")])
-
-(define_insn "zero_extendhisi2"
- [(set (match_operand:SI 0 "general_operand" "=d,d")
- (zero_extend:SI
- (match_operand:HI 1 "general_operand" "0,dim")))]
- ""
- "@
- sub %H0,%H0
- mov %1,%L0\;sub %H0,%H0"
- [(set_attr "cc" "clobber,clobber")])
-
-;; The last alternative is necessary because the second operand might
-;; have been the frame pointer. The frame pointer would get replaced
-;; by (plus (stack_pointer) (const_int)).
-;;
-;; Reload would think that it only needed a PSImode register in
-;; push_reload and at the start of allocate_reload_regs. However,
-;; at the end of allocate_reload_reg it would realize that the
-;; reload register must also be valid for SImode, and if it was
-;; not valid reload would abort.
-(define_insn "zero_extendpsisi2"
- [(set (match_operand:SI 0 "register_operand" "=d,?d,?*d,?*d")
- (zero_extend:SI (match_operand:PSI 1 "extendpsi_operand"
- "m,?0,?*dai,Q")))]
- ""
- "@
- mov %L1,%L0\;movbu %H1,%H0
- jsr ___zero_extendpsisi2_%0
- mov %1,%L0\;jsr ___zero_extendpsisi2_%0
- mov a3,%L0\;add %Z1,%L0\;jsr ___zero_extendpsisi2_%0"
- [(set_attr "cc" "clobber")])
-
-;;- sign extension instructions
-
-(define_insn "extendqihi2"
- [(set (match_operand:HI 0 "general_operand" "=d,d,d")
- (sign_extend:HI
- (match_operand:QI 1 "general_operand" "0,di,m")))]
- ""
- "*
-{
- if (which_alternative == 0)
- return \"extxb %0\";
- else if (which_alternative == 1)
- return \"mov %1,%0\;extxb %0\";
- else if (GET_CODE (XEXP (operands[1], 0)) == REG)
- return \"movbu %1,%0\;extxb %0\";
- else
- return \"movb %1,%0\";
-}"
- [(set_attr "cc" "none_0hit")])
-
-(define_insn "extendqipsi2"
- [(set (match_operand:PSI 0 "general_operand" "=d,d,d")
- (sign_extend:PSI
- (match_operand:QI 1 "general_operand" "0,di,m")))]
- ""
- "*
-{
- if (which_alternative == 0)
- return \"extxb %0\";
- else if (which_alternative == 1)
- return \"mov %1,%0\;extxb %0\";
- else if (GET_CODE (XEXP (operands[1], 0)) == REG)
- return \"movbu %1,%0\;extxb %0\";
- else
- return \"movb %1,%0\";
-}"
- [(set_attr "cc" "none_0hit")])
-
-(define_insn "extendqisi2"
- [(set (match_operand:SI 0 "general_operand" "=d,d,d")
- (sign_extend:SI
- (match_operand:QI 1 "general_operand" "0,di,m")))]
- ""
- "*
-{
- if (which_alternative == 0)
- return \"extxb %L0\;mov %L0,%H0\;add %H0,%H0\;subc %H0,%H0\";
- else if (which_alternative == 1)
- return \"mov %1,%L0\;extxb %L0\;mov %L0,%H0\;add %H0,%H0\;subc %H0,%H0\";
- else if (GET_CODE (XEXP (operands[1], 0)) == REG)
- return \"movbu %1,%L0\;extxb %L0\;mov %L0,%H0\;add %H0,%H0\;subc %H0,%H0\";
- else
- return \"movb %1,%L0\;mov %L0,%H0\;add %H0,%H0\;subc %H0,%H0\";
-}"
- [(set_attr "cc" "clobber")])
-
-(define_insn "extendhipsi2"
- [(set (match_operand:PSI 0 "general_operand" "=d,d,d")
- (sign_extend:PSI
- (match_operand:HI 1 "general_operand" "0,di,m")))]
- ""
- "@
- extx %0
- mov %1,%0\;extx %0
- mov %1,%0"
- [(set_attr "cc" "none_0hit")])
-
-(define_insn "extendhisi2"
- [(set (match_operand:SI 0 "general_operand" "=d,d,d")
- (sign_extend:SI
- (match_operand:HI 1 "general_operand" "0,di,m")))]
- ""
- "@
- mov %L0,%H0\;add %H0,%H0\;subc %H0,%H0
- mov %1,%L0\;mov %L0,%H0\;add %H0,%H0\;subc %H0,%H0
- mov %1,%L0\;mov %L0,%H0\;add %H0,%H0\;subc %H0,%H0"
- [(set_attr "cc" "clobber")])
-
-;; The last alternative is necessary because the second operand might
-;; have been the frame pointer. The frame pointer would get replaced
-;; by (plus (stack_pointer) (const_int)).
-;;
-;; Reload would think that it only needed a PSImode register in
-;; push_reload and at the start of allocate_reload_regs. However,
-;; at the end of allocate_reload_reg it would realize that the
-;; reload register must also be valid for SImode, and if it was
-;; not valid reload would abort.
-(define_insn "extendpsisi2"
- [(set (match_operand:SI 0 "general_operand" "=d,?d,?*d,?*d")
- (sign_extend:SI (match_operand:PSI 1 "extendpsi_operand"
- "m,?0,?*dai,Q")))]
- ""
- "@
- mov %L1,%L0\;movb %H1,%H0
- jsr ___sign_extendpsisi2_%0
- mov %1,%L0\;jsr ___sign_extendpsisi2_%0
- mov a3,%L0\;add %Z1,%L0\;jsr ___sign_extendpsisi2_%0"
- [(set_attr "cc" "clobber")])
-
-(define_insn "truncsipsi2"
- [(set (match_operand:PSI 0 "general_operand" "=a,?d,?*d,da")
- (truncate:PSI (match_operand:SI 1 "psimode_truncation_operand" "m,?m,?*d,i")))]
- ""
- "@
- mov %1,%0
- movx %A1,%0
- jsr ___truncsipsi2_%1_%0
- mov %1,%0"
- [(set_attr "cc" "clobber")])
-
-\f
-;; Combine should be simplifying this stuff, but isn't.
-;;
-(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=d,d,d")
- (sign_extend:SI
- (zero_extend:HI (match_operand:QI 1 "general_operand" "0,di,m"))))]
- ""
- "@
- extxbu %L0\;sub %H0,%H0
- mov %1,%L0\;extxbu %L0\;sub %H0,%H0
- movbu %1,%L0\;sub %H0,%H0"
- [(set_attr "cc" "clobber")])
-
-(define_insn ""
- [(set (match_operand:PSI 0 "general_operand" "=d,d,d")
- (truncate:PSI
- (sign_extend:SI (match_operand:QI 1 "general_operand" "0,di,m"))))]
- ""
- "*
-{
- if (which_alternative == 0)
- return \"extxb %0\";
- else if (which_alternative == 1)
- return \"mov %1,%0\;extxb %0\";
- else if (GET_CODE (XEXP (operands[1], 0)) == REG)
- return \"movbu %1,%0\;extxb %0\";
- else
- return \"movb %1,%0\";
-}"
- [(set_attr "cc" "none_0hit")])
-
-(define_insn ""
- [(set (match_operand:PSI 0 "general_operand" "=d,d,d")
- (truncate:PSI
- (sign_extend:SI (match_operand:HI 1 "general_operand" "0,di,m"))))]
- ""
- "@
- extx %0
- mov %1,%0\;extx %0
- mov %1,%0"
- [(set_attr "cc" "none_0hit")])
-
-(define_insn ""
- [(set (match_operand:PSI 0 "general_operand" "=d,d,d")
- (truncate:PSI
- (sign_extend:SI
- (zero_extend:HI (match_operand:QI 1 "general_operand" "0,di,m")))))]
- ""
- "@
- extxbu %0
- mov %1,%0\;extxbu %0
- movbu %1,%0"
- [(set_attr "cc" "none_0hit")])
-
-(define_insn ""
- [(set (match_operand:PSI 0 "general_operand" "=d,d,d")
- (truncate:PSI
- (zero_extend:SI (match_operand:HI 1 "general_operand" "0,di,m"))))]
- ""
- "@
- extxu %0
- mov %1,%0\;extxu %0
- mov %1,%0\;extxu %0"
- [(set_attr "cc" "none_0hit")])
-
-(define_insn ""
- [(set (match_operand:PSI 0 "general_operand" "=d,d,d")
- (truncate:PSI
- (zero_extend:SI (match_operand:QI 1 "general_operand" "0,di,m"))))]
- ""
- "@
- extxbu %0
- mov %1,%0\;extxbu %0
- movbu %1,%0"
- [(set_attr "cc" "none_0hit")])
-
-;; ----------------------------------------------------------------------
-;; SHIFTS
-;; ----------------------------------------------------------------------
-
-;; If the shift count is small, we expand it into several single bit
-;; shift insns. Otherwise we expand into a generic shift insn which
-;; handles larger shift counts, shift by variable amounts, etc.
-(define_expand "ashlhi3"
- [(set (match_operand:HI 0 "general_operand" "")
- (ashift:HI (match_operand:HI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- /* This is an experiment to see if exposing more of the underlying
- operations results in better code. */
- if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) <= 4)
- {
- int count = INTVAL (operands[2]);
- emit_move_insn (operands[0], operands[1]);
- while (count > 0)
- {
- emit_insn (gen_rtx_SET (HImode, operands[0],
- gen_rtx_ASHIFT (HImode,
- operands[0], GEN_INT (1))));
- count--;
- }
- DONE;
- }
- else
- {
- expand_a_shift (HImode, ASHIFT, operands);
- DONE;
- }
-}")
-
-;; ASHIFT one bit.
-(define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=d")
- (ashift:HI (match_operand:HI 1 "general_operand" "0")
- (const_int 1)))]
- ""
- "add %0,%0"
- [(set_attr "cc" "set_zn")])
-
-(define_expand "lshrhi3"
- [(set (match_operand:HI 0 "general_operand" "")
- (lshiftrt:HI (match_operand:HI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- /* This is an experiment to see if exposing more of the underlying
- operations results in better code. */
- if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) <= 4)
- {
- int count = INTVAL (operands[2]);
- emit_move_insn (operands[0], operands[1]);
- while (count > 0)
- {
- emit_insn (gen_rtx_SET (HImode, operands[0],
- gen_rtx_LSHIFTRT (HImode,
- operands[0],
- GEN_INT (1))));
- count--;
- }
- DONE;
- }
- else
- {
- expand_a_shift (HImode, LSHIFTRT, operands);
- DONE;
- }
-}")
-
-;; LSHIFTRT one bit.
-(define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=d")
- (lshiftrt:HI (match_operand:HI 1 "general_operand" "0")
- (const_int 1)))]
- ""
- "lsr %0"
- [(set_attr "cc" "set_znv")])
-
-(define_expand "ashrhi3"
- [(set (match_operand:HI 0 "general_operand" "")
- (ashiftrt:HI (match_operand:HI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- /* This is an experiment to see if exposing more of the underlying
- operations results in better code. */
- if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) <= 4)
- {
- int count = INTVAL (operands[2]);
- emit_move_insn (operands[0], operands[1]);
- while (count > 0)
- {
- emit_insn (gen_rtx_SET (HImode, operands[0],
- gen_rtx_ASHIFTRT (HImode, operands[0],
- GEN_INT (1))));
- count--;
- }
- DONE;
- }
- else
- {
- expand_a_shift (HImode, ASHIFTRT, operands);
- DONE;
- }
-}")
-
-;; ASHIFTRT one bit.
-(define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=d")
- (ashiftrt:HI (match_operand:HI 1 "general_operand" "0")
- (const_int 1)))]
- ""
- "asr %0"
- [(set_attr "cc" "set_znv")])
-
-;; And the general HImode shift pattern. Handles both shift by constants
-;; and shift by variable counts.
-(define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=d,d")
- (match_operator:HI 3 "nshift_operator"
- [ (match_operand:HI 1 "general_operand" "0,0")
- (match_operand:HI 2 "general_operand" "KL,dan")]))
- (clobber (match_scratch:HI 4 "=X,&d"))]
- ""
- "* return emit_a_shift (insn, operands);"
- [(set_attr "cc" "clobber")])
-
-;; We expect only ASHIFT with constant shift counts to be common for
-;; PSImode, so we optimize just that case. For all other cases we
-;; extend the value to SImode and perform the shift in SImode.
-(define_expand "ashlpsi3"
- [(set (match_operand:PSI 0 "general_operand" "")
- (ashift:PSI (match_operand:PSI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- /* This is an experiment to see if exposing more of the underlying
- operations results in better code. */
- if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) <= 7)
- {
- int count = INTVAL (operands[2]);
- emit_move_insn (operands[0], operands[1]);
- while (count > 0)
- {
- emit_insn (gen_rtx_SET (PSImode, operands[0],
- gen_rtx_ASHIFT (PSImode,
- operands[0], GEN_INT (1))));
- count--;
- }
- DONE;
- }
- else
- {
- expand_a_shift (PSImode, ASHIFT, operands);
- DONE;
- }
-}")
-
-;; ASHIFT one bit.
-(define_insn ""
- [(set (match_operand:PSI 0 "general_operand" "=d")
- (ashift:PSI (match_operand:PSI 1 "general_operand" "0")
- (const_int 1)))]
- ""
- "add %0,%0"
- [(set_attr "cc" "set_zn")])
-
-(define_expand "lshrpsi3"
- [(set (match_operand:PSI 0 "general_operand" "")
- (lshiftrt:PSI (match_operand:PSI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- rtx reg = gen_reg_rtx (SImode);
-
- emit_insn (gen_zero_extendpsisi2 (reg, operands[1]));
- reg = expand_binop (SImode, lshr_optab, reg,
- operands[2], reg, 1, OPTAB_WIDEN);
- emit_insn (gen_truncsipsi2 (operands[0], reg));
- DONE;
-}")
-
-(define_expand "ashrpsi3"
- [(set (match_operand:PSI 0 "general_operand" "")
- (ashiftrt:PSI (match_operand:PSI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- rtx reg = gen_reg_rtx (SImode);
-
- emit_insn (gen_extendpsisi2 (reg, operands[1]));
- reg = expand_binop (SImode, ashr_optab, reg,
- operands[2], reg, 0, OPTAB_WIDEN);
- emit_insn (gen_truncsipsi2 (operands[0], reg));
- DONE;
-}")
-
-(define_expand "ashlsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (ashift:SI (match_operand:SI 1 "nonmemory_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- /* For small shifts, just emit a series of single bit shifts inline.
-
- For other constant shift counts smaller than a word or non-constant
- shift counts we call out to a library call during RTL generation time;
- after RTL generation time we allow optabs.c to open code the operation.
- See comments in addsi3/subsi3 expanders.
-
- Otherwise we allow optabs.c to open code the operation. */
- if (GET_CODE (operands[2]) == CONST_INT
- && (INTVAL (operands[2]) <= 3))
- {
- int count = INTVAL (operands[2]);
- emit_move_insn (operands[0], operands[1]);
- while (count > 0)
- {
- emit_insn (gen_rtx_SET (SImode, operands[0],
- gen_rtx_ASHIFT (SImode,
- operands[0], GEN_INT (1))));
- count--;
- }
- DONE;
- }
- else if (rtx_equal_function_value_matters
- && (GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) <= 15))
- {
- rtx ret, insns;
-
- start_sequence ();
- ret = emit_library_call_value (gen_rtx_SYMBOL_REF (Pmode, \"__ashlsi3\"),
- NULL_RTX, 1, SImode, 2, operands[1],
- SImode, operands[2], HImode);
- insns = get_insns ();
- end_sequence ();
- emit_libcall_block (insns, operands[0], ret,
- gen_rtx_ASHIFT (SImode, operands[1], operands[2]));
- DONE;
- }
- else
- FAIL;
-}")
-
-;; ASHIFT one bit.
-(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=d")
- (ashift:SI (match_operand:SI 1 "general_operand" "0")
- (const_int 1)))]
- ""
- "add %L0,%L0\;addc %H0,%H0"
- [(set_attr "cc" "clobber")])
-
-(define_expand "lshrsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (lshiftrt:SI (match_operand:SI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- /* For small shifts, just emit a series of single bit shifts inline.
-
- For other constant shift counts smaller than a word or non-constant
- shift counts we call out to a library call during RTL generation time;
- after RTL generation time we allow optabs.c to open code the operation.
- See comments in addsi3/subsi3 expanders.
-
- Otherwise we allow optabs.c to open code the operation. */
- if (GET_CODE (operands[2]) == CONST_INT
- && (INTVAL (operands[2]) <= 2))
- {
- int count = INTVAL (operands[2]);
- emit_move_insn (operands[0], operands[1]);
- while (count > 0)
- {
- emit_insn (gen_rtx_SET (SImode, operands[0],
- gen_rtx_LSHIFTRT (SImode, operands[0],
- GEN_INT (1))));
- count--;
- }
- DONE;
- }
- else if (rtx_equal_function_value_matters
- && (GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) <= 15))
- {
- rtx ret, insns;
-
- start_sequence ();
- ret = emit_library_call_value (gen_rtx_SYMBOL_REF (Pmode, \"__lshrsi3\"),
- NULL_RTX, 1, SImode, 2, operands[1],
- SImode, operands[2], HImode);
- insns = get_insns ();
- end_sequence ();
- emit_libcall_block (insns, operands[0], ret,
- gen_rtx_LSHIFTRT (SImode, operands[1], operands[2]));
- DONE;
- }
- else
- FAIL;
-}")
-
-;; LSHIFTRT one bit.
-(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=d")
- (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
- (const_int 1)))]
- ""
- "lsr %H0\;ror %L0"
- [(set_attr "cc" "clobber")])
-
-(define_expand "ashrsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- ""
- "
-{
- /* For small shifts, just emit a series of single bit shifts inline.
-
- For other constant shift counts smaller than a word or non-constant
- shift counts we call out to a library call during RTL generation time;
- after RTL generation time we allow optabs.c to open code the operation.
- See comments in addsi3/subsi3 expanders.
-
- Otherwise we allow optabs.c to open code the operation. */
- if (GET_CODE (operands[2]) == CONST_INT
- && (INTVAL (operands[2]) <= 2))
- {
- int count = INTVAL (operands[2]);
- emit_move_insn (operands[0], operands[1]);
- while (count > 0)
- {
- emit_insn (gen_rtx_SET (SImode, operands[0],
- gen_rtx_ASHIFTRT (SImode, operands[0],
- GEN_INT (1))));
- count--;
- }
- DONE;
- }
- else if (rtx_equal_function_value_matters
- && (GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) <= 15))
- {
- rtx ret, insns;
-
- start_sequence ();
- ret = emit_library_call_value (gen_rtx_SYMBOL_REF (Pmode, \"__ashrsi3\"),
- NULL_RTX, 1, SImode, 2, operands[1],
- SImode, operands[2], HImode);
- insns = get_insns ();
- end_sequence ();
- emit_libcall_block (insns, operands[0], ret,
- gen_rtx_ASHIFTRT (SImode, operands[1], operands[2]));
- DONE;
- }
- else
- FAIL;
-}")
-
-;; ASHIFTRT one bit.
-(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=d")
- (ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
- (const_int 1)))]
- ""
- "asr %H0\;ror %L0"
- [(set_attr "cc" "clobber")])
-
-;; ----------------------------------------------------------------------
-;; FP INSTRUCTIONS
-;; ----------------------------------------------------------------------
-;;
-;; The mn102 series does not have floating point instructions, but since
-;; FP values are held in integer regs, we can clear the high bit easily
-;; which gives us an efficient inline floating point absolute value.
-;;
-;; Similarly for negation of a FP value.
-;;
-
-(define_expand "abssf2"
- [(set (match_operand:SF 0 "register_operand" "")
- (abs:SF (match_operand:SF 1 "register_operand" "")))]
- ""
- "
-{
- rtx target, result, insns;
-
- start_sequence ();
- target = operand_subword (operands[0], 1, 1, SFmode);
- result = expand_binop (HImode, and_optab,
- operand_subword_force (operands[1], 1, SFmode),
- GEN_INT(0x7fff), target, 0, OPTAB_WIDEN);
-
- if (result == 0)
- abort ();
-
- if (result != target)
- emit_move_insn (result, target);
-
- emit_move_insn (operand_subword (operands[0], 0, 1, SFmode),
- operand_subword_force (operands[1], 0, SFmode));
-
- insns = get_insns ();
- end_sequence ();
-
- emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
- DONE;
-}")
-
-(define_expand "negsf2"
- [(set (match_operand:SF 0 "register_operand" "")
- (neg:SF (match_operand:SF 1 "register_operand" "")))]
- ""
- "
-{
- rtx target, result, insns;
-
- start_sequence ();
- target = operand_subword (operands[0], 1, 1, SFmode);
- result = expand_binop (HImode, xor_optab,
- operand_subword_force (operands[1], 1, SFmode),
- GEN_INT(-0x8000), target, 0, OPTAB_WIDEN);
-
- if (result == 0)
- abort ();
-
- if (result != target)
- emit_move_insn (result, target);
-
- emit_move_insn (operand_subword (operands[0], 0, 1, SFmode),
- operand_subword_force (operands[1], 0, SFmode));
-
- insns = get_insns ();
- end_sequence ();
-
- emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
- DONE;
-}")
-
-;; ----------------------------------------------------------------------
-;; PROLOGUE/EPILOGUE
-;; ----------------------------------------------------------------------
-(define_expand "prologue"
- [(const_int 0)]
- ""
- "expand_prologue (); DONE;")
-
-(define_insn "outline_prologue_call"
- [(const_int 1)]
- ""
- "jsr ___prologue"
- [(set_attr "cc" "clobber")])
-
-(define_expand "epilogue"
- [(return)]
- ""
- "
-{
- expand_epilogue ();
- DONE;
-}")
-
-(define_insn "outline_epilogue_call_a0"
- [(const_int 2)]
- ""
- "jsr ___epilogue_a0"
- [(set_attr "cc" "clobber")])
-
-(define_insn "outline_epilogue_call_d0"
- [(const_int 3)]
- ""
- "jsr ___epilogue_d0"
- [(set_attr "cc" "clobber")])
-
-(define_insn "outline_epilogue_jump"
- [(const_int 4)
- (return)]
- ""
- "jmp ___epilogue_noreturn"
- [(set_attr "cc" "clobber")])
-
-(define_insn "return"
- [(return)]
- "reload_completed && total_frame_size () == 0
- && !current_function_needs_context"
- "*
-{
- rtx next = next_active_insn (insn);
-
- if (next
- && GET_CODE (next) == JUMP_INSN
- && GET_CODE (PATTERN (next)) == RETURN)
- return \"\";
- return \"rts\";
-}"
- [(set_attr "cc" "clobber")])
-
-(define_insn "return_internal"
- [(const_int 0)
- (return)]
- ""
- "rts"
- [(set_attr "cc" "clobber")])
-
-;; These are special combiner patterns to improve array/pointer accesses.
-;;
-;; A typical sequence involves extending an integer/char, shifting it left
-;; a few times, then truncating the value to PSImode.
-;;
-;; This first pattern combines the shifting & truncation operations, by
-;; itself it is a win because the shifts end up occurring in PSImode instead
-;; of SImode. However, it has the secondary effect of giving us the
-;; opportunity to match patterns which allow us to remove the initial
-;; extension completely, which is a big win.
-(define_insn ""
- [(set (match_operand:PSI 0 "general_operand" "=d,d,a,da")
- (truncate:PSI
- (ashift:SI (match_operand:SI 1 "psimode_truncation_operand" "d,m,m,i")
- (match_operand:HI 2 "const_int_operand" "i,i,i,i"))))]
- ""
- "*
-{
- int count = INTVAL (operands[2]);
- if (which_alternative == 0)
- output_asm_insn (\"jsr ___truncsipsi2_%1_%0\", operands);
- else if (which_alternative == 1)
- output_asm_insn (\"movx %A1,%0\", operands);
- else
- output_asm_insn (\" mov %1,%0\", operands);
-
- while (count)
- {
- output_asm_insn (\"add %0,%0\", operands);
- count--;
- }
- return \"\";
-}"
- [(set_attr "cc" "clobber")])
-
-;; Similarly, except that we also have zero/sign extension of the
-;; original operand. */
-(define_insn ""
- [(set (match_operand:PSI 0 "general_operand" "=d,d")
- (truncate:PSI
- (ashift:SI
- (zero_extend:SI (match_operand:HI 1 "general_operand" "0,dim"))
- (match_operand:HI 2 "const_int_operand" "i,i"))))]
- ""
- "*
-{
- int count = INTVAL (operands[2]);
-
- /* First extend operand 1 to PSImode. */
- if (which_alternative == 0)
- output_asm_insn (\"extxu %0\", operands);
- else
- output_asm_insn (\"mov %1,%0\;extxu %0\", operands);
-
- /* Now do the shifting. */
- while (count)
- {
- output_asm_insn (\"add %0,%0\", operands);
- count--;
- }
- return \"\";
-}"
- [(set_attr "cc" "clobber")])
-
-(define_insn ""
- [(set (match_operand:PSI 0 "general_operand" "=d,d,d")
- (truncate:PSI
- (ashift:SI
- (sign_extend:SI (match_operand:HI 1 "general_operand" "0,di,m"))
- (match_operand:HI 2 "const_int_operand" "i,i,i"))))]
- ""
- "*
-{
- int count = INTVAL (operands[2]);
-
- /* First extend operand 1 to PSImode. */
- if (which_alternative == 0)
- output_asm_insn (\"extx %0\", operands);
- else if (which_alternative == 1)
- output_asm_insn (\"mov %1,%0\;extx %0\", operands);
- else
- output_asm_insn (\"mov %1,%0\", operands);
-
- /* Now do the shifting. */
- while (count)
- {
- output_asm_insn (\"add %0,%0\", operands);
- count--;
- }
- return \"\";
-}"
- [(set_attr "cc" "clobber")])
-
-(define_insn ""
- [(set (match_operand:PSI 0 "general_operand" "=d,d,d")
- (truncate:PSI
- (ashift:SI
- (sign_extend:SI
- (zero_extend:HI (match_operand:QI 1 "general_operand" "0,di,m")))
- (match_operand:HI 2 "const_int_operand" "i,i,i"))))]
- ""
- "*
-{
- int count = INTVAL (operands[2]);
-
- /* First extend operand 1 to PSImode. */
- if (which_alternative == 0)
- output_asm_insn (\"extxbu %0\", operands);
- else if (which_alternative == 1)
- output_asm_insn (\"mov %1,%0\;extxbu %0\", operands);
- else
- output_asm_insn (\"movbu %1,%0\", operands);
-
- /* Now do the shifting. */
- while (count)
- {
- output_asm_insn (\"add %0,%0\", operands);
- count--;
- }
- return \"\";
-}"
- [(set_attr "cc" "clobber")])
-
-(define_insn ""
- [(set (match_operand:PSI 0 "general_operand" "=d,d,d")
- (truncate:PSI
- (ashift:SI
- (sign_extend:SI
- (match_operand:QI 1 "general_operand" "0,di,m"))
- (match_operand:HI 2 "const_int_operand" "i,i,i"))))]
- ""
- "*
-{
- int count = INTVAL (operands[2]);
-
- /* First extend operand 1 to PSImode. */
- if (which_alternative == 0)
- output_asm_insn (\"extxb %0\", operands);
- else if (which_alternative == 1)
- output_asm_insn (\"mov %1,%0\;extxb %0\", operands);
- else if (GET_CODE (XEXP (operands[1], 0)) == REG)
- output_asm_insn (\"movbu %1,%0\;extxb %0\", operands);
- else
- output_asm_insn (\"movb %1,%0\", operands);
-
- /* Now do the shifting. */
- while (count)
- {
- output_asm_insn (\"add %0,%0\", operands);
- count--;
- }
- return \"\";
-}"
- [(set_attr "cc" "clobber")])
-
-;; Try to combine consecutive updates of the stack pointer (or any
-;; other register for that matter).
-(define_peephole
- [(set (match_operand:PSI 0 "register_operand" "=da")
- (plus:PSI (match_dup 0)
- (match_operand 1 "const_int_operand" "")))
- (set (match_dup 0)
- (plus:PSI (match_dup 0)
- (match_operand 2 "const_int_operand" "")))]
- ""
- "*
-{
- operands[1] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[1]));
- return \"add %1,%0\";
-}"
- [(set_attr "cc" "clobber")])
-
-;;
-;; We had patterns to check eq/ne, but the they don't work because
-;; 0x80000000 + 0x80000000 = 0x0 with a carry out.
-;;
-;; The Z flag and C flag would be set, and we have no way to
-;; check for the Z flag set and C flag clear.
-;;
-;; This will work on the mn10200 because we can check the ZX flag
-;; if the comparison is in HImode.
-(define_peephole
- [(set (cc0) (match_operand:HI 0 "register_operand" "d"))
- (set (pc) (if_then_else (ge (cc0) (const_int 0))
- (match_operand 1 "" "")
- (pc)))]
- "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])"
- "add %0,%0\;bcc %1"
- [(set_attr "cc" "clobber")])
-
-(define_peephole
- [(set (cc0) (match_operand:HI 0 "register_operand" "d"))
- (set (pc) (if_then_else (lt (cc0) (const_int 0))
- (match_operand 1 "" "")
- (pc)))]
- "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])"
- "add %0,%0\;bcs %1"
- [(set_attr "cc" "clobber")])
-
-(define_peephole
- [(set (cc0) (match_operand:HI 0 "register_operand" "d"))
- (set (pc) (if_then_else (ge (cc0) (const_int 0))
- (pc)
- (match_operand 1 "" "")))]
- "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])"
- "add %0,%0\;bcs %1"
- [(set_attr "cc" "clobber")])
-
-(define_peephole
- [(set (cc0) (match_operand:HI 0 "register_operand" "d"))
- (set (pc) (if_then_else (lt (cc0) (const_int 0))
- (pc)
- (match_operand 1 "" "")))]
- "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])"
- "add %0,%0\;bcc %1"
- [(set_attr "cc" "clobber")])
-
-(define_peephole
- [(set (cc0) (match_operand:PSI 0 "register_operand" "d"))
- (set (pc) (if_then_else (ge (cc0) (const_int 0))
- (match_operand 1 "" "")
- (pc)))]
- "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])"
- "add %0,%0\;bccx %1"
- [(set_attr "cc" "clobber")])
-
-(define_peephole
- [(set (cc0) (match_operand:PSI 0 "register_operand" "d"))
- (set (pc) (if_then_else (lt (cc0) (const_int 0))
- (match_operand 1 "" "")
- (pc)))]
- "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])"
- "add %0,%0\;bcsx %1"
- [(set_attr "cc" "clobber")])
-
-(define_peephole
- [(set (cc0) (match_operand:PSI 0 "register_operand" "d"))
- (set (pc) (if_then_else (ge (cc0) (const_int 0))
- (pc)
- (match_operand 1 "" "")))]
- "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])"
- "add %0,%0\;bcsx %1"
- [(set_attr "cc" "clobber")])
-
-(define_peephole
- [(set (cc0) (match_operand:PSI 0 "register_operand" "d"))
- (set (pc) (if_then_else (lt (cc0) (const_int 0))
- (pc)
- (match_operand 1 "" "")))]
- "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])"
- "add %0,%0\;bccx %1"
- [(set_attr "cc" "clobber")])
-
-;; We call out to library routines to perform 32bit addition and subtraction
-;; operations (see addsi3/subsi3 expanders for why). These peepholes catch
-;; the trivial case where the operation could be done with an add;addc or
-;; sub;subc sequence.
-(define_peephole
- [(set (mem:SI (reg:PSI 7)) (reg:SI 2))
- (set (reg:SI 0) (call (match_operand:QI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- "GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
- && strcmp (XSTR (XEXP (operands[1], 0), 0), \"__addsi3\") == 0"
- "add d2,d0\;addc d3,d1"
- [(set_attr "cc" "clobber")])
-
-(define_peephole
- [(set (mem:SI (reg:PSI 7)) (reg:SI 2))
- (set (reg:SI 0) (call (match_operand:QI 1 "general_operand" "")
- (match_operand:HI 2 "general_operand" "")))]
- "GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
- && strcmp (XSTR (XEXP (operands[1], 0), 0), \"__subsi3\") == 0"
- "sub d2,d0\;subc d3,d1"
- [(set_attr "cc" "clobber")])