------- Comment #2 from matz at gcc dot gnu dot org 2006-10-02 11:35 ------- Note that with this patch solves the bug for this testcase, but it still doesn't help with the general case. With this slightly changed testcase:
% cat large-ofs2.c static char l_info[100]; void bug1 (unsigned long tag) { char *info = l_info; info[tag - 0x100000000 + 1] = 1; } void bug2 (unsigned long tag) { char *info = l_info; info[tag - 0x100000000 + 1] = 2; } extern void abort(); int main() { unsigned i; for (i = 0; i < sizeof(l_info); i++) l_info[i] = 0; bug1(0x100000000); bug2(0x100000000); if (l_info[2] != 2 || l_info[1] != 1) abort(); return 0; } % gcc -S -O2 -fPIC -march=z9-109 large-ofs2.c % gcc large-ofs2.s large-ofs2.s: Assembler messages: large-ofs2.s:19: Error: value of -4294967312 too large for field of 4 bytes at 18 Note how the bodies of both functions is exactly the same, but still it only fails in the second function. For reference here the asm of both functions: 6 bug1: 7 .LFB2: 8 larl %r1,l_info-4294967296 9 lhi %r3,1 10 stc %r3,1(%r2,%r1) 11 br %r14 12 .LFE2: 13 .size bug1, .-bug1 14 .align 4 15 .globl bug2 16 .type bug2, @function 17 bug2: 18 .LFB3: 19 larl %r1,l_info-4294967296 20 lhi %r3,2 21 stc %r3,1(%r2,%r1) 22 br %r14 I assume the reason is, that the assembler somehow calculates this pc relative. In that case it could also break later during linking if the linker doesn't have special means to fix up too large offsets. So, I think s390x is in the same situation as x86-64. We can't allow large constant offsets on objects, even though instructions might accept them, because the object might become placed just a bit too far away, so that it's base is still in reach, while the offset added to it is not anymore. On x86-64 we solve that by artificially constraining the range of offsets. That should perhaps be done here too. E.g. by using DISP_IN_RANGE instead of the </>= test I copied from larl_operand. Up to the maintainers. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29319