From: JMGross <ms...@gr...> - 2009-04-30 18:45:33
|
This is what I got when compiling the two code versions (I don't have an MSP device with text output capability at hand right now, so I can't confirm that the result is different.): #define PRR_SCALE 255 uint8_t a = 3; uint8_t b = 4; uint8_t prr; prr = (PRR_SCALE * a) / b; 40ce: 3c 40 fd ff mov #-3, r12 ;#0xfffd 40d2: 2a 42 mov #4, r10 ;r2 As==10 40d4: b0 12 fa 6f call __divmodhi4 ;#0x6ffa 40d8: 0f 4c mov r12, r15 ; printf("prr: %u\n", prr); 40da: 7f f3 and.b #-1, r15 ;r3 As==11 40dc: 0f 12 push r15 ; 40de: 30 12 c0 40 push #16576 ;#0x40c0 40e2: b0 12 9c 67 call printf ;#0x679c 40e6: 21 52 add #4, r1 ;r2 As==10 As we can see, the compiler directly calculates the result of 255*3 to -3 (0xfffd). And here is the problem. Somehow the 255 gets interpreted as -1 signed 8-bit instead of 255 unsigned 16 bit. I only wonder why the wrong result of the following division is reported to be 0. FFFD/4 gives 3FFF (= FF) for me and not 4000 (=00) uint8_t a = 3; uint8_t b = 4; uint8_t c = 255; uint8_t prr; prr = (c * a) / b; 40f2: 02 12 push r2 ; 40f4: 32 c2 dint 40f6: 03 43 nop 40f8: f2 43 30 01 mov.b #-1, &0x0130 ;r3 As==11 40fc: f2 40 03 00 mov.b #3, &0x0138 ;#0x0003 4100: 38 01 4102: 1f 42 3a 01 mov &0x013a,r15 ;0x013a 4106: 32 41 pop r2 ; 4108: 0c 4f mov r15, r12 ; 410a: 2a 42 mov #4, r10 ;r2 As==10 410c: b0 12 fa 6f call __divmodhi4 ;#0x6ffa 4110: 0f 4c mov r12, r15 ; printf("prr: %u\n", prr); 4112: 7f f3 and.b #-1, r15 ;r3 As==11 4114: 0f 12 push r15 ; 4116: 30 12 c0 40 push #16576 ;#0x40c0 411a: b0 12 9c 67 call printf ;#0x679c 411e: 21 52 add #4, r1 ;r2 As==10 Here the multiplication is done first and then the division. Straight and correct. And much larger ;) After re-reading the original post at 'StackOverflow', I noticed that the original poster did not mention the compiler he used. All he said was that it was an MSP430 compiler used for the contiki(?) os. It is possible that this whole thing is not MSPGCC related at all. But looking at the result above, chances are it is an mspgcc he's using. p.s.: in theory, the whole calculation could be done at compile time, in both cases, since all values are known and no variable is declared volatile. While the compiler does not bother to load the initial multiplicants into a register variable (even in the second version, so the compiler noticed that the values are never needed again), it does not go go far enough to eliminate the multiplication in the second case and also in both cases the following division totally. p.p.s.: I'm still using the mspgcc version from 2006-05-02 as most of my code base was built on this and I never bothered updating, because I then would have to validate all projects again. (I'll do so when I have to rebuild most of the libs for the new 54xx processors anyway) So perhaps someone can confirm my results with a more recent version. ----- Ursprüngliche Nachricht ----- Von: Hardy Griech An: msp...@li... Gesendet am: 29 Apr 2009 21:48:11 Betreff: Re: [Mspgcc-users] Fwd: DEFINEd value messes up 8-bit multiplication. Why?] JMGross wrote: : > The second approach does an 8x8 bit multiplication, resulting in a 16 bit intermediate result. This delivers the correct value to the following division. > > But in the first approach, the compiler could optimize the whole thing to a > > ((A<<8)-A) > > which is faster and smaller than a multiplication with 255. > Unfortunately this might be done on 8 bit range, dropping the upper 8 > bit, : Also this seems to be elegant, it is wrong, because uint8_t has to be promoted to int, which is 16bit and will yield the correct result in both cases. It seems, that mspgcc is doing something wrong with int promotion!? Also it seems to be an mspgcc bug, because a native gcc3.2.3 compiler on Debian/386 showed the correct results. Hardy |