authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-07 09:06:12-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-08 07:36:20-04:00
log057139fda575e0e6038b821256a45669cd70a073
tree38b4efefb2f63fdb4a6c369caf38d025810d3dd9
parentea957c4cff77f045108863cb5552b3511cb455c1

x86_64: implement binary operations for float vectors


5 files changed, 651 insertions(+), 290 deletions(-)

src/arch/x86_64/CodeGen.zig+377-265
......@@ -1176,6 +1176,21 @@ fn asmRegisterRegisterRegister(
11761176 });
11771177}
11781178
1179fn asmRegisterRegisterRegisterImmediate(
1180 self: *Self,
1181 tag: Mir.Inst.Tag,
1182 reg1: Register,
1183 reg2: Register,
1184 reg3: Register,
1185 imm: Immediate,
1186) !void {
1187 _ = try self.addInst(.{
1188 .tag = tag,
1189 .ops = .rrri,
1190 .data = .{ .rrri = .{ .r1 = reg1, .r2 = reg2, .r3 = reg3, .i = @intCast(u8, imm.unsigned) } },
1191 });
1192}
1193
11791194fn asmRegisterRegisterImmediate(
11801195 self: *Self,
11811196 tag: Mir.Inst.Tag,
......@@ -2310,20 +2325,31 @@ fn airFptrunc(self: *Self, inst: Air.Inst.Index) !void {
23102325 }),
23112326 }
23122327 } else if (src_bits == 64 and dst_bits == 32) {
2313 if (self.hasFeature(.avx)) if (src_mcv.isRegister()) try self.asmRegisterRegisterRegister(
2328 if (self.hasFeature(.avx)) if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
23142329 .vcvtsd2ss,
23152330 dst_reg,
23162331 dst_reg,
2317 src_mcv.getReg().?.to128(),
2318 ) else try self.asmRegisterRegisterMemory(
2332 src_mcv.mem(.qword),
2333 ) else try self.asmRegisterRegisterRegister(
23192334 .vcvtsd2ss,
23202335 dst_reg,
23212336 dst_reg,
2337 (if (src_mcv.isRegister())
2338 src_mcv.getReg().?
2339 else
2340 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
2341 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
2342 .cvtsd2ss,
2343 dst_reg,
23222344 src_mcv.mem(.qword),
2323 ) else if (src_mcv.isRegister())
2324 try self.asmRegisterRegister(.cvtsd2ss, dst_reg, src_mcv.getReg().?.to128())
2325 else
2326 try self.asmRegisterMemory(.cvtsd2ss, dst_reg, src_mcv.mem(.qword));
2345 ) else try self.asmRegisterRegister(
2346 .cvtsd2ss,
2347 dst_reg,
2348 (if (src_mcv.isRegister())
2349 src_mcv.getReg().?
2350 else
2351 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
2352 );
23272353 } else return self.fail("TODO implement airFptrunc from {} to {}", .{
23282354 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
23292355 });
......@@ -2360,20 +2386,31 @@ fn airFpext(self: *Self, inst: Air.Inst.Index) !void {
23602386 }),
23612387 }
23622388 } else if (src_bits == 32 and dst_bits == 64) {
2363 if (self.hasFeature(.avx)) if (src_mcv.isRegister()) try self.asmRegisterRegisterRegister(
2389 if (self.hasFeature(.avx)) if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
23642390 .vcvtss2sd,
23652391 dst_reg,
23662392 dst_reg,
2367 src_mcv.getReg().?.to128(),
2368 ) else try self.asmRegisterRegisterMemory(
2393 src_mcv.mem(.dword),
2394 ) else try self.asmRegisterRegisterRegister(
23692395 .vcvtss2sd,
23702396 dst_reg,
23712397 dst_reg,
2398 (if (src_mcv.isRegister())
2399 src_mcv.getReg().?
2400 else
2401 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
2402 ) else if (src_mcv.isMemory()) try self.asmRegisterMemory(
2403 .cvtss2sd,
2404 dst_reg,
23722405 src_mcv.mem(.dword),
2373 ) else if (src_mcv.isRegister())
2374 try self.asmRegisterRegister(.cvtss2sd, dst_reg, src_mcv.getReg().?.to128())
2375 else
2376 try self.asmRegisterMemory(.cvtss2sd, dst_reg, src_mcv.mem(.dword));
2406 ) else try self.asmRegisterRegister(
2407 .cvtss2sd,
2408 dst_reg,
2409 (if (src_mcv.isRegister())
2410 src_mcv.getReg().?
2411 else
2412 try self.copyToTmpRegister(src_ty, src_mcv)).to128(),
2413 );
23772414 } else return self.fail("TODO implement airFpext from {} to {}", .{
23782415 src_ty.fmt(self.bin_file.options.module.?), dst_ty.fmt(self.bin_file.options.module.?),
23792416 });
......@@ -4532,7 +4569,7 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
45324569 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
45334570
45344571 const result: MCValue = result: {
4535 const tag = if (@as(?Mir.Inst.Tag, switch (ty.zigTypeTag()) {
4572 const mir_tag = if (@as(?Mir.Inst.Tag, switch (ty.zigTypeTag()) {
45364573 .Float => switch (ty.floatBits(self.target.*)) {
45374574 16 => if (self.hasFeature(.f16c)) {
45384575 const mat_src_reg = if (src_mcv.isRegister())
......@@ -4558,11 +4595,14 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
45584595 .Float => switch (ty.childType().floatBits(self.target.*)) {
45594596 16 => if (self.hasFeature(.f16c)) switch (ty.vectorLen()) {
45604597 1 => {
4561 const mat_src_reg = if (src_mcv.isRegister())
4562 src_mcv.getReg().?
4563 else
4564 try self.copyToTmpRegister(ty, src_mcv);
4565 try self.asmRegisterRegister(.vcvtph2ps, dst_reg, mat_src_reg.to128());
4598 try self.asmRegisterRegister(
4599 .vcvtph2ps,
4600 dst_reg,
4601 (if (src_mcv.isRegister())
4602 src_mcv.getReg().?
4603 else
4604 try self.copyToTmpRegister(ty, src_mcv)).to128(),
4605 );
45664606 try self.asmRegisterRegisterRegister(.vsqrtss, dst_reg, dst_reg, dst_reg);
45674607 try self.asmRegisterRegisterImmediate(
45684608 .vcvtps2ph,
......@@ -4574,16 +4614,19 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
45744614 },
45754615 2...8 => {
45764616 const wide_reg = registerAlias(dst_reg, abi_size * 2);
4577 if (src_mcv.isRegister()) try self.asmRegisterRegister(
4578 .vcvtph2ps,
4579 wide_reg,
4580 src_mcv.getReg().?.to128(),
4581 ) else try self.asmRegisterMemory(
4617 if (src_mcv.isMemory()) try self.asmRegisterMemory(
45824618 .vcvtph2ps,
45834619 wide_reg,
45844620 src_mcv.mem(Memory.PtrSize.fromSize(
45854621 @intCast(u32, @divExact(wide_reg.bitSize(), 16)),
45864622 )),
4623 ) else try self.asmRegisterRegister(
4624 .vcvtph2ps,
4625 wide_reg,
4626 (if (src_mcv.isRegister())
4627 src_mcv.getReg().?
4628 else
4629 try self.copyToTmpRegister(ty, src_mcv)).to128(),
45874630 );
45884631 try self.asmRegisterRegister(.vsqrtps, wide_reg, wide_reg);
45894632 try self.asmRegisterRegisterImmediate(
......@@ -4617,26 +4660,32 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
46174660 })) |tag| tag else return self.fail("TODO implement airSqrt for {}", .{
46184661 ty.fmt(self.bin_file.options.module.?),
46194662 });
4620 switch (tag) {
4621 .vsqrtss, .vsqrtsd => if (src_mcv.isRegister()) try self.asmRegisterRegisterRegister(
4622 tag,
4663 switch (mir_tag) {
4664 .vsqrtss, .vsqrtsd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
4665 mir_tag,
46234666 dst_reg,
46244667 dst_reg,
4625 registerAlias(src_mcv.getReg().?, abi_size),
4626 ) else try self.asmRegisterRegisterMemory(
4627 tag,
4668 src_mcv.mem(Memory.PtrSize.fromSize(abi_size)),
4669 ) else try self.asmRegisterRegisterRegister(
4670 mir_tag,
46284671 dst_reg,
46294672 dst_reg,
4630 src_mcv.mem(Memory.PtrSize.fromSize(abi_size)),
4673 registerAlias(if (src_mcv.isRegister())
4674 src_mcv.getReg().?
4675 else
4676 try self.copyToTmpRegister(ty, src_mcv), abi_size),
46314677 ),
4632 else => if (src_mcv.isRegister()) try self.asmRegisterRegister(
4633 tag,
4634 dst_reg,
4635 registerAlias(src_mcv.getReg().?, abi_size),
4636 ) else try self.asmRegisterMemory(
4637 tag,
4678 else => if (src_mcv.isMemory()) try self.asmRegisterMemory(
4679 mir_tag,
46384680 dst_reg,
46394681 src_mcv.mem(Memory.PtrSize.fromSize(abi_size)),
4682 ) else try self.asmRegisterRegister(
4683 mir_tag,
4684 dst_reg,
4685 registerAlias(if (src_mcv.isRegister())
4686 src_mcv.getReg().?
4687 else
4688 try self.copyToTmpRegister(ty, src_mcv), abi_size),
46404689 ),
46414690 }
46424691 break :result dst_mcv;
......@@ -5800,25 +5849,22 @@ fn genMulDivBinOp(
58005849 }
58015850}
58025851
5803/// Result is always a register.
58045852fn genBinOp(
58055853 self: *Self,
58065854 maybe_inst: ?Air.Inst.Index,
5807 tag: Air.Inst.Tag,
5855 air_tag: Air.Inst.Tag,
58085856 lhs_air: Air.Inst.Ref,
58095857 rhs_air: Air.Inst.Ref,
58105858) !MCValue {
5811 const lhs = try self.resolveInst(lhs_air);
5812 const rhs = try self.resolveInst(rhs_air);
5859 const lhs_mcv = try self.resolveInst(lhs_air);
5860 const rhs_mcv = try self.resolveInst(rhs_air);
58135861 const lhs_ty = self.air.typeOf(lhs_air);
58145862 const rhs_ty = self.air.typeOf(rhs_air);
5815 if (lhs_ty.zigTypeTag() == .Vector) {
5816 return self.fail("TODO implement genBinOp for {}", .{lhs_ty.fmt(self.bin_file.options.module.?)});
5817 }
5863 const abi_size = @intCast(u32, lhs_ty.abiSize(self.target.*));
58185864
5819 switch (lhs) {
5865 switch (lhs_mcv) {
58205866 .immediate => |imm| switch (imm) {
5821 0 => switch (tag) {
5867 0 => switch (air_tag) {
58225868 .sub, .subwrap => return self.genUnOp(maybe_inst, .neg, rhs_air),
58235869 else => {},
58245870 },
......@@ -5827,9 +5873,10 @@ fn genBinOp(
58275873 else => {},
58285874 }
58295875
5830 const is_commutative = switch (tag) {
5876 const is_commutative = switch (air_tag) {
58315877 .add,
58325878 .addwrap,
5879 .mul,
58335880 .bool_or,
58345881 .bit_or,
58355882 .bool_and,
......@@ -5841,48 +5888,42 @@ fn genBinOp(
58415888
58425889 else => false,
58435890 };
5844 const dst_mem_ok = switch (tag) {
5845 .add,
5846 .addwrap,
5847 .sub,
5848 .subwrap,
5849 .mul,
5850 .div_float,
5851 .div_exact,
5852 .div_trunc,
5853 .div_floor,
5854 => !lhs_ty.isRuntimeFloat(),
5855
5856 else => true,
5891 const vec_op = switch (lhs_ty.zigTypeTag()) {
5892 else => false,
5893 .Float, .Vector => true,
58575894 };
58585895
5859 const lhs_lock: ?RegisterLock = switch (lhs) {
5896 const lhs_lock: ?RegisterLock = switch (lhs_mcv) {
58605897 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
58615898 else => null,
58625899 };
58635900 defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock);
58645901
5865 const rhs_lock: ?RegisterLock = switch (rhs) {
5902 const rhs_lock: ?RegisterLock = switch (rhs_mcv) {
58665903 .register => |reg| self.register_manager.lockReg(reg),
58675904 else => null,
58685905 };
58695906 defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock);
58705907
5871 var flipped: bool = false;
5908 var flipped = false;
5909 var copied_to_dst = true;
58725910 const dst_mcv: MCValue = dst: {
58735911 if (maybe_inst) |inst| {
5874 if ((dst_mem_ok or lhs.isRegister()) and self.reuseOperand(inst, lhs_air, 0, lhs)) {
5875 break :dst lhs;
5912 if ((!vec_op or lhs_mcv.isRegister()) and self.reuseOperand(inst, lhs_air, 0, lhs_mcv)) {
5913 break :dst lhs_mcv;
58765914 }
5877 if (is_commutative and (dst_mem_ok or rhs.isRegister()) and
5878 self.reuseOperand(inst, rhs_air, 1, rhs))
5915 if (is_commutative and (!vec_op or rhs_mcv.isRegister()) and
5916 self.reuseOperand(inst, rhs_air, 1, rhs_mcv))
58795917 {
58805918 flipped = true;
5881 break :dst rhs;
5919 break :dst rhs_mcv;
58825920 }
58835921 }
58845922 const dst_mcv = try self.allocRegOrMemAdvanced(lhs_ty, maybe_inst, true);
5885 try self.genCopy(lhs_ty, dst_mcv, lhs);
5923 if (vec_op and lhs_mcv.isRegister() and self.hasFeature(.avx))
5924 copied_to_dst = false
5925 else
5926 try self.genCopy(lhs_ty, dst_mcv, lhs_mcv);
58865927 break :dst dst_mcv;
58875928 };
58885929 const dst_lock: ?RegisterLock = switch (dst_mcv) {
......@@ -5891,160 +5932,47 @@ fn genBinOp(
58915932 };
58925933 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
58935934
5894 const src_mcv = if (flipped) lhs else rhs;
5895 switch (tag) {
5896 .add,
5897 .addwrap,
5898 => try self.genBinOpMir(switch (lhs_ty.zigTypeTag()) {
5899 else => .add,
5900 .Float => switch (lhs_ty.floatBits(self.target.*)) {
5901 32 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse))
5902 .addss
5903 else
5904 return self.fail("TODO implement genBinOp for {s} {} without sse", .{
5905 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
5906 }),
5907 64 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse2))
5908 .addsd
5909 else
5910 return self.fail("TODO implement genBinOp for {s} {} without sse2", .{
5911 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
5912 }),
5913 else => return self.fail("TODO implement genBinOp for {s} {}", .{
5914 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
5915 }),
5916 },
5917 }, lhs_ty, dst_mcv, src_mcv),
5918
5919 .sub,
5920 .subwrap,
5921 => try self.genBinOpMir(switch (lhs_ty.zigTypeTag()) {
5922 else => .sub,
5923 .Float => switch (lhs_ty.floatBits(self.target.*)) {
5924 32 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse))
5925 .subss
5926 else
5927 return self.fail("TODO implement genBinOp for {s} {} without sse", .{
5928 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
5929 }),
5930 64 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse2))
5931 .subsd
5932 else
5933 return self.fail("TODO implement genBinOp for {s} {} without sse2", .{
5934 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
5935 }),
5936 else => return self.fail("TODO implement genBinOp for {s} {}", .{
5937 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
5938 }),
5939 },
5940 }, lhs_ty, dst_mcv, src_mcv),
5941
5942 .mul => try self.genBinOpMir(switch (lhs_ty.zigTypeTag()) {
5943 else => return self.fail("TODO implement genBinOp for {s} {}", .{
5944 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
5945 }),
5946 .Float => switch (lhs_ty.floatBits(self.target.*)) {
5947 32 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse))
5948 .mulss
5949 else
5950 return self.fail("TODO implement genBinOp for {s} {} without sse", .{
5951 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
5952 }),
5953 64 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse2))
5954 .mulsd
5955 else
5956 return self.fail("TODO implement genBinOp for {s} {} without sse2", .{
5957 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
5958 }),
5959 else => return self.fail("TODO implement genBinOp for {s} {}", .{
5960 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
5961 }),
5962 },
5963 }, lhs_ty, dst_mcv, src_mcv),
5935 const src_mcv = if (flipped) lhs_mcv else rhs_mcv;
5936 if (!vec_op) {
5937 switch (air_tag) {
5938 .add,
5939 .addwrap,
5940 => try self.genBinOpMir(.add, lhs_ty, dst_mcv, src_mcv),
59645941
5965 .div_float,
5966 .div_exact,
5967 .div_trunc,
5968 .div_floor,
5969 => {
5970 try self.genBinOpMir(switch (lhs_ty.zigTypeTag()) {
5971 else => return self.fail("TODO implement genBinOp for {s} {}", .{
5972 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
5973 }),
5974 .Float => switch (lhs_ty.floatBits(self.target.*)) {
5975 32 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse))
5976 .divss
5977 else
5978 return self.fail("TODO implement genBinOp for {s} {} without sse", .{
5979 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
5980 }),
5981 64 => if (Target.x86.featureSetHas(self.target.cpu.features, .sse2))
5982 .divsd
5983 else
5984 return self.fail("TODO implement genBinOp for {s} {} without sse2", .{
5985 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
5986 }),
5987 else => return self.fail("TODO implement genBinOp for {s} {}", .{
5988 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
5989 }),
5990 },
5991 }, lhs_ty, dst_mcv, src_mcv);
5992 switch (tag) {
5993 .div_float,
5994 .div_exact,
5995 => {},
5996 .div_trunc,
5997 .div_floor,
5998 => if (self.hasFeature(.sse4_1)) {
5999 const abi_size = @intCast(u32, lhs_ty.abiSize(self.target.*));
6000 const dst_alias = registerAlias(dst_mcv.register, abi_size);
6001 try self.asmRegisterRegisterImmediate(switch (lhs_ty.floatBits(self.target.*)) {
6002 32 => .roundss,
6003 64 => .roundsd,
6004 else => unreachable,
6005 }, dst_alias, dst_alias, Immediate.u(switch (tag) {
6006 .div_trunc => 0b1_0_11,
6007 .div_floor => 0b1_0_01,
6008 else => unreachable,
6009 }));
6010 } else return self.fail("TODO implement genBinOp for {s} {} without sse4_1", .{
6011 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
6012 }),
6013 else => unreachable,
6014 }
6015 },
5942 .sub,
5943 .subwrap,
5944 => try self.genBinOpMir(.sub, lhs_ty, dst_mcv, src_mcv),
60165945
6017 .ptr_add,
6018 .ptr_sub,
6019 => {
6020 const tmp_reg = try self.copyToTmpRegister(rhs_ty, src_mcv);
6021 const tmp_mcv = MCValue{ .register = tmp_reg };
6022 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
6023 defer self.register_manager.unlockReg(tmp_lock);
5946 .ptr_add,
5947 .ptr_sub,
5948 => {
5949 const tmp_reg = try self.copyToTmpRegister(rhs_ty, src_mcv);
5950 const tmp_mcv = MCValue{ .register = tmp_reg };
5951 const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
5952 defer self.register_manager.unlockReg(tmp_lock);
60245953
6025 const elem_size = lhs_ty.elemType2().abiSize(self.target.*);
6026 try self.genIntMulComplexOpMir(rhs_ty, tmp_mcv, .{ .immediate = elem_size });
6027 try self.genBinOpMir(switch (tag) {
6028 .ptr_add => .add,
6029 .ptr_sub => .sub,
6030 else => unreachable,
6031 }, lhs_ty, dst_mcv, tmp_mcv);
6032 },
5954 const elem_size = lhs_ty.elemType2().abiSize(self.target.*);
5955 try self.genIntMulComplexOpMir(rhs_ty, tmp_mcv, .{ .immediate = elem_size });
5956 try self.genBinOpMir(switch (air_tag) {
5957 .ptr_add => .add,
5958 .ptr_sub => .sub,
5959 else => unreachable,
5960 }, lhs_ty, dst_mcv, tmp_mcv);
5961 },
60335962
6034 .bool_or,
6035 .bit_or,
6036 => try self.genBinOpMir(.@"or", lhs_ty, dst_mcv, src_mcv),
5963 .bool_or,
5964 .bit_or,
5965 => try self.genBinOpMir(.@"or", lhs_ty, dst_mcv, src_mcv),
60375966
6038 .bool_and,
6039 .bit_and,
6040 => try self.genBinOpMir(.@"and", lhs_ty, dst_mcv, src_mcv),
5967 .bool_and,
5968 .bit_and,
5969 => try self.genBinOpMir(.@"and", lhs_ty, dst_mcv, src_mcv),
60415970
6042 .xor => try self.genBinOpMir(.xor, lhs_ty, dst_mcv, src_mcv),
5971 .xor => try self.genBinOpMir(.xor, lhs_ty, dst_mcv, src_mcv),
60435972
6044 .min,
6045 .max,
6046 => switch (lhs_ty.zigTypeTag()) {
6047 .Int => {
5973 .min,
5974 .max,
5975 => {
60485976 const mat_src_mcv: MCValue = if (switch (src_mcv) {
60495977 .immediate,
60505978 .eflags,
......@@ -6070,12 +5998,12 @@ fn genBinOp(
60705998
60715999 const int_info = lhs_ty.intInfo(self.target.*);
60726000 const cc: Condition = switch (int_info.signedness) {
6073 .unsigned => switch (tag) {
6001 .unsigned => switch (air_tag) {
60746002 .min => .a,
60756003 .max => .b,
60766004 else => unreachable,
60776005 },
6078 .signed => switch (tag) {
6006 .signed => switch (air_tag) {
60796007 .min => .g,
60806008 .max => .l,
60816009 else => unreachable,
......@@ -6134,26 +6062,222 @@ fn genBinOp(
61346062 }
61356063 try self.genCopy(lhs_ty, dst_mcv, .{ .register = tmp_reg });
61366064 },
6137 .Float => try self.genBinOpMir(switch (lhs_ty.floatBits(self.target.*)) {
6138 32 => switch (tag) {
6139 .min => .minss,
6140 .max => .maxss,
6141 else => unreachable,
6142 },
6143 64 => switch (tag) {
6144 .min => .minsd,
6145 .max => .maxsd,
6146 else => unreachable,
6147 },
6148 else => return self.fail("TODO implement genBinOp for {s} {}", .{
6149 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
6150 }),
6151 }, lhs_ty, dst_mcv, src_mcv),
6065
61526066 else => return self.fail("TODO implement genBinOp for {s} {}", .{
6153 @tagName(tag), lhs_ty.fmt(self.bin_file.options.module.?),
6067 @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?),
61546068 }),
6155 },
6069 }
6070 return dst_mcv;
6071 }
61566072
6073 const mir_tag = if (@as(?Mir.Inst.Tag, switch (lhs_ty.zigTypeTag()) {
6074 else => unreachable,
6075 .Float => switch (lhs_ty.floatBits(self.target.*)) {
6076 32 => switch (air_tag) {
6077 .add => if (self.hasFeature(.avx)) .vaddss else .addss,
6078 .sub => if (self.hasFeature(.avx)) .vsubss else .subss,
6079 .mul => if (self.hasFeature(.avx)) .vmulss else .mulss,
6080 .div_float,
6081 .div_trunc,
6082 .div_floor,
6083 .div_exact,
6084 => if (self.hasFeature(.avx)) .vdivss else .divss,
6085 .max => if (self.hasFeature(.avx)) .vmaxss else .maxss,
6086 .min => if (self.hasFeature(.avx)) .vminss else .minss,
6087 else => unreachable,
6088 },
6089 64 => switch (air_tag) {
6090 .add => if (self.hasFeature(.avx)) .vaddsd else .addsd,
6091 .sub => if (self.hasFeature(.avx)) .vsubsd else .subsd,
6092 .mul => if (self.hasFeature(.avx)) .vmulsd else .mulsd,
6093 .div_float,
6094 .div_trunc,
6095 .div_floor,
6096 .div_exact,
6097 => if (self.hasFeature(.avx)) .vdivsd else .divsd,
6098 .max => if (self.hasFeature(.avx)) .vmaxsd else .maxsd,
6099 .min => if (self.hasFeature(.avx)) .vminsd else .minsd,
6100 else => unreachable,
6101 },
6102 16, 80, 128 => null,
6103 else => unreachable,
6104 },
6105 .Vector => switch (lhs_ty.childType().zigTypeTag()) {
6106 else => null,
6107 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {
6108 32 => switch (lhs_ty.vectorLen()) {
6109 1 => switch (air_tag) {
6110 .add => if (self.hasFeature(.avx)) .vaddss else .addss,
6111 .sub => if (self.hasFeature(.avx)) .vsubss else .subss,
6112 .mul => if (self.hasFeature(.avx)) .vmulss else .mulss,
6113 .div_float,
6114 .div_trunc,
6115 .div_floor,
6116 .div_exact,
6117 => if (self.hasFeature(.avx)) .vdivss else .divss,
6118 .max => if (self.hasFeature(.avx)) .vmaxss else .maxss,
6119 .min => if (self.hasFeature(.avx)) .vminss else .minss,
6120 else => unreachable,
6121 },
6122 2...4 => switch (air_tag) {
6123 .add => if (self.hasFeature(.avx)) .vaddps else .addps,
6124 .sub => if (self.hasFeature(.avx)) .vsubps else .subps,
6125 .mul => if (self.hasFeature(.avx)) .vmulps else .mulps,
6126 .div_float,
6127 .div_trunc,
6128 .div_floor,
6129 .div_exact,
6130 => if (self.hasFeature(.avx)) .vdivps else .divps,
6131 .max => if (self.hasFeature(.avx)) .vmaxps else .maxps,
6132 .min => if (self.hasFeature(.avx)) .vminps else .minps,
6133 else => unreachable,
6134 },
6135 5...8 => if (self.hasFeature(.avx)) switch (air_tag) {
6136 .add => .vaddps,
6137 .sub => .vsubps,
6138 .mul => .vmulps,
6139 .div_float, .div_trunc, .div_floor, .div_exact => .vdivps,
6140 .max => .vmaxps,
6141 .min => .vminps,
6142 else => unreachable,
6143 } else null,
6144 else => null,
6145 },
6146 64 => switch (lhs_ty.vectorLen()) {
6147 1 => switch (air_tag) {
6148 .add => if (self.hasFeature(.avx)) .vaddsd else .addsd,
6149 .sub => if (self.hasFeature(.avx)) .vsubsd else .subsd,
6150 .mul => if (self.hasFeature(.avx)) .vmulsd else .mulsd,
6151 .div_float,
6152 .div_trunc,
6153 .div_floor,
6154 .div_exact,
6155 => if (self.hasFeature(.avx)) .vdivsd else .divsd,
6156 .max => if (self.hasFeature(.avx)) .vmaxsd else .maxsd,
6157 .min => if (self.hasFeature(.avx)) .vminsd else .minsd,
6158 else => unreachable,
6159 },
6160 2 => switch (air_tag) {
6161 .add => if (self.hasFeature(.avx)) .vaddpd else .addpd,
6162 .sub => if (self.hasFeature(.avx)) .vsubpd else .subpd,
6163 .mul => if (self.hasFeature(.avx)) .vmulpd else .mulpd,
6164 .div_float,
6165 .div_trunc,
6166 .div_floor,
6167 .div_exact,
6168 => if (self.hasFeature(.avx)) .vdivpd else .divpd,
6169 .max => if (self.hasFeature(.avx)) .vmaxpd else .maxpd,
6170 .min => if (self.hasFeature(.avx)) .vminpd else .minpd,
6171 else => unreachable,
6172 },
6173 3...4 => if (self.hasFeature(.avx)) switch (air_tag) {
6174 .add => .vaddpd,
6175 .sub => .vsubpd,
6176 .mul => .vmulpd,
6177 .div_float, .div_trunc, .div_floor, .div_exact => .vdivpd,
6178 .max => .vmaxpd,
6179 .min => .vminpd,
6180 else => unreachable,
6181 } else null,
6182 else => null,
6183 },
6184 16, 80, 128 => null,
6185 else => unreachable,
6186 },
6187 },
6188 })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{
6189 @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?),
6190 });
6191 const dst_alias = registerAlias(dst_mcv.getReg().?, abi_size);
6192 if (self.hasFeature(.avx)) {
6193 const src1_alias =
6194 if (copied_to_dst) dst_alias else registerAlias(lhs_mcv.getReg().?, abi_size);
6195 if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
6196 mir_tag,
6197 dst_alias,
6198 src1_alias,
6199 src_mcv.mem(Memory.PtrSize.fromSize(abi_size)),
6200 ) else try self.asmRegisterRegisterRegister(
6201 mir_tag,
6202 dst_alias,
6203 src1_alias,
6204 registerAlias(if (src_mcv.isRegister())
6205 src_mcv.getReg().?
6206 else
6207 try self.copyToTmpRegister(rhs_ty, src_mcv), abi_size),
6208 );
6209 } else {
6210 assert(copied_to_dst);
6211 if (src_mcv.isMemory()) try self.asmRegisterMemory(
6212 mir_tag,
6213 dst_alias,
6214 src_mcv.mem(Memory.PtrSize.fromSize(abi_size)),
6215 ) else try self.asmRegisterRegister(
6216 mir_tag,
6217 dst_alias,
6218 registerAlias(if (src_mcv.isRegister())
6219 src_mcv.getReg().?
6220 else
6221 try self.copyToTmpRegister(rhs_ty, src_mcv), abi_size),
6222 );
6223 }
6224 switch (air_tag) {
6225 .add, .sub, .mul, .div_float, .div_exact => {},
6226 .div_trunc, .div_floor => if (self.hasFeature(.sse4_1)) {
6227 const round_tag = if (@as(?Mir.Inst.Tag, switch (lhs_ty.zigTypeTag()) {
6228 .Float => switch (lhs_ty.floatBits(self.target.*)) {
6229 32 => if (self.hasFeature(.avx)) .vroundss else .roundss,
6230 64 => if (self.hasFeature(.avx)) .vroundsd else .roundsd,
6231 16, 80, 128 => null,
6232 else => unreachable,
6233 },
6234 .Vector => switch (lhs_ty.childType().zigTypeTag()) {
6235 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {
6236 32 => switch (lhs_ty.vectorLen()) {
6237 1 => if (self.hasFeature(.avx)) .vroundss else .roundss,
6238 2...4 => if (self.hasFeature(.avx)) .vroundps else .roundps,
6239 5...8 => if (self.hasFeature(.avx)) .vroundps else null,
6240 else => null,
6241 },
6242 64 => switch (lhs_ty.vectorLen()) {
6243 1 => if (self.hasFeature(.avx)) .vroundsd else .roundsd,
6244 2 => if (self.hasFeature(.avx)) .vroundpd else .roundpd,
6245 3...4 => if (self.hasFeature(.avx)) .vroundpd else null,
6246 else => null,
6247 },
6248 16, 80, 128 => null,
6249 else => unreachable,
6250 },
6251 else => null,
6252 },
6253 else => unreachable,
6254 })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{
6255 @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?),
6256 });
6257 const round_mode = Immediate.u(switch (air_tag) {
6258 .div_trunc => 0b1_0_11,
6259 .div_floor => 0b1_0_01,
6260 else => unreachable,
6261 });
6262 switch (round_tag) {
6263 .vroundss, .vroundsd => try self.asmRegisterRegisterRegisterImmediate(
6264 round_tag,
6265 dst_alias,
6266 dst_alias,
6267 dst_alias,
6268 round_mode,
6269 ),
6270 else => try self.asmRegisterRegisterImmediate(
6271 round_tag,
6272 dst_alias,
6273 dst_alias,
6274 round_mode,
6275 ),
6276 }
6277 } else return self.fail("TODO implement genBinOp for {s} {} without sse4_1", .{
6278 @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?),
6279 }),
6280 .max, .min => {}, // TODO: unordered select
61576281 else => unreachable,
61586282 }
61596283 return dst_mcv;
......@@ -6186,20 +6310,11 @@ fn genBinOpMir(self: *Self, mir_tag: Mir.Inst.Tag, ty: Type, dst_mcv: MCValue, s
61866310 .register_overflow,
61876311 .reserved_frame,
61886312 => unreachable,
6189 .register => |src_reg| switch (ty.zigTypeTag()) {
6190 .Float => {
6191 if (!Target.x86.featureSetHas(self.target.cpu.features, .sse))
6192 return self.fail("TODO genBinOpMir for {s} {} without sse", .{
6193 @tagName(mir_tag), ty.fmt(self.bin_file.options.module.?),
6194 });
6195 return self.asmRegisterRegister(mir_tag, dst_reg.to128(), src_reg.to128());
6196 },
6197 else => try self.asmRegisterRegister(
6198 mir_tag,
6199 dst_alias,
6200 registerAlias(src_reg, abi_size),
6201 ),
6202 },
6313 .register => |src_reg| try self.asmRegisterRegister(
6314 mir_tag,
6315 dst_alias,
6316 registerAlias(src_reg, abi_size),
6317 ),
62036318 .immediate => |imm| switch (self.regBitSize(ty)) {
62046319 8 => try self.asmRegisterImmediate(
62056320 mir_tag,
......@@ -9646,7 +9761,7 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
96469761 lock.* = self.register_manager.lockRegAssumeUnused(reg);
96479762 }
96489763
9649 const tag = if (@as(
9764 const mir_tag = if (@as(
96509765 ?Mir.Inst.Tag,
96519766 if (mem.eql(u2, &order, &.{ 1, 3, 2 }) or mem.eql(u2, &order, &.{ 3, 1, 2 }))
96529767 switch (ty.zigTypeTag()) {
......@@ -9741,20 +9856,17 @@ fn airMulAdd(self: *Self, inst: Air.Inst.Index) !void {
97419856 const abi_size = @intCast(u32, ty.abiSize(self.target.*));
97429857 const mop1_reg = registerAlias(mops[0].getReg().?, abi_size);
97439858 const mop2_reg = registerAlias(mops[1].getReg().?, abi_size);
9744 if (mops[2].isRegister())
9745 try self.asmRegisterRegisterRegister(
9746 tag,
9747 mop1_reg,
9748 mop2_reg,
9749 registerAlias(mops[2].getReg().?, abi_size),
9750 )
9751 else
9752 try self.asmRegisterRegisterMemory(
9753 tag,
9754 mop1_reg,
9755 mop2_reg,
9756 mops[2].mem(Memory.PtrSize.fromSize(abi_size)),
9757 );
9859 if (mops[2].isRegister()) try self.asmRegisterRegisterRegister(
9860 mir_tag,
9861 mop1_reg,
9862 mop2_reg,
9863 registerAlias(mops[2].getReg().?, abi_size),
9864 ) else try self.asmRegisterRegisterMemory(
9865 mir_tag,
9866 mop1_reg,
9867 mop2_reg,
9868 mops[2].mem(Memory.PtrSize.fromSize(abi_size)),
9869 );
97589870 return self.finishAir(inst, mops[0], ops);
97599871}
97609872
src/arch/x86_64/Encoding.zig+21-13
......@@ -262,61 +262,69 @@ pub const Mnemonic = enum {
262262 // MMX
263263 movd,
264264 // SSE
265 addss,
265 addps, addss,
266266 andps,
267267 andnps,
268268 cmpss,
269269 cvtsi2ss,
270 divss,
271 maxss, minss,
270 divps, divss,
271 maxps, maxss,
272 minps, minss,
272273 movaps, movss, movups,
273 mulss,
274 mulps, mulss,
274275 orps,
275276 pextrw, pinsrw,
276 sqrtps,
277 sqrtss,
278 subss,
277 sqrtps, sqrtss,
278 subps, subss,
279279 ucomiss,
280280 xorps,
281281 // SSE2
282 addsd,
282 addpd, addsd,
283283 andpd,
284284 andnpd,
285285 //cmpsd,
286286 cvtsd2ss, cvtsi2sd, cvtss2sd,
287 divsd,
288 maxsd, minsd,
287 divpd, divsd,
288 maxpd, maxsd,
289 minpd, minsd,
289290 movapd,
290291 movq, //movd, movsd,
291292 movupd,
292 mulsd,
293 mulpd, mulsd,
293294 orpd,
294295 pshufhw, pshuflw,
295296 psrld, psrlq, psrlw,
296297 punpckhbw, punpckhdq, punpckhqdq, punpckhwd,
297298 punpcklbw, punpckldq, punpcklqdq, punpcklwd,
298299 sqrtpd, sqrtsd,
299 subsd,
300 subpd, subsd,
300301 ucomisd,
301302 xorpd,
302303 // SSE3
303304 movddup, movshdup, movsldup,
304305 // SSE4.1
305 roundsd, roundss,
306 roundpd, roundps, roundsd, roundss,
306307 // AVX
308 vaddpd, vaddps, vaddsd, vaddss,
307309 vcvtsd2ss, vcvtsi2sd, vcvtsi2ss, vcvtss2sd,
310 vdivpd, vdivps, vdivsd, vdivss,
311 vmaxpd, vmaxps, vmaxsd, vmaxss,
312 vminpd, vminps, vminsd, vminss,
308313 vmovapd, vmovaps,
309314 vmovddup,
310315 vmovsd,
311316 vmovshdup, vmovsldup,
312317 vmovss,
313318 vmovupd, vmovups,
319 vmulpd, vmulps, vmulsd, vmulss,
314320 vpextrw, vpinsrw,
315321 vpshufhw, vpshuflw,
316322 vpsrld, vpsrlq, vpsrlw,
317323 vpunpckhbw, vpunpckhdq, vpunpckhqdq, vpunpckhwd,
318324 vpunpcklbw, vpunpckldq, vpunpcklqdq, vpunpcklwd,
325 vroundpd, vroundps, vroundsd, vroundss,
319326 vsqrtpd, vsqrtps, vsqrtsd, vsqrtss,
327 vsubpd, vsubps, vsubsd, vsubss,
320328 // F16C
321329 vcvtph2ps, vcvtps2ph,
322330 // FMA
src/arch/x86_64/Lower.zig+49
......@@ -124,27 +124,34 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
124124 .xchg,
125125 .xor,
126126
127 .addps,
127128 .addss,
128129 .andnps,
129130 .andps,
130131 .cmpss,
131132 .cvtsi2ss,
133 .divps,
132134 .divss,
135 .maxps,
133136 .maxss,
137 .minps,
134138 .minss,
135139 .movaps,
136140 .movss,
137141 .movups,
142 .mulps,
138143 .mulss,
139144 .orps,
140145 .pextrw,
141146 .pinsrw,
142147 .sqrtps,
143148 .sqrtss,
149 .subps,
144150 .subss,
145151 .ucomiss,
146152 .xorps,
147153
154 .addpd,
148155 .addsd,
149156 .andnpd,
150157 .andpd,
......@@ -152,10 +159,14 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
152159 .cvtsd2ss,
153160 .cvtsi2sd,
154161 .cvtss2sd,
162 .divpd,
155163 .divsd,
164 .maxpd,
156165 .maxsd,
166 .minpd,
157167 .minsd,
158168 .movsd,
169 .mulpd,
159170 .mulsd,
160171 .orpd,
161172 .pshufhw,
......@@ -173,6 +184,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
173184 .punpcklwd,
174185 .sqrtpd,
175186 .sqrtsd,
187 .subpd,
176188 .subsd,
177189 .ucomisd,
178190 .xorpd,
......@@ -181,13 +193,31 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
181193 .movshdup,
182194 .movsldup,
183195
196 .roundpd,
197 .roundps,
184198 .roundsd,
185199 .roundss,
186200
201 .vaddpd,
202 .vaddps,
203 .vaddsd,
204 .vaddss,
187205 .vcvtsd2ss,
188206 .vcvtsi2sd,
189207 .vcvtsi2ss,
190208 .vcvtss2sd,
209 .vdivpd,
210 .vdivps,
211 .vdivsd,
212 .vdivss,
213 .vmaxpd,
214 .vmaxps,
215 .vmaxsd,
216 .vmaxss,
217 .vminpd,
218 .vminps,
219 .vminsd,
220 .vminss,
191221 .vmovapd,
192222 .vmovaps,
193223 .vmovddup,
......@@ -197,6 +227,10 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
197227 .vmovss,
198228 .vmovupd,
199229 .vmovups,
230 .vmulpd,
231 .vmulps,
232 .vmulsd,
233 .vmulss,
200234 .vpextrw,
201235 .vpinsrw,
202236 .vpshufhw,
......@@ -212,10 +246,18 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
212246 .vpunpckldq,
213247 .vpunpcklqdq,
214248 .vpunpcklwd,
249 .vroundpd,
250 .vroundps,
251 .vroundsd,
252 .vroundss,
215253 .vsqrtpd,
216254 .vsqrtps,
217255 .vsqrtsd,
218256 .vsqrtss,
257 .vsubpd,
258 .vsubps,
259 .vsubsd,
260 .vsubss,
219261
220262 .vcvtph2ps,
221263 .vcvtps2ph,
......@@ -304,6 +346,7 @@ fn imm(lower: Lower, ops: Mir.Inst.Ops, i: u32) Immediate {
304346 .lock_mi_rip_s,
305347 => Immediate.s(@bitCast(i32, i)),
306348
349 .rrri,
307350 .rri_u,
308351 .ri_u,
309352 .i_u,
......@@ -429,6 +472,12 @@ fn mirGeneric(lower: *Lower, inst: Mir.Inst) Error!void {
429472 .{ .reg = inst.data.rrr.r2 },
430473 .{ .reg = inst.data.rrr.r3 },
431474 },
475 .rrri => &.{
476 .{ .reg = inst.data.rrri.r1 },
477 .{ .reg = inst.data.rrri.r2 },
478 .{ .reg = inst.data.rrri.r3 },
479 .{ .imm = lower.imm(inst.ops, inst.data.rrri.i) },
480 },
432481 .ri_s, .ri_u => &.{
433482 .{ .reg = inst.data.ri.r },
434483 .{ .imm = lower.imm(inst.ops, inst.data.ri.i) },
src/arch/x86_64/Mir.zig+104-11
......@@ -166,7 +166,9 @@ pub const Inst = struct {
166166 /// Logical exclusive-or
167167 xor,
168168
169 /// Add single precision floating point values
169 /// Add packed single-precision floating-point values
170 addps,
171 /// Add scalar single-precision floating-point values
170172 addss,
171173 /// Bitwise logical and of packed single precision floating-point values
172174 andps,
......@@ -176,11 +178,17 @@ pub const Inst = struct {
176178 cmpss,
177179 /// Convert doubleword integer to scalar single-precision floating-point value
178180 cvtsi2ss,
181 /// Divide packed single-precision floating-point values
182 divps,
179183 /// Divide scalar single-precision floating-point values
180184 divss,
181 /// Return maximum single-precision floating-point value
185 /// Maximum of packed single-precision floating-point values
186 maxps,
187 /// Maximum of scalar single-precision floating-point values
182188 maxss,
183 /// Return minimum single-precision floating-point value
189 /// Minimum of packed single-precision floating-point values
190 minps,
191 /// Minimum of scalar single-precision floating-point values
184192 minss,
185193 /// Move aligned packed single-precision floating-point values
186194 movaps,
......@@ -188,6 +196,8 @@ pub const Inst = struct {
188196 movss,
189197 /// Move unaligned packed single-precision floating-point values
190198 movups,
199 /// Multiply packed single-precision floating-point values
200 mulps,
191201 /// Multiply scalar single-precision floating-point values
192202 mulss,
193203 /// Bitwise logical or of packed single precision floating-point values
......@@ -196,18 +206,22 @@ pub const Inst = struct {
196206 pextrw,
197207 /// Insert word
198208 pinsrw,
199 /// Square root of scalar single precision floating-point value
209 /// Square root of packed single-precision floating-point values
200210 sqrtps,
201 /// Subtract scalar single-precision floating-point values
211 /// Square root of scalar single-precision floating-point value
202212 sqrtss,
203 /// Square root of single precision floating-point values
213 /// Subtract packed single-precision floating-point values
214 subps,
215 /// Subtract scalar single-precision floating-point values
204216 subss,
205217 /// Unordered compare scalar single-precision floating-point values
206218 ucomiss,
207219 /// Bitwise logical xor of packed single precision floating-point values
208220 xorps,
209221
210 /// Add double precision floating point values
222 /// Add packed double-precision floating-point values
223 addpd,
224 /// Add scalar double-precision floating-point values
211225 addsd,
212226 /// Bitwise logical and not of packed double precision floating-point values
213227 andnpd,
......@@ -221,14 +235,22 @@ pub const Inst = struct {
221235 cvtsi2sd,
222236 /// Convert scalar single-precision floating-point value to scalar double-precision floating-point value
223237 cvtss2sd,
238 /// Divide packed double-precision floating-point values
239 divpd,
224240 /// Divide scalar double-precision floating-point values
225241 divsd,
226 /// Return maximum double-precision floating-point value
242 /// Maximum of packed double-precision floating-point values
243 maxpd,
244 /// Maximum of scalar double-precision floating-point values
227245 maxsd,
228 /// Return minimum double-precision floating-point value
246 /// Minimum of packed double-precision floating-point values
247 minpd,
248 /// Minimum of scalar double-precision floating-point values
229249 minsd,
230250 /// Move scalar double-precision floating-point value
231251 movsd,
252 /// Multiply packed double-precision floating-point values
253 mulpd,
232254 /// Multiply scalar double-precision floating-point values
233255 mulsd,
234256 /// Bitwise logical or of packed double precision floating-point values
......@@ -263,6 +285,8 @@ pub const Inst = struct {
263285 sqrtpd,
264286 /// Square root of scalar double precision floating-point value
265287 sqrtsd,
288 /// Subtract packed double-precision floating-point values
289 subpd,
266290 /// Subtract scalar double-precision floating-point values
267291 subsd,
268292 /// Unordered compare scalar double-precision floating-point values
......@@ -277,11 +301,23 @@ pub const Inst = struct {
277301 /// Replicate single floating-point values
278302 movsldup,
279303
280 /// Round scalar double-precision floating-point values
304 /// Round packed double-precision floating-point values
305 roundpd,
306 /// Round packed single-precision floating-point values
307 roundps,
308 /// Round scalar double-precision floating-point value
281309 roundsd,
282 /// Round scalar single-precision floating-point values
310 /// Round scalar single-precision floating-point value
283311 roundss,
284312
313 /// Add packed double-precision floating-point values
314 vaddpd,
315 /// Add packed single-precision floating-point values
316 vaddps,
317 /// Add scalar double-precision floating-point values
318 vaddsd,
319 /// Add scalar single-precision floating-point values
320 vaddss,
285321 /// Convert scalar double-precision floating-point value to scalar single-precision floating-point value
286322 vcvtsd2ss,
287323 /// Convert doubleword integer to scalar double-precision floating-point value
......@@ -290,6 +326,30 @@ pub const Inst = struct {
290326 vcvtsi2ss,
291327 /// Convert scalar single-precision floating-point value to scalar double-precision floating-point value
292328 vcvtss2sd,
329 /// Divide packed double-precision floating-point values
330 vdivpd,
331 /// Divide packed single-precision floating-point values
332 vdivps,
333 /// Divide scalar double-precision floating-point values
334 vdivsd,
335 /// Divide scalar single-precision floating-point values
336 vdivss,
337 /// Maximum of packed double-precision floating-point values
338 vmaxpd,
339 /// Maximum of packed single-precision floating-point values
340 vmaxps,
341 /// Maximum of scalar double-precision floating-point values
342 vmaxsd,
343 /// Maximum of scalar single-precision floating-point values
344 vmaxss,
345 /// Minimum of packed double-precision floating-point values
346 vminpd,
347 /// Minimum of packed single-precision floating-point values
348 vminps,
349 /// Minimum of scalar double-precision floating-point values
350 vminsd,
351 /// Minimum of scalar single-precision floating-point values
352 vminss,
293353 /// Move aligned packed double-precision floating-point values
294354 vmovapd,
295355 /// Move aligned packed single-precision floating-point values
......@@ -308,6 +368,14 @@ pub const Inst = struct {
308368 vmovupd,
309369 /// Move unaligned packed single-precision floating-point values
310370 vmovups,
371 /// Multiply packed double-precision floating-point values
372 vmulpd,
373 /// Multiply packed single-precision floating-point values
374 vmulps,
375 /// Multiply scalar double-precision floating-point values
376 vmulsd,
377 /// Multiply scalar single-precision floating-point values
378 vmulss,
311379 /// Extract word
312380 vpextrw,
313381 /// Insert word
......@@ -338,6 +406,14 @@ pub const Inst = struct {
338406 vpunpcklqdq,
339407 /// Unpack low data
340408 vpunpcklwd,
409 /// Round packed double-precision floating-point values
410 vroundpd,
411 /// Round packed single-precision floating-point values
412 vroundps,
413 /// Round scalar double-precision floating-point value
414 vroundsd,
415 /// Round scalar single-precision floating-point value
416 vroundss,
341417 /// Square root of packed double-precision floating-point value
342418 vsqrtpd,
343419 /// Square root of packed single-precision floating-point value
......@@ -346,6 +422,14 @@ pub const Inst = struct {
346422 vsqrtsd,
347423 /// Square root of scalar single-precision floating-point value
348424 vsqrtss,
425 /// Subtract packed double-precision floating-point values
426 vsubpd,
427 /// Subtract packed single-precision floating-point values
428 vsubps,
429 /// Subtract scalar double-precision floating-point values
430 vsubsd,
431 /// Subtract scalar single-precision floating-point values
432 vsubss,
349433
350434 /// Convert 16-bit floating-point values to single-precision floating-point values
351435 vcvtph2ps,
......@@ -442,6 +526,9 @@ pub const Inst = struct {
442526 /// Register, register, register operands.
443527 /// Uses `rrr` payload.
444528 rrr,
529 /// Register, register, register, immediate (byte) operands.
530 /// Uses `rrri` payload.
531 rrri,
445532 /// Register, register, immediate (sign-extended) operands.
446533 /// Uses `rri` payload.
447534 rri_s,
......@@ -625,6 +712,12 @@ pub const Inst = struct {
625712 r2: Register,
626713 r3: Register,
627714 },
715 rrri: struct {
716 r1: Register,
717 r2: Register,
718 r3: Register,
719 i: u8,
720 },
628721 rri: struct {
629722 r1: Register,
630723 r2: Register,
src/arch/x86_64/encodings.zig+100-1
......@@ -837,6 +837,8 @@ pub const table = [_]Entry{
837837 .{ .xor, .rm, &.{ .r64, .rm64 }, &.{ 0x33 }, 0, .long, .none },
838838
839839 // SSE
840 .{ .addps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x58 }, 0, .none, .sse },
841
840842 .{ .addss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x58 }, 0, .none, .sse },
841843
842844 .{ .andnps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x55 }, 0, .none, .sse },
......@@ -848,10 +850,16 @@ pub const table = [_]Entry{
848850 .{ .cvtsi2ss, .rm, &.{ .xmm, .rm32 }, &.{ 0xf3, 0x0f, 0x2a }, 0, .none, .sse },
849851 .{ .cvtsi2ss, .rm, &.{ .xmm, .rm64 }, &.{ 0xf3, 0x0f, 0x2a }, 0, .long, .sse },
850852
853 .{ .divps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5e }, 0, .none, .sse },
854
851855 .{ .divss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5e }, 0, .none, .sse },
852856
857 .{ .maxps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5f }, 0, .none, .sse },
858
853859 .{ .maxss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5f }, 0, .none, .sse },
854860
861 .{ .minps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5d }, 0, .none, .sse },
862
855863 .{ .minss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5d }, 0, .none, .sse },
856864
857865 .{ .movaps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x28 }, 0, .none, .sse },
......@@ -863,10 +871,14 @@ pub const table = [_]Entry{
863871 .{ .movups, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x10 }, 0, .none, .sse },
864872 .{ .movups, .mr, &.{ .xmm_m128, .xmm }, &.{ 0x0f, 0x11 }, 0, .none, .sse },
865873
874 .{ .mulps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x59 }, 0, .none, .sse },
875
866876 .{ .mulss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x59 }, 0, .none, .sse },
867877
868878 .{ .orps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x56 }, 0, .none, .sse },
869879
880 .{ .subps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x5c }, 0, .none, .sse },
881
870882 .{ .subss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5c }, 0, .none, .sse },
871883
872884 .{ .sqrtps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x51 }, 0, .none, .sse },
......@@ -878,6 +890,8 @@ pub const table = [_]Entry{
878890 .{ .xorps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x57 }, 0, .none, .sse },
879891
880892 // SSE2
893 .{ .addpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x58 }, 0, .none, .sse2 },
894
881895 .{ .addsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x58 }, 0, .none, .sse2 },
882896
883897 .{ .andnpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x55 }, 0, .none, .sse2 },
......@@ -893,10 +907,16 @@ pub const table = [_]Entry{
893907
894908 .{ .cvtss2sd, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5a }, 0, .none, .sse2 },
895909
910 .{ .divpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5e }, 0, .none, .sse2 },
911
896912 .{ .divsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5e }, 0, .none, .sse2 },
897913
914 .{ .maxpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5f }, 0, .none, .sse2 },
915
898916 .{ .maxsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5f }, 0, .none, .sse2 },
899917
918 .{ .minpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5d }, 0, .none, .sse2 },
919
900920 .{ .minsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5d }, 0, .none, .sse2 },
901921
902922 .{ .movapd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x28 }, 0, .none, .sse2 },
......@@ -914,6 +934,8 @@ pub const table = [_]Entry{
914934 .{ .movupd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x10 }, 0, .none, .sse2 },
915935 .{ .movupd, .mr, &.{ .xmm_m128, .xmm }, &.{ 0x66, 0x0f, 0x11 }, 0, .none, .sse2 },
916936
937 .{ .mulpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x59 }, 0, .none, .sse2 },
938
917939 .{ .mulsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x59 }, 0, .none, .sse2 },
918940
919941 .{ .orpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x56 }, 0, .none, .sse2 },
......@@ -947,6 +969,8 @@ pub const table = [_]Entry{
947969
948970 .{ .sqrtsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x51 }, 0, .none, .sse2 },
949971
972 .{ .subpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5c }, 0, .none, .sse2 },
973
950974 .{ .subsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5c }, 0, .none, .sse2 },
951975
952976 .{ .movsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x10 }, 0, .none, .sse2 },
......@@ -966,10 +990,25 @@ pub const table = [_]Entry{
966990 // SSE4.1
967991 .{ .pextrw, .mri, &.{ .r32_m16, .xmm, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x15 }, 0, .none, .sse4_1 },
968992
969 .{ .roundss, .rmi, &.{ .xmm, .xmm_m32, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0a }, 0, .none, .sse4_1 },
993 .{ .roundpd, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x09 }, 0, .none, .sse4_1 },
994
995 .{ .roundps, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x08 }, 0, .none, .sse4_1 },
996
970997 .{ .roundsd, .rmi, &.{ .xmm, .xmm_m64, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0b }, 0, .none, .sse4_1 },
971998
999 .{ .roundss, .rmi, &.{ .xmm, .xmm_m32, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0a }, 0, .none, .sse4_1 },
1000
9721001 // AVX
1002 .{ .vaddpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x58 }, 0, .vex_128_wig, .avx },
1003 .{ .vaddpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x58 }, 0, .vex_256_wig, .avx },
1004
1005 .{ .vaddps, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x0f, 0x58 }, 0, .vex_128_wig, .avx },
1006 .{ .vaddps, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x0f, 0x58 }, 0, .vex_256_wig, .avx },
1007
1008 .{ .vaddsd, .rvm, &.{ .xmm, .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x58 }, 0, .vex_lig_wig, .avx },
1009
1010 .{ .vaddss, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x58 }, 0, .vex_lig_wig, .avx },
1011
9731012 .{ .vcvtsd2ss, .rvm, &.{ .xmm, .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5a }, 0, .vex_lig_wig, .avx },
9741013
9751014 .{ .vcvtsi2sd, .rvm, &.{ .xmm, .xmm, .rm32 }, &.{ 0xf2, 0x0f, 0x2a }, 0, .vex_lig_w0, .avx },
......@@ -980,6 +1019,36 @@ pub const table = [_]Entry{
9801019
9811020 .{ .vcvtss2sd, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf2, 0x0f, 0x5a }, 0, .vex_lig_wig, .avx },
9821021
1022 .{ .vdivpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5e }, 0, .vex_128_wig, .avx },
1023 .{ .vdivpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5e }, 0, .vex_256_wig, .avx },
1024
1025 .{ .vdivps, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x0f, 0x5e }, 0, .vex_128_wig, .avx },
1026 .{ .vdivps, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x0f, 0x5e }, 0, .vex_256_wig, .avx },
1027
1028 .{ .vdivsd, .rvm, &.{ .xmm, .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5e }, 0, .vex_lig_wig, .avx },
1029
1030 .{ .vdivss, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5e }, 0, .vex_lig_wig, .avx },
1031
1032 .{ .vmaxpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5f }, 0, .vex_128_wig, .avx },
1033 .{ .vmaxpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5f }, 0, .vex_256_wig, .avx },
1034
1035 .{ .vmaxps, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x0f, 0x5f }, 0, .vex_128_wig, .avx },
1036 .{ .vmaxps, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x0f, 0x5f }, 0, .vex_256_wig, .avx },
1037
1038 .{ .vmaxsd, .rvm, &.{ .xmm, .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5f }, 0, .vex_lig_wig, .avx },
1039
1040 .{ .vmaxss, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5f }, 0, .vex_lig_wig, .avx },
1041
1042 .{ .vminpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5d }, 0, .vex_128_wig, .avx },
1043 .{ .vminpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5d }, 0, .vex_256_wig, .avx },
1044
1045 .{ .vminps, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x0f, 0x5d }, 0, .vex_128_wig, .avx },
1046 .{ .vminps, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x0f, 0x5d }, 0, .vex_256_wig, .avx },
1047
1048 .{ .vminsd, .rvm, &.{ .xmm, .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5d }, 0, .vex_lig_wig, .avx },
1049
1050 .{ .vminss, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5d }, 0, .vex_lig_wig, .avx },
1051
9831052 .{ .vmovapd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x28 }, 0, .vex_128_wig, .avx },
9841053 .{ .vmovapd, .mr, &.{ .xmm_m128, .xmm }, &.{ 0x66, 0x0f, 0x29 }, 0, .vex_128_wig, .avx },
9851054 .{ .vmovapd, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x28 }, 0, .vex_256_wig, .avx },
......@@ -1019,6 +1088,16 @@ pub const table = [_]Entry{
10191088 .{ .vmovups, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x0f, 0x10 }, 0, .vex_256_wig, .avx },
10201089 .{ .vmovups, .mr, &.{ .ymm_m256, .ymm }, &.{ 0x0f, 0x11 }, 0, .vex_256_wig, .avx },
10211090
1091 .{ .vmulpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x59 }, 0, .vex_128_wig, .avx },
1092 .{ .vmulpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x59 }, 0, .vex_256_wig, .avx },
1093
1094 .{ .vmulps, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x0f, 0x59 }, 0, .vex_128_wig, .avx },
1095 .{ .vmulps, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x0f, 0x59 }, 0, .vex_256_wig, .avx },
1096
1097 .{ .vmulsd, .rvm, &.{ .xmm, .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x59 }, 0, .vex_lig_wig, .avx },
1098
1099 .{ .vmulss, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x59 }, 0, .vex_lig_wig, .avx },
1100
10221101 .{ .vpextrw, .rmi, &.{ .r32, .xmm, .imm8 }, &.{ 0x66, 0x0f, 0x15 }, 0, .vex_128_wig, .avx },
10231102 .{ .vpextrw, .mri, &.{ .r32_m16, .xmm, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x15 }, 0, .vex_128_wig, .avx },
10241103
......@@ -1041,6 +1120,16 @@ pub const table = [_]Entry{
10411120 .{ .vpunpckldq, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x62 }, 0, .vex_128_wig, .avx },
10421121 .{ .vpunpcklqdq, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x6c }, 0, .vex_128_wig, .avx },
10431122
1123 .{ .vroundpd, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x09 }, 0, .vex_128_wig, .avx },
1124 .{ .vroundpd, .rmi, &.{ .ymm, .ymm_m256, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x09 }, 0, .vex_256_wig, .avx },
1125
1126 .{ .vroundps, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x08 }, 0, .vex_128_wig, .avx },
1127 .{ .vroundps, .rmi, &.{ .ymm, .ymm_m256, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x08 }, 0, .vex_256_wig, .avx },
1128
1129 .{ .vroundsd, .rvmi, &.{ .xmm, .xmm, .xmm_m64, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0b }, 0, .vex_lig_wig, .avx },
1130
1131 .{ .vroundss, .rvmi, &.{ .xmm, .xmm, .xmm_m32, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0a }, 0, .vex_lig_wig, .avx },
1132
10441133 .{ .vsqrtpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x51 }, 0, .vex_128_wig, .avx },
10451134 .{ .vsqrtpd, .rm, &.{ .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x51 }, 0, .vex_256_wig, .avx },
10461135
......@@ -1051,6 +1140,16 @@ pub const table = [_]Entry{
10511140
10521141 .{ .vsqrtss, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x51 }, 0, .vex_lig_wig, .avx },
10531142
1143 .{ .vsubpd, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x5c }, 0, .vex_128_wig, .avx },
1144 .{ .vsubpd, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x66, 0x0f, 0x5c }, 0, .vex_256_wig, .avx },
1145
1146 .{ .vsubps, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x0f, 0x5c }, 0, .vex_128_wig, .avx },
1147 .{ .vsubps, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x0f, 0x5c }, 0, .vex_256_wig, .avx },
1148
1149 .{ .vsubsd, .rvm, &.{ .xmm, .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5c }, 0, .vex_lig_wig, .avx },
1150
1151 .{ .vsubss, .rvm, &.{ .xmm, .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5c }, 0, .vex_lig_wig, .avx },
1152
10541153 // F16C
10551154 .{ .vcvtph2ps, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0x66, 0x0f, 0x38, 0x13 }, 0, .vex_128_w0, .f16c },
10561155 .{ .vcvtph2ps, .rm, &.{ .ymm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x38, 0x13 }, 0, .vex_256_w0, .f16c },