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 Sdcc-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/sdcc-user