This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Integral Promotion

We are currently in the process of evaluating Keil tools for possible purchase. Using the evaluation package, I have been checking some common functions. One of them is a simple bit test macro suitable for a large variable where speed is not important.

#define BTST(VAR, BITPOS) ((VAR) & (1<<(BITPOS)))

I used this in the following manner

unsigned long temp;
unsigned char shift;

BTST(temp, shift);

The Keil C51 compiler generates the following:


MOV A,#01H
MOV R6,#00H
MOV R0,shift?143
INC R0
SJMP ?C0015
?C0014:
CLR C
RLC A
XCH A,R6
RLC A
XCH A,R6
?C0015:
DJNZ R0,?C0014
MOV R7,A
MOV A,R7
ANL A,temp?144+03H
MOV R7,A


Note that even though I have ANSI promotions enabled, it does not promote the unsigned character to a long. It appears to promote it to an integer (using A and R6 for the data), but then never uses the MSB (R6) when performing the AND operation.

I have even tried this:
BTST(temp, (unsigned long) shift);

and I get the same results.

I have used this macro with many other compilers with complete success, following what I understand about integral promotion in ANSI C.

There seem to be several threads about bit-fields and the like, but none seemed to deal with integers or longs or shift operations.

Any thoughts?

Thanks much in advance,

Peter

Parents
  • Hi Peter,

    The 'unsigned char shift' doesnt need to be promoted to a long because it is just used to generate a mask '2**shift' internaly by the compiler and as such 'shift' should not exceed 31 (for a 32bit no.).
    If anything it doesnt look like the compiler is generating a 4 byte mask so it might be better to try and cast VAR as long in your macro (but this will be inefficient for char/int variables) to ensure that it works thus,
    #define BSTS(VAR, BITPOS) ( ((unsigned long)VAR) & (1 << BITPOS) )

    Hope this helps,
    Mark.

Reply
  • Hi Peter,

    The 'unsigned char shift' doesnt need to be promoted to a long because it is just used to generate a mask '2**shift' internaly by the compiler and as such 'shift' should not exceed 31 (for a 32bit no.).
    If anything it doesnt look like the compiler is generating a 4 byte mask so it might be better to try and cast VAR as long in your macro (but this will be inefficient for char/int variables) to ensure that it works thus,
    #define BSTS(VAR, BITPOS) ( ((unsigned long)VAR) & (1 << BITPOS) )

    Hope this helps,
    Mark.

Children
No data