authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-02-11 22:29:31+01:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-02-12 05:25:07+01:00
logd89472787353bc69f6a13c80c6f576ee3471c1a8
tree0089bf301f5f42f09e386991354a817f015c908d
parent271505cfc8ed380d974e6f981e261d53884b627a

x86_64: implement `@byteSwap` of big integers


3 files changed, 91 insertions(+), 17 deletions(-)

lib/std/crypto/ecdsa.zig-1
......@@ -389,7 +389,6 @@ test "ECDSA - Basic operations over EcdsaP384Sha384" {
389389
390390test "ECDSA - Basic operations over Secp256k1" {
391391 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
392 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
393392
394393 const Scheme = EcdsaSecp256k1Sha256oSha256;
395394 const kp = try Scheme.KeyPair.create(null);
lib/std/crypto/pcurves/secp256k1.zig-1
......@@ -557,7 +557,6 @@ pub const AffineCoordinates = struct {
557557
558558test {
559559 if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest;
560 if (@import("builtin").zig_backend == .stage2_x86_64) return error.SkipZigTest;
561560
562561 _ = @import("tests/secp256k1.zig");
563562}
src/arch/x86_64/CodeGen.zig+91-15
......@@ -6164,17 +6164,16 @@ fn genByteSwap(
61646164 "TODO implement genByteSwap for {}",
61656165 .{src_ty.fmt(mod)},
61666166 );
6167 const abi_size: u32 = @intCast(src_ty.abiSize(mod));
6167
61686168 const src_lock = switch (src_mcv) {
61696169 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
61706170 else => null,
61716171 };
61726172 defer if (src_lock) |lock| self.register_manager.unlockReg(lock);
61736173
6174 const abi_size: u32 = @intCast(src_ty.abiSize(mod));
61746175 switch (abi_size) {
6175 else => return self.fail("TODO implement genByteSwap for {}", .{
6176 src_ty.fmt(mod),
6177 }),
6176 0 => unreachable,
61786177 1 => return if ((mem_ok or src_mcv.isRegister()) and
61796178 self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
61806179 src_mcv
......@@ -6223,6 +6222,83 @@ fn genByteSwap(
62236222 }
62246223 return .{ .register_pair = .{ dst_regs[1], dst_regs[0] } };
62256224 },
6225 else => {
6226 const limbs_len = math.divCeil(u32, abi_size, 8) catch unreachable;
6227
6228 const temp_regs =
6229 try self.register_manager.allocRegs(4, .{null} ** 4, abi.RegisterClass.gp);
6230 const temp_locks = self.register_manager.lockRegs(4, temp_regs);
6231 defer for (temp_locks) |temp_lock| if (temp_lock) |lock|
6232 self.register_manager.unlockReg(lock);
6233
6234 const dst_mcv = try self.allocRegOrMem(inst, false);
6235 try self.asmRegisterRegister(.{ ._, .xor }, temp_regs[0].to32(), temp_regs[0].to32());
6236 try self.asmRegisterImmediate(
6237 .{ ._, .mov },
6238 temp_regs[1].to32(),
6239 Immediate.u(limbs_len - 1),
6240 );
6241
6242 const loop: Mir.Inst.Index = @intCast(self.mir_instructions.len);
6243 try self.asmRegisterMemory(
6244 .{ ._, if (have_movbe) .movbe else .mov },
6245 temp_regs[2].to64(),
6246 .{
6247 .base = .{ .frame = dst_mcv.load_frame.index },
6248 .mod = .{ .rm = .{
6249 .size = .qword,
6250 .index = temp_regs[0].to64(),
6251 .scale = .@"8",
6252 .disp = dst_mcv.load_frame.off,
6253 } },
6254 },
6255 );
6256 try self.asmRegisterMemory(
6257 .{ ._, if (have_movbe) .movbe else .mov },
6258 temp_regs[3].to64(),
6259 .{
6260 .base = .{ .frame = dst_mcv.load_frame.index },
6261 .mod = .{ .rm = .{
6262 .size = .qword,
6263 .index = temp_regs[1].to64(),
6264 .scale = .@"8",
6265 .disp = dst_mcv.load_frame.off,
6266 } },
6267 },
6268 );
6269 if (!have_movbe) {
6270 try self.asmRegister(.{ ._, .bswap }, temp_regs[2].to64());
6271 try self.asmRegister(.{ ._, .bswap }, temp_regs[3].to64());
6272 }
6273 try self.asmMemoryRegister(.{ ._, .mov }, .{
6274 .base = .{ .frame = dst_mcv.load_frame.index },
6275 .mod = .{ .rm = .{
6276 .size = .qword,
6277 .index = temp_regs[0].to64(),
6278 .scale = .@"8",
6279 .disp = dst_mcv.load_frame.off,
6280 } },
6281 }, temp_regs[3].to64());
6282 try self.asmMemoryRegister(.{ ._, .mov }, .{
6283 .base = .{ .frame = dst_mcv.load_frame.index },
6284 .mod = .{ .rm = .{
6285 .size = .qword,
6286 .index = temp_regs[1].to64(),
6287 .scale = .@"8",
6288 .disp = dst_mcv.load_frame.off,
6289 } },
6290 }, temp_regs[2].to64());
6291 if (self.hasFeature(.slow_incdec)) {
6292 try self.asmRegisterImmediate(.{ ._, .add }, temp_regs[0].to32(), Immediate.u(1));
6293 try self.asmRegisterImmediate(.{ ._, .sub }, temp_regs[1].to32(), Immediate.u(1));
6294 } else {
6295 try self.asmRegister(.{ ._, .inc }, temp_regs[0].to32());
6296 try self.asmRegister(.{ ._, .dec }, temp_regs[1].to32());
6297 }
6298 try self.asmRegisterRegister(.{ ._, .cmp }, temp_regs[0].to32(), temp_regs[1].to32());
6299 _ = try self.asmJccReloc(.be, loop);
6300 return dst_mcv;
6301 },
62266302 }
62276303
62286304 const dst_mcv: MCValue = if (mem_ok and have_movbe and src_mcv.isRegister())
......@@ -6248,20 +6324,20 @@ fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
62486324 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
62496325
62506326 const src_ty = self.typeOf(ty_op.operand);
6251 const abi_size: u32 = @intCast(src_ty.abiSize(mod));
6252 const bit_size: u32 = @intCast(src_ty.bitSize(mod));
6327 const src_bits: u32 = @intCast(src_ty.bitSize(mod));
62536328 const src_mcv = try self.resolveInst(ty_op.operand);
62546329
62556330 const dst_mcv = try self.genByteSwap(inst, src_ty, src_mcv, true);
6256
6257 const extra_bits = abi_size * 8 - bit_size;
6258 const signedness: std.builtin.Signedness =
6259 if (src_ty.isAbiInt(mod)) src_ty.intInfo(mod).signedness else .unsigned;
6260 if (extra_bits > 0) try self.genShiftBinOpMir(switch (signedness) {
6261 .signed => .{ ._r, .sa },
6262 .unsigned => .{ ._r, .sh },
6263 }, src_ty, dst_mcv, Type.u8, .{ .immediate = extra_bits });
6264
6331 try self.genShiftBinOpMir(
6332 .{ ._r, switch (if (src_ty.isAbiInt(mod)) src_ty.intInfo(mod).signedness else .unsigned) {
6333 .signed => .sa,
6334 .unsigned => .sh,
6335 } },
6336 src_ty,
6337 dst_mcv,
6338 if (src_bits > 256) Type.u16 else Type.u8,
6339 .{ .immediate = src_ty.abiSize(mod) * 8 - src_bits },
6340 );
62656341 return self.finishAir(inst, dst_mcv, .{ ty_op.operand, .none, .none });
62666342}
62676343