This is the mail archive of the gcc@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]

Re: [ARM] Cirrus EP93xx Maverick Crunch Support - condexec / bugfixing / "co-processor offset out of range"


On Wed, 27 Jun 2007 12:31:42 +0200, "Rask Ingemann Lambertsen"
<rask@sygehus.dk> said:
> On Wed, Jun 27, 2007 at 06:45:26PM +1000, Hasjim Williams wrote:
> > 
> > It also fixes up the
> > "internal compiler error: output_operand: '%l' operand isn't a label"
> > error...
> > 
> > Incidentally, does anyone know if can you do something like:
> > if_then_else (ge (match_operand:!CCFP 1 "cc_register" "") (const_int 0))
> 
>    You can't (but mode macros help). As Paolo says, you will have to
>    define
> one or more new comparison modes and you will have to define branch insns
> which use the new mode(s), comparison insns which set the cc register in
> the
> new mode(s), new sCC style insns, and so on. Additionally, look at
> SELECT_CC_MODE and TARGET_CC_MODE_COMPATIBLE. If you have some sort of
> arm_output_compare_insn() function, modify that as well.
> 
>    The significance of defining a CCmode is that is says that comparisons
> done in that mode set the flags in a specific way.

Thanks.  This really clears things up for me.  For the moment, I will
leave conditional execution disabled for EVERYTHING when compiling for
MaverickCrunch.  I think the arm.md code only conditionally executes
operands if the compare was in SImode, anyway - (see "scc insns" in
gcc/config/arm/arm.md) .  Can anyone confirm this?

This just leaves me with one other major bug for MaverickCrunch.

It is related to the bugs in the Cirrus silicon.  Mainstream gcc and
older versions of gcc have a parameter -mcirrus-fix-invalid-insns.  The
patch from Nucleus Systems
(http://www.nucleusys.com/projects/crunch.php), removes this parameter,
and replaces it with two -mfix-crunch-d0 and -mfix-crunch-d1.

I've modified it and attached it to this post.  At the moment, I hard
code both to 0, to disable the bug fixes, since enabling them I think is
the cause of a "co-processor offset out of range" error, in the
assembler.  Essentially the two major bugs that the attached code fixes
are, after a branch, two nops are needed.  Secondly, the a register
written to in one instruction can not be read from in the next
instruction, without a non-MaverickCrunch operation in between, i.e. a
nop.  

Essentially this extra code is run in arm_reorg, which is always run on
ARM, since an address can only be loaded a limited distance around the
pc.  Likewise for the MaverickCrunch coprocessor, we only have an 8-bit
word offset, which means a max 1024 byte offset, minus the 8 byte
minimum jump, etc.

Now, it seems whether this patch is applied (and turned on) or not
applied I get "co-processor offset out of range" errors, because of the
extra NOPs inserted between the jump and original label point.  I think
this in turn shifts the offset.  I can't see anyway to easily
recalculate or fix the coprocessor offset instructions, since this
happens AFTER the instruction has been generated.

I tried to hack around this by putting 2 NOPs before all cirrus
instructions, and modifying the length of each instruction.  I think
this means
that the coprocessor offset will be correct, since the NOP has been
generated BEFORE the instruction was generated.  However, it will mean
that all cirrus instructions are slower, since some will have additional
unneccessary NOPs appended before them.  I don't think that alone will
work, though...

I think the "co-processor offset out of range" error is generated
because of the cfldrs and cfldrd instructions.  These are used to Load
Floating Point Values from Memory into MaverickCrunch registers
directly.  I commented out the cirrus_movsf / cirrus_movdf insn patterns
(in asm generation), and it removed the error.  Does this mean that
someone calculated the pool_range & neg_pool_range attrs incorrectly, or
are the constraints I talk about below missing?

Is there something else in arm.c/h that I should be looking at?
arm_legitimate_index_p ??? arm_coproc_mem_operand ???
EXTRA_CONSTRAINT_STR_ARM ?

'Uv' is an address valid for VFP load/store insns. - i.e. doesn't
support writeback
'Uy' is an address valid for iwmmxt load/store insns. - i.e. supports
writeback

Is there supposed to be something similar for FPA / Maverick load/store
insns?  Or should it use the Uy mode?  Only the VFP supports the
writeback modes?  Autoincrement / decrement modes?  Only VFP does this,
I think...  I think m mode is only used for r->mE and m->r.  w->UvE & Uv
-> w for VFP.  y -> yrUy & yrUy -> y for iwMMXt.  However, this isn't
done for FPA.

Is this a bug for FPA?  Or hasn't it been picked up since no-one really
uses FPA?

Also, once I get the code doing what it's supposed to do, and generate a
patch against svn HEAD, do I need to do anything else special besides
posting it to gcc-patches, and letting it go through the review process?

http://gcc.gnu.org/contribute.html mentions some forms for "Legal
Prerequisites"...
diff -ruN /home/hwilliams/openembedded/build/tmp/work/ep9312-angstrom-linux-gnueabi/gcc-cross-4.1.2-r0/gcc-4.1.2/gcc/config/arm/arm.c gcc-4.1.2/gcc/config/arm/arm.c
--- /home/hwilliams/openembedded/build/tmp/work/ep9312-angstrom-linux-gnueabi/gcc-cross-4.1.2-r0/gcc-4.1.2/gcc/config/arm/arm.c	2007-05-09 16:32:29.000000000 +1000
+++ gcc-4.1.2/gcc/config/arm/arm.c	2007-05-15 09:39:41.000000000 +1000
@@ -4,6 +4,7 @@
    Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
    and Martin Simmons (@harleqn.co.uk).
    More major hacks by Richard Earnshaw (rearnsha@arm.com).
+   Cirrus Crunch bugfixes by Vladimir Ivanov (vladit@nucleusys.com)
 
    This file is part of GCC.
 
@@ -131,9 +132,17 @@
 static bool arm_xscale_rtx_costs (rtx, int, int, int *);
 static bool arm_9e_rtx_costs (rtx, int, int, int *);
 static int arm_address_cost (rtx);
-static bool arm_memory_load_p (rtx);
+// static bool arm_memory_load_p (rtx);
 static bool arm_cirrus_insn_p (rtx);
-static void cirrus_reorg (rtx);
+// static void cirrus_reorg (rtx);
+static bool arm_mem_access_p (rtx);
+static bool cirrus_dest_regn_p (rtx, int);
+static rtx cirrus_prev_next_mach_insn (rtx, int *, int);
+static rtx cirrus_prev_mach_insn (rtx, int *);
+static rtx cirrus_next_mach_insn (rtx, int *);
+static void cirrus_reorg_branch (rtx);
+static void cirrus_reorg_bug1 (rtx);
+static void cirrus_reorg_bug10_12 (rtx);
 static void arm_init_builtins (void);
 static rtx arm_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
 static void arm_init_iwmmxt_builtins (void);
@@ -5399,41 +5412,6 @@
               || TREE_CODE (valtype) == COMPLEX_TYPE));
 }
 
-/* Returns TRUE if INSN is an "LDR REG, ADDR" instruction.
-   Use by the Cirrus Maverick code which has to workaround
-   a hardware bug triggered by such instructions.  */
-static bool
-arm_memory_load_p (rtx insn)
-{
-  rtx body, lhs, rhs;;
-
-  if (insn == NULL_RTX || GET_CODE (insn) != INSN)
-    return false;
-
-  body = PATTERN (insn);
-
-  if (GET_CODE (body) != SET)
-    return false;
-
-  lhs = XEXP (body, 0);
-  rhs = XEXP (body, 1);
-
-  lhs = REG_OR_SUBREG_RTX (lhs);
-
-  /* If the destination is not a general purpose
-     register we do not have to worry.  */
-  if (GET_CODE (lhs) != REG
-      || REGNO_REG_CLASS (REGNO (lhs)) != GENERAL_REGS)
-    return false;
-
-  /* As well as loads from memory we also have to react
-     to loads of invalid constants which will be turned
-     into loads from the minipool.  */
-  return (GET_CODE (rhs) == MEM
-	  || GET_CODE (rhs) == SYMBOL_REF
-	  || note_invalid_constants (insn, -1, false));
-}
-
 /* Return TRUE if INSN is a Cirrus instruction.  */
 static bool
 arm_cirrus_insn_p (rtx insn)
@@ -5452,124 +5433,218 @@
   return attr != CIRRUS_NOT;
 }
 
-/* Cirrus reorg for invalid instruction combinations.  */
-static void
-cirrus_reorg (rtx first)
+/* Return TRUE if ISN does memory access.  */
+static bool
+arm_mem_access_p (rtx insn)
 {
-  enum attr_cirrus attr;
-  rtx body = PATTERN (first);
-  rtx t;
-  int nops;
+  enum attr_type attr;
 
-  /* 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);
+  /* 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;
 
-      if (arm_cirrus_insn_p (t))
-	++ nops;
+    attr = get_attr_type (insn);
 
-      if (arm_cirrus_insn_p (next_nonnote_insn (t)))
-	++ nops;
+  return attr == TYPE_LOAD_BYTE
+   || attr == TYPE_LOAD1   || attr == TYPE_LOAD2    || attr == TYPE_LOAD3 || attr == TYPE_LOAD4
+   || attr == TYPE_F_CVT
+   || attr == TYPE_F_MEM_R || attr == TYPE_R_MEM_F  || attr == TYPE_F_2_R || attr == TYPE_R_2_F
+   || attr == TYPE_F_LOAD	|| attr == TYPE_F_LOADS  || attr == TYPE_F_LOADD
+   || attr == TYPE_F_STORE || attr == TYPE_F_STORES || attr == TYPE_F_STORED
+   || attr == TYPE_STORE1  || attr == TYPE_STORE2   || attr == TYPE_STORE3  || attr == TYPE_STORE4;
+
+}
 
-      while (nops --)
-	emit_insn_after (gen_nop (), first);
+/* Return TRUE if destination is certain Cirrus register.  */
+static bool
+cirrus_dest_regn_p (rtx body, int regn)
+{
+  rtx lhs;
+  int reg;
+  lhs = XEXP (body, 0);
+  if (GET_CODE (lhs) != REG)
+    return 0;
 
-      return;
-    }
+  reg = REGNO (lhs);
+  if (REGNO_REG_CLASS (reg) != CIRRUS_REGS)
+    return 0;
 
-  /* (float (blah)) is in parallel with a clobber.  */
-  if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0)
-    body = XVECEXP (body, 0, 0);
+  return reg == regn;
+}
+
+/* Get previous/next machine instruction during Cirrus workaround scans.
+   Assume worst case (for the purpose of Cirrus workarounds)
+   for JUMP / CALL instructions.  */
+static rtx
+cirrus_prev_next_mach_insn (rtx insn, int *len, int next)
+{
+  rtx t;
+  int l = 0;
 
-  if (GET_CODE (body) == SET)
+  /* It seems that we can count only on INSN length.  */
+  for ( ; ; )
     {
-      rtx lhs = XEXP (body, 0), rhs = XEXP (body, 1);
+      if (next)
+    	insn = NEXT_INSN (insn);
+      else
+    	insn = PREV_INSN (insn);
+      if (!insn)
+    	break;
 
-      /* cfldrd, cfldr64, cfstrd, cfstr64 must
-	 be followed by a non Cirrus insn.  */
-      if (get_attr_cirrus (first) == CIRRUS_DOUBLE)
-	{
-	  if (arm_cirrus_insn_p (next_nonnote_insn (first)))
-	    emit_insn_after (gen_nop (), first);
+    if (GET_CODE (insn) == INSN)
+      {
+	    l = get_attr_length (insn) / 4;
+        if (l)
+	      break;
+      }
+    else if (GET_CODE (insn) == JUMP_INSN)
+      {
+        l = 1;
+        t = is_jump_table (insn);
+        if (t)
+          l += get_jump_table_size (t) / 4;
+        break;
+      }
+        else if (GET_CODE (insn) == CALL_INSN)
+      {
+        l = 1;
+        break;
+      }
+    }
 
-	  return;
-	}
-      else if (arm_memory_load_p (first))
-	{
-	  unsigned int arm_regno;
+  if (len)
+    *len = l;
 
-	  /* 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
-	    {
-	      gcc_assert (GET_CODE (rhs) == REG);
-	      arm_regno = REGNO (rhs);
-	    }
+  return insn;
+}
 
-	  /* Next insn.  */
-	  first = next_nonnote_insn (first);
+static rtx
+cirrus_prev_mach_insn (rtx insn, int *len)
+{
+  return cirrus_prev_next_mach_insn (insn, len, 0);
+}
 
-	  if (! arm_cirrus_insn_p (first))
-	    return;
+static rtx
+cirrus_next_mach_insn (rtx insn, int *len)
+{
+  return cirrus_prev_next_mach_insn (insn, len, 1);
+}
 
-	  body = PATTERN (first);
+/* Cirrus reorg for branch slots.  */
+static void
+cirrus_reorg_branch (rtx insn)
+{
+  rtx t;
+  int nops, l;
 
-          /* (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);
+  /* TODO: handle jump-tables.  */
+  t = is_jump_table (insn);
+  if (t)
+    return;
+
+  /* Any branch must be followed by 2 non Cirrus instructions.  */
+  t = insn;
+  for (nops = 2; nops > 0; )
+    {
+      if (!cirrus_next_mach_insn (t, 0))
+        {
+          insn = t;
+          break;
+        }
+      t = cirrus_next_mach_insn (t, &l);
+      if (arm_cirrus_insn_p (t))
+        break;
+      nops -= l;
 
-	  return;
-	}
     }
 
-  /* get_attr cannot accept USE or CLOBBER.  */
-  if (!first
-      || GET_CODE (first) != INSN
-      || GET_CODE (PATTERN (first)) == USE
-      || GET_CODE (PATTERN (first)) == CLOBBER)
-    return;
+  while (nops-- > 0)
+    emit_insn_after (gen_nop (), insn); /* WARNING: this appears to cause "bad immediate value for offset" errors in the assembler */
+}
 
-  attr = get_attr_cirrus (first);
+/* Cirrus reorg for bug #1 (cirrus + cfcmpxx).  */
+static void
+cirrus_reorg_bug1 (rtx insn)
+{
+  rtx body = PATTERN (insn), body2;
+  rtx t;
+  int i, nops, l;
+  enum attr_cirrus attr;
 
-  /* Any coprocessor compare instruction (cfcmps, cfcmpd, ...)
-     must be followed by a non-coprocessor instruction.  */
-  if (attr == CIRRUS_COMPARE)
+  /* Check if destination or clobber is Cirrus register.  */
+  if (GET_CODE (body) == PARALLEL)
     {
-      nops = 0;
-
-      t = next_nonnote_insn (first);
+      for (i = 0; i < XVECLEN (body, 0); i++)
+	  {
+	  body2 = XVECEXP (body, 0, i);
+      if (GET_CODE (body2) == SET)
+        {
+          if (cirrus_dest_regn_p (body2, LAST_CIRRUS_FP_REGNUM))
+            {
+		       nops = 5;
+               goto fix;
+            }
+        }
+      else if (GET_CODE (body2) == CLOBBER)
+        {
+          if (cirrus_dest_regn_p (body2, LAST_CIRRUS_FP_REGNUM))
+		    {
+		      nops = 4;
+		      goto fix;
+            }
+        }
+      }
+    }
+  else if (GET_CODE (body) == SET)
+    {
+      if (cirrus_dest_regn_p (body, LAST_CIRRUS_FP_REGNUM))
+	  {
+	    nops = 5;
+        goto fix;
+	  }
+    }
+  return;
 
-      if (arm_cirrus_insn_p (t))
-	++ nops;
+fix:
+  t = insn;
+  for ( ; nops > 0; )
+    {
+      t = cirrus_next_mach_insn (t, &l);
+      if (!t)
+	break;
+      if (GET_CODE (t) == JUMP_INSN
+	  || GET_CODE (t) == CALL_INSN)
+	{
+	  nops -= l;
+	  break;
+	}
+      else if (arm_cirrus_insn_p (t))
+	{
+	  attr = get_attr_cirrus (t);
+	  if (attr == CIRRUS_COMPARE)
+	    break;
+	}
+      nops -= l;
+    }
 
-      if (arm_cirrus_insn_p (next_nonnote_insn (t)))
-	++ nops;
+  while (nops-- > 0)
+    emit_insn_after (gen_nop (), insn); /* WARNING: this appears to cause "bad immediate value for offset" errors in the assembler */
+}
 
-      while (nops --)
-	emit_insn_after (gen_nop (), first);
+/* Cirrus reorg for bugs #10 and #12 (data aborts).  */
+static void
+cirrus_reorg_bug10_12 (rtx insn)
+{
+  rtx t;
 
-      return;
-    }
+  t = cirrus_next_mach_insn (insn, 0);
+  if (arm_cirrus_insn_p (t))
+    if (TARGET_CIRRUS_D0 ||
+	get_attr_cirrus (t) == CIRRUS_DOUBLE)
+      emit_insn_after (gen_nop (), insn); /* WARNING: this appears to cause "bad immediate value for offset" errors in the assembler */
 }
 
 /* Return TRUE if X references a SYMBOL_REF.  */
@@ -7727,7 +7796,7 @@
 {
   Mnode * mp;
   Mnode * nmp;
-  int align64 = 0;
+  int align64 = 0, stuffnop = 0;
 
   if (ARM_DOUBLEWORD_ALIGN)
     for (mp = minipool_vector_head; mp != NULL; mp = mp->next)
@@ -7742,8 +7811,27 @@
 	     ";; Emitting minipool after insn %u; address %ld; align %d (bytes)\n",
 	     INSN_UID (scan), (unsigned long) minipool_barrier->address, align64 ? 8 : 4);
 
+  /* Check if branch before minipool is already stuffed with nops.  */
+  if (TARGET_CIRRUS_D0 || TARGET_CIRRUS_D1)
+    {
+      rtx t;
+
+      t = prev_active_insn (scan);
+      if (GET_CODE (t) != INSN
+	  || PATTERN (t) != const0_rtx)
+	  stuffnop = 1;
+    }
   scan = emit_label_after (gen_label_rtx (), scan);
   scan = emit_insn_after (align64 ? gen_align_8 () : gen_align_4 (), scan);
+  /* Last instruction was branch, so put two non-Cirrus opcodes.  */
+  if (stuffnop)
+    {
+#if 1 /* This is doubling up on nops, so I don't think this is a good idea */
+      emit_insn_before (gen_nop (), scan); /* WARNING: this appears to cause "bad immediate value for offset" errors in the assembler */
+      emit_insn_before (gen_nop (), scan); /* WARNING: this appears to cause "bad immediate value for offset" errors in the assembler */
+#endif
+    }
+
   scan = emit_label_after (minipool_vector_label, scan);
 
   for (mp = minipool_vector_head; mp != NULL; mp = nmp)
@@ -8151,15 +8239,38 @@
   gcc_assert (GET_CODE (insn) == NOTE);
   minipool_pad = 0;
 
+#if 1 /* I think this is a double-up */
+  /* Scan all the insn and fix Cirrus issues.  */
+  if (TARGET_CIRRUS_D0 || TARGET_CIRRUS_D1)
+    {
+      rtx t, s;
+
+      for (t = cirrus_next_mach_insn (insn, 0); t; t = cirrus_next_mach_insn (t, 0))
+    if (arm_mem_access_p (t))
+      cirrus_reorg_bug10_12 (t);
+
+      if (TARGET_CIRRUS_D0)
+        for (t = cirrus_next_mach_insn (insn, 0); t; t = cirrus_next_mach_insn (t, 0))
+      if (arm_cirrus_insn_p (t))
+        cirrus_reorg_bug1 (t);
+
+      /* Find last insn.  */
+      for (t = insn; ; t = s)
+        {
+          s = cirrus_next_mach_insn (t, 0);
+          if (!s)
+            break;
+	    }
+      /* Scan backward and fix branches. - WARNING: appears to cause "bad immediate value for offset" problems! */
+      for ( ; t; t = cirrus_prev_mach_insn (t, 0))
+        if (GET_CODE (t) == JUMP_INSN
+        || GET_CODE (t) == CALL_INSN)
+          cirrus_reorg_branch (t);
+    }
+#endif
   /* Scan all the insns and record the operands that will need fixing.  */
   for (insn = next_nonnote_insn (insn); insn; insn = next_nonnote_insn (insn))
     {
-      if (TARGET_CIRRUS_FIX_INVALID_INSNS
-          && (arm_cirrus_insn_p (insn)
-	      || GET_CODE (insn) == JUMP_INSN
-	      || arm_memory_load_p (insn)))
-	cirrus_reorg (insn);
-
       if (GET_CODE (insn) == BARRIER)
 	push_minipool_barrier (insn, address);
       else if (INSN_P (insn))
@@ -11755,16 +11910,10 @@
 		  || 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_NOT)
+	      /* To avoid erratic behaviour, we avoid conditional Cirrus
+		 instructions when doing workarounds.  */
+	      if (arm_cirrus_insn_p(this_insn)
+    	  && (TARGET_CIRRUS_D0 || TARGET_CIRRUS_D1))
 		fail = TRUE;
 	      break;
 
diff -ruN /home/hwilliams/openembedded/build/tmp/work/ep9312-angstrom-linux-gnueabi/gcc-cross-4.1.2-r0/gcc-4.1.2/gcc/config/arm/arm.h gcc-4.1.2/gcc/config/arm/arm.h
--- /home/hwilliams/openembedded/build/tmp/work/ep9312-angstrom-linux-gnueabi/gcc-cross-4.1.2-r0/gcc-4.1.2/gcc/config/arm/arm.h	2005-11-05 01:02:51.000000000 +1000
+++ gcc-4.1.2/gcc/config/arm/arm.h	2007-05-15 10:15:05.000000000 +1000
@@ -5,6 +5,7 @@
    and Martin Simmons (@harleqn.co.uk).
    More major hacks by Richard Earnshaw (rearnsha@arm.com)
    Minor hacks by Nick Clifton (nickc@cygnus.com)
+   Cirrus Crunch fixes by Vladimir Ivanov (vladitx@nucleusys.com)
 
    This file is part of GCC.
 
@@ -140,7 +141,9 @@
 %{msoft-float:%{mhard-float:						\
 	%e-msoft-float and -mhard_float may not be used together}}	\
 %{mbig-endian:%{mlittle-endian:						\
-	%e-mbig-endian and -mlittle-endian may not be used together}}"
+	%e-mbig-endian and -mlittle-endian may not be used together}}  \
+%{mfix-crunch-d0:%{mfix-crunch-d1:					\
+	%e-mfix-crunch-d0 and -mfix-crunch-d1 may not be used together}}"
 
 #ifndef CC1_SPEC
 #define CC1_SPEC ""
@@ -179,6 +182,9 @@
 #define TARGET_HARD_FLOAT_ABI		(arm_float_abi == ARM_FLOAT_ABI_HARD)
 #define TARGET_FPA			(arm_fp_model == ARM_FP_MODEL_FPA)
 #define TARGET_MAVERICK			(arm_fp_model == ARM_FP_MODEL_MAVERICK)
+#define TARGET_CIRRUS			(arm_arch_cirrus)
+#define TARGET_CIRRUS_D0		0 /* (target_flags & ARM_FLAG_CIRRUS_D0) */
+#define TARGET_CIRRUS_D1		0 /* (target_flags & ARM_FLAG_CIRRUS_D1) */
 #define TARGET_VFP			(arm_fp_model == ARM_FP_MODEL_VFP)
 #define TARGET_IWMMXT			(arm_arch_iwmmxt)
 #define TARGET_REALLY_IWMMXT		(TARGET_IWMMXT && TARGET_ARM)
diff -ruN /home/hwilliams/openembedded/build/tmp/work/ep9312-angstrom-linux-gnueabi/gcc-cross-4.1.2-r0/gcc-4.1.2/gcc/config/arm/arm.opt gcc-4.1.2/gcc/config/arm/arm.opt
--- /home/hwilliams/openembedded/build/tmp/work/ep9312-angstrom-linux-gnueabi/gcc-cross-4.1.2-r0/gcc-4.1.2/gcc/config/arm/arm.opt	2005-11-05 01:02:51.000000000 +1000
+++ gcc-4.1.2/gcc/config/arm/arm.opt	2007-05-15 10:09:31.000000000 +1000
@@ -68,6 +68,14 @@
 Target Report Mask(CIRRUS_FIX_INVALID_INSNS)
 Cirrus: Place NOPs to avoid invalid instruction combinations
 
+fix-crunch-d0
+Target Report Mask(ARM_FLAG_CIRRUS_D0)
+Cirrus: workarounds for Crunch coprocessor revision D0
+
+fix-crunch-d1
+Target Report Mask(ARM_FLAG_CIRRUS_D1)
+Cirrus: workarounds for Crunch coprocessor revision D1
+
 mcpu=
 Target RejectNegative Joined
 Specify the name of the target CPU
diff -ruN /home/hwilliams/openembedded/build/tmp/work/ep9312-angstrom-linux-gnueabi/gcc-cross-4.1.2-r0/gcc-4.1.2/gcc/doc/invoke.texi gcc-4.1.2/gcc/doc/invoke.texi
--- /home/hwilliams/openembedded/build/tmp/work/ep9312-angstrom-linux-gnueabi/gcc-cross-4.1.2-r0/gcc-4.1.2/gcc/doc/invoke.texi	2006-09-26 07:21:58.000000000 +1000
+++ gcc-4.1.2/gcc/doc/invoke.texi	2007-05-15 10:07:04.000000000 +1000
@@ -408,7 +408,7 @@
 -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
+-mfix-crunch-d0 -mfix-crunch-d1 @gol
 -mpoke-function-name @gol
 -mthumb  -marm @gol
 -mtpcs-frame  -mtpcs-leaf-frame @gol
@@ -7435,17 +7435,12 @@
 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 implementations.  The default
-can be re-enabled by use of the @option{-mno-cirrus-fix-invalid-insns}
-switch.
+@item -mfix-crunch-d0
+@itemx -mfix-crunch-d1
+@opindex mfix-crunch-d0
+@opindex mfix-crunch-d1
+Enable workarounds for the Cirrus MaverickCrunch coprocessor revisions
+D0 and D1 respectively.
 
 @item -mpoke-function-name
 @opindex mpoke-function-name

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