Now we(asm people) all know that if you have an unsigned value, say, in r0, you can divide that by two when you do
lsr r0, #0x1
But! This doesn’t quite apply when the value is SIGNED, that is, you don’t know if it is positive/zero or negative.
You might want to say, "just use asr r0, #0x1
", but due to the way negatives are expressed on a bit level, this won’t work. If you just say asr r0, #0x1
(to do a sign-extending lsr
, essentially) it’ll round UP odds by default. So to combat this, you add one before asr-ing. But wait! It could be positive, and we don’t want to add one then! So we use the sign bit as an indicator. In fact we add that exactly. Here’s the proper way:
lsr r1, r0, #0x1F @Gets the sign bit only
add r0, r1 @Adds one if r0 was negative, nothing if r0 was nonegative
asr r0, #0x1 @Do the division by two
I’m not sure what the constant to add is if you’re dividing by 4 or something, and I don’t care to work it out right now, but my hunch is it’s (division constant-1). Though those aren’t as easy to generate based on the sign bit and may take branching. But the solution for division by 2 is just elegant.
To be fair, I did not come up with this myself. It was in the routine for calculating avoid based on luk; the compiler had to assume luk(after boosts) was signed, so it did this. One person that looked at it (I will not name names) annotated it as setting r1 to 0 (I don’t know if they didn’t understand it or just assumed luk is always positive), but I remembered the trick and am bringing it here to you.
… mainly because my modular power routine hands you signed parameters. And you have to account for possibly negative boosts.