aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Hayes <m.hayes@elec.canterbury.ac.nz>1999-01-24 01:52:01 +0000
committerMichael Hayes <m.hayes@gcc.gnu.org>1999-01-24 01:52:01 +0000
commit50c3308739f502960f3c39ce00fcaac47cd6d391 (patch)
tree0896b913e682e1e0cafd0aa2d8e78c8292368845
parent4c1d5c872b9b4fd53ea69e955df5e56b72049d13 (diff)
downloadgcc-50c3308739f502960f3c39ce00fcaac47cd6d391.zip
gcc-50c3308739f502960f3c39ce00fcaac47cd6d391.tar.gz
gcc-50c3308739f502960f3c39ce00fcaac47cd6d391.tar.bz2
Convert all direct memory references to use LO_SUM and remove machdep hack that used to do this.
Convert all direct memory references to use LO_SUM and remove machdep hack that used to do this. Sun Jan 24 21:24:43 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz> * config/c4x/c4x.c (c4x_emit_move_sequence, c4x_encode_section_info): New functions. (c4x_check_legit_addr): Remove USE and PLUS, allow LO_SUM, and disable SYMBOL_REF, LABEL_REF, and CONST cases. (c4x_legitimize_address): Penalise SYMBOL_REF, LABEL_REF, and CONST cases. Add LO_SUM. (c4x_print_operand): Modified 'C' and 'R' cases for calls. Added 'U' case. Remove dependence on SYMBOL_REF_FLAG. (c4x_print_operand_address): Handle LO_SUM. (c4x_scan_for_ldp): Delete. Hooray! (c4x_process_after_reload): Remove call to c4x_scan_for_ldp. Split all insns. (c4x_immed_int_constant): Renamed from c4x_int_constant. All callers changed. (c4x_immed_float_constant): Renamed from c4x_float_constant. All callers changed. (c4x_T_constraint): Allow LO_SUM, disable SYMBOL_REF, LABEL_REF, and CONST. (c4x_U_constraint, symbolic_operand): New functions. (src_operand): Allow 'I' constants in HImode. Allow LO_SUM, disable SYMBOL_REF, LABEL_REF, and CONST. (lsrc_operand, tsrc_operand): Call src_operand instead of general_operand. (c4x_operand_subword): Update comments. * config/c4x/c4x.c (TARGET_LOAD_ADDRESS): New macro. (LEGITIMATE_CONSTANT_P): Allow SYMBOL_REF, LABEL_REF, CONST, plus HIGH and LO_SUM for the C40. (ENCODE_SECTION_INFO): Define macro. (symbolic_operand, c4x_U_constraint, c4x_emit_move_sequence): New prototypes. (PREDICATE_CODES): Add symbolic_operand. * config/c4x/c4x.md (movqi, movgqf, movhi, movhi): Call c4x_emit_move_sequence. (floatunsqiqf2, fixuns_truncqfqi2): Rework emitted RTL to avoid symbol references. (all patterns with g constraint): Replace 'g' constraint with 'rIm'. (set_high): Renamed from set_high_use. (set_lo_sum): Renamed from set_ior_lo_use. (all call patterns): Make MEM explicit in call address operands. Modified output templates to use 'U' modifier. From-SVN: r24842
-rw-r--r--gcc/ChangeLog45
-rw-r--r--gcc/config/c4x/c4x.c664
-rw-r--r--gcc/config/c4x/c4x.h71
-rw-r--r--gcc/config/c4x/c4x.md545
4 files changed, 710 insertions, 615 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 694d804..776dcdb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,48 @@
+Sun Jan 24 21:24:43 1999 Michael Hayes <m.hayes@elec.canterbury.ac.nz>
+
+ * config/c4x/c4x.c (c4x_emit_move_sequence, c4x_encode_section_info):
+ New functions.
+ (c4x_check_legit_addr): Remove USE and PLUS, allow
+ LO_SUM, and disable SYMBOL_REF, LABEL_REF, and CONST cases.
+ (c4x_legitimize_address): Penalise SYMBOL_REF, LABEL_REF, and
+ CONST cases. Add LO_SUM.
+ (c4x_print_operand): Modified 'C' and 'R' cases for calls.
+ Added 'U' case. Remove dependence on SYMBOL_REF_FLAG.
+ (c4x_print_operand_address): Handle LO_SUM.
+ (c4x_scan_for_ldp): Delete. Hooray!
+ (c4x_process_after_reload): Remove call to c4x_scan_for_ldp.
+ Split all insns.
+ (c4x_immed_int_constant): Renamed from c4x_int_constant. All callers
+ changed.
+ (c4x_immed_float_constant): Renamed from c4x_float_constant. All
+ callers changed.
+ (c4x_T_constraint): Allow LO_SUM, disable SYMBOL_REF, LABEL_REF,
+ and CONST.
+ (c4x_U_constraint, symbolic_operand): New functions.
+ (src_operand): Allow 'I' constants in HImode. Allow LO_SUM,
+ disable SYMBOL_REF, LABEL_REF, and CONST.
+ (lsrc_operand, tsrc_operand): Call src_operand instead of
+ general_operand.
+ (c4x_operand_subword): Update comments.
+
+ * config/c4x/c4x.c (TARGET_LOAD_ADDRESS): New macro.
+ (LEGITIMATE_CONSTANT_P): Allow SYMBOL_REF, LABEL_REF, CONST,
+ plus HIGH and LO_SUM for the C40.
+ (ENCODE_SECTION_INFO): Define macro.
+ (symbolic_operand, c4x_U_constraint, c4x_emit_move_sequence): New
+ prototypes.
+ (PREDICATE_CODES): Add symbolic_operand.
+
+ * config/c4x/c4x.md (movqi, movgqf, movhi, movhi): Call
+ c4x_emit_move_sequence.
+ (floatunsqiqf2, fixuns_truncqfqi2): Rework emitted RTL
+ to avoid symbol references.
+ (all patterns with g constraint): Replace 'g' constraint with 'rIm'.
+ (set_high): Renamed from set_high_use.
+ (set_lo_sum): Renamed from set_ior_lo_use.
+ (all call patterns): Make MEM explicit in call address operands.
+ Modified output templates to use 'U' modifier.
+
Sun Jan 24 01:15:05 PST 1999 Jeff Law (law@cygnus.com)
* version.c: Bump for snapshot.
diff --git a/gcc/config/c4x/c4x.c b/gcc/config/c4x/c4x.c
index f5c6fc2..2e4b941 100644
--- a/gcc/config/c4x/c4x.c
+++ b/gcc/config/c4x/c4x.c
@@ -1016,6 +1016,84 @@ c4x_null_epilogue_p ()
}
+int
+c4x_emit_move_sequence (operands, mode)
+ rtx *operands;
+ enum machine_mode mode;
+{
+ rtx op0 = operands[0];
+ rtx op1 = operands[1];
+
+ if (! reload_in_progress
+ && ! REG_P (op0)
+ && ! REG_P (op1)
+ && ! (stik_const_operand (op1, mode) && ! push_operand (op0, mode)))
+ op1 = force_reg (mode, op1);
+
+ if (symbolic_operand (op1, mode))
+ {
+ if (TARGET_LOAD_ADDRESS)
+ {
+ /* Alias analysis seems to do a better job if we force
+ constant addresses to memory after reload. */
+ emit_insn (gen_load_immed_address (op0, op1));
+ return 1;
+ }
+ else
+ {
+ /* Stick symbol or label address into the constant pool. */
+ op1 = force_const_mem (Pmode, op1);
+ }
+ }
+ else if (mode == HFmode && CONSTANT_P (op1) && ! LEGITIMATE_CONSTANT_P (op1))
+ {
+ /* We could be a lot smarter about loading some of these
+ constants... */
+ op1 = force_const_mem (mode, op1);
+ }
+ else if (mode == HImode && CONSTANT_P (op1) && ! LEGITIMATE_CONSTANT_P (op1))
+ {
+ /* We could load all sorts of constants in two goes by pulling all
+ sorts of tricks... The tricky thing is that we cannot clobber CC
+ so that stifles most of the obvious methods. */
+ op1 = force_const_mem (mode, op1);
+ }
+
+ /* Convert (MEM (SYMREF)) to a (MEM (LO_SUM (REG) (SYMREF)))
+ and emit associated (HIGH (SYMREF)) if large memory model.
+ c4x_legitimize_address could be used to do this,
+ perhaps by calling validize_address. */
+ if (! (reload_in_progress || reload_completed)
+ && GET_CODE (op1) == MEM
+ && symbolic_operand (XEXP (op1, 0), Pmode))
+ {
+ rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);
+ if (! TARGET_SMALL)
+ emit_insn (gen_set_ldp (dp_reg, XEXP (op1, 0)));
+ op1 = change_address (op1, mode,
+ gen_rtx_LO_SUM (Pmode, dp_reg, XEXP (op1, 0)));
+ }
+
+ if (! (reload_in_progress || reload_completed)
+ && GET_CODE (op0) == MEM
+ && symbolic_operand (XEXP (op0, 0), Pmode))
+ {
+ rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);
+ if (! TARGET_SMALL)
+ emit_insn (gen_set_ldp (dp_reg, XEXP (op0, 0)));
+ op0 = change_address (op0, mode,
+ gen_rtx_LO_SUM (Pmode, dp_reg, XEXP (op0, 0)));
+ }
+
+ /* Adjust operands in case we have modified them. */
+ operands[0] = op0;
+ operands[1] = op1;
+
+ /* Emit normal pattern. */
+ return 0;
+}
+
+
void
c4x_emit_libcall (name, code, dmode, smode, noperands, operands)
char *name;
@@ -1066,6 +1144,7 @@ c4x_emit_libcall3 (name, code, mode, operands)
return c4x_emit_libcall (name, code, mode, mode, 3, operands);
}
+
void
c4x_emit_libcall_mulhi (name, code, mode, operands)
char *name;
@@ -1096,7 +1175,7 @@ c4x_emit_libcall_mulhi (name, code, mode, operands)
enum reg_class
c4x_preferred_reload_class (x, class)
- rtx x;
+ rtx x ATTRIBUTE_UNUSED;
enum reg_class class;
{
return class;
@@ -1122,6 +1201,22 @@ c4x_secondary_memory_needed (class1, class2, mode)
}
+/* Set the SYMBOL_REF_FLAG for a function decl. However, wo do not
+ yet use this info. */
+void
+c4x_encode_section_info (decl)
+ tree decl;
+{
+#if 0
+ if (TREE_CODE (TREE_TYPE (decl)) == FUNCTION_TYPE)
+ SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
+#else
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl), 0)) = 1;
+#endif
+}
+
+
int
c4x_check_legit_addr (mode, addr, strict)
enum machine_mode mode;
@@ -1187,19 +1282,6 @@ c4x_check_legit_addr (mode, addr, strict)
switch (code0)
{
- case USE:
- /* The uses are put in to avoid problems
- with referenced things disappearing. */
- return c4x_check_legit_addr (mode, op1, strict);
-
- case PLUS:
- /* This is another reference to keep things
- from disappearing, but it contains a plus
- of a use and DP. */
- if (GET_CODE (XEXP (op0, 0)) == USE)
- return c4x_check_legit_addr (mode, op1, strict);
- return 0;
-
case REG:
if (REG_P (op1))
{
@@ -1224,18 +1306,47 @@ c4x_check_legit_addr (mode, addr, strict)
}
break;
+ /* Direct addressing with DP register. */
+ case LO_SUM:
+ {
+ rtx op0 = XEXP (addr, 0);
+ rtx op1 = XEXP (addr, 1);
+
+ /* HImode and HFmode direct memory references aren't truly
+ offsettable (consider case at end of data page). We
+ probably get better code by loading a pointer and using an
+ indirect memory reference. */
+ if (mode == HImode || mode == HFmode)
+ return 0;
+
+ if (!REG_P (op0) || REGNO (op0) != DP_REGNO)
+ return 0;
+
+ if ((GET_CODE (op1) == SYMBOL_REF || GET_CODE (op1) == LABEL_REF))
+ return 1;
+
+ if (GET_CODE (op1) == CONST)
+ {
+ addr = XEXP (op1, 0);
+
+ if (GET_CODE (addr) == PLUS
+ && (GET_CODE (XEXP (addr, 0)) == SYMBOL_REF
+ || GET_CODE (XEXP (addr, 0)) == LABEL_REF)
+ && GET_CODE (XEXP (addr, 1)) == CONST_INT)
+ return 1;
+ }
+ return 0;
+ }
+ break;
+
/* Direct addressing with some work for the assembler... */
case CONST:
- if (GET_CODE (XEXP (addr, 0)) == PLUS
- && (GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF
- || GET_CODE (XEXP (XEXP (addr, 0), 0)) == LABEL_REF)
- && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
- return 1;
-
/* Direct addressing. */
- case SYMBOL_REF:
case LABEL_REF:
- return 1;
+ case SYMBOL_REF:
+ /* These need to be converted to a LO_SUM (...).
+ c4x_legitimize_address will fix them up. */
+ return 0;
/* Do not allow direct memory access to absolute addresses.
This is more pain than its worth, especially for the
@@ -1313,6 +1424,16 @@ c4x_legitimize_address (orig, mode)
rtx orig ATTRIBUTE_UNUSED;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
+ if (GET_CODE (orig) == SYMBOL_REF)
+ {
+ rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);
+
+ if (! TARGET_SMALL)
+ emit_insn (gen_set_ldp (dp_reg, orig));
+
+ return gen_rtx_LO_SUM (Pmode, dp_reg, orig);
+ }
+
return NULL_RTX;
}
@@ -1332,32 +1453,46 @@ rtx addr;
case REG:
return 1;
- case CONST:
- {
- rtx offset = const0_rtx;
- addr = eliminate_constant_term (addr, &offset);
-
- if (GET_CODE (addr) == LABEL_REF)
- return 3;
-
- if (GET_CODE (addr) != SYMBOL_REF)
- return 4;
-
- if (INTVAL (offset) == 0)
- return 3;
- }
-
- /* fall through */
-
case POST_INC:
case POST_DEC:
case PRE_INC:
case PRE_DEC:
return 1;
+ /* These shouldn't be directly generated. */
case SYMBOL_REF:
case LABEL_REF:
- return TARGET_SMALL ? 3 : 4;
+ case CONST:
+ return 10;
+
+ case LO_SUM:
+ {
+ rtx op1 = XEXP (addr, 1);
+
+ if (GET_CODE (op1) == LABEL_REF || GET_CODE (op1) == SYMBOL_REF)
+ return TARGET_SMALL ? 3 : 4;
+
+ if (GET_CODE (op1) == CONST)
+ {
+ rtx offset = const0_rtx;
+
+ op1 = eliminate_constant_term (op1, &offset);
+
+ /* ??? These costs need rethinking... */
+ if (GET_CODE (op1) == LABEL_REF)
+ return 3;
+
+ if (GET_CODE (op1) != SYMBOL_REF)
+ return 4;
+
+ if (INTVAL (offset) == 0)
+ return 3;
+
+ return 4;
+ }
+ fatal_insn ("c4x_address_cost: Invalid addressing mode", addr);
+ }
+ break;
case PLUS:
{
@@ -1479,18 +1614,9 @@ c4x_print_operand (file, op, letter)
asm_fprintf (file, "@");
break;
- case 'C': /* call */
- if (code != MEM)
- fatal_insn ("c4x_print_operand: %%C inconsistency", op);
- op1 = XEXP (op, 0);
- SYMBOL_REF_FLAG (op1) = 1;
- output_addr_const (file, op1);
- return;
-
case 'H': /* sethi */
- if (code == SYMBOL_REF)
- SYMBOL_REF_FLAG (op) = 1;
- break;
+ output_addr_const (file, op);
+ return;
case 'I': /* reversed condition */
code = reverse_condition (code);
@@ -1511,9 +1637,9 @@ c4x_print_operand (file, op, letter)
case 'K': /* generate ldp(k) if direct address */
if (! TARGET_SMALL
&& code == MEM
- && GET_CODE (XEXP (op, 0)) == PLUS
- && GET_CODE(XEXP (XEXP (op, 0), 0)) == REG
- && REGNO(XEXP (XEXP (op, 0), 0)) == DP_REGNO)
+ && GET_CODE (XEXP (op, 0)) == LO_SUM
+ && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
+ && REGNO (XEXP (XEXP (op, 0), 0)) == DP_REGNO)
{
op1 = XEXP (XEXP (op, 0), 1);
if (GET_CODE(op1) == CONST_INT || GET_CODE(op1) == SYMBOL_REF)
@@ -1548,12 +1674,18 @@ c4x_print_operand (file, op, letter)
fatal_insn ("c4x_print_operand: %%O inconsistency", op);
return;
- case 'R': /* call register */
- op1 = XEXP (op, 0);
- if (code != MEM || GET_CODE (op1) != REG)
- fatal_insn ("c4x_print_operand: %%R inconsistency", op);
- else
- fprintf (file, "%s", reg_names[REGNO (op1)]);
+ case 'C': /* call */
+ if (code != MEM)
+ fatal_insn ("c4x_print_operand: %%C inconsistency", op);
+ op = XEXP (op, 0);
+ code = GET_CODE (op);
+ break;
+
+ case 'U': /* call/callu */
+ if (code != MEM)
+ fatal_insn ("c4x_print_operand: %%U inconsistency", op);
+ if (GET_CODE (XEXP (op, 0)) != SYMBOL_REF)
+ asm_fprintf (file, "u");
return;
default:
@@ -1721,20 +1853,10 @@ c4x_print_operand_address (file, addr)
{
rtx op0 = XEXP (addr, 0);
rtx op1 = XEXP (addr, 1);
- enum rtx_code code0 = GET_CODE (op0);
- if (code0 == USE || code0 == PLUS)
- {
- asm_fprintf (file, "@");
- output_addr_const (file, op1);
- }
- else if (REG_P (op0))
+ if (REG_P (op0))
{
- if (REGNO (op0) == DP_REGNO)
- {
- c4x_print_operand_address (file, op1);
- }
- else if (REG_P (op1))
+ if (REG_P (op1))
{
if (IS_INDEX_REGNO (op0))
{
@@ -1762,16 +1884,28 @@ c4x_print_operand_address (file, addr)
INTVAL (op1)); /* base + displacement */
}
}
+ else
+ fatal_insn ("c4x_print_operand_address: Bad operand case", addr);
+ }
+ break;
+
+ case LO_SUM:
+ {
+ rtx op0 = XEXP (addr, 0);
+ rtx op1 = XEXP (addr, 1);
+
+ if (REG_P (op0) && REGNO (op0) == DP_REGNO)
+ c4x_print_operand_address (file, op1);
+ else
+ fatal_insn ("c4x_print_operand_address: Bad operand case", addr);
}
break;
case CONST:
case SYMBOL_REF:
case LABEL_REF:
- if (! SYMBOL_REF_FLAG (addr))
- fprintf (file, "@");
+ fprintf (file, "@");
output_addr_const (file, addr);
- SYMBOL_REF_FLAG (addr) = 0;
break;
/* We shouldn't access CONST_INT addresses. */
@@ -1783,17 +1917,18 @@ c4x_print_operand_address (file, addr)
}
}
-
+/* Return nonzero if the floating point operand will fit
+ in the immediate field. */
static int
-c4x_immed_float_p (operand)
- rtx operand;
+c4x_immed_float_p (op)
+ rtx op;
{
long convval[2];
int exponent;
REAL_VALUE_TYPE r;
- REAL_VALUE_FROM_CONST_DOUBLE (r, operand);
- if (GET_MODE (operand) == HFmode)
+ REAL_VALUE_FROM_CONST_DOUBLE (r, op);
+ if (GET_MODE (op) == HFmode)
REAL_VALUE_TO_TARGET_DOUBLE (r, convval);
else
{
@@ -1811,157 +1946,6 @@ c4x_immed_float_p (operand)
&& (exponent >= -7); /* Negative exp */
}
-
-/* This function checks for an insn operand that requires direct
- addressing and inserts a load of the DP register prior to the
- insn if the big memory model is being compiled for. Immediate
- operands that do not fit within the opcode field get changed
- into memory references using direct addressing. At this point
- all pseudos have been converted to hard registers. */
-
-int
-c4x_scan_for_ldp (newop, insn, operand0)
- rtx *newop;
- rtx insn;
- rtx operand0;
-{
- int i;
- char *format_ptr;
- rtx op0, op1, op2, addr;
- rtx operand = *newop;
-
- switch (GET_CODE (operand))
- {
- case MEM:
- op0 = XEXP (operand, 0);
-
- /* We have something we need to emit a load dp insn for.
- The first operand should hold the rtx for the instruction
- required. */
-
- switch (GET_CODE (op0))
- {
- case CONST_INT:
- fatal_insn ("c4x_scan_for_ldp: Direct memory access to const_int",
- op0);
- break;
-
- case CONST:
- case SYMBOL_REF:
- if (! TARGET_C3X && ! TARGET_SMALL
- && recog_memoized (insn) == CODE_FOR_movqi_noclobber
- && ((addr = find_reg_note (insn, REG_EQUAL, NULL_RTX))
- || (addr = find_reg_note (insn, REG_EQUIV, NULL_RTX)))
- && (IS_STD_OR_PSEUDO_REGNO (operand0)))
- {
- addr = XEXP (addr, 0);
- if (GET_CODE (addr) == CONST_INT)
- {
- op1 = GEN_INT (INTVAL (addr) & ~0xffff);
- emit_insn_before (gen_movqi (operand0, op1), insn);
- op1 = GEN_INT (INTVAL (addr) & 0xffff);
- emit_insn_before (gen_iorqi3_noclobber (operand0,
- operand0, op1), insn);
- delete_insn (insn);
- return 1;
- }
- else if (GET_CODE (addr) == SYMBOL_REF)
- {
- emit_insn_before (gen_set_high_use (operand0, addr, addr),
- insn);
- emit_insn_before (gen_set_ior_lo_use (operand0, addr, addr),
- insn);
- delete_insn (insn);
- return 1;
- }
- else if (GET_CODE (addr) == CONST
- && GET_CODE (op1 = XEXP (addr, 0)) == PLUS
- && GET_CODE (op2 = XEXP (op1, 0)) == SYMBOL_REF
- && GET_CODE (XEXP (op1, 1)) == CONST_INT)
- {
- emit_insn_before (gen_set_high_use (operand0, addr, op2),
- insn);
- emit_insn_before (gen_set_ior_lo_use (operand0, addr, op2),
- insn);
- delete_insn (insn);
- return 1;
- }
- }
- if (! TARGET_SMALL)
- emit_insn_before (gen_set_ldp (gen_rtx_REG (Pmode, DP_REGNO),
- operand), insn);
-
- /* Replace old memory reference with direct reference. */
- *newop = gen_rtx_MEM (GET_MODE (operand),
- gen_rtx_PLUS (Pmode,
- gen_rtx_REG (Pmode, DP_REGNO),
- op0));
-
- /* Use change_address? */
- RTX_UNCHANGING_P (*newop) = RTX_UNCHANGING_P (operand);
- MEM_COPY_ATTRIBUTES (*newop, operand);
- break;
-
- default:
- break;
- }
-
- return 0;
-
- case CONST_INT:
- if (SMALL_CONST (INTVAL (operand), insn))
- break;
- fatal_insn ("Immediate integer too large", insn);
-
- case CONST_DOUBLE:
- if (c4x_immed_float_p (operand))
- break;
-
- /* We'll come here if a CONST_DOUBLE integer has slipped
- though the net... */
- fatal_insn ("Immediate CONST_DOUBLE integer too large", insn);
-
- case CONST:
- fatal_insn ("Immediate integer not known", insn);
-
- /* Symbol and label immediate addresses cannot be stored
- within a C[34]x instruction, so we store them in memory
- and use direct addressing instead. */
- case LABEL_REF:
- case SYMBOL_REF:
- if (GET_CODE (operand0) != REG)
- break;
-
- op0 = XEXP (force_const_mem (Pmode, operand), 0);
- *newop = gen_rtx_MEM (GET_MODE (operand),
- gen_rtx_PLUS (Pmode,
- gen_rtx_PLUS (Pmode,
- gen_rtx_USE (VOIDmode, operand),
- gen_rtx_REG (Pmode, DP_REGNO)),
- op0));
-
- if (! TARGET_SMALL)
- emit_insn_before (gen_set_ldp_use (gen_rtx_REG (Pmode, DP_REGNO),
- *newop, operand), insn);
- return 0;
-
- default:
- break;
- }
-
- format_ptr = GET_RTX_FORMAT (GET_CODE (operand));
-
- /* Recursively hunt for required loads of DP. */
- for (i = 0; i < GET_RTX_LENGTH (GET_CODE (operand)); i++)
- {
- if (*format_ptr++ == 'e') /* rtx expression */
- if (c4x_scan_for_ldp (&XEXP (operand, i), insn, operand0))
- break;
- }
- return 0;
-}
-
-
/* The last instruction in a repeat block cannot be a Bcond, DBcound,
CALL, CALLCond, TRAPcond, RETIcond, RETScond, IDLE, RPTB or RPTS.
@@ -1993,7 +1977,11 @@ c4x_rptb_nop_p (insn)
/* If there is a label at the end of the loop we must insert
a NOP. */
- insn = prev_nonnote_insn (insn);
+ do {
+ insn = previous_insn (insn);
+ } while (GET_CODE (insn) == NOTE
+ || GET_CODE (insn) == USE
+ || GET_CODE (insn) == CLOBBER);
if (GET_CODE (insn) == CODE_LABEL)
return 1;
@@ -2006,7 +1994,7 @@ c4x_rptb_nop_p (insn)
if (insn == start_label)
return i == 0;
- insn = PREV_INSN (insn);
+ insn = previous_insn (insn);
};
/* If we have a jump instruction we should insert a NOP. If we
@@ -2014,7 +2002,7 @@ c4x_rptb_nop_p (insn)
is empty. */
if (GET_CODE (insn) == JUMP_INSN)
return 1;
- insn = PREV_INSN (insn);
+ insn = previous_insn (insn);
}
return 0;
}
@@ -2053,20 +2041,16 @@ c4x_rptb_insert (insn)
emit_insn_before (gen_rptb_top (start_label, end_label), insn);
}
-/* This function is a C4x special. It scans through all the insn
- operands looking for places where the DP register needs to be
- reloaded and for large immediate operands that need to be converted
- to memory references. The latter should be avoidable with proper
- definition of patterns in machine description. We come here right
- near the end of things, immediately before delayed branch
- scheduling. */
+
+/* This function is a C4x special called immediately before delayed
+ branch scheduling. We fix up RTPB style loops that didn't get RC
+ allocated as the loop counter. */
void
c4x_process_after_reload (first)
rtx first;
{
rtx insn;
- int i;
for (insn = first; insn; insn = NEXT_INSN (insn))
{
@@ -2086,11 +2070,9 @@ c4x_process_after_reload (first)
c4x_rptb_insert(insn);
/* We split all insns here if they have a # for the output
- template if we are using the big memory model since there
- is a chance that we might be accessing memory across a
- page boundary. */
+ template. */
- if (! TARGET_SMALL)
+ if (1)
{
char *template;
@@ -2106,30 +2088,9 @@ c4x_process_after_reload (first)
PUT_CODE (insn, NOTE);
NOTE_SOURCE_FILE (insn) = 0;
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
-
- /* Do we have to update the basic block info here?
- Maybe reorg wants it sorted out... */
-
- /* Continue with the first of the new insns generated
- by the split. */
insn = new;
-
- insn_code_number = recog_memoized (insn);
-
- if (insn_code_number < 0)
- continue;
}
}
-
- /* Ignore jumps and calls. */
- if (GET_CODE (insn) == CALL_INSN || GET_CODE (insn) == JUMP_INSN)
- continue;
-
- insn_extract (insn);
- for (i = 0; i < insn_n_operands[insn_code_number]; i++)
- if (c4x_scan_for_ldp (recog_operand_loc[i], insn,
- recog_operand[0]))
- break;
}
}
}
@@ -2152,11 +2113,12 @@ c4x_x_register (op)
static int
-c4x_int_constant (op)
+c4x_immed_int_constant (op)
rtx op;
{
if (GET_CODE (op) != CONST_INT)
return 0;
+
return GET_MODE (op) == VOIDmode
|| GET_MODE_CLASS (op) == MODE_INT
|| GET_MODE_CLASS (op) == MODE_PARTIAL_INT;
@@ -2164,11 +2126,15 @@ c4x_int_constant (op)
static int
-c4x_float_constant (op)
+c4x_immed_float_constant (op)
rtx op;
{
if (GET_CODE (op) != CONST_DOUBLE)
return 0;
+
+ if (GET_CODE (XEXP (op, 0)) == MEM)
+ return 0;
+
return GET_MODE (op) == QFmode || GET_MODE (op) == HFmode;
}
@@ -2177,7 +2143,7 @@ int
c4x_H_constant (op)
rtx op;
{
- return c4x_float_constant (op) && c4x_immed_float_p (op);
+ return c4x_immed_float_constant (op) && c4x_immed_float_p (op);
}
@@ -2185,7 +2151,7 @@ int
c4x_I_constant (op)
rtx op;
{
- return c4x_int_constant (op) && IS_INT16_CONST (INTVAL (op));
+ return c4x_immed_int_constant (op) && IS_INT16_CONST (INTVAL (op));
}
@@ -2195,7 +2161,7 @@ c4x_J_constant (op)
{
if (TARGET_C3X)
return 0;
- return c4x_int_constant (op) && IS_INT8_CONST (INTVAL (op));
+ return c4x_immed_int_constant (op) && IS_INT8_CONST (INTVAL (op));
}
@@ -2205,7 +2171,7 @@ c4x_K_constant (op)
{
if (TARGET_C3X)
return 0;
- return c4x_int_constant (op) && IS_INT5_CONST (INTVAL (op));
+ return c4x_immed_int_constant (op) && IS_INT5_CONST (INTVAL (op));
}
@@ -2213,7 +2179,7 @@ int
c4x_L_constant (op)
rtx op;
{
- return c4x_int_constant (op) && IS_UINT16_CONST (INTVAL (op));
+ return c4x_immed_int_constant (op) && IS_UINT16_CONST (INTVAL (op));
}
@@ -2221,7 +2187,7 @@ static int
c4x_N_constant (op)
rtx op;
{
- return c4x_int_constant (op) && IS_NOT_UINT16_CONST (INTVAL (op));
+ return c4x_immed_int_constant (op) && IS_NOT_UINT16_CONST (INTVAL (op));
}
@@ -2229,7 +2195,7 @@ static int
c4x_O_constant (op)
rtx op;
{
- return c4x_int_constant (op) && IS_HIGH_CONST (INTVAL (op));
+ return c4x_immed_int_constant (op) && IS_HIGH_CONST (INTVAL (op));
}
@@ -2277,6 +2243,7 @@ c4x_Q_constraint (op)
return IS_DISP8_CONST (INTVAL (op1));
}
break;
+
default:
break;
}
@@ -2508,7 +2475,7 @@ c4x_S_indirect (op)
}
-/* Symbol ref. */
+/* Direct memory operand. */
int
c4x_T_constraint (op)
@@ -2518,27 +2485,37 @@ c4x_T_constraint (op)
return 0;
op = XEXP (op, 0);
- if ((GET_CODE (op) == PLUS)
- && (GET_CODE (XEXP (op, 0)) == REG)
- && (REGNO (XEXP (op, 0)) == DP_REGNO))
+ if (GET_CODE (op) != LO_SUM)
{
- op = XEXP (op, 1);
- }
- else if ((GET_CODE (op) == PLUS)
- && (GET_CODE (XEXP (op, 0)) == PLUS)
- && (GET_CODE (XEXP (XEXP (op, 0), 0)) == USE))
- {
- op = XEXP (op, 1);
- }
- else if ((GET_CODE (op) == PLUS) && (GET_CODE (XEXP (op, 0)) == USE))
- {
- op = XEXP (op, 1);
+ /* Allow call operands. */
+ return GET_CODE (op) == SYMBOL_REF
+ && GET_MODE (op) == Pmode
+ && SYMBOL_REF_FLAG (op);
}
+ /* HImode and HFmode are not offsettable. */
+ if (GET_MODE (op) == HImode || GET_CODE (op) == HFmode)
+ return 0;
+
+ if ((GET_CODE (XEXP (op, 0)) == REG)
+ && (REGNO (XEXP (op, 0)) == DP_REGNO))
+ return c4x_U_constraint (XEXP (op, 1));
+
+ return 0;
+}
+
+
+/* Symbolic operand. */
+
+int
+c4x_U_constraint (op)
+ rtx op;
+{
/* Don't allow direct addressing to an arbitrary constant. */
if (GET_CODE (op) == CONST
&& GET_CODE (XEXP (op, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
+ && (GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
+ || GET_CODE (XEXP (XEXP (op, 0), 0)) == LABEL_REF)
&& GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
return 1;
@@ -2657,6 +2634,7 @@ reg_operand (op, mode)
return register_operand (op, mode);
}
+
int
reg_imm_operand (op, mode)
rtx op;
@@ -2667,6 +2645,7 @@ reg_imm_operand (op, mode)
return 0;
}
+
int
not_modify_reg (op, mode)
rtx op;
@@ -2693,6 +2672,16 @@ not_modify_reg (op, mode)
if (REG_P (op1) || GET_CODE (op1) == CONST_INT)
return 1;
}
+
+ case LO_SUM:
+ {
+ rtx op0 = XEXP (op, 0);
+
+ if (REG_P (op0) && REGNO (op0) == DP_REGNO)
+ return 1;
+ }
+ break;
+
case CONST:
case SYMBOL_REF:
case LABEL_REF:
@@ -2703,6 +2692,7 @@ not_modify_reg (op, mode)
return 0;
}
+
int
not_rc_reg (op, mode)
rtx op;
@@ -2713,6 +2703,7 @@ not_rc_reg (op, mode)
return 1;
}
+
/* Extended precision register R0-R1. */
int
@@ -2867,8 +2858,6 @@ call_operand (op, mode)
rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
- if (GET_CODE (op) != MEM)
- return 0;
op = XEXP (op, 0);
switch (GET_CODE (op))
{
@@ -2881,6 +2870,29 @@ call_operand (op, mode)
}
+/* Symbolic operand. */
+
+int
+symbolic_operand (op, mode)
+ register rtx op;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+ switch (GET_CODE (op))
+ {
+ case SYMBOL_REF:
+ case LABEL_REF:
+ return 1;
+ case CONST:
+ op = XEXP (op, 0);
+ return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
+ || GET_CODE (XEXP (op, 0)) == LABEL_REF)
+ && GET_CODE (XEXP (op, 1)) == CONST_INT);
+ default:
+ return 0;
+ }
+}
+
+
/* Check src operand of two operand arithmetic instructions. */
int
@@ -2894,14 +2906,29 @@ src_operand (op, mode)
if (mode == VOIDmode)
mode = GET_MODE (op);
- /* We could allow certain CONST_INT values for HImode... */
if (GET_CODE (op) == CONST_INT)
- return (mode == QImode || mode == Pmode) && c4x_I_constant (op);
+ return (mode == QImode || mode == Pmode || mode == HImode)
+ && c4x_I_constant (op);
/* We don't like CONST_DOUBLE integers. */
if (GET_CODE (op) == CONST_DOUBLE)
return c4x_H_constant (op);
+ /* Disallow symbolic addresses. */
+ if (GET_CODE (op) == SYMBOL_REF
+ || GET_CODE (op) == LABEL_REF
+ || GET_CODE (op) == CONST)
+ return 0;
+
+ /* Disallow direct memory access symbolic addresses.
+ These are usually caught by the movqi expander and
+ converted to a LO_SUM. */
+ if (GET_CODE (op) == MEM
+ && ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
+ || GET_CODE (XEXP (op, 0)) == LABEL_REF
+ || GET_CODE (XEXP (op, 0)) == CONST)))
+ return 0;
+
return general_operand (op, mode);
}
@@ -2930,13 +2957,10 @@ lsrc_operand (op, mode)
if (mode != QImode && mode != Pmode)
fatal_insn ("Mode not QImode", op);
- if (REG_P (op))
- return reg_operand (op, mode);
-
if (GET_CODE (op) == CONST_INT)
return c4x_L_constant (op) || c4x_J_constant (op);
- return general_operand (op, mode);
+ return src_operand (op, mode);
}
@@ -2953,13 +2977,10 @@ tsrc_operand (op, mode)
if (mode != QImode && mode != Pmode)
fatal_insn ("Mode not QImode", op);
- if (REG_P (op))
- return reg_operand (op, mode);
-
if (GET_CODE (op) == CONST_INT)
return c4x_L_constant (op) || c4x_N_constant (op) || c4x_J_constant (op);
- return general_operand (op, mode);
+ return src_operand (op, mode);
}
@@ -3441,7 +3462,7 @@ c4x_valid_operands (code, operands, mode, force)
break;
default:
- fatal ("c4x_valid_operands: Internal error");
+ fatal_insn ("c4x_valid_operands: Internal error", op2);
break;
}
@@ -3922,16 +3943,19 @@ c4x_operand_subword (op, i, validate_address, mode)
{
enum rtx_code code = GET_CODE (XEXP (op, 0));
enum machine_mode mode = GET_MODE (XEXP (op, 0));
+ enum machine_mode submode;
+
+ submode = mode;
+ if (mode == HImode)
+ submode = QImode;
+ else if (mode == HFmode)
+ submode = QFmode;
switch (code)
{
case POST_INC:
case PRE_INC:
- if (mode == HImode)
- mode = QImode;
- else if (mode == HFmode)
- mode = QFmode;
- return gen_rtx_MEM (mode, XEXP (op, 0));
+ return gen_rtx_MEM (submode, XEXP (op, 0));
case POST_DEC:
case PRE_DEC:
@@ -3941,6 +3965,23 @@ c4x_operand_subword (op, i, validate_address, mode)
e.g., *p-- => *(p-=2); *(p+1). */
fatal_insn ("c4x_operand_subword: invalid autoincrement", op);
+ case SYMBOL_REF:
+ case LABEL_REF:
+ case CONST:
+ case CONST_INT:
+ fatal_insn ("c4x_operand_subword: invalid address", op);
+
+ /* Even though offsettable_address_p considers (MEM
+ (LO_SUM)) to be offsettable, it is not safe if the
+ address is at the end of the data page since we also have
+ to fix up the associated high PART. In this case where
+ we are trying to split a HImode or HFmode memory
+ reference, we would have to emit another insn to reload a
+ new HIGH value. It's easier to disable LO_SUM memory references
+ in HImode or HFmode and we probably get better code. */
+ case LO_SUM:
+ fatal_insn ("c4x_operand_subword: address not offsettable", op);
+
default:
break;
}
@@ -4233,7 +4274,6 @@ c4x_adjust_cost (insn, link, dep_insn, cost)
/* Data dependency; DEP_INSN writes a register that INSN reads some
cycles later. */
-
if (TARGET_C3X)
{
if (get_attr_setgroup1 (dep_insn) && get_attr_usegroup1 (insn))
@@ -4248,7 +4288,6 @@ c4x_adjust_cost (insn, link, dep_insn, cost)
insn uses ar0-ar7. We then test if the same register
is used. The tricky bit is that some operands will
use several registers... */
-
if (get_attr_setar0 (dep_insn) && get_attr_usear0 (insn))
max = SET_USE_COST > max ? SET_USE_COST : max;
if (get_attr_setlda_ar0 (dep_insn) && get_attr_usear0 (insn))
@@ -4342,3 +4381,4 @@ c4x_adjust_cost (insn, link, dep_insn, cost)
else
abort ();
}
+
diff --git a/gcc/config/c4x/c4x.h b/gcc/config/c4x/c4x.h
index 2a0a7c0..c001712 100644
--- a/gcc/config/c4x/c4x.h
+++ b/gcc/config/c4x/c4x.h
@@ -258,12 +258,16 @@ extern int target_flags;
#define TARGET_C40 (target_flags & C40_FLAG)
#define TARGET_C44 (target_flags & C44_FLAG)
+#define TARGET_LOAD_ADDRESS (1 || (! TARGET_C3X && ! TARGET_SMALL))
+
/* -mrpts allows the use of the RPTS instruction irregardless.
-mrpts=max-cycles will use RPTS if the number of cycles is constant
and less than max-cycles. */
#define TARGET_RPTS_CYCLES(CYCLES) (TARGET_RPTS || (CYCLES) < c4x_rpts_cycles)
+#define BCT_CHECK_LOOP_ITERATIONS !(TARGET_LOOP_UNSIGNED)
+
/* -mcpu=XX with XX = target DSP version number */
/* This macro is similar to `TARGET_SWITCHES' but defines names of
@@ -836,16 +840,17 @@ c4x_secondary_memory_needed(CLASS1, CLASS2, MODE)
: ((C) == 'O') ? (IS_HIGH_CONST (VAL)) \
: 0 )
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VAL, C) \
- ( ((C) == 'G') ? (fp_zero_operand (VAL)) \
- : ((C) == 'H') ? (c4x_H_constant (VAL)) \
+#define CONST_DOUBLE_OK_FOR_LETTER_P(OP, C) \
+ ( ((C) == 'G') ? (fp_zero_operand (OP)) \
+ : ((C) == 'H') ? (c4x_H_constant (OP)) \
: 0 )
-#define EXTRA_CONSTRAINT(VAL, C) \
- ( ((C) == 'Q') ? (c4x_Q_constraint (VAL)) \
- : ((C) == 'R') ? (c4x_R_constraint (VAL)) \
- : ((C) == 'S') ? (c4x_S_constraint (VAL)) \
- : ((C) == 'T') ? (c4x_T_constraint (VAL)) \
+#define EXTRA_CONSTRAINT(OP, C) \
+ ( ((C) == 'Q') ? (c4x_Q_constraint (OP)) \
+ : ((C) == 'R') ? (c4x_R_constraint (OP)) \
+ : ((C) == 'S') ? (c4x_S_constraint (OP)) \
+ : ((C) == 'T') ? (c4x_T_constraint (OP)) \
+ : ((C) == 'U') ? (c4x_U_constraint (OP)) \
: 0 )
#define SMALL_CONST(VAL, insn) \
@@ -1613,17 +1618,44 @@ extern struct rtx_def *c4x_legitimize_address ();
/* Nonzero if the constant value X is a legitimate general operand.
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE.
- The C4x can only load 16-bit immediate values, so we only allow
- a restricted subset of CONST_INT and CONST_DOUBLE and reject
- LABEL_REF, SYMBOL_REF, CONST, and HIGH codes. */
+ The C4x can only load 16-bit immediate values, so we only allow a
+ restricted subset of CONST_INT and CONST_DOUBLE. Disallow
+ LABEL_REF and SYMBOL_REF (except on the C40 with the big memory
+ model) so that the symbols will be forced into the constant pool.
+ On second thoughts, lets do this with the move expanders.
+*/
#define LEGITIMATE_CONSTANT_P(X) \
((GET_CODE (X) == CONST_DOUBLE && c4x_H_constant (X)) \
- || (GET_CODE (X) == CONST_INT && c4x_I_constant (X)))
-
+ || (GET_CODE (X) == CONST_INT && c4x_I_constant (X)) \
+ || (GET_CODE (X) == SYMBOL_REF) \
+ || (GET_CODE (X) == LABEL_REF) \
+ || (GET_CODE (X) == CONST) \
+ || (GET_CODE (X) == HIGH && ! TARGET_C3X) \
+ || (GET_CODE (X) == LO_SUM && ! TARGET_C3X))
#define LEGITIMATE_DISPLACEMENT_P(X) IS_DISP8_CONST (INTVAL (X))
+/* Define this macro if references to a symbol must be treated
+ differently depending on something about the variable or
+ function named by the symbol (such as what section it is in).
+
+ The macro definition, if any, is executed immediately after the
+ rtl for DECL or other node is created.
+ The value of the rtl will be a `mem' whose address is a
+ `symbol_ref'.
+
+ The usual thing for this macro to do is to a flag in the
+ `symbol_ref' (such as `SYMBOL_REF_FLAG') or to store a modified
+ name string in the `symbol_ref' (if one bit is not enough
+ information).
+
+ On the C4x we use this to indicate if a symbol is in text or
+ data space. */
+
+extern void c4x_encode_section_info ();
+#define ENCODE_SECTION_INFO(DECL) c4x_encode_section_info (DECL);
+
/* Descripting Relative Cost of Operations */
/* Provide the costs of a rtl expression. This is in the body of a
@@ -1912,7 +1944,7 @@ dtors_section () \
|| ! TREE_READONLY (DECL) || TREE_SIDE_EFFECTS (DECL) \
|| ! DECL_INITIAL (DECL) \
|| (DECL_INITIAL (DECL) != error_mark_node \
- && ! TREE_CONSTANT (DECL_INITIAL (DECL)))) \
+ && ! TREE_CONSTANT (DECL_INITIAL (DECL)))) \
data_section (); \
else \
const_section (); \
@@ -2440,8 +2472,6 @@ do { fprintf (asm_out_file, "\t.sdef\t"); \
#define MACHINE_DEPENDENT_REORG(INSNS) c4x_process_after_reload(INSNS)
-#define MACHINE_DEPENDENT_COMBINE(INSNS) c4x_combine_parallel(INSNS)
-
#define DBR_OUTPUT_SEQEND(FILE) \
if (final_sequence != NULL_RTX) \
{ \
@@ -2492,7 +2522,8 @@ if (final_sequence != NULL_RTX) \
{"any_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE}}, \
{"par_ind_operand", {MEM}}, \
{"parallel_operand", {SUBREG, REG, MEM}}, \
- {"mem_operand", {MEM}}, \
+ {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}}, \
+ {"mem_operand", {MEM}},
/* Variables in c4x.c */
@@ -2582,6 +2613,8 @@ extern int rc_reg_operand ();
extern int st_reg_operand ();
+extern int symbolic_operand ();
+
extern int ar0_reg_operand ();
extern int ar0_mem_operand ();
@@ -2652,12 +2685,16 @@ extern int c4x_S_constraint ();
extern int c4x_T_constraint ();
+extern int c4x_U_constraint ();
+
extern void c4x_emit_libcall ();
extern void c4x_emit_libcall3 ();
extern void c4x_emit_libcall_mulhi ();
+extern int c4x_emit_move_sequence ();
+
extern int legitimize_operands ();
extern int valid_operands ();
diff --git a/gcc/config/c4x/c4x.md b/gcc/config/c4x/c4x.md
index 7d85854..60bc43f 100644
--- a/gcc/config/c4x/c4x.md
+++ b/gcc/config/c4x/c4x.md
@@ -23,7 +23,6 @@
;
; TODO :
-; Set up addressing macros to handle direct memory references properly.
; Try using PQImode again for addresses since C30 only uses
; 24-bit addresses. Ideally GCC would emit different insns
; for QImode and Pmode, whether Pmode was QImode or PQImode.
@@ -66,7 +65,7 @@
; st_reg_operand ST [y]
; dp_reg_operand DP [z]
; stik_const_operand 5-bit const [K]
-; src_operand general operand [rfmHI]
+; src_operand general operand [rfHmI]
; par_ind_operand indirect S mode (ARx + 0, 1, IRx) [S<>]
; parallel_operand par_ind_operand or ext_low_reg_operand
@@ -125,7 +124,7 @@
; Q ARx + 9-bit signed disp
; R ARx + 5-bit unsigned disp (C4x only)
; S ARx + 0, 1, IRx disp
-; T symbol ref (direct)
+; T direct memory operand
; V non offsettable memory
; X any operand
; < memory operand with autodecrement addressing
@@ -133,8 +132,12 @@
; { memory operand with pre-modify addressing
; } memory operand with post-modify addressing
-; Note that the d, f, and h constraints are equivalent.
-; The m constraint is equivalent to QT<>{}
+; Note that the 'd', 'f', and 'h' constraints are equivalent.
+; The m constraint is equivalent to 'QT<>{}'
+
+; Note we cannot use the 'g' constraint with Pmode (i.e, QImode)
+; operations since LEGITIMATE_CONSTANT_P accepts SYMBOL_REF.
+; So instead we use 'rIm' for signed operands or 'rLm' for unsigned operands.
; Note that the constraints are used to select the operands
; for a chosen pattern. The constraint that requires the fewest
@@ -1099,37 +1102,79 @@
"* return (TARGET_C3X) ? \"ldp\\t%A1\" : \"ldpk\\t%A1\";"
[(set_attr "type" "ldp")])
-
-; Used when moving a constant label reference to an external
-; location, this will make sure the original label is still
-; used so the optimizer will not optimize it away.
-;
-(define_insn "set_ldp_use"
- [(parallel [(set (match_operand:QI 0 "dp_reg_operand" "=z")
- (high:QI (match_operand:QI 1 "" "")))
- (use (match_operand 2 "" ""))])]
- "! TARGET_SMALL"
- "* return (TARGET_C3X) ? \"ldp\\t%A1\" : \"ldpk\\t%A1\";"
- [(set_attr "type" "ldp")])
-
-(define_insn "set_high_use"
- [(parallel [(set (match_operand:QI 0 "std_reg_operand" "=c")
- (high:QI (match_operand:QI 1 "" "")))
- (use (match_operand 2 "" ""))])]
- "! TARGET_C3X && ! TARGET_SMALL"
+(define_insn "set_high"
+ [(set (match_operand:QI 0 "std_reg_operand" "=c")
+ (high:QI (match_operand:QI 1 "symbolic_operand" "")))]
+ "! TARGET_C3X "
"ldhi\\t^%H1,%0"
[(set_attr "type" "unary")])
-(define_insn "set_ior_lo_use"
- [(parallel [(set (match_operand:QI 0 "std_reg_operand" "=c")
- (ior:QI (match_dup 0)
- (and:QI (match_operand:QI 1 "" "")
- (const_int 65535))))
- (use (match_operand 2 "" ""))])]
- "! TARGET_C3X && ! TARGET_SMALL"
+(define_insn "set_lo_sum"
+ [(set (match_operand:QI 0 "std_reg_operand" "=c")
+ (lo_sum:QI (match_dup 0)
+ (match_operand:QI 1 "symbolic_operand" "")))]
+ ""
"or\\t#%H1,%0"
[(set_attr "type" "unary")])
+(define_split
+ [(set (match_operand:QI 0 "std_reg_operand" "")
+ (match_operand:QI 1 "symbolic_operand" ""))]
+ "! TARGET_C3X"
+ [(set (match_dup 0) (high:QI (match_dup 1)))
+ (set (match_dup 0) (lo_sum:QI (match_dup 0) (match_dup 1)))]
+ "")
+
+; This pattern is required to handle the case where a register that clobbers
+; CC has been selected to load a symbolic address. We force the address
+; into memory and then generate LDP and LDIU insns.
+; This is also required for the C30 if we pretend that we can
+; easily load symbolic addresses into a register.
+(define_split
+ [(set (match_operand:QI 0 "reg_operand" "")
+ (match_operand:QI 1 "symbolic_operand" ""))]
+ "! TARGET_SMALL
+ && (TARGET_C3X || (reload_completed
+ && ! std_reg_operand (operands[0], QImode)))"
+ [(set (match_dup 2) (high:QI (match_dup 3)))
+ (set (match_dup 0) (match_dup 4))
+ (use (match_dup 1))]
+ "
+{
+ rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);
+ operands[2] = dp_reg;
+ operands[3] = force_const_mem (Pmode, operands[1]);
+ operands[4] = change_address (operands[3], QImode,
+ gen_rtx_LO_SUM (Pmode, dp_reg,
+ XEXP (operands[3], 0)));
+ operands[3] = XEXP (operands[3], 0);
+}")
+
+; This pattern is similar to the above but does not emit a LDP
+; for the small memory model.
+(define_split
+ [(set (match_operand:QI 0 "reg_operand" "")
+ (match_operand:QI 1 "symbolic_operand" ""))]
+ "TARGET_SMALL
+ && (TARGET_C3X || (reload_completed
+ && ! std_reg_operand (operands[0], QImode)))"
+ [(set (match_dup 0) (match_dup 1))]
+ "
+{
+ rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);
+ operands[1] = force_const_mem (Pmode, operands[1]);
+ operands[1] = change_address (operands[1], QImode,
+ gen_rtx_LO_SUM (Pmode, dp_reg,
+ XEXP (operands[1], 0)));
+}")
+
+(define_insn "load_immed_address"
+ [(set (match_operand:QI 0 "reg_operand" "=a?x?c*r")
+ (match_operand:QI 1 "symbolic_operand" ""))]
+ "TARGET_LOAD_ADDRESS"
+ "#"
+ [(set_attr "type" "multi")])
+
;
; LDIU/LDA/STI/STIK
;
@@ -1148,9 +1193,11 @@
; spill a register.
(define_insn "movqi_noclobber"
[(set (match_operand:QI 0 "src_operand" "=d,*c,m,r")
- (match_operand:QI 1 "src_hi_operand" "rmI,rmI,r,O"))]
- "reg_operand (operands[0], QImode)
- || reg_operand (operands[1], QImode)"
+ (match_operand:QI 1 "src_hi_operand" "rIm,rIm,r,O"))]
+ "(REG_P (operands[0]) || REG_P (operands[1])
+ || GET_CODE (operands[0]) == SUBREG
+ || GET_CODE (operands[1]) == SUBREG)
+ && ! symbolic_operand (operands[1], QImode)"
"*
if (which_alternative == 2)
return \"sti\\t%1,%0\";
@@ -1181,7 +1228,7 @@
; We shouldn't need these peepholes, but the combiner seems to miss them...
(define_peephole
[(set (match_operand:QI 0 "ext_reg_operand" "=d")
- (match_operand:QI 1 "src_operand" "g"))
+ (match_operand:QI 1 "src_operand" "rIm"))
(set (reg:CC 21)
(compare:CC (match_dup 0) (const_int 0)))]
""
@@ -1192,7 +1239,7 @@
(define_insn "*movqi_set"
[(set (reg:CC 21)
- (compare:CC (match_operand:QI 1 "src_operand" "g")
+ (compare:CC (match_operand:QI 1 "src_operand" "rIm")
(const_int 0)))
(set (match_operand:QI 0 "ext_reg_operand" "=d")
(match_dup 1))]
@@ -1206,7 +1253,7 @@
; when a simple compare with zero will suffice.
;(define_insn "*movqi_test"
; [(set (reg:CC 21)
-; (compare:CC (match_operand:QI 1 "src_operand" "g")
+; (compare:CC (match_operand:QI 1 "src_operand" "rIm")
; (const_int 0)))
; (clobber (match_scratch:QI 0 "=d"))]
; ""
@@ -1226,28 +1273,14 @@
; the compiler, have memoized the insn number already.
(define_expand "movqi"
- [(set (match_operand:QI 0 "src_operand" "")
- (match_operand:QI 1 "src_operand" ""))]
+ [(set (match_operand:QI 0 "general_operand" "")
+ (match_operand:QI 1 "general_operand" ""))]
""
"
- /* We shouldn't have to do this, since reload is supposed to
- be able to do this if we have a memory constraint. */
- if (CONSTANT_P (operands[1])
- && ! const_operand (operands[1], QImode))
- {
- operands[1] = force_const_mem (QImode, operands[1]);
- if (! memory_address_p (QImode, XEXP (operands[1], 0))
- && ! reload_in_progress)
- operands[1] = change_address (operands[1], QImode,
- XEXP (operands[1], 0));
- }
-
- if (! reload_in_progress
- && ! reg_operand (operands[0], QImode)
- && ! reg_operand (operands[1], QImode)
- && ! (stik_const_operand (operands[1], QImode)
- && ! push_operand (operands[0], QImode)))
- operands[1] = force_reg (QImode, operands[1]);")
+{
+ if (c4x_emit_move_sequence (operands, QImode))
+ DONE;
+}")
(define_insn "*movqi_update"
[(set (match_operand:QI 0 "reg_operand" "=r")
@@ -1303,7 +1336,7 @@
(define_insn "*absqi2_clobber"
[(set (match_operand:QI 0 "reg_operand" "=d,c")
- (abs:QI (match_operand:QI 1 "src_operand" "g,g")))
+ (abs:QI (match_operand:QI 1 "src_operand" "rIm,rIm")))
(clobber (reg:CC_NOOV 21))]
""
"absi\\t%1,%0"
@@ -1312,7 +1345,7 @@
(define_insn "*absqi2_test"
[(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (abs:QI (match_operand:QI 1 "src_operand" "g"))
+ (compare:CC_NOOV (abs:QI (match_operand:QI 1 "src_operand" "rIm"))
(const_int 0)))
(clobber (match_scratch:QI 0 "=d"))]
""
@@ -1322,7 +1355,7 @@
(define_insn "*absqi2_set"
[(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (abs:QI (match_operand:QI 1 "src_operand" "g"))
+ (compare:CC_NOOV (abs:QI (match_operand:QI 1 "src_operand" "rIm"))
(const_int 0)))
(set (match_operand:QI 0 "ext_reg_operand" "=d")
(abs:QI (match_dup 1)))]
@@ -1343,7 +1376,7 @@
(define_insn "*negqi2_clobber"
[(set (match_operand:QI 0 "reg_operand" "=d,c")
- (neg:QI (match_operand:QI 1 "src_operand" "g,g")))
+ (neg:QI (match_operand:QI 1 "src_operand" "rIm,rIm")))
(clobber (reg:CC_NOOV 21))]
""
"negi\\t%1,%0"
@@ -1352,7 +1385,7 @@
(define_insn "*negqi2_test"
[(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (neg:QI (match_operand:QI 1 "src_operand" "g"))
+ (compare:CC_NOOV (neg:QI (match_operand:QI 1 "src_operand" "rIm"))
(const_int 0)))
(clobber (match_scratch:QI 0 "=d"))]
""
@@ -1362,7 +1395,7 @@
(define_insn "*negqi2_set"
[(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (neg:QI (match_operand:QI 1 "src_operand" "g"))
+ (compare:CC_NOOV (neg:QI (match_operand:QI 1 "src_operand" "rIm"))
(const_int 0)))
(set (match_operand:QI 0 "ext_reg_operand" "=d")
(neg:QI (match_dup 1)))]
@@ -1373,7 +1406,7 @@
(define_insn "*negbqi2_clobber"
[(set (match_operand:QI 0 "ext_reg_operand" "=d")
- (neg:QI (match_operand:QI 1 "src_operand" "g")))
+ (neg:QI (match_operand:QI 1 "src_operand" "rIm")))
(use (reg:CC_NOOV 21))
(clobber (reg:CC_NOOV 21))]
""
@@ -1393,7 +1426,7 @@
(define_insn "*one_cmplqi2_clobber"
[(set (match_operand:QI 0 "reg_operand" "=d,c")
- (not:QI (match_operand:QI 1 "lsrc_operand" "g,g")))
+ (not:QI (match_operand:QI 1 "lsrc_operand" "rLm,rLm")))
(clobber (reg:CC 21))]
""
"not\\t%1,%0"
@@ -1402,7 +1435,7 @@
(define_insn "*one_cmplqi2_test"
[(set (reg:CC 21)
- (compare:CC (not:QI (match_operand:QI 1 "lsrc_operand" "g"))
+ (compare:CC (not:QI (match_operand:QI 1 "lsrc_operand" "rLm"))
(const_int 0)))
(clobber (match_scratch:QI 0 "=d"))]
""
@@ -1412,7 +1445,7 @@
(define_insn "*one_cmplqi2_set"
[(set (reg:CC 21)
- (compare:CC (not:QI (match_operand:QI 1 "lsrc_operand" "g"))
+ (compare:CC (not:QI (match_operand:QI 1 "lsrc_operand" "rLm"))
(const_int 0)))
(set (match_operand:QI 0 "ext_reg_operand" "=d")
(not:QI (match_dup 1)))]
@@ -1565,7 +1598,7 @@
(define_insn "*addqi3_clobber"
[(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c")
(plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g")))
+ (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,JR,rS<>,rIm")))
(clobber (reg:CC_NOOV 21))]
"valid_operands (PLUS, operands, QImode)"
"@
@@ -1581,7 +1614,7 @@
(define_insn "*addqi3_test"
[(set (reg:CC_NOOV 21)
(compare:CC_NOOV (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g"))
+ (match_operand:QI 2 "src_operand" "JR,rS<>,rIm"))
(const_int 0)))
(clobber (match_scratch:QI 0 "=d,?d,d"))]
"valid_operands (PLUS, operands, QImode)"
@@ -1622,7 +1655,7 @@
(define_insn "*addqi3_set"
[(set (reg:CC_NOOV 21)
(compare:CC_NOOV (plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g"))
+ (match_operand:QI 2 "src_operand" "JR,rS<>,rIm"))
(const_int 0)))
(set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d")
(plus:QI (match_dup 1) (match_dup 2)))]
@@ -1640,7 +1673,7 @@
(define_insn "addqi3_noclobber"
[(set (match_operand:QI 0 "std_reg_operand" "=c,?c,c")
(plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g")))]
+ (match_operand:QI 2 "src_operand" "JR,rS<>,rIm")))]
"valid_operands (PLUS, operands, QImode)"
"@
addi3\\t%2,%1,%0
@@ -1669,7 +1702,7 @@
(define_insn "*addqi3_noclobber_reload"
[(set (match_operand:QI 0 "general_operand" "=c,?c,c")
(plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g")))]
+ (match_operand:QI 2 "src_operand" "JR,rS<>,rIm")))]
"reload_in_progress"
"@
addi3\\t%2,%1,%0
@@ -1682,7 +1715,7 @@
(define_insn "*addqi3_carry_clobber"
[(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c")
(plus:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g")))
+ (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,JR,rS<>,rIm")))
(use (reg:CC_NOOV 21))
(clobber (reg:CC_NOOV 21))]
"valid_operands (PLUS, operands, QImode)"
@@ -1710,8 +1743,8 @@
(define_insn "*subqi3_clobber"
[(set (match_operand:QI 0 "reg_operand" "=d,?d,d,d,c,?c,c,c")
- (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g,rR,rS<>,0,g")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,0,JR,rS<>,g,0")))
+ (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rIm,rR,rS<>,0,rIm")
+ (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,0,JR,rS<>,rIm,0")))
(clobber (reg:CC_NOOV 21))]
"valid_operands (MINUS, operands, QImode)"
"@
@@ -1728,8 +1761,8 @@
(define_insn "*subqi3_test"
[(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,0"))
+ (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rIm")
+ (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,0"))
(const_int 0)))
(clobber (match_scratch:QI 0 "=d,?d,d,d"))]
"valid_operands (MINUS, operands, QImode)"
@@ -1743,8 +1776,8 @@
(define_peephole
[(parallel [(set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d,d")
- (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,0")))
+ (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rIm")
+ (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,0")))
(clobber (reg:CC_NOOV 21))])
(set (reg:CC_NOOV 21)
(compare:CC_NOOV (match_dup 0) (const_int 0)))]
@@ -1758,8 +1791,8 @@
(define_insn "*subqi3_set"
[(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,0"))
+ (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rIm")
+ (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,0"))
(const_int 0)))
(set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d,d")
(minus:QI (match_dup 1)
@@ -1775,8 +1808,8 @@
(define_insn "*subqi3_carry_clobber"
[(set (match_operand:QI 0 "reg_operand" "=d,?d,d,d,c,?c,c,c")
- (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g,rR,rS<>,0,g")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,0,JR,rS<>,g,0")))
+ (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rIm,rR,rS<>,0,rIm")
+ (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,0,JR,rS<>,rIm,0")))
(use (reg:CC_NOOV 21))
(clobber (reg:CC_NOOV 21))]
"valid_operands (MINUS, operands, QImode)"
@@ -1794,8 +1827,8 @@
(define_insn "*subqi3_carry_set"
[(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,g")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,0"))
+ (compare:CC_NOOV (minus:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rIm")
+ (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,0"))
(const_int 0)))
(set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d,d")
(minus:QI (match_dup 1)
@@ -1851,7 +1884,7 @@
(define_insn "*mulqi3_clobber"
[(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c")
(mult:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g")))
+ (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,JR,rS<>,rIm")))
(clobber (reg:CC_NOOV 21))]
"valid_operands (MULT, operands, QImode)"
"*
@@ -1872,7 +1905,7 @@
(define_insn "*mulqi3_test"
[(set (reg:CC_NOOV 21)
(compare:CC_NOOV (mult:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g"))
+ (match_operand:QI 2 "src_operand" "JR,rS<>,rIm"))
(const_int 0)))
(clobber (match_scratch:QI 0 "=d,?d,d"))]
"valid_operands (MULT, operands, QImode)"
@@ -1894,7 +1927,7 @@
(define_insn "*mulqi3_set"
[(set (reg:CC_NOOV 21)
(compare:CC_NOOV (mult:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g"))
+ (match_operand:QI 2 "src_operand" "JR,rS<>,rIm"))
(const_int 0)))
(set (match_operand:QI 0 "ext_reg_operand" "=d,?d,d")
(mult:QI (match_dup 1)
@@ -1924,7 +1957,7 @@
(and:QI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0")
(const_int 16777215)))
(sign_extend:QI
- (and:QI (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g")
+ (and:QI (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,JR,rS<>,rIm")
(const_int 16777215)))))
(clobber (reg:CC_NOOV 21))]
"TARGET_C3X && valid_operands (MULT, operands, QImode)"
@@ -2065,7 +2098,7 @@
(lshiftrt:HI
(mult:HI
(sign_extend:HI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0"))
- (sign_extend:HI (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g")))
+ (sign_extend:HI (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,JR,rS<>,rIm")))
(const_int 32))))
(clobber (reg:CC_NOOV 21))]
"! TARGET_C3X && valid_operands (MULT, operands, QImode)"
@@ -2106,7 +2139,7 @@
(lshiftrt:HI
(mult:HI
(zero_extend:HI (match_operand:QI 1 "src_operand" "%rR,rS<>,0,rR,rS<>,0"))
- (zero_extend:HI (match_operand:QI 2 "lsrc_operand" "JR,rS<>,g,JR,rS<>,g")))
+ (zero_extend:HI (match_operand:QI 2 "lsrc_operand" "JR,rS<>,rLm,JR,rS<>,rLm")))
(const_int 32))))
(clobber (reg:CC_NOOV 21))]
"! TARGET_C3X && valid_operands (MULT, operands, QImode)"
@@ -2414,7 +2447,7 @@
(define_insn "*ashlqi3_clobber"
[(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c")
(ashift:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g")))
+ (match_operand:QI 2 "src_operand" "JR,rS<>,rIm,JR,rS<>,rIm")))
(clobber (reg:CC 21))]
"valid_operands (ASHIFT, operands, QImode)"
"@
@@ -2431,7 +2464,7 @@
[(set (reg:CC 21)
(compare:CC
(ashift:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0")
- (match_operand:QI 2 "src_operand" "JR,rS<>,g"))
+ (match_operand:QI 2 "src_operand" "JR,rS<>,rIm"))
(const_int 0)))
(set (match_operand:QI 0 "reg_operand" "=d,?d,d")
(ashift:QI (match_dup 1)
@@ -2449,7 +2482,7 @@
(define_insn "*lshlqi3_clobber"
[(set (match_operand:QI 0 "reg_operand" "=d,?d,d,c,?c,c")
(ashift:QI (match_operand:QI 1 "src_operand" "rR,rS<>,0,rR,rS<>,0")
- (unspec [(match_operand:QI 2 "src_operand" "JR,rS<>,g,JR,rS<>,g")] 3)))
+ (unspec [(match_operand:QI 2 "src_operand" "JR,rS<>,rIm,JR,rS<>,rIm")] 3)))
(clobber (reg:CC 21))]
"valid_operands (ASHIFT, operands, QImode)"
"@
@@ -2614,7 +2647,7 @@
(define_insn "*cmpqi_test"
[(set (reg:CC 21)
(compare:CC (match_operand:QI 0 "src_operand" "rR,?rS<>,r")
- (match_operand:QI 1 "src_operand" "JR,rS<>,g")))]
+ (match_operand:QI 1 "src_operand" "JR,rS<>,rIm")))]
"valid_operands (COMPARE, operands, QImode)"
"@
cmpi3\\t%1,%0
@@ -2625,7 +2658,7 @@
(define_insn "*cmpqi_test_noov"
[(set (reg:CC_NOOV 21)
(compare:CC_NOOV (match_operand:QI 0 "src_operand" "rR,?rS<>,r")
- (match_operand:QI 1 "src_operand" "JR,rS<>,g")))]
+ (match_operand:QI 1 "src_operand" "JR,rS<>,rIm")))]
"valid_operands (COMPARE, operands, QImode)"
"@
cmpi3\\t%1,%0
@@ -2698,7 +2731,7 @@
(define_insn "*extv_clobber"
[(set (match_operand:QI 0 "reg_operand" "=d,c")
- (sign_extract:QI (match_operand:QI 1 "src_operand" "g,g")
+ (sign_extract:QI (match_operand:QI 1 "src_operand" "rLm,rLm")
(match_operand:QI 2 "const_int_operand" "n,n")
(match_operand:QI 3 "const_int_operand" "n,n")))
(clobber (reg:CC 21))]
@@ -2719,7 +2752,7 @@
(define_insn "*extv_clobber_test"
[(set (reg:CC 21)
- (compare:CC (sign_extract:QI (match_operand:QI 1 "src_operand" "g")
+ (compare:CC (sign_extract:QI (match_operand:QI 1 "src_operand" "rLm")
(match_operand:QI 2 "const_int_operand" "n")
(match_operand:QI 3 "const_int_operand" "n"))
(const_int 0)))
@@ -2741,7 +2774,7 @@
(define_insn "*extv_clobber_set"
[(set (reg:CC 21)
- (compare:CC (sign_extract:QI (match_operand:QI 1 "src_operand" "g")
+ (compare:CC (sign_extract:QI (match_operand:QI 1 "src_operand" "rLm")
(match_operand:QI 2 "const_int_operand" "n")
(match_operand:QI 3 "const_int_operand" "n"))
(const_int 0)))
@@ -2781,7 +2814,7 @@
(define_insn "*extzv_clobber"
[(set (match_operand:QI 0 "reg_operand" "=d,c")
- (zero_extract:QI (match_operand:QI 1 "src_operand" "g,g")
+ (zero_extract:QI (match_operand:QI 1 "src_operand" "rLm,rLm")
(match_operand:QI 2 "const_int_operand" "n,n")
(match_operand:QI 3 "const_int_operand" "n,n")))
(clobber (reg:CC 21))]
@@ -2802,7 +2835,7 @@
(define_insn "*extzv_test"
[(set (reg:CC 21)
- (compare:CC (zero_extract:QI (match_operand:QI 1 "src_operand" "g")
+ (compare:CC (zero_extract:QI (match_operand:QI 1 "src_operand" "rLm")
(match_operand:QI 2 "const_int_operand" "n")
(match_operand:QI 3 "const_int_operand" "n"))
(const_int 0)))
@@ -2824,11 +2857,11 @@
(define_insn "*extzv_set"
[(set (reg:CC 21)
- (compare:CC (zero_extract:QI (match_operand:QI 1 "src_operand" "g")
+ (compare:CC (zero_extract:QI (match_operand:QI 1 "src_operand" "rLm")
(match_operand:QI 2 "const_int_operand" "n")
(match_operand:QI 3 "const_int_operand" "n"))
(const_int 0)))
- (set (match_operand:QI 0 "reg_operand" "=d")
+ (set (match_operand:QI 0 "ext_reg_operand" "=d")
(zero_extract:QI (match_dup 1)
(match_dup 2)
(match_dup 3)))]
@@ -2867,7 +2900,7 @@
[(set (zero_extract:QI (match_operand:QI 0 "reg_operand" "=d,c")
(match_operand:QI 1 "const_int_operand" "n,n")
(match_operand:QI 2 "const_int_operand" "n,n"))
- (match_operand:QI 3 "src_operand" "g,g"))
+ (match_operand:QI 3 "src_operand" "rLm,rLm"))
(clobber (reg:CC 21))]
"! TARGET_C3X
&& (((INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
@@ -2890,10 +2923,10 @@
(set_attr "data" "uint16,uint16")])
(define_peephole
- [(parallel [(set (zero_extract:QI (match_operand:QI 0 "reg_operand" "=d")
+ [(parallel [(set (zero_extract:QI (match_operand:QI 0 "ext_reg_operand" "=d")
(match_operand:QI 1 "const_int_operand" "n")
(match_operand:QI 2 "const_int_operand" "n"))
- (match_operand:QI 3 "src_operand" "g"))
+ (match_operand:QI 3 "src_operand" "rLm"))
(clobber (reg:CC 21))])
(set (reg:CC 21)
(compare:CC (match_dup 0) (const_int 0)))]
@@ -2929,28 +2962,17 @@
(match_operand:QF 1 "src_operand" ""))]
""
"
- if (CONSTANT_P (operands[1]) && ! const_operand (operands[1], QFmode))
- {
- operands[1] = force_const_mem (QFmode, operands[1]);
- if (! memory_address_p (QFmode, XEXP (operands[1], 0))
- && ! reload_in_progress)
- operands[1] = change_address (operands[1], QFmode,
- XEXP (operands[1], 0));
- }
-
- if (! reload_in_progress
- && ! reg_operand (operands[0], QFmode)
- && ! reg_operand (operands[1], QFmode))
- operands[1] = force_reg (QFmode, operands[1]);
- ")
+{
+ if (c4x_emit_move_sequence (operands, QFmode))
+ DONE;
+}")
; We must provide an alternative to store to memory in case we have to
; spill a register.
-(define_insn "*movqf_noclobber"
+(define_insn "movqf_noclobber"
[(set (match_operand:QF 0 "src_operand" "=f,m")
- (match_operand:QF 1 "src_operand" "fmH,f"))]
- "reg_operand (operands[0], QFmode)
- || reg_operand (operands[1], QFmode)"
+ (match_operand:QF 1 "src_operand" "fHm,f"))]
+ "REG_P (operands[0]) || REG_P (operands[1])"
"@
ldfu\\t%1,%0
stf\\t%1,%0"
@@ -2958,7 +2980,7 @@
;(define_insn "*movqf_clobber"
; [(set (match_operand:QF 0 "reg_operand" "=f")
-; (match_operand:QF 1 "src_operand" "fmH"))
+; (match_operand:QF 1 "src_operand" "fHm"))
; (clobber (reg:CC 21))]
; "0"
; "ldf\\t%1,%0"
@@ -2966,7 +2988,7 @@
(define_insn "*movqf_test"
[(set (reg:CC 21)
- (compare:CC (match_operand:QF 1 "src_operand" "fmH")
+ (compare:CC (match_operand:QF 1 "src_operand" "fHm")
(const_int 0)))
(clobber (match_scratch:QF 0 "=f"))]
""
@@ -2975,7 +2997,7 @@
(define_insn "*movqf_set"
[(set (reg:CC 21)
- (compare:CC (match_operand:QF 1 "src_operand" "fmH")
+ (compare:CC (match_operand:QF 1 "src_operand" "fHm")
(match_operand:QF 2 "fp_zero_operand" "G")))
(set (match_operand:QF 0 "reg_operand" "=f")
(match_dup 1))]
@@ -3038,7 +3060,7 @@
(define_insn "*absqf2_clobber"
[(set (match_operand:QF 0 "reg_operand" "=f")
- (abs:QF (match_operand:QF 1 "src_operand" "fmH")))
+ (abs:QF (match_operand:QF 1 "src_operand" "fHm")))
(clobber (reg:CC_NOOV 21))]
""
"absf\\t%1,%0"
@@ -3046,7 +3068,7 @@
(define_insn "*absqf2_test"
[(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (abs:QF (match_operand:QF 1 "src_operand" "fmH"))
+ (compare:CC_NOOV (abs:QF (match_operand:QF 1 "src_operand" "fHm"))
(match_operand:QF 2 "fp_zero_operand" "G")))
(clobber (match_scratch:QF 0 "=f"))]
""
@@ -3055,7 +3077,7 @@
(define_insn "*absqf2_set"
[(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (abs:QF (match_operand:QF 1 "src_operand" "fmH"))
+ (compare:CC_NOOV (abs:QF (match_operand:QF 1 "src_operand" "fHm"))
(match_operand:QF 2 "fp_zero_operand" "G")))
(set (match_operand:QF 0 "reg_operand" "=f")
(abs:QF (match_dup 1)))]
@@ -3076,7 +3098,7 @@
(define_insn "*negqf2_clobber"
[(set (match_operand:QF 0 "reg_operand" "=f")
- (neg:QF (match_operand:QF 1 "src_operand" "fmH")))
+ (neg:QF (match_operand:QF 1 "src_operand" "fHm")))
(clobber (reg:CC_NOOV 21))]
""
"negf\\t%1,%0"
@@ -3084,7 +3106,7 @@
(define_insn "*negqf2_test"
[(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (neg:QF (match_operand:QF 1 "src_operand" "fmH"))
+ (compare:CC_NOOV (neg:QF (match_operand:QF 1 "src_operand" "fHm"))
(match_operand:QF 2 "fp_zero_operand" "G")))
(clobber (match_scratch:QF 0 "=f"))]
""
@@ -3093,7 +3115,7 @@
(define_insn "*negqf2_set"
[(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (neg:QF (match_operand:QF 1 "src_operand" "fmH"))
+ (compare:CC_NOOV (neg:QF (match_operand:QF 1 "src_operand" "fHm"))
(match_operand:QF 2 "fp_zero_operand" "G")))
(set (match_operand:QF 0 "reg_operand" "=f")
(neg:QF (match_dup 1)))]
@@ -3106,7 +3128,7 @@
;
(define_insn "floatqiqf2"
[(set (match_operand:QF 0 "reg_operand" "=f")
- (float:QF (match_operand:QI 1 "src_operand" "g")))
+ (float:QF (match_operand:QI 1 "src_operand" "rIm")))
(clobber (reg:CC 21))]
""
"float\\t%1,%0"
@@ -3114,17 +3136,17 @@
(define_insn "*floatqiqf2_set"
[(set (reg:CC 21)
- (compare:CC (float:QF (match_operand:QI 1 "src_operand" "g"))
+ (compare:CC (float:QF (match_operand:QI 1 "src_operand" "rIm"))
(match_operand:QF 2 "fp_zero_operand" "G")))
(set (match_operand:QF 0 "reg_operand" "=f")
(float:QF (match_dup 1)))]
-
""
"float\\t%1,%0"
[(set_attr "type" "unarycc")])
; Unsigned conversions are a little tricky because we need to
; add the value for the high bit if necessary.
+;
;
(define_expand "floatunsqiqf2"
[(set (match_dup 2) (match_dup 3))
@@ -3133,22 +3155,25 @@
(match_dup 3)))
(set (match_dup 4)
(float:QF (match_dup 1)))])
- (set (match_dup 2)
+ (set (match_dup 6)
(if_then_else:QF (lt (reg:CC 21) (const_int 0))
- (mem:QF (symbol_ref:QF "*___unsfltconst"))
+ (match_dup 5)
(match_dup 2)))
(parallel [(set (match_operand:QF 0 "reg_operand" "")
- (plus:QF (match_dup 2) (match_dup 4)))
+ (plus:QF (match_dup 6) (match_dup 4)))
(clobber (reg:CC_NOOV 21))])]
""
"operands[2] = gen_reg_rtx (QFmode);
operands[3] = CONST0_RTX (QFmode);
operands[4] = gen_reg_rtx (QFmode);
- ")
+ operands[5] = gen_reg_rtx (QFmode);
+ operands[6] = gen_reg_rtx (QFmode);
+ emit_move_insn (operands[5],
+ immed_real_const_1 (REAL_VALUE_ATOF (\"4294967296.0\", QFmode), QFmode));")
(define_insn "floatqihf2"
[(set (match_operand:HF 0 "reg_operand" "=h")
- (float:HF (match_operand:QI 1 "src_operand" "g")))
+ (float:HF (match_operand:QI 1 "src_operand" "rIm")))
(clobber (reg:CC 21))]
""
"float\\t%1,%0"
@@ -3159,7 +3184,7 @@
;
(define_insn "fixqfqi_clobber"
[(set (match_operand:QI 0 "reg_operand" "=d,c")
- (fix:QI (match_operand:QF 1 "src_operand" "fmH,fmH")))
+ (fix:QI (match_operand:QF 1 "src_operand" "fHm,fHm")))
(clobber (reg:CC 21))]
""
"fix\\t%1,%0"
@@ -3167,9 +3192,9 @@
(define_insn "*fixqfqi_set"
[(set (reg:CC 21)
- (compare:CC (fix:QI (match_operand:QF 1 "src_operand" "fmH"))
+ (compare:CC (fix:QI (match_operand:QF 1 "src_operand" "fHm"))
(const_int 0)))
- (set (match_operand:QI 0 "reg_operand" "=d")
+ (set (match_operand:QI 0 "ext_reg_operand" "=d")
(fix:QI (match_dup 1)))]
""
"fix\\t%1,%0"
@@ -3215,26 +3240,20 @@
"c4x_emit_libcall (FIX_TRUNCQFHI2_LIBCALL, FIX, HImode, QFmode, 2, operands);
DONE;")
+; Is this allowed to be implementation dependent? If so, we can
+; omit the conditional load. Otherwise we should emit a split.
(define_expand "fixuns_truncqfqi2"
- [(set (match_dup 2) (match_dup 4))
- (set (reg:CC 21)
- (compare:CC (match_operand:QF 1 "reg_operand" "")
- (mem:QF (symbol_ref "*___unsfltcompare"))))
- (set (match_dup 2)
- (if_then_else:QF (ge (reg:CC 21) (const_int 0))
- (mem:QF (symbol_ref "*___unsfltconst"))
- (match_dup 2)))
- (parallel [(set (match_dup 3)
- (minus:QF (match_dup 1) (match_dup 2)))
- (clobber (reg:CC_NOOV 21))])
- (parallel [(set (match_operand:QI 0 "reg_operand" "")
- (fix:QI (match_dup 3)))
- (clobber (reg:CC 21))])]
+ [(parallel [(set (reg:CC 21)
+ (compare:CC (fix:QI (match_operand:QF 1 "src_operand" "fHm"))
+ (const_int 0)))
+ (set (match_dup 2)
+ (fix:QI (match_dup 1)))])
+ (set (match_operand:QI 0 "reg_operand" "=r")
+ (if_then_else:QI (lt (reg:CC 21) (const_int 0))
+ (const_int 0)
+ (match_dup 2)))]
""
- "operands[2] = gen_reg_rtx (QFmode);
- operands[3] = gen_reg_rtx (QFmode);
- operands[4] = CONST0_RTX (QFmode);
- ")
+ "operands[2] = gen_reg_rtx (QImode);")
(define_expand "fixuns_truncqfhi2"
[(parallel [(set (match_operand:HI 0 "reg_operand" "")
@@ -3250,7 +3269,7 @@
;
(define_insn "*rcpfqf_clobber"
[(set (match_operand:QF 0 "reg_operand" "=f")
- (unspec [(match_operand:QF 1 "src_operand" "fmH")] 5))
+ (unspec [(match_operand:QF 1 "src_operand" "fHm")] 5))
(clobber (reg:CC_NOOV 21))]
"! TARGET_C3X"
"rcpf\\t%1,%0"
@@ -3261,7 +3280,7 @@
;
(define_insn "*rsqrfqf_clobber"
[(set (match_operand:QF 0 "reg_operand" "=f")
- (unspec [(match_operand:QF 1 "src_operand" "fmH")] 10))
+ (unspec [(match_operand:QF 1 "src_operand" "fHm")] 10))
(clobber (reg:CC_NOOV 21))]
"! TARGET_C3X"
"rsqrf\\t%1,%0"
@@ -3272,7 +3291,7 @@
;
(define_insn "*rndqf_clobber"
[(set (match_operand:QF 0 "reg_operand" "=f")
- (unspec [(match_operand:QF 1 "src_operand" "fmH")] 6))
+ (unspec [(match_operand:QF 1 "src_operand" "fHm")] 6))
(clobber (reg:CC_NOOV 21))]
"! TARGET_C3X"
"rnd\\t%1,%0"
@@ -3351,7 +3370,7 @@
(define_insn "*addqf3_clobber"
[(set (match_operand:QF 0 "reg_operand" "=f,?f,f")
(plus:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0")
- (match_operand:QF 2 "src_operand" "R,fS<>,fmH")))
+ (match_operand:QF 2 "src_operand" "R,fS<>,fHm")))
(clobber (reg:CC_NOOV 21))]
"valid_operands (PLUS, operands, QFmode)"
"@
@@ -3363,7 +3382,7 @@
(define_insn "*addqf3_test"
[(set (reg:CC_NOOV 21)
(compare:CC_NOOV (plus:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0")
- (match_operand:QF 2 "src_operand" "R,fS<>,fmH"))
+ (match_operand:QF 2 "src_operand" "R,fS<>,fHm"))
(match_operand:QF 3 "fp_zero_operand" "G,G,G")))
(clobber (match_scratch:QF 0 "=f,?f,f"))]
"valid_operands (PLUS, operands, QFmode)"
@@ -3376,7 +3395,7 @@
(define_insn "*addqf3_set"
[(set (reg:CC_NOOV 21)
(compare:CC_NOOV (plus:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0")
- (match_operand:QF 2 "src_operand" "R,fS<>,fmH"))
+ (match_operand:QF 2 "src_operand" "R,fS<>,fHm"))
(match_operand:QF 3 "fp_zero_operand" "G,G,G")))
(set (match_operand:QF 0 "reg_operand" "=f,?f,f")
(plus:QF (match_dup 1)
@@ -3401,8 +3420,8 @@
(define_insn "*subqf3_clobber"
[(set (match_operand:QF 0 "reg_operand" "=f,?f,f,f")
- (minus:QF (match_operand:QF 1 "src_operand" "fR,fS<>,0,fmH")
- (match_operand:QF 2 "src_operand" "R,fS<>,fmH,0")))
+ (minus:QF (match_operand:QF 1 "src_operand" "fR,fS<>,0,fHm")
+ (match_operand:QF 2 "src_operand" "R,fS<>,fHm,0")))
(clobber (reg:CC_NOOV 21))]
"valid_operands (MINUS, operands, QFmode)"
"@
@@ -3414,8 +3433,8 @@
(define_insn "*subqf3_test"
[(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (minus:QF (match_operand:QF 1 "src_operand" "fR,fS<>,0,fmH")
- (match_operand:QF 2 "src_operand" "R,fS<>,fmH,0"))
+ (compare:CC_NOOV (minus:QF (match_operand:QF 1 "src_operand" "fR,fS<>,0,fHm")
+ (match_operand:QF 2 "src_operand" "R,fS<>,fHm,0"))
(match_operand:QF 3 "fp_zero_operand" "G,G,G,G")))
(clobber (match_scratch:QF 0 "=f,?f,f,f"))]
"valid_operands (MINUS, operands, QFmode)"
@@ -3428,8 +3447,8 @@
(define_insn "*subqf3_set"
[(set (reg:CC_NOOV 21)
- (compare:CC_NOOV (minus:QF (match_operand:QF 1 "src_operand" "fR,fS<>,0,fmH")
- (match_operand:QF 2 "src_operand" "R,fS<>,fmH,0"))
+ (compare:CC_NOOV (minus:QF (match_operand:QF 1 "src_operand" "fR,fS<>,0,fHm")
+ (match_operand:QF 2 "src_operand" "R,fS<>,fHm,0"))
(match_operand:QF 3 "fp_zero_operand" "G,G,G,G")))
(set (match_operand:QF 0 "reg_operand" "=f,?f,f,f")
(minus:QF (match_dup 1)
@@ -3456,7 +3475,7 @@
(define_insn "*mulqf3_clobber"
[(set (match_operand:QF 0 "reg_operand" "=f,?f,f")
(mult:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0")
- (match_operand:QF 2 "src_operand" "R,fS<>,fmH")))
+ (match_operand:QF 2 "src_operand" "R,fS<>,fHm")))
(clobber (reg:CC_NOOV 21))]
"valid_operands (MULT, operands, QFmode)"
"@
@@ -3468,7 +3487,7 @@
(define_insn "*mulqf3_test"
[(set (reg:CC_NOOV 21)
(compare:CC_NOOV (mult:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0")
- (match_operand:QF 2 "src_operand" "R,fS<>,fmH"))
+ (match_operand:QF 2 "src_operand" "R,fS<>,fHm"))
(match_operand:QF 3 "fp_zero_operand" "G,G,G")))
(clobber (match_scratch:QF 0 "=f,?f,f"))]
"valid_operands (MULT, operands, QFmode)"
@@ -3481,7 +3500,7 @@
(define_insn "*mulqf3_set"
[(set (reg:CC_NOOV 21)
(compare:CC_NOOV (mult:QF (match_operand:QF 1 "src_operand" "%fR,fS<>,0")
- (match_operand:QF 2 "src_operand" "R,fS<>,fmH"))
+ (match_operand:QF 2 "src_operand" "R,fS<>,fHm"))
(match_operand:QF 3 "fp_zero_operand" "G,G,G")))
(set (match_operand:QF 0 "reg_operand" "=f,?f,f")
(mult:QF (match_dup 1)
@@ -3509,7 +3528,7 @@
(define_insn "*cmpqf"
[(set (reg:CC 21)
(compare:CC (match_operand:QF 0 "src_operand" "fR,?fS<>,f")
- (match_operand:QF 1 "src_operand" "R,fS<>,fmH")))]
+ (match_operand:QF 1 "src_operand" "R,fS<>,fHm")))]
"valid_operands (COMPARE, operands, QFmode)"
"@
cmpf3\\t%1,%0
@@ -3520,7 +3539,7 @@
(define_insn "*cmpqf_noov"
[(set (reg:CC_NOOV 21)
(compare:CC_NOOV (match_operand:QF 0 "src_operand" "fR,?fS<>,f")
- (match_operand:QF 1 "src_operand" "R,fS<>,fmH")))]
+ (match_operand:QF 1 "src_operand" "R,fS<>,fHm")))]
"valid_operands (COMPARE, operands, QFmode)"
"@
cmpf3\\t%1,%0
@@ -3586,8 +3605,8 @@
[(set (match_operand:QI 0 "reg_operand" "=r,r")
(if_then_else:QI (match_operator 1 "comparison_operator"
[(reg:CC 21) (const_int 0)])
- (match_operand:QI 2 "src_operand" "g,0")
- (match_operand:QI 3 "src_operand" "0,g")))]
+ (match_operand:QI 2 "src_operand" "rIm,0")
+ (match_operand:QI 3 "src_operand" "0,rIm")))]
""
"@
ldi%1\\t%2,%0
@@ -3598,8 +3617,8 @@
[(set (match_operand:QI 0 "reg_operand" "=r,r")
(if_then_else:QI (match_operator 1 "comparison_operator"
[(reg:CC_NOOV 21) (const_int 0)])
- (match_operand:QI 2 "src_operand" "g,0")
- (match_operand:QI 3 "src_operand" "0,g")))]
+ (match_operand:QI 2 "src_operand" "rIm,0")
+ (match_operand:QI 3 "src_operand" "0,rIm")))]
"GET_CODE (operands[1]) != LE
&& GET_CODE (operands[1]) != GE
&& GET_CODE (operands[1]) != LT
@@ -3634,8 +3653,8 @@
[(set (match_operand:QF 0 "reg_operand" "=f,f")
(if_then_else:QF (match_operator 1 "comparison_operator"
[(reg:CC 21) (const_int 0)])
- (match_operand:QF 2 "src_operand" "fmH,0")
- (match_operand:QF 3 "src_operand" "0,fmH")))]
+ (match_operand:QF 2 "src_operand" "fHm,0")
+ (match_operand:QF 3 "src_operand" "0,fHm")))]
""
"@
ldf%1\\t%2,%0
@@ -3646,8 +3665,8 @@
[(set (match_operand:QF 0 "reg_operand" "=f,f")
(if_then_else:QF (match_operator 1 "comparison_operator"
[(reg:CC_NOOV 21) (const_int 0)])
- (match_operand:QF 2 "src_operand" "fmH,0")
- (match_operand:QF 3 "src_operand" "0,fmH")))]
+ (match_operand:QF 2 "src_operand" "fHm,0")
+ (match_operand:QF 3 "src_operand" "0,fHm")))]
"GET_CODE (operands[1]) != LE
&& GET_CODE (operands[1]) != GE
&& GET_CODE (operands[1]) != LT
@@ -4336,92 +4355,68 @@
; CALL
;
(define_insn "*call_c3x"
- [(call (match_operand:QI 0 "call_operand" "T,!o")
+ [(call (mem:QI (match_operand:QI 0 "call_operand" ""))
(match_operand:QI 1 "general_operand" ""))
(clobber (reg:QI 31))]
;; Operand 1 not really used on the C4x. The C30 doesn't have reg 31.
"TARGET_C3X"
- "@
- call\\t%C0
- callu\\t%R0"
- [(set_attr "type" "call,call")])
+ "call%U0\\t%C0"
+ [(set_attr "type" "call")])
; LAJ requires R11 (31) for the return address
(define_insn "*laj"
- [(call (match_operand:QI 0 "call_operand" "T,!o")
+ [(call (mem:QI (match_operand:QI 0 "call_operand" ""))
(match_operand:QI 1 "general_operand" ""))
(clobber (reg:QI 31))]
;; Operand 1 not really used on the C4x.
"! TARGET_C3X"
"*
- if (which_alternative == 0)
- {
- if (final_sequence)
- return \"laj\\t%C0\";
- else
- return \"call\\t%C0\";
- }
+ if (final_sequence)
+ return \"laj%U0\\t%C0\";
else
- {
- if (final_sequence)
- return \"laju\\t%R0\";
- else
- return \"callu\\t%R0\";
- }"
- [(set_attr "type" "laj,laj")])
+ return \"call%U0\\t%C0\";"
+ [(set_attr "type" "laj")])
(define_expand "call"
- [(parallel [(call (match_operand:QI 0 "call_operand" "")
+ [(parallel [(call (mem:QI (match_operand:QI 0 "call_operand" ""))
(match_operand:QI 1 "general_operand" ""))
(clobber (reg:QI 31))])]
""
"")
(define_insn "*callv_c3x"
- [(set (match_operand 0 "" "=r,r")
- (call (match_operand:QI 1 "call_operand" "T,!o")
+ [(set (match_operand 0 "" "=r")
+ (call (mem:QI (match_operand:QI 1 "call_operand" ""))
(match_operand:QI 2 "general_operand" "")))
(clobber (reg:QI 31))]
;; Operand 0 and 2 not really used for the C4x.
;; The C30 doesn't have reg 31.
"TARGET_C3X"
- "@
- call\\t%C1
- callu\\t%R1"
- [(set_attr "type" "call,call")])
+ "call%U1\\t%C1"
+ [(set_attr "type" "call")])
; LAJ requires R11 (31) for the return address
(define_insn "*lajv"
- [(set (match_operand 0 "" "=r,r")
- (call (match_operand:QI 1 "call_operand" "T,!o")
+ [(set (match_operand 0 "" "=r")
+ (call (mem:QI (match_operand:QI 1 "call_operand" ""))
(match_operand:QI 2 "general_operand" "")))
(clobber (reg:QI 31))]
;; Operand 0 and 2 not really used in the C30 instruction.
"! TARGET_C3X"
"*
- if (which_alternative == 0)
- {
- if (final_sequence)
- return \"laj\\t%C1\";
- else
- return \"call\\t%C1\";
- }
+ if (final_sequence)
+ return \"laj%U1\\t%C1\";
else
- {
- if (final_sequence)
- return \"laju\\t%R1\";
- else
- return \"callu\\t%R1\";
- }"
- [(set_attr "type" "laj,laj")])
+ return \"call%U1\\t%C1\";"
+ [(set_attr "type" "laj")])
(define_expand "call_value"
[(parallel [(set (match_operand 0 "" "")
- (call (match_operand:QI 1 "call_operand" "")
+ (call (mem:QI (match_operand:QI 1 "call_operand" ""))
(match_operand:QI 2 "general_operand" "")))
(clobber (reg:QI 31))])]
""
@@ -4787,7 +4782,7 @@
(define_insn "*cmpstrqi"
- [(set (match_operand:QI 0 "reg_operand" "=d")
+ [(set (match_operand:QI 0 "ext_reg_operand" "=d")
(compare:QI (mem:BLK (match_operand:QI 1 "addr_reg_operand" "a"))
(mem:BLK (match_operand:QI 2 "addr_reg_operand" "a"))))
(use (match_operand:QI 3 "immediate_operand" "i"))
@@ -4833,32 +4828,20 @@
[(set (match_operand:HF 0 "src_operand" "")
(match_operand:HF 1 "src_operand" ""))]
""
- "if (CONSTANT_P (operands[1]))
- {
- operands[1] = force_const_mem (HFmode, operands[1]);
- if (! memory_address_p (HFmode, XEXP (operands[1], 0))
- && ! reload_in_progress)
- operands[1] = change_address (operands[1], HFmode,
- XEXP (operands[1], 0));
- }
-
- /* Memory to memory copies must go through a register. */
- if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[0]) == MEM
- && ! reload_in_progress)
- operands[1] = force_reg (HFmode, operands[1]);
-")
+ "if (c4x_emit_move_sequence (operands, HFmode))
+ DONE;")
(define_insn "*movhf_noclobber_reg"
[(set (match_operand:HF 0 "reg_operand" "=h")
- (match_operand:HF 1 "reg_operand" "h"))]
- ""
+ (match_operand:HF 1 "src_operand" "Hh"))]
+ "GET_CODE (operands[1]) != MEM"
"ldfu\\t%1,%0"
[(set_attr "type" "unary")])
; The predicates could be tightened to disallow constants
(define_insn "*movhf_noclobber"
[(set (match_operand:HF 0 "src_operand" "=h,m")
- (match_operand:HF 1 "src_operand" "m,h"))]
+ (match_operand:HF 1 "src_operand" "HQT>,h"))]
"reg_operand (operands[0], HFmode) ^ reg_operand (operands[1], HFmode)"
"#"
[(set_attr "type" "multi,multi")])
@@ -4917,7 +4900,7 @@
(define_insn "*loadhf_float"
[(set (match_operand:HF 0 "reg_operand" "=h")
- (float_extend:HF (match_operand:QF 1 "src_operand" "fmH")))]
+ (float_extend:HF (match_operand:QF 1 "src_operand" "fHm")))]
""
"@
ldfu\\t%1,%0"
@@ -4926,7 +4909,7 @@
(define_insn "*loadhf_int"
[(set (match_operand:HF 0 "reg_operand" "=h")
(unspec[(subreg:QI (match_dup 0) 0)
- (match_operand:QI 1 "src_operand" "g")] 8))]
+ (match_operand:QI 1 "src_operand" "rIm")] 8))]
""
"@
ldiu\\t%1,%0"
@@ -5372,22 +5355,8 @@
[(set (match_operand:HI 0 "src_operand" "")
(match_operand:HI 1 "src_operand" ""))]
""
- "if (CONSTANT_P (operands[1]))
- {
- /* We don't need to force all constants into memory.
- This could be improved.... */
- operands[1] = force_const_mem (HImode, operands[1]);
- if (! memory_address_p (HImode, XEXP (operands[1], 0))
- && ! reload_in_progress)
- operands[1] = change_address (operands[1], HImode,
- XEXP (operands[1], 0));
- }
-
- /* Memory to memory copies must go through a register. */
- if (GET_CODE (operands[1]) == MEM && GET_CODE (operands[0]) == MEM
- && ! reload_in_progress)
- operands[1] = force_reg (HImode, operands[1]);
-")
+ "if (c4x_emit_move_sequence (operands, HImode))
+ DONE;")
; The constraints for movhi must include 'r' if we don't
; restrict HImode regnos to start on an even number, since
@@ -5395,7 +5364,7 @@
; votes for FP_REGS so we use dr as the constraints.
(define_insn "*movhi_noclobber"
[(set (match_operand:HI 0 "src_operand" "=dr,m")
- (match_operand:HI 1 "src_operand" "drm,r"))]
+ (match_operand:HI 1 "src_operand" "drIQT>,r"))]
"reg_operand (operands[0], HImode)
|| reg_operand (operands[1], HImode)"
"#"
@@ -5416,7 +5385,7 @@
(define_insn "extendqihi2"
[(set (match_operand:HI 0 "reg_operand" "=dc")
- (sign_extend:HI (match_operand:QI 1 "src_operand" "g")))
+ (sign_extend:HI (match_operand:QI 1 "src_operand" "rIm")))
(clobber (reg:CC 21))]
""
"#"
@@ -5424,7 +5393,7 @@
(define_split
[(set (match_operand:HI 0 "reg_operand" "=?dc")
- (sign_extend:HI (match_operand:QI 1 "src_operand" "g")))
+ (sign_extend:HI (match_operand:QI 1 "src_operand" "rIm")))
(clobber (reg:CC 21))]
"reload_completed && TARGET_C3X"
[(set (match_dup 2) (match_dup 1))
@@ -5436,7 +5405,7 @@
(define_split
[(set (match_operand:HI 0 "reg_operand" "=?dc")
- (sign_extend:HI (match_operand:QI 1 "src_operand" "g")))
+ (sign_extend:HI (match_operand:QI 1 "src_operand" "rIm")))
(clobber (reg:CC 21))]
"reload_completed && ! TARGET_C3X"
[(set (match_dup 2) (match_dup 1))
@@ -5447,7 +5416,7 @@
(define_insn "zero_extendqihi2"
[(set (match_operand:HI 0 "reg_operand" "=?dc")
- (zero_extend:HI (match_operand:QI 1 "src_operand" "g")))
+ (zero_extend:HI (match_operand:QI 1 "src_operand" "rIm")))
(clobber (reg:CC 21))]
""
"#"
@@ -5457,7 +5426,7 @@
; the first set.
(define_split
[(set (match_operand:HI 0 "reg_operand" "=?dc")
- (zero_extend:HI (match_operand:QI 1 "src_operand" "g")))
+ (zero_extend:HI (match_operand:QI 1 "src_operand" "rIm")))
(clobber (reg:CC 21))]
"reload_completed"
[(set (match_dup 2) (match_dup 1))
@@ -6209,12 +6178,12 @@
(parallel
[(set (pc)
(if_then_else
- (ge (plus:QI (match_operand:QI 4 "addr_reg_operand" "0")
+ (ge (plus:QI (match_operand:QI 0 "addr_reg_operand" "+a")
(const_int -1))
(const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))
- (set (match_operand:QI 0 "addr_reg_operand" "+a")
+ (set (match_dup 0)
(plus:QI (match_dup 0)
(const_int -1)))
(clobber (reg:CC_NOOV 21))])]
@@ -6230,11 +6199,11 @@
(parallel
[(set (pc)
(if_then_else
- (ne (match_operand:QI 4 "addr_reg_operand" "0")
+ (ne (match_operand:QI 0 "addr_reg_operand" "+a")
(const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))
- (set (match_operand:QI 0 "addr_reg_operand" "+a")
+ (set (match_dup 0)
(plus:QI (match_dup 0)
(const_int -1)))
(clobber (reg:CC_NOOV 21))])]
@@ -6246,27 +6215,31 @@
; Peepholes to convert 'call label; rets' into jump label
;
(define_peephole
- [(parallel [(call (match_operand:QI 0 "call_operand" "T,!o")
+ [(parallel [(call (mem:QI (match_operand:QI 0 "call_operand" ""))
(match_operand:QI 1 "general_operand" ""))
(clobber (reg:QI 31))])
(return)]
"c4x_null_epilogue_p ()"
- "@
- br%#\\t%C0
- bu%#\\t%R0"
- [(set_attr "type" "jump,jump")])
+ "*
+ if (GET_CODE (XEXP (operands[0], 0)) == REG)
+ return \"bu%#\\t%C0\";
+ else
+ return \"br%#\\t%C0\";"
+ [(set_attr "type" "jump")])
(define_peephole
[(parallel [(set (match_operand 0 "" "")
- (call (match_operand:QI 1 "call_operand" "T,!o")
+ (call (mem:QI (match_operand:QI 1 "call_operand" ""))
(match_operand:QI 2 "general_operand" "")))
(clobber (reg:QI 31))])
(return)]
"c4x_null_epilogue_p ()"
- "@
- br%#\\t%C1
- bu%#\\t%R1"
- [(set_attr "type" "jump,jump")])
+ "*
+ if (GET_CODE (XEXP (operands[1], 0)) == REG)
+ return \"bu%#\\t%C1\";
+ else
+ return \"br%#\\t%C1\";"
+ [(set_attr "type" "jump")])
;
; Peepholes for parallel instructions