#define UIP_LLH_LEN 10000 #define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) #define u8_t unsigned char #define u16_t unsigned short #define UIP_BUFSIZE 1000 typedef struct { /* IP header. */ u8_t vhl, tos, len[2], ipid[2], ipoffset[2], ttl, proto; u16_t ipchksum; u16_t srcipaddr[2], destipaddr[2]; /* TCP header. */ u16_t srcport, destport; u8_t seqno[4], ackno[4], tcpoffset, flags, wnd[2]; u16_t tcpchksum; u8_t urgp[2]; u8_t optdata[4]; } uip_tcpip_hdr; u8_t uip_buf[UIP_BUFSIZE+2]; volatile u8_t uip_acc32[4]; int jaroslav; int main(void) { if((BUF->ackno[0] == uip_acc32[0]) && (BUF->ackno[1] == uip_acc32[1]) && (BUF->ackno[2] == uip_acc32[2]) && (BUF->ackno[3] == uip_acc32[3])) jaroslav++; return 1; } .file "main.c" .text .align 2 .global main .type main, %function main: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. ldr r0, .L10 ldr r1, .L10+4 ldrb r2, [r0, #28] @ zero_extendqisi2 ldrb r3, [r1, #0] @ zero_extendqisi2 cmp r2, r3 @ lr needed for prologue beq .L9 .L2: mov r0, #1 bx lr .L9: ldrb r2, [r1, #1] @ zero_extendqisi2 ldrb r3, [r0, #29] @ zero_extendqisi2 cmp r3, r2 bne .L2 ldrb r2, [r1, #2] @ zero_extendqisi2 ldrb r3, [r0, #30] @ zero_extendqisi2 cmp r3, r2 bne .L2 ldrb r2, [r1, #3] @ zero_extendqisi2 ldrb r3, [r0, #31] @ zero_extendqisi2 cmp r3, r2 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!I THINK CC's OF THIS COMPARE NEVER GET LOOKED AT ldreq r2, .L10+8 ldreq r3, [r2, #0] addeq r3, r3, #1 streq r3, [r2, #0] b .L2 .L11: .align 2 .L10: .word uip_buf+10000 .word uip_acc32 .word jaroslav .size main, .-main .comm uip_buf,1002,1 .comm uip_acc32,4,1 .comm jaroslav,4,4 .ident "GCC: (GNU) 4.2.0"
> #define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) Right there is an alias violation.
The attached sample code does not illustrate the real problem. Further investigation is required why the code works with -O0 and does not work with -O2.
Created attachment 14077 [details] This file does not compile correctly with -O2
Created attachment 14078 [details] This is the working unoptimized assembly of uip.c
Created attachment 14079 [details] This is the nonworking optimized assembly of uip.c
Created attachment 14180 [details] Test of optimized comparison (-O2) Comparison of four consecutive bytes gets optimized (-O2) as comparison of a word. The word address produced does not have the last two bits zero and the ARM7 processor either ignores them (LPC2000) or data aborts (SAM7).
Did you read comment #1? Does -fno-strict-aliasing magically "fix" your code?
Subject: RE: Bad code generation with -O2 (ARM 7 architecture) The -fno-strict-aliasing does not fix the unaligned access. -----Original Message----- From: rask at gcc dot gnu dot org [mailto:gcc-bugzilla@gcc.gnu.org] Sent: Monday, 10 September 2007 07:08 To: gressau@optusnet.com.au Subject: [Bug c/33111] Bad code generation with -O2 (ARM 7 architecture) ------- Comment #7 from rask at gcc dot gnu dot org 2007-09-09 21:08 ------- Did you read comment #1? Does -fno-strict-aliasing magically "fix" your code?
(In reply to comment #1) > > #define BUF ((uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN]) > Right there is an alias violation. More than that this is an alignment violation.
The ARM7 does not support unaligned accesses in the way that C programmers normally expect (even if it doesn't fault them in the MMU then it still won't fetch what you might expect -- see the CPU manuals for details). As of ARM11 the rules were changed, but that's a different story...