2

I'd like to write a function that takes an ARMv8 instruction containing a condition code, and returns an ARMv8 instruction whose effect is the same as the original but with the condition inverted.

Most cases are easy:

  • If the condition code is not AL, then just toggle bit 0 of the condition code.
  • Otherwise (if the condition code is AL) there is no inverse condition code. Bizarrely NV behaves like AL! Instead we have to rewrite the instruction to pretend that its condition is always false:
    • If the instruction is a branch, replace it with a no-op.
    • If the instruction is CSEL, replace it with MOV.
    • If the instruction is CSINC, replace it with ADD.
    • If the instruction is CSINV, replace it with MVN.
    • If the instruction is CSNEG, replace it with NEG.
    • Otherwise it's CCMP or CCMN...

It's the last case that is causing me trouble. It doesn't matter whether the instruction is CCMP or CCMN since the arithmetic operation isn't going to happen anyway. What is needed is a way of setting the N, Z, C and V flags to arbitrary constant values in a single instruction. Is it possible?

apt1002
  • 969
  • 6
  • 15
  • While the question at hand is interesting, I think you're overthinking the `AL` case. After all, `ccmp w0, 0, 0, al` is really just `cmp w0, 0`, so there's nothing there to invert... – Siguza Jun 14 '21 at 07:03
  • @Siguza The point is to reverse the instruction to `ccmp w0, 0, 0, nv` (using the imaginary `nv` "never" condition code). That version would clear all flags unconditionally. – Raymond Chen Jun 15 '21 at 15:53
  • Yes, but my argument is that no matter your point of reference, it should always be legal to substitute `ccmp w0, 0, 0, al` with `cmp w0, 0` and `b.al 0xabc` with `b 0xabc` without any change in behaviour. And if your set of rules does not require `cmp` and `b` instructions to be "inverted", then this would make the argument that neither do conditionals with `al`. – Siguza Jun 15 '21 at 16:00
  • 1
    The exercise is not "How can I replace `ccmp w0, 0, 0, al` with something simpler." The exercise is "Given `ccmp w0, 0, 0, al`, how do I create an instruction that tests the opposite condition: If `al` is **false**, then compare `w0` with `0`; otherwise copy `0` to `nzcv`. `cmp` is not encoded with a condition code, so it is out of scope of the exercise. I agree that negating `b` shouldn't be in scope, since `b` is not shorthand for `bal`; it's a separate encoding. – Raymond Chen Jun 15 '21 at 17:37
  • 1
    Skimming all instructions in the architecture reference that set NZCV, I'm pretty sure this is not possible. If you could use two instructions you could do `cmp wzr, #0 ; ccmp w0, 0, #nzcv, ne`. If you could keep a GP register preloaded with `0x0123456789abcdef` then you could use `rmif` with a shift count selecting the desired nibble. – Nate Eldredge Aug 06 '21 at 03:51

0 Answers0