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


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

[patch] coprocessor modes


[oops, wrong list]

> Coprocessor types - the MeP chip has optional coprocessors, each with
> their own register sets.  They need their own internal types (mostly
> to keep track of which unit to use), which we've created by prefixing
> the existing types with COP (i.e. COPSImode, COPDFmode, etc).  This
> affects the generators, some MI files, etc.  The types don't exist
> unless the target calls for them.

Here's the first pass at this portion of the patch, originally written
by Richard over three years ago.  No regressions on i686-linux.

2007-03-26  Richard Sandiford  <rsandifo@gcc.gnu.org>
	    DJ Delorie  <dj@redhat.com>

	* tree.h (signed_copro_types, unsigned_copro_types): Declare.

	* machmode.h (copro_modes): Declare.
	(COPRO_MODE_P): New macro.
	(COPRO_MODE, NON_COPRO_MODE): New macros.

	* rtl.h (COPRO_VALUE_P): New macro.

	* expr.c (convert_move): Handle conversions involving coprocessor
	modes by converting to the equivalent non-coprocessor mode.
	Remove truncation handling.
	(subreg_strength, change_int_mode): New functions.
	(emit_move_insn_1): Consider changing between coprocessor and
	non-coprocessor modes if doing so would avoid a subreg.
	(expand_expr_real_1): Treat coprocessor targets like normal
	REGs.  Don't set SUBREG_PROMOTED_VAR_P if a decl's mode is the
	coprocessor equivalent of the type's mode.  Return a SUBREG
	for coprocessor variables.

	* optabs.c (expand_unop, expand_binop): Handle coprocessor modes
	like the equivalent non-coprocessor mode, then convert the result.

	* tree.c (signed_copro_types, unsigned_copro_types): Define.
	(build_common_tree_nodes): Initialize them.

	* c-common.c (c_common_type_for_mode): Handle coprocessor modes.

	* postreload.c (reload_cse_move2add): Don't look for strict lowparts
	of coprocessor modes.

	* reload.c (find_reloads_toplev): Fix order of coprocessor-related
	reg_equiv_constant check.

	* genmodes.c (struct mode_data): Add copro_p field.
	(blank_mode): Add an entry for it in the initializer.
	(mode_prefixes): New array.
	(for_all_mode_prefixes): New macro.
	(COPRO_MODE): Redefine.
	(make_copro_mode): New function.
	(tagged_printf): Take a prefix as argument.
	(emit_insn_modes_h): Iterate over each mode prefix.
	(emit_mode_name, emit_mode_class, emit_mode_bitsize): Likewise.
	(emit_mode_size, emit_mode_unit_size, emit_mode_wider): Likewise.
	(emit_mode_mask, emit_mode_inner, emit_mode_base_align): Likewise.
	(emit_real_format_for_mode): Likewise.
	(emit_class_narrowest_mode): Update call to tagged_printf.
	(emit_copro_table): New function.
	(emit_insn_modes_c): Call it.

	* emit-rtl.c (insn_emit_once): Create tiny constants for COP?I modes.

	* c-typeck.c (convert_for_assignment): Don't relax reference check.

	* expmed.c (expand_mult): If the variable operand is a coprocessor
	value, use a coprocessor accumulator.
	

Index: machmode.h
===================================================================
--- machmode.h	(revision 123248)
+++ machmode.h	(working copy)
@@ -41,12 +41,25 @@ enum mode_class { MODE_CLASSES, MAX_MODE
 /* Get the general kind of object that mode MODE represents
    (integer, floating, complex, etc.)  */
 
 extern const unsigned char mode_class[NUM_MACHINE_MODES];
 #define GET_MODE_CLASS(MODE)  mode_class[MODE]
 
+extern const unsigned char copro_modes[NUM_MACHINE_MODES][2];
+
+/* Return the coprocessor mode for MODE, or MODE itself if there
+   is none.  */
+#define COPRO_MODE(MODE) copro_modes[MODE][1]
+
+/* The reverse of COPRO_MODE.  */
+#define NON_COPRO_MODE(MODE) copro_modes[MODE][0]
+
+/* True if MODE is a coprocessor mode.  */
+#define COPRO_MODE_P(MODE) (NON_COPRO_MODE (MODE) != MODE)
+
+
 /* Nonzero if MODE is an integral mode.  */
 #define INTEGRAL_MODE_P(MODE)			\
   (GET_MODE_CLASS (MODE) == MODE_INT		\
    || GET_MODE_CLASS (MODE) == MODE_PARTIAL_INT \
    || GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT \
    || GET_MODE_CLASS (MODE) == MODE_VECTOR_INT)
Index: optabs.c
===================================================================
--- optabs.c	(revision 123248)
+++ optabs.c	(working copy)
@@ -1254,12 +1254,21 @@ expand_binop (enum machine_mode mode, op
 		  || binoptab->code == ROTATE
 		  || binoptab->code == ROTATERT);
   rtx entry_last = get_last_insn ();
   rtx last;
   bool first_pass_p = true;
 
+  if (COPRO_MODE_P (mode))
+    {
+      if (target)
+	target = gen_lowpart (NON_COPRO_MODE (mode), target);
+      return gen_lowpart (mode, expand_binop (NON_COPRO_MODE (mode),
+					      binoptab, op0, op1,
+					      target, unsignedp, methods));
+    }
+
   class = GET_MODE_CLASS (mode);
 
   /* If subtracting an integer constant, convert this into an addition of
      the negated constant.  */
 
   if (binoptab == sub_optab && GET_CODE (op1) == CONST_INT)
@@ -1322,12 +1331,14 @@ expand_binop (enum machine_mode mode, op
       enum machine_mode tmp_mode;
       rtx pat;
       rtx xop0 = op0, xop1 = op1;
 
       if (target)
 	temp = target;
+      else if (COPRO_VALUE_P (op0) || COPRO_VALUE_P (op1))
+	temp = gen_lowpart (mode, gen_reg_rtx (COPRO_MODE (mode)));
       else
 	temp = gen_reg_rtx (mode);
 
       /* If it is a commutative operator and the modes would match
 	 if we would swap the operands, we can save the conversions.  */
       if (commutative_op)
@@ -2656,22 +2667,32 @@ expand_unop (enum machine_mode mode, opt
   enum mode_class class;
   enum machine_mode wider_mode;
   rtx temp;
   rtx last = get_last_insn ();
   rtx pat;
 
+  if (COPRO_MODE_P (mode))
+    {
+      if (target)
+	target = gen_lowpart (NON_COPRO_MODE (mode), target);
+      return gen_lowpart (mode, expand_unop (NON_COPRO_MODE (mode),
+					     unoptab, op0, target, unsignedp));
+    }
+
   class = GET_MODE_CLASS (mode);
 
   if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
     {
       int icode = (int) unoptab->handlers[(int) mode].insn_code;
       enum machine_mode mode0 = insn_data[icode].operand[1].mode;
       rtx xop0 = op0;
 
       if (target)
 	temp = target;
+      else if (COPRO_VALUE_P (op0))
+	temp = gen_lowpart (mode, gen_reg_rtx (COPRO_MODE (mode)));
       else
 	temp = gen_reg_rtx (mode);
 
       if (GET_MODE (xop0) != VOIDmode
 	  && GET_MODE (xop0) != mode0)
 	xop0 = convert_to_mode (mode0, xop0, unsignedp);
Index: tree.c
===================================================================
--- tree.c	(revision 123248)
+++ tree.c	(working copy)
@@ -107,12 +107,14 @@ static const char * const tree_node_kind
 
 /* Unique id for next decl created.  */
 static GTY(()) int next_decl_uid;
 /* Unique id for next type created.  */
 static GTY(()) int next_type_uid = 1;
 
+tree signed_copro_types   [MAX_MACHINE_MODE];
+tree unsigned_copro_types [MAX_MACHINE_MODE];
 /* Since we cannot rehash a type after it is in the table, we have to
    keep the hash code.  */
 
 struct type_hash GTY(())
 {
   unsigned long hash;
@@ -6920,12 +6922,26 @@ build_common_tree_nodes (bool signed_cha
   unsigned_intDI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (DImode), 1);
   unsigned_intTI_type_node = make_or_reuse_type (GET_MODE_BITSIZE (TImode), 1);
 
   access_public_node = get_identifier ("public");
   access_protected_node = get_identifier ("protected");
   access_private_node = get_identifier ("private");
+
+  {
+    enum machine_mode mode;
+
+    for (mode = 0; mode < MAX_MACHINE_MODE; mode ++)
+      if (COPRO_MODE_P (mode))
+	{
+	  signed_copro_types[mode] = make_signed_type (GET_MODE_BITSIZE (mode));
+	  unsigned_copro_types[mode]
+	    = make_unsigned_type (GET_MODE_BITSIZE (mode));
+	  TYPE_MODE (signed_copro_types[mode]) = mode;
+	  TYPE_MODE (unsigned_copro_types[mode]) = mode;
+	}
+  }
 }
 
 /* Call this function after calling build_common_tree_nodes and set_sizetype.
    It will create several other common tree nodes.  */
 
 void
Index: tree.h
===================================================================
--- tree.h	(revision 123248)
+++ tree.h	(working copy)
@@ -3448,12 +3448,14 @@ enum tree_index
   TI_MAIN_IDENTIFIER,
 
   TI_MAX
 };
 
 extern GTY(()) tree global_trees[TI_MAX];
+extern GTY(()) tree signed_copro_types   [MAX_MACHINE_MODE];
+extern GTY(()) tree unsigned_copro_types [MAX_MACHINE_MODE];
 
 #define error_mark_node			global_trees[TI_ERROR_MARK]
 
 #define intQI_type_node			global_trees[TI_INTQI_TYPE]
 #define intHI_type_node			global_trees[TI_INTHI_TYPE]
 #define intSI_type_node			global_trees[TI_INTSI_TYPE]
Index: reload.c
===================================================================
--- reload.c	(revision 123248)
+++ reload.c	(working copy)
@@ -4611,13 +4611,18 @@ find_reloads_toplev (rtx x, int opnum, e
 	  && (tem = gen_lowpart_common (GET_MODE (x),
 					reg_equiv_constant[regno])) != 0)
 	return tem;
 
       if (regno >= FIRST_PSEUDO_REGISTER
 	  && reg_renumber[regno] < 0
-	  && reg_equiv_constant[regno] != 0)
+	  && reg_equiv_constant[regno] != 0
+	  /* Symbolic constants have no representation in coprocessor
+	     modes.  Just handle known constants.  */
+	  && (!COPRO_MODE_P (GET_MODE (x))
+	      || GET_CODE (reg_equiv_constant[regno]) == CONST_INT
+	      || GET_CODE (reg_equiv_constant[regno]) == CONST_DOUBLE))
 	{
 	  tem =
 	    simplify_gen_subreg (GET_MODE (x), reg_equiv_constant[regno],
 				 GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
 	  gcc_assert (tem);
 	  return tem;
Index: expr.c
===================================================================
--- expr.c	(revision 123248)
+++ expr.c	(working copy)
@@ -132,12 +132,14 @@ static void emit_block_move_via_loop (rt
 static rtx clear_by_pieces_1 (void *, HOST_WIDE_INT, enum machine_mode);
 static void clear_by_pieces (rtx, unsigned HOST_WIDE_INT, unsigned int);
 static void store_by_pieces_1 (struct store_by_pieces *, unsigned int);
 static void store_by_pieces_2 (rtx (*) (rtx, ...), enum machine_mode,
 			       struct store_by_pieces *);
 static tree clear_storage_libcall_fn (int);
+static int subreg_strength (rtx);
+static rtx change_int_mode (enum machine_mode, rtx);
 static rtx compress_float_constant (rtx, rtx);
 static rtx get_subtarget (rtx);
 static void store_constructor_field (rtx, unsigned HOST_WIDE_INT,
 				     HOST_WIDE_INT, enum machine_mode,
 				     tree, tree, int, int);
 static void store_constructor (tree, rtx, int, HOST_WIDE_INT);
@@ -381,12 +383,26 @@ convert_move (rtx to, rtx from, int unsi
       || (from_mode == VOIDmode && CONSTANT_P (from)))
     {
       emit_move_insn (to, from);
       return;
     }
 
+  if (COPRO_MODE_P (from_mode))
+    {
+      convert_move (to, change_int_mode (NON_COPRO_MODE (from_mode), from),
+		    unsignedp);
+      return;
+    }
+
+  if (COPRO_MODE_P (to_mode))
+    {
+      convert_move (change_int_mode (NON_COPRO_MODE (to_mode), to),
+		    from, unsignedp);
+      return;
+    }
+
   if (VECTOR_MODE_P (to_mode) || VECTOR_MODE_P (from_mode))
     {
       gcc_assert (GET_MODE_BITSIZE (from_mode) == GET_MODE_BITSIZE (to_mode));
 
       if (VECTOR_MODE_P (to_mode))
 	from = simplify_gen_subreg (to_mode, from, GET_MODE (from), 0);
@@ -3240,24 +3256,71 @@ emit_move_multi_word (enum machine_mode 
 
   emit_insn (seq);
 
   return last_insn;
 }
 
+/* Subroutine of emit_move_insn_1.  See if it would be better to convert
+   X from a coprocessor mode to a non-coprocessor mode (or vice versa)
+   before using it.  Return 1 if it would be benifical.  Return 0 if it
+   could be done but doesn't matter either way.  Return -1 if it shouldn't
+   be done.  */
+static int
+subreg_strength (rtx x)
+{
+  if (GET_CODE (x) == SUBREG
+      && COPRO_MODE (GET_MODE (x)) == COPRO_MODE (GET_MODE (SUBREG_REG (x))))
+    return 1;
+
+  if (GET_CODE (x) == MEM || CONSTANT_P (x))
+    return 0;
+
+  return -1;
+}
+
+/* Change X so that it has the given integer mode.
+   X already has an integer mode of the same size.  */
+static rtx
+change_int_mode (enum machine_mode mode, rtx x)
+{
+  if (GET_MODE (x) == VOIDmode)
+    return x;
+
+  if (GET_CODE (x) == MEM)
+    return change_address (x, mode, 0);
+
+  return simplify_gen_subreg (mode, x, GET_MODE (x), 0);
+}
+
 /* Low level part of emit_move_insn.
    Called just like emit_move_insn, but assumes X and Y
    are basically valid.  */
 
 rtx
 emit_move_insn_1 (rtx x, rtx y)
 {
   enum machine_mode mode = GET_MODE (x);
   enum insn_code code;
 
   gcc_assert ((unsigned int) mode < (unsigned int) MAX_MACHINE_MODE);
 
+  /* See whether we're moving into or out of an expression such as
+     (subreg:SI (reg:COPSI FOO)).  If we are, and the other operand
+     could be converted to COPSImode without making it more complex,
+     then it is better to do the move in COPSImode instead.
+
+     This a way of reducing the number of SUBREGs involved in
+     coprocessor operations: most optimization passes work better
+     when moves are between bare registers.  */
+  if (subreg_strength (x) + subreg_strength (y) > 0)
+    {
+      mode = (COPRO_MODE_P (mode) ? NON_COPRO_MODE (mode) : COPRO_MODE (mode));
+      x = change_int_mode (mode, x);
+      y = change_int_mode (mode, y);
+    }
+
   code = mov_optab->handlers[mode].insn_code;
   if (code != CODE_FOR_nothing)
     return emit_insn (GEN_FCN (code) (x, y));
 
   /* Expand complex moves by moving real part and imag part.  */
   if (COMPLEX_MODE_P (mode))
@@ -7034,17 +7097,23 @@ expand_expr_real_1 (tree exp, rtx target
 	  pmode = promote_mode (type, DECL_MODE (exp), &unsignedp,
 				(TREE_CODE (exp) == RESULT_DECL
 				 || TREE_CODE (exp) == PARM_DECL) ? 1 : 0);
 	  gcc_assert (GET_MODE (decl_rtl) == pmode);
 
 	  temp = gen_lowpart_SUBREG (mode, decl_rtl);
-	  SUBREG_PROMOTED_VAR_P (temp) = 1;
-	  SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
+          if (GET_MODE (DECL_RTL (exp)) != COPRO_MODE (DECL_MODE (exp)))
+	    {
+	      SUBREG_PROMOTED_VAR_P (temp) = 1;
+	      SUBREG_PROMOTED_UNSIGNED_SET (temp, unsignedp);
+	    }
 	  return temp;
 	}
 
+      if (COPRO_MODE_P (DECL_MODE (exp)))
+	return gen_lowpart (mode, DECL_RTL (exp));
+
       return decl_rtl;
 
     case INTEGER_CST:
       temp = immed_double_const (TREE_INT_CST_LOW (exp),
 				 TREE_INT_CST_HIGH (exp), mode);
 
Index: genmodes.c
===================================================================
--- genmodes.c	(revision 123248)
+++ genmodes.c	(working copy)
@@ -59,12 +59,14 @@ struct mode_data
   unsigned int precision;	/* size in bits, equiv to TYPE_PRECISION */
   unsigned int bytesize;	/* storage size in addressable units */
   unsigned int ncomponents;	/* number of subunits */
   unsigned int alignment;	/* mode alignment */
   const char *format;		/* floating point format - float modes only */
 
+  bool copro_p;			/* mode has a coprocessor variant.  */
+
   struct mode_data *component;	/* mode of components */
   struct mode_data *wider;	/* next wider mode */
   struct mode_data *wider_2x;	/* 2x wider mode */
 
   struct mode_data *contained;  /* Pointer to list of modes that have
 				   this mode as a component.  */
@@ -79,13 +81,13 @@ static struct mode_data *modes[MAX_MODE_
 static unsigned int n_modes[MAX_MODE_CLASS];
 static struct mode_data *void_mode;
 
 static const struct mode_data blank_mode = {
   0, "<unknown>", MAX_MODE_CLASS,
   -1U, -1U, -1U, -1U,
-  0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0,
   "<unknown>", 0, 0
 };
 
 static htab_t modes_by_name;
 
 /* Data structure for recording target-specified runtime adjustments
@@ -102,12 +104,14 @@ struct mode_adjust
 };
 
 static struct mode_adjust *adj_bytesize;
 static struct mode_adjust *adj_alignment;
 static struct mode_adjust *adj_format;
 
+static const char *const mode_prefixes[] = { "", "COP" };
+
 /* Mode class operations.  */
 static enum mode_class
 complex_class (enum mode_class c)
 {
   switch (c)
     {
@@ -193,12 +197,17 @@ eq_mode (const void *p, const void *q)
 }
 
 #define for_all_modes(C, M)			\
   for (C = 0; C < MAX_MODE_CLASS; C++)		\
     for (M = modes[C]; M; M = M->next)
 
+#define for_all_mode_prefixes(C, M, P)		\
+  for (C = 0; C < MAX_MODE_CLASS; C ++)		\
+    for (M = modes[C]; M; M = M->next)		\
+      for (P = 0; P <= M->copro_p; P ++)
+
 static void ATTRIBUTE_UNUSED
 new_adjust (const char *name,
 	    struct mode_adjust **category, const char *catname,
 	    const char *adjustment,
 	    enum mode_class required_class,
 	    const char *file, unsigned int line)
@@ -654,12 +663,28 @@ make_vector_mode (enum mode_class bclass
 
   v = new_mode (vclass, xstrdup (namebuf), file, line);
   v->ncomponents = ncomponents;
   v->component = component;
 }
 
+#undef  COPRO_MODE
+#define COPRO_MODE(BASE) \
+  make_copro_mode (#BASE, __FILE__, __LINE__);
+
+static void ATTRIBUTE_UNUSED
+make_copro_mode (const char * base, const char * file, unsigned int line)
+{
+  struct mode_data * component;
+
+  component = find_mode (base);
+  if (component)
+    component->copro_p = true;
+  else
+    error ("%s:%d: no mode \"%s\"", file, line, base);
+}
+
 /* Adjustability.  */
 #define _ADD_ADJUST(A, M, X, C) \
   new_adjust (#M, &adj_##A, #A, #X, MODE_##C, __FILE__, __LINE__)
 
 #define ADJUST_BYTESIZE(M, X)  _ADD_ADJUST(bytesize, M, X, RANDOM)
 #define ADJUST_ALIGNMENT(M, X) _ADD_ADJUST(alignment, M, X, RANDOM)
@@ -782,16 +807,16 @@ calc_wider_mode (void)
 	}
     }
 }
 
 /* Output routines.  */
 
-#define tagged_printf(FMT, ARG, TAG) do {		\
+#define tagged_printf(FMT, ARG, PREFIX, TAG) do {	\
   int count_;						\
   printf ("  " FMT ",%n", ARG, &count_);		\
-  printf ("%*s/* %s */\n", 27 - count_, "", TAG);	\
+  printf ("%*s/* %s%s */\n", 27 - count_, "", PREFIX, TAG);	\
 } while (0)
 
 #define print_decl(TYPE, NAME, ASIZE) \
   puts ("\nconst " TYPE " " NAME "[" ASIZE "] =\n{");
 
 #define print_maybe_const_decl(TYPE, NAME, ASIZE, CATEGORY)	\
@@ -802,12 +827,13 @@ calc_wider_mode (void)
 
 static void
 emit_insn_modes_h (void)
 {
   int c;
   struct mode_data *m, *first, *last;
+  int p;
 
   printf ("/* Generated automatically from machmode.def%s%s\n",
 	   HAVE_EXTRA_MODES ? " and " : "",
 	   EXTRA_MODES_FILE);
 
   puts ("\
@@ -817,18 +843,19 @@ emit_insn_modes_h (void)
 #define GCC_INSN_MODES_H\n\
 \n\
 enum machine_mode\n{");
 
   for (c = 0; c < MAX_MODE_CLASS; c++)
     for (m = modes[c]; m; m = m->next)
-      {
-	int count_;
-	printf ("  %smode,%n", m->name, &count_);
-	printf ("%*s/* %s:%d */\n", 27 - count_, "",
-		 trim_filename (m->file), m->line);
-      }
+      for (p = 0; p <= m->copro_p; p++)
+	{
+	  int count_;
+	  printf ("  %s%smode,%n", mode_prefixes[p], m->name, &count_);
+	  printf ("%*s/* %s:%d */\n", 27 - count_, "",
+		  trim_filename (m->file), m->line);
+	}
 
   puts ("  MAX_MACHINE_MODE,\n");
 
   for (c = 0; c < MAX_MODE_CLASS; c++)
     {
       first = modes[c];
@@ -903,98 +930,104 @@ emit_min_insn_modes_c_header (void)
 
 static void
 emit_mode_name (void)
 {
   int c;
   struct mode_data *m;
+  int p;
 
   print_decl ("char *const", "mode_name", "NUM_MACHINE_MODES");
 
-  for_all_modes (c, m)
-    printf ("  \"%s\",\n", m->name);
+  for_all_mode_prefixes (c, m, p)
+    printf ("  \"%s%s\",\n", mode_prefixes[p], m->name);
 
   print_closer ();
 }
 
 static void
 emit_mode_class (void)
 {
   int c;
   struct mode_data *m;
+  int p;
 
   print_decl ("unsigned char", "mode_class", "NUM_MACHINE_MODES");
 
-  for_all_modes (c, m)
-    tagged_printf ("%s", mode_class_names[m->cl], m->name);
+   for_all_mode_prefixes (c, m, p)
+     tagged_printf ("%s", mode_class_names[m->cl], mode_prefixes[p], m->name);
 
   print_closer ();
 }
 
 static void
 emit_mode_precision (void)
 {
   int c;
   struct mode_data *m;
+  int p;
 
   print_decl ("unsigned short", "mode_precision", "NUM_MACHINE_MODES");
 
-  for_all_modes (c, m)
+  for_all_mode_prefixes (c, m, p)
     if (m->precision != (unsigned int)-1)
-      tagged_printf ("%u", m->precision, m->name);
+      tagged_printf ("%u", m->precision, mode_prefixes[p], m->name);
     else
-      tagged_printf ("%u*BITS_PER_UNIT", m->bytesize, m->name);
+      tagged_printf ("%u*BITS_PER_UNIT", m->bytesize, mode_prefixes[p], m->name);
 
   print_closer ();
 }
 
 static void
 emit_mode_size (void)
 {
   int c;
   struct mode_data *m;
+  int p;
 
   print_maybe_const_decl ("%sunsigned char", "mode_size",
 			  "NUM_MACHINE_MODES", bytesize);
 
-  for_all_modes (c, m)
-    tagged_printf ("%u", m->bytesize, m->name);
+  for_all_mode_prefixes (c, m, p)
+    tagged_printf ("%u", m->bytesize, mode_prefixes[p], m->name);
 
   print_closer ();
 }
 
 static void
 emit_mode_nunits (void)
 {
   int c;
   struct mode_data *m;
+  int p;
 
   print_decl ("unsigned char", "mode_nunits", "NUM_MACHINE_MODES");
 
-  for_all_modes (c, m)
-    tagged_printf ("%u", m->ncomponents, m->name);
+  for_all_mode_prefixes (c, m, p)
+    tagged_printf ("%u", m->ncomponents, mode_prefixes[p], m->name);
 
   print_closer ();
 }
 
 static void
 emit_mode_wider (void)
 {
   int c;
   struct mode_data *m;
+  int p;
 
   print_decl ("unsigned char", "mode_wider", "NUM_MACHINE_MODES");
 
-  for_all_modes (c, m)
+  for_all_mode_prefixes (c, m, p)
     tagged_printf ("%smode",
 		   m->wider ? m->wider->name : void_mode->name,
-		   m->name);
+		   mode_prefixes[p], m->name);
 
   print_closer ();
   print_decl ("unsigned char", "mode_2xwider", "NUM_MACHINE_MODES");
 
-  for_all_modes (c, m)
+  for_all_mode_prefixes (c, m, p)
     {
       struct mode_data * m2;
 
       for (m2 = m;
 	   m2 && m2 != void_mode;
 	   m2 = m2->wider)
@@ -1015,70 +1048,73 @@ emit_mode_wider (void)
 	  break;
 	}
       if (m2 == void_mode)
 	m2 = 0;
       tagged_printf ("%smode",
 		     m2 ? m2->name : void_mode->name,
-		     m->name);
+		     mode_prefixes[p], m->name);
     }
 
   print_closer ();
 }
 
 static void
 emit_mode_mask (void)
 {
   int c;
   struct mode_data *m;
+  int p;
 
   print_decl ("unsigned HOST_WIDE_INT", "mode_mask_array",
 	      "NUM_MACHINE_MODES");
   puts ("\
 #define MODE_MASK(m)                          \\\n\
   ((m) >= HOST_BITS_PER_WIDE_INT)             \\\n\
    ? ~(unsigned HOST_WIDE_INT) 0              \\\n\
    : ((unsigned HOST_WIDE_INT) 1 << (m)) - 1\n");
 
-  for_all_modes (c, m)
+  for_all_mode_prefixes (c, m, p)
     if (m->precision != (unsigned int)-1)
-      tagged_printf ("MODE_MASK (%u)", m->precision, m->name);
+      tagged_printf ("MODE_MASK (%u)", m->precision, mode_prefixes[p], m->name);
     else
-      tagged_printf ("MODE_MASK (%u*BITS_PER_UNIT)", m->bytesize, m->name);
+      tagged_printf ("MODE_MASK (%u*BITS_PER_UNIT)", m->bytesize, mode_prefixes[p], m->name);
 
   puts ("#undef MODE_MASK");
   print_closer ();
 }
 
 static void
 emit_mode_inner (void)
 {
   int c;
   struct mode_data *m;
+  int p;
 
   print_decl ("unsigned char", "mode_inner", "NUM_MACHINE_MODES");
 
-  for_all_modes (c, m)
+  for_all_mode_prefixes (c, m, p)
     tagged_printf ("%smode",
 		   m->component ? m->component->name : void_mode->name,
-		   m->name);
+		   mode_prefixes[p], m->name);
 
   print_closer ();
 }
 
 static void
 emit_mode_base_align (void)
 {
   int c;
   struct mode_data *m;
+  int p;
 
   print_maybe_const_decl ("%sunsigned char",
 			  "mode_base_align", "NUM_MACHINE_MODES",
 			  alignment);
 
-  for_all_modes (c, m)
-    tagged_printf ("%u", m->alignment, m->name);
+  for_all_mode_prefixes (c, m, p)
+    tagged_printf ("%u", m->alignment, mode_prefixes[p], m->name);
 
   print_closer ();
 }
 
 static void
 emit_class_narrowest_mode (void)
@@ -1086,13 +1122,13 @@ emit_class_narrowest_mode (void)
   int c;
 
   print_decl ("unsigned char", "class_narrowest_mode", "MAX_MODE_CLASS");
 
   for (c = 0; c < MAX_MODE_CLASS; c++)
     /* Bleah, all this to get the comment right for MIN_MODE_INT.  */
-    tagged_printf ("MIN_%s", mode_class_names[c],
+    tagged_printf ("MIN_%s", mode_class_names[c], "",
 		   modes[c]
 		   ? (modes[c]->precision != 1
 		      ? modes[c]->name
 		      : (modes[c]->next
 			 ? modes[c]->next->name
 			 : void_mode->name))
@@ -1102,12 +1138,13 @@ emit_class_narrowest_mode (void)
 }
 
 static void
 emit_real_format_for_mode (void)
 {
   struct mode_data *m;
+  int p;
 
   /* The entities pointed to by this table are constant, whether
      or not the table itself is constant.
 
      For backward compatibility this table is always writable
      (several targets modify it in OVERRIDE_OPTIONS).   FIXME:
@@ -1122,23 +1159,25 @@ emit_real_format_for_mode (void)
 	      "MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1 "
 	      "+ MAX_MODE_DECIMAL_FLOAT - MIN_MODE_DECIMAL_FLOAT + 1");
 #endif
 
   /* The beginning of the table is entries for float modes.  */
   for (m = modes[MODE_FLOAT]; m; m = m->next)
-    if (!strcmp (m->format, "0"))
-      tagged_printf ("%s", m->format, m->name);
-    else
-      tagged_printf ("&%s", m->format, m->name);
+    for (p = 0; p <= m->copro_p; p++)
+      if (!strcmp (m->format, "0"))
+	tagged_printf ("%s", m->format, mode_prefixes[p], m->name);
+      else
+	tagged_printf ("&%s", m->format, mode_prefixes[p], m->name);
 
   /* The end of the table is entries for decimal float modes.  */
   for (m = modes[MODE_DECIMAL_FLOAT]; m; m = m->next)
-    if (!strcmp (m->format, "0"))
-      tagged_printf ("%s", m->format, m->name);
-    else
-      tagged_printf ("&%s", m->format, m->name);
+    for (p = 0; p <= m->copro_p; p++)
+      if (!strcmp (m->format, "0"))
+	tagged_printf ("%s", m->format, mode_prefixes[p], m->name);
+      else
+	tagged_printf ("&%s", m->format, mode_prefixes[p], m->name);
 
   print_closer ();
 }
 
 static void
 emit_mode_adjustments (void)
@@ -1228,12 +1267,30 @@ emit_mode_adjustments (void)
 	    a->file, a->line, a->mode->name, a->adjustment);
 
   puts ("}");
 }
 
 static void
+emit_copro_table (void)
+{
+  int c;
+  struct mode_data * m;
+  int p;
+
+  puts ("\nconst unsigned char copro_modes [NUM_MACHINE_MODES][2] = {");
+
+  for_all_mode_prefixes (c, m, p)
+    if (m->copro_p)
+      printf ("  { %smode, COP%smode },\n", m->name, m->name);
+    else
+      printf ("  { %smode, %smode },\n", m->name, m->name);
+
+  print_closer ();
+}
+
+static void
 emit_insn_modes_c (void)
 {
   emit_insn_modes_c_header ();
   emit_mode_name ();
   emit_mode_class ();
   emit_mode_precision ();
@@ -1243,12 +1300,13 @@ emit_insn_modes_c (void)
   emit_mode_mask ();
   emit_mode_inner ();
   emit_mode_base_align ();
   emit_class_narrowest_mode ();
   emit_real_format_for_mode ();
   emit_mode_adjustments ();
+  emit_copro_table ();
 }
 
 static void
 emit_min_insn_modes_c (void)
 {
   emit_min_insn_modes_c_header ();
Index: expmed.c
===================================================================
--- expmed.c	(revision 123248)
+++ expmed.c	(working copy)
@@ -2982,23 +2982,26 @@ expand_mult_const (enum machine_mode mod
   enum machine_mode nmode;
 
   /* Avoid referencing memory over and over and invalid sharing
      on SUBREGs.  */
   op0 = force_reg (mode, op0);
 
+  accum = gen_reg_rtx (COPRO_VALUE_P (op0) ? COPRO_MODE (mode) : mode);
+  accum = simplify_gen_subreg (mode, accum, GET_MODE (accum), 0);
+
   /* ACCUM starts out either as OP0 or as a zero, depending on
      the first operation.  */
 
   if (alg->op[0] == alg_zero)
     {
-      accum = copy_to_mode_reg (mode, const0_rtx);
+      emit_move_insn (accum, const0_rtx);
       val_so_far = 0;
     }
   else if (alg->op[0] == alg_m)
     {
-      accum = copy_to_mode_reg (mode, op0);
+      emit_move_insn (accum, op0);
       val_so_far = 1;
     }
   else
     gcc_unreachable ();
 
   for (opno = 1; opno < alg->ops; opno++)
Index: emit-rtl.c
===================================================================
--- emit-rtl.c	(revision 123248)
+++ emit-rtl.c	(working copy)
@@ -5225,12 +5225,17 @@ init_emit_once (int line_numbers)
 	const_tiny_rtx[i][(int) mode] = GEN_INT (i);
 
       for (mode = GET_CLASS_NARROWEST_MODE (MODE_PARTIAL_INT);
 	   mode != VOIDmode;
 	   mode = GET_MODE_WIDER_MODE (mode))
 	const_tiny_rtx[i][(int) mode] = GEN_INT (i);
+
+      for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
+	   mode = GET_MODE_WIDER_MODE (mode))
+	if (COPRO_MODE (mode) != mode)
+	  const_tiny_rtx[i][COPRO_MODE (mode)] = GEN_INT (i);
     }
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
        mode != VOIDmode;
        mode = GET_MODE_WIDER_MODE (mode))
     {
Index: rtl.h
===================================================================
--- rtl.h	(revision 123248)
+++ rtl.h	(working copy)
@@ -1412,12 +1412,18 @@ do {						\
 #endif
 
 #ifndef USE_STORE_POST_INCREMENT
 #define USE_STORE_POST_INCREMENT(MODE)  HAVE_POST_INCREMENT
 #endif
 
+/* True if X was declared to be in a coprocessor register.  */
+#define COPRO_VALUE_P(X)			\
+  (GET_CODE (X) == SUBREG			\
+   && REG_P (SUBREG_REG (X))			\
+   && COPRO_MODE_P (GET_MODE (SUBREG_REG (X))))
+
 #ifndef USE_STORE_POST_DECREMENT
 #define USE_STORE_POST_DECREMENT(MODE)  HAVE_POST_DECREMENT
 #endif
 
 #ifndef USE_STORE_PRE_INCREMENT
 #define USE_STORE_PRE_INCREMENT(MODE)   HAVE_PRE_INCREMENT
Index: c-common.c
===================================================================
--- c-common.c	(revision 123248)
+++ c-common.c	(working copy)
@@ -1895,12 +1895,15 @@ static GTY(()) tree registered_builtin_t
 
 tree
 c_common_type_for_mode (enum machine_mode mode, int unsignedp)
 {
   tree t;
 
+  if (COPRO_MODE_P (mode))
+    return unsignedp ? unsigned_copro_types[mode] : signed_copro_types[mode];
+
   if (mode == TYPE_MODE (integer_type_node))
     return unsignedp ? unsigned_type_node : integer_type_node;
 
   if (mode == TYPE_MODE (signed_char_type_node))
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
 


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