I'm using MPLAB X and XC8 to compile a simple project for the PIC16F886. To manipulate the GPIOs, what I'm doing is

#define gpio_ra1(b) (b ? porta |= 0x02 : (porta &= ~(0x02)))

and then letting the compiler do its constant propagation and whatever so that the expressions gpio_ra1(true) and gpio_ra1(false) can be compiled to a single bcf or bsf instruction. Works great on SDCC, but, at least in the case where b evaluates to false, such as in the statement gpio_ra1(0), XC8 produces the following buffoonery:

movlw 253                          ; the relevant bit is now 0
movwf ??random_local_variable      ; why is the compiler keeping a copy of this?
movf  ??random_local_variable,w    ; why is the compiler reloading the value it just saved?
bcf 3,5                            ; banksel the gpio ports
andwf 6,f                          ; now bring the gpio pin low

I'm not sure what the XC8 compiler is doing with random_local_variable; this variable is never used outside of sequences like this, meaning it's never meaningful to read this variable. But my biggest concerns with the generated code are basically

  • is the write actually atomic? When I use this on port B it interferes with the in-circuit debugger

  • the whole sequence of instructions can just be replaced with bcf 6,1.

  • does XC8 actually provide an intrinsic you're "supposed to" use?

  • 2
    \$\begingroup\$ Please show the full (but minimal) code producing this assembly, not only the macro definition. \$\endgroup\$
    – Eugene Sh.
    Oct 18, 2021 at 14:20
  • \$\begingroup\$ @EugeneSh. is it better now? \$\endgroup\$ Oct 18, 2021 at 14:28
  • \$\begingroup\$ Not really, as you haven't posted the code. Anyway, the conditional operator (AKA the "ternary") is "designed" to return the evaluated value. In your case you could do something like x=gpio_ra1(true) - and then the expectation would be that x will receive the value of the evaluated expression (that is porta |= 0x02). For that reason the compiler wants to "keep" this value. And looks like it is not optimizing well enough to understand you don't need this value. I suggest to replace the macro with static inline void function (with if/else construct) \$\endgroup\$
    – Eugene Sh.
    Oct 18, 2021 at 14:33

1 Answer 1


Which version of XC8 do you have? Free one or paid? Free one is know to have optimization level limits which cause such useless instructions inserted.

Intrinsic are basically RA1 macro from pic16f886.h (include it). You can browse it for other macros there. Or check out the XC8 manual, section ACCESSING REGISTERS FROM ASSEMBLY CODE.

  • \$\begingroup\$ I have the free version of XC8. It's lousy enough I don't want to pay money for it. Where can I find the definition of the RA1 macro? \$\endgroup\$ Oct 18, 2021 at 14:27
  • \$\begingroup\$ I've already wrote where you can find it. What do you mean? \$\endgroup\$
    – NStorm
    Oct 18, 2021 at 14:37
  • \$\begingroup\$ Oh, I understand now. \$\endgroup\$ Oct 18, 2021 at 14:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.