Shop OBEX P1 Docs P2 Docs Learn Events
[PUZZLE] Testing the bits of a constant in PASM — Parallax Forums

[PUZZLE] Testing the bits of a constant in PASM

Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
edited 2011-08-07 20:43 in Propeller 1
'Learned a new trick today (new for me, at least); but, rather than divulging it right away, I thought it would be fun to present it as a puzzle. So here it is: How do you set a flag depending on the value of a certain bit in a CONstant?

Obviously, you could do something like this:
              mov       x,#CONSTANT
              test      x,#BIT wc
But that takes two instructions, plus an extra register. Can you do it with one instruction and no extra registers?

For extra recognition, how could you extend the same technique to replace the following with a single instruction and no extra registers?
              mov       x,#CONSTANT
              cmp       x,#"A" wz

-Phil

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2011-08-06 17:05
    email sent
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-08-06 17:30
    'Got one winner so far, including the bonus (DING! DING! DING!) points.

    -Phil

    Edit: Oops! Marko's answer for the first part did not produce results equivalent to the code posted for the puzzle.

    Edit 2: Okay, nonetheless, he did provide a more general solution for the case of testing a single bit.
  • kuronekokuroneko Posts: 3,623
    edited 2011-08-06 17:47
    Edit: Oops! Marko's answer for the first part did not produce results equivalent to the code posted for the puzzle.
    The original post said value of a certain bit, my solution does exactly that (or rather doesn't behave differently from the verbose version). Which CONSTANT/BIT pair is giving you (or me that is) trouble? Or do you really need multi-bit behaviour?
  • potatoheadpotatohead Posts: 10,261
    edited 2011-08-06 18:17
    sent

    (please enter 10 characters)
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-08-06 19:33
    Okay, my apoligies for the delay: my internet (Broadstripe cable) was out for the last 1.5 hrs. So I got busy in the kitchen boiling syrup to make amaretto cherries. Washington's cherry crop is late this year, but OMG are they sweet and juicy! Amaretto just makes them better.

    Kuroneko, you're right: 1/2 point awarded for that; the other for providing a more general solution than the 9-bit-restricted answer I had in mind. :)

    potatohead: Ooh, sorry: no.

    -Phil
  • AribaAriba Posts: 2,690
    edited 2011-08-07 10:33
    I've also sent an email (PM would be easier).

    Andy
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-08-07 10:43
    Andy submitted an entry that required an auxiliary register. It would work, but an auxiliary register is not necessary for the solution.

    (Sorry about the PM, Andy. I just like to have all my correspondence in one place.)

    -Phil
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-08-07 13:06
    Andy submitted a second entry. Both parts involved an auxiliary, presumptively unused, SFR. This is an improvement over his first solution, since it does not add to the total word count. However, not even an SFR is necessary to solve either part of the puzzle.

    The second part of Andy's entry (the cmp) works but produces the wrong (i.e. inverted) result for the zero flag.

    -Phil
  • AribaAriba Posts: 2,690
    edited 2011-08-07 14:59
    The second part of Andy's entry (the cmp) works but produces the wrong (i.e. inverted) result for the zero flag.

    -Phil

    Have you seen the ! before the parentheses ?
    Andy
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-08-07 15:13
    Oh sorry, Andy, I missed that important detail. Your cmp does produce the right output for the z flag after all.

    -Phil
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-08-07 16:59
    Third time's the charm for Andy! He submitted solutions to both parts of the puzzle that don't require an auxiliary register or SFR.

    -Phil
  • AribaAriba Posts: 2,690
    edited 2011-08-07 17:34
    Thanks

    I think I will soon receive another star under my name for this solution...:smile:

    Andy
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-08-07 18:20
    'Just one more post, Andy (I think)! So how did you finally figure out the solution. (It's okay now to reveal what you submitted.)

    -Phil
  • AribaAriba Posts: 2,690
    edited 2011-08-07 19:32
    ...So how did you finally figure out the solution...

    I thought, the instruction needs a destination register, and if it should not be an initalized register and no SFR, then the only other register with a known value is the instruction itself.
    The higher bits disturb a bit when comparing with the source immediate value, so we need an AND to eliminate these higher bits. And we should not modify the instruction, so a NR is necessary. An AND with NR is known as TEST instruction.

    Testing a bit of a constant with result in Carry:
    test $,#(CONSTANT & BITMASK)  wc
    
    An AND of CONSTANT and BITMASK results in zero or the BITMASK, this is ANDed with itself by the TEST instruction which eliminates the higher bits of the instruction and sets the Carry flag only according the source field.

    Comparing a constant with another:
    test $,#!(CONSTANT == "A")>>31  wz
    
    The compile time compare of CONSTANT and "A" results in zero (False) or $FFFF_FFFF (True). $FFFF_FFFF is to big for the source field, so I shift it right and we have only 0 or 1 in the source field. Again the TEST eliminates the higher bits and the ZERO flag is set according this 0 or 1. Because the Z Flag would be set invers to a compare, I add a NOT (!) before the parentheses.

    Puhh, now I have deserved my fourth star, I hope...

    Andy
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2011-08-07 19:42
    Ariba wrote:
    Puhh, now I have deserved my fourth star, I hope...
    Yes, definitely! :)

    -Phil
  • frank freedmanfrank freedman Posts: 1,983
    edited 2011-08-07 20:14
    Ariba wrote: »
    I thought, the instruction needs a destination register, and if it should not be an initalized register and no SFR, then the only other register with a known value is the instruction itself.
    The higher bits disturb a bit when comparing with the source immediate value, so we need an AND to eliminate these higher bits. And we should not modify the instruction, so a NR is necessary. An AND with NR is known as TEST instruction.

    Testing a bit of a constant with result in Carry:
    test $,#(CONSTANT & BITMASK)  wc
    
    An AND of CONSTANT and BITMASK results in zero or the BITMASK, this is ANDed with itself by the TEST instruction which eliminates the higher bits of the instruction and sets the Carry flag only according the source field.

    Comparing a constant with another:
    test $,#!(CONSTANT == "A")>>31  wz
    
    The compile time compare of CONSTANT and "A" results in zero (False) or $FFFF_FFFF (True). $FFFF_FFFF is to big for the source field, so I shift it right and we have only 0 or 1 in the source field. Again the TEST eliminates the higher bits and the ZERO flag is set according this 0 or 1. Because the Z Flag would be set invers to a compare, I add a NOT (!) before the parentheses.

    Puhh, now I have deserved my fourth star, I hope...

    Andy

    While I am greenwood when it comes to the prop, I started to reply a few times. I did not because I was not sure of the context in which you were comparing a two literals as shown. If CONSTANT and BIT are already defined, could a logical have been used to compare the contents of the address of the CONSTANT and BIT locations? (Run time assuming the values have been stored)

    What would be more interesting if this is a compile time trick would be to see what the resultant code is in the hex listings and compare what the compiler generated to carry out your trick as opposed to the original two instruction.

    If I am way off the mark, just give a chuckle and let me know so I can adjust my frame of reference.

    Thanks
    Frank


    Frank
  • Andrey DemenevAndrey Demenev Posts: 377
    edited 2011-08-07 20:35
    In general, the solution is simple : execute an instruction that affects the flags as needed, with NR modifier.

    code deleted - it was completely wrong :(
  • kuronekokuroneko Posts: 3,623
    edited 2011-08-07 20:43
    [thread=108002]Direct flag manipulation in assembler ...[/thread] is a nice place to start.
Sign In or Register to comment.