c/7527: gcc 2.95.3 and gcc 3.0.4 generate incorrect code
Thomas D. Dean
tomdean@asus.tddhome
Wed Aug 7 10:26:00 GMT 2002
>Number: 7527
>Category: c
>Synopsis: gcc 2.95.3 and gcc 3.0.4 generate incorrect code
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: unassigned
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Aug 07 10:26:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator: Thomas D. Dean
>Release: 3.0.4 m68hc1x-20020616
>Organization:
>Environment:
System: FreeBSD asus 4.6-STABLE FreeBSD 4.6-STABLE #7: Mon Jul 22 14:18:44 PDT 2002 root@asus:/usr/src/sys/compile/ASUS i386
host: i386-unknown-freebsd4.6
build: i386-unknown-freebsd4.6
target: m6811-unknown-none
configured with: ./configure --target=m6811-elf --program-prefix=m6811-elf- --enable-languages=c,c++
>Description:
Compiling the simple 10 statement c-source, below, causes incorrect
code to be generated. The 40 lines of comments in the code explain
details.
The statement 'if(!_io_ports[0x59]&0x80) {...}' is compiled incorrectly.
The problem was first noticed with
# m6811-elf-gcc -v
Reading specs from /usr/local/lib/gcc-lib/m6811-elf/3.0.4/specs
Configured with: ./configure --target=m6811-elf --program-prefix=m6811-elf- \
--enable-languages=c,c++
Thread model: single
gcc version 3.0.4 m68hc1x-20020616
and reproduced with
# gcc -v
Using builtin specs.
gcc version 2.95.3 20010315 (release) [FreeBSD]
tomdean
/*
* example to generate incorrect code.
*
* compiled with `gcc -Wall -o f f.c
*/
volatile unsigned char *_io_ports = (unsigned char *)0x7500;
int main() {
/*
* produces correct code
*/
if(!(_io_ports[0x39]&0x80)) {
_io_ports[0x29] = 0xff;
}
/*
* produces incorrect code - accesses _io_ports[0x59], but,
* the if() is ignored. There is no value testing or conditional
* branch in the elf file. The above code is the preferred syntax,
* but, the below code should do something with the value.
*
* at 8048485 in the output of objdump, below, _io_ports[0x59] is
* accessed as 0x59(%eax). The next line, 8048488, is the start of
* 'return 0'. There should be some form of conditional between.
*
*/
if(!_io_ports[0x59]&0x80) {
_io_ports[0x49] = 0;
}
return 0;
}
/*
* objdump -d f shows
* ...
*
* 0804846c <main>:
* 804846c: 55 push %ebp
* 804846d: 89 e5 mov %esp,%ebp
* 804846f: 8b 15 d8 94 04 08 mov 0x80494d8,%edx
* 8048475: 8a 42 39 mov 0x39(%edx),%al
* 8048478: 84 c0 test %al,%al
* 804847a: 7c 04 jl 8048480 <main+0x14>
* 804847c: c6 42 29 ff movb $0xff,0x29(%edx)
* 8048480: a1 d8 94 04 08 mov 0x80494d8,%eax
* 8048485: 8a 40 59 mov 0x59(%eax),%al
* 8048488: 31 c0 xor %eax,%eax
* 804848a: c9 leave
* 804848b: c3 ret
*
* ...
*/
>How-To-Repeat:
Compile the source code above
>Fix:
The first conditional, 'if(!(_io_ports[0x39]&0x80))' generates correct code.
The 2nd conditional, 'if(!_io_ports[0x39]&0x80)' generates incorrect code.
>Release-Note:
>Audit-Trail:
>Unformatted:
medium
wrong-code
More information about the Gcc-bugs
mailing list