Hacker News new | ask | show | jobs
by dougall 1111 days ago
Though it'd be preferable to do:

    cmp wzr, w19      // set the carry flag if w19 is zero
    adc w8, w19, w19  // w8 = w19 + w19 + carry
1 comments

Parent is 12 bytes, yours is 8, but x86 can do it in 5:

    add eax, eax
    setz al
Nope. If eax is initially 1, then it will be 0 after your sequence, where 2 was desired.
My mistake. I was thinking of the other idiom for !. How about this then:

      add eax, eax
      jnz skipinc
      inc eax
    skipinc:
Also 5 bytes.
Nice!

Sorry if this comment is overly pedantic, I just enjoy having an excuse to talk about assembly.

It's worth noting that 0x80000000 would pass this "is zero" check. (I think this is probably a legal compiler optimisation because signed integer overflow is undefined, but I'm not 100% sure either way.)

Using a jump is also a bit risky - slightly better if it's predictable, much worse if it's unpredictable.

As far as size, this is 5 bytes on 32-bit x86 (as stated), 6 bytes on 64-bit x86, but can be 8 bytes if different registers are used:

    4501C0            add r8d,r8d
    7503              jnz 0x8
    41FFC0            inc r8d
(And, unlike the ARM code, you'd need an additional mov instruction if you wanted to preserve the input value.)

It feels like an ADC-based variant might be possible on x86 too - CMP and ADC are also x86 instructions. The problem is that ARM and x86 invert the value of the carry flag on subtraction (and comparison), so it doesn't translate directly, and I can't immediately see how to fix it up without using more instructions.