egcs-980406 (and earlier)/ARM ldrsb - incorrect offset range

Richard Earnshaw Richard.Earnshaw@arm.com
Tue Apr 14 22:02:00 GMT 1998


I'm out of the office at the moment, so I can't generate a patch.  But I
think a better approach would be to handle this case by modifying the
sign-extend pattern to cope with this (until such time as gcc is extended
to handle addressing modes on a pattern-by-pattern basis).  This would
probably be much more efficient than restricting all byte accesses to a
range of +/- 255 bytes.  The way to do this is by adding (part of) the
offset into the target register, and then using the modified address as the
basis of the load.  Ie, for this case, the code generated should be:

         mov     ip, sp
         stmfd   sp!, {fp, ip, lr, pc}
         sub     fp, ip, #4
         add     r0, r0, #768
         ldrsb   r0, [r0, #32]
         ldmea   fp, {fp, sp, pc}^

At 11:30 13/04/98 -0700, Nick Clifton wrote:
>: Date: Sat, 11 Apr 1998 01:36:41 +0100 (BST)
>: From: Dave Gilbert <gilbertd@treblig.org>
>: 
>: Hi,
>:   In egcs-980406 (and earlier versions) the address offset range of the
>: ldrsb instruction (introduced in ARM architecture v4) is set to be the
>: same as normal ARM ldr (load register) instructions when it is actually
>: a lot smaller.  The following example excersises this:
>: 
>: ------------------------------------------------------------------------
>: struct foo {
>:   int padding[200];
>:   signed char toget;
>: };
>: 
>: signed char bar(struct foo* p) {
>:   return p->toget;
>: };
>: -------------------------------------------------------------------------
>: gcc -mcpu=strongarm110  egbug.c -O2
>: /tmp/cca06251.s: Assembler messages:
>: /tmp/cca06251.s:19: Error: address offset too large
>: 
>: _bar:
>:         @ args = 0, pretend = 0, frame = 0
>:         @ frame_needed = 1, current_function_anonymous_args = 0
>:         mov     ip, sp
>:         stmfd   sp!, {fp, ip, lr, pc}
>:         sub     fp, ip, #4
>:         ldrsb   r0, [r0, #800]     ******** Range should be +/- 255
>:         ldmea   fp, {fp, sp, pc}^
>: 
>
>Applying this patch fixes the problem:
>
>Index: arm.h
>===================================================================
>RCS file: /egcs/carton/cvsfiles/egcs/gcc/config/arm/arm.h,v
>retrieving revision 1.5
>diff -p -r1.5 arm.h
>*** arm.h	1998/04/08 06:19:00	1.5
>--- arm.h	1998/04/13 18:30:02
>*************** do									\
>*** 1408,1414 ****
>  	      && INTVAL (op) <= 31)					\
>  	    goto LABEL;							\
>          }								\
>!       range = (MODE) == HImode ? (arm_arch4 ? 256 : 4095) : 4096;	\
>        if (code == CONST_INT && INTVAL (INDEX) < range			\
>  	  && INTVAL (INDEX) > -range)  	      				\
>          goto LABEL;							\
>--- 1408,1416 ----
>  	      && INTVAL (op) <= 31)					\
>  	    goto LABEL;							\
>          }								\
>!       /* NASTY: Since this limits the addressing of unsigned byte loads
*/      \
>!       range = ((MODE) == HImode || (MODE) == QImode)                    \
>!               ? (arm_arch4 ? 256 : 4095) : 4096;                        \
>        if (code == CONST_INT && INTVAL (INDEX) < range			\
>  	  && INTVAL (INDEX) > -range)  	      				\
>          goto LABEL;							\
>
>The code now produced looks like this:
>
>  _bar:
>        mov     ip, sp
>        stmfd   sp!, {fp, ip, lr, pc}
>        mov     r3, #800
>        sub     fp, ip, #4
>        ldrsb   r0, [r0, r3]
>        ldmea   fp, {fp, sp, pc}
>
>Nick
>
>



More information about the Gcc-bugs mailing list