This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][2/3] Instruction patterns changes and instruction attributes


Hi,

Here is updated patch with two minor bugs fixed. Particularly, splits for tst_internal and addsi3_5200 were fixed.

Original split for tst_internal could generate an excessive reload instruction and bug in split condition of addsi3_5200 could cause a miscompilation.


Thanks,


Maxim
2007-08-09  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.
--- doc/md.texi	(/csl/gcc/branches/maxim/fsf-trunk/gcc)	(revision 180896)
+++ doc/md.texi	(/csl/gcc/branches/maxim/fsf-cf-sched-m68k/gcc)	(revision 180896)
@@ -2542,7 +2542,7 @@ Floating-point zero.
 An address that can be used in a non-macro load or store.
 @end table
 
-@item Motorola 680x0---@file{config/m68k/m68k.h}
+@item Motorola 680x0---@file{config/m68k/constraints.md}
 @table @code
 @item a
 Address register
@@ -2568,8 +2568,66 @@ Integer in the range @minus{}8 to @minus
 @item M
 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
 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
 
 @item Motorola 68HC11 & 68HC12 families---@file{config/m68hc11/m68hc11.h}
--- config/m68k/predicates.md	(/csl/gcc/branches/maxim/fsf-trunk/gcc)	(revision 180896)
+++ config/m68k/predicates.md	(/csl/gcc/branches/maxim/fsf-cf-sched-m68k/gcc)	(revision 180896)
@@ -192,3 +192,17 @@
 (define_predicate "pre_dec_operand"
   (and (match_code "mem")
        (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)"))))
--- config/m68k/m68k.md	(/csl/gcc/branches/maxim/fsf-trunk/gcc)	(revision 180896)
+++ config/m68k/m68k.md	(/csl/gcc/branches/maxim/fsf-cf-sched-m68k/gcc)	(revision 180896)
@@ -114,6 +114,7 @@
   [(UNSPEC_SIN 1)
    (UNSPEC_COS 2)
    (UNSPEC_GOT 3)
+   (UNSPEC_IB 4)
   ])
 
 ;; UNSPEC_VOLATILE usage:
@@ -136,6 +137,205 @@
 (include "predicates.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.
 ;; Valid floating point modes
 (define_mode_iterator FP [SF DF (XF "TARGET_68881")])
@@ -150,22 +350,33 @@
 ;; Allowable 68881 constant constraints
 (define_mode_attr const [(SF "F") (DF "G") (XF "")])
 
-(define_insn ""
-  [(set (match_operand:DF 0 "push_operand" "=m")
-	(match_operand:DF 1 "general_operand" "ro<>fE"))]
+
+(define_insn_and_split "*movdf_internal"
+  [(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]))
-    return "fmove%.d %f1,%0";
-  return output_move_double (operands);
-})
+  m68k_emit_move_double (operands);
+  DONE;
+}
+  [(set_attr "type" "fmove,*")
+   (set_attr "split" "done,*")])
 
-(define_insn "pushdi"
+(define_insn_and_split "pushdi"
   [(set (match_operand:DI 0 "push_operand" "=m")
 	(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
@@ -194,12 +405,12 @@
       xoperands[0] = operands[2];
       xoperands[1] = operands[0];
       output_move_double (xoperands);
-      cc_status.flags |= CC_REVERSED;
+      cc_status.flags |= CC_REVERSED; /*|*/
       return "neg%.l %R2\;negx%.l %2";
     }
   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";
     }
   else
@@ -217,18 +428,24 @@
   ""
   "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)
 	(match_operand:SI 0 "nonimmediate_operand" "rm"))]
-  ""
-{
-  if (TARGET_68020 || TARGET_COLDFIRE || ! ADDRESS_REG_P (operands[0]))
-    return "tst%.l %0";
-  /* If you think that the 68020 does not support tstl a0,
-     reread page B-167 of the 68020 manual more carefully.  */
-  /* On an address reg, cmpw may replace cmpl.  */
-  return "cmp%.w #0,%0";
-})
+  "TARGET_68020 || TARGET_COLDFIRE"
+  "tst%.l %0"
+  [(set_attr "type" "tst_l")])
+
+;; On an address reg, cmpw may replace cmpl.
+(define_insn "*tstsi_internal"
+  [(set (cc0)
+	(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
 ;; with address registers as second operand always test the whole word.
@@ -238,11 +455,12 @@
   ""
   "m68k_last_compare_had_fp_operands = 0;")
 
-(define_insn ""
+(define_insn "*tsthi_internal"
   [(set (cc0)
 	(match_operand:HI 0 "nonimmediate_operand" "dm"))]
   ""
-  "tst%.w %0")
+  "tst%.w %0"
+  [(set_attr "type" "tst_w")])
 
 (define_expand "tstqi"
   [(set (cc0)
@@ -250,11 +468,12 @@
   ""
   "m68k_last_compare_had_fp_operands = 0;")
 
-(define_insn ""
+(define_insn "*tstqi_internal"
   [(set (cc0)
 	(match_operand:QI 0 "nonimmediate_operand" "dm"))]
   ""
-  "tst%.b %0")
+  "tst%.b %0"
+  [(set_attr "type" "tst_b")])
 
 (define_expand "tst<mode>"
   [(set (cc0)
@@ -284,7 +503,8 @@
   if (FP_REG_P (operands[0]))
     return "ftst%.d %0";
   return "ftst%.<FP:prec> %0";
-})
+}
+  [(set_attr "type" "ftst")])
 
 
 ;; compare instructions.
@@ -309,7 +529,7 @@
     return "sub%.l %R2,%R0\;subx%.l %2,%0";
   else
     {
-      cc_status.flags |= CC_REVERSED;
+      cc_status.flags |= CC_REVERSED; /*|*/
       return "sub%.l %R1,%R0\;subx%.l %1,%0";
     }
 })
@@ -335,7 +555,7 @@
   if (REG_P (operands[1])
       || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
     {
-      cc_status.flags |= CC_REVERSED;
+      cc_status.flags |= CC_REVERSED; /*|*/
       return "cmp%.l %d0,%d1";
     }
   if (ADDRESS_REG_P (operands[0])
@@ -346,7 +566,7 @@
   return "cmp%.l %d1,%d0";
 })
 
-(define_insn ""
+(define_insn "*cmpsi_cf"
   [(set (cc0)
 	(compare (match_operand:SI 0 "nonimmediate_operand" "mrKs,r")
 		 (match_operand:SI 1 "general_operand" "r,mrKs")))]
@@ -355,11 +575,12 @@
   if (REG_P (operands[1])
       || (!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 %d1,%d0";
-})
+}
+  [(set_attr "type" "cmp_l")])
 
 (define_expand "cmphi"
   [(set (cc0)
@@ -403,7 +624,7 @@
   if (REG_P (operands[1])
       || (!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 %d1,%d0";
@@ -434,9 +655,10 @@
       else
         return "fcmp%.<FP:prec> %f1,%0";
     }
-  cc_status.flags |= CC_REVERSED;
+  cc_status.flags |= CC_REVERSED; /*|*/
   return "fcmp%.<FP:prec> %f0,%1";
-})
+}
+  [(set_attr "type" "fcmp")])
 
 (define_insn "cmp<mode>_cf"
   [(set (cc0)
@@ -452,9 +674,10 @@
       else
 	return "fcmp%.<FP:prec> %f1,%0";
     }
-  cc_status.flags |= CC_REVERSED;
+  cc_status.flags |= CC_REVERSED; /*|*/
   return "fcmp%.<FP:prec> %f0,%1";
-})
+}
+  [(set_attr "type" "fcmp")])
 
 ;; Recognizers for btst instructions.
 
@@ -578,16 +801,15 @@
 ;; A special case in which it is not desirable
 ;; to reload the constant into a data register.
 (define_insn "pushexthisi_const"
-  [(set (match_operand:SI 0 "push_operand" "=m")
-	(match_operand:SI 1 "const_int_operand" "J"))]
+  [(set (match_operand:SI 0 "push_operand" "=m,m,m")
+	(match_operand:SI 1 "const_int_operand" "C0,R,J"))]
   "INTVAL (operands[1]) >= -0x8000 && INTVAL (operands[1]) < 0x8000"
-{
-  if (operands[1] == const0_rtx)
-    return "clr%.l %0";
-  if (valid_mov3q_const (INTVAL (operands[1])))
-    return "mov3q%.l %1,%-";
-  return "pea %a1";
-})
+  "@
+   clr%.l %0
+   mov3q%.l %1,%-
+   pea %a1"
+  [(set_attr "type" "clr_l,mov3q_l,pea")
+   (set_attr "split" "done")])
 
 ;This is never used.
 ;(define_insn "swapsi"
@@ -597,30 +819,52 @@
 ;  ""
 ;  "exg %1,%0")
 
-;; Special case of fullword move when source is zero.
-;; The reason this is special is to avoid loading a zero
-;; into a data reg with moveq in order to store it elsewhere.
-
-(define_insn "movsi_const0"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=g")
+;; Special case of fullword move when source is zero for 68000_10.
+;; moveq is faster on the 68000.
+(define_insn "*movsi_const0_68000_10"
+  [(set (match_operand:SI 0 "movsi_const0_operand" "=d,a,g")
+	(const_int 0))]
+  "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))]
-  ;; clr insns on 68000 read before writing.
-  "((TARGET_68010 || TARGET_COLDFIRE)
-    || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))"
+  "TUNE_68040_60"
 {
-  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 */
-      if (TUNE_68040_60)
-	return MOTOROLA ? "lea 0.w,%0" : "lea 0:w,%0";
-      else
-	return "sub%.l %0,%0";
+      gcc_unreachable ();
+      return "";
     }
-  /* moveq is faster on the 68000.  */
-  if (DATA_REG_P (operands[0]) && TUNE_68000_10)
-    return "moveq #0,%0";
-  return "clr%.l %0";
-})
+}
+  [(set_attr "type" "lea,clr_l")
+   (set_attr "opy_type" "imm_w,*")
+   (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.
 ;;
@@ -688,10 +932,59 @@
 
 ;; ColdFire move instructions can have at most one operand of mode >= 6.
 (define_insn "*movsi_cf"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r<Q>,g,U")
-	(match_operand:SI 1 "general_operand" "g,Rr<Q>,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"      " R,CQ,CW,CZ,CS,Ci,J,J Cs,Cs, g,   Rr<Q>,U"))]
   "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
 ;; reference into an address register.
@@ -771,11 +1064,17 @@
   "!TARGET_COLDFIRE"
   "* return output_move_strictqi (operands);")
 
-(define_insn ""
-  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+d,m"))
-	(match_operand:QI 1 "general_src_operand" "dmn,d"))]
+(define_insn "*movstrictqi_cf"
+  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+d, Ac, d,m"))
+	(match_operand:QI 1 "general_src_operand"                    "C0,C0, dmn,d"))]
   "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"
   [(set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int -2)))
@@ -864,9 +1163,8 @@
   [(set (match_operand:SF 0 "nonimmediate_operand" "=r<Q>,g,U")
 	(match_operand:SF 1 "general_operand" "g,r<Q>,U"))]
   "TARGET_COLDFIRE && !TARGET_COLDFIRE_FPU"
-{
-  return "move%.l %1,%0";
-})
+  "move%.l %1,%0"
+  [(set_attr "type" "move_l")])
 
 ;; SFmode MEMs are restricted to modes 2-4 if TARGET_COLDFIRE_FPU.
 ;; The move instructions can handle all combinations.
@@ -1003,12 +1301,16 @@
   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")
 	(match_operand:DF 1 "general_operand" "g,r"))]
   "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"
@@ -1230,7 +1532,8 @@
   [(set (match_operand:SI 0 "push_operand" "=m")
 	(match_operand:SI 1 "address_operand" "p"))]
   ""
-  "pea %a1")
+  "pea %a1"
+  [(set_attr "type" "pea")])
 
 ;; truncation instructions
 (define_insn "truncsiqi2"
@@ -1391,7 +1694,8 @@
   [(set (match_operand:SI 0 "register_operand" "=d")
 	(zero_extend:SI (match_operand:HI 1 "nonimmediate_src_operand" "rmS")))]
   "ISA_HAS_MVS_MVZ"
-  "mvz%.w %1,%0")
+  "mvz%.w %1,%0"
+  [(set_attr "type" "mvz_w")])
 
 (define_insn "zero_extendhisi2"
   [(set (match_operand:SI 0 "register_operand" "=d")
@@ -1415,7 +1719,8 @@
   [(set (match_operand:SI 0 "register_operand" "=d")
 	(zero_extend:SI (match_operand:QI 1 "nonimmediate_src_operand" "dmS")))]
   "ISA_HAS_MVS_MVZ"
-  "mvz%.b %1,%0")
+  "mvz%.b %1,%0"
+  [(set_attr "type" "mvz_b")])
 
 (define_insn "zero_extendqisi2"
   [(set (match_operand:SI 0 "register_operand" "=d")
@@ -1567,24 +1872,25 @@
 	(sign_extend:SI
 	 (match_operand:HI 1 "nonimmediate_src_operand" "rmS")))]
   "ISA_HAS_MVS_MVZ"
-  "mvs%.w %1,%0")
+  "mvs%.w %1,%0"
+  [(set_attr "type" "mvs_w")])
 
 (define_insn "*68k_extendhisi2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=*d,a")
 	(sign_extend:SI
 	 (match_operand:HI 1 "nonimmediate_src_operand" "0,rmS")))]
   "!ISA_HAS_MVS_MVZ"
-{
-  if (ADDRESS_REG_P (operands[0]))
-    return "move%.w %1,%0";
-  return "ext%.l %0";
-})
+  "@
+   ext%.l %0
+   move%.w %1,%0"
+  [(set_attr "type" "ext_l,move_w")])
 
 (define_insn "extendqihi2"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=d")
 	(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0")))]
   ""
-  "ext%.w %0")
+  "ext%.w %0"
+  [(set_attr "type" "ext_w")])
 
 (define_expand "extendqisi2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "")
@@ -1596,13 +1902,15 @@
   [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
 	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rms")))]
   "ISA_HAS_MVS_MVZ"
-  "mvs%.b %1,%0")
+  "mvs%.b %1,%0"
+  [(set_attr "type" "mvs_b")])
 
 (define_insn "*68k_extendqisi2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
 	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0")))]
   "TARGET_68020 || (TARGET_COLDFIRE && !ISA_HAS_MVS_MVZ)"
-  "extb%.l %0")
+  "extb%.l %0"
+  [(set_attr "type" "extb_l")])
 
 ;; Conversions between float and double.
 
@@ -1691,14 +1999,16 @@
   "TARGET_COLDFIRE_FPU"
   "@
   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")
 	(float_truncate:SF
 	  (match_operand:DF 1 "general_operand" "f")))]
   "TARGET_68881"
-  "fmove%.s %f1,%0")
+  "fmove%.s %f1,%0"
+  [(set_attr "type" "fmove")])
 
 ;; Conversion between fixed point and floating point.
 ;; Note that among the fix-to-float insns
@@ -1724,7 +2034,8 @@
   [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
 	(float:FP (match_operand:SI 1 "general_operand" "d<Q>U")))]
   "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"
@@ -1737,13 +2048,15 @@
   [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
 	(float:FP (match_operand:HI 1 "general_operand" "dmn")))]
   "TARGET_68881"
-  "fmove%.w %1,%0")
+  "fmove%.w %1,%0"
+  [(set_attr "type" "fmove")])
 
 (define_insn "floathi<mode>2_cf"
   [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
         (float:FP (match_operand:HI 1 "general_operand" "d<Q>U")))]
   "TARGET_COLDFIRE_FPU"
-  "fmove%.w %1,%0")
+  "fmove%.w %1,%0"
+  [(set_attr "type" "fmove")])
 
 
 (define_expand "floatqi<mode>2"
@@ -1756,13 +2069,15 @@
   [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
 	(float:FP (match_operand:QI 1 "general_operand" "dmn")))]
   "TARGET_68881"
-  "fmove%.b %1,%0")
+  "fmove%.b %1,%0"
+  [(set_attr "type" "fmove")])
 
 (define_insn "floatqi<mode>2_cf"
   [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
 	(float:FP (match_operand:QI 1 "general_operand" "d<Q>U")))]
   "TARGET_COLDFIRE_FPU"
-  "fmove%.b %1,%0")
+  "fmove%.b %1,%0"
+  [(set_attr "type" "fmove")])
 
 
 ;; New routines to convert floating-point values to integers
@@ -1830,7 +2145,8 @@
   if (FP_REG_P (operands[1]))
     return "fintrz%.d %f1,%0";
   return "fintrz%.<FP:prec> %f1,%0";
-})
+}
+  [(set_attr "type" "fintrz")])
 
 ;; Convert a float whose value is an integer
 ;; to an actual integer.  Second stage of converting float to integer type.
@@ -1850,7 +2166,8 @@
   [(set (match_operand:QI 0 "nonimmediate_operand" "=d<Q>U")
 	(fix:QI (match_operand:FP 1 "general_operand" "f")))]
   "TARGET_COLDFIRE_FPU"
-  "fmove%.b %1,%0")
+  "fmove%.b %1,%0"
+  [(set_attr "type" "fmove")])
 
 (define_expand "fix<mode>hi2"
   [(set (match_operand:HI 0 "nonimmediate_operand" "")
@@ -1868,7 +2185,8 @@
   [(set (match_operand:HI 0 "nonimmediate_operand" "=d<Q>U")
 	(fix:HI (match_operand:FP 1 "general_operand" "f")))]
   "TARGET_COLDFIRE_FPU"
-  "fmove%.w %1,%0")
+  "fmove%.w %1,%0"
+  [(set_attr "type" "fmove")])
 
 (define_expand "fix<mode>si2"
   [(set (match_operand:SI 0 "nonimmediate_operand" "")
@@ -1886,7 +2204,8 @@
   [(set (match_operand:SI 0 "nonimmediate_operand" "=d<Q>U")
 	(fix:SI (match_operand:FP 1 "general_operand" "f")))]
   "TARGET_COLDFIRE_FPU"
-  "fmove%.l %1,%0")
+  "fmove%.l %1,%0"
+  [(set_attr "type" "fmove")])
 
 
 ;; add instructions
@@ -1984,7 +2303,8 @@
   else
     operands[1] = adjust_address (operands[1], SImode, 4);
   return "add%.l %1,%0";
-})
+}
+  [(set_attr "type" "add_l")])
 
 (define_insn "adddi3"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=o<>,d,d,d")
@@ -2107,12 +2427,54 @@
   "! TARGET_COLDFIRE"
   "* return output_addsi3 (operands);")
 
-(define_insn "*addsi3_5200"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=m,?a,?a,r")
-	(plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0")
-		 (match_operand:SI 2 "general_src_operand" "dIL,rJK,a,mrIKLi")))]
+(define_insn_and_split "*addsi3_5200"
+  [(set (match_operand:SI 0 "nonimmediate_operand"         "=mr,mr,m,r,  ?a,?a,?a,?a")
+	(plus:SI (match_operand:SI 1 "general_operand"     "%0, 0, 0,0,   a, a, r, a")
+		 (match_operand:SI 2 "general_src_operand" " I, L, d,mrKi,Cj,r, a, J")))]
   "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 ""
   [(set (match_operand:SI 0 "nonimmediate_operand" "=a")
@@ -2392,7 +2754,8 @@
   if (FP_REG_P (operands[2]))
     return "f<FP:prec>add%.d %2,%0";
   return "f<FP:prec>add%.<FP:prec> %2,%0";
-})
+}
+  [(set_attr "type" "fadd")])
 
 ;; subtract instructions
 
@@ -2426,7 +2789,8 @@
   else
     operands[1] = adjust_address (operands[1], SImode, 4);
   return "sub%.l %1,%0";
-})
+}
+  [(set_attr "type" "sub_l")])
 
 (define_insn "subdi3"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=o<>,d,d,d")
@@ -2508,11 +2872,17 @@
 })
 
 (define_insn "subsi3"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=m,d,a")
-	(minus:SI (match_operand:SI 1 "general_operand" "0,0,0")
-		  (match_operand:SI 2 "general_src_operand" "dT,mSrT,mSrs")))]
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=mda,m,d,a")
+	(minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
+		  (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 ""
   [(set (match_operand:SI 0 "nonimmediate_operand" "=a")
@@ -2598,7 +2968,8 @@
   if (FP_REG_P (operands[2]))
     return "f<FP:prec>sub%.d %2,%0";
   return "f<FP:prec>sub%.<FP:prec> %2,%0";
-})
+}
+  [(set_attr "type" "fsub")])
 
 ;; multiply instructions
 
@@ -2609,7 +2980,9 @@
   ""
 {
   return MOTOROLA ? "muls%.w %2,%0" : "muls %2,%0";
-})
+}
+  [(set_attr "type" "muls_w")
+   (set_attr "opy" "2")])
 
 (define_insn "mulhisi3"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
@@ -2620,9 +2993,11 @@
   ""
 {
   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")
 	(mult:SI (sign_extend:SI
 		  (match_operand:HI 1 "nonimmediate_operand" "%0"))
@@ -2630,7 +3005,9 @@
   "INTVAL (operands[2]) >= -0x8000 && INTVAL (operands[2]) <= 0x7fff"
 {
   return MOTOROLA ? "muls%.w %2,%0" : "muls %2,%0";
-})
+}
+  [(set_attr "type" "muls_w")
+   (set_attr "opy" "2")])
 
 (define_expand "mulsi3"
   [(set (match_operand:SI 0 "nonimmediate_operand" "")
@@ -2639,20 +3016,24 @@
   "TARGET_68020 || TARGET_COLDFIRE"
   "")
 
-(define_insn ""
+(define_insn "*mulsi3_68020"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
 	(mult:SI (match_operand:SI 1 "general_operand" "%0")
                  (match_operand:SI 2 "general_src_operand" "dmSTK")))]
 
   "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")
 	(mult:SI (match_operand:SI 1 "general_operand" "%0")
 		 (match_operand:SI 2 "general_operand" "d<Q>")))]
   "TARGET_COLDFIRE"
-  "muls%.l %2,%0")
+  "muls%.l %2,%0"
+  [(set_attr "type" "muls_l")
+   (set_attr "opy" "2")])
 
 (define_insn "umulhisi3"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
@@ -2663,9 +3044,11 @@
   ""
 {
   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")
 	(mult:SI (zero_extend:SI
 		  (match_operand:HI 1 "nonimmediate_operand" "%0"))
@@ -2673,7 +3056,9 @@
   "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 0xffff"
 {
   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
 ;; proper matching constraint.  This is because the matching is between
@@ -2932,7 +3317,8 @@
   if (FP_REG_P (operands[2]))
     return "f<FP:prec>mul%.d %2,%0";
   return "f<FP:prec>mul%.<FP:prec> %2,%0";
-})
+}
+  [(set_attr "type" "fmul")])
 
 ;; divide instructions
 
@@ -3000,7 +3386,8 @@
   if (FP_REG_P (operands[2]))
     return "f<FP:prec>div%.d %2,%0";
   return "f<FP:prec>div%.<FP:prec> %2,%0";
-})
+}
+  [(set_attr "type" "fdiv")])
 
 ;; Remainder instructions.
 
@@ -3692,13 +4079,15 @@
   [(set (match_operand:SI 0 "nonimmediate_operand" "=dm")
 	(neg:SI (match_operand:SI 1 "general_operand" "0")))]
   "!TARGET_COLDFIRE"
-  "neg%.l %0")
+  "neg%.l %0"
+  [(set_attr "type" "neg_l")])
 
 (define_insn "negsi2_5200"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
 	(neg:SI (match_operand:SI 1 "general_operand" "0")))]
   "TARGET_COLDFIRE"
-  "neg%.l %0")
+  "neg%.l %0"
+  [(set_attr "type" "neg_l")])
 
 (define_insn "neghi2"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
@@ -3863,7 +4252,8 @@
   if (FP_REG_P (operands[1]))
     return "f<FP:round>sqrt%.x %1,%0";
   return "f<FP:round>sqrt%.<FP:prec> %1,%0";
-})
+}
+  [(set_attr "type" "fsqrt")])
 
 (define_insn "sqrt<mode>2_cf"
   [(set (match_operand:FP 0 "nonimmediate_operand" "=f")
@@ -4005,7 +4395,8 @@
   [(set (match_operand:SI 0 "register_operand" "=d")
  	(clz:SI (match_operand:SI 1 "register_operand" "0")))]
   "ISA_HAS_FF1"
-  "ff1 %0")
+  "ff1 %0"
+  [(set_attr "type" "ff1")])
 
 ;; one complement instructions
 
@@ -4048,7 +4439,8 @@
   [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
 	(not:SI (match_operand:SI 1 "general_operand" "0")))]
   "TARGET_COLDFIRE"
-  "not%.l %0")
+  "not%.l %0"
+  [(set_attr "type" "not_l")])
 
 (define_insn "one_cmplhi2"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
@@ -4399,7 +4791,8 @@
   if (GET_CODE (operands[1]) != REG)
     operands[1] = adjust_address (operands[1], HImode, 2);
   return "move%.w %1,%0";
-})
+}
+  [(set_attr "type" "move_w")])
 
 (define_insn "subregsi1ashrdi_const32"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
@@ -4408,7 +4801,8 @@
   ""
 {
   return "move%.l %1,%0";
-})
+}
+  [(set_attr "type" "move_l")])
 
 (define_insn "*ashrdi3_const1"
   [(set (match_operand:DI 0 "register_operand" "=d")
@@ -4577,7 +4971,9 @@
 	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
 		     (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"
   [(set (match_operand:HI 0 "register_operand" "=d")
@@ -4643,9 +5039,8 @@
     (subreg:SI (lshiftrt:DI (match_operand:DI 1 "general_operand" "ro")
             (const_int 32)) 4))]
   ""
-{
-  return "move%.l %1,%0";
-})
+  "move%.l %1,%0"
+  [(set_attr "type" "move_l")])
 
 (define_insn "*lshrdi3_const1"
   [(set (match_operand:DI 0 "register_operand" "=d")
@@ -4872,7 +5267,9 @@
 	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
 		     (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"
   [(set (match_operand:HI 0 "register_operand" "=d")
@@ -5029,10 +5426,11 @@
 {
   CC_STATUS_INIT;
   return "bset %1,%0";
-})
+}
+  [(set_attr "type" "bset")])
 
 ;; 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")
 	(ior:QI (subreg:QI (ashift:SI (const_int 1)
 	    (match_operator:SI 2 "extend_operator"
@@ -5042,7 +5440,8 @@
 {
   CC_STATUS_INIT;
   return "bset %1,%0";
-})
+}
+  [(set_attr "type" "bset")])
 
 ;; clear bit, bit number is int
 (define_insn "bclrmemqi"
@@ -5055,10 +5454,11 @@
 {
   CC_STATUS_INIT;
   return "bclr %1,%0";
-})
+}
+  [(set_attr "type" "bclr")])
 
 ;; 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")
 	(const_int 1)
 	(minus:SI (const_int 7)
@@ -5069,7 +5469,8 @@
 {
   CC_STATUS_INIT;
   return "bclr %1,%0";
-})
+}
+  [(set_attr "type" "bclr")])
 
 ;; Special cases of bit-field insns which we should
 ;; recognize in preference to the general case.
@@ -5641,14 +6042,15 @@
   ""
   "")
 
-(define_insn ""
+(define_insn "*scc"
   [(set (match_operand:QI 0 "register_operand" "=d")
 	(geu:QI (cc0) (const_int 0)))]
   ""
 {
    cc_status = cc_prev_status;
    return "scc %0";
-})
+}
+  [(set_attr "type" "scc")])
 
 (define_expand "sle"
   [(set (match_operand:QI 0 "register_operand" "")
@@ -5678,14 +6080,15 @@
   ""
   "")
 
-(define_insn ""
+(define_insn "*sls"
   [(set (match_operand:QI 0 "register_operand" "=d")
 	(leu:QI (cc0) (const_int 0)))]
   ""
 {
    cc_status = cc_prev_status;
    return "sls %0";
-})
+}
+  [(set_attr "type" "scc")])
 
 (define_expand "sordered"
   [(set (match_operand:QI 0 "register_operand" "")
@@ -6085,7 +6488,9 @@
     OUTPUT_JUMP ("jbeq %l0", "fbeq %l0", "jbeq %l0");
   else
     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"
   [(set (pc)
@@ -6099,7 +6504,9 @@
     OUTPUT_JUMP ("jbne %l0", "fbne %l0", "jbne %l0");
   else
     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"
   [(set (pc)
@@ -6113,7 +6520,9 @@
     OUTPUT_JUMP ("jbgt %l0", "fbgt %l0", 0);
   else
     OUTPUT_JUMP ("jgt %l0", "fjgt %l0", 0);
-})
+}
+  [(set (attr "type") (symbol_ref "m68k_sched_branch_type (insn)"))
+   (set_attr "split" "done")])
 
 (define_insn "bgtu"
   [(set (pc)
@@ -6124,7 +6533,8 @@
   ""
 {
   return MOTOROLA ? "jbhi %l0" : "jhi %l0";
-})
+}
+  [(set_attr "type" "bcc")])
 
 (define_insn "blt"
   [(set (pc)
@@ -6138,7 +6548,9 @@
     OUTPUT_JUMP ("jblt %l0", "fblt %l0", "jbmi %l0");
   else
     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"
   [(set (pc)
@@ -6149,7 +6561,8 @@
   ""
 {
   return MOTOROLA ? "jbcs %l0" : "jcs %l0";
-})
+}
+  [(set_attr "type" "bcc")])
 
 (define_insn "bge"
   [(set (pc)
@@ -6174,7 +6587,8 @@
   ""
 {
   return MOTOROLA ? "jbcc %l0" : "jcc %l0";
-})
+}
+  [(set_attr "type" "bcc")])
 
 (define_insn "ble"
   [(set (pc)
@@ -6188,7 +6602,8 @@
     OUTPUT_JUMP ("jble %l0", "fble %l0", 0);
   else
     OUTPUT_JUMP ("jle %l0", "fjle %l0", 0);
-})
+}
+  [(set_attr "type" "bcc")])
 
 (define_insn "bleu"
   [(set (pc)
@@ -6199,7 +6614,8 @@
   ""
 {
   return MOTOROLA ? "jbls %l0" : "jls %l0";
-})
+}
+  [(set_attr "type" "bcc")])
 
 (define_insn "bordered"
   [(set (pc)
@@ -6291,7 +6707,7 @@
 
 ;; Negated conditional jump instructions.
 
-(define_insn ""
+(define_insn "*beq2"
   [(set (pc)
 	(if_then_else (eq (cc0)
 			  (const_int 0))
@@ -6303,9 +6719,10 @@
     OUTPUT_JUMP ("jbne %l0", "fbne %l0", "jbne %l0");
   else
     OUTPUT_JUMP ("jne %l0", "fjne %l0", "jne %l0");
-})
+}
+  [(set_attr "type" "bcc")])
 
-(define_insn ""
+(define_insn "*bne2"
   [(set (pc)
 	(if_then_else (ne (cc0)
 			  (const_int 0))
@@ -6317,9 +6734,10 @@
     OUTPUT_JUMP ("jbeq %l0", "fbeq %l0", "jbeq %l0");
   else
     OUTPUT_JUMP ("jeq %l0", "fjeq %l0", "jeq %l0");
-})
+}
+  [(set_attr "type" "bcc")])
 
-(define_insn ""
+(define_insn "*bgt2"
   [(set (pc)
 	(if_then_else (gt (cc0)
 			  (const_int 0))
@@ -6331,9 +6749,10 @@
     OUTPUT_JUMP ("jble %l0", "fbngt %l0", 0);
   else
     OUTPUT_JUMP ("jle %l0", "fjngt %l0", 0);
-})
+}
+  [(set_attr "type" "bcc")])
 
-(define_insn ""
+(define_insn "*bgtu2"
   [(set (pc)
 	(if_then_else (gtu (cc0)
 			   (const_int 0))
@@ -6342,9 +6761,10 @@
   ""
 {
   return MOTOROLA ? "jbls %l0" : "jls %l0";
-})
+}
+  [(set_attr "type" "bcc")])
 
-(define_insn ""
+(define_insn "*blt2"
   [(set (pc)
 	(if_then_else (lt (cc0)
 			  (const_int 0))
@@ -6356,9 +6776,10 @@
     OUTPUT_JUMP ("jbge %l0", "fbnlt %l0", "jbpl %l0");
   else
     OUTPUT_JUMP ("jge %l0", "fjnlt %l0", "jpl %l0");
-})
+}
+  [(set_attr "type" "bcc")])
 
-(define_insn ""
+(define_insn "*bltu2"
   [(set (pc)
 	(if_then_else (ltu (cc0)
 			   (const_int 0))
@@ -6367,9 +6788,10 @@
   ""
 {
   return MOTOROLA ? "jbcc %l0" : "jcc %l0";
-})
+}
+  [(set_attr "type" "bcc")])
 
-(define_insn ""
+(define_insn "*bge2"
   [(set (pc)
 	(if_then_else (ge (cc0)
 			  (const_int 0))
@@ -6381,9 +6803,10 @@
     OUTPUT_JUMP ("jblt %l0", "fbnge %l0", "jbmi %l0");
   else
     OUTPUT_JUMP ("jlt %l0", "fjnge %l0", "jmi %l0");
-})
+}
+  [(set_attr "type" "bcc")])
 
-(define_insn ""
+(define_insn "*bgeu2"
   [(set (pc)
 	(if_then_else (geu (cc0)
 			   (const_int 0))
@@ -6392,9 +6815,10 @@
   ""
 {
   return MOTOROLA ? "jbcs %l0" : "jcs %l0";
-})
+}
+  [(set_attr "type" "bcc")])
 
-(define_insn ""
+(define_insn "*ble2"
   [(set (pc)
 	(if_then_else (le (cc0)
 			  (const_int 0))
@@ -6406,9 +6830,10 @@
     OUTPUT_JUMP ("jbgt %l0", "fbnle %l0", 0);
   else
     OUTPUT_JUMP ("jgt %l0", "fjnle %l0", 0);
-})
+}
+  [(set_attr "type" "bcc")])
 
-(define_insn ""
+(define_insn "*bleu2"
   [(set (pc)
 	(if_then_else (leu (cc0)
 			   (const_int 0))
@@ -6417,7 +6842,8 @@
   ""
 {
   return MOTOROLA ? "jbhi %l0" : "jhi %l0";
-})
+}
+  [(set_attr "type" "bcc")])
 
 (define_insn "*bordered_rev"
   [(set (pc)
@@ -6514,7 +6940,8 @@
   ""
 {
   return MOTOROLA ? "jbra %l0" : "jra %l0";
-})
+}
+  [(set_attr "type" "bra")])
 
 (define_expand "tablejump"
   [(parallel [(set (pc) (match_operand 0 "" ""))
@@ -6528,13 +6955,14 @@
 })
 
 ;; 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"))
    (use (label_ref (match_operand 1 "" "")))]
   ""
 {
   return MOTOROLA ? "jmp (%0)" : "jmp %0@";
-})
+}
+  [(set_attr "type" "bra")])
 
 ;; Jump to variable address from dispatch table of relative addresses.
 (define_insn ""
@@ -6746,16 +7174,46 @@
   operands[1] = m68k_legitimize_call_address (operands[1]);
 })
 
-(define_insn "*call_value"
+(define_insn "*non_symbolic_call_value"
   [(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")))]
   ;; Operand 2 not really used on the m68000.
   "!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];
-  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.
 
@@ -6796,7 +7254,8 @@
 (define_insn "nop"
   [(const_int 0)]
   ""
-  "nop")
+  "nop"
+  [(set_attr "type" "nop")])
 
 (define_expand "prologue"
   [(const_int 0)]
@@ -6849,7 +7308,8 @@
       else
 	return "rts";
     }
-})
+}
+  [(set_attr "type" "rts")])
 
 (define_insn "*m68k_store_multiple"
   [(match_parallel 0 "" [(match_operand 1 "")])]
@@ -6939,7 +7399,8 @@
 	(plus:SI (match_dup 0)
 		 (const_int 4)))]
   ""
-  "unlk %0")
+  "unlk %0"
+  [(set_attr "type" "unlk")])
 
 (define_insn "load_got"
   [(set (match_operand:SI 0 "register_operand" "=a")
@@ -6971,7 +7432,8 @@
 (define_insn "indirect_jump"
   [(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.
 
@@ -7373,10 +7835,12 @@
     return "fcos%.<FP:prec> %1,%0";
 })
 
+;; Unconditional traps are assumed to have (const_int 1) for the condition.
 (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"
   [(trap_if (match_operator 0 "valid_dbcc_comparison_p"
@@ -7399,3 +7863,12 @@
   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")])
--- config/m68k/constraints.md	(/csl/gcc/branches/maxim/fsf-trunk/gcc)	(revision 180896)
+++ config/m68k/constraints.md	(/csl/gcc/branches/maxim/fsf-cf-sched-m68k/gcc)	(revision 180896)
@@ -104,3 +104,51 @@
 (define_constraint "W"
   "Used for const_call_operands."
   (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)")))
--- config/m68k/m68k.c	(/csl/gcc/branches/maxim/fsf-trunk/gcc)	(revision 180896)
+++ config/m68k/m68k.c	(/csl/gcc/branches/maxim/fsf-cf-sched-m68k/gcc)	(revision 180896)
@@ -353,6 +353,10 @@ unsigned int m68k_cpu_flags;
    in operand 0.  */
 const char *m68k_symbolic_call;
 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
    store the entry in *ENTRY if so, otherwise return false and
@@ -563,11 +567,11 @@ override_options (void)
 
   if (!flag_pic)
     {
+      m68k_symbolic_call_var = M68K_SYMBOLIC_CALL_JSR;
+
 #if MOTOROLA && !defined (USE_GAS)
-      m68k_symbolic_call = "jsr %a0";
       m68k_symbolic_jump = "jmp %a0";
 #else
-      m68k_symbolic_call = "jbsr %a0";
       m68k_symbolic_jump = "jra %a0";
 #endif
     }
@@ -577,15 +581,10 @@ override_options (void)
   else if (TARGET_68020 || TARGET_ISAB || TARGET_ISAC)
     {
       if (TARGET_PCREL)
-	m68k_symbolic_call = "bsr.l %c0";
+	m68k_symbolic_call_var = M68K_SYMBOLIC_CALL_BSR_C;
       else
-	{
-#if defined(USE_GAS)
-	  m68k_symbolic_call = "bsr.l %p0";
-#else
-	  m68k_symbolic_call = "bsr %p0";
-#endif
-	}
+	m68k_symbolic_call_var = M68K_SYMBOLIC_CALL_BSR_P;
+
       if (TARGET_ISAC)
 	/* No unconditional long branch */;
       else if (TARGET_PCREL)
@@ -605,7 +604,48 @@ override_options (void)
       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;
+
+  /* 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
@@ -2039,14 +2079,13 @@ legitimize_pic_address (rtx orig, enum m
 }
 
 
-typedef enum { MOVL, SWAP, NEGW, NOTW, NOTB, MOVQ, MVS, MVZ } CONST_METHOD;
 
 #define USE_MOVQ(i)	((unsigned) ((i) + 128) <= 255)
 
 /* Return the type of move that should be used for integer I.  */
 
-static CONST_METHOD
-const_method (HOST_WIDE_INT i)
+M68K_CONST_METHOD
+m68k_const_method (HOST_WIDE_INT i)
 {
   unsigned u;
 
@@ -2092,7 +2131,7 @@ const_method (HOST_WIDE_INT i)
 static int
 const_int_cost (HOST_WIDE_INT i)
 {
-  switch (const_method (i))
+  switch (m68k_const_method (i))
     {
     case MOVQ:
       /* Constants between -128 and 127 are cheap due to moveq.  */
@@ -2256,7 +2295,7 @@ output_move_const_into_data_reg (rtx *op
   HOST_WIDE_INT i;
 
   i = INTVAL (operands[1]);
-  switch (const_method (i))
+  switch (m68k_const_method (i))
     {
     case MVZ:
       return "mvzw %1,%0";
@@ -2480,11 +2519,18 @@ singlemove_string (rtx *operands)
 }
 
 
-/* Output assembler code to perform a doubleword move insn
-   with operands OPERANDS.  */
+/* Output assembler or rtl code to perform a doubleword move insn
+   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 *
-output_move_double (rtx *operands)
+static void
+handle_move_double (rtx operands[2],
+		    void (*handle_reg_adjust) (rtx, int),
+		    void (*handle_compadr) (rtx [2]),
+		    void (*handle_movsi) (rtx [2]))
 {
   enum
     {
@@ -2542,10 +2588,9 @@ output_move_double (rtx *operands)
   if (optype0 == PUSHOP && optype1 == POPOP)
     {
       operands[0] = XEXP (XEXP (operands[0], 0), 0);
-      if (size == 12)
-        output_asm_insn ("sub%.l #12,%0", operands);
-      else
-        output_asm_insn ("subq%.l #8,%0", operands);
+
+      handle_reg_adjust (operands[0], -size);
+
       if (GET_MODE (operands[1]) == XFmode)
 	operands[0] = gen_rtx_MEM (XFmode, operands[0]);
       else if (GET_MODE (operands[0]) == DFmode)
@@ -2557,10 +2602,9 @@ output_move_double (rtx *operands)
   if (optype0 == POPOP && optype1 == PUSHOP)
     {
       operands[1] = XEXP (XEXP (operands[1], 0), 0);
-      if (size == 12)
-        output_asm_insn ("sub%.l #12,%1", operands);
-      else
-        output_asm_insn ("subq%.l #8,%1", operands);
+
+      handle_reg_adjust (operands[1], -size);
+
       if (GET_MODE (operands[1]) == XFmode)
 	operands[1] = gen_rtx_MEM (XFmode, operands[1]);
       else if (GET_MODE (operands[1]) == DFmode)
@@ -2602,8 +2646,8 @@ output_move_double (rtx *operands)
 	}
       else
 	{
-	  middlehalf[0] = operands[0];
-	  latehalf[0] = operands[0];
+	  middlehalf[0] = adjust_address (operands[0], SImode, 0);
+	  latehalf[0] = adjust_address (operands[0], SImode, 0);
 	}
 
       if (optype1 == REGOP)
@@ -2638,8 +2682,8 @@ output_move_double (rtx *operands)
 	}
       else
 	{
-	  middlehalf[1] = operands[1];
-	  latehalf[1] = operands[1];
+	  middlehalf[1] = adjust_address (operands[1], SImode, 0);
+	  latehalf[1] = adjust_address (operands[1], SImode, 0);
 	}
     }
   else
@@ -2650,7 +2694,7 @@ output_move_double (rtx *operands)
       else if (optype0 == OFFSOP)
 	latehalf[0] = adjust_address (operands[0], SImode, size - 4);
       else
-	latehalf[0] = operands[0];
+	latehalf[0] = adjust_address (operands[0], SImode, 0);
 
       if (optype1 == REGOP)
 	latehalf[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
@@ -2659,7 +2703,7 @@ output_move_double (rtx *operands)
       else if (optype1 == CNSTOP)
 	split_double (operands[1], &operands[1], &latehalf[1]);
       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
@@ -2689,8 +2733,9 @@ output_move_double (rtx *operands)
 	compadr:
 	  xops[0] = latehalf[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]);
 	      middlehalf[1] = adjust_address (operands[1], DImode, size - 8);
@@ -2720,10 +2765,11 @@ output_move_double (rtx *operands)
 	  gcc_assert (!addreg0 && !addreg1);
 
 	  /* Only the middle reg conflicts; simply put it last.  */
-	  output_asm_insn (singlemove_string (operands), operands);
-	  output_asm_insn (singlemove_string (latehalf), latehalf);
-	  output_asm_insn (singlemove_string (middlehalf), middlehalf);
-	  return "";
+	  handle_movsi (operands);
+	  handle_movsi (latehalf);
+	  handle_movsi (middlehalf);
+
+	  return;
 	}
       else if (reg_overlap_mentioned_p (testlow, XEXP (operands[1], 0)))
 	/* If the low half of dest is mentioned in the source memory
@@ -2747,85 +2793,194 @@ output_move_double (rtx *operands)
     {
       /* Make any unoffsettable addresses point at high-numbered word.  */
       if (addreg0)
-	{
-	  if (size == 12)
-	    output_asm_insn ("addq%.l #8,%0", &addreg0);
-	  else
-	    output_asm_insn ("addq%.l #4,%0", &addreg0);
-	}
+	handle_reg_adjust (addreg0, size - 4);
       if (addreg1)
-	{
-	  if (size == 12)
-	    output_asm_insn ("addq%.l #8,%0", &addreg1);
-	  else
-	    output_asm_insn ("addq%.l #4,%0", &addreg1);
-	}
+	handle_reg_adjust (addreg1, size - 4);
 
       /* Do that word.  */
-      output_asm_insn (singlemove_string (latehalf), latehalf);
+      handle_movsi (latehalf);
 
       /* Undo the adds we just did.  */
       if (addreg0)
-	output_asm_insn ("subq%.l #4,%0", &addreg0);
+	handle_reg_adjust (addreg0, -4);
       if (addreg1)
-	output_asm_insn ("subq%.l #4,%0", &addreg1);
+	handle_reg_adjust (addreg1, -4);
 
       if (size == 12)
 	{
-	  output_asm_insn (singlemove_string (middlehalf), middlehalf);
+	  handle_movsi (middlehalf);
+
 	  if (addreg0)
-	    output_asm_insn ("subq%.l #4,%0", &addreg0);
+	    handle_reg_adjust (addreg0, -4);
 	  if (addreg1)
-	    output_asm_insn ("subq%.l #4,%0", &addreg1);
+	    handle_reg_adjust (addreg1, -4);
 	}
 
       /* Do low-numbered word.  */
-      return singlemove_string (operands);
+
+      handle_movsi (operands);
+      return;
     }
 
   /* 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 */
   if (size == 12)
     {
       if (addreg0)
-	output_asm_insn ("addq%.l #4,%0", &addreg0);
+	handle_reg_adjust (addreg0, 4);
       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.  */
   if (addreg0)
-    output_asm_insn ("addq%.l #4,%0", &addreg0);
+    handle_reg_adjust (addreg0, 4);
   if (addreg1)
-    output_asm_insn ("addq%.l #4,%0", &addreg1);
+    handle_reg_adjust (addreg1, 4);
 
   /* Do that word.  */
-  output_asm_insn (singlemove_string (latehalf), latehalf);
+  handle_movsi (latehalf);
 
   /* Undo the adds we just did.  */
   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)
-        output_asm_insn ("subq%.l #8,%0", &addreg0);
-      else
-        output_asm_insn ("subq%.l #4,%0", &addreg0);
+    case 12:
+      s = "add%.l #12,%0";
+      break;
+
+    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)
-        output_asm_insn ("subq%.l #8,%0", &addreg1);
+      if (REG_P (op))
+	op = gen_rtx_REG (mode, REGNO (op));
       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 "";
 }
 
+/* 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
    new rtx with the correct mode.  */
@@ -4434,3 +4589,455 @@ m68k_return_in_memory (tree type, tree f
   return false;
 }
 #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;
+}
--- config/m68k/m68k.h	(/csl/gcc/branches/maxim/fsf-trunk/gcc)	(revision 180896)
+++ config/m68k/m68k.h	(/csl/gcc/branches/maxim/fsf-cf-sched-m68k/gcc)	(revision 180896)
@@ -1125,3 +1125,27 @@ extern enum fpu_type m68k_fpu;
 extern unsigned int m68k_cpu_flags;
 extern const char *m68k_symbolic_call;
 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);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]