Single bit XOR in 8051

Thread Starter

cmartinez

Joined Jan 17, 2007
8,253
This is embarrassing... I consider myself an expert in the 8051 architecture, but I've never had to perform a single bit xor operation before.

What I want to do is fairly simple, I want C = XOR(DOWN_FLAG, UP_FLAG). I've performed plenty of byte-to-byte XRL operations before, but I've never had the need to perform a bit-to-bit xor, until now.

This is how the code would look like if the XRL C, bit instruction existed (which it doesn't ... numbers in parenthesis are the clock cycles performed by each instruction in an AT89LP4052):

Code:
   MOV DOWN_FLAG, C   ;(2)
   XRL C, UP_FLAG     ;(?) 
   JC CHECK_UP_DOWN_INPUTS_EXIT ;(3)
But since the stupid bit-to-bit XRL instruction doesn't exist, I've been forced to translate them into bytes and performing XRL there.

Code:
   MOV DOWN_FLAG, C   ;(2)
   CLR A              ;(1)
   MOV A.0, C         ;(2)
   MOV C, UP_FLAG     ;(2)
   MOV B, #00H        ;(3)
   MOV B.0, C         ;(2)
   XRL A, B           ;(2)
   JNZ CHECK_UP_DOWN_INPUTS_EXIT ;(3)
This bothers me because it seems like an awful waste of cycles and instructions for such a simple task. And I know that a standard gate XOR instruction (which can easily be translated to code) looks like this.

upload_2019-1-6_15-3-1.png

But it still looks like an awful number of steps. Is there an easier way?
 

JohnInTX

Joined Jun 26, 2012
4,787
My 8051 is rusty so I might not be getting how you are storing UP_FLAG and DOWN_FLAG but the trick is to perform normal byte operations on the whole register-even the bit addressable ones- then just strip off the other bits in the result by ANDing.
If the flags are corresponding bits in two registers, just XRL the two registers to A, and ANL A, #mask to strip off the unused bits then check for Z.

If the flags are not aligned (2 bits in the same register or random different bit locations in different registers) load one register to A, rotate A to align the first flag under the other flag in its register then XRL A with the register, ANL with the mask and check for Z.

The ANL mask is constructed to have a '1' where the flags are and zeros in the other 7 bits i.e.
ANL A,#80h would expect both flags to have been stored or rotated to the MSbit for the byte-wide XRL operation.

Apologies if I'm misunderstanding the problem and for sketchy 8051 code...
Code:
; Don't remember how to specify the bits but you get the idea
UP_FLAG equ 20h.0   ; addressable bit 0 (MSbit of addressible segment register at 20h)
DOWN_FLAG equ 20h.1   ; addressable bit 1 (next bit of same register)

  mov A,20h     ; get the register with the flags to A
  RL  A       ; rotate one bit left, DOWN_FLAG is now MSbit of A and aligned with UP_FLAG in the register
  XRL A,20h     ; XOR, the two MSbits are valid. Ignore the others
  ANL A,#80h     ; strip off unused bits. Z/NZ indicates XOR result on the 2 flags
  JZ FlagsWereTheSame
 
Last edited:

Thread Starter

cmartinez

Joined Jan 17, 2007
8,253
Thanks, John. But I think I already solved it:

Code:
   CHECK_DOWN_FLAG:
     JNB, DOWN_FLAG, CHECK_UP_FLAG ;(3) if down_flag was cleared, then compare with up_flag
     JB UP_FLAG, CLEAR_ALL_FLAGS   ;(4) if up_flag was also set, clear both flags
    JMP CHECK_UP_DOWN_INPUTS_EXIT  ;(3) otherwise, exit directly

   CHECK_UP_FLAG:                  ;DOWN_FLAG was cleared
     JB UP_FLAG, CHECK_UP_DOWN_INPUTS_EXIT ;(4) if up_flag is set, exit directly, clear both flags if not

  CLEAR_ALL_FLAGS:
    CLR UP_FLAG                    ;(2)
    CLR DOWN_FLAG                  ;(2)

  CHECK_UP_DOWN_INPUTS_EXIT:
What an annoying pain in the (_*_) ... really ...
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,253
I like your routine, though. I'm going to evaluate it against mine... see which one is the most efficient ... the loser pays the next round of beers! ;)
 

JohnInTX

Joined Jun 26, 2012
4,787
I like your routine, though. I'm going to evaluate it against mine... see which one is the most efficient ... the loser pays the next round of beers! ;)
Deal!
And to increase my odds, keep in mind that you can eliminate the rotation(s) by judicious selection of where the flags are located i.e. bits 0 and 8 are MSbits in different bit-mapped registers.
mmmm.. beer
 
Last edited:

BobaMosfet

Joined Jul 1, 2009
2,113
This is embarrassing... I consider myself an expert in the 8051 architecture, but I've never had to perform a single bit xor operation before.

What I want to do is fairly simple, I want C = XOR(DOWN_FLAG, UP_FLAG). I've performed plenty of byte-to-byte XRL operations before, but I've never had the need to perform a bit-to-bit xor, until now.

This is how the code would look like if the XRL C, bit instruction existed (which it doesn't ... numbers in parenthesis are the clock cycles performed by each instruction in an AT89LP4052):

Code:
   MOV DOWN_FLAG, C   ;(2)
   XRL C, UP_FLAG     ;(?)
   JC CHECK_UP_DOWN_INPUTS_EXIT ;(3)
But since the stupid bit-to-bit XRL instruction doesn't exist, I've been forced to translate them into bytes and performing XRL there.

Code:
   MOV DOWN_FLAG, C   ;(2)
   CLR A              ;(1)
   MOV A.0, C         ;(2)
   MOV C, UP_FLAG     ;(2)
   MOV B, #00H        ;(3)
   MOV B.0, C         ;(2)
   XRL A, B           ;(2)
   JNZ CHECK_UP_DOWN_INPUTS_EXIT ;(3)
This bothers me because it seems like an awful waste of cycles and instructions for such a simple task. And I know that a standard gate XOR instruction (which can easily be translated to code) looks like this.


But it still looks like an awful number of steps. Is there an easier way?
But you do know what a mask is, right? You access individual bits using masks.
 

Thread Starter

cmartinez

Joined Jan 17, 2007
8,253
But you do know what a mask is, right? You access individual bits using masks.
Of course I know what a mask is. I've been programming this things for more than 20 years already... it's just that I was surprised about all the gymnastics involved in such a simple operation.

Also, I found that a bitwise And, followed by jump condition, and then an Or followed by another conditional jump will do the job quite nicely. But it still takes way too many instructions and clock cycles for my taste.
 
Top