Even or odd, count the set bits, multiply by shifting

Four questions about one number answered with a mask, two shifts and a loop that adds a bit to a counter.

Four questions about one number, none of them answered with arithmetic. Is 182 odd, what is it times eight, what are its bottom four bits, and how many of its 32 bits are ones. The answers land in t1 to t4.

The instructions of the Example before this one treat a register as a number. These four treat the same register as 32 bits side by side, which is the other way to read one and often the cheaper way.

You need to know: the "Arithmetic, logic and bits" lecture. What is new here is that a masked bit is already a 0 or a 1, so counting one costs an add and no branch at all.

andi t1, t0, 1 is C's n & 1, and the answer is the value: t1 comes out at 0 because 182 is even, and it would be 1 for an odd number, with nothing else to read and no flag anywhere. The M68K tests that bit with btst, which sets Z to 1 when the bit was 0, and then needs an sne to turn the flag back into a number.

Shifting left by three multiplies by eight, since every place a bit moves left doubles what it is worth. t2 comes out at 000005B0, which is 1456. The shift amount is five bits, so 0 to 31, and sll takes it from a register when the program worked it out, where slli has it written down.

andi t3, t0, 0xF keeps the four bits the mask has set and clears everything else, so t3 is 6, the 6 of 0xB6. That is how any field is taken out of a packed value: mask what you want, then shift it down to the bottom if it was not there already.

The constant of andi is 12 bits and sign extended, so it reaches from -2048 to 2047 and nothing else. andi t0, t0, -256 is legal and clears the low byte, because -256 sign extends to FFFFFF00; andi t0, t0, 0xFF00 is a build error, operand is out of range, and a mask like that goes through an li into a register and a plain and.

The loop runs 32 times, once per bit, and does C's count += n & 1; n >>= 1;. srli is the shift that brings zeroes in at the top. srai copies the sign bit down instead, which is what divides a signed number by two, and here the register is a row of bits to take apart. t4 comes out at 5, the number of ones in 10110110. The M68K writes the same loop around its carry flag, shifting the bottom bit into C and branching on it; here the masked bit is a number and add t4, t4, s0 counts it without a branch.

The second loop counts the leading zeroes, the run of 0 bits from the top down, and s1 comes out at 24: the highest set bit of 182 is bit 7, and there are 24 above it. MIPS answers that in one instruction, clz, and this assembler does not know the word: counting leading zeroes is in RISC-V's Zbb bit manipulation extension, which is not here, so the base instructions do it in a loop.

Try changing li t0, 182 to li t0, 183, one more. t1 becomes 1 because the number is now odd, t3 becomes 7, and t4 becomes 6.