58371476ee
From-SVN: r8402
1379 lines
34 KiB
Markdown
1379 lines
34 KiB
Markdown
;;- 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.
|
||
;;
|