Commit c47b0cb4 by Maxim Kuvyrkov Committed by Maxim Kuvyrkov

predicates.md (movsi_const0_operand, [...]): New predicates.

	* config/m68k/predicates.md (movsi_const0_operand,
	non_symbolic_call_operand): New predicates.

	* config/m68k/constraints.md: (Cs, Ci, C0, Cj, CQ, CW, CZ, CS, Ap, Ac):
	New constraints.
	* doc/md.texi (Constraints for Particular Machines: Motorola 680x0):
	Document constraints N, O, P, R, S, T, Q, U, W, Cs, Ci, C0, Cj, CQ,
	CW, CZ, CS, Ap and Ac.

	* config/m68k/m68k.md (UNSPEC_IB): New constant.
	(constraints.md): New include.
	(cpu, type, type1, opx, opy, opx_type, opy_type, size, opx_access,
	opx_mem, opy_mem, op_mem, guess, split): New attributes.
	(movdf_internal): Name pattern.  Fix to use alternatives.  Add split.
	Specify attributes.
	(pushdi): Add split.
	(tstsi_internal): Name pattern.  Fix to use alternatives.  Specify
	attributes.  Split tstsi_internal_68020_cf from it.
	(tstsi_internal_68020_cf): New pattern.
	(tsthi_internal, tstqi_internal): Name pattern.  Specify attributes.
	(tst<mode>_cf): Specify attributea.
	(cmpsi_cf): Name pattern.  Specify attributes.
	(cmp<mode>_68881, cmp<mode>_cf): Specify type attribute.
	(pushexthisi_const): Fix to use alternatives.  Specify
	attributes.
	(movsi_const0): Split movsi_const0_68000_10 and movsi_const0_68040_60
	from it.  Fix to use alternatives.  Specify attributes.
	(movsi_const0_68040_10, movsi_const0_68040_60): New patterns.
	(movsi_cf, movstrictqi_cf): Fix to use alternatives.  Specify
	attributes.
	(movsf_cf_soft): Specify attributes.
	(movdf_cf_soft): Add split.
	(pushasi, zero_extendhisi2_cf, zero_extendqisi2_cfv4,
	cfv4_extendhisi2, 68k_extendhisi2, extendqihi2, cfv4_extendqisi2,
	68k_extendqisi2, truncdfsf2_cf): Specify attributes.
	(truncdfsf2_68881): Name pattern.  Specify attributes.
	(floatsi<mode>2_cf, floathi<mode>2_68881, floathi<mode>2_cf,
	floatqi<mode>2_68881, floatqi<mode>2_cf, ftrunc<mode>2_cf,
	fix<mode>qi2_cf, fix<mode>hi2_cf, fix<mode>si2_cf, adddi_dishl32):
	Specify attributes.
	(addsi3_5200): Fix to use alternatives.  Specify attributes.
	Add splits.
	(add<mode>3_cf, subdi_dishl32): Specify attributes.
	(subsi3): Add alternative for subq.l.  Specify attributes.
	(sub<mode>3_cf, mulhi3, mulhisi3): Specify attributes.
	(mulhisisi3_s, mulsi3_68020, mulsi3_cf): Name pattern.  Specify
	attributes.
	(umulhisi3): Specify attributes.
	(mulhisisi3_z): Name pattern.  Specify attributes.
	(fmul<mode>3_cf, div<mode>3_cf, negsi2_internal, negsi2_5200,
	sqrt<mode>2_68881, clzsi2, one_cmplsi2_5200, subreghi1ashrdi_const32,
	subregsi1ashrdi_const32, ashrsi3, subreg1lshrdi_const32, lshrsi3,
	bsetmemqi): Specify attributes.
	(bsetmemqi_ext): Name pattern.  Specify attributes.
	(bclrmemqi): Specify attributes.
	(bclrmemqi_ext, scc, sls): Name pattern.  Specify attributes.
	(beq, bne, bgt, bgtu, blt, bltu, bge, bgeu, ble, bleu): Specify
	attributes.
	(beq2, bne2, bgt2, bgtu2, blt2, bltu2, bge2, bgeu2, ble2, bleu2): Name
	pattern.  Specify attributes.
	(jump): Specify attributes.
	(tablejump_internal): Name pattern.  Specify attributes.
	(call_value): Split into non_symbolic_call_value,
	symbolic_call_value_jsr, symbolic_call_value_bsr.  Fix to use
	alternatives.  Specify attributes.
	(non_symbolic_call_value, symbolic_call_value_jsr,
	symbolic_call_value_bsr): New patterns.
	(nop, return, unlink, indirect_jump): Specify attributes.
	(trap): Fix condition.  Specify attributes.
	(ib): New pattern.

	* config/m68k/m68k.c (m68k_symbolic_call_var): New variable.
	(override_options): Initialize it.  Initialize m68k_sched_cpu.
	(CONST_METHOD): Rename to M68K_CONST_METHOD, move to m68k.h.
	(const_method): Make global, rename to m68k_const_method.
	(const_int_cost, output_move_const_into_data_reg): Update.
	(output_move_double): Parametrize to emit rtl code, rename to
	handle_move_double.
	(output_reg_adjust, emit_reg_adjust, output_compadr, output_movsi,
	emit_movsi): New static functions.
	(output_move_double): New function with semantics of old
	output_move_double.
	(m68k_emit_move_double): New function.
	(m68k_sched_cpu): New variable.
	(attr_op_type): New enum.
	(sched_guess_p): New variable.
	(sched_address_type, sched_operand_type, sched_attr_op_type):
	New static functions.
	(m68k_sched_attr_opx_type, m68k_sched_attr_opy_type,
	m68k_sched_attr_size, m68k_sched_attr_op_mem): New functions.
	(sched_branch_type): New static variable.
	(m68k_sched_branch_type): New function.
	* config/m68k/m68k.h (M68K_SYMBOLIC_CALL): New enum.
	(m68k_symbolic_call_var): Declare.
	(M68K_CONST_METHOD): Rename from CONST_METHOD.  Move here from m68k.c.
	(m68k_const_method, m68k_emit_move_double, m68k_sched_cpu,
	m68k_sched_attr_opx_type, m68k_sched_attr_opy_type,
	m68k_sched_attr_size, m68k_sched_attr_op_mem, m68k_sched_branch_type):
	Declare.

From-SVN: r128377
parent ab0e176c
2007-09-11 Maxim Kuvyrkov <maxim@codesourcery.com>
* config/m68k/predicates.md (movsi_const0_operand,
non_symbolic_call_operand): New predicates.
* config/m68k/constraints.md: (Cs, Ci, C0, Cj, CQ, CW, CZ, CS, Ap, Ac):
New constraints.
* doc/md.texi (Constraints for Particular Machines: Motorola 680x0):
Document constraints N, O, P, R, S, T, Q, U, W, Cs, Ci, C0, Cj, CQ,
CW, CZ, CS, Ap and Ac.
* config/m68k/m68k.md (UNSPEC_IB): New constant.
(constraints.md): New include.
(cpu, type, type1, opx, opy, opx_type, opy_type, size, opx_access,
opx_mem, opy_mem, op_mem, guess, split): New attributes.
(movdf_internal): Name pattern. Fix to use alternatives. Add split.
Specify attributes.
(pushdi): Add split.
(tstsi_internal): Name pattern. Fix to use alternatives. Specify
attributes. Split tstsi_internal_68020_cf from it.
(tstsi_internal_68020_cf): New pattern.
(tsthi_internal, tstqi_internal): Name pattern. Specify attributes.
(tst<mode>_cf): Specify attributea.
(cmpsi_cf): Name pattern. Specify attributes.
(cmp<mode>_68881, cmp<mode>_cf): Specify type attribute.
(pushexthisi_const): Fix to use alternatives. Specify
attributes.
(movsi_const0): Split movsi_const0_68000_10 and movsi_const0_68040_60
from it. Fix to use alternatives. Specify attributes.
(movsi_const0_68040_10, movsi_const0_68040_60): New patterns.
(movsi_cf, movstrictqi_cf): Fix to use alternatives. Specify
attributes.
(movsf_cf_soft): Specify attributes.
(movdf_cf_soft): Add split.
(pushasi, zero_extendhisi2_cf, zero_extendqisi2_cfv4,
cfv4_extendhisi2, 68k_extendhisi2, extendqihi2, cfv4_extendqisi2,
68k_extendqisi2, truncdfsf2_cf): Specify attributes.
(truncdfsf2_68881): Name pattern. Specify attributes.
(floatsi<mode>2_cf, floathi<mode>2_68881, floathi<mode>2_cf,
floatqi<mode>2_68881, floatqi<mode>2_cf, ftrunc<mode>2_cf,
fix<mode>qi2_cf, fix<mode>hi2_cf, fix<mode>si2_cf, adddi_dishl32):
Specify attributes.
(addsi3_5200): Fix to use alternatives. Specify attributes.
Add splits.
(add<mode>3_cf, subdi_dishl32): Specify attributes.
(subsi3): Add alternative for subq.l. Specify attributes.
(sub<mode>3_cf, mulhi3, mulhisi3): Specify attributes.
(mulhisisi3_s, mulsi3_68020, mulsi3_cf): Name pattern. Specify
attributes.
(umulhisi3): Specify attributes.
(mulhisisi3_z): Name pattern. Specify attributes.
(fmul<mode>3_cf, div<mode>3_cf, negsi2_internal, negsi2_5200,
sqrt<mode>2_68881, clzsi2, one_cmplsi2_5200, subreghi1ashrdi_const32,
subregsi1ashrdi_const32, ashrsi3, subreg1lshrdi_const32, lshrsi3,
bsetmemqi): Specify attributes.
(bsetmemqi_ext): Name pattern. Specify attributes.
(bclrmemqi): Specify attributes.
(bclrmemqi_ext, scc, sls): Name pattern. Specify attributes.
(beq, bne, bgt, bgtu, blt, bltu, bge, bgeu, ble, bleu): Specify
attributes.
(beq2, bne2, bgt2, bgtu2, blt2, bltu2, bge2, bgeu2, ble2, bleu2): Name
pattern. Specify attributes.
(jump): Specify attributes.
(tablejump_internal): Name pattern. Specify attributes.
(call_value): Split into non_symbolic_call_value,
symbolic_call_value_jsr, symbolic_call_value_bsr. Fix to use
alternatives. Specify attributes.
(non_symbolic_call_value, symbolic_call_value_jsr,
symbolic_call_value_bsr): New patterns.
(nop, return, unlink, indirect_jump): Specify attributes.
(trap): Fix condition. Specify attributes.
(ib): New pattern.
* config/m68k/m68k.c (m68k_symbolic_call_var): New variable.
(override_options): Initialize it. Initialize m68k_sched_cpu.
(CONST_METHOD): Rename to M68K_CONST_METHOD, move to m68k.h.
(const_method): Make global, rename to m68k_const_method.
(const_int_cost, output_move_const_into_data_reg): Update.
(output_move_double): Parametrize to emit rtl code, rename to
handle_move_double.
(output_reg_adjust, emit_reg_adjust, output_compadr, output_movsi,
emit_movsi): New static functions.
(output_move_double): New function with semantics of old
output_move_double.
(m68k_emit_move_double): New function.
(m68k_sched_cpu): New variable.
(attr_op_type): New enum.
(sched_guess_p): New variable.
(sched_address_type, sched_operand_type, sched_attr_op_type):
New static functions.
(m68k_sched_attr_opx_type, m68k_sched_attr_opy_type,
m68k_sched_attr_size, m68k_sched_attr_op_mem): New functions.
(sched_branch_type): New static variable.
(m68k_sched_branch_type): New function.
* config/m68k/m68k.h (M68K_SYMBOLIC_CALL): New enum.
(m68k_symbolic_call_var): Declare.
(M68K_CONST_METHOD): Rename from CONST_METHOD. Move here from m68k.c.
(m68k_const_method, m68k_emit_move_double, m68k_sched_cpu,
m68k_sched_attr_opx_type, m68k_sched_attr_opy_type,
m68k_sched_attr_size, m68k_sched_attr_op_mem, m68k_sched_branch_type):
Declare.
2007-09-11 Jakub Jelinek <jakub@redhat.com> 2007-09-11 Jakub Jelinek <jakub@redhat.com>
* builtins.def (BUILT_IN_VA_ARG_PACK_LEN): New builtin. * builtins.def (BUILT_IN_VA_ARG_PACK_LEN): New builtin.
...@@ -104,3 +104,51 @@ ...@@ -104,3 +104,51 @@
(define_constraint "W" (define_constraint "W"
"Used for const_call_operands." "Used for const_call_operands."
(match_operand 0 "const_call_operand")) (match_operand 0 "const_call_operand"))
(define_constraint "Cs"
"symbol_ref or const."
(match_code "symbol_ref,const"))
(define_constraint "Ci"
"const_int."
(and (match_code "const_int")
(match_test "true")))
(define_constraint "C0"
"const_int 0."
(and (match_code "const_int")
(match_test "ival == 0")))
(define_constraint "Cj"
"Range of signed numbers that don't fit in 16 bits."
(and (match_code "const_int")
(match_test "ival < -0x8000 || ival > 0x7FFF")))
(define_constraint "CQ"
"Integers valid for mvq."
(and (match_code "const_int")
(match_test "m68k_const_method (ival) == MOVQ")))
(define_constraint "CW"
"Integers valid for a moveq followed by a swap."
(and (match_code "const_int")
(match_test "m68k_const_method (ival) == SWAP")))
(define_constraint "CZ"
"Integers valid for mvz."
(and (match_code "const_int")
(match_test "m68k_const_method (ival) == MVZ")))
(define_constraint "CS"
"Integers valid for mvs."
(and (match_code "const_int")
(match_test "m68k_const_method (ival) == MVS")))
(define_constraint "Ap"
"push_operand."
(match_operand 0 "push_operand"))
(define_constraint "Ac"
"Non-register operands allowed in clr."
(and (match_operand 0 "movsi_const0_operand")
(match_test "!REG_P (op)")))
...@@ -353,6 +353,10 @@ unsigned int m68k_cpu_flags; ...@@ -353,6 +353,10 @@ unsigned int m68k_cpu_flags;
in operand 0. */ in operand 0. */
const char *m68k_symbolic_call; const char *m68k_symbolic_call;
const char *m68k_symbolic_jump; const char *m68k_symbolic_jump;
/* Enum variable that corresponds to m68k_symbolic_call values. */
enum M68K_SYMBOLIC_CALL m68k_symbolic_call_var;
/* See whether TABLE has an entry with name NAME. Return true and /* See whether TABLE has an entry with name NAME. Return true and
store the entry in *ENTRY if so, otherwise return false and store the entry in *ENTRY if so, otherwise return false and
...@@ -563,11 +567,11 @@ override_options (void) ...@@ -563,11 +567,11 @@ override_options (void)
if (!flag_pic) if (!flag_pic)
{ {
m68k_symbolic_call_var = M68K_SYMBOLIC_CALL_JSR;
#if MOTOROLA && !defined (USE_GAS) #if MOTOROLA && !defined (USE_GAS)
m68k_symbolic_call = "jsr %a0";
m68k_symbolic_jump = "jmp %a0"; m68k_symbolic_jump = "jmp %a0";
#else #else
m68k_symbolic_call = "jbsr %a0";
m68k_symbolic_jump = "jra %a0"; m68k_symbolic_jump = "jra %a0";
#endif #endif
} }
...@@ -577,15 +581,10 @@ override_options (void) ...@@ -577,15 +581,10 @@ override_options (void)
else if (TARGET_68020 || TARGET_ISAB || TARGET_ISAC) else if (TARGET_68020 || TARGET_ISAB || TARGET_ISAC)
{ {
if (TARGET_PCREL) if (TARGET_PCREL)
m68k_symbolic_call = "bsr.l %c0"; m68k_symbolic_call_var = M68K_SYMBOLIC_CALL_BSR_C;
else else
{ m68k_symbolic_call_var = M68K_SYMBOLIC_CALL_BSR_P;
#if defined(USE_GAS)
m68k_symbolic_call = "bsr.l %p0";
#else
m68k_symbolic_call = "bsr %p0";
#endif
}
if (TARGET_ISAC) if (TARGET_ISAC)
/* No unconditional long branch */; /* No unconditional long branch */;
else if (TARGET_PCREL) else if (TARGET_PCREL)
...@@ -605,7 +604,48 @@ override_options (void) ...@@ -605,7 +604,48 @@ override_options (void)
flag_no_function_cse = 1; flag_no_function_cse = 1;
} }
switch (m68k_symbolic_call_var)
{
case M68K_SYMBOLIC_CALL_JSR:
#if MOTOROLA && !defined (USE_GAS)
m68k_symbolic_call = "jsr %a0";
#else
m68k_symbolic_call = "jbsr %a0";
#endif
break;
case M68K_SYMBOLIC_CALL_BSR_C:
m68k_symbolic_call = "bsr.l %c0";
break;
case M68K_SYMBOLIC_CALL_BSR_P:
#if defined(USE_GAS)
m68k_symbolic_call = "bsr.l %p0";
#else
m68k_symbolic_call = "bsr %p0";
#endif
break;
case M68K_SYMBOLIC_CALL_NONE:
gcc_assert (m68k_symbolic_call == NULL);
break;
default:
gcc_unreachable ();
}
SUBTARGET_OVERRIDE_OPTIONS; SUBTARGET_OVERRIDE_OPTIONS;
/* Setup scheduling options. */
if (TUNE_CFV2)
m68k_sched_cpu = CPU_CF_V2;
else
{
m68k_sched_cpu = CPU_UNKNOWN;
flag_schedule_insns = 0;
flag_schedule_insns_after_reload = 0;
flag_modulo_sched = 0;
}
} }
/* Generate a macro of the form __mPREFIX_cpu_NAME, where PREFIX is the /* Generate a macro of the form __mPREFIX_cpu_NAME, where PREFIX is the
...@@ -2037,14 +2077,13 @@ legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED, ...@@ -2037,14 +2077,13 @@ legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
} }
typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ, MVS, MVZ } CONST_METHOD;
#define USE_MOVQ(i) ((unsigned) ((i) + 128) <= 255) #define USE_MOVQ(i) ((unsigned) ((i) + 128) <= 255)
/* Return the type of move that should be used for integer I. */ /* Return the type of move that should be used for integer I. */
static CONST_METHOD M68K_CONST_METHOD
const_method (HOST_WIDE_INT i) m68k_const_method (HOST_WIDE_INT i)
{ {
unsigned u; unsigned u;
...@@ -2090,7 +2129,7 @@ const_method (HOST_WIDE_INT i) ...@@ -2090,7 +2129,7 @@ const_method (HOST_WIDE_INT i)
static int static int
const_int_cost (HOST_WIDE_INT i) const_int_cost (HOST_WIDE_INT i)
{ {
switch (const_method (i)) switch (m68k_const_method (i))
{ {
case MOVQ: case MOVQ:
/* Constants between -128 and 127 are cheap due to moveq. */ /* Constants between -128 and 127 are cheap due to moveq. */
...@@ -2254,7 +2293,7 @@ output_move_const_into_data_reg (rtx *operands) ...@@ -2254,7 +2293,7 @@ output_move_const_into_data_reg (rtx *operands)
HOST_WIDE_INT i; HOST_WIDE_INT i;
i = INTVAL (operands[1]); i = INTVAL (operands[1]);
switch (const_method (i)) switch (m68k_const_method (i))
{ {
case MVZ: case MVZ:
return "mvzw %1,%0"; return "mvzw %1,%0";
...@@ -2478,11 +2517,18 @@ singlemove_string (rtx *operands) ...@@ -2478,11 +2517,18 @@ singlemove_string (rtx *operands)
} }
/* Output assembler code to perform a doubleword move insn /* Output assembler or rtl code to perform a doubleword move insn
with operands OPERANDS. */ with operands OPERANDS.
Pointers to 3 helper functions should be specified:
HANDLE_REG_ADJUST to adjust a register by a small value,
HANDLE_COMPADR to compute an address and
HANDLE_MOVSI to move 4 bytes. */
const char * static void
output_move_double (rtx *operands) handle_move_double (rtx operands[2],
void (*handle_reg_adjust) (rtx, int),
void (*handle_compadr) (rtx [2]),
void (*handle_movsi) (rtx [2]))
{ {
enum enum
{ {
...@@ -2540,10 +2586,9 @@ output_move_double (rtx *operands) ...@@ -2540,10 +2586,9 @@ output_move_double (rtx *operands)
if (optype0 == PUSHOP && optype1 == POPOP) if (optype0 == PUSHOP && optype1 == POPOP)
{ {
operands[0] = XEXP (XEXP (operands[0], 0), 0); operands[0] = XEXP (XEXP (operands[0], 0), 0);
if (size == 12)
output_asm_insn ("sub%.l #12,%0", operands); handle_reg_adjust (operands[0], -size);
else
output_asm_insn ("subq%.l #8,%0", operands);
if (GET_MODE (operands[1]) == XFmode) if (GET_MODE (operands[1]) == XFmode)
operands[0] = gen_rtx_MEM (XFmode, operands[0]); operands[0] = gen_rtx_MEM (XFmode, operands[0]);
else if (GET_MODE (operands[0]) == DFmode) else if (GET_MODE (operands[0]) == DFmode)
...@@ -2555,10 +2600,9 @@ output_move_double (rtx *operands) ...@@ -2555,10 +2600,9 @@ output_move_double (rtx *operands)
if (optype0 == POPOP && optype1 == PUSHOP) if (optype0 == POPOP && optype1 == PUSHOP)
{ {
operands[1] = XEXP (XEXP (operands[1], 0), 0); operands[1] = XEXP (XEXP (operands[1], 0), 0);
if (size == 12)
output_asm_insn ("sub%.l #12,%1", operands); handle_reg_adjust (operands[1], -size);
else
output_asm_insn ("subq%.l #8,%1", operands);
if (GET_MODE (operands[1]) == XFmode) if (GET_MODE (operands[1]) == XFmode)
operands[1] = gen_rtx_MEM (XFmode, operands[1]); operands[1] = gen_rtx_MEM (XFmode, operands[1]);
else if (GET_MODE (operands[1]) == DFmode) else if (GET_MODE (operands[1]) == DFmode)
...@@ -2600,8 +2644,8 @@ output_move_double (rtx *operands) ...@@ -2600,8 +2644,8 @@ output_move_double (rtx *operands)
} }
else else
{ {
middlehalf[0] = operands[0]; middlehalf[0] = adjust_address (operands[0], SImode, 0);
latehalf[0] = operands[0]; latehalf[0] = adjust_address (operands[0], SImode, 0);
} }
if (optype1 == REGOP) if (optype1 == REGOP)
...@@ -2636,8 +2680,8 @@ output_move_double (rtx *operands) ...@@ -2636,8 +2680,8 @@ output_move_double (rtx *operands)
} }
else else
{ {
middlehalf[1] = operands[1]; middlehalf[1] = adjust_address (operands[1], SImode, 0);
latehalf[1] = operands[1]; latehalf[1] = adjust_address (operands[1], SImode, 0);
} }
} }
else else
...@@ -2648,7 +2692,7 @@ output_move_double (rtx *operands) ...@@ -2648,7 +2692,7 @@ output_move_double (rtx *operands)
else if (optype0 == OFFSOP) else if (optype0 == OFFSOP)
latehalf[0] = adjust_address (operands[0], SImode, size - 4); latehalf[0] = adjust_address (operands[0], SImode, size - 4);
else else
latehalf[0] = operands[0]; latehalf[0] = adjust_address (operands[0], SImode, 0);
if (optype1 == REGOP) if (optype1 == REGOP)
latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1); latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
...@@ -2657,7 +2701,7 @@ output_move_double (rtx *operands) ...@@ -2657,7 +2701,7 @@ output_move_double (rtx *operands)
else if (optype1 == CNSTOP) else if (optype1 == CNSTOP)
split_double (operands[1], &operands[1], &latehalf[1]); split_double (operands[1], &operands[1], &latehalf[1]);
else else
latehalf[1] = operands[1]; latehalf[1] = adjust_address (operands[1], SImode, 0);
} }
/* If insn is effectively movd N(sp),-(sp) then we will do the /* If insn is effectively movd N(sp),-(sp) then we will do the
...@@ -2687,8 +2731,9 @@ output_move_double (rtx *operands) ...@@ -2687,8 +2731,9 @@ output_move_double (rtx *operands)
compadr: compadr:
xops[0] = latehalf[0]; xops[0] = latehalf[0];
xops[1] = XEXP (operands[1], 0); xops[1] = XEXP (operands[1], 0);
output_asm_insn ("lea %a1,%0", xops);
if (GET_MODE (operands[1]) == XFmode ) handle_compadr (xops);
if (GET_MODE (operands[1]) == XFmode)
{ {
operands[1] = gen_rtx_MEM (XFmode, latehalf[0]); operands[1] = gen_rtx_MEM (XFmode, latehalf[0]);
middlehalf[1] = adjust_address (operands[1], DImode, size - 8); middlehalf[1] = adjust_address (operands[1], DImode, size - 8);
...@@ -2718,10 +2763,11 @@ output_move_double (rtx *operands) ...@@ -2718,10 +2763,11 @@ output_move_double (rtx *operands)
gcc_assert (!addreg0 && !addreg1); gcc_assert (!addreg0 && !addreg1);
/* Only the middle reg conflicts; simply put it last. */ /* Only the middle reg conflicts; simply put it last. */
output_asm_insn (singlemove_string (operands), operands); handle_movsi (operands);
output_asm_insn (singlemove_string (latehalf), latehalf); handle_movsi (latehalf);
output_asm_insn (singlemove_string (middlehalf), middlehalf); handle_movsi (middlehalf);
return "";
return;
} }
else if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0))) else if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0)))
/* If the low half of dest is mentioned in the source memory /* If the low half of dest is mentioned in the source memory
...@@ -2745,85 +2791,194 @@ output_move_double (rtx *operands) ...@@ -2745,85 +2791,194 @@ output_move_double (rtx *operands)
{ {
/* Make any unoffsettable addresses point at high-numbered word. */ /* Make any unoffsettable addresses point at high-numbered word. */
if (addreg0) if (addreg0)
{ handle_reg_adjust (addreg0, size - 4);
if (size == 12)
output_asm_insn ("addq%.l #8,%0", &addreg0);
else
output_asm_insn ("addq%.l #4,%0", &addreg0);
}
if (addreg1) if (addreg1)
{ handle_reg_adjust (addreg1, size - 4);
if (size == 12)
output_asm_insn ("addq%.l #8,%0", &addreg1);
else
output_asm_insn ("addq%.l #4,%0", &addreg1);
}
/* Do that word. */ /* Do that word. */
output_asm_insn (singlemove_string (latehalf), latehalf); handle_movsi (latehalf);
/* Undo the adds we just did. */ /* Undo the adds we just did. */
if (addreg0) if (addreg0)
output_asm_insn ("subq%.l #4,%0", &addreg0); handle_reg_adjust (addreg0, -4);
if (addreg1) if (addreg1)
output_asm_insn ("subq%.l #4,%0", &addreg1); handle_reg_adjust (addreg1, -4);
if (size == 12) if (size == 12)
{ {
output_asm_insn (singlemove_string (middlehalf), middlehalf); handle_movsi (middlehalf);
if (addreg0) if (addreg0)
output_asm_insn ("subq%.l #4,%0", &addreg0); handle_reg_adjust (addreg0, -4);
if (addreg1) if (addreg1)
output_asm_insn ("subq%.l #4,%0", &addreg1); handle_reg_adjust (addreg1, -4);
} }
/* Do low-numbered word. */ /* Do low-numbered word. */
return singlemove_string (operands);
handle_movsi (operands);
return;
} }
/* Normal case: do the two words, low-numbered first. */ /* Normal case: do the two words, low-numbered first. */
output_asm_insn (singlemove_string (operands), operands); handle_movsi (operands);
/* Do the middle one of the three words for long double */ /* Do the middle one of the three words for long double */
if (size == 12) if (size == 12)
{ {
if (addreg0) if (addreg0)
output_asm_insn ("addq%.l #4,%0", &addreg0); handle_reg_adjust (addreg0, 4);
if (addreg1) if (addreg1)
output_asm_insn ("addq%.l #4,%0", &addreg1); handle_reg_adjust (addreg1, 4);
output_asm_insn (singlemove_string (middlehalf), middlehalf); handle_movsi (middlehalf);
} }
/* Make any unoffsettable addresses point at high-numbered word. */ /* Make any unoffsettable addresses point at high-numbered word. */
if (addreg0) if (addreg0)
output_asm_insn ("addq%.l #4,%0", &addreg0); handle_reg_adjust (addreg0, 4);
if (addreg1) if (addreg1)
output_asm_insn ("addq%.l #4,%0", &addreg1); handle_reg_adjust (addreg1, 4);
/* Do that word. */ /* Do that word. */
output_asm_insn (singlemove_string (latehalf), latehalf); handle_movsi (latehalf);
/* Undo the adds we just did. */ /* Undo the adds we just did. */
if (addreg0) if (addreg0)
handle_reg_adjust (addreg0, -(size - 4));
if (addreg1)
handle_reg_adjust (addreg1, -(size - 4));
return;
}
/* Output assembler code to adjust REG by N. */
static void
output_reg_adjust (rtx reg, int n)
{
const char *s;
gcc_assert (GET_MODE (reg) == SImode
&& -12 <= n && n != 0 && n <= 12);
switch (n)
{ {
if (size == 12) case 12:
output_asm_insn ("subq%.l #8,%0", &addreg0); s = "add%.l #12,%0";
else break;
output_asm_insn ("subq%.l #4,%0", &addreg0);
case 8:
s = "addq%.l #8,%0";
break;
case 4:
s = "addq%.l #4,%0";
break;
case -12:
s = "sub%.l #12,%0";
break;
case -8:
s = "subq%.l #8,%0";
break;
case -4:
s = "subq%.l #4,%0";
break;
default:
gcc_unreachable ();
s = NULL;
} }
if (addreg1)
output_asm_insn (s, &reg);
}
/* Emit rtl code to adjust REG by N. */
static void
emit_reg_adjust (rtx reg1, int n)
{
rtx reg2;
gcc_assert (GET_MODE (reg1) == SImode
&& -12 <= n && n != 0 && n <= 12);
reg1 = copy_rtx (reg1);
reg2 = copy_rtx (reg1);
if (n < 0)
emit_insn (gen_subsi3 (reg1, reg2, GEN_INT (-n)));
else if (n > 0)
emit_insn (gen_addsi3 (reg1, reg2, GEN_INT (n)));
else
gcc_unreachable ();
}
/* Output assembler to load address OPERANDS[0] to register OPERANDS[1]. */
static void
output_compadr (rtx operands[2])
{
output_asm_insn ("lea %a1,%0", operands);
}
/* Output the best assembler insn for moving operands[1] into operands[0]
as a fullword. */
static void
output_movsi (rtx operands[2])
{
output_asm_insn (singlemove_string (operands), operands);
}
/* Copy OP and change its mode to MODE. */
static rtx
copy_operand (rtx op, enum machine_mode mode)
{
/* ??? This looks really ugly. There must be a better way
to change a mode on the operand. */
if (GET_MODE (op) != VOIDmode)
{ {
if (size == 12) if (REG_P (op))
output_asm_insn ("subq%.l #8,%0", &addreg1); op = gen_rtx_REG (mode, REGNO (op));
else else
output_asm_insn ("subq%.l #4,%0", &addreg1); {
op = copy_rtx (op);
PUT_MODE (op, mode);
}
} }
return op;
}
/* Emit rtl code for moving operands[1] into operands[0] as a fullword. */
static void
emit_movsi (rtx operands[2])
{
operands[0] = copy_operand (operands[0], SImode);
operands[1] = copy_operand (operands[1], SImode);
emit_insn (gen_movsi (operands[0], operands[1]));
}
/* Output assembler code to perform a doubleword move insn
with operands OPERANDS. */
const char *
output_move_double (rtx *operands)
{
handle_move_double (operands,
output_reg_adjust, output_compadr, output_movsi);
return ""; return "";
} }
/* Output rtl code to perform a doubleword move insn
with operands OPERANDS. */
void
m68k_emit_move_double (rtx operands[2])
{
handle_move_double (operands, emit_reg_adjust, emit_movsi, emit_movsi);
}
/* Ensure mode of ORIG, a REG rtx, is MODE. Returns either ORIG or a /* Ensure mode of ORIG, a REG rtx, is MODE. Returns either ORIG or a
new rtx with the correct mode. */ new rtx with the correct mode. */
...@@ -4432,3 +4587,455 @@ m68k_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED) ...@@ -4432,3 +4587,455 @@ m68k_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
return false; return false;
} }
#endif #endif
/* CPU to schedule the program for. */
enum attr_cpu m68k_sched_cpu;
/* Operand type. */
enum attr_op_type
{
/* No operand. */
OP_TYPE_NONE,
/* Register. */
OP_TYPE_REG,
/* Implicit mem reference (e.g. stack). */
OP_TYPE_MEM1,
/* Memory without offset or indexing. EA modes 2, 3 and 4. */
OP_TYPE_MEM234,
/* Memory with offset but without indexing. EA mode 5. */
OP_TYPE_MEM5,
/* Memory with indexing. EA mode 6. */
OP_TYPE_MEM6,
/* Memory referenced by absolute address. EA mode 7. */
OP_TYPE_MEM7,
/* Immediate operand that doesn't require extension word. */
OP_TYPE_IMM_Q,
/* Immediate 16 bit operand. */
OP_TYPE_IMM_W,
/* Immediate 32 bit operand. */
OP_TYPE_IMM_L
};
/* True if current insn doesn't have complete pipeline description. */
static bool sched_guess_p;
/* Return type of memory ADDR_RTX refers to. */
static enum attr_op_type
sched_address_type (enum machine_mode mode, rtx addr_rtx)
{
struct m68k_address address;
if (!m68k_decompose_address (mode, addr_rtx,
reload_completed, &address))
{
gcc_assert (sched_guess_p);
/* Reload will likely fix the address to be in the register. */
return OP_TYPE_MEM234;
}
if (address.scale != 0)
return OP_TYPE_MEM6;
if (address.base != NULL_RTX)
{
if (address.offset == NULL_RTX)
return OP_TYPE_MEM234;
return OP_TYPE_MEM5;
}
gcc_assert (address.offset != NULL_RTX);
return OP_TYPE_MEM7;
}
/* Return type of the operand OP.
If ADDRESS_P is true, return type of memory location OP refers to. */
static enum attr_op_type
sched_operand_type (rtx op, bool address_p)
{
gcc_assert (op != NULL_RTX);
if (address_p)
return sched_address_type (QImode, op);
if (memory_operand (op, VOIDmode))
return sched_address_type (GET_MODE (op), XEXP (op, 0));
if (register_operand (op, VOIDmode))
return OP_TYPE_REG;
if (GET_CODE (op) == CONST_INT)
{
/* ??? Below condition should probably check if the operation is
signed or unsigned. */
if (IN_RANGE (INTVAL (op), -0x8000, 0x7fff))
return OP_TYPE_IMM_W;
return OP_TYPE_IMM_L;
}
if (GET_CODE (op) == CONST_DOUBLE)
{
switch (GET_MODE (op))
{
case SFmode:
return OP_TYPE_IMM_W;
case VOIDmode:
case DFmode:
return OP_TYPE_IMM_L;
default:
gcc_unreachable ();
}
}
if (symbolic_operand (op, VOIDmode)
|| LABEL_P (op))
{
switch (GET_MODE (op))
{
case QImode:
return OP_TYPE_IMM_Q;
case HImode:
return OP_TYPE_IMM_W;
case SImode:
return OP_TYPE_IMM_L;
default:
if (GET_CODE (op) == SYMBOL_REF)
/* ??? Just a guess. Probably we can guess better using length
attribute of the instructions. */
return OP_TYPE_IMM_W;
return OP_TYPE_IMM_L;
}
}
gcc_assert (sched_guess_p);
return OP_TYPE_REG;
}
/* Return type of INSN's operand X (if OPX_P) or operand Y (if !OPX_P).
If ADDRESS_P is true, return type of memory location operand refers to. */
static enum attr_op_type
sched_attr_op_type (rtx insn, bool opx_p, bool address_p)
{
int i;
extract_constrain_insn_cached (insn);
if (opx_p)
i = get_attr_opx (insn);
else
i = get_attr_opy (insn);
if (i >= recog_data.n_operands)
{
gcc_assert (sched_guess_p);
return OP_TYPE_REG;
}
return sched_operand_type (recog_data.operand[i], address_p);
}
/* Implement opx_type attribute.
Return type of INSN's operand X.
If ADDRESS_P is true, return type of memory location operand refers to. */
enum attr_opx_type
m68k_sched_attr_opx_type (rtx insn, int address_p)
{
sched_guess_p = (get_attr_guess (insn) == GUESS_YES);
switch (sched_attr_op_type (insn, true, address_p != 0))
{
case OP_TYPE_REG:
return OPX_TYPE_REG;
case OP_TYPE_MEM1:
return OPX_TYPE_MEM1;
case OP_TYPE_MEM234:
return OPX_TYPE_MEM234;
case OP_TYPE_MEM5:
return OPX_TYPE_MEM5;
case OP_TYPE_MEM6:
return OPX_TYPE_MEM6;
case OP_TYPE_MEM7:
return OPX_TYPE_MEM7;
case OP_TYPE_IMM_Q:
return OPX_TYPE_IMM_Q;
case OP_TYPE_IMM_W:
return OPX_TYPE_IMM_W;
case OP_TYPE_IMM_L:
return OPX_TYPE_IMM_L;
default:
gcc_unreachable ();
return 0;
}
}
/* Implement opy_type attribute.
Return type of INSN's operand Y.
If ADDRESS_P is true, return type of memory location operand refers to. */
enum attr_opy_type
m68k_sched_attr_opy_type (rtx insn, int address_p)
{
sched_guess_p = (get_attr_guess (insn) == GUESS_YES);
switch (sched_attr_op_type (insn, false, address_p != 0))
{
case OP_TYPE_REG:
return OPY_TYPE_REG;
case OP_TYPE_MEM1:
return OPY_TYPE_MEM1;
case OP_TYPE_MEM234:
return OPY_TYPE_MEM234;
case OP_TYPE_MEM5:
return OPY_TYPE_MEM5;
case OP_TYPE_MEM6:
return OPY_TYPE_MEM6;
case OP_TYPE_MEM7:
return OPY_TYPE_MEM7;
case OP_TYPE_IMM_Q:
return OPY_TYPE_IMM_Q;
case OP_TYPE_IMM_W:
return OPY_TYPE_IMM_W;
case OP_TYPE_IMM_L:
return OPY_TYPE_IMM_L;
default:
gcc_unreachable ();
return 0;
}
}
/* Return the size of INSN. */
int
m68k_sched_attr_size (rtx insn)
{
int size;
sched_guess_p = (get_attr_guess (insn) == GUESS_YES);
switch (get_attr_type1 (insn))
{
case TYPE1_MUL_L:
size = 2;
break;
default:
size = 1;
break;
}
switch (get_attr_opx_type (insn))
{
case OPX_TYPE_NONE:
case OPX_TYPE_REG:
case OPX_TYPE_MEM1:
case OPX_TYPE_MEM234:
case OPY_TYPE_IMM_Q:
break;
case OPX_TYPE_MEM5:
case OPX_TYPE_MEM6:
/* Here we assume that most absolute references are short. */
case OPX_TYPE_MEM7:
case OPY_TYPE_IMM_W:
++size;
break;
case OPY_TYPE_IMM_L:
size += 2;
break;
default:
gcc_unreachable ();
}
switch (get_attr_opy_type (insn))
{
case OPY_TYPE_NONE:
case OPY_TYPE_REG:
case OPY_TYPE_MEM1:
case OPY_TYPE_MEM234:
case OPY_TYPE_IMM_Q:
break;
case OPY_TYPE_MEM5:
case OPY_TYPE_MEM6:
/* Here we assume that most absolute references are short. */
case OPY_TYPE_MEM7:
case OPY_TYPE_IMM_W:
++size;
break;
case OPY_TYPE_IMM_L:
size += 2;
break;
default:
gcc_unreachable ();
}
if (size > 3)
{
gcc_assert (sched_guess_p);
size = 3;
}
return size;
}
/* Implement op_mem attribute. */
enum attr_op_mem
m68k_sched_attr_op_mem (rtx insn)
{
enum attr_opy_mem opy;
enum attr_opx_mem opx;
sched_guess_p = (get_attr_guess (insn) == GUESS_YES);
opy = get_attr_opy_mem (insn);
opx = get_attr_opx_mem (insn);
if (opy == OPY_MEM_R && opx == OPX_MEM_R)
return OP_MEM_00;
if (opy == OPY_MEM_R && opx == OPX_MEM_M)
{
switch (get_attr_opx_access (insn))
{
case OPX_ACCESS_R:
return OP_MEM_10;
case OPX_ACCESS_W:
return OP_MEM_01;
case OPX_ACCESS_RW:
return OP_MEM_11;
default:
gcc_assert (sched_guess_p);
return OP_MEM_UNKNOWN;
}
}
if (opy == OPY_MEM_R && opx == OPX_MEM_I)
{
switch (get_attr_opx_access (insn))
{
case OPX_ACCESS_R:
return OP_MEM_I0;
case OPX_ACCESS_W:
return OP_MEM_0I;
case OPX_ACCESS_RW:
return OP_MEM_I1;
default:
gcc_assert (sched_guess_p);
return OP_MEM_UNKNOWN;
}
}
if (opy == OPY_MEM_M && opx == OPX_MEM_R)
return OP_MEM_10;
if (opy == OPY_MEM_M && opx == OPX_MEM_M)
{
switch (get_attr_opx_access (insn))
{
case OPX_ACCESS_W:
return OP_MEM_11;
default:
gcc_assert (sched_guess_p);
return OP_MEM_UNKNOWN;
}
}
if (opy == OPY_MEM_M && opx == OPX_MEM_I)
{
switch (get_attr_opx_access (insn))
{
case OPX_ACCESS_W:
return OP_MEM_1I;
default:
gcc_assert (sched_guess_p);
return OP_MEM_UNKNOWN;
}
}
if (opy == OPY_MEM_I && opx == OPX_MEM_R)
return OP_MEM_I0;
if (opy == OPY_MEM_I && opx == OPX_MEM_M)
{
switch (get_attr_opx_access (insn))
{
case OPX_ACCESS_W:
return OP_MEM_I1;
default:
gcc_assert (sched_guess_p);
return OP_MEM_UNKNOWN;
}
}
gcc_assert (sched_guess_p);
return OP_MEM_UNKNOWN;
}
/* Jump instructions types. Indexed by INSN_UID.
The same rtl insn can be expanded into different asm instructions
depending on the cc0_status. To properly determine type of jump
instructions we scan instruction stream and map jumps types to this
array. */
static enum attr_type *sched_branch_type;
/* Return the type of the jump insn. */
enum attr_type
m68k_sched_branch_type (rtx insn)
{
enum attr_type type;
type = sched_branch_type[INSN_UID (insn)];
gcc_assert (type != 0);
return type;
}
...@@ -1125,3 +1125,27 @@ extern enum fpu_type m68k_fpu; ...@@ -1125,3 +1125,27 @@ extern enum fpu_type m68k_fpu;
extern unsigned int m68k_cpu_flags; extern unsigned int m68k_cpu_flags;
extern const char *m68k_symbolic_call; extern const char *m68k_symbolic_call;
extern const char *m68k_symbolic_jump; extern const char *m68k_symbolic_jump;
enum M68K_SYMBOLIC_CALL { M68K_SYMBOLIC_CALL_NONE, M68K_SYMBOLIC_CALL_JSR,
M68K_SYMBOLIC_CALL_BSR_C, M68K_SYMBOLIC_CALL_BSR_P };
extern enum M68K_SYMBOLIC_CALL m68k_symbolic_call_var;
/* ??? HOST_WIDE_INT is not being defined for auto-generated files.
Workaround that. */
#ifdef HOST_WIDE_INT
typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ, MVS, MVZ }
M68K_CONST_METHOD;
extern M68K_CONST_METHOD m68k_const_method (HOST_WIDE_INT);
#endif
extern void m68k_emit_move_double (rtx [2]);
extern enum attr_cpu m68k_sched_cpu;
extern enum attr_opx_type m68k_sched_attr_opx_type (rtx, int);
extern enum attr_opy_type m68k_sched_attr_opy_type (rtx, int);
extern int m68k_sched_attr_size (rtx);
extern enum attr_op_mem m68k_sched_attr_op_mem (rtx);
extern enum attr_type m68k_sched_branch_type (rtx);
...@@ -114,6 +114,7 @@ ...@@ -114,6 +114,7 @@
[(UNSPEC_SIN 1) [(UNSPEC_SIN 1)
(UNSPEC_COS 2) (UNSPEC_COS 2)
(UNSPEC_GOT 3) (UNSPEC_GOT 3)
(UNSPEC_IB 4)
]) ])
;; UNSPEC_VOLATILE usage: ;; UNSPEC_VOLATILE usage:
...@@ -136,6 +137,205 @@ ...@@ -136,6 +137,205 @@
(include "predicates.md") (include "predicates.md")
(include "constraints.md") (include "constraints.md")
;; ::::::::::::::::::::
;; ::
;; :: Attributes
;; ::
;; ::::::::::::::::::::
;; Processor type.
(define_attr "cpu" "cf_v2, unknown" (const (symbol_ref "m68k_sched_cpu")))
;; Instruction type.
;; Basically, an asm pattern.
(define_attr "type"
"add_l, addq_l, asr_l, bcc, bclr, bra, bset, bsr,
clr_b, clr_w, clr_l, cmp_l,
ext_w, extb_l, ext_l,
fadd, fcmp, fdiv, ff1, fintrz, fmove, fmul, fsqrt, fsub, ftst, jmp, jsr,
ib,
lea, lsr_l,
move_b, move_w, move_l, moveq_l, mov3q_l, mvs_b, mvs_w, mvz_b, mvz_w,
muls_w, muls_l, mulu_w, mulu_l,
neg_l, nop, not_l,
pea, rts,
scc, sub_l, subq_l,
trap, tst_b, tst_l, tst_w,
unlk, unknown"
(const_string "unknown"))
;; Instruction type for use in scheduling description.
;; _l and _w suffixes indicate size of the operands of instruction.
;; alu - usual arithmetic or logic instruction.
;; alu_reg1 - arithmetic or logic instruction with one operand that is
;; a register.
;; alu_regx - arithmetic or logic instruction which has a register for its
;; X operand.
;; aluq - arithmetic or logic instruction which has a quick immediate (the one
;; that is encoded in the instruction word) for its Y operand.
;; <all other values> - corresponding asm instructions.
(define_attr "type1"
"alu_l, alu_reg1, alu_regx, aluq_l, bcc, bra, bsr, clr, cmp_l, jmp, jsr, lea,
mov3q_l, move, move_l, moveq_l, mul_l, mul_w, pea, rts, tst, tst_l, unlk,
unknown"
(cond [(eq_attr "type" "add_l,sub_l") (const_string "alu_l")
(eq_attr "type" "ext_w,extb_l,ext_l,neg_l,not_l")
(const_string "alu_reg1")
(eq_attr "type" "asr_l,lsr_l") (const_string "alu_regx")
(eq_attr "type" "addq_l,subq_l") (const_string "aluq_l")
(eq_attr "type" "bcc") (const_string "bcc")
(eq_attr "type" "bra") (const_string "bra")
(eq_attr "type" "bsr") (const_string "bsr")
(eq_attr "type" "clr_b,clr_l,clr_w") (const_string "clr")
(eq_attr "type" "cmp_l") (const_string "cmp_l")
(eq_attr "type" "jmp") (const_string "jmp")
(eq_attr "type" "jsr") (const_string "jsr")
(eq_attr "type" "lea") (const_string "lea")
(eq_attr "type" "mov3q_l") (const_string "mov3q_l")
(eq_attr "type" "move_b,move_w") (const_string "move")
(eq_attr "type" "move_l") (const_string "move_l")
(eq_attr "type" "moveq_l") (const_string "moveq_l")
(eq_attr "type" "muls_l,mulu_l") (const_string "mul_l")
(eq_attr "type" "muls_w,mulu_w") (const_string "mul_w")
(eq_attr "type" "pea") (const_string "pea")
(eq_attr "type" "rts") (const_string "rts")
(eq_attr "type" "tst_b,tst_w") (const_string "tst")
(eq_attr "type" "tst_l") (const_string "tst_l")
(eq_attr "type" "unlk") (const_string "unlk")]
(const_string "unknown")))
;; Index of the X or Y operand in recog_data.operand[].
;; Should be used only within opx_type and opy_type.
(define_attr "opx" "" (const_int 0))
(define_attr "opy" "" (const_int 1))
;; Type of the X operand.
;; See m68k.c: enum attr_op_type.
(define_attr "opx_type"
"none, reg, mem1, mem234, mem5, mem6, mem7, imm_q, imm_w, imm_l"
(cond [(eq_attr "type1" "rts,unlk") (const_string "none")
(eq_attr "type1" "alu_reg1,alu_regx,lea,moveq_l,mul_l,mul_w")
(const_string "reg")
(eq_attr "type1" "pea") (const_string "mem1")
(eq_attr "type1" "bcc") (const_string "imm_q")
(eq_attr "type1" "bra,bsr") (const_string "imm_w")
(eq_attr "type1" "jmp,jsr")
(symbol_ref "m68k_sched_attr_opx_type (insn, 1)")]
(symbol_ref "m68k_sched_attr_opx_type (insn, 0)")))
;; Type of the Y operand.
;; See m68k.c: enum attr_op_type.
(define_attr "opy_type"
"none, reg, mem1, mem234, mem5, mem6, mem7, imm_q, imm_w, imm_l"
(cond [(eq_attr "type1" "alu_reg1,bcc,bra,bsr,clr,jmp,jsr,rts,tst,tst_l,
unlk") (const_string "none")
(eq_attr "type1" "mov3q_l,moveq_l,aluq_l") (const_string "imm_q")
(eq_attr "type1" "lea,pea")
(symbol_ref "m68k_sched_attr_opy_type (insn, 1)")]
(symbol_ref "m68k_sched_attr_opy_type (insn, 0)")))
;; Instruction size in words.
(define_attr "size" ""
(cond [(eq_attr "type1" "alu_reg1,moveq_l,rts,unlk") (const_int 1)]
(symbol_ref "m68k_sched_attr_size (insn)")))
;; Access to the X operand: none, read, write, read/write, unknown.
;; Access to the Y operand is either none (if opy_type is none)
;; or read otherwise.
(define_attr "opx_access" "none, r, w, rw, unknown"
(cond [(eq_attr "type1" "rts,unlk") (const_string "none")
(eq_attr "type1" "bcc,bra,bsr,cmp_l,jmp,jsr,tst,tst_l")
(const_string "r")
(eq_attr "type1" "clr,lea,mov3q_l,move,move_l,moveq_l,pea")
(const_string "w")
(eq_attr "type1" "alu_l,alu_reg1,alu_regx,aluq_l")
(const_string "rw")]
(const_string "unknown")))
;; Memory relation of operands:
;; r - register or immediate operand
;; m - non-indexed memory location
;; i - indexed memory location
(define_attr "opx_mem" "r, m, i, unknown"
(cond [(eq_attr "opx_type" "none,reg,imm_q,imm_w,imm_l") (const_string "r")
(eq_attr "opx_type" "mem1,mem234,mem5,mem7") (const_string "m")
(eq_attr "opx_type" "mem6") (const_string "i")]
(const_string "unknown")))
(define_attr "opy_mem" "r, m, i, unknown"
(cond [(eq_attr "opy_type" "none,reg,imm_q,imm_w,imm_l") (const_string "r")
(eq_attr "opy_type" "mem1,mem234,mem5,mem7") (const_string "m")
(eq_attr "opy_type" "mem6") (const_string "i")]
(const_string "unknown")))
;; Memory accesses of the insn.
;; 00 - no memory references
;; 10 - memory is read
;; i10 - indexed memory is read
;; 01 - memory is written
;; 0i1 - indexed memory is written
;; 11 - memory is read, memory is written
;; i11 - indexed memory is read, memory is written
;; 1i1 - memory is read, indexed memory is written
;;
;; unknown - should now occur on normal insn.
;; ??? This attribute is implemented in C to spare genattrtab from
;; ??? optimizing it.
(define_attr "op_mem" "00, 10, i0, 01, 0i, 11, i1, 1i, unknown"
; (cond [(and (eq_attr "opy_mem" "r") (eq_attr "opx_mem" "r"))
; (const_string "00")
;
; (and (eq_attr "opy_mem" "r") (eq_attr "opx_mem" "m"))
; (cond [(eq_attr "opx_access" "r") (const_string "10")
; (eq_attr "opx_access" "w") (const_string "01")
; (eq_attr "opx_access" "rw") (const_string "11")]
; (const_string "unknown"))
;
; (and (eq_attr "opy_mem" "r") (eq_attr "opx_mem" "i"))
; (cond [(eq_attr "opx_access" "r") (const_string "i0")
; (eq_attr "opx_access" "w") (const_string "0i")
; (eq_attr "opx_access" "rw") (const_string "i1")]
; (const_string "unknown"))
;
; (and (eq_attr "opy_mem" "m") (eq_attr "opx_mem" "r"))
; (const_string "10")
;
; (and (eq_attr "opy_mem" "m") (eq_attr "opx_mem" "m"))
; (cond [(eq_attr "opx_access" "w") (const_string "11")]
; (const_string "unknown"))
;
; (and (eq_attr "opy_mem" "m") (eq_attr "opx_mem" "i"))
; (cond [(eq_attr "opx_access" "w") (const_string "1i")]
; (const_string "unknown"))
;
; (and (eq_attr "opy_mem" "i") (eq_attr "opx_mem" "r"))
; (const_string "i0")
;
; (and (eq_attr "opy_mem" "i") (eq_attr "opx_mem" "m"))
; (cond [(eq_attr "opx_access" "w") (const_string "i1")]
; (const_string "unknown"))]
; (const_string "unknown"))
(symbol_ref "m68k_sched_attr_op_mem (insn)"))
;; Attribute to support partial automata description.
;; This attribute has value 'yes' for instructions that are not
;; fully handled yet.
(define_attr "guess" "yes, no"
(cond [(ior (eq (symbol_ref "reload_completed") (const_int 0))
(eq_attr "type1" "unknown"))
(const_string "yes")]
(const_string "no")))
;; Attribute to support statistics gathering.
;; Todo means that insn lacks something to get pipeline description.
;; Done means that insn was transformed to suit pipeline description.
;; Nothing means that insn was originally good enough for scheduling.
(define_attr "split" "todo, done, nothing"
(if_then_else (eq_attr "type" "unknown")
(const_string "todo")
(const_string "nothing")))
;; Mode macros for floating point operations. ;; Mode macros for floating point operations.
;; Valid floating point modes ;; Valid floating point modes
(define_mode_iterator FP [SF DF (XF "TARGET_68881")]) (define_mode_iterator FP [SF DF (XF "TARGET_68881")])
...@@ -150,22 +350,33 @@ ...@@ -150,22 +350,33 @@
;; Allowable 68881 constant constraints ;; Allowable 68881 constant constraints
(define_mode_attr const [(SF "F") (DF "G") (XF "")]) (define_mode_attr const [(SF "F") (DF "G") (XF "")])
(define_insn ""
[(set (match_operand:DF 0 "push_operand" "=m") (define_insn_and_split "*movdf_internal"
(match_operand:DF 1 "general_operand" "ro<>fE"))] [(set (match_operand:DF 0 "push_operand" "=m, m")
(match_operand:DF 1 "general_operand" "f, ro<>E"))]
"" ""
"@
fmove%.d %f1,%0
#"
"&& reload_completed && (extract_constrain_insn_cached (insn), which_alternative == 1)"
[(const_int 0)]
{ {
if (FP_REG_P (operands[1])) m68k_emit_move_double (operands);
return "fmove%.d %f1,%0"; DONE;
return output_move_double (operands); }
}) [(set_attr "type" "fmove,*")
(set_attr "split" "done,*")])
(define_insn "pushdi" (define_insn_and_split "pushdi"
[(set (match_operand:DI 0 "push_operand" "=m") [(set (match_operand:DI 0 "push_operand" "=m")
(match_operand:DI 1 "general_operand" "ro<>Fi"))] (match_operand:DI 1 "general_operand" "ro<>Fi"))]
"" ""
"#"
"&& reload_completed"
[(const_int 0)]
{ {
return output_move_double (operands); m68k_emit_move_double (operands);
DONE;
}) })
;; We don't want to allow a constant operand for test insns because ;; We don't want to allow a constant operand for test insns because
...@@ -194,12 +405,12 @@ ...@@ -194,12 +405,12 @@
xoperands[0] = operands[2]; xoperands[0] = operands[2];
xoperands[1] = operands[0]; xoperands[1] = operands[0];
output_move_double (xoperands); output_move_double (xoperands);
cc_status.flags |= CC_REVERSED; cc_status.flags |= CC_REVERSED; /*|*/
return "neg%.l %R2\;negx%.l %2"; return "neg%.l %R2\;negx%.l %2";
} }
if (find_reg_note (insn, REG_DEAD, operands[0])) if (find_reg_note (insn, REG_DEAD, operands[0]))
{ {
cc_status.flags |= CC_REVERSED; cc_status.flags |= CC_REVERSED; /*|*/
return "neg%.l %R0\;negx%.l %0"; return "neg%.l %R0\;negx%.l %0";
} }
else else
...@@ -217,18 +428,24 @@ ...@@ -217,18 +428,24 @@
"" ""
"m68k_last_compare_had_fp_operands = 0;") "m68k_last_compare_had_fp_operands = 0;")
(define_insn "" ;; If you think that the 68020 does not support tstl a0,
;; reread page B-167 of the 68020 manual more carefully.
(define_insn "*tstsi_internal_68020_cf"
[(set (cc0) [(set (cc0)
(match_operand:SI 0 "nonimmediate_operand" "rm"))] (match_operand:SI 0 "nonimmediate_operand" "rm"))]
"" "TARGET_68020 || TARGET_COLDFIRE"
{ "tst%.l %0"
if (TARGET_68020 || TARGET_COLDFIRE || ! ADDRESS_REG_P (operands[0])) [(set_attr "type" "tst_l")])
return "tst%.l %0";
/* If you think that the 68020 does not support tstl a0, ;; On an address reg, cmpw may replace cmpl.
reread page B-167 of the 68020 manual more carefully. */ (define_insn "*tstsi_internal"
/* On an address reg, cmpw may replace cmpl. */ [(set (cc0)
return "cmp%.w #0,%0"; (match_operand:SI 0 "nonimmediate_operand" "dm,r"))]
}) "!(TARGET_68020 || TARGET_COLDFIRE)"
"@
tst%.l %0
cmp%.w #0,%0"
[(set_attr "type" "tst_l,*")])
;; This can't use an address register, because comparisons ;; This can't use an address register, because comparisons
;; with address registers as second operand always test the whole word. ;; with address registers as second operand always test the whole word.
...@@ -238,11 +455,12 @@ ...@@ -238,11 +455,12 @@
"" ""
"m68k_last_compare_had_fp_operands = 0;") "m68k_last_compare_had_fp_operands = 0;")
(define_insn "" (define_insn "*tsthi_internal"
[(set (cc0) [(set (cc0)
(match_operand:HI 0 "nonimmediate_operand" "dm"))] (match_operand:HI 0 "nonimmediate_operand" "dm"))]
"" ""
"tst%.w %0") "tst%.w %0"
[(set_attr "type" "tst_w")])
(define_expand "tstqi" (define_expand "tstqi"
[(set (cc0) [(set (cc0)
...@@ -250,11 +468,12 @@ ...@@ -250,11 +468,12 @@
"" ""
"m68k_last_compare_had_fp_operands = 0;") "m68k_last_compare_had_fp_operands = 0;")
(define_insn "" (define_insn "*tstqi_internal"
[(set (cc0) [(set (cc0)
(match_operand:QI 0 "nonimmediate_operand" "dm"))] (match_operand:QI 0 "nonimmediate_operand" "dm"))]
"" ""
"tst%.b %0") "tst%.b %0"
[(set_attr "type" "tst_b")])
(define_expand "tst<mode>" (define_expand "tst<mode>"
[(set (cc0) [(set (cc0)
...@@ -284,7 +503,8 @@ ...@@ -284,7 +503,8 @@
if (FP_REG_P (operands[0])) if (FP_REG_P (operands[0]))
return "ftst%.d %0"; return "ftst%.d %0";
return "ftst%.<FP:prec> %0"; return "ftst%.<FP:prec> %0";
}) }
[(set_attr "type" "ftst")])
;; compare instructions. ;; compare instructions.
...@@ -309,7 +529,7 @@ ...@@ -309,7 +529,7 @@
return "sub%.l %R2,%R0\;subx%.l %2,%0"; return "sub%.l %R2,%R0\;subx%.l %2,%0";
else else
{ {
cc_status.flags |= CC_REVERSED; cc_status.flags |= CC_REVERSED; /*|*/
return "sub%.l %R1,%R0\;subx%.l %1,%0"; return "sub%.l %R1,%R0\;subx%.l %1,%0";
} }
}) })
...@@ -335,7 +555,7 @@ ...@@ -335,7 +555,7 @@
if (REG_P (operands[1]) if (REG_P (operands[1])
|| (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
{ {
cc_status.flags |= CC_REVERSED; cc_status.flags |= CC_REVERSED; /*|*/
return "cmp%.l %d0,%d1"; return "cmp%.l %d0,%d1";
} }
if (ADDRESS_REG_P (operands[0]) if (ADDRESS_REG_P (operands[0])
...@@ -346,7 +566,7 @@ ...@@ -346,7 +566,7 @@
return "cmp%.l %d1,%d0"; return "cmp%.l %d1,%d0";
}) })
(define_insn "" (define_insn "*cmpsi_cf"
[(set (cc0) [(set (cc0)
(compare (match_operand:SI 0 "nonimmediate_operand" "mrKs,r") (compare (match_operand:SI 0 "nonimmediate_operand" "mrKs,r")
(match_operand:SI 1 "general_operand" "r,mrKs")))] (match_operand:SI 1 "general_operand" "r,mrKs")))]
...@@ -355,11 +575,12 @@ ...@@ -355,11 +575,12 @@
if (REG_P (operands[1]) if (REG_P (operands[1])
|| (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
{ {
cc_status.flags |= CC_REVERSED; cc_status.flags |= CC_REVERSED; /*|*/
return "cmp%.l %d0,%d1"; return "cmp%.l %d0,%d1";
} }
return "cmp%.l %d1,%d0"; return "cmp%.l %d1,%d0";
}) }
[(set_attr "type" "cmp_l")])
(define_expand "cmphi" (define_expand "cmphi"
[(set (cc0) [(set (cc0)
...@@ -403,7 +624,7 @@ ...@@ -403,7 +624,7 @@
if (REG_P (operands[1]) if (REG_P (operands[1])
|| (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
{ {
cc_status.flags |= CC_REVERSED; cc_status.flags |= CC_REVERSED; /*|*/
return "cmp%.b %d0,%d1"; return "cmp%.b %d0,%d1";
} }
return "cmp%.b %d1,%d0"; return "cmp%.b %d1,%d0";
...@@ -434,9 +655,10 @@ ...@@ -434,9 +655,10 @@
else else
return "fcmp%.<FP:prec> %f1,%0"; return "fcmp%.<FP:prec> %f1,%0";
} }
cc_status.flags |= CC_REVERSED; cc_status.flags |= CC_REVERSED; /*|*/
return "fcmp%.<FP:prec> %f0,%1"; return "fcmp%.<FP:prec> %f0,%1";
}) }
[(set_attr "type" "fcmp")])
(define_insn "cmp<mode>_cf" (define_insn "cmp<mode>_cf"
[(set (cc0) [(set (cc0)
...@@ -452,9 +674,10 @@ ...@@ -452,9 +674,10 @@
else else
return "fcmp%.<FP:prec> %f1,%0"; return "fcmp%.<FP:prec> %f1,%0";
} }
cc_status.flags |= CC_REVERSED; cc_status.flags |= CC_REVERSED; /*|*/
return "fcmp%.<FP:prec> %f0,%1"; return "fcmp%.<FP:prec> %f0,%1";
}) }
[(set_attr "type" "fcmp")])
;; Recognizers for btst instructions. ;; Recognizers for btst instructions.
...@@ -578,16 +801,15 @@ ...@@ -578,16 +801,15 @@
;; A special case in which it is not desirable ;; A special case in which it is not desirable
;; to reload the constant into a data register. ;; to reload the constant into a data register.
(define_insn "pushexthisi_const" (define_insn "pushexthisi_const"
[(set (match_operand:SI 0 "push_operand" "=m") [(set (match_operand:SI 0 "push_operand" "=m,m,m")
(match_operand:SI 1 "const_int_operand" "J"))] (match_operand:SI 1 "const_int_operand" "C0,R,J"))]
"INTVAL (operands[1]) >= -0x8000 && INTVAL (operands[1]) < 0x8000" "INTVAL (operands[1]) >= -0x8000 && INTVAL (operands[1]) < 0x8000"
{ "@
if (operands[1] == const0_rtx) clr%.l %0
return "clr%.l %0"; mov3q%.l %1,%-
if (valid_mov3q_const (INTVAL (operands[1]))) pea %a1"
return "mov3q%.l %1,%-"; [(set_attr "type" "clr_l,mov3q_l,pea")
return "pea %a1"; (set_attr "split" "done")])
})
;This is never used. ;This is never used.
;(define_insn "swapsi" ;(define_insn "swapsi"
...@@ -597,30 +819,52 @@ ...@@ -597,30 +819,52 @@
; "" ; ""
; "exg %1,%0") ; "exg %1,%0")
;; Special case of fullword move when source is zero. ;; Special case of fullword move when source is zero for 68000_10.
;; The reason this is special is to avoid loading a zero ;; moveq is faster on the 68000.
;; into a data reg with moveq in order to store it elsewhere. (define_insn "*movsi_const0_68000_10"
[(set (match_operand:SI 0 "movsi_const0_operand" "=d,a,g")
(define_insn "movsi_const0" (const_int 0))]
[(set (match_operand:SI 0 "nonimmediate_operand" "=g") "TUNE_68000_10"
"@
moveq #0,%0
sub%.l %0,%0
clr%.l %0"
[(set_attr "type" "moveq_l,sub_l,clr_l")
(set_attr "opy_type" "imm_q,reg,*")
(set_attr "split" "done")])
;; Special case of fullword move when source is zero for 68040_60.
;; On the '040, 'subl an,an' takes 2 clocks while lea takes only 1
(define_insn "*movsi_const0_68040_60"
[(set (match_operand:SI 0 "movsi_const0_operand" "=a,g")
(const_int 0))] (const_int 0))]
;; clr insns on 68000 read before writing. "TUNE_68040_60"
"((TARGET_68010 || TARGET_COLDFIRE)
|| !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))"
{ {
if (ADDRESS_REG_P (operands[0])) if (which_alternative == 0)
return MOTOROLA ? "lea 0.w,%0" : "lea 0:w,%0";
else if (which_alternative == 1)
return "clr%.l %0";
else
{ {
/* On the '040, 'subl an,an' takes 2 clocks while lea takes only 1 */ gcc_unreachable ();
if (TUNE_68040_60) return "";
return MOTOROLA ? "lea 0.w,%0" : "lea 0:w,%0";
else
return "sub%.l %0,%0";
} }
/* moveq is faster on the 68000. */ }
if (DATA_REG_P (operands[0]) && TUNE_68000_10) [(set_attr "type" "lea,clr_l")
return "moveq #0,%0"; (set_attr "opy_type" "imm_w,*")
return "clr%.l %0"; (set_attr "split" "done")])
})
;; Special case of fullword move when source is zero.
(define_insn "*movsi_const0"
[(set (match_operand:SI 0 "movsi_const0_operand" "=a,g")
(const_int 0))]
"!(TUNE_68000_10 || TUNE_68040_60)"
"@
sub%.l %0,%0
clr%.l %0"
[(set_attr "type" "sub_l,clr_l")
(set_attr "opy_type" "reg,*")
(set_attr "split" "done")])
;; General case of fullword move. ;; General case of fullword move.
;; ;;
...@@ -688,10 +932,59 @@ ...@@ -688,10 +932,59 @@
;; ColdFire move instructions can have at most one operand of mode >= 6. ;; ColdFire move instructions can have at most one operand of mode >= 6.
(define_insn "*movsi_cf" (define_insn "*movsi_cf"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r<Q>,g,U") [(set (match_operand:SI 0 "nonimmediate_operand" "=g,d, d, d, d, d, a,Ap, a, r<Q>,g, U")
(match_operand:SI 1 "general_operand" "g,Rr<Q>,U"))] (match_operand:SI 1 "general_operand" " R,CQ,CW,CZ,CS,Ci,J,J Cs,Cs, g, Rr<Q>,U"))]
"TARGET_COLDFIRE" "TARGET_COLDFIRE"
"* return output_move_simode (operands);") {
switch (which_alternative)
{
case 0:
return "mov3q%.l %1,%0";
case 1:
return "moveq %1,%0";
case 2:
{
unsigned u = INTVAL (operands[1]);
operands[1] = GEN_INT ((u << 16) | (u >> 16)); /*|*/
return "moveq %1,%0\n\tswap %0";
}
case 3:
return "mvz%.w %1,%0";
case 4:
return "mvs%.w %1,%0";
case 5:
return "move%.l %1,%0";
case 6:
return "move%.w %1,%0";
case 7:
return "pea %a1";
case 8:
return "lea %a1,%0";
case 9:
case 10:
case 11:
return "move%.l %1,%0";
default:
gcc_unreachable ();
return "";
}
}
[(set_attr "type" "mov3q_l, moveq_l,*, mvz_w, mvs_w, move_l, move_w, pea, lea, move_l, move_l, move_l")
(set (attr "split")
(if_then_else (eq_attr "alternative" "2")
(const_string "*")
(const_string "done")))])
;; Special case of fullword move, where we need to get a non-GOT PIC ;; Special case of fullword move, where we need to get a non-GOT PIC
;; reference into an address register. ;; reference into an address register.
...@@ -771,11 +1064,17 @@ ...@@ -771,11 +1064,17 @@
"!TARGET_COLDFIRE" "!TARGET_COLDFIRE"
"* return output_move_strictqi (operands);") "* return output_move_strictqi (operands);")
(define_insn "" (define_insn "*movstrictqi_cf"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+d,m")) [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+d, Ac, d,m"))
(match_operand:QI 1 "general_src_operand" "dmn,d"))] (match_operand:QI 1 "general_src_operand" "C0,C0, dmn,d"))]
"TARGET_COLDFIRE" "TARGET_COLDFIRE"
"* return output_move_strictqi (operands);") "@
clr%.b %0
clr%.b %0
move%.b %1,%0
move%.b %1,%0"
[(set_attr "type" "clr_b,clr_b,move_b,move_b")
(set_attr "split" "done")])
(define_expand "pushqi1" (define_expand "pushqi1"
[(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -2))) [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -2)))
...@@ -864,9 +1163,8 @@ ...@@ -864,9 +1163,8 @@
[(set (match_operand:SF 0 "nonimmediate_operand" "=r<Q>,g,U") [(set (match_operand:SF 0 "nonimmediate_operand" "=r<Q>,g,U")
(match_operand:SF 1 "general_operand" "g,r<Q>,U"))] (match_operand:SF 1 "general_operand" "g,r<Q>,U"))]
"TARGET_COLDFIRE && !TARGET_COLDFIRE_FPU" "TARGET_COLDFIRE && !TARGET_COLDFIRE_FPU"
{ "move%.l %1,%0"
return "move%.l %1,%0"; [(set_attr "type" "move_l")])
})
;; SFmode MEMs are restricted to modes 2-4 if TARGET_COLDFIRE_FPU. ;; SFmode MEMs are restricted to modes 2-4 if TARGET_COLDFIRE_FPU.
;; The move instructions can handle all combinations. ;; The move instructions can handle all combinations.
...@@ -1003,12 +1301,16 @@ ...@@ -1003,12 +1301,16 @@
return output_move_double (operands); return output_move_double (operands);
}) })
(define_insn "movdf_cf_soft" (define_insn_and_split "movdf_cf_soft"
[(set (match_operand:DF 0 "nonimmediate_operand" "=r,g") [(set (match_operand:DF 0 "nonimmediate_operand" "=r,g")
(match_operand:DF 1 "general_operand" "g,r"))] (match_operand:DF 1 "general_operand" "g,r"))]
"TARGET_COLDFIRE && !TARGET_COLDFIRE_FPU" "TARGET_COLDFIRE && !TARGET_COLDFIRE_FPU"
"#"
"&& reload_completed"
[(const_int 0)]
{ {
return output_move_double (operands); m68k_emit_move_double (operands);
DONE;
}) })
(define_insn "movdf_cf_hard" (define_insn "movdf_cf_hard"
...@@ -1230,7 +1532,8 @@ ...@@ -1230,7 +1532,8 @@
[(set (match_operand:SI 0 "push_operand" "=m") [(set (match_operand:SI 0 "push_operand" "=m")
(match_operand:SI 1 "address_operand" "p"))] (match_operand:SI 1 "address_operand" "p"))]
"" ""
"pea %a1") "pea %a1"
[(set_attr "type" "pea")])
;; truncation instructions ;; truncation instructions
(define_insn "truncsiqi2" (define_insn "truncsiqi2"
...@@ -1391,7 +1694,8 @@ ...@@ -1391,7 +1694,8 @@
[(set (match_operand:SI 0 "register_operand" "=d") [(set (match_operand:SI 0 "register_operand" "=d")
(zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "rmS")))] (zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "rmS")))]
"ISA_HAS_MVS_MVZ" "ISA_HAS_MVS_MVZ"
"mvz%.w %1,%0") "mvz%.w %1,%0"
[(set_attr "type" "mvz_w")])
(define_insn "zero_extendhisi2" (define_insn "zero_extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=d") [(set (match_operand:SI 0 "register_operand" "=d")
...@@ -1415,7 +1719,8 @@ ...@@ -1415,7 +1719,8 @@
[(set (match_operand:SI 0 "register_operand" "=d") [(set (match_operand:SI 0 "register_operand" "=d")
(zero_extend:SI (match_operand:QI 1 "nonimmediate_src_operand" "dmS")))] (zero_extend:SI (match_operand:QI 1 "nonimmediate_src_operand" "dmS")))]
"ISA_HAS_MVS_MVZ" "ISA_HAS_MVS_MVZ"
"mvz%.b %1,%0") "mvz%.b %1,%0"
[(set_attr "type" "mvz_b")])
(define_insn "zero_extendqisi2" (define_insn "zero_extendqisi2"
[(set (match_operand:SI 0 "register_operand" "=d") [(set (match_operand:SI 0 "register_operand" "=d")
...@@ -1567,24 +1872,25 @@ ...@@ -1567,24 +1872,25 @@
(sign_extend:SI (sign_extend:SI
(match_operand:HI 1 "nonimmediate_src_operand" "rmS")))] (match_operand:HI 1 "nonimmediate_src_operand" "rmS")))]
"ISA_HAS_MVS_MVZ" "ISA_HAS_MVS_MVZ"
"mvs%.w %1,%0") "mvs%.w %1,%0"
[(set_attr "type" "mvs_w")])
(define_insn "*68k_extendhisi2" (define_insn "*68k_extendhisi2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=*d,a") [(set (match_operand:SI 0 "nonimmediate_operand" "=*d,a")
(sign_extend:SI (sign_extend:SI
(match_operand:HI 1 "nonimmediate_src_operand" "0,rmS")))] (match_operand:HI 1 "nonimmediate_src_operand" "0,rmS")))]
"!ISA_HAS_MVS_MVZ" "!ISA_HAS_MVS_MVZ"
{ "@
if (ADDRESS_REG_P (operands[0])) ext%.l %0
return "move%.w %1,%0"; move%.w %1,%0"
return "ext%.l %0"; [(set_attr "type" "ext_l,move_w")])
})
(define_insn "extendqihi2" (define_insn "extendqihi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=d") [(set (match_operand:HI 0 "nonimmediate_operand" "=d")
(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0")))] (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0")))]
"" ""
"ext%.w %0") "ext%.w %0"
[(set_attr "type" "ext_w")])
(define_expand "extendqisi2" (define_expand "extendqisi2"
[(set (match_operand:SI 0 "nonimmediate_operand" "") [(set (match_operand:SI 0 "nonimmediate_operand" "")
...@@ -1596,13 +1902,15 @@ ...@@ -1596,13 +1902,15 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=d") [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rms")))] (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rms")))]
"ISA_HAS_MVS_MVZ" "ISA_HAS_MVS_MVZ"
"mvs%.b %1,%0") "mvs%.b %1,%0"
[(set_attr "type" "mvs_b")])
(define_insn "*68k_extendqisi2" (define_insn "*68k_extendqisi2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d") [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0")))] (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0")))]
"TARGET_68020 || (TARGET_COLDFIRE && !ISA_HAS_MVS_MVZ)" "TARGET_68020 || (TARGET_COLDFIRE && !ISA_HAS_MVS_MVZ)"
"extb%.l %0") "extb%.l %0"
[(set_attr "type" "extb_l")])
;; Conversions between float and double. ;; Conversions between float and double.
...@@ -1691,14 +1999,16 @@ ...@@ -1691,14 +1999,16 @@
"TARGET_COLDFIRE_FPU" "TARGET_COLDFIRE_FPU"
"@ "@
fsmove%.d %1,%0 fsmove%.d %1,%0
fmove%.s %1,%0") fmove%.s %1,%0"
[(set_attr "type" "fmove")])
(define_insn "" (define_insn "*truncdfsf2_68881"
[(set (match_operand:SF 0 "nonimmediate_operand" "=dm") [(set (match_operand:SF 0 "nonimmediate_operand" "=dm")
(float_truncate:SF (float_truncate:SF
(match_operand:DF 1 "general_operand" "f")))] (match_operand:DF 1 "general_operand" "f")))]
"TARGET_68881" "TARGET_68881"
"fmove%.s %f1,%0") "fmove%.s %f1,%0"
[(set_attr "type" "fmove")])
;; Conversion between fixed point and floating point. ;; Conversion between fixed point and floating point.
;; Note that among the fix-to-float insns ;; Note that among the fix-to-float insns
...@@ -1724,7 +2034,8 @@ ...@@ -1724,7 +2034,8 @@
[(set (match_operand:FP 0 "nonimmediate_operand" "=f") [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
(float:FP (match_operand:SI 1 "general_operand" "d<Q>U")))] (float:FP (match_operand:SI 1 "general_operand" "d<Q>U")))]
"TARGET_COLDFIRE_FPU" "TARGET_COLDFIRE_FPU"
"f<FP:prec>move%.l %1,%0") "f<FP:prec>move%.l %1,%0"
[(set_attr "type" "fmove")])
(define_expand "floathi<mode>2" (define_expand "floathi<mode>2"
...@@ -1737,13 +2048,15 @@ ...@@ -1737,13 +2048,15 @@
[(set (match_operand:FP 0 "nonimmediate_operand" "=f") [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
(float:FP (match_operand:HI 1 "general_operand" "dmn")))] (float:FP (match_operand:HI 1 "general_operand" "dmn")))]
"TARGET_68881" "TARGET_68881"
"fmove%.w %1,%0") "fmove%.w %1,%0"
[(set_attr "type" "fmove")])
(define_insn "floathi<mode>2_cf" (define_insn "floathi<mode>2_cf"
[(set (match_operand:FP 0 "nonimmediate_operand" "=f") [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
(float:FP (match_operand:HI 1 "general_operand" "d<Q>U")))] (float:FP (match_operand:HI 1 "general_operand" "d<Q>U")))]
"TARGET_COLDFIRE_FPU" "TARGET_COLDFIRE_FPU"
"fmove%.w %1,%0") "fmove%.w %1,%0"
[(set_attr "type" "fmove")])
(define_expand "floatqi<mode>2" (define_expand "floatqi<mode>2"
...@@ -1756,13 +2069,15 @@ ...@@ -1756,13 +2069,15 @@
[(set (match_operand:FP 0 "nonimmediate_operand" "=f") [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
(float:FP (match_operand:QI 1 "general_operand" "dmn")))] (float:FP (match_operand:QI 1 "general_operand" "dmn")))]
"TARGET_68881" "TARGET_68881"
"fmove%.b %1,%0") "fmove%.b %1,%0"
[(set_attr "type" "fmove")])
(define_insn "floatqi<mode>2_cf" (define_insn "floatqi<mode>2_cf"
[(set (match_operand:FP 0 "nonimmediate_operand" "=f") [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
(float:FP (match_operand:QI 1 "general_operand" "d<Q>U")))] (float:FP (match_operand:QI 1 "general_operand" "d<Q>U")))]
"TARGET_COLDFIRE_FPU" "TARGET_COLDFIRE_FPU"
"fmove%.b %1,%0") "fmove%.b %1,%0"
[(set_attr "type" "fmove")])
;; New routines to convert floating-point values to integers ;; New routines to convert floating-point values to integers
...@@ -1830,7 +2145,8 @@ ...@@ -1830,7 +2145,8 @@
if (FP_REG_P (operands[1])) if (FP_REG_P (operands[1]))
return "fintrz%.d %f1,%0"; return "fintrz%.d %f1,%0";
return "fintrz%.<FP:prec> %f1,%0"; return "fintrz%.<FP:prec> %f1,%0";
}) }
[(set_attr "type" "fintrz")])
;; Convert a float whose value is an integer ;; Convert a float whose value is an integer
;; to an actual integer. Second stage of converting float to integer type. ;; to an actual integer. Second stage of converting float to integer type.
...@@ -1850,7 +2166,8 @@ ...@@ -1850,7 +2166,8 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=d<Q>U") [(set (match_operand:QI 0 "nonimmediate_operand" "=d<Q>U")
(fix:QI (match_operand:FP 1 "general_operand" "f")))] (fix:QI (match_operand:FP 1 "general_operand" "f")))]
"TARGET_COLDFIRE_FPU" "TARGET_COLDFIRE_FPU"
"fmove%.b %1,%0") "fmove%.b %1,%0"
[(set_attr "type" "fmove")])
(define_expand "fix<mode>hi2" (define_expand "fix<mode>hi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "") [(set (match_operand:HI 0 "nonimmediate_operand" "")
...@@ -1868,7 +2185,8 @@ ...@@ -1868,7 +2185,8 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=d<Q>U") [(set (match_operand:HI 0 "nonimmediate_operand" "=d<Q>U")
(fix:HI (match_operand:FP 1 "general_operand" "f")))] (fix:HI (match_operand:FP 1 "general_operand" "f")))]
"TARGET_COLDFIRE_FPU" "TARGET_COLDFIRE_FPU"
"fmove%.w %1,%0") "fmove%.w %1,%0"
[(set_attr "type" "fmove")])
(define_expand "fix<mode>si2" (define_expand "fix<mode>si2"
[(set (match_operand:SI 0 "nonimmediate_operand" "") [(set (match_operand:SI 0 "nonimmediate_operand" "")
...@@ -1886,7 +2204,8 @@ ...@@ -1886,7 +2204,8 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=d<Q>U") [(set (match_operand:SI 0 "nonimmediate_operand" "=d<Q>U")
(fix:SI (match_operand:FP 1 "general_operand" "f")))] (fix:SI (match_operand:FP 1 "general_operand" "f")))]
"TARGET_COLDFIRE_FPU" "TARGET_COLDFIRE_FPU"
"fmove%.l %1,%0") "fmove%.l %1,%0"
[(set_attr "type" "fmove")])
;; add instructions ;; add instructions
...@@ -1984,7 +2303,8 @@ ...@@ -1984,7 +2303,8 @@
else else
operands[1] = adjust_address (operands[1], SImode, 4); operands[1] = adjust_address (operands[1], SImode, 4);
return "add%.l %1,%0"; return "add%.l %1,%0";
}) }
[(set_attr "type" "add_l")])
(define_insn "adddi3" (define_insn "adddi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "=o<>,d,d,d") [(set (match_operand:DI 0 "nonimmediate_operand" "=o<>,d,d,d")
...@@ -2107,12 +2427,54 @@ ...@@ -2107,12 +2427,54 @@
"! TARGET_COLDFIRE" "! TARGET_COLDFIRE"
"* return output_addsi3 (operands);") "* return output_addsi3 (operands);")
(define_insn "*addsi3_5200" (define_insn_and_split "*addsi3_5200"
[(set (match_operand:SI 0 "nonimmediate_operand" "=m,?a,?a,r") [(set (match_operand:SI 0 "nonimmediate_operand" "=mr,mr,m,r, ?a,?a,?a,?a")
(plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0") (plus:SI (match_operand:SI 1 "general_operand" "%0, 0, 0,0, a, a, r, a")
(match_operand:SI 2 "general_src_operand" "dIL,rJK,a,mrIKLi")))] (match_operand:SI 2 "general_src_operand" " I, L, d,mrKi,Cj,r, a, J")))]
"TARGET_COLDFIRE" "TARGET_COLDFIRE"
"* return output_addsi3 (operands);") {
switch (which_alternative)
{
case 0:
return "addq%.l %2,%0";
case 1:
operands[2] = GEN_INT (- INTVAL (operands[2]));
return "subq%.l %2,%0";
case 2:
case 3:
return "add%.l %2,%0";
case 4:
/* move%.l %2,%0\n\tadd%.l %1,%0 */
return "#";
case 5:
return MOTOROLA ? "lea (%1,%2.l),%0" : "lea %1@(0,%2:l),%0";
case 6:
return MOTOROLA ? "lea (%2,%1.l),%0" : "lea %2@(0,%1:l),%0";
case 7:
return MOTOROLA ? "lea (%c2,%1),%0" : "lea %1@(%c2),%0";
default:
gcc_unreachable ();
return "";
}
}
"&& reload_completed && (extract_constrain_insn_cached (insn), which_alternative == 4) && !operands_match_p (operands[0], operands[1])"
[(set (match_dup 0)
(match_dup 2))
(set (match_dup 0)
(plus:SI (match_dup 0)
(match_dup 1)))]
""
[(set_attr "type" "addq_l,subq_l,add_l,add_l,*,lea,lea,lea")
(set_attr "opy" "2,2,2,2,*,*,*,*")
(set_attr "opy_type" "*,*,*,*,*,mem6,mem6,mem5")
(set_attr "split" "done,done,done,done,*,done,done,done")])
(define_insn "" (define_insn ""
[(set (match_operand:SI 0 "nonimmediate_operand" "=a") [(set (match_operand:SI 0 "nonimmediate_operand" "=a")
...@@ -2392,7 +2754,8 @@ ...@@ -2392,7 +2754,8 @@
if (FP_REG_P (operands[2])) if (FP_REG_P (operands[2]))
return "f<FP:prec>add%.d %2,%0"; return "f<FP:prec>add%.d %2,%0";
return "f<FP:prec>add%.<FP:prec> %2,%0"; return "f<FP:prec>add%.<FP:prec> %2,%0";
}) }
[(set_attr "type" "fadd")])
;; subtract instructions ;; subtract instructions
...@@ -2426,7 +2789,8 @@ ...@@ -2426,7 +2789,8 @@
else else
operands[1] = adjust_address (operands[1], SImode, 4); operands[1] = adjust_address (operands[1], SImode, 4);
return "sub%.l %1,%0"; return "sub%.l %1,%0";
}) }
[(set_attr "type" "sub_l")])
(define_insn "subdi3" (define_insn "subdi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "=o<>,d,d,d") [(set (match_operand:DI 0 "nonimmediate_operand" "=o<>,d,d,d")
...@@ -2508,11 +2872,17 @@ ...@@ -2508,11 +2872,17 @@
}) })
(define_insn "subsi3" (define_insn "subsi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "=m,d,a") [(set (match_operand:SI 0 "nonimmediate_operand" "=mda,m,d,a")
(minus:SI (match_operand:SI 1 "general_operand" "0,0,0") (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
(match_operand:SI 2 "general_src_operand" "dT,mSrT,mSrs")))] (match_operand:SI 2 "general_src_operand" "I,dT,mSrT,mSrs")))]
"" ""
"sub%.l %2,%0") "@
subq%.l %2, %0
sub%.l %2,%0
sub%.l %2,%0
sub%.l %2,%0"
[(set_attr "type" "subq_l,sub_l,sub_l,sub_l")
(set_attr "opy" "2")])
(define_insn "" (define_insn ""
[(set (match_operand:SI 0 "nonimmediate_operand" "=a") [(set (match_operand:SI 0 "nonimmediate_operand" "=a")
...@@ -2598,7 +2968,8 @@ ...@@ -2598,7 +2968,8 @@
if (FP_REG_P (operands[2])) if (FP_REG_P (operands[2]))
return "f<FP:prec>sub%.d %2,%0"; return "f<FP:prec>sub%.d %2,%0";
return "f<FP:prec>sub%.<FP:prec> %2,%0"; return "f<FP:prec>sub%.<FP:prec> %2,%0";
}) }
[(set_attr "type" "fsub")])
;; multiply instructions ;; multiply instructions
...@@ -2609,7 +2980,9 @@ ...@@ -2609,7 +2980,9 @@
"" ""
{ {
return MOTOROLA ? "muls%.w %2,%0" : "muls %2,%0"; return MOTOROLA ? "muls%.w %2,%0" : "muls %2,%0";
}) }
[(set_attr "type" "muls_w")
(set_attr "opy" "2")])
(define_insn "mulhisi3" (define_insn "mulhisi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d") [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
...@@ -2620,9 +2993,11 @@ ...@@ -2620,9 +2993,11 @@
"" ""
{ {
return MOTOROLA ? "muls%.w %2,%0" : "muls %2,%0"; return MOTOROLA ? "muls%.w %2,%0" : "muls %2,%0";
}) }
[(set_attr "type" "muls_w")
(set_attr "opy" "2")])
(define_insn "" (define_insn "*mulhisisi3_s"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d") [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(mult:SI (sign_extend:SI (mult:SI (sign_extend:SI
(match_operand:HI 1 "nonimmediate_operand" "%0")) (match_operand:HI 1 "nonimmediate_operand" "%0"))
...@@ -2630,7 +3005,9 @@ ...@@ -2630,7 +3005,9 @@
"INTVAL (operands[2]) >= -0x8000 && INTVAL (operands[2]) <= 0x7fff" "INTVAL (operands[2]) >= -0x8000 && INTVAL (operands[2]) <= 0x7fff"
{ {
return MOTOROLA ? "muls%.w %2,%0" : "muls %2,%0"; return MOTOROLA ? "muls%.w %2,%0" : "muls %2,%0";
}) }
[(set_attr "type" "muls_w")
(set_attr "opy" "2")])
(define_expand "mulsi3" (define_expand "mulsi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "") [(set (match_operand:SI 0 "nonimmediate_operand" "")
...@@ -2639,20 +3016,24 @@ ...@@ -2639,20 +3016,24 @@
"TARGET_68020 || TARGET_COLDFIRE" "TARGET_68020 || TARGET_COLDFIRE"
"") "")
(define_insn "" (define_insn "*mulsi3_68020"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d") [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(mult:SI (match_operand:SI 1 "general_operand" "%0") (mult:SI (match_operand:SI 1 "general_operand" "%0")
(match_operand:SI 2 "general_src_operand" "dmSTK")))] (match_operand:SI 2 "general_src_operand" "dmSTK")))]
"TARGET_68020" "TARGET_68020"
"muls%.l %2,%0") "muls%.l %2,%0"
[(set_attr "type" "muls_l")
(set_attr "opy" "2")])
(define_insn "" (define_insn "*mulsi3_cf"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d") [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(mult:SI (match_operand:SI 1 "general_operand" "%0") (mult:SI (match_operand:SI 1 "general_operand" "%0")
(match_operand:SI 2 "general_operand" "d<Q>")))] (match_operand:SI 2 "general_operand" "d<Q>")))]
"TARGET_COLDFIRE" "TARGET_COLDFIRE"
"muls%.l %2,%0") "muls%.l %2,%0"
[(set_attr "type" "muls_l")
(set_attr "opy" "2")])
(define_insn "umulhisi3" (define_insn "umulhisi3"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d") [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
...@@ -2663,9 +3044,11 @@ ...@@ -2663,9 +3044,11 @@
"" ""
{ {
return MOTOROLA ? "mulu%.w %2,%0" : "mulu %2,%0"; return MOTOROLA ? "mulu%.w %2,%0" : "mulu %2,%0";
}) }
[(set_attr "type" "mulu_w")
(set_attr "opy" "2")])
(define_insn "" (define_insn "*mulhisisi3_z"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d") [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(mult:SI (zero_extend:SI (mult:SI (zero_extend:SI
(match_operand:HI 1 "nonimmediate_operand" "%0")) (match_operand:HI 1 "nonimmediate_operand" "%0"))
...@@ -2673,7 +3056,9 @@ ...@@ -2673,7 +3056,9 @@
"INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 0xffff" "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 0xffff"
{ {
return MOTOROLA ? "mulu%.w %2,%0" : "mulu %2,%0"; return MOTOROLA ? "mulu%.w %2,%0" : "mulu %2,%0";
}) }
[(set_attr "type" "mulu_w")
(set_attr "opy" "2")])
;; We need a separate DEFINE_EXPAND for u?mulsidi3 to be able to use the ;; We need a separate DEFINE_EXPAND for u?mulsidi3 to be able to use the
;; proper matching constraint. This is because the matching is between ;; proper matching constraint. This is because the matching is between
...@@ -2932,7 +3317,8 @@ ...@@ -2932,7 +3317,8 @@
if (FP_REG_P (operands[2])) if (FP_REG_P (operands[2]))
return "f<FP:prec>mul%.d %2,%0"; return "f<FP:prec>mul%.d %2,%0";
return "f<FP:prec>mul%.<FP:prec> %2,%0"; return "f<FP:prec>mul%.<FP:prec> %2,%0";
}) }
[(set_attr "type" "fmul")])
;; divide instructions ;; divide instructions
...@@ -3000,7 +3386,8 @@ ...@@ -3000,7 +3386,8 @@
if (FP_REG_P (operands[2])) if (FP_REG_P (operands[2]))
return "f<FP:prec>div%.d %2,%0"; return "f<FP:prec>div%.d %2,%0";
return "f<FP:prec>div%.<FP:prec> %2,%0"; return "f<FP:prec>div%.<FP:prec> %2,%0";
}) }
[(set_attr "type" "fdiv")])
;; Remainder instructions. ;; Remainder instructions.
...@@ -3692,13 +4079,15 @@ ...@@ -3692,13 +4079,15 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=dm") [(set (match_operand:SI 0 "nonimmediate_operand" "=dm")
(neg:SI (match_operand:SI 1 "general_operand" "0")))] (neg:SI (match_operand:SI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE" "!TARGET_COLDFIRE"
"neg%.l %0") "neg%.l %0"
[(set_attr "type" "neg_l")])
(define_insn "negsi2_5200" (define_insn "negsi2_5200"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d") [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(neg:SI (match_operand:SI 1 "general_operand" "0")))] (neg:SI (match_operand:SI 1 "general_operand" "0")))]
"TARGET_COLDFIRE" "TARGET_COLDFIRE"
"neg%.l %0") "neg%.l %0"
[(set_attr "type" "neg_l")])
(define_insn "neghi2" (define_insn "neghi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=dm") [(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
...@@ -3863,7 +4252,8 @@ ...@@ -3863,7 +4252,8 @@
if (FP_REG_P (operands[1])) if (FP_REG_P (operands[1]))
return "f<FP:round>sqrt%.x %1,%0"; return "f<FP:round>sqrt%.x %1,%0";
return "f<FP:round>sqrt%.<FP:prec> %1,%0"; return "f<FP:round>sqrt%.<FP:prec> %1,%0";
}) }
[(set_attr "type" "fsqrt")])
(define_insn "sqrt<mode>2_cf" (define_insn "sqrt<mode>2_cf"
[(set (match_operand:FP 0 "nonimmediate_operand" "=f") [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
...@@ -4005,7 +4395,8 @@ ...@@ -4005,7 +4395,8 @@
[(set (match_operand:SI 0 "register_operand" "=d") [(set (match_operand:SI 0 "register_operand" "=d")
(clz:SI (match_operand:SI 1 "register_operand" "0")))] (clz:SI (match_operand:SI 1 "register_operand" "0")))]
"ISA_HAS_FF1" "ISA_HAS_FF1"
"ff1 %0") "ff1 %0"
[(set_attr "type" "ff1")])
;; one complement instructions ;; one complement instructions
...@@ -4048,7 +4439,8 @@ ...@@ -4048,7 +4439,8 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=d") [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(not:SI (match_operand:SI 1 "general_operand" "0")))] (not:SI (match_operand:SI 1 "general_operand" "0")))]
"TARGET_COLDFIRE" "TARGET_COLDFIRE"
"not%.l %0") "not%.l %0"
[(set_attr "type" "not_l")])
(define_insn "one_cmplhi2" (define_insn "one_cmplhi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=dm") [(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
...@@ -4399,7 +4791,8 @@ ...@@ -4399,7 +4791,8 @@
if (GET_CODE (operands[1]) != REG) if (GET_CODE (operands[1]) != REG)
operands[1] = adjust_address (operands[1], HImode, 2); operands[1] = adjust_address (operands[1], HImode, 2);
return "move%.w %1,%0"; return "move%.w %1,%0";
}) }
[(set_attr "type" "move_w")])
(define_insn "subregsi1ashrdi_const32" (define_insn "subregsi1ashrdi_const32"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm") [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
...@@ -4408,7 +4801,8 @@ ...@@ -4408,7 +4801,8 @@
"" ""
{ {
return "move%.l %1,%0"; return "move%.l %1,%0";
}) }
[(set_attr "type" "move_l")])
(define_insn "*ashrdi3_const1" (define_insn "*ashrdi3_const1"
[(set (match_operand:DI 0 "register_operand" "=d") [(set (match_operand:DI 0 "register_operand" "=d")
...@@ -4577,7 +4971,9 @@ ...@@ -4577,7 +4971,9 @@
(ashiftrt:SI (match_operand:SI 1 "register_operand" "0") (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "general_operand" "dI")))] (match_operand:SI 2 "general_operand" "dI")))]
"" ""
"asr%.l %2,%0") "asr%.l %2,%0"
[(set_attr "type" "asr_l")
(set_attr "opy" "2")])
(define_insn "ashrhi3" (define_insn "ashrhi3"
[(set (match_operand:HI 0 "register_operand" "=d") [(set (match_operand:HI 0 "register_operand" "=d")
...@@ -4643,9 +5039,8 @@ ...@@ -4643,9 +5039,8 @@
(subreg:SI (lshiftrt:DI (match_operand:DI 1 "general_operand" "ro") (subreg:SI (lshiftrt:DI (match_operand:DI 1 "general_operand" "ro")
(const_int 32)) 4))] (const_int 32)) 4))]
"" ""
{ "move%.l %1,%0"
return "move%.l %1,%0"; [(set_attr "type" "move_l")])
})
(define_insn "*lshrdi3_const1" (define_insn "*lshrdi3_const1"
[(set (match_operand:DI 0 "register_operand" "=d") [(set (match_operand:DI 0 "register_operand" "=d")
...@@ -4872,7 +5267,9 @@ ...@@ -4872,7 +5267,9 @@
(lshiftrt:SI (match_operand:SI 1 "register_operand" "0") (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "general_operand" "dI")))] (match_operand:SI 2 "general_operand" "dI")))]
"" ""
"lsr%.l %2,%0") "lsr%.l %2,%0"
[(set_attr "type" "lsr_l")
(set_attr "opy" "2")])
(define_insn "lshrhi3" (define_insn "lshrhi3"
[(set (match_operand:HI 0 "register_operand" "=d") [(set (match_operand:HI 0 "register_operand" "=d")
...@@ -5029,10 +5426,11 @@ ...@@ -5029,10 +5426,11 @@
{ {
CC_STATUS_INIT; CC_STATUS_INIT;
return "bset %1,%0"; return "bset %1,%0";
}) }
[(set_attr "type" "bset")])
;; set bit, bit number is (sign/zero)_extended from HImode/QImode ;; set bit, bit number is (sign/zero)_extended from HImode/QImode
(define_insn "" (define_insn "*bsetmemqi_ext"
[(set (match_operand:QI 0 "memory_operand" "+m") [(set (match_operand:QI 0 "memory_operand" "+m")
(ior:QI (subreg:QI (ashift:SI (const_int 1) (ior:QI (subreg:QI (ashift:SI (const_int 1)
(match_operator:SI 2 "extend_operator" (match_operator:SI 2 "extend_operator"
...@@ -5042,7 +5440,8 @@ ...@@ -5042,7 +5440,8 @@
{ {
CC_STATUS_INIT; CC_STATUS_INIT;
return "bset %1,%0"; return "bset %1,%0";
}) }
[(set_attr "type" "bset")])
;; clear bit, bit number is int ;; clear bit, bit number is int
(define_insn "bclrmemqi" (define_insn "bclrmemqi"
...@@ -5055,10 +5454,11 @@ ...@@ -5055,10 +5454,11 @@
{ {
CC_STATUS_INIT; CC_STATUS_INIT;
return "bclr %1,%0"; return "bclr %1,%0";
}) }
[(set_attr "type" "bclr")])
;; clear bit, bit number is (sign/zero)_extended from HImode/QImode ;; clear bit, bit number is (sign/zero)_extended from HImode/QImode
(define_insn "" (define_insn "*bclrmemqi_ext"
[(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+m") [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+m")
(const_int 1) (const_int 1)
(minus:SI (const_int 7) (minus:SI (const_int 7)
...@@ -5069,7 +5469,8 @@ ...@@ -5069,7 +5469,8 @@
{ {
CC_STATUS_INIT; CC_STATUS_INIT;
return "bclr %1,%0"; return "bclr %1,%0";
}) }
[(set_attr "type" "bclr")])
;; Special cases of bit-field insns which we should ;; Special cases of bit-field insns which we should
;; recognize in preference to the general case. ;; recognize in preference to the general case.
...@@ -5641,14 +6042,15 @@ ...@@ -5641,14 +6042,15 @@
"" ""
"") "")
(define_insn "" (define_insn "*scc"
[(set (match_operand:QI 0 "register_operand" "=d") [(set (match_operand:QI 0 "register_operand" "=d")
(geu:QI (cc0) (const_int 0)))] (geu:QI (cc0) (const_int 0)))]
"" ""
{ {
cc_status = cc_prev_status; cc_status = cc_prev_status;
return "scc %0"; return "scc %0";
}) }
[(set_attr "type" "scc")])
(define_expand "sle" (define_expand "sle"
[(set (match_operand:QI 0 "register_operand" "") [(set (match_operand:QI 0 "register_operand" "")
...@@ -5678,14 +6080,15 @@ ...@@ -5678,14 +6080,15 @@
"" ""
"") "")
(define_insn "" (define_insn "*sls"
[(set (match_operand:QI 0 "register_operand" "=d") [(set (match_operand:QI 0 "register_operand" "=d")
(leu:QI (cc0) (const_int 0)))] (leu:QI (cc0) (const_int 0)))]
"" ""
{ {
cc_status = cc_prev_status; cc_status = cc_prev_status;
return "sls %0"; return "sls %0";
}) }
[(set_attr "type" "scc")])
(define_expand "sordered" (define_expand "sordered"
[(set (match_operand:QI 0 "register_operand" "") [(set (match_operand:QI 0 "register_operand" "")
...@@ -6085,7 +6488,9 @@ ...@@ -6085,7 +6488,9 @@
OUTPUT_JUMP ("jbeq %l0", "fbeq %l0", "jbeq %l0"); OUTPUT_JUMP ("jbeq %l0", "fbeq %l0", "jbeq %l0");
else else
OUTPUT_JUMP ("jeq %l0", "fjeq %l0", "jeq %l0"); OUTPUT_JUMP ("jeq %l0", "fjeq %l0", "jeq %l0");
}) }
[(set (attr "type") (symbol_ref "m68k_sched_branch_type (insn)"))
(set_attr "split" "done")])
(define_insn "bne" (define_insn "bne"
[(set (pc) [(set (pc)
...@@ -6099,7 +6504,9 @@ ...@@ -6099,7 +6504,9 @@
OUTPUT_JUMP ("jbne %l0", "fbne %l0", "jbne %l0"); OUTPUT_JUMP ("jbne %l0", "fbne %l0", "jbne %l0");
else else
OUTPUT_JUMP ("jne %l0", "fjne %l0", "jne %l0"); OUTPUT_JUMP ("jne %l0", "fjne %l0", "jne %l0");
}) }
[(set (attr "type") (symbol_ref "m68k_sched_branch_type (insn)"))
(set_attr "split" "done")])
(define_insn "bgt" (define_insn "bgt"
[(set (pc) [(set (pc)
...@@ -6113,7 +6520,9 @@ ...@@ -6113,7 +6520,9 @@
OUTPUT_JUMP ("jbgt %l0", "fbgt %l0", 0); OUTPUT_JUMP ("jbgt %l0", "fbgt %l0", 0);
else else
OUTPUT_JUMP ("jgt %l0", "fjgt %l0", 0); OUTPUT_JUMP ("jgt %l0", "fjgt %l0", 0);
}) }
[(set (attr "type") (symbol_ref "m68k_sched_branch_type (insn)"))
(set_attr "split" "done")])
(define_insn "bgtu" (define_insn "bgtu"
[(set (pc) [(set (pc)
...@@ -6124,7 +6533,8 @@ ...@@ -6124,7 +6533,8 @@
"" ""
{ {
return MOTOROLA ? "jbhi %l0" : "jhi %l0"; return MOTOROLA ? "jbhi %l0" : "jhi %l0";
}) }
[(set_attr "type" "bcc")])
(define_insn "blt" (define_insn "blt"
[(set (pc) [(set (pc)
...@@ -6138,7 +6548,9 @@ ...@@ -6138,7 +6548,9 @@
OUTPUT_JUMP ("jblt %l0", "fblt %l0", "jbmi %l0"); OUTPUT_JUMP ("jblt %l0", "fblt %l0", "jbmi %l0");
else else
OUTPUT_JUMP ("jlt %l0", "fjlt %l0", "jmi %l0"); OUTPUT_JUMP ("jlt %l0", "fjlt %l0", "jmi %l0");
}) }
[(set (attr "type") (symbol_ref "m68k_sched_branch_type (insn)"))
(set_attr "split" "done")])
(define_insn "bltu" (define_insn "bltu"
[(set (pc) [(set (pc)
...@@ -6149,7 +6561,8 @@ ...@@ -6149,7 +6561,8 @@
"" ""
{ {
return MOTOROLA ? "jbcs %l0" : "jcs %l0"; return MOTOROLA ? "jbcs %l0" : "jcs %l0";
}) }
[(set_attr "type" "bcc")])
(define_insn "bge" (define_insn "bge"
[(set (pc) [(set (pc)
...@@ -6174,7 +6587,8 @@ ...@@ -6174,7 +6587,8 @@
"" ""
{ {
return MOTOROLA ? "jbcc %l0" : "jcc %l0"; return MOTOROLA ? "jbcc %l0" : "jcc %l0";
}) }
[(set_attr "type" "bcc")])
(define_insn "ble" (define_insn "ble"
[(set (pc) [(set (pc)
...@@ -6188,7 +6602,8 @@ ...@@ -6188,7 +6602,8 @@
OUTPUT_JUMP ("jble %l0", "fble %l0", 0); OUTPUT_JUMP ("jble %l0", "fble %l0", 0);
else else
OUTPUT_JUMP ("jle %l0", "fjle %l0", 0); OUTPUT_JUMP ("jle %l0", "fjle %l0", 0);
}) }
[(set_attr "type" "bcc")])
(define_insn "bleu" (define_insn "bleu"
[(set (pc) [(set (pc)
...@@ -6199,7 +6614,8 @@ ...@@ -6199,7 +6614,8 @@
"" ""
{ {
return MOTOROLA ? "jbls %l0" : "jls %l0"; return MOTOROLA ? "jbls %l0" : "jls %l0";
}) }
[(set_attr "type" "bcc")])
(define_insn "bordered" (define_insn "bordered"
[(set (pc) [(set (pc)
...@@ -6291,7 +6707,7 @@ ...@@ -6291,7 +6707,7 @@
;; Negated conditional jump instructions. ;; Negated conditional jump instructions.
(define_insn "" (define_insn "*beq2"
[(set (pc) [(set (pc)
(if_then_else (eq (cc0) (if_then_else (eq (cc0)
(const_int 0)) (const_int 0))
...@@ -6303,9 +6719,10 @@ ...@@ -6303,9 +6719,10 @@
OUTPUT_JUMP ("jbne %l0", "fbne %l0", "jbne %l0"); OUTPUT_JUMP ("jbne %l0", "fbne %l0", "jbne %l0");
else else
OUTPUT_JUMP ("jne %l0", "fjne %l0", "jne %l0"); OUTPUT_JUMP ("jne %l0", "fjne %l0", "jne %l0");
}) }
[(set_attr "type" "bcc")])
(define_insn "" (define_insn "*bne2"
[(set (pc) [(set (pc)
(if_then_else (ne (cc0) (if_then_else (ne (cc0)
(const_int 0)) (const_int 0))
...@@ -6317,9 +6734,10 @@ ...@@ -6317,9 +6734,10 @@
OUTPUT_JUMP ("jbeq %l0", "fbeq %l0", "jbeq %l0"); OUTPUT_JUMP ("jbeq %l0", "fbeq %l0", "jbeq %l0");
else else
OUTPUT_JUMP ("jeq %l0", "fjeq %l0", "jeq %l0"); OUTPUT_JUMP ("jeq %l0", "fjeq %l0", "jeq %l0");
}) }
[(set_attr "type" "bcc")])
(define_insn "" (define_insn "*bgt2"
[(set (pc) [(set (pc)
(if_then_else (gt (cc0) (if_then_else (gt (cc0)
(const_int 0)) (const_int 0))
...@@ -6331,9 +6749,10 @@ ...@@ -6331,9 +6749,10 @@
OUTPUT_JUMP ("jble %l0", "fbngt %l0", 0); OUTPUT_JUMP ("jble %l0", "fbngt %l0", 0);
else else
OUTPUT_JUMP ("jle %l0", "fjngt %l0", 0); OUTPUT_JUMP ("jle %l0", "fjngt %l0", 0);
}) }
[(set_attr "type" "bcc")])
(define_insn "" (define_insn "*bgtu2"
[(set (pc) [(set (pc)
(if_then_else (gtu (cc0) (if_then_else (gtu (cc0)
(const_int 0)) (const_int 0))
...@@ -6342,9 +6761,10 @@ ...@@ -6342,9 +6761,10 @@
"" ""
{ {
return MOTOROLA ? "jbls %l0" : "jls %l0"; return MOTOROLA ? "jbls %l0" : "jls %l0";
}) }
[(set_attr "type" "bcc")])
(define_insn "" (define_insn "*blt2"
[(set (pc) [(set (pc)
(if_then_else (lt (cc0) (if_then_else (lt (cc0)
(const_int 0)) (const_int 0))
...@@ -6356,9 +6776,10 @@ ...@@ -6356,9 +6776,10 @@
OUTPUT_JUMP ("jbge %l0", "fbnlt %l0", "jbpl %l0"); OUTPUT_JUMP ("jbge %l0", "fbnlt %l0", "jbpl %l0");
else else
OUTPUT_JUMP ("jge %l0", "fjnlt %l0", "jpl %l0"); OUTPUT_JUMP ("jge %l0", "fjnlt %l0", "jpl %l0");
}) }
[(set_attr "type" "bcc")])
(define_insn "" (define_insn "*bltu2"
[(set (pc) [(set (pc)
(if_then_else (ltu (cc0) (if_then_else (ltu (cc0)
(const_int 0)) (const_int 0))
...@@ -6367,9 +6788,10 @@ ...@@ -6367,9 +6788,10 @@
"" ""
{ {
return MOTOROLA ? "jbcc %l0" : "jcc %l0"; return MOTOROLA ? "jbcc %l0" : "jcc %l0";
}) }
[(set_attr "type" "bcc")])
(define_insn "" (define_insn "*bge2"
[(set (pc) [(set (pc)
(if_then_else (ge (cc0) (if_then_else (ge (cc0)
(const_int 0)) (const_int 0))
...@@ -6381,9 +6803,10 @@ ...@@ -6381,9 +6803,10 @@
OUTPUT_JUMP ("jblt %l0", "fbnge %l0", "jbmi %l0"); OUTPUT_JUMP ("jblt %l0", "fbnge %l0", "jbmi %l0");
else else
OUTPUT_JUMP ("jlt %l0", "fjnge %l0", "jmi %l0"); OUTPUT_JUMP ("jlt %l0", "fjnge %l0", "jmi %l0");
}) }
[(set_attr "type" "bcc")])
(define_insn "" (define_insn "*bgeu2"
[(set (pc) [(set (pc)
(if_then_else (geu (cc0) (if_then_else (geu (cc0)
(const_int 0)) (const_int 0))
...@@ -6392,9 +6815,10 @@ ...@@ -6392,9 +6815,10 @@
"" ""
{ {
return MOTOROLA ? "jbcs %l0" : "jcs %l0"; return MOTOROLA ? "jbcs %l0" : "jcs %l0";
}) }
[(set_attr "type" "bcc")])
(define_insn "" (define_insn "*ble2"
[(set (pc) [(set (pc)
(if_then_else (le (cc0) (if_then_else (le (cc0)
(const_int 0)) (const_int 0))
...@@ -6406,9 +6830,10 @@ ...@@ -6406,9 +6830,10 @@
OUTPUT_JUMP ("jbgt %l0", "fbnle %l0", 0); OUTPUT_JUMP ("jbgt %l0", "fbnle %l0", 0);
else else
OUTPUT_JUMP ("jgt %l0", "fjnle %l0", 0); OUTPUT_JUMP ("jgt %l0", "fjnle %l0", 0);
}) }
[(set_attr "type" "bcc")])
(define_insn "" (define_insn "*bleu2"
[(set (pc) [(set (pc)
(if_then_else (leu (cc0) (if_then_else (leu (cc0)
(const_int 0)) (const_int 0))
...@@ -6417,7 +6842,8 @@ ...@@ -6417,7 +6842,8 @@
"" ""
{ {
return MOTOROLA ? "jbhi %l0" : "jhi %l0"; return MOTOROLA ? "jbhi %l0" : "jhi %l0";
}) }
[(set_attr "type" "bcc")])
(define_insn "*bordered_rev" (define_insn "*bordered_rev"
[(set (pc) [(set (pc)
...@@ -6514,7 +6940,8 @@ ...@@ -6514,7 +6940,8 @@
"" ""
{ {
return MOTOROLA ? "jbra %l0" : "jra %l0"; return MOTOROLA ? "jbra %l0" : "jra %l0";
}) }
[(set_attr "type" "bra")])
(define_expand "tablejump" (define_expand "tablejump"
[(parallel [(set (pc) (match_operand 0 "" "")) [(parallel [(set (pc) (match_operand 0 "" ""))
...@@ -6528,13 +6955,14 @@ ...@@ -6528,13 +6955,14 @@
}) })
;; Jump to variable address from dispatch table of absolute addresses. ;; Jump to variable address from dispatch table of absolute addresses.
(define_insn "" (define_insn "*tablejump_internal"
[(set (pc) (match_operand:SI 0 "register_operand" "a")) [(set (pc) (match_operand:SI 0 "register_operand" "a"))
(use (label_ref (match_operand 1 "" "")))] (use (label_ref (match_operand 1 "" "")))]
"" ""
{ {
return MOTOROLA ? "jmp (%0)" : "jmp %0@"; return MOTOROLA ? "jmp (%0)" : "jmp %0@";
}) }
[(set_attr "type" "bra")])
;; Jump to variable address from dispatch table of relative addresses. ;; Jump to variable address from dispatch table of relative addresses.
(define_insn "" (define_insn ""
...@@ -6746,16 +7174,46 @@ ...@@ -6746,16 +7174,46 @@
operands[1] = m68k_legitimize_call_address (operands[1]); operands[1] = m68k_legitimize_call_address (operands[1]);
}) })
(define_insn "*call_value" (define_insn "*non_symbolic_call_value"
[(set (match_operand 0 "" "=rf,rf") [(set (match_operand 0 "" "=rf,rf")
(call (mem:QI (match_operand:SI 1 "call_operand" "a,W")) (call (mem:QI (match_operand:SI 1 "non_symbolic_call_operand" "a,W"))
(match_operand:SI 2 "general_operand" "g,g")))] (match_operand:SI 2 "general_operand" "g,g")))]
;; Operand 2 not really used on the m68000. ;; Operand 2 not really used on the m68000.
"!SIBLING_CALL_P (insn)" "!SIBLING_CALL_P (insn)"
"jsr %a1"
[(set_attr "type" "jsr")
(set_attr "split" "done")
(set_attr "opx" "1")])
(define_insn "*symbolic_call_value_jsr"
[(set (match_operand 0 "" "=rf,rf")
(call (mem:QI (match_operand:SI 1 "symbolic_operand" "a,W"))
(match_operand:SI 2 "general_operand" "g,g")))]
;; Operand 2 not really used on the m68000.
"!SIBLING_CALL_P (insn) && m68k_symbolic_call_var == M68K_SYMBOLIC_CALL_JSR"
{ {
operands[0] = operands[1]; operands[0] = operands[1];
return output_call (operands[0]); return m68k_symbolic_call;
}) }
[(set_attr "type" "jsr")
(set_attr "split" "done")
(set_attr "opx" "1")])
(define_insn "*symbolic_call_value_bsr"
[(set (match_operand 0 "" "=rf,rf")
(call (mem:QI (match_operand:SI 1 "symbolic_operand" "a,W"))
(match_operand:SI 2 "general_operand" "g,g")))]
;; Operand 2 not really used on the m68000.
"!SIBLING_CALL_P (insn)
&& (m68k_symbolic_call_var == M68K_SYMBOLIC_CALL_BSR_C
|| m68k_symbolic_call_var == M68K_SYMBOLIC_CALL_BSR_P)"
{
operands[0] = operands[1];
return m68k_symbolic_call;
}
[(set_attr "type" "bsr")
(set_attr "split" "done")
(set_attr "opx" "1")])
;; Call subroutine returning any type. ;; Call subroutine returning any type.
...@@ -6796,7 +7254,8 @@ ...@@ -6796,7 +7254,8 @@
(define_insn "nop" (define_insn "nop"
[(const_int 0)] [(const_int 0)]
"" ""
"nop") "nop"
[(set_attr "type" "nop")])
(define_expand "prologue" (define_expand "prologue"
[(const_int 0)] [(const_int 0)]
...@@ -6849,7 +7308,8 @@ ...@@ -6849,7 +7308,8 @@
else else
return "rts"; return "rts";
} }
}) }
[(set_attr "type" "rts")])
(define_insn "*m68k_store_multiple" (define_insn "*m68k_store_multiple"
[(match_parallel 0 "" [(match_operand 1 "")])] [(match_parallel 0 "" [(match_operand 1 "")])]
...@@ -6939,7 +7399,8 @@ ...@@ -6939,7 +7399,8 @@
(plus:SI (match_dup 0) (plus:SI (match_dup 0)
(const_int 4)))] (const_int 4)))]
"" ""
"unlk %0") "unlk %0"
[(set_attr "type" "unlk")])
(define_insn "load_got" (define_insn "load_got"
[(set (match_operand:SI 0 "register_operand" "=a") [(set (match_operand:SI 0 "register_operand" "=a")
...@@ -6971,7 +7432,8 @@ ...@@ -6971,7 +7432,8 @@
(define_insn "indirect_jump" (define_insn "indirect_jump"
[(set (pc) (match_operand:SI 0 "address_operand" "p"))] [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
"" ""
"jmp %a0") "jmp %a0"
[(set_attr "type" "jmp")])
;; This should not be used unless the add/sub insns can't be. ;; This should not be used unless the add/sub insns can't be.
...@@ -7373,10 +7835,12 @@ ...@@ -7373,10 +7835,12 @@
return "fcos%.<FP:prec> %1,%0"; return "fcos%.<FP:prec> %1,%0";
}) })
;; Unconditional traps are assumed to have (const_int 1) for the condition.
(define_insn "trap" (define_insn "trap"
[(trap_if (const_int -1) (const_int 7))] [(trap_if (const_int 1) (const_int 7))]
"" ""
"trap #7") "trap #7"
[(set_attr "type" "trap")])
(define_insn "conditional_trap" (define_insn "conditional_trap"
[(trap_if (match_operator 0 "valid_dbcc_comparison_p" [(trap_if (match_operator 0 "valid_dbcc_comparison_p"
...@@ -7399,3 +7863,12 @@ ...@@ -7399,3 +7863,12 @@
default: gcc_unreachable (); default: gcc_unreachable ();
} }
}) })
;; Instruction that subscribes one word in ColdFire instruction buffer.
;; This instruction is used within scheduler only and should not appear
;; in the instruction stream.
(define_insn "ib"
[(unspec [(const_int 0)] UNSPEC_IB)]
""
"#"
[(set_attr "type" "ib")])
...@@ -192,3 +192,17 @@ ...@@ -192,3 +192,17 @@
(define_predicate "pre_dec_operand" (define_predicate "pre_dec_operand"
(and (match_code "mem") (and (match_code "mem")
(match_test "GET_CODE (XEXP (op, 0)) == PRE_DEC"))) (match_test "GET_CODE (XEXP (op, 0)) == PRE_DEC")))
;; An operand for movsi_const0 pattern.
(define_predicate "movsi_const0_operand"
(and (match_operand 0 "nonimmediate_operand")
(match_test "(TARGET_68010 || TARGET_COLDFIRE)
|| !(MEM_P (op) && MEM_VOLATILE_P (op))")))
;; A non-symbolic call operand.
;; We need to special case 'const_int' to ignore its mode while matching.
(define_predicate "non_symbolic_call_operand"
(and (match_operand 0 "call_operand")
(ior (and (match_code "const_int")
(match_test "!symbolic_operand (op, mode)"))
(match_test "!symbolic_operand (op,mode)"))))
...@@ -2542,7 +2542,7 @@ Floating-point zero. ...@@ -2542,7 +2542,7 @@ Floating-point zero.
An address that can be used in a non-macro load or store. An address that can be used in a non-macro load or store.
@end table @end table
@item Motorola 680x0---@file{config/m68k/m68k.h} @item Motorola 680x0---@file{config/m68k/constraints.md}
@table @code @table @code
@item a @item a
Address register Address register
...@@ -2568,8 +2568,66 @@ Integer in the range @minus{}8 to @minus{}1 ...@@ -2568,8 +2568,66 @@ Integer in the range @minus{}8 to @minus{}1
@item M @item M
Signed number whose magnitude is greater than 0x100 Signed number whose magnitude is greater than 0x100
@item N
Range 24 to 31, rotatert:SI 8 to 1 expressed as rotate
@item O
16 (for rotate using swap)
@item P
Range 8 to 15, rotatert:HI 8 to 1 expressed as rotate
@item R
Numbers that mov3q can handle
@item G @item G
Floating point constant that is not a 68881 constant Floating point constant that is not a 68881 constant
@item S
Operands that satisfy 'm' when -mpcrel is in effect
@item T
Operands that satisfy 's' when -mpcrel is not in effect
@item Q
Address register indirect addressing mode
@item U
Register offset addressing
@item W
const_call_operand
@item Cs
symbol_ref or const
@item Ci
const_int
@item C0
const_int 0
@item Cj
Range of signed numbers that don't fit in 16 bits
@item Cmvq
Integers valid for mvq
@item Capsw
Integers valid for a moveq followed by a swap
@item Cmvz
Integers valid for mvz
@item Cmvs
Integers valid for mvs
@item Ap
push_operand
@item Ac
Non-register operands allowed in clr
@end table @end table
@item Motorola 68HC11 & 68HC12 families---@file{config/m68hc11/m68hc11.h} @item Motorola 68HC11 & 68HC12 families---@file{config/m68hc11/m68hc11.h}
......
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