aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/clipper/clipper.md
diff options
context:
space:
mode:
authorRichard Stallman <rms@gnu.org>1993-02-09 23:47:17 +0000
committerRichard Stallman <rms@gnu.org>1993-02-09 23:47:17 +0000
commitedc03e8aa2ad34584ba40cafa82774dc69dc25f7 (patch)
tree8bdd8ce3ca83d75aae22de224e3c06f07c7e6ac3 /gcc/config/clipper/clipper.md
parent7988fd364ac120730ec4fdaf48e2bbc5c1df1443 (diff)
downloadgcc-edc03e8aa2ad34584ba40cafa82774dc69dc25f7.zip
gcc-edc03e8aa2ad34584ba40cafa82774dc69dc25f7.tar.gz
gcc-edc03e8aa2ad34584ba40cafa82774dc69dc25f7.tar.bz2
Initial revision
From-SVN: r3452
Diffstat (limited to 'gcc/config/clipper/clipper.md')
-rw-r--r--gcc/config/clipper/clipper.md1284
1 files changed, 1284 insertions, 0 deletions
diff --git a/gcc/config/clipper/clipper.md b/gcc/config/clipper/clipper.md
new file mode 100644
index 0000000..72758fa
--- /dev/null
+++ b/gcc/config/clipper/clipper.md
@@ -0,0 +1,1284 @@
+;;- 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")))]
+ ""
+ "*
+{
+ if (which_alternative == 0)
+ return \"cmpw %1,%0\";
+
+ if (which_alternative == 1)
+ return \"cmpi %1,%0\";
+
+ cc_status.flags |= CC_REVERSED; /* immediate must be first */
+ 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" "r,f"))]
+ ""
+ "*
+{
+ if (which_alternative == 0) /* r -> o */
+ {
+ 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 \"\";
+ }
+
+ return \"stord %1,%0\"; /* f-> m */
+}")
+
+
+(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 */
+}")
+
+
+(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 < 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")
+
+
+(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")
+
+(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")
+
+(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")
+
+
+;;- 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")
+
+(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")
+
+(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")
+
+(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")
+
+(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")
+
+(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")
+
+(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 "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")])
+
+(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")])
+
+
+(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 "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
+(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 "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")])
+
+
+(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")])
+
+
+;;
+;; define insns for loops
+;; subtract, test and branch are tied together and the test can be omitted
+;;
+
+;; while (--foo > 0)
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (gt (plus:SI (match_operand:SI 0 "int_reg_operand" "+r")
+ (const_int -1))
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))]
+ ""
+ "subq $1,%0\;brgt %l1")
+
+;; while (--foo >= 0)
+;;
+;; this does not work and I don't know why
+;; gcc 2.3.3 says that is doesn't match its contraint ?!?
+;; the problem seem to be the "+r" constraint. "r" works, but is this okay??
+;;
+;;(define_insn ""
+;; [(set (pc)
+;; (if_then_else
+;; (ge (plus:SI (match_operand:SI 0 "int_reg_operand" "+r")
+;; (const_int -1))
+;; (const_int 0))
+;; (label_ref (match_operand 1 "" ""))
+;; (pc)))
+;; (set (match_dup 0)
+;; (plus:SI (match_dup 0)
+;; (const_int -1)))]
+;; ""
+;; "subq $1,%0\;brge %l1")
+
+
+;; `while (foo--)' -> `while (--foo != -1)'.
+
+(define_insn ""
+ [(set (pc)
+ (if_then_else
+ (ne (match_operand:SI 0 "int_reg_operand" "+r")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))
+ (set (match_dup 0)
+ (plus:SI (match_dup 0)
+ (const_int -1)))]
+ ""
+ "subq $1,%0\;brgeu %l1")
+
+
+;;- Local variables:
+;;- mode:c
+;;- comment-start: ";;- "
+;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
+;;- eval: (modify-syntax-entry ?[ "(]")
+;;- eval: (modify-syntax-entry ?] ")[")
+;;- eval: (modify-syntax-entry ?{ "(}")
+;;- eval: (modify-syntax-entry ?} "){")
+;;- End: