y) xやyはレジスタやメモリを指す xとyのopの操作結果がxに代入される 殆どの命令はEFLAGSを実行ごとに更新する mov x, y # x ← y mov(x, ptr(y)) は x = *(uint64_t*)y; の意味(xが64ビットの場合) xがSIMDレジスタのときはvmovupsなどを使う 算術演算(add, sub, ...)や論理演算(and, xor, or, ...) add x, y # x ← x + y and x, y # x ← x & y 11 / 58
Flag) : x == yなら1 CF(Carry Flag) : x < yなら1 (unsigned) cf. sub x, yは演算結果がxに反映される(x ← x - y) テスト : test x, y x & yの結果をEFLAGSにセットするが演算結果はxに反映されない ZF : x & y == 0なら1 and x, yは同じ値をEFLAGSにセットしてxに反映される(x ← x & y) その他の命令 多くの演算はEFLAGSを変更するが主に使われるのは上記2種類 12 / 58
+ x * (0.69314697759916432673321651236619800329208374023437 + x * (0.24022242085378028852993281816452508792281150817871 + x * (5.5507337432541360711102385039339424110949039459229e-2 + x * (9.6715126395259202324306002651610469911247491836548e-3 + x * 1.326472719636653634089906717008489067666232585907e-3)))) 28 / 58
op and outputs a function that takes *args and outputs n unrolled op """ def fn(op, addrOffset=None): def gn(*args): Unroll(n, op, *args, addrOffset=addrOffset) return gn return fn # v0 = [zmm0, zmm1, ...], v1 = [zmm4, zmm5, ...], ... un = genUnrollFunc(n) # アンロール回数を指定する un(vmulps)(v0, v0, self.log2_e) un(vreduceps)(v1, v0, 0) # a = x - n un(vsubps)(v0, v0, v1) # n = x - a = round(x) 37 / 58