People use ``switch'' to mean 2 very different things.
I assume you've already evaluated the condition and put the result in some bit somewhere (very often the Z or C bit of the STATUS byte). Then implementing the standard ``if...then...else...endif'' code looks like
; is the result true ? btfss result_byte,result_bit goto else ; then: ; result was true (bit=1), so execute following code. ... ; goto endif else: ; result was false (bit=0), so execute the following code. ... ; endif:
The ``switch...case...default'' from C, or the ``case..of'' from Pascal, can choose any one of dozens of alternatives. Here's how this is implemented on the PIC.
The best way (least programming effort) I've found so far is the ``select...case...endcase...endselect'' set of macros from Karl Lunt (1999-05)
Tom Hartman says:
...I came up with a method for a "switch" statement, its a little faster than average because it doesn't reload the variable for each case. Each case is 3 clocks if not equal, 4 clocks if equal. Code can appear between cases, but be careful not to alter the contents of w.; Switch, case macros: ; Typical usage: ; #define CONSTANT1 1 ; #define CONSTANT2 2 ; SWITCH_F file_register ; CASE_W CONSTANT1, do_case_1 ; CASE_W CONSTANT2, do_case_2 ; ; --- Or where W is already the variable--- ; SWITCH_W ; CASE_W CONSTANT1, do_case_1 ; CASE_W CONSTANT2, do_case_2 ;-------------- SWITCH_W macro _previous_case set 0 ; W already contains the switch variable endm ;-------------- SWITCH_F macro f_label movf f_label,w ; read the location into w _previous_case set 0 endm ;-------------- CASE_W macro case_const, case_label xorlw case_const^_previous_case btfsc STATUS,Z goto case_label _previous_case set case_const endm ;------------------------------------------------------------------
18C specific
Comments:
Tom Hartman switch-case is pretty neat, but it appears it's possible to get a match that shouldn't match. The exclusive or works on columns of bits. When we finally get a match, the each column of bits in w exclusive or's out to the same result as the exclusive or'd column of bits in the updated _previous_case. However, we could switch any bits in the column and still get the same match. We could switch bits out of the current case constant to a previous case constant and still get the match on the current case constant, even though it's wrong. It seems that by carefully choosing the order of the case statements (like putting them in numerical order), it will still work. So, while this is great efficient code, there's some gotcha's (and this one got me!).
Harold
[FIXME: Huh ? Tom's code looks fine to me. Can anyone give me a specific example of when it might fail ?]
Archive:
This works because: (X xor A) xor (A xor B) is the same as: X xor (A xor A) xor B which is the same as X xor 0 xor B which is the same as X xor B.
See also: