Menu

#2495 GCSE results in incorrect assembly

closed-fixed
None
Front-end
5
2016-08-02
2016-04-22
Sean Bolton
No

The following code (also attached) produces incorrect assembly
when compiled with SDCC r9575 using 'sdcc -mstm8 -c minimal.c'.
When compiled with 'sdcc -mstm8 --nogcse -c minimal.c', the code
produced is correct.

Based on a quick look at other targets, I think I'm seeing the same
problem in some (z80/z180/r2k/r3ka/gbz80/tlcs90/), but not in others
(mcs51/ds390/ds400/hc08/s08).

In the incorrect output, in testfunc(), the argument pushed to
the second call of calledfunc() is the cached value of 'j + k'. The
code should instead calculate the new value of 'j + k1' and push that.

void calledfunc(char i) { (void)i; }
char condition(void) { return 1; }

void testfunc(char j, char k) {
    char k1 = k;

    calledfunc(j + k);

    while (k1 > 0) {
        if (condition())
            k1--;

        calledfunc(j + k1);
    }
}

void
main(void)
{
    testfunc(10, 5);
}

The relevant part of the incorrect assembly:

      000004                        128 _testfunc:
                                    129 ;   minimal.c: 7: char k1 = k;
      000004 7B 04            [ 1]  130     ld  a, (0x04, sp)
                                    131 ;   minimal.c: 9: calledfunc(j + k);
      000006 95               [ 1]  132     ld  xh, a
      000007 1B 03            [ 1]  133     add a, (0x03, sp)
      000009 97               [ 1]  134     ld  xl, a
      00000A 89               [ 2]  135     pushw   x
      00000B 9F               [ 1]  136     ld  a, xl
      00000C 88               [ 1]  137     push    a
      00000D CDr00r00         [ 4]  138     call    _calledfunc
      000010 84               [ 1]  139     pop a
      000011 85               [ 2]  140     popw    x
                                    141 ;   minimal.c: 11: while (k1 > 0) {
      000012                        142 00103$:
      000012 9E               [ 1]  143     ld  a, xh
      000013 4D               [ 1]  144     tnz a
      000014 27 15            [ 1]  145     jreq    00106$
                                    146 ;   minimal.c: 12: if (condition())
      000016 89               [ 2]  147     pushw   x
      000017 CDr00r01         [ 4]  148     call    _condition
      00001A 85               [ 2]  149     popw    x
      00001B 4D               [ 1]  150     tnz a
      00001C 27 03            [ 1]  151     jreq    00102$
                                    152 ;   minimal.c: 13: k1--;
      00001E 1D 01 00         [ 2]  153     subw    x, #256
      000021                        154 00102$:
                                    155 ;   minimal.c: 15: calledfunc(j + k1);
      000021 89               [ 2]  156     pushw   x
      000022 9F               [ 1]  157     ld  a, xl
      000023 88               [ 1]  158     push    a
      000024 CDr00r00         [ 4]  159     call    _calledfunc
      000027 84               [ 1]  160     pop a
      000028 85               [ 2]  161     popw    x
      000029 20 E7            [ 2]  162     jra 00103$
      00002B                        163 00106$:
      00002B 81               [ 4]  164     ret

In lines 130 and 132, the value of 'k' is put into XH.
In lines 133 and 134, the value of 'j' is added to 'k' and put in XL.
In lines 136 and 137, XL is pushed, so the call to 'calledfunc' at line 138 receives the correct argument ('j + k').
In lines 157 through 159, XL is again pushed for the call to 'calledfunc', which is incorrect.

When compiled with '--nogcse', the second call to 'calledfunc' correctly computes and pushes the sum 'j + k1':

                                    152 ;   minimal.c: 15: calledfunc(j + k1);
      000023 7B 05            [ 1]  153     ld  a, (0x05, sp)
      000025 1B 02            [ 1]  154     add a, (0x02, sp)
      000027 88               [ 1]  155     push    a
      000028 CDr00r00         [ 4]  156     call    _calledfunc

Thank you!

1 Attachments

Related

Bugs: #1968
Bugs: #3285

Discussion

  • Ben Shi

    Ben Shi - 2016-04-23
    • Description has changed:

    Diff:

    --- old
    +++ new
    @@ -11,6 +11,7 @@
     the second call of calledfunc() is the cached value of 'j + k'. The
     code should instead calculate the new value of 'j + k1' and push that.
    
    +~~~~
     void calledfunc(char i) { (void)i; }
     char condition(void) { return 1; }
    
    @@ -32,6 +33,7 @@
     {
         testfunc(10, 5);
     }
    +~~~~
    
     The relevant part of the incorrect assembly:
    
     
  • Ben Shi

    Ben Shi - 2016-04-23
    • Description has changed:

    Diff:

    --- old
    +++ new
    @@ -36,6 +36,7 @@
     ~~~~
    
     The relevant part of the incorrect assembly:
    +~~~~
    
           000004                        128 _testfunc:
                                         129 ;  minimal.c: 7: char k1 = k;
    @@ -74,6 +75,7 @@
           000029 20 E7            [ 2]  162    jra 00103$
           00002B                        163 00106$:
           00002B 81               [ 4]  164    ret
    +~~~~
    
     In lines 130 and 132, the value of 'k' is put into XH.
     In lines 133 and 134, the value of 'j' is added to 'k' and put in XL.
    @@ -81,11 +83,13 @@
     In lines 157 through 159, XL is again pushed for the call to 'calledfunc', which is incorrect.
    
     When compiled with '--nogcse', the second call to 'calledfunc' correctly computes and pushes the sum 'j + k1':
    +~~~~
    
                                         152 ;  minimal.c: 15: calledfunc(j + k1);
           000023 7B 05            [ 1]  153    ld  a, (0x05, sp)
           000025 1B 02            [ 1]  154    add a, (0x02, sp)
           000027 88               [ 1]  155    push    a
           000028 CDr00r00         [ 4]  156    call    _calledfunc
    +~~~~
    
     Thank you!
    
     
  • Erik Petrich

    Erik Petrich - 2016-08-02
    • status: open --> closed-fixed
    • assigned_to: Erik Petrich
    • Category: other --> Front-end
     
  • Erik Petrich

    Erik Petrich - 2016-08-02

    Fixed in [r9700]

     

Log in to post a comment.