Menu

#357 Shift operations may produce incorrect results

4.7.x_development
open
pending (2)
5
2015-02-04
2013-07-03
No

Certain operations involving shifts have incorrect results. The bug only happens on CPUX architectures.

For example, when compiling (with no optimization) and then executing the following lines of code the obtained result is 16 instead of 64.

uint32_t  u32_var;

int main(void)
{
    int tmp;
    ...
    u32_var = 0xa;
    tmp = 16 << (u32_var & 0x07);
    printf("tmp: %d\n", tmp); // "tmp: 16" is printed instead of "tmp: 64"
    ...
}

That happens because the compiler generates incorrect assembly code:

5c44:       b2 40 0a 00     mov     #10,    &0x1c02 ;#0x000a                 
5c48:       02 1c                                                            
5c4a:       82 43 04 1c     mov     #0,     &0x1c04 ;r3 As==00               
5c4e:       1e 42 02 1c     mov     &0x1c02,r14                              
5c52:       1f 42 04 1c     mov     &0x1c04,r15                              
5c56:       0f 4e           mov     r14,    r15                              
5c58:       3f f0 07 00     and     #7,     r15     ;#0x0007                 
5c5c:       3e 40 10 00     mov     #16,    r14     ;#0x0010                 
5c60:       4f 4f           mov.b   r15,    r15                              
5c62:       7f f0 0f 00     and.b   #15,    r15     ;#0x000f                 
5c66:       84 4e fc ff     mov     r14,    -4(r4)  ;0xfffc(r4)              
5c6a:       4f 93           tst.b   r15                                      
5c6c:       03 24           jz      $+8             ;abs 0x5c74              
5c6e:       7f 53           add.b   #-1,    r15     ;r3 As==11               
5c70:       cf 18 0e 5e     .rpt    r15                                      
                            addx    r14,    r14                              
5c74:       14 12 fc ff     push    -4(r4)          ;0xfffc(r4)              
5c78:       30 12 9a 66     push    #26266          ;#0x669a                 
5c7c:       b0 12 ae 5c     call    #0x5cae                      

As you can see, at address 0x5c66, register 14 (containing 16) is stored in memory before being shifted. The stored valued (i.e., 16) is then pushed in the stack (i.e., passed as an argument to the printf() function).

With more complex code, the bug can happen also when using optimization.

Related

Bugs: #358

Discussion

  • Peter A. Bigot

    Peter A. Bigot - 2013-07-03

    The attached patch appears to fix this. It has not undergone complete regression testing, but I will be using it in my internal development.

     
  • Peter A. Bigot

    Peter A. Bigot - 2013-07-03
    • labels: --> pending
    • assigned_to: Peter A. Bigot
     
  • Peter A. Bigot

    Peter A. Bigot - 2013-07-03

    Never mind, that fix broke the other code path. Back soon....

     

Log in to post a comment.