Menu

#440 Loop check value saved in register and not updated!

closed-fixed
nobody
5
2014-08-16
2003-01-19
No

I'm no computing wiz but I've found that if you use a
global variable as your check value in a while loop in a
function, then call another function within loop that
changes the value of the global variable, the check value
of the original while loop remains the same! This is due
to the fact that the assembly code generated pushes
the value of the global variable into a register at start of
function and then uses that value throughout the function
without ever updating it after nested function calls that
may or may not change value of specified global
variable. This to me seems like a major flaw since global
variables can no longer be used as parameters in loops
without extreme caution. I found some sdcc parameter
called --noinduction which seemed according to the
sdcc user guide to possibly solve the problem in
question but result turned out the same. Now, is this
supposed to work like this or are there any options to
force compiler to update registers of global variables
after all / some function calls within loops?

Help is much appreciated, need answer asap since I'm
working with a final year project and have a deadline to
keep!

Discussion

  • David Duxstad

    David Duxstad - 2003-02-12

    Logged In: YES
    user_id=306209

    I have the same problem. The work-around appears to be to
    assign the loop check value to be "xdata" and then use
    --noinduction. This worked in my case.
    Good luck.
    Dave

     
  • Bernhard Held

    Bernhard Held - 2003-05-09

    Logged In: YES
    user_id=203539

    Please provide a short source snippet, so that we can
    reproduce the problem.

     
  • David Duxstad

    David Duxstad - 2003-05-09

    Logged In: YES
    user_id=306209

    Here's a code snippet. Looking at the assembly, the loopCnt
    variable is overwritten during the subroutine but never restored
    before it is checked again. Let me know if you need anything
    else. SDCC version is:
    SDCC : mcs51/gbz80/z80/avr/ds390/pic14/TININative/xa51
    0.0.0 (Mar 27 2003) (CYGWIN)

    xdata at 0xE678 unsigned char I2CS;
    xdata at 0xE679 unsigned char I2DAT;
    xdata at 0xE67A unsigned char I2CTL;

    int i2cRead( unsigned char cntlByte,
    unsigned char byteCnt,
    unsigned char *myData)
    {
    unsigned char i;
    unsigned char loopCnt; /* xdata needed due 2 loop check
    compiler bug*/
    unsigned char temp;
    I2CS |= START;
    I2DAT = cntlByte;
    while( !(I2CS & DONE) );
    if((I2CS & BERR) || ( !(I2CS & ACK) ) )
    {
    if( I2CS & BERR )
    myPrStr("BERR on I2C bus");
    else
    myPrStr("No ACK on I2C bus");
    I2CS |= STOP;
    return(-1);
    }
    loopCnt = byteCnt+1;

    for( i = 0; i < loopCnt; i++) /* plus 1 because 1st rd undef*/
    {
    if( i == (byteCnt - 1))
    {
    I2CS |= LASTRD;
    }
    if( i == 0)
    {
    temp = I2DAT;
    }
    else
    {
    if( i == byteCnt )
    {
    I2CS |= STOP;
    }
    temp = I2DAT;
    LEDPORT = temp;
    *myData++ = temp;
    }
    if( i != byteCnt )
    {
    while( !(I2CS & DONE) );
    /*
    myPrStr("Waiting for DONE 3");
    */
    if((I2CS & BERR) )
    {
    myPrStr("BERR on I2C bus");
    I2CS |= STOP;
    return(-1);
    }
    }
    }
    return(0);
    }

     
  • Bernhard Held

    Bernhard Held - 2003-05-10

    Logged In: YES
    user_id=203539

    Unfortunately there's a life-range bug in SDCC, which is very difficult
    to fix. A (untested) workaround for this problem is:

    volatile unsigned char loopCnt;

     
  • Bernhard Held

    Bernhard Held - 2003-05-10
    • labels: --> Live range problems
     
  • Erik Petrich

    Erik Petrich - 2003-12-03
    • milestone: --> fixed
    • status: open --> closed-fixed
     
  • Erik Petrich

    Erik Petrich - 2003-12-03

    Logged In: YES
    user_id=635249

    The gcse bug in the initial report has probably been fixed
    by the updates noted in ChangeLog 1.514 and 1.506, but no
    source code was posted to absolutely verify this.

    The follow-up posted by dduxstad seems unrelated to the
    original bug and instead a live-range problem that is likely
    fixed by Klaus's new code (see ChangeLog 1.445 and later)

     

Log in to post a comment.