This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

A bug in C166 v.4.27

The C166 compiler generates incorrect code when using __inline functions with bit return type. Test source code:

bit bitvar1 = 1;
bit bitvar2;

__inline bit test()
{
	return bitvar1;
}

void main()
{
	bitvar2 = test();
}
In the disassembly window of the simulator the generated code looks like this:
     9: void main()
    10: {
0000000A 4A00F000  BMOV     R0.0,0xFD00.0
    11:         bitvar2 = test();
0000000E 4AF00001  BMOV     0xFD00.1,R0.0
    12: }
00000012 CB00      RET
which is obviously wrong since the user stack pointer R0 gets corrupted. If we add local variables to test the use of the user stack pointer we will see that a word memory access on odd address will be generated because of the corrupt R0.
When compiling via SRC file and assembler everything is different:
; line 4: __inline bit test()
; line 5: {
; line 6: 	return bitvar1;
	BMOV	R4.0,bitvar1
; line 7: }
	RET
; line 8:
; line 9: void main()
; line 10: {
; line 11: 	bitvar2 = test();
	CALL	test
	BMOV	bitvar2,R4.0
; line 12: }
	RET
We can see that the __inline keyword is ignored here and the code is correct.

- mike

Parents
  • Hi Holger,

    To make things as simple as possible I tried this in command line:

    \Keil\C166\BIN\C166 test.c code
    where test.c is the file with the sample code that I posted.
    Here is the compiler listing:
                 ; FUNCTION test (BEGIN  RMASK = @0x0010)
                                               ; SOURCE LINE # 3
                                               ; SOURCE LINE # 5
    0000 4A00F400 R    BMOV      R4.0,bitvar1
                                               ; SOURCE LINE # 6
    0004 CB00          RET
                 ; FUNCTION test (END    RMASK = @0x0010)
    
                 ; FUNCTION main (BEGIN  RMASK = @0x4000)
                                               ; SOURCE LINE # 7
                                               ; SOURCE LINE # 9
                                               ; SOURCE LINE # 5
    0006 4A00F000 R    BMOV      Rvb?1?test,bitvar1
                                               ; SOURCE LINE # 9
    000A 4AF00000 R    BMOV      bitvar2,Rvb?1?test
                                               ; SOURCE LINE # 10
    000E CB00          RET
                 ; FUNCTION main (END    RMASK = @0x4000)
    
    I don't know what Rvb?1?test means. Maybe it's the linker's job to substitute it with something sensible. Anyway, apparently this code results in user stack pointer corruption, that is Rvb?1?test is substituted with R0.
    Could you please verify that you get the same listing given the same source code and command line.

    - mike

Reply
  • Hi Holger,

    To make things as simple as possible I tried this in command line:

    \Keil\C166\BIN\C166 test.c code
    where test.c is the file with the sample code that I posted.
    Here is the compiler listing:
                 ; FUNCTION test (BEGIN  RMASK = @0x0010)
                                               ; SOURCE LINE # 3
                                               ; SOURCE LINE # 5
    0000 4A00F400 R    BMOV      R4.0,bitvar1
                                               ; SOURCE LINE # 6
    0004 CB00          RET
                 ; FUNCTION test (END    RMASK = @0x0010)
    
                 ; FUNCTION main (BEGIN  RMASK = @0x4000)
                                               ; SOURCE LINE # 7
                                               ; SOURCE LINE # 9
                                               ; SOURCE LINE # 5
    0006 4A00F000 R    BMOV      Rvb?1?test,bitvar1
                                               ; SOURCE LINE # 9
    000A 4AF00000 R    BMOV      bitvar2,Rvb?1?test
                                               ; SOURCE LINE # 10
    000E CB00          RET
                 ; FUNCTION main (END    RMASK = @0x4000)
    
    I don't know what Rvb?1?test means. Maybe it's the linker's job to substitute it with something sensible. Anyway, apparently this code results in user stack pointer corruption, that is Rvb?1?test is substituted with R0.
    Could you please verify that you get the same listing given the same source code and command line.

    - mike

Children
  • Hi mike,

    sorry, I think in my last post I used a different source code.

    So let's try again with this source code:

    bit bitvar1 = 1;
    bit bitvar2;

    __inline bit test()
    {
    return bitvar1;
    }

    void main()
    {
    bitvar2 = test();
    }

    Compiling this with "code"-option delivers the same result as you have shown. So we're on the same line.
    The "Rvb?1?test" is a static bit which is reserved in bit-addressable memory. So the code should be correct, R0 is not changed.

    The only "bad" thing is: the main()-function is not reentrant, because it uses a static variable. For example: replace "bitvar1" by a port input pin, and rename main() into "read_pin()", then call this function from different interrupts. You will get confusing results!

    Compiling with "src"-option is also correct, even though the __inline keyword is ignored:

    ; line 4: __inline bit test()

    test PROC NEAR
    PUBLIC test
    ; FUNCTION test (BEGIN RMASK = @0x0010)
    ; line 5: {
    ; line 6: return bitvar1;
    BMOV R4.0,bitvar1
    ; line 7: }
    RET
    ; FUNCTION test (END RMASK = @0x0010)
    test ENDP
    ; line 8:
    ; line 9: void main()

    main PROC NEAR
    GLOBAL main
    ; FUNCTION main (BEGIN RMASK = @0x0010)
    ; line 10: {
    ; line 11: bitvar2 = test();
    CALL test
    BMOV bitvar2,R4.0
    ; line 12: }
    RET
    ; FUNCTION main (END RMASK = @0x0010)
    main ENDP

    This code is reentrant!

    Holger.

  • Hi Mike, hi Holger

    I was reading this interesting fact and
    if I have time I will try out this here.
    Using the V427 too.

    Why I answer is the RvB?1?test,bitvar
    Mike concerns of.

    I play for some demonstration purposes with
    µVision2 Linker/Locator.
    This seems to be a codesegment you can see in map-file.
    ( Hope that I avoid to making angry Mike,
    he seems very competent on the C166 area )

    I think it means
    Return virtually Bit or
    more likely
    Return value Bit with a size of one bit from code section or module "test" and parameter is "bitvar" what would be identically with that, what Mike wrote.

    Hope this can help you to better understand the code, since some new features are not well documented.

    "Sorry" again for interrupting this dialog,
    I will observe your results and try a test on friday.

    Stefan

  • The "Rvb?1?test" is a static bit which is reserved in bit-addressable memory.

    Can I see some evidence to support this, please?:-) I've checked all the listing files in the project and I didn't find such a name. It only shows in the compiler listing. Besides, the disassembly window in the simulator is still giving this:

         9: void main()
        10: {
    0000000A 4A00F000  BMOV     R0.0,0xFD00.0
        11:         bitvar2 = test();
    0000000E 4AF00001  BMOV     0xFD00.1,R0.0
    
    and this is not a glitch in the disassembler, I've checked instruction opcodes with C166 Instruction Manual.
    So the compiler output may look OK if we assume that Rvb?1?test is dealt with properly by the linker. But it appears that it isn't: the binary code (in simulator) is incorrect.

    - mike

  • Hi Mike, Hi Stefan,

    I've again analysed our little problem.

    Mike, you are right, the variable "Rvb?1?test" is indeed replaced by R0.0. This is done by the linker.

    To proof this, I've generated an absolute binary file from the linker output file, and disassembled the crucial part:
    4A16 F0F0 -> BMOV R0.0,FD2C.F ; = Rvb?1?test,bitvar1
    4AF0 160E -> BMOV FD2C.E,R0.0 ; = bitvar2,Rvb?1?test

    This is actually a bug! You can report it to Keil.

    The bug does not appear if you use OPTIMIZE(7,SPEED):
    ; FUNCTION main (BEGIN RMASK = @0x4000)
    0006 4A000000 R BMOV bitvar2,bitvar1
    000A CB00 RET
    ; FUNCTION main (END RMASK = @0x4000)

    Holger.

  • Hi Holger, hi Mike,

    thanks for find this bug. I did the test on friday but only find that what Mike has posted as first message on 28.05.03.
    I tried out with different optimization levels but got a identical result.

    So it was good idea to disassemble and find the detail in the binary.

    You are excellent guys.
    Stefan.
    (This to find would not have been an easy thing ;-} Thanks again )

  • Hi Holger, hi Mike,

    this is known by KEIL and will be solved in the next release.

    Stefan

  • Hi, Stefan,

    thanks for find this bug

    No problem. But does it mean that I don't have to report this bug to Keil anymore? I mean, with your interest in the bug, it sounds like you work for Keil. If not, how do I report a bug? Do I write an email to support.intl@keil.com? There is a couple more bugs I found some time ago. One of them was in the implementation of scanf and the other was in RTX166 tiny. So while I am at it, I could as well verify that the bugs are still there and report them too.

    - mike