This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
sparc64 changes and generic backend patches
- To: egcs at cygnus dot com
- Subject: sparc64 changes and generic backend patches
- From: Richard Henderson <rth at cygnus dot com>
- Date: Sun, 3 May 1998 14:56:48 -0700
- Reply-To: Richard Henderson <rth at cygnus dot com>
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),