entered into RCS
authorCharles Hannum <mycroft@gnu.org>
Wed, 8 Jan 1992 11:11:21 +0000 (11:11 +0000)
committerCharles Hannum <mycroft@gnu.org>
Wed, 8 Jan 1992 11:11:21 +0000 (11:11 +0000)
From-SVN: r172

gcc/config/spur/spur.md [new file with mode: 0644]

diff --git a/gcc/config/spur/spur.md b/gcc/config/spur/spur.md
new file mode 100644 (file)
index 0000000..7b86911
--- /dev/null
@@ -0,0 +1,1115 @@
+;;- Machine description for SPUR chip for GNU C compiler
+;;   Copyright (C) 1988 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:
+\f
+;; Compare instructions.
+;; This pattern is used for generating an "insn"
+;; which does just a compare and sets a (fictitious) condition code.
+
+;; The actual SPUR insns are compare-and-conditional-jump.
+;; The define_peephole's below recognize the combinations of
+;; compares and jumps, and output each pair as a single assembler insn.
+
+;; This controls RTL generation and register allocation.
+(define_insn "cmpsi"
+  [(set (cc0)
+       (compare (match_operand:SI 0 "register_operand" "rK")
+                (match_operand:SI 1 "nonmemory_operand" "rK")))]
+  ""
+  "*
+{
+  cc_status.value1 = operands[0], cc_status.value2 = operands[1];
+  return \"\";
+}")
+
+;; We have to have this because cse can optimize the previous pattern
+;; into this one.
+
+(define_insn "tstsi"
+  [(set (cc0)
+       (match_operand:SI 0 "register_operand" "r"))]
+  ""
+  "*
+{
+  cc_status.value1 = operands[0], cc_status.value2 = const0_rtx;
+  return \"\";
+}")
+
+
+;; These control RTL generation for conditional jump insns
+;; and match them for register allocation.
+
+(define_insn "beq"
+  [(set (pc)
+       (if_then_else (eq (cc0)
+                         (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "* return output_compare (operands, \"eq\", \"eq\", \"ne\", \"ne\"); ")
+
+(define_insn "bne"
+  [(set (pc)
+       (if_then_else (ne (cc0)
+                         (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "* return output_compare (operands, \"ne\", \"ne\", \"eq\", \"eq\"); ")
+
+(define_insn "bgt"
+  [(set (pc)
+       (if_then_else (gt (cc0)
+                         (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "* return output_compare (operands, \"gt\", \"lt\", \"le\", \"ge\"); ")
+
+(define_insn "bgtu"
+  [(set (pc)
+       (if_then_else (gtu (cc0)
+                          (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "* return output_compare (operands, \"ugt\", \"ult\", \"ule\", \"uge\"); ")
+
+(define_insn "blt"
+  [(set (pc)
+       (if_then_else (lt (cc0)
+                         (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "* return output_compare (operands, \"lt\", \"gt\", \"ge\", \"le\"); ")
+
+(define_insn "bltu"
+  [(set (pc)
+       (if_then_else (ltu (cc0)
+                          (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "* return output_compare (operands, \"ult\", \"ugt\", \"uge\", \"ule\"); ")
+
+(define_insn "bge"
+  [(set (pc)
+       (if_then_else (ge (cc0)
+                         (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "* return output_compare (operands, \"ge\", \"le\", \"lt\", \"gt\"); ")
+
+(define_insn "bgeu"
+  [(set (pc)
+       (if_then_else (geu (cc0)
+                          (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "* return output_compare (operands, \"uge\", \"ule\", \"ult\", \"ugt\"); ")
+
+(define_insn "ble"
+  [(set (pc)
+       (if_then_else (le (cc0)
+                         (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "* return output_compare (operands, \"le\", \"ge\", \"gt\", \"lt\"); ")
+
+(define_insn "bleu"
+  [(set (pc)
+       (if_then_else (leu (cc0)
+                          (const_int 0))
+                     (label_ref (match_operand 0 "" ""))
+                     (pc)))]
+  ""
+  "* return output_compare (operands, \"ule\", \"uge\", \"ugt\", \"ult\"); ")
+\f
+;; These match inverted jump insns for register allocation.
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (eq (cc0)
+                         (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "* return output_compare (operands, \"ne\", \"ne\", \"eq\", \"eq\"); ")
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (ne (cc0)
+                         (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "* return output_compare (operands, \"eq\", \"eq\", \"ne\", \"ne\"); ")
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (gt (cc0)
+                         (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "* return output_compare (operands, \"le\", \"ge\", \"gt\", \"lt\"); ")
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (gtu (cc0)
+                          (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "* return output_compare (operands, \"ule\", \"uge\", \"ugt\", \"ult\"); ")
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (lt (cc0)
+                         (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "* return output_compare (operands, \"ge\", \"le\", \"lt\", \"gt\"); ")
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (ltu (cc0)
+                          (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "* return output_compare (operands, \"uge\", \"ule\", \"ult\", \"ugt\"); ")
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (ge (cc0)
+                         (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "* return output_compare (operands, \"lt\", \"gt\", \"ge\", \"le\"); ")
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (geu (cc0)
+                          (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "* return output_compare (operands, \"ult\", \"ugt\", \"uge\", \"ule\"); ")
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (le (cc0)
+                         (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "* return output_compare (operands, \"gt\", \"lt\", \"le\", \"ge\"); ")
+
+(define_insn ""
+  [(set (pc)
+       (if_then_else (leu (cc0)
+                          (const_int 0))
+                     (pc)
+                     (label_ref (match_operand 0 "" ""))))]
+  ""
+  "* return output_compare (operands, \"ugt\", \"ult\", \"ule\", \"uge\"); ")
+\f
+;; Move instructions
+
+(define_insn "movsi"
+  [(set (match_operand:SI 0 "general_operand" "=r,m")
+       (match_operand:SI 1 "general_operand" "rmi,rJ"))]
+  ""
+  "*
+{
+  if (GET_CODE (operands[0]) == MEM)
+    return \"st_32 %r1,%0\";
+  if (GET_CODE (operands[1]) == MEM)
+    return \"ld_32 %0,%1\;nop\";
+  if (GET_CODE (operands[1]) == REG)
+    return \"add_nt %0,%1,$0\";
+  if (GET_CODE (operands[1]) == SYMBOL_REF && operands[1]->unchanging)
+    return \"add_nt %0,r24,$(%1-0b)\";
+  return \"add_nt %0,r0,%1\";
+}")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
+                        (match_operand:SI 2 "register_operand" "r"))))]
+  ""
+  "ld_32 %0,%1,%2\;nop")
+\f
+;; Generate insns for moving single bytes.
+
+(define_expand "movqi"
+  [(set (match_operand:QI 0 "general_operand" "")
+       (match_operand:QI 1 "general_operand" ""))]
+  ""
+  "
+{
+  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+    operands[1] = copy_to_reg (operands[1]);
+
+  if (GET_CODE (operands[1]) == MEM)
+    {
+      rtx tem = gen_reg_rtx (SImode);
+      rtx addr = force_reg (SImode, XEXP (operands[1], 0));
+      rtx subreg;
+
+      emit_move_insn (tem, gen_rtx (MEM, SImode, addr));
+      if (GET_CODE (operands[0]) == SUBREG)
+       subreg = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[0]),
+                         SUBREG_WORD (operands[0]));
+      else
+       subreg = gen_rtx (SUBREG, SImode, operands[0], 0);
+
+      emit_insn (gen_rtx (SET, VOIDmode, subreg,
+                         gen_rtx (ZERO_EXTRACT, SImode, tem,
+                                  gen_rtx (CONST_INT, VOIDmode, 8),
+                                  addr)));
+    }
+  else if (GET_CODE (operands[0]) == MEM)
+    {
+      rtx tem = gen_reg_rtx (SImode);
+      rtx addr = force_reg (SImode, XEXP (operands[0], 0));
+      rtx subreg;
+
+      emit_move_insn (tem, gen_rtx (MEM, SImode, addr));
+      if (! CONSTANT_ADDRESS_P (operands[1]))
+       {
+         if (GET_CODE (operands[1]) == SUBREG)
+           subreg = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]),
+                             SUBREG_WORD (operands[1]));
+         else
+           subreg = gen_rtx (SUBREG, SImode, operands[1], 0);
+       }
+
+      emit_insn (gen_rtx (SET, VOIDmode,
+                         gen_rtx (ZERO_EXTRACT, SImode, tem,
+                                  gen_rtx (CONST_INT, VOIDmode, 8),
+                                  addr),
+                         subreg));
+      emit_move_insn (gen_rtx (MEM, SImode, addr), tem);
+    }
+  else
+    {
+      emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
+    }
+  DONE;
+}")
+\f
+;; Recognize insns generated for moving single bytes.
+
+(define_insn ""
+  [(set (match_operand:QI 0 "general_operand" "=r,m")
+       (match_operand:QI 1 "general_operand" "rmi,r"))]
+  ""
+  "*
+{
+  if (GET_CODE (operands[0]) == MEM)
+    return \"st_32 %1,%0\";
+  if (GET_CODE (operands[1]) == MEM)
+    return \"ld_32 %0,%1\;nop\";
+  if (GET_CODE (operands[1]) == REG)
+    return \"add_nt %0,%1,$0\";
+  return \"add_nt %0,r0,%1\";
+}")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
+                        (const_int 8)
+                        (match_operand:SI 2 "nonmemory_operand" "rI")))]
+  ""
+  "extract %0,%1,%2")
+
+(define_insn ""
+  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
+                        (const_int 8)
+                        (match_operand:SI 1 "nonmemory_operand" "rI"))
+       (match_operand:SI 2 "nonmemory_operand" "ri"))]
+  ""
+  "wr_insert %1\;insert %0,%0,%2")
+
+;; Constant propagation can optimize the previous pattern into this pattern.
+;[Not any more.  It could when the position-operand contains a MULT.]
+
+;(define_insn ""
+;  [(set (zero_extract:QI (match_operand:SI 0 "register_operand" "+r")
+;                       (const_int 8)
+;                       (match_operand:SI 1 "immediate_operand" "I"))
+;      (match_operand:QI 2 "register_operand" "r"))]
+;  "GET_CODE (operands[1]) == CONST_INT
+;   && INTVAL (operands[1]) % 8 == 0
+;   && (unsigned) INTVAL (operands[1]) < 32"
+;  "*
+;{
+;  operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) / 8);
+;  return \"wr_insert 0,0,%1\;insert %0,%0,%2\";
+;}")
+\f
+;; The three define_expand patterns on this page
+;; serve as subroutines of "movhi".
+
+;; Generate code to fetch an aligned halfword from memory.
+;; Operand 0 is the destination register (HImode).
+;; Operand 1 is the memory address (SImode).
+;; Operand 2 is a temporary (SImode).
+;; Operand 3 is a temporary (SImode).
+;; Operand 4 is a temporary (QImode).
+
+;; Operand 5 is an internal temporary (HImode).
+
+(define_expand "loadhi"
+  [(set (match_operand:SI 2 "register_operand" "")
+       (mem:SI (match_operand:SI 1 "register_operand" "")))
+   ;; Extract the low byte.
+   (set (subreg:SI (match_dup 5) 0)
+       (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 1)))
+   ;; Form address of high byte.
+   (set (match_operand:SI 3 "register_operand" "")
+       (plus:SI (match_dup 1) (const_int 1)))
+   ;; Extract the high byte.
+   (set (subreg:SI (match_operand:QI 4 "register_operand" "") 0)
+       (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 3)))
+   ;; Put the high byte in with the low one.
+   (set (zero_extract:SI (match_dup 5) (const_int 8) (const_int 1))
+       (subreg:SI (match_dup 4) 0))
+   (set (match_operand:HI 0 "register_operand" "") (match_dup 5))]
+  ""
+  "operands[5] = gen_reg_rtx (HImode);")
+
+;; Generate code to store an aligned halfword into memory.
+;; Operand 0 is the destination address (SImode).
+;; Operand 1 is the source register (HImode, not constant).
+;; Operand 2 is a temporary (SImode).
+;; Operand 3 is a temporary (SImode).
+;; Operand 4 is a temporary (QImode).
+
+;; Operand 5 is an internal variable made from operand 1.
+
+(define_expand "storehi"
+  [(set (match_operand:SI 2 "register_operand" "")
+       (mem:SI (match_operand:SI 0 "register_operand" "")))
+   ;; Insert the low byte.
+   (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 0))
+       (match_dup 5))
+   ;; Form address of high byte.
+   (set (match_operand:SI 3 "register_operand" "")
+       (plus:SI (match_dup 0) (const_int 1)))
+   ;; Extract the high byte from the source.
+   (set (subreg:SI (match_operand:QI 4 "register_operand" "") 0)
+       (zero_extract:SI (match_operand:HI 1 "register_operand" "")
+                        (const_int 8) (const_int 1)))
+   ;; Store high byte into the memory word
+   (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 3))
+       (subreg:SI (match_dup 4) 0))
+   ;; Put memory word back into memory.
+   (set (mem:SI (match_dup 0))
+       (match_dup 2))]
+  ""
+  "
+{
+  if (GET_CODE (operands[1]) == SUBREG)
+    operands[5] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]),
+                          SUBREG_WORD (operands[1]));
+  else
+    operands[5] = gen_rtx (SUBREG, SImode, operands[1], 0);
+}")
+
+;; Like storehi but operands[1] is a CONST_INT.
+
+(define_expand "storeinthi"
+  [(set (match_operand:SI 2 "register_operand" "")
+       (mem:SI (match_operand:SI 0 "register_operand" "")))
+   ;; Insert the low byte.
+   (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 0))
+       (match_dup 5))
+   ;; Form address of high byte.
+   (set (match_operand:SI 3 "register_operand" "")
+       (plus:SI (match_dup 0) (const_int 1)))
+   ;; Store high byte into the memory word
+   (set (zero_extract:SI (match_dup 2) (const_int 8) (match_dup 3))
+       (match_dup 6))
+   ;; Put memory word back into memory.
+   (set (mem:SI (match_dup 0))
+       (match_dup 2))]
+  ""
+  " operands[5] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) & 255);
+    operands[6] = gen_rtx (CONST_INT, VOIDmode,
+                          (INTVAL (operands[1]) >> 8) & 255);
+")
+\f
+;; Main entry for generating insns to move halfwords.
+
+(define_expand "movhi"
+  [(set (match_operand:HI 0 "general_operand" "")
+       (match_operand:HI 1 "general_operand" ""))]
+  ""
+  "
+{
+  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+    operands[1] = copy_to_reg (operands[1]);
+  
+  if (GET_CODE (operands[1]) == MEM)
+    {
+      rtx insn =
+       emit_insn (gen_loadhi (operands[0],
+                              force_reg (SImode, XEXP (operands[1], 0)),
+                              gen_reg_rtx (SImode), gen_reg_rtx (SImode),
+                              gen_reg_rtx (QImode)));
+      /* Tell cse what value the loadhi produces, so it detect duplicates.  */
+      REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUAL, operands[1],
+                                            REG_NOTES (insn));
+    }
+  else if (GET_CODE (operands[0]) == MEM)
+    {
+      if (GET_CODE (operands[1]) == CONST_INT)
+       emit_insn (gen_storeinthi (force_reg (SImode, XEXP (operands[0], 0)),
+                                  operands[1],
+                                  gen_reg_rtx (SImode), gen_reg_rtx (SImode),
+                                  gen_reg_rtx (QImode)));
+      else
+       {
+         if (CONSTANT_P (operands[1]))
+            operands[1] = force_reg (HImode, operands[1]);
+         emit_insn (gen_storehi (force_reg (SImode, XEXP (operands[0], 0)),
+                                 operands[1],
+                                 gen_reg_rtx (SImode), gen_reg_rtx (SImode),
+                                 gen_reg_rtx (QImode)));
+       }
+    }
+  else
+    emit_insn (gen_rtx (SET, VOIDmode, operands[0], operands[1]));
+  DONE;
+}")
+\f
+;; Recognize insns generated for moving halfwords.
+;; (Note that the extract and insert patterns for single-byte moves
+;;  are also involved in recognizing some of the insns used for this purpose.)
+
+(define_insn ""
+  [(set (match_operand:HI 0 "general_operand" "=r,m")
+       (match_operand:HI 1 "general_operand" "rmi,r"))]
+  ""
+  "*
+{
+  if (GET_CODE (operands[0]) == MEM)
+    return \"st_32 %1,%0\";
+  if (GET_CODE (operands[1]) == MEM)
+    return \"ld_32 %0,%1\;nop\";
+  if (GET_CODE (operands[1]) == REG)
+    return \"add_nt %0,%1,$0\";
+  return \"add_nt %0,r0,%1\";
+}")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (zero_extract:SI (match_operand:HI 1 "register_operand" "r")
+                        (const_int 8)
+                        (match_operand:SI 2 "nonmemory_operand" "rI")))]
+  ""
+  "extract %0,%1,%2")
+
+(define_insn ""
+  [(set (zero_extract:SI (match_operand:HI 0 "register_operand" "+r")
+                        (const_int 8)
+                        (match_operand:SI 1 "nonmemory_operand" "rI"))
+       (match_operand:SI 2 "nonmemory_operand" "ri"))]
+  ""
+  "wr_insert %1\;insert %0,%0,%2")
+
+;; Constant propagation can optimize the previous pattern into this pattern.
+
+;(define_insn ""
+;  [(set (zero_extract:QI (match_operand:HI 0 "register_operand" "+r")
+;                       (const_int 8)
+;                       (match_operand:SI 1 "immediate_operand" "I"))
+;      (match_operand:QI 2 "register_operand" "r"))]
+;  "GET_CODE (operands[1]) == CONST_INT
+;   && INTVAL (operands[1]) % 8 == 0
+;   && (unsigned) INTVAL (operands[1]) < 32"
+;  "*
+;{
+;  operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) / 8);
+;  return \"wr_insert 0,0,%1\;insert %0,%0,%2\";
+;}")
+\f
+;; 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]))
+    return output_fp_move_double (operands);
+  if (operands[1] == CONST0_RTX (DFmode) && GET_CODE (operands[0]) == REG)
+    {
+      operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+      return \"add_nt %0,r0,$0\;add_nt %1,r0,$0\";
+    }
+  if (operands[1] == CONST0_RTX (DFmode) && GET_CODE (operands[0]) == MEM)
+    {
+      operands[1] = adj_offsettable_operand (operands[0], 4);
+      return \"st_32 r0,%0\;st_32 r0,%1\";
+    }
+  return output_move_double (operands);
+}
+")
+  
+(define_insn "movdf"
+  [(set (match_operand:DF 0 "general_operand" "=r,&r,m,?f,?rm")
+       (match_operand:DF 1 "general_operand" "r,m,r,rfm,f"))]
+  ""
+  "*
+{
+  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" "=r,&r,m,?f,?rm")
+       (match_operand:DI 1 "general_operand" "r,m,r,rfm,f"))]
+  ""
+  "*
+{
+  if (FP_REG_P (operands[0]) || FP_REG_P (operands[1]))
+    return output_fp_move_double (operands);
+  return output_move_double (operands);
+}
+")
+
+(define_insn "movsf"
+  [(set (match_operand:SF 0 "general_operand" "=rf,m")
+       (match_operand:SF 1 "general_operand" "rfm,rf"))]
+  ""
+  "*
+{
+  if (FP_REG_P (operands[0]))
+    {
+      if (FP_REG_P (operands[1]))
+       return \"fmov %0,%1\";
+      if (GET_CODE (operands[1]) == REG)
+       {
+         rtx xoperands[2];
+         int offset = - get_frame_size () - 8;
+         xoperands[1] = operands[1];
+         xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset);
+         output_asm_insn (\"st_32 %1,r25,%0\", xoperands);
+         xoperands[1] = operands[0];
+         output_asm_insn (\"ld_sgl %1,r25,%0\;nop\", xoperands);
+         return \"\";
+       }
+      return \"ld_sgl %0,%1\;nop\";
+    }
+  if (FP_REG_P (operands[1]))
+    {
+      if (GET_CODE (operands[0]) == REG)
+       {
+         rtx xoperands[2];
+         int offset = - get_frame_size () - 8;
+         xoperands[0] = gen_rtx (CONST_INT, VOIDmode, offset);
+         xoperands[1] = operands[1];
+         output_asm_insn (\"st_sgl %1,r25,%0\", xoperands);
+         xoperands[1] = operands[0];
+         output_asm_insn (\"ld_32 %1,r25,%0\;nop\", xoperands);
+         return \"\";
+       }
+      return \"st_sgl %1,%0\";
+    }
+  if (GET_CODE (operands[0]) == MEM)
+    return \"st_32 %r1,%0\";
+  if (GET_CODE (operands[1]) == MEM)
+    return \"ld_32 %0,%1\;nop\";
+  if (GET_CODE (operands[1]) == REG)
+    return \"add_nt %0,%1,$0\";
+  return \"add_nt %0,r0,%1\";
+}")
+\f
+;;- truncation instructions
+(define_insn "truncsiqi2"
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (truncate:QI
+        (match_operand:SI 1 "register_operand" "r")))]
+  ""
+  "add_nt %0,%1,$0")
+
+(define_insn "trunchiqi2"
+  [(set (match_operand:QI 0 "register_operand" "=r")
+       (truncate:QI
+        (match_operand:HI 1 "register_operand" "r")))]
+  ""
+  "add_nt %0,%1,$0")
+
+(define_insn "truncsihi2"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (truncate:HI
+        (match_operand:SI 1 "register_operand" "r")))]
+  ""
+  "add_nt %0,%1,$0")
+\f
+;;- zero extension instructions
+
+;; Note that the one starting from HImode comes before those for QImode
+;; so that a constant operand will match HImode, not QImode.
+(define_expand "zero_extendhisi2"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (and:SI (match_operand:HI 1 "register_operand" "") ;Changed to SI below
+               ;; This constant is invalid, but reloading will handle it.
+               ;; It's useless to generate here the insns to construct it
+               ;; because constant propagation would simplify them anyway.
+               (match_dup 2)))]
+  ""
+  "
+{
+  if (GET_CODE (operands[1]) == SUBREG)
+    operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]),
+                          SUBREG_WORD (operands[1]));
+  else
+    operands[1] = gen_rtx (SUBREG, SImode, operands[1], 0);
+
+  operands[2] = force_reg (SImode, gen_rtx (CONST_INT, VOIDmode, 65535));
+}")
+
+(define_insn "zero_extendqihi2"
+  [(set (match_operand:HI 0 "register_operand" "=r")
+       (zero_extend:HI
+        (match_operand:QI 1 "register_operand" "r")))]
+  ""
+  "extract %0,%1,$0")
+
+(define_insn "zero_extendqisi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (zero_extend:SI
+        (match_operand:QI 1 "register_operand" "r")))]
+  ""
+  "extract %0,%1,$0")
+\f
+;;- sign extension instructions
+;; Note that the one starting from HImode comes before those for QImode
+;; so that a constant operand will match HImode, not QImode.
+
+(define_expand "extendhisi2"
+  [(set (match_dup 2)
+       (and:SI (match_operand:HI 1 "register_operand" "") ;Changed to SI below
+               (match_dup 4)))
+   (set (match_dup 3) (plus:SI (match_dup 2) (match_dup 5)))
+   (set (match_operand:SI 0 "register_operand" "")
+       (xor:SI (match_dup 3) (match_dup 5)))]
+  ""
+  "
+{
+  if (GET_CODE (operands[1]) == SUBREG)
+    operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]),
+                          SUBREG_WORD (operands[1]));
+  else
+    operands[1] = gen_rtx (SUBREG, SImode, operands[1], 0);
+
+  operands[2] = gen_reg_rtx (SImode);
+  operands[3] = gen_reg_rtx (SImode);
+  operands[4] = force_reg (SImode, gen_rtx (CONST_INT, VOIDmode, 65535));
+  operands[5] = force_reg (SImode, gen_rtx (CONST_INT, VOIDmode, -32768));
+}")
+
+(define_expand "extendqihi2"
+  [(set (match_dup 2)
+       (and:HI (match_operand:QI 1 "register_operand" "") ;Changed to SI below
+               (const_int 255)))
+   (set (match_dup 3)
+       (plus:SI (match_dup 2) (const_int -128)))
+   (set (match_operand:HI 0 "register_operand" "")
+       (xor:SI (match_dup 3) (const_int -128)))]
+  ""
+  "
+{
+  if (GET_CODE (operands[1]) == SUBREG)
+    operands[1] = gen_rtx (SUBREG, HImode, SUBREG_REG (operands[1]),
+                          SUBREG_WORD (operands[1]));
+  else
+    operands[1] = gen_rtx (SUBREG, HImode, operands[1], 0);
+
+  operands[2] = gen_reg_rtx (HImode);
+  operands[3] = gen_reg_rtx (HImode);
+}")
+
+(define_expand "extendqisi2"
+  [(set (match_dup 2)
+       (and:SI (match_operand:QI 1 "register_operand" "") ;Changed to SI below
+               (const_int 255)))
+   (set (match_dup 3) (plus:SI (match_dup 2) (const_int -128)))
+   (set (match_operand:SI 0 "register_operand" "")
+       (xor:SI (match_dup 3) (const_int -128)))]
+  ""
+  "
+{
+  if (GET_CODE (operands[1]) == SUBREG)
+    operands[1] = gen_rtx (SUBREG, SImode, SUBREG_REG (operands[1]),
+                          SUBREG_WORD (operands[1]));
+  else
+    operands[1] = gen_rtx (SUBREG, SImode, operands[1], 0);
+
+  operands[2] = gen_reg_rtx (SImode);
+  operands[3] = gen_reg_rtx (SImode);
+}")
+\f
+;;- arithmetic instructions
+
+(define_insn "addsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (plus:SI (match_operand:SI 1 "nonmemory_operand" "%r")
+                (match_operand:SI 2 "nonmemory_operand" "rI")))]
+  ""
+  "add %0,%1,%2")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (plus:SI (match_operand:SI 1 "nonmemory_operand" "%r")
+                (match_operand:SI 2 "big_immediate_operand" "g")))]
+  "GET_CODE (operands[2]) == CONST_INT 
+   && (unsigned) (INTVAL (operands[2]) + 0x8000000) < 0x10000000"
+  "*
+{
+  return 
+    output_add_large_offset (operands[0], operands[1], INTVAL (operands[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 "nonmemory_operand" "rI")))]
+  ""
+  "sub %0,%1,%2")
+
+(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" "rI")))]
+  ""
+  "and %0,%1,%2")
+
+(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" "rI")))]
+  ""
+  "or %0,%1,%2")
+
+(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" "rI")))]
+  ""
+  "xor %0,%1,%2")
+
+(define_insn "negsi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (neg:SI (match_operand:SI 1 "nonmemory_operand" "rI")))]
+  ""
+  "sub %0,r0,%1")
+
+(define_insn "one_cmplsi2"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (not:SI (match_operand:SI 1 "register_operand" "r")))]
+  ""
+  "xor %0,%1,$-1")
+\f
+;; 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")))]
+  "TARGET_FPU"
+  "fadd %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")))]
+  "TARGET_FPU"
+  "fadd %0,%1,%2")
+
+(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")))]
+  "TARGET_FPU"
+  "fsub %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")))]
+  "TARGET_FPU"
+  "fsub %0,%1,%2")
+
+(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")))]
+  "TARGET_FPU"
+  "fmul %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")))]
+  "TARGET_FPU"
+  "fmul %0,%1,%2")
+
+(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")))]
+  "TARGET_FPU"
+  "fdiv %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")))]
+  "TARGET_FPU"
+  "fdiv %0,%1,%2")
+
+(define_insn "negdf2"
+  [(set (match_operand:DF 0 "register_operand" "=f")
+       (neg:DF (match_operand:DF 1 "nonmemory_operand" "f")))]
+  "TARGET_FPU"
+  "fneg %0,%1")
+
+(define_insn "negsf2"
+  [(set (match_operand:SF 0 "register_operand" "=f")
+       (neg:SF (match_operand:SF 1 "nonmemory_operand" "f")))]
+  "TARGET_FPU"
+  "fneg %0,%1")
+
+(define_insn "absdf2"
+  [(set (match_operand:DF 0 "register_operand" "=f")
+       (abs:DF (match_operand:DF 1 "nonmemory_operand" "f")))]
+  "TARGET_FPU"
+  "fabs %0,%1")
+
+(define_insn "abssf2"
+  [(set (match_operand:SF 0 "register_operand" "=f")
+       (abs:SF (match_operand:SF 1 "nonmemory_operand" "f")))]
+  "TARGET_FPU"
+  "fabs %0,%1")
+\f
+;; Shift instructions
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ashift:SI (match_operand:SI 1 "register_operand" "r")
+                  (match_operand:SI 2 "immediate_operand" "I")))]
+  "GET_CODE (operands[2]) == CONST_INT"
+  "*
+{
+  unsigned int amount = INTVAL (operands[2]);
+
+  switch (amount)
+    {
+    case 0:
+      return \"add_nt %0,%1,$0\";
+    case 1:
+      return \"sll %0,%1,$1\";
+    case 2:
+      return \"sll %0,%1,$2\";
+    default:
+      output_asm_insn (\"sll %0,%1,$3\", operands);
+
+      for (amount -= 3; amount >= 3; amount -= 3)
+       output_asm_insn (\"sll %0,%0,$3\", operands);
+
+      if (amount > 0)
+       output_asm_insn (amount == 1 ? \"sll %0,%0,$1\" : \"sll %0,%0,$2\",
+                        operands);
+      return \"\";
+    }
+}")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
+                    (match_operand:SI 2 "immediate_operand" "I")))]
+  "GET_CODE (operands[2]) == CONST_INT"
+  "*
+{
+  unsigned int amount = INTVAL (operands[2]);
+
+  if (amount == 0) 
+    return \"add_nt %0,%1,$0\";
+  else
+    output_asm_insn (\"sra %0,%1,$1\", operands);
+  
+  for (amount -= 1; amount > 0; amount -= 1)
+    output_asm_insn (\"sra %0,%0,$1\", operands);
+
+  return \"\";
+}")
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
+                    (match_operand:SI 2 "immediate_operand" "I")))]
+  "GET_CODE (operands[2]) == CONST_INT"
+  "*
+{
+  unsigned int amount = INTVAL (operands[2]);
+
+  if (amount == 0) 
+    return \"add_nt %0,%1,$0\";
+  else
+    output_asm_insn (\"srl %0,%1,$1\", operands);
+  
+  for (amount -= 1; amount > 0; amount -= 1)
+    output_asm_insn (\"srl %0,%0,$1\", operands);
+
+  return \"\";
+}")
+
+(define_expand "ashlsi3"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (ashift:SI (match_operand:SI 1 "register_operand" "")
+                  (match_operand:SI 2 "nonmemory_operand" "")))]
+  ""
+  "
+{
+  if (GET_CODE (operands[2]) != CONST_INT
+      || (! TARGET_EXPAND_SHIFTS && (unsigned) INTVAL (operands[2]) > 3))
+    FAIL;
+}")
+
+(define_expand "lshlsi3"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (ashift:SI (match_operand:SI 1 "register_operand" "")
+                  (match_operand:SI 2 "nonmemory_operand" "")))]
+  ""
+  "
+{
+  if (GET_CODE (operands[2]) != CONST_INT
+      || (! TARGET_EXPAND_SHIFTS && (unsigned) INTVAL (operands[2]) > 3))
+    FAIL;
+}")
+
+(define_expand "ashrsi3"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
+                    (match_operand:SI 2 "nonmemory_operand" "")))]
+  ""
+  "
+{
+  if (GET_CODE (operands[2]) != CONST_INT
+      || (! TARGET_EXPAND_SHIFTS && (unsigned) INTVAL (operands[2]) > 1))
+    FAIL;
+}")
+
+(define_expand "lshrsi3"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
+                    (match_operand:SI 2 "nonmemory_operand" "")))]
+  ""
+  "
+{
+  if (GET_CODE (operands[2]) != CONST_INT
+      || (! TARGET_EXPAND_SHIFTS && (unsigned) INTVAL (operands[2]) > 1))
+    FAIL;
+}")
+\f
+;; Unconditional and other jump instructions
+(define_insn "jump"
+  [(set (pc)
+       (label_ref (match_operand 0 "" "")))]
+  ""
+  "jump %l0\;nop")
+
+(define_insn "tablejump"
+  [(set (pc) (match_operand:SI 0 "register_operand" "r"))
+   (use (label_ref (match_operand 1 "" "")))]
+  ""
+  "jump_reg r0,%0\;nop")
+
+;;- jump to subroutine
+(define_insn "call"
+  [(call (match_operand:SI 0 "memory_operand" "m")
+        (match_operand:SI 1 "general_operand" "g"))]
+  ;;- Don't use operand 1 for most machines.
+  ""
+  "add_nt r2,%0\;call .+8\;jump_reg r0,r2\;nop")
+
+(define_insn "call_value"
+  [(set (match_operand 0 "" "=g")
+       (call (match_operand:SI 1 "memory_operand" "m")
+             (match_operand:SI 2 "general_operand" "g")))]
+  ;;- Don't use operand 1 for most machines.
+  ""
+  "add_nt r2,%1\;call .+8\;jump_reg r0,r2\;nop")
+
+;; A memory ref with constant address is not normally valid.
+;; But it is valid in a call insns.  This pattern allows the
+;; loading of the address to combine with the call.
+(define_insn ""
+  [(call (mem:SI (match_operand:SI 0 "" "i"))
+        (match_operand:SI 1 "general_operand" "g"))]
+  ;;- Don't use operand 1 for most machines.
+  "GET_CODE (operands[0]) == SYMBOL_REF"
+  "call %0\;nop")
+
+(define_insn ""
+  [(set (match_operand 0 "" "=g")
+       (call (mem:SI (match_operand:SI 1 "" "i"))
+             (match_operand:SI 2 "general_operand" "g")))]
+  ;;- Don't use operand 1 for most machines.
+  "GET_CODE (operands[1]) == SYMBOL_REF"
+  "call %1\;nop")
+
+(define_insn "nop"
+  [(const_int 0)]
+  ""
+  "nop")
+\f
+;;- 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:
+