This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28069: Compiler Bug: Register Optimisations causing incorrect bitwise AND

Part Number: TMS320F28069


Microcontroller: ARM f2806x

My colleague Chris and I think we've found a bug in the cl2000 compiler. If you turn on Register Optimisations, you get buggy behaviour when performing a bitwise AND.

For example:

    char unsigned i = Some_Function_That_Returns_Zero();

    if ( i & 1 )
    {
        // control should never reach here
        // but it does!
    }

When you run the debugger, it shows that the value of "i" is 0 and that it's stored in the AL register, but nonetheless the true leg of the 'if' statement is entered. If I check the value of the AL register in the debugger, I confirm that it's 0.

To get around this buggy behaviour, I've had to do:

    char unsigned i = Some_Function_That_Returns_Zero();

    i &= 1;

    if ( i )
    {
        // control never reaches here
    }

My colleague Chris has commented the C++ code (lines 148 to 163):

void CTLC59116LedDriverControl::SetupRegisterMap()

{

    CTLC59116LedDriverControl probe(0b1100101);

    unsigned char temp = 0x7f;

 

   probe.ReadReg(0x1, temp);  // This functions takes 'temp' by reference and sets it to 0

 

   int r = temp & 0x1;

 

   temp &= 0x1;

 

   //here be dragons. If you put the & into the if () then there's a compiler bug where it knows it's 0 but thinks 0 is true.

    // so dont do that. Oh, it's only with register optimizations switched on...

    if (r) {

        registerMap = &PCA9955BRegisterMap;  // This line shouldn't be executed but it is!

    } else {

        registerMap = &TLC59116RegisterMap;

    }

}

 

And here's the buggy assembler produced by cl2000:

 

_SetupRegisterMap__25CTLC59116LedDriverControlSFv:

       .dwcfi cfa_offset, -2

       .dwcfi save_reg_to_mem, 26, 0

        ADDB      SP,#6                 ; [CPU_ARAU]

       .dwcfi cfa_offset, -8

$C$DW$97     .dwtag  DW_TAG_variable

       .dwattr $C$DW$97, DW_AT_name("probe")

       .dwattr $C$DW$97, DW_AT_TI_symbol_name("_probe")

       .dwattr $C$DW$97, DW_AT_type(*$C$DW$T$41)

       .dwattr $C$DW$97, DW_AT_location[DW_OP_breg20 -4]

 

$C$DW$98     .dwtag  DW_TAG_variable

       .dwattr $C$DW$98, DW_AT_name("temp")

       .dwattr $C$DW$98, DW_AT_TI_symbol_name("_temp")

       .dwattr $C$DW$98, DW_AT_type(*$C$DW$T$6)

       .dwattr $C$DW$98, DW_AT_location[DW_OP_breg20 -5]

 

;* AL    assigned to _r

$C$DW$99     .dwtag  DW_TAG_variable

       .dwattr $C$DW$99, DW_AT_name("r")

       .dwattr $C$DW$99, DW_AT_TI_symbol_name("_r")

       .dwattr $C$DW$99, DW_AT_type(*$C$DW$T$10)

       .dwattr $C$DW$99, DW_AT_location[DW_OP_reg0]

 

       .dwpsn file "../DeviceControllers/TLC59116LedDriverControl.cpp",line 150,column 31,is_stmt,isa 0

        MOVZ      AR4,SP                ; [CPU_ALU] |150|

        MOVB      AL,#101               ; [CPU_ALU] |150|

        SUBB      XAR4,#4               ; [CPU_ARAU] |150|

        MOVZ      AR4,AR4               ; [CPU_ALU] |150|

$C$DW$100    .dwtag  DW_TAG_TI_branch

       .dwattr $C$DW$100, DW_AT_low_pc(0x00)

       .dwattr $C$DW$100, DW_AT_name("___ct__25CTLC59116LedDriverControlFUc")

       .dwattr $C$DW$100, DW_AT_TI_call

 

        LCR       #___ct__25CTLC59116LedDriverControlFUc ; [CPU_ALU] |150|

        ; call occurs [#___ct__25CTLC59116LedDriverControlFUc] ; [] |150|

       .dwpsn file "../DeviceControllers/TLC59116LedDriverControl.cpp",line 151,column 24,is_stmt,isa 0

        MOVB      *-SP[5],#127,UNC      ; [CPU_ALU] |151|

       .dwpsn file "../DeviceControllers/TLC59116LedDriverControl.cpp",line 153,column 5,is_stmt,isa 0

        MOVZ      AR4,SP                ; [CPU_ALU] |153|

        MOVZ      AR5,SP                ; [CPU_ALU] |153|

        MOVB      AL,#1                 ; [CPU_ALU] |153|

        SUBB      XAR4,#4               ; [CPU_ARAU] |153|

        SUBB      XAR5,#5               ; [CPU_ARAU] |153|

        MOVZ      AR4,AR4               ; [CPU_ALU] |153|

        MOVZ      AR5,AR5               ; [CPU_ALU] |153|

$C$DW$101    .dwtag  DW_TAG_TI_branch

       .dwattr $C$DW$101, DW_AT_low_pc(0x00)

       .dwattr $C$DW$101, DW_AT_name("_ReadReg__25CTLC59116LedDriverControlFUcRUc")

       .dwattr $C$DW$101, DW_AT_TI_call

 

        LCR       #_ReadReg__25CTLC59116LedDriverControlFUcRUc ; [CPU_ALU] |153|

        ; call occurs [#_ReadReg__25CTLC59116LedDriverControlFUcRUc] ; [] |153|

       .dwpsn file "../DeviceControllers/TLC59116LedDriverControl.cpp",line 154,column 11,is_stmt,isa 0

        AND       AL,*-SP[5],#0x0001    ; [CPU_ALU] |154|

       .dwpsn file "../DeviceControllers/TLC59116LedDriverControl.cpp",line 155,column 5,is_stmt,isa 0

        AND       *-SP[5],#0x0001       ; [CPU_ALU] |155|

       .dwpsn file "../DeviceControllers/TLC59116LedDriverControl.cpp",line 159,column 9,is_stmt,isa 0

        CMPB      AL,#0                 ; [CPU_ALU] |159|

        B         $C$L9,EQ              ; [CPU_ALU] |159|

        ; branchcc occurs ; [] |159|

        MOVL      XAR4,#_PCA9955BRegisterMap__25CTLC59116LedDriverControl ; [CPU_ARAU] |159|

        B         $C$L10,UNC            ; [CPU_ALU] |159|

        ; branch occurs ; [] |159|

$C$L9:   

        MOVL      XAR4,#_TLC59116RegisterMap__25CTLC59116LedDriverControl ; [CPU_ARAU] |159|

$C$L10:   

        MOVW      DP,#_registerMap__25CTLC59116LedDriverControl ; [CPU_ARAU]

        MOVL      @_registerMap__25CTLC59116LedDriverControl,XAR4 ; [CPU_ALU] |159|

       .dwpsn file "../DeviceControllers/TLC59116LedDriverControl.cpp",line 163,column 1,is_stmt,isa 0

        MOVZ      AR4,SP                ; [CPU_ALU] |163|

        MOVB      AL,#2                 ; [CPU_ALU] |163|

        SUBB      XAR4,#4               ; [CPU_ARAU] |163|

        MOVZ      AR4,AR4               ; [CPU_ALU] |163|

$C$DW$102    .dwtag  DW_TAG_TI_branch

       .dwattr $C$DW$102, DW_AT_low_pc(0x00)

       .dwattr $C$DW$102, DW_AT_name("___dt__25CTLC59116LedDriverControlFv")

       .dwattr $C$DW$102, DW_AT_TI_call

 

        LCR       #___dt__25CTLC59116LedDriverControlFv ; [CPU_ALU] |163|

        ; call occurs [#___dt__25CTLC59116LedDriverControlFv] ; [] |163|

        SUBB      SP,#6                 ; [CPU_ARAU]

       .dwcfi cfa_offset, -2

$C$DW$103    .dwtag  DW_TAG_TI_branch

       .dwattr $C$DW$103, DW_AT_low_pc(0x00)

       .dwattr $C$DW$103, DW_AT_TI_return

 

        LRETR     ; [CPU_ALU]

        ; return occurs ; []

       .dwattr $C$DW$96, DW_AT_TI_end_file("../DeviceControllers/TLC59116LedDriverControl.cpp")

       .dwattr $C$DW$96, DW_AT_TI_end_line(0xa3)

       .dwattr $C$DW$96, DW_AT_TI_end_column(0x01)