| ... | ... | @@ -105,6 +105,17 @@ pub const Ghash = struct { |
| 105 | 105 | return product[0]; |
| 106 | 106 | } |
| 107 | 107 | |
| 108 | inline fn clmul_pmull(x: u64, y: u64) u64 { |
| 109 | const Vector = std.meta.Vector; |
| 110 | const product = asm ( |
| 111 | \\ pmull %[out].1q, %[x].1d, %[y].1d |
| 112 | : [out] "=w" (-> Vector(2, u64)) |
| 113 | : [x] "w" (@bitCast(Vector(2, u64), @as(u128, x))), |
| 114 | [y] "w" (@bitCast(Vector(2, u64), @as(u128, y))) |
| 115 | ); |
| 116 | return product[0]; |
| 117 | } |
| 118 | |
| 108 | 119 | fn clmul_soft(x: u64, y: u64) u64 { |
| 109 | 120 | const x0 = x & 0x1111111111111111; |
| 110 | 121 | const x1 = x & 0x2222222222222222; |
| ... | ... | @@ -127,7 +138,14 @@ pub const Ghash = struct { |
| 127 | 138 | |
| 128 | 139 | const has_pclmul = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .pclmul); |
| 129 | 140 | const has_avx = comptime std.Target.x86.featureSetHas(std.Target.current.cpu.features, .avx); |
| 130 | | const clmul = if (std.Target.current.cpu.arch == .x86_64 and has_pclmul and has_avx) clmul_pclmul else clmul_soft; |
| 141 | const has_armaes = comptime std.Target.aarch64.featureSetHas(std.Target.current.cpu.features, .aes); |
| 142 | const clmul = if (std.Target.current.cpu.arch == .x86_64 and has_pclmul and has_avx) impl: { |
| 143 | break :impl clmul_pclmul; |
| 144 | } else if (std.Target.current.cpu.arch == .aarch64 and has_armaes) impl: { |
| 145 | break :impl clmul_pmull; |
| 146 | } else impl: { |
| 147 | break :impl clmul_soft; |
| 148 | }; |
| 131 | 149 | |
| 132 | 150 | fn blocks(st: *Ghash, msg: []const u8) void { |
| 133 | 151 | assert(msg.len % 16 == 0); // GHASH blocks() expects full blocks |