51 lines
1.5 KiB
Plaintext
51 lines
1.5 KiB
Plaintext
include './base'
|
|
|
|
def pdep{x:u64, m:u64} = emit{u64, '_pdep_u64', x, m}
|
|
def pdep{x:u32, m:u32} = emit{u32, '_pdep_u32', x, m}
|
|
def pext{x:u64, m:u64} = emit{u64, '_pext_u64', x, m}
|
|
def pext{x:u32, m:u32} = emit{u32, '_pext_u32', x, m}
|
|
def popc{x:T & isint{T} & width{T}==64} = emit{u8, '__builtin_popcountll', x}
|
|
def popc{x:T & isint{T} & width{T}<=32} = emit{u8, '__builtin_popcount', x}
|
|
|
|
def comp8{w:*u64, X, r:*i8, l:u64} = {
|
|
@for(w in reinterpret{*u8,w} over i to cdiv{l,8}) {
|
|
pc:= popc{w}
|
|
store{reinterpret{*u64,r}, 0, pext{promote{u64,X{}}, pdep{promote{u64, w}, cast{u64,0x0101010101010101}}*255}}
|
|
r+= pc
|
|
}
|
|
}
|
|
|
|
def tab{n,l} = {
|
|
def m=n-1; def t=tab{m,l}
|
|
def k = (1<<l - 1) << (m*l)
|
|
merge{t, k+t}
|
|
}
|
|
def tab{n==0,l} = tup{0}
|
|
c16lut:*u64 = tab{4,16}
|
|
|
|
def comp16{w:*u64, X, r:*i16, l:u64} = {
|
|
@for(w in reinterpret{*u8,w} over i to cdiv{l,8}) {
|
|
def step{w} = {
|
|
pc:= popc{w}
|
|
store{reinterpret{*u64,r}, 0, pext{promote{u64,X{}}, load{c16lut, w}}}
|
|
r+= pc
|
|
}
|
|
step{w&15}
|
|
step{w>>4}
|
|
}
|
|
}
|
|
|
|
slash2{F, T}(w:*u64, x:*T, r:*T, l:u64) : void = {
|
|
xv:= reinterpret{*u64, x}
|
|
F{w, {} => {c:=load{xv,0}; xv+=1; c}, r, l}
|
|
}
|
|
|
|
slash1{F, T, iota, add}(w:*u64, r:*T, l:u64) : void = {
|
|
x:u64 = iota
|
|
F{w, {} => {c:=x; x+= add; c}, r, l}
|
|
}
|
|
|
|
'bmipopc_2slash8' = slash2{comp8, i8}
|
|
'bmipopc_2slash16' = slash2{comp16, i16}
|
|
'bmipopc_1slash8' = slash1{comp8, i8, 0x0706050403020100, 0x0808080808080808}
|
|
'bmipopc_1slash16' = slash1{comp16, i16, 0x0003000200010000, 0x0004000400040004} |