 Question: C code running on C32.
He compares 32-bit floating-point numbers/expressions:
e.g. if (10.0/3.0==Float)
Whenever an intermediate result, hold in one of the eight 40-bit register, is compared
with a variable (32-bit), the extended 8-bits, if not zero, lead to a mismatch, as shown
in the example shown below.
Answer:
Workaround
----------
If you store the value to a " volatile "
variable just before making the compare, the compiler must assume that the value can
change on a cycle by cycle basis, or by an ISR. In other words, the compiler will be
forced to store the value to 32 bit memory, and then read it right back. The CMPF now
works.
MAIN.C
float f1 = 10.0/3.0;
float f2 = 10.0;
float f3;
volatile float v;
void main(void)
{
v = f2/3.0;
if(v == f1)
f3 = 2.22;
}
It may be possible to teach the compiler to perform this trick by simply rewriting any
line of code that has a compare in it. However, as you can probably quickly surmise, this
will cost dearly in cycle count. Other workarounds either in the C code, or the compiler
itself would need to be considered very carefully. For example if a "rnd" (round
operation) is used, the resulting value (in hex) would result in 0x0155555600, which is
also not correct for the compare. Or, if the lower 8 bits are zero"d with a mask,
this now depends on how the value in the CONST storage was created. Essentially the same
problem as now. And, in both cases, an extra cycle would be consumed, and nobody likes
that for DSP performance. The other issue is that we could end up with untold numbers of
customers with code that no longer behaves the same as it once did. Classifying this as an
artifact or paradox brings me to my next example. You may have seen this before where the
result is not a whole or exact fraction. The paradox is that it appears that 1!=1.
x = (1.0/3.0) * 3.0;
x = 0.333333333 * 3.0;
x = 0.999999999; The result should be 1.0, but its not.
Incidentally, these kinds of problems will sometimes occur in other compilers and CPU
architectures. |