79 KiB
;;- Machine description for Intel 80960 chip for GNU C compiler ;; Copyright (C) 1992, 1995, 1998 Free Software Foundation, Inc. ;; Contributed by Steven McGeady, Intel Corp. ;; Additional work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson ;; Converted to GCC 2.0 by Jim Wilson and Michael Tiemann, Cygnus Support.
;; This file is part of GNU CC.
;; GNU CC is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version.
;; GNU CC is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License ;; along with GNU CC; see the file COPYING. If not, write to ;; the Free Software Foundation, 59 Temple Place - Suite 330, ;; Boston, MA 02111-1307, USA.
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. ;; There are very few (4) 'f' registers, they can't be loaded/stored from/to ;; memory, and some instructions explicitly require them, so we get better ;; code by discouraging pseudo-registers from being allocated to them. ;; However, we do want to allow all patterns which can store to them to ;; include them in their constraints, so we always use '*f' in a destination ;; constraint except when 'f' is the only alternative. ;; Insn attributes which describe the i960.
;; Modscan is not used, since the compiler never emits any of these insns. (define_attr "type" "move,arith,alu2,mult,div,modscan,load,store,branch,call,address,compare,fpload,fpstore,fpmove,fpcvt,fpcc,fpadd,fpmul,fpdiv,multi,misc" (const_string "arith"))
;; Length (in # of insns). (define_attr "length" "" (cond [(eq_attr "type" "load,fpload") (if_then_else (match_operand 1 "symbolic_memory_operand" "") (const_int 2) (const_int 1)) (eq_attr "type" "store,fpstore") (if_then_else (match_operand 0 "symbolic_memory_operand" "") (const_int 2) (const_int 1)) (eq_attr "type" "address") (const_int 2)] (const_int 1)))
(define_asm_attributes [(set_attr "length" "1") (set_attr "type" "multi")])
;; (define_function_unit {name} {num-units} {n-users} {test} ;; {ready-delay} {issue-delay} [{conflict-list}])
;; The integer ALU (define_function_unit "alu" 2 0 (eq_attr "type" "arith,compare,move,address") 1 0) (define_function_unit "alu" 2 0 (eq_attr "type" "alu2") 2 0) (define_function_unit "alu" 2 0 (eq_attr "type" "mult") 5 0) (define_function_unit "alu" 2 0 (eq_attr "type" "div") 35 0) (define_function_unit "alu" 2 0 (eq_attr "type" "modscan") 3 0)
;; Memory with load-delay of 1 (i.e., 2 cycle load). (define_function_unit "memory" 1 0 (eq_attr "type" "load,fpload") 2 0)
;; Floating point operations. (define_function_unit "fp" 1 2 (eq_attr "type" "fpmove") 5 0) (define_function_unit "fp" 1 2 (eq_attr "type" "fpcvt") 35 0) (define_function_unit "fp" 1 2 (eq_attr "type" "fpcc") 10 0) (define_function_unit "fp" 1 2 (eq_attr "type" "fpadd") 10 0) (define_function_unit "fp" 1 2 (eq_attr "type" "fpmul") 20 0) (define_function_unit "fp" 1 2 (eq_attr "type" "fpdiv") 35 0) ;; Compare instructions. ;; This controls RTL generation and register allocation.
;; We generate RTL for comparisons and branches by having the cmpxx ;; patterns store away the operands. Then, the scc and bcc patterns ;; emit RTL for both the compare and the branch. ;; ;; We start with the DEFINE_EXPANDs, then then DEFINE_INSNs to match ;; the patterns. Finally, we have the DEFINE_SPLITs for some of the scc ;; insns that actually require more than one machine instruction.
;; Put cmpsi first because it is expected to be the most common.
(define_expand "cmpsi" [(set (reg:CC 36) (compare:CC (match_operand:SI 0 "nonimmediate_operand" "") (match_operand:SI 1 "general_operand" "")))] "" " { i960_compare_op0 = operands[0]; i960_compare_op1 = operands[1]; DONE; }")
(define_expand "cmpdf" [(set (reg:CC 36) (compare:CC (match_operand:DF 0 "register_operand" "r") (match_operand:DF 1 "nonmemory_operand" "rGH")))] "TARGET_NUMERICS" " { i960_compare_op0 = operands[0]; i960_compare_op1 = operands[1]; DONE; }")
(define_expand "cmpsf" [(set (reg:CC 36) (compare:CC (match_operand:SF 0 "register_operand" "r") (match_operand:SF 1 "nonmemory_operand" "rGH")))] "TARGET_NUMERICS" " { i960_compare_op0 = operands[0]; i960_compare_op1 = operands[1]; DONE; }")
;; Now the DEFINE_INSNs for the compare and scc cases. First the compares.
(define_insn "" [(set (reg:CC 36) (compare:CC (match_operand:SI 0 "register_operand" "d") (match_operand:SI 1 "arith_operand" "dI")))] "" "cmpi %0,%1" [(set_attr "type" "compare")])
(define_insn "" [(set (reg:CC_UNS 36) (compare:CC_UNS (match_operand:SI 0 "register_operand" "d") (match_operand:SI 1 "arith_operand" "dI")))] "" "cmpo %0,%1" [(set_attr "type" "compare")])
(define_insn "" [(set (reg:CC 36) (compare:CC (match_operand:DF 0 "register_operand" "r") (match_operand:DF 1 "nonmemory_operand" "rGH")))] "TARGET_NUMERICS" "cmprl %0,%1" [(set_attr "type" "fpcc")])
(define_insn "" [(set (reg:CC 36) (compare:CC (match_operand:SF 0 "register_operand" "r") (match_operand:SF 1 "nonmemory_operand" "rGH")))] "TARGET_NUMERICS" "cmpr %0,%1" [(set_attr "type" "fpcc")])
;; Instruction definitions for branch-on-bit-set and clear insns.
(define_insn "" [(set (pc) (if_then_else (ne (sign_extract:SI (match_operand:SI 1 "register_operand" "d") (const_int 1) (match_operand:SI 2 "arith_operand" "dI")) (const_int 0)) (label_ref (match_operand 3 "" "")) (pc)))] "" "bbs %2,%1,%l3" [(set_attr "type" "branch")])
(define_insn "" [(set (pc) (if_then_else (eq (sign_extract:SI (match_operand:SI 1 "register_operand" "d") (const_int 1) (match_operand:SI 2 "arith_operand" "dI")) (const_int 0)) (label_ref (match_operand 3 "" "")) (pc)))] "" "bbc %2,%1,%l3" [(set_attr "type" "branch")])
(define_insn "" [(set (pc) (if_then_else (ne (zero_extract:SI (match_operand:SI 1 "register_operand" "d") (const_int 1) (match_operand:SI 2 "arith_operand" "dI")) (const_int 0)) (label_ref (match_operand 3 "" "")) (pc)))] "" "bbs %2,%1,%l3" [(set_attr "type" "branch")])
(define_insn "" [(set (pc) (if_then_else (eq (zero_extract:SI (match_operand:SI 1 "register_operand" "d") (const_int 1) (match_operand:SI 2 "arith_operand" "dI")) (const_int 0)) (label_ref (match_operand 3 "" "")) (pc)))] "" "bbc %2,%1,%l3" [(set_attr "type" "branch")])
;; ??? These will never match. The LOG_LINKs necessary to make these match ;; are not created by flow. These remain as a reminder to make this work ;; some day.
(define_insn "" [(set (reg:CC 36) (compare (match_operand:SI 0 "arith_operand" "d") (match_operand:SI 1 "arith_operand" "d"))) (set (match_dup 1) (plus:SI (match_dup 1) (const_int 1)))] "0" "cmpinci %0,%1" [(set_attr "type" "compare")])
(define_insn "" [(set (reg:CC_UNS 36) (compare (match_operand:SI 0 "arith_operand" "d") (match_operand:SI 1 "arith_operand" "d"))) (set (match_dup 1) (plus:SI (match_dup 1) (const_int 1)))] "0" "cmpinco %0,%1" [(set_attr "type" "compare")])
(define_insn "" [(set (reg:CC 36) (compare (match_operand:SI 0 "arith_operand" "d") (match_operand:SI 1 "arith_operand" "d"))) (set (match_dup 1) (minus:SI (match_dup 1) (const_int 1)))] "0" "cmpdeci %0,%1" [(set_attr "type" "compare")])
(define_insn "" [(set (reg:CC_UNS 36) (compare (match_operand:SI 0 "arith_operand" "d") (match_operand:SI 1 "arith_operand" "d"))) (set (match_dup 1) (minus:SI (match_dup 1) (const_int 1)))] "0" "cmpdeco %0,%1" [(set_attr "type" "compare")]) ;; Templates to store result of condition. ;; '1' is stored if condition is true. ;; '0' is stored if condition is false. ;; These should use predicate "general_operand", since ;; gcc seems to be creating mem references which use these ;; templates.
(define_expand "seq" [(set (match_operand:SI 0 "general_operand" "=d") (eq:SI (match_dup 1) (const_int 0)))] "" " { operands[1] = gen_compare_reg (EQ, i960_compare_op0, i960_compare_op1); }")
(define_expand "sne" [(set (match_operand:SI 0 "general_operand" "=d") (ne:SI (match_dup 1) (const_int 0)))] "" " { operands[1] = gen_compare_reg (NE, i960_compare_op0, i960_compare_op1); }")
(define_expand "sgt" [(set (match_operand:SI 0 "general_operand" "=d") (gt:SI (match_dup 1) (const_int 0)))] "" " { operands[1] = gen_compare_reg (GT, i960_compare_op0, i960_compare_op1); }")
(define_expand "sgtu" [(set (match_operand:SI 0 "general_operand" "=d") (gtu:SI (match_dup 1) (const_int 0)))] "" " { operands[1] = gen_compare_reg (GTU, i960_compare_op0, i960_compare_op1); }")
(define_expand "slt" [(set (match_operand:SI 0 "general_operand" "=d") (lt:SI (match_dup 1) (const_int 0)))] "" " { operands[1] = gen_compare_reg (LT, i960_compare_op0, i960_compare_op1); }")
(define_expand "sltu" [(set (match_operand:SI 0 "general_operand" "=d") (ltu:SI (match_dup 1) (const_int 0)))] "" " { operands[1] = gen_compare_reg (LTU, i960_compare_op0, i960_compare_op1); }")
(define_expand "sge" [(set (match_operand:SI 0 "general_operand" "=d") (ge:SI (match_dup 1) (const_int 0)))] "" " { operands[1] = gen_compare_reg (GE, i960_compare_op0, i960_compare_op1); }")
(define_expand "sgeu" [(set (match_operand:SI 0 "general_operand" "=d") (geu:SI (match_dup 1) (const_int 0)))] "" " { operands[1] = gen_compare_reg (GEU, i960_compare_op0, i960_compare_op1); }")
(define_expand "sle" [(set (match_operand:SI 0 "general_operand" "=d") (le:SI (match_dup 1) (const_int 0)))] "" " { operands[1] = gen_compare_reg (LE, i960_compare_op0, i960_compare_op1); }")
(define_expand "sleu" [(set (match_operand:SI 0 "general_operand" "=d") (leu:SI (match_dup 1) (const_int 0)))] "" " { operands[1] = gen_compare_reg (LEU, i960_compare_op0, i960_compare_op1); }")
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=d") (eq:SI (match_operand:SI 1 "register_operand" "d") (const_int 0)))] "" "shro %1,1,%0" [(set_attr "type" "alu2")])
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=d") (match_operator:SI 1 "comparison_operator" [(reg:CC 36) (const_int 0)]))] "" "test%C1 %0" [(set_attr "type" "compare")])
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=d") (match_operator:SI 1 "comparison_operator" [(reg:CC_UNS 36) (const_int 0)]))] "" "test%C1 %0" [(set_attr "type" "compare")]) ;; These control RTL generation for conditional jump insns ;; and match them for register allocation.
(define_expand "beq" [(set (pc) (if_then_else (eq (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { operands[1] = gen_compare_reg (EQ, i960_compare_op0, i960_compare_op1); }")
(define_expand "bne" [(set (pc) (if_then_else (ne (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { operands[1] = gen_compare_reg (NE, i960_compare_op0, i960_compare_op1); }")
(define_expand "bgt" [(set (pc) (if_then_else (gt (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { operands[1] = gen_compare_reg (GT, i960_compare_op0, i960_compare_op1); }")
(define_expand "bgtu" [(set (pc) (if_then_else (gtu (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { operands[1] = gen_compare_reg (GTU, i960_compare_op0, i960_compare_op1); }")
(define_expand "blt" [(set (pc) (if_then_else (lt (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { operands[1] = gen_compare_reg (LT, i960_compare_op0, i960_compare_op1); }")
(define_expand "bltu" [(set (pc) (if_then_else (ltu (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { operands[1] = gen_compare_reg (LTU, i960_compare_op0, i960_compare_op1); }")
(define_expand "bge" [(set (pc) (if_then_else (ge (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { operands[1] = gen_compare_reg (GE, i960_compare_op0, i960_compare_op1); }")
(define_expand "bgeu" [(set (pc) (if_then_else (geu (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { operands[1] = gen_compare_reg (GEU, i960_compare_op0, i960_compare_op1); }")
(define_expand "ble" [(set (pc) (if_then_else (le (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { operands[1] = gen_compare_reg (LE, i960_compare_op0, i960_compare_op1); }")
(define_expand "bleu" [(set (pc) (if_then_else (leu (match_dup 1) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "" " { operands[1] = gen_compare_reg (LEU, i960_compare_op0, i960_compare_op1); }") ;; Now the normal branch insns (forward and reverse).
(define_insn "" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(reg:CC 36) (const_int 0)]) (label_ref (match_operand 1 "" "")) (pc)))] "" "b%C0 %l1" [(set_attr "type" "branch")])
(define_insn "" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(reg:CC 36) (const_int 0)]) (pc) (label_ref (match_operand 1 "" ""))))] "" "b%I0 %l1" [(set_attr "type" "branch")])
(define_insn "" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(reg:CC_UNS 36) (const_int 0)]) (label_ref (match_operand 1 "" "")) (pc)))] "" "b%C0 %l1" [(set_attr "type" "branch")])
(define_insn "" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(reg:CC_UNS 36) (const_int 0)]) (pc) (label_ref (match_operand 1 "" ""))))] "" "b%I0 %l1" [(set_attr "type" "branch")])
(define_insn "" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(match_operand:SI 1 "arith_operand" "d") (match_operand:SI 2 "arith_operand" "dI")]) (label_ref (match_operand 3 "" "")) (pc)))] "" "cmp%S0%B0%R0 %2,%1,%l3" [(set_attr "type" "branch")])
(define_insn "" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" [(match_operand:SI 1 "arith_operand" "d") (match_operand:SI 2 "arith_operand" "dI")]) (pc) (label_ref (match_operand 3 "" ""))))] "" "cmp%S0%B0%X0 %2,%1,%l3" [(set_attr "type" "branch")]) ;; Normal move instructions. ;; This code is based on the sparc machine description.
(define_expand "movsi" [(set (match_operand:SI 0 "general_operand" "") (match_operand:SI 1 "general_operand" ""))] "" " { if (emit_move_sequence (operands, SImode)) DONE; }")
;; The store case can not be separate, because reload may convert a register ;; to register move insn to a store (or load) insn without rerecognizing ;; the insn.
;; The i960 does not have any store constant to memory instruction. However, ;; the calling convention is defined so that the arg pointer when it is not ;; overwise being used is zero. Thus, we can handle store zero to memory ;; by storing an unused arg pointer. The arg pointer will be unused if ;; current_function_args_size is zero and this is not a stdarg/varargs ;; function. This value of the former variable is not valid until after ;; all rtl generation is complete, including function inlining (because a ;; function that doesn't need an arg pointer may be inlined into a function ;; that does need an arg pointer), so we must also check that ;; rtx_equal_function_value_matters is zero.
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=d,d,d,m")
(match_operand:SI 1 "general_operand" "dI,i,m,dJ"))]
"(current_function_args_size == 0
&& current_function_varargs == 0
&& current_function_stdarg == 0
&& rtx_equal_function_value_matters == 0)
&& (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode)
|| operands[1] == const0_rtx)"
"*
{
switch (which_alternative)
{
case 0:
if (i960_last_insn_type == I_TYPE_REG && TARGET_C_SERIES)
{
if (GET_CODE (operands[1]) == REG)
return "lda (%1),%0";
else
return "lda %1,%0";
}
return "mov %1,%0";
case 1:
return i960_output_ldconst (operands[0], operands[1]);
case 2:
return "ld %1,%0";
case 3:
if (operands[1] == const0_rtx)
return "st g14,%0";
return "st %1,%0";
}
}"
[(set_attr "type" "move,address,load,store")
(set_attr "length" ",3,,*")])
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=d,d,d,m")
(match_operand:SI 1 "general_operand" "dI,i,m,d"))]
"(current_function_args_size != 0
|| current_function_varargs != 0
|| current_function_stdarg != 0
|| rtx_equal_function_value_matters != 0)
&& (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
"*
{
switch (which_alternative)
{
case 0:
if (i960_last_insn_type == I_TYPE_REG && TARGET_C_SERIES)
{
if (GET_CODE (operands[1]) == REG)
return "lda (%1),%0";
else
return "lda %1,%0";
}
return "mov %1,%0";
case 1:
return i960_output_ldconst (operands[0], operands[1]);
case 2:
return "ld %1,%0";
case 3:
return "st %1,%0";
}
}"
[(set_attr "type" "move,address,load,store")
(set_attr "length" ",3,,*")])
(define_expand "movhi" [(set (match_operand:HI 0 "general_operand" "") (match_operand:HI 1 "general_operand" ""))] "" " { if (emit_move_sequence (operands, HImode)) DONE; }")
;; Special pattern for zero stores to memory for functions which don't use ;; the arg pointer.
;; The store case can not be separate. See above. (define_insn "" [(set (match_operand:HI 0 "general_operand" "=d,d,d,m") (match_operand:HI 1 "general_operand" "dI,i,m,dJ"))] "(current_function_args_size == 0 && current_function_varargs == 0 && current_function_stdarg == 0 && rtx_equal_function_value_matters == 0) && (register_operand (operands[0], HImode) || register_operand (operands[1], HImode) || operands[1] == const0_rtx)" "* { switch (which_alternative) { case 0: if (i960_last_insn_type == I_TYPE_REG && TARGET_C_SERIES) { if (GET_CODE (operands[1]) == REG) return "lda (%1),%0"; else return "lda %1,%0"; } return "mov %1,%0"; case 1: return i960_output_ldconst (operands[0], operands[1]); case 2: return "ldos %1,%0"; case 3: if (operands[1] == const0_rtx) return "stos g14,%0"; return "stos %1,%0"; } }" [(set_attr "type" "move,misc,load,store") (set_attr "length" ",3,,*")])
;; The store case can not be separate. See above. (define_insn "" [(set (match_operand:HI 0 "general_operand" "=d,d,d,m") (match_operand:HI 1 "general_operand" "dI,i,m,d"))] "(current_function_args_size != 0 || current_function_varargs != 0 || current_function_stdarg != 0 || rtx_equal_function_value_matters != 0) && (register_operand (operands[0], HImode) || register_operand (operands[1], HImode))" "* { switch (which_alternative) { case 0: if (i960_last_insn_type == I_TYPE_REG && TARGET_C_SERIES) { if (GET_CODE (operands[1]) == REG) return "lda (%1),%0"; else return "lda %1,%0"; } return "mov %1,%0"; case 1: return i960_output_ldconst (operands[0], operands[1]); case 2: return "ldos %1,%0"; case 3: return "stos %1,%0"; } }" [(set_attr "type" "move,misc,load,store") (set_attr "length" ",3,,*")])
(define_expand "movqi" [(set (match_operand:QI 0 "general_operand" "") (match_operand:QI 1 "general_operand" ""))] "" " { if (emit_move_sequence (operands, QImode)) DONE; }")
;; The store case can not be separate. See comment above. (define_insn "" [(set (match_operand:QI 0 "general_operand" "=d,d,d,m") (match_operand:QI 1 "general_operand" "dI,i,m,dJ"))] "(current_function_args_size == 0 && current_function_varargs == 0 && current_function_stdarg == 0 && rtx_equal_function_value_matters == 0) && (register_operand (operands[0], QImode) || register_operand (operands[1], QImode) || operands[1] == const0_rtx)" "* { switch (which_alternative) { case 0: if (i960_last_insn_type == I_TYPE_REG && TARGET_C_SERIES) { if (GET_CODE (operands[1]) == REG) return "lda (%1),%0"; else return "lda %1,%0"; } return "mov %1,%0"; case 1: return i960_output_ldconst (operands[0], operands[1]); case 2: return "ldob %1,%0"; case 3: if (operands[1] == const0_rtx) return "stob g14,%0"; return "stob %1,%0"; } }" [(set_attr "type" "move,misc,load,store") (set_attr "length" ",3,,*")])
;; The store case can not be separate. See comment above. (define_insn "" [(set (match_operand:QI 0 "general_operand" "=d,d,d,m") (match_operand:QI 1 "general_operand" "dI,i,m,d"))] "(current_function_args_size != 0 || current_function_varargs != 0 || current_function_stdarg != 0 || rtx_equal_function_value_matters != 0) && (register_operand (operands[0], QImode) || register_operand (operands[1], QImode))" "* { switch (which_alternative) { case 0: if (i960_last_insn_type == I_TYPE_REG && TARGET_C_SERIES) { if (GET_CODE (operands[1]) == REG) return "lda (%1),%0"; else return "lda %1,%0"; } return "mov %1,%0"; case 1: return i960_output_ldconst (operands[0], operands[1]); case 2: return "ldob %1,%0"; case 3: return "stob %1,%0"; } }" [(set_attr "type" "move,misc,load,store") (set_attr "length" ",3,,*")])
(define_expand "movdi" [(set (match_operand:DI 0 "general_operand" "") (match_operand:DI 1 "general_operand" ""))] "" " { if (emit_move_sequence (operands, DImode)) DONE; }")
;; The store case can not be separate. See comment above. (define_insn "" [(set (match_operand:DI 0 "general_operand" "=d,d,d,d,m,o") (match_operand:DI 1 "general_operand" "d,I,i,m,d,J"))] "(current_function_args_size == 0 && current_function_varargs == 0 && current_function_stdarg == 0 && rtx_equal_function_value_matters == 0) && (register_operand (operands[0], DImode) || register_operand (operands[1], DImode) || operands[1] == const0_rtx)" "* { switch (which_alternative) { case 0: case 1: case 3: case 4: return i960_output_move_double (operands[0], operands[1]); case 2: return i960_output_ldconst (operands[0], operands[1]); case 5: operands[1] = adj_offsettable_operand (operands[0], 4); return "st g14,%0;st g14,%1"; } }" [(set_attr "type" "move,move,load,load,store,store")])
;; The store case can not be separate. See comment above. (define_insn "" [(set (match_operand:DI 0 "general_operand" "=d,d,d,d,m") (match_operand:DI 1 "general_operand" "d,I,i,m,d"))] "(current_function_args_size != 0 || current_function_varargs != 0 || current_function_stdarg != 0 || rtx_equal_function_value_matters != 0) && (register_operand (operands[0], DImode) || register_operand (operands[1], DImode))" "* { switch (which_alternative) { case 0: case 1: case 3: case 4: return i960_output_move_double (operands[0], operands[1]); case 2: return i960_output_ldconst (operands[0], operands[1]); } }" [(set_attr "type" "move,move,load,load,store")])
(define_insn "store_unaligned_di_reg" [(set (match_operand:DI 0 "general_operand" "=d,m") (match_operand:DI 1 "register_operand" "d,d")) (clobber (match_scratch:SI 2 "=X,&d"))] "" " { if (which_alternative == 0) return i960_output_move_double (operands[0], operands[1]);
operands[3] = gen_rtx (MEM, word_mode, operands[2]); operands[4] = adj_offsettable_operand (operands[3], UNITS_PER_WORD); return "lda %0,%2;st %1,%3;st %D1,%4"; }" [(set_attr "type" "move,store")])
(define_expand "movti" [(set (match_operand:TI 0 "general_operand" "") (match_operand:TI 1 "general_operand" ""))] "" " { if (emit_move_sequence (operands, TImode)) DONE; }")
;; The store case can not be separate. See comment above. (define_insn "" [(set (match_operand:TI 0 "general_operand" "=d,d,d,d,m,o") (match_operand:TI 1 "general_operand" "d,I,i,m,d,J"))] "(current_function_args_size == 0 && current_function_varargs == 0 && current_function_stdarg == 0 && rtx_equal_function_value_matters == 0) && (register_operand (operands[0], TImode) || register_operand (operands[1], TImode) || operands[1] == const0_rtx)" "* { switch (which_alternative) { case 0: case 1: case 3: case 4: return i960_output_move_quad (operands[0], operands[1]); case 2: return i960_output_ldconst (operands[0], operands[1]); case 5: operands[1] = adj_offsettable_operand (operands[0], 4); operands[2] = adj_offsettable_operand (operands[0], 8); operands[3] = adj_offsettable_operand (operands[0], 12); return "st g14,%0;st g14,%1;st g14,%2;st g14,%3"; } }" [(set_attr "type" "move,move,load,load,store,store")])
;; The store case can not be separate. See comment above. (define_insn "" [(set (match_operand:TI 0 "general_operand" "=d,d,d,d,m") (match_operand:TI 1 "general_operand" "d,I,i,m,d"))] "(current_function_args_size != 0 || current_function_varargs != 0 || current_function_stdarg != 0 || rtx_equal_function_value_matters != 0) && (register_operand (operands[0], TImode) || register_operand (operands[1], TImode))" "* { switch (which_alternative) { case 0: case 1: case 3: case 4: return i960_output_move_quad (operands[0], operands[1]); case 2: return i960_output_ldconst (operands[0], operands[1]); } }" [(set_attr "type" "move,move,load,load,store")])
(define_insn "store_unaligned_ti_reg" [(set (match_operand:TI 0 "general_operand" "=d,m") (match_operand:TI 1 "register_operand" "d,d")) (clobber (match_scratch:SI 2 "=X,&d"))] "" " { if (which_alternative == 0) return i960_output_move_quad (operands[0], operands[1]);
operands[3] = gen_rtx (MEM, word_mode, operands[2]); operands[4] = adj_offsettable_operand (operands[3], UNITS_PER_WORD); operands[5] = adj_offsettable_operand (operands[4], UNITS_PER_WORD); operands[6] = adj_offsettable_operand (operands[5], UNITS_PER_WORD); return "lda %0,%2;st %1,%3;st %D1,%4;st %E1,%5;st %F1,%6"; }" [(set_attr "type" "move,store")])
(define_expand "store_multiple" [(set (match_operand:SI 0 "" "") ;;- dest (match_operand:SI 1 "" "")) ;;- src (use (match_operand:SI 2 "" ""))] ;;- nregs "" " { int regno; int count; rtx from; int i;
if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != REG || GET_CODE (operands[2]) != CONST_INT) FAIL;
count = INTVAL (operands[2]); if (count > 12) FAIL;
regno = REGNO (operands[1]); from = memory_address (SImode, XEXP (operands[0], 0)); while (count >= 4 && ((regno & 3) == 0)) { emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, TImode, from), gen_rtx (REG, TImode, regno))); count -= 4; regno += 4; from = memory_address (TImode, plus_constant (from, 16)); } while (count >= 2 && ((regno & 1) == 0)) { emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, DImode, from), gen_rtx (REG, DImode, regno))); count -= 2; regno += 2; from = memory_address (DImode, plus_constant (from, 8)); } while (count > 0) { emit_insn (gen_rtx (SET, VOIDmode, gen_rtx (MEM, SImode, from), gen_rtx (REG, SImode, regno))); count -= 1; regno += 1; from = memory_address (SImode, plus_constant (from, 4)); } DONE; }") ;; Floating point move insns
(define_expand "movdf" [(set (match_operand:DF 0 "general_operand" "") (match_operand:DF 1 "fpmove_src_operand" ""))] "" " { if (emit_move_sequence (operands, DFmode)) DONE; }")
(define_insn "" [(set (match_operand:DF 0 "general_operand" "=r,f,d,d,m,o") (match_operand:DF 1 "fpmove_src_operand" "r,GH,F,m,d,G"))] "(current_function_args_size == 0 && current_function_varargs == 0 && current_function_stdarg == 0 && rtx_equal_function_value_matters == 0) && (register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode) || operands[1] == CONST0_RTX (DFmode))" " { switch (which_alternative) { case 0: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) return "movrl %1,%0"; else return "movl %1,%0"; case 1: return "movrl %1,%0"; case 2: return i960_output_ldconst (operands[0], operands[1]); case 3: return "ldl %1,%0"; case 4: return "stl %1,%0"; case 5: operands[1] = adj_offsettable_operand (operands[0], 4); return "st g14,%0;st g14,%1"; } }" [(set_attr "type" "move,move,load,fpload,fpstore,fpstore")])
(define_insn "" [(set (match_operand:DF 0 "general_operand" "=r,f,d,d,m") (match_operand:DF 1 "fpmove_src_operand" "r,GH,F,m,d"))] "(current_function_args_size != 0 || current_function_varargs != 0 || current_function_stdarg != 0 || rtx_equal_function_value_matters != 0) && (register_operand (operands[0], DFmode) || register_operand (operands[1], DFmode))" " { switch (which_alternative) { case 0: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) return "movrl %1,%0"; else return "movl %1,%0"; case 1: return "movrl %1,%0"; case 2: return i960_output_ldconst (operands[0], operands[1]); case 3: return "ldl %1,%0"; case 4: return "stl %1,%0"; } }" [(set_attr "type" "move,move,load,fpload,fpstore")])
(define_expand "movsf" [(set (match_operand:SF 0 "general_operand" "") (match_operand:SF 1 "fpmove_src_operand" ""))] "" " { if (emit_move_sequence (operands, SFmode)) DONE; }")
(define_insn "" [(set (match_operand:SF 0 "general_operand" "=r,f,d,d,m") (match_operand:SF 1 "fpmove_src_operand" "r,GH,F,m,dG"))] "(current_function_args_size == 0 && current_function_varargs == 0 && current_function_stdarg == 0 && rtx_equal_function_value_matters == 0) && (register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode) || operands[1] == CONST0_RTX (SFmode))" " { switch (which_alternative) { case 0: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) return "movr %1,%0"; else return "mov %1,%0"; case 1: return "movr %1,%0"; case 2: return i960_output_ldconst (operands[0], operands[1]); case 3: return "ld %1,%0"; case 4: if (operands[1] == CONST0_RTX (SFmode)) return "st g14,%0"; return "st %1,%0"; } }" [(set_attr "type" "move,move,load,fpload,fpstore")])
(define_insn "" [(set (match_operand:SF 0 "general_operand" "=r,f,d,d,m") (match_operand:SF 1 "fpmove_src_operand" "r,GH,F,m,d"))] "(current_function_args_size != 0 || current_function_varargs != 0 || current_function_stdarg != 0 || rtx_equal_function_value_matters != 0) && (register_operand (operands[0], SFmode) || register_operand (operands[1], SFmode))" " { switch (which_alternative) { case 0: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) return "movr %1,%0"; else return "mov %1,%0"; case 1: return "movr %1,%0"; case 2: return i960_output_ldconst (operands[0], operands[1]); case 3: return "ld %1,%0"; case 4: return "st %1,%0"; } }" [(set_attr "type" "move,move,load,fpload,fpstore")]) ;; Mixed-mode moves with sign and zero-extension.
;; 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_operand:SI 0 "register_operand" "") (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] "" " { if (GET_CODE (operand1) == REG || (GET_CODE (operand1) == SUBREG && GET_CODE (XEXP (operand1, 0)) == REG)) { rtx temp = gen_reg_rtx (SImode); rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16); int op1_subreg_word = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subreg_word = SUBREG_WORD (operand1);
operand1 = SUBREG_REG (operand1);
}
operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
emit_insn (gen_ashlsi3 (temp, operand1, shift_16));
emit_insn (gen_ashrsi3 (operand0, temp, shift_16));
DONE;
}
}")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))] "" "ldis %1,%0" [(set_attr "type" "load")])
(define_expand "extendqisi2" [(set (match_operand:SI 0 "register_operand" "") (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] "" " { if (GET_CODE (operand1) == REG || (GET_CODE (operand1) == SUBREG && GET_CODE (XEXP (operand1, 0)) == REG)) { rtx temp = gen_reg_rtx (SImode); rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24); int op1_subreg_word = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subreg_word = SUBREG_WORD (operand1);
operand1 = SUBREG_REG (operand1);
}
operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word),
emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
DONE;
}
}")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))] "" "ldib %1,%0" [(set_attr "type" "load")])
(define_expand "extendqihi2" [(set (match_operand:HI 0 "register_operand" "") (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] "" " { if (GET_CODE (operand1) == REG || (GET_CODE (operand1) == SUBREG && GET_CODE (XEXP (operand1, 0)) == REG)) { rtx temp = gen_reg_rtx (SImode); rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24); int op0_subreg_word = 0; int op1_subreg_word = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subreg_word = SUBREG_WORD (operand1);
operand1 = SUBREG_REG (operand1);
}
operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
if (GET_CODE (operand0) == SUBREG)
{
op0_subreg_word = SUBREG_WORD (operand0);
operand0 = SUBREG_REG (operand0);
}
if (GET_MODE (operand0) != SImode)
operand0 = gen_rtx (SUBREG, SImode, operand0, op0_subreg_word);
emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
emit_insn (gen_ashrsi3 (operand0, temp, shift_24));
DONE;
}
}")
(define_insn "" [(set (match_operand:HI 0 "register_operand" "=d") (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))] "" "ldib %1,%0" [(set_attr "type" "load")])
(define_expand "zero_extendhisi2" [(set (match_operand:SI 0 "register_operand" "") (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] "" " { if (GET_CODE (operand1) == REG || (GET_CODE (operand1) == SUBREG && GET_CODE (XEXP (operand1, 0)) == REG)) { rtx temp = gen_reg_rtx (SImode); rtx shift_16 = gen_rtx (CONST_INT, VOIDmode, 16); int op1_subreg_word = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subreg_word = SUBREG_WORD (operand1);
operand1 = SUBREG_REG (operand1);
}
operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
emit_insn (gen_ashlsi3 (temp, operand1, shift_16));
emit_insn (gen_lshrsi3 (operand0, temp, shift_16));
DONE;
}
}")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))] "" "ldos %1,%0" [(set_attr "type" "load")])
;; Using shifts here generates much better code than doing an and 255'. ;; This is mainly because the
and' requires loading the constant separately,
;; the constant is likely to get optimized, and then the compiler can't
;; optimize the `and' because it doesn't know that one operand is a constant.
(define_expand "zero_extendqisi2" [(set (match_operand:SI 0 "register_operand" "") (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] "" " { if (GET_CODE (operand1) == REG || (GET_CODE (operand1) == SUBREG && GET_CODE (XEXP (operand1, 0)) == REG)) { rtx temp = gen_reg_rtx (SImode); rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24); int op1_subreg_word = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subreg_word = SUBREG_WORD (operand1);
operand1 = SUBREG_REG (operand1);
}
operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
emit_insn (gen_lshrsi3 (operand0, temp, shift_24));
DONE;
}
}")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))] "" "ldob %1,%0" [(set_attr "type" "load")])
(define_expand "zero_extendqihi2" [(set (match_operand:HI 0 "register_operand" "") (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] "" " { if (GET_CODE (operand1) == REG || (GET_CODE (operand1) == SUBREG && GET_CODE (XEXP (operand1, 0)) == REG)) { rtx temp = gen_reg_rtx (SImode); rtx shift_24 = gen_rtx (CONST_INT, VOIDmode, 24); int op0_subreg_word = 0; int op1_subreg_word = 0;
if (GET_CODE (operand1) == SUBREG)
{
op1_subreg_word = SUBREG_WORD (operand1);
operand1 = SUBREG_REG (operand1);
}
operand1 = gen_rtx (SUBREG, SImode, operand1, op1_subreg_word);
if (GET_CODE (operand0) == SUBREG)
{
op0_subreg_word = SUBREG_WORD (operand0);
operand0 = SUBREG_REG (operand0);
}
if (GET_MODE (operand0) != SImode)
operand0 = gen_rtx (SUBREG, SImode, operand0, op0_subreg_word);
emit_insn (gen_ashlsi3 (temp, operand1, shift_24));
emit_insn (gen_lshrsi3 (operand0, temp, shift_24));
DONE;
}
}")
(define_insn "" [(set (match_operand:HI 0 "register_operand" "=d") (zero_extend:HI (match_operand:QI 1 "memory_operand" "m")))] "" "ldob %1,%0" [(set_attr "type" "load")]) ;; Conversions between float and double.
(define_insn "extendsfdf2" [(set (match_operand:DF 0 "register_operand" "=*f,d") (float_extend:DF (match_operand:SF 1 "fp_arith_operand" "dGH,fGH")))] "TARGET_NUMERICS" "@ movr %1,%0 movrl %1,%0" [(set_attr "type" "fpmove")])
(define_insn "truncdfsf2" [(set (match_operand:SF 0 "register_operand" "=d") (float_truncate:SF (match_operand:DF 1 "fp_arith_operand" "fGH")))] "TARGET_NUMERICS" "movr %1,%0" [(set_attr "type" "fpmove")])
;; Conversion between fixed point and floating point.
(define_insn "floatsidf2" [(set (match_operand:DF 0 "register_operand" "=f") (float:DF (match_operand:SI 1 "register_operand" "d")))] "TARGET_NUMERICS" "cvtir %1,%0" [(set_attr "type" "fpcvt")])
(define_insn "floatsisf2" [(set (match_operand:SF 0 "register_operand" "=d*f") (float:SF (match_operand:SI 1 "register_operand" "d")))] "TARGET_NUMERICS" "cvtir %1,%0" [(set_attr "type" "fpcvt")])
;; Convert a float to an actual integer. ;; Truncation is performed as part of the conversion. ;; The i960 requires conversion from DFmode to DImode to make ;; unsigned conversions work properly.
(define_insn "fixuns_truncdfdi2" [(set (match_operand:DI 0 "register_operand" "=d") (unsigned_fix:DI (fix:DF (match_operand:DF 1 "fp_arith_operand" "fGH"))))] "TARGET_NUMERICS" "cvtzril %1,%0" [(set_attr "type" "fpcvt")])
(define_insn "fixuns_truncsfdi2" [(set (match_operand:DI 0 "register_operand" "=d") (unsigned_fix:DI (fix:SF (match_operand:SF 1 "fp_arith_operand" "fGH"))))] "TARGET_NUMERICS" "cvtzril %1,%0" [(set_attr "type" "fpcvt")])
(define_insn "fix_truncdfsi2" [(set (match_operand:SI 0 "register_operand" "=d") (fix:SI (fix:DF (match_operand:DF 1 "fp_arith_operand" "fGH"))))] "TARGET_NUMERICS" "cvtzri %1,%0" [(set_attr "type" "fpcvt")])
(define_expand "fixuns_truncdfsi2" [(set (match_operand:SI 0 "register_operand" "") (unsigned_fix:SI (fix:DF (match_operand:DF 1 "fp_arith_operand" ""))))] "TARGET_NUMERICS" " { rtx temp = gen_reg_rtx (DImode); emit_insn (gen_rtx (SET, VOIDmode, temp, gen_rtx (UNSIGNED_FIX, DImode, gen_rtx (FIX, DFmode, operands[1])))); emit_insn (gen_rtx (SET, VOIDmode, operands[0], gen_rtx (SUBREG, SImode, temp, 0))); DONE; }")
(define_insn "fix_truncsfsi2" [(set (match_operand:SI 0 "register_operand" "=d") (fix:SI (fix:SF (match_operand:SF 1 "fp_arith_operand" "dfGH"))))] "TARGET_NUMERICS" "cvtzri %1,%0" [(set_attr "type" "fpcvt")])
(define_expand "fixuns_truncsfsi2" [(set (match_operand:SI 0 "register_operand" "") (unsigned_fix:SI (fix:SF (match_operand:SF 1 "fp_arith_operand" ""))))] "TARGET_NUMERICS" " { rtx temp = gen_reg_rtx (DImode); emit_insn (gen_rtx (SET, VOIDmode, temp, gen_rtx (UNSIGNED_FIX, DImode, gen_rtx (FIX, SFmode, operands[1])))); emit_insn (gen_rtx (SET, VOIDmode, operands[0], gen_rtx (SUBREG, SImode, temp, 0))); DONE; }") ;; Arithmetic instructions.
(define_insn "subsi3" [(set (match_operand:SI 0 "register_operand" "=d") (minus:SI (match_operand:SI 1 "arith_operand" "dI") (match_operand:SI 2 "arith_operand" "dI")))] "" "subo %2,%1,%0")
;; Try to generate an lda instruction when it would be faster than an ;; add instruction. ;; Some assemblers apparently won't accept two addresses added together.
;; ??? The condition should be improved to reject the case of two ;; symbolic constants.
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d,d,d") (plus:SI (match_operand:SI 1 "arith32_operand" "%dn,i,dn") (match_operand:SI 2 "arith32_operand" "dn,dn,i")))] "(TARGET_C_SERIES) && (CONSTANT_P (operands[1]) || CONSTANT_P (operands[2]))" "* { if (GET_CODE (operands[1]) == CONST_INT) { rtx tmp = operands[1]; operands[1] = operands[2]; operands[2] = tmp; } if (GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[1]) == REG && i960_last_insn_type != I_TYPE_REG) { if (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) > -32) return "subo %n2,%1,%0"; else if (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32) return "addo %1,%2,%0"; } /* Non-canonical results (op1 == const, op2 != const) have been seen in reload output when both operands were symbols before reload, so we deal with it here. This may be a fault of the constraints above. */ if (CONSTANT_P (operands[1])) { if (CONSTANT_P (operands[2])) return "lda %1+%2,%0"; else return "lda %1(%2),%0"; } return "lda %2(%1),%0"; }")
(define_insn "addsi3" [(set (match_operand:SI 0 "register_operand" "=d") (plus:SI (match_operand:SI 1 "signed_arith_operand" "%dI") (match_operand:SI 2 "signed_arith_operand" "dIK")))] "" "* { if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) return "subo %n2,%1,%0"; if (i960_bypass (insn, operands[1], operands[2], 0)) return "addo %2,%1,%0"; return "addo %1,%2,%0"; }")
(define_insn "mulsi3" [(set (match_operand:SI 0 "register_operand" "=d") (mult:SI (match_operand:SI 1 "arith_operand" "%dI") (match_operand:SI 2 "arith_operand" "dI")))] "" "* { if (i960_bypass (insn, operands[1], operands[2], 0)) return "mulo %2,%1,%0"; return "mulo %1,%2,%0"; }" [(set_attr "type" "mult")])
(define_insn "umulsidi3" [(set (match_operand:DI 0 "register_operand" "=d") (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "d")) (zero_extend:DI (match_operand:SI 2 "register_operand" "d"))))] "" "* { if (i960_bypass (insn, operands[1], operands[2], 0)) return "emul %2,%1,%0"; return "emul %1,%2,%0"; }" [(set_attr "type" "mult")])
(define_insn "" [(set (match_operand:DI 0 "register_operand" "=d") (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%d")) (match_operand:SI 2 "literal" "I")))] "" "* { if (i960_bypass (insn, operands[1], operands[2], 0)) return "emul %2,%1,%0"; return "emul %1,%2,%0"; }" [(set_attr "type" "mult")])
;; This goes after the move/add/sub/mul instructions
;; because those instructions are better when they apply.
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (match_operand:SI 1 "address_operand" "p"))] "" "lda %a1,%0" [(set_attr "type" "load")])
;; This will never be selected because of an "optimization" that GCC does. ;; It always converts divides by a power of 2 into a sequence of instructions ;; that does a right shift, and then corrects the result if it was negative.
;; (define_insn "" ;; [(set (match_operand:SI 0 "register_operand" "=d") ;; (div:SI (match_operand:SI 1 "arith_operand" "dI") ;; (match_operand:SI 2 "power2_operand" "nI")))] ;; "" ;; "*{ ;; operands[2] = gen_rtx(CONST_INT, VOIDmode,bitpos (INTVAL (operands[2]))); ;; return "shrdi %2,%1,%0"; ;; }"
(define_insn "divsi3" [(set (match_operand:SI 0 "register_operand" "=d") (div:SI (match_operand:SI 1 "arith_operand" "dI") (match_operand:SI 2 "arith_operand" "dI")))] "" "divi %2,%1,%0" [(set_attr "type" "div")])
(define_insn "udivsi3" [(set (match_operand:SI 0 "register_operand" "=d") (udiv:SI (match_operand:SI 1 "arith_operand" "dI") (match_operand:SI 2 "arith_operand" "dI")))] "" "divo %2,%1,%0" [(set_attr "type" "div")])
;; We must use remi' not
modi' here, to ensure that `%' has the effects
;; specified by the ANSI C standard.
(define_insn "modsi3" [(set (match_operand:SI 0 "register_operand" "=d") (mod:SI (match_operand:SI 1 "arith_operand" "dI") (match_operand:SI 2 "arith_operand" "dI")))] "" "remi %2,%1,%0" [(set_attr "type" "div")])
(define_insn "umodsi3" [(set (match_operand:SI 0 "register_operand" "=d") (umod:SI (match_operand:SI 1 "arith_operand" "dI") (match_operand:SI 2 "arith_operand" "dI")))] "" "remo %2,%1,%0" [(set_attr "type" "div")])
;; And instructions (with complement also).
(define_insn "andsi3" [(set (match_operand:SI 0 "register_operand" "=d") (and:SI (match_operand:SI 1 "register_operand" "%d") (match_operand:SI 2 "logic_operand" "dIM")))] "" "* { if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) return "andnot %C2,%1,%0"; if (i960_bypass (insn, operands[1], operands[2], 0)) return "and %2,%1,%0"; return "and %1,%2,%0"; }")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (and:SI (match_operand:SI 1 "arith_operand" "dI") (match_operand:SI 2 "cmplpower2_operand" "n")))] "" "* { operands[2] = gen_rtx (CONST_INT, VOIDmode, bitpos (~INTVAL (operands[2]))); return "clrbit %2,%1,%0"; }")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (and:SI (not:SI (match_operand:SI 1 "register_operand" "d")) (match_operand:SI 2 "logic_operand" "dIM")))] "" "* { if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) return "nor %C2,%1,%0"; if (i960_bypass (insn, operands[1], operands[2], 0)) return "notand %2,%1,%0"; return "andnot %1,%2,%0"; }")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (ior:SI (not:SI (match_operand:SI 1 "register_operand" "%d")) (not:SI (match_operand:SI 2 "register_operand" "d"))))] "" "* { if (i960_bypass (insn, operands[1], operands[2], 0)) return "nand %2,%1,%0"; return "nand %1,%2,%0"; }")
(define_insn "iorsi3" [(set (match_operand:SI 0 "register_operand" "=d") (ior:SI (match_operand:SI 1 "register_operand" "%d") (match_operand:SI 2 "logic_operand" "dIM")))] "" "* { if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) return "ornot %C2,%1,%0"; if (i960_bypass (insn, operands[1], operands[2], 0)) return "or %2,%1,%0"; return "or %1,%2,%0"; }")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (ior:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "power2_operand" "n")))] "" "* { operands[2] = gen_rtx (CONST_INT, VOIDmode, bitpos (INTVAL (operands[2]))); return "setbit %2,%1,%0"; }")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (ior:SI (not:SI (match_operand:SI 1 "register_operand" "d")) (match_operand:SI 2 "logic_operand" "dIM")))] "" "* { if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) return "nand %C2,%1,%0"; if (i960_bypass (insn, operands[1], operands[2], 0)) return "notor %2,%1,%0"; return "ornot %1,%2,%0"; }")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (and:SI (not:SI (match_operand:SI 1 "register_operand" "%d")) (not:SI (match_operand:SI 2 "register_operand" "d"))))] "" "* { if (i960_bypass (insn, operands[1], operands[2], 0)) return "nor %2,%1,%0"; return "nor %1,%2,%0"; }")
(define_insn "xorsi3" [(set (match_operand:SI 0 "register_operand" "=d") (xor:SI (match_operand:SI 1 "register_operand" "%d") (match_operand:SI 2 "logic_operand" "dIM")))] "" "* { if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) return "xnor %C2,%1,%0"; if (i960_bypass (insn, operands[1], operands[2], 0)) return "xor %2,%1,%0"; return "xor %1,%2,%0"; }")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (xor:SI (match_operand:SI 1 "arith_operand" "dI") (match_operand:SI 2 "power2_operand" "n")))] "" "* { operands[2] = gen_rtx (CONST_INT, VOIDmode, bitpos (INTVAL (operands[2]))); return "notbit %2,%1,%0"; }")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (not:SI (xor:SI (match_operand:SI 1 "register_operand" "%d") (match_operand:SI 2 "register_operand" "d"))))] "" "* { if (i960_bypass (insn, operands[1], operands[2], 0)) return "xnor %2,%1,%0"; return "xnor %2,%1,%0"; }")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (ior:SI (ashift:SI (const_int 1) (match_operand:SI 1 "register_operand" "d")) (match_operand:SI 2 "arith_operand" "dI")))] "" "setbit %1,%2,%0")
;; (not (ashift 1 reg)) canonicalizes to (rotate -2 reg) (define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (and:SI (rotate:SI (const_int -2) (match_operand:SI 1 "register_operand" "d")) (match_operand:SI 2 "register_operand" "d")))] "" "clrbit %1,%2,%0")
;; The above pattern canonicalizes to this when both the input and output ;; are the same pseudo-register. (define_insn "" [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "=d") (const_int 1) (match_operand:SI 1 "register_operand" "d")) (const_int 0))] "" "clrbit %1,%0,%0")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (xor:SI (ashift:SI (const_int 1) (match_operand:SI 1 "register_operand" "d")) (match_operand:SI 2 "arith_operand" "dI")))] "" "notbit %1,%2,%0")
(define_insn "negsi2" [(set (match_operand:SI 0 "register_operand" "=d") (neg:SI (match_operand:SI 1 "arith_operand" "dI")))] "" "subo %1,0,%0" [(set_attr "length" "1")])
(define_insn "one_cmplsi2" [(set (match_operand:SI 0 "register_operand" "=d") (not:SI (match_operand:SI 1 "arith_operand" "dI")))] "" "not %1,%0" [(set_attr "length" "1")]) ;; Floating point arithmetic instructions.
(define_insn "adddf3" [(set (match_operand:DF 0 "register_operand" "=d*f") (plus:DF (match_operand:DF 1 "fp_arith_operand" "%rGH") (match_operand:DF 2 "fp_arith_operand" "rGH")))] "TARGET_NUMERICS" "addrl %1,%2,%0" [(set_attr "type" "fpadd")])
(define_insn "addsf3" [(set (match_operand:SF 0 "register_operand" "=d*f") (plus:SF (match_operand:SF 1 "fp_arith_operand" "%rGH") (match_operand:SF 2 "fp_arith_operand" "rGH")))] "TARGET_NUMERICS" "addr %1,%2,%0" [(set_attr "type" "fpadd")])
(define_insn "subdf3" [(set (match_operand:DF 0 "register_operand" "=d*f") (minus:DF (match_operand:DF 1 "fp_arith_operand" "rGH") (match_operand:DF 2 "fp_arith_operand" "rGH")))] "TARGET_NUMERICS" "subrl %2,%1,%0" [(set_attr "type" "fpadd")])
(define_insn "subsf3" [(set (match_operand:SF 0 "register_operand" "=d*f") (minus:SF (match_operand:SF 1 "fp_arith_operand" "rGH") (match_operand:SF 2 "fp_arith_operand" "rGH")))] "TARGET_NUMERICS" "subr %2,%1,%0" [(set_attr "type" "fpadd")])
(define_insn "muldf3" [(set (match_operand:DF 0 "register_operand" "=d*f") (mult:DF (match_operand:DF 1 "fp_arith_operand" "%rGH") (match_operand:DF 2 "fp_arith_operand" "rGH")))] "TARGET_NUMERICS" "mulrl %1,%2,%0" [(set_attr "type" "fpmul")])
(define_insn "mulsf3" [(set (match_operand:SF 0 "register_operand" "=d*f") (mult:SF (match_operand:SF 1 "fp_arith_operand" "%rGH") (match_operand:SF 2 "fp_arith_operand" "rGH")))] "TARGET_NUMERICS" "mulr %1,%2,%0" [(set_attr "type" "fpmul")])
(define_insn "divdf3" [(set (match_operand:DF 0 "register_operand" "=d*f") (div:DF (match_operand:DF 1 "fp_arith_operand" "rGH") (match_operand:DF 2 "fp_arith_operand" "rGH")))] "TARGET_NUMERICS" "divrl %2,%1,%0" [(set_attr "type" "fpdiv")])
(define_insn "divsf3" [(set (match_operand:SF 0 "register_operand" "=d*f") (div:SF (match_operand:SF 1 "fp_arith_operand" "rGH") (match_operand:SF 2 "fp_arith_operand" "rGH")))] "TARGET_NUMERICS" "divr %2,%1,%0" [(set_attr "type" "fpdiv")])
(define_insn "negdf2" [(set (match_operand:DF 0 "register_operand" "=d,df") (neg:DF (match_operand:DF 1 "register_operand" "d,r")))] "" " { if (which_alternative == 0) { if (REGNO (operands[0]) == REGNO (operands[1])) return "notbit 31,%D1,%D0"; return "mov %1,%0;notbit 31,%D1,%D0"; } return "subrl %1,0f0.0,%0"; }" [(set_attr "type" "fpadd")])
(define_insn "negsf2" [(set (match_operand:SF 0 "register_operand" "=d,d*f") (neg:SF (match_operand:SF 1 "register_operand" "d,r")))] "" "@ notbit 31,%1,%0 subr %1,0f0.0,%0" [(set_attr "type" "fpadd")])
;;; The abs patterns also work even if the target machine doesn't have ;;; floating point, because in that case dstreg and srcreg will always be ;;; less than 32.
(define_insn "absdf2" [(set (match_operand:DF 0 "register_operand" "=df") (abs:DF (match_operand:DF 1 "register_operand" "df")))] "" " { int dstreg = REGNO (operands[0]); int srcreg = REGNO (operands[1]);
if (dstreg < 32) { if (srcreg < 32) { if (dstreg != srcreg) output_asm_insn ("mov %1,%0", operands); return "clrbit 31,%D1,%D0"; } /* Src is an fp reg. */ return "movrl %1,%0;clrbit 31,%D1,%D0"; } if (srcreg >= 32) return "cpysre %1,0f0.0,%0"; return "movrl %1,%0;cpysre %0,0f0.0,%0"; }" [(set_attr "type" "multi")])
(define_insn "abssf2" [(set (match_operand:SF 0 "register_operand" "=df") (abs:SF (match_operand:SF 1 "register_operand" "df")))] "" " { int dstreg = REGNO (operands[0]); int srcreg = REGNO (operands[1]);
if (dstreg < 32 && srcreg < 32) return "clrbit 31,%1,%0";
if (dstreg >= 32 && srcreg >= 32) return "cpysre %1,0f0.0,%0";
if (dstreg < 32) return "movr %1,%0;clrbit 31,%0,%0";
return "movr %1,%0;cpysre %0,0f0.0,%0"; }" [(set_attr "type" "multi")]) ;; Tetra (16 byte) float support.
(define_expand "cmpxf" [(set (reg:CC 36) (compare:CC (match_operand:XF 0 "register_operand" "") (match_operand:XF 1 "nonmemory_operand" "")))] "TARGET_NUMERICS" " { i960_compare_op0 = operands[0]; i960_compare_op1 = operands[1]; DONE; }")
(define_insn "" [(set (reg:CC 36) (compare:CC (match_operand:XF 0 "register_operand" "f") (match_operand:XF 1 "nonmemory_operand" "fGH")))] "TARGET_NUMERICS" "cmpr %0,%1" [(set_attr "type" "fpcc")])
(define_expand "movxf" [(set (match_operand:XF 0 "general_operand" "") (match_operand:XF 1 "fpmove_src_operand" ""))] "" " { if (emit_move_sequence (operands, XFmode)) DONE; }")
(define_insn "" [(set (match_operand:XF 0 "general_operand" "=r,f,d,d,m") (match_operand:XF 1 "fpmove_src_operand" "r,GH,F,m,d"))] "register_operand (operands[0], XFmode) || register_operand (operands[1], XFmode)" "* { switch (which_alternative) { case 0: if (FP_REG_P (operands[0]) || FP_REG_P (operands[1])) return "movre %1,%0"; else return "movq %1,%0"; case 1: return "movre %1,%0"; case 2: return i960_output_ldconst (operands[0], operands[1]); case 3: return "ldt %1,%0"; case 4: return "stt %1,%0"; } }" [(set_attr "type" "move,move,load,fpload,fpstore")])
(define_insn "extendsfxf2" [(set (match_operand:XF 0 "register_operand" "=f,d") (float_extend:XF (match_operand:SF 1 "register_operand" "d,f")))] "TARGET_NUMERICS" "@ movr %1,%0 movre %1,%0" [(set_attr "type" "fpmove")])
(define_insn "extenddfxf2" [(set (match_operand:XF 0 "register_operand" "=f,d") (float_extend:XF (match_operand:DF 1 "register_operand" "d,f")))] "TARGET_NUMERICS" "@ movrl %1,%0 movre %1,%0" [(set_attr "type" "fpmove")])
(define_insn "truncxfdf2" [(set (match_operand:DF 0 "register_operand" "=d") (float_truncate:DF (match_operand:XF 1 "register_operand" "f")))] "TARGET_NUMERICS" "movrl %1,%0" [(set_attr "type" "fpmove")])
(define_insn "truncxfsf2" [(set (match_operand:SF 0 "register_operand" "=d") (float_truncate:SF (match_operand:XF 1 "register_operand" "f")))] "TARGET_NUMERICS" "movr %1,%0" [(set_attr "type" "fpmove")])
(define_insn "floatsixf2" [(set (match_operand:XF 0 "register_operand" "=f") (float:XF (match_operand:SI 1 "register_operand" "d")))] "TARGET_NUMERICS" "cvtir %1,%0" [(set_attr "type" "fpcvt")])
(define_insn "fix_truncxfsi2" [(set (match_operand:SI 0 "register_operand" "=d") (fix:SI (fix:XF (match_operand:XF 1 "register_operand" "f"))))] "TARGET_NUMERICS" "cvtzri %1,%0" [(set_attr "type" "fpcvt")])
(define_insn "fixuns_truncxfsi2" [(set (match_operand:SI 0 "register_operand" "=d") (unsigned_fix:SI (fix:XF (match_operand:XF 1 "register_operand" "f"))))] "TARGET_NUMERICS" "cvtzri %1,%0" [(set_attr "type" "fpcvt")])
(define_insn "addxf3" [(set (match_operand:XF 0 "register_operand" "=f") (plus:XF (match_operand:XF 1 "nonmemory_operand" "%fGH") (match_operand:XF 2 "nonmemory_operand" "fGH")))] "TARGET_NUMERICS" "addr %1,%2,%0" [(set_attr "type" "fpadd")])
(define_insn "subxf3" [(set (match_operand:XF 0 "register_operand" "=f") (minus:XF (match_operand:XF 1 "nonmemory_operand" "fGH") (match_operand:XF 2 "nonmemory_operand" "fGH")))] "TARGET_NUMERICS" "subr %2,%1,%0" [(set_attr "type" "fpadd")])
(define_insn "mulxf3" [(set (match_operand:XF 0 "register_operand" "=f") (mult:XF (match_operand:XF 1 "nonmemory_operand" "%fGH") (match_operand:XF 2 "nonmemory_operand" "fGH")))] "TARGET_NUMERICS" "mulr %1,%2,%0" [(set_attr "type" "fpmul")])
(define_insn "divxf3" [(set (match_operand:XF 0 "register_operand" "=f") (div:XF (match_operand:XF 1 "nonmemory_operand" "fGH") (match_operand:XF 2 "nonmemory_operand" "fGH")))] "TARGET_NUMERICS" "divr %2,%1,%0" [(set_attr "type" "fpdiv")])
(define_insn "negxf2" [(set (match_operand:XF 0 "register_operand" "=f") (neg:XF (match_operand:XF 1 "register_operand" "f")))] "TARGET_NUMERICS" "subr %1,0f0.0,%0" [(set_attr "type" "fpadd")])
(define_insn "absxf2" [(set (match_operand:XF 0 "register_operand" "=f") (abs:XF (match_operand:XF 1 "register_operand" "f")))] "(TARGET_NUMERICS)" "cpysre %1,0f0.0,%0" [(set_attr "type" "fpmove")]) ;; Arithmetic shift instructions.
;; The shli instruction generates an overflow fault if the sign changes. ;; In the case of overflow, it does not give the natural result, it instead ;; gives the last shift value before the overflow. We can not use this ;; instruction because gcc thinks that arithmetic left shift and logical ;; left shift are identical, and sometimes canonicalizes the logical left ;; shift to an arithmetic left shift. Therefore we must always use the ;; logical left shift instruction.
(define_insn "ashlsi3" [(set (match_operand:SI 0 "register_operand" "=d") (ashift:SI (match_operand:SI 1 "arith_operand" "dI") (match_operand:SI 2 "arith_operand" "dI")))] "" "shlo %2,%1,%0" [(set_attr "type" "alu2")])
(define_insn "ashrsi3" [(set (match_operand:SI 0 "register_operand" "=d") (ashiftrt:SI (match_operand:SI 1 "arith_operand" "dI") (match_operand:SI 2 "arith_operand" "dI")))] "" "shri %2,%1,%0" [(set_attr "type" "alu2")])
(define_insn "lshrsi3" [(set (match_operand:SI 0 "register_operand" "=d") (lshiftrt:SI (match_operand:SI 1 "arith_operand" "dI") (match_operand:SI 2 "arith_operand" "dI")))] "" "shro %2,%1,%0" [(set_attr "type" "alu2")]) ;; Unconditional and other jump instructions.
(define_insn "jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "" "b %l0" [(set_attr "type" "branch")])
(define_insn "indirect_jump" [(set (pc) (match_operand:SI 0 "address_operand" "p"))] "" "bx %a0" [(set_attr "type" "branch")])
(define_insn "tablejump" [(set (pc) (match_operand:SI 0 "register_operand" "d")) (use (label_ref (match_operand 1 "" "")))] "" "bx (%0)" [(set_attr "type" "branch")])
;;- jump to subroutine
(define_expand "call" [(call (match_operand:SI 0 "memory_operand" "m") (match_operand:SI 1 "immediate_operand" "i"))] "" " { emit_insn (gen_call_internal (operands[0], operands[1], virtual_outgoing_args_rtx)); DONE; }")
;; We need a call saved register allocated for the match_scratch, so we use ;; 'l' because all local registers are call saved.
;; ??? I would prefer to use a match_scratch here, but match_scratch allocated ;; registers can't be used for spills. In a function with lots of calls, ;; local-alloc may allocate all local registers to a match_scratch, leaving ;; no local registers available for spills.
(define_insn "call_internal" [(call (match_operand:SI 0 "memory_operand" "m") (match_operand:SI 1 "immediate_operand" "i")) (use (match_operand:SI 2 "address_operand" "p")) (clobber (reg:SI 19))] "" "* return i960_output_call_insn (operands[0], operands[1], operands[2], insn);" [(set_attr "type" "call")])
(define_expand "call_value" [(set (match_operand 0 "register_operand" "=d") (call (match_operand:SI 1 "memory_operand" "m") (match_operand:SI 2 "immediate_operand" "i")))] "" " { emit_insn (gen_call_value_internal (operands[0], operands[1], operands[2], virtual_outgoing_args_rtx)); DONE; }")
;; We need a call saved register allocated for the match_scratch, so we use ;; 'l' because all local registers are call saved.
(define_insn "call_value_internal" [(set (match_operand 0 "register_operand" "=d") (call (match_operand:SI 1 "memory_operand" "m") (match_operand:SI 2 "immediate_operand" "i"))) (use (match_operand:SI 3 "address_operand" "p")) (clobber (reg:SI 19))] "" "* return i960_output_call_insn (operands[1], operands[2], operands[3], insn);" [(set_attr "type" "call")])
(define_insn "return" [(return)] "" "* return i960_output_ret_insn (insn);" [(set_attr "type" "branch")])
(define_insn "nop" [(const_int 0)] "" "") ;; Various peephole optimizations for multiple-word moves, loads, and stores. ;; Multiple register moves.
;; Matched 5/28/91 (define_peephole [(set (match_operand:SI 0 "register_operand" "=r") (match_operand:SI 1 "register_operand" "r")) (set (match_operand:SI 2 "register_operand" "=r") (match_operand:SI 3 "register_operand" "r")) (set (match_operand:SI 4 "register_operand" "=r") (match_operand:SI 5 "register_operand" "r")) (set (match_operand:SI 6 "register_operand" "=r") (match_operand:SI 7 "register_operand" "r"))] "((REGNO (operands[0]) & 3) == 0) && ((REGNO (operands[1]) & 3) == 0) && (REGNO (operands[0]) + 1 == REGNO (operands[2])) && (REGNO (operands[1]) + 1 == REGNO (operands[3])) && (REGNO (operands[0]) + 2 == REGNO (operands[4])) && (REGNO (operands[1]) + 2 == REGNO (operands[5])) && (REGNO (operands[0]) + 3 == REGNO (operands[6])) && (REGNO (operands[1]) + 3 == REGNO (operands[7]))" "movq %1,%0")
;; Matched 4/17/92 (define_peephole [(set (match_operand:DI 0 "register_operand" "=r") (match_operand:DI 1 "register_operand" "r")) (set (match_operand:DI 2 "register_operand" "=r") (match_operand:DI 3 "register_operand" "r"))] "((REGNO (operands[0]) & 3) == 0) && ((REGNO (operands[1]) & 3) == 0) && (REGNO (operands[0]) + 2 == REGNO (operands[2])) && (REGNO (operands[1]) + 2 == REGNO (operands[3]))" "movq %1,%0")
;; Matched 4/17/92 (define_peephole [(set (match_operand:DI 0 "register_operand" "=r") (match_operand:DI 1 "register_operand" "r")) (set (match_operand:SI 2 "register_operand" "=r") (match_operand:SI 3 "register_operand" "r")) (set (match_operand:SI 4 "register_operand" "=r") (match_operand:SI 5 "register_operand" "r"))] "((REGNO (operands[0]) & 3) == 0) && ((REGNO (operands[1]) & 3) == 0) && (REGNO (operands[0]) + 2 == REGNO (operands[2])) && (REGNO (operands[1]) + 2 == REGNO (operands[3])) && (REGNO (operands[0]) + 3 == REGNO (operands[4])) && (REGNO (operands[1]) + 3 == REGNO (operands[5]))" "movq %1,%0")
;; Matched 4/17/92 (define_peephole [(set (match_operand:SI 0 "register_operand" "=r") (match_operand:SI 1 "register_operand" "r")) (set (match_operand:SI 2 "register_operand" "=r") (match_operand:SI 3 "register_operand" "r")) (set (match_operand:DI 4 "register_operand" "=r") (match_operand:DI 5 "register_operand" "r"))] "((REGNO (operands[0]) & 3) == 0) && ((REGNO (operands[1]) & 3) == 0) && (REGNO (operands[0]) + 1 == REGNO (operands[2])) && (REGNO (operands[1]) + 1 == REGNO (operands[3])) && (REGNO (operands[0]) + 2 == REGNO (operands[4])) && (REGNO (operands[1]) + 2 == REGNO (operands[5]))" "movq %1,%0")
;; Matched 4/17/92 (define_peephole [(set (match_operand:DI 0 "register_operand" "=r") (match_operand:DI 1 "register_operand" "r")) (set (match_operand:SI 2 "register_operand" "=r") (match_operand:SI 3 "register_operand" "r"))] "((REGNO (operands[0]) & 3) == 0) && ((REGNO (operands[1]) & 3) == 0) && (REGNO (operands[0]) + 2 == REGNO (operands[2])) && (REGNO (operands[1]) + 2 == REGNO (operands[3]))" "movt %1,%0")
;; Matched 5/28/91 (define_peephole [(set (match_operand:SI 0 "register_operand" "=r") (match_operand:SI 1 "register_operand" "r")) (set (match_operand:SI 2 "register_operand" "=r") (match_operand:SI 3 "register_operand" "r")) (set (match_operand:SI 4 "register_operand" "=r") (match_operand:SI 5 "register_operand" "r"))] "((REGNO (operands[0]) & 3) == 0) && ((REGNO (operands[1]) & 3) == 0) && (REGNO (operands[0]) + 1 == REGNO (operands[2])) && (REGNO (operands[1]) + 1 == REGNO (operands[3])) && (REGNO (operands[0]) + 2 == REGNO (operands[4])) && (REGNO (operands[1]) + 2 == REGNO (operands[5]))" "movt %1,%0")
;; Matched 5/28/91 (define_peephole [(set (match_operand:SI 0 "register_operand" "=r") (match_operand:SI 1 "register_operand" "r")) (set (match_operand:SI 2 "register_operand" "=r") (match_operand:SI 3 "register_operand" "r"))] "((REGNO (operands[0]) & 1) == 0) && ((REGNO (operands[1]) & 1) == 0) && (REGNO (operands[0]) + 1 == REGNO (operands[2])) && (REGNO (operands[1]) + 1 == REGNO (operands[3]))" "movl %1,%0") ; Multiple register loads.
;; Matched 6/15/91 (define_peephole [(set (match_operand:SI 0 "register_operand" "=r") (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r") (match_operand:SI 2 "immediate_operand" "n")))) (set (match_operand:SI 3 "register_operand" "=r") (mem:SI (plus:SI (match_dup 1) (match_operand:SI 4 "immediate_operand" "n")))) (set (match_operand:SI 5 "register_operand" "=r") (mem:SI (plus:SI (match_dup 1) (match_operand:SI 6 "immediate_operand" "n")))) (set (match_operand:SI 7 "register_operand" "=r") (mem:SI (plus:SI (match_dup 1) (match_operand:SI 8 "immediate_operand" "n"))))] "(i960_si_ti (operands[1], operands[2]) && ((REGNO (operands[0]) & 3) == 0) && (REGNO (operands[1]) != REGNO (operands[0])) && (REGNO (operands[0]) + 1 == REGNO (operands[3])) && (REGNO (operands[1]) != REGNO (operands[3])) && (REGNO (operands[0]) + 2 == REGNO (operands[5])) && (REGNO (operands[1]) != REGNO (operands[5])) && (REGNO (operands[0]) + 3 == REGNO (operands[7])) && (INTVAL (operands[2]) + 4 == INTVAL (operands[4])) && (INTVAL (operands[2]) + 8 == INTVAL (operands[6])) && (INTVAL (operands[2]) + 12 == INTVAL (operands[8])))" "ldq %2(%1),%0")
;; Matched 5/28/91 (define_peephole [(set (match_operand:DF 0 "register_operand" "=d") (mem:DF (plus:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "immediate_operand" "n")))) (set (match_operand:DF 3 "register_operand" "=d") (mem:DF (plus:SI (match_dup 1) (match_operand:SI 4 "immediate_operand" "n"))))] "(i960_si_ti (operands[1], operands[2]) && ((REGNO (operands[0]) & 3) == 0) && (REGNO (operands[1]) != REGNO (operands[0])) && (REGNO (operands[0]) + 2 == REGNO (operands[3])) && (REGNO (operands[1]) != REGNO (operands[3])) && (INTVAL (operands[2]) + 8 == INTVAL (operands[4])))" "ldq %2(%1),%0")
;; Matched 1/24/92 (define_peephole [(set (match_operand:DI 0 "register_operand" "=d") (mem:DI (plus:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "immediate_operand" "n")))) (set (match_operand:DI 3 "register_operand" "=d") (mem:DI (plus:SI (match_dup 1) (match_operand:SI 4 "immediate_operand" "n"))))] "(i960_si_ti (operands[1], operands[2]) && ((REGNO (operands[0]) & 3) == 0) && (REGNO (operands[1]) != REGNO (operands[0])) && (REGNO (operands[0]) + 2 == REGNO (operands[3])) && (REGNO (operands[1]) != REGNO (operands[3])) && (INTVAL (operands[2]) + 8 == INTVAL (operands[4])))" "ldq %2(%1),%0")
;; Matched 4/17/92 (define_peephole [(set (match_operand:SI 0 "register_operand" "=d") (mem:SI (match_operand:SI 1 "register_operand" "d"))) (set (match_operand:SI 2 "register_operand" "=d") (mem:SI (plus:SI (match_dup 1) (match_operand:SI 3 "immediate_operand" "n")))) (set (match_operand:SI 4 "register_operand" "=d") (mem:SI (plus:SI (match_dup 1) (match_operand:SI 5 "immediate_operand" "n")))) (set (match_operand:SI 6 "register_operand" "=d") (mem:SI (plus:SI (match_dup 1) (match_operand:SI 7 "immediate_operand" "n"))))] "(i960_si_ti (operands[1], 0) && ((REGNO (operands[0]) & 3) == 0) && (REGNO (operands[1]) != REGNO (operands[0])) && (REGNO (operands[0]) + 1 == REGNO (operands[2])) && (REGNO (operands[1]) != REGNO (operands[2])) && (REGNO (operands[0]) + 2 == REGNO (operands[4])) && (REGNO (operands[1]) != REGNO (operands[4])) && (REGNO (operands[0]) + 3 == REGNO (operands[6])) && (INTVAL (operands[3]) == 4) && (INTVAL (operands[5]) == 8) && (INTVAL (operands[7]) == 12))" "ldq (%1),%0")
;; Matched 5/28/91 (define_peephole [(set (match_operand:SI 0 "register_operand" "=d") (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "immediate_operand" "n")))) (set (match_operand:SI 3 "register_operand" "=d") (mem:SI (plus:SI (match_dup 1) (match_operand:SI 4 "immediate_operand" "n")))) (set (match_operand:SI 5 "register_operand" "=d") (mem:SI (plus:SI (match_dup 1) (match_operand:SI 6 "immediate_operand" "n"))))] "(i960_si_ti (operands[1], operands[2]) && ((REGNO (operands[0]) & 3) == 0) && (REGNO (operands[1]) != REGNO (operands[0])) && (REGNO (operands[0]) + 1 == REGNO (operands[3])) && (REGNO (operands[1]) != REGNO (operands[3])) && (REGNO (operands[0]) + 2 == REGNO (operands[5])) && (INTVAL (operands[2]) + 4 == INTVAL (operands[4])) && (INTVAL (operands[2]) + 8 == INTVAL (operands[6])))" "ldt %2(%1),%0")
;; Matched 6/15/91 (define_peephole [(set (match_operand:SI 0 "register_operand" "=d") (mem:SI (match_operand:SI 1 "register_operand" "d"))) (set (match_operand:SI 2 "register_operand" "=d") (mem:SI (plus:SI (match_dup 1) (match_operand:SI 3 "immediate_operand" "n")))) (set (match_operand:SI 4 "register_operand" "=d") (mem:SI (plus:SI (match_dup 1) (match_operand:SI 5 "immediate_operand" "n"))))] "(i960_si_ti (operands[1], 0) && ((REGNO (operands[0]) & 3) == 0) && (REGNO (operands[1]) != REGNO (operands[0])) && (REGNO (operands[0]) + 1 == REGNO (operands[2])) && (REGNO (operands[1]) != REGNO (operands[2])) && (REGNO (operands[0]) + 2 == REGNO (operands[4])) && (INTVAL (operands[3]) == 4) && (INTVAL (operands[5]) == 8))" "ldt (%1),%0")
;; Matched 5/28/91 (define_peephole [(set (match_operand:SI 0 "register_operand" "=d") (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "immediate_operand" "n")))) (set (match_operand:SI 3 "register_operand" "=d") (mem:SI (plus:SI (match_dup 1) (match_operand:SI 4 "immediate_operand" "n"))))] "(i960_si_di (operands[1], operands[2]) && ((REGNO (operands[0]) & 1) == 0) && (REGNO (operands[1]) != REGNO (operands[0])) && (REGNO (operands[0]) + 1 == REGNO (operands[3])) && (INTVAL (operands[2]) + 4 == INTVAL (operands[4])))" "ldl %2(%1),%0")
;; Matched 5/28/91 (define_peephole [(set (match_operand:SI 0 "register_operand" "=d") (mem:SI (match_operand:SI 1 "register_operand" "d"))) (set (match_operand:SI 2 "register_operand" "=d") (mem:SI (plus:SI (match_dup 1) (match_operand:SI 3 "immediate_operand" "n"))))] "(i960_si_di (operands[1], 0) && ((REGNO (operands[0]) & 1) == 0) && (REGNO (operands[1]) != REGNO (operands[0])) && (REGNO (operands[0]) + 1 == REGNO (operands[2])) && (INTVAL (operands[3]) == 4))" "ldl (%1),%0") ; Multiple register stores.
;; Matched 5/28/91 (define_peephole [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "d") (match_operand:SI 1 "immediate_operand" "n"))) (match_operand:SI 2 "register_operand" "d")) (set (mem:SI (plus:SI (match_dup 0) (match_operand:SI 3 "immediate_operand" "n"))) (match_operand:SI 4 "register_operand" "d")) (set (mem:SI (plus:SI (match_dup 0) (match_operand:SI 5 "immediate_operand" "n"))) (match_operand:SI 6 "register_operand" "d")) (set (mem:SI (plus:SI (match_dup 0) (match_operand:SI 7 "immediate_operand" "n"))) (match_operand:SI 8 "register_operand" "d"))] "(i960_si_ti (operands[0], operands[1]) && ((REGNO (operands[2]) & 3) == 0) && (REGNO (operands[2]) + 1 == REGNO (operands[4])) && (REGNO (operands[2]) + 2 == REGNO (operands[6])) && (REGNO (operands[2]) + 3 == REGNO (operands[8])) && (INTVAL (operands[1]) + 4 == INTVAL (operands[3])) && (INTVAL (operands[1]) + 8 == INTVAL (operands[5])) && (INTVAL (operands[1]) + 12 == INTVAL (operands[7])))" "stq %2,%1(%0)")
;; Matched 6/16/91 (define_peephole [(set (mem:DF (plus:SI (match_operand:SI 0 "register_operand" "d") (match_operand:SI 1 "immediate_operand" "n"))) (match_operand:DF 2 "register_operand" "d")) (set (mem:DF (plus:SI (match_dup 0) (match_operand:SI 3 "immediate_operand" "n"))) (match_operand:DF 4 "register_operand" "d"))] "(i960_si_ti (operands[0], operands[1]) && ((REGNO (operands[2]) & 3) == 0) && (REGNO (operands[2]) + 2 == REGNO (operands[4])) && (INTVAL (operands[1]) + 8 == INTVAL (operands[3])))" "stq %2,%1(%0)")
;; Matched 4/17/92 (define_peephole [(set (mem:DI (plus:SI (match_operand:SI 0 "register_operand" "d") (match_operand:SI 1 "immediate_operand" "n"))) (match_operand:DI 2 "register_operand" "d")) (set (mem:DI (plus:SI (match_dup 0) (match_operand:SI 3 "immediate_operand" "n"))) (match_operand:DI 4 "register_operand" "d"))] "(i960_si_ti (operands[0], operands[1]) && ((REGNO (operands[2]) & 3) == 0) && (REGNO (operands[2]) + 2 == REGNO (operands[4])) && (INTVAL (operands[1]) + 8 == INTVAL (operands[3])))" "stq %2,%1(%0)")
;; Matched 1/23/92 (define_peephole [(set (mem:SI (match_operand:SI 0 "register_operand" "d")) (match_operand:SI 1 "register_operand" "d")) (set (mem:SI (plus:SI (match_dup 0) (match_operand:SI 2 "immediate_operand" "n"))) (match_operand:SI 3 "register_operand" "d")) (set (mem:SI (plus:SI (match_dup 0) (match_operand:SI 4 "immediate_operand" "n"))) (match_operand:SI 5 "register_operand" "d")) (set (mem:SI (plus:SI (match_dup 0) (match_operand:SI 6 "immediate_operand" "n"))) (match_operand:SI 7 "register_operand" "d"))] "(i960_si_ti (operands[0], 0) && ((REGNO (operands[1]) & 3) == 0) && (REGNO (operands[1]) + 1 == REGNO (operands[3])) && (REGNO (operands[1]) + 2 == REGNO (operands[5])) && (REGNO (operands[1]) + 3 == REGNO (operands[7])) && (INTVAL (operands[2]) == 4) && (INTVAL (operands[4]) == 8) && (INTVAL (operands[6]) == 12))" "stq %1,(%0)")
;; Matched 5/29/91 (define_peephole [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "d") (match_operand:SI 1 "immediate_operand" "n"))) (match_operand:SI 2 "register_operand" "d")) (set (mem:SI (plus:SI (match_dup 0) (match_operand:SI 3 "immediate_operand" "n"))) (match_operand:SI 4 "register_operand" "d")) (set (mem:SI (plus:SI (match_dup 0) (match_operand:SI 5 "immediate_operand" "n"))) (match_operand:SI 6 "register_operand" "d"))] "(i960_si_ti (operands[0], operands[1]) && ((REGNO (operands[2]) & 3) == 0) && (REGNO (operands[2]) + 1 == REGNO (operands[4])) && (REGNO (operands[2]) + 2 == REGNO (operands[6])) && (INTVAL (operands[1]) + 4 == INTVAL (operands[3])) && (INTVAL (operands[1]) + 8 == INTVAL (operands[5])))" "stt %2,%1(%0)")
;; Matched 5/29/91 (define_peephole [(set (mem:SI (match_operand:SI 0 "register_operand" "d")) (match_operand:SI 1 "register_operand" "d")) (set (mem:SI (plus:SI (match_dup 0) (match_operand:SI 2 "immediate_operand" "n"))) (match_operand:SI 3 "register_operand" "d")) (set (mem:SI (plus:SI (match_dup 0) (match_operand:SI 4 "immediate_operand" "n"))) (match_operand:SI 5 "register_operand" "d"))] "(i960_si_ti (operands[0], 0) && ((REGNO (operands[1]) & 3) == 0) && (REGNO (operands[1]) + 1 == REGNO (operands[3])) && (REGNO (operands[1]) + 2 == REGNO (operands[5])) && (INTVAL (operands[2]) == 4) && (INTVAL (operands[4]) == 8))" "stt %1,(%0)")
;; Matched 5/28/91 (define_peephole [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "d") (match_operand:SI 1 "immediate_operand" "n"))) (match_operand:SI 2 "register_operand" "d")) (set (mem:SI (plus:SI (match_dup 0) (match_operand:SI 3 "immediate_operand" "n"))) (match_operand:SI 4 "register_operand" "d"))] "(i960_si_di (operands[0], operands[1]) && ((REGNO (operands[2]) & 1) == 0) && (REGNO (operands[2]) + 1 == REGNO (operands[4])) && (INTVAL (operands[1]) + 4 == INTVAL (operands[3])))" "stl %2,%1(%0)")
;; Matched 5/28/91 (define_peephole [(set (mem:SI (match_operand:SI 0 "register_operand" "d")) (match_operand:SI 1 "register_operand" "d")) (set (mem:SI (plus:SI (match_dup 0) (match_operand:SI 2 "immediate_operand" "n"))) (match_operand:SI 3 "register_operand" "d"))] "(i960_si_di (operands[0], 0) && ((REGNO (operands[1]) & 1) == 0) && (REGNO (operands[1]) + 1 == REGNO (operands[3])) && (INTVAL (operands[2]) == 4))" "stl %1,(%0)")