;;- Machine description for Intel 80960 chip for GNU C compiler ;; Copyright (C) 1992, 1995 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") (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 "memory_operand" "=m") (match_operand:DI 1 "register_operand" "d")) (clobber (match_scratch:SI 2 "=&d"))] "" "* { 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" "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 "memory_operand" "=m") (match_operand:TI 1 "register_operand" "d")) (clobber (match_scratch:SI 2 "=&d"))] "" "* { 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" "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. (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\"; } if (CONSTANT_P (operands[1])) 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 "arith_operand" "%dI") (match_operand:SI 2 "arith_operand" "dI")))] "" "* { 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 (not: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 \"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 "arith_operand" "%dI")) (not:SI (match_operand:SI 2 "arith_operand" "dI"))))] "" "* { if (i960_bypass (insn, operands[1], operands[2], 0)) return \"nand %2,%1,%0\"; return \"nand %1,%2,%0\"; }") (define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (ior: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 \"setbit %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") (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\"; }") ;; (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 (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") (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 "iorsi3" [(set (match_operand:SI 0 "register_operand" "=d") (ior: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 \"or %2,%1,%0\"; return \"or %1,%2,%0\"; }") (define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (ior:SI (not: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 \"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 "arith_operand" "%dI")) (not:SI (match_operand:SI 2 "arith_operand" "dI"))))] "" "* { 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 "arith_operand" "%dI") (match_operand:SI 2 "arith_operand" "dI")))] "" "* { 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") (not:SI (xor: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 \"xnor %2,%1,%0\"; return \"xnor %2,%1,%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,d*f") (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" "=d*f") (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" "=d*f") (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)")