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]

Contribution: Support for Cirrus Maverick EP9312 chip


Hi Guys,

  I am applying the patch below to add support for Cirrus's EP9312
  chip, an ARM variant which includes their Maverick floating point
  co-processor.  The port was written by Aldy Hernandez a while ago,
  and I have now, finally, found time to submit it.

  The port still has some problems with its floating point handling,
  and it only really works with an ELF target, since I have not
  arranged for a way to label COFF binaries as supporting the Maverick
  co-processor.  Also, although I have added code to t-arm-elf to
  generate the multilibs to support the EP9312, they are currently
  commented out, in order to save time and disk space for majority of
  people using the arm-elf port.

  I tried to keep most of the new instruction patterns in a new
  cirrus.md file, but for some it was necessary to add them to the
  arm.md file, in order for them to be in the correct place.

  I have remembered to create an entry for the HTML documentation this
  time, although the notes include a mention of the patch to the
  t-arm-elf file.  I am not sure if some special formatting tags are
  needed for this path.

Cheers
        Nick


gcc/ChangeLog
2003-02-10  Nick Clifton  <nickc@redhat.com>

	* Contributed support for the Cirrus EP9312 "Maverick"
	floating point co-processor.  Written by Aldy Hernandez
	<aldyh@redhat.com>. 
	(config/arm/arm.c): Add Cirrus support.
	(config/arm/arm.h): Likewise.
	(config/arm/aout.h): Likewise.
	(config/arm/arm.md): Likewise.
	(config/arm/arm-protos.h): Likewise.
	(config.gcc): Likewise.
	(doc/invoke.texi): Describe new -mcpu value and new
	-mcirrus-fix-invalid-insns switch,
	(cirrus.md): New file.

Index: gcc/config.gcc
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config.gcc,v
retrieving revision 1.282
diff -c -3 -p -w -r1.282 config.gcc
*** gcc/config.gcc	6 Feb 2003 21:17:12 -0000	1.282
--- gcc/config.gcc	10 Feb 2003 11:23:30 -0000
*************** strongarm*-*-*)
*** 259,264 ****
--- 259,267 ----
  arm*-*-*)
  	cpu_type=arm
  	;;
+ ep9312*-*-*)
+ 	cpu_type=arm
+ 	;;
  xscale-*-*)
  	cpu_type=arm
  	;;
*************** arm*-*-rtems*)
*** 700,706 ****
  	  thread_file='rtems'
  	fi
  	;;
! arm*-*-elf)
  	tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/aout.h arm/arm.h"
  	tmake_file=arm/t-arm-elf
  	;;
--- 703,709 ----
  	  thread_file='rtems'
  	fi
  	;;
! arm*-*-elf | ep9312-*-elf)
  	tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/aout.h arm/arm.h"
  	tmake_file=arm/t-arm-elf
  	;;
*************** arm*-*-*)
*** 2789,2794 ****
--- 2792,2798 ----
  		| xarm7m | xarm7dm | xarm7dmi | xarm[79]tdmi \
  		| xarm7100 | xarm7500 | xarm7500fe | xarm810 \
  		| xxscale \
+ 		| xep9312 \
  		| xstrongarm | xstrongarm110 | xstrongarm1100)
  			target_cpu_default2="TARGET_CPU_$with_cpu"
  			;;
*************** arm*-*-*)
*** 2804,2809 ****
--- 2808,2818 ----
  				echo "Unknown cpu used with --with-cpu=$with_cpu" 1>&2
  				exit 1
  			fi
+ 			;;
+ 	esac
+ 	case $machine in
+ 		9ep9312-*-*)
+ 			target_cpu_default2="TARGET_CPU_9ep9312"
  			;;
  	esac
  	;;

Index: gcc/config/arm/aout.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/aout.h,v
retrieving revision 1.28
diff -c -3 -p -w -r1.28 aout.h
*** gcc/config/arm/aout.h	16 Dec 2002 18:20:54 -0000	1.28
--- gcc/config/arm/aout.h	10 Feb 2003 11:23:37 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 73,79 ****
    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",  \
    "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc",  \
    "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",  \
!   "cc", "sfp", "afp"		   		   \
  }
  #endif
  
--- 73,82 ----
    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",  \
    "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc",  \
    "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",  \
!   "cc", "sfp", "afp",		   		   \
!   "mv0",  "mv1",   "mv2",  "mv3",  "mv4",   "mv5", \
!   "mv6",  "mv7",   "mv8",  "mv9",  "mv10",  "mv11",\
!   "mv12", "mv13",  "mv14", "mv15"		   \
  }
  #endif
  
*************** Boston, MA 02111-1307, USA.  */
*** 98,104 ****
    {"r12", 12},	/* ip */			\
    {"r13", 13},	/* sp */			\
    {"r14", 14},	/* lr */			\
!   {"r15", 15}	/* pc */			\
  }
  #endif
  
--- 101,171 ----
    {"r12", 12},	/* ip */			\
    {"r13", 13},	/* sp */			\
    {"r14", 14},	/* lr */			\
!   {"r15", 15},	/* pc */			\
!   {"mvf0", 27},					\
!   {"mvf1", 28},					\
!   {"mvf2", 29},					\
!   {"mvf3", 30},					\
!   {"mvf4", 31},					\
!   {"mvf5", 32},					\
!   {"mvf6", 33},					\
!   {"mvf7", 34},					\
!   {"mvf8", 35},					\
!   {"mvf9", 36},					\
!   {"mvf10", 37},				\
!   {"mvf11", 38},				\
!   {"mvf12", 39},				\
!   {"mvf13", 40},				\
!   {"mvf14", 41},				\
!   {"mvf15", 42},				\
!   {"mvd0", 27},					\
!   {"mvd1", 28},					\
!   {"mvd2", 29},					\
!   {"mvd3", 30},					\
!   {"mvd4", 31},					\
!   {"mvd5", 32},					\
!   {"mvd6", 33},					\
!   {"mvd7", 34},					\
!   {"mvd8", 35},					\
!   {"mvd9", 36},					\
!   {"mvd10", 37},				\
!   {"mvd11", 38},				\
!   {"mvd12", 39},				\
!   {"mvd13", 40},				\
!   {"mvd14", 41},				\
!   {"mvd15", 42},				\
!   {"mvfx0", 27},				\
!   {"mvfx1", 28},				\
!   {"mvfx2", 29},				\
!   {"mvfx3", 30},				\
!   {"mvfx4", 31},				\
!   {"mvfx5", 32},				\
!   {"mvfx6", 33},				\
!   {"mvfx7", 34},				\
!   {"mvfx8", 35},				\
!   {"mvfx9", 36},				\
!   {"mvfx10", 37},				\
!   {"mvfx11", 38},				\
!   {"mvfx12", 39},				\
!   {"mvfx13", 40},				\
!   {"mvfx14", 41},				\
!   {"mvfx15", 42},				\
!   {"mvdx0", 27},				\
!   {"mvdx1", 28},				\
!   {"mvdx2", 29},				\
!   {"mvdx3", 30},				\
!   {"mvdx4", 31},				\
!   {"mvdx5", 32},				\
!   {"mvdx6", 33},				\
!   {"mvdx7", 34},				\
!   {"mvdx8", 35},				\
!   {"mvdx9", 36},				\
!   {"mvdx10", 37},				\
!   {"mvdx11", 38},				\
!   {"mvdx12", 39},				\
!   {"mvdx13", 40},				\
!   {"mvdx14", 41},				\
!   {"mvdx15", 42}				\
  }
  #endif
  
Index: gcc/config/arm/arm-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm-protos.h,v
retrieving revision 1.47
diff -c -3 -p -w -r1.47 arm-protos.h
*** gcc/config/arm/arm-protos.h	5 Feb 2003 22:37:53 -0000	1.47
--- gcc/config/arm/arm-protos.h	10 Feb 2003 11:23:37 -0000
*************** extern int    logical_binary_operator	PA
*** 94,99 ****
--- 94,104 ----
  extern int    multi_register_push	PARAMS ((rtx, enum machine_mode));
  extern int    load_multiple_operation	PARAMS ((rtx, enum machine_mode));
  extern int    store_multiple_operation	PARAMS ((rtx, enum machine_mode));
+ extern int    cirrus_fp_register	PARAMS ((rtx, enum machine_mode));
+ extern int    cirrus_general_operand	PARAMS ((rtx, enum machine_mode));
+ extern int    cirrus_register_operand	PARAMS ((rtx, enum machine_mode));
+ extern int    cirrus_shift_const	PARAMS ((rtx, enum machine_mode));
+ extern int    cirrus_memory_offset	PARAMS ((rtx));
  
  extern int    symbol_mentioned_p	PARAMS ((rtx));
  extern int    label_mentioned_p		PARAMS ((rtx));
*************** extern rtx    arm_va_arg                
*** 149,155 ****
  extern int    arm_function_arg_pass_by_reference PARAMS ((CUMULATIVE_ARGS *,
  							 enum machine_mode,
  						         tree, int));
- 
  #endif
  
  #if defined AOF_ASSEMBLER 
--- 154,159 ----

Index: gcc/config/arm/arm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.257
diff -c -3 -p -w -r1.257 arm.c
*** gcc/config/arm/arm.c	5 Feb 2003 22:37:53 -0000	1.257
--- gcc/config/arm/arm.c	10 Feb 2003 11:23:45 -0000
*************** typedef struct minipool_fixup   Mfix;
*** 62,67 ****
--- 62,73 ----
  #define Ulong    unsigned long
  #define Ccstar   const char *
  
+ const char extra_reg_names1[][16] =
+ { "mv0", "mv1", "mv2",  "mv3",  "mv4",  "mv5",  "mv6",  "mv7",
+   "mv8", "mv9", "mv10", "mv11", "mv12", "mv13", "mv14", "mv15"
+ };
+ #define extra_reg_names1 bogus1_regnames
+ 
  const struct attribute_spec arm_attribute_table[];
  
  /* Forward function declarations.  */
*************** static int arm_rtx_costs_1			PARAMS ((rt
*** 144,149 ****
--- 150,158 ----
  							 enum rtx_code));
  static bool arm_rtx_costs			PARAMS ((rtx, int, int, int*));
  static int arm_address_cost			PARAMS ((rtx));
+ static int 	 is_load_address                PARAMS ((rtx));
+ static int       is_cirrus_insn                 PARAMS ((rtx));
+ static void      cirrus_reorg                   PARAMS ((rtx));
  
  #undef Hint
  #undef Mmode
*************** int    arm_structure_size_boundary = DEF
*** 263,268 ****
--- 272,278 ----
  #define FL_STRONG     (1 << 8)	      /* StrongARM */
  #define FL_ARCH5E     (1 << 9)        /* DSP extensions to v5 */
  #define FL_XSCALE     (1 << 10)	      /* XScale */
+ #define FL_CIRRUS     (1 << 11)	      /* Cirrus/DSP.  */
  
  /* The bits in this mask specify which
     instructions we are allowed to generate.  */
*************** int arm_is_xscale = 0;
*** 301,306 ****
--- 311,319 ----
  /* Nonzero if this chip is an ARM6 or an ARM7.  */
  int arm_is_6_or_7 = 0;
  
+ /* Nonzero if this chip is a Cirrus/DSP.  */
+ int arm_is_cirrus = 0;
+ 
  /* Nonzero if generating Thumb instructions.  */
  int thumb_code = 0;
  
*************** static const struct processors all_cores
*** 391,396 ****
--- 404,410 ----
    {"arm940t",	                         FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED },
    {"arm9tdmi",	                         FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED },
    {"arm9e",	       	      		 FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED },
+   {"ep9312",	   			 FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED |             FL_CIRRUS },
    {"strongarm",	             FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED | FL_STRONG },
    {"strongarm110",           FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED | FL_STRONG },
    {"strongarm1100",          FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 |            FL_LDSCHED | FL_STRONG },
*************** static const struct processors all_archi
*** 417,422 ****
--- 431,437 ----
    { "armv5",     FL_CO_PROC |             FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 },
    { "armv5t",    FL_CO_PROC |             FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 },
    { "armv5te",   FL_CO_PROC |             FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 | FL_ARCH5E },
+   { "ep9312",				  FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED | FL_CIRRUS },
    { NULL, 0 }
  };
  
*************** arm_override_options ()
*** 514,519 ****
--- 529,535 ----
  	{ TARGET_CPU_arm9,      "arm9" },
  	{ TARGET_CPU_strongarm, "strongarm" },
  	{ TARGET_CPU_xscale,    "xscale" },
+ 	{ TARGET_CPU_ep9312,    "ep9312" },
  	{ TARGET_CPU_generic,   "arm" },
  	{ 0, 0 }
        };
*************** arm_override_options ()
*** 712,718 ****
--- 728,744 ----
    thumb_code	    = (TARGET_ARM == 0);
    arm_is_6_or_7     = (((tune_flags & (FL_MODE26 | FL_MODE32))
  		       && !(tune_flags & FL_ARCH4))) != 0;
+   arm_is_cirrus	    = (tune_flags & FL_CIRRUS) != 0;
  
+   if (arm_is_cirrus)
+     {
+       arm_fpu = FP_CIRRUS;
+ 
+       /* Ignore -mhard-float if -mcpu=ep9312.  */
+       if (TARGET_HARD_FLOAT)
+ 	target_flags ^= ARM_FLAG_SOFT_FLOAT;
+     }
+   else
      /* Default value for floating point code... if no co-processor
         bus, then schedule for emulated floating point.  Otherwise,
         assume the user has an FPA.
*************** arm_override_options ()
*** 733,740 ****
    else
      arm_fpu_arch = FP_DEFAULT;
    
!   if (TARGET_FPE && arm_fpu != FP_HARD)
      arm_fpu = FP_SOFT2;
    
    /* For arm2/3 there is no need to do any scheduling if there is only
       a floating point emulator, or we are doing software floating-point.  */
--- 759,773 ----
    else
      arm_fpu_arch = FP_DEFAULT;
    
!   if (TARGET_FPE)
!     {
!       if (arm_fpu == FP_SOFT3)
  	arm_fpu = FP_SOFT2;
+       else if (arm_fpu == FP_CIRRUS)
+ 	warning ("-mpfpe switch not supported by ep9312 target cpu - ignored.");
+       else if (arm_fpu != FP_HARD)
+     arm_fpu = FP_SOFT2;
+     }
    
    /* For arm2/3 there is no need to do any scheduling if there is only
       a floating point emulator, or we are doing software floating-point.  */
*************** arm_return_in_memory (type)
*** 1902,1907 ****
--- 1935,1942 ----
  int
  arm_float_words_big_endian ()
  {
+   if (TARGET_CIRRUS)
+     return 0;
  
    /* For FPA, float words are always big-endian.  For VFP, floats words
       follow the memory system mode.  */
*************** arm_legitimate_index_p (mode, index, str
*** 2688,2693 ****
--- 2723,2734 ----
  	    && INTVAL (index) > -1024
  	    && (INTVAL (index) & 3) == 0);
  
+   if (TARGET_CIRRUS
+       && (GET_MODE_CLASS (mode) == MODE_FLOAT || mode == DImode))
+     return (code == CONST_INT
+ 	    && INTVAL (index) < 255
+ 	    && INTVAL (index) > -255);
+ 
    if (arm_address_register_rtx_p (index, strict_p)
        && GET_MODE_SIZE (mode) <= 4)
      return 1;
*************** fpu_add_operand (op, mode)
*** 3856,3861 ****
--- 3897,4158 ----
    return FALSE;
  }
  
+ /* Return nonzero if OP is a valid Cirrus memory address pattern.  */
+ 
+ int
+ cirrus_memory_offset (op)
+      rtx op;
+ {
+   /* Reject eliminable registers.  */
+   if (! (reload_in_progress || reload_completed)
+       && (   reg_mentioned_p (frame_pointer_rtx, op)
+ 	  || reg_mentioned_p (arg_pointer_rtx, op)
+ 	  || reg_mentioned_p (virtual_incoming_args_rtx, op)
+ 	  || reg_mentioned_p (virtual_outgoing_args_rtx, op)
+ 	  || reg_mentioned_p (virtual_stack_dynamic_rtx, op)
+ 	  || reg_mentioned_p (virtual_stack_vars_rtx, op)))
+     return 0;
+ 
+   if (GET_CODE (op) == MEM)
+     {
+       rtx ind;
+ 
+       ind = XEXP (op, 0);
+ 
+       /* Match: (mem (reg)).  */
+       if (GET_CODE (ind) == REG)
+ 	return 1;
+ 
+       /* Match:
+ 	 (mem (plus (reg)
+ 	            (const))).  */
+       if (GET_CODE (ind) == PLUS
+ 	  && GET_CODE (XEXP (ind, 0)) == REG
+ 	  && REG_MODE_OK_FOR_BASE_P (XEXP (ind, 0), VOIDmode)
+ 	  && GET_CODE (XEXP (ind, 1)) == CONST_INT)
+ 	return 1;
+     }
+ 
+   return 0;
+ }
+ 
+ /* Return nonzero if OP is a Cirrus or general register.  */
+ 
+ int
+ cirrus_register_operand (op, mode)
+      rtx op;
+      enum machine_mode mode;
+ {
+   if (GET_MODE (op) != mode && mode != VOIDmode)
+     return FALSE;
+ 
+   if (GET_CODE (op) == SUBREG)
+     op = SUBREG_REG (op);
+ 
+   return (GET_CODE (op) == REG
+ 	  && (REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS
+ 	      || REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS));
+ }
+ 
+ /* Return nonzero if OP is a cirrus FP register.  */
+ 
+ int
+ cirrus_fp_register (op, mode)
+      rtx op;
+      enum machine_mode mode;
+ {
+   if (GET_MODE (op) != mode && mode != VOIDmode)
+     return FALSE;
+ 
+   if (GET_CODE (op) == SUBREG)
+     op = SUBREG_REG (op);
+ 
+   return (GET_CODE (op) == REG
+ 	  && (REGNO (op) >= FIRST_PSEUDO_REGISTER
+ 	      || REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS));
+ }
+ 
+ /* Return nonzero if OP is a 6bit constant (0..63).  */
+ 
+ int
+ cirrus_shift_const (op, mode)
+      rtx op;
+      enum machine_mode mode ATTRIBUTE_UNUSED;
+ {
+   return (GET_CODE (op) == CONST_INT
+ 	  && INTVAL (op) >= 0
+ 	  && INTVAL (op) < 64);
+ }
+ 
+ /* Return nonzero if INSN is an LDR R0,ADDR instruction.  */
+ 
+ static int
+ is_load_address (insn)
+      rtx insn;
+ {
+   rtx body, lhs, rhs;;
+ 
+   if (!insn)
+     return 0;
+ 
+   if (GET_CODE (insn) != INSN)
+     return 0;
+ 
+   body = PATTERN (insn);
+ 
+   if (GET_CODE (body) != SET)
+     return 0;
+ 
+   lhs = XEXP (body, 0);
+   rhs = XEXP (body, 1);
+ 
+   return (GET_CODE (lhs) == REG
+ 	  && REGNO_REG_CLASS (REGNO (lhs)) == GENERAL_REGS
+ 	  && (GET_CODE (rhs) == MEM
+ 	      || GET_CODE (rhs) == SYMBOL_REF));
+ }
+ 
+ /* Return nonzero if INSN is a Cirrus instruction.  */
+ 
+ static int
+ is_cirrus_insn (insn)
+      rtx insn;
+ {
+   enum attr_cirrus attr;
+ 
+   /* get_attr aborts on USE and CLOBBER.  */
+   if (!insn
+       || GET_CODE (insn) != INSN
+       || GET_CODE (PATTERN (insn)) == USE
+       || GET_CODE (PATTERN (insn)) == CLOBBER)
+     return 0;
+ 
+   attr = get_attr_cirrus (insn);
+ 
+   return attr != CIRRUS_NO;
+ }
+ 
+ /* Cirrus reorg for invalid instruction combinations.  */
+ 
+ static void
+ cirrus_reorg (first)
+      rtx first;
+ {
+   enum attr_cirrus attr;
+   rtx body = PATTERN (first);
+   rtx t;
+   int nops;
+ 
+   /* Any branch must be followed by 2 non Cirrus instructions.  */
+   if (GET_CODE (first) == JUMP_INSN && GET_CODE (body) != RETURN)
+     {
+       nops = 0;
+       t = next_nonnote_insn (first);
+ 
+       if (is_cirrus_insn (t))
+ 	++ nops;
+ 
+       if (is_cirrus_insn (next_nonnote_insn (t)))
+ 	++ nops;
+ 
+       while (nops --)
+ 	emit_insn_after (gen_nop (), first);
+ 
+       return;
+     }
+ 
+   /* (float (blah)) is in parallel with a clobber.  */
+   if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0)
+     body = XVECEXP (body, 0, 0);
+ 
+   if (GET_CODE (body) == SET)
+     {
+       rtx lhs = XEXP (body, 0), rhs = XEXP (body, 1);
+ 
+       /* cfldrd, cfldr64, cfstrd, cfstr64 must
+ 	 be followed by a non Cirrus insn.  */
+       if (get_attr_cirrus (first) == CIRRUS_DOUBLE)
+ 	{
+ 	  if (is_cirrus_insn (next_nonnote_insn (first)))
+ 	    emit_insn_after (gen_nop (), first);
+ 
+ 	  return;
+ 	}
+       else if (is_load_address (first))
+ 	{
+ 	  unsigned int arm_regno;
+ 
+ 	  /* Any ldr/cfmvdlr, ldr/cfmvdhr, ldr/cfmvsr, ldr/cfmv64lr,
+ 	     ldr/cfmv64hr combination where the Rd field is the same
+ 	     in both instructions must be split with a non Cirrus
+ 	     insn.  Example:
+ 
+ 	     ldr r0, blah
+ 	     nop
+ 	     cfmvsr mvf0, r0.  */
+ 
+ 	  /* Get Arm register number for ldr insn.  */
+ 	  if (GET_CODE (lhs) == REG)
+ 	    arm_regno = REGNO (lhs);
+ 	  else if (GET_CODE (rhs) == REG)
+ 	    arm_regno = REGNO (rhs);
+ 	  else
+ 	    abort ();
+ 
+ 	  /* Next insn.  */
+ 	  first = next_nonnote_insn (first);
+ 
+ 	  if (!is_cirrus_insn (first))
+ 	    return;
+ 
+ 	  body = PATTERN (first);
+ 
+           /* (float (blah)) is in parallel with a clobber.  */
+           if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0))
+ 	    body = XVECEXP (body, 0, 0);
+ 
+ 	  if (GET_CODE (body) == FLOAT)
+ 	    body = XEXP (body, 0);
+ 
+ 	  if (get_attr_cirrus (first) == CIRRUS_MOVE
+ 	      && GET_CODE (XEXP (body, 1)) == REG
+ 	      && arm_regno == REGNO (XEXP (body, 1)))
+ 	    emit_insn_after (gen_nop (), first);
+ 
+ 	  return;
+ 	}
+     }
+ 
+   /* get_attr aborts on USE and CLOBBER.  */
+   if (!first
+       || GET_CODE (first) != INSN
+       || GET_CODE (PATTERN (first)) == USE
+       || GET_CODE (PATTERN (first)) == CLOBBER)
+     return;
+ 
+   attr = get_attr_cirrus (first);
+ 
+   /* Any coprocessor compare instruction (cfcmps, cfcmpd, ...)
+      must be followed by a non-coprocessor instruction.  */
+   if (attr == CIRRUS_COMPARE)
+     {
+       nops = 0;
+ 
+       t = next_nonnote_insn (first);
+ 
+       if (is_cirrus_insn (t))
+ 	++ nops;
+ 
+       if (is_cirrus_insn (next_nonnote_insn (t)))
+ 	++ nops;
+ 
+       while (nops --)
+ 	emit_insn_after (gen_nop (), first);
+ 
+       return;
+     }
+ }
+ 
  /* Return nonzero if OP is a constant power of two.  */
  
  int
*************** arm_select_cc_mode (op, x, y)
*** 5355,5360 ****
--- 5652,5659 ----
  	case LE:
  	case GT:
  	case GE:
+ 	  if (TARGET_CIRRUS)
+ 	    return CCFPmode;
  	  return CCFPEmode;
  
  	default:
*************** arm_reorg (first)
*** 6678,6683 ****
--- 6977,6988 ----
    /* Scan all the insns and record the operands that will need fixing.  */
    for (insn = next_nonnote_insn (first); insn; insn = next_nonnote_insn (insn))
      {
+       if (TARGET_CIRRUS_FIX_INVALID_INSNS
+           && (is_cirrus_insn (insn)
+ 	      || GET_CODE (insn) == JUMP_INSN
+ 	      || is_load_address (insn)))
+ 	cirrus_reorg (insn);
+ 
        if (GET_CODE (insn) == BARRIER)
  	push_minipool_barrier (insn, address);
        else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN
*************** arm_print_operand (stream, x, code)
*** 9168,9173 ****
--- 9473,9488 ----
        fprintf (stream, "%s", arithmetic_instr (x, 1));
        return;
  
+     /* Truncate Cirrus shift counts.  */
+     case 's':
+       if (GET_CODE (x) == CONST_INT)
+ 	{
+ 	  fprintf (stream, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0x3f);
+ 	  return;
+ 	}
+       arm_print_operand (stream, x, 0);
+       return;
+ 
      case 'I':
        fprintf (stream, "%s", arithmetic_instr (x, 0));
        return;
*************** arm_print_operand (stream, x, code)
*** 9274,9279 ****
--- 9589,9631 ----
  	fputs (thumb_condition_code (x, 1), stream);
        return;
  
+ 
+     /* Cirrus registers can be accessed in a variety of ways:
+          single floating point (f)
+ 	 double floating point (d)
+ 	 32bit integer         (fx)
+ 	 64bit integer         (dx).  */
+     case 'W':			/* Cirrus register in F mode.  */
+     case 'X':			/* Cirrus register in D mode.  */
+     case 'Y':			/* Cirrus register in FX mode.  */
+     case 'Z':			/* Cirrus register in DX mode.  */
+       if (GET_CODE (x) != REG || REGNO_REG_CLASS (REGNO (x)) != CIRRUS_REGS)
+ 	abort ();
+ 
+       fprintf (stream, "mv%s%s",
+ 	       code == 'W' ? "f"
+ 	       : code == 'X' ? "d"
+ 	       : code == 'Y' ? "fx" : "dx", reg_names[REGNO (x)] + 2);
+ 
+       return;
+ 
+     /* Print cirrus register in the mode specified by the register's mode.  */
+     case 'V':
+       {
+ 	int mode = GET_MODE (x);
+ 
+ 	if (GET_CODE (x) != REG || REGNO_REG_CLASS (REGNO (x)) != CIRRUS_REGS)
+ 	  abort ();
+ 
+ 	fprintf (stream, "mv%s%s",
+ 		 mode == DFmode ? "d"
+ 		 : mode == SImode ? "fx"
+ 		 : mode == DImode ? "dx"
+ 		 : "f", reg_names[REGNO (x)] + 2);
+ 
+ 	return;
+       }
+ 
      default:
        if (x == 0)
  	abort ();
*************** arm_final_prescan_insn (insn)
*** 9765,9770 ****
--- 10117,10134 ----
  		    || GET_CODE (scanbody) == PARALLEL)
  		  || get_attr_conds (this_insn) != CONDS_NOCOND)
  		fail = TRUE;
+ 
+ 	      /* A conditional cirrus instruction must be followed by
+ 		 a non Cirrus instruction.  However, since we
+ 		 conditionalize instructions in this function and by
+ 		 the time we get here we can't add instructions
+ 		 (nops), because shorten_branches() has already been
+ 		 called, we will disable conditionalizing Cirrus
+ 		 instructions to be safe.  */
+ 	      if (GET_CODE (scanbody) != USE
+ 		  && GET_CODE (scanbody) != CLOBBER
+ 		  && get_attr_cirrus (this_insn) != CIRRUS_NO)
+ 		fail = TRUE;
  	      break;
  
  	    default:
*************** arm_hard_regno_mode_ok (regno, mode)
*** 9848,9853 ****
--- 10212,10225 ----
         start of an even numbered register pair.  */
      return (ARM_NUM_REGS (mode) < 2) || (regno < LAST_LO_REGNUM);
  
+   if (IS_CIRRUS_REGNUM (regno))
+     /* We have outlawed SI values in Cirrus registers because they
+        reside in the lower 32 bits, but SF values reside in the
+        upper 32 bits.  This causes gcc all sorts of grief.  We can't
+        even split the registers into pairs because Cirrus SI values
+        get sign extended to 64bits-- aldyh.  */
+     return (GET_MODE_CLASS (mode) == MODE_FLOAT) || (mode == DImode);
+ 
    if (regno <= LAST_ARM_REGNUM)
      /* We allow any value to be stored in the general regisetrs.  */
      return 1;
*************** arm_regno_class (regno)
*** 9886,9891 ****
--- 10258,10266 ----
    
    if (regno == CC_REGNUM)
      return NO_REGS;
+ 
+   if (IS_CIRRUS_REGNUM (regno))
+     return CIRRUS_REGS;
  
    return FPU_REGS;
  }

Index: gcc/config/arm/arm.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.h,v
retrieving revision 1.181
diff -c -3 -p -w -r1.181 arm.h
*** gcc/config/arm/arm.h	5 Feb 2003 22:37:53 -0000	1.181
--- gcc/config/arm/arm.h	10 Feb 2003 11:23:50 -0000
*************** Boston, MA 02111-1307, USA.  */
*** 96,101 ****
--- 96,102 ----
  #define TARGET_CPU_arm9		0x0080
  #define TARGET_CPU_arm9tdmi	0x0080
  #define TARGET_CPU_xscale       0x0100
+ #define TARGET_CPU_ep9312	0x0200
  /* Configure didn't specify.  */
  #define TARGET_CPU_generic	0x8000
  
*************** extern GTY(()) rtx aof_pic_label;
*** 164,169 ****
--- 165,178 ----
  #if TARGET_CPU_DEFAULT == TARGET_CPU_xscale
  #define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_5TE__ -D__XSCALE__"
  #else
+ #if TARGET_CPU_DEFAULT == TARGET_CPU_ep9312
+ #define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_4T__ -D__MAVERICK__"
+ /* Set TARGET_DEFAULT to the default, but without soft-float.  */
+ #ifdef  TARGET_DEFAULT
+ #undef  TARGET_DEFAULT
+ #define TARGET_DEFAULT	(ARM_FLAG_APCS_32 | ARM_FLAG_APCS_FRAME)
+ #endif /* TARGET_CPU_DEFAULT */
+ #else
  Unrecognized value in TARGET_CPU_DEFAULT.
  #endif
  #endif
*************** Unrecognized value in TARGET_CPU_DEFAULT
*** 171,176 ****
--- 180,186 ----
  #endif
  #endif
  #endif
+ #endif
  
  #undef  CPP_SPEC
  #define CPP_SPEC "%(cpp_cpu_arch) %(subtarget_cpp_spec)			\
*************** Unrecognized value in TARGET_CPU_DEFAULT
*** 212,217 ****
--- 222,229 ----
  %{march=strongarm1100:-D__ARM_ARCH_4__} \
  %{march=xscale:-D__ARM_ARCH_5TE__} \
  %{march=xscale:-D__XSCALE__} \
+ %{march=ep9312:-D__ARM_ARCH_4T__} \
+ %{march=ep9312:-D__MAVERICK__} \
  %{march=armv2:-D__ARM_ARCH_2__} \
  %{march=armv2a:-D__ARM_ARCH_2__} \
  %{march=armv3:-D__ARM_ARCH_3__} \
*************** Unrecognized value in TARGET_CPU_DEFAULT
*** 251,256 ****
--- 263,270 ----
   %{mcpu=strongarm1100:-D__ARM_ARCH_4__} \
   %{mcpu=xscale:-D__ARM_ARCH_5TE__} \
   %{mcpu=xscale:-D__XSCALE__} \
+  %{mcpu=ep9312:-D__ARM_ARCH_4T__} \
+  %{mcpu=ep9312:-D__MAVERICK__} \
   %{!mcpu*:%(cpp_cpu_arch_default)}} \
  "
  
*************** Unrecognized value in TARGET_CPU_DEFAULT
*** 376,381 ****
--- 390,398 ----
  /* Nonzero means to use ARM/Thumb Procedure Call Standard conventions.  */
  #define ARM_FLAG_ATPCS		(1 << 22)
  
+ /* Fix invalid Cirrus instruction combinations by inserting NOPs.  */
+ #define CIRRUS_FIX_INVALID_INSNS (1 << 23)
+ 
  #define TARGET_APCS_FRAME		(target_flags & ARM_FLAG_APCS_FRAME)
  #define TARGET_POKE_FUNCTION_NAME	(target_flags & ARM_FLAG_POKE)
  #define TARGET_FPE			(target_flags & ARM_FLAG_FPE)
*************** Unrecognized value in TARGET_CPU_DEFAULT
*** 387,392 ****
--- 404,411 ----
  #define TARGET_MMU_TRAPS		(target_flags & ARM_FLAG_MMU_TRAPS)
  #define TARGET_SOFT_FLOAT		(target_flags & ARM_FLAG_SOFT_FLOAT)
  #define TARGET_HARD_FLOAT		(! TARGET_SOFT_FLOAT)
+ #define TARGET_CIRRUS			(arm_is_cirrus)
+ #define TARGET_ANY_HARD_FLOAT		(TARGET_HARD_FLOAT || TARGET_CIRRUS)
  #define TARGET_VFP			(target_flags & ARM_FLAG_VFP)
  #define TARGET_BIG_END			(target_flags & ARM_FLAG_BIG_END)
  #define TARGET_INTERWORK		(target_flags & ARM_FLAG_INTERWORK)
*************** Unrecognized value in TARGET_CPU_DEFAULT
*** 403,408 ****
--- 422,428 ----
  #define TARGET_BACKTRACE	        (leaf_function_p ()	      			\
  				         ? (target_flags & THUMB_FLAG_LEAF_BACKTRACE)	\
  				         : (target_flags & THUMB_FLAG_BACKTRACE))
+ #define TARGET_CIRRUS_FIX_INVALID_INSNS	(target_flags & CIRRUS_FIX_INVALID_INSNS)
  
  /* SUBTARGET_SWITCHES is used to add flags on a per-config basis.  */
  #ifndef SUBTARGET_SWITCHES
*************** Unrecognized value in TARGET_CPU_DEFAULT
*** 481,486 ****
--- 501,510 ----
     N_("Thumb: Assume function pointers may go to non-Thumb aware code") }, \
    {"no-caller-super-interworking", -THUMB_FLAG_CALLER_SUPER_INTERWORKING,  \
     "" },								   \
+   {"cirrus-fix-invalid-insns",      CIRRUS_FIX_INVALID_INSNS,		   \
+    N_("Cirrus: Place NOPs to avoid invalid instruction combinations") },   \
+   {"no-cirrus-fix-invalid-insns",  -CIRRUS_FIX_INVALID_INSNS,		   \
+    N_("Cirrus: Do not break up invalid instruction combinations with NOPs") },\
    SUBTARGET_SWITCHES							   \
    {"",				TARGET_DEFAULT, "" }			   \
  }
*************** enum floating_point_type
*** 530,536 ****
  {
    FP_HARD,
    FP_SOFT2,
!   FP_SOFT3
  };
  
  /* Recast the floating point class to be the floating point attribute.  */
--- 554,561 ----
  {
    FP_HARD,
    FP_SOFT2,
!   FP_SOFT3,
!   FP_CIRRUS
  };
  
  /* Recast the floating point class to be the floating point attribute.  */
*************** extern enum floating_point_type arm_fpu_
*** 548,553 ****
--- 573,583 ----
  #define FP_DEFAULT FP_SOFT2
  #endif
  
+ #if TARGET_CPU_DEFAULT == TARGET_CPU_ep9312
+ #undef  FP_DEFAULT
+ #define FP_DEFAULT FP_CIRRUS
+ #endif
+ 
  /* Nonzero if the processor has a fast multiply insn, and one that does
     a 64-bit multiply of two 32-bit values.  */
  extern int arm_fast_multiply;
*************** extern int thumb_code;
*** 570,575 ****
--- 600,608 ----
  /* Nonzero if this chip is a StrongARM.  */
  extern int arm_is_strong;
  
+ /* Nonzero if this chip is a Cirrus variant.  */
+ extern int arm_is_cirrus;
+ 
  /* Nonzero if this chip is an XScale.  */
  extern int arm_is_xscale;
  
*************** extern const char * structure_size_strin
*** 756,761 ****
--- 789,799 ----
  
     *: See CONDITIONAL_REGISTER_USAGE  */
  
+ /*
+   	mvf0		Cirrus floating point result
+ 	mvf1-mvf3	Cirrus floating point scratch
+ 	mvf4-mvf15   S	Cirrus floating point variable.  */
+ 
  /* The stack backtrace structure is as follows:
    fp points to here:  |  save code pointer  |      [fp]
                        |  return link value  |      [fp, #-4]
*************** extern const char * structure_size_strin
*** 785,791 ****
    0,0,0,0,0,0,0,0,	 \
    0,0,0,0,0,1,0,1,	 \
    0,0,0,0,0,0,0,0,	 \
!   1,1,1			 \
  }
  
  /* 1 for registers not available across function calls.
--- 823,831 ----
    0,0,0,0,0,0,0,0,	 \
    0,0,0,0,0,1,0,1,	 \
    0,0,0,0,0,0,0,0,	 \
!   1,1,1,		\
!   1,1,1,1,1,1,1,1,	\
!   1,1,1,1,1,1,1,1	\
  }
  
  /* 1 for registers not available across function calls.
*************** extern const char * structure_size_strin
*** 801,807 ****
    1,1,1,1,0,0,0,0,	     \
    0,0,0,0,1,1,1,1,	     \
    1,1,1,1,0,0,0,0,	     \
!   1,1,1			     \
  }
  
  #ifndef SUBTARGET_CONDITIONAL_REGISTER_USAGE
--- 841,849 ----
    1,1,1,1,0,0,0,0,	     \
    0,0,0,0,1,1,1,1,	     \
    1,1,1,1,0,0,0,0,	     \
!   1,1,1,		     \
!   1,1,1,1,1,1,1,1,	     \
!   1,1,1,1,1,1,1,1	     \
  }
  
  #ifndef SUBTARGET_CONDITIONAL_REGISTER_USAGE
*************** extern const char * structure_size_strin
*** 818,823 ****
--- 860,879 ----
  	   regno <= LAST_ARM_FP_REGNUM; ++regno)		\
  	fixed_regs[regno] = call_used_regs[regno] = 1;		\
      }								\
+ 								\
+   if (TARGET_CIRRUS)						\
+     {								\
+       for (regno = FIRST_ARM_FP_REGNUM;				\
+ 	   regno <= LAST_ARM_FP_REGNUM; ++ regno)		\
+ 	fixed_regs[regno] = call_used_regs[regno] = 1;		\
+       for (regno = FIRST_CIRRUS_FP_REGNUM;			\
+ 	   regno <= LAST_CIRRUS_FP_REGNUM; ++ regno)		\
+ 	{							\
+ 	  fixed_regs[regno] = 0;				\
+ 	  call_used_regs[regno] = regno < FIRST_CIRRUS_FP_REGNUM + 4; \
+ 	}							\
+     }								\
+ 								\
    if ((unsigned) PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)	\
      {								\
        fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;			\
*************** extern const char * structure_size_strin
*** 941,948 ****
  /* Base register for access to arguments of the function.  */
  #define ARG_POINTER_REGNUM	26
  
  /* The number of hard registers is 16 ARM + 8 FPU + 1 CC + 1 SFP.  */
! #define FIRST_PSEUDO_REGISTER	27
  
  /* Value should be nonzero if functions must have frame pointers.
     Zero means the frame pointer need not be set up (and parms may be accessed
--- 997,1010 ----
  /* Base register for access to arguments of the function.  */
  #define ARG_POINTER_REGNUM	26
  
+ #define FIRST_CIRRUS_FP_REGNUM	27
+ #define LAST_CIRRUS_FP_REGNUM	42
+ #define IS_CIRRUS_REGNUM(REGNUM) \
+   (((REGNUM) >= FIRST_CIRRUS_FP_REGNUM) && ((REGNUM) <= LAST_CIRRUS_FP_REGNUM))
+ 
  /* The number of hard registers is 16 ARM + 8 FPU + 1 CC + 1 SFP.  */
! /* Cirrus registers take us up to 43... */
! #define FIRST_PSEUDO_REGISTER	43
  
  /* Value should be nonzero if functions must have frame pointers.
     Zero means the frame pointer need not be set up (and parms may be accessed
*************** extern const char * structure_size_strin
*** 990,995 ****
--- 1052,1059 ----
       3,  2,  1,  0, 12, 14,  4,  5, \
       6,  7,  8, 10,  9, 11, 13, 15, \
      16, 17, 18, 19, 20, 21, 22, 23, \
+     27, 28, 29, 30, 31, 32, 33, 34, \
+     35, 36, 37, 38, 39, 40, 41, 42, \
      24, 25, 26			    \
  }
  
*************** enum reg_class
*** 1008,1013 ****
--- 1072,1078 ----
  {
    NO_REGS,
    FPU_REGS,
+   CIRRUS_REGS,
    LO_REGS,
    STACK_REG,
    BASE_REGS,
*************** enum reg_class
*** 1025,1030 ****
--- 1090,1096 ----
  {			\
    "NO_REGS",		\
    "FPU_REGS",		\
+   "CIRRUS_REGS",	\
    "LO_REGS",		\
    "STACK_REG",		\
    "BASE_REGS",		\
*************** enum reg_class
*** 1039,1053 ****
     of length N_REG_CLASSES.  */
  #define REG_CLASS_CONTENTS  		\
  {					\
!   { 0x0000000 }, /* NO_REGS  */		\
!   { 0x0FF0000 }, /* FPU_REGS */		\
!   { 0x00000FF }, /* LO_REGS */		\
!   { 0x0002000 }, /* STACK_REG */	\
!   { 0x00020FF }, /* BASE_REGS */	\
!   { 0x000FF00 }, /* HI_REGS */		\
!   { 0x1000000 }, /* CC_REG */		\
!   { 0x200FFFF }, /* GENERAL_REGS */	\
!   { 0x2FFFFFF }  /* ALL_REGS */		\
  }
  
  /* The same information, inverted:
--- 1105,1120 ----
     of length N_REG_CLASSES.  */
  #define REG_CLASS_CONTENTS  		\
  {					\
!   { 0x00000000, 0x0 },        /* NO_REGS  */	\
!   { 0x00FF0000, 0x0 },        /* FPU_REGS */	\
!   { 0xF8000000, 0x000007FF }, /* CIRRUS_REGS */	\
!   { 0x000000FF, 0x0 },        /* LO_REGS */	\
!   { 0x00002000, 0x0 },        /* STACK_REG */	\
!   { 0x000020FF, 0x0 },        /* BASE_REGS */	\
!   { 0x0000FF00, 0x0 },        /* HI_REGS */	\
!   { 0x01000000, 0x0 },        /* CC_REG */	\
!   { 0x0200FFFF, 0x0 },        /* GENERAL_REGS */\
!   { 0xFAFFFFFF, 0x000007FF }  /* ALL_REGS */	\
  }
  
  /* The same information, inverted:
*************** enum reg_class
*** 1080,1085 ****
--- 1147,1153 ----
     ARM, but several more letters for the Thumb.  */
  #define REG_CLASS_FROM_LETTER(C)  	\
    (  (C) == 'f' ? FPU_REGS		\
+    : (C) == 'v' ? CIRRUS_REGS		\
     : (C) == 'l' ? (TARGET_ARM ? GENERAL_REGS : LO_REGS)	\
     : TARGET_ARM ? NO_REGS		\
     : (C) == 'h' ? HI_REGS		\
*************** enum reg_class
*** 1143,1150 ****
     (C) == 'R' ? (GET_CODE (OP) == MEM					    \
  		 && GET_CODE (XEXP (OP, 0)) == SYMBOL_REF		    \
  		 && CONSTANT_POOL_ADDRESS_P (XEXP (OP, 0))) :		    \
!    (C) == 'S' ? (optimize > 0 && CONSTANT_ADDRESS_P (OP))		    \
!    : 0)
  
  #define EXTRA_CONSTRAINT_THUMB(X, C)					\
    ((C) == 'Q' ? (GET_CODE (X) == MEM					\
--- 1211,1219 ----
     (C) == 'R' ? (GET_CODE (OP) == MEM					    \
  		 && GET_CODE (XEXP (OP, 0)) == SYMBOL_REF		    \
  		 && CONSTANT_POOL_ADDRESS_P (XEXP (OP, 0))) :		    \
!    (C) == 'S' ? (optimize > 0 && CONSTANT_ADDRESS_P (OP)) :		    \
!    (C) == 'T' ? cirrus_memory_offset (OP) : 		    		    \
!    0)
  
  #define EXTRA_CONSTRAINT_THUMB(X, C)					\
    ((C) == 'Q' ? (GET_CODE (X) == MEM					\
*************** enum reg_class
*** 1188,1200 ****
     
  /* If we need to load shorts byte-at-a-time, then we need a scratch. */
  #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X)		\
    (TARGET_ARM ?							\
     (((MODE) == HImode && ! arm_arch4 && TARGET_MMU_TRAPS	\
       && (GET_CODE (X) == MEM					\
  	 || ((GET_CODE (X) == REG || GET_CODE (X) == SUBREG)	\
  	     && true_regnum (X) == -1)))			\
      ? GENERAL_REGS : NO_REGS)					\
!    : THUMB_SECONDARY_INPUT_RELOAD_CLASS (CLASS, MODE, X))
  
  /* Try a machine-dependent way of reloading an illegitimate address
     operand.  If we find one, push the reload and jump to WIN.  This
--- 1257,1274 ----
     
  /* If we need to load shorts byte-at-a-time, then we need a scratch. */
  #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X)		\
+   /* Cannot load constants into Cirrus registers.  */		\
+   ((TARGET_CIRRUS						\
+      && (CLASS) == CIRRUS_REGS					\
+      && (CONSTANT_P (X) || GET_CODE (X) == SYMBOL_REF))		\
+     ? GENERAL_REGS :						\
    (TARGET_ARM ?							\
     (((MODE) == HImode && ! arm_arch4 && TARGET_MMU_TRAPS	\
       && (GET_CODE (X) == MEM					\
  	 || ((GET_CODE (X) == REG || GET_CODE (X) == SUBREG)	\
  	     && true_regnum (X) == -1)))			\
      ? GENERAL_REGS : NO_REGS)					\
!    : THUMB_SECONDARY_INPUT_RELOAD_CLASS (CLASS, MODE, X)))
  
  /* Try a machine-dependent way of reloading an illegitimate address
     operand.  If we find one, push the reload and jump to WIN.  This
*************** enum reg_class
*** 1217,1222 ****
--- 1291,1299 ----
  									   \
  	  if (MODE == DImode || (TARGET_SOFT_FLOAT && MODE == DFmode))	   \
  	    low = ((val & 0xf) ^ 0x8) - 0x8;				   \
+ 	  else if (TARGET_CIRRUS)					   \
+ 	    /* Need to be careful, -256 is not a valid offset.  */	   \
+ 	    low = val >= 0 ? (val & 0xff) : -((-val) & 0xff);		   \
  	  else if (MODE == SImode					   \
  		   || (MODE == SFmode && TARGET_SOFT_FLOAT)		   \
  		   || ((MODE == HImode || MODE == QImode) && ! arm_arch4)) \
*************** enum reg_class
*** 1289,1301 ****
     needed to represent mode MODE in a register of class CLASS.
     ARM regs are UNITS_PER_WORD bits while FPU regs can hold any FP mode */
  #define CLASS_MAX_NREGS(CLASS, MODE)  \
!   ((CLASS) == FPU_REGS ? 1 : ARM_NUM_REGS (MODE))
  
  /* Moves between FPU_REGS and GENERAL_REGS are two memory insns.  */
  #define REGISTER_MOVE_COST(MODE, FROM, TO)		\
    (TARGET_ARM ?						\
     ((FROM) == FPU_REGS && (TO) != FPU_REGS ? 20 :	\
!     (FROM) != FPU_REGS && (TO) == FPU_REGS ? 20 : 2)	\
     :							\
     ((FROM) == HI_REGS || (TO) == HI_REGS) ? 4 : 2)
  
--- 1366,1384 ----
     needed to represent mode MODE in a register of class CLASS.
     ARM regs are UNITS_PER_WORD bits while FPU regs can hold any FP mode */
  #define CLASS_MAX_NREGS(CLASS, MODE)  \
!   (((CLASS) == FPU_REGS || (CLASS) == CIRRUS_REGS) ? 1 : ARM_NUM_REGS (MODE))
! 
! /* If defined, gives a class of registers that cannot be used as the
!    operand of a SUBREG that changes the mode of the object illegally.  */
  
  /* Moves between FPU_REGS and GENERAL_REGS are two memory insns.  */
  #define REGISTER_MOVE_COST(MODE, FROM, TO)		\
    (TARGET_ARM ?						\
     ((FROM) == FPU_REGS && (TO) != FPU_REGS ? 20 :	\
!     (FROM) != FPU_REGS && (TO) == FPU_REGS ? 20 :	\
!     (FROM) == CIRRUS_REGS && (TO) != CIRRUS_REGS ? 20 :	\
!     (FROM) != CIRRUS_REGS && (TO) == CIRRUS_REGS ? 20 :	\
!    2)							\
     :							\
     ((FROM) == HI_REGS || (TO) == HI_REGS) ? 4 : 2)
  
*************** enum reg_class
*** 1347,1352 ****
--- 1430,1437 ----
  #define LIBCALL_VALUE(MODE)  \
    (TARGET_ARM && TARGET_HARD_FLOAT && GET_MODE_CLASS (MODE) == MODE_FLOAT \
     ? gen_rtx_REG (MODE, FIRST_ARM_FP_REGNUM) \
+    : TARGET_ARM && TARGET_CIRRUS && GET_MODE_CLASS (MODE) == MODE_FLOAT \
+    ? gen_rtx_REG (MODE, FIRST_CIRRUS_FP_REGNUM) 			\
     : gen_rtx_REG (MODE, ARG_REGISTER (1)))
  
  /* Define how to find the value returned by a function.
*************** enum reg_class
*** 1358,1365 ****
--- 1443,1452 ----
  
  /* 1 if N is a possible register number for a function value.
     On the ARM, only r0 and f0 can return results.  */
+ /* On a Cirrus chip, mvf0 can return results.  */
  #define FUNCTION_VALUE_REGNO_P(REGNO)  \
    ((REGNO) == ARG_REGISTER (1) \
+    || (TARGET_ARM && ((REGNO) == FIRST_CIRRUS_FP_REGNUM) && TARGET_CIRRUS) \
     || (TARGET_ARM && ((REGNO) == FIRST_ARM_FP_REGNUM) && TARGET_HARD_FLOAT))
  
  /* How large values are returned */
*************** extern int making_const_table;
*** 2449,2454 ****
--- 2536,2544 ----
    {"multi_register_push", {PARALLEL}},					\
    {"cc_register", {REG}},						\
    {"logical_binary_operator", {AND, IOR, XOR}},				\
+   {"cirrus_register_operand", {REG}},					\
+   {"cirrus_fp_register", {REG}},					\
+   {"cirrus_shift_const", {CONST_INT}},					\
    {"dominant_cc_register", {REG}},
  
  /* Define this if you have special predicates that know special things

Index: gcc/config/arm/arm.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/arm.md,v
retrieving revision 1.118
diff -c -3 -p -w -r1.118 arm.md
*** gcc/config/arm/arm.md	5 Feb 2003 22:37:53 -0000	1.118
--- gcc/config/arm/arm.md	10 Feb 2003 11:23:54 -0000
***************
*** 386,391 ****
--- 386,393 ----
    (and (eq_attr "core_cycles" "multi")
         (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
  
+ (include "cirrus.md")
+ 
  ;;---------------------------------------------------------------------------
  ;; Insn patterns
  ;;
***************
*** 394,399 ****
--- 396,403 ----
  ;; Note: For DImode insns, there is normally no reason why operands should
  ;; not be in the same register, what we don't want is for something being
  ;; written to partially overlap something that is an input.
+ ;; Cirrus 64bit additions should not be split because we have a native
+ ;; 64bit addition instructions.
  
  (define_expand "adddi3"
   [(parallel
***************
*** 403,408 ****
--- 407,422 ----
      (clobber (reg:CC CC_REGNUM))])]
    "TARGET_EITHER"
    "
+   if (TARGET_CIRRUS)
+     {
+       if (!cirrus_fp_register (operands[0], DImode))
+         operands[0] = force_reg (DImode, operands[0]);
+       if (!cirrus_fp_register (operands[1], DImode))
+         operands[1] = force_reg (DImode, operands[1]);
+       emit_insn (gen_cirrus_adddi3 (operands[0], operands[1], operands[2]));
+       DONE;
+     }
+ 
    if (TARGET_THUMB)
      {
        if (GET_CODE (operands[1]) != REG)
***************
*** 429,435 ****
  	(plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
  		 (match_operand:DI 2 "s_register_operand" "r,  0")))
     (clobber (reg:CC CC_REGNUM))]
!   "TARGET_ARM"
    "#"
    "TARGET_ARM && reload_completed"
    [(parallel [(set (reg:CC_C CC_REGNUM)
--- 443,449 ----
  	(plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
  		 (match_operand:DI 2 "s_register_operand" "r,  0")))
     (clobber (reg:CC CC_REGNUM))]
!   "TARGET_ARM && !TARGET_CIRRUS"
    "#"
    "TARGET_ARM && reload_completed"
    [(parallel [(set (reg:CC_C CC_REGNUM)
***************
*** 457,463 ****
  		  (match_operand:SI 2 "s_register_operand" "r,r"))
  		 (match_operand:DI 1 "s_register_operand" "r,0")))
     (clobber (reg:CC CC_REGNUM))]
!   "TARGET_ARM"
    "#"
    "TARGET_ARM && reload_completed"
    [(parallel [(set (reg:CC_C CC_REGNUM)
--- 471,477 ----
  		  (match_operand:SI 2 "s_register_operand" "r,r"))
  		 (match_operand:DI 1 "s_register_operand" "r,0")))
     (clobber (reg:CC CC_REGNUM))]
!   "TARGET_ARM && !TARGET_CIRRUS"
    "#"
    "TARGET_ARM && reload_completed"
    [(parallel [(set (reg:CC_C CC_REGNUM)
***************
*** 486,492 ****
  		  (match_operand:SI 2 "s_register_operand" "r,r"))
  		 (match_operand:DI 1 "s_register_operand" "r,0")))
     (clobber (reg:CC CC_REGNUM))]
!   "TARGET_ARM"
    "#"
    "TARGET_ARM && reload_completed"
    [(parallel [(set (reg:CC_C CC_REGNUM)
--- 500,506 ----
  		  (match_operand:SI 2 "s_register_operand" "r,r"))
  		 (match_operand:DI 1 "s_register_operand" "r,0")))
     (clobber (reg:CC CC_REGNUM))]
!   "TARGET_ARM && !TARGET_CIRRUS"
    "#"
    "TARGET_ARM && reload_completed"
    [(parallel [(set (reg:CC_C CC_REGNUM)
***************
*** 789,795 ****
     (set_attr "length" "4,8")]
  )
  
! (define_insn "addsf3"
    [(set (match_operand:SF          0 "s_register_operand" "=f,f")
  	(plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
  		 (match_operand:SF 2 "fpu_add_operand"    "fG,H")))]
--- 803,809 ----
     (set_attr "length" "4,8")]
  )
  
! (define_insn "*arm_addsf3"
    [(set (match_operand:SF          0 "s_register_operand" "=f,f")
  	(plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
  		 (match_operand:SF 2 "fpu_add_operand"    "fG,H")))]
***************
*** 801,807 ****
     (set_attr "predicable" "yes")]
  )
  
! (define_insn "adddf3"
    [(set (match_operand:DF          0 "s_register_operand" "=f,f")
  	(plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
  		 (match_operand:DF 2 "fpu_add_operand"    "fG,H")))]
--- 815,821 ----
     (set_attr "predicable" "yes")]
  )
  
! (define_insn "*arm_adddf3"
    [(set (match_operand:DF          0 "s_register_operand" "=f,f")
  	(plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
  		 (match_operand:DF 2 "fpu_add_operand"    "fG,H")))]
***************
*** 857,862 ****
--- 871,885 ----
      (clobber (reg:CC CC_REGNUM))])]
    "TARGET_EITHER"
    "
+   if (TARGET_CIRRUS
+       && TARGET_ARM
+       && cirrus_fp_register (operands[0], DImode)
+       && cirrus_fp_register (operands[1], DImode))
+     {
+       emit_insn (gen_cirrus_subdi3 (operands[0], operands[1], operands[2]));
+       DONE;
+     }
+ 
    if (TARGET_THUMB)
      {
        if (GET_CODE (operands[1]) != REG)
***************
*** 1042,1048 ****
     (set_attr "length" "*,8")]
  )
  
! (define_insn "subsf3"
    [(set (match_operand:SF 0 "s_register_operand" "=f,f")
  	(minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
  		  (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
--- 1065,1071 ----
     (set_attr "length" "*,8")]
  )
  
! (define_insn "*arm_subsf3"
    [(set (match_operand:SF 0 "s_register_operand" "=f,f")
  	(minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
  		  (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
***************
*** 1053,1059 ****
    [(set_attr "type" "farith")]
  )
  
! (define_insn "subdf3"
    [(set (match_operand:DF           0 "s_register_operand" "=f,f")
  	(minus:DF (match_operand:DF 1 "fpu_rhs_operand"     "f,G")
  		  (match_operand:DF 2 "fpu_rhs_operand"    "fG,f")))]
--- 1076,1082 ----
    [(set_attr "type" "farith")]
  )
  
! (define_insn "*arm_subdf3"
    [(set (match_operand:DF           0 "s_register_operand" "=f,f")
  	(minus:DF (match_operand:DF 1 "fpu_rhs_operand"     "f,G")
  		  (match_operand:DF 2 "fpu_rhs_operand"    "fG,f")))]
***************
*** 1332,1338 ****
    "smlalbb%?\\t%Q0, %R0, %2, %3"
  [(set_attr "type" "mult")])
  
! (define_insn "mulsf3"
    [(set (match_operand:SF 0 "s_register_operand" "=f")
  	(mult:SF (match_operand:SF 1 "s_register_operand" "f")
  		 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
--- 1355,1361 ----
    "smlalbb%?\\t%Q0, %R0, %2, %3"
  [(set_attr "type" "mult")])
  
! (define_insn "*arm_mulsf3"
    [(set (match_operand:SF 0 "s_register_operand" "=f")
  	(mult:SF (match_operand:SF 1 "s_register_operand" "f")
  		 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
***************
*** 1342,1348 ****
     (set_attr "predicable" "yes")]
  )
  
! (define_insn "muldf3"
    [(set (match_operand:DF 0 "s_register_operand" "=f")
  	(mult:DF (match_operand:DF 1 "s_register_operand" "f")
  		 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
--- 1365,1371 ----
     (set_attr "predicable" "yes")]
  )
  
! (define_insn "*arm_muldf3"
    [(set (match_operand:DF 0 "s_register_operand" "=f")
  	(mult:DF (match_operand:DF 1 "s_register_operand" "f")
  		 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
***************
*** 2529,2534 ****
--- 2552,2570 ----
    [(set_attr "length" "2")]
  )
  
+ (define_expand "ashldi3"
+   [(set (match_operand:DI            0 "s_register_operand" "")
+ 	(ashift:DI (match_operand:DI 1 "general_operand"    "")
+ 		   (match_operand:SI 2 "general_operand"    "")))]
+   "TARGET_ARM && (TARGET_CIRRUS)"
+   "
+   if (! s_register_operand (operands[1], DImode))
+     operands[1] = copy_to_mode_reg (DImode, operands[1]);
+   if (! s_register_operand (operands[2], SImode))
+     operands[2] = copy_to_mode_reg (SImode, operands[2]);
+   "
+ )
+ 
  (define_insn "*arm_shiftsi3"
    [(set (match_operand:SI   0 "s_register_operand" "=r")
  	(match_operator:SI  3 "shift_operator"
***************
*** 2702,2708 ****
    [(set_attr "length" "2")]
  )
  
! (define_insn "negsf2"
    [(set (match_operand:SF         0 "s_register_operand" "=f")
  	(neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
    "TARGET_ARM && TARGET_HARD_FLOAT"
--- 2738,2744 ----
    [(set_attr "length" "2")]
  )
  
! (define_insn "*arm_negsf2"
    [(set (match_operand:SF         0 "s_register_operand" "=f")
  	(neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
    "TARGET_ARM && TARGET_HARD_FLOAT"
***************
*** 2711,2717 ****
     (set_attr "predicable" "yes")]
  )
  
! (define_insn "negdf2"
    [(set (match_operand:DF         0 "s_register_operand" "=f")
  	(neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
    "TARGET_ARM && TARGET_HARD_FLOAT"
--- 2747,2753 ----
     (set_attr "predicable" "yes")]
  )
  
! (define_insn "*arm_negdf2"
    [(set (match_operand:DF         0 "s_register_operand" "=f")
  	(neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
    "TARGET_ARM && TARGET_HARD_FLOAT"
***************
*** 2735,2741 ****
  ;; it does, but tell the final scan operator the truth.  Similarly for
  ;; (neg (abs...))
  
! (define_insn "abssi2"
    [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
  	(abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
     (clobber (reg:CC CC_REGNUM))]
--- 2771,2777 ----
  ;; it does, but tell the final scan operator the truth.  Similarly for
  ;; (neg (abs...))
  
! (define_insn "*arm_abssi2"
    [(set (match_operand:SI         0 "s_register_operand" "=r,&r")
  	(abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
     (clobber (reg:CC CC_REGNUM))]
***************
*** 2763,2769 ****
     (set_attr "length" "8")]
  )
  
! (define_insn "abssf2"
    [(set (match_operand:SF          0 "s_register_operand" "=f")
  	 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
    "TARGET_ARM && TARGET_HARD_FLOAT"
--- 2799,2805 ----
     (set_attr "length" "8")]
  )
  
! (define_insn "*arm_abssf2"
    [(set (match_operand:SF          0 "s_register_operand" "=f")
  	 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
    "TARGET_ARM && TARGET_HARD_FLOAT"
***************
*** 2772,2778 ****
     (set_attr "predicable" "yes")]
  )
  
! (define_insn "absdf2"
    [(set (match_operand:DF         0 "s_register_operand" "=f")
  	(abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
    "TARGET_ARM && TARGET_HARD_FLOAT"
--- 2808,2814 ----
     (set_attr "predicable" "yes")]
  )
  
! (define_insn "*arm_absdf2"
    [(set (match_operand:DF         0 "s_register_operand" "=f")
  	(abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
    "TARGET_ARM && TARGET_HARD_FLOAT"
***************
*** 2884,2890 ****
  
  ;; Fixed <--> Floating conversion insns
  
! (define_insn "floatsisf2"
    [(set (match_operand:SF           0 "s_register_operand" "=f")
  	(float:SF (match_operand:SI 1 "s_register_operand" "r")))]
    "TARGET_ARM && TARGET_HARD_FLOAT"
--- 2920,2926 ----
  
  ;; Fixed <--> Floating conversion insns
  
! (define_insn "*arm_floatsisf2"
    [(set (match_operand:SF           0 "s_register_operand" "=f")
  	(float:SF (match_operand:SI 1 "s_register_operand" "r")))]
    "TARGET_ARM && TARGET_HARD_FLOAT"
***************
*** 2893,2899 ****
     (set_attr "predicable" "yes")]
  )
  
! (define_insn "floatsidf2"
    [(set (match_operand:DF           0 "s_register_operand" "=f")
  	(float:DF (match_operand:SI 1 "s_register_operand" "r")))]
    "TARGET_ARM && TARGET_HARD_FLOAT"
--- 2929,2935 ----
     (set_attr "predicable" "yes")]
  )
  
! (define_insn "*arm_floatsidf2"
    [(set (match_operand:DF           0 "s_register_operand" "=f")
  	(float:DF (match_operand:SI 1 "s_register_operand" "r")))]
    "TARGET_ARM && TARGET_HARD_FLOAT"
***************
*** 2902,2908 ****
     (set_attr "predicable" "yes")]
  )
  
! (define_insn "fix_truncsfsi2"
    [(set (match_operand:SI         0 "s_register_operand" "=r")
  	(fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
    "TARGET_ARM && TARGET_HARD_FLOAT"
--- 2938,2944 ----
     (set_attr "predicable" "yes")]
  )
  
! (define_insn "*arm_fix_truncsfsi2"
    [(set (match_operand:SI         0 "s_register_operand" "=r")
  	(fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
    "TARGET_ARM && TARGET_HARD_FLOAT"
***************
*** 2911,2917 ****
     (set_attr "predicable" "yes")]
  )
  
! (define_insn "fix_truncdfsi2"
    [(set (match_operand:SI         0 "s_register_operand" "=r")
  	(fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
    "TARGET_ARM && TARGET_HARD_FLOAT"
--- 2947,2953 ----
     (set_attr "predicable" "yes")]
  )
  
! (define_insn "*arm_fix_truncdfsi2"
    [(set (match_operand:SI         0 "s_register_operand" "=r")
  	(fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
    "TARGET_ARM && TARGET_HARD_FLOAT"
***************
*** 2922,2928 ****
  
  ;; Truncation insns
  
! (define_insn "truncdfsf2"
    [(set (match_operand:SF 0 "s_register_operand" "=f")
  	(float_truncate:SF
  	 (match_operand:DF 1 "s_register_operand" "f")))]
--- 2958,2964 ----
  
  ;; Truncation insns
  
! (define_insn "*arm_truncdfsf2"
    [(set (match_operand:SF 0 "s_register_operand" "=f")
  	(float_truncate:SF
  	 (match_operand:DF 1 "s_register_operand" "f")))]
***************
*** 3654,3660 ****
     (set_attr "pool_range" "32,32")]
  )
  
! (define_insn "extendsfdf2"
    [(set (match_operand:DF                  0 "s_register_operand" "=f")
  	(float_extend:DF (match_operand:SF 1 "s_register_operand"  "f")))]
    "TARGET_ARM && TARGET_HARD_FLOAT"
--- 3690,3696 ----
     (set_attr "pool_range" "32,32")]
  )
  
! (define_insn "*arm_extendsfdf2"
    [(set (match_operand:DF                  0 "s_register_operand" "=f")
  	(float_extend:DF (match_operand:SF 1 "s_register_operand"  "f")))]
    "TARGET_ARM && TARGET_HARD_FLOAT"
***************
*** 3743,3749 ****
  (define_insn "*arm_movdi"
    [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
  	(match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
!   "TARGET_ARM"
    "*
    return (output_move_double (operands));
    "
--- 3779,3785 ----
  (define_insn "*arm_movdi"
    [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
  	(match_operand:DI 1 "di_operand"              "rIK,mi,r"))]
!   "TARGET_ARM && !TARGET_CIRRUS"
    "*
    return (output_move_double (operands));
    "
***************
*** 3761,3766 ****
--- 3797,3803 ----
    [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
  	(match_operand:DI 1 "general_operand"      "l, I,J,>,l,mi,l,*r"))]
    "TARGET_THUMB
+    && !TARGET_CIRRUS
     && (   register_operand (operands[0], DImode)
         || register_operand (operands[1], DImode))"
    "*
***************
*** 4769,4774 ****
--- 4806,4812 ----
    [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
  	(match_operand:SF 1 "general_operand"  "r,mE,r"))]
    "TARGET_ARM
+    && !TARGET_CIRRUS
     && TARGET_SOFT_FLOAT
     && (GET_CODE (operands[0]) != MEM
         || register_operand (operands[1], SFmode))"
***************
*** 4909,4914 ****
--- 4947,4953 ----
    [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
  	(match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
    "TARGET_ARM && TARGET_SOFT_FLOAT
+    && !TARGET_CIRRUS
    "
    "* return output_move_double (operands);"
    [(set_attr "length" "8,8,8")
***************
*** 5414,5421 ****
  (define_expand "cmpsf"
    [(match_operand:SF 0 "s_register_operand" "")
     (match_operand:SF 1 "fpu_rhs_operand" "")]
!   "TARGET_ARM && TARGET_HARD_FLOAT"
    "
    arm_compare_op0 = operands[0];
    arm_compare_op1 = operands[1];
    DONE;
--- 5453,5463 ----
  (define_expand "cmpsf"
    [(match_operand:SF 0 "s_register_operand" "")
     (match_operand:SF 1 "fpu_rhs_operand" "")]
!   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
    "
+   if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
+     operands[1] = force_reg (SFmode, operands[1]);
+ 
    arm_compare_op0 = operands[0];
    arm_compare_op1 = operands[1];
    DONE;
***************
*** 5425,5432 ****
  (define_expand "cmpdf"
    [(match_operand:DF 0 "s_register_operand" "")
     (match_operand:DF 1 "fpu_rhs_operand" "")]
!   "TARGET_ARM && TARGET_HARD_FLOAT"
    "
    arm_compare_op0 = operands[0];
    arm_compare_op1 = operands[1];
    DONE;
--- 5467,5477 ----
  (define_expand "cmpdf"
    [(match_operand:DF 0 "s_register_operand" "")
     (match_operand:DF 1 "fpu_rhs_operand" "")]
!   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
    "
+   if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
+     operands[1] = force_reg (DFmode, operands[1]);
+ 
    arm_compare_op0 = operands[0];
    arm_compare_op1 = operands[1];
    DONE;
***************
*** 5531,5536 ****
--- 5576,5640 ----
     (set_attr "type" "f_2_r")]
  )
  
+ ;; There is no CCFPE or CCFP modes in the code below so we can have
+ ;; one pattern to match either one.  Besides, we're pretty sure we
+ ;; have either CCFPE or CCFP because we made the patterns
+ ;; (arm_gen_compare_reg).
+ 
+ ;; Cirrus SF compare instruction
+ (define_insn "*cirrus_cmpsf"
+   [(set (reg:CCFP CC_REGNUM)
+ 	(compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
+ 		      (match_operand:SF 1 "cirrus_fp_register" "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfcmps%?\\tr15, %V0, %V1"
+   [(set_attr "cirrus_type" "farith")
+    (set_attr "cirrus" "compare")]
+ )
+ 
+ ;; Cirrus DF compare instruction
+ (define_insn "*cirrus_cmpdf"
+   [(set (reg:CCFP CC_REGNUM)
+ 	(compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
+ 		      (match_operand:DF 1 "cirrus_fp_register" "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfcmpd%?\\tr15, %V0, %V1"
+   [(set_attr "cirrus_type" "farith")
+    (set_attr "cirrus" "compare")]
+ )
+ 
+ ;; Cirrus DI compare instruction
+ (define_expand "cmpdi"
+   [(match_operand:DI 0 "cirrus_fp_register" "")
+    (match_operand:DI 1 "cirrus_fp_register" "")]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "{
+      arm_compare_op0 = operands[0];
+      arm_compare_op1 = operands[1];
+      DONE;
+    }")
+ 
+ (define_insn "*cirrus_cmpdi"
+   [(set (reg:CC CC_REGNUM)
+ 	(compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
+ 		    (match_operand:DI 1 "cirrus_fp_register" "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfcmp64%?\\tr15, %V0, %V1"
+   [(set_attr "cirrus_type" "farith")
+    (set_attr "cirrus" "compare")]
+ )
+ 
+ ;; Cirrus SI compare instruction
+ (define_insn "*cirrus_cmpsi_1"
+   [(set (reg:CC CC_REGNUM)
+ 	(compare:CC (match_operand:SI 0 "cirrus_fp_register" "v")
+ 		    (match_operand:SI 1 "cirrus_fp_register" "v")))]
+   "TARGET_ARM && TARGET_CIRRUS && 0"
+   "cfcmp32%?\\tr15, %V0, %V1"
+   [(set_attr "cirrus_type" "farith")
+    (set_attr "cirrus" "compare")]
+ )
+ 
  (define_insn "*cmpsf_trap"
    [(set (reg:CCFPE CC_REGNUM)
  	(compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
***************
*** 6347,6354 ****
  )
  
  (define_insn "*call_value_reg"
!   [(set (match_operand 0 "" "=r,f")
!         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r"))
  	      (match_operand 2 "" "")))
     (use (match_operand 3 "" ""))
     (clobber (reg:SI LR_REGNUM))]
--- 6451,6458 ----
  )
  
  (define_insn "*call_value_reg"
!   [(set (match_operand 0 "" "=r,f,v")
!         (call (mem:SI (match_operand:SI 1 "s_register_operand" "r,r,r"))
  	      (match_operand 2 "" "")))
     (use (match_operand 3 "" ""))
     (clobber (reg:SI LR_REGNUM))]
***************
*** 6361,6368 ****
  )
  
  (define_insn "*call_value_mem"
!   [(set (match_operand 0 "" "=r,f")
! 	(call (mem:SI (match_operand:SI 1 "memory_operand" "m,m"))
  	      (match_operand 2 "" "")))
     (use (match_operand 3 "" ""))
     (clobber (reg:SI LR_REGNUM))]
--- 6465,6472 ----
  )
  
  (define_insn "*call_value_mem"
!   [(set (match_operand 0 "" "=r,f,v")
! 	(call (mem:SI (match_operand:SI 1 "memory_operand" "m,m,m"))
  	      (match_operand 2 "" "")))
     (use (match_operand 3 "" ""))
     (clobber (reg:SI LR_REGNUM))]
***************
*** 6393,6400 ****
  )
  
  (define_insn "*call_value_symbol"
!   [(set (match_operand 0 "s_register_operand" "=r,f")
! 	(call (mem:SI (match_operand:SI 1 "" "X,X"))
  	(match_operand:SI 2 "" "")))
     (use (match_operand 3 "" ""))
     (clobber (reg:SI LR_REGNUM))]
--- 6497,6504 ----
  )
  
  (define_insn "*call_value_symbol"
!   [(set (match_operand 0 "s_register_operand" "=r,f,v")
! 	(call (mem:SI (match_operand:SI 1 "" "X,X,X"))
  	(match_operand:SI 2 "" "")))
     (use (match_operand 3 "" ""))
     (clobber (reg:SI LR_REGNUM))]
***************
*** 6476,6483 ****
  )
  
  (define_insn "*sibcall_value_insn"
!  [(set (match_operand 0 "s_register_operand" "=r,f")
!        (call (mem:SI (match_operand:SI 1 "" "X,X"))
  	     (match_operand 2 "" "")))
    (return)
    (use (match_operand 3 "" ""))]
--- 6580,6587 ----
  )
  
  (define_insn "*sibcall_value_insn"
!  [(set (match_operand 0 "s_register_operand" "=r,f,v")
!        (call (mem:SI (match_operand:SI 1 "" "X,X,X"))
  	     (match_operand 2 "" "")))
    (return)
    (use (match_operand 3 "" ""))]
***************
*** 8274,8279 ****
--- 8378,8386 ----
     (set (reg:CC CC_REGNUM)
  	(compare:CC (match_dup 1) (const_int 0)))]
    "TARGET_ARM
+    && (!TARGET_CIRRUS
+        || (!cirrus_fp_register (operands[0], SImode)
+            && !cirrus_fp_register (operands[1], SImode)))
    "
    [(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
  	      (set (match_dup 0) (match_dup 1))])]

Index: gcc/config/arm/t-arm-elf
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/arm/t-arm-elf,v
retrieving revision 1.16
diff -c -3 -p -w -r1.16 t-arm-elf
*** gcc/config/arm/t-arm-elf	8 May 2002 15:01:13 -0000	1.16
--- gcc/config/arm/t-arm-elf	10 Feb 2003 11:23:54 -0000
*************** dp-bit.c: $(srcdir)/config/fp-bit.c
*** 24,29 ****
--- 24,33 ----
  MULTILIB_OPTIONS     = marm/mthumb
  MULTILIB_DIRNAMES    = arm thumb
  MULTILIB_EXCEPTIONS  = 
+ 
+ # MULTILIB_OPTIONS    += mcpu=ep9312
+ # MULTILIB_DIRNAMES   += ep9312
+ # MULTILIB_EXCEPTIONS += *mthumb/*mcpu=ep9312*
  	
  # MULTILIB_OPTIONS     += mlittle-endian/mbig-endian
  # MULTILIB_DIRNAMES    += le be

Index: gcc/doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.235
diff -c -3 -p -w -r1.235 invoke.texi
*** gcc/doc/invoke.texi	8 Feb 2003 14:51:05 -0000	1.235
--- gcc/doc/invoke.texi	10 Feb 2003 11:24:12 -0000
*************** in the following sections.
*** 386,391 ****
--- 386,392 ----
  -msingle-pic-base  -mno-single-pic-base @gol
  -mpic-register=@var{reg} @gol
  -mnop-fun-dllimport @gol
+ -mcirrus-fix-invalid-insns -mno-cirrus-fix-invalid-insns @gol
  -mpoke-function-name @gol
  -mthumb  -marm @gol
  -mtpcs-frame  -mtpcs-leaf-frame @gol
*************** assembly code.  Permissible names are: @
*** 6132,6138 ****
  @samp{strongarm}, @samp{strongarm110}, @samp{strongarm1100},
  @samp{arm8}, @samp{arm810}, @samp{arm9}, @samp{arm9e}, @samp{arm920},
  @samp{arm920t}, @samp{arm940t}, @samp{arm9tdmi}, @samp{arm10tdmi},
! @samp{arm1020t}, @samp{xscale}.
  
  @itemx -mtune=@var{name}
  @opindex mtune
--- 6133,6139 ----
  @samp{strongarm}, @samp{strongarm110}, @samp{strongarm1100},
  @samp{arm8}, @samp{arm810}, @samp{arm9}, @samp{arm9e}, @samp{arm920},
  @samp{arm920t}, @samp{arm940t}, @samp{arm9tdmi}, @samp{arm10tdmi},
! @samp{arm1020t}, @samp{xscale}, @samp{ep9312}.
  
  @itemx -mtune=@var{name}
  @opindex mtune
*************** name to determine what kind of instructi
*** 6152,6158 ****
  assembly code.  This option can be used in conjunction with or instead
  of the @option{-mcpu=} option.  Permissible names are: @samp{armv2},
  @samp{armv2a}, @samp{armv3}, @samp{armv3m}, @samp{armv4}, @samp{armv4t},
! @samp{armv5}, @samp{armv5t}, @samp{armv5te}.
  
  @item -mfpe=@var{number}
  @itemx -mfp=@var{number}
--- 6153,6159 ----
  assembly code.  This option can be used in conjunction with or instead
  of the @option{-mcpu=} option.  Permissible names are: @samp{armv2},
  @samp{armv2a}, @samp{armv3}, @samp{armv3m}, @samp{armv4}, @samp{armv4t},
! @samp{armv5}, @samp{armv5t}, @samp{armv5te}, @samp{ep9312}.
  
  @item -mfpe=@var{number}
  @itemx -mfp=@var{number}
*************** before execution begins.
*** 6223,6228 ****
--- 6224,6241 ----
  @opindex mpic-register
  Specify the register to be used for PIC addressing.  The default is R10
  unless stack-checking is enabled, when R9 is used.
+ 
+ @item -mcirrus-fix-invalid-insns
+ @opindex -mcirrus-fix-invalid-insns
+ @opindex -mno-cirrus-fix-invalid-insns
+ Insert NOPs into the instruction stream to in order to work around
+ problems with invalid Maverick instruction combinations.  This option
+ is only valid if the @option{-mcpu=ep9312} option has been used to
+ enable generation of instructions for the Cirrus Maverick floating
+ point co-processor.  This option is not enabled by default, since the
+ problem is only present in older Maverick implemenations.  The default
+ can be re-enabled by use of the @option{-mno-cirrus-fix-invalid-insns}
+ switch.
  
  @item -mpoke-function-name
  @opindex mpoke-function-name

*** /dev/null	Sat Oct 19 15:41:17 2002
--- gcc/config/arm/cirrus.md	Sat Feb  8 12:06:34 2003
***************
*** 0 ****
--- 1,667 ----
+ ;; Cirrus EP9312 "Maverick" ARM floating point co-processor description.
+ ;; Copyright (C) 2003 Free Software Foundation, Inc.
+ ;; Contributed by Red Hat.
+ ;; Written by Aldy Hernandez (aldyh@redhat.com)
+ 
+ ;; This file is part of GNU CC.
+ 
+ ;; GNU CC is free software; you can redistribute it and/or modify
+ ;; it under the terms of the GNU General Public License as published by
+ ;; the Free Software Foundation; either version 2, or (at your option)
+ ;; any later version.
+ 
+ ;; GNU CC is distributed in the hope that it will be useful,
+ ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ ;; GNU General Public License for more details.
+ 
+ ;; You should have received a copy of the GNU General Public License
+ ;; along with GNU CC; see the file COPYING.  If not, write to
+ ;; the Free Software Foundation, 59 Temple Place - Suite 330,
+ ;; Boston, MA 02111-1307, USA.
+ 
+ 
+ (define_attr "cirrus_fpu" "fpa,fpe2,fpe3,yes" (const (symbol_ref "arm_fpu_attr")))
+ 
+ ; Classification of each insn
+ ; farith	Floating point arithmetic (4 cycle)
+ ; dmult		Double multiplies (7 cycle)
+ (define_attr "cirrus_type" "normal,farith,dmult" (const_string "normal"))
+ 
+ ; Cirrus types for invalid insn combinations
+ ; no		Not a cirrus insn
+ ; yes		Cirrus insn
+ ; double	cfldrd, cfldr64, cfstrd, cfstr64
+ ; compare	cfcmps, cfcmpd, cfcmp32, cfcmp64
+ ; move		cfmvdlr, cfmvdhr, cfmvsr, cfmv64lr, cfmv64hr
+ (define_attr "cirrus" "no,yes,double,compare,move" (const_string "no"))
+ 
+ (define_function_unit "cirrus_fpa" 1 0
+   (and (eq_attr "cirrus_fpu" "yes")
+        (eq_attr "cirrus_type" "farith")) 4 1)
+ 
+ (define_function_unit "cirrus_fpa" 1 0
+   (and (eq_attr "cirrus_fpu" "yes")
+        (eq_attr "cirrus_type" "dmult")) 7 4)
+ 
+ (define_function_unit "cirrus_fpa" 1 0
+   (and (eq_attr "cirrus_fpu" "yes")
+        (eq_attr "cirrus_type" "normal")) 1 1)
+ 
+ (define_insn "cirrus_adddi3"
+   [(set (match_operand:DI          0 "cirrus_fp_register" "=v")
+ 	(plus:DI (match_operand:DI 1 "cirrus_fp_register"  "v")
+ 		 (match_operand:DI 2 "cirrus_fp_register"  "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfadd64%?\\t%V0, %V1, %V2"
+   [(set_attr "cirrus_type" "farith")
+    (set_attr "cirrus" "yes")]
+ )
+ 
+ (define_insn "*cirrus_addsi3"
+   [(set (match_operand:SI          0 "cirrus_fp_register" "=v")
+ 	(plus:SI (match_operand:SI 1 "cirrus_fp_register" "v")
+ 		 (match_operand:SI 2 "cirrus_fp_register" "v")))]
+   "TARGET_ARM && TARGET_CIRRUS && 0"
+   "cfadd32%?\\t%V0, %V1, %V2"
+   [(set_attr "cirrus_type" "farith")
+    (set_attr "cirrus" "yes")]
+ )
+ 
+ ;; define_insn replaced by define_expand and define_insn
+ (define_expand "addsf3"
+   [(set (match_operand:SF          0 "s_register_operand" "")
+ 	(plus:SF (match_operand:SF 1 "s_register_operand" "")
+ 		 (match_operand:SF 2 "fpu_add_operand" "")))]
+   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+   "
+   if (TARGET_CIRRUS
+       && !cirrus_fp_register (operands[2], SFmode))
+     operands[2] = force_reg (SFmode, operands[2]);
+ ")
+ 
+ (define_insn "*cirrus_addsf3"
+   [(set (match_operand:SF          0 "cirrus_fp_register" "=v")
+ 	(plus:SF (match_operand:SF 1 "cirrus_fp_register" "v")
+ 		 (match_operand:SF 2 "cirrus_fp_register" "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfadds%?\\t%V0, %V1, %V2"
+   [(set_attr "cirrus_type" "farith")
+    (set_attr "cirrus" "yes")]
+ )
+ 
+ ;; define_insn replaced by define_expand and define_insn
+ (define_expand "adddf3"
+   [(set (match_operand:DF          0 "s_register_operand" "")
+ 	(plus:DF (match_operand:DF 1 "s_register_operand" "")
+ 		 (match_operand:DF 2 "fpu_add_operand" "")))]
+   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+   "
+   if (TARGET_CIRRUS
+       && !cirrus_fp_register (operands[2], DFmode))
+     operands[2] = force_reg (DFmode, operands[2]);
+ ")
+ 
+ (define_insn "*cirrus_adddf3"
+   [(set (match_operand:DF          0 "cirrus_fp_register" "=v")
+ 	(plus:DF (match_operand:DF 1 "cirrus_fp_register" "v")
+ 		 (match_operand:DF 2 "cirrus_fp_register" "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfaddd%?\\t%V0, %V1, %V2"
+   [(set_attr "cirrus_type" "farith")
+    (set_attr "cirrus" "yes")]
+ )
+ 
+ (define_insn "cirrus_subdi3"
+   [(set (match_operand:DI           0 "cirrus_fp_register" "=v")
+ 	(minus:DI (match_operand:DI 1 "cirrus_fp_register"  "v")
+ 		  (match_operand:DI 2 "cirrus_fp_register"  "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfsub64%?\\t%V0, %V1, %V2"
+   [(set_attr "cirrus_type" "farith")
+    (set_attr "cirrus" "yes")]
+ )
+ 
+ (define_insn "*cirrus_subsi3_insn"
+   [(set (match_operand:SI           0 "cirrus_fp_register" "=v")
+ 	(minus:SI (match_operand:SI 1 "cirrus_fp_register" "v")
+ 		  (match_operand:SI 2 "cirrus_fp_register" "v")))]
+   "TARGET_ARM && TARGET_CIRRUS && 0"
+   "cfsub32%?\\t%V0, %V1, %V2"
+   [(set_attr "cirrus_type" "farith")
+    (set_attr "cirrus" "yes")]
+ )
+ 
+ (define_expand "subsf3"
+   [(set (match_operand:SF           0 "s_register_operand" "")
+ 	(minus:SF (match_operand:SF 1 "fpu_rhs_operand" "")
+ 		  (match_operand:SF 2 "fpu_rhs_operand" "")))]
+   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+   "
+   if (TARGET_CIRRUS)
+     {
+       if (!cirrus_fp_register (operands[1], SFmode))
+         operands[1] = force_reg (SFmode, operands[1]);
+       if (!cirrus_fp_register (operands[2], SFmode))
+         operands[2] = force_reg (SFmode, operands[2]);
+     }
+ ")
+ 
+ (define_insn "*cirrus_subsf3"
+   [(set (match_operand:SF           0 "cirrus_fp_register" "=v")
+ 	(minus:SF (match_operand:SF 1 "cirrus_fp_register"  "v")
+ 		  (match_operand:SF 2 "cirrus_fp_register"  "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfsubs%?\\t%V0, %V1, %V2"
+   [(set_attr "cirrus_type" "farith")
+    (set_attr "cirrus" "yes")]
+ )
+ 
+ (define_expand "subdf3"
+   [(set (match_operand:DF           0 "s_register_operand" "")
+ 	(minus:DF (match_operand:DF 1 "fpu_rhs_operand"     "")
+ 		  (match_operand:DF 2 "fpu_rhs_operand"    "")))]
+   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+   "
+   if (TARGET_CIRRUS)
+     {
+        if (!cirrus_fp_register (operands[1], DFmode))
+          operands[1] = force_reg (DFmode, operands[1]);
+        if (!cirrus_fp_register (operands[2], DFmode))
+          operands[2] = force_reg (DFmode, operands[2]);
+     }
+ ")
+ 
+ (define_insn "*cirrus_subdf3"
+   [(set (match_operand:DF           0 "cirrus_fp_register" "=v")
+ 	(minus:DF (match_operand:DF 1 "cirrus_fp_register" "v")
+ 		  (match_operand:DF 2 "cirrus_fp_register" "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfsubd%?\\t%V0, %V1, %V2"
+   [(set_attr "cirrus_type" "farith")
+    (set_attr "cirrus" "yes")]
+ )
+ 
+ (define_insn "*cirrus_mulsi3"
+   [(set (match_operand:SI          0 "cirrus_fp_register" "=v")
+ 	(mult:SI (match_operand:SI 2 "cirrus_fp_register"  "v")
+ 		 (match_operand:SI 1 "cirrus_fp_register"  "v")))]
+   "TARGET_ARM && TARGET_CIRRUS && 0"
+   "cfmul32%?\\t%V0, %V1, %V2"
+   [(set_attr "cirrus_type" "farith")
+    (set_attr "cirrus" "yes")]
+ )
+ 
+ (define_insn "muldi3"
+   [(set (match_operand:DI          0 "cirrus_fp_register" "=v")
+ 	(mult:DI (match_operand:DI 2 "cirrus_fp_register"  "v")
+ 		 (match_operand:DI 1 "cirrus_fp_register"  "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfmul64%?\\t%V0, %V1, %V2"
+   [(set_attr "cirrus_type" "dmult")
+    (set_attr "cirrus" "yes")]
+ )
+ 
+ (define_insn "*cirrus_mulsi3addsi"
+   [(set (match_operand:SI            0 "cirrus_fp_register" "=v")
+ 	(plus:SI
+ 	  (mult:SI (match_operand:SI 1 "cirrus_fp_register"  "v")
+ 		   (match_operand:SI 2 "cirrus_fp_register"  "v"))
+ 	  (match_operand:SI          3 "cirrus_fp_register"  "0")))]
+   "TARGET_ARM && TARGET_CIRRUS && 0"
+   "cfmac32%?\\t%V0, %V1, %V2"
+   [(set_attr "cirrus_type" "farith")
+    (set_attr "cirrus" "yes")]
+ )
+ 
+ ;; Cirrus SI multiply-subtract
+ (define_insn "*cirrus_mulsi3subsi"
+   [(set (match_operand:SI            0 "cirrus_fp_register" "=v")
+ 	(minus:SI
+ 	  (match_operand:SI          1 "cirrus_fp_register"  "0")
+ 	  (mult:SI (match_operand:SI 2 "cirrus_fp_register"  "v")
+ 		   (match_operand:SI 3 "cirrus_fp_register"  "v"))))]
+   "0 && TARGET_ARM && TARGET_CIRRUS"
+   "cfmsc32%?\\t%V0, %V2, %V3"
+   [(set_attr "cirrus_type" "farith")
+    (set_attr "cirrus" "yes")]
+ )
+ 
+ (define_expand "mulsf3"
+   [(set (match_operand:SF          0 "s_register_operand" "")
+ 	(mult:SF (match_operand:SF 1 "s_register_operand" "")
+ 		 (match_operand:SF 2 "fpu_rhs_operand" "")))]
+   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+   "
+   if (TARGET_CIRRUS
+       && !cirrus_fp_register (operands[2], SFmode))
+     operands[2] = force_reg (SFmode, operands[2]);
+ ")
+ 
+ (define_insn "*cirrus_mulsf3"
+   [(set (match_operand:SF          0 "cirrus_fp_register" "=v")
+ 	(mult:SF (match_operand:SF 1 "cirrus_fp_register"  "v")
+ 		 (match_operand:SF 2 "cirrus_fp_register"  "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfmuls%?\\t%V0, %V1, %V2"
+   [(set_attr "cirrus_type" "farith")
+    (set_attr "cirrus" "yes")]
+ )
+ 
+ (define_expand "muldf3"
+   [(set (match_operand:DF          0 "s_register_operand" "")
+ 	(mult:DF (match_operand:DF 1 "s_register_operand" "")
+ 		 (match_operand:DF 2 "fpu_rhs_operand" "")))]
+   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+   "
+   if (TARGET_CIRRUS
+       && !cirrus_fp_register (operands[2], DFmode))
+     operands[2] = force_reg (DFmode, operands[2]);
+ ")
+ 
+ (define_insn "*cirrus_muldf3"
+   [(set (match_operand:DF          0 "cirrus_fp_register" "=v")
+ 	(mult:DF (match_operand:DF 1 "cirrus_fp_register"  "v")
+ 		 (match_operand:DF 2 "cirrus_fp_register"  "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfmuld%?\\t%V0, %V1, %V2"
+   [(set_attr "cirrus_type" "dmult")
+    (set_attr "cirrus" "yes")]
+ )
+ 
+ (define_insn "cirrus_ashl_const"
+   [(set (match_operand:SI            0 "cirrus_fp_register" "=v")
+ 	(ashift:SI (match_operand:SI 1 "cirrus_fp_register"  "v")
+ 		   (match_operand:SI 2 "cirrus_shift_const"  "")))]
+   "TARGET_ARM && TARGET_CIRRUS && 0"
+   "cfsh32%?\\t%V0, %V1, #%s2"
+   [(set_attr "cirrus" "yes")]
+ )
+ 
+ (define_insn "cirrus_ashiftrt_const"
+   [(set (match_operand:SI	       0 "cirrus_fp_register" "=v")
+ 	(ashiftrt:SI (match_operand:SI 1 "cirrus_fp_register"  "v")
+ 		     (match_operand:SI 2 "cirrus_shift_const"  "")))]
+   "TARGET_ARM && TARGET_CIRRUS && 0"
+   "cfsh32%?\\t%V0, %V1, #-%s2"
+   [(set_attr "cirrus" "yes")]
+ )
+ 
+ (define_insn "cirrus_ashlsi3"
+   [(set (match_operand:SI            0 "cirrus_fp_register" "=v")
+ 	(ashift:SI (match_operand:SI 1 "cirrus_fp_register"  "v")
+ 		   (match_operand:SI 2 "register_operand"    "r")))]
+   "TARGET_ARM && TARGET_CIRRUS && 0"
+   "cfrshl32%?\\t%V1, %V0, %s2"
+   [(set_attr "cirrus" "yes")]
+ )
+ 
+ (define_insn "ashldi3_cirrus"
+   [(set (match_operand:DI            0 "cirrus_fp_register" "=v")
+ 	(ashift:DI (match_operand:DI 1 "cirrus_fp_register"  "v")
+ 		   (match_operand:SI 2 "register_operand"    "r")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfrshl64%?\\t%V1, %V0, %s2"
+   [(set_attr "cirrus" "yes")]
+ )
+ 
+ (define_insn "cirrus_ashldi_const"
+   [(set (match_operand:DI            0 "cirrus_fp_register" "=v")
+ 	(ashift:DI (match_operand:DI 1 "cirrus_fp_register"  "v")
+ 		   (match_operand:SI 2 "cirrus_shift_const"  "")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfsh64%?\\t%V0, %V1, #%s2"
+   [(set_attr "cirrus" "yes")]
+ )
+ 
+ (define_insn "cirrus_ashiftrtdi_const"
+   [(set (match_operand:DI            0 "cirrus_fp_register" "=v")
+ 	(ashiftrt:DI (match_operand:DI 1 "cirrus_fp_register"  "v")
+ 		     (match_operand:SI 2 "cirrus_shift_const"  "")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfsh64%?\\t%V0, %V1, #-%s2"
+   [(set_attr "cirrus" "yes")]
+ )
+ 
+ (define_insn "*cirrus_absdi2"
+   [(set (match_operand:DI         0 "cirrus_fp_register" "=v")
+ 	(abs:DI (match_operand:DI 1 "cirrus_fp_register"  "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfabs64%?\\t%V0, %V1"
+   [(set_attr "cirrus" "yes")]
+ )
+ 
+ ;; This doesn't really clobber ``cc''.  Fixme: aldyh.  
+ (define_insn "*cirrus_negdi2"
+   [(set (match_operand:DI         0 "cirrus_fp_register" "=v")
+ 	(neg:DI (match_operand:DI 1 "cirrus_fp_register"  "v")))
+    (clobber (reg:CC CC_REGNUM))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfneg64%?\\t%V0, %V1"
+   [(set_attr "cirrus" "yes")]
+ )
+ 
+ (define_insn "*cirrus_negsi2"
+   [(set (match_operand:SI         0 "cirrus_fp_register" "=v")
+ 	(neg:SI (match_operand:SI 1 "cirrus_fp_register"  "v")))]
+   "TARGET_ARM && TARGET_CIRRUS && 0"
+   "cfneg32%?\\t%V0, %V1"
+   [(set_attr "cirrus" "yes")]
+ )
+ 
+ (define_expand "negsf2"
+   [(set (match_operand:SF         0 "s_register_operand" "")
+ 	(neg:SF (match_operand:SF 1 "s_register_operand" "")))]
+   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+   ""
+ )
+ 
+ (define_insn "*cirrus_negsf2"
+   [(set (match_operand:SF         0 "cirrus_fp_register" "=v")
+ 	(neg:SF (match_operand:SF 1 "cirrus_fp_register"  "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfnegs%?\\t%V0, %V1"
+   [(set_attr "cirrus" "yes")]
+ )
+ 
+ (define_expand "negdf2"
+   [(set (match_operand:DF         0 "s_register_operand" "")
+ 	(neg:DF (match_operand:DF 1 "s_register_operand" "")))]
+   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+   "")
+ 
+ (define_insn "*cirrus_negdf2"
+   [(set (match_operand:DF         0 "cirrus_fp_register" "=v")
+ 	(neg:DF (match_operand:DF 1 "cirrus_fp_register"  "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfnegd%?\\t%V0, %V1"
+   [(set_attr "cirrus" "yes")]
+ )
+ 
+ (define_expand "abssi2"
+   [(parallel
+     [(set (match_operand:SI         0 "s_register_operand" "")
+ 	  (abs:SI (match_operand:SI 1 "s_register_operand" "")))
+      (clobber (reg:CC CC_REGNUM))])]
+   "TARGET_ARM"
+   "")
+ 
+ ;; This doesn't really clobber the condition codes either.  
+ (define_insn "*cirrus_abssi2"
+   [(set (match_operand:SI         0 "cirrus_fp_register" "=v")
+         (abs:SI (match_operand:SI 1 "cirrus_fp_register"  "v")))
+    (clobber (reg:CC CC_REGNUM))]
+   "TARGET_ARM && TARGET_CIRRUS && 0"
+   "cfabs32%?\\t%V0, %V1"
+   [(set_attr "cirrus" "yes")]
+ )
+ 
+ (define_expand "abssf2"
+   [(set (match_operand:SF         0 "s_register_operand" "")
+ 	(abs:SF (match_operand:SF 1 "s_register_operand" "")))]
+   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+   "")
+ 
+ (define_insn "*cirrus_abssf2"
+   [(set (match_operand:SF         0 "cirrus_fp_register" "=v")
+         (abs:SF (match_operand:SF 1 "cirrus_fp_register"  "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfabss%?\\t%V0, %V1"
+   [(set_attr "cirrus" "yes")]
+ )
+ 
+ (define_expand "absdf2"
+   [(set (match_operand:DF         0 "s_register_operand" "")
+ 	(abs:DF (match_operand:DF 1 "s_register_operand" "")))]
+   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+   "")
+ 
+ (define_insn "*cirrus_absdf2"
+   [(set (match_operand:DF         0 "cirrus_fp_register" "=v")
+         (abs:DF (match_operand:DF 1 "cirrus_fp_register"  "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfabsd%?\\t%V0, %V1"
+   [(set_attr "cirrus" "yes")]
+ )
+ 
+ (define_expand "floatsisf2"
+   [(set (match_operand:SF           0 "s_register_operand" "")
+ 	(float:SF (match_operand:SI 1 "s_register_operand" "")))]
+   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+   "
+   if (TARGET_CIRRUS)
+     {
+       emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
+       DONE;
+     }
+ ")
+ 
+ ;; Convert Cirrus-SI to Cirrus-SF
+ (define_insn "cirrus_floatsisf2"
+   [(set (match_operand:SF           0 "cirrus_fp_register" "=v")
+  	(float:SF (match_operand:SI 1 "s_register_operand"  "r")))
+    (clobber (match_scratch:DF 2 "=v"))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfmv64lr%?\\t%Z2, %1\;cfcvt32s%?\\t%V0, %Y2"
+   [(set_attr "length" "8")
+    (set_attr "cirrus" "move")]
+ )
+ 
+ (define_expand "floatsidf2"
+   [(set (match_operand:DF           0 "s_register_operand" "")
+ 	(float:DF (match_operand:SI 1 "s_register_operand" "")))]
+   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+   "
+   if (TARGET_CIRRUS)
+     {
+       emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
+       DONE;
+     }
+ ")
+ 
+ (define_insn "cirrus_floatsidf2"
+   [(set (match_operand:DF           0 "cirrus_fp_register" "=v")
+ 	(float:DF (match_operand:SI 1 "s_register_operand" "r")))
+    (clobber (match_scratch:DF 2 "=v"))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfmv64lr%?\\t%Z2, %1\;cfcvt32d%?\\t%V0, %Y2"
+   [(set_attr "length" "8")
+    (set_attr "cirrus" "move")]
+ )
+ 
+ (define_insn "floatdisf2"
+   [(set (match_operand:SF           0 "cirrus_fp_register" "=v")
+ 	(float:SF (match_operand:DI 1 "cirrus_fp_register" "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfcvt64s%?\\t%V0, %V1"
+   [(set_attr "cirrus" "yes")])
+ 
+ (define_insn "floatdidf2"
+   [(set (match_operand:DF 0 "cirrus_fp_register" "=v")
+ 	(float:DF (match_operand:DI 1 "cirrus_fp_register" "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfcvt64d%?\\t%V0, %V1"
+   [(set_attr "cirrus" "yes")])
+ 
+ (define_expand "fix_truncsfsi2"
+   [(set (match_operand:SI         0 "s_register_operand" "")
+ 	(fix:SI (match_operand:SF 1 "s_register_operand"  "")))]
+   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+   "
+   if (TARGET_CIRRUS)
+     {
+       if (!cirrus_fp_register (operands[0], SImode))
+         operands[0] = force_reg (SImode, operands[0]);
+       if (!cirrus_fp_register (operands[1], SFmode))
+         operands[1] = force_reg (SFmode, operands[0]);
+       emit_insn (gen_cirrus_truncsfsi2 (operands[0], operands[1]));
+       DONE;
+     }
+ ")
+ 
+ (define_insn "cirrus_truncsfsi2"
+   [(set (match_operand:SI         0 "s_register_operand" "=r")
+ 	(fix:SI (match_operand:SF 1 "cirrus_fp_register"  "v")))
+    (clobber (match_scratch:DF     2                      "=v"))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cftruncs32%?\\t%Y2, %V1\;cfmvr64l%?\\t%0, %Z2"
+   [(set_attr "length" "8")
+    (set_attr "cirrus" "yes")]
+ )
+ 
+ (define_expand "fix_truncdfsi2"
+   [(set (match_operand:SI         0 "s_register_operand" "")
+ 	(fix:SI (match_operand:DF 1 "s_register_operand"  "")))]
+   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+   "
+   if (TARGET_CIRRUS)
+     {
+       if (!cirrus_fp_register (operands[1], DFmode))
+         operands[1] = force_reg (DFmode, operands[0]);
+       emit_insn (gen_cirrus_truncdfsi2 (operands[0], operands[1]));
+       DONE;
+     }
+ ")
+ 
+ (define_insn "cirrus_truncdfsi2"
+   [(set (match_operand:SI         0 "s_register_operand" "=r")
+ 	(fix:SI (match_operand:DF 1 "cirrus_fp_register"  "v")))
+    (clobber (match_scratch:DF     2                      "=v"))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cftruncd32%?\\t%Y2, %V1\;cfmvr64l%?\\t%0, %Z2"
+   [(set_attr "length" "8")]
+ )
+ 
+ (define_expand "truncdfsf2"
+   [(set (match_operand:SF  0 "s_register_operand" "")
+ 	(float_truncate:SF
+  	 (match_operand:DF 1 "s_register_operand" "")))]
+   "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+   ""
+ )
+ 
+ (define_insn "*cirrus_truncdfsf2"
+   [(set (match_operand:SF  0 "cirrus_fp_register" "=v")
+         (float_truncate:SF
+          (match_operand:DF 1 "cirrus_fp_register" "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfcvtds%?\\t%V0, %V1"
+   [(set_attr "cirrus" "yes")]
+ )
+ 
+ (define_insn "*cirrus_extendsfdf2"
+   [(set (match_operand:DF                  0 "cirrus_fp_register" "=v")
+         (float_extend:DF (match_operand:SF 1 "cirrus_fp_register"  "v")))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "cfcvtsd%?\\t%V0, %V1"
+   [(set_attr "cirrus" "yes")]
+ )
+ 
+ (define_insn "*cirrus_arm_movdi"
+   [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,o<>,v,r,v,m,v")
+ 	(match_operand:DI 1 "di_operand"              "rIK,mi,r,r,v,m,v,v"))]
+   "TARGET_ARM && TARGET_CIRRUS"
+   "*
+   {
+   switch (which_alternative)
+     {
+     case 0:
+     case 1:
+     case 2:
+       return (output_move_double (operands));
+ 
+     case 3: return \"cfmv64lr%?\\t%V0, %Q1\;cfmv64hr%?\\t%V0, %R1\";
+     case 4: return \"cfmvr64l%?\\t%Q0, %V1\;cfmvr64h%?\\t%R0, %V1\";
+ 
+     case 5: return \"cfldr64%?\\t%V0, %1\";
+     case 6: return \"cfstr64%?\\t%V1, %0\";
+ 
+     /* Shifting by 0 will just copy %1 into %0.  */
+     case 7: return \"cfsh64%?\\t%V0, %V1, #0\";
+ 
+     default: abort ();
+     }
+   }"
+   [(set_attr "length" "8,8,8,8,8,4,4,4")
+    (set_attr "type" "*,load,store2,*,*,load,store2,*")
+    (set_attr "pool_range" "*,1020,*,*,*,*,*,*")
+    (set_attr "neg_pool_range" "*,1012,*,*,*,*,*,*")
+    (set_attr "cirrus" "no,no,no,move,yes,double,double,yes")]
+ )
+ 
+ ;; Cirrus SI values have been outlawed.  Look in arm.h for the comment
+ ;; on HARD_REGNO_MODE_OK.
+ 
+ (define_insn "*cirrus_arm_movsi_insn"
+   [(set (match_operand:SI 0 "general_operand" "=r,r,r,m,*v,r,*v,T,*v")
+         (match_operand:SI 1 "general_operand" "rI,K,mi,r,r,*v,T,*v,*v"))]
+   "TARGET_ARM && TARGET_CIRRUS && 0
+    && (register_operand (operands[0], SImode)
+        || register_operand (operands[1], SImode))"
+   "@
+    mov%?\\t%0, %1
+    mvn%?\\t%0, #%B1
+    ldr%?\\t%0, %1
+    str%?\\t%1, %0
+    cfmv64lr%?\\t%Z0, %1
+    cfmvr64l%?\\t%0, %Z1
+    cfldr32%?\\t%V0, %1
+    cfstr32%?\\t%V1, %0
+    cfsh32%?\\t%V0, %V1, #0"
+   [(set_attr "type" "*,*,load,store1,*,*,load,store1,*")
+    (set_attr "pool_range" "*,*,4096,*,*,*,1024,*,*")
+    (set_attr "neg_pool_range" "*,*,4084,*,*,*,1012,*,*")
+    (set_attr "cirrus" "no,no,no,no,move,yes,yes,yes,yes")]
+ )
+ 
+ (define_insn "*cirrus_movsf_hard_insn"
+   [(set (match_operand:SF 0 "nonimmediate_operand" "=v,v,v,r,m,r,r,m")
+         (match_operand:SF 1 "general_operand"       "v,m,r,v,v,r,mE,r"))]
+   "TARGET_ARM && TARGET_CIRRUS
+    && (GET_CODE (operands[0]) != MEM
+        || register_operand (operands[1], SFmode))"
+   "@
+    cfcpys%?\\t%V0, %V1
+    cfldrs%?\\t%V0, %1
+    cfmvsr%?\\t%V0, %1
+    cfmvrs%?\\t%0, %V1
+    cfstrs%?\\t%V1, %0
+    mov%?\\t%0, %1
+    ldr%?\\t%0, %1\\t%@ float
+    str%?\\t%1, %0\\t%@ float"
+   [(set_attr "length" "*,*,*,*,*,4,4,4")
+    (set_attr "type" "*,load,*,*,store1,*,load,store1")
+    (set_attr "pool_range" "*,*,*,*,*,*,4096,*")
+    (set_attr "neg_pool_range" "*,*,*,*,*,*,4084,*")
+    (set_attr "cirrus" "yes,yes,move,yes,yes,no,no,no")]
+ )
+ 
+ (define_insn "*cirrus_movdf_hard_insn"
+   [(set (match_operand:DF 0 "nonimmediate_operand" "=r,Q,r,m,r,v,v,v,r,m")
+ 	(match_operand:DF 1 "general_operand"       "Q,r,r,r,mF,v,m,r,v,v"))]
+   "TARGET_ARM
+    && TARGET_CIRRUS
+    && (GET_CODE (operands[0]) != MEM
+        || register_operand (operands[1], DFmode))"
+   "*
+   {
+   switch (which_alternative)
+     {
+     case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
+     case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
+     case 2: case 3: case 4: return output_move_double (operands);
+     case 5: return \"cfcpyd%?\\t%V0, %V1\";
+     case 6: return \"cfldrd%?\\t%V0, %1\";
+     case 7: return \"cfmvdlr\\t%V0, %Q1\;cfmvdhr%?\\t%V0, %R1\";
+     case 8: return \"cfmvrdl%?\\t%Q0, %V1\;cfmvrdh%?\\t%R0, %V1\";
+     case 9: return \"cfstrd%?\\t%V1, %0\";
+     default: abort ();
+     }
+   }"
+   [(set_attr "type" "load,store2,*,store2,load,*,load,*,*,store2")
+    (set_attr "length" "4,4,8,8,8,4,4,8,8,4")
+    (set_attr "pool_range" "*,*,*,*,252,*,*,*,*,*")
+    (set_attr "neg_pool_range" "*,*,*,*,244,*,*,*,*,*")
+    (set_attr "cirrus" "no,no,no,no,no,yes,double,move,yes,double")]
+ )
+ 

Index: htdocs/gcc-3.4/changes.html
===================================================================
RCS file: /cvs/gcc/wwwdocs/htdocs/gcc-3.4/changes.html,v
retrieving revision 1.13
diff -c -3 -p -w -r1.13 changes.html
*** htdocs/gcc-3.4/changes.html	1 Feb 2003 17:41:41 -0000	1.13
--- htdocs/gcc-3.4/changes.html	10 Feb 2003 11:29:16 -0000
***************
*** 80,85 ****
--- 80,93 ----
      Enabled at run time with the <code>-m2e</code> command line
      switch, or at configure time by specifying sh2e as the machine
      part of the target triple.</li>
+     
+     <li>Support for the Cirrus EP9312 Maverick floating point
+     co-processor added to the ARM port.  Enabled at run time with the
+     <code>-mcpu=ep9312</code> command line switch.  Note however that
+     the multilibs to support this chip are currently disabled in
+     gcc/config/arm/t-arm-elf, so if you want to enable their
+     production you will have to uncomment the entries in that
+     file.</li>
    </ul>


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