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.

Unexpected bit shift results on CC1111 with IAR EW8051

I'm using the CC1111 with IAR EW8051 8.10.3.   Consider the following code (intended to verify the sample CRC16 value in the CC1111 datasheet, page 146), simplified further to demonstrate the problem:

#include "hal_types.h"
#include <ccxx10/ioCCxx10_bitdef.h>
#include <bsp_board_defs.h>

#define LEN 4
uint8 bytes[LEN] = {0x03, 0x41, 0x42, 0x43};

int main() {
uint16 crc16;

RNDL = 0xFF;
RNDL = 0xFF;

for (int i=0; i < LEN; i++)
RNDH = bytes[i];

crc16 = RNDH; // crc16 == 0x00B4 (expected)
crc16 = crc16 << 8; // crc16 == 0x0000 ?????
crc16 |= RNDL; // crc16 == 0x00BC

return 0;
}

The values in the comments are taken from running the IAR debugger on a CC1111 usb dongle. 
I would expect that after "crc16 = crc16 << 8;", crc16 would have the value 0xB400, not 0x0000.  

According to the C99 standard (well, the May 2005-05-06 draft), section 6.5.7.3-4,
The integer promotions are performed on each of the operands. The type of the result is
that of the promoted left operand. If the value of the right operand is negative or is
greater than or equal to the width of the promoted left operand, the behavior is undefined.
The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with
zeros. If E1 has an unsigned type, the value of the result is E1 × 2^E2, reduced modulo
one more than the maximum value representable in the result type. If E1 has a signed
type and nonnegative value, and E1 × 2^E2 is representable in the result type, then that is
the resulting value; otherwise, the behavior is undefined.

My take on this is that the result type should be an unsigned 16-bit integer. (0x00B4)^2^8 % 0x10000 is 0xB400. 
Am I missing something? Thanks!

-David
  • I figured it out.  Even though I had no optimization configured, the fact that I never read the crc16 variable seems to have changed the behavior.  If I add these lines before the return statement,


    if (crc16)
    crc16 = 0x123;

    then I get the expected value for crc16, even before it gets to that point.