From 647daf35445bc6597fb183f0af4dedcfd696aa92 Mon Sep 17 00:00:00 2001 From: Richard Kenner Date: Wed, 8 Jan 1992 06:12:04 -0500 Subject: [PATCH] Initial revision From-SVN: r173 --- gcc/config/convex/convex.md | 1334 ++++++++++++++++++ gcc/config/i860/i860.md | 2441 +++++++++++++++++++++++++++++++++ gcc/config/ns32k/ns32k.md | 2531 +++++++++++++++++++++++++++++++++++ 3 files changed, 6306 insertions(+) create mode 100644 gcc/config/convex/convex.md create mode 100644 gcc/config/i860/i860.md create mode 100644 gcc/config/ns32k/ns32k.md diff --git a/gcc/config/convex/convex.md b/gcc/config/convex/convex.md new file mode 100644 index 00000000000..4e7ea5a99f0 --- /dev/null +++ b/gcc/config/convex/convex.md @@ -0,0 +1,1334 @@ +;;- 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: diff --git a/gcc/config/i860/i860.md b/gcc/config/i860/i860.md new file mode 100644 index 00000000000..8b4ab420db8 --- /dev/null +++ b/gcc/config/i860/i860.md @@ -0,0 +1,2441 @@ +;;- 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 )) ) +;; which we expand poorly as four shift insns. +;; These patters yeild two shifts: +;; (shiftrt (shift ) ) +(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: + diff --git a/gcc/config/ns32k/ns32k.md b/gcc/config/ns32k/ns32k.md new file mode 100644 index 00000000000..f94312c9d78 --- /dev/null +++ b/gcc/config/ns32k/ns32k.md @@ -0,0 +1,2531 @@ +; 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: -- 2.30.2