first alternative. From-SVN: r5070
34 KiB
;;- Machine description for GNU compiler, Clipper Version ;; Copyright (C) 1987, 1988, 1991 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]); }")
(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,%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")])
(define_insn "lshldi3" [(set (match_operand:DI 0 "int_reg_operand" "=r,r") (lshift:DI (match_operand:DI 1 "int_reg_operand" "0,0") (match_operand:SI 2 "nonmemory_operand" "r,n")))] "" "@ shll %2,%0 shlli %2,%0" [(set_attr "type" "arith")])
(define_insn "lshlsi3" [(set (match_operand:SI 0 "int_reg_operand" "=r,r") (lshift:SI (match_operand:SI 1 "int_reg_operand" "0,0") (match_operand:SI 2 "nonmemory_operand" "r,n")))] "" "@ shlw %2,%0 shli %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. ;;