pub rotate_left: ; (r1 >> r2) | (r1 << (32 - r2)) sub r3, zr, r2 add r3, r3, 32 lsr r3, r1, r3 lsl r1, r1, r2 or r1, r1, r3 jmp r13 pub rotate_right: ; (r1 << r2) | (r1 >> (32 - r2)) sub r3, zr, r2 add r3, r3, 32 lsl r3, r1, r3 lsr r1, r1, r2 or r1, r1, r3 jmp r13 pub clz: ; special case mov r4, 0 ; since we start the loop by shifting r2 load twice the value we need mov r2, 32 mov r3, r1 ; divide and conquer algorithm clz_loop: ; next finer step lsr r2, r2, 1 ; abort if there is no finer step cmp r2, 0 je clz_end ; see if there are still some 1 bits left with this additional shift lsr r3, r3, r2 add r4, r4, r2 cmp r3, 0 jne clz_loop ; undo shift if it resulted in zero sub r4, r4, r2 lsr r3, r1, r4 jmp clz_loop clz_end: ; we calculated the position of the last 1 from the least significant side ; inverse is what we want (position of last 0 from most significant side) mov r1, 31 sub r1, r1, r4 jmp r13 pub popc: mov r2, 0x0101 ; load mask of 0x01010101 lsl r2, r2, 16 or r2, r2, 0x0101 mov r3, 8 ; bits in byte mov r4, 0 ; pop count of each byte popc_loop: and r5, r1, r2 ; extract least significant bit of byte add r4, r4, r5 lsr r1, r1, 1 ; cycle through bits sub r3, r3, 1 cmp r3, 0 jg popc_loop ; sum up bytes lsr r2, r4, 8 add r4, r4, r2 lsr r2, r4, 16 add r4, r4, r2 and r1, r4, 0xFF ; mask out end result in lowest byte jmp r13