The bit shifting operations are fairly straightforward.

; arithmetic (signed) shifts SHAL Rn ; Rn <<= 1, T = the bit shifted out SHAR Rn ; Rn >>= 1, T = the bit shifted out ; logical (unsigned) shifts SHLL Rn ; Rn <<= 1, T = the bit shifted out SHLR Rn ; Rn >>= 1, T = the bit shifted out SHLL2 Rn ; Rn <<= 2 SHLR2 Rn ; Rn >>= 2 SHLL8 Rn ; Rn <<= 8 SHLR8 Rn ; Rn >>= 8 SHLL16 Rn ; Rn <<= 16 SHLR16 Rn ; Rn >>= 16

You cannot shift by arbitrary constant amounts. Only certain fixed values are permitted. If you want to shift left by, say, 9, you’ll have to construct it from a `SHLL8`

and a `SHLL`

.

Note also that `SHAL`

and `SHLL`

are functionally equivalent. But they have different encodings, so the designers burned an opcode for a redundant operation.

There are no “large shift” options for right shifts. You can perform multiple one-bit shifts, or use a variable shift:

SHAD Rm, Rn ; if Rm > 0: Rn <<= (31 & Rm) ; if Rm = 0: nop ; if Rm < 0: Rn >>= (31 & -Rm), signed SHLD Rm, Rn ; if Rm > 0: Rn <<= (31 & Rm) ; if Rm = 0: nop ; if Rm < 0: Rn >>= (31 & -Rm), unsigned

Note that these shift instructions shift both left *and* right, depending on the sign of the shift amount. If you want to shift right by an amount in a register, you therefore need to negate the value, and then shift left.

Finally, we have rotation.

ROTL Rn ; rotate left, T contains carried-out bit ROTR Rn ; rotate right, T contains carried-out bit ROTCL Rn ; 33-bit rotate through T ROTCR Rn ; 33-bit rotate through T

The rotation instructions rotate either a 32-bit or 33-bit value by one position. For the 32-bit rotations, the bit that rotated off the end is copied to `T`. For the 33-bit rotations, the `T` flag acts as the 33rd bit.

We saw earlier that there is no `NEGV`

instruction. To detect overflow from a negation, you just have to check for the value `0x80000000`

directly. Here’s the shortest sequence I could come up with:

; branch if Rn equals 0x80000000 rotl Rn ; rotate left one bit dt Rn ; decrement and test for zero bt underflow ; Y: underflow occurred

The result of the `DT`

is zero if the previous value was 1, and the previous value was 1 if the original value was `0x80000000`

.

This is a destructive operation, so do it in a scratch register. You should have one available, since it’s the source register for the `NEGV`

you were checking.

“There are no “large shift” options for right shifts.”

Can you elaborate? The available operations for left and right shifts look totally symmetrical to me, so I must have misunderstood what is meant here.

On another note, seeing another dive into a to me unfamiliar architecture is very exciting. I was fearing that we ran out of qualifying architectures already. (As far as I remember, you only cover architectures for which a version of Windows existed?)

Derp. I’m not sure what I was thinking when I wrote that.