This is the mail archive of the crossgcc@sourceware.cygnus.com mailing list for the crossgcc project.
See the CrossGCC FAQ for lots more infromation.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
We've got both gcc 2.95.2 and egcs 2.91.57 compiling for an arm-coff target, and both are exhibiting an identical strange behavior in some cases with unsigned short parameters to functions and unsigned short local variables. Unfortunately, I can only find one brief code snippet that clearly exhibits the problem (others are long and complicated), and it uses inline assembly. But I'll post it anyway, hoping that the inline assembly is straightforward enough. It crops up other places that are pure ANSI C, so I don't think the use of assembly is causing the problem. pcx09> cat testus2.c #include <stdio.h> static unsigned short swabw(unsigned short x) { __asm__("orr %0, %0, %0, lsl #16 ; mov %0, %0, lsr #8" : "+r" (x) ); return x & 0xffff; } void testus2(unsigned short x) { printf("x = 0x%04x, swabbed = 0x%04x\r\n", x, swabw(x)); } pcx09> The swabw function swaps bytes within a short. Normally we inline that function, but when we don't, we get this output from runs through the testus2() function... x = 0x1234, swabbed = 0x3412 x = 0x789a, swabbed = 0x9a78 x = 0x89ab, swabbed = 0xff89 In general, the failure mode is that whenever bit 15 is set in the input to swabw, the output comes out with bits 15-8 all set regardless of what bits 7-0 of the input were. Again, when we inline swabw, this does not happen, as the bug appears in the function prologue. Here's the assembly generated by this source file... pcx09> odarm -d testus2.o testus2.o: file format coff-arm-big Disassembly of section .text: 00000000 <LM1>: 0: e1a0c00d mov ip, sp 4: e92dd800 stmdb sp!, {fp, ip, lr, pc} 8: e24cb004 sub fp, ip, #4 c: e1a00800 mov r0, r0, lsl #16 10: e1a00840 mov r0, r0, asr #16 00000014 <LM2>: 14: e1800800 orr r0, r0, r0, lsl #16 18: e1a00420 mov r0, r0, lsr #8 0000001c <LM3>: 1c: e1a00800 mov r0, r0, lsl #16 20: e1a00820 mov r0, r0, lsr #16 24: e91ba800 ldmdb fp, {fp, sp, pc} 00000028 <_testus2>: 28: e1a0c00d mov ip, sp 2c: e92dd810 stmdb sp!, {r4, fp, ip, lr, pc} 30: e24cb004 sub fp, ip, #4 34: e1a04800 mov r4, r0, lsl #16 38: e1a04824 mov r4, r4, lsr #16 3c: e1a00004 mov r0, r4 40: ebffffee bl 0 <LM1> 44: e1a02800 mov r2, r0, lsl #16 48: e1a01004 mov r1, r4 4c: e59f0008 ldr r0, 5c <L4> 50: e1a02822 mov r2, r2, lsr #16 54: ebfffffe bl 54 <_testus2+0x2c> 00000058 <LM6>: 58: e91ba810 ldmdb fp, {r4, fp, sp, pc} 0000005c <L4>: 5c: 00000000 andeq r0, r0, r0 pcx09> The bug is at offset 0x10 into the disassembly. The parameter is declared unsigned short, which should generate a mov r0, r0, lsr #16 instruction as it does elsewhere in the file. But an arithmetic shift is generated instead of a logical one, which, considering the value signed, fills the top 16 bits with ones if bit 15 is set. This is the cause of the errant behavior we see with our printfs. Has anyone seen this behavior before, erroneously treating unsigned shorts as signed while zeroing out their top 16 bits before using them? Is there an explanation for it? Should I report it as a gcc bug? Thanks for your help... ------------------------------------------- Carl Miller Firmware Engineer chaz@gordian.com Gordian, Inc. (714) 850-0205 http://www.gordian.com (posted from my personal e-mail address since that's the one that's subscribed to the list) ------ Want more information? See the CrossGCC FAQ, http://www.objsw.com/CrossGCC/ Want to unsubscribe? Send a note to crossgcc-unsubscribe@sourceware.cygnus.com
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |