8sa1-gcc/gcc/config/clipper/clipper.md
Torbjorn Granlund 58371476ee (subdi3): Delete % from constraints.
From-SVN: r8402
1994-11-07 22:52:31 +00:00

1379 lines
34 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;- Machine description for GNU compiler, Clipper Version
;; Copyright (C) 1987, 1988, 1991, 1993, 1994 Free Software Foundation, Inc.
;; Contributed by Holger Teutsch (holger@hotbso.rhein-main.de)
;; 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.
;;- Instruction patterns. When multiple patterns apply,
;;- the first one in the file is chosen.
;;-
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
;;-
;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
;;- updates for most instructions.
;;
;; define attributes
;;
;; instruction type
;;
;; unknown is temporary in order to generate 'cc clobber' until attribute
;; assignment is consistent
;;
(define_attr "type" "load,store,arith,fp,branch,unknown"
(const_string "unknown"))
;; condition code setting
;;
;; clobber destroyed
;; unchanged
;; set1 set cc_status.value1, e.g. sub r0,r1
;; set2 set value1 and value2, e.g. mov r0,r1
;; change0 may be side effect, i.e. load mem,r0
;;
;; note: loadi and loadq are 'arith' instructions that set the condition codes
;; mul,div,mod do NOT set the condition codes
;;
(define_attr "cc" "clobber,unchanged,set1,set2,change0"
(cond [(eq_attr "type" "load") (const_string "change0")
(eq_attr "type" "store,branch") (const_string "unchanged")
(eq_attr "type" "arith") (if_then_else (match_operand:SI 0 "" "")
(const_string "set1")
(const_string "clobber"))
]
(const_string "clobber")))
;;
;; clipper seems to be a tradional risc processor
;; we define a functional unit 'memory'
;;
(define_function_unit "memory" 1 1 (eq_attr "type" "load") 4 0)
;; We don't want to allow a constant operand for test insns because
;; (set (cc0) (const_int foo)) has no mode information. Such insns will
;; be folded while optimizing anyway.
(define_insn "tstsi"
[(set (cc0)
(match_operand:SI 0 "int_reg_operand" "r"))]
""
"cmpq $0,%0")
(define_insn "cmpsi"
[(set (cc0)
(compare (match_operand:SI 0 "nonimmediate_operand" "r,r,n")
(match_operand:SI 1 "nonmemory_operand" "r,n,r")))]
""
"*
{
int val;
if (which_alternative == 0)
return \"cmpw %1,%0\";
if (which_alternative == 1)
{
val = INTVAL (operands[1]);
if (0 <= val && val < 16)
return \"cmpq %1,%0\";
return \"cmpi %1,%0\";
}
cc_status.flags |= CC_REVERSED; /* immediate must be first */
val = INTVAL (operands[0]);
if (0 <= val && val < 16)
return \"cmpq %0,%1\";
return \"cmpi %0,%1\";
}")
(define_insn "cmpdf"
[(set (cc0)
(compare (match_operand:DF 0 "fp_reg_operand" "f")
(match_operand:DF 1 "fp_reg_operand" "f")))]
""
"cmpd %1,%0")
(define_insn "cmpsf"
[(set (cc0)
(compare (match_operand:SF 0 "fp_reg_operand" "f")
(match_operand:SF 1 "fp_reg_operand" "f")))]
""
"cmps %1,%0")
;;
;; double and single float move
;;
(define_expand "movdf"
[(set (match_operand:DF 0 "general_operand" "")
(match_operand:DF 1 "general_operand" ""))]
""
"
{
if (GET_CODE (operands[0]) == MEM)
{
if (GET_CODE (operands[1]) == CONST_DOUBLE)
operands[1] = force_reg (DFmode,
force_const_mem (DFmode, operands[1]));
else if (GET_CODE (operands[1]) != REG)
operands[1] = force_reg (DFmode, operands[1]);
}
else if (GET_CODE (operands[1]) == CONST_DOUBLE)
operands[1] = force_const_mem (DFmode, operands[1]);
}")
;;
;; provide two patterns with different predicates as we don't want combine
;; to recombine a mem -> mem move
;;
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=*rf")
(match_operand:DF 1 "nonimmediate_operand" "*rfo"))]
""
"*
{
#define FP_REG_P(X) (GET_CODE (X) == REG && REGNO (X) >= 16)
if (FP_REG_P (operands[0]))
{
if (FP_REG_P (operands[1])) /* f -> f */
return \"movd %1,%0\";
if (GET_CODE (operands[1]) == REG) /* r -> f */
return \"movld %1,%0\";
return \"loadd %1,%0\"; /* m -> f */
}
if (FP_REG_P (operands[1]))
{
if (GET_CODE (operands[0]) == REG) /* f -> r */
return \"movdl %1,%0\";
abort ();
}
if (GET_CODE (operands[1]) == MEM) /* m -> r */
{
rtx xops[4];
xops[0] = operands[0];
xops[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
xops[2] = operands[1];
xops[3] = adj_offsettable_operand (operands[1], 4);
output_asm_insn (\"loadw %2,%0\;loadw %3,%1\", xops);
return \"\";
}
if (GET_CODE (operands[1]) == REG) /* r -> r */
{
rtx xops[4];
xops[0] = operands[0];
xops[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
xops[2] = operands[1];
xops[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
output_asm_insn (\"movw %2,%0\;movw %3,%1\", xops);
return \"\";
}
abort ();
#undef FP_REG_P
}")
(define_insn ""
[(set (match_operand:DF 0 "memory_operand" "=o,m")
(match_operand:DF 1 "register_operand" "*rf,f"))]
""
"*
{
rtx xops[4];
if (REGNO (operands[1]) >= 16) /* f -> m */
return \"stord %1,%0\";
xops[0] = operands[0]; /* r -> o */
xops[1] = adj_offsettable_operand (operands[0], 4);
xops[2] = operands[1];
xops[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
output_asm_insn (\"storw %2,%0\;storw %3,%1\", xops);
return \"\";
}"
[(set_attr "type" "store,store")
(set_attr "cc" "clobber,unchanged")])
(define_expand "movsf"
[(set (match_operand:SF 0 "general_operand" "")
(match_operand:SF 1 "general_operand" ""))]
""
"
{
if (GET_CODE (operands[0]) == MEM)
{
if (GET_CODE (operands[1]) == CONST_DOUBLE)
operands[1] = force_reg (SFmode,
force_const_mem (SFmode, operands[1]));
else if (GET_CODE (operands[1]) != REG)
operands[1] = force_reg (SFmode, operands[1]);
}
else if (GET_CODE (operands[1]) == CONST_DOUBLE)
operands[1] = force_const_mem (SFmode, operands[1]);
}")
;;
;; provide two patterns with different predicates as we don't want combine
;; to recombine a mem -> mem move
;;
(define_insn ""
[(set (match_operand:SF 0 "register_operand" "=*rf")
(match_operand:SF 1 "nonimmediate_operand" "*rfm"))]
""
"*
{
#define FP_REG_P(X) (GET_CODE (X) == REG && REGNO (X) >= 16)
if (FP_REG_P (operands[0]))
{
if (FP_REG_P (operands[1])) /* f -> f */
return \"movs %1,%0\";
if (GET_CODE (operands[1]) == REG) /* r -> f */
return
\"subq $8,sp\;storw %1,(sp)\;loads (sp),%0\;addq $8,sp\";
return \"loads %1,%0\"; /* m -> f */
}
if (FP_REG_P (operands[1]))
{
if (GET_CODE (operands[0]) == REG) /* f -> r */
return
\"subq $8,sp\;stors %1,(sp)\;loadw (sp),%0\;addq $8,sp\";
abort ();
}
if (GET_CODE (operands[1]) == MEM) /* m -> r */
return \"loadw %1,%0\";
if (GET_CODE (operands[1]) == REG) /* r -> r */
return \"movw %1,%0\";
abort ();
#undef FP_REG_P
}")
(define_insn ""
[(set (match_operand:SF 0 "memory_operand" "=m")
(match_operand:SF 1 "register_operand" "*rf"))]
""
"*
{
if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) >= 16)
return \"stors %1,%0\"; /* f-> m */
return \"storw %1,%0\"; /* r -> m */
}"
[(set_attr "type" "store")])
(define_expand "movdi"
[(set (match_operand:DI 0 "general_operand" "")
(match_operand:DI 1 "general_operand" ""))]
""
"
{
if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) != REG)
operands[1] = force_reg (DImode, operands[1]);
}")
;; If an operand is a MEM but not offsetable, we can't load it into
;; a register, so we must force the third alternative to be the one
;; reloaded. Hence we show the first as more expensive.
(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=?r,r,r")
(match_operand:DI 1 "general_operand" "r,n,o"))]
""
"*
{
rtx xoperands[2],yoperands[2];
xoperands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
if (which_alternative == 0) /* r -> r */
{
output_asm_insn (\"movw %1,%0\", operands);
xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
output_asm_insn (\"movw %1,%0\", xoperands);
return \"\";
}
if (which_alternative == 1) /* n -> r */
{
if (GET_CODE (operands[1]) == CONST_INT)
{
output_asm_insn (\"loadi %1,%0\", operands);
output_asm_insn (\"loadq $0,%0\", xoperands);
return \"\";
}
if (GET_CODE (operands[1]) != CONST_DOUBLE)
abort ();
yoperands[0] = operands[0];
yoperands[1] = gen_rtx (CONST_INT, VOIDmode,
CONST_DOUBLE_LOW (operands[1]));
output_asm_insn (\"loadi %1,%0\", yoperands);
xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
CONST_DOUBLE_HIGH (operands[1]));
output_asm_insn (\"loadi %1,%0\", xoperands);
return \"\";
}
/* m -> r */
output_asm_insn (\"loadw %1,%0\", operands);
xoperands[1] = adj_offsettable_operand (operands[1], 4);
output_asm_insn (\"loadw %1,%0\", xoperands);
return \"\";
}"
[(set_attr "type" "arith,arith,load")
(set_attr "cc" "clobber,clobber,clobber")])
(define_insn ""
[(set (match_operand:DI 0 "memory_operand" "=o")
(match_operand:DI 1 "register_operand" "r"))]
""
"*
{
rtx xops[4];
xops[0] = operands[0];
xops[1] = adj_offsettable_operand (operands[0], 4);
xops[2] = operands[1];
xops[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
output_asm_insn (\"storw %2,%0\;storw %3,%1\", xops);
return \"\";
}"
[(set_attr "type" "store")
(set_attr "cc" "clobber")])
(define_expand "movsi"
[(set (match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" ""))]
""
"
{
if (GET_CODE (operands[0]) == MEM &&
GET_CODE (operands[1]) != REG)
operands[1] = force_reg (SImode, operands[1]);
}")
;; provide 2 patterns with different predicates as 'general_operand' in both
;; positions results in a 'mem -> mem' move from combine that must be reloaded
;;
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
(match_operand:SI 1 "general_operand" "r,m,n,i"))]
""
"*
{
int val;
if (which_alternative == 0)
return \"movw %1,%0\"; /* reg -> reg */
if (which_alternative == 1)
return \"loadw %1,%0\"; /* mem -> reg */
if (which_alternative == 2)
{
val = INTVAL (operands[1]); /* known const ->reg */
if (val == -1)
return \"notq $0,%0\";
if (val < 0 || val >= 16)
return \"loadi %1,%0\";
return \"loadq %1,%0\";
}
if (which_alternative == 3) /* unknown const */
return \"loada %a1,%0\";
}"
[(set_attr "type" "arith,load,arith,load")
(set_attr "cc" "set2,change0,set1,change0")])
(define_insn ""
[(set (match_operand:SI 0 "memory_operand" "=m")
(match_operand:SI 1 "int_reg_operand" "r"))]
""
"storw %1,%0"
[(set_attr "type" "store")])
;; movhi
;;
;; loadh mem to reg
;; storh reg to mem
;;
;;
(define_expand "movhi"
[(set (match_operand:HI 0 "general_operand" "")
(match_operand:HI 1 "general_operand" ""))]
""
"
{
if (GET_CODE (operands[0]) == MEM
&& ! register_operand (operands[1], HImode))
operands[1] = force_reg (HImode, operands[1]);
}")
(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r,r")
(match_operand:HI 1 "general_operand" "r,m,n"))]
""
"@
movw %1,%0
loadh %1,%0
loadi %1,%0"
[(set_attr "type" "arith,load,arith")])
(define_insn ""
[(set (match_operand:HI 0 "memory_operand" "=m")
(match_operand:HI 1 "register_operand" "r"))]
""
"storh %1,%0"
[(set_attr "type" "store")])
;; movqi
;;
;; loadb mem to reg
;; storb reg to mem
;;
(define_expand "movqi"
[(set (match_operand:QI 0 "general_operand" "")
(match_operand:QI 1 "general_operand" ""))]
""
"
{
if (GET_CODE (operands[0]) == MEM &&
! register_operand (operands[1], QImode))
operands[1] = force_reg (QImode, operands[1]);
}")
(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=r,r,r")
(match_operand:QI 1 "general_operand" "r,m,n"))]
""
"@
movw %1,%0
loadb %1,%0
loadi %1,%0"
[(set_attr "type" "arith,load,arith")])
(define_insn ""
[(set (match_operand:QI 0 "memory_operand" "=m")
(match_operand:QI 1 "register_operand" "r"))]
""
"storb %1,%0"
[(set_attr "type" "store")])
;;
;; block move
;;
(define_expand "movstrsi"
[(parallel
[(set (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:SI 2 "general_operand" ""))
(use (match_operand:SI 3 "const_int_operand" ""))
(clobber (match_scratch:SI 4 ""))
(clobber (match_scratch:SI 5 ""))
(clobber (match_dup 6))
(clobber (match_dup 7))])]
""
"
{
rtx addr0, addr1;
addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
operands[6] = addr0;
operands[7] = addr1;
operands[0] = gen_rtx (MEM, BLKmode, addr0);
operands[1] = gen_rtx (MEM, BLKmode, addr1);
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = force_reg (SImode, operands[2]);
}")
;;
;; there is a problem with this insn in gcc-2.2.3
;; (clobber (match_dup 2)) does not prevent use of this operand later
;; we always use a scratch register and leave operand 2 unchanged
;;
(define_insn ""
[(set (mem:BLK (match_operand:SI 0 "register_operand" "r"))
(mem:BLK (match_operand:SI 1 "register_operand" "r")))
(use (match_operand:SI 2 "nonmemory_operand" "rn"))
(use (match_operand:SI 3 "const_int_operand" "n"))
(clobber (match_scratch:SI 4 "=r"))
(clobber (match_scratch:SI 5 "=r"))
(clobber (match_dup 0))
(clobber (match_dup 1))]
""
"*
{
extern void clipper_movstr ();
clipper_movstr (operands);
return \"\";
}"
[(set_attr "cc" "clobber")])
;; Extension and truncation insns.
(define_insn "extendhisi2"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r")
(sign_extend:SI (match_operand:HI 1 "general_operand" "0,m")))]
""
"@
andi $65535,%0\;xori $32768,%0\;subi $32768,%0
loadh %1,%0"
[(set_attr "type" "arith,load")])
(define_insn "extendqihi2"
[(set (match_operand:HI 0 "int_reg_operand" "=r,r")
(sign_extend:HI (match_operand:QI 1 "general_operand" "0,m")))]
""
"@
andi $255,%0\;xori $128,%0\;subi $128,%0
loadb %1,%0"
[(set_attr "type" "arith,load")
(set_attr "cc" "set1,change0")])
(define_insn "extendqisi2"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r")
(sign_extend:SI (match_operand:QI 1 "general_operand" "0,m")))]
""
"@
andi $255,%0\;xori $128,%0\;subi $128,%0
loadb %1,%0"
[(set_attr "type" "arith,load")])
(define_insn "extendsfdf2"
[(set (match_operand:DF 0 "fp_reg_operand" "=f")
(float_extend:DF (match_operand:SF 1 "fp_reg_operand" "f")))]
""
"cnvsd %1,%0")
(define_insn "truncdfsf2"
[(set (match_operand:SF 0 "fp_reg_operand" "=f")
(float_truncate:SF (match_operand:DF 1 "fp_reg_operand" "f")))]
""
"cnvds %1,%0")
(define_insn "zero_extendhisi2"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r")
(zero_extend:SI (match_operand:HI 1 "general_operand" "0,m")))]
""
"@
andi $65535,%0
loadhu %1,%0"
[(set_attr "type" "arith,load")])
(define_insn "zero_extendqihi2"
[(set (match_operand:HI 0 "int_reg_operand" "=r,r")
(zero_extend:HI (match_operand:QI 1 "general_operand" "0,m")))]
""
"@
andi $255,%0
loadbu %1,%0"
[(set_attr "type" "arith,load")
(set_attr "cc" "clobber,clobber")])
(define_insn "zero_extendqisi2"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r")
(zero_extend:SI (match_operand:QI 1 "general_operand" "0,m")))]
""
"@
andi $255,%0
loadbu %1,%0"
[(set_attr "type" "arith,load")])
;; Fix-to-float conversion insns.
(define_insn "floatsisf2"
[(set (match_operand:SF 0 "fp_reg_operand" "=f")
(float:SF (match_operand:SI 1 "int_reg_operand" "r")))]
""
"cnvws %1,%0")
(define_insn "floatsidf2"
[(set (match_operand:DF 0 "fp_reg_operand" "=f")
(float:DF (match_operand:SI 1 "int_reg_operand" "r")))]
""
"cnvwd %1,%0")
;; Float-to-fix conversion insns.
(define_insn "fix_truncsfsi2"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(fix:SI (fix:SF (match_operand:SF 1 "fp_reg_operand" "f"))))]
""
"cnvtsw %1,%0")
(define_insn "fix_truncdfsi2"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(fix:SI (fix:DF (match_operand:DF 1 "fp_reg_operand" "f"))))]
""
"cnvtdw %1,%0")
;;- All kinds of add instructions.
(define_insn "adddf3"
[(set (match_operand:DF 0 "fp_reg_operand" "=f")
(plus:DF (match_operand:DF 1 "fp_reg_operand" "0")
(match_operand:DF 2 "fp_reg_operand" "f")))]
""
"addd %2,%0"
[(set_attr "type" "fp")])
(define_insn "addsf3"
[(set (match_operand:SF 0 "fp_reg_operand" "=f")
(plus:SF (match_operand:SF 1 "fp_reg_operand" "0")
(match_operand:SF 2 "fp_reg_operand" "f")))]
""
"adds %2,%0"
[(set_attr "type" "fp")])
(define_insn "adddi3"
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(plus:DI (match_operand:DI 1 "int_reg_operand" "%0")
(match_operand:DI 2 "int_reg_operand" "r")))]
""
"*
{
rtx xoperands[4];
xoperands[0] = operands[0];
xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
xoperands[2] = operands[2];
xoperands[3] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
output_asm_insn (\"addw %2,%0\;addwc %3,%1\", xoperands);
return \"\";
}"
[(set_attr "type" "arith")
(set_attr "cc" "clobber")])
(define_insn "addsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r,r")
(plus:SI (match_operand:SI 1 "int_reg_operand" "%0,r,r")
(match_operand:SI 2 "nonmemory_operand" "rn,0,rn")))]
""
"*
{
if (which_alternative == 2) /* 3 address version */
{
if (GET_CODE (operands[2]) == CONST_INT)
return \"loada %a2(%1),%0\";
return \"loada [%2](%1),%0\";
}
/* 2 address version */
if (GET_CODE (operands[2]) == CONST_INT)
{
int val = INTVAL (operands[2]);
if (val >= 16 || val == 0x80000000)
return \"addi %2,%0\";
if (val < 0) /* change to sub */
{
rtx xops[2];
val = -val;
xops[0] = operands[0];
xops[1] = gen_rtx (CONST_INT, VOIDmode, val);
if (val >= 16)
output_asm_insn (\"subi %1,%0\", xops);
else
output_asm_insn (\"subq %1,%0\", xops);
return \"\";
}
return \"addq %2,%0\";
}
if (which_alternative == 0)
return \"addw %2,%0\";
return \"addw %1,%0\";
}"
[(set_attr "type" "arith,arith,arith")
(set_attr "cc" "set1,set1,change0")])
;;- All kinds of subtract instructions.
(define_insn "subdi3"
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(minus:DI (match_operand:DI 1 "int_reg_operand" "0")
(match_operand:DI 2 "int_reg_operand" "r")))]
""
"*
{
rtx xoperands[4];
xoperands[0] = operands[0];
xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
xoperands[2] = operands[2];
xoperands[3] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
output_asm_insn (\"subw %2,%0\;subwc %3,%1\", xoperands);
return \"\";
}"
[(set_attr "type" "arith")
(set_attr "cc" "clobber")])
(define_insn "subsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(minus:SI (match_operand:SI 1 "int_reg_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "rn")))]
""
"*
{
if (GET_CODE (operands[2]) == CONST_INT)
{
int val = INTVAL (operands[2]);
if (val < 0 || val >= 16)
return \"subi %2,%0\";
else
return \"subq %2,%0\";
}
return \"subw %2,%0\";
}"
[(set_attr "type" "arith")])
(define_insn "subdf3"
[(set (match_operand:DF 0 "fp_reg_operand" "=f")
(minus:DF (match_operand:DF 1 "fp_reg_operand" "0")
(match_operand:DF 2 "fp_reg_operand" "f")))]
""
"subd %2,%0"
[(set_attr "type" "fp")])
(define_insn "subsf3"
[(set (match_operand:SF 0 "fp_reg_operand" "=f")
(minus:SF (match_operand:SF 1 "fp_reg_operand" "0")
(match_operand:SF 2 "fp_reg_operand" "f")))]
""
"subs %2,%0"
[(set_attr "type" "fp")])
;;- Multiply instructions.
(define_insn "muldf3"
[(set (match_operand:DF 0 "fp_reg_operand" "=f")
(mult:DF (match_operand:DF 1 "fp_reg_operand" "0")
(match_operand:DF 2 "fp_reg_operand" "f")))]
""
"muld %2,%0"
[(set_attr "type" "fp")])
(define_insn "mulsf3"
[(set (match_operand:SF 0 "fp_reg_operand" "=f")
(mult:SF (match_operand:SF 1 "fp_reg_operand" "0")
(match_operand:SF 2 "fp_reg_operand" "f")))]
""
"muls %2,%0"
[(set_attr "type" "fp")])
(define_insn "mulsidi3"
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(mult:DI (sign_extend:DI (match_operand:SI 1 "int_reg_operand" "%0"))
(sign_extend:DI (match_operand:SI 2 "int_reg_operand" "r"))))]
""
"mulwx %2,%0"
[(set_attr "type" "arith")
(set_attr "cc" "clobber")])
(define_insn "umulsidi3"
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(mult:DI (zero_extend:DI (match_operand:SI 1 "int_reg_operand" "%0"))
(zero_extend:DI (match_operand:SI 2 "int_reg_operand" "r"))))]
""
"mulwux %2,%0"
[(set_attr "type" "arith")
(set_attr "cc" "clobber")])
(define_insn "mulsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(mult:SI (match_operand:SI 1 "int_reg_operand" "%0")
(match_operand:SI 2 "int_reg_operand" "r")))]
""
"mulw %2,%0"
[(set_attr "type" "arith")
(set_attr "cc" "clobber")])
;;- Divide and mod instructions.
(define_insn "divdf3"
[(set (match_operand:DF 0 "fp_reg_operand" "=f")
(div:DF (match_operand:DF 1 "fp_reg_operand" "0")
(match_operand:DF 2 "fp_reg_operand" "f")))]
""
"divd %2,%0"
[(set_attr "type" "fp")])
(define_insn "divsf3"
[(set (match_operand:SF 0 "fp_reg_operand" "=f")
(div:SF (match_operand:SF 1 "fp_reg_operand" "0")
(match_operand:SF 2 "fp_reg_operand" "f")))]
""
"divs %2,%0"
[(set_attr "type" "fp")])
(define_insn "divsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(div:SI (match_operand:SI 1 "int_reg_operand" "0")
(match_operand:SI 2 "int_reg_operand" "r")))]
""
"divw %2,%0"
[(set_attr "type" "arith")
(set_attr "cc" "clobber")])
(define_insn "udivsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(udiv:SI (match_operand:SI 1 "int_reg_operand" "0")
(match_operand:SI 2 "int_reg_operand" "r")))]
""
"divwu %2,%0"
[(set_attr "type" "arith")
(set_attr "cc" "clobber")])
(define_insn "modsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(mod:SI (match_operand:SI 1 "int_reg_operand" "0")
(match_operand:SI 2 "int_reg_operand" "r")))]
""
"modw %2,%0"
[(set_attr "type" "arith")
(set_attr "cc" "clobber")])
(define_insn "umodsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(umod:SI (match_operand:SI 1 "int_reg_operand" "0")
(match_operand:SI 2 "int_reg_operand" "r")))]
""
"modwu %2,%0"
[(set_attr "type" "arith")
(set_attr "cc" "clobber")])
;;
;; bit and/or instructions
;;
(define_insn "andsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r")
(and:SI (match_operand:SI 1 "int_reg_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "r,n")))]
""
"@
andw %2,%0
andi %2,%0"
[(set_attr "type" "arith")])
(define_insn "iorsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r")
(ior:SI (match_operand:SI 1 "int_reg_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "r,n")))]
""
"@
orw %2,%0
ori %2,%0"
[(set_attr "type" "arith")])
(define_insn "xorsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r")
(xor:SI (match_operand:SI 1 "int_reg_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "r,n")))]
""
"@
xorw %2,%0
xori %2,%0"
[(set_attr "type" "arith")])
(define_insn "negdf2"
[(set (match_operand:DF 0 "fp_reg_operand" "=f")
(neg:DF (match_operand:DF 1 "fp_reg_operand" "f")))]
""
"negd %1,%0"
[(set_attr "type" "fp")])
(define_insn "negsf2"
[(set (match_operand:SF 0 "fp_reg_operand" "=f")
(neg:SF (match_operand:SF 1 "fp_reg_operand" "f")))]
""
"negs %1,%0"
[(set_attr "type" "fp")])
(define_insn "negsi2"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(neg:SI (match_operand:SI 1 "int_reg_operand" "r")))]
""
"negw %1,%0"
[(set_attr "type" "arith")])
(define_insn "one_cmplsi2"
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(not:SI (match_operand:SI 1 "int_reg_operand" "r")))]
""
"notw %1,%0"
[(set_attr "type" "arith")])
;; Right shift on the clipper works by negating the shift count,
;; then emitting a right shift with the shift count negated. This means
;; that all actual shift counts in the RTL will be positive.
(define_expand "ashrdi3"
[(set (match_operand:DI 0 "int_reg_operand" "")
(ashiftrt:DI (match_operand:DI 1 "int_reg_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(ashiftrt:DI (match_operand:DI 1 "int_reg_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))]
""
"shali $%n2,%0"
[(set_attr "type" "arith")])
(define_insn ""
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(ashiftrt:DI (match_operand:DI 1 "int_reg_operand" "0")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "r"))))]
""
"shal %2,%0"
[(set_attr "type" "arith")])
(define_expand "ashrsi3"
[(set (match_operand:SI 0 "int_reg_operand" "")
(ashiftrt:SI (match_operand:SI 1 "int_reg_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(ashiftrt:SI (match_operand:SI 1 "int_reg_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))]
""
"shai $%n2,%0"
[(set_attr "type" "arith")])
(define_insn ""
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(ashiftrt:SI (match_operand:SI 1 "int_reg_operand" "0")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "r"))))]
""
"shaw %2,%0"
[(set_attr "type" "arith")])
;;
;; left shift
;;
(define_insn "ashldi3"
[(set (match_operand:DI 0 "int_reg_operand" "=r,r")
(ashift:DI (match_operand:DI 1 "int_reg_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "r,n")))]
""
"@
shal %2,%0
shali %2,%0"
[(set_attr "type" "arith")])
(define_insn "ashlsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r")
(ashift:SI (match_operand:SI 1 "int_reg_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "r,n")))]
""
"*
{
int val;
if (which_alternative == 0)
return \"shaw %2,%0\";
val = INTVAL (operands[2]);
if (val == 2)
return \"addw %0,%0\;addw %0,%0\";
if (val == 1)
return \"addw %0,%0\";
return \"shai %2,%0\";
}"
[(set_attr "type" "arith")])
;;
;; logical shift
;;
(define_expand "lshrdi3"
[(set (match_operand:DI 0 "int_reg_operand" "")
(lshiftrt:DI (match_operand:DI 1 "int_reg_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(lshiftrt:DI (match_operand:DI 1 "int_reg_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))]
""
"shlli $%n2,%0"
[(set_attr "type" "arith")])
(define_insn ""
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(lshiftrt:DI (match_operand:DI 1 "int_reg_operand" "0")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "r"))))]
""
"shll %2,%0"
[(set_attr "type" "arith")])
(define_expand "lshrsi3"
[(set (match_operand:SI 0 "int_reg_operand" "")
(lshiftrt:SI (match_operand:SI 1 "int_reg_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(lshiftrt:SI (match_operand:SI 1 "int_reg_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))]
""
"shli $%n2,%0"
[(set_attr "type" "arith")])
(define_insn ""
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(lshiftrt:SI (match_operand:SI 1 "int_reg_operand" "0")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "r"))))]
""
"shlw %2,%0"
[(set_attr "type" "arith")])
;;
;; rotate insn
;;
(define_expand "rotrdi3"
[(set (match_operand:DI 0 "int_reg_operand" "")
(rotatert:DI (match_operand:DI 1 "int_reg_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(rotatert:DI (match_operand:DI 1 "int_reg_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))]
""
"rotli $%n2,%0"
[(set_attr "type" "arith")])
(define_insn ""
[(set (match_operand:DI 0 "int_reg_operand" "=r")
(rotatert:DI (match_operand:DI 1 "int_reg_operand" "0")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "r"))))]
""
"rotl %2,%0"
[(set_attr "type" "arith")])
(define_expand "rotrsi3"
[(set (match_operand:SI 0 "int_reg_operand" "")
(rotatert:SI (match_operand:SI 1 "int_reg_operand" "")
(match_operand:SI 2 "nonmemory_operand" "")))]
""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(rotatert:SI (match_operand:SI 1 "int_reg_operand" "0")
(match_operand:SI 2 "const_int_operand" "n")))]
""
"roti $%n2,%0"
[(set_attr "type" "arith")])
(define_insn ""
[(set (match_operand:SI 0 "int_reg_operand" "=r")
(rotatert:SI (match_operand:SI 1 "int_reg_operand" "0")
(neg:SI (match_operand:SI 2 "nonmemory_operand" "r"))))]
""
"rotw %2,%0"
[(set_attr "type" "arith")])
(define_insn "rotldi3"
[(set (match_operand:DI 0 "int_reg_operand" "=r,r")
(rotate:DI (match_operand:DI 1 "int_reg_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "r,n")))]
""
"@
rotl %2,%0
rotli %2,%0"
[(set_attr "type" "arith")])
(define_insn "rotlsi3"
[(set (match_operand:SI 0 "int_reg_operand" "=r,r")
(rotate:SI (match_operand:SI 1 "int_reg_operand" "0,0")
(match_operand:SI 2 "nonmemory_operand" "r,n")))]
""
"@
rotw %2,%0
roti %2,%0"
[(set_attr "type" "arith")])
;;
;; jump and branch insns
;;
(define_insn "jump"
[(set (pc)
(label_ref (match_operand 0 "" "")))]
""
"b %l0"
[(set_attr "type" "branch")])
(define_insn "tablejump"
[(set (pc) (match_operand:SI 0 "register_operand" "r"))
(use (label_ref (match_operand 1 "" "")))]
""
"b (%0)"
[(set_attr "type" "branch")])
(define_insn "beq"
[(set (pc)
(if_then_else (eq (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"breq %l0"
[(set_attr "type" "branch")])
(define_insn "bne"
[(set (pc)
(if_then_else (ne (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"brne %l0"
[(set_attr "type" "branch")])
(define_insn "bgt"
[(set (pc)
(if_then_else (gt (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"brgt %l0"
[(set_attr "type" "branch")])
(define_insn "bgtu"
[(set (pc)
(if_then_else (gtu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"brgtu %l0"
[(set_attr "type" "branch")])
(define_insn "blt"
[(set (pc)
(if_then_else (lt (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"brlt %l0"
[(set_attr "type" "branch")])
(define_insn "bltu"
[(set (pc)
(if_then_else (ltu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"brltu %l0"
[(set_attr "type" "branch")])
(define_insn "bge"
[(set (pc)
(if_then_else (ge (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"brge %l0"
[(set_attr "type" "branch")])
(define_insn "bgeu"
[(set (pc)
(if_then_else (geu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"brgeu %l0"
[(set_attr "type" "branch")])
(define_insn "ble"
[(set (pc)
(if_then_else (le (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"brle %l0"
[(set_attr "type" "branch")])
(define_insn "bleu"
[(set (pc)
(if_then_else (leu (cc0)
(const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
""
"brleu %l0"
[(set_attr "type" "branch")])
;; Recognize reversed jumps.
(define_insn ""
[(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
[(cc0)
(const_int 0)])
(pc)
(label_ref (match_operand 1 "" ""))))]
""
"br%C0 %l1" ; %C0 negates condition
[(set_attr "type" "branch")])
;;
;; call instructions
;;
(define_insn "call"
[(call (match_operand:QI 0 "general_operand" "m")
(match_operand:SI 1 "general_operand" ""))]
;; Operand 1 not used on the clipper.
""
"call sp,%0")
(define_insn "call_value"
[(set (match_operand 0 "" "=rf")
(call (match_operand:QI 1 "general_operand" "m")
(match_operand:SI 2 "general_operand" "g")))]
;; Operand 2 not used on the clipper
""
"call sp,%1")
(define_insn "indirect_jump"
[(set (pc) (match_operand:SI 0 "register_operand" "r"))]
""
"b (%0)"
[(set_attr "type" "branch")])
(define_insn "nop"
[(const_int 0)]
""
"noop"
[(set_attr "type" "arith")
(set_attr "cc" "unchanged")])
;; while (--foo >= 0)
;;
;; Combiners for 'decrement test and branch' do not work for clipper.
;; These patters are jump_insns that do not allow output reloads and clipper
;; can only decrement and test registers.
;;