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

Nick Clifton nickc@cygnus.com
Mon Apr 13 11:44:00 GMT 1998


: 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