Menu

#2480 STM8: sucessive bitwise operations produce incorrect assembly

closed-fixed
Ben Shi
None
STM8
5
2016-03-10
2016-03-07
Sean Bolton
No

The following code (also attached) produces incorrect assembly when compiled with SDCC r9514 using 'sdcc -mstm8 -c minimal.c'. v[2] should be set to (v[0] & 0x7f), but is incorrectly always set to zero.

typedef unsigned char uint8_t;

extern uint8_t v[3];

void
main(void)
{
uint8_t aa;
uint8_t bb;

aa = v[0];

bb = aa & 0x80;
aa &= 0x7F;

v[1] = bb;
v[2] = aa;

}

The relevant part of the resulting assembly:

  000000                        112 _main:
  000000 52 02            [ 2]  113     sub sp, #2
                                114 ;   minimal.c: 16: aa = v[0];
  000002 AEr00r00         [ 2]  115     ldw x, #_v+0
  000005 1F 01            [ 2]  116     ldw (0x01, sp), x
  000007 1E 01            [ 2]  117     ldw x, (0x01, sp)
  000009 F6               [ 1]  118     ld  a, (x)
                                119 ;   minimal.c: 18: bb = aa & 0x80;
  00000A A4 80            [ 1]  120     and a, #0x80
  00000C 90 97            [ 1]  121     ld  yl, a
                                122 ;   minimal.c: 19: aa &= 0x7F;
  00000E A4 7F            [ 1]  123     and a, #0x7f
                                124 ;   minimal.c: 21: v[1] = bb;
  000010 1E 01            [ 2]  125     ldw x, (0x01, sp)
  000012 5C               [ 2]  126     incw    x
  000013 88               [ 1]  127     push    a
  000014 90 9F            [ 1]  128     ld  a, yl
  000016 F7               [ 1]  129     ld  (x), a
  000017 84               [ 1]  130     pop a
                                131 ;   minimal.c: 22: v[2] = aa;
  000018 1E 01            [ 2]  132     ldw x, (0x01, sp)
  00001A 5C               [ 2]  133     incw    x
  00001B 5C               [ 2]  134     incw    x
  00001C F7               [ 1]  135     ld  (x), a
  00001D 5B 02            [ 2]  136     addw    sp, #2
  00001F 81               [ 4]  137     ret

The problem can be seen in lines 120-123. The contents of v[0], having been previously loaded into the 'a' register, are ANDed with 0x80, then saved in 'yl' for later saving to v[1]. So after line 121, both 'a' and 'yl' contain the value of variable bb. Register 'a' is then ANDed with 0x7f on line 123, but it should be the value of variable aa which is ANDed with 0x7f, NOT variable bb. As a result, the value eventually stored in v[2] is wrong.

I examined the assembly produced from this code for other targets (mcs51/z80/z180/r2k/r3ka/gbz80/tlcs90/ds390/ds400/hc08/s08), and only saw this problem with the stm8 target.

1 Attachments

Discussion

  • Ben Shi

    Ben Shi - 2016-03-07
    • status: open --> closed-rejected
     
  • Ben Shi

    Ben Shi - 2016-03-07

    The value of variable aa containing in the register A is pushed to the stack on line 127, and the poped back to A on line 130.

    So when saving to v[2], the register A is right holding the value of variable aa.

     
  • Maarten Brock

    Maarten Brock - 2016-03-07
    • status: closed-rejected --> open
     
  • Maarten Brock

    Maarten Brock - 2016-03-07

    After line 121 a should be reloaded from (x) and it isn't. Reopening.

     
  • Ben Shi

    Ben Shi - 2016-03-09
    • status: open --> closed-fixed
    • assigned_to: Ben Shi
     
  • Ben Shi

    Ben Shi - 2016-03-09

    Fixed in revision #9516.

     
  • Sean Bolton

    Sean Bolton - 2016-03-10

    Thanks, Ben!

     

Log in to post a comment.