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.

CCS/TMS320F28377D: Bit-shift Problem

Part Number: TMS320F28377D


Tool/software: Code Composer Studio

Hi, there.

There is a bit-shift problem like:

if variable M and N are both type of "long", when description is like "M = 1 << N" and N is bigger than 15, such like 16, I'll get M as "1" instead of "0".

Why did I get M as "1" instead of "0"? 

  • For the source file which contains the problem shift expression, please follow the directions in the article How to Submit a Compiler Test Case.  If the problem shift expression is not obvious, please add a comment like // PROBLEM HERE .

    Thanks and regards,

    -George

  • Hi George

    Does C2000 use circular shift on bit-wise shift?

  • Willie LAi said:
    Does C2000 use circular shift on bit-wise shift?

    No.

    Thanks and regards,

    -George

  • Hi, George.
    First, thanks for reply. Please check my problem attached below:

    "C:/ti/ccsv6/tools/compiler/ti-cgt-c2000_18.1.4.LTS/bin/cl2000" -v28 -ml -mt --cla_support=cla1 --float_support=fpu32 --tmu_support=tmu0 --vcu_support=vcu2 --include_path="C:/ti/ccsv6/tools/compiler/ti-cgt-c2000_18.1.4.LTS/include" -g --preproc_with_comment --preproc_with_compile --diag_warning=225 --diag_wrap=off --display_error_number  "../main.c"

    attached pp. file:

    /*
     * main.c
     */
    int main(void)
    {
    	//-------------------------
    	// Problem 1
    	//-------------------------
    	long ShiftData;
    	long ShiftCount;
    
    	ShiftCount = 16;
    	ShiftData = 1 << ShiftCount; // PROBLEM HERE: ShiftData won't be "0", "1" instead.
    
    	ShiftCount = 32;
    	ShiftData = 1L << ShiftCount; // PROBLEM HERE: ShiftData won't be "0", "1" instead.
    
    	//-------------------------
    	// Problem 2
    	//-------------------------
    	long RawData = 0xFFFFFFFF;
    	long MaskData;
    	
    	MaskData = RawData & ~(0x00001000 | 0x00000100 | 0x00000010); // PROBLEM HERE: MaskData won't be "0xFFFFEEEF", "0x0000EEEF" instead.
    	return 0;
    }
    

  • Thank you for the test case.  I can reproduce the same behavior.

    The shift expressions are undefined because the shift count is too big.  A shift is defined only when the shift count is less than the size, in bits, of the first operand.  In the code you sent, the shift count of each expression is too big by one.

    Your code contains a second problem which is not mentioned in earlier posts.  The key source lines are ...

            long RawData = 0xFFFFFFFF;
            long MaskData;
    
            // MaskData won't be "0xFFFFEEEF", "0x0000EEEF" instead.
            MaskData = RawData & ~(0x00001000 | 0x00000100 | 0x00000010);

    It appears the compiler generates the incorrect AND instruction.  I filed the entry EXT_EP-9788 to have this investigated.  You are welcome to follow it with the link below in my signature.

    Thanks and regards,

    -George

  • Hi, George.

    Thanks for help.

  • Actually, it's not a bug that only one 16-bit AND instruction is generated because the upper 16 bits of the mask are 0xffff, and (AH&0xffff) yields AH.  I am not able to reproduce a problem given the test case with 18.1.4.LTS.  I suspect this test case is a cutdown test case that was cut down too far.

    How are you detecting the problem?  How do you see the value of MaskData?  Are you looking at it in CCS, or is its value incorrect in subsequent code?

    Now, I must address the hexadecimal constants used in the test case.  I don't think this is part of the problem, but these constants should probably be re-written to use the 'ul' suffix.  Despite the fact that it uses hexadecimal constants, those constants are signed.  Despite the fact the hexadecimal constants have 8 digits, they are actually only 16 bits wide.  According to the C99 standard, unsuffixed hexadecimal constants with a value that fits into "signed int" are given type "signed int."  Don't forget that C2000 has 16-bit "int."  Thus, the expression

    (0x00001000 | 0x00000100 | 0x00000010)

    is equal to

    (signed int)0x1110

    and

    ~(0x00001000 | 0x00000100 | 0x00000010)

    is equal to

    (signed int)0xeeef

    Next, the value is converted from signed int to signed long so that it may be used in the binary and expression.  Because the value is negative, it gets sign-extended and becomes:

    (signed long)0xffffeeef

    So it appears that you get the intended mask, but only because the upper bit happened to be set.  You should really use the 'ul' suffix on each of those constants if you intend this to be a 32-bit unsigned constant expression:

    ~(0x00001000ul | 0x00000100ul | 0x00000010ul)