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]

sparc64 changes and generic backend patches


This weekend I merged the sparc64 work to support Sun's official,
though still unpublished, Sparc v9 ABI.  

I went ahead and committed the bits under the sparc subdirectory.
This shouldn't affect sunos, solaris, or sparc-linux users.  It
will affect sparc64-linux users, but then yall have been waiting
on this for some time.

However, as-is it is fairly brittle, as there are generic backend
changes yet to be applied.  I present several of them here.

(1) Attachment 1 rewrites emit_group_load/store to handle all of the
    nifty structure size and alignment problems that do not affect the
    IRIX6 n64 ABI.  The canonical problem struct is

	struct foo { char x[7]; };

    which might live at page_boundary-7.  The old code would produce
    either an unaligned trap or a segmentation fault trying to load
    these bits into the single outgoing 64-bit register.

(2) Attachment 2 disables a check in reload not applicable to Sparc's
    32-bit FP regs when considered with a 64-bit word size.

(3) Attachment 3 contains a few unidentified fixes I found in my tree.
    Most of it consists of propogating a change made by Jeff

    Wed Dec 31 01:28:37 1997  Jeff Law  <law@cygnus.com>

	* expr.c (expand_expr): For {BITFIELD,COMPONENT,ARRAY}_REF, if the
	offset's mode is not ptr_mode, convert it.

    to the other similar cases in the same function.

    It also contains a change to store_expr that appears to be a typo.
    I can't remember the problem it caused, but I present it for your
    consideration.

In addition to this, there appear to be some reload problems that
were not present some months ago.  And some bad interactions with
SImode data in FP regs and the fact that user variables are subject
to promote_mode in stmt.c.  These are not addressed here.


r~
Sun May  3 14:28:51 1998  Richard Henderson  <rth@cygnus.com>

	* expr.c (emit_group_load, emit_group_store): Rewrite considering
	the size and alignment of the structure being manipulated.  Update
	all callers.
	* cse.c (invalidate): Cope with parallels.


Index: calls.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/calls.c,v
retrieving revision 1.21
diff -c -p -d -r1.21 calls.c
*** calls.c	1998/04/29 12:41:21	1.21
--- calls.c	1998/05/03 21:22:23
*************** expand_call (exp, target, ignore)
*** 1920,1926 ****
  	     locations.  The Irix 6 ABI has examples of this.  */
  
  	  if (GET_CODE (reg) == PARALLEL)
! 	    emit_group_load (reg, args[i].value);
  
  	  /* If simple case, just do move.  If normal partial, store_one_arg
  	     has already loaded the register for us.  In all other cases,
--- 1920,1931 ----
  	     locations.  The Irix 6 ABI has examples of this.  */
  
  	  if (GET_CODE (reg) == PARALLEL)
! 	    {
! 	      emit_group_load (reg, args[i].value,
! 			       int_size_in_bytes (TREE_TYPE (args[i].tree_value)),
! 			       (TYPE_ALIGN (TREE_TYPE (args[i].tree_value))
! 				/ BITS_PER_UNIT));
! 	    }
  
  	  /* If simple case, just do move.  If normal partial, store_one_arg
  	     has already loaded the register for us.  In all other cases,
*************** expand_call (exp, target, ignore)
*** 2087,2101 ****
       The Irix 6 ABI has examples of this.  */
    else if (GET_CODE (valreg) == PARALLEL)
      {
        if (target == 0)
  	{
- 	  int bytes = int_size_in_bytes (TREE_TYPE (exp));
  	  target = assign_stack_temp (TYPE_MODE (TREE_TYPE (exp)), bytes, 0);
  	  MEM_IN_STRUCT_P (target) = AGGREGATE_TYPE_P (TREE_TYPE (exp));
  	  preserve_temp_slots (target);
  	}
  
!       emit_group_store (target, valreg);
      }
    else if (target && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp))
  	   && GET_MODE (target) == GET_MODE (valreg))
--- 2092,2108 ----
       The Irix 6 ABI has examples of this.  */
    else if (GET_CODE (valreg) == PARALLEL)
      {
+       int bytes = int_size_in_bytes (TREE_TYPE (exp));
+ 
        if (target == 0)
  	{
  	  target = assign_stack_temp (TYPE_MODE (TREE_TYPE (exp)), bytes, 0);
  	  MEM_IN_STRUCT_P (target) = AGGREGATE_TYPE_P (TREE_TYPE (exp));
  	  preserve_temp_slots (target);
  	}
  
!       emit_group_store (target, valreg, bytes,
! 			TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
      }
    else if (target && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp))
  	   && GET_MODE (target) == GET_MODE (valreg))
Index: cse.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cse.c,v
retrieving revision 1.30
diff -c -p -d -r1.30 cse.c
*** cse.c	1998/04/24 13:03:42	1.30
--- cse.c	1998/05/03 21:22:23
*************** invalidate (x, full_mode)
*** 1528,1533 ****
--- 1528,1548 ----
    register int i;
    register struct table_elt *p;
  
+   /* If X is a parallel, invalidate all of its elements.  */
+ 
+   if (GET_CODE (x) == PARALLEL)
+     {
+       for (i = XVECLEN (x, 0) - 1; i >= 0 ; --i)
+ 	invalidate (XVECEXP (x, 0, i), full_mode);
+       return;
+     }
+ 
+   /* If X is an expr_list, this is part of a disjoint return value;
+      extract the location in question ignoring the offset.  */
+ 
+   if (GET_CODE (x) == EXPR_LIST)
+     x = XEXP (x, 0);
+ 
    /* If X is a register, dependencies on its contents
       are recorded through the qty number mechanism.
       Just change the qty number of the register,
Index: expr.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/expr.c,v
retrieving revision 1.50
diff -c -p -d -r1.50 expr.c
*** expr.c	1998/04/28 19:12:47	1.50
--- expr.c	1998/05/03 21:22:24
*************** move_block_from_reg (regno, x, nregs, si
*** 1804,1906 ****
      }
  }
  
! /* Emit code to move a block Y to a block X, where X is non-consecutive
!    registers represented by a PARALLEL.  */
  
  void
! emit_group_load (x, y)
!      rtx x, y;
  {
!   rtx target_reg, source;
!   int i;
  
!   if (GET_CODE (x) != PARALLEL)
      abort ();
  
    /* Check for a NULL entry, used to indicate that the parameter goes
       both on the stack and in registers.  */
!   if (XEXP (XVECEXP (x, 0, 0), 0))
!     i = 0;
    else
!     i = 1;
  
!   for (; i < XVECLEN (x, 0); i++)
      {
!       rtx element = XVECEXP (x, 0, i);
  
!       target_reg = XEXP (element, 0);
  
!       if (GET_CODE (y) == MEM)
! 	source = change_address (y, GET_MODE (target_reg),
! 				 plus_constant (XEXP (y, 0),
! 						INTVAL (XEXP (element, 1))));
!       else if (XEXP (element, 1) == const0_rtx)
  	{
! 	  if (GET_MODE (target_reg) == GET_MODE (y))
! 	    source = y;
! 	  /* Allow for the target_reg to be smaller than the input register
! 	     to allow for AIX with 4 DF arguments after a single SI arg.  The
! 	     last DF argument will only load 1 word into the integer registers,
! 	     but load a DF value into the float registers.  */
! 	  else if ((GET_MODE_SIZE (GET_MODE (target_reg))
! 		    <= GET_MODE_SIZE (GET_MODE (y)))
! 		   && GET_MODE (target_reg) == word_mode)
! 	    /* This might be a const_double, so we can't just use SUBREG.  */
! 	    source = operand_subword (y, 0, 0, VOIDmode);
! 	  else if (GET_MODE_SIZE (GET_MODE (target_reg))
! 		   == GET_MODE_SIZE (GET_MODE (y)))
! 	    source = gen_lowpart (GET_MODE (target_reg), y);
! 	  else
! 	    abort ();	    
  	}
        else
! 	abort ();
  
!       emit_move_insn (target_reg, source);
      }
  }
  
! /* Emit code to move a block Y to a block X, where Y is non-consecutive
!    registers represented by a PARALLEL.  */
  
  void
! emit_group_store (x, y)
!      rtx x, y;
  {
!   rtx source_reg, target;
!   int i;
  
!   if (GET_CODE (y) != PARALLEL)
      abort ();
  
    /* Check for a NULL entry, used to indicate that the parameter goes
       both on the stack and in registers.  */
!   if (XEXP (XVECEXP (y, 0, 0), 0))
!     i = 0;
    else
!     i = 1;
  
!   for (; i < XVECLEN (y, 0); i++)
      {
!       rtx element = XVECEXP (y, 0, i);
  
!       source_reg = XEXP (element, 0);
  
!       if (GET_CODE (x) == MEM)
! 	target = change_address (x, GET_MODE (source_reg),
! 				 plus_constant (XEXP (x, 0),
! 						INTVAL (XEXP (element, 1))));
!       else if (XEXP (element, 1) == const0_rtx)
  	{
! 	  target = x;
! 	  if (GET_MODE (target) != GET_MODE (source_reg))
! 	    target = gen_lowpart (GET_MODE (source_reg), target);
  	}
-       else
- 	abort ();
  
!       emit_move_insn (target, source_reg);
      }
  }
  
  /* Add a USE expression for REG to the (possibly empty) list pointed
--- 1804,1982 ----
      }
  }
  
! /* Emit code to move a block SRC to a block DST, where DST is non-consecutive
!    registers represented by a PARALLEL.  SSIZE represents the total size of
!    block SRC, or -1 if not known.  ALIGN is the known alignment of SRC.  */
  
  void
! emit_group_load (dst, orig_src, ssize, align)
!      rtx dst, orig_src;
!      int align, ssize;
  {
!   rtx *tmps, src;
!   int start, i;
  
!   if (GET_CODE (dst) != PARALLEL)
      abort ();
  
    /* Check for a NULL entry, used to indicate that the parameter goes
       both on the stack and in registers.  */
!   if (XEXP (XVECEXP (dst, 0, 0), 0))
!     start = 0;
    else
!     start = 1;
  
!   tmps = (rtx *) alloca (sizeof(rtx) * XVECLEN (dst, 0));
! 
!   /* If we won't be loading directly from memory, protect the real source
!      from strange tricks we might play.  */
!   src = orig_src;
!   if (GET_CODE (src) != MEM)
      {
!       src = gen_reg_rtx (GET_MODE (orig_src));
!       emit_move_insn (src, orig_src);
!     }
  
!   /* Process the pieces.  */
!   for (i = start; i < XVECLEN (dst, 0); i++)
!     {
!       enum machine_mode mode = GET_MODE (XEXP (XVECEXP (dst, 0, i), 0));
!       int bytepos = INTVAL (XEXP (XVECEXP (dst, 0, i), 1));
!       int bytelen = GET_MODE_SIZE (mode);
!       int shift = 0;
  
!       /* Handle trailing fragments that run over the size of the struct.  */
!       if (ssize >= 0 && bytepos + bytelen > ssize)
  	{
! 	  shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT;
! 	  bytelen = ssize - bytepos;
! 	  if (bytelen <= 0)
! 	    abort();
  	}
+ 
+       /* Optimize the access just a bit.  */
+       if (GET_CODE (src) == MEM
+ 	  && align*BITS_PER_UNIT >= GET_MODE_ALIGNMENT (mode)
+ 	  && bytepos*BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
+ 	  && bytelen == GET_MODE_SIZE (mode))
+ 	{
+ 	  tmps[i] = gen_reg_rtx (mode);
+ 	  emit_move_insn (tmps[i],
+ 			  change_address (src, mode,
+ 					  plus_constant (XEXP (src, 0),
+ 							 bytepos)));
+ 	}
        else
! 	{
! 	  tmps[i] = extract_bit_field (src, bytelen*BITS_PER_UNIT,
! 				       bytepos*BITS_PER_UNIT, 1, NULL_RTX,
! 				       mode, mode, align, ssize);
! 	}
  
!       if (BITS_BIG_ENDIAN && shift)
! 	{
! 	  expand_binop (mode, ashl_optab, tmps[i], GEN_INT (shift),
! 			tmps[i], 0, OPTAB_WIDEN);
! 	}
      }
+   emit_queue();
+ 
+   /* Copy the extracted pieces into the proper (probable) hard regs.  */
+   for (i = start; i < XVECLEN (dst, 0); i++)
+     emit_move_insn (XEXP (XVECEXP (dst, 0, i), 0), tmps[i]);
  }
  
! /* Emit code to move a block SRC to a block DST, where SRC is non-consecutive
!    registers represented by a PARALLEL.  SSIZE represents the total size of
!    block DST, or -1 if not known.  ALIGN is the known alignment of DST.  */
  
  void
! emit_group_store (orig_dst, src, ssize, align)
!      rtx orig_dst, src;
!      int ssize, align;
  {
!   rtx *tmps, dst;
!   int start, i;
  
!   if (GET_CODE (src) != PARALLEL)
      abort ();
  
    /* Check for a NULL entry, used to indicate that the parameter goes
       both on the stack and in registers.  */
!   if (XEXP (XVECEXP (src, 0, 0), 0))
!     start = 0;
    else
!     start = 1;
  
!   tmps = (rtx *) alloca (sizeof(rtx) * XVECLEN (src, 0));
! 
!   /* Copy the (probable) hard regs into pseudos.  */
!   for (i = start; i < XVECLEN (src, 0); i++)
      {
!       rtx reg = XEXP (XVECEXP (src, 0, i), 0);
!       tmps[i] = gen_reg_rtx (GET_MODE (reg));
!       emit_move_insn (tmps[i], reg);
!     }
!   emit_queue();
  
!   /* If we won't be storing directly into memory, protect the real destination
!      from strange tricks we might play.  */
!   dst = orig_dst;
!   if (GET_CODE (dst) != MEM)
!     {
!       dst = gen_reg_rtx (GET_MODE (orig_dst));
!       /* Make life a bit easier for combine.  */
!       emit_move_insn (dst, const0_rtx);
!     }
!   else if (! MEM_IN_STRUCT_P (dst))
!     {
!       /* store_bit_field requires that memory operations have
! 	 mem_in_struct_p set; we might not.  */
  
!       dst = gen_rtx (MEM, GET_MODE (orig_dst), XEXP (orig_dst, 0));
!       MEM_IN_STRUCT_P (dst) = 1;
!     }
! 
!   /* Process the pieces.  */
!   for (i = start; i < XVECLEN (src, 0); i++)
!     {
!       int bytepos = INTVAL (XEXP (XVECEXP (src, 0, i), 1));
!       enum machine_mode mode = GET_MODE (tmps[i]);
!       int bytelen = GET_MODE_SIZE (mode);
! 
!       /* Handle trailing fragments that run over the size of the struct.  */
!       if (ssize >= 0 && bytepos + bytelen > ssize)
  	{
! 	  if (BITS_BIG_ENDIAN)
! 	    {
! 	      int shift = (bytelen - (ssize - bytepos)) * BITS_PER_UNIT;
! 	      expand_binop (mode, ashr_optab, tmps[i], GEN_INT (shift),
! 			    tmps[i], 0, OPTAB_WIDEN);
! 	    }
! 	  bytelen = ssize - bytepos;
  	}
  
!       /* Optimize the access just a bit.  */
!       if (GET_CODE (dst) == MEM
! 	  && align*BITS_PER_UNIT >= GET_MODE_ALIGNMENT (mode)
! 	  && bytepos*BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0
! 	  && bytelen == GET_MODE_SIZE (mode))
! 	{
! 	  emit_move_insn (change_address (dst, mode,
! 					  plus_constant (XEXP (dst, 0),
! 							 bytepos)),
! 			  tmps[i]);
! 	}
!       else
! 	{
! 	  store_bit_field (dst, bytelen*BITS_PER_UNIT, bytepos*BITS_PER_UNIT,
! 			   mode, tmps[i], align, ssize);
! 	}
      }
+ 
+   /* Copy from the pseudo into the (probable) hard reg.  */
+   if (GET_CODE (dst) == REG)
+     emit_move_insn (orig_dst, dst);
  }
  
  /* Add a USE expression for REG to the (possibly empty) list pointed
*************** emit_push_insn (x, mode, type, size, ali
*** 2840,2846 ****
        /* Handle calls that pass values in multiple non-contiguous locations.
  	 The Irix 6 ABI has examples of this.  */
        if (GET_CODE (reg) == PARALLEL)
! 	emit_group_load (reg, x);
        else
  	move_block_to_reg (REGNO (reg), x, partial, mode);
      }
--- 2916,2922 ----
        /* Handle calls that pass values in multiple non-contiguous locations.
  	 The Irix 6 ABI has examples of this.  */
        if (GET_CODE (reg) == PARALLEL)
! 	emit_group_load (reg, x, -1, align);  /* ??? size? */
        else
  	move_block_to_reg (REGNO (reg), x, partial, mode);
      }
*************** expand_assignment (to, from, want_value,
*** 3019,3025 ****
        /* Handle calls that return values in multiple non-contiguous locations.
  	 The Irix 6 ABI has examples of this.  */
        if (GET_CODE (to_rtx) == PARALLEL)
! 	emit_group_load (to_rtx, value);
        else if (GET_MODE (to_rtx) == BLKmode)
  	emit_block_move (to_rtx, value, expr_size (from),
  			 TYPE_ALIGN (TREE_TYPE (from)) / BITS_PER_UNIT);
--- 3105,3112 ----
        /* Handle calls that return values in multiple non-contiguous locations.
  	 The Irix 6 ABI has examples of this.  */
        if (GET_CODE (to_rtx) == PARALLEL)
! 	emit_group_load (to_rtx, value, int_size_in_bytes (TREE_TYPE (from)),
! 			 TYPE_ALIGN (TREE_TYPE (from)) / BITS_PER_UNIT);
        else if (GET_MODE (to_rtx) == BLKmode)
  	emit_block_move (to_rtx, value, expr_size (from),
  			 TYPE_ALIGN (TREE_TYPE (from)) / BITS_PER_UNIT);
*************** store_expr (exp, target, want_value)
*** 3420,3426 ****
        /* Handle calls that return values in multiple non-contiguous locations.
  	 The Irix 6 ABI has examples of this.  */
        else if (GET_CODE (target) == PARALLEL)
! 	emit_group_load (target, temp);
        else if (GET_MODE (temp) == BLKmode)
  	emit_block_move (target, temp, expr_size (exp),
  			 TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
--- 3507,3514 ----
        /* Handle calls that return values in multiple non-contiguous locations.
  	 The Irix 6 ABI has examples of this.  */
        else if (GET_CODE (target) == PARALLEL)
! 	emit_group_load (target, temp, int_size_in_bytes (TREE_TYPE (exp)),
! 			 TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
        else if (GET_MODE (temp) == BLKmode)
  	emit_block_move (target, temp, expr_size (exp),
  			 TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT);
Index: expr.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/expr.h,v
retrieving revision 1.11
diff -c -p -d -r1.11 expr.h
*** expr.h	1998/04/04 17:37:51	1.11
--- expr.h	1998/05/03 21:22:24
*************** extern void move_block_from_reg PROTO((i
*** 700,709 ****
  
  /* Load a BLKmode value into non-consecutive registers represented by a
     PARALLEL.  */
! extern void emit_group_load PROTO((rtx, rtx));
  /* Store a BLKmode value from non-consecutive registers represented by a
     PARALLEL.  */
! extern void emit_group_store PROTO((rtx, rtx));
  
  /* Mark REG as holding a parameter for the next CALL_INSN.  */
  extern void use_reg PROTO((rtx *, rtx));
--- 700,709 ----
  
  /* Load a BLKmode value into non-consecutive registers represented by a
     PARALLEL.  */
! extern void emit_group_load PROTO((rtx, rtx, int, int));
  /* Store a BLKmode value from non-consecutive registers represented by a
     PARALLEL.  */
! extern void emit_group_store PROTO((rtx, rtx, int, int));
  
  /* Mark REG as holding a parameter for the next CALL_INSN.  */
  extern void use_reg PROTO((rtx *, rtx));
Index: function.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/function.c,v
retrieving revision 1.26
diff -c -p -d -r1.26 function.c
*** function.c	1998/04/16 22:08:49	1.26
--- function.c	1998/05/03 21:22:24
*************** assign_parms (fndecl, second_time)
*** 3899,3906 ****
  		  /* Handle calls that pass values in multiple non-contiguous
  		     locations.  The Irix 6 ABI has examples of this.  */
  		  if (GET_CODE (entry_parm) == PARALLEL)
! 		    emit_group_store (validize_mem (stack_parm),
! 					 entry_parm);
  		  else
  		    move_block_from_reg (REGNO (entry_parm),
  					 validize_mem (stack_parm), nregs,
--- 3899,3908 ----
  		  /* Handle calls that pass values in multiple non-contiguous
  		     locations.  The Irix 6 ABI has examples of this.  */
  		  if (GET_CODE (entry_parm) == PARALLEL)
! 		    emit_group_store (validize_mem (stack_parm), entry_parm,
! 				      int_size_in_bytes (TREE_TYPE (parm)),
! 				      (TYPE_ALIGN (TREE_TYPE (parm))
! 				       / BITS_PER_UNIT));
  		  else
  		    move_block_from_reg (REGNO (entry_parm),
  					 validize_mem (stack_parm), nregs,
*************** assign_parms (fndecl, second_time)
*** 4070,4076 ****
  	      /* Handle calls that pass values in multiple non-contiguous
  		 locations.  The Irix 6 ABI has examples of this.  */
  	      if (GET_CODE (entry_parm) == PARALLEL)
! 		emit_group_store (validize_mem (stack_parm), entry_parm);
  	      else
  		move_block_from_reg (REGNO (entry_parm),
  				     validize_mem (stack_parm),
--- 4072,4081 ----
  	      /* Handle calls that pass values in multiple non-contiguous
  		 locations.  The Irix 6 ABI has examples of this.  */
  	      if (GET_CODE (entry_parm) == PARALLEL)
! 		emit_group_store (validize_mem (stack_parm), entry_parm,
! 				  int_size_in_bytes (TREE_TYPE (parm)),
! 				  (TYPE_ALIGN (TREE_TYPE (parm))
! 				   / BITS_PER_UNIT));
  	      else
  		move_block_from_reg (REGNO (entry_parm),
  				     validize_mem (stack_parm),
Sun May  3 14:31:16 1998  Richard Henderson  <rth@cygnus.com>

	* reload.c (find_reloads): Don't prohibit reloading into registers
	smaller than the word size.

Index: reload.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/reload.c,v
retrieving revision 1.23
diff -c -p -d -r1.23 reload.c
*** reload.c	1998/05/01 17:40:50	1.23
--- reload.c	1998/05/03 21:22:25
*************** find_reloads (insn, replace, ind_levels,
*** 2806,2812 ****
  		     registers for subregging to work.  */
  		  || (GET_CODE (operand) == REG
  		      && REGNO (operand) < FIRST_PSEUDO_REGISTER
! 		      && ((GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
  			   && (GET_MODE_SIZE (GET_MODE (operand))
  			       > UNITS_PER_WORD)
  			   && ((GET_MODE_SIZE (GET_MODE (operand))
--- 2806,2815 ----
  		     registers for subregging to work.  */
  		  || (GET_CODE (operand) == REG
  		      && REGNO (operand) < FIRST_PSEUDO_REGISTER
! 		      && ((/* ??? Disable this test because Sparc64 FP regs
! 			      are smaller than one word.  */
! 			   0
! 			   && GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
  			   && (GET_MODE_SIZE (GET_MODE (operand))
  			       > UNITS_PER_WORD)
  			   && ((GET_MODE_SIZE (GET_MODE (operand))
Index: expr.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/expr.c,v
retrieving revision 1.50
diff -c -p -d -r1.50 expr.c
*** expr.c	1998/04/28 19:12:47	1.50
--- expr.c	1998/05/03 21:22:24
*************** expand_assignment (to, from, want_value,
*** 2912,2917 ****
--- 2988,3003 ----
  
  	  if (GET_CODE (to_rtx) != MEM)
  	    abort ();
+ 
+ 	  if (GET_MODE (offset_rtx) != ptr_mode)
+ 	    {
+ #ifdef POINTERS_EXTEND_UNSIGNED
+ 	      offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 1);
+ #else
+ 	      offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
+ #endif
+ 	    }
+ 
  	  to_rtx = change_address (to_rtx, VOIDmode,
  				   gen_rtx_PLUS (ptr_mode, XEXP (to_rtx, 0),
  						 force_reg (ptr_mode, offset_rtx)));
*************** store_expr (exp, target, want_value)
*** 3312,3318 ****
      {
        target = protect_from_queue (target, 1);
        if (GET_MODE (temp) != GET_MODE (target)
! 	  && GET_MODE (temp) != VOIDmode)
  	{
  	  int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
  	  if (dont_return_target)
--- 3399,3405 ----
      {
        target = protect_from_queue (target, 1);
        if (GET_MODE (temp) != GET_MODE (target)
! 	  && GET_MODE (target) != VOIDmode)
  	{
  	  int unsignedp = TREE_UNSIGNED (TREE_TYPE (exp));
  	  if (dont_return_target)
*************** store_constructor (exp, target, cleared)
*** 3678,3683 ****
--- 3766,3780 ----
  	      if (GET_CODE (to_rtx) != MEM)
  		abort ();
  
+               if (GET_MODE (offset_rtx) != ptr_mode)
+                 {
+ #ifdef POINTERS_EXTEND_UNSIGNED
+                   offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 1);
+ #else
+                   offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
+ #endif
+                 }
+ 
  	      to_rtx
  		= change_address (to_rtx, VOIDmode,
  				  gen_rtx_PLUS (ptr_mode, XEXP (to_rtx, 0),
*************** expand_expr (exp, target, tmode, modifie
*** 5737,5747 ****
  	      abort ();
  
  	    if (GET_MODE (offset_rtx) != ptr_mode)
  #ifdef POINTERS_EXTEND_UNSIGNED
! 	      offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 1);
  #else
! 	      offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
  #endif
  
  	    op0 = change_address (op0, VOIDmode,
  				  gen_rtx_PLUS (ptr_mode, XEXP (op0, 0),
--- 5834,5846 ----
  	      abort ();
  
  	    if (GET_MODE (offset_rtx) != ptr_mode)
+ 	      {
  #ifdef POINTERS_EXTEND_UNSIGNED
! 		offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 1);
  #else
! 		offset_rtx = convert_to_mode (ptr_mode, offset_rtx, 0);
  #endif
+ 	      }
  
  	    op0 = change_address (op0, VOIDmode,
  				  gen_rtx_PLUS (ptr_mode, XEXP (op0, 0),

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