aboutsummaryrefslogtreecommitdiff
path: root/gcc-1.40/config/mips.md
diff options
context:
space:
mode:
authorAndrew Lee <alee14498@protonmail.com>2021-08-15 00:34:05 -0400
committerAndrew Lee <alee14498@protonmail.com>2021-08-15 00:34:05 -0400
commit60cc83bf91bfc9bb02f6304b5d6c8234ba6d210f (patch)
treefdc0be85a1ca35e34c3ae2c805fe9b718e3c1091 /gcc-1.40/config/mips.md
parentdd8dfab51b832a654365ed00c06bf802ff628bfa (diff)
downloadlinux-0.01-distro-master.tar.gz
linux-0.01-distro-master.tar.bz2
linux-0.01-distro-master.zip
Added gccHEADmaster
Diffstat (limited to 'gcc-1.40/config/mips.md')
-rw-r--r--gcc-1.40/config/mips.md1957
1 files changed, 1957 insertions, 0 deletions
diff --git a/gcc-1.40/config/mips.md b/gcc-1.40/config/mips.md
new file mode 100644
index 0000000..82b4a50
--- /dev/null
+++ b/gcc-1.40/config/mips.md
@@ -0,0 +1,1957 @@
+;; Mips.md Naive version of Machine Description for MIPS
+;; Contributed by A. Lichnewsky, lich@inria.inria.fr
+;; Changes by Michael Meissner, meissner@osf.org
+;; 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 1, 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.
+
+;;
+;;------------------------------------------------------------------------
+;;
+
+;;
+;; ....................
+;;
+;; Peephole Optimizations for
+;;
+;; ARITHMETIC
+;;
+;; ....................
+;;
+ ;;- The following peepholes are
+ ;;- motivated by the fact that
+ ;;- stack movement result in some
+ ;;- cases in embarrassing sequences
+ ;;- of addiu SP,SP,int
+ ;;- addiu SP,SP,other_int
+
+ ;;- --------------------
+ ;;- REMARK: this would be done better
+ ;;- by analysis of dependencies in
+ ;;- basic blocks, prior to REG ALLOC,
+ ;;- and simplification of trees:
+ ;;- (+ (+ REG const) const)
+ ;;- -> (+ REG newconst)
+ ;;- --------------------
+ ;;- Merged peephole code from
+ ;;- raeburn@ATHENA.MIT.EDU
+
+(define_peephole
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (match_operator 1 "additive_op"
+ [(match_operand:SI 2 "register_operand" "r")
+ (match_operand:SI 3 "small_int" "I")]))
+ (set (match_operand:SI 4 "register_operand" "=r")
+ (match_operator 5 "additive_op"
+ [(match_dup 0)
+ (match_operand:SI 6 "small_int" "I")]))]
+ "(REGNO (operands[0]) == REGNO (operands[4])
+ || dead_or_set_p (insn, operands[0]))"
+ "*
+{
+ int addend;
+ /* compute sum, with signs */
+ addend = INTVAL (operands[3]) * (GET_CODE (operands[1]) == PLUS ? 1 : -1);
+ addend += INTVAL (operands[6]) * (GET_CODE (operands[5]) == PLUS ? 1 : -1);
+ if (addend != 0)
+ {
+ operands[0] = gen_rtx (CONST_INT, VOIDmode, addend);
+ return \"addi%:\\t%4,%2,%0\";
+ }
+ /* value is zero; copy */
+ if (REGNO (operands[4]) != REGNO (operands[2]))
+ return \"add%:\\t%4,%2,$0\";
+ /* copying to self; punt */
+ return \" # null operation: additive operands cancel (%0,%2)\";
+}")
+
+;;
+;; ....................
+;;
+;; ARITHMETIC
+;;
+;; ....................
+;;
+
+(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")))]
+ ""
+ "add.d\\t%0,%1,%2")
+
+(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")))]
+ ""
+ "add.s\\t%0,%1,%2")
+
+;; The following is generated when omiting the frame pointer
+;; and for referencing large auto arrays during optimization.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "register_operand" "%r")
+ (match_operand:SI 2 "immediate_operand" "i")))]
+ "operands[1] == stack_pointer_rtx || operands[1] == frame_pointer_rtx"
+ "*
+{
+ int number;
+ if (GET_CODE (operands[2]) != CONST_INT)
+ return \"add%:\\t%0,%1,%2\";
+
+ number = INTVAL (operands[2]);
+ if (((unsigned) (number + 0x8000) > 0xffff))
+ {
+ operands[3] = gen_rtx (REG, SImode, 1); /* assembler temp. */
+ return \".set\\tnoat\\n\\tli\\t%3,%2\\n\\tadd%:\\t%0,%1,%3\\n\\t.set\\tat\";
+ }
+
+ return (number < 0) ? \"sub%:\\t%0,%1,%n2\" : \"add%:\\t%0,%1,%2\";
+}")
+
+(define_insn "addsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (match_operand:SI 1 "arith_operand" "%r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "*
+{
+ return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
+ ? \"sub%:\\t%0,%1,%n2\"
+ : \"add%:\\t%0,%1,%2\";
+}")
+
+
+;;- All kinds of subtract instructions.
+
+(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")))]
+ ""
+ "sub.d\\t%0,%1,%2")
+
+(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")))]
+ ""
+ "sub.s\\t%0,%1,%2")
+
+;; The following is generated when omiting the frame pointer
+;; and for referencing large auto arrays during optimization.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_operand:SI 1 "register_operand" "%r")
+ (match_operand:SI 2 "immediate_operand" "i")))]
+ "operands[1] == stack_pointer_rtx || operands[1] == frame_pointer_rtx"
+ "*
+{
+ int number;
+ if (GET_CODE (operands[2]) != CONST_INT)
+ return \"sub%:\\t%0,%1,%2\";
+
+ number = INTVAL (operands[2]);
+ if (((unsigned) (number + 0x8000) > 0xffff))
+ {
+ operands[3] = gen_rtx (REG, SImode, 1); /* assembler temp. */
+ return \".set\\tnoat\\n\\tli\\t%3,%2\\n\\tsub%:\\t%0,%1,%3\\n\\t.set\\tat\";
+ }
+
+ return (number < 0) ? \"add%:\\t%0,%1,%n2\" : \"sub%:\\t%0,%1,%2\";
+}")
+
+(define_insn "subsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "*
+{
+ return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0)
+ ? \"add%:\\t%0,%1,%n2\"
+ : \"sub%:\\t%0,%1,%2\";
+}")
+
+
+;;- Multiply instructions.
+
+(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")))]
+ ""
+ "mul.d\\t%0,%1,%2")
+
+(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")))]
+ ""
+ "mul.s\\t%0,%1,%2")
+
+(define_insn "mulsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mult:SI (match_operand:SI 1 "arith_operand" "%r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "mul\\t%0,%1,%2")
+
+
+;;- Divide instructions.
+
+(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")))]
+ ""
+ "div.d\\t%0,%1,%2")
+
+(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")))]
+ ""
+ "div.s\\t%0,%1,%2")
+
+(define_insn "divmodsi4"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (div:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (mod:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+ "div\\t$0,%1,%2\\n\\tmflo\\t%0\\t\\t#quotient\\n\\tmfhi\\t%3\\t\\t#remainder")
+
+(define_insn "divsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (div:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "div\\t%0,%1,%2")
+
+(define_insn "udivmodsi4"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (udiv:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))
+ (set (match_operand:SI 3 "register_operand" "=r")
+ (umod:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+ "divu\\t$0,%1,%2\\n\\tmflo\\t%0\\t\\t#quotient\\n\\tmfhi\\t%3\\t\\t#remainder")
+
+(define_insn "udivsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (udiv:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "divu\\t%0,%1,%2")
+
+
+;; Remainder instructions
+
+
+(define_insn "modsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (mod:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "rem\\t%0,%1,%2")
+
+(define_insn "umodsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (umod:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "remu\\t%0,%1,%2")
+
+
+;; Absoluate value instructions -- Don't use the integer abs,
+;; since that signals an exception on -2147483648 (sigh).
+
+(define_insn "abssf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (abs:SF (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "abs.s\\t%0,%1")
+
+(define_insn "absdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (abs:DF (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "abs.d\\t%0,%1")
+
+;;
+;; ....................
+;;
+;; LOGICAL
+;;
+;; ....................
+;;
+
+(define_insn "anddi3"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (and:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "register_operand" "r")))]
+ ""
+ "and\\t%0,%1,%2\;and\\t%D0,%D1,%D2")
+
+(define_insn "andsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (and:SI (match_operand:SI 1 "uns_arith_operand" "%r")
+ (match_operand:SI 2 "uns_arith_operand" "rK")))]
+ ""
+ "*
+{
+ return (GET_CODE (operands[2]) == CONST_INT)
+ ? \"andi\\t%0,%1,%x2\"
+ : \"and\\t%0,%1,%2\";
+}")
+
+
+;; Simple hack to recognize the "nor" instruction on the MIPS
+;; [rms: I don't think the following is actually required.]
+;; This must appear before the normal or patterns, so that the
+;; combiner will correctly fold things.
+
+(define_insn ""
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (not:DI (ior:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "register_operand" "r"))))]
+ ""
+ "nor\\t%0,%1,%2\;nor\\t%D0,%D1,%D2")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (not:SI (ior:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r"))))]
+ ""
+ "nor\\t%0,%1,%2")
+
+(define_insn "iordi3"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (ior:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "register_operand" "r")))]
+ ""
+ "or\\t%0,%1,%2\;or\\t%D0,%D1,%D2")
+
+(define_insn "iorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ior:SI (match_operand:SI 1 "uns_arith_operand" "%r")
+ (match_operand:SI 2 "uns_arith_operand" "rJ")))]
+ ""
+ "*
+{
+ return (GET_CODE (operands[2]) == CONST_INT)
+ ? \"ori\\t%0,%1,%x2\"
+ : \"or\\t%0,%1,%2\";
+}")
+
+(define_insn "xordi3"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (xor:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "register_operand" "r")))]
+ ""
+ "xor\\t%0,%1,%2\;xor\\t%D0,%D1,%D2")
+
+(define_insn "xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (xor:SI (match_operand:SI 1 "uns_arith_operand" "%r")
+ (match_operand:SI 2 "uns_arith_operand" "rK")))]
+ ""
+ "*
+{
+ return (GET_CODE (operands[2]) == CONST_INT)
+ ? \"xori\\t%0,%1,%x2\"
+ : \"xor\\t%0,%1,%2\";
+}")
+
+;;
+;; ....................
+;;
+;; TRUNCATION
+;;
+;; ....................
+
+;; 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" "=r")
+ (truncate:QI (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "andi\\t%0,%1,0xff\\t#truncsiqi2\\t %1 -> %0")
+
+(define_insn "truncsihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (truncate:HI (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "*
+ output_asm_insn (\"sll\\t%0,%1,0x10\\t#truncsihi2\\t %1 -> %0\",
+ operands);
+ return \"sra\\t%0,%0,0x10\\t#truncsihi2\\t %1 -> %0\";
+")
+
+(define_insn "trunchiqi2"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (truncate:QI (match_operand:HI 1 "register_operand" "r")))]
+ ""
+ "andi\\t%0,%1,0xff\\t#trunchiqi2\\t %1 -> %0")
+
+(define_insn "truncdfsf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "cvt.s.d\\t%0,%1\\t#truncdfsf2\\t %1 -> %0")
+
+;;
+;; ....................
+;;
+;; ZERO EXTENSION
+;;
+;; ....................
+
+;; Extension insns.
+;; Those for integer source operand
+;; are ordered widest source type first.
+
+
+
+(define_insn "zero_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extend:SI (match_operand:HI 1 "general_operand" "r,m")))]
+ ""
+ "*
+{
+ if (which_alternative == 0)
+ {
+ output_asm_insn (\"sll\\t%0,%1,0x10\\t#zero_extendhisi2\\t %1 -> %0\",
+ operands);
+ return \"srl\\t%0,%0,0x10\\t#zero_extendhisi2\\t %1 -> %0\";
+ }
+ else
+ return \"lhu\\t%0,%1\\t#zero extendhisi2 %1 -> %0\";
+}")
+
+(define_insn "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (zero_extend:HI (match_operand:QI 1 "register_operand" "r")))]
+ ""
+ "*
+ output_asm_insn (\"sll\\t%0,%1,0x18\\t#zero_extendqihi2\\t %1 -> %0\",
+ operands);
+ return \"srl\\t%0,%0,0x18\\t#zero_extendqihi2\\t %1 -> %0\";
+ ")
+
+
+(define_insn "zero_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (zero_extend:SI (match_operand:QI 1 "general_operand" "r,m")))]
+ ""
+ "*
+{
+ if (which_alternative == 0)
+ {
+ return \"andi\\t%0,%1,0xff\\t#zero_extendqisi2\\t %1 -> %0\";
+ }
+ else
+ return \"lbu\\t%0,%1\\t#zero extendqisi2 %1 -> %0\";
+}")
+
+
+;;
+;; ....................
+;;
+;; SIGN EXTENSION
+;;
+;; ....................
+
+;; Extension insns.
+;; Those for integer source operand
+;; are ordered widest source type first.
+
+
+
+(define_insn "extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (sign_extend:SI (match_operand:HI 1 "general_operand" "r,m")))]
+ ""
+ "*
+{
+ if (which_alternative == 0)
+ {
+ output_asm_insn (\"sll\\t%0,%1,0x10\\t#sign extendhisi2\\t %1 -> %0\",
+ operands);
+ return \"sra\\t%0,%0,0x10\\t#sign extendhisi2\\t %1 -> %0\";
+ }
+ else
+ return \"lh\\t%0,%1\\t#sign extendhisi2 %1 -> %0\";
+}")
+
+(define_insn "extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (sign_extend:HI (match_operand:QI 1 "register_operand" "r")))]
+ ""
+ "*
+ output_asm_insn (\"sll\\t%0,%1,0x18\\t#sign extendqihi2\\t %1 -> %0\",
+ operands);
+ return \"sra\\t%0,%0,0x18\\t#sign extendqihi2\\t %1 -> %0\";
+ ")
+
+
+(define_insn "extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (sign_extend:SI (match_operand:QI 1 "general_operand" "r,m")))]
+ ""
+ "*
+{
+ if (which_alternative == 0)
+ {
+ output_asm_insn (\"sll\\t%0,%1,0x18\\t#sign extendqisi2\\t %1 -> %0\",
+ operands);
+ return \"sra\\t%0,%0,0x18\\t#sign extendqisi2\\t %1 -> %0\";
+ }
+ else
+ return \"lb\\t%0,%1\\t#sign extendqisi2 %1 -> %0\";
+}")
+
+
+(define_insn "extendsfdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float_extend:DF (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "cvt.d.s\\t%0,%1\\t#extendsfdf2\\t %1 -> %0")
+
+
+;;
+;; ....................
+;;
+;; CONVERSIONS
+;;
+;; ....................
+
+
+(define_insn "fix_truncdfsi2_internal"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (fix:DF (match_operand:DF 1 "register_operand" "f")))
+ (clobber (match_operand:SI 2 "register_operand" "r"))]
+ ""
+ "trunc.w.d %0,%1,%2")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))]
+ ""
+ "mfc1\\t%0,%1")
+
+(define_expand "fix_truncdfsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))]
+ ""
+ "
+{
+ rtx reg1 = gen_reg_rtx (DFmode); /* fp reg that gets trunc result */
+ rtx reg2 = gen_reg_rtx (SImode); /* gp reg that saves FP status bits */
+ emit_insn (gen_fix_truncdfsi2_internal (reg1, operands[1], reg2));
+ operands[1] = reg1;
+ /* Fall through and generate default code */
+}")
+
+(define_insn "fix_truncsfsi2_internal"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (fix:SF (match_operand:SF 1 "register_operand" "f")))
+ (clobber (match_operand:SI 2 "register_operand" "r"))]
+ ""
+ "trunc.w.s %0,%1,%2")
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
+ ""
+ "mfc1\\t%0,%1")
+
+(define_expand "fix_truncsfsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))]
+ ""
+ "
+{
+ rtx reg1 = gen_reg_rtx (SFmode); /* fp reg that gets trunc result */
+ rtx reg2 = gen_reg_rtx (SImode); /* gp reg that saves FP status bits */
+ emit_insn (gen_fix_truncsfsi2_internal (reg1, operands[1], reg2));
+ operands[1] = reg1;
+ /* Fall through and generate default code */
+}")
+
+(define_insn "floatsidf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float:DF (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "mtc1\\t%1,%0\\t\\t#floatsidf2\\t%1 -> %0\;cvt.d.w\\t%0,%0")
+
+
+(define_insn "floatsisf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float:SF (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "mtc1\\t%1,%0\\t\\t#floatsisf2\\t%1 -> %0\;cvt.s.w\\t%0,%0")
+
+(define_expand "fixuns_truncdfsi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (unsigned_fix:SI (match_operand:DF 1 "register_operand" "")))]
+ ""
+ "
+{
+ rtx reg1 = gen_reg_rtx (DFmode);
+ rtx reg2 = gen_reg_rtx (DFmode);
+ rtx reg3 = gen_reg_rtx (SImode);
+ rtx label1 = gen_label_rtx ();
+ rtx label2 = gen_label_rtx ();
+ REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 31);
+
+ if (reg1) /* turn off complaints about unreached code */
+ {
+ emit_move_insn (reg1, immed_real_const_1 (offset, DFmode));
+ do_pending_stack_adjust ();
+ emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx,
+ gen_rtx (COMPARE, DFmode, operands[1], reg1)));
+
+ emit_jump_insn (gen_bge (label1));
+
+ emit_insn (gen_fix_truncdfsi2 (operands[0], operands[1]));
+ emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
+ gen_rtx (LABEL_REF, VOIDmode, label2)));
+ emit_barrier ();
+
+ emit_label (label1);
+ emit_move_insn (reg2, gen_rtx (MINUS, DFmode, operands[1], reg1));
+ emit_move_insn (reg3, gen_rtx (CONST_INT, VOIDmode, 0x80000000));
+
+ emit_insn (gen_fix_truncdfsi2 (operands[0], reg2));
+ emit_insn (gen_iorsi3 (operands[0], operands[0], reg3));
+
+ emit_label (label2);
+
+ /* allow REG_NOTES to be set on last insn (labels don't have enough
+ fields, and can't be used for REG_NOTES anyway). */
+ emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
+ DONE;
+ }
+}")
+
+(define_expand "fixuns_truncsfsi2"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (unsigned_fix:SI (match_operand:SF 1 "register_operand" "")))]
+ ""
+ "
+{
+ rtx reg1 = gen_reg_rtx (SFmode);
+ rtx reg2 = gen_reg_rtx (SFmode);
+ rtx reg3 = gen_reg_rtx (SImode);
+ rtx label1 = gen_label_rtx ();
+ rtx label2 = gen_label_rtx ();
+ REAL_VALUE_TYPE offset = REAL_VALUE_LDEXP (1.0, 31);
+
+ if (reg1) /* turn off complaints about unreached code */
+ {
+ emit_move_insn (reg1, immed_real_const_1 (offset, SFmode));
+ do_pending_stack_adjust ();
+ emit_insn (gen_rtx (SET, VOIDmode, cc0_rtx,
+ gen_rtx (COMPARE, SFmode, operands[1], reg1)));
+
+ emit_jump_insn (gen_bge (label1));
+
+ emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1]));
+ emit_jump_insn (gen_rtx (SET, VOIDmode, pc_rtx,
+ gen_rtx (LABEL_REF, VOIDmode, label2)));
+ emit_barrier ();
+
+ emit_label (label1);
+ emit_move_insn (reg2, gen_rtx (MINUS, SFmode, operands[1], reg1));
+ emit_move_insn (reg3, gen_rtx (CONST_INT, VOIDmode, 0x80000000));
+
+ emit_insn (gen_fix_truncsfsi2 (operands[0], reg2));
+ emit_insn (gen_iorsi3 (operands[0], operands[0], reg3));
+
+ emit_label (label2);
+
+ /* allow REG_NOTES to be set on last insn (labels don't have enough
+ fields, and can't be used for REG_NOTES anyway). */
+ emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
+ DONE;
+ }
+}")
+
+ ;;- Wild things used when
+ ;;- unions make double and int
+ ;;- overlap.
+ ;;-
+ ;;- This must be supported
+ ;;- since corresponding code
+ ;;- gets generated
+
+(define_insn ""
+ [(set (subreg:DF (match_operand:DI 0 "register_operand" "=ry") 0)
+ (match_operand:DF 1 "register_operand" "rf"))
+ (clobber (match_operand 2 "register_operand" "rf"))]
+ ""
+ "mfc1\\t%0,%L1\;mfc1\\t%D0,%M1")
+
+(define_insn ""
+ [(set (subreg:DF (match_operand:DI 0 "register_operand" "=ry") 0)
+ (match_operand:DF 1 "register_operand" "rf"))]
+ ""
+ "mfc1\\t%0,%L1\;mfc1\\t%D0,%M1")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=rf")
+ (subreg:DF (match_operand:DI 1 "register_operand" "ry") 0))
+ (clobber (match_operand 2 "register_operand" "rf"))]
+ ""
+ "mfc1\\t%0,%L1\;mfc1\\t%D0,%M1")
+
+(define_insn ""
+ [(set (match_operand:DF 0 "register_operand" "=rf")
+ (subreg:DF (match_operand:DI 1 "register_operand" "ry") 0))]
+ ""
+ "mfc1\\t%0,%L1\;mfc1\\t%D0,%M1")
+
+;;
+;; ....................
+;;
+;; MOVES
+;;
+;; and
+;;
+;; LOADS AND STORES
+;;
+;; ....................
+
+(define_insn "movdi"
+ [(set (match_operand:DI 0 "general_operand" "=r,*r,*m")
+ (match_operand:DI 1 "general_operand" "r,*miF,*r"))]
+ ""
+ "*
+{
+ extern rtx adj_offsettable_operand ();
+ extern int offsettable_address_p ();
+
+ if (which_alternative == 0)
+ {
+ /* Move REGISTER <- REGISTER */
+ if (REGNO (operands[0]) != (REGNO (operands[1])+1))
+ return \"move\\t%0,%1\\n\\tmove\\t%D0,%D1\";
+ else
+ return \"move\\t%D0,%D1\\n\\tmove\\t%0,%1\";
+ }
+
+ else if (which_alternative == 1)
+ {
+ if (GET_CODE (operands[1]) == MEM)
+ {
+ /* REGISTER <- MEMORY */
+ if (offsettable_address_p (1, DImode, XEXP (operands[1], 0)))
+ {
+ operands[2] = adj_offsettable_operand (operands[1], 4);
+ return \"lw\\t%0,%1\;lw\\t%D0,%2\";
+ }
+
+ else
+ {
+ operands[2] = gen_rtx (REG, Pmode, 1);
+ return \".set\\tnoat\;la\\t%2,%1\;lw\\t%0,0(%2)\;lw\\t%D0,4(%2)\;set\\tat\";
+ }
+ }
+
+ /* REGISTER <- small integer constant */
+ else if (CONSTANT_P (operands[1]))
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) >= 0 ? 0 : -1);
+ return \"li\\t%M0,%2\;li\\t%L0,%1\";
+ }
+
+ /* Register <- large integer constant */
+ else if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (operands[1]));
+ operands[3] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (operands[1]));
+ return \"li\\t%M0,%3\;li\\t%L0,%2\";
+ }
+ }
+
+ else if (which_alternative == 2 && GET_CODE (operands[0]) == MEM)
+ {
+ /* Memory <- Register */
+ if (offsettable_address_p (1, DImode, XEXP (operands[0], 0)))
+ {
+ operands[2] = adj_offsettable_operand (operands[0], 4);
+ return \"sw\\t%1,%0\;sw\\t%D1,%2\";
+ }
+
+ else
+ {
+ operands[2] = gen_rtx (REG, Pmode, 1);
+ return \".set\\tnoat\;la\\t%2,%0\;sw\\t%1,0(%2)\;sw\\t%D1,4(%2)\;set\\tat\";
+ }
+ }
+
+ abort_with_insn (insn, \"impossible case in movdi\");
+ return \"\";
+}")
+
+(define_insn "movsi"
+ [(set (match_operand:SI 0 "general_operand" "=r,r,m,r,r,m,*r")
+ (match_operand:SI 1 "general_operand" "r,m,r,i,J,J,*p"))]
+ ""
+ "*
+{
+ enum rtx_code code0 = GET_CODE (operands[0]);
+ enum rtx_code code1 = GET_CODE (operands[1]);
+
+ if (code0 == REG && code1 == REG)
+ return \"move\\t%0,%1\";
+
+ else if (code0 == REG && code1 == MEM)
+ return \"lw\\t%0,%1\";
+
+ else if (code0 == MEM && code1 == REG)
+ return \"sw\\t%1,%0\";
+
+ else if (code0 == REG && code1 == CONST_INT)
+ return \"li\\t%0,%1\";
+
+ else if (code0 == MEM && code1 == CONST_INT && INTVAL (operands[1]) == 0)
+ return \"sw\\t$0,%0\";
+
+ else if (code0 == REG && CONSTANT_P (operands[1]))
+ return \"la\\t%0,%a1\";
+
+ else if (code0 == REG && code1 == PLUS
+ && GET_CODE (XEXP (operands[1], 0)) == REG
+ && GET_CODE (XEXP (operands[1], 1)) == CONST_INT)
+ {
+ operands[2] = XEXP (operands[1], 0);
+ operands[3] = XEXP (operands[1], 1);
+ return \"add%:\\t%0,%2,%3\";
+ }
+
+ abort_with_insn (insn, \"Bad movsi\");
+ return 0;
+}")
+
+(define_insn "movhi"
+ [(set (match_operand:HI 0 "general_operand" "=r,r,m,r,r,m")
+ (match_operand:HI 1 "general_operand" "r,m,r,i,J,J"))]
+ ""
+ "*
+{
+ enum rtx_code code0 = GET_CODE (operands[0]);
+ enum rtx_code code1 = GET_CODE (operands[1]);
+
+ if (code0 == REG && code1 == REG)
+ return \"move\\t%0,%1\";
+
+ else if (code0 == REG && code1 == MEM)
+ return \"lh\\t%0,%1\";
+
+ else if (code0 == MEM && code1 == REG)
+ return \"sh\\t%1,%0\";
+
+ else if (code0 == REG && code1 == CONST_INT)
+ return \"li\\t%0,%1\";
+
+ else if (code0 == MEM && code1 == CONST_INT && INTVAL (operands[1]) == 0)
+ return \"sh\\t$0,%0\";
+
+ else if (code0 == REG && CONSTANT_P (operands[1]))
+ return \"la\\t%0,%a1\";
+
+ else if (code0 == REG && code1 == PLUS
+ && GET_CODE (XEXP (operands[1], 0)) == REG
+ && GET_CODE (XEXP (operands[1], 1)) == CONST_INT)
+ {
+ operands[2] = XEXP (operands[1], 0);
+ operands[3] = XEXP (operands[1], 1);
+ return \"add%:\\t%0,%2,%3\";
+ }
+
+ abort_with_insn (insn, \"Bad movhi\");
+ return 0;
+}")
+
+(define_insn "movqi"
+ [(set (match_operand:QI 0 "general_operand" "=r,r,m,r,r,m")
+ (match_operand:QI 1 "general_operand" "r,m,r,i,J,J"))]
+ ""
+ "*
+{
+ enum rtx_code code0 = GET_CODE (operands[0]);
+ enum rtx_code code1 = GET_CODE (operands[1]);
+
+ if (code0 == REG && code1 == REG)
+ return \"move\\t%0,%1\";
+
+ else if (code0 == REG && code1 == MEM)
+ return \"lb\\t%0,%1\";
+
+ else if (code0 == MEM && code1 == REG)
+ return \"sb\\t%1,%0\";
+
+ else if (code0 == REG && code1 == CONST_INT)
+ return \"li\\t%0,%1\";
+
+ else if (code0 == MEM && code1 == CONST_INT && INTVAL (operands[1]) == 0)
+ return \"sb\\t$0,%0\";
+
+ else if (code0 == REG && CONSTANT_P (operands[1]))
+ return \"la\\t%0,%a1\";
+
+ else if (code0 == REG && code1 == PLUS
+ && GET_CODE (XEXP (operands[1], 0)) == REG
+ && GET_CODE (XEXP (operands[1], 1)) == CONST_INT)
+ {
+ operands[2] = XEXP (operands[1], 0);
+ operands[3] = XEXP (operands[1], 1);
+ return \"add%:\\t%0,%2,%3\";
+ }
+
+ abort_with_insn (insn, \"Bad movqi\");
+ return 0;
+}")
+
+(define_insn "movsf"
+ [(set (match_operand:SF 0 "general_operand" "=f,f,m,fy,*f,*y,*y,*m")
+ (match_operand:SF 1 "general_operand" "f,m,f,F,*y,*f,*m,*y"))]
+ ""
+ "*
+{
+ enum rtx_code code0 = GET_CODE (operands[0]);
+ enum rtx_code code1 = GET_CODE (operands[1]);
+
+ if (code0 == REG)
+ {
+ if (code1 == REG)
+ {
+ if (FP_REG_P (REGNO (operands[0])))
+ {
+ if (FP_REG_P (REGNO (operands[1])))
+ return \"mov.s\\t%0,%1\";
+ else
+ return \"mtc1\\t%1,%0\\t\\t# Calling sequence trick\";
+ }
+
+ else if (FP_REG_P (REGNO (operands[1])))
+ return \"mfc1\\t%0,%1\\t\\t# Calling sequence trick\";
+
+ else
+ return \"move\\t%0,%1\";
+ }
+
+ else if (code1 == CONST_DOUBLE)
+ return \"li.s\\t%0,%1\";
+
+ else if (code1 == MEM)
+ return (GP_REG_P (REGNO (operands[0]))) ? \"lw\\t%0,%1\" : \"l.s\\t%0,%1\";
+ }
+
+ else if (code0 == MEM && code1 == REG)
+ return (GP_REG_P (REGNO (operands[1]))) ? \"sw\\t%1,%0\" : \"s.s\\t%1,%0\";
+
+ abort_with_insn (insn, \"Bad movsf\");
+ return \"\";
+}")
+
+
+(define_insn "movdf"
+ [(set (match_operand:DF 0 "general_operand" "=f,f,m,fy,*f,*y,&*y,*m")
+ (match_operand:DF 1 "general_operand" "f,m,f,F,*y,*f,*m,*y"))]
+ ""
+ "*
+{
+ extern rtx adj_offsettable_operand ();
+ extern int offsettable_address_p ();
+
+ enum rtx_code code0 = GET_CODE (operands[0]);
+ enum rtx_code code1 = GET_CODE (operands[1]);
+
+ if (code0 == REG)
+ {
+ if (code1 == REG)
+ {
+ if (FP_REG_P (REGNO (operands[0])))
+ {
+ if (FP_REG_P (REGNO (operands[1])))
+ return \"mov.d\\t%0,%1\";
+ else
+ return \"mtc1\\t%L1,%0\\t\\t# Calling sequence trick\;mtc1\\t%M1,%D0\";
+ }
+
+ else if (FP_REG_P (REGNO (operands[1])))
+ return \"mfc1\\t%L0,%1\\t\\t# Calling sequence trick\;mfc1\\t%M0,%D1\";
+
+ else if (REGNO (operands[0]) != (REGNO (operands[1])+1))
+ return \"move\\t%0,%1\\n\\tmove\\t%D0,%D1\";
+
+ else
+ return \"move\\t%D0,%D1\\n\\tmove\\t%0,%1\";
+ }
+
+ else if (code1 == CONST_DOUBLE)
+ return \"li.d\\t%0,%1\";
+
+ else if (code1 == MEM)
+ {
+ if (FP_REG_P (REGNO (operands[0])))
+ return \"l.d\\t%0,%1\";
+
+ else if (offsettable_address_p (1, DFmode, XEXP (operands[1], 0)))
+ {
+ operands[2] = adj_offsettable_operand (operands[1], 4);
+ if (reg_mentioned_p (operands[0], operands[1]))
+ return \"lw\\t%D0,%2\;lw\\t%0,%1\";
+ else
+ return \"lw\\t%0,%1\;lw\\t%D0,%2\";
+ }
+
+ else
+ {
+ operands[2] = gen_rtx (REG, Pmode, 1);
+ return \".set\\tnoat\;la\\t%2,%1\;lw\\t%0,0(%2)\;lw\\t%D0,4(%2)\;set\\tat\";
+ }
+ }
+ }
+
+ else if (code0 == MEM && code1 == REG)
+ {
+ if (FP_REG_P (REGNO (operands[1])))
+ return \"s.d\\t%1,%0\";
+
+ else if (offsettable_address_p (1, DFmode, XEXP (operands[0], 0)))
+ {
+ operands[2] = adj_offsettable_operand (operands[0], 4);
+ return \"sw\\t%1,%0\;sw\\t%D1,%2\";
+ }
+
+ else
+ {
+ operands[2] = gen_rtx (REG, Pmode, 1);
+ return \".set\\tnoat\;la\\t%2,%0\;sw\\t%1,0(%2)\;sw\\t%D1,4(%2)\;set\\tat\";
+ }
+ }
+
+ abort_with_insn (insn, \"Bad movdf\");
+ return \"\";
+}")
+
+
+;;
+;; ....................
+;;
+;; OTHER ARITHMETIC AND SHIFT
+;;
+;; ....................
+
+(define_insn "ashlsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashift:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, (XINT (operands[2], 0))& 0x1f);
+
+ return \"sll\\t%0,%1,%2\";
+}")
+
+(define_insn "ashrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, (XINT (operands[2], 0))& 0x1f);
+
+ return \"sra\\t%0,%1,%2\";
+}")
+
+(define_insn "lshrsi3"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "arith_operand" "rI")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ operands[2] = gen_rtx (CONST_INT, VOIDmode, (XINT (operands[2], 0))& 0x1f);
+
+ return \"srl\\t%0,%1,%2\";
+}")
+
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (neg:SI (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "sub%:\\t%0,$0,%1")
+
+(define_insn "negdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (neg:DF (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "neg.d\\t%0,%1")
+
+(define_insn "negsf2"
+
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (neg:SF (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "neg.s\\t%0,%1")
+
+
+(define_insn "one_cmplsi2"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (not:SI (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "nor\\t%0,$0,%1")
+
+;;
+;; ....................
+;;
+;; COMPARISONS
+;;
+;; ....................
+
+ ;;- Order is significant here
+ ;;- because there are untyped
+ ;;- comparisons generated by
+ ;;- the optimizer
+ ;;- (set (cc0)
+ ;;- (compare (const_int 2)
+ ;;- (const_int 1)))
+
+(define_insn "cmpsi"
+ [(set (cc0)
+ (compare (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "arith_operand" "rI")))]
+ ""
+ "*
+ compare_collect (SImode, operands[0], operands[1]);
+ return \"\\t\\t\\t\\t# cmpsi\\t%0,%1\";
+")
+
+
+(define_insn ""
+ [(set (cc0)
+ (match_operand:SI 0 "register_operand" "r"))]
+ ""
+ "*
+ compare_collect (SImode, operands[0], gen_rtx (REG, SImode, 0));
+ return \"\\t\\t\\t\\t# (set (cc0)\\t%0)\";
+")
+
+;; These patterns are hopelessly invalid, because
+;; comparing subword values properly requires extending them.
+
+;; (define_insn "cmphi"
+;; [(set (cc0)
+;; (compare (match_operand:HI 0 "register_operand" "r")
+;; (match_operand:HI 1 "register_operand" "r")))]
+;; ""
+;; "*
+;; compare_collect (HImode, operands[0], operands[1]);
+;; return \" #\\tcmphi\\t%0,%1\";
+;; ")
+;;
+;; (define_insn "cmpqi"
+;; [(set (cc0)
+;; (compare (match_operand:QI 0 "register_operand" "r")
+;; (match_operand:QI 1 "register_operand" "r")))]
+;; ""
+;; "*
+;; compare_collect (QImode, operands[0], operands[1]);
+;; return \" #\\tcmpqi\\t%0,%1\";
+;; ")
+;;
+;; (define_insn ""
+;; [(set (cc0)
+;; (match_operand:QI 0 "register_operand" "r"))]
+;; ""
+;; "*
+;; compare_collect (QImode, operands[0], gen_rtx (REG, QImode, 0));
+;; return \" #\\t (set (cc0)\\t%0)\";
+;; ")
+;;
+;; (define_insn ""
+;; [(set (cc0)
+;; (match_operand:HI 0 "register_operand" "r"))]
+;; ""
+;; "*
+;; compare_collect (HImode, operands[0], gen_rtx (REG, HImode, 0));
+;; return \" #\\t (set (cc0)\\t%0)\";
+;; ")
+
+(define_insn "cmpdf"
+ [(set (cc0)
+ (compare (match_operand:DF 0 "register_operand" "f")
+ (match_operand:DF 1 "register_operand" "f")))]
+ ""
+ "*
+ compare_collect (DFmode, operands[0], operands[1]);
+ return \" #\\t\\t\\t\\tcmpdf\\t%0,%1\" ;
+")
+
+(define_insn "cmpsf"
+ [(set (cc0)
+ (compare (match_operand:SF 0 "register_operand" "f")
+ (match_operand:SF 1 "register_operand" "f")))]
+ ""
+ "*
+ compare_collect (SFmode, operands[0], operands[1]);
+ return \"\\t\\t\\t\\t# cmpsf\\t%0,%1\" ;
+")
+
+;;
+;; ....................
+;;
+;; BRANCHES
+;;
+;; ....................
+
+(define_insn "jump"
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ ""
+ "*
+{
+ if (GET_CODE (operands[0]) == REG)
+ return \"j\\t%0\";
+ else
+ return \"j\\t%l0\";
+}")
+
+
+(define_insn "tablejump"
+ [(set (pc)
+ (match_operand:SI 0 "register_operand" "r"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "j\\t%0")
+
+
+(define_insn "beq"
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.eq.d\\t%0,%1\\t\\t# beq\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# beq\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.eq.s\\t%0,%1\\t\\t# beq\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# beq\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"beq\\t%0,%1,%2\\t\\t# beq\", br_ops);
+ }
+ return \"\";
+}
+ ")
+
+(define_insn "bne"
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.eq.d\\t%0,%1\\t\\t# bne\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bne\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.eq.s\\t%0,%1\\t\\t# bne\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bne\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bne\\t%0,%1,%2\\t\\t# bne\", br_ops);
+ }
+ return \"\";
+}
+
+")
+
+(define_insn "bgt"
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.le.d\\t%0,%1\\t\\t# bgt branch %0 > %1\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bgt\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.le.s\\t%0,%1\\t\\t# bgt branch %0 > %1\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bgt\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bgt\\t%0,%1,%2\\t\\t# bgt\", br_ops);
+ }
+ return \"\";
+}
+
+")
+
+(define_insn "blt"
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.lt.d\\t%0,%1\\t\\t# blt\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# blt\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.lt.s\\t%0,%1\\t\\t# blt\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# blt\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"blt\\t%0,%1,%2\\t\\t# blt\", br_ops);
+ }
+ return \" #\\tblt\\t%l0\\t\\t# blt\";
+}
+")
+
+(define_insn "bgtu"
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.le.d\\t%0,%1\\t\\t# bgtu\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bgtu\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.le.s\\t%0,%1\\t\\t# bgtu\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bgtu\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bgtu\\t%0,%1,%2\\t\\t# bgtu\", br_ops);
+ }
+ return \" #\\tbgtu\\t%l0\\t\\t# bgtu\";
+}
+")
+
+(define_insn "bltu"
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.lt.d\\t%0,%1\\t\\t# bltu\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# bltu\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.lt.s\\t%0,%1\\t\\t# bltu\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# bltu\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bltu\\t%0,%1,%2\\t\\t# bltu\", br_ops);
+ }
+ return \"\";
+}
+")
+
+(define_insn "bge"
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.lt.d\\t%0,%1\\t\\t# bge\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bge\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.lt.s\\t%0,%1\\t\\t# bge\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bge\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bge\\t%0,%1,%2\\t\\t# bge\", br_ops);
+ }
+ return \"\";
+}
+")
+
+(define_insn "bgeu"
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.lt.d\\t%0,%1\\t\\t# bgeu\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bgeu\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.lt.s\\t%0,%1\\t\\t# bgeu\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bgeu\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bgeu\\t%0,%1,%2\\t\\t# bgeu\", br_ops);
+ }
+ return \"\";
+}
+")
+
+(define_insn "ble"
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.le.d\\t%0,%1\\t\\t# ble\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# ble\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.le.s\\t%0,%1\\t\\t# ble\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# ble\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"ble\\t%0,%1,%2\\t\\t# ble\", br_ops);
+ }
+ return \"\";
+}
+")
+
+(define_insn "bleu"
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.le.d\\t%0,%1\\t\\t# ble\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# ble\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.le.s\\t%0,%1\\t\\t# ble\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# ble\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bleu\\t%0,%1,%2\\t\\t# bleu\", br_ops);
+ }
+ return \" #\\tbleu\\t%l0\\t\\t# bleu\";
+}
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ne (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.eq.d\\t%0,%1\\t\\t# beq\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# beq\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.eq.s\\t%0,%1\\t\\t# beq\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# beq\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"beq\\t%0,%1,%2\\t\\t# beq Inv.\", br_ops);
+ }
+ return \"\";
+}
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (eq (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.eq.d\\t%0,%1\\t\\t# bne\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bne\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.eq.s\\t%0,%1\\t\\t# bne\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# beq\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bne\\t%0,%1,%2\\t\\t# bne Inv.\", br_ops);
+ }
+ return \"\";
+}
+
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (le (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.le.d\\t%0,%1\\t\\t# bgt\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# beq\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.le.s\\t%0,%1\\t\\t# bgt\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# beq\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bgt\\t%0,%1,%2\\t\\t# bgt Inv.\", br_ops);
+ }
+ return \"\";
+}
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (leu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.le.d\\t%0,%1\\t\\t# bgt\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# beq\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.le.s\\t%0,%1\\t\\t# bgt\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# beq\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bgtu\\t%0,%1,%2\\t\\t# bgtu Inv.\", br_ops);
+ }
+ return \" #\\tbgtu\\t%l0\\t\\t# bgtu\";
+}
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ge (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.lt.d\\t%0,%1\\t\\t# blt\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# beq\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.lt.s\\t%0,%1\\t\\t# blt\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# beq\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"blt\\t%0,%1,%2\\t\\t# blt Inv.\", br_ops);
+ }
+ return \"\";
+}
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (geu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.lt.d\\t%0,%1\\t\\t# bltu\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# bltu\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.lt.s\\t%0,%1\\t\\t# bltu\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# bltu\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bltu\\t%0,%1,%2\\t\\t# bltu Inv.\", br_ops);
+ }
+ return \" #\\tbltu\\t%l0\\t\\t# bltu\";
+}
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (lt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.lt.d\\t%0,%1\\t\\t# bge\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bge (DF) Inv.\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.lt.s\\t%0,%1\\t\\t# bge\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bge (SF) Inv.\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bge\\t%0,%1,%2\\t\\t# bge Inv.\", br_ops);
+ }
+ return \"\";
+}
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (ltu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.lt.d\\t%0,%1\\t\\t# bge\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bgeu (DF) Inv.\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.lt.s\\t%0,%1\\t\\t# bge\", br_ops);
+ output_asm_insn (\"bc1f\\t%2\\t\\t# bgeu (SF )Inv.\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bgeu\\t%0,%1,%2\\t\\t# bgeu Inv.\", br_ops);
+ }
+ return \" #\\tbgeu\\t%l0\\t\\t# bgeu\";
+}
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gt (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.le.d\\t%0,%1\\t\\t# ble\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# ble\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.le.s\\t%0,%1\\t\\t# ble\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# ble\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"ble\\t%0,%1,%2\\t\\t# ble Inv.\", br_ops);
+ }
+ return \"\";
+}
+")
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else (gtu (cc0)
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ ""
+ "*
+{
+ rtx br_ops[3];
+ enum machine_mode mode;
+ compare_restore (br_ops, &mode, insn);
+ br_ops[2] = operands[0];
+ if (mode == DFmode)
+ {
+ output_asm_insn (\"c.le.d\\t%0,%1\\t\\t# bleu\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# bleu\", br_ops);
+ }
+ else if (mode == SFmode)
+ {
+ output_asm_insn (\"c.le.s\\t%0,%1\\t\\t# bleu\", br_ops);
+ output_asm_insn (\"bc1t\\t%2\\t\\t# bleu\", br_ops);
+ }
+ else
+ {
+ output_asm_insn (\"bleu\\t%0,%1,%2\\t\\t# bleu Inv.\", br_ops);
+ }
+ return \"\";
+}
+")
+
+;;
+;; ....................
+;;
+;; LINKAGE
+;;
+;; ....................
+
+(define_insn "call"
+ [(call (match_operand 0 "memory_operand" "m")
+ (match_operand 1 "" "i"))
+ (clobber (reg:SI 31))]
+ ""
+ "*
+{
+ register rtx target = XEXP (operands[0], 0);
+
+ if (GET_CODE (target) == SYMBOL_REF)
+ return \"jal\\t%0\";
+
+ else
+ {
+ operands[0] = target;
+ return \"jal\\t$31,%0\";
+ }
+}")
+
+
+(define_insn "call_value"
+ [(set (match_operand 0 "" "=rf")
+ (call (match_operand 1 "memory_operand" "m")
+ (match_operand 2 "" "i")))
+ (clobber (reg:SI 31))]
+ ""
+ "*
+{
+ register rtx target = XEXP (operands[1], 0);
+
+ if (GET_CODE (target) == SYMBOL_REF)
+ return \"jal\\t%1\";
+
+ else
+ {
+ operands[1] = target;
+ return \"jal\\t$31,%1\";
+ }
+}")
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ ".set\\tnoreorder\;nop\;.set\\treorder")
+
+(define_insn "probe"
+ [(mem:SI (reg:SI 29))]
+ ""
+ "*
+{
+ operands[0] = gen_rtx (REG, SImode, 1);
+ operands[1] = stack_pointer_rtx;
+ return \".set\\tnoat\;lw\\t%0,0(%1)\\t\\t# stack probe\;.set\\tat\";
+}")
+
+;;
+;;- 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: