5 ms·
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
by dougall 3y 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
- userbinator 3y agoParent is 12 bytes, yours is 8, but x86 can do it in 5: add eax, eax setz al
- moonchild 3y agoNope. If eax is initially 1, then it will be 0 after your sequence, where 2 was desired.
- userbinator 3y agoMy mistake. I was thinking of the other idiom for !. How about this then: add eax, eax jnz skipinc inc eax skipinc: Also 5 bytes.
- dougall 3y agoNice! 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.