Commit 50c33087 by Michael Hayes Committed by Michael Hayes

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
parent 4c1d5c87
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.
......
......@@ -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 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)
/* 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:
/* 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 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:
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;
addr = eliminate_constant_term (addr, &offset);
if (GET_CODE (addr) == LABEL_REF)
op1 = eliminate_constant_term (op1, &offset);
/* ??? These costs need rethinking... */
if (GET_CODE (op1) == LABEL_REF)
return 3;
if (GET_CODE (addr) != SYMBOL_REF)
if (GET_CODE (op1) != 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;
case SYMBOL_REF:
case LABEL_REF:
return TARGET_SMALL ? 3 : 4;
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 (REGNO (op0) == DP_REGNO)
if (REG_P (op0))
{
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, "@");
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))
{
op = XEXP (op, 1);
}
else if ((GET_CODE (op) == PLUS)
&& (GET_CODE (XEXP (op, 0)) == PLUS)
&& (GET_CODE (XEXP (XEXP (op, 0), 0)) == USE))
if (GET_CODE (op) != LO_SUM)
{
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 ();
}
......@@ -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
......@@ -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 ();
......
......@@ -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,11 +3136,10 @@
(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")])
......@@ -3126,6 +3147,7 @@
; 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))
(parallel [(set (reg:CC 21)
......@@ -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"))))
[(parallel [(set (reg:CC 21)
(compare:CC (fix:QI (match_operand:QF 1 "src_operand" "fHm"))
(const_int 0)))
(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))])]
(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\";
return \"laj%U0\\t%C0\";
else
return \"call\\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\";
return \"laj%U1\\t%C1\";
else
return \"call\\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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment