;;- Machine description for GNU compiler, Clipper Version
-;; Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
-
+;; Copyright (C) 1987, 1988, 1991, 1993, 1994, 1997, 1998, 1999, 2001
+;; Free Software Foundation, Inc.
;; Contributed by Holger Teutsch (holger@hotbso.rhein-main.de)
;; This file is part of GNU CC.
;; 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.
+;; the Free Software Foundation, 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
;;- Instruction patterns. When multiple patterns apply,
(const_string "clobber")))
;;
-;; clipper seems to be a tradional risc processor
+;; clipper seems to be a traditional risc processor
;; we define a functional unit 'memory'
;;
(define_function_unit "memory" 1 1 (eq_attr "type" "load") 4 0)
""
"*
{
+ int val;
+
if (which_alternative == 0)
return \"cmpw %1,%0\";
if (which_alternative == 1)
- return \"cmpi %1,%0\";
+ {
+ 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\";
}")
;; to recombine a mem -> mem move
;;
(define_insn ""
- [(set (match_operand:DF 0 "register_operand" "=rf")
- (match_operand:DF 1 "nonimmediate_operand" "rfo"))]
+ [(set (match_operand:DF 0 "register_operand" "=*rf")
+ (match_operand:DF 1 "nonimmediate_operand" "*rfo"))]
""
"*
{
{
rtx xops[4];
xops[0] = operands[0];
- xops[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ xops[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
xops[2] = operands[1];
- xops[3] = adj_offsettable_operand (operands[1], 4);
+ xops[3] = adjust_address (operands[1], SImode, 4);
output_asm_insn (\"loadw %2,%0\;loadw %3,%1\", xops);
return \"\";
}
{
rtx xops[4];
xops[0] = operands[0];
- xops[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ xops[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
xops[2] = operands[1];
- xops[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ xops[3] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
output_asm_insn (\"movw %2,%0\;movw %3,%1\", xops);
return \"\";
}
(define_insn ""
[(set (match_operand:DF 0 "memory_operand" "=o,m")
- (match_operand:DF 1 "register_operand" "r,f"))]
+ (match_operand:DF 1 "register_operand" "*rf,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 \"\";
- }
+ rtx xops[4];
- return \"stord %1,%0\"; /* f-> m */
+ if (REGNO (operands[1]) >= 16) /* f -> m */
+ return \"stord %1,%0\";
+
+ xops[0] = operands[0]; /* r -> o */
+ xops[1] = adjust_address (operands[0], SImode, 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")])
;; to recombine a mem -> mem move
;;
(define_insn ""
- [(set (match_operand:SF 0 "register_operand" "=rf")
- (match_operand:SF 1 "nonimmediate_operand" "rfm"))]
+ [(set (match_operand:SF 0 "register_operand" "=*rf")
+ (match_operand:SF 1 "nonimmediate_operand" "*rfm"))]
""
"*
{
(define_insn ""
[(set (match_operand:SF 0 "memory_operand" "=m")
- (match_operand:SF 1 "register_operand" "rf"))]
+ (match_operand:SF 1 "register_operand" "*rf"))]
""
"*
{
operands[1] = force_reg (DImode, operands[1]);
}")
+;; If an operand is a MEM but not offsettable, 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")
+ [(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);
+ 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);
+ xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
output_asm_insn (\"movw %1,%0\", xoperands);
return \"\";
}
abort ();
yoperands[0] = operands[0];
- yoperands[1] = gen_rtx (CONST_INT, VOIDmode,
- CONST_DOUBLE_LOW (operands[1]));
+ yoperands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
output_asm_insn (\"loadi %1,%0\", yoperands);
- xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
- CONST_DOUBLE_HIGH (operands[1]));
+ xoperands[1] = GEN_INT (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);
+ xoperands[1] = adjust_address (operands[1], SImode, 4);
output_asm_insn (\"loadw %1,%0\", xoperands);
return \"\";
}"
{
rtx xops[4];
xops[0] = operands[0];
- xops[1] = adj_offsettable_operand (operands[0], 4);
+ xops[1] = adjust_address (operands[0], SImode, 4);
xops[2] = operands[1];
- xops[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
+ xops[3] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
output_asm_insn (\"storw %2,%0\;storw %3,%1\", xops);
return \"\";
}"
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
+;; Reject both args with `general_operand' if not reloading because a
+;; mem -> mem move that was split by 'movsi' can be recombined to
+;; mem -> mem by the combiner.
;;
-
+;; As a pseudo register can end up in a stack slot during reloading we must
+;; allow a r->m move for the next pattern.
+;; The first predicate must be `general_operand' because a predicate must
+;; be true for each constraint.
+;;
(define_insn ""
- [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
- (match_operand:SI 1 "general_operand" "r,m,n,i"))]
- ""
+ [(set (match_operand:SI 0 "general_operand" "=r,r,r,r,m")
+ (match_operand:SI 1 "general_operand" "r,m,n,i,r"))]
+ "reload_in_progress || register_operand (operands[0], SImode)"
"*
{
int val;
if (which_alternative == 3) /* unknown const */
return \"loada %a1,%0\";
+
+ return \"storw %1,%0\";
}"
-[(set_attr "type" "arith,load,arith,load")
- (set_attr "cc" "set2,change0,set1,change0")])
+[(set_attr "type" "arith,load,arith,load,store")
+ (set_attr "cc" "set2,change0,set1,change0,unchanged")])
(define_insn ""
operands[6] = addr0;
operands[7] = addr1;
- operands[0] = gen_rtx (MEM, BLKmode, addr0);
- operands[1] = gen_rtx (MEM, BLKmode, addr1);
+ operands[0] = replace_equiv_address (operands[0], addr0);
+ operands[1] = replace_equiv_address (operands[1], addr1);
if (GET_CODE (operands[2]) != CONST_INT)
operands[2] = force_reg (SImode, operands[2]);
rtx xoperands[4];
xoperands[0] = operands[0];
- xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ xoperands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
xoperands[2] = operands[2];
- xoperands[3] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
+ xoperands[3] = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
output_asm_insn (\"addw %2,%0\;addwc %3,%1\", xoperands);
return \"\";
}"
(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,r")))]
+ (match_operand:SI 2 "nonmemory_operand" "rn,0,rn")))]
""
"*
{
if (which_alternative == 2) /* 3 address version */
- return \"loada [%2](%1),%0\";
+ {
+ 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)
{
val = -val;
xops[0] = operands[0];
- xops[1] = gen_rtx (CONST_INT, VOIDmode, val);
+ xops[1] = GEN_INT (val);
if (val >= 16)
output_asm_insn (\"subi %1,%0\", xops);
(define_insn "subdi3"
[(set (match_operand:DI 0 "int_reg_operand" "=r")
- (minus:DI (match_operand:DI 1 "int_reg_operand" "%0")
+ (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[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
xoperands[2] = operands[2];
- xoperands[3] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1);
+ xoperands[3] = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
output_asm_insn (\"subw %2,%0\;subwc %3,%1\", xoperands);
return \"\";
}"
"
{
if (GET_CODE (operands[2]) != CONST_INT)
- operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
+ operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
- operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
+ operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
- operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
+ operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
- operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
+ operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
"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
"
{
if (GET_CODE (operands[2]) != CONST_INT)
- operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
+ operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
"
{
if (GET_CODE (operands[2]) != CONST_INT)
- operands[2] = gen_rtx (NEG, SImode, negate_rtx (SImode, operands[2]));
+ operands[2] = gen_rtx_NEG (SImode, negate_rtx (SImode, operands[2]));
}")
(define_insn ""
""
"call sp,%1")
+;; Call subroutine returning any type.
+
+(define_expand "untyped_call"
+ [(parallel [(call (match_operand 0 "" "")
+ (const_int 0))
+ (match_operand 1 "" "")
+ (match_operand 2 "" "")])]
+ ""
+ "
+{
+ int i;
+
+ emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+
+ for (i = 0; i < XVECLEN (operands[2], 0); i++)
+ {
+ rtx set = XVECEXP (operands[2], 0, i);
+ emit_move_insn (SET_DEST (set), SET_SRC (set));
+ }
+
+ /* The optimizer does not know that the call sets the function value
+ registers we stored in the result block. We avoid problems by
+ claiming that all hard registers are used and clobbered at this
+ point. */
+ emit_insn (gen_blockage ());
+
+ DONE;
+}")
+
+;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
+;; all of memory. This blocks insns from being moved across this point.
+
+(define_insn "blockage"
+ [(unspec_volatile [(const_int 0)] 0)]
+ ""
+ "")
+
(define_insn "indirect_jump"
[(set (pc) (match_operand:SI 0 "register_operand" "r"))]
""
;; These patters are jump_insns that do not allow output reloads and clipper
;; can only decrement and test registers.
;;
-
-\f
-;;- 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: