Commit 647daf35 by Richard Kenner

Initial revision

From-SVN: r173
parent 66954a38
;;- Machine description for GNU compiler
;;- Convex Version
;; Copyright (C) 1991 Free Software Foundation, Inc.
;; 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, 675 Mass Ave, Cambridge, MA 02139, USA.
;; Scheduling defs
;;
;; Insn scheduling is not used at present. Scheduling increases
;; register pressure so much that many spills are generated
;; even for very small functions.
;; Compares
(define_insn "tstsi"
[(set (cc0)
(match_operand:SI 0 "register_operand" "r"))]
""
"* return set_cmp (operands[0], const0_rtx, 'w');")
(define_insn "tsthi"
[(set (cc0)
(match_operand:HI 0 "register_operand" "r"))]
""
"* return set_cmp (operands[0], const0_rtx, 'h');")
(define_expand "tstqi"
[(set (match_dup 1)
(sign_extend:SI (match_operand:QI 0 "register_operand" "r")))
(set (cc0)
(match_dup 1))]
""
"operands[1] = gen_reg_rtx (SImode);")
(define_expand "tstdi"
[(parallel [(set (cc0) (match_operand:DI 0 "register_operand" "d"))
(use (match_dup 1))])]
""
"operands[1] = force_reg (DImode, const0_rtx);")
(define_insn ""
[(set (cc0) (match_operand:DI 0 "register_operand" "d"))
(use (match_operand:DI 1 "register_operand" "d"))]
""
"* return set_cmp (operands[0], operands[1], 'l');")
(define_expand "tstdf"
[(set (cc0)
(compare (match_operand:DF 0 "register_operand" "d")
(match_dup 1)))]
""
"operands[1] = force_reg (DFmode, CONST0_RTX (DFmode));")
(define_insn "tstsf"
[(set (cc0)
(match_operand:SF 0 "register_operand" "d"))]
""
"* return set_cmp (operands[0], CONST0_RTX (SFmode), 's');")
(define_insn "cmpsi"
[(set (cc0)
(compare (match_operand:SI 0 "register_operand" "d,a,i,r")
(match_operand:SI 1 "nonmemory_operand" "d,a,r,i")))]
""
"* return set_cmp (operands[0], operands[1], 'w');")
(define_insn "cmphi"
[(set (cc0)
(compare (match_operand:HI 0 "register_operand" "d,a,r,i")
(match_operand:HI 1 "nonmemory_operand" "d,a,i,r")))]
""
"* return set_cmp (operands[0], operands[1], 'h');")
(define_insn "cmpqi"
[(set (cc0)
(compare (match_operand:QI 0 "register_operand" "d")
(match_operand:QI 1 "register_operand" "d")))]
""
"* return set_cmp (operands[0], operands[1], 'b');")
(define_insn "cmpdi"
[(set (cc0)
(compare (match_operand:DI 0 "register_operand" "d")
(match_operand:DI 1 "register_operand" "d")))]
""
"* return set_cmp (operands[0], operands[1], 'l');")
(define_insn "cmpdf"
[(set (cc0)
(compare (match_operand:DF 0 "register_operand" "d")
(match_operand:DF 1 "register_operand" "d")))]
""
"* return set_cmp (operands[0], operands[1], 'd');")
(define_insn "cmpsf"
[(set (cc0)
(compare (match_operand:SF 0 "nonmemory_operand" "dF,d")
(match_operand:SF 1 "nonmemory_operand" "d,F")))]
""
"* return set_cmp (operands[0], operands[1], 's');")
;; Moves
;(define_insn "movtf"
; [(set (match_operand:TF 0 "general_operand" "=g,d")
; (match_operand:TF 1 "general_operand" "d,g"))]
; ""
; "*
;{
; rtx opaddr = 0;
; rtx xoperands[4];
; xoperands[0] = operands[0];
; xoperands[2] = operands[1];
;
; if (REG_P (operands[0]))
; xoperands[1] = gen_rtx (REG, TFmode, REGNO (operands[0]) + 1);
; else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
; xoperands[1] = 0;
; else if (offsettable_memref_p (operands[0]))
; xoperands[1] = adj_offsettable_operand (operands[0], 8);
; else
; {
; opaddr = XEXP (operands[0], 0);
; xoperands[0] = gen_rtx (MEM, TFmode, gen_rtx (REG, SImode, 13));
; xoperands[1] = adj_offsettable_operand (xoperands[0], 8);
; }
;
; if (REG_P (operands[1]))
; xoperands[3] = gen_rtx (REG, TFmode, REGNO (operands[1]) + 1);
; else if (offsettable_memref_p (operands[1]))
; xoperands[3] = adj_offsettable_operand (operands[1], 8);
; else
; {
; opaddr = XEXP (operands[1], 0);
; xoperands[2] = gen_rtx (MEM, TFmode, gen_rtx (REG, SImode, 13));
; xoperands[3] = adj_offsettable_operand (xoperands[2], 8);
; }
;
; if (opaddr)
; output_asm_insn (\"psh.w a5\;ld.w %0,a5\", &opaddr);
; if (push_operand (operands[0], TFmode))
; output_asm_insn (\"psh.l %3\;psh.l %2\", xoperands);
; else if (GET_CODE (operands[0]) == MEM)
; output_asm_insn (\"st.l %2,%0\;st.l %3,%1\", xoperands);
; else if (GET_CODE (operands[1]) == REG)
; output_asm_insn (\"mov %2,%0\;mov %3,%1\", xoperands);
; else
; output_asm_insn (\"ld.l %2,%0\;ld.l %3,%1\", xoperands);
; if (opaddr)
; output_asm_insn (\"pop.w a5\");
; return \"\";
;}")
(define_insn "movdf"
[(set (match_operand:DF 0 "general_operand" "=g,d")
(match_operand:DF 1 "general_operand" "d,dmG"))]
""
"*
{
if (push_operand (operands[0], DFmode))
return \"psh.l %1\";
else if (GET_CODE (operands[0]) == MEM)
return \"st.l %1,%0\";
else if (GET_CODE (operands[1]) == REG)
return \"mov %1,%0\";
else if (GET_CODE (operands[1]) == CONST_DOUBLE && LD_D_P (operands[1]))
{
operands[1] = gen_rtx (CONST_INT, VOIDmode,
const_double_high_int (operands[1]));
return \"ld.d %1,%0\";
}
else if (GET_CODE (operands[1]) == CONST_DOUBLE && LD_L_P (operands[1]))
{
operands[1] = gen_rtx (CONST_INT, VOIDmode,
const_double_low_int (operands[1]));
return \"ld.l %1,%0\";
}
else
return \"ld.l %1,%0\";
}")
(define_insn "movsf"
[(set (match_operand:SF 0 "general_operand" "=g,d")
(match_operand:SF 1 "general_operand" "d,gF"))]
""
"*
{
if (push_operand (operands[0], SFmode))
return \"psh.w %1\";
else if (GET_CODE (operands[0]) == MEM)
return \"st.s %1,%0\";
else if (GET_CODE (operands[1]) == REG)
return \"mov.s %1,%0\";
else
return \"ld.s %1,%0\";
}")
(define_insn "movdi"
[(set (match_operand:DI 0 "general_operand" "=g,d")
(match_operand:DI 1 "general_operand" "d,dmiG"))]
""
"*
{
if (push_operand (operands[0], DImode))
return \"psh.l %1\";
else if (GET_CODE (operands[0]) == MEM)
return \"st.l %1,%0\";
else if (GET_CODE (operands[1]) == REG)
return \"mov %1,%0\";
else if (GET_CODE (operands[1]) == CONST_DOUBLE && LD_D_P (operands[1]))
{
operands[1] = gen_rtx (CONST_INT, VOIDmode,
const_double_high_int (operands[1]));
return \"ld.d %1,%0\";
}
else
return \"ld.l %1,%0\";
}")
;; Special case of movsi, needed to express A-reg preference.
(define_insn ""
[(set (match_operand:SI 0 "push_operand" "=<")
(plus:SI (match_operand:SI 1 "register_operand" "a")
(match_operand:SI 2 "immediate_operand" "i")))]
"operands[1] != stack_pointer_rtx"
"pshea %a2(%1)")
;; General movsi. Constraints will be selected based on TARGET_INDIRECTS
;; to avoid indirect addressing on C3, where it is slow.
(define_expand "movsi"
[(set (match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" ""))]
""
"")
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=g,r,<")
(match_operand:SI 1 "general_operand" "r,g,io"))]
"TARGET_INDIRECTS"
"*
{
if (push_operand (operands[0], SImode))
{
if (GET_CODE (operands[1]) == REG)
return \"psh.w %1\";
else
return \"pshea %a1\";
}
if (GET_CODE (operands[0]) == MEM)
return \"st.w %1,%0\";
if (GET_CODE (operands[1]) != REG)
return \"ld.w %1,%0\";
if (S_REG_P (operands[0]) && S_REG_P (operands[1]))
return \"mov.w %1,%0\";
return \"mov %1,%0\";
}")
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=g,r,<")
(match_operand:SI 1 "general_operand" "r,g,i"))]
"! TARGET_INDIRECTS"
"*
{
if (push_operand (operands[0], SImode))
{
if (GET_CODE (operands[1]) == REG)
return \"psh.w %1\";
else
return \"pshea %a1\";
}
if (GET_CODE (operands[0]) == MEM)
return \"st.w %1,%0\";
if (GET_CODE (operands[1]) != REG)
return \"ld.w %1,%0\";
if (S_REG_P (operands[0]) && S_REG_P (operands[1]))
return \"mov.w %1,%0\";
return \"mov %1,%0\";
}")
(define_insn "movstrictsi"
[(set (strict_low_part (match_operand:SI 0 "general_operand" "=g,r"))
(match_operand:SI 1 "general_operand" "r,g"))]
""
"*
{
if (GET_CODE (operands[0]) == MEM)
return \"st.w %1,%0\";
if (GET_CODE (operands[1]) != REG)
return \"ld.w %1,%0\";
if (S_REG_P (operands[0]) && S_REG_P (operands[1]))
return \"mov.w %1,%0\";
return \"mov %1,%0\";
}")
(define_insn "movhi"
[(set (match_operand:HI 0 "general_operand" "=g,r")
(match_operand:HI 1 "general_operand" "r,g"))]
""
"*
{
if (push_operand (operands[0], HImode))
abort ();
else if (GET_CODE (operands[0]) == MEM)
return \"st.h %1,%0\";
else if (GET_CODE (operands[1]) == REG)
{
if (S_REG_P (operands[0]) && S_REG_P (operands[1]))
return \"mov.w %1,%0\";
else
return \"mov %1,%0\";
}
else if (GET_CODE (operands[1]) == CONST_INT)
return \"ld.w %1,%0\";
else
return \"ld.h %1,%0\";
}")
(define_insn "movqi"
[(set (match_operand:QI 0 "general_operand" "=g,r")
(match_operand:QI 1 "general_operand" "r,g"))]
""
"*
{
if (push_operand (operands[0], QImode))
abort ();
else if (GET_CODE (operands[0]) == MEM)
return \"st.b %1,%0\";
else if (GET_CODE (operands[1]) == REG)
{
if (S_REG_P (operands[0]) && S_REG_P (operands[1]))
return \"mov.w %1,%0\";
else
return \"mov %1,%0\";
}
else if (GET_CODE (operands[1]) == CONST_INT)
return \"ld.w %1,%0\";
else
return \"ld.b %1,%0\";
}")
;; Extension and truncation insns.
;; Those for integer source operand
;; are ordered widest source type first.
(define_insn "truncsiqi2"
[(set (match_operand:QI 0 "register_operand" "=d,a")
(truncate:QI (match_operand:SI 1 "register_operand" "d,a")))]
""
"cvtw.b %1,%0")
(define_insn "truncsihi2"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(truncate:HI (match_operand:SI 1 "register_operand" "d,a")))]
""
"cvtw.h %1,%0")
(define_insn "trunchiqi2"
[(set (match_operand:QI 0 "register_operand" "=r")
(truncate:QI (match_operand:HI 1 "register_operand" "0")))]
""
"")
(define_insn "truncdisi2"
[(set (match_operand:SI 0 "register_operand" "=d")
(truncate:SI (match_operand:DI 1 "register_operand" "d")))]
""
"cvtl.w %1,%0")
(define_insn "extendsidi2"
[(set (match_operand:DI 0 "register_operand" "=d")
(sign_extend:DI (match_operand:SI 1 "register_operand" "d")))]
""
"cvtw.l %1,%0")
(define_insn "extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(sign_extend:SI (match_operand:HI 1 "register_operand" "d,a")))]
""
"cvth.w %1,%0")
(define_insn "extendqihi2"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(sign_extend:HI (match_operand:QI 1 "register_operand" "d,a")))]
""
"cvtb.w %1,%0")
(define_insn "extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(sign_extend:SI (match_operand:QI 1 "register_operand" "d,a")))]
""
"cvtb.w %1,%0")
(define_insn "extendsfdf2"
[(set (match_operand:DF 0 "register_operand" "=d")
(float_extend:DF (match_operand:SF 1 "register_operand" "d")))]
""
"cvts.d %1,%0")
(define_insn "truncdfsf2"
[(set (match_operand:SF 0 "register_operand" "=d")
(float_truncate:SF (match_operand:DF 1 "register_operand" "d")))]
""
"cvtd.s %1,%0")
(define_insn "zero_extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI (match_operand:HI 1 "register_operand" "0")))]
""
"and #0xffff,%0")
(define_insn "zero_extendqihi2"
[(set (match_operand:HI 0 "register_operand" "=r")
(zero_extend:HI (match_operand:QI 1 "register_operand" "0")))]
""
"and #0xff,%0")
(define_insn "zero_extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI (match_operand:QI 1 "register_operand" "0")))]
""
"and #0xff,%0")
(define_insn "zero_extendsidi2"
[(set (match_operand:DI 0 "register_operand" "=d")
(zero_extend:DI (match_operand:SI 1 "register_operand" "0")))]
""
"ld.u #0,%0")
;; Fix-to-float conversion insns.
;; Note that the ones that start with SImode come first.
;; That is so that an operand that is a CONST_INT
;; (and therefore lacks a specific machine mode).
;; will be recognized as SImode (which is always valid)
;; rather than as QImode or HImode.
(define_insn "floatsisf2"
[(set (match_operand:SF 0 "register_operand" "=d")
(float:SF (match_operand:SI 1 "register_operand" "d")))]
""
"cvtw.s %1,%0")
(define_insn "floatdisf2"
[(set (match_operand:SF 0 "register_operand" "=d")
(float:SF (match_operand:DI 1 "register_operand" "d")))]
""
"cvtl.s %1,%0")
(define_insn "floatsidf2"
[(set (match_operand:DF 0 "register_operand" "=d")
(float:DF (match_operand:SI 1 "register_operand" "d")))]
"TARGET_C2"
"cvtw.d %1,%0")
(define_insn "floatdidf2"
[(set (match_operand:DF 0 "register_operand" "=d")
(float:DF (match_operand:DI 1 "register_operand" "d")))]
""
"cvtl.d %1,%0")
;; Float-to-fix conversion insns.
(define_insn "fix_truncsfsi2"
[(set (match_operand:SI 0 "register_operand" "=d")
(fix:SI (fix:SF (match_operand:SF 1 "register_operand" "d"))))]
""
"cvts.w %1,%0")
(define_insn "fix_truncsfdi2"
[(set (match_operand:DI 0 "register_operand" "=d")
(fix:DI (fix:SF (match_operand:SF 1 "register_operand" "d"))))]
""
"cvts.l %1,%0")
(define_insn "fix_truncdfsi2"
[(set (match_operand:SI 0 "register_operand" "=d")
(fix:SI (fix:DF (match_operand:DF 1 "register_operand" "d"))))]
""
"*
{
if (TARGET_C2)
return \"cvtd.w %1,%0\";
return \"cvtd.l %1,%0\";
}")
(define_insn "fix_truncdfdi2"
[(set (match_operand:DI 0 "register_operand" "=d")
(fix:DI (fix:DF (match_operand:DF 1 "register_operand" "d"))))]
""
"cvtd.l %1,%0")
;;- All kinds of add instructions.
(define_insn "adddf3"
[(set (match_operand:DF 0 "register_operand" "=d")
(plus:DF (match_operand:DF 1 "register_operand" "%0")
(match_operand:DF 2 "register_operand" "d")))]
""
"add.d %2,%0")
(define_insn "addsf3"
[(set (match_operand:SF 0 "register_operand" "=d")
(plus:SF (match_operand:SF 1 "register_operand" "%0")
(match_operand:SF 2 "nonmemory_operand" "dF")))]
""
"add.s %2,%0")
(define_insn "adddi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(plus:DI (match_operand:DI 1 "register_operand" "%0")
(match_operand:DI 2 "register_operand" "d")))]
""
"add.l %2,%0")
;; special case of addsi3, needed to specify an A reg for the destination
;; when the source is a sum involving FP or AP.
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=a")
(plus:SI (match_operand:SI 1 "register_operand" "%a")
(match_operand:SI 2 "immediate_operand" "i")))]
"operands[1] == frame_pointer_rtx || operands[1] == arg_pointer_rtx"
"ldea %a2(%1),%0")
(define_insn "addsi3"
[(set (match_operand:SI 0 "register_operand" "=d,a,a")
(plus:SI (match_operand:SI 1 "nonmemory_operand" "%0,0,a")
(match_operand:SI 2 "nonmemory_operand" "di,ri,i")))]
""
"* switch (which_alternative)
{
case 0:
case 1:
return \"add.w %2,%0\";
case 2:
if ((TARGET_C2 || A_REG_P (operands[0]))
&& operands[1] != stack_pointer_rtx)
return \"ldea %a2(%1),%0\";
else
return \"mov %1,%0\;add.w %2,%0\";
}")
(define_insn "addhi3"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(plus:HI (match_operand:HI 1 "register_operand" "%0,0")
(match_operand:HI 2 "nonmemory_operand" "di,ai")))]
""
"add.h %2,%0")
(define_insn "addqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(plus:QI (match_operand:QI 1 "register_operand" "%0")
(match_operand:QI 2 "register_operand" "d")))]
""
"add.b %2,%0")
;;- All kinds of subtract instructions.
(define_insn "subdf3"
[(set (match_operand:DF 0 "register_operand" "=d")
(minus:DF (match_operand:DF 1 "register_operand" "0")
(match_operand:DF 2 "register_operand" "d")))]
""
"sub.d %2,%0")
(define_insn "subsf3"
[(set (match_operand:SF 0 "register_operand" "=d")
(minus:SF (match_operand:SF 1 "register_operand" "0")
(match_operand:SF 2 "nonmemory_operand" "dF")))]
""
"sub.s %2,%0")
(define_insn "subdi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(minus:DI (match_operand:DI 1 "register_operand" "0")
(match_operand:DI 2 "register_operand" "d")))]
""
"sub.l %2,%0")
(define_insn "subsi3"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(minus:SI (match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "di,ai")))]
""
"sub.w %2,%0")
(define_insn "subhi3"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(minus:HI (match_operand:HI 1 "register_operand" "0,0")
(match_operand:HI 2 "nonmemory_operand" "di,ai")))]
""
"sub.h %2,%0")
(define_insn "subqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(minus:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "register_operand" "d")))]
""
"sub.b %2,%0")
;;- Multiply instructions.
(define_insn "muldf3"
[(set (match_operand:DF 0 "register_operand" "=d")
(mult:DF (match_operand:DF 1 "register_operand" "%0")
(match_operand:DF 2 "register_operand" "d")))]
""
"mul.d %2,%0")
(define_insn "mulsf3"
[(set (match_operand:SF 0 "register_operand" "=d")
(mult:SF (match_operand:SF 1 "register_operand" "%0")
(match_operand:SF 2 "nonmemory_operand" "dF")))]
""
"mul.s %2,%0")
(define_insn "muldi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(mult:DI (match_operand:DI 1 "register_operand" "%0")
(match_operand:DI 2 "register_operand" "d")))]
""
"mul.l %2,%0")
(define_insn "mulsi3"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(mult:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "di,ai")))]
""
"mul.w %2,%0")
(define_insn "mulhi3"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(mult:HI (match_operand:HI 1 "register_operand" "%0,0")
(match_operand:HI 2 "nonmemory_operand" "di,ai")))]
""
"mul.h %2,%0")
(define_insn "mulqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(mult:QI (match_operand:QI 1 "register_operand" "%0")
(match_operand:QI 2 "register_operand" "d")))]
""
"mul.b %2,%0")
;;- Divide instructions.
(define_insn "divdf3"
[(set (match_operand:DF 0 "register_operand" "=d")
(div:DF (match_operand:DF 1 "register_operand" "0")
(match_operand:DF 2 "register_operand" "d")))]
""
"div.d %2,%0")
(define_insn "divsf3"
[(set (match_operand:SF 0 "register_operand" "=d")
(div:SF (match_operand:SF 1 "register_operand" "0")
(match_operand:SF 2 "nonmemory_operand" "dF")))]
""
"div.s %2,%0")
(define_insn "divdi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(div:DI (match_operand:DI 1 "register_operand" "0")
(match_operand:DI 2 "register_operand" "d")))]
""
"div.l %2,%0")
(define_insn "udivdi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(udiv:DI (match_operand:DI 1 "register_operand" "d")
(match_operand:DI 2 "register_operand" "d")))]
""
"psh.l %2\;psh.l %1\;callq udiv64\;pop.l %0\;add.w #8,sp")
(define_insn "divsi3"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(div:SI (match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "di,ai")))]
""
"div.w %2,%0")
(define_insn "divhi3"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(div:HI (match_operand:HI 1 "register_operand" "0,0")
(match_operand:HI 2 "nonmemory_operand" "di,ai")))]
""
"div.h %2,%0")
(define_insn "divqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(div:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "register_operand" "d")))]
""
"div.b %2,%0")
;; - and, or, xor
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d")
(and:DI (match_operand:DI 1 "register_operand" "%0")
(match_operand:DI 2 "immediate_operand" "Fn")))]
"GET_CODE (operands[2]) == CONST_INT
|| (GET_CODE (operands[2]) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (operands[2]) == -1)"
"and %2,%0")
(define_insn "anddi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(and:DI (match_operand:DI 1 "register_operand" "%0")
(match_operand:DI 2 "register_operand" "d")))]
""
"and %2,%0")
(define_insn "andsi3"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(and:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "di,ai")))]
""
"and %2,%0")
(define_insn "andhi3"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(and:HI (match_operand:HI 1 "register_operand" "%0,0")
(match_operand:HI 2 "nonmemory_operand" "di,ai")))]
""
"and %2,%0")
(define_insn "andqi3"
[(set (match_operand:QI 0 "register_operand" "=d,a")
(and:QI (match_operand:QI 1 "register_operand" "%0,0")
(match_operand:QI 2 "nonmemory_operand" "di,ai")))]
""
"and %2,%0")
;;- Bit set instructions.
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d")
(ior:DI (match_operand:DI 1 "register_operand" "%0")
(match_operand:DI 2 "immediate_operand" "Fn")))]
"GET_CODE (operands[2]) == CONST_INT
|| (GET_CODE (operands[2]) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (operands[2]) == 0)"
"or %2,%0")
(define_insn "iordi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(ior:DI (match_operand:DI 1 "register_operand" "%0")
(match_operand:DI 2 "register_operand" "d")))]
""
"or %2,%0")
(define_insn "iorsi3"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(ior:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "di,ai")))]
""
"or %2,%0")
(define_insn "iorhi3"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(ior:HI (match_operand:HI 1 "register_operand" "%0,0")
(match_operand:HI 2 "nonmemory_operand" "di,ai")))]
""
"or %2,%0")
(define_insn "iorqi3"
[(set (match_operand:QI 0 "register_operand" "=d,a")
(ior:QI (match_operand:QI 1 "register_operand" "%0,0")
(match_operand:QI 2 "nonmemory_operand" "di,ai")))]
""
"or %2,%0")
;;- xor instructions.
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d")
(xor:DI (match_operand:DI 1 "register_operand" "%0")
(match_operand:DI 2 "immediate_operand" "Fn")))]
"GET_CODE (operands[2]) == CONST_INT
|| (GET_CODE (operands[2]) == CONST_DOUBLE
&& CONST_DOUBLE_HIGH (operands[2]) == 0)"
"xor %2,%0")
(define_insn "xordi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(xor:DI (match_operand:DI 1 "register_operand" "%0")
(match_operand:DI 2 "register_operand" "d")))]
""
"xor %2,%0")
(define_insn "xorsi3"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(xor:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "di,ai")))]
""
"xor %2,%0")
(define_insn "xorhi3"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(xor:HI (match_operand:HI 1 "register_operand" "%0,0")
(match_operand:HI 2 "nonmemory_operand" "di,ai")))]
""
"xor %2,%0")
(define_insn "xorqi3"
[(set (match_operand:QI 0 "register_operand" "=d,a")
(xor:QI (match_operand:QI 1 "register_operand" "%0,0")
(match_operand:QI 2 "nonmemory_operand" "di,ai")))]
""
"xor %2,%0")
(define_insn "negdf2"
[(set (match_operand:DF 0 "register_operand" "=d")
(neg:DF (match_operand:DF 1 "register_operand" "d")))]
""
"neg.d %1,%0")
(define_insn "negsf2"
[(set (match_operand:SF 0 "register_operand" "=d")
(neg:SF (match_operand:SF 1 "register_operand" "d")))]
""
"neg.s %1,%0")
(define_insn "negdi2"
[(set (match_operand:DI 0 "register_operand" "=d")
(neg:DI (match_operand:DI 1 "register_operand" "d")))]
""
"neg.l %1,%0")
(define_insn "negsi2"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(neg:SI (match_operand:SI 1 "register_operand" "d,a")))]
""
"neg.w %1,%0")
(define_insn "neghi2"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(neg:HI (match_operand:HI 1 "register_operand" "d,a")))]
""
"neg.h %1,%0")
(define_insn "negqi2"
[(set (match_operand:QI 0 "register_operand" "=d")
(neg:QI (match_operand:QI 1 "register_operand" "d")))]
""
"neg.b %1,%0")
(define_insn "one_cmpldi2"
[(set (match_operand:DI 0 "register_operand" "=d")
(not:DI (match_operand:DI 1 "register_operand" "d")))]
""
"not %1,%0")
(define_insn "one_cmplsi2"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(not:SI (match_operand:SI 1 "register_operand" "d,a")))]
""
"not %1,%0")
(define_insn "one_cmplhi2"
[(set (match_operand:HI 0 "register_operand" "=d,a")
(not:HI (match_operand:HI 1 "register_operand" "d,a")))]
""
"not %1,%0")
(define_insn "one_cmplqi2"
[(set (match_operand:QI 0 "register_operand" "=d,a")
(not:QI (match_operand:QI 1 "register_operand" "d,a")))]
""
"not %1,%0")
;;- shifts
;;
;; Convex shift instructions are logical shifts.
;; To make signed right shifts:
;; for SImode, sign extend to DImode and shift, works for 0..32
;; for DImode, shift and then extend the sign, works for 0..63 -- but not 64
(define_insn "lshlsi3"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(lshift:SI (match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "di,ai")))]
""
"*
{
if (operands[2] == const1_rtx)
return \"add.w %0,%0\";
else if (TARGET_C2 && S_REG_P (operands[0]))
return \"shf.w %2,%0\";
else
return \"shf %2,%0\";
}")
(define_insn "ashlsi3"
[(set (match_operand:SI 0 "register_operand" "=d,a")
(ashift:SI (match_operand:SI 1 "register_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "di,ai")))]
""
"*
{
if (operands[2] == const1_rtx)
return \"add.w %0,%0\";
else if (TARGET_C2 && S_REG_P (operands[0]))
return \"shf.w %2,%0\";
else
return \"shf %2,%0\";
}")
(define_expand "lshrsi3"
[(set (match_operand:SI 0 "register_operand" "")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "")
(neg:SI (match_operand:SI 2 "nonmemory_operand" ""))))]
""
"operands[2] = negate_rtx (SImode, operands[2]);")
(define_insn ""
[(set
(match_operand:SI 0 "register_operand" "=d,a")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "0,0")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "di,ai"))))]
""
"*
{
if (A_REG_P (operands[0]))
return \"shf %2,%0\";
else if (TARGET_C2)
return \"shf.w %2,%0\";
else
return \"ld.u #0,%0\;shf %2,%0\";
}")
(define_insn ""
[(set
(match_operand:SI 0 "register_operand" "=r")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "immediate_operand" "i")))]
""
"*
{
if (A_REG_P (operands[0]))
return \"shf #%n2,%0\";
else if (TARGET_C2)
return \"shf.w #%n2,%0\";
else
return \"ld.u #0,%0\;shf #%n2,%0\";
}")
(define_expand "ashrsi3"
[(set (match_operand:SI 0 "register_operand" "=d")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "d")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "di"))))]
""
"operands[2] = negate_rtx (SImode, operands[2]);")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=&d")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "d")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "di"))))]
""
"cvtw.l %1,%0\;shf %2,%0")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=&d")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "immediate_operand" "i")))]
""
"cvtw.l %1,%0\;shf #%n2,%0")
(define_insn "lshldi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(lshift:DI (match_operand:DI 1 "register_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "di")))]
""
"shf %2,%0")
(define_insn "ashldi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(ashift:DI (match_operand:DI 1 "register_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "di")))]
""
"shf %2,%0")
(define_expand "lshrdi3"
[(set (match_operand:DI 0 "register_operand" "=d")
(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "di"))))]
""
"operands[2] = negate_rtx (SImode, operands[2]);")
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d")
(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "di"))))]
""
"shf %2,%0")
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=d")
(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
(match_operand:SI 2 "immediate_operand" "i")))]
""
"shf #%n2,%0")
;; signed a >> b is
;; ((a >> b) ^ signbit) - signbit
;; where signbit is (1 << 63) >> b
(define_expand "ashrdi3"
[(match_operand:DI 0 "register_operand" "")
(match_operand:DI 1 "register_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")
(match_dup 3)]
""
"
{
if (GET_CODE (operands[2]) == CONST_INT)
{
int rshift = INTVAL (operands[2]);
operands[3] =
force_reg (DImode, immed_double_const (1 << (63 - rshift),
1 << (31 - rshift), DImode));
}
else
{
operands[3] =
force_reg (DImode, immed_double_const (0, 1 << 31, DImode));
emit_insn (gen_lshrdi3 (operands[3], operands[3], operands[2]));
}
emit_insn (gen_lshrdi3 (operands[0], operands[1], operands[2]));
emit_insn (gen_rtx (SET, VOIDmode, operands[0],
gen_rtx (XOR, DImode, operands[0], operands[3])));
emit_insn (gen_rtx (SET, VOIDmode, operands[0],
gen_rtx (MINUS, DImode, operands[0], operands[3])));
DONE;
}")
;; __builtin instructions
(define_insn "sqrtdf2"
[(set (match_operand:DF 0 "register_operand" "=d")
(sqrt:DF (match_operand:DF 1 "register_operand" "0")))]
"TARGET_C2"
"sqrt.d %0")
(define_insn "sqrtsf2"
[(set (match_operand:SF 0 "register_operand" "=d")
(sqrt:SF (match_operand:SF 1 "register_operand" "0")))]
"TARGET_C2"
"sqrt.s %0")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d")
(minus:SI (ffs:SI (match_operand:SI 1 "register_operand" "d"))
(const_int 1)))]
""
"tzc %1,%0\;le.w #32,%0\;jbrs.f .+6\;ld.w #-1,%0")
(define_expand "ffssi2"
[(set (match_operand:SI 0 "register_operand" "=d")
(minus:SI (ffs:SI (match_operand:SI 1 "register_operand" "d"))
(const_int 1)))
(set (match_dup 0)
(plus:SI (match_dup 0)
(const_int 1)))]
""
"")
(define_insn "abssf2"
[(set (match_operand:SF 0 "register_operand" "=d")
(abs:SF (match_operand:SF 1 "register_operand" "0")))]
""
"and #0x7fffffff,%0")
(define_expand "absdf2"
[(set (subreg:DI (match_operand:DF 0 "register_operand" "=d") 0)
(and:DI (subreg:DI (match_operand:DF 1 "register_operand" "d") 0)
(match_dup 2)))]
""
"operands[2] = force_reg (DImode,
immed_double_const (-1, 0x7fffffff, DImode));")
;; Jumps
(define_insn "jump"
[(set (pc)
(label_ref (match_operand 0 "" "")))]
""
"jbr %l0")
(define_insn "beq"
[(set (pc)
(if_then_else (eq (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return gen_cmp (operands[0], \"eq\", 't'); ")
(define_insn "bne"
[(set (pc)
(if_then_else (ne (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return gen_cmp (operands[0], \"eq\", 'f'); ")
(define_insn "bgt"
[(set (pc)
(if_then_else (gt (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return gen_cmp (operands[0], \"le\", 'f'); ")
(define_insn "bgtu"
[(set (pc)
(if_then_else (gtu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return gen_cmp (operands[0], \"leu\", 'f'); ")
(define_insn "blt"
[(set (pc)
(if_then_else (lt (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return gen_cmp (operands[0], \"lt\", 't'); ")
(define_insn "bltu"
[(set (pc)
(if_then_else (ltu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return gen_cmp (operands[0], \"ltu\", 't'); ")
(define_insn "bge"
[(set (pc)
(if_then_else (ge (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return gen_cmp (operands[0], \"lt\", 'f'); ")
(define_insn "bgeu"
[(set (pc)
(if_then_else (geu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return gen_cmp (operands[0], \"ltu\", 'f'); ")
(define_insn "ble"
[(set (pc)
(if_then_else (le (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return gen_cmp (operands[0], \"le\", 't'); ")
(define_insn "bleu"
[(set (pc)
(if_then_else (leu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"* return gen_cmp (operands[0], \"leu\", 't'); ")
(define_insn ""
[(set (pc)
(if_then_else (eq (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return gen_cmp (operands[0], \"eq\", 'f'); ")
(define_insn ""
[(set (pc)
(if_then_else (ne (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return gen_cmp (operands[0], \"eq\", 't'); ")
(define_insn ""
[(set (pc)
(if_then_else (gt (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return gen_cmp (operands[0], \"le\", 't'); ")
(define_insn ""
[(set (pc)
(if_then_else (gtu (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return gen_cmp (operands[0], \"leu\", 't'); ")
(define_insn ""
[(set (pc)
(if_then_else (lt (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return gen_cmp (operands[0], \"lt\", 'f'); ")
(define_insn ""
[(set (pc)
(if_then_else (ltu (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return gen_cmp (operands[0], \"ltu\", 'f'); ")
(define_insn ""
[(set (pc)
(if_then_else (ge (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return gen_cmp (operands[0], \"lt\", 't'); ")
(define_insn ""
[(set (pc)
(if_then_else (geu (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return gen_cmp (operands[0], \"ltu\", 't'); ")
(define_insn ""
[(set (pc)
(if_then_else (le (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return gen_cmp (operands[0], \"le\", 'f'); ")
(define_insn ""
[(set (pc)
(if_then_else (leu (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"* return gen_cmp (operands[0], \"leu\", 'f'); ")
;; - Calls
;;
;; arg count word may be omitted to save a push and let gcc try to
;; combine the arg list pop. RETURN_POPS_ARGS from tm.h decides this.
(define_insn "call"
[(call (match_operand:QI 0 "memory_operand" "m")
(match_operand:SI 1 "general_operand" "g"))]
""
"* return output_call (insn, operands[0], operands[1]);")
(define_insn "call_value"
[(set (match_operand 0 "" "=g")
(call (match_operand:QI 1 "memory_operand" "m")
(match_operand:SI 2 "general_operand" "g")))]
""
"* return output_call (insn, operands[1], operands[2]);")
(define_insn "return"
[(return)]
""
"rtn")
(define_insn "nop"
[(const_int 0)]
""
"nop")
(define_insn "tablejump"
[(set (pc) (match_operand:SI 0 "address_operand" "p"))
(use (label_ref (match_operand 1 "" "")))]
""
"jmp %a0")
(define_insn "indirect_jump"
[(set (pc) (match_operand:SI 0 "address_operand" "p"))]
""
"jmp %a0")
;;- Local variables:
;;- mode:emacs-lisp
;;- comment-start: ";;- "
;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
;;- eval: (modify-syntax-entry ?[ "(]")
;;- eval: (modify-syntax-entry ?] ")[")
;;- eval: (modify-syntax-entry ?{ "(}")
;;- eval: (modify-syntax-entry ?} "){")
;;- End:
;;- Machine description for Intel 860 chip for GNU C compiler
;; Copyright (C) 1989, 1990 Free Software Foundation, Inc.
;; 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, 675 Mass Ave, Cambridge, MA 02139, USA.
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
;;- updates for most instructions.
;;- Operand classes for the register allocator:
/* Bit-test instructions. */
(define_insn ""
[(set (cc0) (eq (and:SI (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "logic_operand" "rL"))
(const_int 0)))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
return \"and %1,%0,%?r0\";
}")
(define_insn ""
[(set (cc0) (ne (and:SI (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "logic_operand" "rL"))
(const_int 0)))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
cc_status.flags |= CC_NEGATED;
return \"and %1,%0,%?r0\";
}")
(define_insn ""
[(set (cc0) (eq (and:SI (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "immediate_operand" "i"))
(const_int 0)))]
"GET_CODE (operands[1]) == CONST_INT && (INTVAL (operands[1]) & 0xffff) == 0"
"*
{
CC_STATUS_PARTIAL_INIT;
return \"andh %H1,%0,%?r0\";
}")
(define_insn ""
[(set (cc0) (ne (and:SI (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "immediate_operand" "i"))
(const_int 0)))]
"GET_CODE (operands[1]) == CONST_INT && (INTVAL (operands[1]) & 0xffff) == 0"
"*
{
CC_STATUS_PARTIAL_INIT;
cc_status.flags |= CC_NEGATED;
return \"andh %H1,%0,%?r0\";
}")
(define_insn ""
[(set (cc0) (eq (ashiftrt:SI
(sign_extend:SI
(ashift:QI (match_operand:QI 0 "register_operand" "r")
(match_operand:QI 1 "logic_int" "n")))
(match_operand:SI 2 "logic_int" "n"))
(const_int 0)))]
""
"*
{
int width = 8 - INTVAL (operands[2]);
int pos = 8 - width - INTVAL (operands[1]);
CC_STATUS_PARTIAL_INIT;
operands[2] = gen_rtx (CONST_INT, VOIDmode,
~((-1) << width) << pos);
return \"and %2,%0,%?r0\";
}")
;; -------------------------------------------------------------------------
;; SImode signed integer comparisons
;; -------------------------------------------------------------------------
(define_insn "cmpeqsi"
[(set (cc0) (eq (match_operand:SI 0 "logic_operand" "r,rL")
(match_operand:SI 1 "logic_operand" "L,r")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
if (REG_P (operands[0]))
return \"xor %1,%0,%?r0\";
else
return \"xor %0,%1,%?r0\";
}")
(define_insn "cmpnesi"
[(set (cc0) (ne (match_operand:SI 0 "logic_operand" "r,rL")
(match_operand:SI 1 "logic_operand" "L,r")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
cc_status.flags |= CC_NEGATED;
if (REG_P (operands[0]))
return \"xor %1,%0,%?r0\";
else
return \"xor %0,%1,%?r0\";
}")
(define_insn "cmpltsi"
[(set (cc0) (lt (match_operand:SI 0 "arith_operand" "r,rI")
(match_operand:SI 1 "arith_operand" "I,r")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
if (REG_P (operands[1]))
return \"subs %0,%1,%?r0\";
else
{
cc_status.flags |= CC_REVERSED;
operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1]));
return \"adds %1,%0,%?r0\";
}
}")
(define_insn "cmpgtsi"
[(set (cc0) (gt (match_operand:SI 0 "arith_operand" "r,rI")
(match_operand:SI 1 "arith_operand" "I,r")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
if (REG_P (operands[0]))
return \"subs %1,%0,%?r0\";
else
{
cc_status.flags |= CC_REVERSED;
operands[0] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[0]));
return \"adds %0,%1,%?r0\";
}
}")
(define_insn "cmplesi"
[(set (cc0) (le (match_operand:SI 0 "arith_operand" "r,rI")
(match_operand:SI 1 "arith_operand" "I,r")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
cc_status.flags |= CC_NEGATED;
if (REG_P (operands[0]))
return \"subs %1,%0,%?r0\";
else
{
cc_status.flags |= CC_REVERSED;
operands[0] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[0]));
return \"adds %0,%1,%?r0\";
}
}")
(define_insn "cmpgesi"
[(set (cc0) (ge (match_operand:SI 0 "arith_operand" "r,rI")
(match_operand:SI 1 "arith_operand" "I,r")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
cc_status.flags |= CC_NEGATED;
if (REG_P (operands[1]))
return \"subs %0,%1,%?r0\";
else
{
cc_status.flags |= CC_REVERSED;
operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1]));
return \"adds %1,%0,%?r0\";
}
}")
;; -------------------------------------------------------------------------
;; SImode unsigned integer comparisons
;; -------------------------------------------------------------------------
;; WARNING! There is a small i860 hardware limitation (bug?) which we
;; may run up against (if we are not careful) when we are trying to do
;; unsigned comparisons like (x >= 0), (x < 0), (0 <= x), and (0 > x).
;; Specifically, we must avoid using an `addu' instruction to perform
;; such comparisons because the result (in the CC bit register) will
;; come out wrong. (This fact is documented in a footnote on page 7-10
;; of the 1991 version of the i860 Microprocessor Family Programmer's
;; Reference Manual). Note that unsigned comparisons of this sort are
;; always redundant anyway, because an unsigned quantity can never be
;; less than zero. When we see cases like this, we generate an
;; `or K,%r0,%r0' instruction instead (where K is a constant 0 or -1)
;; so as to get the CC bit register set properly for any subsequent
;; conditional jump instruction.
(define_insn "cmpgeusi"
[(set (cc0) (geu (match_operand:SI 0 "arith_operand" "r,rI")
(match_operand:SI 1 "arith_operand" "I,r")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
if (REG_P (operands[1]))
return \"subu %0,%1,%?r0\";
else
{
if (INTVAL (operands[1]) == 0)
return \"or 0,%?r0,%?r0\";
else
{
cc_status.flags |= CC_REVERSED;
operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1]));
return \"addu %1,%0,%?r0\";
}
}
}")
(define_insn "cmpleusi"
[(set (cc0) (leu (match_operand:SI 0 "arith_operand" "r,rI")
(match_operand:SI 1 "arith_operand" "I,r")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
if (REG_P (operands[0]))
return \"subu %1,%0,%?r0\";
else
{
if (INTVAL (operands[0]) == 0)
return \"or 0,%?r0,%?r0\";
else
{
cc_status.flags |= CC_REVERSED;
operands[0] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[0]));
return \"addu %0,%1,%?r0\";
}
}
}")
;; -------------------------------------------------------------------------
;; SFmode floating-point comparisons
;; -------------------------------------------------------------------------
(define_insn "cmpeqsf"
[(set (cc0) (eq (match_operand:SF 0 "reg_or_0_operand" "fG")
(match_operand:SF 1 "reg_or_0_operand" "fG")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
return \"pfeq.ss %r0,%r1,%?f0\";
}")
(define_insn "cmpnesf"
[(set (cc0) (ne (match_operand:SF 0 "reg_or_0_operand" "fG")
(match_operand:SF 1 "reg_or_0_operand" "fG")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
cc_status.flags |= CC_NEGATED;
return \"pfeq.ss %r1,%r0,%?f0\";
}")
;; NOTE: The i860 Programmer's Reference Manual says that when we are
;; doing (A < B) or (A > B) comparisons, we have to use pfgt for these
;; in order to be IEEE compliant (in case a trap occurs during these
;; operations). Conversely, for (A <= B) or (A >= B) comparisons, we
;; must use pfle to be IEEE compliant.
(define_insn "cmpltsf"
[(set (cc0) (lt (match_operand:SF 0 "reg_or_0_operand" "fG")
(match_operand:SF 1 "reg_or_0_operand" "fG")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
return \"pfgt.ss %r1,%r0,%?f0\";
}")
(define_insn "cmpgtsf"
[(set (cc0) (gt (match_operand:SF 0 "reg_or_0_operand" "fG")
(match_operand:SF 1 "reg_or_0_operand" "fG")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
return \"pfgt.ss %r0,%r1,%?f0\";
}")
;; NOTE: The pfle opcode doesn't do what you think it does. It is
;; bass-ackwards. It *clears* the CC flag if the first operand is
;; less than or equal to the second. Thus, we have to set CC_NEGATED
;; for the following two patterns.
(define_insn "cmplesf"
[(set (cc0) (le (match_operand:SF 0 "reg_or_0_operand" "fG")
(match_operand:SF 1 "reg_or_0_operand" "fG")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
cc_status.flags |= CC_NEGATED;
return \"pfle.ss %r0,%r1,%?f0\";
}")
(define_insn "cmpgesf"
[(set (cc0) (ge (match_operand:SF 0 "reg_or_0_operand" "fG")
(match_operand:SF 1 "reg_or_0_operand" "fG")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
cc_status.flags |= CC_NEGATED;
return \"pfle.ss %r1,%r0,%?f0\";
}")
;; -------------------------------------------------------------------------
;; DFmode floating-point comparisons
;; -------------------------------------------------------------------------
(define_insn "cmpeqdf"
[(set (cc0) (eq (match_operand:DF 0 "reg_or_0_operand" "fG")
(match_operand:DF 1 "reg_or_0_operand" "fG")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
return \"pfeq.dd %r0,%r1,%?f0\";
}")
(define_insn "cmpnedf"
[(set (cc0) (ne (match_operand:DF 0 "reg_or_0_operand" "fG")
(match_operand:DF 1 "reg_or_0_operand" "fG")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
cc_status.flags |= CC_NEGATED;
return \"pfeq.dd %r1,%r0,%?f0\";
}")
;; NOTE: The i860 Programmer's Reference Manual says that when we are
;; doing (A < B) or (A > B) comparisons, we have to use pfgt for these
;; in order to be IEEE compliant (in case a trap occurs during these
;; operations). Conversely, for (A <= B) or (A >= B) comparisons, we
;; must use pfle to be IEEE compliant.
(define_insn "cmpltdf"
[(set (cc0) (lt (match_operand:DF 0 "reg_or_0_operand" "fG")
(match_operand:DF 1 "reg_or_0_operand" "fG")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
return \"pfgt.dd %r1,%r0,%?f0\";
}")
(define_insn "cmpgtdf"
[(set (cc0) (gt (match_operand:DF 0 "reg_or_0_operand" "fG")
(match_operand:DF 1 "reg_or_0_operand" "fG")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
return \"pfgt.dd %r0,%r1,%?f0\";
}")
;; NOTE: The pfle opcode doesn't do what you think it does. It is
;; bass-ackwards. It *clears* the CC flag if the first operand is
;; less than or equal to the second. Thus, we have to set CC_NEGATED
;; for the following two patterns.
(define_insn "cmpledf"
[(set (cc0) (le (match_operand:DF 0 "reg_or_0_operand" "fG")
(match_operand:DF 1 "reg_or_0_operand" "fG")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
cc_status.flags |= CC_NEGATED;
return \"pfle.dd %r0,%r1,%?f0\";
}")
(define_insn "cmpgedf"
[(set (cc0) (ge (match_operand:DF 0 "reg_or_0_operand" "fG")
(match_operand:DF 1 "reg_or_0_operand" "fG")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
cc_status.flags |= CC_NEGATED;
return \"pfle.dd %r1,%r0,%?f0\";
}")
;; ------------------------------------------------------------------------
;; Integer EQ/NE comparisons against constant values which will fit in the
;; 16-bit immediate field of an instruction. These are made by combining.
;; ------------------------------------------------------------------------
(define_insn ""
[(set (cc0) (eq (zero_extend:SI (match_operand:HI 0 "load_operand" "m"))
(match_operand:SI 1 "small_int" "I")))]
"INTVAL (operands[1]) >= 0"
"*
{
CC_STATUS_PARTIAL_INIT;
return \"ld.s %0,%?r31\;xor %1,%?r31,%?r0\";
}")
(define_insn ""
[(set (cc0) (eq (match_operand:SI 0 "small_int" "I")
(zero_extend:SI (match_operand:HI 1 "load_operand" "m"))))]
"INTVAL (operands[0]) >= 0"
"*
{
CC_STATUS_PARTIAL_INIT;
return \"ld.s %1,%?r31\;xor %0,%?r31,%?r0\";
}")
;; ------------------------------------------------------------------------
;; Define the real conditional branch instructions.
;; ------------------------------------------------------------------------
(define_insn "cbranch"
[(set (pc) (if_then_else (eq (cc0) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"*
{
if ((cc_prev_status.flags & CC_NEGATED) == 0)
return \"bnc %l0\";
else
return \"bc %l0\";
}")
(define_insn "flipped_cbranch"
[(set (pc) (if_then_else (ne (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"*
{
if ((cc_prev_status.flags & CC_NEGATED) == 0)
return \"bnc %l0\";
else
return \"bc %l0\";
}")
(define_insn "inverse_cbranch"
[(set (pc) (if_then_else (eq (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"*
{
if ((cc_prev_status.flags & CC_NEGATED) == 0)
return \"bc %l0\";
else
return \"bnc %l0\";
}")
(define_insn "flipped_inverse_cbranch"
[(set (pc) (if_then_else (ne (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"*
{
if ((cc_prev_status.flags & CC_NEGATED) == 0)
return \"bc %l0\";
else
return \"bnc %l0\";
}")
;; Simple BTE/BTNE compare-and-branch insns made by combining.
(define_insn ""
[(set (pc)
(if_then_else (eq (match_operand:QI 0 "register_operand" "r")
(match_operand:QI 1 "bte_operand" "rK"))
(label_ref (match_operand 2 "" ""))
(pc)))]
""
"bte %1,%0,%2")
(define_insn ""
[(set (pc)
(if_then_else (ne (match_operand:QI 0 "register_operand" "r")
(match_operand:QI 1 "bte_operand" "rK"))
(label_ref (match_operand 2 "" ""))
(pc)))]
""
"btne %1,%0,%2")
(define_insn ""
[(set (pc)
(if_then_else (eq (match_operand:QI 0 "register_operand" "r")
(match_operand:QI 1 "bte_operand" "rK"))
(pc)
(label_ref (match_operand 2 "" ""))))]
""
"btne %1,%0,%2")
(define_insn ""
[(set (pc)
(if_then_else (ne (match_operand:QI 0 "register_operand" "r")
(match_operand:QI 1 "bte_operand" "rK"))
(pc)
(label_ref (match_operand 2 "" ""))))]
""
"bte %1,%0,%2")
(define_insn ""
[(set (pc)
(if_then_else (eq (match_operand:HI 0 "register_operand" "r")
(match_operand:HI 1 "bte_operand" "rK"))
(label_ref (match_operand 2 "" ""))
(pc)))]
""
"bte %1,%0,%2")
(define_insn ""
[(set (pc)
(if_then_else (ne (match_operand:HI 0 "register_operand" "r")
(match_operand:HI 1 "bte_operand" "rK"))
(label_ref (match_operand 2 "" ""))
(pc)))]
""
"btne %1,%0,%2")
(define_insn ""
[(set (pc)
(if_then_else (eq (match_operand:HI 0 "register_operand" "r")
(match_operand:HI 1 "bte_operand" "rK"))
(pc)
(label_ref (match_operand 2 "" ""))))]
""
"btne %1,%0,%2")
(define_insn ""
[(set (pc)
(if_then_else (ne (match_operand:HI 0 "register_operand" "r")
(match_operand:HI 1 "bte_operand" "rK"))
(pc)
(label_ref (match_operand 2 "" ""))))]
""
"bte %1,%0,%2")
(define_insn ""
[(set (pc)
(if_then_else (eq (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "bte_operand" "rK"))
(label_ref (match_operand 2 "" ""))
(pc)))]
""
"bte %1,%0,%2")
(define_insn ""
[(set (pc)
(if_then_else (ne (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "bte_operand" "rK"))
(label_ref (match_operand 2 "" ""))
(pc)))]
""
"btne %1,%0,%2")
(define_insn ""
[(set (pc)
(if_then_else (eq (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "bte_operand" "rK"))
(pc)
(label_ref (match_operand 2 "" ""))))]
""
"btne %1,%0,%2")
(define_insn ""
[(set (pc)
(if_then_else (ne (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "bte_operand" "rK"))
(pc)
(label_ref (match_operand 2 "" ""))))]
""
"bte %1,%0,%2")
;; Load byte/halfword, zero-extend, & compare-and-branch insns.
;; These are made by combining.
(define_insn ""
[(set (pc)
(if_then_else (eq (zero_extend:SI (match_operand:QI 0 "memory_operand" "m"))
(match_operand:SI 1 "bte_operand" "K"))
(label_ref (match_operand 2 "" ""))
(pc)))
(match_scratch:SI 3 "=r")]
""
"ld.b %0,%3;bte %1,%3,%2")
(define_insn ""
[(set (pc)
(if_then_else (ne (zero_extend:SI (match_operand:QI 0 "memory_operand" "m"))
(match_operand:SI 1 "bte_operand" "K"))
(label_ref (match_operand 2 "" ""))
(pc)))
(match_scratch:SI 3 "=r")]
""
"ld.b %0,%3;btne %1,%3,%2")
(define_insn ""
[(set (pc)
(if_then_else (eq (zero_extend:SI (match_operand:QI 0 "memory_operand" "m"))
(match_operand:SI 1 "bte_operand" "K"))
(pc)
(label_ref (match_operand 2 "" ""))))
(match_scratch:SI 3 "=r")]
""
"ld.b %0,%3;btne %1,%3,%2")
(define_insn ""
[(set (pc)
(if_then_else (ne (zero_extend:SI (match_operand:QI 0 "memory_operand" "m"))
(match_operand:SI 1 "bte_operand" "K"))
(pc)
(label_ref (match_operand 2 "" ""))))
(match_scratch:SI 3 "=r")]
""
"ld.b %0,%3;bte %1,%3,%2")
(define_insn ""
[(set (pc)
(if_then_else (eq (zero_extend:SI (match_operand:HI 0 "memory_operand" "m"))
(match_operand:SI 1 "bte_operand" "K"))
(label_ref (match_operand 2 "" ""))
(pc)))
(match_scratch:SI 3 "=r")]
""
"ld.s %0,%3;bte %1,%3,%2")
(define_insn ""
[(set (pc)
(if_then_else (ne (zero_extend:SI (match_operand:HI 0 "memory_operand" "m"))
(match_operand:SI 1 "bte_operand" "K"))
(label_ref (match_operand 2 "" ""))
(pc)))
(match_scratch:SI 3 "=r")]
""
"ld.s %0,%3;btne %1,%3,%2")
(define_insn ""
[(set (pc)
(if_then_else (eq (zero_extend:SI (match_operand:HI 0 "memory_operand" "m"))
(match_operand:SI 1 "bte_operand" "K"))
(pc)
(label_ref (match_operand 2 "" ""))))
(match_scratch:SI 3 "=r")]
""
"ld.s %0,%3;btne %1,%3,%2")
(define_insn ""
[(set (pc)
(if_then_else (ne (zero_extend:SI (match_operand:HI 0 "memory_operand" "m"))
(match_operand:SI 1 "bte_operand" "K"))
(pc)
(label_ref (match_operand 2 "" ""))))
(match_scratch:SI 3 "=r")]
""
"ld.s %0,%3;bte %1,%3,%2")
;; Generation of conditionals.
;; The first step is the emission of a standard-looking compare insn.
;; Then a standard-named conditional branch pattern is run.
;; That branch pattern looks back at the compare insn and deletes it.
;; It then emits a machine-specific compare insn and a branch-if-true
;; or a branch-if-false.
;; These patterns have `abort' because they are supposed to be deleted
;; in that fashion.
(define_insn "cmpsi"
[(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "compare_operand" "")))]
""
"* abort ();")
(define_insn "cmpsf"
[(set (cc0) (compare (match_operand:SF 0 "register_operand" "")
(match_operand:SF 1 "register_operand" "")))]
""
"* abort ();")
(define_insn "cmpdf"
[(set (cc0) (compare (match_operand:DF 0 "register_operand" "")
(match_operand:DF 1 "register_operand" "")))]
""
"* abort ();")
;; These are the standard-named conditional branch patterns.
;; Detailed comments are found in the first one only.
(define_expand "beq"
[(set (pc)
(if_then_else (eq (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
rtx label = operands[0];
enum insn_code code;
rtx prev;
/* Get out of the sequence just started for us. */
end_sequence ();
prev = get_last_insn ();
/* Examine the preceding compare insn, and get rid of it. */
code = recog_memoized (prev);
insn_extract (prev);
NEXT_INSN (PREV_INSN (prev)) = 0;
set_last_insn (PREV_INSN (prev));
/* Now once again start a sequence for our new instructions. */
start_sequence ();
/* Emit a single-condition compare insn according to
the type of operands and the condition to be tested. */
if (code == CODE_FOR_cmpsi)
emit_insn (gen_cmpeqsi (recog_operand[0], recog_operand[1]));
else if (code == CODE_FOR_cmpsf)
emit_insn (gen_cmpeqsf (recog_operand[0], recog_operand[1]));
else if (code == CODE_FOR_cmpdf)
emit_insn (gen_cmpeqdf (recog_operand[0], recog_operand[1]));
else
abort ();
/* Emit branch-if-true. */
emit_jump_insn (gen_flipped_inverse_cbranch (label));
DONE;
}")
(define_expand "bne"
[(set (pc)
(if_then_else (ne (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
rtx label = operands[0];
enum insn_code code;
rtx prev;
end_sequence ();
prev = get_last_insn ();
code = recog_memoized (prev);
insn_extract (prev);
NEXT_INSN (PREV_INSN (prev)) = 0;
set_last_insn (PREV_INSN (prev));
start_sequence ();
if (code == CODE_FOR_cmpsi)
emit_insn (gen_cmpeqsi (recog_operand[0], recog_operand[1]));
else if (code == CODE_FOR_cmpsf)
emit_insn (gen_cmpeqsf (recog_operand[0], recog_operand[1]));
else if (code == CODE_FOR_cmpdf)
emit_insn (gen_cmpeqdf (recog_operand[0], recog_operand[1]));
else
abort ();
emit_jump_insn (gen_flipped_cbranch (label));
DONE;
}")
(define_expand "bgt"
[(set (pc)
(if_then_else (gt (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
rtx label = operands[0];
enum insn_code code;
rtx prev;
end_sequence ();
prev = get_last_insn ();
code = recog_memoized (prev);
insn_extract (prev);
NEXT_INSN (PREV_INSN (prev)) = 0;
set_last_insn (PREV_INSN (prev));
start_sequence ();
if (code == CODE_FOR_cmpsi)
emit_insn (gen_cmpgtsi (recog_operand[0], recog_operand[1]));
else if (code == CODE_FOR_cmpsf)
emit_insn (gen_cmpgtsf (recog_operand[0], recog_operand[1]));
else if (code == CODE_FOR_cmpdf)
emit_insn (gen_cmpgtdf (recog_operand[0], recog_operand[1]));
else
abort ();
emit_jump_insn (gen_flipped_inverse_cbranch (label));
DONE;
}")
(define_expand "blt"
[(set (pc)
(if_then_else (lt (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
rtx label = operands[0];
enum insn_code code;
rtx prev;
end_sequence ();
prev = get_last_insn ();
code = recog_memoized (prev);
insn_extract (prev);
NEXT_INSN (PREV_INSN (prev)) = 0;
set_last_insn (PREV_INSN (prev));
start_sequence ();
if (code == CODE_FOR_cmpsi)
emit_insn (gen_cmpltsi (recog_operand[0], recog_operand[1]));
else if (code == CODE_FOR_cmpsf)
emit_insn (gen_cmpltsf (recog_operand[0], recog_operand[1]));
else if (code == CODE_FOR_cmpdf)
emit_insn (gen_cmpltdf (recog_operand[0], recog_operand[1]));
else
abort ();
emit_jump_insn (gen_flipped_inverse_cbranch (label));
DONE;
}")
(define_expand "ble"
[(set (pc)
(if_then_else (le (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
rtx label = operands[0];
enum insn_code code;
rtx prev;
end_sequence ();
prev = get_last_insn ();
code = recog_memoized (prev);
insn_extract (prev);
NEXT_INSN (PREV_INSN (prev)) = 0;
set_last_insn (PREV_INSN (prev));
start_sequence ();
if (code == CODE_FOR_cmpsi)
{
emit_insn (gen_cmpgtsi (recog_operand[0], recog_operand[1]));
emit_jump_insn (gen_flipped_cbranch (label));
}
else
{
if (code == CODE_FOR_cmpsf)
emit_insn (gen_cmplesf (recog_operand[0], recog_operand[1]));
else if (code == CODE_FOR_cmpdf)
emit_insn (gen_cmpledf (recog_operand[0], recog_operand[1]));
else
abort ();
emit_jump_insn (gen_flipped_inverse_cbranch (label));
}
DONE;
}")
(define_expand "bge"
[(set (pc)
(if_then_else (ge (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
rtx label = operands[0];
enum insn_code code;
rtx prev;
end_sequence ();
prev = get_last_insn ();
code = recog_memoized (prev);
insn_extract (prev);
NEXT_INSN (PREV_INSN (prev)) = 0;
set_last_insn (PREV_INSN (prev));
start_sequence ();
if (code == CODE_FOR_cmpsi)
{
emit_insn (gen_cmpltsi (recog_operand[0], recog_operand[1]));
emit_jump_insn (gen_flipped_cbranch (label));
}
else
{
if (code == CODE_FOR_cmpsf)
emit_insn (gen_cmpgesf (recog_operand[0], recog_operand[1]));
else if (code == CODE_FOR_cmpdf)
emit_insn (gen_cmpgedf (recog_operand[0], recog_operand[1]));
else
abort ();
emit_jump_insn (gen_flipped_inverse_cbranch (label));
}
DONE;
}")
(define_expand "bgtu"
[(set (pc)
(if_then_else (gtu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
rtx label = operands[0];
enum insn_code code;
rtx prev;
end_sequence ();
prev = get_last_insn ();
code = recog_memoized (prev);
insn_extract (prev);
NEXT_INSN (PREV_INSN (prev)) = 0;
set_last_insn (PREV_INSN (prev));
start_sequence ();
if (code == CODE_FOR_cmpsi)
emit_insn (gen_cmpleusi (recog_operand[0], recog_operand[1]));
else
abort ();
emit_jump_insn (gen_flipped_cbranch (label));
DONE;
}")
(define_expand "bltu"
[(set (pc)
(if_then_else (ltu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
rtx label = operands[0];
enum insn_code code;
rtx prev;
end_sequence ();
prev = get_last_insn ();
code = recog_memoized (prev);
insn_extract (prev);
NEXT_INSN (PREV_INSN (prev)) = 0;
set_last_insn (PREV_INSN (prev));
start_sequence ();
if (code == CODE_FOR_cmpsi)
emit_insn (gen_cmpgeusi (recog_operand[0], recog_operand[1]));
else
abort ();
emit_jump_insn (gen_flipped_cbranch (label));
DONE;
}")
(define_expand "bgeu"
[(set (pc)
(if_then_else (geu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
rtx label = operands[0];
enum insn_code code;
rtx prev;
end_sequence ();
prev = get_last_insn ();
code = recog_memoized (prev);
insn_extract (prev);
NEXT_INSN (PREV_INSN (prev)) = 0;
set_last_insn (PREV_INSN (prev));
start_sequence ();
if (code == CODE_FOR_cmpsi)
emit_insn (gen_cmpgeusi (recog_operand[0], recog_operand[1]));
else
abort ();
emit_jump_insn (gen_flipped_inverse_cbranch (label));
DONE;
}")
(define_expand "bleu"
[(set (pc)
(if_then_else (leu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"
{
rtx label = operands[0];
enum insn_code code;
rtx prev;
end_sequence ();
prev = get_last_insn ();
code = recog_memoized (prev);
insn_extract (prev);
NEXT_INSN (PREV_INSN (prev)) = 0;
set_last_insn (PREV_INSN (prev));
start_sequence ();
if (code == CODE_FOR_cmpsi)
emit_insn (gen_cmpleusi (recog_operand[0], recog_operand[1]));
else
abort ();
emit_jump_insn (gen_flipped_inverse_cbranch (label));
DONE;
}")
;; Move instructions
;; Note that source operands for `mov' pseudo-instructions are no longer
;; allowed (by the svr4 assembler) to be "big" things, i.e. constants that
;; won't fit in 16-bits. (This includes any sort of a relocatable address
;; also.) Thus, we must use an explicit orh/or pair of instructions if
;; the source operand is something "big".
(define_insn "movsi"
[(set (match_operand:SI 0 "general_operand" "=r,m,f")
(match_operand:SI 1 "general_operand" "rmif,rfJ,rmfJ"))]
""
"*
{
if (GET_CODE (operands[0]) == MEM)
{
if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
return output_store (operands);
if (FP_REG_P (operands[1]))
return \"fst.l %1,%0\";
return \"st.l %r1,%0\";
}
if (GET_CODE (operands[1]) == MEM)
{
if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
return output_load (operands);
if (FP_REG_P (operands[0]))
return \"fld.l %1,%0\";
return \"ld.l %1,%0\";
}
if (FP_REG_P (operands[1]) && FP_REG_P (operands[0]))
return \"fmov.ss %1,%0\";
if (FP_REG_P (operands[1]))
return \"fxfr %1,%0\";
if (FP_REG_P (operands[0]) && operands[1] == const0_rtx)
return \"fmov.ss %?f0,%0\";
if (FP_REG_P (operands[0]))
return \"ixfr %1,%0\";
if (GET_CODE (operands[1]) == REG)
return \"shl %?r0,%1,%0\";
CC_STATUS_PARTIAL_INIT;
if (GET_CODE (operands[1]) == CONST_INT)
{
if((INTVAL (operands[1]) & 0xffff0000) == 0)
return \"or %L1,%?r0,%0\";
if((INTVAL (operands[1]) & 0x0000ffff) == 0)
return \"orh %H1,%?r0,%0\";
}
return \"orh %H1,%?r0,%0\;or %L1,%0,%0\";
}")
(define_insn "movhi"
[(set (match_operand:HI 0 "general_operand" "=r,m,!*f,!r")
(match_operand:HI 1 "general_operand" "rmi,rJ,rJ*f,*f"))]
""
"*
{
if (GET_CODE (operands[0]) == MEM)
{
if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
return output_store (operands);
return \"st.s %r1,%0\";
}
if (GET_CODE (operands[1]) == MEM)
{
if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
return output_load (operands);
return \"ld.s %1,%0\";
}
if (FP_REG_P (operands[1]) && FP_REG_P (operands[0]))
return \"fmov.ss %1,%0\";
if (FP_REG_P (operands[1]))
return \"fxfr %1,%0\";
if (FP_REG_P (operands[0]) && operands[1] == const0_rtx)
return \"fmov.ss %?f0,%0\";
if (FP_REG_P (operands[0]))
return \"ixfr %1,%0\";
if (GET_CODE (operands[1]) == REG)
return \"shl %?r0,%1,%0\";
CC_STATUS_PARTIAL_INIT;
return \"or %L1,%?r0,%0\";
}")
(define_insn "movqi"
[(set (match_operand:QI 0 "general_operand" "=r,m,!*f,!r")
(match_operand:QI 1 "general_operand" "rmi,rJ,rJ*f,*f"))]
""
"*
{
if (GET_CODE (operands[0]) == MEM)
{
if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
return output_store (operands);
return \"st.b %r1,%0\";
}
if (GET_CODE (operands[1]) == MEM)
{
if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
return output_load (operands);
return \"ld.b %1,%0\";
}
if (FP_REG_P (operands[1]) && FP_REG_P (operands[0]))
return \"fmov.ss %1,%0\";
if (FP_REG_P (operands[1]))
return \"fxfr %1,%0\";
if (FP_REG_P (operands[0]) && operands[1] == const0_rtx)
return \"fmov.ss %?f0,%0\";
if (FP_REG_P (operands[0]))
return \"ixfr %1,%0\";
if (GET_CODE (operands[1]) == REG)
return \"shl %?r0,%1,%0\";
CC_STATUS_PARTIAL_INIT;
return \"or %L1,%?r0,%0\";
}")
;; The definition of this insn does not really explain what it does,
;; but it should suffice
;; that anything generated as this insn will be recognized as one
;; and that it won't successfully combine with anything.
(define_expand "movstrsi"
[(parallel [(set (mem:BLK (match_operand:BLK 0 "general_operand" ""))
(mem:BLK (match_operand:BLK 1 "general_operand" "")))
(use (match_operand:SI 2 "nonmemory_operand" ""))
(use (match_operand:SI 3 "immediate_operand" ""))
(clobber (match_dup 4))
(clobber (match_dup 5))
(clobber (match_dup 6))
(clobber (match_dup 0))
(clobber (match_dup 1))])]
""
"
{
operands[0] = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
operands[4] = gen_reg_rtx (SImode);
operands[5] = gen_reg_rtx (SImode);
operands[6] = gen_reg_rtx (SImode);
}")
(define_insn ""
[(set (mem:BLK (match_operand:SI 0 "register_operand" "r"))
(mem:BLK (match_operand:SI 1 "register_operand" "r")))
(use (match_operand:SI 2 "general_operand" "rn"))
(use (match_operand:SI 3 "immediate_operand" "i"))
(clobber (match_operand:SI 4 "register_operand" "=r"))
(clobber (match_operand:SI 5 "register_operand" "=r"))
(clobber (match_operand:SI 6 "register_operand" "=r"))
(clobber (match_dup 0))
(clobber (match_dup 1))]
""
"* return output_block_move (operands);")
;; Floating point move insns
;; This pattern forces (set (reg:DF ...) (const_double ...))
;; to be reloaded by putting the constant into memory.
;; It must come before the more general movdf pattern.
(define_insn ""
[(set (match_operand:DF 0 "general_operand" "=r,f,o")
(match_operand:DF 1 "" "mG,m,G"))]
"GET_CODE (operands[1]) == CONST_DOUBLE"
"*
{
if (FP_REG_P (operands[0]) || operands[1] == CONST0_RTX (DFmode))
return output_fp_move_double (operands);
return output_move_double (operands);
}")
(define_insn "movdf"
[(set (match_operand:DF 0 "general_operand" "=*rm,&*r,?f,?*rm")
(match_operand:DF 1 "general_operand" "*r,m,*rfmG,f"))]
""
"*
{
if (GET_CODE (operands[0]) == MEM
&& CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
return output_store (operands);
if (GET_CODE (operands[1]) == MEM
&& CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
return output_load (operands);
if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
return output_fp_move_double (operands);
return output_move_double (operands);
}")
(define_insn "movdi"
[(set (match_operand:DI 0 "general_operand" "=rm,&r,?f,?rm")
(match_operand:DI 1 "general_operand" "r,miF,rfmG,f"))]
""
"*
{
if (GET_CODE (operands[0]) == MEM
&& CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
return output_store (operands);
if (GET_CODE (operands[1]) == MEM
&& CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
return output_load (operands);
/* ??? How can we have a DFmode arg here with DImode above? */
if (FP_REG_P (operands[0]) && operands[1] == CONST0_RTX (DFmode))
return \"fmov.dd %?f0,%0\";
if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
return output_fp_move_double (operands);
return output_move_double (operands);
}")
;; The alternative m/r is separate from m/f
;; The first alternative is separate from the second for the same reason.
(define_insn "movsf"
[(set (match_operand:SF 0 "general_operand" "=*rf,*rf,*r,m,m")
(match_operand:SF 1 "general_operand" "*r,fmG,F,*r,f"))]
""
"*
{
if (GET_CODE (operands[0]) == MEM
&& CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
return output_store (operands);
if (GET_CODE (operands[1]) == MEM
&& CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
return output_load (operands);
if (FP_REG_P (operands[0]))
{
if (FP_REG_P (operands[1]))
return \"fmov.ss %1,%0\";
if (GET_CODE (operands[1]) == REG)
return \"ixfr %1,%0\";
if (operands[1] == CONST0_RTX (SFmode))
return \"fmov.ss %?f0,%0\";
if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
{
if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
&& (cc_prev_status.flags & CC_HI_R31_ADJ)
&& cc_prev_status.mdep == XEXP(operands[1],0)))
{
CC_STATUS_INIT;
cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
cc_status.mdep = XEXP (operands[1], 0);
return \"orh %h1,%?r0,%?r31\;fld.l %L1(%?r31),%0\";
}
return \"fld.l %L1(%?r31),%0\";
}
return \"fld.l %1,%0\";
}
if (FP_REG_P (operands[1]) || GET_CODE (operands[1]) == CONST_DOUBLE)
{
if (GET_CODE (operands[0]) == REG && FP_REG_P (operands[1]))
return \"fxfr %1,%0\";
if (GET_CODE (operands[0]) == REG)
{
CC_STATUS_PARTIAL_INIT;
if (GET_CODE (operands[1]) == CONST_DOUBLE)
{
register unsigned long ul;
ul = sfmode_constant_to_ulong (operands[1]);
if ((ul & 0x0000ffff) == 0)
return \"orh %H1,%?r0,%0\";
if ((ul & 0xffff0000) == 0)
return \"or %L1,%?r0,%0\";
}
return \"orh %H1,%?r0,%0\;or %L1,%0,%0\";
}
/* Now operand 0 must be memory.
If operand 1 is CONST_DOUBLE, its value must be 0. */
if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
{
if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
&& (cc_prev_status.flags & CC_HI_R31_ADJ)
&& XEXP (operands[0], 0) == cc_prev_status.mdep))
{
CC_STATUS_INIT;
cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
cc_status.mdep = XEXP (operands[0], 0);
output_asm_insn (\"orh %h0,%?r0,%?r31\", operands);
}
return \"fst.l %r1,%L0(%?r31)\";
}
return \"fst.l %r1,%0\";
}
if (GET_CODE (operands[0]) == MEM)
return \"st.l %r1,%0\";
if (GET_CODE (operands[1]) == MEM)
return \"ld.l %1,%0\";
if (operands[1] == CONST0_RTX (SFmode))
return \"shl %?r0,%?r0,%0\";
return \"mov %1,%0\";
}")
;; Special load insns for REG+REG addresses.
;; Such addresses are not "legitimate" because st rejects them.
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=rf")
(match_operand:DF 1 "indexed_operand" "m"))]
""
"*
{
if (FP_REG_P (operands[0]))
return output_fp_move_double (operands);
return output_move_double (operands);
}")
(define_insn ""
[(set (match_operand:SF 0 "register_operand" "=rf")
(match_operand:SF 1 "indexed_operand" "m"))]
""
"*
{
if (FP_REG_P (operands[0]))
return \"fld.l %1,%0\";
return \"ld.l %1,%0\";
}")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=rf")
(match_operand:SI 1 "indexed_operand" "m"))]
""
"*
{
if (FP_REG_P (operands[0]))
return \"fld.l %1,%0\";
return \"ld.l %1,%0\";
}")
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
(match_operand:HI 1 "indexed_operand" "m"))]
""
"ld.s %1,%0")
(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=r")
(match_operand:QI 1 "indexed_operand" "m"))]
""
"ld.b %1,%0")
;; Likewise for floating-point store insns.
(define_insn ""
[(set (match_operand:DF 0 "indexed_operand" "=m")
(match_operand:DF 1 "register_operand" "f"))]
""
"fst.d %1,%0")
(define_insn ""
[(set (match_operand:SF 0 "indexed_operand" "=m")
(match_operand:SF 1 "register_operand" "f"))]
""
"fst.l %1,%0")
;;- truncation instructions
(define_insn "truncsiqi2"
[(set (match_operand:QI 0 "general_operand" "=g")
(truncate:QI
(match_operand:SI 1 "register_operand" "r")))]
""
"*
{
if (GET_CODE (operands[0]) == MEM)
if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
{
if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
&& (cc_prev_status.flags & CC_HI_R31_ADJ)
&& XEXP (operands[0], 0) == cc_prev_status.mdep))
{
CC_STATUS_INIT;
cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
cc_status.mdep = XEXP (operands[0], 0);
output_asm_insn (\"orh %h0,%?r0,%?r31\", operands);
}
return \"st.b %1,%L0(%?r31)\";
}
else
return \"st.b %1,%0\";
return \"shl %?r0,%1,%0\";
}")
(define_insn "trunchiqi2"
[(set (match_operand:QI 0 "general_operand" "=g")
(truncate:QI
(match_operand:HI 1 "register_operand" "r")))]
""
"*
{
if (GET_CODE (operands[0]) == MEM)
if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
{
if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
&& (cc_prev_status.flags & CC_HI_R31_ADJ)
&& XEXP (operands[0], 0) == cc_prev_status.mdep))
{
CC_STATUS_INIT;
cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
cc_status.mdep = XEXP (operands[0], 0);
output_asm_insn (\"orh %h0,%?r0,%?r31\", operands);
}
return \"st.b %1,%L0(%?r31)\";
}
else
return \"st.b %1,%0\";
return \"shl %?r0,%1,%0\";
}")
(define_insn "truncsihi2"
[(set (match_operand:HI 0 "general_operand" "=g")
(truncate:HI
(match_operand:SI 1 "register_operand" "r")))]
""
"*
{
if (GET_CODE (operands[0]) == MEM)
if (CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
{
if (! ((cc_prev_status.flags & CC_KNOW_HI_R31)
&& (cc_prev_status.flags & CC_HI_R31_ADJ)
&& XEXP (operands[0], 0) == cc_prev_status.mdep))
{
CC_STATUS_INIT;
cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
cc_status.mdep = XEXP (operands[0], 0);
output_asm_insn (\"orh %h0,%?r0,%?r31\", operands);
}
return \"st.s %1,%L0(%?r31)\";
}
else
return \"st.s %1,%0\";
return \"shl %?r0,%1,%0\";
}")
;;- zero extension instructions
(define_insn "zero_extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI
(match_operand:HI 1 "register_operand" "r")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
return \"and 0xffff,%1,%0\";
}")
(define_insn "zero_extendqihi2"
[(set (match_operand:HI 0 "register_operand" "=r")
(zero_extend:HI
(match_operand:QI 1 "register_operand" "r")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
return \"and 0xff,%1,%0\";
}")
(define_insn "zero_extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(zero_extend:SI
(match_operand:QI 1 "register_operand" "r")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
return \"and 0xff,%1,%0\";
}")
;; Sign extension instructions.
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(sign_extend:SI
(match_operand:HI 1 "indexed_operand" "m")))]
""
"ld.s %1,%0")
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
(sign_extend:HI
(match_operand:QI 1 "indexed_operand" "m")))]
""
"ld.b %1,%0")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(sign_extend:SI
(match_operand:QI 1 "indexed_operand" "m")))]
""
"ld.b %1,%0")
(define_insn "extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(sign_extend:SI
(match_operand:HI 1 "nonimmediate_operand" "mr")))]
""
"*
{
if (REG_P (operands[1]))
return \"shl 16,%1,%0\;shra 16,%0,%0\";
if (GET_CODE (operands[1]) == CONST_INT)
abort ();
if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
{
CC_STATUS_INIT;
cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
cc_status.mdep = XEXP (operands[1], 0);
return \"orh %h1,%?r0,%?r31\;ld.s %L1(%?r31),%0\";
}
else
return \"ld.s %1,%0\";
}")
(define_insn "extendqihi2"
[(set (match_operand:HI 0 "register_operand" "=r")
(sign_extend:HI
(match_operand:QI 1 "nonimmediate_operand" "mr")))]
""
"*
{
if (REG_P (operands[1]))
return \"shl 24,%1,%0\;shra 24,%0,%0\";
if (GET_CODE (operands[1]) == CONST_INT)
abort ();
if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
{
CC_STATUS_INIT;
cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
cc_status.mdep = XEXP (operands[1], 0);
return \"orh %h1,%?r0,%?r31\;ld.b %L1(%?r31),%0\";
}
else
return \"ld.b %1,%0\";
}")
(define_insn "extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=r")
(sign_extend:SI
(match_operand:QI 1 "nonimmediate_operand" "mr")))]
""
"*
{
if (REG_P (operands[1]))
return \"shl 24,%1,%0\;shra 24,%0,%0\";
if (GET_CODE (operands[1]) == CONST_INT)
abort ();
if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
{
CC_STATUS_INIT;
cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
cc_status.mdep = XEXP (operands[1], 0);
return \"orh %h1,%?r0,%?r31\;ld.b %L1(%?r31),%0\";
}
else
return \"ld.b %1,%0\";
}")
;; Signed bitfield extractions come out looking like
;; (shiftrt (sign_extend (shift <Y> <C1>)) <C2>)
;; which we expand poorly as four shift insns.
;; These patters yeild two shifts:
;; (shiftrt (shift <Y> <C3>) <C4>)
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(ashiftrt:SI
(sign_extend:SI
(match_operand:QI 1 "register_operand" "r"))
(match_operand:SI 2 "logic_int" "n")))]
"INTVAL (operands[2]) < 8"
"*
{
return \"shl 24,%1,%0\;shra 24+%2,%0,%0\";
}")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(ashiftrt:SI
(sign_extend:SI
(subreg:QI (ashift:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "logic_int" "n")) 0))
(match_operand:SI 3 "logic_int" "n")))]
"INTVAL (operands[3]) < 8"
"*
{
return \"shl 0x18+%2,%1,%0\;shra 0x18+%3,%0,%0\";
}")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(ashiftrt:SI
(sign_extend:SI
(ashift:QI (match_operand:QI 1 "register_operand" "r")
(match_operand:QI 2 "logic_int" "n")))
(match_operand:SI 3 "logic_int" "n")))]
"INTVAL (operands[3]) < 8"
"*
{
return \"shl 0x18+%2,%1,%0\;shra 0x18+%3,%0,%0\";
}")
;; Special patterns for optimizing bit-field instructions.
;; First two patterns are for bitfields that came from memory
;; testing only the high bit. They work with old combiner.
(define_insn ""
[(set (cc0)
(eq (zero_extend:SI (subreg:QI (lshiftrt:SI (match_operand:SI 0 "register_operand" "r")
(const_int 7)) 0))
(const_int 0)))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
return \"and 128,%0,%?r0\";
}")
(define_insn ""
[(set (cc0)
(eq (sign_extend:SI (subreg:QI (ashiftrt:SI (match_operand:SI 0 "register_operand" "r")
(const_int 7)) 0))
(const_int 0)))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
return \"and 128,%0,%?r0\";
}")
;; next two patterns are good for bitfields coming from memory
;; (via pseudo-register) or from a register, though this optimization
;; is only good for values contained wholly within the bottom 13 bits
(define_insn ""
[(set (cc0)
(eq
(and:SI (lshiftrt:SI (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "logic_int" "n"))
(match_operand:SI 2 "logic_int" "n"))
(const_int 0)))]
"LOGIC_INTVAL (INTVAL (operands[2]) << INTVAL (operands[1]))"
"*
{
CC_STATUS_PARTIAL_INIT;
operands[2] = gen_rtx (CONST_INT, VOIDmode,
(INTVAL (operands[2]) << INTVAL (operands[1])));
return \"and %2,%0,%?r0\";
}")
(define_insn ""
[(set (cc0)
(eq
(and:SI (ashiftrt:SI (match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "logic_int" "n"))
(match_operand:SI 2 "logic_int" "n"))
(const_int 0)))]
"LOGIC_INTVAL (INTVAL (operands[2]) << INTVAL (operands[1]))"
"*
{
CC_STATUS_PARTIAL_INIT;
operands[2] = gen_rtx (CONST_INT, VOIDmode,
(INTVAL (operands[2]) << INTVAL (operands[1])));
return \"and %2,%0,%?r0\";
}")
;; Conversions between float and double.
(define_insn "extendsfdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
(float_extend:DF
(match_operand:SF 1 "register_operand" "f")))]
""
"fmov.sd %1,%0")
(define_insn "truncdfsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
(float_truncate:SF
(match_operand:DF 1 "register_operand" "f")))]
""
"fmov.ds %1,%0")
;; Conversion between fixed point and floating point.
;; Note that among the fix-to-float insns
;; the ones that start with SImode come first.
;; That is so that an operand that is a CONST_INT
;; (and therefore lacks a specific machine mode).
;; will be recognized as SImode (which is always valid)
;; rather than as QImode or HImode.
;; This pattern forces (set (reg:SF ...) (float:SF (const_int ...)))
;; to be reloaded by putting the constant into memory.
;; It must come before the more general floatsisf2 pattern.
(define_expand "floatsidf2"
[(set (match_dup 2) (match_dup 3))
(set (match_dup 4) (xor:SI (match_operand:SI 1 "register_operand" "")
(const_int -2147483648)))
(set (subreg:SI (match_dup 5) 0) (match_dup 4))
(set (subreg:SI (match_dup 5) 1) (subreg:SI (match_dup 2) 1))
(set (match_operand:DF 0 "register_operand" "")
(minus:DF (match_dup 5) (match_dup 2)))]
""
"
{
REAL_VALUE_TYPE d;
/* 4503601774854144 is (1 << 30) * ((1 << 22) + (1 << 1)). */
d = REAL_VALUE_ATOF (\"4503601774854144\");
operands[2] = gen_reg_rtx (DFmode);
operands[3] = CONST_DOUBLE_FROM_REAL_VALUE (d, DFmode);
operands[4] = gen_reg_rtx (SImode);
operands[5] = gen_reg_rtx (DFmode);
}")
;; Floating to fixed conversion.
(define_expand "fix_truncdfsi2"
;; This first insn produces a double-word value
;; in which only the low word is valid.
[(set (match_dup 2)
(fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
(set (match_operand:SI 0 "register_operand" "=f")
(subreg:SI (match_dup 2) 0))]
""
"
{
operands[2] = gen_reg_rtx (DImode);
}")
;; Recognize the first insn generated above.
;; This RTL looks like a fix_truncdfdi2 insn,
;; but we dont call it that, because only 32 bits
;; of the result are valid.
;; This pattern will work for the intended purposes
;; as long as we do not have any fixdfdi2 or fix_truncdfdi2.
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=f")
(fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f"))))]
""
"ftrunc.dd %1,%0")
(define_expand "fix_truncsfsi2"
;; This first insn produces a double-word value
;; in which only the low word is valid.
[(set (match_dup 2)
(fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
(set (match_operand:SI 0 "register_operand" "=f")
(subreg:SI (match_dup 2) 0))]
""
"
{
operands[2] = gen_reg_rtx (DImode);
}")
;; Recognize the first insn generated above.
;; This RTL looks like a fix_truncsfdi2 insn,
;; but we dont call it that, because only 32 bits
;; of the result are valid.
;; This pattern will work for the intended purposes
;; as long as we do not have any fixsfdi2 or fix_truncsfdi2.
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=f")
(fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
""
"ftrunc.sd %1,%0")
;;- arithmetic instructions
(define_insn "addsi3"
[(set (match_operand:SI 0 "register_operand" "=r,*f")
(plus:SI (match_operand:SI 1 "nonmemory_operand" "%r,!*f")
(match_operand:SI 2 "arith_operand" "rI,!*f")))]
""
"*
{
if (which_alternative == 1)
return \"fiadd.ss %2,%1,%0\";
CC_STATUS_PARTIAL_INIT;
return \"addu %2,%1,%0\";
}")
(define_insn "adddi3"
[(set (match_operand:DI 0 "register_operand" "=f")
(plus:DI (match_operand:DI 1 "register_operand" "%f")
(match_operand:DI 2 "register_operand" "f")))]
""
"fiadd.dd %1,%2,%0")
(define_insn "subsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r,*f")
(minus:SI (match_operand:SI 1 "register_operand" "r,I,!*f")
(match_operand:SI 2 "arith_operand" "rI,r,!*f")))]
""
"*
{
if (which_alternative == 2)
return \"fisub.ss %1,%2,%0\";
CC_STATUS_PARTIAL_INIT;
if (REG_P (operands[2]))
return \"subu %1,%2,%0\";
operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2]));
return \"addu %2,%1,%0\";
}")
(define_insn "subdi3"
[(set (match_operand:DI 0 "register_operand" "=f")
(minus:DI (match_operand:DI 1 "register_operand" "%f")
(match_operand:DI 2 "register_operand" "f")))]
""
"fisub.dd %1,%2,%0")
(define_expand "mulsi3"
[(set (subreg:SI (match_dup 4) 0) (match_operand:SI 1 "general_operand" ""))
(set (subreg:SI (match_dup 5) 0) (match_operand:SI 2 "general_operand" ""))
(clobber (match_dup 3))
(set (subreg:SI (match_dup 3) 0)
(mult:SI (subreg:SI (match_dup 4) 0) (subreg:SI (match_dup 5) 0)))
(set (match_operand:SI 0 "register_operand" "") (subreg:SI (match_dup 3) 0))]
""
"
{
operands[3] = gen_reg_rtx (DImode);
operands[4] = gen_reg_rtx (DImode);
operands[5] = gen_reg_rtx (DImode);
}")
(define_insn ""
[(set (subreg:SI (match_operand:DI 0 "register_operand" "=f") 0)
(mult:SI (subreg:SI (match_operand:DI 1 "register_operand" "f") 0)
(subreg:SI (match_operand:DI 2 "register_operand" "f") 0)))]
""
"fmlow.dd %2,%1,%0")
;;- and instructions (with compliment also)
(define_insn "andsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(and:SI (match_operand:SI 1 "nonmemory_operand" "%r")
(match_operand:SI 2 "nonmemory_operand" "rL")))]
""
"*
{
rtx xop[3];
CC_STATUS_PARTIAL_INIT;
if (REG_P (operands[2]) || LOGIC_INT (operands[2]))
return \"and %2,%1,%0\";
if ((INTVAL (operands[2]) & 0xffff) == 0)
{
operands[2] = gen_rtx (CONST_INT, VOIDmode,
(unsigned) INTVAL (operands[2]) >> 16);
return \"andh %2,%1,%0\";
}
xop[0] = operands[0];
xop[1] = operands[1];
xop[2] = gen_rtx (CONST_INT, VOIDmode, ~INTVAL (operands[2]) & 0xffff);
output_asm_insn (\"andnot %2,%1,%0\", xop);
operands[2] = gen_rtx (CONST_INT, VOIDmode,
~(unsigned) INTVAL (operands[2]) >> 16);
return \"andnoth %2,%0,%0\";
}")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(and:SI (not:SI (match_operand:SI 1 "register_operand" "rn"))
(match_operand:SI 2 "register_operand" "r")))]
""
"*
{
rtx xop[3];
CC_STATUS_PARTIAL_INIT;
if (REG_P (operands[1]) || LOGIC_INT (operands[1]))
return \"andnot %1,%2,%0\";
if ((INTVAL (operands[1]) & 0xffff) == 0)
{
operands[1] = gen_rtx (CONST_INT, VOIDmode,
(unsigned) INTVAL (operands[1]) >> 16);
return \"andnoth %1,%2,%0\";
}
xop[0] = operands[0];
xop[1] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[1]) & 0xffff));
xop[2] = operands[2];
output_asm_insn (\"andnot %1,%2,%0\", xop);
operands[1] = gen_rtx (CONST_INT, VOIDmode,
(unsigned) INTVAL (operands[1]) >> 16);
return \"andnoth %1,%0,%0\";
}")
(define_insn "iorsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(ior:SI (match_operand:SI 1 "nonmemory_operand" "%r")
(match_operand:SI 2 "nonmemory_operand" "rL")))]
""
"*
{
rtx xop[3];
CC_STATUS_PARTIAL_INIT;
if (REG_P (operands[2]) || LOGIC_INT (operands[2]))
return \"or %2,%1,%0\";
if ((INTVAL (operands[2]) & 0xffff) == 0)
{
operands[2] = gen_rtx (CONST_INT, VOIDmode,
(unsigned) INTVAL (operands[2]) >> 16);
return \"orh %2,%1,%0\";
}
xop[0] = operands[0];
xop[1] = operands[1];
xop[2] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[2]) & 0xffff));
output_asm_insn (\"or %2,%1,%0\", xop);
operands[2] = gen_rtx (CONST_INT, VOIDmode,
(unsigned) INTVAL (operands[2]) >> 16);
return \"orh %2,%0,%0\";
}")
(define_insn "xorsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(xor:SI (match_operand:SI 1 "nonmemory_operand" "%r")
(match_operand:SI 2 "nonmemory_operand" "rL")))]
""
"*
{
rtx xop[3];
CC_STATUS_PARTIAL_INIT;
if (REG_P (operands[2]) || LOGIC_INT (operands[2]))
return \"xor %2,%1,%0\";
if ((INTVAL (operands[2]) & 0xffff) == 0)
{
operands[2] = gen_rtx (CONST_INT, VOIDmode,
(unsigned) INTVAL (operands[2]) >> 16);
return \"xorh %2,%1,%0\";
}
xop[0] = operands[0];
xop[1] = operands[1];
xop[2] = gen_rtx (CONST_INT, VOIDmode, (INTVAL (operands[2]) & 0xffff));
output_asm_insn (\"xor %2,%1,%0\", xop);
operands[2] = gen_rtx (CONST_INT, VOIDmode,
(unsigned) INTVAL (operands[2]) >> 16);
return \"xorh %2,%0,%0\";
}")
;(The i860 instruction set doesn't allow an immediate second operand in
; a subtraction.)
(define_insn "negsi2"
[(set (match_operand:SI 0 "general_operand" "=r")
(neg:SI (match_operand:SI 1 "arith_operand" "r")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
return \"subu %?r0,%1,%0\";
}")
(define_insn "one_cmplsi2"
[(set (match_operand:SI 0 "general_operand" "=r")
(not:SI (match_operand:SI 1 "arith_operand" "r")))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
return \"subu -1,%1,%0\";
}")
;; Floating point arithmetic instructions.
(define_insn "adddf3"
[(set (match_operand:DF 0 "register_operand" "=f")
(plus:DF (match_operand:DF 1 "register_operand" "f")
(match_operand:DF 2 "register_operand" "f")))]
""
"fadd.dd %1,%2,%0")
(define_insn "addsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
(plus:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
""
"fadd.ss %1,%2,%0")
(define_insn "subdf3"
[(set (match_operand:DF 0 "register_operand" "=f")
(minus:DF (match_operand:DF 1 "register_operand" "f")
(match_operand:DF 2 "register_operand" "f")))]
""
"fsub.dd %1,%2,%0")
(define_insn "subsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
(minus:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
""
"fsub.ss %1,%2,%0")
(define_insn "muldf3"
[(set (match_operand:DF 0 "register_operand" "=f")
(mult:DF (match_operand:DF 1 "register_operand" "f")
(match_operand:DF 2 "register_operand" "f")))]
""
"fmul.dd %1,%2,%0")
(define_insn "mulsf3"
[(set (match_operand:SF 0 "register_operand" "=f")
(mult:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
""
"fmul.ss %1,%2,%0")
(define_insn "negdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
(neg:DF (match_operand:DF 1 "register_operand" "f")))]
""
"fsub.dd %?f0,%1,%0")
(define_insn "negsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
(neg:SF (match_operand:SF 1 "register_operand" "f")))]
""
"fsub.ss %?f0,%1,%0")
(define_insn "divdf3"
[(set (match_operand:DF 0 "register_operand" "=&f")
(div:DF (match_operand:DF 1 "register_operand" "f")
(match_operand:DF 2 "register_operand" "f")))
(clobber (match_scratch:DF 3 "=&f"))
(clobber (match_scratch:DF 4 "=&f"))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
if (((cc_prev_status.flags & CC_KNOW_HI_R31) == 0)
|| (cc_prev_status.flags & CC_HI_R31_ADJ)
|| (cc_prev_status.mdep != CONST2_RTX (SFmode)))
{
cc_status.flags |= CC_KNOW_HI_R31;
cc_status.flags &= ~CC_HI_R31_ADJ;
cc_status.mdep = CONST2_RTX (SFmode);
return \"frcp.dd %2,%3\;fmul.dd %2,%3,%0\;fmov.dd %?f0,%4\;\\\
orh 0x4000,%?r0,%?r31\;ixfr %?r31,%R4\;fsub.dd %4,%0,%0\;\\\
fmul.dd %3,%0,%3\;fmul.dd %2,%3,%0\;fsub.dd %4,%0,%0\;\\\
fmul.dd %3,%0,%3\;fmul.dd %2,%3,%0\;fsub.dd %4,%0,%0\;\\\
fmul.dd %3,%1,%3\;fmul.dd %0,%3,%0\";
}
else
return \"frcp.dd %2,%3\;fmul.dd %2,%3,%0\;fmov.dd %?f0,%4\;\\\
ixfr %?r31,%R4\;fsub.dd %4,%0,%0\;\\\
fmul.dd %3,%0,%3\;fmul.dd %2,%3,%0\;fsub.dd %4,%0,%0\;\\\
fmul.dd %3,%0,%3\;fmul.dd %2,%3,%0\;fsub.dd %4,%0,%0\;\\\
fmul.dd %3,%1,%3\;fmul.dd %0,%3,%0\";
}")
(define_insn "divsf3"
[(set (match_operand:SF 0 "register_operand" "=&f")
(div:SF (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))
(clobber (match_scratch:SF 3 "=&f"))
(clobber (match_scratch:SF 4 "=&f"))]
""
"*
{
CC_STATUS_PARTIAL_INIT;
if (((cc_prev_status.flags & CC_KNOW_HI_R31) == 0)
|| (cc_prev_status.flags & CC_HI_R31_ADJ)
|| (cc_prev_status.mdep != CONST2_RTX (SFmode)))
{
cc_status.flags |= CC_KNOW_HI_R31;
cc_status.flags &= ~CC_HI_R31_ADJ;
cc_status.mdep = CONST2_RTX (SFmode);
output_asm_insn (\"orh 0x4000,%?r0,%?r31\", operands);
}
return \"ixfr %?r31,%4\;frcp.ss %2,%0\;\\\
fmul.ss %2,%0,%3\;fsub.ss %4,%3,%3\;fmul.ss %0,%3,%0\;\\\
fmul.ss %2,%0,%3\;fsub.ss %4,%3,%3\;\\\
fmul.ss %1,%0,%4\;fmul.ss %3,%4,%0\";
}")
;; Shift instructions
;; Optimized special case of shifting.
;; Must precede the general case.
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(ashiftrt:SI (match_operand:SI 1 "memory_operand" "m")
(const_int 24)))]
""
"*
{
if (CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
{
CC_STATUS_INIT;
cc_status.flags |= CC_KNOW_HI_R31 | CC_HI_R31_ADJ;
cc_status.mdep = XEXP (operands[1], 0);
return \"orh %h1,%?r0,%?r31\;ld.b %L1(%?r31),%0\";
}
return \"ld.b %1,%0\";
}")
;;- arithmetic shift instructions
(define_insn "ashlsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(ashift:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "shift_operand" "rn")))]
""
"*
{
return \"shl %2,%1,%0\";
}")
(define_insn "ashlhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
(ashift:HI (match_operand:HI 1 "register_operand" "r")
(match_operand:HI 2 "shift_operand" "rn")))]
""
"*
{
return \"shl %2,%1,%0\";
}")
(define_insn "ashlqi3"
[(set (match_operand:QI 0 "register_operand" "=r")
(ashift:QI (match_operand:QI 1 "register_operand" "r")
(match_operand:QI 2 "shift_operand" "rn")))]
""
"*
{
return \"shl %2,%1,%0\";
}")
(define_insn "ashrsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "shift_operand" "rn")))]
""
"*
{
return \"shra %2,%1,%0\";
}")
(define_insn "lshrsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "shift_operand" "rn")))]
""
"*
{
return \"shr %2,%1,%0\";
}")
;; Unconditional and other jump instructions
(define_insn "jump"
[(set (pc) (label_ref (match_operand 0 "" "")))]
""
"*
{
return \"br %l0\;nop\";
}")
;; Here are two simple peepholes which fill the delay slot of
;; an unconditional branch.
(define_peephole
[(set (match_operand:SI 0 "register_operand" "=rf")
(match_operand:SI 1 "single_insn_src_p" "gfG"))
(set (pc) (label_ref (match_operand 2 "" "")))]
""
"* return output_delayed_branch (\"br %l2\", operands, insn);")
(define_peephole
[(set (match_operand:SI 0 "memory_operand" "=m")
(match_operand:SI 1 "reg_or_0_operand" "rfJ"))
(set (pc) (label_ref (match_operand 2 "" "")))]
""
"* return output_delayed_branch (\"br %l2\", operands, insn);")
(define_insn "tablejump"
[(set (pc) (match_operand:SI 0 "register_operand" "r"))
(use (label_ref (match_operand 1 "" "")))]
""
"bri %0\;nop")
(define_peephole
[(set (match_operand:SI 0 "memory_operand" "=m")
(match_operand:SI 1 "reg_or_0_operand" "rfJ"))
(set (pc) (match_operand:SI 2 "register_operand" "r"))
(use (label_ref (match_operand 3 "" "")))]
""
"* return output_delayed_branch (\"bri %2\", operands, insn);")
;;- jump to subroutine
(define_expand "call"
[(call (match_operand:SI 0 "memory_operand" "m")
(match_operand 1 "" "i"))]
;; operand[2] is next_arg_register
""
"
{
if (INTVAL (operands[1]) > 0)
{
emit_move_insn (arg_pointer_rtx, stack_pointer_rtx);
emit_insn (gen_rtx (USE, VOIDmode, arg_pointer_rtx));
}
}")
;;- jump to subroutine
(define_insn ""
[(call (match_operand:SI 0 "memory_operand" "m")
(match_operand 1 "" "i"))]
;; operand[2] is next_arg_register
""
"*
{
/* strip the MEM. */
operands[0] = XEXP (operands[0], 0);
CC_STATUS_INIT;
if (GET_CODE (operands[0]) == REG)
return \"calli %0\;nop\";
return \"call %0\;nop\";
}")
(define_peephole
[(set (match_operand:SI 0 "register_operand" "=rf")
(match_operand:SI 1 "single_insn_src_p" "gfG"))
(call (match_operand:SI 2 "memory_operand" "m")
(match_operand 3 "" "i"))]
;;- Don't use operand 1 for most machines.
"! reg_mentioned_p (operands[0], operands[2])"
"*
{
/* strip the MEM. */
operands[2] = XEXP (operands[2], 0);
if (GET_CODE (operands[2]) == REG)
return output_delayed_branch (\"calli %2\", operands, insn);
return output_delayed_branch (\"call %2\", operands, insn);
}")
(define_peephole
[(set (match_operand:SI 0 "memory_operand" "=m")
(match_operand:SI 1 "reg_or_0_operand" "rfJ"))
(call (match_operand:SI 2 "memory_operand" "m")
(match_operand 3 "" "i"))]
;;- Don't use operand 1 for most machines.
""
"*
{
/* strip the MEM. */
operands[2] = XEXP (operands[2], 0);
if (GET_CODE (operands[2]) == REG)
return output_delayed_branch (\"calli %2\", operands, insn);
return output_delayed_branch (\"call %2\", operands, insn);
}")
(define_expand "call_value"
[(set (match_operand 0 "register_operand" "=rf")
(call (match_operand:SI 1 "memory_operand" "m")
(match_operand 2 "" "i")))]
;; operand 3 is next_arg_register
""
"
{
if (INTVAL (operands[2]) > 0)
{
emit_move_insn (arg_pointer_rtx, stack_pointer_rtx);
emit_insn (gen_rtx (USE, VOIDmode, arg_pointer_rtx));
}
}")
(define_insn ""
[(set (match_operand 0 "register_operand" "=rf")
(call (match_operand:SI 1 "memory_operand" "m")
(match_operand 2 "" "i")))]
;; operand 3 is next_arg_register
""
"*
{
/* strip the MEM. */
operands[1] = XEXP (operands[1], 0);
CC_STATUS_INIT;
if (GET_CODE (operands[1]) == REG)
return \"calli %1\;nop\";
return \"call %1\;nop\";
}")
(define_peephole
[(set (match_operand:SI 0 "register_operand" "=rf")
(match_operand:SI 1 "single_insn_src_p" "gfG"))
(set (match_operand 2 "" "=rf")
(call (match_operand:SI 3 "memory_operand" "m")
(match_operand 4 "" "i")))]
;;- Don't use operand 4 for most machines.
"! reg_mentioned_p (operands[0], operands[3])"
"*
{
/* strip the MEM. */
operands[3] = XEXP (operands[3], 0);
if (GET_CODE (operands[3]) == REG)
return output_delayed_branch (\"calli %3\", operands, insn);
return output_delayed_branch (\"call %3\", operands, insn);
}")
(define_peephole
[(set (match_operand:SI 0 "memory_operand" "=m")
(match_operand:SI 1 "reg_or_0_operand" "rJf"))
(set (match_operand 2 "" "=rf")
(call (match_operand:SI 3 "memory_operand" "m")
(match_operand 4 "" "i")))]
;;- Don't use operand 4 for most machines.
""
"*
{
/* strip the MEM. */
operands[3] = XEXP (operands[3], 0);
if (GET_CODE (operands[3]) == REG)
return output_delayed_branch (\"calli %3\", operands, insn);
return output_delayed_branch (\"call %3\", operands, insn);
}")
(define_insn "nop"
[(const_int 0)]
""
"nop")
(define_insn "indirect_jump"
[(set (pc) (match_operand:SI 0 "register_operand" "r"))]
""
"bri %0")
;;
;; A special insn that does the work to get setup just
;; before a table jump.
;;
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
(label_ref (match_operand 2 "" "")))))]
""
"*
{
CC_STATUS_INIT;
return \"orh %H2,%?r0,%?r31\;or %L2,%?r31,%?r31\;ld.l %?r31(%1),%0\";
}")
(define_peephole
[(set (match_operand:SI 0 "register_operand" "=rf")
(match_operand:SI 1 "single_insn_src_p" "gfG"))
(set (pc) (match_operand:SI 2 "register_operand" "r"))
(use (label_ref (match_operand 3 "" "")))]
"REGNO (operands[0]) != REGNO (operands[2])"
"* return output_delayed_branch (\"bri %2\", operands, insn);")
;;- Local variables:
;;- mode:emacs-lisp
;;- comment-start: ";;- "
;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
;;- eval: (modify-syntax-entry ?[ "(]")
;;- eval: (modify-syntax-entry ?] ")[")
;;- eval: (modify-syntax-entry ?{ "(}")
;;- eval: (modify-syntax-entry ?} "){")
;;- End:
; BUGS:
;; Insert no-op between an insn with memory read-write operands
;; following by a scale-indexing operation.
;; The Sequent assembler does not allow addresses to be used
;; except in insns which explicitly compute an effective address.
;; I.e., one cannot say "cmpd _p,@_x"
;; Implement unsigned multiplication??
;;- Machine descrption for GNU compiler
;;- ns32000 Version
;; Copyright (C) 1988 Free Software Foundation, Inc.
;; Contributed by Michael Tiemann (tiemann@mcc.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, 675 Mass Ave, Cambridge, MA 02139, USA.
;;- Instruction patterns. When multiple patterns apply,
;;- the first one in the file is chosen.
;;-
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
;;-
;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
;;- updates for most instructions.
;; We don't want to allow a constant operand for test insns because
;; (set (cc0) (const_int foo)) has no mode information. Such insns will
;; be folded while optimizing anyway.
(define_insn "tstsi"
[(set (cc0)
(match_operand:SI 0 "nonimmediate_operand" "rm"))]
""
"*
{ cc_status.flags |= CC_REVERSED;
operands[1] = const0_rtx;
return \"cmpqd %1,%0\"; }")
(define_insn "tsthi"
[(set (cc0)
(match_operand:HI 0 "nonimmediate_operand" "g"))]
""
"*
{ cc_status.flags |= CC_REVERSED;
operands[1] = const0_rtx;
return \"cmpqw %1,%0\"; }")
(define_insn "tstqi"
[(set (cc0)
(match_operand:QI 0 "nonimmediate_operand" "g"))]
""
"*
{ cc_status.flags |= CC_REVERSED;
operands[1] = const0_rtx;
return \"cmpqb %1,%0\"; }")
(define_insn "tstdf"
[(set (cc0)
(match_operand:DF 0 "general_operand" "fmF"))]
"TARGET_32081"
"*
{ cc_status.flags |= CC_REVERSED;
operands[1] = CONST0_RTX (DFmode);
return \"cmpl %1,%0\"; }")
(define_insn "tstsf"
[(set (cc0)
(match_operand:SF 0 "general_operand" "fmF"))]
"TARGET_32081"
"*
{ cc_status.flags |= CC_REVERSED;
operands[1] = CONST0_RTX (SFmode);
return \"cmpf %1,%0\"; }")
(define_insn "cmpsi"
[(set (cc0)
(compare (match_operand:SI 0 "nonimmediate_operand" "rmn")
(match_operand:SI 1 "general_operand" "rmn")))]
""
"*
{
if (GET_CODE (operands[1]) == CONST_INT)
{
int i = INTVAL (operands[1]);
if (i <= 7 && i >= -8)
{
cc_status.flags |= CC_REVERSED;
return \"cmpqd %1,%0\";
}
}
cc_status.flags &= ~CC_REVERSED;
if (GET_CODE (operands[0]) == CONST_INT)
{
int i = INTVAL (operands[0]);
if (i <= 7 && i >= -8)
return \"cmpqd %0,%1\";
}
return \"cmpd %0,%1\";
}")
(define_insn "cmphi"
[(set (cc0)
(compare (match_operand:HI 0 "nonimmediate_operand" "g")
(match_operand:HI 1 "general_operand" "g")))]
""
"*
{
if (GET_CODE (operands[1]) == CONST_INT)
{
short i = INTVAL (operands[1]);
if (i <= 7 && i >= -8)
{
cc_status.flags |= CC_REVERSED;
if (INTVAL (operands[1]) > 7)
operands[1] = gen_rtx(CONST_INT, VOIDmode, i);
return \"cmpqw %1,%0\";
}
}
cc_status.flags &= ~CC_REVERSED;
if (GET_CODE (operands[0]) == CONST_INT)
{
short i = INTVAL (operands[0]);
if (i <= 7 && i >= -8)
{
if (INTVAL (operands[0]) > 7)
operands[0] = gen_rtx(CONST_INT, VOIDmode, i);
return \"cmpqw %0,%1\";
}
}
return \"cmpw %0,%1\";
}")
(define_insn "cmpqi"
[(set (cc0)
(compare (match_operand:QI 0 "nonimmediate_operand" "g")
(match_operand:QI 1 "general_operand" "g")))]
""
"*
{
if (GET_CODE (operands[1]) == CONST_INT)
{
char i = INTVAL (operands[1]);
if (i <= 7 && i >= -8)
{
cc_status.flags |= CC_REVERSED;
if (INTVAL (operands[1]) > 7)
operands[1] = gen_rtx(CONST_INT, VOIDmode, i);
return \"cmpqb %1,%0\";
}
}
cc_status.flags &= ~CC_REVERSED;
if (GET_CODE (operands[0]) == CONST_INT)
{
char i = INTVAL (operands[0]);
if (i <= 7 && i >= -8)
{
if (INTVAL (operands[0]) > 7)
operands[0] = gen_rtx(CONST_INT, VOIDmode, i);
return \"cmpqb %0,%1\";
}
}
return \"cmpb %0,%1\";
}")
(define_insn "cmpdf"
[(set (cc0)
(compare (match_operand:DF 0 "general_operand" "fmF")
(match_operand:DF 1 "general_operand" "fmF")))]
"TARGET_32081"
"cmpl %0,%1")
(define_insn "cmpsf"
[(set (cc0)
(compare (match_operand:SF 0 "general_operand" "fmF")
(match_operand:SF 1 "general_operand" "fmF")))]
"TARGET_32081"
"cmpf %0,%1")
(define_insn "movdf"
[(set (match_operand:DF 0 "general_operand" "=&fg<")
(match_operand:DF 1 "general_operand" "fFg"))]
""
"*
{
if (FP_REG_P (operands[0]))
{
if (FP_REG_P (operands[1]) || GET_CODE (operands[1]) == CONST_DOUBLE)
return \"movl %1,%0\";
if (REG_P (operands[1]))
{
rtx xoperands[2];
xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
output_asm_insn (\"movd %1,tos\", xoperands);
output_asm_insn (\"movd %1,tos\", operands);
return \"movl tos,%0\";
}
return \"movl %1,%0\";
}
else if (FP_REG_P (operands[1]))
{
if (REG_P (operands[0]))
{
output_asm_insn (\"movl %1,tos\;movd tos,%0\", operands);
operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
return \"movd tos,%0\";
}
else
return \"movl %1,%0\";
}
return output_move_double (operands);
}")
(define_insn "movsf"
[(set (match_operand:SF 0 "general_operand" "=fg<")
(match_operand:SF 1 "general_operand" "fFg"))]
""
"*
{
if (FP_REG_P (operands[0]))
{
if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 8)
return \"movd %1,tos\;movf tos,%0\";
else
return \"movf %1,%0\";
}
else if (FP_REG_P (operands[1]))
{
if (REG_P (operands[0]))
return \"movf %1,tos\;movd tos,%0\";
return \"movf %1,%0\";
}
#if 0
#ifndef GAS_SYNTAX
/* GAS understands floating constants in ordinary movd instructions
but other assemblers might object. */
else if (GET_CODE (operands[1]) == CONST_DOUBLE)
{
union {int i[2]; float f; double d;} convrt;
convrt.i[0] = CONST_DOUBLE_LOW (operands[1]);
convrt.i[1] = CONST_DOUBLE_HIGH (operands[1]);
convrt.f = convrt.d;
/* Is there a better machine-independent way to to this? */
operands[1] = gen_rtx (CONST_INT, VOIDmode, convrt.i[0]);
return \"movd %1,%0\";
}
#endif
#endif
else return \"movd %1,%0\";
}")
(define_insn ""
[(set (match_operand:TI 0 "memory_operand" "=m")
(match_operand:TI 1 "memory_operand" "m"))]
""
"movmd %1,%0,4")
(define_insn "movdi"
[(set (match_operand:DI 0 "general_operand" "=&g<,*f,g")
(match_operand:DI 1 "general_operand" "gF,g,*f"))]
""
"*
{
if (FP_REG_P (operands[0]))
{
if (FP_REG_P (operands[1]) || GET_CODE (operands[1]) == CONST_DOUBLE)
return \"movl %1,%0\";
if (REG_P (operands[1]))
{
rtx xoperands[2];
xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
output_asm_insn (\"movd %1,tos\", xoperands);
output_asm_insn (\"movd %1,tos\", operands);
return \"movl tos,%0\";
}
return \"movl %1,%0\";
}
else if (FP_REG_P (operands[1]))
{
if (REG_P (operands[0]))
{
output_asm_insn (\"movl %1,tos\;movd tos,%0\", operands);
operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
return \"movd tos,%0\";
}
else
return \"movl %1,%0\";
}
return output_move_double (operands);
}")
;; This special case must precede movsi.
(define_insn ""
[(set (reg:SI 17)
(match_operand:SI 0 "general_operand" "rmn"))]
""
"lprd sp,%0")
(define_insn "movsi"
[(set (match_operand:SI 0 "general_operand" "=g<,*f,g")
(match_operand:SI 1 "general_operand" "gxy,g,*f"))]
""
"*
{
if (FP_REG_P (operands[0]))
{
if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 8)
return \"movd %1,tos\;movf tos,%0\";
else
return \"movf %1,%0\";
}
else if (FP_REG_P (operands[1]))
{
if (REG_P (operands[0]))
return \"movf %1,tos\;movd tos,%0\";
return \"movf %1,%0\";
}
if (GET_CODE (operands[1]) == CONST_INT)
{
int i = INTVAL (operands[1]);
if (i <= 7 && i >= -8)
return \"movqd %1,%0\";
if (i < 0x4000 && i >= -0x4000 && ! TARGET_32532)
#if defined (GNX_V3) || defined (UTEK_ASM)
return \"addr %c1,%0\";
#else
return \"addr @%c1,%0\";
#endif
return \"movd %1,%0\";
}
else if (GET_CODE (operands[1]) == REG)
{
if (REGNO (operands[1]) < 16)
return \"movd %1,%0\";
else if (REGNO (operands[1]) == FRAME_POINTER_REGNUM)
{
if (GET_CODE(operands[0]) == REG)
return \"sprd fp,%0\";
else
return \"addr 0(fp),%0\" ;
}
else if (REGNO (operands[1]) == STACK_POINTER_REGNUM)
{
if (GET_CODE(operands[0]) == REG)
return \"sprd sp,%0\";
else
return \"addr 0(sp),%0\" ;
}
else abort ();
}
else if (GET_CODE (operands[1]) == MEM)
return \"movd %1,%0\";
/* Check if this effective address can be
calculated faster by pulling it apart. */
if (REG_P (operands[0])
&& GET_CODE (operands[1]) == MULT
&& GET_CODE (XEXP (operands[1], 1)) == CONST_INT
&& (INTVAL (XEXP (operands[1], 1)) == 2
|| INTVAL (XEXP (operands[1], 1)) == 4))
{
rtx xoperands[3];
xoperands[0] = operands[0];
xoperands[1] = XEXP (operands[1], 0);
xoperands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (XEXP (operands[1], 1)) >> 1);
return output_shift_insn (xoperands);
}
return \"addr %a1,%0\";
}")
(define_insn "movhi"
[(set (match_operand:HI 0 "general_operand" "=g<,*f,g")
(match_operand:HI 1 "general_operand" "g,g,*f"))]
""
"*
{
if (GET_CODE (operands[1]) == CONST_INT)
{
short i = INTVAL (operands[1]);
if (i <= 7 && i >= -8)
{
if (INTVAL (operands[1]) > 7)
operands[1] =
gen_rtx (CONST_INT, VOIDmode, i);
return \"movqw %1,%0\";
}
return \"movw %1,%0\";
}
else if (FP_REG_P (operands[0]))
{
if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 8)
return \"movwf %1,tos\;movf tos,%0\";
else
return \"movwf %1,%0\";
}
else if (FP_REG_P (operands[1]))
{
if (REG_P (operands[0]))
return \"movf %1,tos\;movd tos,%0\";
return \"movf %1,%0\";
}
else
return \"movw %1,%0\";
}")
(define_insn "movstricthi"
[(set (strict_low_part (match_operand:HI 0 "general_operand" "+r"))
(match_operand:HI 1 "general_operand" "g"))]
""
"*
{
if (GET_CODE (operands[1]) == CONST_INT
&& INTVAL(operands[1]) <= 7 && INTVAL(operands[1]) >= -8)
return \"movqw %1,%0\";
return \"movw %1,%0\";
}")
(define_insn "movqi"
[(set (match_operand:QI 0 "general_operand" "=g<,*f,g")
(match_operand:QI 1 "general_operand" "g,g,*f"))]
""
"*
{ if (GET_CODE (operands[1]) == CONST_INT)
{
char char_val = (char)INTVAL (operands[1]);
if (char_val <= 7 && char_val >= -8)
{
if (INTVAL (operands[1]) > 7)
operands[1] =
gen_rtx (CONST_INT, VOIDmode, char_val);
return \"movqb %1,%0\";
}
return \"movb %1,%0\";
}
else if (FP_REG_P (operands[0]))
{
if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) < 8)
return \"movbf %1,tos\;movf tos,%0\";
else
return \"movbf %1,%0\";
}
else if (FP_REG_P (operands[1]))
{
if (REG_P (operands[0]))
return \"movf %1,tos\;movd tos,%0\";
return \"movf %1,%0\";
}
else
return \"movb %1,%0\";
}")
(define_insn "movstrictqi"
[(set (strict_low_part (match_operand:QI 0 "general_operand" "+r"))
(match_operand:QI 1 "general_operand" "g"))]
""
"*
{
if (GET_CODE (operands[1]) == CONST_INT
&& INTVAL(operands[1]) < 8 && INTVAL(operands[1]) > -9)
return \"movqb %1,%0\";
return \"movb %1,%0\";
}")
;; The definition of this insn does not really explain what it does,
;; but it should suffice
;; that anything generated as this insn will be recognized as one
;; and that it won't successfully combine with anything.
(define_insn "movstrsi"
[(set (match_operand:BLK 0 "general_operand" "=g")
(match_operand:BLK 1 "general_operand" "g"))
(use (match_operand:SI 2 "general_operand" "rmn"))
(clobber (reg:SI 0))
(clobber (reg:SI 1))
(clobber (reg:SI 2))]
""
"*
{
if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
abort ();
operands[0] = XEXP (operands[0], 0);
operands[1] = XEXP (operands[1], 0);
if (GET_CODE (operands[0]) == MEM)
if (GET_CODE (operands[1]) == MEM)
output_asm_insn (\"movd %0,r2\;movd %1,r1\", operands);
else
output_asm_insn (\"movd %0,r2\;addr %a1,r1\", operands);
else if (GET_CODE (operands[1]) == MEM)
output_asm_insn (\"addr %a0,r2\;movd %1,r1\", operands);
else
output_asm_insn (\"addr %a0,r2\;addr %a1,r1\", operands);
#ifdef UTEK_ASM
if (GET_CODE (operands[2]) == CONST_INT && (INTVAL (operands[2]) & 0x3) == 0)
{
operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) >> 2);
if ((unsigned) INTVAL (operands[2]) <= 7)
return \"movqd %2,r0\;movsd $0\";
else
return \"movd %2,r0\;movsd $0\";
}
else
{
return \"movd %2,r0\;movsb $0\";
}
#else
if (GET_CODE (operands[2]) == CONST_INT && (INTVAL (operands[2]) & 0x3) == 0)
{
operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) >> 2);
if ((unsigned) INTVAL (operands[2]) <= 7)
return \"movqd %2,r0\;movsd\";
else
return \"movd %2,r0\;movsd\";
}
else
{
return \"movd %2,r0\;movsb\";
}
#endif
}")
;; Extension and truncation insns.
;; Those for integer source operand
;; are ordered widest source type first.
(define_insn "truncsiqi2"
[(set (match_operand:QI 0 "general_operand" "=g<")
(truncate:QI (match_operand:SI 1 "nonimmediate_operand" "rmn")))]
""
"movb %1,%0")
(define_insn "truncsihi2"
[(set (match_operand:HI 0 "general_operand" "=g<")
(truncate:HI (match_operand:SI 1 "nonimmediate_operand" "rmn")))]
""
"movw %1,%0")
(define_insn "trunchiqi2"
[(set (match_operand:QI 0 "general_operand" "=g<")
(truncate:QI (match_operand:HI 1 "nonimmediate_operand" "g")))]
""
"movb %1,%0")
(define_insn "extendhisi2"
[(set (match_operand:SI 0 "general_operand" "=g<")
(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "g")))]
""
"movxwd %1,%0")
(define_insn "extendqihi2"
[(set (match_operand:HI 0 "general_operand" "=g<")
(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "g")))]
""
"movxbw %1,%0")
(define_insn "extendqisi2"
[(set (match_operand:SI 0 "general_operand" "=g<")
(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "g")))]
""
"movxbd %1,%0")
(define_insn "extendsfdf2"
[(set (match_operand:DF 0 "general_operand" "=fm<")
(float_extend:DF (match_operand:SF 1 "general_operand" "fmF")))]
"TARGET_32081"
"movfl %1,%0")
(define_insn "truncdfsf2"
[(set (match_operand:SF 0 "general_operand" "=fm<")
(float_truncate:SF (match_operand:DF 1 "general_operand" "fmF")))]
"TARGET_32081"
"movlf %1,%0")
(define_insn "zero_extendhisi2"
[(set (match_operand:SI 0 "general_operand" "=g<")
(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "g")))]
""
"movzwd %1,%0")
(define_insn "zero_extendqihi2"
[(set (match_operand:HI 0 "general_operand" "=g<")
(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "g")))]
""
"movzbw %1,%0")
(define_insn "zero_extendqisi2"
[(set (match_operand:SI 0 "general_operand" "=g<")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "g")))]
""
"movzbd %1,%0")
;; Fix-to-float conversion insns.
;; Note that the ones that start with SImode come first.
;; That is so that an operand that is a CONST_INT
;; (and therefore lacks a specific machine mode).
;; will be recognized as SImode (which is always valid)
;; rather than as QImode or HImode.
;; Rumor has it that the National part does not correctly convert
;; constant ints to floats. This conversion is therefore disabled.
;; A register must be used to perform the conversion.
(define_insn "floatsisf2"
[(set (match_operand:SF 0 "general_operand" "=fm<")
(float:SF (match_operand:SI 1 "general_operand" "rm")))]
"TARGET_32081"
"movdf %1,%0")
(define_insn "floatsidf2"
[(set (match_operand:DF 0 "general_operand" "=fm<")
(float:DF (match_operand:SI 1 "general_operand" "rm")))]
"TARGET_32081"
"movdl %1,%0")
(define_insn "floathisf2"
[(set (match_operand:SF 0 "general_operand" "=fm<")
(float:SF (match_operand:HI 1 "general_operand" "rm")))]
"TARGET_32081"
"movwf %1,%0")
(define_insn "floathidf2"
[(set (match_operand:DF 0 "general_operand" "=fm<")
(float:DF (match_operand:HI 1 "general_operand" "rm")))]
"TARGET_32081"
"movwl %1,%0")
(define_insn "floatqisf2"
[(set (match_operand:SF 0 "general_operand" "=fm<")
(float:SF (match_operand:QI 1 "general_operand" "rm")))]
"TARGET_32081"
"movbf %1,%0")
; Some assemblers warn that this insn doesn't work.
; Maybe they know something we don't.
;(define_insn "floatqidf2"
; [(set (match_operand:DF 0 "general_operand" "=fm<")
; (float:DF (match_operand:QI 1 "general_operand" "rm")))]
; "TARGET_32081"
; "movbl %1,%0")
;; Float-to-fix conversion insns.
;; The sequent compiler always generates "trunc" insns.
(define_insn "fixsfqi2"
[(set (match_operand:QI 0 "general_operand" "=g<")
(fix:QI (fix:SF (match_operand:SF 1 "general_operand" "fm"))))]
"TARGET_32081"
"truncfb %1,%0")
(define_insn "fixsfhi2"
[(set (match_operand:HI 0 "general_operand" "=g<")
(fix:HI (fix:SF (match_operand:SF 1 "general_operand" "fm"))))]
"TARGET_32081"
"truncfw %1,%0")
(define_insn "fixsfsi2"
[(set (match_operand:SI 0 "general_operand" "=g<")
(fix:SI (fix:SF (match_operand:SF 1 "general_operand" "fm"))))]
"TARGET_32081"
"truncfd %1,%0")
(define_insn "fixdfqi2"
[(set (match_operand:QI 0 "general_operand" "=g<")
(fix:QI (fix:DF (match_operand:DF 1 "general_operand" "fm"))))]
"TARGET_32081"
"trunclb %1,%0")
(define_insn "fixdfhi2"
[(set (match_operand:HI 0 "general_operand" "=g<")
(fix:HI (fix:DF (match_operand:DF 1 "general_operand" "fm"))))]
"TARGET_32081"
"trunclw %1,%0")
(define_insn "fixdfsi2"
[(set (match_operand:SI 0 "general_operand" "=g<")
(fix:SI (fix:DF (match_operand:DF 1 "general_operand" "fm"))))]
"TARGET_32081"
"truncld %1,%0")
;; Unsigned
(define_insn "fixunssfqi2"
[(set (match_operand:QI 0 "general_operand" "=g<")
(unsigned_fix:QI (fix:SF (match_operand:SF 1 "general_operand" "fm"))))]
"TARGET_32081"
"truncfb %1,%0")
(define_insn "fixunssfhi2"
[(set (match_operand:HI 0 "general_operand" "=g<")
(unsigned_fix:HI (fix:SF (match_operand:SF 1 "general_operand" "fm"))))]
"TARGET_32081"
"truncfw %1,%0")
(define_insn "fixunssfsi2"
[(set (match_operand:SI 0 "general_operand" "=g<")
(unsigned_fix:SI (fix:SF (match_operand:SF 1 "general_operand" "fm"))))]
"TARGET_32081"
"truncfd %1,%0")
(define_insn "fixunsdfqi2"
[(set (match_operand:QI 0 "general_operand" "=g<")
(unsigned_fix:QI (fix:DF (match_operand:DF 1 "general_operand" "fm"))))]
"TARGET_32081"
"trunclb %1,%0")
(define_insn "fixunsdfhi2"
[(set (match_operand:HI 0 "general_operand" "=g<")
(unsigned_fix:HI (fix:DF (match_operand:DF 1 "general_operand" "fm"))))]
"TARGET_32081"
"trunclw %1,%0")
(define_insn "fixunsdfsi2"
[(set (match_operand:SI 0 "general_operand" "=g<")
(unsigned_fix:SI (fix:DF (match_operand:DF 1 "general_operand" "fm"))))]
"TARGET_32081"
"truncld %1,%0")
;;; These are not yet used by GCC
(define_insn "fix_truncsfqi2"
[(set (match_operand:QI 0 "general_operand" "=g<")
(fix:QI (match_operand:SF 1 "general_operand" "fm")))]
"TARGET_32081"
"truncfb %1,%0")
(define_insn "fix_truncsfhi2"
[(set (match_operand:HI 0 "general_operand" "=g<")
(fix:HI (match_operand:SF 1 "general_operand" "fm")))]
"TARGET_32081"
"truncfw %1,%0")
(define_insn "fix_truncsfsi2"
[(set (match_operand:SI 0 "general_operand" "=g<")
(fix:SI (match_operand:SF 1 "general_operand" "fm")))]
"TARGET_32081"
"truncfd %1,%0")
(define_insn "fix_truncdfqi2"
[(set (match_operand:QI 0 "general_operand" "=g<")
(fix:QI (match_operand:DF 1 "general_operand" "fm")))]
"TARGET_32081"
"trunclb %1,%0")
(define_insn "fix_truncdfhi2"
[(set (match_operand:HI 0 "general_operand" "=g<")
(fix:HI (match_operand:DF 1 "general_operand" "fm")))]
"TARGET_32081"
"trunclw %1,%0")
(define_insn "fix_truncdfsi2"
[(set (match_operand:SI 0 "general_operand" "=g<")
(fix:SI (match_operand:DF 1 "general_operand" "fm")))]
"TARGET_32081"
"truncld %1,%0")
;;- All kinds of add instructions.
(define_insn "adddf3"
[(set (match_operand:DF 0 "general_operand" "=fm")
(plus:DF (match_operand:DF 1 "general_operand" "%0")
(match_operand:DF 2 "general_operand" "fmF")))]
"TARGET_32081"
"addl %2,%0")
(define_insn "addsf3"
[(set (match_operand:SF 0 "general_operand" "=fm")
(plus:SF (match_operand:SF 1 "general_operand" "%0")
(match_operand:SF 2 "general_operand" "fmF")))]
"TARGET_32081"
"addf %2,%0")
(define_insn ""
[(set (reg:SI 17)
(plus:SI (reg:SI 17)
(match_operand:SI 0 "immediate_operand" "i")))]
"GET_CODE (operands[0]) == CONST_INT"
"*
{
#ifndef SEQUENT_ADJUST_STACK
if (TARGET_32532)
if (INTVAL (operands[0]) == 8)
return \"cmpd tos,tos\";
if (TARGET_32532 || TARGET_32332)
if (INTVAL (operands[0]) == 4)
return \"cmpqd %$0,tos\";
#endif
if (! TARGET_32532)
{
if (INTVAL (operands[0]) < 64 && INTVAL (operands[0]) > -64)
return \"adjspb %$%n0\";
else if (INTVAL (operands[0]) < 8192 && INTVAL (operands[0]) >= -8192)
return \"adjspw %$%n0\";
}
return \"adjspd %$%n0\";
}")
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=g<")
(plus:SI (reg:SI 16)
(match_operand:SI 1 "immediate_operand" "i")))]
"GET_CODE (operands[1]) == CONST_INT"
"addr %c1(fp),%0")
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=g<")
(plus:SI (reg:SI 17)
(match_operand:SI 1 "immediate_operand" "i")))]
"GET_CODE (operands[1]) == CONST_INT"
"addr %c1(sp),%0")
(define_insn "addsi3"
[(set (match_operand:SI 0 "general_operand" "=g,=g<")
(plus:SI (match_operand:SI 1 "general_operand" "%0,%r")
(match_operand:SI 2 "general_operand" "rmn,n")))]
""
"*
{
if (which_alternative == 1)
{
int i = INTVAL (operands[2]);
if ( i < 0x40000000 && i >= -0x40000000 )
return \"addr %c2(%1),%0\";
else
return \"movd %1,%0\;addd %2,%0\";
}
if (GET_CODE (operands[2]) == CONST_INT)
{
int i = INTVAL (operands[2]);
if (i <= 7 && i >= -8)
return \"addqd %2,%0\";
else if (GET_CODE (operands[0]) == REG
&& i < 0x4000 && i >= -0x4000 && ! TARGET_32532)
return \"addr %c2(%0),%0\";
}
return \"addd %2,%0\";
}")
(define_insn "addhi3"
[(set (match_operand:HI 0 "general_operand" "=g")
(plus:HI (match_operand:HI 1 "general_operand" "%0")
(match_operand:HI 2 "general_operand" "g")))]
""
"*
{ if (GET_CODE (operands[2]) == CONST_INT)
{
int i = INTVAL (operands[2]);
if (i <= 7 && i >= -8)
return \"addqw %2,%0\";
}
return \"addw %2,%0\";
}")
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "general_operand" "=r"))
(plus:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:HI 2 "general_operand" "g")))]
""
"*
{
if (GET_CODE (operands[1]) == CONST_INT
&& INTVAL (operands[1]) >-9 && INTVAL(operands[1]) < 8)
return \"addqw %1,%0\";
return \"addw %1,%0\";
}")
(define_insn "addqi3"
[(set (match_operand:QI 0 "general_operand" "=g")
(plus:QI (match_operand:QI 1 "general_operand" "%0")
(match_operand:QI 2 "general_operand" "g")))]
""
"*
{ if (GET_CODE (operands[2]) == CONST_INT)
{
int i = INTVAL (operands[2]);
if (i <= 7 && i >= -8)
return \"addqb %2,%0\";
}
return \"addb %2,%0\";
}")
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "general_operand" "=r"))
(plus:QI (match_operand:QI 1 "general_operand" "0")
(match_operand:QI 2 "general_operand" "g")))]
""
"*
{
if (GET_CODE (operands[1]) == CONST_INT
&& INTVAL (operands[1]) >-9 && INTVAL(operands[1]) < 8)
return \"addqb %1,%0\";
return \"addb %1,%0\";
}")
;;- All kinds of subtract instructions.
(define_insn "subdf3"
[(set (match_operand:DF 0 "general_operand" "=fm")
(minus:DF (match_operand:DF 1 "general_operand" "0")
(match_operand:DF 2 "general_operand" "fmF")))]
"TARGET_32081"
"subl %2,%0")
(define_insn "subsf3"
[(set (match_operand:SF 0 "general_operand" "=fm")
(minus:SF (match_operand:SF 1 "general_operand" "0")
(match_operand:SF 2 "general_operand" "fmF")))]
"TARGET_32081"
"subf %2,%0")
(define_insn ""
[(set (reg:SI 17)
(minus:SI (reg:SI 17)
(match_operand:SI 0 "immediate_operand" "i")))]
"GET_CODE (operands[0]) == CONST_INT"
"*
{
if (GET_CODE(operands[0]) == CONST_INT && INTVAL(operands[0]) < 64
&& INTVAL(operands[0]) > -64 && ! TARGET_32532)
return \"adjspb %0\";
return \"adjspd %0\";
}")
(define_insn "subsi3"
[(set (match_operand:SI 0 "general_operand" "=g")
(minus:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_operand" "rmn")))]
""
"*
{ if (GET_CODE (operands[2]) == CONST_INT)
{
int i = INTVAL (operands[2]);
if (i <= 8 && i >= -7)
return \"addqd %$%n2,%0\";
}
return \"subd %2,%0\";
}")
(define_insn "subhi3"
[(set (match_operand:HI 0 "general_operand" "=g")
(minus:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:HI 2 "general_operand" "g")))]
""
"*
{ if (GET_CODE (operands[2]) == CONST_INT)
{
int i = INTVAL (operands[2]);
if (i <= 8 && i >= -7)
return \"addqw %$%n2,%0\";
}
return \"subw %2,%0\";
}")
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "general_operand" "=r"))
(minus:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:HI 2 "general_operand" "g")))]
""
"*
{
if (GET_CODE (operands[1]) == CONST_INT
&& INTVAL (operands[1]) >-8 && INTVAL(operands[1]) < 9)
return \"addqw %$%n1,%0\";
return \"subw %1,%0\";
}")
(define_insn "subqi3"
[(set (match_operand:QI 0 "general_operand" "=g")
(minus:QI (match_operand:QI 1 "general_operand" "0")
(match_operand:QI 2 "general_operand" "g")))]
""
"*
{ if (GET_CODE (operands[2]) == CONST_INT)
{
int i = INTVAL (operands[2]);
if (i <= 8 && i >= -7)
return \"addqb %$%n2,%0\";
}
return \"subb %2,%0\";
}")
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "general_operand" "=r"))
(minus:QI (match_operand:QI 1 "general_operand" "0")
(match_operand:QI 2 "general_operand" "g")))]
""
"*
{
if (GET_CODE (operands[1]) == CONST_INT
&& INTVAL (operands[1]) >-8 && INTVAL(operands[1]) < 9)
return \"addqb %$%n1,%0\";
return \"subb %1,%0\";
}")
;;- Multiply instructions.
(define_insn "muldf3"
[(set (match_operand:DF 0 "general_operand" "=fm")
(mult:DF (match_operand:DF 1 "general_operand" "%0")
(match_operand:DF 2 "general_operand" "fmF")))]
"TARGET_32081"
"mull %2,%0")
(define_insn "mulsf3"
[(set (match_operand:SF 0 "general_operand" "=fm")
(mult:SF (match_operand:SF 1 "general_operand" "%0")
(match_operand:SF 2 "general_operand" "fmF")))]
"TARGET_32081"
"mulf %2,%0")
(define_insn "mulsi3"
[(set (match_operand:SI 0 "general_operand" "=g")
(mult:SI (match_operand:SI 1 "general_operand" "%0")
(match_operand:SI 2 "general_operand" "rmn")))]
""
"muld %2,%0")
(define_insn "mulhi3"
[(set (match_operand:HI 0 "general_operand" "=g")
(mult:HI (match_operand:HI 1 "general_operand" "%0")
(match_operand:HI 2 "general_operand" "g")))]
""
"mulw %2,%0")
(define_insn "mulqi3"
[(set (match_operand:QI 0 "general_operand" "=g")
(mult:QI (match_operand:QI 1 "general_operand" "%0")
(match_operand:QI 2 "general_operand" "g")))]
""
"mulb %2,%0")
(define_insn "umulsidi3"
[(set (match_operand:DI 0 "general_operand" "=g")
(mult:DI (zero_extend:DI
(match_operand:SI 1 "nonimmediate_operand" "0"))
(zero_extend:DI
(match_operand:SI 2 "nonimmediate_operand" "rmn"))))]
""
"meid %2,%0")
;;- Divide instructions.
(define_insn "divdf3"
[(set (match_operand:DF 0 "general_operand" "=fm")
(div:DF (match_operand:DF 1 "general_operand" "0")
(match_operand:DF 2 "general_operand" "fmF")))]
"TARGET_32081"
"divl %2,%0")
(define_insn "divsf3"
[(set (match_operand:SF 0 "general_operand" "=fm")
(div:SF (match_operand:SF 1 "general_operand" "0")
(match_operand:SF 2 "general_operand" "fmF")))]
"TARGET_32081"
"divf %2,%0")
(define_insn "divsi3"
[(set (match_operand:SI 0 "general_operand" "=g")
(div:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_operand" "rmn")))]
""
"quod %2,%0")
(define_insn "divhi3"
[(set (match_operand:HI 0 "general_operand" "=g")
(div:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:HI 2 "general_operand" "g")))]
""
"quow %2,%0")
(define_insn "divqi3"
[(set (match_operand:QI 0 "general_operand" "=g")
(div:QI (match_operand:QI 1 "general_operand" "0")
(match_operand:QI 2 "general_operand" "g")))]
""
"quob %2,%0")
(define_insn "udivsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(udiv:SI (subreg:SI (match_operand:DI 1 "reg_or_mem_operand" "0") 0)
(match_operand:SI 2 "general_operand" "rmn")))]
""
"*
{
operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
return \"deid %2,%0\;movd %1,%0\";
}")
(define_insn "udivhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
(udiv:HI (subreg:HI (match_operand:DI 1 "reg_or_mem_operand" "0") 0)
(match_operand:HI 2 "general_operand" "g")))]
""
"*
{
operands[1] = gen_rtx (REG, HImode, REGNO (operands[0]) + 1);
return \"deiw %2,%0\;movw %1,%0\";
}")
(define_insn "udivqi3"
[(set (match_operand:QI 0 "register_operand" "=r")
(udiv:QI (subreg:QI (match_operand:DI 1 "reg_or_mem_operand" "0") 0)
(match_operand:QI 2 "general_operand" "g")))]
""
"*
{
operands[1] = gen_rtx (REG, QImode, REGNO (operands[0]) + 1);
return \"deib %2,%0\;movb %1,%0\";
}")
;; Remainder instructions.
(define_insn "modsi3"
[(set (match_operand:SI 0 "general_operand" "=g")
(mod:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_operand" "rmn")))]
""
"remd %2,%0")
(define_insn "modhi3"
[(set (match_operand:HI 0 "general_operand" "=g")
(mod:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:HI 2 "general_operand" "g")))]
""
"remw %2,%0")
(define_insn "modqi3"
[(set (match_operand:QI 0 "general_operand" "=g")
(mod:QI (match_operand:QI 1 "general_operand" "0")
(match_operand:QI 2 "general_operand" "g")))]
""
"remb %2,%0")
(define_insn "umodsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(umod:SI (subreg:SI (match_operand:DI 1 "reg_or_mem_operand" "0") 0)
(match_operand:SI 2 "general_operand" "rmn")))]
""
"deid %2,%0")
(define_insn "umodhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
(umod:HI (subreg:HI (match_operand:DI 1 "reg_or_mem_operand" "0") 0)
(match_operand:HI 2 "general_operand" "g")))]
""
"deiw %2,%0")
(define_insn "umodqi3"
[(set (match_operand:QI 0 "register_operand" "=r")
(umod:QI (subreg:QI (match_operand:DI 1 "reg_or_mem_operand" "0") 0)
(match_operand:QI 2 "general_operand" "g")))]
""
"deib %2,%0")
; This isn't be usable in its current form.
;(define_insn "udivmoddisi4"
; [(set (subreg:SI (match_operand:DI 0 "general_operand" "=r") 1)
; (udiv:SI (match_operand:DI 1 "general_operand" "0")
; (match_operand:SI 2 "general_operand" "rmn")))
; (set (subreg:SI (match_dup 0) 0)
; (umod:SI (match_dup 1) (match_dup 2)))]
; ""
; "deid %2,%0")
;;- Logical Instructions: AND
(define_insn "andsi3"
[(set (match_operand:SI 0 "general_operand" "=g")
(and:SI (match_operand:SI 1 "general_operand" "%0")
(match_operand:SI 2 "general_operand" "rmn")))]
""
"*
{
if (GET_CODE (operands[2]) == CONST_INT)
{
if ((INTVAL (operands[2]) | 0xff) == 0xffffffff)
{
if (INTVAL (operands[2]) == 0xffffff00)
return \"movqb %$0,%0\";
else
{
operands[2] = gen_rtx (CONST_INT, VOIDmode,
INTVAL (operands[2]) & 0xff);
return \"andb %2,%0\";
}
}
if ((INTVAL (operands[2]) | 0xffff) == 0xffffffff)
{
if (INTVAL (operands[2]) == 0xffff0000)
return \"movqw %$0,%0\";
else
{
operands[2] = gen_rtx (CONST_INT, VOIDmode,
INTVAL (operands[2]) & 0xffff);
return \"andw %2,%0\";
}
}
}
return \"andd %2,%0\";
}")
(define_insn "andhi3"
[(set (match_operand:HI 0 "general_operand" "=g")
(and:HI (match_operand:HI 1 "general_operand" "%0")
(match_operand:HI 2 "general_operand" "g")))]
""
"*
{
if (GET_CODE (operands[2]) == CONST_INT
&& (INTVAL (operands[2]) | 0xff) == 0xffffffff)
{
if (INTVAL (operands[2]) == 0xffffff00)
return \"movqb %$0,%0\";
else
{
operands[2] = gen_rtx (CONST_INT, VOIDmode,
INTVAL (operands[2]) & 0xff);
return \"andb %2,%0\";
}
}
return \"andw %2,%0\";
}")
(define_insn "andqi3"
[(set (match_operand:QI 0 "general_operand" "=g")
(and:QI (match_operand:QI 1 "general_operand" "%0")
(match_operand:QI 2 "general_operand" "g")))]
""
"andb %2,%0")
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=g")
(and:SI (not:SI (match_operand:SI 1 "general_operand" "rmn"))
(match_operand:SI 2 "general_operand" "0")))]
""
"bicd %1,%0")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=g")
(and:HI (not:HI (match_operand:HI 1 "general_operand" "g"))
(match_operand:HI 2 "general_operand" "0")))]
""
"bicw %1,%0")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=g")
(and:QI (not:QI (match_operand:QI 1 "general_operand" "g"))
(match_operand:QI 2 "general_operand" "0")))]
""
"bicb %1,%0")
;;- Bit set instructions.
(define_insn "iorsi3"
[(set (match_operand:SI 0 "general_operand" "=g")
(ior:SI (match_operand:SI 1 "general_operand" "%0")
(match_operand:SI 2 "general_operand" "rmn")))]
""
"*
{
if (GET_CODE (operands[2]) == CONST_INT) {
if ((INTVAL (operands[2]) & 0xffffff00) == 0)
return \"orb %2,%0\";
if ((INTVAL (operands[2]) & 0xffff0000) == 0)
return \"orw %2,%0\";
}
return \"ord %2,%0\";
}")
(define_insn "iorhi3"
[(set (match_operand:HI 0 "general_operand" "=g")
(ior:HI (match_operand:HI 1 "general_operand" "%0")
(match_operand:HI 2 "general_operand" "g")))]
""
"*
{
if (GET_CODE(operands[2]) == CONST_INT &&
(INTVAL(operands[2]) & 0xffffff00) == 0)
return \"orb %2,%0\";
return \"orw %2,%0\";
}")
(define_insn "iorqi3"
[(set (match_operand:QI 0 "general_operand" "=g")
(ior:QI (match_operand:QI 1 "general_operand" "%0")
(match_operand:QI 2 "general_operand" "g")))]
""
"orb %2,%0")
;;- xor instructions.
(define_insn "xorsi3"
[(set (match_operand:SI 0 "general_operand" "=g")
(xor:SI (match_operand:SI 1 "general_operand" "%0")
(match_operand:SI 2 "general_operand" "rmn")))]
""
"*
{
if (GET_CODE (operands[2]) == CONST_INT) {
if ((INTVAL (operands[2]) & 0xffffff00) == 0)
return \"xorb %2,%0\";
if ((INTVAL (operands[2]) & 0xffff0000) == 0)
return \"xorw %2,%0\";
}
return \"xord %2,%0\";
}")
(define_insn "xorhi3"
[(set (match_operand:HI 0 "general_operand" "=g")
(xor:HI (match_operand:HI 1 "general_operand" "%0")
(match_operand:HI 2 "general_operand" "g")))]
""
"*
{
if (GET_CODE(operands[2]) == CONST_INT &&
(INTVAL(operands[2]) & 0xffffff00) == 0)
return \"xorb %2,%0\";
return \"xorw %2,%0\";
}")
(define_insn "xorqi3"
[(set (match_operand:QI 0 "general_operand" "=g")
(xor:QI (match_operand:QI 1 "general_operand" "%0")
(match_operand:QI 2 "general_operand" "g")))]
""
"xorb %2,%0")
(define_insn "negdf2"
[(set (match_operand:DF 0 "general_operand" "=fm<")
(neg:DF (match_operand:DF 1 "general_operand" "fmF")))]
"TARGET_32081"
"negl %1,%0")
(define_insn "negsf2"
[(set (match_operand:SF 0 "general_operand" "=fm<")
(neg:SF (match_operand:SF 1 "general_operand" "fmF")))]
"TARGET_32081"
"negf %1,%0")
(define_insn "negsi2"
[(set (match_operand:SI 0 "general_operand" "=g<")
(neg:SI (match_operand:SI 1 "general_operand" "rmn")))]
""
"negd %1,%0")
(define_insn "neghi2"
[(set (match_operand:HI 0 "general_operand" "=g<")
(neg:HI (match_operand:HI 1 "general_operand" "g")))]
""
"negw %1,%0")
(define_insn "negqi2"
[(set (match_operand:QI 0 "general_operand" "=g<")
(neg:QI (match_operand:QI 1 "general_operand" "g")))]
""
"negb %1,%0")
(define_insn "one_cmplsi2"
[(set (match_operand:SI 0 "general_operand" "=g<")
(not:SI (match_operand:SI 1 "general_operand" "rmn")))]
""
"comd %1,%0")
(define_insn "one_cmplhi2"
[(set (match_operand:HI 0 "general_operand" "=g<")
(not:HI (match_operand:HI 1 "general_operand" "g")))]
""
"comw %1,%0")
(define_insn "one_cmplqi2"
[(set (match_operand:QI 0 "general_operand" "=g<")
(not:QI (match_operand:QI 1 "general_operand" "g")))]
""
"comb %1,%0")
;; arithmetic left and right shift operations
;; on the 32532 we will always use lshd for arithmetic left shifts,
;; because it is three times faster. Broken programs which
;; use negative shift counts are probably broken differently
;; than elsewhere.
;; alternative 0 never matches on the 32532
(define_insn "ashlsi3"
[(set (match_operand:SI 0 "general_operand" "=g,g")
(ashift:SI (match_operand:SI 1 "general_operand" "r,0")
(match_operand:SI 2 "general_operand" "I,rmn")))]
""
"*
{ if (TARGET_32532)
return \"lshd %2,%0\";
else
return output_shift_insn (operands);
}")
(define_insn "ashlhi3"
[(set (match_operand:HI 0 "general_operand" "=g")
(ashift:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:SI 2 "general_operand" "rmn")))]
""
"*
{ if (GET_CODE (operands[2]) == CONST_INT)
{
if (INTVAL (operands[2]) == 1)
return \"addw %0,%0\";
else if (INTVAL (operands[2]) == 2 && !TARGET_32532)
return \"addw %0,%0\;addw %0,%0\";
}
if (TARGET_32532)
return \"lshw %2,%0\";
else
return \"ashw %2,%0\";
}")
(define_insn "ashlqi3"
[(set (match_operand:QI 0 "general_operand" "=g")
(ashift:QI (match_operand:QI 1 "general_operand" "0")
(match_operand:SI 2 "general_operand" "rmn")))]
""
"*
{ if (GET_CODE (operands[2]) == CONST_INT)
{
if (INTVAL (operands[2]) == 1)
return \"addb %0,%0\";
else if (INTVAL (operands[2]) == 2 && !TARGET_32532)
return \"addb %0,%0\;addb %0,%0\";
}
if (TARGET_32532)
return \"lshb %2,%0\";
else
return \"ashb %2,%0\";
}")
;; Arithmetic right shift on the 32k works by negating the shift count.
(define_expand "ashrsi3"
[(set (match_operand:SI 0 "general_operand" "=g")
(ashiftrt:SI (match_operand:SI 1 "general_operand" "g")
(match_operand:SI 2 "general_operand" "g")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=g")
(ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "immediate_operand" "i")))]
""
"ashd %$%n2,%0")
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=g")
(ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
(neg:SI (match_operand:SI 2 "general_operand" "r"))))]
""
"ashd %2,%0")
(define_expand "ashrhi3"
[(set (match_operand:HI 0 "general_operand" "=g")
(ashiftrt:HI (match_operand:HI 1 "general_operand" "g")
(match_operand:SI 2 "general_operand" "g")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=g")
(ashiftrt:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:SI 2 "immediate_operand" "i")))]
""
"ashw %$%n2,%0")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=g")
(ashiftrt:HI (match_operand:HI 1 "general_operand" "0")
(neg:SI (match_operand:SI 2 "general_operand" "r"))))]
""
"ashw %2,%0")
(define_expand "ashrqi3"
[(set (match_operand:QI 0 "general_operand" "=g")
(ashiftrt:QI (match_operand:QI 1 "general_operand" "g")
(match_operand:SI 2 "general_operand" "g")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=g")
(ashiftrt:QI (match_operand:QI 1 "general_operand" "0")
(match_operand:SI 2 "immediate_operand" "i")))]
""
"ashb %$%n2,%0")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=g")
(ashiftrt:QI (match_operand:QI 1 "general_operand" "0")
(neg:SI (match_operand:SI 2 "general_operand" "r"))))]
""
"ashb %2,%0")
;; logical shift instructions
(define_insn "lshlsi3"
[(set (match_operand:SI 0 "general_operand" "=g")
(lshift:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_operand" "rmn")))]
""
"lshd %2,%0")
(define_insn "lshlhi3"
[(set (match_operand:HI 0 "general_operand" "=g")
(lshift:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:SI 2 "general_operand" "rmn")))]
""
"lshw %2,%0")
(define_insn "lshlqi3"
[(set (match_operand:QI 0 "general_operand" "=g")
(lshift:QI (match_operand:QI 1 "general_operand" "0")
(match_operand:SI 2 "general_operand" "rmn")))]
""
"lshb %2,%0")
;; Logical right shift on the 32k works by negating the shift count.
(define_expand "lshrsi3"
[(set (match_operand:SI 0 "general_operand" "=g")
(lshiftrt:SI (match_operand:SI 1 "general_operand" "g")
(match_operand:SI 2 "general_operand" "g")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=g")
(lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "immediate_operand" "i")))]
""
"lshd %$%n2,%0")
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=g")
(lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
(neg:SI (match_operand:SI 2 "general_operand" "r"))))]
""
"lshd %2,%0")
(define_expand "lshrhi3"
[(set (match_operand:HI 0 "general_operand" "=g")
(lshiftrt:HI (match_operand:HI 1 "general_operand" "g")
(match_operand:SI 2 "general_operand" "g")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=g")
(lshiftrt:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:SI 2 "immediate_operand" "i")))]
""
"lshw %$%n2,%0")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=g")
(lshiftrt:HI (match_operand:HI 1 "general_operand" "0")
(neg:SI (match_operand:SI 2 "general_operand" "r"))))]
""
"lshw %2,%0")
(define_expand "lshrqi3"
[(set (match_operand:QI 0 "general_operand" "=g")
(lshiftrt:QI (match_operand:QI 1 "general_operand" "g")
(match_operand:SI 2 "general_operand" "g")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=g")
(lshiftrt:QI (match_operand:QI 1 "general_operand" "0")
(match_operand:SI 2 "immediate_operand" "i")))]
""
"lshb %$%n2,%0")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=g")
(lshiftrt:QI (match_operand:QI 1 "general_operand" "0")
(neg:SI (match_operand:SI 2 "general_operand" "r"))))]
""
"lshb %2,%0")
;; Rotate instructions
(define_insn "rotlsi3"
[(set (match_operand:SI 0 "general_operand" "=g")
(rotate:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_operand" "rmn")))]
""
"rotd %2,%0")
(define_insn "rotlhi3"
[(set (match_operand:HI 0 "general_operand" "=g")
(rotate:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:SI 2 "general_operand" "rmn")))]
""
"rotw %2,%0")
(define_insn "rotlqi3"
[(set (match_operand:QI 0 "general_operand" "=g")
(rotate:QI (match_operand:QI 1 "general_operand" "0")
(match_operand:SI 2 "general_operand" "rmn")))]
""
"rotb %2,%0")
;; Right rotate on the 32k works by negating the shift count.
(define_expand "rotrsi3"
[(set (match_operand:SI 0 "general_operand" "=g")
(rotatert:SI (match_operand:SI 1 "general_operand" "g")
(match_operand:SI 2 "general_operand" "g")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=g")
(rotatert:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "immediate_operand" "i")))]
""
"rotd %$%n2,%0")
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=g")
(rotatert:SI (match_operand:SI 1 "general_operand" "0")
(neg:SI (match_operand:SI 2 "general_operand" "r"))))]
""
"rotd %2,%0")
(define_expand "rotrhi3"
[(set (match_operand:HI 0 "general_operand" "=g")
(rotatert:HI (match_operand:HI 1 "general_operand" "g")
(match_operand:SI 2 "general_operand" "g")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=g")
(rotatert:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:SI 2 "immediate_operand" "i")))]
""
"rotw %$%n2,%0")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=g")
(rotatert:HI (match_operand:HI 1 "general_operand" "0")
(neg:SI (match_operand:SI 2 "general_operand" "r"))))]
""
"rotw %2,%0")
(define_expand "rotrqi3"
[(set (match_operand:QI 0 "general_operand" "=g")
(rotatert:QI (match_operand:QI 1 "general_operand" "g")
(match_operand:SI 2 "general_operand" "g")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=g")
(rotatert:QI (match_operand:QI 1 "general_operand" "0")
(match_operand:SI 2 "immediate_operand" "i")))]
""
"rotb %$%n2,%0")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=g")
(rotatert:QI (match_operand:QI 1 "general_operand" "0")
(neg:SI (match_operand:SI 2 "general_operand" "r"))))]
""
"rotb %2,%0")
;;- load or push effective address
;; These come after the move, add, and multiply patterns
;; because we don't want pushl $1 turned into pushad 1.
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=g<")
(match_operand:QI 1 "address_operand" "p"))]
""
"*
{
if (REG_P (operands[0])
&& GET_CODE (operands[1]) == MULT
&& GET_CODE (XEXP (operands[1], 1)) == CONST_INT
&& (INTVAL (XEXP (operands[1], 1)) == 2
|| INTVAL (XEXP (operands[1], 1)) == 4))
{
rtx xoperands[3];
xoperands[0] = operands[0];
xoperands[1] = XEXP (operands[1], 0);
xoperands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (XEXP (operands[1], 1)) >> 1);
return output_shift_insn (xoperands);
}
return \"addr %a1,%0\";
}")
;;; Index insns. These are about the same speed as multiply-add counterparts.
;;; but slower then using power-of-2 shifts if we can use them
;
;(define_insn ""
; [(set (match_operand:SI 0 "register_operand" "=r")
; (plus:SI (match_operand:SI 1 "general_operand" "rmn")
; (mult:SI (match_operand:SI 2 "register_operand" "0")
; (plus:SI (match_operand:SI 3 "general_operand" "rmn") (const_int 1)))))]
; "GET_CODE (operands[3]) != CONST_INT || INTVAL (operands[3]) > 8"
; "indexd %0,%3,%1")
;
;(define_insn ""
; [(set (match_operand:SI 0 "register_operand" "=r")
; (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "0")
; (plus:SI (match_operand:SI 2 "general_operand" "rmn") (const_int 1)))
; (match_operand:SI 3 "general_operand" "rmn")))]
; "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) > 8"
; "indexd %0,%2,%3")
;; Set, Clear, and Invert bit
(define_insn ""
[(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+g")
(const_int 1)
(match_operand:SI 1 "general_operand" "rmn"))
(const_int 1))]
""
"sbitd %1,%0")
(define_insn ""
[(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+g")
(const_int 1)
(match_operand:SI 1 "general_operand" "rmn"))
(const_int 0))]
""
"cbitd %1,%0")
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "+g")
(xor:SI (ashift:SI (const_int 1)
(match_operand:SI 1 "general_operand" "rmn"))
(match_dup 0)))]
""
"ibitd %1,%0")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=g")
(xor:QI (subreg:QI
(ashift:SI (const_int 1)
(match_operand:QI 1 "general_operand" "rmn")) 0)
(match_dup 0)))]
""
"ibitb %1,%0")
;; Recognize jbs and jbc instructions.
(define_insn ""
[(set (cc0)
(zero_extract (match_operand:SI 0 "general_operand" "rm")
(const_int 1)
(match_operand:SI 1 "general_operand" "g")))]
""
"*
{ cc_status.flags = CC_Z_IN_F;
return \"tbitd %1,%0\";
}")
;; extract(base, width, offset)
;; Signed bitfield extraction is not supported in hardware on the
;; NS 32032. It is therefore better to let GCC figure out a
;; good strategy for generating the proper instruction sequence
;; and represent it as rtl.
;; Optimize the case of extracting a byte or word from a register.
;; Otherwise we must load a register with the offset of the
;; chunk we want, and perform an extract insn (each of which
;; is very expensive). Since we use the stack to do our bit-twiddling
;; we cannot use it for a destination. Perhaps things are fast
;; enough on the 32532 that such hacks are not needed.
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=ro")
(zero_extract:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "const_int_operand" "i")
(match_operand:SI 3 "const_int_operand" "i")))]
"(INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
&& (INTVAL (operands[3]) == 8 || INTVAL (operands[3]) == 16 || INTVAL (operands[3]) == 24)"
"*
{
output_asm_insn (\"movd %1,tos\", operands);
if (INTVAL (operands[2]) == 16)
{
if (INTVAL (operands[3]) == 8)
output_asm_insn (\"movzwd 1(sp),%0\", operands);
else
output_asm_insn (\"movzwd 2(sp),%0\", operands);
}
else
{
if (INTVAL (operands[3]) == 8)
output_asm_insn (\"movzbd 1(sp),%0\", operands);
else if (INTVAL (operands[3]) == 16)
output_asm_insn (\"movzbd 2(sp),%0\", operands);
else
output_asm_insn (\"movzbd 3(sp),%0\", operands);
}
if (TARGET_32532 || TARGET_32332)
return \"cmpqd %$0,tos\";
else
return \"adjspb %$-4\";
}")
(define_insn "extzv"
[(set (match_operand:SI 0 "general_operand" "=g<")
(zero_extract:SI (match_operand:QI 1 "general_operand" "g")
(match_operand:SI 2 "const_int_operand" "i")
(match_operand:SI 3 "general_operand" "rK")))]
""
"*
{ if (GET_CODE (operands[3]) == CONST_INT)
return \"extsd %1,%0,%3,%2\";
else return \"extd %3,%1,%0,%2\";
}")
(define_insn ""
[(set (zero_extract:SI (match_operand:SI 0 "memory_operand" "+o")
(match_operand:SI 1 "const_int_operand" "i")
(match_operand:SI 2 "general_operand" "rn"))
(match_operand:SI 3 "general_operand" "rm"))]
""
"*
{ if (GET_CODE (operands[2]) == CONST_INT)
{
if (INTVAL (operands[2]) >= 8)
{
operands[0] = adj_offsettable_operand (operands[0],
INTVAL (operands[2]) / 8);
operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) % 8);
}
if (INTVAL (operands[1]) <= 8)
return \"inssb %3,%0,%2,%1\";
else if (INTVAL (operands[1]) <= 16)
return \"inssw %3,%0,%2,%1\";
else
return \"inssd %3,%0,%2,%1\";
}
return \"insd %2,%3,%0,%1\";
}")
(define_insn ""
[(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
(match_operand:SI 1 "const_int_operand" "i")
(match_operand:SI 2 "general_operand" "rK"))
(match_operand:SI 3 "general_operand" "rm"))]
""
"*
{ if (GET_CODE (operands[2]) == CONST_INT)
if (INTVAL (operands[1]) <= 8)
return \"inssb %3,%0,%2,%1\";
else if (INTVAL (operands[1]) <= 16)
return \"inssw %3,%0,%2,%1\";
else
return \"inssd %3,%0,%2,%1\";
return \"insd %2,%3,%0,%1\";
}")
(define_insn "insv"
[(set (zero_extract:SI (match_operand:QI 0 "general_operand" "+g")
(match_operand:SI 1 "const_int_operand" "i")
(match_operand:SI 2 "general_operand" "rK"))
(match_operand:SI 3 "general_operand" "rm"))]
""
"*
{ if (GET_CODE (operands[2]) == CONST_INT)
if (INTVAL (operands[1]) <= 8)
return \"inssb %3,%0,%2,%1\";
else if (INTVAL (operands[1]) <= 16)
return \"inssw %3,%0,%2,%1\";
else
return \"inssd %3,%0,%2,%1\";
return \"insd %2,%3,%0,%1\";
}")
(define_insn "jump"
[(set (pc)
(label_ref (match_operand 0 "" "")))]
""
"br %l0")
(define_insn "beq"
[(set (pc)
(if_then_else (eq (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"*
{ if (cc_prev_status.flags & CC_Z_IN_F)
return \"bfc %l0\";
else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
return \"bfs %l0\";
else return \"beq %l0\";
}")
(define_insn "bne"
[(set (pc)
(if_then_else (ne (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"*
{ if (cc_prev_status.flags & CC_Z_IN_F)
return \"bfs %l0\";
else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
return \"bfc %l0\";
else return \"bne %l0\";
}")
(define_insn "bgt"
[(set (pc)
(if_then_else (gt (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"bgt %l0")
(define_insn "bgtu"
[(set (pc)
(if_then_else (gtu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"bhi %l0")
(define_insn "blt"
[(set (pc)
(if_then_else (lt (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"blt %l0")
(define_insn "bltu"
[(set (pc)
(if_then_else (ltu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"blo %l0")
(define_insn "bge"
[(set (pc)
(if_then_else (ge (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"bge %l0")
(define_insn "bgeu"
[(set (pc)
(if_then_else (geu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"bhs %l0")
(define_insn "ble"
[(set (pc)
(if_then_else (le (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"ble %l0")
(define_insn "bleu"
[(set (pc)
(if_then_else (leu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"bls %l0")
(define_insn ""
[(set (pc)
(if_then_else (eq (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"*
{ if (cc_prev_status.flags & CC_Z_IN_F)
return \"bfs %l0\";
else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
return \"bfc %l0\";
else return \"bne %l0\";
}")
(define_insn ""
[(set (pc)
(if_then_else (ne (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"*
{ if (cc_prev_status.flags & CC_Z_IN_F)
return \"bfc %l0\";
else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
return \"bfs %l0\";
else return \"beq %l0\";
}")
(define_insn ""
[(set (pc)
(if_then_else (gt (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"ble %l0")
(define_insn ""
[(set (pc)
(if_then_else (gtu (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"bls %l0")
(define_insn ""
[(set (pc)
(if_then_else (lt (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"bge %l0")
(define_insn ""
[(set (pc)
(if_then_else (ltu (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"bhs %l0")
(define_insn ""
[(set (pc)
(if_then_else (ge (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"blt %l0")
(define_insn ""
[(set (pc)
(if_then_else (geu (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"blo %l0")
(define_insn ""
[(set (pc)
(if_then_else (le (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"bgt %l0")
(define_insn ""
[(set (pc)
(if_then_else (leu (cc0)
(const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
""
"bhi %l0")
;; Subtract-and-jump and Add-and-jump insns.
;; These can actually be used for adding numbers in the range -8 to 7
(define_insn ""
[(set (pc)
(if_then_else
(ne (match_operand:SI 0 "general_operand" "+g")
(match_operand:SI 1 "const_int_operand" "i"))
(label_ref (match_operand 2 "" ""))
(pc)))
(set (match_dup 0)
(minus:SI (match_dup 0)
(match_dup 1)))]
"INTVAL (operands[1]) > -8 && INTVAL (operands[1]) <= 8"
"acbd %$%n1,%0,%l2")
(define_insn ""
[(set (pc)
(if_then_else
(ne (match_operand:SI 0 "general_operand" "+g")
(match_operand:SI 1 "const_int_operand" "i"))
(label_ref (match_operand 2 "" ""))
(pc)))
(set (match_dup 0)
(plus:SI (match_dup 0)
(match_operand:SI 3 "const_int_operand" "i")))]
"INTVAL (operands[1]) == - INTVAL (operands[3])
&& INTVAL (operands[3]) >= -8 && INTVAL (operands[3]) < 8"
"acbd %3,%0,%l2")
(define_insn "call"
[(call (match_operand:QI 0 "memory_operand" "m")
(match_operand:QI 1 "general_operand" "g"))]
""
"*
{
#ifndef JSR_ALWAYS
if (GET_CODE (operands[0]) == MEM)
{
rtx temp = XEXP (operands[0], 0);
if (CONSTANT_ADDRESS_P (temp))
{
operands[0] = temp;
return \"bsr %0\";
#if 0
#ifdef GNX_V3
return \"bsr %0\";
#else
return \"bsr %?%a0\";
#endif
#endif
}
if (GET_CODE (XEXP (operands[0], 0)) == REG)
return \"jsr %0\";
#if 0
return \"jsr %a0\";
#endif
}
#endif /* not JSR_ALWAYS */
return \"jsr %0\";
}")
(define_insn "call_value"
[(set (match_operand 0 "" "=rf")
(call (match_operand:QI 1 "memory_operand" "m")
(match_operand:QI 2 "general_operand" "g")))]
""
"*
{
#ifndef JSR_ALWAYS
if (GET_CODE (operands[1]) == MEM)
{
rtx temp = XEXP (operands[1], 0);
if (CONSTANT_ADDRESS_P (temp))
{
operands[1] = temp;
return \"bsr %1\";
#if 0
#ifdef GNX_V3
return \"bsr %1\";
#else
return \"bsr %?%a1\";
#endif
#endif
}
if (GET_CODE (XEXP (operands[1], 0)) == REG)
return \"jsr %1\";
#if 0
return \"jsr %a1\";
#endif
}
#endif /* not JSR_ALWAYS */
return \"jsr %1\";
}")
(define_insn "return"
[(return)]
"0"
"ret 0")
(define_insn "abssf2"
[(set (match_operand:SF 0 "general_operand" "=fm<")
(abs:SF (match_operand:SF 1 "general_operand" "fmF")))]
"TARGET_32081"
"absf %1,%0")
(define_insn "absdf2"
[(set (match_operand:DF 0 "general_operand" "=fm<")
(abs:DF (match_operand:DF 1 "general_operand" "fmF")))]
"TARGET_32081"
"absl %1,%0")
(define_insn "abssi2"
[(set (match_operand:SI 0 "general_operand" "=g<")
(abs:SI (match_operand:SI 1 "general_operand" "rmn")))]
""
"absd %1,%0")
(define_insn "abshi2"
[(set (match_operand:HI 0 "general_operand" "=g<")
(abs:HI (match_operand:HI 1 "general_operand" "g")))]
""
"absw %1,%0")
(define_insn "absqi2"
[(set (match_operand:QI 0 "general_operand" "=g<")
(abs:QI (match_operand:QI 1 "general_operand" "g")))]
""
"absb %1,%0")
(define_insn "nop"
[(const_int 0)]
""
"nop")
(define_insn "indirect_jump"
[(set (pc) (match_operand:SI 0 "register_operand" "r"))]
""
"jump %0")
;;(define_insn "tablejump"
;; [(set (pc)
;; (plus:SI (match_operand:SI 0 "general_operand" "g")
;; (pc)))]
;; ""
;; "cased %0")
(define_insn "tablejump"
[(set (pc)
(plus:SI (pc) (match_operand:HI 0 "general_operand" "g")))
(use (label_ref (match_operand 1 "" "")))]
""
"*
{
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"LI\",
CODE_LABEL_NUMBER (operands[1]));
return \"casew %0\";
}")
;;(define_insn ""
;; [(set (pc)
;; (plus:SI (match_operand:QI 0 "general_operand" "g")
;; (pc)))]
;; ""
;; "caseb %0")
;; Scondi instructions
(define_insn "seq"
[(set (match_operand:SI 0 "general_operand" "=g<")
(eq:SI (cc0) (const_int 0)))]
""
"*
{ if (cc_prev_status.flags & CC_Z_IN_F)
return \"sfcd %0\";
else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
return \"sfsd %0\";
else return \"seqd %0\";
}")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=g<")
(eq:HI (cc0) (const_int 0)))]
""
"*
{ if (cc_prev_status.flags & CC_Z_IN_F)
return \"sfcw %0\";
else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
return \"sfsw %0\";
else return \"seqw %0\";
}")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=g<")
(eq:QI (cc0) (const_int 0)))]
""
"*
{ if (cc_prev_status.flags & CC_Z_IN_F)
return \"sfcb %0\";
else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
return \"sfsb %0\";
else return \"seqb %0\";
}")
(define_insn "sne"
[(set (match_operand:SI 0 "general_operand" "=g<")
(ne:SI (cc0) (const_int 0)))]
""
"*
{ if (cc_prev_status.flags & CC_Z_IN_F)
return \"sfsd %0\";
else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
return \"sfcd %0\";
else return \"sned %0\";
}")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=g<")
(ne:HI (cc0) (const_int 0)))]
""
"*
{ if (cc_prev_status.flags & CC_Z_IN_F)
return \"sfsw %0\";
else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
return \"sfcw %0\";
else return \"snew %0\";
}")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=g<")
(ne:QI (cc0) (const_int 0)))]
""
"*
{ if (cc_prev_status.flags & CC_Z_IN_F)
return \"sfsb %0\";
else if (cc_prev_status.flags & CC_Z_IN_NOT_F)
return \"sfcb %0\";
else return \"sneb %0\";
}")
(define_insn "sgt"
[(set (match_operand:SI 0 "general_operand" "=g<")
(gt:SI (cc0) (const_int 0)))]
""
"sgtd %0")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=g<")
(gt:HI (cc0) (const_int 0)))]
""
"sgtw %0")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=g<")
(gt:QI (cc0) (const_int 0)))]
""
"sgtb %0")
(define_insn "sgtu"
[(set (match_operand:SI 0 "general_operand" "=g<")
(gtu:SI (cc0) (const_int 0)))]
""
"shid %0")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=g<")
(gtu:HI (cc0) (const_int 0)))]
""
"shiw %0")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=g<")
(gtu:QI (cc0) (const_int 0)))]
""
"shib %0")
(define_insn "slt"
[(set (match_operand:SI 0 "general_operand" "=g<")
(lt:SI (cc0) (const_int 0)))]
""
"sltd %0")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=g<")
(lt:HI (cc0) (const_int 0)))]
""
"sltw %0")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=g<")
(lt:QI (cc0) (const_int 0)))]
""
"sltb %0")
(define_insn "sltu"
[(set (match_operand:SI 0 "general_operand" "=g<")
(ltu:SI (cc0) (const_int 0)))]
""
"slod %0")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=g<")
(ltu:HI (cc0) (const_int 0)))]
""
"slow %0")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=g<")
(ltu:QI (cc0) (const_int 0)))]
""
"slob %0")
(define_insn "sge"
[(set (match_operand:SI 0 "general_operand" "=g<")
(ge:SI (cc0) (const_int 0)))]
""
"sged %0")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=g<")
(ge:HI (cc0) (const_int 0)))]
""
"sgew %0")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=g<")
(ge:QI (cc0) (const_int 0)))]
""
"sgeb %0")
(define_insn "sgeu"
[(set (match_operand:SI 0 "general_operand" "=g<")
(geu:SI (cc0) (const_int 0)))]
""
"shsd %0")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=g<")
(geu:HI (cc0) (const_int 0)))]
""
"shsw %0")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=g<")
(geu:QI (cc0) (const_int 0)))]
""
"shsb %0")
(define_insn "sle"
[(set (match_operand:SI 0 "general_operand" "=g<")
(le:SI (cc0) (const_int 0)))]
""
"sled %0")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=g<")
(le:HI (cc0) (const_int 0)))]
""
"slew %0")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=g<")
(le:QI (cc0) (const_int 0)))]
""
"sleb %0")
(define_insn "sleu"
[(set (match_operand:SI 0 "general_operand" "=g<")
(leu:SI (cc0) (const_int 0)))]
""
"slsd %0")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=g<")
(leu:HI (cc0) (const_int 0)))]
""
"slsw %0")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=g<")
(leu:QI (cc0) (const_int 0)))]
""
"slsb %0")
;;- Local variables:
;;- mode:emacs-lisp
;;- comment-start: ";;- "
;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
;;- eval: (modify-syntax-entry ?[ "(]")
;;- eval: (modify-syntax-entry ?] ")[")
;;- eval: (modify-syntax-entry ?{ "(}")
;;- eval: (modify-syntax-entry ?} "){")
;;- End:
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment