Hi Jonathan,
> I'm trying to get the following assignment to work with the PIC16 port
> of sdcc. Is there a reason the sdcc assembler is so complex and more
> to the point a reason for it not working?
>
> PORTBbits.RB4 = PORTBbits.RB0
>
> The sdcc generated binary doesn't seem to work and generates the
> following assembler:
> 0000d2 6a00 clrf 0, 0 CLRF r0x00
> 0000d4 b081 btfsc 0x81, 0, 0 BTFSC _PORTBbits, 0
> 0000d6 2a00 incf 0, 0x1, 0 INCF r0x00, F
> 0000d8 5000 movf 0, 0, 0 MOVF r0x00, W
> 0000da 0b01 andlw 0x1 ANDLW 0x01
> 0000dc 38e8 swapf 0xe8, 0, 0 SWAPF WREG, W
> 0000de 6ef4 movwf 0xf4, 0 MOVWF PRODH
> 0000e0 5081 movf 0x81, 0, 0 MOVF _PORTBbits, W
> 0000e2 0bef andlw 0xef ANDLW 0xef
> 0000e4 10f4 iorwf 0xf4, 0, 0 IORWF PRODH, W
> 0000e6 6e81 movwf 0x81, 0 MOVWF _PORTBbits
This is a more complicated case than one might believe due to PORTB
being volatile, but even if you used non-volatile variables, the
generated code would be the same so I will go into more details on the
volatility problem here.
The real problem is that the compiler is not smart enough to take the
left-hand side as a (one-of-two-values) pseudo-literal value; however,
only literal assignments to a single bit are optimized using BCF/BSF
instructions. The compiler first reads the bitfield, turns its value
into a char (or int), and then assigns the general integer value to the
bitfield.
If I find the time, I will try to have it optimized into
; read PORTBbits.RB0
CLRF r0x00
BTFSC _PORTBbits, 0
INCF r0x00, F
MOVF r0x00, W
ANDLW 0x01
; assign to PORTBbits.RB4
BTFSC WREG, 0
BSF _PORTBbits, 4
BTFSS WREG, 0
BCF _PORTBbits, 4
The even better (optimal?) variant
MOVF _PORTBbits, W
BTFSC WREG, 0
BSF _PORTBbits, 4
BTFSS WREG, 0
BCF _PORTBbits, 4
is out of reach for the compiler.
Note: PORTBbits must be copied into WREG in order to guarantee a
consistent value on the following 2 bittests; required by PORTB being
volatile...
Using the semantically equivalent
void t4(void) {
// TRISB and PORTB setup skipped for brevity
while (1) {
if (PORTBbits.RB0) {
PORTBbits.RB4 = 1;
} else {
PORTBbits.RB4 = 0;
}
}
}
and --optimize-df I get the pretty good
_t4:
_00133_DS_:
; .line 53; port.c if (PORTBbits.RB0) {
BTFSS _PORTBbits, 0
BRA _00130_DS_
; .line 54; port.c PORTBbits.RB4 = 1;
BSF _PORTBbits, 4
BRA _00133_DS_
_00130_DS_:
; .line 56; port.c PORTBbits.RB4 = 0;
BCF _PORTBbits, 4
BRA _00133_DS_
RETURN
taking 5 (if true) or 6 cycles per iteration.
> I had a colleague send me the Hi-TECH assembler instruction! which
> does work.
>
> 3FF8 8881 BSF 0xf81, 0x4, ACCESS
Unconditionally setting RB4 is not what you asked for in the program,
there is obviously some conditional code missing; probably similar to
what t4() above yields, though possibly using more BTFSx and less BRA.
I hope the workaround is kind'a acceptable,
Raphael
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Sdcc-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sdcc-user