b4aee14e5a
From-SVN: r1908
2713 lines
76 KiB
Markdown
2713 lines
76 KiB
Markdown
;;- Machine description for AMD Am29000 for GNU C compiler
|
||
;; Copyright (C) 1991 Free Software Foundation, Inc.
|
||
;; Contributed by Richard Kenner (kenner@nyu.edu)
|
||
|
||
;; This file is part of GNU CC.
|
||
|
||
;; GNU CC is free software; you can redistribute it and/or modify
|
||
;; it under the terms of the GNU General Public License as published by
|
||
;; the Free Software Foundation; either version 2, or (at your option)
|
||
;; any later version.
|
||
|
||
;; GNU CC is distributed in the hope that it will be useful,
|
||
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
;; GNU General Public License for more details.
|
||
|
||
;; You should have received a copy of the GNU General Public License
|
||
;; along with GNU CC; see the file COPYING. If not, write to
|
||
;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||
|
||
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
|
||
|
||
;; The insns in this file are presented in the same order as the AMD 29000
|
||
;; User's Manual (i.e., alphabetical by machine op-code).
|
||
;;
|
||
;; DEFINE_EXPAND's are located near the first occurrence of the major insn
|
||
;; that they generate.
|
||
|
||
;; The only attribute we have is the type. We only care about calls, branches,
|
||
;; loads, stores, floating-point operations, and multi-word insns.
|
||
;; Everything else is miscellaneous.
|
||
|
||
(define_attr "type"
|
||
"call,branch,load,store,fadd,fmul,fam,fdiv,dmul,dam,ddiv,multi,misc"
|
||
(const_string "misc"))
|
||
|
||
;; ASM insns cannot go into a delay slot, so call them "multi".
|
||
(define_asm_attributes [(set_attr "type" "multi")])
|
||
|
||
(define_attr "in_delay_slot" "yes,no"
|
||
(if_then_else (eq_attr "type" "call,branch,multi") (const_string "no")
|
||
(const_string "yes")))
|
||
|
||
;; Branch and call insns require a single delay slot. Annulling is not
|
||
;; supported.
|
||
(define_delay (eq_attr "type" "call,branch")
|
||
[(eq_attr "in_delay_slot" "yes") (nil) (nil)])
|
||
|
||
;; Define the function unit usages. We first define memory as a unit.
|
||
(define_function_unit "memory" 1 2 (eq_attr "type" "load") 6 11)
|
||
(define_function_unit "memory" 1 2 (eq_attr "type" "store") 1 0)
|
||
|
||
;; Now define the function units for the floating-point support. Most
|
||
;; units are pipelined and can accept an input every cycle.
|
||
;;
|
||
;; Note that we have an inaccuracy here. If a fmac insn is issued, followed
|
||
;; 2 cycles later by a fadd, there will be a conflict for the floating
|
||
;; adder that we can't represent. Also, all insns will conflict for the
|
||
;; floating-point rounder. It isn't clear how to represent this.
|
||
|
||
(define_function_unit "multiplier" 1 0 (eq_attr "type" "fmul") 3 0)
|
||
(define_function_unit "multiplier" 1 0 (eq_attr "type" "dmul") 6 8)
|
||
(define_function_unit "multiplier" 1 0 (eq_attr "type" "fam") 6 8)
|
||
(define_function_unit "multiplier" 1 0 (eq_attr "type" "dam") 9 8)
|
||
|
||
(define_function_unit "adder" 1 0 (eq_attr "type" "fadd,fam,dam") 3 0)
|
||
|
||
(define_function_unit "divider" 1 1 (eq_attr "type" "fdiv") 11 20)
|
||
(define_function_unit "divider" 1 1 (eq_attr "type" "ddiv") 18 34)
|
||
|
||
;; ADD
|
||
(define_insn "addsi3"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
|
||
(plus:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r")
|
||
(match_operand:SI 2 "add_operand" "rI,N")))]
|
||
""
|
||
"@
|
||
add %0,%1,%2
|
||
sub %0,%1,%n2")
|
||
|
||
(define_insn "adddi3"
|
||
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
|
||
(plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
|
||
(match_operand:DI 2 "gpc_reg_operand" "r")))]
|
||
""
|
||
"add %L0,%L1,%L2\;addc %0,%1,%2"
|
||
[(set_attr "type" "multi")])
|
||
|
||
;; AND/ANDN
|
||
(define_insn "andsi3"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
|
||
(and:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r")
|
||
(match_operand:SI 2 "and_operand" "rI,K")))]
|
||
""
|
||
"@
|
||
and %0,%1,%2
|
||
andn %0,%1,%C2")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(and:SI (not:SI (match_operand:SI 1 "srcb_operand" "rI"))
|
||
(match_operand:SI 2 "gpc_reg_operand" "r")))]
|
||
""
|
||
"andn %0,%2,%1")
|
||
|
||
|
||
;; CALLI
|
||
;;
|
||
;; Start with a subroutine to write out CLOBBERs starting at lr2 up to,
|
||
;; but not including, the next parameter register. If operand[0] is null,
|
||
;; it means that all the argument registers have been used.
|
||
(define_expand "clobbers_to"
|
||
[(clobber (match_operand:SI 0 "" ""))]
|
||
""
|
||
"
|
||
{
|
||
int i;
|
||
int high_regno;
|
||
|
||
if (operands[0] == 0)
|
||
high_regno = R_LR (18);
|
||
else if (GET_CODE (operands[0]) != REG || REGNO (operands[0]) < R_LR (0)
|
||
|| REGNO (operands[0]) > R_LR (18))
|
||
abort ();
|
||
else
|
||
high_regno = REGNO (operands[0]);
|
||
|
||
for (i = R_LR (2); i < high_regno; i++)
|
||
emit_insn (gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, i)));
|
||
|
||
DONE;
|
||
}")
|
||
|
||
(define_expand "call"
|
||
[(parallel [(call (match_operand:SI 0 "" "")
|
||
(match_operand 1 "" ""))
|
||
(clobber (reg:SI 32))])
|
||
(match_operand 2 "" "")]
|
||
""
|
||
"
|
||
{
|
||
if (GET_CODE (operands[0]) != MEM)
|
||
abort ();
|
||
|
||
if (! TARGET_SMALL_MEMORY
|
||
&& GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
|
||
operands[0] = gen_rtx (MEM, GET_MODE (operands[0]),
|
||
force_reg (Pmode, XEXP (operands[0], 0)));
|
||
|
||
operands[2] = gen_clobbers_to (operands[2]);
|
||
}")
|
||
|
||
(define_insn ""
|
||
[(call (match_operand:SI 0 "memory_operand" "m")
|
||
(match_operand 1 "" ""))
|
||
(clobber (reg:SI 32))]
|
||
""
|
||
"calli lr0,%0%#"
|
||
[(set_attr "type" "call")])
|
||
|
||
(define_expand "call_value"
|
||
[(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(call (match_operand:SI 1 "" "")
|
||
(match_operand 2 "" "")))
|
||
(clobber (reg:SI 32))])
|
||
(match_operand 3 "" "")]
|
||
""
|
||
"
|
||
{
|
||
if (GET_CODE (operands[1]) != MEM)
|
||
abort ();
|
||
|
||
if (! TARGET_SMALL_MEMORY
|
||
&& GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
|
||
operands[1] = gen_rtx (MEM, GET_MODE (operands[1]),
|
||
force_reg (Pmode, XEXP (operands[1], 0)));
|
||
|
||
operands[3] = gen_clobbers_to (operands[3]);
|
||
}")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand 0 "gpc_reg_operand" "=r")
|
||
(call (match_operand:SI 1 "memory_operand" "m")
|
||
(match_operand 2 "" "")))
|
||
(clobber (reg:SI 32))]
|
||
""
|
||
"calli lr0,%1%#"
|
||
[(set_attr "type" "call")])
|
||
|
||
(define_insn ""
|
||
[(call (mem:SI (match_operand:SI 0 "immediate_operand" "i"))
|
||
(match_operand:SI 1 "general_operand" "g"))
|
||
(clobber (reg:SI 32))]
|
||
"GET_CODE (operands[0]) == SYMBOL_REF
|
||
&& (TARGET_SMALL_MEMORY
|
||
|| ! strcmp (XSTR (operands[0], 0), current_function_name))"
|
||
"call lr0,%F0"
|
||
[(set_attr "type" "call")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand 0 "gpc_reg_operand" "=r")
|
||
(call (mem:SI (match_operand:SI 1 "immediate_operand" "i"))
|
||
(match_operand:SI 2 "general_operand" "g")))
|
||
(clobber (reg:SI 32))]
|
||
"GET_CODE (operands[1]) == SYMBOL_REF
|
||
&& (TARGET_SMALL_MEMORY
|
||
|| ! strcmp (XSTR (operands[1], 0), current_function_name))"
|
||
"call lr0,%F1"
|
||
[(set_attr "type" "call")])
|
||
|
||
(define_expand "probe"
|
||
[(call (mem:SI (symbol_ref:SI "_msp_check"))
|
||
(const_int 1))]
|
||
"TARGET_STACK_CHECK"
|
||
"")
|
||
|
||
;; This is used for internal routine calls via TPC. Currently used only
|
||
;; in probe, above.
|
||
(define_insn ""
|
||
[(call (mem:SI (match_operand:SI 0 "immediate_operand" "s"))
|
||
(const_int 1))]
|
||
""
|
||
"call %*,%0"
|
||
[(set_attr "type" "call")])
|
||
|
||
;; CONST, CONSTH, CONSTN
|
||
;;
|
||
;; Many of these are generated from move insns.
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(and:SI (match_operand:SI 1 "immediate_operand" "i")
|
||
(const_int 65535)))]
|
||
""
|
||
"const %0,%1")
|
||
|
||
(define_insn ""
|
||
[(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
|
||
(const_int 16)
|
||
(match_operand:SI 1 "const_0_operand" ""))
|
||
(ashiftrt:SI (match_operand:SI 2 "immediate_operand" "i")
|
||
(const_int 16)))]
|
||
""
|
||
"consth %0,%2")
|
||
|
||
(define_insn ""
|
||
[(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
|
||
(const_int 16)
|
||
(match_operand:SI 1 "const_0_operand" ""))
|
||
(match_operand:SI 2 "cint_16_operand" "J"))]
|
||
""
|
||
"*
|
||
{ operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) << 16);
|
||
return \"consth %0,%2\";
|
||
}")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(ior:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "0")
|
||
(const_int 65535))
|
||
(match_operand:SI 2 "const_int_operand" "n")))]
|
||
"(INTVAL (operands[1]) & 0xffff) == 0"
|
||
"consth %0,%2")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(ior:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "0")
|
||
(const_int 65535))
|
||
(and:SI (match_operand:SI 2 "immediate_operand" "i")
|
||
(const_int -65536))))]
|
||
""
|
||
"consth %0,%2")
|
||
|
||
|
||
;; CONVERT
|
||
(define_insn "fix_truncsfsi2"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(fix:SI (match_operand:SF 1 "register_operand" "r")))]
|
||
""
|
||
"convert %0,%1,0,3,0,1")
|
||
|
||
(define_insn "fix_truncdfsi2"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(fix:SI (match_operand:DF 1 "register_operand" "r")))]
|
||
""
|
||
"convert %0,%1,0,3,0,2")
|
||
|
||
(define_insn "fixuns_truncsfsi2"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(unsigned_fix:SI (match_operand:SF 1 "register_operand" "r")))]
|
||
""
|
||
"convert %0,%1,1,3,0,1")
|
||
|
||
(define_insn "fixuns_truncdfsi2"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(unsigned_fix:SI (match_operand:DF 1 "register_operand" "r")))]
|
||
""
|
||
"convert %0,%1,1,3,0,2")
|
||
|
||
(define_insn "truncdfsf2"
|
||
[(set (match_operand:SF 0 "register_operand" "=r")
|
||
(float_truncate:SF (match_operand:DF 1 "register_operand" "r")))]
|
||
""
|
||
"convert %0,%1,0,4,1,2")
|
||
|
||
(define_insn "extendsfdf2"
|
||
[(set (match_operand:DF 0 "register_operand" "=r")
|
||
(float_extend:DF (match_operand:SF 1 "register_operand" "r")))]
|
||
""
|
||
"convert %0,%1,0,4,2,1")
|
||
|
||
(define_insn "floatsisf2"
|
||
[(set (match_operand:SF 0 "register_operand" "=r")
|
||
(float:SF (match_operand:SI 1 "gpc_reg_operand" "r")))]
|
||
""
|
||
"convert %0,%1,0,4,1,0")
|
||
|
||
(define_insn "floatsidf2"
|
||
[(set (match_operand:DF 0 "register_operand" "=r")
|
||
(float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))]
|
||
""
|
||
"convert %0,%1,0,4,2,0")
|
||
|
||
(define_insn "floatunssisf2"
|
||
[(set (match_operand:SF 0 "register_operand" "=r")
|
||
(unsigned_float:SF (match_operand:SI 1 "gpc_reg_operand" "r")))]
|
||
""
|
||
"convert %0,%1,1,4,1,0")
|
||
|
||
(define_insn "floatunssidf2"
|
||
[(set (match_operand:DF 0 "register_operand" "=r")
|
||
(unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))]
|
||
""
|
||
"convert %0,%1,1,4,2,0")
|
||
|
||
;; CPxxx, DEQ, DGT, DGE, FEQ, FGT, FGE
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(match_operator 3 "comparison_operator"
|
||
[(match_operand:SI 1 "gpc_reg_operand" "r")
|
||
(match_operand:SI 2 "srcb_operand" "rI")]))]
|
||
""
|
||
"cp%J3 %0,%1,%2")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(match_operator 3 "fp_comparison_operator"
|
||
[(match_operand:SF 1 "register_operand" "r")
|
||
(match_operand:SF 2 "register_operand" "r")]))]
|
||
""
|
||
"f%J3 %0,%1,%2"
|
||
[(set_attr "type" "fadd")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(match_operator 3 "fp_comparison_operator"
|
||
[(match_operand:DF 1 "register_operand" "r")
|
||
(match_operand:DF 2 "register_operand" "r")]))]
|
||
""
|
||
"d%J3 %0,%1,%2"
|
||
[(set_attr "type" "fadd")])
|
||
|
||
;; DADD
|
||
(define_expand "adddf3"
|
||
[(set (match_operand:DF 0 "register_operand" "")
|
||
(plus:DF (match_operand:DF 1 "register_operand" "")
|
||
(match_operand:DF 2 "register_operand" "")))]
|
||
""
|
||
"")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:DF 0 "register_operand" "=r")
|
||
(plus:DF (match_operand:DF 1 "register_operand" "%r")
|
||
(match_operand:DF 2 "register_operand" "r")))]
|
||
"! TARGET_29050 "
|
||
"dadd %0,%1,%2"
|
||
[(set_attr "type" "fadd")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:DF 0 "register_operand" "=r,a")
|
||
(plus:DF (match_operand:DF 1 "register_operand" "%r,r")
|
||
(match_operand:DF 2 "register_operand" "r,0")))]
|
||
"TARGET_29050"
|
||
"@
|
||
dadd %0,%1,%2
|
||
dmac 8,%0,%1,0"
|
||
[(set_attr "type" "fadd,dam")])
|
||
|
||
;; DDIV
|
||
(define_insn "divdf3"
|
||
[(set (match_operand:DF 0 "register_operand" "=r")
|
||
(div:DF (match_operand:DF 1 "register_operand" "=r")
|
||
(match_operand:DF 2 "register_operand" "r")))]
|
||
""
|
||
"ddiv %0,%1,%2"
|
||
[(set_attr "type" "ddiv")])
|
||
|
||
;; DIVIDE
|
||
;;
|
||
;; We must set Q to the sign extension of the dividend first. For MOD, we
|
||
;; must get the remainder from Q.
|
||
;;
|
||
;; For divmod: operand 1 is divided by operand 2; quotient goes to operand
|
||
;; 0 and remainder to operand 3.
|
||
(define_expand "divmodsi4"
|
||
[(set (match_dup 4)
|
||
(ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "")
|
||
(const_int 31)))
|
||
(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(div:SI (match_dup 1)
|
||
(match_operand:SI 2 "gpc_reg_operand" "")))
|
||
(set (match_operand:SI 3 "gpc_reg_operand" "")
|
||
(mod:SI (match_dup 1)
|
||
(match_dup 2)))
|
||
(use (match_dup 4))])]
|
||
""
|
||
"
|
||
{
|
||
operands[4] = gen_reg_rtx (SImode);
|
||
}")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(div:SI (match_operand:SI 1 "gpc_reg_operand" "r")
|
||
(match_operand:SI 2 "gpc_reg_operand" "r")))
|
||
(set (match_operand:SI 3 "register_operand" "=q")
|
||
(mod:SI (match_dup 1)
|
||
(match_dup 2)))
|
||
(use (match_operand:SI 4 "register_operand" "3"))]
|
||
""
|
||
"divide %0,%1,%2")
|
||
|
||
;; DIVIDU
|
||
;;
|
||
;; Similar to DIVIDE.
|
||
(define_expand "udivmodsi4"
|
||
[(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(udiv:SI (match_operand:SI 1 "gpc_reg_operand" "")
|
||
(match_operand:SI 2 "gpc_reg_operand" "")))
|
||
(set (match_operand:SI 3 "gpc_reg_operand" "")
|
||
(umod:SI (match_dup 1)
|
||
(match_dup 2)))
|
||
(use (const_int 0))])]
|
||
""
|
||
"")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(udiv:SI (match_operand:SI 1 "gpc_reg_operand" "r")
|
||
(match_operand:SI 2 "gpc_reg_operand" "r")))
|
||
(set (match_operand:SI 3 "register_operand" "=q")
|
||
(umod:SI (match_dup 1)
|
||
(match_dup 2)))
|
||
(use (match_operand:SI 4 "const_int_operand" "3"))]
|
||
""
|
||
"dividu %0,%1,%2")
|
||
|
||
;; DMAC/DMSM
|
||
(define_insn ""
|
||
[(set (match_operand:DF 0 "register_operand" "=a,*r")
|
||
(plus:DF (mult:DF (match_operand:DF 1 "register_operand" "%r,A")
|
||
(match_operand:DF 2 "register_operand" "r,r"))
|
||
(match_operand:DF 3 "register_operand" "0,*r")))]
|
||
"TARGET_29050"
|
||
"@
|
||
dmac 0,%0,%1,%2
|
||
dmsm %0,%2,%3"
|
||
[(set_attr "type" "dam")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:DF 0 "register_operand" "=a")
|
||
(plus:DF (mult:DF (neg:DF (match_operand:DF 1 "register_operand" "r"))
|
||
(match_operand:DF 2 "register_operand" "r"))
|
||
(match_operand:DF 3 "register_operand" "0")))]
|
||
"TARGET_29050"
|
||
"dmac 1,%0,%2,%1"
|
||
[(set_attr "type" "dam")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:DF 0 "register_operand" "=a")
|
||
(minus:DF (mult:DF (match_operand:DF 1 "register_operand" "%r")
|
||
(match_operand:DF 2 "register_operand" "r"))
|
||
(match_operand:DF 3 "register_operand" "0")))]
|
||
"TARGET_29050"
|
||
"dmac 2,%0,%1,%2"
|
||
[(set_attr "type" "dam")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:DF 0 "register_operand" "=a")
|
||
(minus:DF (mult:DF (match_operand:DF 1 "register_operand" "r")
|
||
(neg:DF (match_operand:DF 2 "register_operand" "r")))
|
||
(match_operand:DF 3 "register_operand" "0")))]
|
||
"TARGET_29050"
|
||
"dmac 3,%0,%1,%2"
|
||
[(set_attr "type" "dam")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:DF 0 "register_operand" "=a")
|
||
(mult:DF (neg:DF (match_operand:DF 1 "register_operand" "r"))
|
||
(match_operand:DF 2 "register_operand" "r")))]
|
||
"TARGET_29050"
|
||
"dmac 5,%0,%2,%1"
|
||
[(set_attr "type" "dam")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:DF 0 "register_operand" "=a")
|
||
(minus:DF (neg:DF (match_operand:DF 1 "register_operand" "r"))
|
||
(match_operand:DF 2 "register_operand" "0")))]
|
||
"TARGET_29050"
|
||
"dmac 11,%0,%1,0"
|
||
[(set_attr "type" "dam")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:DF 0 "register_operand" "=a")
|
||
(neg:DF (plus:DF (match_operand:DF 1 "register_operand" "%r")
|
||
(match_operand:DF 2 "register_operand" "0"))))]
|
||
"TARGET_29050"
|
||
"dmac 11,%0,%1,0"
|
||
[(set_attr "type" "dam")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:DF 0 "register_operand" "=r,r,a")
|
||
(neg:DF (match_operand:DF 1 "register_operand" "0,r,r")))
|
||
(clobber (match_scratch:SI 2 "=&r,&r,X"))]
|
||
"TARGET_29050"
|
||
"@
|
||
cpeq %2,gr1,gr1\;xor %0,%1,%2
|
||
cpeq %2,gr1,gr1\;xor %0,%1,%2\;sll %L0,%L1,0
|
||
dmac 13,%0,%1,0"
|
||
[(set_attr "type" "multi,multi,dam")])
|
||
|
||
;; DMUL
|
||
(define_expand "muldf3"
|
||
[(set (match_operand:DF 0 "register_operand" "")
|
||
(mult:DF (match_operand:DF 1 "register_operand" "")
|
||
(match_operand:DF 2 "register_operand" "")))]
|
||
""
|
||
"")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:DF 0 "register_operand" "=r")
|
||
(mult:DF (match_operand:DF 1 "register_operand" "%r")
|
||
(match_operand:DF 2 "register_operand" "r")))]
|
||
"! TARGET_29050"
|
||
"dmul %0,%1,%2"
|
||
[(set_attr "type" "dmul")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:DF 0 "register_operand" "=r,a")
|
||
(mult:DF (match_operand:DF 1 "register_operand" "%r,r")
|
||
(match_operand:DF 2 "register_operand" "r,r")))]
|
||
"TARGET_29050"
|
||
"@
|
||
dmul %0,%1,%2
|
||
dmac 4,%0,%1,%2"
|
||
[(set_attr "type" "dmul,dam")])
|
||
|
||
;; DSUB
|
||
(define_expand "subdf3"
|
||
[(set (match_operand:DF 0 "register_operand" "=r")
|
||
(minus:DF (match_operand:DF 1 "register_operand" "r")
|
||
(match_operand:DF 2 "register_operand" "r")))]
|
||
""
|
||
"")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:DF 0 "register_operand" "=r")
|
||
(minus:DF (match_operand:DF 1 "register_operand" "r")
|
||
(match_operand:DF 2 "register_operand" "r")))]
|
||
"! TARGET_29050"
|
||
"dsub %0,%1,%2"
|
||
[(set_attr "type" "fadd")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:DF 0 "register_operand" "=r,a,a")
|
||
(minus:DF (match_operand:DF 1 "register_operand" "r,0,r")
|
||
(match_operand:DF 2 "register_operand" "r,r,0")))]
|
||
"TARGET_29050"
|
||
"@
|
||
dsub %0,%1,%2
|
||
dmac 9,%0,%2,0
|
||
dmac 10,%0,%1,0"
|
||
[(set_attr "type" "fadd,dam,dam")])
|
||
|
||
;; EXBYTE
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(ior:SI (and:SI (match_operand:SI 1 "srcb_operand" "rI")
|
||
(const_int -256))
|
||
(zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r")
|
||
(const_int 8)
|
||
(ashift:SI (match_operand:SI 3 "register_operand" "b")
|
||
(const_int 3)))))]
|
||
""
|
||
"exbyte %0,%2,%1")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r")
|
||
(const_int 8)
|
||
(ashift:SI (match_operand:SI 2 "register_operand" "b")
|
||
(const_int 3))))]
|
||
""
|
||
"exbyte %0,%1,0")
|
||
|
||
(define_insn ""
|
||
[(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
|
||
(const_int 8)
|
||
(match_operand:SI 1 "const_24_operand" ""))
|
||
(zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r")
|
||
(const_int 8)
|
||
(ashift:SI (match_operand:SI 3 "register_operand" "b")
|
||
(const_int 3))))]
|
||
""
|
||
"exbyte %0,%2,%0")
|
||
|
||
(define_expand "extzv"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "")
|
||
(match_operand:SI 2 "general_operand" "")
|
||
(match_operand:SI 3 "general_operand" "")))]
|
||
""
|
||
"
|
||
{
|
||
int size, pos;
|
||
|
||
if (GET_CODE (operands[2]) != CONST_INT
|
||
|| GET_CODE (operands[3]) != CONST_INT)
|
||
FAIL;
|
||
|
||
size = INTVAL (operands[2]);
|
||
pos = INTVAL (operands[3]);
|
||
if ((size != 8 && size != 16) || pos % size != 0)
|
||
FAIL;
|
||
|
||
operands[3] = gen_rtx (ASHIFT, SImode,
|
||
force_reg (SImode,
|
||
gen_rtx (CONST_INT, VOIDmode, pos / 8)),
|
||
gen_rtx (CONST_INT, VOIDmode, 3));
|
||
}")
|
||
|
||
(define_expand "extv"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "")
|
||
(match_operand:SI 2 "general_operand" "")
|
||
(match_operand:SI 3 "general_operand" "")))]
|
||
""
|
||
"
|
||
{
|
||
int pos;
|
||
|
||
if (GET_CODE (operands[2]) != CONST_INT
|
||
|| GET_CODE (operands[3]) != CONST_INT)
|
||
FAIL;
|
||
|
||
pos = INTVAL (operands[3]);
|
||
if (INTVAL (operands[2]) != 16 || pos % 16 != 0)
|
||
FAIL;
|
||
|
||
operands[3] = gen_rtx (ASHIFT, SImode,
|
||
force_reg (SImode,
|
||
gen_rtx (CONST_INT, VOIDmode, pos / 8)),
|
||
gen_rtx (CONST_INT, VOIDmode, 3));
|
||
}")
|
||
|
||
;; EXHW
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(ior:SI (and:SI (match_operand:SI 1 "srcb_operand" "rI")
|
||
(const_int -65536))
|
||
(zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r")
|
||
(const_int 16)
|
||
(ashift:SI (match_operand:SI 3 "register_operand" "b")
|
||
(const_int 3)))))]
|
||
""
|
||
"exhw %0,%2,%1")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(zero_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r")
|
||
(const_int 16)
|
||
(ashift:SI (match_operand:SI 2 "register_operand" "b")
|
||
(const_int 3))))]
|
||
""
|
||
"exhw %0,%1,0")
|
||
|
||
(define_insn ""
|
||
[(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
|
||
(const_int 16)
|
||
(match_operand:SI 1 "const_16_operand" ""))
|
||
(zero_extract:SI (match_operand:SI 2 "gpc_reg_operand" "r")
|
||
(const_int 16)
|
||
(ashift:SI (match_operand:SI 3 "register_operand" "b")
|
||
(const_int 3))))]
|
||
""
|
||
"exhw %0,%2,%0")
|
||
|
||
;; EXHWS
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(sign_extract:SI (match_operand:SI 1 "gpc_reg_operand" "r")
|
||
(const_int 16)
|
||
(ashift:SI (match_operand:SI 2 "register_operand" "b")
|
||
(const_int 3))))]
|
||
""
|
||
"exhws %0,%1")
|
||
|
||
;; EXTRACT
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "r")
|
||
(reg:QI 178)))]
|
||
""
|
||
"extract %0,%1,%1")
|
||
|
||
(define_expand "rotlsi3"
|
||
[(set (reg:QI 178)
|
||
(match_operand: SI 2 "gpc_reg_or_immediate_operand" ""))
|
||
(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(rotate:SI (match_operand:SI 1 "gpc_reg_operand" "")
|
||
(reg:QI 178)))]
|
||
""
|
||
"
|
||
{ operands[2] = gen_lowpart (QImode, operands[2]); }")
|
||
|
||
;; FADD
|
||
(define_expand "addsf3"
|
||
[(set (match_operand:SF 0 "register_operand" "")
|
||
(plus:SF (match_operand:SF 1 "register_operand" "")
|
||
(match_operand:SF 2 "register_operand" "")))]
|
||
""
|
||
"")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SF 0 "register_operand" "=r")
|
||
(plus:SF (match_operand:SF 1 "register_operand" "%r")
|
||
(match_operand:SF 2 "register_operand" "r")))]
|
||
"! TARGET_29050"
|
||
"fadd %0,%1,%2"
|
||
[(set_attr "type" "fadd")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SF 0 "register_operand" "=r,a")
|
||
(plus:SF (match_operand:SF 1 "register_operand" "%r,r")
|
||
(match_operand:SF 2 "register_operand" "r,0")))]
|
||
"TARGET_29050"
|
||
"@
|
||
fadd %0,%1,%2
|
||
fmac 8,%0,%1,0"
|
||
[(set_attr "type" "fadd,fam")])
|
||
|
||
;; FDIV
|
||
(define_insn "divsf3"
|
||
[(set (match_operand:SF 0 "register_operand" "=r")
|
||
(div:DF (match_operand:SF 1 "register_operand" "=r")
|
||
(match_operand:SF 2 "register_operand" "r")))]
|
||
""
|
||
"fdiv %0,%1,%2"
|
||
[(set_attr "type" "fdiv")])
|
||
|
||
;; FDMUL
|
||
(define_insn ""
|
||
[(set (match_operand:DF 0 "register_operand" "=r")
|
||
(mult:DF (float_extend:DF (match_operand:SF 1 "register_operand" "%r"))
|
||
(float_extend:DF (match_operand:SF 2 "register_operand" "r"))))]
|
||
""
|
||
"fdmul %0,%1,%2")
|
||
|
||
;; FMAC/FMSM
|
||
(define_insn ""
|
||
[(set (match_operand:SF 0 "register_operand" "=a,*r")
|
||
(plus:SF (mult:SF (match_operand:SF 1 "register_operand" "%r,A")
|
||
(match_operand:SF 2 "register_operand" "r,r"))
|
||
(match_operand:SF 3 "register_operand" "0,*r")))]
|
||
"TARGET_29050"
|
||
"@
|
||
fmac 0,%0,%1,%2
|
||
fmsm %0,%2,%3"
|
||
[(set_attr "type" "fam")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SF 0 "register_operand" "=a")
|
||
(plus:SF (mult:SF (neg:SF (match_operand:SF 1 "register_operand" "r"))
|
||
(match_operand:SF 2 "register_operand" "r"))
|
||
(match_operand:SF 3 "register_operand" "0")))]
|
||
"TARGET_29050"
|
||
"fmac 1,%0,%2,%1"
|
||
[(set_attr "type" "fam")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SF 0 "register_operand" "=a")
|
||
(minus:SF (mult:SF (match_operand:SF 1 "register_operand" "%r")
|
||
(match_operand:SF 2 "register_operand" "r"))
|
||
(match_operand:SF 3 "register_operand" "0")))]
|
||
"TARGET_29050"
|
||
"fmac 2,%0,%1,%2"
|
||
[(set_attr "type" "fam")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SF 0 "register_operand" "=a")
|
||
(minus:SF (mult:SF (neg:SF (match_operand:SF 1 "register_operand" "r"))
|
||
(match_operand:SF 2 "register_operand" "r"))
|
||
(match_operand:SF 3 "register_operand" "0")))]
|
||
"TARGET_29050"
|
||
"fmac 3,%0,%2,%1"
|
||
[(set_attr "type" "fam")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SF 0 "register_operand" "=a")
|
||
(mult:SF (neg:SF (match_operand:SF 1 "register_operand" "r"))
|
||
(match_operand:SF 2 "register_operand" "r")))]
|
||
"TARGET_29050"
|
||
"fmac 5,%0,%2,%1"
|
||
[(set_attr "type" "fam")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SF 0 "register_operand" "=a")
|
||
(minus:SF (neg:SF (match_operand:SF 1 "register_operand" "%r"))
|
||
(match_operand:SF 2 "register_operand" "0")))]
|
||
"TARGET_29050"
|
||
"fmac 11,%0,%1,0"
|
||
[(set_attr "type" "fam")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SF 0 "register_operand" "=a")
|
||
(neg:SF (plus:SF (match_operand:SF 1 "register_operand" "%r")
|
||
(match_operand:SF 2 "register_operand" "0"))))]
|
||
"TARGET_29050"
|
||
"fmac 11,%0,%1,0"
|
||
[(set_attr "type" "fam")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SF 0 "register_operand" "=r,a")
|
||
(neg:SF (match_operand:SF 1 "register_operand" "r,r")))
|
||
(clobber (match_scratch:SI 2 "=&r,X"))]
|
||
"TARGET_29050"
|
||
"@
|
||
cpeq %2,gr1,gr1\;xor %0,%1,%2
|
||
fmac 13,%0,%1,0"
|
||
[(set_attr "type" "multi,fam")])
|
||
|
||
;; FMUL
|
||
(define_expand "mulsf3"
|
||
[(set (match_operand:SF 0 "register_operand" "")
|
||
(mult:SF (match_operand:SF 1 "register_operand" "")
|
||
(match_operand:SF 2 "register_operand" "")))]
|
||
""
|
||
"")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SF 0 "register_operand" "=r")
|
||
(mult:SF (match_operand:SF 1 "register_operand" "%r")
|
||
(match_operand:SF 2 "register_operand" "r")))]
|
||
"! TARGET_29050"
|
||
"fmul %0,%1,%2"
|
||
[(set_attr "type" "fmul")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SF 0 "register_operand" "=r,a")
|
||
(mult:SF (match_operand:SF 1 "register_operand" "%r,r")
|
||
(match_operand:SF 2 "register_operand" "r,r")))]
|
||
"TARGET_29050"
|
||
"@
|
||
fmul %0,%1,%2
|
||
fmac 4,%0,%1,%2"
|
||
[(set_attr "type" "fmul,fam")])
|
||
|
||
;; FSUB
|
||
(define_expand "subsf3"
|
||
[(set (match_operand:SF 0 "register_operand" "")
|
||
(minus:SF (match_operand:SF 1 "register_operand" "")
|
||
(match_operand:SF 2 "register_operand" "")))]
|
||
""
|
||
"")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SF 0 "register_operand" "=r")
|
||
(minus:SF (match_operand:SF 1 "register_operand" "r")
|
||
(match_operand:SF 2 "register_operand" "r")))]
|
||
"! TARGET_29050"
|
||
"fsub %0,%1,%2"
|
||
[(set_attr "type" "fadd")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SF 0 "register_operand" "=r,a,a")
|
||
(minus:SF (match_operand:SF 1 "register_operand" "r,0,r")
|
||
(match_operand:SF 2 "register_operand" "r,r,0")))]
|
||
"TARGET_29050"
|
||
"@
|
||
fsub %0,%1,%2
|
||
fmac 9,%0,%2,0
|
||
fmac 10,%0,%1,0"
|
||
[(set_attr "type" "fadd,fam,fam")])
|
||
|
||
;; INBYTE
|
||
(define_insn ""
|
||
[(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
|
||
(const_int 8)
|
||
(ashift:SI (match_operand:SI 2 "register_operand" "b")
|
||
(const_int 3)))
|
||
(match_operand:SI 1 "srcb_operand" "rI"))]
|
||
""
|
||
"inbyte %0,%0,%1")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(ior:SI (and:SI (not:SI (ashift:SI (const_int 255)
|
||
(ashift:SI (match_operand:SI 3 "register_operand" "b")
|
||
(const_int 3))))
|
||
(match_operand:SI 1 "gpc_reg_operand" "r"))
|
||
(ashift:SI (and:SI (match_operand:SI 2 "srcb_operand" "rI")
|
||
(const_int 255))
|
||
(match_operand:SI 4 "const_24_operand" ""))))]
|
||
""
|
||
"inbyte %0,%1,%2")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(ior:SI (and:SI (not:SI (ashift:SI (const_int 255)
|
||
(ashift:SI (match_operand:SI 3 "register_operand" "b")
|
||
(const_int 3))))
|
||
(match_operand:SI 1 "gpc_reg_operand" "r"))
|
||
(ashift:SI (match_operand:SI 2 "srcb_operand" "rI")
|
||
(match_operand:SI 4 "const_24_operand" ""))))]
|
||
""
|
||
"inbyte %0,%1,%2")
|
||
|
||
;; INHW
|
||
(define_insn ""
|
||
[(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
|
||
(const_int 16)
|
||
(ashift:SI (match_operand:SI 2 "register_operand" "b")
|
||
(const_int 3)))
|
||
(match_operand:SI 1 "srcb_operand" "rI"))]
|
||
""
|
||
"inhw %0,%0,%1")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(ior:SI (and:SI (not:SI (ashift:SI (const_int 65535)
|
||
(ashift:SI (match_operand:SI 3 "register_operand" "b")
|
||
(const_int 3))))
|
||
(match_operand:SI 1 "gpc_reg_operand" "r"))
|
||
(ashift:SI (and:SI (match_operand:SI 2 "srcb_operand" "rI")
|
||
(const_int 65535))
|
||
(match_operand:SI 4 "const_24_operand" ""))))]
|
||
""
|
||
"inhw %0,%1,%2")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(ior:SI (and:SI (not:SI (ashift:SI (const_int 65535)
|
||
(ashift:SI (match_operand:SI 3 "register_operand" "b")
|
||
(const_int 3))))
|
||
(match_operand:SI 1 "gpc_reg_operand" "r"))
|
||
(ashift:SI (match_operand:SI 2 "srcb_operand" "rI")
|
||
(match_operand:SI 4 "const_24_operand" ""))))]
|
||
""
|
||
"inhw %0,%1,%2")
|
||
|
||
(define_expand "insv"
|
||
[(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(match_operand:SI 1 "general_operand" "")
|
||
(match_operand:SI 2 "general_operand" ""))
|
||
(match_operand:SI 3 "srcb_operand" ""))]
|
||
""
|
||
"
|
||
{
|
||
int size, pos;
|
||
|
||
if (GET_CODE (operands[1]) != CONST_INT
|
||
|| GET_CODE (operands[2]) != CONST_INT)
|
||
FAIL;
|
||
|
||
size = INTVAL (operands[1]);
|
||
pos = INTVAL (operands[2]);
|
||
if ((size != 8 && size != 16) || pos % size != 0)
|
||
FAIL;
|
||
|
||
operands[2] = gen_rtx (ASHIFT, SImode,
|
||
force_reg (SImode,
|
||
gen_rtx (CONST_INT, VOIDmode, pos / 8)),
|
||
gen_rtx (CONST_INT, VOIDmode, 3));
|
||
}")
|
||
|
||
;; LOAD (also used by move insn).
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(mem:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "r")
|
||
(const_int -4))))
|
||
(set (reg:SI 177)
|
||
(and:SI (match_dup 1)
|
||
(const_int 3)))]
|
||
"! TARGET_DW_ENABLE"
|
||
"load 0,17,%0,%1"
|
||
[(set_attr "type" "load")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(mem:SI (and:SI (match_operand:SI 1 "gpc_reg_operand" "r")
|
||
(const_int -4))))
|
||
(set (reg:SI 177)
|
||
(and:SI (match_dup 1)
|
||
(const_int 2)))]
|
||
"! TARGET_DW_ENABLE"
|
||
"load 0,18,%0,%1"
|
||
[(set_attr "type" "load")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand 0 "gpc_reg_operand" "=r")
|
||
(match_operator 2 "extend_operator"
|
||
[(match_operand 1 "memory_operand" "m")]))]
|
||
"TARGET_DW_ENABLE && GET_MODE (operands[0]) == GET_MODE (operands[2])"
|
||
"load 0,%X2,%0,%1"
|
||
[(set_attr "type" "load")])
|
||
|
||
;; LOADM
|
||
(define_expand "load_multiple"
|
||
[(set (reg:SI 179)
|
||
(match_operand:SI 2 "const_int_operand" ""))
|
||
(match_par_dup 3 [(set (match_operand:SI 0 "" "")
|
||
(match_operand:SI 1 "" ""))])]
|
||
""
|
||
"
|
||
{
|
||
int regno;
|
||
int count;
|
||
rtx from;
|
||
int i;
|
||
|
||
/* Support only loading a constant number of hard registers from memory. */
|
||
if (GET_CODE (operands[2]) != CONST_INT
|
||
|| operands[2] == const1_rtx
|
||
|| GET_CODE (operands[1]) != MEM
|
||
|| GET_CODE (operands[0]) != REG
|
||
|| REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER)
|
||
FAIL;
|
||
|
||
count = INTVAL (operands[2]);
|
||
regno = REGNO (operands[0]);
|
||
|
||
/* CR gets set to the number of registers minus one. */
|
||
operands[2] = gen_rtx (CONST_INT, VOIDmode, count - 1);
|
||
|
||
operands[3] = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (count + 2));
|
||
from = memory_address (SImode, XEXP (operands[1], 0));
|
||
XVECEXP (operands[3], 0, 0) = gen_rtx (SET, VOIDmode,
|
||
gen_rtx (REG, SImode, regno),
|
||
gen_rtx (MEM, SImode, from));
|
||
XVECEXP (operands[3], 0, 1)
|
||
= gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, R_CR));
|
||
XVECEXP (operands[3], 0, 2)
|
||
= gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, R_CR));
|
||
|
||
for (i = 1; i < count; i++)
|
||
XVECEXP (operands[3], 0, i + 2)
|
||
= gen_rtx (SET, VOIDmode, gen_rtx (REG, SImode, regno + i),
|
||
gen_rtx (MEM, SImode, plus_constant (from, i * 4)));
|
||
}")
|
||
|
||
;; Indicate that CR is used and is then clobbered.
|
||
(define_insn ""
|
||
[(set (match_operand 0 "gpc_reg_operand" "=r")
|
||
(match_operand 1 "memory_operand" "m"))
|
||
(use (reg:SI 179))
|
||
(clobber (reg:SI 179))]
|
||
"GET_MODE (operands[0]) == GET_MODE (operands[1])
|
||
&& GET_MODE_SIZE (GET_MODE (operands[0])) > UNITS_PER_WORD
|
||
&& ! TARGET_29050"
|
||
"loadm 0,0,%0,%1"
|
||
[(set_attr "type" "load")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand 0 "gpc_reg_operand" "=&r")
|
||
(match_operand 1 "memory_operand" "m"))
|
||
(use (reg:SI 179))
|
||
(clobber (reg:SI 179))]
|
||
"GET_MODE (operands[0]) == GET_MODE (operands[1])
|
||
&& GET_MODE_SIZE (GET_MODE (operands[0])) > UNITS_PER_WORD
|
||
&& TARGET_29050"
|
||
"loadm 0,0,%0,%1"
|
||
[(set_attr "type" "load")])
|
||
|
||
(define_insn ""
|
||
[(match_parallel 0 "load_multiple_operation"
|
||
[(set (match_operand:SI 1 "gpc_reg_operand" "=r")
|
||
(match_operand:SI 2 "memory_operand" "m"))
|
||
(use (reg:SI 179))
|
||
(clobber (reg:SI 179))])]
|
||
"! TARGET_29050"
|
||
"loadm 0,0,%1,%2"
|
||
[(set_attr "type" "load")])
|
||
|
||
(define_insn ""
|
||
[(match_parallel 0 "load_multiple_operation"
|
||
[(set (match_operand:SI 1 "gpc_reg_operand" "=&r")
|
||
(match_operand:SI 2 "memory_operand" "m"))
|
||
(use (reg:SI 179))
|
||
(clobber (reg:SI 179))])]
|
||
"TARGET_29050"
|
||
"loadm 0,0,%1,%2"
|
||
[(set_attr "type" "load")])
|
||
|
||
;; MTSR (used also by move insn)
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "spec_reg_operand" "=*h,*h")
|
||
(and:SI (match_operand:SI 1 "gpc_reg_or_immediate_operand" "r,i")
|
||
(match_operand:SI 2 "const_int_operand" "n,n")))]
|
||
"masks_bits_for_special (operands[0], operands[2])"
|
||
"@
|
||
mtsr %0,%1
|
||
mtsrim %0,%1")
|
||
|
||
;; MULTIPLY, MULTM, MULTMU
|
||
(define_insn "mulsi3"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(mult:SI (match_operand:SI 1 "gpc_reg_operand" "%r")
|
||
(match_operand:SI 2 "gpc_reg_operand" "r")))]
|
||
""
|
||
"multiply %0,%1,%2")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(subreg:SI
|
||
(mult:DI
|
||
(sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "%r"))
|
||
(sign_extend:DI (match_operand:SI 2 "gpc_reg_operand" "r"))) 0))]
|
||
""
|
||
"multm %0,%1,%2")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(subreg:SI
|
||
(mult:DI
|
||
(zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" "%r"))
|
||
(zero_extend:DI (match_operand:SI 2 "gpc_reg_operand" "r"))) 0))]
|
||
""
|
||
"multmu %0,%1,%2")
|
||
|
||
(define_insn "mulsidi3"
|
||
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
|
||
(mult:DI (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r"))
|
||
(sign_extend:DI (match_operand:SI 2 "gpc_reg_operand" "r"))))]
|
||
""
|
||
"multiply %L0,%1,%2\;multm %0,%1,%2"
|
||
[(set_attr "type" "multi")])
|
||
|
||
(define_split
|
||
[(set (match_operand:DI 0 "gpc_reg_operand" "")
|
||
(mult:DI (sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" ""))
|
||
(sign_extend:DI (match_operand:SI 2 "gpc_reg_operand" ""))))]
|
||
"reload_completed"
|
||
[(set (match_dup 3)
|
||
(mult:SI (match_dup 1) (match_dup 2)))
|
||
(set (match_dup 4)
|
||
(subreg:SI (mult:DI
|
||
(sign_extend:DI (match_dup 1))
|
||
(sign_extend:DI (match_dup 2))) 0))]
|
||
"
|
||
{ operands[3] = operand_subword (operands[0], 1, 1, DImode);
|
||
operands[4] = operand_subword (operands[1], 0, 1, DImode); } ")
|
||
|
||
(define_insn "umulsidi3"
|
||
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
|
||
(mult:DI (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r"))
|
||
(zero_extend:DI (match_operand:SI 2 "gpc_reg_operand" "r"))))]
|
||
""
|
||
"multiplu %L0,%1,%2\;multmu %0,%1,%2"
|
||
[(set_attr "type" "multi")])
|
||
|
||
(define_split
|
||
[(set (match_operand:DI 0 "gpc_reg_operand" "")
|
||
(mult:DI (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" ""))
|
||
(zero_extend:DI (match_operand:SI 2 "gpc_reg_operand" ""))))]
|
||
"reload_completed"
|
||
[(set (match_dup 3)
|
||
(mult:SI (match_dup 1) (match_dup 2)))
|
||
(set (match_dup 4)
|
||
(subreg:SI (mult:DI (zero_extend:DI (match_dup 1))
|
||
(zero_extend:DI (match_dup 2))) 0))]
|
||
"
|
||
{ operands[3] = operand_subword (operands[0], 1, 1, DImode);
|
||
operands[4] = operand_subword (operands[1], 0, 1, DImode); } ")
|
||
|
||
;; NAND
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(ior:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "%r"))
|
||
(not:SI (match_operand:SI 2 "srcb_operand" "rI"))))]
|
||
""
|
||
"nand %0,%1,%2")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(ior:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r"))
|
||
(match_operand:SI 2 "const_int_operand" "K")))]
|
||
"((unsigned) ~ INTVAL (operands[2])) < 256"
|
||
"nand %0,%1,%C2")
|
||
|
||
;; NOR
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "%r"))
|
||
(not:SI (match_operand:SI 2 "srcb_operand" "rI"))))]
|
||
""
|
||
"nor %0,%1,%2")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(and:SI (not:SI (match_operand:SI 1 "gpc_reg_operand" "r"))
|
||
(match_operand:SI 2 "const_int_operand" "K")))]
|
||
"((unsigned) ~ INTVAL (operands[2])) < 256"
|
||
"nor %0,%1,%C2")
|
||
|
||
(define_insn "one_cmplsi2"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(not:SI (match_operand:SI 1 "gpc_reg_operand" "r")))]
|
||
""
|
||
"nor %0,%1,0")
|
||
|
||
;; OR/ORN
|
||
(define_expand "iorsi3"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(ior:SI (match_operand:SI 1 "gpc_reg_operand" "")
|
||
(match_operand:SI 2 "srcb_operand" "")))]
|
||
""
|
||
"")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(ior:SI (match_operand:SI 1 "gpc_reg_operand" "%r")
|
||
(match_operand:SI 2 "srcb_operand" "rI")))]
|
||
"! TARGET_29050"
|
||
"or %0,%1,%2")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
|
||
(ior:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r")
|
||
(match_operand:SI 2 "srcb_operand" "rI,K")))]
|
||
"TARGET_29050"
|
||
"@
|
||
or %0,%1,%2
|
||
orn %0,%1,%C2")
|
||
|
||
|
||
;; SLL (also used by move insn)
|
||
(define_insn "nop"
|
||
[(const_int 0)]
|
||
""
|
||
"aseq 0x40,gr1,gr1")
|
||
|
||
(define_insn "ashlsi3"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r")
|
||
(match_operand:QI 2 "srcb_operand" "rn")))]
|
||
""
|
||
"sll %0,%1,%Q2")
|
||
|
||
;; SRA
|
||
(define_insn "ashrsi3"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(ashiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
|
||
(match_operand:QI 2 "srcb_operand" "rn")))]
|
||
""
|
||
"sra %0,%1,%Q2")
|
||
|
||
;; SRL
|
||
(define_insn "lshrsi3"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(lshiftrt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
|
||
(match_operand:QI 2 "srcb_operand" "rn")))]
|
||
""
|
||
"srl %0,%1,%Q2")
|
||
|
||
;; STORE
|
||
;;
|
||
;; These somewhat bogus patterns exist to set OPT = 001/010 for partial-word
|
||
;; stores on systems with DW not set.
|
||
(define_insn ""
|
||
[(set (mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "r")
|
||
(const_int -4)))
|
||
(match_operand:SI 1 "gpc_reg_operand" "r"))]
|
||
"! TARGET_DW_ENABLE"
|
||
"store 0,1,%1,%0"
|
||
[(set_attr "type" "store")])
|
||
|
||
(define_insn ""
|
||
[(set (mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "r")
|
||
(const_int -3)))
|
||
(match_operand:SI 1 "gpc_reg_operand" "r"))]
|
||
"! TARGET_DW_ENABLE"
|
||
"store 0,2,%1,%0"
|
||
[(set_attr "type" "store")])
|
||
|
||
;; STOREM
|
||
(define_expand "store_multiple"
|
||
[(use (match_operand 0 "" ""))
|
||
(use (match_operand 1 "" ""))
|
||
(use (match_operand 2 "" ""))]
|
||
""
|
||
"
|
||
{ rtx pat;
|
||
|
||
if (TARGET_NO_STOREM_BUG)
|
||
pat = gen_store_multiple_no_bug (operands[0], operands[1], operands[2]);
|
||
else
|
||
pat = gen_store_multiple_bug (operands[0], operands[1], operands[2]);
|
||
|
||
if (pat)
|
||
emit_insn (pat);
|
||
else
|
||
FAIL;
|
||
|
||
DONE;
|
||
}")
|
||
|
||
(define_expand "store_multiple_no_bug"
|
||
[(set (reg:SI 179)
|
||
(match_operand:SI 2 "const_int_operand" ""))
|
||
(match_par_dup 3 [(set (match_operand:SI 0 "" "")
|
||
(match_operand:SI 1 "" ""))])]
|
||
""
|
||
"
|
||
{
|
||
int regno;
|
||
int count;
|
||
rtx from;
|
||
int i;
|
||
|
||
/* Support only storing a constant number of hard registers to memory. */
|
||
if (GET_CODE (operands[2]) != CONST_INT
|
||
|| operands[2] == const1_rtx
|
||
|| GET_CODE (operands[0]) != MEM
|
||
|| GET_CODE (operands[1]) != REG
|
||
|| REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
|
||
FAIL;
|
||
|
||
count = INTVAL (operands[2]);
|
||
regno = REGNO (operands[1]);
|
||
|
||
/* CR gets set to the number of registers minus one. */
|
||
operands[2] = gen_rtx (CONST_INT, VOIDmode, count - 1);
|
||
|
||
operands[3] = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (count + 2));
|
||
from = memory_address (SImode, XEXP (operands[0], 0));
|
||
XVECEXP (operands[3], 0, 0) = gen_rtx (SET, VOIDmode,
|
||
gen_rtx (MEM, SImode, from),
|
||
gen_rtx (REG, SImode, regno));
|
||
XVECEXP (operands[3], 0, 1)
|
||
= gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, R_CR));
|
||
XVECEXP (operands[3], 0, 2)
|
||
= gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, R_CR));
|
||
|
||
for (i = 1; i < count; i++)
|
||
XVECEXP (operands[3], 0, i + 2)
|
||
= gen_rtx (SET, VOIDmode,
|
||
gen_rtx (MEM, SImode, plus_constant (from, i * 4)),
|
||
gen_rtx (REG, SImode, regno + i));
|
||
}")
|
||
|
||
(define_expand "store_multiple_bug"
|
||
[(match_par_dup 3 "" [(set (match_operand:SI 0 "" "")
|
||
(match_operand:SI 1 "" ""))
|
||
(use (match_operand:SI 2 "" ""))])]
|
||
""
|
||
"
|
||
{
|
||
int regno;
|
||
int count;
|
||
rtx from;
|
||
int i;
|
||
|
||
/* Support only storing a constant number of hard registers to memory. */
|
||
if (GET_CODE (operands[2]) != CONST_INT
|
||
|| operands[2] == const1_rtx
|
||
|| GET_CODE (operands[0]) != MEM
|
||
|| GET_CODE (operands[1]) != REG
|
||
|| REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER)
|
||
FAIL;
|
||
|
||
count = INTVAL (operands[2]);
|
||
regno = REGNO (operands[1]);
|
||
|
||
operands[3] = gen_rtx (PARALLEL, VOIDmode, rtvec_alloc (count + 1));
|
||
from = memory_address (SImode, XEXP (operands[0], 0));
|
||
XVECEXP (operands[3], 0, 0) = gen_rtx (SET, VOIDmode,
|
||
gen_rtx (MEM, SImode, from),
|
||
gen_rtx (REG, SImode, regno));
|
||
XVECEXP (operands[3], 0, 1)
|
||
= gen_rtx (CLOBBER, VOIDmode, gen_rtx (REG, SImode, R_CR));
|
||
|
||
for (i = 1; i < count; i++)
|
||
XVECEXP (operands[3], 0, i + 1)
|
||
= gen_rtx (SET, VOIDmode,
|
||
gen_rtx (MEM, SImode, plus_constant (from, i * 4)),
|
||
gen_rtx (REG, SImode, regno + i));
|
||
}")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand 0 "memory_operand" "=m")
|
||
(match_operand 1 "gpc_reg_operand" "r"))
|
||
(clobber (reg:SI 179))]
|
||
"!TARGET_NO_STOREM_BUG
|
||
&& GET_MODE (operands[0]) == GET_MODE (operands[1])
|
||
&& GET_MODE_SIZE (GET_MODE (operands[0])) > UNITS_PER_WORD"
|
||
"mtsrim cr,%S1\;storem 0,0,%1,%0"
|
||
[(set_attr "type" "multi")])
|
||
|
||
(define_insn ""
|
||
[(match_parallel 0 "store_multiple_operation"
|
||
[(set (match_operand:SI 1 "memory_operand" "=m")
|
||
(match_operand:SI 2 "gpc_reg_operand" "r"))
|
||
(clobber (reg:SI 179))])]
|
||
"!TARGET_NO_STOREM_BUG"
|
||
"mtsrim cr,%V0\;storem 0,0,%2,%1"
|
||
[(set_attr "type" "multi")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand 0 "memory_operand" "=m")
|
||
(match_operand 1 "gpc_reg_operand" "r"))
|
||
(use (reg:SI 179))
|
||
(clobber (reg:SI 179))]
|
||
"TARGET_NO_STOREM_BUG
|
||
&& GET_MODE (operands[0]) == GET_MODE (operands[1])
|
||
&& GET_MODE_SIZE (GET_MODE (operands[0])) > UNITS_PER_WORD"
|
||
"storem 0,0,%1,%0"
|
||
[(set_attr "type" "store")])
|
||
|
||
(define_insn ""
|
||
[(match_parallel 0 "store_multiple_operation"
|
||
[(set (match_operand:SI 1 "memory_operand" "=m")
|
||
(match_operand:SI 2 "gpc_reg_operand" "r"))
|
||
(use (reg:SI 179))
|
||
(clobber (reg:SI 179))])]
|
||
"TARGET_NO_STOREM_BUG"
|
||
"storem 0,0,%2,%1"
|
||
[(set_attr "type" "store")])
|
||
|
||
;; SUB
|
||
;;
|
||
;; Either operand can be a register or an 8-bit constant, but both cannot be
|
||
;; constants (can't usually occur anyway).
|
||
(define_expand "subsi3"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(minus:SI (match_operand:SI 1 "srcb_operand" "")
|
||
(match_operand:SI 2 "srcb_operand" "")))]
|
||
""
|
||
"
|
||
{
|
||
if (GET_CODE (operands[0]) == CONST_INT
|
||
&& GET_CODE (operands[1]) == CONST_INT)
|
||
operands[1] = force_reg (SImode, operands[1]);
|
||
}")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
|
||
(minus:SI (match_operand:SI 1 "srcb_operand" "r,I")
|
||
(match_operand:SI 2 "srcb_operand" "rI,r")))]
|
||
"register_operand (operands[1], SImode)
|
||
|| register_operand (operands[2], SImode)"
|
||
"@
|
||
sub %0,%1,%2
|
||
subr %0,%2,%1")
|
||
|
||
(define_insn "subdi3"
|
||
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
|
||
(minus:DI (match_operand:DI 1 "gpc_reg_operand" "r")
|
||
(match_operand:DI 2 "gpc_reg_operand" "r")))]
|
||
""
|
||
"sub %L0,%L1,%L2\;subc %0,%1,%2"
|
||
[(set_attr "type" "multi")])
|
||
|
||
;; SUBR (also used above in SUB)
|
||
(define_insn "negdi2"
|
||
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
|
||
(neg:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
|
||
""
|
||
"subr %L0,%L1,0\;subrc %0,%1,0"
|
||
[(set_attr "type" "multi")])
|
||
|
||
(define_insn "negsi2"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(neg:SI (match_operand:SI 1 "gpc_reg_operand" "r")))]
|
||
""
|
||
"subr %0,%1,0")
|
||
|
||
;; XNOR
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(not:SI (xor:SI (match_operand:SI 1 "gpc_reg_operand" "%r")
|
||
(match_operand:SI 2 "srcb_operand" "rI"))))]
|
||
""
|
||
"xnor %0,%1,%2")
|
||
|
||
;; XOR
|
||
(define_insn "xorsi3"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(xor:SI (match_operand:SI 1 "gpc_reg_operand" "%r")
|
||
(match_operand:SI 2 "srcb_operand" "rI")))]
|
||
""
|
||
"xor %0,%1,%2")
|
||
|
||
;; Can use XOR to negate floating-point values, but we are better off not doing
|
||
;; it that way on the 29050 so it can combine with the fmac insns.
|
||
(define_expand "negsf2"
|
||
[(parallel [(set (match_operand:SF 0 "register_operand" "")
|
||
(neg:SF (match_operand:SF 1 "register_operand" "")))
|
||
(clobber (match_scratch:SI 2 ""))])]
|
||
""
|
||
"
|
||
{
|
||
rtx result;
|
||
rtx target;
|
||
|
||
if (! TARGET_29050)
|
||
{
|
||
target = operand_subword_force (operands[0], 0, SFmode);
|
||
result = expand_binop (SImode, xor_optab,
|
||
operand_subword_force (operands[1], 0, SFmode),
|
||
gen_rtx (CONST_INT, VOIDmode, 0x80000000),
|
||
target, 0, OPTAB_WIDEN);
|
||
if (result == 0)
|
||
abort ();
|
||
|
||
if (result != target)
|
||
emit_move_insn (result, target);
|
||
|
||
/* Make a place for REG_EQUAL. */
|
||
emit_move_insn (operands[0], operands[0]);
|
||
DONE;
|
||
}
|
||
}")
|
||
|
||
(define_expand "negdf2"
|
||
[(parallel [(set (match_operand:DF 0 "register_operand" "")
|
||
(neg:DF (match_operand:DF 1 "register_operand" "")))
|
||
(clobber (match_scratch:SI 2 ""))])]
|
||
""
|
||
"
|
||
{
|
||
rtx result;
|
||
rtx target;
|
||
rtx insns;
|
||
|
||
if (! TARGET_29050)
|
||
{
|
||
start_sequence ();
|
||
target = operand_subword (operands[0], 0, 1, DFmode);
|
||
result = expand_binop (SImode, xor_optab,
|
||
operand_subword_force (operands[1], 0, DFmode),
|
||
gen_rtx (CONST_INT, VOIDmode, 0x80000000),
|
||
target, 0, OPTAB_WIDEN);
|
||
if (result == 0)
|
||
abort ();
|
||
|
||
if (result != target)
|
||
emit_move_insn (result, target);
|
||
|
||
emit_move_insn (operand_subword (operands[0], 1, 1, DFmode),
|
||
operand_subword_force (operands[1], 1, DFmode));
|
||
|
||
insns = get_insns ();
|
||
end_sequence ();
|
||
|
||
emit_no_conflict_block (insns, operands[0], operands[1], 0, 0);
|
||
DONE;
|
||
}
|
||
}")
|
||
|
||
;; Sign extend and truncation operations.
|
||
(define_insn "zero_extendqihi2"
|
||
[(set (match_operand:HI 0 "gpc_reg_operand" "=r")
|
||
(zero_extend:HI (match_operand:QI 1 "gpc_reg_operand" "r")))]
|
||
""
|
||
"and %0,%1,255")
|
||
|
||
(define_insn "zero_extendqisi2"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(zero_extend:SI (match_operand:QI 1 "gpc_reg_operand" "r")))]
|
||
""
|
||
"and %0,%1,255")
|
||
|
||
(define_insn "zero_extendhisi2"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
|
||
(zero_extend:SI (match_operand:HI 1 "gpc_reg_operand" "0")))]
|
||
""
|
||
"consth %0,0")
|
||
|
||
(define_expand "extendqihi2"
|
||
[(set (match_dup 2)
|
||
(ashift:SI (match_operand:QI 1 "gpc_reg_operand" "")
|
||
(const_int 24)))
|
||
(set (match_operand:HI 0 "gpc_reg_operand" "")
|
||
(ashiftrt:SI (match_dup 2)
|
||
(const_int 24)))]
|
||
""
|
||
"
|
||
{ operands[0] = gen_lowpart (SImode, operands[0]);
|
||
operands[1] = gen_lowpart (SImode, operands[1]);
|
||
operands[2] = gen_reg_rtx (SImode); }")
|
||
|
||
(define_expand "extendqisi2"
|
||
[(set (match_dup 2)
|
||
(ashift:SI (match_operand:QI 1 "gpc_reg_operand" "")
|
||
(const_int 24)))
|
||
(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(ashiftrt:SI (match_dup 2)
|
||
(const_int 24)))]
|
||
""
|
||
"
|
||
{ operands[1] = gen_lowpart (SImode, operands[1]);
|
||
operands[2] = gen_reg_rtx (SImode); }")
|
||
|
||
(define_expand "extendhisi2"
|
||
[(set (match_dup 2)
|
||
(ashift:SI (match_operand:HI 1 "gpc_reg_operand" "")
|
||
(const_int 16)))
|
||
(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(ashiftrt:SI (match_dup 2)
|
||
(const_int 16)))]
|
||
""
|
||
"
|
||
{ operands[1] = gen_lowpart (SImode, operands[1]);
|
||
operands[2] = gen_reg_rtx (SImode); }")
|
||
|
||
;; Define the methods used to move data around.
|
||
;;
|
||
;; movsi:
|
||
;;
|
||
;; If storing into memory, force source into register.
|
||
(define_expand "movsi"
|
||
[(set (match_operand:SI 0 "general_operand" "")
|
||
(match_operand:SI 1 "general_operand" ""))]
|
||
""
|
||
"
|
||
{
|
||
if (GET_CODE (operands[0]) == MEM && ! gpc_reg_operand (operands[1], SImode))
|
||
operands[1] = copy_to_mode_reg (SImode, operands[1]);
|
||
else if (spec_reg_operand (operands[0], SImode)
|
||
&& ! (register_operand (operands[1], SImode)
|
||
|| cint_16_operand (operands[1], SImode)))
|
||
operands[1] = force_reg (SImode, operands[1]);
|
||
}")
|
||
|
||
(define_split
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(match_operand:SI 1 "long_const_operand" ""))]
|
||
""
|
||
[(set (match_dup 0)
|
||
(and:SI (match_dup 1)
|
||
(const_int 65535)))
|
||
(set (match_dup 0)
|
||
(ior:SI (and:SI (match_dup 0)
|
||
(const_int 65535))
|
||
(and:SI (match_dup 1)
|
||
(const_int -65536))))]
|
||
"")
|
||
|
||
;; Subroutines to load/store halfwords. Use TAV (gr121) as scratch. We have
|
||
;; two versions of storehi, one when halfword writes are supported and one
|
||
;; where they aren't.
|
||
(define_expand "loadhi"
|
||
[(parallel [(set (match_dup 2)
|
||
(mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(const_int -4))))
|
||
(set (reg:SI 177)
|
||
(and:SI (match_dup 0)
|
||
(const_int 2)))])
|
||
(set (match_operand:HI 1 "gpc_reg_operand" "")
|
||
(zero_extract:SI (match_dup 2)
|
||
(const_int 16)
|
||
(ashift:SI (reg:SI 177)
|
||
(const_int 3))))]
|
||
""
|
||
"
|
||
{ operands[1] = gen_lowpart (SImode, operands[1]);
|
||
|
||
if (reload_in_progress)
|
||
operands[2] = gen_rtx (REG, SImode, R_TAV);
|
||
else
|
||
operands[2] = gen_reg_rtx (SImode);
|
||
}")
|
||
|
||
(define_expand "storehinhww"
|
||
[(parallel [(set (match_dup 2)
|
||
(mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(const_int -4))))
|
||
(set (reg:SI 177)
|
||
(and:SI (match_dup 0)
|
||
(const_int 2)))])
|
||
(set (zero_extract:SI (match_dup 2)
|
||
(const_int 16)
|
||
(ashift:SI (reg:SI 177)
|
||
(const_int 3)))
|
||
(match_operand:HI 1 "gpc_reg_operand" ""))
|
||
(set (mem:SI (match_dup 0))
|
||
(match_dup 2))]
|
||
""
|
||
"
|
||
{ operands[1] = gen_lowpart (SImode, operands[1]);
|
||
|
||
if (reload_in_progress)
|
||
operands[2] = gen_rtx (REG, SImode, R_TAV);
|
||
else
|
||
operands[2] = gen_reg_rtx (SImode);
|
||
}")
|
||
|
||
(define_expand "storehihww"
|
||
[(set (reg:SI 177)
|
||
(and:SI (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(const_int 3)))
|
||
(set (match_dup 2)
|
||
(ior:SI (and:SI (not:SI (ashift:SI (const_int 65535)
|
||
(ashift:SI (reg:SI 177)
|
||
(const_int 3))))
|
||
(match_operand:HI 1 "gpc_reg_operand" ""))
|
||
(ashift:SI (and:SI (match_dup 1)
|
||
(const_int 65535))
|
||
(ashift:SI (reg:SI 177)
|
||
(const_int 3)))))
|
||
(set (mem:SI (and:SI (match_dup 0)
|
||
(const_int -3)))
|
||
(match_dup 2))]
|
||
""
|
||
"
|
||
{ operands[1] = gen_lowpart (SImode, operands[1]);
|
||
|
||
if (reload_in_progress)
|
||
operands[2] = gen_rtx (REG, SImode, R_TAV);
|
||
else
|
||
operands[2] = gen_reg_rtx (SImode);
|
||
}")
|
||
|
||
(define_expand "movhi"
|
||
[(set (match_operand:HI 0 "general_operand" "")
|
||
(match_operand:HI 1 "general_operand" ""))]
|
||
""
|
||
"
|
||
{ if (GET_CODE (operands[0]) == MEM)
|
||
{
|
||
if (! gpc_reg_operand (operands[1], HImode))
|
||
operands[1] = copy_to_mode_reg (HImode, operands[1]);
|
||
if (! TARGET_DW_ENABLE)
|
||
{
|
||
if (TARGET_BYTE_WRITES)
|
||
emit_insn (gen_storehihww (XEXP (operands[0], 0), operands[1]));
|
||
else
|
||
emit_insn (gen_storehinhww (XEXP (operands[0], 0), operands[1]));
|
||
DONE;
|
||
}
|
||
}
|
||
else if (GET_CODE (operands[1]) == MEM)
|
||
{
|
||
if (! TARGET_DW_ENABLE)
|
||
{
|
||
emit_insn (gen_loadhi (XEXP (operands[1], 0), operands[0]));
|
||
DONE;
|
||
}
|
||
}
|
||
}")
|
||
|
||
;; Subroutines to load/store bytes. Use TAV (gr121) as scratch.
|
||
(define_expand "loadqi"
|
||
[(parallel [(set (match_dup 2)
|
||
(mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(const_int -4))))
|
||
(set (reg:SI 177)
|
||
(and:SI (match_dup 0)
|
||
(const_int 3)))])
|
||
(set (match_operand:QI 1 "gpc_reg_operand" "")
|
||
(zero_extract:SI (match_dup 2)
|
||
(const_int 8)
|
||
(ashift:SI (reg:SI 177)
|
||
(const_int 3))))]
|
||
""
|
||
"
|
||
{ operands[1] = gen_lowpart (SImode, operands[1]);
|
||
|
||
if (reload_in_progress)
|
||
operands[2] = gen_rtx (REG, SImode, R_TAV);
|
||
else
|
||
operands[2] = gen_reg_rtx (SImode);
|
||
}")
|
||
|
||
(define_expand "storeqinhww"
|
||
[(parallel [(set (match_dup 2)
|
||
(mem:SI (and:SI (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(const_int -4))))
|
||
(set (reg:SI 177)
|
||
(and:SI (match_dup 0)
|
||
(const_int 3)))])
|
||
(set (zero_extract:SI (match_dup 2)
|
||
(const_int 8)
|
||
(ashift:SI (reg:SI 177)
|
||
(const_int 3)))
|
||
(match_operand:QI 1 "gpc_reg_operand" ""))
|
||
(set (mem:SI (match_dup 0))
|
||
(match_dup 2))]
|
||
""
|
||
"
|
||
{ operands[1] = gen_lowpart (SImode, operands[1]);
|
||
|
||
if (reload_in_progress)
|
||
operands[2] = gen_rtx (REG, SImode, R_TAV);
|
||
else
|
||
operands[2] = gen_reg_rtx (SImode);
|
||
}")
|
||
|
||
(define_expand "storeqihww"
|
||
[(set (reg:SI 177)
|
||
(and:SI (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(const_int 3)))
|
||
(set (match_dup 2)
|
||
(ior:SI (and:SI (not:SI (ashift:SI (const_int 255)
|
||
(ashift:SI (reg:SI 177)
|
||
(const_int 3))))
|
||
(match_operand:HI 1 "gpc_reg_operand" ""))
|
||
(ashift:SI (and:SI (match_dup 1)
|
||
(const_int 255))
|
||
(ashift:SI (reg:SI 177)
|
||
(const_int 3)))))
|
||
(set (mem:SI (and:SI (match_dup 0)
|
||
(const_int -4)))
|
||
(match_dup 2))]
|
||
""
|
||
"
|
||
{ operands[1] = gen_lowpart (SImode, operands[1]);
|
||
|
||
if (reload_in_progress)
|
||
operands[2] = gen_rtx (REG, SImode, R_TAV);
|
||
else
|
||
operands[2] = gen_reg_rtx (SImode);
|
||
}")
|
||
|
||
(define_expand "movqi"
|
||
[(set (match_operand:QI 0 "general_operand" "")
|
||
(match_operand:QI 1 "general_operand" ""))]
|
||
""
|
||
"
|
||
{ if (GET_CODE (operands[0]) == MEM)
|
||
{
|
||
if (! gpc_reg_operand (operands[1], QImode))
|
||
operands[1] = copy_to_mode_reg (QImode, operands[1]);
|
||
if (! TARGET_DW_ENABLE)
|
||
{
|
||
if (TARGET_BYTE_WRITES)
|
||
emit_insn (gen_storeqihww (XEXP (operands[0], 0), operands[1]));
|
||
else
|
||
emit_insn (gen_storeqinhww (XEXP (operands[0], 0), operands[1]));
|
||
DONE;
|
||
}
|
||
}
|
||
else if (GET_CODE (operands[1]) == MEM)
|
||
{
|
||
if (! TARGET_DW_ENABLE)
|
||
{
|
||
emit_insn (gen_loadqi (XEXP (operands[1], 0), operands[0]));
|
||
DONE;
|
||
}
|
||
}
|
||
}")
|
||
|
||
;; Now the actual insns used to move data around. We include here the
|
||
;; DEFINE_SPLITs that may be needed. In some cases these will be
|
||
;; split again. For floating-point, if we can look inside the constant,
|
||
;; always split it. This can eliminate unnecessary insns.
|
||
(define_insn ""
|
||
[(set (match_operand:SF 0 "out_operand" "=r,r,r,r,m")
|
||
(match_operand:SF 1 "in_operand" "r,E,F,m,r"))]
|
||
"(gpc_reg_operand (operands[0], SFmode)
|
||
|| gpc_reg_operand (operands[1], SFmode))
|
||
&& ! TARGET_29050"
|
||
"@
|
||
sll %0,%1,0
|
||
#
|
||
const %0,%1\;consth %0,%1
|
||
load 0,0,%0,%1
|
||
store 0,0,%1,%0"
|
||
[(set_attr "type" "misc,multi,multi,load,store")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SF 0 "out_operand" "=r,r,r,r,m,*a,r")
|
||
(match_operand:SF 1 "in_operand" "r,E,F,m,r,r,*a"))]
|
||
"(gpc_reg_operand (operands[0], SFmode)
|
||
|| gpc_reg_operand (operands[1], SFmode))
|
||
&& TARGET_29050"
|
||
"@
|
||
sll %0,%1,0
|
||
#
|
||
const %0,%1\;consth %0,%1
|
||
load 0,0,%0,%1
|
||
store 0,0,%1,%0
|
||
mtacc %1,1,%0
|
||
mfacc %0,1,%1"
|
||
[(set_attr "type" "misc,multi,multi,load,store,fadd,fadd")])
|
||
|
||
;; Turn this into SImode. It will then be split up that way.
|
||
(define_split
|
||
[(set (match_operand:SF 0 "register_operand" "")
|
||
(match_operand:SF 1 "float_const_operand" ""))]
|
||
"HOST_FLOAT_FORMAT == TARGET_FLOAT_FORMAT"
|
||
[(set (match_dup 0)
|
||
(match_dup 1))]
|
||
"
|
||
{ operands[0] = operand_subword (operands[0], 0, 0, SFmode);
|
||
operands[1] = operand_subword (operands[1], 0, 0, SFmode);
|
||
|
||
if (operands[0] == 0 || operands[1] == 0)
|
||
FAIL;
|
||
}")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:DF 0 "out_operand" "=r,r,r,m")
|
||
(match_operand:DF 1 "in_operand" "rE,F,m,r"))
|
||
(clobber (reg:SI 179))]
|
||
"(gpc_reg_operand (operands[0], DFmode)
|
||
|| gpc_reg_operand (operands[1], DFmode))
|
||
&& ! TARGET_29050"
|
||
"@
|
||
#
|
||
const %0,%1\;consth %0,%1\;const %L0,%L1\;consth %L0,%L1
|
||
mtsrim cr,1\;loadm 0,0,%0,%1
|
||
mtsrim cr,1\;storem 0,0,%1,%0"
|
||
[(set_attr "type" "multi")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:DF 0 "out_operand" "=r,r,&r,m,*a,r")
|
||
(match_operand:DF 1 "in_operand" "rE,F,m,r,r,*a"))
|
||
(clobber (reg:SI 179))]
|
||
"(gpc_reg_operand (operands[0], DFmode)
|
||
|| gpc_reg_operand (operands[1], DFmode))
|
||
&& TARGET_29050"
|
||
"@
|
||
#
|
||
const %0,%1\;consth %0,%1\;const %L0,%L1\;consth %L0,%L1
|
||
mtsrim cr,1\;loadm 0,0,%0,%1
|
||
mtsrim cr,1\;storem 0,0,%1,%0
|
||
mtacc %1,2,%0
|
||
mfacc %0,2,%1"
|
||
[(set_attr "type" "multi,multi,multi,multi,fadd,fadd")])
|
||
|
||
;; Split register-register copies and constant loads into two SImode loads,
|
||
;; one for each word. In the constant case, they will get further split.
|
||
;; Don't so this until register allocation, though, since it will
|
||
;; interfere with register allocation. Normally copy the lowest-addressed
|
||
;; word first; the exception is if we are copying register to register and
|
||
;; the lowest register of the first operand is the highest register of the
|
||
;; second operand.
|
||
(define_split
|
||
[(set (match_operand:DF 0 "gpc_reg_operand" "")
|
||
(match_operand:DF 1 "gpc_reg_or_float_constant_operand" ""))
|
||
(clobber (reg:SI 179))]
|
||
"reload_completed"
|
||
[(set (match_dup 2) (match_dup 3))
|
||
(set (match_dup 4) (match_dup 5))]
|
||
"
|
||
{ if (GET_CODE (operands[1]) == REG
|
||
&& REGNO (operands[0]) == REGNO (operands[1]) + 1)
|
||
{
|
||
operands[2] = operand_subword (operands[0], 1, 1, DFmode);
|
||
operands[3] = operand_subword (operands[1], 1, 1, DFmode);
|
||
operands[4] = operand_subword (operands[0], 0, 1, DFmode);
|
||
operands[5] = operand_subword (operands[1], 0, 1, DFmode);
|
||
}
|
||
else
|
||
{
|
||
operands[2] = operand_subword (operands[0], 0, 1, DFmode);
|
||
operands[3] = operand_subword (operands[1], 0, 1, DFmode);
|
||
operands[4] = operand_subword (operands[0], 1, 1, DFmode);
|
||
operands[5] = operand_subword (operands[1], 1, 1, DFmode);
|
||
}
|
||
|
||
if (operands[2] == 0 || operands[3] == 0
|
||
|| operands[4] == 0 || operands[5] == 0)
|
||
FAIL;
|
||
}")
|
||
|
||
;; Split memory loads and stores into the MTSR and LOADM/STOREM.
|
||
(define_split
|
||
[(set (match_operand:DF 0 "out_operand" "")
|
||
(match_operand:DF 1 "in_operand" ""))
|
||
(clobber (reg:SI 179))]
|
||
"TARGET_NO_STOREM_BUG
|
||
&& (memory_operand (operands[0], DFmode)
|
||
|| memory_operand (operands[1], DFmode))"
|
||
[(set (reg:SI 179) (const_int 1))
|
||
(parallel [(set (match_dup 0) (match_dup 1))
|
||
(use (reg:SI 179))
|
||
(clobber (reg:SI 179))])]
|
||
"")
|
||
|
||
;; DI move is similar to DF move.
|
||
(define_insn ""
|
||
[(set (match_operand:DI 0 "out_operand" "=r,r,m")
|
||
(match_operand:DI 1 "in_operand" "rn,m,r"))
|
||
(clobber (reg:SI 179))]
|
||
"(gpc_reg_operand (operands[0], DImode)
|
||
|| gpc_reg_operand (operands[1], DImode))
|
||
&& ! TARGET_29050"
|
||
"@
|
||
#
|
||
mtsrim cr,1\;loadm 0,0,%0,%1
|
||
mtsrim cr,1\;storem 0,0,%1,%0"
|
||
[(set_attr "type" "multi")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:DI 0 "out_operand" "=r,&r,m")
|
||
(match_operand:DI 1 "in_operand" "rn,m,r"))
|
||
(clobber (reg:SI 179))]
|
||
"(gpc_reg_operand (operands[0], DImode)
|
||
|| gpc_reg_operand (operands[1], DImode))
|
||
&& TARGET_29050"
|
||
"@
|
||
#
|
||
mtsrim cr,1\;loadm 0,0,%0,%1
|
||
mtsrim cr,1\;storem 0,0,%1,%0"
|
||
[(set_attr "type" "multi")])
|
||
|
||
(define_split
|
||
[(set (match_operand:DI 0 "gpc_reg_operand" "")
|
||
(match_operand:DI 1 "gpc_reg_or_integer_constant_operand" ""))
|
||
(clobber (reg:SI 179))]
|
||
"reload_completed"
|
||
[(set (match_dup 2) (match_dup 3))
|
||
(set (match_dup 4) (match_dup 5))]
|
||
"
|
||
{ if (GET_CODE (operands[1]) == REG
|
||
&& REGNO (operands[0]) == REGNO (operands[1]) + 1)
|
||
{
|
||
operands[2] = operand_subword (operands[0], 1, 1, DImode);
|
||
operands[3] = operand_subword (operands[1], 1, 1, DImode);
|
||
operands[4] = operand_subword (operands[0], 0, 1, DImode);
|
||
operands[5] = operand_subword (operands[1], 0, 1, DImode);
|
||
}
|
||
else
|
||
{
|
||
operands[2] = operand_subword (operands[0], 0, 1, DImode);
|
||
operands[3] = operand_subword (operands[1], 0, 1, DImode);
|
||
operands[4] = operand_subword (operands[0], 1, 1, DImode);
|
||
operands[5] = operand_subword (operands[1], 1, 1, DImode);
|
||
}
|
||
}")
|
||
|
||
(define_split
|
||
[(set (match_operand:DI 0 "out_operand" "")
|
||
(match_operand:DI 1 "in_operand" ""))
|
||
(clobber (reg:SI 179))]
|
||
"TARGET_NO_STOREM_BUG
|
||
&& (memory_operand (operands[0], DImode)
|
||
|| memory_operand (operands[1], DImode))"
|
||
[(set (reg:SI 179) (const_int 1))
|
||
(parallel [(set (match_dup 0) (match_dup 1))
|
||
(use (reg:SI 179))
|
||
(clobber (reg:SI 179))])]
|
||
"")
|
||
|
||
;; TImode moves are very similar to DImode moves, except that we can't
|
||
;; have constants.
|
||
(define_insn ""
|
||
[(set (match_operand:TI 0 "out_operand" "=r,r,m")
|
||
(match_operand:TI 1 "in_operand" "r,m,r"))
|
||
(clobber (reg:SI 179))]
|
||
"(gpc_reg_operand (operands[0], TImode)
|
||
|| gpc_reg_operand (operands[1], TImode))
|
||
&& ! TARGET_29050"
|
||
"@
|
||
#
|
||
mtsrim cr,3\;loadm 0,0,%0,%1
|
||
mtsrim cr,3\;storem 0,0,%1,%0"
|
||
[(set_attr "type" "multi,multi,multi")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:TI 0 "out_operand" "=r,&r,m")
|
||
(match_operand:TI 1 "in_operand" "r,m,r"))
|
||
(clobber (reg:SI 179))]
|
||
"(gpc_reg_operand (operands[0], TImode)
|
||
|| gpc_reg_operand (operands[1], TImode))
|
||
&& TARGET_29050"
|
||
"@
|
||
#
|
||
mtsrim cr,3\;loadm 0,0,%0,%1
|
||
mtsrim cr,3\;storem 0,0,%1,%0"
|
||
[(set_attr "type" "multi,multi,multi")])
|
||
|
||
(define_split
|
||
[(set (match_operand:TI 0 "gpc_reg_operand" "")
|
||
(match_operand:TI 1 "gpc_reg_operand" ""))
|
||
(clobber (reg:SI 179))]
|
||
"reload_completed"
|
||
[(set (match_dup 2) (match_dup 3))
|
||
(set (match_dup 4) (match_dup 5))
|
||
(set (match_dup 6) (match_dup 7))
|
||
(set (match_dup 8) (match_dup 9))]
|
||
"
|
||
{
|
||
if (REGNO (operands[0]) >= REGNO (operands[1]) + 1
|
||
&& REGNO (operands[0]) <= REGNO (operands[1]) + 3)
|
||
{
|
||
operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 3);
|
||
operands[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 3);
|
||
operands[4] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
|
||
operands[5] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
|
||
operands[6] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
|
||
operands[7] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
|
||
operands[8] = gen_rtx (REG, SImode, REGNO (operands[0]));
|
||
operands[9] = gen_rtx (REG, SImode, REGNO (operands[1]));
|
||
}
|
||
else
|
||
{
|
||
operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]));
|
||
operands[3] = gen_rtx (REG, SImode, REGNO (operands[1]));
|
||
operands[4] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
|
||
operands[5] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
|
||
operands[6] = gen_rtx (REG, SImode, REGNO (operands[0]) + 2);
|
||
operands[7] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2);
|
||
operands[8] = gen_rtx (REG, SImode, REGNO (operands[0]) + 3);
|
||
operands[9] = gen_rtx (REG, SImode, REGNO (operands[1]) + 3);
|
||
}
|
||
}")
|
||
|
||
(define_split
|
||
[(set (match_operand:TI 0 "out_operand" "")
|
||
(match_operand:TI 1 "in_operand" ""))
|
||
(clobber (reg:SI 179))]
|
||
"TARGET_NO_STOREM_BUG
|
||
&& (memory_operand (operands[0], TImode)
|
||
|| memory_operand (operands[1], TImode))"
|
||
[(set (reg:SI 179) (const_int 1))
|
||
(parallel [(set (match_dup 0) (match_dup 1))
|
||
(use (reg:SI 179))
|
||
(clobber (reg:SI 179))])]
|
||
"")
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "out_operand" "=r,r,r,r,r,r,r,m,*h,*h")
|
||
(match_operand:SI 1 "in_operand" "r,J,M,O,i,m,*h,r,r,J"))]
|
||
"(gpc_reg_operand (operands[0], SImode)
|
||
|| gpc_reg_operand (operands[1], SImode)
|
||
|| (spec_reg_operand (operands[0], SImode)
|
||
&& cint_16_operand (operands[1], SImode)))
|
||
&& ! TARGET_29050"
|
||
"@
|
||
sll %0,%1,0
|
||
const %0,%1
|
||
constn %0,%M1
|
||
cpeq %0,gr1,gr1
|
||
#
|
||
load 0,0,%0,%1
|
||
mfsr %0,%1
|
||
store 0,0,%1,%0
|
||
mtsr %0,%1
|
||
mtsrim %0,%1"
|
||
[(set_attr "type" "misc,misc,misc,misc,multi,load,misc,store,misc,misc")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:SI 0 "out_operand" "=r,r,r,r,r,r,r,m,*h,*h")
|
||
(match_operand:SI 1 "in_operand" "r,J,M,O,i,m,*h,r,r,J"))]
|
||
"(gpc_reg_operand (operands[0], SImode)
|
||
|| gpc_reg_operand (operands[1], SImode)
|
||
|| (spec_reg_operand (operands[0], SImode)
|
||
&& cint_16_operand (operands[1], SImode)))
|
||
&& TARGET_29050"
|
||
"@
|
||
sll %0,%1,0
|
||
const %0,%1
|
||
constn %0,%M1
|
||
consthz %0,%1
|
||
#
|
||
load 0,0,%0,%1
|
||
mfsr %0,%1
|
||
store 0,0,%1,%0
|
||
mtsr %0,%1
|
||
mtsrim %0,%1"
|
||
[(set_attr "type" "misc,misc,misc,misc,multi,load,misc,store,misc,misc")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:HI 0 "out_operand" "=r,r,r,m,r,*h,*h")
|
||
(match_operand:HI 1 "in_operand" "r,i,m,r,*h,r,i"))]
|
||
"gpc_reg_operand (operands[0], HImode)
|
||
|| gpc_reg_operand (operands[1], HImode)"
|
||
"@
|
||
sll %0,%1,0
|
||
const %0,%1
|
||
load 0,2,%0,%1
|
||
store 0,2,%1,%0
|
||
mfsr %0,%1
|
||
mtsr %0,%1
|
||
mtsrim %0,%1"
|
||
[(set_attr "type" "misc,misc,load,store,misc,misc,misc")])
|
||
|
||
(define_insn ""
|
||
[(set (match_operand:QI 0 "out_operand" "=r,r,r,m,r,*h,*h")
|
||
(match_operand:QI 1 "in_operand" "r,i,m,r,*h,r,i"))]
|
||
"gpc_reg_operand (operands[0], QImode)
|
||
|| gpc_reg_operand (operands[1], QImode)"
|
||
"@
|
||
sll %0,%1,0
|
||
const %0,%1
|
||
load 0,1,%0,%1
|
||
store 0,1,%1,%0
|
||
mfsr %0,%1
|
||
mtsr %0,%1
|
||
mtsrim %0,%1"
|
||
[(set_attr "type" "misc,misc,load,store,misc,misc,misc")])
|
||
|
||
;; Define move insns for DI, TI, SF, and DF.
|
||
;;
|
||
;; In no case do we support mem->mem directly.
|
||
;;
|
||
;; For DI move of constant to register, split apart at this time since these
|
||
;; can require anywhere from 2 to 4 insns and determining which is complex.
|
||
;;
|
||
;; In other cases, handle similarly to SImode moves.
|
||
;;
|
||
;; However, indicate that DI, TI, and DF moves (can) clobber CR (reg 179).
|
||
(define_expand "movdi"
|
||
[(parallel [(set (match_operand:DI 0 "general_operand" "")
|
||
(match_operand:DI 1 "general_operand" ""))
|
||
(clobber (reg:SI 179))])]
|
||
""
|
||
"
|
||
{
|
||
if (GET_CODE (operands[0]) == MEM)
|
||
operands[1] = force_reg (DImode, operands[1]);
|
||
}")
|
||
|
||
(define_expand "movsf"
|
||
[(set (match_operand:SF 0 "general_operand" "")
|
||
(match_operand:SF 1 "general_operand" ""))]
|
||
""
|
||
"
|
||
{ if (GET_CODE (operands[0]) == MEM)
|
||
operands[1] = force_reg (SFmode, operands[1]);
|
||
}")
|
||
|
||
(define_expand "movdf"
|
||
[(parallel [(set (match_operand:DF 0 "general_operand" "")
|
||
(match_operand:DF 1 "general_operand" ""))
|
||
(clobber (reg:SI 179))])]
|
||
""
|
||
"
|
||
{ if (GET_CODE (operands[0]) == MEM)
|
||
operands[1] = force_reg (DFmode, operands[1]);
|
||
}")
|
||
|
||
(define_expand "movti"
|
||
[(parallel [(set (match_operand:TI 0 "general_operand" "")
|
||
(match_operand:TI 1 "general_operand" ""))
|
||
(clobber (reg:SI 179))])]
|
||
""
|
||
"
|
||
{
|
||
if (GET_CODE (operands[0]) == MEM)
|
||
operands[1] = force_reg (TImode, operands[1]);
|
||
}")
|
||
|
||
;; For compare operations, we simply store the comparison operands and
|
||
;; do nothing else. The following branch or scc insn will output whatever
|
||
;; is needed.
|
||
(define_expand "cmpsi"
|
||
[(set (cc0)
|
||
(compare (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(match_operand:SI 1 "srcb_operand" "")))]
|
||
""
|
||
"
|
||
{
|
||
a29k_compare_op0 = operands[0];
|
||
a29k_compare_op1 = operands[1];
|
||
a29k_compare_fp_p = 0;
|
||
DONE;
|
||
}")
|
||
|
||
(define_expand "cmpsf"
|
||
[(set (cc0)
|
||
(compare (match_operand:SF 0 "gpc_reg_operand" "")
|
||
(match_operand:SF 1 "gpc_reg_operand" "")))]
|
||
""
|
||
"
|
||
{
|
||
a29k_compare_op0 = operands[0];
|
||
a29k_compare_op1 = operands[1];
|
||
a29k_compare_fp_p = 1;
|
||
DONE;
|
||
}")
|
||
|
||
(define_expand "cmpdf"
|
||
[(set (cc0)
|
||
(compare (match_operand:DF 0 "gpc_reg_operand" "")
|
||
(match_operand:DF 1 "gpc_reg_operand" "")))]
|
||
""
|
||
"
|
||
{
|
||
a29k_compare_op0 = operands[0];
|
||
a29k_compare_op1 = operands[1];
|
||
a29k_compare_fp_p = 1;
|
||
DONE;
|
||
}")
|
||
|
||
;; We can generate bit-tests better if we use NE instead of EQ, but we
|
||
;; don't have an NE for floating-point. So we have to have two patterns
|
||
;; for EQ and two for NE.
|
||
|
||
(define_expand "beq"
|
||
[(set (match_dup 1) (ne:SI (match_dup 2) (match_dup 3)))
|
||
(set (pc)
|
||
(if_then_else (ge (match_dup 1) (const_int 0))
|
||
(label_ref (match_operand 0 "" ""))
|
||
(pc)))]
|
||
""
|
||
"
|
||
{
|
||
if (GET_MODE_CLASS (GET_MODE (a29k_compare_op0)) == MODE_FLOAT)
|
||
{
|
||
emit_insn (gen_beq_fp (operands[0]));
|
||
DONE;
|
||
}
|
||
|
||
operands[1] = gen_reg_rtx (SImode);
|
||
operands[2] = a29k_compare_op0;
|
||
operands[3] = a29k_compare_op1;
|
||
}")
|
||
|
||
(define_expand "beq_fp"
|
||
[(set (match_dup 1) (eq:SI (match_dup 2) (match_dup 3)))
|
||
(set (pc)
|
||
(if_then_else (lt (match_dup 1) (const_int 0))
|
||
(label_ref (match_operand 0 "" ""))
|
||
(pc)))]
|
||
""
|
||
"
|
||
{
|
||
operands[1] = gen_reg_rtx (SImode);
|
||
operands[2] = a29k_compare_op0;
|
||
operands[3] = a29k_compare_op1;
|
||
}")
|
||
|
||
(define_expand "bne"
|
||
[(set (match_dup 1) (ne:SI (match_dup 2) (match_dup 3)))
|
||
(set (pc)
|
||
(if_then_else (lt (match_dup 1) (const_int 0))
|
||
(label_ref (match_operand 0 "" ""))
|
||
(pc)))]
|
||
""
|
||
"
|
||
{
|
||
if (GET_MODE_CLASS (GET_MODE (a29k_compare_op0)) == MODE_FLOAT)
|
||
{
|
||
emit_insn (gen_bne_fp (operands[0]));
|
||
DONE;
|
||
}
|
||
|
||
operands[1] = gen_reg_rtx (SImode);
|
||
operands[2] = a29k_compare_op0;
|
||
operands[3] = a29k_compare_op1;
|
||
}")
|
||
|
||
(define_expand "bne_fp"
|
||
[(set (match_dup 1) (eq:SI (match_dup 2) (match_dup 3)))
|
||
(set (pc)
|
||
(if_then_else (ge (match_dup 1) (const_int 0))
|
||
(label_ref (match_operand 0 "" ""))
|
||
(pc)))]
|
||
""
|
||
"
|
||
{
|
||
operands[1] = gen_reg_rtx (SImode);
|
||
operands[2] = a29k_compare_op0;
|
||
operands[3] = a29k_compare_op1;
|
||
}")
|
||
|
||
;; We don't have a floating-point "lt" insn, so we have to use "gt" in that
|
||
;; case with the operands swapped. The operands must both be registers in
|
||
;; the floating-point case, so we know that swapping them is OK.
|
||
(define_expand "blt"
|
||
[(set (match_dup 1) (match_dup 2))
|
||
(set (pc)
|
||
(if_then_else (lt (match_dup 1) (const_int 0))
|
||
(label_ref (match_operand 0 "" ""))
|
||
(pc)))]
|
||
""
|
||
"
|
||
{
|
||
operands[1] = gen_reg_rtx (SImode);
|
||
if (a29k_compare_fp_p)
|
||
operands[2] = gen_rtx (GT, SImode, a29k_compare_op1, a29k_compare_op0);
|
||
else
|
||
operands[2] = gen_rtx (LT, SImode, a29k_compare_op0, a29k_compare_op1);
|
||
}")
|
||
|
||
;; Similarly for "le".
|
||
(define_expand "ble"
|
||
[(set (match_dup 1) (match_dup 2))
|
||
(set (pc)
|
||
(if_then_else (lt (match_dup 1) (const_int 0))
|
||
(label_ref (match_operand 0 "" ""))
|
||
(pc)))]
|
||
""
|
||
"
|
||
{
|
||
operands[1] = gen_reg_rtx (SImode);
|
||
if (a29k_compare_fp_p)
|
||
operands[2] = gen_rtx (GE, SImode, a29k_compare_op1, a29k_compare_op0);
|
||
else
|
||
operands[2] = gen_rtx (LE, SImode, a29k_compare_op0, a29k_compare_op1);
|
||
}")
|
||
|
||
(define_expand "bltu"
|
||
[(set (match_dup 1) (ltu:SI (match_dup 2) (match_dup 3)))
|
||
(set (pc)
|
||
(if_then_else (lt (match_dup 1) (const_int 0))
|
||
(label_ref (match_operand 0 "" ""))
|
||
(pc)))]
|
||
""
|
||
"
|
||
{
|
||
operands[1] = gen_reg_rtx (SImode);
|
||
operands[2] = a29k_compare_op0;
|
||
operands[3] = a29k_compare_op1;
|
||
}")
|
||
|
||
(define_expand "bleu"
|
||
[(set (match_dup 1) (leu:SI (match_dup 2) (match_dup 3)))
|
||
(set (pc)
|
||
(if_then_else (lt (match_dup 1) (const_int 0))
|
||
(label_ref (match_operand 0 "" ""))
|
||
(pc)))]
|
||
""
|
||
"
|
||
{
|
||
operands[1] = gen_reg_rtx (SImode);
|
||
operands[2] = a29k_compare_op0;
|
||
operands[3] = a29k_compare_op1;
|
||
}")
|
||
|
||
(define_expand "bgt"
|
||
[(set (match_dup 1) (gt:SI (match_dup 2) (match_dup 3)))
|
||
(set (pc)
|
||
(if_then_else (lt (match_dup 1) (const_int 0))
|
||
(label_ref (match_operand 0 "" ""))
|
||
(pc)))]
|
||
""
|
||
"
|
||
{
|
||
operands[1] = gen_reg_rtx (SImode);
|
||
operands[2] = a29k_compare_op0;
|
||
operands[3] = a29k_compare_op1;
|
||
}")
|
||
|
||
(define_expand "bge"
|
||
[(set (match_dup 1) (ge:SI (match_dup 2) (match_dup 3)))
|
||
(set (pc)
|
||
(if_then_else (lt (match_dup 1) (const_int 0))
|
||
(label_ref (match_operand 0 "" ""))
|
||
(pc)))]
|
||
""
|
||
"
|
||
{
|
||
operands[1] = gen_reg_rtx (SImode);
|
||
operands[2] = a29k_compare_op0;
|
||
operands[3] = a29k_compare_op1;
|
||
}")
|
||
|
||
(define_expand "bgtu"
|
||
[(set (match_dup 1) (gtu:SI (match_dup 2) (match_dup 3)))
|
||
(set (pc)
|
||
(if_then_else (lt (match_dup 1) (const_int 0))
|
||
(label_ref (match_operand 0 "" ""))
|
||
(pc)))]
|
||
""
|
||
"
|
||
{
|
||
operands[1] = gen_reg_rtx (SImode);
|
||
operands[2] = a29k_compare_op0;
|
||
operands[3] = a29k_compare_op1;
|
||
}")
|
||
|
||
(define_expand "bgeu"
|
||
[(set (match_dup 1) (geu:SI (match_dup 2) (match_dup 3)))
|
||
(set (pc)
|
||
(if_then_else (lt (match_dup 1) (const_int 0))
|
||
(label_ref (match_operand 0 "" ""))
|
||
(pc)))]
|
||
""
|
||
"
|
||
{
|
||
operands[1] = gen_reg_rtx (SImode);
|
||
operands[2] = a29k_compare_op0;
|
||
operands[3] = a29k_compare_op1;
|
||
}")
|
||
|
||
(define_expand "seq"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(eq:SI (match_dup 1) (match_dup 2)))]
|
||
""
|
||
"
|
||
{
|
||
operands[1] = a29k_compare_op0;
|
||
operands[2] = a29k_compare_op1;
|
||
}")
|
||
|
||
;; This is the most complicated case, because we don't have a floating-point
|
||
;; "ne" insn. If integer, handle normally. If floating-point, write the
|
||
;; compare and then write an insn to reverse the test.
|
||
(define_expand "sne_fp"
|
||
[(set (match_dup 3)
|
||
(eq:SI (match_operand 1 "gpc_reg_operand" "")
|
||
(match_operand 2 "gpc_reg_operand" "")))
|
||
(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(ge:SI (match_dup 3) (const_int 0)))]
|
||
""
|
||
"
|
||
{ operands[3] = gen_reg_rtx (SImode);
|
||
}");
|
||
|
||
(define_expand "sne"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(ne:SI (match_dup 1) (match_dup 2)))]
|
||
""
|
||
"
|
||
{
|
||
operands[1] = a29k_compare_op0;
|
||
operands[2] = a29k_compare_op1;
|
||
|
||
if (a29k_compare_fp_p)
|
||
{
|
||
emit_insn (gen_sne_fp (operands[0], operands[1], operands[2]));
|
||
DONE;
|
||
}
|
||
}")
|
||
|
||
;; We don't have a floating-point "lt" insn, so use "gt" and swap the
|
||
;; operands, the same as we do "blt".
|
||
(define_expand "slt"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(match_dup 1))]
|
||
""
|
||
"
|
||
{
|
||
if (a29k_compare_fp_p)
|
||
operands[1] = gen_rtx (GT, SImode, a29k_compare_op1, a29k_compare_op0);
|
||
else
|
||
operands[1] = gen_rtx (LT, SImode, a29k_compare_op0, a29k_compare_op1);
|
||
}")
|
||
|
||
;; Similarly for "le"
|
||
(define_expand "sle"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(match_dup 1))]
|
||
""
|
||
"
|
||
{
|
||
if (a29k_compare_fp_p)
|
||
operands[1] = gen_rtx (GE, SImode, a29k_compare_op1, a29k_compare_op0);
|
||
else
|
||
operands[1] = gen_rtx (LE, SImode, a29k_compare_op0, a29k_compare_op1);
|
||
}")
|
||
|
||
(define_expand "sltu"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(ltu:SI (match_dup 1) (match_dup 2)))]
|
||
""
|
||
"
|
||
{
|
||
operands[1] = a29k_compare_op0;
|
||
operands[2] = a29k_compare_op1;
|
||
}")
|
||
|
||
(define_expand "sleu"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(leu:SI (match_dup 1) (match_dup 2)))]
|
||
""
|
||
"
|
||
{
|
||
operands[1] = a29k_compare_op0;
|
||
operands[2] = a29k_compare_op1;
|
||
}")
|
||
|
||
(define_expand "sgt"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(gt:SI (match_dup 1) (match_dup 2)))]
|
||
""
|
||
"
|
||
{
|
||
operands[1] = a29k_compare_op0;
|
||
operands[2] = a29k_compare_op1;
|
||
}")
|
||
|
||
(define_expand "sge"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(ge:SI (match_dup 1) (match_dup 2)))]
|
||
""
|
||
"
|
||
{
|
||
operands[1] = a29k_compare_op0;
|
||
operands[2] = a29k_compare_op1;
|
||
}")
|
||
|
||
(define_expand "sgtu"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(gtu:SI (match_dup 1) (match_dup 2)))]
|
||
""
|
||
"
|
||
{
|
||
operands[1] = a29k_compare_op0;
|
||
operands[2] = a29k_compare_op1;
|
||
}")
|
||
|
||
(define_expand "sgeu"
|
||
[(set (match_operand:SI 0 "gpc_reg_operand" "")
|
||
(geu:SI (match_dup 1) (match_dup 2)))]
|
||
""
|
||
"
|
||
{
|
||
operands[1] = a29k_compare_op0;
|
||
operands[2] = a29k_compare_op1;
|
||
}")
|
||
|
||
;; Now define the actual jump insns.
|
||
(define_insn ""
|
||
[(set (pc)
|
||
(if_then_else (match_operator 0 "branch_operator"
|
||
[(match_operand:SI 1 "gpc_reg_operand" "r")
|
||
(const_int 0)])
|
||
(label_ref (match_operand 2 "" ""))
|
||
(pc)))]
|
||
""
|
||
"jmp%b0 %1,%l2%#"
|
||
[(set_attr "type" "branch")])
|
||
|
||
(define_insn ""
|
||
[(set (pc)
|
||
(if_then_else (match_operator 0 "branch_operator"
|
||
[(match_operand:SI 1 "gpc_reg_operand" "r")
|
||
(const_int 0)])
|
||
(return)
|
||
(pc)))]
|
||
"null_epilogue ()"
|
||
"jmp%b0i %1,lr0%#"
|
||
[(set_attr "type" "branch")])
|
||
|
||
(define_insn ""
|
||
[(set (pc)
|
||
(if_then_else (match_operator 0 "branch_operator"
|
||
[(match_operand:SI 1 "gpc_reg_operand" "r")
|
||
(const_int 0)])
|
||
(pc)
|
||
(label_ref (match_operand 2 "" ""))))]
|
||
""
|
||
"jmp%B0 %1,%l2%#"
|
||
[(set_attr "type" "branch")])
|
||
|
||
(define_insn ""
|
||
[(set (pc)
|
||
(if_then_else (match_operator 0 "branch_operator"
|
||
[(match_operand:SI 1 "gpc_reg_operand" "r")
|
||
(const_int 0)])
|
||
(pc)
|
||
(return)))]
|
||
"null_epilogue ()"
|
||
"jmp%B0i %1,lr0%#"
|
||
[(set_attr "type" "branch")])
|
||
|
||
(define_insn "jump"
|
||
[(set (pc)
|
||
(label_ref (match_operand 0 "" "")))]
|
||
""
|
||
"jmp %e0%E0"
|
||
[(set_attr "type" "branch")])
|
||
|
||
(define_insn "return"
|
||
[(return)]
|
||
"null_epilogue ()"
|
||
"jmpi lr0%#"
|
||
[(set_attr "type" "branch")])
|
||
|
||
(define_insn "indirect_jump"
|
||
[(set (pc)
|
||
(match_operand:SI 0 "gpc_reg_operand" "r"))]
|
||
""
|
||
"jmpi %0%#"
|
||
[(set_attr "type" "branch")])
|
||
|
||
(define_insn "tablejump"
|
||
[(set (pc)
|
||
(match_operand:SI 0 "gpc_reg_operand" "r"))
|
||
(use (label_ref (match_operand 1 "" "")))]
|
||
""
|
||
"jmpi %0%#"
|
||
[(set_attr "type" "branch")])
|
||
|
||
;; JMPFDEC
|
||
(define_insn ""
|
||
[(set (pc)
|
||
(if_then_else (ge (match_operand:SI 0 "gpc_reg_operand" "r")
|
||
(const_int 0))
|
||
(label_ref (match_operand 1 "" ""))
|
||
(pc)))
|
||
(set (match_dup 0)
|
||
(plus:SI (match_dup 0)
|
||
(const_int -1)))]
|
||
""
|
||
"jmpfdec %0,%l1%#"
|
||
[(set_attr "type" "branch")])
|
||
|
||
;;- Local variables:
|
||
;;- mode:emacs-lisp
|
||
;;- comment-start: ";;- "
|
||
;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
|
||
;;- eval: (modify-syntax-entry ?[ "(]")
|
||
;;- eval: (modify-syntax-entry ?] ")[")
|
||
;;- eval: (modify-syntax-entry ?{ "(}")
|
||
;;- eval: (modify-syntax-entry ?} "){")
|
||
;;- End:
|