Files
symphony_stdlib/src/bit.asm
T

94 lines
1.8 KiB
NASM

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
; Calculates the parity of the value provided in the r1 register
; i.e. 0 means even bits set, 1 means odd bits set
; Based on Stanford's BitHacks
; Clobbers r2
pub parity:
; v ^= v >> 16;
lsr r2, r1, 16
xor r1, r1, r2
; v ^= v >> 8;
lsr r2, r1, 8
xor r1, r1, r2
; v ^= v >> 4;
lsr r2, r1, 4
xor r1, r1, r2
; v &= 0xf;
and r1, r1, 0x0F
; return (0x6996 >> v) & 1;
mov r2, 0x6996
lsr r1, r2, r1
and r1, r1, 0x01
jmp r13