satz@CISCO.COM (01/04/89)
We have a single piece of code which has given compilers from many different types of systems fits. Apparently the case table generation code was enhanced since gcc 1.30, the last release we used. gcc 1.32 on a Sun 3/280 (68020) running SunOS 3.5 tries to structure the case table into a tree of conditionals so the cost of any item in the table was o(log n). gcc 1.30 just tested for each value which for the end of list was o(n). Unfortunately it seems that the unsignedness of the value was overlooked or broken. long test (unsigned short arg) { switch ((unsigned int)arg) { /* removing this cast makes it work too */ case 0x0800: return(1); case 0x0806: return(2); case 0x0200: return(3); case 0x0201: return(4); case 0x8035: return(5); case 0x0804: return(6); case 0x6003: return(7); case 0x9000: return(8); case 0x0600: return(9); case 0x8038: return(10); default: return(-1); case 0: return(-2); } } main() { printf("result = %d\n",test(0x9000)); } Will return -1 when it should return 8. The following assembler is generated with -O: #NO_APP gcc_compiled.: .text .even .globl _test _test: link a6,#0 movew a6@(10),d0 cmpw #2052,d0 jeq L8 jgt L16 cmpw #513,d0 jeq L6 jgt L17 tstw d0 jeq L14 cmpw #512,d0 jeq L5 jra L13 L17: cmpw #1536,d0 jeq L11 cmpw #2048,d0 jeq L3 jra L13 L16: cmpw #32821,d0 jeq L7 jgt L18 cmpw #2054,d0 jeq L4 cmpw #24579,d0 jeq L9 jra L13 L18: cmpw #32824,d0 jeq L12 cmpw #36864,d0 jeq L10 jra L13 L3: moveq #1,d0 jra L1 L4: moveq #2,d0 jra L1 L5: moveq #3,d0 jra L1 L6: moveq #4,d0 jra L1 L7: moveq #5,d0 jra L1 L8: moveq #6,d0 jra L1 L9: moveq #7,d0 jra L1 L10: moveq #8,d0 jra L1 L11: moveq #9,d0 jra L1 L12: moveq #10,d0 jra L1 L13: moveq #-1,d0 jra L1 L14: moveq #-2,d0 L1: unlk a6 rts LC0: .ascii "result = %d\12\0" .even .globl _main _main: link a6,#0 movel #36864,sp@- jbsr _test movel d0,sp@- pea LC0 jbsr _printf unlk a6 rts Note that 0x9000 has the sign bit set for unsigned short values and that the jump/test instructions aren't ignoring the sign bit. Modifying the variable used in the switch statement to be unsigned long is the work-around we used. PS. gcc-1.30 generated the following code with -O: #NO_APP .text .even .globl _test _test: link a6,#0 movew a6@(10),d0 jeq L14 cmpw #32824,d0 jeq L12 cmpw #1536,d0 jeq L11 cmpw #36864,d0 jeq L10 cmpw #24579,d0 jeq L9 cmpw #2052,d0 jeq L8 cmpw #32821,d0 jeq L7 cmpw #513,d0 jeq L6 cmpw #512,d0 jeq L5 cmpw #2054,d0 jeq L4 cmpw #2048,d0 jne L13 moveq #1,d0 jra L1 L4: moveq #2,d0 jra L1 L5: moveq #3,d0 jra L1 L6: moveq #4,d0 jra L1 L7: moveq #5,d0 jra L1 L8: moveq #6,d0 jra L1 L9: moveq #7,d0 jra L1 L10: moveq #8,d0 jra L1 L11: moveq #9,d0 jra L1 L12: moveq #10,d0 jra L1 L13: moveq #-1,d0 jra L1 L14: moveq #-2,d0 L1: unlk a6 rts LC0: .ascii "result = %d\12\0" .even .globl _main _main: link a6,#0 movel #36864,sp@- jbsr _test movel d0,sp@- pea LC0 jbsr _printf unlk a6 rts