}
+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;
return c4x_emit_libcall (name, code, mode, mode, 3, operands);
}
+
void
c4x_emit_libcall_mulhi (name, code, mode, operands)
char *name;
enum reg_class
c4x_preferred_reload_class (x, class)
- rtx x;
+ rtx x ATTRIBUTE_UNUSED;
enum reg_class class;
{
return class;
}
+/* 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;
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))
{
}
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
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;
}
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:
{
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);
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)
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:
{
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))
{
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. */
}
}
-
+/* 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
{
&& (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.
/* 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;
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
is empty. */
if (GET_CODE (insn) == JUMP_INSN)
return 1;
- insn = PREV_INSN (insn);
+ insn = previous_insn (insn);
}
return 0;
}
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))
{
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;
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;
}
}
}
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;
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;
}
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);
}
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));
}
{
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));
}
{
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));
}
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));
}
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));
}
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));
}
return IS_DISP8_CONST (INTVAL (op1));
}
break;
+
default:
break;
}
}
-/* Symbol ref. */
+/* Direct memory operand. */
int
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;
return register_operand (op, mode);
}
+
int
reg_imm_operand (op, mode)
rtx op;
return 0;
}
+
int
not_modify_reg (op, mode)
rtx op;
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:
return 0;
}
+
int
not_rc_reg (op, mode)
rtx op;
return 1;
}
+
/* Extended precision register R0-R1. */
int
rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
- if (GET_CODE (op) != MEM)
- return 0;
op = XEXP (op, 0);
switch (GET_CODE (op))
{
}
+/* 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
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);
}
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);
}
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);
}
break;
default:
- fatal ("c4x_valid_operands: Internal error");
+ fatal_insn ("c4x_valid_operands: Internal error", op2);
break;
}
{
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:
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;
}
/* 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))
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))
else
abort ();
}
+
;
; 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.
; 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
; 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
; { 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
"* 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
;
; 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\";
; 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)))]
""
(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))]
; 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"))]
; ""
; 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")
(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"
(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"))]
""
(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)))]
(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"
(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"))]
""
(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)))]
(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))]
""
(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"
(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"))]
""
(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)))]
(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)"
"@
(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)"
(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)))]
(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
(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
(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)"
(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)"
"@
(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)"
(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)))]
(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)
(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)"
(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)
(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)"
"*
(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)"
(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)
(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)"
(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)"
(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)"
(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)"
"@
[(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)
(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)"
"@
(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
(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
(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))]
(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)))
(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)))
(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))]
(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)))
(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)))]
[(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)
(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)))]
(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"
;(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"
(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"))]
""
(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))]
(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"
(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"))]
""
(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)))]
(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"
(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"))]
""
(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)))]
;
(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"
(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))
(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"
;
(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"
(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"
"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" "")
;
(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"
;
(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"
;
(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"
(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)"
"@
(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)"
(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)
(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)"
"@
(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)"
(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)
(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)"
"@
(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)"
(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)
(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
(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
[(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
[(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
[(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
[(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
; 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))])]
""
(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"))
[(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")])
(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"
(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"
[(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
; 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)"
"#"
(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))]
""
"#"
(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))
(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))
(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))]
""
"#"
; 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))
(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))])]
(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))])]
; 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