I've been writing code with FOR and WHILE loops for the
pic16f84a - however, the generated code for the loop
conditionals is incorrect, which causes the loops to
terminate immediately. For example:
test.c:
#define __16F84A
#include "16f84a.h"
void main(void)
{
static unsigned char i;
TRISB = 0;
i = 0;
while (1) {
for (i = 0; i < 42; i++) {
PORTB = i;
}
}
}
> sdcc -mpic14 -p16f84 test.c
Generates this assembly (snippet relevant to the inner
loop)
;#CSRC test.c 13
; for (i = 0; i < 42; i++) {
CLRF _main_i_1_1
_00108_DS_
MOVLW 0x2a
SUBWF _main_i_1_1,W
BTFSC STATUS,0
GOTO _00106_DS_
;#CSRC test.c 14
; PORTB = i;
MOVF _main_i_1_1,W
BCF STATUS,5
BCF STATUS,6
MOVWF _PORTB
;#CSRC test.c 13
; for (i = 0; i < 42; i++) {
BANKSEL _main_i_1_1
INCF _main_i_1_1,F
GOTO _00108_DS_
RETURN
The conditional test, (i < 42), where (i) is an
unsigned 8-bit integer compared with a literal, occurs
in the first block of code after the _00108_DS_ label:
MOVLW 0x2a - set W to 0x2a (42)
SUBWF _main_i_1_1,W - subtract W from i,
store result in W
BTFSC STATUS,0 - skip next
instruction if the carry bit is clear
GOTO _00106_DS_ - Restart the inner loop
The carry bit will be set on the subtraction operation
if (i < 42) - so on the first step of the loop, the
carry bit is set, so the GOTO is not skipped, so the
inner loop effectively never runs.
I am attempting to fix the problem, but my familiarity
with the compiler is still very limited. I am able to
fix the problem by commenting out line 4040 of
src/pic/gen.c:
//rFalseIfx.condition ^= 1;
However, given the code that surrounds this line, I
suspect that, while my change apparently fixes unsigned
8-bit comparisons with literals, it may break
comparisons of larger sizes.
Logged In: YES
user_id=771
Ugh, it appears I was wrong.
I was testing my code on nitpic, which seems to have this
logic wrong. On gpsim and actual hardware it appears the
generated code is correct.
Sorry for the erroneous report. I am trying. :)