Skip to main content
Visitor II
February 1, 2013
Question

Cosmic compiler unexpected result

  • February 1, 2013
  • 18 replies
  • 3923 views
Posted on February 01, 2013 at 12:05

Hi.

I'm using the Cosmic STM8 compiler (''free'' version, v4.3.9) and it appears to generate unexpected results for the following test :-

static char test(unsigned int x, unsigned int y)

{

   return (int)(x - y) < 0;

}

This function unexpectedly returns 0 when presented with the values x=0x7f80 and y=0x8080.

If I modify the function thus is then returns 1 as expected :-

static char test(unsigned int x, unsigned int y)

{

   x -= y;

   return (int) x < 0;

}

Am I misunderstanding what the result should be ?

P.
    This topic has been closed for replies.

    18 replies

    phortonAuthor
    Visitor II
    February 1, 2013
    Posted on February 01, 2013 at 12:19

    Additionally, if I mark the test() function as ''@inline'' I get the expected result.

    Visitor II
    February 1, 2013
    Posted on February 01, 2013 at 13:00

    Maybe ''unsigned int'' is uint8_t internally. You can check this in the types.h files.

    What if you try specifying uint16_t directly?

    phortonAuthor
    Visitor II
    February 1, 2013
    Posted on February 01, 2013 at 13:23

    ''unsigned int'' is definitely a 16-bit type, you can see it in the generated assembler output.

    Visitor II
    February 1, 2013
    Posted on February 01, 2013 at 13:27

    Hello Peter.

    There is nothing wrong in the Cosmic compiler.

    Your unexpected results are due to the difference between what you want and what your code says.

    Since x and y are unsigned values, their difference is unsigned too, so it's never negative.

    If you cast x-y to an integer the result is always positive or zero because the cast happens after the difference is computed.

    To have the expected result, you'd write:

    return ((int)x - (int) y) < 0;

    EtaPhi

    phortonAuthor
    Visitor II
    February 1, 2013
    Posted on February 01, 2013 at 13:42

    This is quite a normal construct to use when working with values that can wrap (tick counts, buffer indexes etc).

    The fact that the compiler generates a different result for the inline / non-inline case would indicate that there is an issue here.

    Visitor II
    February 6, 2013
    Posted on February 06, 2013 at 11:09

    I was testing the example and  - sorry EtaPhi - in my opinion Peter would be correct.

    At my configuration (CXSTM8, unlimited V4.9.10 at  STVD) curiously the result is as expected.

    With unsigned int x,y;

    the codes

      return((signed int )(x-y) < 0);

     

    and

      return((signed int )x - (signed int )y) < 0; 

    bring absolutely identical code in the resulting .ls-file.

    WoRo

    Visitor II
    February 6, 2013
    Posted on February 06, 2013 at 11:24

    It's nice to hear from you again, WoRo!

    If the CXSTM8 compiler outputs the same code, Peter discovered a bug of Cosmic compiler because my code has no implementation ambiguity.

    The compiler MUST convert x and y into signed quantities before taking their difference.

    EtaPhi

    Visitor II
    February 6, 2013
    Posted on February 06, 2013 at 11:54

    Hi EtaPhi - and of course all others too,

    using cast operation, any (signed or unsigned) number with the MSbit = '1' to a signed number, will result in a negative sign. 

    With e.g. 0x7F80U - 0x8080U = 0xFF00 you'll get a negative number when casting (signed int)(0xFF00)  with no respect to the type of the uncasted number.

    The compiler 

    MUST

    DON'T NEED convert x and y into signed quantities before taking their difference.

    It's quite the same result!

    WoRo

    Visitor II
    February 6, 2013
    Posted on February 06, 2013 at 14:47

    I apologize for my mistake that is due to my wrong assumption that an int is a 32 bit quantity.

    When x = 0x7F80 and y = 0x8080, the result should be 0xFF00 i.e. -256 and test(x,y) should return TRUE.

    If an int is a 32 bit quantity, the value of y becomes 0xFFFF8080 after the cast, so x - y = 0x0000FF00 = 65280 is greater than zero and test(x,y) should return FALSE.

    Now I wonder what is the meaning of the statement:

    return (int)(x-y) < 0;

    If x and y contain a conter reading, x - y may be the elapsed time between two events.

    If such is the case, why is the sign tested?

    I thank you, WoRo, for the lesson learned!

    EtaPhi.

    PS: what is the compiler output in the ''correct'' and in the ''wrong'' case?

    Visitor II
    February 6, 2013
    Posted on February 06, 2013 at 15:20

    Apologies if this a stupid remark, but it is not clear to me why the int cast is only done after the subtraction.

    To me, the result cannot be negative because it is an unsigned value, so it is wrapped, and then you cast it to int and because MSB=1 you get a negative value.

    If I understand the purpose of the code, I would write

    return( ((int) x) - ((int) y) )<0