authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-15 20:17:06-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-18 20:42:38-04:00
log403c2d91bed456085eb685a9f89996c4635ce4b9
tree0c3f60b5c7152dff3367f29f970845b88c210c03
parentb9d2e0e308794463db1b1acf04d76778c470a070

x86_64: fix float min/max behavior


7 files changed, 393 insertions(+), 40 deletions(-)

src/arch/x86_64/CodeGen.zig+292-10
...@@ -1271,6 +1271,27 @@ fn asmRegisterRegisterRegister(...@@ -1271,6 +1271,27 @@ fn asmRegisterRegisterRegister(
1271 });1271 });
1272}1272}
12731273
1274fn asmRegisterRegisterRegisterRegister(
1275 self: *Self,
1276 tag: Mir.Inst.FixedTag,
1277 reg1: Register,
1278 reg2: Register,
1279 reg3: Register,
1280 reg4: Register,
1281) !void {
1282 _ = try self.addInst(.{
1283 .tag = tag[1],
1284 .ops = .rrrr,
1285 .data = .{ .rrrr = .{
1286 .fixes = tag[0],
1287 .r1 = reg1,
1288 .r2 = reg2,
1289 .r3 = reg3,
1290 .r4 = reg4,
1291 } },
1292 });
1293}
1294
1274fn asmRegisterRegisterRegisterImmediate(1295fn asmRegisterRegisterRegisterImmediate(
1275 self: *Self,1296 self: *Self,
1276 tag: Mir.Inst.FixedTag,1297 tag: Mir.Inst.FixedTag,
...@@ -6224,12 +6245,26 @@ fn genBinOp(...@@ -6224,12 +6245,26 @@ fn genBinOp(
6224 lhs_air: Air.Inst.Ref,6245 lhs_air: Air.Inst.Ref,
6225 rhs_air: Air.Inst.Ref,6246 rhs_air: Air.Inst.Ref,
6226) !MCValue {6247) !MCValue {
6227 const lhs_mcv = try self.resolveInst(lhs_air);
6228 const rhs_mcv = try self.resolveInst(rhs_air);
6229 const lhs_ty = self.air.typeOf(lhs_air);6248 const lhs_ty = self.air.typeOf(lhs_air);
6230 const rhs_ty = self.air.typeOf(rhs_air);6249 const rhs_ty = self.air.typeOf(rhs_air);
6231 const abi_size = @intCast(u32, lhs_ty.abiSize(self.target.*));6250 const abi_size = @intCast(u32, lhs_ty.abiSize(self.target.*));
62326251
6252 const maybe_mask_reg = switch (air_tag) {
6253 else => null,
6254 .max, .min => if (lhs_ty.scalarType().isRuntimeFloat()) registerAlias(
6255 if (!self.hasFeature(.avx) and self.hasFeature(.sse4_1)) mask: {
6256 try self.register_manager.getReg(.xmm0, null);
6257 break :mask .xmm0;
6258 } else try self.register_manager.allocReg(null, sse),
6259 abi_size,
6260 ) else null,
6261 };
6262 const mask_lock =
6263 if (maybe_mask_reg) |mask_reg| self.register_manager.lockRegAssumeUnused(mask_reg) else null;
6264 defer if (mask_lock) |lock| self.register_manager.unlockReg(lock);
6265
6266 const lhs_mcv = try self.resolveInst(lhs_air);
6267 const rhs_mcv = try self.resolveInst(rhs_air);
6233 switch (lhs_mcv) {6268 switch (lhs_mcv) {
6234 .immediate => |imm| switch (imm) {6269 .immediate => |imm| switch (imm) {
6235 0 => switch (air_tag) {6270 0 => switch (air_tag) {
...@@ -6300,7 +6335,16 @@ fn genBinOp(...@@ -6300,7 +6335,16 @@ fn genBinOp(
6300 };6335 };
6301 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);6336 defer if (dst_lock) |lock| self.register_manager.unlockReg(lock);
63026337
6303 const src_mcv = if (flipped) lhs_mcv else rhs_mcv;6338 const unmat_src_mcv = if (flipped) lhs_mcv else rhs_mcv;
6339 const src_mcv: MCValue = if (maybe_mask_reg) |mask_reg|
6340 if (self.hasFeature(.avx) and unmat_src_mcv.isRegister() and maybe_inst != null and
6341 self.liveness.operandDies(maybe_inst.?, if (flipped) 0 else 1)) unmat_src_mcv else src: {
6342 try self.genSetReg(mask_reg, rhs_ty, unmat_src_mcv);
6343 break :src .{ .register = mask_reg };
6344 }
6345 else
6346 unmat_src_mcv;
6347
6304 if (!vec_op) {6348 if (!vec_op) {
6305 switch (air_tag) {6349 switch (air_tag) {
6306 .add,6350 .add,
...@@ -7009,18 +7053,26 @@ fn genBinOp(...@@ -7009,18 +7053,26 @@ fn genBinOp(
7009 })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{7053 })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{
7010 @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?),7054 @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?),
7011 });7055 });
7056
7057 const lhs_copy_reg = if (maybe_mask_reg) |_| registerAlias(
7058 if (copied_to_dst) try self.copyToTmpRegister(lhs_ty, dst_mcv) else lhs_mcv.getReg().?,
7059 abi_size,
7060 ) else null;
7061 const lhs_copy_lock = if (lhs_copy_reg) |reg| self.register_manager.lockReg(reg) else null;
7062 defer if (lhs_copy_lock) |lock| self.register_manager.unlockReg(lock);
7063
7012 if (self.hasFeature(.avx)) {7064 if (self.hasFeature(.avx)) {
7013 const src1_alias =7065 const lhs_reg =
7014 if (copied_to_dst) dst_reg else registerAlias(lhs_mcv.getReg().?, abi_size);7066 if (copied_to_dst) dst_reg else registerAlias(lhs_mcv.getReg().?, abi_size);
7015 if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(7067 if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory(
7016 mir_tag,7068 mir_tag,
7017 dst_reg,7069 dst_reg,
7018 src1_alias,7070 lhs_reg,
7019 src_mcv.mem(Memory.PtrSize.fromSize(abi_size)),7071 src_mcv.mem(Memory.PtrSize.fromSize(abi_size)),
7020 ) else try self.asmRegisterRegisterRegister(7072 ) else try self.asmRegisterRegisterRegister(
7021 mir_tag,7073 mir_tag,
7022 dst_reg,7074 dst_reg,
7023 src1_alias,7075 lhs_reg,
7024 registerAlias(if (src_mcv.isRegister())7076 registerAlias(if (src_mcv.isRegister())
7025 src_mcv.getReg().?7077 src_mcv.getReg().?
7026 else7078 else
...@@ -7041,9 +7093,10 @@ fn genBinOp(...@@ -7041,9 +7093,10 @@ fn genBinOp(
7041 try self.copyToTmpRegister(rhs_ty, src_mcv), abi_size),7093 try self.copyToTmpRegister(rhs_ty, src_mcv), abi_size),
7042 );7094 );
7043 }7095 }
7096
7044 switch (air_tag) {7097 switch (air_tag) {
7045 .add, .addwrap, .sub, .subwrap, .mul, .mulwrap, .div_float, .div_exact => {},7098 .add, .addwrap, .sub, .subwrap, .mul, .mulwrap, .div_float, .div_exact => {},
7046 .div_trunc, .div_floor => try self.genRound(7099 .div_trunc, .div_floor => if (self.hasFeature(.sse4_1)) try self.genRound(
7047 lhs_ty,7100 lhs_ty,
7048 dst_reg,7101 dst_reg,
7049 .{ .register = dst_reg },7102 .{ .register = dst_reg },
...@@ -7052,11 +7105,240 @@ fn genBinOp(...@@ -7052,11 +7105,240 @@ fn genBinOp(
7052 .div_floor => 0b1_0_01,7105 .div_floor => 0b1_0_01,
7053 else => unreachable,7106 else => unreachable,
7054 },7107 },
7055 ),7108 ) else return self.fail("TODO implement genBinOp for {s} {} without sse4_1 feature", .{
7109 @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?),
7110 }),
7056 .bit_and, .bit_or, .xor => {},7111 .bit_and, .bit_or, .xor => {},
7057 .max, .min => {}, // TODO: unordered select7112 .max, .min => if (maybe_mask_reg) |mask_reg| if (self.hasFeature(.avx)) {
7113 const rhs_copy_reg = registerAlias(src_mcv.getReg().?, abi_size);
7114
7115 try self.asmRegisterRegisterRegisterImmediate(
7116 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {
7117 .Float => switch (lhs_ty.floatBits(self.target.*)) {
7118 32 => .{ .v_ss, .cmp },
7119 64 => .{ .v_sd, .cmp },
7120 16, 80, 128 => null,
7121 else => unreachable,
7122 },
7123 .Vector => switch (lhs_ty.childType().zigTypeTag()) {
7124 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {
7125 32 => switch (lhs_ty.vectorLen()) {
7126 1 => .{ .v_ss, .cmp },
7127 2...8 => .{ .v_ps, .cmp },
7128 else => null,
7129 },
7130 64 => switch (lhs_ty.vectorLen()) {
7131 1 => .{ .v_sd, .cmp },
7132 2...4 => .{ .v_pd, .cmp },
7133 else => null,
7134 },
7135 16, 80, 128 => null,
7136 else => unreachable,
7137 },
7138 else => unreachable,
7139 },
7140 else => unreachable,
7141 })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{
7142 @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?),
7143 }),
7144 mask_reg,
7145 rhs_copy_reg,
7146 rhs_copy_reg,
7147 Immediate.u(3), // unord
7148 );
7149 try self.asmRegisterRegisterRegisterRegister(
7150 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {
7151 .Float => switch (lhs_ty.floatBits(self.target.*)) {
7152 32 => .{ .v_ps, .blendv },
7153 64 => .{ .v_pd, .blendv },
7154 16, 80, 128 => null,
7155 else => unreachable,
7156 },
7157 .Vector => switch (lhs_ty.childType().zigTypeTag()) {
7158 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {
7159 32 => switch (lhs_ty.vectorLen()) {
7160 1...8 => .{ .v_ps, .blendv },
7161 else => null,
7162 },
7163 64 => switch (lhs_ty.vectorLen()) {
7164 1...4 => .{ .v_pd, .blendv },
7165 else => null,
7166 },
7167 16, 80, 128 => null,
7168 else => unreachable,
7169 },
7170 else => unreachable,
7171 },
7172 else => unreachable,
7173 })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{
7174 @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?),
7175 }),
7176 dst_reg,
7177 dst_reg,
7178 lhs_copy_reg.?,
7179 mask_reg,
7180 );
7181 } else {
7182 const has_blend = self.hasFeature(.sse4_1);
7183 try self.asmRegisterRegisterImmediate(
7184 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {
7185 .Float => switch (lhs_ty.floatBits(self.target.*)) {
7186 32 => .{ ._ss, .cmp },
7187 64 => .{ ._sd, .cmp },
7188 16, 80, 128 => null,
7189 else => unreachable,
7190 },
7191 .Vector => switch (lhs_ty.childType().zigTypeTag()) {
7192 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {
7193 32 => switch (lhs_ty.vectorLen()) {
7194 1 => .{ ._ss, .cmp },
7195 2...4 => .{ ._ps, .cmp },
7196 else => null,
7197 },
7198 64 => switch (lhs_ty.vectorLen()) {
7199 1 => .{ ._sd, .cmp },
7200 2 => .{ ._pd, .cmp },
7201 else => null,
7202 },
7203 16, 80, 128 => null,
7204 else => unreachable,
7205 },
7206 else => unreachable,
7207 },
7208 else => unreachable,
7209 })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{
7210 @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?),
7211 }),
7212 mask_reg,
7213 mask_reg,
7214 Immediate.u(if (has_blend) 3 else 7), // unord, ord
7215 );
7216 if (has_blend) try self.asmRegisterRegisterRegister(
7217 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {
7218 .Float => switch (lhs_ty.floatBits(self.target.*)) {
7219 32 => .{ ._ps, .blendv },
7220 64 => .{ ._pd, .blendv },
7221 16, 80, 128 => null,
7222 else => unreachable,
7223 },
7224 .Vector => switch (lhs_ty.childType().zigTypeTag()) {
7225 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {
7226 32 => switch (lhs_ty.vectorLen()) {
7227 1...4 => .{ ._ps, .blendv },
7228 else => null,
7229 },
7230 64 => switch (lhs_ty.vectorLen()) {
7231 1...2 => .{ ._pd, .blendv },
7232 else => null,
7233 },
7234 16, 80, 128 => null,
7235 else => unreachable,
7236 },
7237 else => unreachable,
7238 },
7239 else => unreachable,
7240 })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{
7241 @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?),
7242 }),
7243 dst_reg,
7244 lhs_copy_reg.?,
7245 mask_reg,
7246 ) else {
7247 try self.asmRegisterRegister(
7248 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {
7249 .Float => switch (lhs_ty.floatBits(self.target.*)) {
7250 32 => .{ ._ps, .@"and" },
7251 64 => .{ ._pd, .@"and" },
7252 16, 80, 128 => null,
7253 else => unreachable,
7254 },
7255 .Vector => switch (lhs_ty.childType().zigTypeTag()) {
7256 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {
7257 32 => switch (lhs_ty.vectorLen()) {
7258 1...4 => .{ ._ps, .@"and" },
7259 else => null,
7260 },
7261 64 => switch (lhs_ty.vectorLen()) {
7262 1...2 => .{ ._pd, .@"and" },
7263 else => null,
7264 },
7265 16, 80, 128 => null,
7266 else => unreachable,
7267 },
7268 else => unreachable,
7269 },
7270 else => unreachable,
7271 })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{
7272 @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?),
7273 }),
7274 dst_reg,
7275 mask_reg,
7276 );
7277 try self.asmRegisterRegister(
7278 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {
7279 .Float => switch (lhs_ty.floatBits(self.target.*)) {
7280 32 => .{ ._ps, .andn },
7281 64 => .{ ._pd, .andn },
7282 16, 80, 128 => null,
7283 else => unreachable,
7284 },
7285 .Vector => switch (lhs_ty.childType().zigTypeTag()) {
7286 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {
7287 32 => switch (lhs_ty.vectorLen()) {
7288 1...4 => .{ ._ps, .andn },
7289 else => null,
7290 },
7291 64 => switch (lhs_ty.vectorLen()) {
7292 1...2 => .{ ._pd, .andn },
7293 else => null,
7294 },
7295 16, 80, 128 => null,
7296 else => unreachable,
7297 },
7298 else => unreachable,
7299 },
7300 else => unreachable,
7301 })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{
7302 @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?),
7303 }),
7304 mask_reg,
7305 lhs_copy_reg.?,
7306 );
7307 try self.asmRegisterRegister(
7308 if (@as(?Mir.Inst.FixedTag, switch (lhs_ty.zigTypeTag()) {
7309 .Float => switch (lhs_ty.floatBits(self.target.*)) {
7310 32 => .{ ._ps, .@"or" },
7311 64 => .{ ._pd, .@"or" },
7312 16, 80, 128 => null,
7313 else => unreachable,
7314 },
7315 .Vector => switch (lhs_ty.childType().zigTypeTag()) {
7316 .Float => switch (lhs_ty.childType().floatBits(self.target.*)) {
7317 32 => switch (lhs_ty.vectorLen()) {
7318 1...4 => .{ ._ps, .@"or" },
7319 else => null,
7320 },
7321 64 => switch (lhs_ty.vectorLen()) {
7322 1...2 => .{ ._pd, .@"or" },
7323 else => null,
7324 },
7325 16, 80, 128 => null,
7326 else => unreachable,
7327 },
7328 else => unreachable,
7329 },
7330 else => unreachable,
7331 })) |tag| tag else return self.fail("TODO implement genBinOp for {s} {}", .{
7332 @tagName(air_tag), lhs_ty.fmt(self.bin_file.options.module.?),
7333 }),
7334 dst_reg,
7335 mask_reg,
7336 );
7337 }
7338 },
7058 else => unreachable,7339 else => unreachable,
7059 }7340 }
7341
7060 return dst_mcv;7342 return dst_mcv;
7061}7343}
70627344
...@@ -9282,7 +9564,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr...@@ -9282,7 +9564,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
9282 17...32 => if (self.hasFeature(.avx)) .{ .v_, .movdqa } else null,9564 17...32 => if (self.hasFeature(.avx)) .{ .v_, .movdqa } else null,
9283 else => null,9565 else => null,
9284 },9566 },
9285 .Float => switch (ty.floatBits(self.target.*)) {9567 .Float => switch (ty.scalarType().floatBits(self.target.*)) {
9286 16, 128 => switch (abi_size) {9568 16, 128 => switch (abi_size) {
9287 2...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },9569 2...4 => if (self.hasFeature(.avx)) .{ .v_d, .mov } else .{ ._d, .mov },
9288 5...8 => if (self.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov },9570 5...8 => if (self.hasFeature(.avx)) .{ .v_q, .mov } else .{ ._q, .mov },
src/arch/x86_64/Encoding.zig+20-13
...@@ -178,7 +178,7 @@ pub fn format(...@@ -178,7 +178,7 @@ pub fn format(
178 try writer.print("+{s} ", .{tag});178 try writer.print("+{s} ", .{tag});
179 },179 },
180 .m, .mi, .m1, .mc, .vmi => try writer.print("/{d} ", .{encoding.modRmExt()}),180 .m, .mi, .m1, .mc, .vmi => try writer.print("/{d} ", .{encoding.modRmExt()}),
181 .mr, .rm, .rmi, .mri, .mrc, .rvm, .rvmi, .mvr => try writer.writeAll("/r "),181 .mr, .rm, .rmi, .mri, .mrc, .rm0, .rvm, .rvmr, .rvmi, .mvr => try writer.writeAll("/r "),
182 }182 }
183183
184 switch (encoding.data.op_en) {184 switch (encoding.data.op_en) {
...@@ -202,7 +202,8 @@ pub fn format(...@@ -202,7 +202,8 @@ pub fn format(
202 };202 };
203 try writer.print("{s} ", .{tag});203 try writer.print("{s} ", .{tag});
204 },204 },
205 .np, .fd, .td, .o, .m, .m1, .mc, .mr, .rm, .mrc, .rvm, .mvr => {},205 .rvmr => try writer.writeAll("/is4 "),
206 .np, .fd, .td, .o, .m, .m1, .mc, .mr, .rm, .mrc, .rm0, .rvm, .mvr => {},
206 }207 }
207208
208 try writer.print("{s} ", .{@tagName(encoding.mnemonic)});209 try writer.print("{s} ", .{@tagName(encoding.mnemonic)});
...@@ -270,7 +271,7 @@ pub const Mnemonic = enum {...@@ -270,7 +271,7 @@ pub const Mnemonic = enum {
270 addps, addss,271 addps, addss,
271 andps,272 andps,
272 andnps,273 andnps,
273 cmpss,274 cmpps, cmpss,
274 cvtpi2ps, cvtps2pi, cvtsi2ss, cvtss2si, cvttps2pi, cvttss2si,275 cvtpi2ps, cvtps2pi, cvtsi2ss, cvtss2si, cvttps2pi, cvttss2si,
275 divps, divss,276 divps, divss,
276 maxps, maxss,277 maxps, maxss,
...@@ -290,7 +291,7 @@ pub const Mnemonic = enum {...@@ -290,7 +291,7 @@ pub const Mnemonic = enum {
290 addpd, addsd,291 addpd, addsd,
291 andpd,292 andpd,
292 andnpd,293 andnpd,
293 //cmpsd,294 cmppd, //cmpsd,
294 cvtdq2pd, cvtdq2ps, cvtpd2dq, cvtpd2pi, cvtpd2ps, cvtpi2pd,295 cvtdq2pd, cvtdq2ps, cvtpd2dq, cvtpd2pi, cvtpd2ps, cvtpi2pd,
295 cvtps2dq, cvtps2pd, cvtsd2si, cvtsd2ss, cvtsi2sd, cvtss2sd,296 cvtps2dq, cvtps2pd, cvtsd2si, cvtsd2ss, cvtsi2sd, cvtss2sd,
296 cvttpd2dq, cvttpd2pi, cvttps2dq, cvttsd2si,297 cvttpd2dq, cvttpd2pi, cvttps2dq, cvttsd2si,
...@@ -315,6 +316,7 @@ pub const Mnemonic = enum {...@@ -315,6 +316,7 @@ pub const Mnemonic = enum {
315 // SSE3316 // SSE3
316 movddup, movshdup, movsldup,317 movddup, movshdup, movsldup,
317 // SSE4.1318 // SSE4.1
319 blendpd, blendps, blendvpd, blendvps,
318 extractps,320 extractps,
319 insertps,321 insertps,
320 pextrb, pextrd, pextrq,322 pextrb, pextrd, pextrq,
...@@ -325,7 +327,9 @@ pub const Mnemonic = enum {...@@ -325,7 +327,9 @@ pub const Mnemonic = enum {
325 // AVX327 // AVX
326 vaddpd, vaddps, vaddsd, vaddss,328 vaddpd, vaddps, vaddsd, vaddss,
327 vandnpd, vandnps, vandpd, vandps,329 vandnpd, vandnps, vandpd, vandps,
330 vblendpd, vblendps, vblendvpd, vblendvps,
328 vbroadcastf128, vbroadcastsd, vbroadcastss,331 vbroadcastf128, vbroadcastsd, vbroadcastss,
332 vcmppd, vcmpps, vcmpsd, vcmpss,
329 vcvtdq2pd, vcvtdq2ps, vcvtpd2dq, vcvtpd2ps,333 vcvtdq2pd, vcvtdq2ps, vcvtpd2dq, vcvtpd2ps,
330 vcvtps2dq, vcvtps2pd, vcvtsd2si, vcvtsd2ss,334 vcvtps2dq, vcvtps2pd, vcvtsd2si, vcvtsd2ss,
331 vcvtsi2sd, vcvtsi2ss, vcvtss2sd, vcvtss2si,335 vcvtsi2sd, vcvtsi2ss, vcvtss2sd, vcvtss2si,
...@@ -385,7 +389,7 @@ pub const OpEn = enum {...@@ -385,7 +389,7 @@ pub const OpEn = enum {
385 fd, td,389 fd, td,
386 m1, mc, mi, mr, rm,390 m1, mc, mi, mr, rm,
387 rmi, mri, mrc,391 rmi, mri, mrc,
388 vmi, rvm, rvmi, mvr,392 rm0, vmi, rvm, rvmr, rvmi, mvr,
389 // zig fmt: on393 // zig fmt: on
390};394};
391395
...@@ -407,7 +411,7 @@ pub const Op = enum {...@@ -407,7 +411,7 @@ pub const Op = enum {
407 moffs,411 moffs,
408 sreg,412 sreg,
409 st, mm, mm_m64,413 st, mm, mm_m64,
410 xmm, xmm_m32, xmm_m64, xmm_m128,414 xmm0, xmm, xmm_m32, xmm_m64, xmm_m128,
411 ymm, ymm_m256,415 ymm, ymm_m256,
412 // zig fmt: on416 // zig fmt: on
413417
...@@ -436,7 +440,9 @@ pub const Op = enum {...@@ -436,7 +440,9 @@ pub const Op = enum {
436 .segment => .sreg,440 .segment => .sreg,
437 .x87 => .st,441 .x87 => .st,
438 .mmx => .mm,442 .mmx => .mm,
439 .sse => switch (reg.bitSize()) {443 .sse => if (reg == .xmm0)
444 .xmm0
445 else switch (reg.bitSize()) {
440 128 => .xmm,446 128 => .xmm,
441 256 => .ymm,447 256 => .ymm,
442 else => unreachable,448 else => unreachable,
...@@ -494,7 +500,7 @@ pub const Op = enum {...@@ -494,7 +500,7 @@ pub const Op = enum {
494 .eax, .r32, .rm32, .r32_m16 => unreachable,500 .eax, .r32, .rm32, .r32_m16 => unreachable,
495 .rax, .r64, .rm64, .r64_m16 => unreachable,501 .rax, .r64, .rm64, .r64_m16 => unreachable,
496 .st, .mm, .mm_m64 => unreachable,502 .st, .mm, .mm_m64 => unreachable,
497 .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => unreachable,503 .xmm0, .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => unreachable,
498 .ymm, .ymm_m256 => unreachable,504 .ymm, .ymm_m256 => unreachable,
499 .m8, .m16, .m32, .m64, .m80, .m128, .m256 => unreachable,505 .m8, .m16, .m32, .m64, .m80, .m128, .m256 => unreachable,
500 .unity => 1,506 .unity => 1,
...@@ -516,7 +522,7 @@ pub const Op = enum {...@@ -516,7 +522,7 @@ pub const Op = enum {
516 .eax, .r32, .rm32, .r32_m8, .r32_m16 => 32,522 .eax, .r32, .rm32, .r32_m8, .r32_m16 => 32,
517 .rax, .r64, .rm64, .r64_m16, .mm, .mm_m64 => 64,523 .rax, .r64, .rm64, .r64_m16, .mm, .mm_m64 => 64,
518 .st => 80,524 .st => 80,
519 .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => 128,525 .xmm0, .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => 128,
520 .ymm, .ymm_m256 => 256,526 .ymm, .ymm_m256 => 256,
521 };527 };
522 }528 }
...@@ -526,7 +532,8 @@ pub const Op = enum {...@@ -526,7 +532,8 @@ pub const Op = enum {
526 .none, .o16, .o32, .o64, .moffs, .m, .sreg => unreachable,532 .none, .o16, .o32, .o64, .moffs, .m, .sreg => unreachable,
527 .unity, .imm8, .imm8s, .imm16, .imm16s, .imm32, .imm32s, .imm64 => unreachable,533 .unity, .imm8, .imm8s, .imm16, .imm16s, .imm32, .imm32s, .imm64 => unreachable,
528 .rel8, .rel16, .rel32 => unreachable,534 .rel8, .rel16, .rel32 => unreachable,
529 .al, .cl, .r8, .ax, .r16, .eax, .r32, .rax, .r64, .st, .mm, .xmm, .ymm => unreachable,535 .al, .cl, .r8, .ax, .r16, .eax, .r32, .rax, .r64 => unreachable,
536 .st, .mm, .xmm0, .xmm, .ymm => unreachable,
530 .m8, .rm8, .r32_m8 => 8,537 .m8, .rm8, .r32_m8 => 8,
531 .m16, .rm16, .r32_m16, .r64_m16 => 16,538 .m16, .rm16, .r32_m16, .r64_m16 => 16,
532 .m32, .rm32, .xmm_m32 => 32,539 .m32, .rm32, .xmm_m32 => 32,
...@@ -558,7 +565,7 @@ pub const Op = enum {...@@ -558,7 +565,7 @@ pub const Op = enum {
558 .rm8, .rm16, .rm32, .rm64,565 .rm8, .rm16, .rm32, .rm64,
559 .r32_m8, .r32_m16, .r64_m16,566 .r32_m8, .r32_m16, .r64_m16,
560 .st, .mm, .mm_m64,567 .st, .mm, .mm_m64,
561 .xmm, .xmm_m32, .xmm_m64, .xmm_m128,568 .xmm0, .xmm, .xmm_m32, .xmm_m64, .xmm_m128,
562 .ymm, .ymm_m256,569 .ymm, .ymm_m256,
563 => true,570 => true,
564 else => false,571 else => false,
...@@ -612,7 +619,7 @@ pub const Op = enum {...@@ -612,7 +619,7 @@ pub const Op = enum {
612 .sreg => .segment,619 .sreg => .segment,
613 .st => .x87,620 .st => .x87,
614 .mm, .mm_m64 => .mmx,621 .mm, .mm_m64 => .mmx,
615 .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => .sse,622 .xmm0, .xmm, .xmm_m32, .xmm_m64, .xmm_m128 => .sse,
616 .ymm, .ymm_m256 => .sse,623 .ymm, .ymm_m256 => .sse,
617 };624 };
618 }625 }
...@@ -629,7 +636,7 @@ pub const Op = enum {...@@ -629,7 +636,7 @@ pub const Op = enum {
629 else => {636 else => {
630 if (op.isRegister() and target.isRegister()) {637 if (op.isRegister() and target.isRegister()) {
631 return switch (target) {638 return switch (target) {
632 .cl, .al, .ax, .eax, .rax => op == target,639 .cl, .al, .ax, .eax, .rax, .xmm0 => op == target,
633 else => op.class() == target.class() and op.regBitSize() == target.regBitSize(),640 else => op.class() == target.class() and op.regBitSize() == target.regBitSize(),
634 };641 };
635 }642 }
src/arch/x86_64/Lower.zig+7
...@@ -377,6 +377,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {...@@ -377,6 +377,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
377 .r => inst.data.r.fixes,377 .r => inst.data.r.fixes,
378 .rr => inst.data.rr.fixes,378 .rr => inst.data.rr.fixes,
379 .rrr => inst.data.rrr.fixes,379 .rrr => inst.data.rrr.fixes,
380 .rrrr => inst.data.rrrr.fixes,
380 .rrri => inst.data.rrri.fixes,381 .rrri => inst.data.rrri.fixes,
381 .rri_s, .rri_u => inst.data.rri.fixes,382 .rri_s, .rri_u => inst.data.rri.fixes,
382 .ri_s, .ri_u => inst.data.ri.fixes,383 .ri_s, .ri_u => inst.data.ri.fixes,
...@@ -430,6 +431,12 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {...@@ -430,6 +431,12 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void {
430 .{ .reg = inst.data.rrr.r2 },431 .{ .reg = inst.data.rrr.r2 },
431 .{ .reg = inst.data.rrr.r3 },432 .{ .reg = inst.data.rrr.r3 },
432 },433 },
434 .rrrr => &.{
435 .{ .reg = inst.data.rrrr.r1 },
436 .{ .reg = inst.data.rrrr.r2 },
437 .{ .reg = inst.data.rrrr.r3 },
438 .{ .reg = inst.data.rrrr.r4 },
439 },
433 .rrri => &.{440 .rrri => &.{
434 .{ .reg = inst.data.rrri.r1 },441 .{ .reg = inst.data.rrri.r1 },
435 .{ .reg = inst.data.rrri.r2 },442 .{ .reg = inst.data.rrri.r2 },
src/arch/x86_64/Mir.zig+20
...@@ -596,6 +596,16 @@ pub const Inst = struct {...@@ -596,6 +596,16 @@ pub const Inst = struct {
596 /// Replicate single floating-point values596 /// Replicate single floating-point values
597 movsldup,597 movsldup,
598598
599 /// Blend packed single-precision floating-point values
600 /// Blend scalar single-precision floating-point values
601 /// Blend packed double-precision floating-point values
602 /// Blend scalar double-precision floating-point values
603 blend,
604 /// Variable blend packed single-precision floating-point values
605 /// Variable blend scalar single-precision floating-point values
606 /// Variable blend packed double-precision floating-point values
607 /// Variable blend scalar double-precision floating-point values
608 blendv,
599 /// Extract packed floating-point values609 /// Extract packed floating-point values
600 extract,610 extract,
601 /// Insert scalar single-precision floating-point value611 /// Insert scalar single-precision floating-point value
...@@ -651,6 +661,9 @@ pub const Inst = struct {...@@ -651,6 +661,9 @@ pub const Inst = struct {
651 /// Register, register, register operands.661 /// Register, register, register operands.
652 /// Uses `rrr` payload.662 /// Uses `rrr` payload.
653 rrr,663 rrr,
664 /// Register, register, register, register operands.
665 /// Uses `rrrr` payload.
666 rrrr,
654 /// Register, register, register, immediate (byte) operands.667 /// Register, register, register, immediate (byte) operands.
655 /// Uses `rrri` payload.668 /// Uses `rrri` payload.
656 rrri,669 rrri,
...@@ -870,6 +883,13 @@ pub const Inst = struct {...@@ -870,6 +883,13 @@ pub const Inst = struct {
870 r2: Register,883 r2: Register,
871 r3: Register,884 r3: Register,
872 },885 },
886 rrrr: struct {
887 fixes: Fixes = ._,
888 r1: Register,
889 r2: Register,
890 r3: Register,
891 r4: Register,
892 },
873 rrri: struct {893 rrri: struct {
874 fixes: Fixes = ._,894 fixes: Fixes = ._,
875 r1: Register,895 r1: Register,
src/arch/x86_64/encoder.zig+16-15
...@@ -226,8 +226,8 @@ pub const Instruction = struct {...@@ -226,8 +226,8 @@ pub const Instruction = struct {
226 else => {226 else => {
227 const mem_op = switch (data.op_en) {227 const mem_op = switch (data.op_en) {
228 .m, .mi, .m1, .mc, .mr, .mri, .mrc, .mvr => inst.ops[0],228 .m, .mi, .m1, .mc, .mr, .mri, .mrc, .mvr => inst.ops[0],
229 .rm, .rmi, .vmi => inst.ops[1],229 .rm, .rmi, .rm0, .vmi => inst.ops[1],
230 .rvm, .rvmi => inst.ops[2],230 .rvm, .rvmr, .rvmi => inst.ops[2],
231 else => unreachable,231 else => unreachable,
232 };232 };
233 switch (mem_op) {233 switch (mem_op) {
...@@ -235,7 +235,7 @@ pub const Instruction = struct {...@@ -235,7 +235,7 @@ pub const Instruction = struct {
235 const rm = switch (data.op_en) {235 const rm = switch (data.op_en) {
236 .m, .mi, .m1, .mc, .vmi => enc.modRmExt(),236 .m, .mi, .m1, .mc, .vmi => enc.modRmExt(),
237 .mr, .mri, .mrc => inst.ops[1].reg.lowEnc(),237 .mr, .mri, .mrc => inst.ops[1].reg.lowEnc(),
238 .rm, .rmi, .rvm, .rvmi => inst.ops[0].reg.lowEnc(),238 .rm, .rmi, .rm0, .rvm, .rvmr, .rvmi => inst.ops[0].reg.lowEnc(),
239 .mvr => inst.ops[2].reg.lowEnc(),239 .mvr => inst.ops[2].reg.lowEnc(),
240 else => unreachable,240 else => unreachable,
241 };241 };
...@@ -245,7 +245,7 @@ pub const Instruction = struct {...@@ -245,7 +245,7 @@ pub const Instruction = struct {
245 const op = switch (data.op_en) {245 const op = switch (data.op_en) {
246 .m, .mi, .m1, .mc, .vmi => .none,246 .m, .mi, .m1, .mc, .vmi => .none,
247 .mr, .mri, .mrc => inst.ops[1],247 .mr, .mri, .mrc => inst.ops[1],
248 .rm, .rmi, .rvm, .rvmi => inst.ops[0],248 .rm, .rmi, .rm0, .rvm, .rvmr, .rvmi => inst.ops[0],
249 .mvr => inst.ops[2],249 .mvr => inst.ops[2],
250 else => unreachable,250 else => unreachable,
251 };251 };
...@@ -257,6 +257,7 @@ pub const Instruction = struct {...@@ -257,6 +257,7 @@ pub const Instruction = struct {
257 switch (data.op_en) {257 switch (data.op_en) {
258 .mi => try encodeImm(inst.ops[1].imm, data.ops[1], encoder),258 .mi => try encodeImm(inst.ops[1].imm, data.ops[1], encoder),
259 .rmi, .mri, .vmi => try encodeImm(inst.ops[2].imm, data.ops[2], encoder),259 .rmi, .mri, .vmi => try encodeImm(inst.ops[2].imm, data.ops[2], encoder),
260 .rvmr => try encoder.imm8(@as(u8, inst.ops[3].reg.enc()) << 4),
260 .rvmi => try encodeImm(inst.ops[3].imm, data.ops[3], encoder),261 .rvmi => try encodeImm(inst.ops[3].imm, data.ops[3], encoder),
261 else => {},262 else => {},
262 }263 }
...@@ -298,7 +299,7 @@ pub const Instruction = struct {...@@ -298,7 +299,7 @@ pub const Instruction = struct {
298 .i, .zi, .o, .oi, .d, .np => null,299 .i, .zi, .o, .oi, .d, .np => null,
299 .fd => inst.ops[1].mem.base().reg,300 .fd => inst.ops[1].mem.base().reg,
300 .td => inst.ops[0].mem.base().reg,301 .td => inst.ops[0].mem.base().reg,
301 .rm, .rmi => if (inst.ops[1].isSegmentRegister())302 .rm, .rmi, .rm0 => if (inst.ops[1].isSegmentRegister())
302 switch (inst.ops[1]) {303 switch (inst.ops[1]) {
303 .reg => |reg| reg,304 .reg => |reg| reg,
304 .mem => |mem| mem.base().reg,305 .mem => |mem| mem.base().reg,
...@@ -314,7 +315,7 @@ pub const Instruction = struct {...@@ -314,7 +315,7 @@ pub const Instruction = struct {
314 }315 }
315 else316 else
316 null,317 null,
317 .vmi, .rvm, .rvmi, .mvr => unreachable,318 .vmi, .rvm, .rvmr, .rvmi, .mvr => unreachable,
318 };319 };
319 if (segment_override) |seg| {320 if (segment_override) |seg| {
320 legacy.setSegmentOverride(seg);321 legacy.setSegmentOverride(seg);
...@@ -333,23 +334,23 @@ pub const Instruction = struct {...@@ -333,23 +334,23 @@ pub const Instruction = struct {
333 switch (op_en) {334 switch (op_en) {
334 .np, .i, .zi, .fd, .td, .d => {},335 .np, .i, .zi, .fd, .td, .d => {},
335 .o, .oi => rex.b = inst.ops[0].reg.isExtended(),336 .o, .oi => rex.b = inst.ops[0].reg.isExtended(),
336 .m, .mi, .m1, .mc, .mr, .rm, .rmi, .mri, .mrc => {337 .m, .mi, .m1, .mc, .mr, .rm, .rmi, .mri, .mrc, .rm0 => {
337 const r_op = switch (op_en) {338 const r_op = switch (op_en) {
338 .rm, .rmi => inst.ops[0],339 .rm, .rmi, .rm0 => inst.ops[0],
339 .mr, .mri, .mrc => inst.ops[1],340 .mr, .mri, .mrc => inst.ops[1],
340 else => .none,341 else => .none,
341 };342 };
342 rex.r = r_op.isBaseExtended();343 rex.r = r_op.isBaseExtended();
343344
344 const b_x_op = switch (op_en) {345 const b_x_op = switch (op_en) {
345 .rm, .rmi => inst.ops[1],346 .rm, .rmi, .rm0 => inst.ops[1],
346 .m, .mi, .m1, .mc, .mr, .mri, .mrc => inst.ops[0],347 .m, .mi, .m1, .mc, .mr, .mri, .mrc => inst.ops[0],
347 else => unreachable,348 else => unreachable,
348 };349 };
349 rex.b = b_x_op.isBaseExtended();350 rex.b = b_x_op.isBaseExtended();
350 rex.x = b_x_op.isIndexExtended();351 rex.x = b_x_op.isIndexExtended();
351 },352 },
352 .vmi, .rvm, .rvmi, .mvr => unreachable,353 .vmi, .rvm, .rvmr, .rvmi, .mvr => unreachable,
353 }354 }
354355
355 try encoder.rex(rex);356 try encoder.rex(rex);
...@@ -367,9 +368,9 @@ pub const Instruction = struct {...@@ -367,9 +368,9 @@ pub const Instruction = struct {
367 switch (op_en) {368 switch (op_en) {
368 .np, .i, .zi, .fd, .td, .d => {},369 .np, .i, .zi, .fd, .td, .d => {},
369 .o, .oi => vex.b = inst.ops[0].reg.isExtended(),370 .o, .oi => vex.b = inst.ops[0].reg.isExtended(),
370 .m, .mi, .m1, .mc, .mr, .rm, .rmi, .mri, .mrc, .vmi, .rvm, .rvmi, .mvr => {371 .m, .mi, .m1, .mc, .mr, .rm, .rmi, .mri, .mrc, .rm0, .vmi, .rvm, .rvmr, .rvmi, .mvr => {
371 const r_op = switch (op_en) {372 const r_op = switch (op_en) {
372 .rm, .rmi, .rvm, .rvmi => inst.ops[0],373 .rm, .rmi, .rm0, .rvm, .rvmr, .rvmi => inst.ops[0],
373 .mr, .mri, .mrc => inst.ops[1],374 .mr, .mri, .mrc => inst.ops[1],
374 .mvr => inst.ops[2],375 .mvr => inst.ops[2],
375 .m, .mi, .m1, .mc, .vmi => .none,376 .m, .mi, .m1, .mc, .vmi => .none,
...@@ -378,9 +379,9 @@ pub const Instruction = struct {...@@ -378,9 +379,9 @@ pub const Instruction = struct {
378 vex.r = r_op.isBaseExtended();379 vex.r = r_op.isBaseExtended();
379380
380 const b_x_op = switch (op_en) {381 const b_x_op = switch (op_en) {
381 .rm, .rmi, .vmi => inst.ops[1],382 .rm, .rmi, .rm0, .vmi => inst.ops[1],
382 .m, .mi, .m1, .mc, .mr, .mri, .mrc, .mvr => inst.ops[0],383 .m, .mi, .m1, .mc, .mr, .mri, .mrc, .mvr => inst.ops[0],
383 .rvm, .rvmi => inst.ops[2],384 .rvm, .rvmr, .rvmi => inst.ops[2],
384 else => unreachable,385 else => unreachable,
385 };386 };
386 vex.b = b_x_op.isBaseExtended();387 vex.b = b_x_op.isBaseExtended();
...@@ -408,7 +409,7 @@ pub const Instruction = struct {...@@ -408,7 +409,7 @@ pub const Instruction = struct {
408 switch (op_en) {409 switch (op_en) {
409 else => {},410 else => {},
410 .vmi => vex.v = inst.ops[0].reg,411 .vmi => vex.v = inst.ops[0].reg,
411 .rvm, .rvmi => vex.v = inst.ops[1].reg,412 .rvm, .rvmr, .rvmi => vex.v = inst.ops[1].reg,
412 }413 }
413414
414 try encoder.vex(vex);415 try encoder.vex(vex);
src/arch/x86_64/encodings.zig+34
...@@ -846,6 +846,8 @@ pub const table = [_]Entry{...@@ -846,6 +846,8 @@ pub const table = [_]Entry{
846846
847 .{ .andps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x54 }, 0, .none, .sse },847 .{ .andps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x54 }, 0, .none, .sse },
848848
849 .{ .cmpps, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x0f, 0xc2 }, 0, .none, .sse },
850
849 .{ .cmpss, .rmi, &.{ .xmm, .xmm_m32, .imm8 }, &.{ 0xf3, 0x0f, 0xc2 }, 0, .none, .sse },851 .{ .cmpss, .rmi, &.{ .xmm, .xmm_m32, .imm8 }, &.{ 0xf3, 0x0f, 0xc2 }, 0, .none, .sse },
850852
851 .{ .cvtpi2ps, .rm, &.{ .xmm, .mm_m64 }, &.{ 0x0f, 0x2a }, 0, .none, .sse },853 .{ .cvtpi2ps, .rm, &.{ .xmm, .mm_m64 }, &.{ 0x0f, 0x2a }, 0, .none, .sse },
...@@ -917,6 +919,8 @@ pub const table = [_]Entry{...@@ -917,6 +919,8 @@ pub const table = [_]Entry{
917919
918 .{ .andpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x54 }, 0, .none, .sse2 },920 .{ .andpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x54 }, 0, .none, .sse2 },
919921
922 .{ .cmppd, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0xc2 }, 0, .none, .sse2 },
923
920 .{ .cmpsd, .rmi, &.{ .xmm, .xmm_m64, .imm8 }, &.{ 0xf2, 0x0f, 0xc2 }, 0, .none, .sse2 },924 .{ .cmpsd, .rmi, &.{ .xmm, .xmm_m64, .imm8 }, &.{ 0xf2, 0x0f, 0xc2 }, 0, .none, .sse2 },
921925
922 .{ .cvtdq2pd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf3, 0x0f, 0xe6 }, 0, .none, .sse2 },926 .{ .cvtdq2pd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf3, 0x0f, 0xe6 }, 0, .none, .sse2 },
...@@ -1085,6 +1089,14 @@ pub const table = [_]Entry{...@@ -1085,6 +1089,14 @@ pub const table = [_]Entry{
1085 .{ .movsldup, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0xf3, 0x0f, 0x12 }, 0, .none, .sse3 },1089 .{ .movsldup, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0xf3, 0x0f, 0x12 }, 0, .none, .sse3 },
10861090
1087 // SSE4.11091 // SSE4.1
1092 .{ .blendpd, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0d }, 0, .none, .sse4_1 },
1093
1094 .{ .blendps, .rmi, &.{ .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0c }, 0, .none, .sse4_1 },
1095
1096 .{ .blendvpd, .rm0, &.{ .xmm, .xmm_m128, .xmm0 }, &.{ 0x66, 0x0f, 0x38, 0x15 }, 0, .none, .sse4_1 },
1097
1098 .{ .blendvps, .rm0, &.{ .xmm, .xmm_m128, .xmm0 }, &.{ 0x66, 0x0f, 0x38, 0x14 }, 0, .none, .sse4_1 },
1099
1088 .{ .extractps, .mri, &.{ .rm32, .xmm, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x17 }, 0, .none, .sse4_1 },1100 .{ .extractps, .mri, &.{ .rm32, .xmm, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x17 }, 0, .none, .sse4_1 },
10891101
1090 .{ .insertps, .rmi, &.{ .xmm, .xmm_m32, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x21 }, 0, .none, .sse4_1 },1102 .{ .insertps, .rmi, &.{ .xmm, .xmm_m32, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x21 }, 0, .none, .sse4_1 },
...@@ -1146,11 +1158,33 @@ pub const table = [_]Entry{...@@ -1146,11 +1158,33 @@ pub const table = [_]Entry{
1146 .{ .vandps, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x0f, 0x54 }, 0, .vex_128_wig, .avx },1158 .{ .vandps, .rvm, &.{ .xmm, .xmm, .xmm_m128 }, &.{ 0x0f, 0x54 }, 0, .vex_128_wig, .avx },
1147 .{ .vandps, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x0f, 0x54 }, 0, .vex_256_wig, .avx },1159 .{ .vandps, .rvm, &.{ .ymm, .ymm, .ymm_m256 }, &.{ 0x0f, 0x54 }, 0, .vex_256_wig, .avx },
11481160
1161 .{ .vblendpd, .rvmi, &.{ .xmm, .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0d }, 0, .vex_128_wig, .avx },
1162 .{ .vblendpd, .rvmi, &.{ .ymm, .ymm, .ymm_m256, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0d }, 0, .vex_256_wig, .avx },
1163
1164 .{ .vblendps, .rvmi, &.{ .xmm, .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0c }, 0, .vex_128_wig, .avx },
1165 .{ .vblendps, .rvmi, &.{ .ymm, .ymm, .ymm_m256, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0c }, 0, .vex_256_wig, .avx },
1166
1167 .{ .vblendvpd, .rvmr, &.{ .xmm, .xmm, .xmm_m128, .xmm }, &.{ 0x66, 0x0f, 0x3a, 0x4b }, 0, .vex_128_w0, .avx },
1168 .{ .vblendvpd, .rvmr, &.{ .ymm, .ymm, .ymm_m256, .ymm }, &.{ 0x66, 0x0f, 0x3a, 0x4b }, 0, .vex_256_w0, .avx },
1169
1170 .{ .vblendvps, .rvmr, &.{ .xmm, .xmm, .xmm_m128, .xmm }, &.{ 0x66, 0x0f, 0x3a, 0x4a }, 0, .vex_128_w0, .avx },
1171 .{ .vblendvps, .rvmr, &.{ .ymm, .ymm, .ymm_m256, .ymm }, &.{ 0x66, 0x0f, 0x3a, 0x4a }, 0, .vex_256_w0, .avx },
1172
1149 .{ .vbroadcastss, .rm, &.{ .xmm, .m32 }, &.{ 0x66, 0x0f, 0x38, 0x18 }, 0, .vex_128_w0, .avx },1173 .{ .vbroadcastss, .rm, &.{ .xmm, .m32 }, &.{ 0x66, 0x0f, 0x38, 0x18 }, 0, .vex_128_w0, .avx },
1150 .{ .vbroadcastss, .rm, &.{ .ymm, .m32 }, &.{ 0x66, 0x0f, 0x38, 0x18 }, 0, .vex_256_w0, .avx },1174 .{ .vbroadcastss, .rm, &.{ .ymm, .m32 }, &.{ 0x66, 0x0f, 0x38, 0x18 }, 0, .vex_256_w0, .avx },
1151 .{ .vbroadcastsd, .rm, &.{ .ymm, .m64 }, &.{ 0x66, 0x0f, 0x38, 0x19 }, 0, .vex_256_w0, .avx },1175 .{ .vbroadcastsd, .rm, &.{ .ymm, .m64 }, &.{ 0x66, 0x0f, 0x38, 0x19 }, 0, .vex_256_w0, .avx },
1152 .{ .vbroadcastf128, .rm, &.{ .ymm, .m128 }, &.{ 0x66, 0x0f, 0x38, 0x1a }, 0, .vex_256_w0, .avx },1176 .{ .vbroadcastf128, .rm, &.{ .ymm, .m128 }, &.{ 0x66, 0x0f, 0x38, 0x1a }, 0, .vex_256_w0, .avx },
11531177
1178 .{ .vcmppd, .rvmi, &.{ .xmm, .xmm, .xmm_m128, .imm8 }, &.{ 0x66, 0x0f, 0xc2 }, 0, .vex_128_wig, .avx },
1179 .{ .vcmppd, .rvmi, &.{ .ymm, .ymm, .ymm_m256, .imm8 }, &.{ 0x66, 0x0f, 0xc2 }, 0, .vex_256_wig, .avx },
1180
1181 .{ .vcmpps, .rvmi, &.{ .xmm, .xmm, .xmm_m128, .imm8 }, &.{ 0x0f, 0xc2 }, 0, .vex_128_wig, .avx },
1182 .{ .vcmpps, .rvmi, &.{ .ymm, .ymm, .ymm_m256, .imm8 }, &.{ 0x0f, 0xc2 }, 0, .vex_256_wig, .avx },
1183
1184 .{ .vcmpsd, .rvmi, &.{ .xmm, .xmm, .xmm_m64, .imm8 }, &.{ 0xf2, 0x0f, 0xc2 }, 0, .vex_lig_wig, .avx },
1185
1186 .{ .vcmpss, .rvmi, &.{ .xmm, .xmm, .xmm_m32, .imm8 }, &.{ 0xf3, 0x0f, 0xc2 }, 0, .vex_lig_wig, .avx },
1187
1154 .{ .vcvtdq2pd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf3, 0x0f, 0xe6 }, 0, .vex_128_wig, .avx },1188 .{ .vcvtdq2pd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf3, 0x0f, 0xe6 }, 0, .vex_128_wig, .avx },
1155 .{ .vcvtdq2pd, .rm, &.{ .ymm, .xmm_m128 }, &.{ 0xf3, 0x0f, 0xe6 }, 0, .vex_256_wig, .avx },1189 .{ .vcvtdq2pd, .rm, &.{ .ymm, .xmm_m128 }, &.{ 0xf3, 0x0f, 0xe6 }, 0, .vex_256_wig, .avx },
11561190
test/behavior/maximum_minimum.zig+4-2
...@@ -24,7 +24,8 @@ test "@max" {...@@ -24,7 +24,8 @@ test "@max" {
2424
25test "@max on vectors" {25test "@max on vectors" {
26 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO26 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
27 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO27 if (builtin.zig_backend == .stage2_x86_64 and
28 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; // TODO
28 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO29 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
29 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO30 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
30 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO31 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
...@@ -72,7 +73,8 @@ test "@min" {...@@ -72,7 +73,8 @@ test "@min" {
7273
73test "@min for vectors" {74test "@min for vectors" {
74 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO75 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
75 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO76 if (builtin.zig_backend == .stage2_x86_64 and
77 !comptime std.Target.x86.featureSetHas(builtin.cpu.features, .sse4_1)) return error.SkipZigTest; // TODO
76 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO78 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO79 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO80 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO