Menu ▾ ▴

#124 MSB, perhaps preprocessor or compiler bug, HC08 core

open
nobody
None
5
2019-06-07
2019-06-06
xiaolaba
No

the code and the problem, C preprocesor has something odd, perhaps not really understand the rule of mathmatical expression.

In order to form uint_32, i.e. 0x1234xxxx, a few of expression and difference of asm code, depends on bit16 of xxxx, result will be 0x1233xxxx and 0x1234xxxx

why the carry bit always taken effect as the MSB without knowing to the constant type ?

#define base 0x12340000
volatile unsigned long ir_code32bit = 0xFFFFFFFF;

void main() {
    ir_code32bit = base + (0b01000000  <<8); // 0x40  << 8, correct 0x12340000
    ir_code32bit = base + (0b01000000u <<8); // 0x40u << 8, correct 0x12340000

    ir_code32bit = base + (0b11000000  <<8); // 0xc0  << 8, wrong   0x1233c000
    ir_code32bit = base + (0b11000000u <<8); // 0xc0u << 8, correct 0x1234c000
}

the asm shows the code and undesired result.

;test.c:29: ir_code32bit = base + (0b11000000  <<8); // 0xc0  << 8, wrong   0x1233c000
    ldhx    #_ir_code32bit
    lda #0x12
    sta ,x
    lda #0x33
    sta 1,x
    lda #0xc0
    sta 2,x
    clra
    sta 3,x
3 Attachments

Discussion

  • Erik Petrich

    Erik Petrich - 2019-06-06

    The case that you think SDCC is generating the wrong result will only work as you desire if type int is larger than 16 bits. So you will get your expected result if compiling for 32-bit or 64-bit x86 processors that use a larger int. But SDCC uses a 16-bit int and is correctly following the C standard in that situation.

    0b11000000 is a constant of type int, which is signed. Left shifting by 8 will move the 1 into the bit 15, the sign bit for ints (when int is 16-bit), making the result negative. The sign bit will be extended when converting the int to unsigned long before performing the addition, which is what is creating your undesired result.

    You should either: 1) Add the u suffix so that the constant is unsigned, so that there will be no sign extension, 2) add the l suffix so that the constant is type long int (the sign bit will be bit 31 instead of 15), or 3) add both suffixes.

     
    👍
    1
    • xiaolaba

      xiaolaba - 2019-06-07

      thanks Eric, this really helped.
      however, I am still a bit hesitant, as seen 0b11000000 represents signed -0x40 & unsigned as 0xc0, but why the sign bit carryed as sign bit and data bit simultanously when happened extension.

       

      Last edit: xiaolaba 2019-06-07

Log in to post a comment.