mirror of
https://github.com/pmret/gcc-papermario.git
synced 2024-09-19 23:31:33 +02:00
2680 lines
79 KiB
Markdown
2680 lines
79 KiB
Markdown
|
;;- 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,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)")
|