/* Subroutines for assembler code output on the TMS320C[34]x
- Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1994-98, 1999 Free Software Foundation, Inc.
Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz)
and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl).
Boston, MA 02111-1307, USA. */
/* Some output-actions in c4x.md need these. */
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
#include "config.h"
+#include "system.h"
#include "toplev.h"
#include "rtl.h"
#include "regs.h"
VOIDmode, /* IIF/IOF No */
QImode, /* RS QI No */
QImode, /* RE QI No */
- QImode, /* RC QI No */
+ VOIDmode, /* RC QI No */
QFmode, /* R8 QI, QF, HF QI */
HFmode, /* R9 QI, QF, HF No */
HFmode, /* R10 QI, QF, HF No */
/* Convert foo / 8.0 into foo * 0.125, etc. */
flag_fast_math = 1;
- /* We should phase out the following at some stage.
- This provides compatibility with the old -mno-rptb option. */
- if (! TARGET_RPTB && flag_branch_on_count_reg)
- flag_branch_on_count_reg = 0;
-
/* We should phase out the following at some stage.
This provides compatibility with the old -mno-aliases option. */
if (! TARGET_ALIASES && ! flag_argument_noalias)
int level;
int size ATTRIBUTE_UNUSED;
{
+ /* Scheduling before register allocation can screw up global
+ register allocation, especially for functions that use MPY||ADD
+ instructions. The benefit we gain we get by scheduling before
+ register allocation is probably marginal anyhow. */
+ flag_schedule_insns = 0;
+
/* When optimizing, enable use of RPTB instruction. */
if (level >= 1)
flag_branch_on_count_reg = 1;
/* Validate combination of operands for parallel load/store instructions. */
+int
valid_parallel_load_store (operands, mode)
rtx *operands;
enum machine_mode mode ATTRIBUTE_UNUSED;
rtx *operands;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
- int regs = 0;
rtx op0 = operands[0];
rtx op2 = operands[2];
/* Definitions of target machine for GNU compiler. TMS320C[34]x
- Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1994-98, 1999 Free Software Foundation, Inc.
Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz)
and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl).
#define EXPENSIVE_CLASS_P(CLASS) (ADDR_CLASS_P(CLASS) \
|| INDEX_CLASS_P(CLASS) || (CLASS) == SP_REG)
-/* Make the Rx register a little easier to use so they are used for
- calculations and the ARx registers are used for addressing. */
+/* Compute extra cost of moving data between one register class
+ and another. */
-#define REGISTER_MOVE_COST(FROM, TO) \
-(EXPENSIVE_CLASS_P(TO) ? 5 : EXPENSIVE_CLASS_P(FROM) ? 4 : 3)
+#define REGISTER_MOVE_COST(FROM, TO) 2
/* Memory move cost is same as fast register move. Maybe this should
be bumped up? */
;; Machine description for the TMS320C[34]x for GNU C compiler
-;; Copyright (C) 1994, 95-98, 1999 Free Software Foundation, Inc.
+;; Copyright (C) 1994-98, 1999 Free Software Foundation, Inc.
-;; Contributed by Michael Hayes (m.hayes@elec.canterbury.cri.nz)
+;; Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz)
;; and Herman Ten Brugge (Haj.Ten.Brugge@net.HCC.nl)
;; This file is part of GNU CC.
(define_attr "in_annul_slot_3" "false,true"
(if_then_else (and (eq_attr "cpu" "c4x")
- (eq_attr "type" "!jump,call,rets,jmpc,db,dbc,repeat,repeat_top,laj,push,pop,multi"))
+ (eq_attr "type" "!jump,call,rets,jmpc,unarycc,binarycc,db,dbc,repeat,repeat_top,laj,push,pop,multi"))
(const_string "true")
(const_string "false")))
(match_operand:QI 2 "const_int_operand" "")))
(clobber (reg:CC 21))])]
""
- "if (INTVAL (operands[2]) >= 4)
+ "if (INTVAL (operands[2]) > 4)
FAIL; /* Open code as two shifts and an or */
if (INTVAL (operands[2]) > 1)
{
int i;
+ rtx tmp;
/* If we have 4 or fewer shifts, then it is probably faster
to emit separate ROL instructions. A C3x requires
at least 4 instructions (a C4x requires at least 3), to
perform a rotation by shifts. */
- for (i = 0; i < INTVAL (operands[2]); i++)
- emit_insn (gen_rotl_1_clobber (operands[0], operands[1]));
+ tmp = operands[1];
+ for (i = 0; i < INTVAL (operands[2]) - 1; i++)
+ {
+ tmp = gen_reg_rtx (QImode);
+ emit_insn (gen_rotl_1_clobber (tmp, operands[1]));
+ operands[1] = tmp;
+ }
+ emit_insn (gen_rotl_1_clobber (operands[0], tmp));
DONE;
}")
(match_operand:QI 2 "const_int_operand" "")))
(clobber (reg:CC 21))])]
""
- "if (INTVAL (operands[2]) >= 4)
+ "if (INTVAL (operands[2]) > 4)
FAIL; /* Open code as two shifts and an or */
if (INTVAL (operands[2]) > 1)
{
int i;
+ rtx tmp;
/* If we have 4 or fewer shifts, then it is probably faster
to emit separate ROL instructions. A C3x requires
at least 4 instructions (a C4x requires at least 3), to
perform a rotation by shifts. */
- for (i = 0; i < INTVAL (operands[2]); i++)
- emit_insn (gen_rotr_1_clobber (operands[0], operands[1]));
+ tmp = operands[1];
+ for (i = 0; i < INTVAL (operands[2]) - 1; i++)
+ {
+ tmp = gen_reg_rtx (QImode);
+ emit_insn (gen_rotr_1_clobber (tmp, operands[1]));
+ operands[1] = tmp;
+ }
+ emit_insn (gen_rotr_1_clobber (operands[0], tmp));
DONE;
}")
; have an option to disable this instruction.
(define_insn "*db"
[(set (pc)
- (if_then_else (ne (match_operand:QI 2 "addr_reg_operand" "0,0,0,0")
+ (if_then_else (ne (match_operand:QI 0 "addr_reg_operand" "+a,?*d,??*r,!m")
(const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))
- (set (match_operand:QI 0 "addr_reg_operand" "+a,?*d,??*r,!m")
+ (set (match_dup 0)
(plus:QI (match_dup 0)
(const_int -1)))
(clobber (reg:CC_NOOV 21))]
"
[(set_attr "type" "db,jmpc,jmpc,jmpc")])
+
+; This insn is used for some loop tests, typically loops reversed when
+; strength reduction is used. It is actually created when the instruction
+; combination phase combines the special loop test. Since this insn
+; is both a jump insn and has an output, it must deal with its own
+; reloads, hence the `m' constraints.
+
+; The C4x does the decrement and then compares the result against zero.
+; It branches if the result was greater than or equal to zero.
+; In the RTL the comparison and decrement are assumed to happen
+; at the same time so we bias the iteration counter with by -1
+; when we make the test.
(define_insn "decrement_and_branch_until_zero"
[(set (pc)
- (if_then_else (ge (plus:QI (match_operand:QI 2 "addr_reg_operand" "0,0,0,0")
+ (if_then_else (ge (plus:QI (match_operand:QI 0 "addr_reg_operand" "+a,?*d,??*r,!m")
(const_int -1))
(const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))
- (set (match_operand:QI 0 "addr_reg_operand" "+a,?*d,??*r,!m")
+ (set (match_dup 0)
(plus:QI (match_dup 0)
(const_int -1)))
(clobber (reg:CC_NOOV 21))]