Topic : Strange behaviour by the RCSTM8 compiler

Forum : ST7/STM8

Original Post
Post Information Post
May 17, 2011 - 8:32am
Guest

Please take a look at this function

uint16_t val;

uint16_t func2(void)
{
uint16_t t = 18000;
uint32_t w = (uint32_t)(t) * 10;
w /= val;
return (uint16_t)w;
}

In this case, val = 10. That means that the function should return 18000 * 10 / 10 = 18000. But it actually return 4892. It is easy to understand how it could be 4892 since 18000*10 = 180000 = 0x0002BF20, cut the 2 most significant bytes and you have 0xBF20, divide by 10 and we have 0x131c = 4892 .

If we change one line in the function from “w /= val; “ to “w = w / val;” the return value is correct (18000). So there seems to be something strange with the '/=' operator!

The generated assembler code look like this

; FUNCTION ?func2 (BEGIN)
; SOURCE LINE # 17
0000 5204 SUB SP,#004H
; SOURCE LINE # 20
0002 AEBF20 LDW X,#0BF20H
0005 1F03 F LDW (003H,SP),X ; [ w + 02H ]
0007 5F CLRW X
0008 1F01 F LDW (001H,SP),X ; [ w ]
; SOURCE LINE # 21
000A 1E03 F LDW X,(003H,SP) ; [ w + 02H ]
000C 89 PUSHW X
000D 1E03 F LDW X,(003H,SP) ; [ w ]
000F 89 PUSHW X
0010 CE0000 F LDW X,val
0013 BF03 F LDW ?CH,X
0015 5F CLRW X
0016 BF03 F LDW ?BH,X
0018 CD0000 F CALL ?C?swap_skbc
001B CD0000 F DNF CALL ?C?divu3232
001E 4F CLR A
001F CD0000 F CALL ?C?mv4_bc2isa
; SOURCE LINE # 22
0022 1E03 F LDW X,(003H,SP) ; [ w + 02H ]
0024 5B04 ADD SP,#004H
0026 81 RET

This does not look right to me. It seems that the function calculates the result of 0xBF20 / 10 which is what we get though it is incorrect.

This is the complete source file if you want to compile it yourself.

#include

typedef unsigned char uint8_t;
typedef unsigned long uint32_t;
typedef unsigned short uint16_t;

uint16_t val;

char buf[100];
static int count = 0;
int putchar(char c)
{
buf[count++] = c;
return 1;
}

uint16_t func2(void)
{
uint16_t t = 18000;
uint32_t w = (uint32_t)(t) * 10;
w /= val;
return (uint16_t)w;
}

void main(void)
{
val = 10;
printf("%d\n", func2());
}

My tools:
STM8 compiler/linker ver 2.32.10.0307

I am compiling for the STM8 family, SCINAME(STM8). Target CPU is STM8S207M8.

Best Regards
Andreas Hansson

Replies
Post Information Post
+1
0
-1
May 19, 2011 - 10:07am
Raisonance Support Team

Hi Andreas,

Thanks for this report.

We have been able to reproduce this behavior in our Labs.
The problem comes from a bug in our compiler: The constant propagation "inverts" the order of evaluation hence forgets the (uint32_t) cast. This is technically present in all binary operators, but it is visible only for multiplication, addition and left shift, only in the case where both operands are constants (or propagated constants as in your case) and one of them is cast from 16 to 32 bits.
This makes it a low exposure bug.

The bug will be fixed in our next RKit-STM8 release which will be available soon (next week hopefully).

The workaround is to rewrite the code a little bit so that the constant is not cast to 32-bits anymore. Just keeping the variable t as a long (uint32_t) is enough in your case.

Sorry for the inconvenience.
Best Regards,