5
\$\begingroup\$

I want to save/restore the PIC's carry bit. I'm using the 16F628A.

SAVE_CARRY
    btfss STATUS, 0
    goto CARRY_OFF 

CARRY_ON
    bsf carry, 0
    return

CARRY_OFF
   bcf carry, 0
   return

RESTORE_CARRY
   btfss carry, 0
   goto RESTORE_CARRY_OFF

RESTORE_CARRY_ON
   bsf STATUS, 0
   return

RESTORE_CARRY_OFF
   bcf STATUS, 0
   return

There must be a better way. Is there?

\$\endgroup\$
5
\$\begingroup\$

One way that you can do:

SAVE_CARRY:
    bsf    carry, 0
    btfss  status, c
    bcf    carry, 0
    return

RESTORE_CARRY
    bsf    status, c
    btfss  carry, 0
    bcf    status, c
    return

If you need to save the registers "W" and "Status", before execute an interrupt code, there is another way:

Save_Context:
    movwf w_temp
    swapf status,w
    movwf status_temp
    ;Your interrupt code here. 

Restore_Context:
    swapf status_temp,w
    movwf status
    swapf w_temp,f
    swapf w_temp,w
    retfie
\$\endgroup\$
3
\$\begingroup\$

If you just want to save/restore the carry bit, and if you don't mind losing the value when you store it and trashing the saved value when you restore it, just use "rlf saved_carry,f" to save it and "rrf saved_carry,f" to restore it. No other registers or flags affected.

If speed is of utmost importance and you need to save/set some other bit and restore it later (e.g. RP0), you can do something like:

Int_Entry:
  btfss STATUS,RP0
   goto Version_with_RP0_clear
  bcf   STATUS,RP0
  do_interrupt_logic
  bsf   STATUS,RP0
  retfie
Int_with_RP0_Clear:
  do_interrupt_logic
  bcf   STATUS,RP0 ; If interrupt logic might have left it set
  retfie

That's a total of four cycles to not only save/restore RP0, but also set it to a known state for the ISR (if the branch is taken, RP0 is already in the correct state so there's no need to set it). If the interrupt logic wouldn't affect W or other flags (e.g. if it uses bsf/bcf/btfss/btfsc/incfsz/decfsz for just about everything) this logic can save four cycles versus saving W and status, clearing status, running the interrupt, and then restoring status and W. Such savings aren't important in a whole lot of cases, but may be very important if one is trying to e.g. use a TMR2 interrupt to do something every 50 cycles. Since TMR2IF is in a banked register, one has to clear RP0 to reset TMR2IF. If TMR2 is ticking every 50 cycles and the ISR would take 26 cycles with the improvement or 30 cycles without, saving those three cycles in the ISR could increase main-line CPU availability by 20%.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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