#1822 [PIC14] logical problem - if then - vs - if then else

open
nobody
PIC14
5
2013-07-16
2011-08-09
Gál Zsolt
No

SDCC : pic16/pic14 3.0.4 #6726 (Aug 9 2011) (Linux)

There is problem in logical function where i use bit variables .
Here is the two tipical syntax, first whithout else:

if ( condition ) {
expr_set1;
}

And with else:

if ( condition ) {
expr_set1;
}
else {
expr_set2;
}

If I use "if" with "else" the compiled code is correct. If I don't use "else" the compiled code doesn't follow the original logic.
I attached an example which will show clearly the differece.

I wanted to make logical OR function but this compiled code doesen't follow it:

.line 39; "logical_test.c" if( B0 && B2 )
BTFSS _b,0

GOTO _00118_DS_

BTFSS _b,2

.line 41; "logical_test.c" if( !B1 || !B3 ) B4 = 1;
GOTO _00118_DS_
BTFSC _b,1
BTFSS _b,3
BSF _b,4
_00118_DS_

And the well working result with "else":

.line 31; "logical_test.c" if( B0 && B2 )
BTFSS _b,0
GOTO _00109_DS_
BTFSS _b,2
GOTO _00109_DS_
BTFSS _b,1
GOTO _00105_DS_
BTFSC _b,3
GOTO _00110_DS_

_00105_DS_
BANKSEL _b
BSF _b,4
GOTO _00110_DS_

_00109_DS_

.line 35; "logical_test.c" else B4 = 0;
BANKSEL _b
BCF _b,4

_00110_DS_
.line 38; "logical_test.c" B4 = 0;
BANKSEL _b
BCF _b,4

Discussion

  • Gál Zsolt

    Gál Zsolt - 2011-08-09
     
  • Gál Zsolt

    Gál Zsolt - 2011-08-09
     
  • Gál Zsolt

    Gál Zsolt - 2011-08-09

    Sorry for confusion. I wasn't enough attentive and I complained about a well working code. So here is the problematic code:

    .line 23; "logical_test.c" b.common_byte = 0x0B;
    MOVLW 0x0b
    BANKSEL _b
    MOVWF (_b + 0)

    .line 25; "logical_test.c" b.B4 = 0;
    BCF _b,4

    .line 26; "logical_test.c" if( b.B0 && b.B1 )
    BTFSS _b,0
    GOTO _00001_DS_
    BTFSS _b,1

    .line 28; "logical_test.c" if( !b.B2 || !b.B3 ) c.B0 = 1;
    GOTO _00001_DS_
    BTFSC _b,2
    BTFSC _b,3
    GOTO _00001_DS_
    BANKSEL _c
    BSF _c,0
    _00001_DS_
    RETURN

    And I attached the source of it. I tested it by GPsim whith the following inputs in "b":
    0x03 -> result: c = 0 ( it should be 1 )
    0x07 -> result: c = 1
    0x0B -> result: c = 0 ( it should be 1 )
    0x0F -> result: c = 1 ( it should be 0 )

    If I uncomment the "else NOP" line I get the correct result for these inputs.

     
  • Gál Zsolt

    Gál Zsolt - 2011-08-13

    I made the simpliest test for showing the problem, which consist one if() statement. This code show, how can avoid this this type of bugs with an empty inline assembly definition. Using it in the else branch eliminate the problem.
    The file name is: logical_test_small.c

     
  • Gál Zsolt

    Gál Zsolt - 2011-08-13

    simpliest example

     
  • Raphael Neider

    Raphael Neider - 2011-08-15

    Short story: This is a bug in the BANKSEL insertion algorithm, which is
    triggered in conjunction with peephole optimizations.
    As a workaround, use --no-peep for now.

    Long story:

    if (b.B0 || b.B1) c.B0 = 1;

    is correctly compiled into

    BTFSC b,0
    GOTO Ltrue
    BTFSS b,1
    GOTO Lfalse
    Ltrue: BSF c,0
    Lfalse:

    This is twice optimized by peephole rules, first to

    BTFSC b,0
    GOTO Ltrue
    BTFSC b,1
    Ltrue: BSF c,0
    Lfalse:

    and then to

    BTFSS b,0
    BTFSC b,1
    Ltrue: BSF c,0
    Lfalse:

    All of this is perfectly fine. Now we need to insert a BANKSEL instruction for
    accessing c.

    BTFSC b,1
    BSF c,0

    is transformed into

    BTFSS b,1
    GOTO Lskip
    BANKSEL c
    BSF c,0
    Lskip:

    which is correct if (and only if) the fragment is not preceded by another SKIP
    instruction. Unfortunately, the peephole optimizations created such a series
    of SKIP instructions ...

    BTFSS b,0
    BTFSC b,1
    Ltrue: BSF c,0
    Lfalse:

    should be transformed first into

    BTFSS b,0 /* FIXME */
    BTFSS b,1
    GOTO Lskip
    BANKSEL c
    BSF c,0
    Lskip:

    and then further into

    BTFSC b,0
    GOTO Ldo
    BTFSS b,1
    GOTO Lskip
    Ldo: BANKSEL c
    BSF c,0
    Lskip:

    because the first SKIP instruction must now skip 2 instructions.
    Of course, in this case, the resulting code fragment is exactly what had been
    generated in the first place and all the peephole optimizations have been in
    vain. Generally, however, the optimizations are both useful.
    An alternative solution, inserting BANKSELs before the peephole optimizations,
    would yield correct results (as code generation never (?) produces chained
    SKIPs), but also reduces the effectiveness of the peephole optimizations.

    I'll report back once BANKSEL insertion has been fixed for the
    multiple-skip-case.

     
  • Gál Zsolt

    Gál Zsolt - 2011-08-19

    Thanks for the explanation. That is an additional information for me to handle this situation.

     
  • Philipp Klaus Krause

    • Category: --> PIC14
     

Log in to post a comment.