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)