ham@Neon.Stanford.EDU (Peter R. Ham) (12/15/89)
On the DecStation, immediate constants are limited to 16 bits where
the highest bit is sign extended.
gcc generates some immediate constants that are too large.
Unfortunately, a bug in the mips as doesn't generate an error, but
instead treats large positive constants as negative ones.
Enclosed is a test case, sample run, and resulting assembly.
main()
{
char* s[0xfffff];
}
32 Huey.Stanford.EDU> gcc -v -S -O big.c
gcc version 1.36
/usr/local/lib/gcc-cpp -v -undef -D__GNUC__ -Dmips -Dunix -Dultrix -D__mips__ -D__unix__ -D__ultrix__ -D__OPTIMIZE__ -DR3000 -DLANGUAGE_C -DMIPSEL -DSYSTYPE_BSD big.c /usr/tmp/cca00609.cpp
GNU CPP version 1.36
/usr/local/lib/gcc-cc1 /usr/tmp/cca00609.cpp -O -fstrength-reduce -fomit-frame-pointer -quiet -dumpbase big.c -O -version -o big.s
GNU C version 1.36 (MIPS 1.10) <DECStation>
compiled by GNU C version 1.36.
default target switches: -munix -mnofixed-ovfl -mG0 -mG1
# .verstamp 2 0
gcc_compiled.:
.text
.align 2
.globl main
.ent main
main:
subu $29,4194312 # saveregs= 8
.frame $30,0,$31
.mask 0x40000000,-4194308
sw $30,4($29)
addiu $30,$29,4194312 # define fp
addu $8,$0,$30 # don't trust sp?
lw $30,-4194308($8)
addu $29,$0,$8 # sp not trusted here
j $31
.end main
--
Peter Ham PO Box 3430 (h)(415) 322-4390
MS Computer Science Student Stanford, CA ham@cs.stanford.edu
Stanford University 94309 (o)(415) 723-2067
grunwald@FOOBAR.COLORADO.EDU (Dirk Grunwald) (12/16/89)
In-reply-to: ham@Neon.Stanford.EDU's message of 15 Dec 89 00:22:29 GMT 1.37beta produces the same output, however, I don't think it's wrong. If you assemble & disassemble the source, you get: [foo.s: 10] 0x0: 3c010040 lui at,0x40 [foo.s: 10] 0x4: 34210010 ori at,at,0x10 [foo.s: 10] 0x8: 03a1e823 subu sp,sp,at [foo.s: 11] 0xc: afbe0000 sw s8,0(sp) [foo.s: 13] 0x10: 3c0f0040 lui t7,0x40 [foo.s: 14] 0x14: 35ef0010 ori t7,t7,0x10 [foo.s: 15] 0x18: 03aff021 addu s8,sp,t7 [foo.s: 18] 0x1c: 001e4021 addu t0,zero,s8 [foo.s: 20] 0x20: 3c1effc0 lui s8,0xffc0 [foo.s: 20] 0x24: 03c8f021 addu s8,s8,t0 [foo.s: 20] 0x28: 8fdefff0 lw s8,-16(s8) [foo.s: 23] 0x2c: 03e00008 jr ra [foo.s: 22] 0x30: 0008e821 addu sp,zero,t0 the MIPS assembler quietly converts insns like subu $29,4194312 # saveregs= 8 into [foo.s: 10] 0x0: 3c010040 lui at,0x40 [foo.s: 10] 0x4: 34210010 ori at,at,0x10 [foo.s: 10] 0x8: 03a1e823 subu sp,sp,at the 'lui' insn loads the upper half of 'at'(..a temporary register allocated to the assembler for just this purpose) , clearing the lower half and the 'ori' sets the lower half. when you reach the 'subu' you'll have 0x400010 in the at register; the subtract should then work as expected. Perhaps the MIPS backend should be changed to do these things explicitly, I dunno. It might allow more optimizations (sharing of similar high parts, etc) than the current scheme. Dirk Grunwald -- Univ. of Colorado at Boulder (grunwald@foobar.colorado.edu) (grunwald@boulder.colorado.edu)